diff --git a/set_version.sh b/set_version.sh index 990e58aa2bda000829e6f119d8600fecf49fcc4b..8121b54113ff19d3c4ed825848f4d4063a435ada 100755 --- a/set_version.sh +++ b/set_version.sh @@ -1,3 +1,3 @@ #!/bin/bash -export version=0.5.1-alpha.7 +export version=0.5.1-alpha.8 echo "pub const VERSION: &str = \"${version}\";" > src/version.rs diff --git a/src/notifications/events.rs b/src/notifications/events.rs index 4490d9047ff6bcabcd0f8ed14716a9c80ddb0230..aa28cd76d55460000cd5b099371659a87dfbc89a 100644 --- a/src/notifications/events.rs +++ b/src/notifications/events.rs @@ -46,6 +46,11 @@ pub enum RemoveServerField { Description, } +#[derive(Serialize, Deserialize, Debug, Clone)] +pub enum RemoveRoleField { + Colour, +} + #[derive(Serialize, Deserialize, Debug, Clone)] pub enum RemoveMemberField { Nickname, @@ -132,7 +137,9 @@ pub enum ClientboundNotification { ServerRoleUpdate { id: String, role_id: String, - data: JsonValue + data: JsonValue, + #[serde(skip_serializing_if = "Option::is_none")] + clear: Option<RemoveRoleField> }, ServerRoleDelete { id: String, diff --git a/src/routes/servers/mod.rs b/src/routes/servers/mod.rs index 15968de8f3f6d32df4ae9db6d854199f4a151924..b137d26471afb619078cc071e98591285424ed1b 100644 --- a/src/routes/servers/mod.rs +++ b/src/routes/servers/mod.rs @@ -19,6 +19,7 @@ mod ban_remove; mod invites_fetch; mod roles_create; +mod roles_edit; mod roles_delete; mod permissions_set; mod permissions_set_default; @@ -39,6 +40,7 @@ pub fn routes() -> Vec<Route> { ban_list::req, invites_fetch::req, roles_create::req, + roles_edit::req, roles_delete::req, permissions_set::req, permissions_set_default::req diff --git a/src/routes/servers/permissions_set.rs b/src/routes/servers/permissions_set.rs index 62ffa3c8583a01f357a16c18d3f9057e33c7f6e9..74359a24e2b85f1f681b7cb50a5aaee96fb3ef61 100644 --- a/src/routes/servers/permissions_set.rs +++ b/src/routes/servers/permissions_set.rs @@ -66,7 +66,8 @@ pub async fn req(user: User, target: Ref, role_id: String, data: Json<Data>) -> server_permissions as i32, channel_permissions as i32 ] - }) + }), + clear: None } .publish(target.id); diff --git a/src/routes/servers/roles_create.rs b/src/routes/servers/roles_create.rs index e55887c2e8c2b700845e2c8fa988d328ed9198f8..3f13d753d740fc5e754f7437fb8b9887d09e3e47 100644 --- a/src/routes/servers/roles_create.rs +++ b/src/routes/servers/roles_create.rs @@ -67,7 +67,8 @@ pub async fn req(user: User, target: Ref, data: Json<Data>) -> Result<JsonValue> data: json!({ "name": data.name, "permissions": &perm_tuple - }) + }), + clear: None } .publish(target.id); diff --git a/src/routes/servers/roles_edit.rs b/src/routes/servers/roles_edit.rs new file mode 100644 index 0000000000000000000000000000000000000000..3cc796e2481ee6c5cee69fe7da686d44ed23296a --- /dev/null +++ b/src/routes/servers/roles_edit.rs @@ -0,0 +1,98 @@ +use crate::notifications::events::ClientboundNotification; +use crate::util::result::{Error, Result}; +use crate::{database::*, notifications::events::RemoveRoleField}; + +use mongodb::bson::doc; +use rocket_contrib::json::Json; +use serde::{Deserialize, Serialize}; +use validator::Validate; + +#[derive(Validate, Serialize, Deserialize)] +pub struct Data { + #[validate(length(min = 1, max = 32))] + name: Option<String>, + #[validate(length(min = 1, max = 32))] + colour: Option<String>, + remove: Option<RemoveRoleField>, +} + +#[patch("/<target>/roles/<role_id>", data = "<data>")] +pub async fn req(user: User, target: Ref, role_id: String, data: Json<Data>) -> Result<()> { + let data = data.into_inner(); + data.validate() + .map_err(|error| Error::FailedValidation { error })?; + + if data.name.is_none() && data.colour.is_none() && data.remove.is_none() + { + return Ok(()); + } + + let target = target.fetch_server().await?; + let perm = permissions::PermissionCalculator::new(&user) + .with_server(&target) + .for_server() + .await?; + + if !perm.get_manage_roles() { + return Err(Error::MissingPermission) + } + + if !target.roles.contains_key(&role_id) { + return Err(Error::InvalidRole) + } + + let mut set = doc! {}; + let mut unset = doc! {}; + + // ! FIXME: we should probably just require clients to support basic MQL incl. $set / $unset + let mut set_update = doc! {}; + + let role_key = "roles.".to_owned() + &role_id; + + if let Some(remove) = &data.remove { + match remove { + RemoveRoleField::Colour => { + unset.insert(role_key.clone() + ".colour", 1); + } + } + } + + if let Some(name) = &data.name { + set.insert(role_key.clone() + ".name", name); + set_update.insert("name", name); + } + + if let Some(colour) = &data.colour { + set.insert(role_key.clone() + ".colour", colour); + set_update.insert("colour", colour); + } + + let mut operations = doc! {}; + if set.len() > 0 { + operations.insert("$set", &set); + } + + if unset.len() > 0 { + operations.insert("$unset", unset); + } + + if operations.len() > 0 { + get_collection("servers") + .update_one(doc! { "_id": &target.id }, operations, None) + .await + .map_err(|_| Error::DatabaseError { + operation: "update_one", + with: "server", + })?; + } + + ClientboundNotification::ServerRoleUpdate { + id: target.id.clone(), + role_id, + data: json!(set_update), + clear: data.remove, + } + .publish(target.id.clone()); + + Ok(()) +} diff --git a/src/version.rs b/src/version.rs index 99ae5c62b0d2606e370a8fffe0cdf5dbf7b92c70..918a989a77ebf875569ab16010e24e4c483e7fc1 100644 --- a/src/version.rs +++ b/src/version.rs @@ -1 +1 @@ -pub const VERSION: &str = "0.5.1-alpha.7"; +pub const VERSION: &str = "0.5.1-alpha.8";