diff --git a/src/api/client/admin/lock.rs b/src/api/client/admin/lock.rs new file mode 100644 index 000000000..eeee5bcb8 --- /dev/null +++ b/src/api/client/admin/lock.rs @@ -0,0 +1,89 @@ +use axum::extract::State; +use conduwuit::Err; +use futures::future::{join, join3}; +use ruma::api::client::admin::{is_user_locked, lock_user}; + +use crate::router::Ruma; + +/// # `GET /_matrix/client/v1/admin/lock/{userId}` +/// +/// Check the account lock status of a target user +pub(crate) async fn get_locked_status( + State(services): State, + body: Ruma, +) -> conduwuit::Result { + let sender_user = body.sender_user(); + + let (admin, active) = + join(services.users.is_admin(sender_user), services.users.is_active(&body.user_id)).await; + if !admin { + return Err!(Request(Forbidden("Only server administrators can use this endpoint"))); + } + if !services.globals.user_is_local(&body.user_id) { + return Err!(Request(InvalidParam("Can only check the lock status of local users"))); + } + if !active { + return Err!(Request(NotFound("Unknown user"))); + } + Ok(is_user_locked::v1::Response::new( + services.users.is_locked(&body.user_id).await?, + )) +} + +/// # `PUT /_matrix/client/v1/admin/lock/{userId}` +/// +/// Set the account lock status of a target user +pub(crate) async fn put_locked_status( + State(services): State, + body: Ruma, +) -> conduwuit::Result { + let sender_user = body.sender_user(); + + let (sender_admin, active, target_admin) = join3( + services.users.is_admin(sender_user), + services.users.is_active(&body.user_id), + services.users.is_admin(&body.user_id), + ) + .await; + + if !sender_admin { + return Err!(Request(Forbidden("Only server administrators can use this endpoint"))); + } + if !services.globals.user_is_local(&body.user_id) { + return Err!(Request(InvalidParam("Can only set the locked status of local users"))); + } + if !active { + return Err!(Request(NotFound("Unknown user"))); + } + if body.user_id == *sender_user { + return Err!(Request(Forbidden("You cannot lock yourself"))); + } + if target_admin { + return Err!(Request(Forbidden("You cannot lock another server administrator"))); + } + if services.users.is_locked(&body.user_id).await? == body.locked { + // No change + return Ok(lock_user::v1::Response::new(body.locked)); + } + + let action = if body.locked { + services + .users + .lock_account(&body.user_id, sender_user) + .await; + "suspended" + } else { + services.users.unlock_account(&body.user_id).await; + "unsuspended" + }; + + if services.config.admin_room_notices { + // Notify the admin room that an account has been un/suspended + services + .admin + .send_text(&format!("{} has been {} by {}.", body.user_id, action, sender_user)) + .await; + } + + Ok(lock_user::v1::Response::new(body.locked)) +} diff --git a/src/api/client/admin/mod.rs b/src/api/client/admin/mod.rs index 8355a600c..88f434385 100644 --- a/src/api/client/admin/mod.rs +++ b/src/api/client/admin/mod.rs @@ -1,3 +1,4 @@ +mod lock; mod suspend; -pub(crate) use self::suspend::*; +pub(crate) use self::{lock::*, suspend::*}; diff --git a/src/api/client/admin/suspend.rs b/src/api/client/admin/suspend.rs index b78c0beec..181a1f313 100644 --- a/src/api/client/admin/suspend.rs +++ b/src/api/client/admin/suspend.rs @@ -1,7 +1,7 @@ use axum::extract::State; use conduwuit::{Err, Result}; use futures::future::{join, join3}; -use ruminuwuity::admin::{get_suspended, set_suspended}; +use ruma::api::client::admin::{is_user_suspended, suspend_user}; use crate::Ruma; @@ -10,8 +10,8 @@ use crate::Ruma; /// Check the suspension status of a target user pub(crate) async fn get_suspended_status( State(services): State, - body: Ruma, -) -> Result { + body: Ruma, +) -> Result { let (admin, active) = join( services.users.is_admin(body.identity.sender_user()), services.users.is_active(&body.user_id), @@ -26,7 +26,7 @@ pub(crate) async fn get_suspended_status( if !active { return Err!(Request(NotFound("Unknown user"))); } - Ok(get_suspended::v1::Response::new( + Ok(is_user_suspended::v1::Response::new( services.users.is_suspended(&body.user_id).await?, )) } @@ -36,8 +36,8 @@ pub(crate) async fn get_suspended_status( /// Set the suspension status of a target user pub(crate) async fn put_suspended_status( State(services): State, - body: Ruma, -) -> Result { + body: Ruma, +) -> Result { let sender_user = body.identity.sender_user(); let (sender_admin, active, target_admin) = join3( @@ -64,7 +64,7 @@ pub(crate) async fn put_suspended_status( } if services.users.is_suspended(&body.user_id).await? == body.suspended { // No change - return Ok(set_suspended::v1::Response::new(body.suspended)); + return Ok(suspend_user::v1::Response::new(body.suspended)); } let action = if body.suspended { @@ -86,5 +86,5 @@ pub(crate) async fn put_suspended_status( .await; } - Ok(set_suspended::v1::Response::new(body.suspended)) + Ok(suspend_user::v1::Response::new(body.suspended)) } diff --git a/src/api/router.rs b/src/api/router.rs index eacc85359..5634fce5c 100644 --- a/src/api/router.rs +++ b/src/api/router.rs @@ -181,6 +181,8 @@ pub fn build(router: Router, state: State) -> Router { .ruma_route(&client::get_room_summary) .ruma_route(&client::get_suspended_status) .ruma_route(&client::put_suspended_status) + .ruma_route(&client::get_locked_status) + .ruma_route(&client::put_locked_status) .ruma_route(&client::well_known_support) .ruma_route(&client::well_known_client) .ruma_route(&client::well_known_policy_server)