From f10aaa5bbeeed3ad15eb01236f2865d2e570cb6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0spik?= Date: Sun, 28 Jun 2026 17:49:45 +0300 Subject: [PATCH] feat: add admin account email change route MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: İspik --- crates/core/models/src/v0/admin.rs | 2 + .../admin/accounts/account_email_change.rs | 66 +++++++++++++++++++ crates/delta/src/routes/admin/mod.rs | 1 + 3 files changed, 69 insertions(+) diff --git a/crates/core/models/src/v0/admin.rs b/crates/core/models/src/v0/admin.rs index 0114b7a1..cf47e9e9 100644 --- a/crates/core/models/src/v0/admin.rs +++ b/crates/core/models/src/v0/admin.rs @@ -325,6 +325,7 @@ auto_derived! { // Accounts DeleteAccount, DisableAccount, + EmailChange, // Channels DeleteChannel, @@ -379,6 +380,7 @@ impl AdminAuditItemActions { AdminAuditItemActions::ServerFetchMembers => false, AdminAuditItemActions::DeleteAccount => true, AdminAuditItemActions::DisableAccount => true, + AdminAuditItemActions::EmailChange => true, AdminAuditItemActions::DeleteChannel => true, AdminAuditItemActions::EditChannel => true, AdminAuditItemActions::WipeChannel => true, diff --git a/crates/delta/src/routes/admin/accounts/account_email_change.rs b/crates/delta/src/routes/admin/accounts/account_email_change.rs index e69de29b..62b48758 100644 --- a/crates/delta/src/routes/admin/accounts/account_email_change.rs +++ b/crates/delta/src/routes/admin/accounts/account_email_change.rs @@ -0,0 +1,66 @@ +use crate::routes::admin::util::{ + create_audit_action, flatten_authorized_user, user_has_permission, +}; +use revolt_database::util::reference::Reference; +use revolt_database::{AdminAuthorization, Database}; +use revolt_models::v0::{self}; +use revolt_result::{create_error, Result}; +use rocket::serde::json::Json; +use rocket::State; +use rocket_empty::EmptyResponse; +use revolt_database::util::email::{normalise_email, validate_email}; + +/// Change the email of an account. Requires ManageAccounts permissions +#[openapi(tag = "Admin")] +#[patch("/accounts/email/?", data = "")] +pub async fn admin_account_email_change( + db: &State, + auth: AdminAuthorization, + target: Reference<'_>, + case: Option<&str>, + data: Json, +) -> Result { + let data = data.into_inner(); + + validate_email(&data.email)?; + + let user = flatten_authorized_user(&auth); + if !user_has_permission(user, v0::AdminUserPermissionFlags::ManageAccounts) { + return Err(create_error!(MissingPermission { + permission: "ManageAccounts".to_string() + })); + } + + let target = target.as_user(db).await?; + + if target.privileged { + return Err(create_error!(PrivilegedAccount)); + } + + let admin = db.admin_user_fetch(&target.id).await.ok(); + + if let Some(admin) = admin { + if user_has_permission(&admin, v0::AdminUserPermissionFlags::ManageAccounts) { + return Err(create_error!(PrivilegedAccount)); + } + } + + let mut account = db.fetch_account(&target.id).await?; + + account.email_normalised = normalise_email(data.email.clone()); + account.email = data.email; + account.save(db).await?; + + + create_audit_action( + db, + &user.id, + v0::AdminAuditItemActions::EmailChange, + case, + Some(&target.id), + None, + ) + .await?; + + Ok(EmptyResponse) +} diff --git a/crates/delta/src/routes/admin/mod.rs b/crates/delta/src/routes/admin/mod.rs index ceb03dd4..8db831bc 100644 --- a/crates/delta/src/routes/admin/mod.rs +++ b/crates/delta/src/routes/admin/mod.rs @@ -40,6 +40,7 @@ pub fn routes() -> (Vec, OpenApi) { servers::actions::server_remove_members::admin_server_remove_members, accounts::account_delete::admin_account_delete, accounts::account_disable::admin_account_disable, + accounts::account_email_change::admin_account_email_change, channels::actions::channel_delete::admin_delete_channel, channels::actions::channel_edit::admin_channel_edit, channels::actions::channel_wipe::admin_channel_wipe,