diff --git a/src/routes/servers/channel_create.rs b/src/routes/servers/channel_create.rs index 338bb47c..0317e73a 100644 --- a/src/routes/servers/channel_create.rs +++ b/src/routes/servers/channel_create.rs @@ -1,9 +1,11 @@ use std::collections::HashMap; -use revolt_quark::{Error, Result}; +use revolt_quark::{ + models::{server::PartialServer, Channel, User}, + perms, Db, Error, Ref, Result, ServerPermission, +}; -use mongodb::bson::doc; -use rocket::serde::json::{Json, Value}; +use rocket::serde::json::Json; use serde::{Deserialize, Serialize}; use ulid::Ulid; use validator::Validate; @@ -33,9 +35,74 @@ pub struct Data { } #[post("//channels", data = "")] -pub async fn req( - /*_idempotency: IdempotencyKey, user: User, target: Ref,*/ target: String, - info: Json, -) -> Result { - todo!() +pub async fn req(db: &Db, user: User, target: Ref, info: Json) -> Result> { + let info = info.into_inner(); + info.validate() + .map_err(|error| Error::FailedValidation { error })?; + + let server = target.as_server(db).await?; + if !perms(&user) + .server(&server) + .calc_server(db) + .await + .get_manage_channels() + { + return Err(Error::MissingPermission { + permission: ServerPermission::ManageChannels as i32, + }); + } + + let id = Ulid::new().to_string(); + let mut channels = server.channels; + channels.push(id.clone()); + + let Data { + name, + description, + nsfw, + channel_type, + } = info; + let channel = match channel_type { + ChannelType::Text => Channel::TextChannel { + id, + server: server.id.clone(), + + name, + description, + + icon: None, + last_message_id: None, + + default_permissions: None, + role_permissions: HashMap::new(), + + nsfw: nsfw.unwrap_or(false), + }, + ChannelType::Voice => Channel::VoiceChannel { + id, + server: server.id.clone(), + + name, + description, + icon: None, + + default_permissions: None, + role_permissions: HashMap::new(), + + nsfw: nsfw.unwrap_or(false), + }, + }; + + db.insert_channel(&channel).await?; + db.update_server( + &server.id, + &PartialServer { + channels: Some(channels), + ..Default::default() + }, + vec![], + ) + .await?; + + Ok(Json(channel)) } diff --git a/src/routes/servers/invites_fetch.rs b/src/routes/servers/invites_fetch.rs index 11026a58..870f7662 100644 --- a/src/routes/servers/invites_fetch.rs +++ b/src/routes/servers/invites_fetch.rs @@ -1,8 +1,9 @@ -use revolt_quark::{Error, Result}; +use revolt_quark::{ + models::{Invite, User}, + perms, Db, Error, Ref, Result, ServerPermission, +}; -use futures::StreamExt; -use mongodb::bson::{doc, from_document}; -use rocket::serde::json::Value; +use rocket::serde::json::Json; use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, Debug, Clone)] @@ -14,6 +15,18 @@ pub struct ServerInvite { } #[get("//invites")] -pub async fn req(/*user: UserRef, target: Ref*/ target: String) -> Result { - todo!() +pub async fn req(db: &Db, user: User, target: Ref) -> Result>> { + let server = target.as_server(db).await?; + if !perms(&user) + .server(&server) + .calc_server(db) + .await + .get_manage_server() + { + return Err(Error::MissingPermission { + permission: ServerPermission::ManageServer as i32, + }); + } + + db.fetch_invites_for_server(&server.id).await.map(Json) } diff --git a/src/routes/servers/permissions_set.rs b/src/routes/servers/permissions_set.rs index df0b3950..8546c169 100644 --- a/src/routes/servers/permissions_set.rs +++ b/src/routes/servers/permissions_set.rs @@ -2,7 +2,7 @@ use mongodb::bson::doc; use rocket::serde::json::Json; use serde::{Deserialize, Serialize}; -use revolt_quark::{EmptyResponse, Result}; +use revolt_quark::{models::User, perms, Db, EmptyResponse, Error, Ref, Result}; #[derive(Serialize, Deserialize)] pub struct Values { @@ -17,9 +17,30 @@ pub struct Data { #[put("//permissions/", data = "", rank = 2)] pub async fn req( - /*user: UserRef, target: Ref,*/ target: String, + db: &Db, + user: User, + target: Ref, role_id: String, data: Json, ) -> Result { - todo!() + let server = target.as_server(db).await?; + if !perms(&user) + .server(&server) + .calc_server(db) + .await + .get_manage_roles() + { + return Err(Error::NotFound); + } + + db.update_role_permission( + &server.id, + &role_id, + &( + data.permissions.server as i32, + data.permissions.channel as i32, + ), + ) + .await + .map(|_| EmptyResponse) } diff --git a/src/routes/servers/permissions_set_default.rs b/src/routes/servers/permissions_set_default.rs index 8db31493..569babdd 100644 --- a/src/routes/servers/permissions_set_default.rs +++ b/src/routes/servers/permissions_set_default.rs @@ -2,7 +2,10 @@ use mongodb::bson::doc; use rocket::serde::json::Json; use serde::{Deserialize, Serialize}; -use revolt_quark::{EmptyResponse, Result}; +use revolt_quark::{ + models::{server::PartialServer, User}, + perms, Db, EmptyResponse, Error, Ref, Result, +}; #[derive(Serialize, Deserialize)] pub struct Values { @@ -16,9 +19,30 @@ pub struct Data { } #[put("//permissions/default", data = "", rank = 1)] -pub async fn req( - /*user: UserRef, target: Ref,*/ target: String, - data: Json, -) -> Result { - todo!() +pub async fn req(db: &Db, user: User, target: Ref, data: Json) -> Result { + let data = data.into_inner(); + + let server = target.as_server(db).await?; + if !perms(&user) + .server(&server) + .calc_server(db) + .await + .get_manage_roles() + { + return Err(Error::NotFound); + } + + db.update_server( + &server.id, + &PartialServer { + default_permissions: Some(( + data.permissions.server as i32, + data.permissions.channel as i32, + )), + ..Default::default() + }, + vec![], + ) + .await + .map(|_| EmptyResponse) } diff --git a/src/routes/servers/roles_create.rs b/src/routes/servers/roles_create.rs index b81420e4..c63b8b70 100644 --- a/src/routes/servers/roles_create.rs +++ b/src/routes/servers/roles_create.rs @@ -1,6 +1,8 @@ -use revolt_quark::{Error, Result}; +use revolt_quark::{ + models::{server::Role, User}, + perms, Db, Error, Ref, Result, DEFAULT_PERMISSION_CHANNEL_SERVER, DEFAULT_SERVER_PERMISSION, +}; -use mongodb::bson::doc; use rocket::serde::json::{Json, Value}; use serde::{Deserialize, Serialize}; use ulid::Ulid; @@ -13,9 +15,35 @@ pub struct Data { } #[post("//roles", data = "")] -pub async fn req( - /*user: UserRef, target: Ref,*/ target: String, - data: Json, -) -> Result { - todo!() +pub async fn req(db: &Db, user: User, target: Ref, data: Json) -> Result { + let data = data.into_inner(); + data.validate() + .map_err(|error| Error::FailedValidation { error })?; + + let server = target.as_server(db).await?; + if !perms(&user) + .server(&server) + .calc_server(db) + .await + .get_manage_roles() + { + return Err(Error::NotFound); + } + + let role_id = Ulid::new().to_string(); + db.insert_role( + &server.id, + &role_id, + &Role { + name: data.name, + permissions: ( + *DEFAULT_SERVER_PERMISSION as i32, + *DEFAULT_PERMISSION_CHANNEL_SERVER as i32, + ), + ..Default::default() + }, + ) + .await?; + + Ok(json!({ "id": role_id })) } diff --git a/src/routes/servers/roles_delete.rs b/src/routes/servers/roles_delete.rs index 520914fe..4b2e6908 100644 --- a/src/routes/servers/roles_delete.rs +++ b/src/routes/servers/roles_delete.rs @@ -1,9 +1,18 @@ -use revolt_quark::{EmptyResponse, Result}; +use revolt_quark::{models::User, perms, Db, EmptyResponse, Error, Ref, Result}; #[delete("//roles/")] -pub async fn req( - /*user: UserRef, target: Ref,*/ target: String, - role_id: String, -) -> Result { - todo!() +pub async fn req(db: &Db, user: User, target: Ref, role_id: String) -> Result { + let server = target.as_server(db).await?; + if !perms(&user) + .server(&server) + .calc_server(db) + .await + .get_manage_roles() + { + return Err(Error::NotFound); + } + + db.delete_role(&server.id, &role_id) + .await + .map(|_| EmptyResponse) } diff --git a/src/routes/servers/roles_edit.rs b/src/routes/servers/roles_edit.rs index f890e459..1d2034b3 100644 --- a/src/routes/servers/roles_edit.rs +++ b/src/routes/servers/roles_edit.rs @@ -1,6 +1,11 @@ -use revolt_quark::{EmptyResponse, Result}; +use revolt_quark::{ + models::{ + server::{FieldsRole, PartialRole, Role}, + User, + }, + perms, Db, Error, Ref, Result, +}; -use mongodb::bson::doc; use rocket::serde::json::Json; use serde::{Deserialize, Serialize}; use validator::Validate; @@ -13,15 +18,66 @@ pub struct Data { colour: Option, hoist: Option, rank: Option, - // #[validate(length(min = 1))] - // remove: Option>, + #[validate(length(min = 1))] + remove: Option>, } #[patch("//roles/", data = "")] pub async fn req( - /*user: UserRef, target: Ref,*/ target: String, + db: &Db, + user: User, + target: Ref, role_id: String, data: Json, -) -> Result { - todo!() +) -> Result> { + let data = data.into_inner(); + data.validate() + .map_err(|error| Error::FailedValidation { error })?; + + let mut server = target.as_server(db).await?; + if !perms(&user) + .server(&server) + .calc_server(db) + .await + .get_manage_roles() + { + return Err(Error::NotFound); + } + + if let Some(mut role) = server.roles.remove(&role_id) { + let Data { + name, + colour, + hoist, + rank, + remove, + } = data; + + let partial = PartialRole { + name, + colour, + hoist, + rank, + ..Default::default() + }; + + if let Some(remove) = &remove { + for field in remove { + role.remove(field); + } + } + + db.update_role( + &server.id, + &role_id, + &partial, + remove.unwrap_or_else(Vec::new), + ) + .await?; + + role.apply_options(partial.clone()); + Ok(Json(role)) + } else { + Err(Error::NotFound) + } } diff --git a/src/routes/servers/server_ack.rs b/src/routes/servers/server_ack.rs index 28f387a3..3fc28b8f 100644 --- a/src/routes/servers/server_ack.rs +++ b/src/routes/servers/server_ack.rs @@ -1,6 +1,18 @@ -use revolt_quark::{EmptyResponse, Result}; +use revolt_quark::{models::User, perms, Db, EmptyResponse, Error, Ref, Result}; #[put("//ack")] -pub async fn req(/*user: UserRef, target: Ref*/ target: String) -> Result { - todo!() +pub async fn req(db: &Db, user: User, target: Ref) -> Result { + let server = target.as_server(db).await?; + if !perms(&user) + .server(&server) + .calc_server(db) + .await + .get_view() + { + return Err(Error::NotFound); + } + + db.acknowledge_channels(&user.id, &server.channels) + .await + .map(|_| EmptyResponse) } diff --git a/src/routes/servers/server_create.rs b/src/routes/servers/server_create.rs index 97e12abd..e2b25d48 100644 --- a/src/routes/servers/server_create.rs +++ b/src/routes/servers/server_create.rs @@ -1,9 +1,10 @@ +use std::collections::HashMap; + use revolt_quark::{ - models::{Server, User}, + models::{Channel, Server, User}, Db, Error, Result, DEFAULT_PERMISSION_CHANNEL_SERVER, DEFAULT_SERVER_PERMISSION, }; -use mongodb::bson::doc; use rocket::serde::json::Json; use serde::{Deserialize, Serialize}; use ulid::Ulid; @@ -38,11 +39,32 @@ pub async fn req(db: &Db, user: User, info: Json) -> Result> description, nsfw, } = info; - + + let channel_id = Ulid::new().to_string(); + let server_id = Ulid::new().to_string(); + + let channel = Channel::TextChannel { + id: channel_id.clone(), + server: server_id.clone(), + + name: "General".into(), + description: None, + + icon: None, + last_message_id: None, + + default_permissions: None, + role_permissions: HashMap::new(), + + nsfw: nsfw.unwrap_or(false), + }; + let server = Server { - id: Ulid::new().to_string(), + id: server_id, + owner: user.id, name, description, + channels: vec![channel_id], nsfw: nsfw.unwrap_or(false), default_permissions: ( *DEFAULT_SERVER_PERMISSION as i32, @@ -51,6 +73,7 @@ pub async fn req(db: &Db, user: User, info: Json) -> Result> ..Default::default() }; + db.insert_channel(&channel).await?; db.insert_server(&server).await?; Ok(Json(server)) } diff --git a/src/routes/servers/server_delete.rs b/src/routes/servers/server_delete.rs index 6899a1a8..f77dd8fe 100644 --- a/src/routes/servers/server_delete.rs +++ b/src/routes/servers/server_delete.rs @@ -1,23 +1,16 @@ -use revolt_quark::{models::User, perms, Db, EmptyResponse, Error, Ref, Result}; +use revolt_quark::{models::User, Db, EmptyResponse, Ref, Result}; use mongodb::bson::doc; #[delete("/")] pub async fn req(db: &Db, user: User, target: Ref) -> Result { let server = target.as_server(db).await?; - if !perms(&user) - .server(&server) - .calc_server(db) - .await - .get_view() - { - return Err(Error::NotFound); - } + let member = db.fetch_member(&target.id, &user.id).await?; if server.owner == user.id { db.delete_server(&server.id).await?; } else { - db.delete_member(&server.id, &user.id).await?; + db.delete_member(&member.id).await?; } Ok(EmptyResponse)