feat: add admin work visibility controls

This commit is contained in:
kdletters
2026-05-28 00:49:45 +08:00
parent 8e96c8a67c
commit dbbd48083a
38 changed files with 1807 additions and 89 deletions

View File

@@ -24,7 +24,9 @@ use shared_contracts::admin::{
AdminDebugHeaderInput, AdminDebugHttpRequest, AdminDebugHttpResponse, AdminLoginRequest,
AdminLoginResponse, AdminMeResponse, AdminOverviewResponse, AdminServiceOverviewPayload,
AdminSessionPayload, AdminTrackingEventEntryPayload, AdminTrackingEventListQuery,
AdminTrackingEventListResponse, AdminUpsertCreationEntryTypeConfigRequest,
AdminTrackingEventListResponse, AdminUpdateWorkVisibilityRequest,
AdminUpdateWorkVisibilityResponse, AdminUpsertCreationEntryTypeConfigRequest,
AdminWorkVisibilityListResponse,
};
use time::{OffsetDateTime, format_description::well_known::Rfc3339};
@@ -239,6 +241,40 @@ pub async fn admin_upsert_creation_entry_config(
))
}
pub async fn admin_list_work_visibility(
State(state): State<AppState>,
Extension(request_context): Extension<RequestContext>,
Extension(admin): Extension<AuthenticatedAdmin>,
) -> Result<Json<Value>, AppError> {
let admin_user_id = admin.session().subject.clone();
let entries = state
.list_admin_work_visibility(admin_user_id)
.await
.map_err(map_admin_spacetime_error)?;
Ok(json_success_body(
Some(&request_context),
AdminWorkVisibilityListResponse { entries },
))
}
pub async fn admin_update_work_visibility(
State(state): State<AppState>,
Extension(request_context): Extension<RequestContext>,
Extension(admin): Extension<AuthenticatedAdmin>,
Json(payload): Json<AdminUpdateWorkVisibilityRequest>,
) -> Result<Json<Value>, AppError> {
let entry = validate_admin_work_visibility(payload)?;
let admin_user_id = admin.session().subject.clone();
let record = state
.update_admin_work_visibility(admin_user_id, entry.0, entry.1, entry.2)
.await
.map_err(map_admin_spacetime_error)?;
Ok(json_success_body(
Some(&request_context),
AdminUpdateWorkVisibilityResponse { entry: record },
))
}
fn map_admin_creation_entry_type_config(
entry: shared_contracts::creation_entry_config::CreationEntryTypeResponse,
) -> AdminCreationEntryTypeConfigPayload {
@@ -284,6 +320,20 @@ fn validate_admin_creation_entry_config(
})
}
fn validate_admin_work_visibility(
payload: AdminUpdateWorkVisibilityRequest,
) -> Result<(String, String, bool), AppError> {
let source_type = payload.source_type.trim().to_string();
if source_type.is_empty() {
return Err(AppError::from_status(StatusCode::BAD_REQUEST).with_message("sourceType 不能为空"));
}
let profile_id = payload.profile_id.trim().to_string();
if profile_id.is_empty() {
return Err(AppError::from_status(StatusCode::BAD_REQUEST).with_message("profileId 不能为空"));
}
Ok((source_type, profile_id, payload.visible))
}
fn map_admin_spacetime_error(error: spacetime_client::SpacetimeClientError) -> AppError {
AppError::from_status(StatusCode::BAD_GATEWAY).with_details(serde_json::json!({
"provider": "spacetimedb",

View File

@@ -3,8 +3,9 @@ use axum::{Router, middleware, routing::get};
use crate::{
admin::{
admin_debug_http, admin_get_creation_entry_config, admin_list_database_table_rows,
admin_list_database_tables, admin_list_tracking_events, admin_login, admin_me,
admin_overview, admin_upsert_creation_entry_config, require_admin_auth,
admin_list_database_tables, admin_list_tracking_events, admin_list_work_visibility,
admin_login, admin_me, admin_overview, admin_update_work_visibility,
admin_upsert_creation_entry_config, require_admin_auth,
},
runtime_profile::{
admin_disable_profile_redeem_code, admin_disable_profile_task_config,
@@ -70,6 +71,15 @@ pub fn router(state: AppState) -> Router<AppState> {
require_admin_auth,
)),
)
.route(
"/admin/api/works/visibility",
get(admin_list_work_visibility)
.post(admin_update_work_visibility)
.route_layer(middleware::from_fn_with_state(
state.clone(),
require_admin_auth,
)),
)
.route(
"/admin/api/profile/redeem-codes",
get(admin_list_profile_redeem_codes)

View File

@@ -478,6 +478,29 @@ impl AppState {
}
}
pub async fn list_admin_work_visibility(
&self,
admin_user_id: String,
) -> Result<Vec<shared_contracts::admin::AdminWorkVisibilityEntryPayload>, SpacetimeClientError>
{
self.spacetime_client
.admin_list_work_visibility(admin_user_id)
.await
}
pub async fn update_admin_work_visibility(
&self,
admin_user_id: String,
source_type: String,
profile_id: String,
visible: bool,
) -> Result<shared_contracts::admin::AdminWorkVisibilityEntryPayload, SpacetimeClientError>
{
self.spacetime_client
.admin_update_work_visibility(admin_user_id, source_type, profile_id, visible)
.await
}
pub async fn is_creation_entry_route_enabled(
&self,
creation_type_id: &str,