diff --git a/src/api/v1/channels/mod.rs b/src/api/v1/channels/mod.rs new file mode 100644 index 0000000..d3d5d23 --- /dev/null +++ b/src/api/v1/channels/mod.rs @@ -0,0 +1,11 @@ +use actix_web::{web, Scope}; + +mod uuid; + +pub fn web() -> Scope { + web::scope("/channels") + .service(uuid::get) + .service(uuid::delete) + .service(uuid::messages::get) + .service(uuid::socket::ws) +} diff --git a/src/api/v1/servers/uuid/channels/uuid/messages.rs b/src/api/v1/channels/uuid/messages.rs similarity index 76% rename from src/api/v1/servers/uuid/channels/uuid/messages.rs rename to src/api/v1/channels/uuid/messages.rs index 27bf0cf..25134d2 100644 --- a/src/api/v1/servers/uuid/channels/uuid/messages.rs +++ b/src/api/v1/channels/uuid/messages.rs @@ -43,10 +43,10 @@ struct MessageRequest { /// }); /// ``` /// -#[get("{uuid}/channels/{channel_uuid}/messages")] +#[get("/{uuid}/messages")] pub async fn get( req: HttpRequest, - path: web::Path<(Uuid, Uuid)>, + path: web::Path<(Uuid,)>, message_request: web::Query, data: web::Data, ) -> Result { @@ -54,7 +54,7 @@ pub async fn get( let auth_header = get_auth_header(headers)?; - let (guild_uuid, channel_uuid) = path.into_inner(); + let channel_uuid = path.into_inner().0; let mut conn = data.pool.get().await?; @@ -62,18 +62,9 @@ pub async fn get( global_checks(&data, uuid).await?; - Member::fetch_one(&mut conn, uuid, guild_uuid).await?; + let channel = Channel::fetch_one(&data, channel_uuid).await?; - let channel: Channel; - - if let Ok(cache_hit) = data.get_cache_key(format!("{}", channel_uuid)).await { - channel = serde_json::from_str(&cache_hit)? - } else { - channel = Channel::fetch_one(&mut conn, channel_uuid).await?; - - data.set_cache_key(format!("{}", channel_uuid), channel.clone(), 60) - .await?; - } + Member::fetch_one(&mut conn, uuid, channel.guild_uuid).await?; let messages = channel .fetch_messages(&data, message_request.amount, message_request.offset) diff --git a/src/api/v1/channels/uuid/mod.rs b/src/api/v1/channels/uuid/mod.rs new file mode 100644 index 0000000..f6c93fe --- /dev/null +++ b/src/api/v1/channels/uuid/mod.rs @@ -0,0 +1,60 @@ +pub mod messages; +pub mod socket; + +use crate::{ + api::v1::auth::check_access_token, error::Error, structs::{Channel, Member}, utils::{get_auth_header, global_checks}, Data +}; +use actix_web::{HttpRequest, HttpResponse, delete, get, web}; +use uuid::Uuid; + +#[get("/{uuid}")] +pub async fn get( + req: HttpRequest, + path: web::Path<(Uuid,)>, + data: web::Data, +) -> Result { + let headers = req.headers(); + + let auth_header = get_auth_header(headers)?; + + let channel_uuid = path.into_inner().0; + + let mut conn = data.pool.get().await?; + + let uuid = check_access_token(auth_header, &mut conn).await?; + + global_checks(&data, uuid).await?; + + let channel = Channel::fetch_one(&data, channel_uuid).await?; + + Member::fetch_one(&mut conn, uuid, channel.guild_uuid).await?; + + Ok(HttpResponse::Ok().json(channel)) +} + +#[delete("/{uuid}")] +pub async fn delete( + req: HttpRequest, + path: web::Path<(Uuid,)>, + data: web::Data, +) -> Result { + let headers = req.headers(); + + let auth_header = get_auth_header(headers)?; + + let channel_uuid = path.into_inner().0; + + let mut conn = data.pool.get().await?; + + let uuid = check_access_token(auth_header, &mut conn).await?; + + global_checks(&data, uuid).await?; + + let channel = Channel::fetch_one(&data, channel_uuid).await?; + + Member::fetch_one(&mut conn, uuid, channel.guild_uuid).await?; + + channel.delete(&data).await?; + + Ok(HttpResponse::Ok().finish()) +} diff --git a/src/api/v1/servers/uuid/channels/uuid/socket.rs b/src/api/v1/channels/uuid/socket.rs similarity index 82% rename from src/api/v1/servers/uuid/channels/uuid/socket.rs rename to src/api/v1/channels/uuid/socket.rs index 3cbdb8f..c7ca1e8 100644 --- a/src/api/v1/servers/uuid/channels/uuid/socket.rs +++ b/src/api/v1/channels/uuid/socket.rs @@ -11,10 +11,10 @@ use crate::{ api::v1::auth::check_access_token, structs::{Channel, Member}, utils::{get_ws_protocol_header, global_checks}, Data }; -#[get("{uuid}/channels/{channel_uuid}/socket")] +#[get("/{uuid}/socket")] pub async fn ws( req: HttpRequest, - path: web::Path<(Uuid, Uuid)>, + path: web::Path<(Uuid,)>, stream: web::Payload, data: web::Data, ) -> Result { @@ -24,8 +24,8 @@ pub async fn ws( // Retrieve auth header let auth_header = get_ws_protocol_header(headers)?; - // Get uuids from path - let (guild_uuid, channel_uuid) = path.into_inner(); + // Get uuid from path + let channel_uuid = path.into_inner().0; let mut conn = data.pool.get().await.map_err(crate::error::Error::from)?; @@ -34,20 +34,10 @@ pub async fn ws( global_checks(&data, uuid).await?; + let channel = Channel::fetch_one(&data, channel_uuid).await?; + // Get server member from psql - Member::fetch_one(&mut conn, uuid, guild_uuid).await?; - - let channel: Channel; - - // Return channel cache or result from psql as `channel` variable - if let Ok(cache_hit) = data.get_cache_key(format!("{}", channel_uuid)).await { - channel = serde_json::from_str(&cache_hit)? - } else { - channel = Channel::fetch_one(&mut conn, channel_uuid).await?; - - data.set_cache_key(format!("{}", channel_uuid), channel.clone(), 60) - .await?; - } + Member::fetch_one(&mut conn, uuid, channel.guild_uuid).await?; let (mut res, mut session_1, stream) = actix_ws::handle(&req, stream)?; diff --git a/src/api/v1/mod.rs b/src/api/v1/mod.rs index f30ad58..c08e1e3 100644 --- a/src/api/v1/mod.rs +++ b/src/api/v1/mod.rs @@ -3,6 +3,7 @@ use actix_web::{Scope, web}; mod auth; +mod channels; mod invites; mod servers; mod stats; @@ -14,6 +15,7 @@ pub fn web() -> Scope { .service(stats::res) .service(auth::web()) .service(users::web()) + .service(channels::web()) .service(servers::web()) .service(invites::web()) .service(me::web()) diff --git a/src/api/v1/servers/uuid/channels/mod.rs b/src/api/v1/servers/uuid/channels.rs similarity index 99% rename from src/api/v1/servers/uuid/channels/mod.rs rename to src/api/v1/servers/uuid/channels.rs index 6327e33..813de13 100644 --- a/src/api/v1/servers/uuid/channels/mod.rs +++ b/src/api/v1/servers/uuid/channels.rs @@ -5,8 +5,6 @@ use ::uuid::Uuid; use actix_web::{HttpRequest, HttpResponse, get, post, web}; use serde::Deserialize; -pub mod uuid; - #[derive(Deserialize)] struct ChannelInfo { name: String, diff --git a/src/api/v1/servers/uuid/channels/uuid/mod.rs b/src/api/v1/servers/uuid/channels/uuid/mod.rs deleted file mode 100644 index 946adf3..0000000 --- a/src/api/v1/servers/uuid/channels/uuid/mod.rs +++ /dev/null @@ -1,77 +0,0 @@ -pub mod messages; -pub mod socket; - -use crate::{ - api::v1::auth::check_access_token, error::Error, structs::{Channel, Member}, utils::{get_auth_header, global_checks}, Data -}; -use actix_web::{HttpRequest, HttpResponse, delete, get, web}; -use uuid::Uuid; - -#[get("{uuid}/channels/{channel_uuid}")] -pub async fn get( - req: HttpRequest, - path: web::Path<(Uuid, Uuid)>, - data: web::Data, -) -> Result { - let headers = req.headers(); - - let auth_header = get_auth_header(headers)?; - - let (guild_uuid, channel_uuid) = path.into_inner(); - - let mut conn = data.pool.get().await?; - - let uuid = check_access_token(auth_header, &mut conn).await?; - - global_checks(&data, uuid).await?; - - Member::fetch_one(&mut conn, uuid, guild_uuid).await?; - - if let Ok(cache_hit) = data.get_cache_key(format!("{}", channel_uuid)).await { - return Ok(HttpResponse::Ok() - .content_type("application/json") - .body(cache_hit)); - } - - let channel = Channel::fetch_one(&mut conn, channel_uuid).await?; - - data.set_cache_key(format!("{}", channel_uuid), channel.clone(), 60) - .await?; - - Ok(HttpResponse::Ok().json(channel)) -} - -#[delete("{uuid}/channels/{channel_uuid}")] -pub async fn delete( - req: HttpRequest, - path: web::Path<(Uuid, Uuid)>, - data: web::Data, -) -> Result { - let headers = req.headers(); - - let auth_header = get_auth_header(headers)?; - - let (guild_uuid, channel_uuid) = path.into_inner(); - - let mut conn = data.pool.get().await?; - - let uuid = check_access_token(auth_header, &mut conn).await?; - - global_checks(&data, uuid).await?; - - Member::fetch_one(&mut conn, uuid, guild_uuid).await?; - - let channel: Channel; - - if let Ok(cache_hit) = data.get_cache_key(format!("{}", channel_uuid)).await { - channel = serde_json::from_str(&cache_hit)?; - - data.del_cache_key(format!("{}", channel_uuid)).await?; - } else { - channel = Channel::fetch_one(&mut conn, channel_uuid).await?; - } - - channel.delete(&mut conn).await?; - - Ok(HttpResponse::Ok().finish()) -} diff --git a/src/api/v1/servers/uuid/mod.rs b/src/api/v1/servers/uuid/mod.rs index 39b2925..f874b91 100644 --- a/src/api/v1/servers/uuid/mod.rs +++ b/src/api/v1/servers/uuid/mod.rs @@ -19,10 +19,6 @@ pub fn web() -> Scope { // Channels .service(channels::get) .service(channels::create) - .service(channels::uuid::get) - .service(channels::uuid::delete) - .service(channels::uuid::messages::get) - .service(channels::uuid::socket::ws) // Roles .service(roles::get) .service(roles::create) diff --git a/src/structs.rs b/src/structs.rs index 500396f..8d1d367 100644 --- a/src/structs.rs +++ b/src/structs.rs @@ -183,15 +183,26 @@ impl Channel { futures::future::try_join_all(channel_futures).await } - pub async fn fetch_one(conn: &mut Conn, channel_uuid: Uuid) -> Result { + pub async fn fetch_one(data: &Data, channel_uuid: Uuid) -> Result { + if let Ok(cache_hit) = data.get_cache_key(channel_uuid.to_string()).await { + return Ok(serde_json::from_str(&cache_hit)?); + } + + let mut conn = data.pool.get().await?; + use channels::dsl; let channel_builder: ChannelBuilder = dsl::channels .filter(dsl::uuid.eq(channel_uuid)) .select(ChannelBuilder::as_select()) - .get_result(conn) + .get_result(&mut conn) .await?; - channel_builder.build(conn).await + let channel = channel_builder.build(&mut conn).await?; + + data.set_cache_key(channel_uuid.to_string(), channel.clone(), 60) + .await?; + + Ok(channel) } pub async fn new( @@ -245,19 +256,27 @@ impl Channel { data.set_cache_key(channel_uuid.to_string(), channel.clone(), 1800) .await?; - data.del_cache_key(format!("{}_channels", guild_uuid)) - .await?; + if let Ok(_) = data.get_cache_key(format!("{}_channels", guild_uuid)).await { + data.del_cache_key(format!("{}_channels", guild_uuid)) + .await?; + } Ok(channel) } - pub async fn delete(self, conn: &mut Conn) -> Result<(), Error> { + pub async fn delete(self, data: &Data) -> Result<(), Error> { + let mut conn = data.pool.get().await?; + use channels::dsl; delete(channels::table) .filter(dsl::uuid.eq(self.uuid)) - .execute(conn) + .execute(&mut conn) .await?; + if let Ok(_) = data.get_cache_key(self.uuid.to_string()).await { + data.del_cache_key(self.uuid.to_string()).await?; + } + Ok(()) }