add: user ban_reason
This commit is contained in:
parent
b25bda29b8
commit
d1c3643574
11 changed files with 100 additions and 9 deletions
|
@ -198,6 +198,7 @@ version = "1.0.0"
|
|||
"mod_panel:label.associations" = "Associations"
|
||||
"mod_panel:label.invited_by" = "Invited by"
|
||||
"mod_panel:label.send_debug_payload" = "Send debug payload"
|
||||
"mod_panel:label.ban_reason" = "Ban reason"
|
||||
"mod_panel:action.send" = "Send"
|
||||
|
||||
"requests:label.requests" = "Requests"
|
||||
|
|
|
@ -87,7 +87,10 @@ macro_rules! get_user_from_token {
|
|||
{
|
||||
Ok(ua) => {
|
||||
if ua.permissions.check_banned() {
|
||||
Some(tetratto_core::model::auth::User::banned())
|
||||
let mut banned_user = tetratto_core::model::auth::User::banned();
|
||||
banned_user.ban_reason = ua.ban_reason;
|
||||
|
||||
Some(banned_user)
|
||||
} else {
|
||||
Some(ua)
|
||||
}
|
||||
|
|
|
@ -102,7 +102,11 @@
|
|||
("class" "flush")
|
||||
("style" "font-weight: 600")
|
||||
("target" "_top")
|
||||
(text "{{ self::username(user=user) }}"))
|
||||
(text "{% if user.permissions|has_banned -%}")
|
||||
(del ("class" "fade") (text "{{ self::username(user=user) }}"))
|
||||
(text "{% else %}")
|
||||
(text "{{ self::username(user=user) }}")
|
||||
(text "{%- endif %}"))
|
||||
(text "{{ self::online_indicator(user=user) }} {% if user.is_verified -%}")
|
||||
(span
|
||||
("title" "Verified")
|
||||
|
|
|
@ -84,7 +84,7 @@
|
|||
const ui = await ns(\"ui\");
|
||||
const element = document.getElementById(\"mod_options\");
|
||||
|
||||
async function profile_request(do_confirm, path, body) {
|
||||
globalThis.profile_request = async (do_confirm, path, body) => {
|
||||
if (do_confirm) {
|
||||
if (
|
||||
!(await trigger(\"atto::confirm\", [
|
||||
|
@ -273,6 +273,33 @@
|
|||
("class" "card lowered flex flex-wrap gap-2")
|
||||
(text "{{ components::user_plate(user=invite[0], show_menu=false) }}")))
|
||||
(text "{%- endif %}")
|
||||
(div
|
||||
("class" "card-nest w-full")
|
||||
(div
|
||||
("class" "card small flex items-center justify-between gap-2")
|
||||
(div
|
||||
("class" "flex items-center gap-2")
|
||||
(icon (text "scale"))
|
||||
(span
|
||||
(str (text "mod_panel:label.ban_reason")))))
|
||||
(form
|
||||
("class" "card flex flex-col gap-2")
|
||||
("onsubmit" "event.preventDefault(); profile_request(false, 'ban_reason', { reason: event.target.reason.value || '' })")
|
||||
(div
|
||||
("class" "flex flex-col gap-1")
|
||||
(label
|
||||
("for" "title")
|
||||
(str (text "mod_panel:label.ban_reason")))
|
||||
(textarea
|
||||
("type" "text")
|
||||
("name" "reason")
|
||||
("id" "reason")
|
||||
("placeholder" "ban reason")
|
||||
("minlength" "2")
|
||||
(text "{{ profile.ban_reason|remove_script_tags|safe }}")))
|
||||
(button
|
||||
("class" "primary")
|
||||
(str (text "general:action.save")))))
|
||||
(div
|
||||
("class" "card-nest w-full")
|
||||
(div
|
||||
|
|
|
@ -70,8 +70,13 @@
|
|||
(str (text "general:label.account_banned")))
|
||||
|
||||
(div
|
||||
("class" "card")
|
||||
(str (text "general:label.account_banned_body"))))))
|
||||
("class" "card flex flex-col gap-2 no_p_margin")
|
||||
(str (text "general:label.account_banned_body"))
|
||||
(hr)
|
||||
(span ("class" "fade") (text "The following reason was provided by a moderator:"))
|
||||
(div
|
||||
("class" "card lowered w-full")
|
||||
(text "{{ user.ban_reason|markdown|safe }}"))))))
|
||||
|
||||
; if we aren't banned, just show the page body
|
||||
(text "{% elif user and user.awaiting_purchase %}")
|
||||
|
|
|
@ -4,8 +4,9 @@ use crate::{
|
|||
model::{ApiReturn, Error},
|
||||
routes::api::v1::{
|
||||
AppendAssociations, AwardAchievement, DeleteUser, DisableTotp, RefreshGrantToken,
|
||||
UpdateSecondaryUserRole, UpdateUserAwaitingPurchase, UpdateUserInviteCode,
|
||||
UpdateUserIsVerified, UpdateUserPassword, UpdateUserRole, UpdateUserUsername,
|
||||
UpdateSecondaryUserRole, UpdateUserAwaitingPurchase, UpdateUserBanReason,
|
||||
UpdateUserInviteCode, UpdateUserIsVerified, UpdateUserPassword, UpdateUserRole,
|
||||
UpdateUserUsername,
|
||||
},
|
||||
State,
|
||||
};
|
||||
|
@ -424,6 +425,35 @@ pub async fn update_user_secondary_role_request(
|
|||
}
|
||||
}
|
||||
|
||||
/// Update the ban reason of the given user.
|
||||
///
|
||||
/// Does not support third-party grants.
|
||||
pub async fn update_user_ban_reason_request(
|
||||
jar: CookieJar,
|
||||
Path(id): Path<usize>,
|
||||
Extension(data): Extension<State>,
|
||||
Json(req): Json<UpdateUserBanReason>,
|
||||
) -> impl IntoResponse {
|
||||
let data = &(data.read().await).0;
|
||||
let user = match get_user_from_token!(jar, data) {
|
||||
Some(ua) => ua,
|
||||
None => return Json(Error::NotAllowed.into()),
|
||||
};
|
||||
|
||||
if !user.permissions.check(FinePermission::MANAGE_USERS) {
|
||||
return Json(Error::NotAllowed.into());
|
||||
}
|
||||
|
||||
match data.update_user_ban_reason(id, &req.reason).await {
|
||||
Ok(_) => Json(ApiReturn {
|
||||
ok: true,
|
||||
message: "User updated".to_string(),
|
||||
payload: (),
|
||||
}),
|
||||
Err(e) => Json(e.into()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Update the current user's last seen value.
|
||||
pub async fn seen_request(jar: CookieJar, Extension(data): Extension<State>) -> impl IntoResponse {
|
||||
let data = &(data.read().await).0;
|
||||
|
|
|
@ -322,6 +322,10 @@ pub fn routes() -> Router {
|
|||
"/auth/user/{id}/role/2",
|
||||
post(auth::profile::update_user_secondary_role_request),
|
||||
)
|
||||
.route(
|
||||
"/auth/user/{id}/ban_reason",
|
||||
post(auth::profile::update_user_ban_reason_request),
|
||||
)
|
||||
.route(
|
||||
"/auth/user/{id}",
|
||||
delete(auth::profile::delete_user_request),
|
||||
|
@ -840,6 +844,11 @@ pub struct UpdateSecondaryUserRole {
|
|||
pub role: SecondaryPermission,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct UpdateUserBanReason {
|
||||
pub reason: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct UpdateUserInviteCode {
|
||||
pub invite_code: String,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue