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 未配置和关闭状态的说明。
95 lines
3.3 KiB
Rust
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())
|
|
}
|