feat: add admin creation entry switches
Some checks failed
CI / verify (pull_request) Has been cancelled

This commit is contained in:
2026-05-11 12:02:39 +08:00
parent d23cf3807d
commit 0461c0ee41
18 changed files with 745 additions and 4 deletions

View File

@@ -18,6 +18,8 @@ use reqwest::Client;
use serde::Deserialize;
use serde_json::{Map, Value};
use shared_contracts::admin::{
AdminCreationEntryConfigResponse, AdminCreationEntryTypeConfigPayload,
AdminUpsertCreationEntryTypeConfigRequest,
AdminDatabaseOverviewPayload, AdminDatabaseTableListResponse, AdminDatabaseTableRowPayload,
AdminDatabaseTableRowsQuery, AdminDatabaseTableRowsResponse, AdminDatabaseTableStatPayload,
AdminDebugHeaderInput, AdminDebugHttpRequest, AdminDebugHttpResponse, AdminLoginRequest,
@@ -194,6 +196,94 @@ pub async fn admin_list_database_table_rows(
Ok(json_success_body(Some(&request_context), response))
}
pub async fn admin_get_creation_entry_config(
State(state): State<AppState>,
Extension(request_context): Extension<RequestContext>,
Extension(_admin): Extension<AuthenticatedAdmin>,
) -> Result<Json<Value>, AppError> {
let config = state.get_creation_entry_config().await.map_err(map_admin_spacetime_error)?;
Ok(json_success_body(
Some(&request_context),
AdminCreationEntryConfigResponse {
entries: config
.creation_types
.into_iter()
.map(map_admin_creation_entry_type_config)
.collect(),
},
))
}
pub async fn admin_upsert_creation_entry_config(
State(state): State<AppState>,
Extension(request_context): Extension<RequestContext>,
Extension(_admin): Extension<AuthenticatedAdmin>,
Json(payload): Json<AdminUpsertCreationEntryTypeConfigRequest>,
) -> Result<Json<Value>, AppError> {
let entry = validate_admin_creation_entry_config(payload)?;
let config = state
.upsert_creation_entry_type_config(entry)
.await
.map_err(map_admin_spacetime_error)?;
Ok(json_success_body(
Some(&request_context),
AdminCreationEntryConfigResponse {
entries: config
.creation_types
.into_iter()
.map(map_admin_creation_entry_type_config)
.collect(),
},
))
}
fn map_admin_creation_entry_type_config(
entry: shared_contracts::creation_entry_config::CreationEntryTypeResponse,
) -> AdminCreationEntryTypeConfigPayload {
AdminCreationEntryTypeConfigPayload {
id: entry.id,
title: entry.title,
subtitle: entry.subtitle,
badge: entry.badge,
image_src: entry.image_src,
visible: entry.visible,
open: entry.open,
sort_order: entry.sort_order,
updated_at_micros: entry.updated_at_micros,
}
}
fn validate_admin_creation_entry_config(
payload: AdminUpsertCreationEntryTypeConfigRequest,
) -> Result<module_runtime::CreationEntryTypeAdminUpsertInput, AppError> {
let id = payload.id.trim().to_string();
if id.is_empty() {
return Err(AppError::from_status(StatusCode::BAD_REQUEST).with_message("入口 ID 不能为空"));
}
let title = payload.title.trim().to_string();
if title.is_empty() {
return Err(AppError::from_status(StatusCode::BAD_REQUEST).with_message("入口标题不能为空"));
}
Ok(module_runtime::CreationEntryTypeAdminUpsertInput {
id,
title,
subtitle: payload.subtitle.trim().to_string(),
badge: payload.badge.trim().to_string(),
image_src: payload.image_src.trim().to_string(),
visible: payload.visible,
open: payload.open,
sort_order: payload.sort_order,
})
}
fn map_admin_spacetime_error(error: spacetime_client::SpacetimeClientError) -> AppError {
AppError::from_status(StatusCode::BAD_GATEWAY).with_details(serde_json::json!({
"provider": "spacetimedb",
"message": error.to_string(),
}))
}
pub async fn require_admin_auth(
State(state): State<AppState>,
mut request: Request,
@@ -1237,7 +1327,9 @@ mod tests {
};
use axum::{http::StatusCode, response::IntoResponse};
use serde_json::json;
use shared_contracts::admin::{AdminDatabaseTableRowsQuery, AdminTrackingEventListQuery};
use shared_contracts::admin::{
AdminCreationEntryConfigResponse, AdminCreationEntryTypeConfigPayload,
AdminUpsertCreationEntryTypeConfigRequest,AdminDatabaseTableRowsQuery, AdminTrackingEventListQuery};
#[test]
fn normalize_debug_path_rejects_absolute_url() {