mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-13 05:12:50 +00:00
list audit logs handler
This commit is contained in:
1 parent
3c2db53a27
commit
53df3097a5
9 files changed
+549
No files matched your search
+146
@@ -0,0 +1,146 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "\nSELECT\n sal.id,\n sal.token as `token: StaffAuditLogToken`,\n sal.audit_action,\n sal.maybe_entity_type,\n sal.maybe_entity_token,\n target_user.username as maybe_target_username,\n target_user.display_name as maybe_target_display_name,\n sal.staff_user_token as `staff_user_token: UserToken`,\n staff_user.username as staff_username,\n staff_user.display_name as staff_display_name,\n sal.staff_ip_address,\n sal.created_at\nFROM staff_audit_logs sal\nLEFT JOIN users target_user ON target_user.token = sal.maybe_entity_token\nLEFT JOIN users staff_user ON staff_user.token = sal.staff_user_token\nORDER BY sal.id DESC\nLIMIT ?\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "id",
|
||||
"type_info": {
|
||||
"type": "LongLong",
|
||||
"flags": "NOT_NULL | PRIMARY_KEY | UNSIGNED | AUTO_INCREMENT",
|
||||
"char_set": 63,
|
||||
"max_size": 20
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "token: StaffAuditLogToken",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | UNIQUE_KEY | BINARY | NO_DEFAULT_VALUE",
|
||||
"char_set": 224,
|
||||
"max_size": 128
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 2,
|
||||
"name": "audit_action",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | BINARY | NO_DEFAULT_VALUE",
|
||||
"char_set": 224,
|
||||
"max_size": 128
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 3,
|
||||
"name": "maybe_entity_type",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "MULTIPLE_KEY | BINARY",
|
||||
"char_set": 224,
|
||||
"max_size": 64
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 4,
|
||||
"name": "maybe_entity_token",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | MULTIPLE_KEY | BINARY | NO_DEFAULT_VALUE",
|
||||
"char_set": 224,
|
||||
"max_size": 128
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 5,
|
||||
"name": "maybe_target_username",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "UNIQUE_KEY | BINARY | NO_DEFAULT_VALUE",
|
||||
"char_set": 224,
|
||||
"max_size": 80
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 6,
|
||||
"name": "maybe_target_display_name",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "BINARY | NO_DEFAULT_VALUE",
|
||||
"char_set": 224,
|
||||
"max_size": 80
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 7,
|
||||
"name": "staff_user_token: UserToken",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "MULTIPLE_KEY | BINARY",
|
||||
"char_set": 224,
|
||||
"max_size": 128
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 8,
|
||||
"name": "staff_username",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "UNIQUE_KEY | BINARY | NO_DEFAULT_VALUE",
|
||||
"char_set": 224,
|
||||
"max_size": 80
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 9,
|
||||
"name": "staff_display_name",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "BINARY | NO_DEFAULT_VALUE",
|
||||
"char_set": 224,
|
||||
"max_size": 80
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 10,
|
||||
"name": "staff_ip_address",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | BINARY | NO_DEFAULT_VALUE",
|
||||
"char_set": 224,
|
||||
"max_size": 160
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 11,
|
||||
"name": "created_at",
|
||||
"type_info": {
|
||||
"type": "Timestamp",
|
||||
"flags": "NOT_NULL | MULTIPLE_KEY | BINARY | TIMESTAMP",
|
||||
"char_set": 63,
|
||||
"max_size": 19
|
||||
}
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Right": 1
|
||||
},
|
||||
"nullable": [
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "3846628765bd34ea2ce01e15a0db732121ce473c5c542d0e971ad29b2b421193"
|
||||
}
|
||||
+146
@@ -0,0 +1,146 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "\nSELECT\n sal.id,\n sal.token as `token: StaffAuditLogToken`,\n sal.audit_action,\n sal.maybe_entity_type,\n sal.maybe_entity_token,\n target_user.username as maybe_target_username,\n target_user.display_name as maybe_target_display_name,\n sal.staff_user_token as `staff_user_token: UserToken`,\n staff_user.username as staff_username,\n staff_user.display_name as staff_display_name,\n sal.staff_ip_address,\n sal.created_at\nFROM staff_audit_logs sal\nLEFT JOIN users target_user ON target_user.token = sal.maybe_entity_token\nLEFT JOIN users staff_user ON staff_user.token = sal.staff_user_token\nWHERE sal.id < ?\nORDER BY sal.id DESC\nLIMIT ?\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "id",
|
||||
"type_info": {
|
||||
"type": "LongLong",
|
||||
"flags": "NOT_NULL | PRIMARY_KEY | UNSIGNED | AUTO_INCREMENT",
|
||||
"char_set": 63,
|
||||
"max_size": 20
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "token: StaffAuditLogToken",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | UNIQUE_KEY | BINARY | NO_DEFAULT_VALUE",
|
||||
"char_set": 224,
|
||||
"max_size": 128
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 2,
|
||||
"name": "audit_action",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | BINARY | NO_DEFAULT_VALUE",
|
||||
"char_set": 224,
|
||||
"max_size": 128
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 3,
|
||||
"name": "maybe_entity_type",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "MULTIPLE_KEY | BINARY",
|
||||
"char_set": 224,
|
||||
"max_size": 64
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 4,
|
||||
"name": "maybe_entity_token",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | MULTIPLE_KEY | BINARY | NO_DEFAULT_VALUE",
|
||||
"char_set": 224,
|
||||
"max_size": 128
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 5,
|
||||
"name": "maybe_target_username",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "UNIQUE_KEY | BINARY | NO_DEFAULT_VALUE",
|
||||
"char_set": 224,
|
||||
"max_size": 80
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 6,
|
||||
"name": "maybe_target_display_name",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "BINARY | NO_DEFAULT_VALUE",
|
||||
"char_set": 224,
|
||||
"max_size": 80
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 7,
|
||||
"name": "staff_user_token: UserToken",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "MULTIPLE_KEY | BINARY",
|
||||
"char_set": 224,
|
||||
"max_size": 128
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 8,
|
||||
"name": "staff_username",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "UNIQUE_KEY | BINARY | NO_DEFAULT_VALUE",
|
||||
"char_set": 224,
|
||||
"max_size": 80
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 9,
|
||||
"name": "staff_display_name",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "BINARY | NO_DEFAULT_VALUE",
|
||||
"char_set": 224,
|
||||
"max_size": 80
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 10,
|
||||
"name": "staff_ip_address",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | BINARY | NO_DEFAULT_VALUE",
|
||||
"char_set": 224,
|
||||
"max_size": 160
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 11,
|
||||
"name": "created_at",
|
||||
"type_info": {
|
||||
"type": "Timestamp",
|
||||
"flags": "NOT_NULL | MULTIPLE_KEY | BINARY | TIMESTAMP",
|
||||
"char_set": 63,
|
||||
"max_size": 19
|
||||
}
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Right": 2
|
||||
},
|
||||
"nullable": [
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "9132f832752ea40736bedf4729c76af7fe019cc69ed5cc280fce87e68c3f4846"
|
||||
}
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
use chrono::{DateTime, Utc};
|
||||
use sqlx::MySqlPool;
|
||||
|
||||
use tokens::tokens::staff_audit_logs::StaffAuditLogToken;
|
||||
use tokens::tokens::users::UserToken;
|
||||
|
||||
pub struct StaffAuditLogListItem {
|
||||
pub id: u64,
|
||||
pub token: StaffAuditLogToken,
|
||||
pub audit_action: String,
|
||||
pub maybe_entity_type: Option<String>,
|
||||
pub maybe_entity_token: Option<String>,
|
||||
pub maybe_target_username: Option<String>,
|
||||
pub maybe_target_display_name: Option<String>,
|
||||
pub staff_user_token: Option<UserToken>,
|
||||
pub staff_username: Option<String>,
|
||||
pub staff_display_name: Option<String>,
|
||||
pub staff_ip_address: String,
|
||||
pub created_at: DateTime<Utc>,
|
||||
}
|
||||
|
||||
pub struct ListStaffAuditLogsArgs<'a> {
|
||||
pub maybe_cursor_id: Option<u64>,
|
||||
pub limit: u32,
|
||||
pub mysql_pool: &'a MySqlPool,
|
||||
}
|
||||
|
||||
pub async fn list_staff_audit_logs(
|
||||
args: ListStaffAuditLogsArgs<'_>,
|
||||
) -> Result<Vec<StaffAuditLogListItem>, sqlx::Error> {
|
||||
|
||||
let limit = args.limit as i64;
|
||||
|
||||
let items = match args.maybe_cursor_id {
|
||||
Some(cursor_id) => {
|
||||
sqlx::query_as!(
|
||||
StaffAuditLogListItem,
|
||||
r#"
|
||||
SELECT
|
||||
sal.id,
|
||||
sal.token as `token: StaffAuditLogToken`,
|
||||
sal.audit_action,
|
||||
sal.maybe_entity_type,
|
||||
sal.maybe_entity_token,
|
||||
target_user.username as maybe_target_username,
|
||||
target_user.display_name as maybe_target_display_name,
|
||||
sal.staff_user_token as `staff_user_token: UserToken`,
|
||||
staff_user.username as staff_username,
|
||||
staff_user.display_name as staff_display_name,
|
||||
sal.staff_ip_address,
|
||||
sal.created_at
|
||||
FROM staff_audit_logs sal
|
||||
LEFT JOIN users target_user ON target_user.token = sal.maybe_entity_token
|
||||
LEFT JOIN users staff_user ON staff_user.token = sal.staff_user_token
|
||||
WHERE sal.id < ?
|
||||
ORDER BY sal.id DESC
|
||||
LIMIT ?
|
||||
"#,
|
||||
cursor_id as u64,
|
||||
limit,
|
||||
)
|
||||
.fetch_all(args.mysql_pool)
|
||||
.await?
|
||||
}
|
||||
None => {
|
||||
sqlx::query_as!(
|
||||
StaffAuditLogListItem,
|
||||
r#"
|
||||
SELECT
|
||||
sal.id,
|
||||
sal.token as `token: StaffAuditLogToken`,
|
||||
sal.audit_action,
|
||||
sal.maybe_entity_type,
|
||||
sal.maybe_entity_token,
|
||||
target_user.username as maybe_target_username,
|
||||
target_user.display_name as maybe_target_display_name,
|
||||
sal.staff_user_token as `staff_user_token: UserToken`,
|
||||
staff_user.username as staff_username,
|
||||
staff_user.display_name as staff_display_name,
|
||||
sal.staff_ip_address,
|
||||
sal.created_at
|
||||
FROM staff_audit_logs sal
|
||||
LEFT JOIN users target_user ON target_user.token = sal.maybe_entity_token
|
||||
LEFT JOIN users staff_user ON staff_user.token = sal.staff_user_token
|
||||
ORDER BY sal.id DESC
|
||||
LIMIT ?
|
||||
"#,
|
||||
limit,
|
||||
)
|
||||
.fetch_all(args.mysql_pool)
|
||||
.await?
|
||||
}
|
||||
};
|
||||
|
||||
Ok(items)
|
||||
}
|
||||
@@ -1 +1,2 @@
|
||||
pub mod insert_staff_audit_log;
|
||||
pub mod list_staff_audit_logs;
|
||||
@@ -86,6 +86,7 @@ use crate::http_server::endpoints::media_files::upsert_upload::write_error::Medi
|
||||
use crate::http_server::endpoints::media_files::upsert_upload::write_scene_file::write_scene_file_media_file_handler::*;
|
||||
use crate::http_server::endpoints::model_download::enqueue_gptsovits_model_download_handler::*;
|
||||
use crate::http_server::endpoints::moderation::user_feature_flags::edit_user_feature_flags_handler::*;
|
||||
use crate::http_server::endpoints::moderation::staff_audit_logs::moderator_list_staff_audit_logs_handler::*;
|
||||
use crate::http_server::endpoints::moderation::user_sessions::moderator_list_user_session_impersonation_requests_for_user_handler::*;
|
||||
use crate::http_server::endpoints::moderation::user_sessions::moderator_list_user_session_impersonation_requests_handler::*;
|
||||
use crate::http_server::endpoints::moderation::user_sessions::moderator_user_session_impersonation_request_handler::*;
|
||||
@@ -510,6 +511,7 @@ use crate::http_server::endpoints::media_files::list::list_batch_generated_redux
|
||||
crate::http_server::endpoints::moderation::wallets::moderator_add_banked_balance_to_wallet_handler::moderator_add_banked_balance_to_wallet_handler,
|
||||
crate::http_server::endpoints::moderation::wallets::moderator_create_wallet_for_user_handler::moderator_create_wallet_for_user_handler,
|
||||
crate::http_server::endpoints::moderation::wallets::moderator_get_wallet_handler::moderator_get_wallet_handler,
|
||||
crate::http_server::endpoints::moderation::staff_audit_logs::moderator_list_staff_audit_logs_handler::moderator_list_staff_audit_logs_handler,
|
||||
crate::http_server::endpoints::moderation::user_sessions::moderator_list_user_session_impersonation_requests_for_user_handler::moderator_list_user_session_impersonation_requests_for_user_handler,
|
||||
crate::http_server::endpoints::moderation::user_sessions::moderator_list_user_session_impersonation_requests_handler::moderator_list_user_session_impersonation_requests_handler,
|
||||
crate::http_server::endpoints::moderation::user_sessions::moderator_user_session_impersonation_request_handler::moderator_user_session_impersonation_request_handler,
|
||||
@@ -895,6 +897,8 @@ use crate::http_server::endpoints::media_files::list::list_batch_generated_redux
|
||||
ListAllImpersonationRequestsQueryParams,
|
||||
ListAllImpersonationRequestsSuccessResponse,
|
||||
ListImpersonationRequestsPathInfo,
|
||||
ListStaffAuditLogsQueryParams,
|
||||
ListStaffAuditLogsSuccessResponse,
|
||||
ListImpersonationRequestsQueryParams,
|
||||
ListUserImpersonationRequestsSuccessResponse,
|
||||
ListMediaFilesByBatchPathInfo,
|
||||
@@ -960,6 +964,7 @@ use crate::http_server::endpoints::media_files::list::list_batch_generated_redux
|
||||
RenameMediaFileRequest,
|
||||
RequestDetailsResponse,
|
||||
ResultDetailsResponse,
|
||||
StaffAuditLogResponse,
|
||||
SearchFeaturedMediaFileListItem,
|
||||
SearchFeaturedMediaFilesError,
|
||||
SearchFeaturedMediaFilesQueryParams,
|
||||
|
||||
@@ -2,6 +2,7 @@ pub mod alerts;
|
||||
pub mod info;
|
||||
pub mod ip_bans;
|
||||
pub mod jobs;
|
||||
pub mod staff_audit_logs;
|
||||
pub mod user;
|
||||
pub mod user_bans;
|
||||
pub mod user_feature_flags;
|
||||
|
||||
+1
@@ -0,0 +1 @@
|
||||
pub mod moderator_list_staff_audit_logs_handler;
|
||||
+146
@@ -0,0 +1,146 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use actix_web::web::{Json, Query};
|
||||
use actix_web::{web, HttpRequest};
|
||||
use chrono::{DateTime, Utc};
|
||||
use log::warn;
|
||||
use utoipa::{IntoParams, ToSchema};
|
||||
|
||||
use mysql_queries::queries::staff_audit_logs::list_staff_audit_logs::{
|
||||
list_staff_audit_logs, ListStaffAuditLogsArgs,
|
||||
};
|
||||
use tokens::tokens::staff_audit_logs::StaffAuditLogToken;
|
||||
use tokens::tokens::users::UserToken;
|
||||
|
||||
use crate::http_server::common_responses::advanced_common_web_error::AdvancedCommonWebError;
|
||||
use crate::http_server::web_utils::user_session::require_moderator::{
|
||||
require_moderator, UseDatabase,
|
||||
};
|
||||
use crate::state::server_state::ServerState;
|
||||
|
||||
const CURSOR_NAME: &str = "modstfaud";
|
||||
const DEFAULT_LIMIT: u32 = 50;
|
||||
const MAX_LIMIT: u32 = 1000;
|
||||
|
||||
// --- Request ---
|
||||
|
||||
#[derive(Deserialize, ToSchema, IntoParams)]
|
||||
pub struct ListStaffAuditLogsQueryParams {
|
||||
pub cursor: Option<String>,
|
||||
pub limit: Option<u32>,
|
||||
}
|
||||
|
||||
// --- Response ---
|
||||
|
||||
#[derive(Serialize, ToSchema)]
|
||||
pub struct ListStaffAuditLogsSuccessResponse {
|
||||
pub success: bool,
|
||||
pub audit_logs: Vec<StaffAuditLogResponse>,
|
||||
pub maybe_cursor: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, ToSchema)]
|
||||
pub struct StaffAuditLogResponse {
|
||||
pub token: StaffAuditLogToken,
|
||||
pub audit_action: String,
|
||||
pub maybe_entity_type: Option<String>,
|
||||
pub maybe_entity_token: Option<String>,
|
||||
pub maybe_target_username: Option<String>,
|
||||
pub maybe_target_display_name: Option<String>,
|
||||
pub staff_user_token: Option<UserToken>,
|
||||
pub staff_username: Option<String>,
|
||||
pub staff_display_name: Option<String>,
|
||||
pub staff_ip_address: String,
|
||||
pub created_at: DateTime<Utc>,
|
||||
}
|
||||
|
||||
// --- Handler ---
|
||||
|
||||
/// List all staff audit logs. Moderators only.
|
||||
#[utoipa::path(
|
||||
get,
|
||||
tag = "Moderation",
|
||||
path = "/v1/moderation/staff_audit_logs/list",
|
||||
params(
|
||||
ListStaffAuditLogsQueryParams,
|
||||
),
|
||||
responses(
|
||||
(status = 200, description = "Success", body = ListStaffAuditLogsSuccessResponse),
|
||||
(status = 401, description = "Unauthorized"),
|
||||
(status = 500, description = "Server error"),
|
||||
),
|
||||
)]
|
||||
pub async fn moderator_list_staff_audit_logs_handler(
|
||||
http_request: HttpRequest,
|
||||
query: Query<ListStaffAuditLogsQueryParams>,
|
||||
server_state: web::Data<Arc<ServerState>>,
|
||||
) -> Result<Json<ListStaffAuditLogsSuccessResponse>, AdvancedCommonWebError> {
|
||||
|
||||
let _user_session = require_moderator(
|
||||
&http_request,
|
||||
&server_state,
|
||||
UseDatabase::GrabNewConnection,
|
||||
).await.map_err(|err| {
|
||||
warn!("Moderator check failed: {:?}", err);
|
||||
AdvancedCommonWebError::NotAuthorized
|
||||
})?;
|
||||
|
||||
let limit = query.limit
|
||||
.unwrap_or(DEFAULT_LIMIT)
|
||||
.min(MAX_LIMIT);
|
||||
|
||||
let maybe_cursor_id = match &query.cursor {
|
||||
None => None,
|
||||
Some(cursor_str) => {
|
||||
let decoded = server_state.opaque_cursors
|
||||
.decode_cursor_expecting_name(CURSOR_NAME, cursor_str)
|
||||
.map_err(|err| {
|
||||
warn!("Failed to decode cursor: {:?}", err);
|
||||
AdvancedCommonWebError::BadInputWithSimpleMessage(
|
||||
"Invalid cursor".to_string())
|
||||
})?;
|
||||
decoded.last_id
|
||||
}
|
||||
};
|
||||
|
||||
let records = list_staff_audit_logs(
|
||||
ListStaffAuditLogsArgs {
|
||||
maybe_cursor_id,
|
||||
limit,
|
||||
mysql_pool: &server_state.mysql_pool,
|
||||
},
|
||||
).await.map_err(|err| {
|
||||
warn!("Failed to list staff audit logs: {:?}", err);
|
||||
AdvancedCommonWebError::from_error(err)
|
||||
})?;
|
||||
|
||||
let maybe_cursor = records.last().map(|last| {
|
||||
server_state.opaque_cursors
|
||||
.encode_last_id_cursor(CURSOR_NAME, last.id)
|
||||
}).transpose().map_err(|err| {
|
||||
warn!("Failed to encode cursor: {:?}", err);
|
||||
AdvancedCommonWebError::server_error_with_message("Failed to encode cursor")
|
||||
})?;
|
||||
|
||||
let audit_logs = records.into_iter().map(|r| {
|
||||
StaffAuditLogResponse {
|
||||
token: r.token,
|
||||
audit_action: r.audit_action,
|
||||
maybe_entity_type: r.maybe_entity_type,
|
||||
maybe_entity_token: r.maybe_entity_token,
|
||||
maybe_target_username: r.maybe_target_username,
|
||||
maybe_target_display_name: r.maybe_target_display_name,
|
||||
staff_user_token: r.staff_user_token,
|
||||
staff_username: r.staff_username,
|
||||
staff_display_name: r.staff_display_name,
|
||||
staff_ip_address: r.staff_ip_address,
|
||||
created_at: r.created_at,
|
||||
}
|
||||
}).collect();
|
||||
|
||||
Ok(Json(ListStaffAuditLogsSuccessResponse {
|
||||
success: true,
|
||||
audit_logs,
|
||||
maybe_cursor,
|
||||
}))
|
||||
}
|
||||
+7
@@ -35,6 +35,7 @@ use crate::http_server::endpoints::moderation::user::moderator_list_users_by_sig
|
||||
use crate::http_server::endpoints::moderation::user::moderator_user_lookup_by_stripe_customer_id_handler::moderator_user_lookup_by_stripe_customer_id_handler;
|
||||
use crate::http_server::endpoints::moderation::user::moderator_user_lookup_handler::moderator_user_lookup_handler;
|
||||
use crate::http_server::endpoints::moderation::alerts::moderation_send_alert_handler::moderation_send_alert_handler;
|
||||
use crate::http_server::endpoints::moderation::staff_audit_logs::moderator_list_staff_audit_logs_handler::moderator_list_staff_audit_logs_handler;
|
||||
use crate::http_server::endpoints::moderation::user_feature_flags::edit_user_feature_flags_handler::edit_user_feature_flags_handler;
|
||||
use crate::http_server::endpoints::moderation::user_sessions::moderator_list_user_session_impersonation_requests_for_user_handler::moderator_list_user_session_impersonation_requests_for_user_handler;
|
||||
use crate::http_server::endpoints::moderation::user_sessions::moderator_list_user_session_impersonation_requests_handler::moderator_list_user_session_impersonation_requests_handler;
|
||||
@@ -106,6 +107,12 @@ pub fn add_moderator_routes<T, B> (app: App<T>) -> App<T>
|
||||
.route(web::head().to(|| HttpResponse::Ok()))
|
||||
)
|
||||
)
|
||||
.service(web::scope("/staff_audit_logs")
|
||||
.service(web::resource("/list")
|
||||
.route(web::get().to(moderator_list_staff_audit_logs_handler))
|
||||
.route(web::head().to(|| HttpResponse::Ok()))
|
||||
)
|
||||
)
|
||||
.service(web::scope("/user_sessions")
|
||||
.service(web::resource("/impersonate")
|
||||
.route(web::post().to(moderator_user_session_impersonation_request_handler))
|
||||
|
||||
Reference in new issue
Block a user