feat: implement admin account disable functionality
This commit is contained in:
@@ -3,6 +3,7 @@ mod mongodb;
|
|||||||
mod reference;
|
mod reference;
|
||||||
|
|
||||||
use authifier::config::Captcha;
|
use authifier::config::Captcha;
|
||||||
|
use authifier::config::EmailExpiryConfig;
|
||||||
use authifier::config::EmailVerificationConfig;
|
use authifier::config::EmailVerificationConfig;
|
||||||
use authifier::config::PasswordScanning;
|
use authifier::config::PasswordScanning;
|
||||||
use authifier::config::ResolveIp;
|
use authifier::config::ResolveIp;
|
||||||
@@ -10,10 +11,10 @@ use authifier::config::SMTPSettings;
|
|||||||
use authifier::config::Shield;
|
use authifier::config::Shield;
|
||||||
use authifier::config::Template;
|
use authifier::config::Template;
|
||||||
use authifier::config::Templates;
|
use authifier::config::Templates;
|
||||||
use authifier::config::EmailExpiryConfig;
|
|
||||||
use authifier::Authifier;
|
use authifier::Authifier;
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use revolt_config::config;
|
use revolt_config::config;
|
||||||
|
use revolt_result::Result;
|
||||||
|
|
||||||
#[cfg(feature = "mongodb")]
|
#[cfg(feature = "mongodb")]
|
||||||
pub use self::mongodb::*;
|
pub use self::mongodb::*;
|
||||||
@@ -251,4 +252,22 @@ impl Database {
|
|||||||
event_channel: None,
|
event_channel: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub async fn disable_authifier_account(&self, user_id: &str) -> Result<()> {
|
||||||
|
let auth = self.clone().to_authifier().await;
|
||||||
|
|
||||||
|
let mut account = auth
|
||||||
|
.database
|
||||||
|
.find_account(user_id)
|
||||||
|
.await
|
||||||
|
.map_err(|_| create_database_error!("find_account", "accounts"))?;
|
||||||
|
|
||||||
|
account.disabled = true;
|
||||||
|
|
||||||
|
auth.database
|
||||||
|
.save_account(&account)
|
||||||
|
.await
|
||||||
|
.map_err(|_| create_database_error!("save_account", "accounts"))?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -288,6 +288,8 @@ auto_derived! {
|
|||||||
Search = 14,
|
Search = 14,
|
||||||
ManageNotes = 15,
|
ManageNotes = 15,
|
||||||
Discover = 16,
|
Discover = 16,
|
||||||
|
|
||||||
|
AccountDisable = 17,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum AdminAuditItemActions {
|
pub enum AdminAuditItemActions {
|
||||||
@@ -317,7 +319,10 @@ auto_derived! {
|
|||||||
ServerSetFlags,
|
ServerSetFlags,
|
||||||
ServerInstanceBanAllMembers,
|
ServerInstanceBanAllMembers,
|
||||||
ServerBanMember,
|
ServerBanMember,
|
||||||
ServerUnbanMember
|
ServerUnbanMember,
|
||||||
|
|
||||||
|
// Accounts
|
||||||
|
AccountDisable
|
||||||
}
|
}
|
||||||
|
|
||||||
// Joiner payloads
|
// Joiner payloads
|
||||||
@@ -365,6 +370,7 @@ impl AdminAuditItemActions {
|
|||||||
AdminAuditItemActions::ServerBanMember => true,
|
AdminAuditItemActions::ServerBanMember => true,
|
||||||
AdminAuditItemActions::ServerUnbanMember => true,
|
AdminAuditItemActions::ServerUnbanMember => true,
|
||||||
AdminAuditItemActions::ServerFetchMembers => false,
|
AdminAuditItemActions::ServerFetchMembers => false,
|
||||||
|
AdminAuditItemActions::AccountDisable => true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,9 +37,7 @@ impl IntoResponse for Error {
|
|||||||
ErrorType::NotAMember => StatusCode::BAD_REQUEST,
|
ErrorType::NotAMember => StatusCode::BAD_REQUEST,
|
||||||
ErrorType::AlreadyPinned => StatusCode::BAD_REQUEST,
|
ErrorType::AlreadyPinned => StatusCode::BAD_REQUEST,
|
||||||
ErrorType::NotPinned => StatusCode::BAD_REQUEST,
|
ErrorType::NotPinned => StatusCode::BAD_REQUEST,
|
||||||
ErrorType::InSlowmode {
|
ErrorType::InSlowmode { retry_after: _ } => StatusCode::TOO_MANY_REQUESTS,
|
||||||
retry_after: _,
|
|
||||||
} => StatusCode::TOO_MANY_REQUESTS,
|
|
||||||
ErrorType::InviteExists => StatusCode::BAD_REQUEST,
|
ErrorType::InviteExists => StatusCode::BAD_REQUEST,
|
||||||
|
|
||||||
ErrorType::CantCreateServers => StatusCode::FORBIDDEN,
|
ErrorType::CantCreateServers => StatusCode::FORBIDDEN,
|
||||||
@@ -98,6 +96,8 @@ impl IntoResponse for Error {
|
|||||||
ErrorType::NoEmbedData => StatusCode::BAD_REQUEST,
|
ErrorType::NoEmbedData => StatusCode::BAD_REQUEST,
|
||||||
|
|
||||||
ErrorType::ImATeaPot => StatusCode::IM_A_TEAPOT,
|
ErrorType::ImATeaPot => StatusCode::IM_A_TEAPOT,
|
||||||
|
|
||||||
|
ErrorType::PrivilegedAccount => StatusCode::FORBIDDEN,
|
||||||
};
|
};
|
||||||
|
|
||||||
(status, Json(&self)).into_response()
|
(status, Json(&self)).into_response()
|
||||||
|
|||||||
@@ -190,6 +190,9 @@ pub enum ErrorType {
|
|||||||
feature: String,
|
feature: String,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// ? Admin API relate errors
|
||||||
|
PrivilegedAccount,
|
||||||
|
|
||||||
// :)
|
// :)
|
||||||
ImATeaPot,
|
ImATeaPot,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,9 +43,7 @@ impl<'r> Responder<'r, 'static> for Error {
|
|||||||
ErrorType::NotAMember => Status::BadRequest,
|
ErrorType::NotAMember => Status::BadRequest,
|
||||||
ErrorType::AlreadyPinned => Status::BadRequest,
|
ErrorType::AlreadyPinned => Status::BadRequest,
|
||||||
ErrorType::NotPinned => Status::BadRequest,
|
ErrorType::NotPinned => Status::BadRequest,
|
||||||
ErrorType::InSlowmode {
|
ErrorType::InSlowmode { retry_after: _ } => Status::TooManyRequests,
|
||||||
retry_after: _,
|
|
||||||
} => Status::TooManyRequests,
|
|
||||||
ErrorType::InvalidFlagValue => Status::BadRequest,
|
ErrorType::InvalidFlagValue => Status::BadRequest,
|
||||||
ErrorType::InviteExists => Status::BadRequest,
|
ErrorType::InviteExists => Status::BadRequest,
|
||||||
|
|
||||||
@@ -104,6 +102,8 @@ impl<'r> Responder<'r, 'static> for Error {
|
|||||||
ErrorType::VosoUnavailable => Status::BadRequest,
|
ErrorType::VosoUnavailable => Status::BadRequest,
|
||||||
|
|
||||||
ErrorType::ImATeaPot => Status::ImATeapot,
|
ErrorType::ImATeaPot => Status::ImATeapot,
|
||||||
|
|
||||||
|
ErrorType::PrivilegedAccount => Status::Forbidden,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Serialize the error data structure into JSON.
|
// Serialize the error data structure into JSON.
|
||||||
|
|||||||
@@ -0,0 +1,53 @@
|
|||||||
|
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;
|
||||||
|
|
||||||
|
/// Disable an account. Requires AccountDisable permissions
|
||||||
|
#[openapi(tag = "Admin")]
|
||||||
|
#[post("/accounts/disable/<id>")]
|
||||||
|
pub async fn admin_account_disable(
|
||||||
|
db: &State<Database>,
|
||||||
|
auth: AdminAuthorization,
|
||||||
|
id: Reference<'_>,
|
||||||
|
) -> Result<()> {
|
||||||
|
let user = flatten_authorized_user(&auth);
|
||||||
|
if !user_has_permission(user, v0::AdminUserPermissionFlags::AccountDisable) {
|
||||||
|
return Err(create_error!(MissingPermission {
|
||||||
|
permission: "AccountDisable".to_string()
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
let target = id.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::AccountDisable) {
|
||||||
|
return Err(create_error!(PrivilegedAccount));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
create_audit_action(
|
||||||
|
db,
|
||||||
|
&user.id,
|
||||||
|
v0::AdminAuditItemActions::AccountDisable,
|
||||||
|
None,
|
||||||
|
Some(id.id),
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
db.disable_authifier_account(&target.id).await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user