Skip to main content

max / multithreaded

5.4 KB · 174 lines History Blame Raw
1 //! Platform admin handlers.
2
3 use axum::{
4 extract::{Path, Query},
5 http::StatusCode,
6 response::{IntoResponse, Redirect, Response},
7 Form,
8 };
9 use tower_sessions::Session;
10
11 use crate::auth::PlatformAdmin;
12 use crate::csrf;
13 use crate::templates::*;
14 use crate::AppState;
15
16 use mt_core::types::ModAction;
17
18 use super::{log_mod_action, parse_uuid, AdminSearchQuery, SuspendForm};
19
20 #[tracing::instrument(skip_all)]
21 pub(super) async fn admin_dashboard(
22 axum::extract::State(state): axum::extract::State<AppState>,
23 session: Session,
24 PlatformAdmin(admin): PlatformAdmin,
25 Query(query): Query<AdminSearchQuery>,
26 ) -> Result<impl IntoResponse, Response> {
27 let csrf_token = Some(csrf::get_or_create_token(&session).await);
28
29 let communities = mt_db::queries::list_all_communities(&state.db)
30 .await
31 .map_err(|e| {
32 tracing::error!(error = ?e, "db error listing communities");
33 StatusCode::INTERNAL_SERVER_ERROR.into_response()
34 })?
35 .into_iter()
36 .map(|c| AdminCommunityViewRow {
37 id: c.id.to_string(),
38 name: c.name,
39 slug: c.slug,
40 is_suspended: c.suspended_at.is_some(),
41 suspension_reason: c.suspension_reason,
42 })
43 .collect();
44
45 let search_query = query.q.unwrap_or_default();
46 let users = if !search_query.is_empty() {
47 mt_db::queries::search_users(&state.db, &search_query)
48 .await
49 .map_err(|e| {
50 tracing::error!(error = ?e, "db error searching users");
51 StatusCode::INTERNAL_SERVER_ERROR.into_response()
52 })?
53 .into_iter()
54 .map(|u| AdminUserViewRow {
55 id: u.id.to_string(),
56 username: u.username,
57 display_name: u.display_name,
58 is_suspended: u.suspended_at.is_some(),
59 suspension_reason: u.suspension_reason,
60 })
61 .collect()
62 } else {
63 vec![]
64 };
65
66 Ok(AdminDashboardTemplate {
67 csrf_token,
68 session_user: Some(TemplateSessionUser {
69 is_platform_admin: true,
70 username: admin.username,
71 }),
72 mnw_base_url: state.config.mnw_base_url.clone(),
73 communities,
74 users,
75 search_query,
76 })
77 }
78
79 #[tracing::instrument(skip_all)]
80 pub(super) async fn suspend_community_handler(
81 axum::extract::State(state): axum::extract::State<AppState>,
82 PlatformAdmin(admin): PlatformAdmin,
83 Path(id): Path<String>,
84 Form(form): Form<SuspendForm>,
85 ) -> Result<Redirect, Response> {
86 let community_id = parse_uuid(&id)?;
87 let reason = form.reason.as_deref().filter(|r| !r.trim().is_empty());
88
89 mt_db::mutations::suspend_community(&state.db, community_id, reason)
90 .await
91 .map_err(|e| {
92 tracing::error!(error = ?e, "db error suspending community");
93 StatusCode::INTERNAL_SERVER_ERROR.into_response()
94 })?;
95
96 log_mod_action(
97 &state.db, None, admin.user_id,
98 ModAction::SuspendCommunity, None, Some(community_id), reason,
99 ).await;
100
101 Ok(Redirect::to("/_admin?toast=Community+suspended"))
102 }
103
104 #[tracing::instrument(skip_all)]
105 pub(super) async fn unsuspend_community_handler(
106 axum::extract::State(state): axum::extract::State<AppState>,
107 PlatformAdmin(admin): PlatformAdmin,
108 Path(id): Path<String>,
109 ) -> Result<Redirect, Response> {
110 let community_id = parse_uuid(&id)?;
111
112 mt_db::mutations::unsuspend_community(&state.db, community_id)
113 .await
114 .map_err(|e| {
115 tracing::error!(error = ?e, "db error unsuspending community");
116 StatusCode::INTERNAL_SERVER_ERROR.into_response()
117 })?;
118
119 log_mod_action(
120 &state.db, None, admin.user_id,
121 ModAction::UnsuspendCommunity, None, Some(community_id), None,
122 ).await;
123
124 Ok(Redirect::to("/_admin?toast=Community+unsuspended"))
125 }
126
127 #[tracing::instrument(skip_all)]
128 pub(super) async fn suspend_user_handler(
129 axum::extract::State(state): axum::extract::State<AppState>,
130 PlatformAdmin(admin): PlatformAdmin,
131 Path(id): Path<String>,
132 Form(form): Form<SuspendForm>,
133 ) -> Result<Redirect, Response> {
134 let user_id = parse_uuid(&id)?;
135 let reason = form.reason.as_deref().filter(|r| !r.trim().is_empty());
136
137 mt_db::mutations::suspend_user(&state.db, user_id, reason)
138 .await
139 .map_err(|e| {
140 tracing::error!(error = ?e, "db error suspending user");
141 StatusCode::INTERNAL_SERVER_ERROR.into_response()
142 })?;
143
144 log_mod_action(
145 &state.db, None, admin.user_id,
146 ModAction::SuspendUser, Some(user_id), None, reason,
147 ).await;
148
149 Ok(Redirect::to("/_admin?toast=User+suspended"))
150 }
151
152 #[tracing::instrument(skip_all)]
153 pub(super) async fn unsuspend_user_handler(
154 axum::extract::State(state): axum::extract::State<AppState>,
155 PlatformAdmin(admin): PlatformAdmin,
156 Path(id): Path<String>,
157 ) -> Result<Redirect, Response> {
158 let user_id = parse_uuid(&id)?;
159
160 mt_db::mutations::unsuspend_user(&state.db, user_id)
161 .await
162 .map_err(|e| {
163 tracing::error!(error = ?e, "db error unsuspending user");
164 StatusCode::INTERNAL_SERVER_ERROR.into_response()
165 })?;
166
167 log_mod_action(
168 &state.db, None, admin.user_id,
169 ModAction::UnsuspendUser, Some(user_id), None, None,
170 ).await;
171
172 Ok(Redirect::to("/_admin?toast=User+unsuspended"))
173 }
174