diff --git a/crates/delta/src/routes/users/edit_user.rs b/crates/delta/src/routes/users/edit_user.rs index 40788c96..c7c2b30c 100644 --- a/crates/delta/src/routes/users/edit_user.rs +++ b/crates/delta/src/routes/users/edit_user.rs @@ -1,6 +1,6 @@ use revolt_quark::models::user::{FieldsUser, PartialUser, User}; use revolt_quark::models::File; -use revolt_quark::{Database, Error, Result}; +use revolt_quark::{Database, Error, Ref, Result}; use revolt_quark::models::user::UserStatus; use rocket::serde::json::Json; @@ -24,6 +24,10 @@ pub struct UserProfileData { /// # User Data #[derive(Validate, Serialize, Deserialize, JsonSchema)] pub struct DataEditUser { + /// Attachment Id for avatar + #[validate(length(min = 1, max = 128))] + avatar: Option, + /// New user status #[validate] status: Option, @@ -32,9 +36,14 @@ pub struct DataEditUser { /// This is applied as a partial. #[validate] profile: Option, - /// Attachment Id for avatar - #[validate(length(min = 1, max = 128))] - avatar: Option, + + /// Bitfield of user badges + #[serde(skip_serializing_if = "Option::is_none")] + badges: Option, + /// Enum of user flags + #[serde(skip_serializing_if = "Option::is_none")] + flags: Option, + /// Fields to remove from user object #[validate(length(min = 1))] remove: Option>, @@ -44,19 +53,36 @@ pub struct DataEditUser { /// /// Edit currently authenticated user. #[openapi(tag = "User Information")] -#[patch("/@me", data = "")] +#[patch("/", data = "")] pub async fn req( db: &State, mut user: User, + target: Ref, data: Json, ) -> Result> { let data = data.into_inner(); data.validate() .map_err(|error| Error::FailedValidation { error })?; + // If we want to edit a different user than self, ensure we have + // permissions and subsequently replace the user in question + if target.id != "@me" { + if !user.privileged { + return Err(Error::NotPrivileged); + } + + user = target.as_user(db).await?; + // Otherwise, filter out invalid edit fields + } else if data.badges.is_some() || data.flags.is_some() { + return Err(Error::NotPrivileged); + } + + // Exit out early if nothing is changed if data.status.is_none() && data.profile.is_none() && data.avatar.is_none() + && data.badges.is_none() + && data.flags.is_none() && data.remove.is_none() { return Ok(Json(user)); @@ -83,7 +109,11 @@ pub async fn req( } } - let mut partial: PartialUser = Default::default(); + let mut partial: PartialUser = PartialUser { + badges: data.badges, + flags: data.flags, + ..Default::default() + }; // 2. Apply new avatar if let Some(avatar) = data.avatar {