Files
Genarrative/server-rs/crates/api-server/src/frontend_runtime_config.rs
T
suzmii 772e9f0d42
Project CI / AI game creator shell Rust crates (pull_request) Successful in 1m53s
Project CI / Backend tests (pull_request) Failing after 15s
Project CI / AI game creator shell Rust smoke (pull_request) Successful in 2m41s
Project CI / Frontend tests (pull_request) Failing after 1m5s
Project CI / Repository checks (pull_request) Failing after 23s
Project CI / AI game creator shell web tests (pull_request) Successful in 1m48s
Project CI / Native shell tests (pull_request) Successful in 5m43s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 10m6s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 10m9s
修复游戏封面预览并统一发布灰度说明
封面生成结果经鉴权 read-url 转为安全 data URL 预览,失败时不阻断已登记素材发布。

统一后台、前端与后端对 game-distribution:publish 未配置和关闭状态的说明。
2026-10-02 16:03:28 +08:00

95 lines
3.3 KiB
Rust

use axum::{
extract::{Extension, State},
http::{HeaderMap, StatusCode, header},
response::{IntoResponse, Response},
};
use serde::Serialize;
use serde_json::json;
use crate::{
api_response::json_success_body, auth::optional_access_token_from_headers,
http_error::AppError, request_context::RequestContext, state::AppState,
};
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct FrontendRuntimeConfigResponse {
pub image_editor_agent_sidebar_enabled: bool,
pub agc_template_library_enabled: bool,
/// 游戏发布灰度:未配置 `game-distribution:publish` 或 `enabled=false` 时不开放;
/// 显式配置后按 enabled、白名单、标签和灰度比例判定,匿名一律 `false`(发布必须先登录)。
pub game_distribution_publish_enabled: bool,
}
pub async fn get_frontend_runtime_config(
State(state): State<AppState>,
Extension(request_context): Extension<RequestContext>,
headers: HeaderMap,
) -> Result<Response, AppError> {
let authenticated = optional_access_token_from_headers(
&state,
"/api/runtime/frontend-config".to_string(),
headers,
request_context.request_id().to_string(),
)
.await?;
let user_id = authenticated
.as_ref()
.map(|authenticated| authenticated.claims().user_id());
let image_editor_agent_sidebar_enabled = state
.is_image_editor_agent_sidebar_enabled_for_user(user_id)
.await
.map_err(|error| {
AppError::from_status(StatusCode::BAD_GATEWAY)
.with_message("读取前端运行时配置失败")
.with_details(json!({
"provider": "spacetimedb",
"message": error.to_string(),
}))
})?;
let agc_template_library_enabled = state
.is_agc_template_library_enabled_for_user(user_id)
.await
.map_err(|error| {
AppError::from_status(StatusCode::BAD_GATEWAY)
.with_message("读取前端运行时配置失败")
.with_details(json!({
"provider": "spacetimedb",
"message": error.to_string(),
}))
})?;
let game_distribution_publish_enabled = match user_id {
Some(user_id) => state
.is_game_distribution_publish_enabled_for_user(Some(user_id))
.await
.map_err(|error| {
AppError::from_status(StatusCode::BAD_GATEWAY)
.with_message("读取前端运行时配置失败")
.with_details(json!({
"provider": "spacetimedb",
"message": error.to_string(),
}))
})?,
// 未登录时发布入口不开放:灰度只面向已登录作者,写入口也要求 Bearer 会话。
None => false,
};
Ok((
[
(header::CACHE_CONTROL, "no-store"),
(header::VARY, "Authorization"),
],
json_success_body(
Some(&request_context),
FrontendRuntimeConfigResponse {
image_editor_agent_sidebar_enabled,
agc_template_library_enabled,
game_distribution_publish_enabled,
},
),
)
.into_response())
}