refactor(后台契约): AdminAgcModel.access 改 ProfileMembershipModelAccessToken
- shared-contracts 的 AdminAgcModel.access 由裸 String 改为 ProfileMembershipModelAccessToken,未知值在反序列化阶段被拒(评审第 18 条) - module-runtime 补 AgcModelAccess <-> ProfileMembershipModelAccessToken 双向 From - api-server 的 agc_models 去掉 AgcModelAccess::parse 兜底,改直接 From - admin-web 的 AdminAgcModelAccess 改为复用 @genarrative/shared 生成类型 - 扩展 catalog_dto 测试断言缺省 Basic 与未知 access 反序列化失败
This commit is contained in:
@@ -244,10 +244,7 @@ pub async fn admin_save_agc_models(
|
||||
.map_err(|message| {
|
||||
AppError::from_status(StatusCode::BAD_REQUEST).with_message(message)
|
||||
})?;
|
||||
let access = AgcModelAccess::parse(&m.access).ok_or_else(|| {
|
||||
AppError::from_status(StatusCode::BAD_REQUEST)
|
||||
.with_message("权限档只允许 basic 或 full")
|
||||
})?;
|
||||
let access = AgcModelAccess::from(m.access);
|
||||
Ok(module_runtime::AgcModel {
|
||||
id: m.id,
|
||||
alias: m.alias,
|
||||
@@ -302,7 +299,7 @@ fn catalog_dto(catalog: AgcModelCatalog) -> AdminAgcModelCatalog {
|
||||
enabled: m.enabled,
|
||||
agent_mode: m.agent_mode.as_str().to_string(),
|
||||
protocol: Some(protocol),
|
||||
access: m.access.as_str().to_string(),
|
||||
access: m.access.into(),
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
@@ -330,6 +327,21 @@ mod tests {
|
||||
}))
|
||||
.unwrap();
|
||||
assert_eq!(legacy.agent_mode, "codex");
|
||||
assert_eq!(
|
||||
legacy.access,
|
||||
shared_contracts::runtime::ProfileMembershipModelAccessToken::Basic
|
||||
);
|
||||
// 权限档 token 在反序列化阶段就收口,未知值不再推迟到 `AgcModelAccess::parse`。
|
||||
assert!(
|
||||
serde_json::from_value::<AdminAgcModel>(json!({
|
||||
"id": "model-a",
|
||||
"alias": "model-a",
|
||||
"modelId": "model-a",
|
||||
"enabled": true,
|
||||
"access": "premium"
|
||||
}))
|
||||
.is_err()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -66,6 +66,24 @@ impl From<RuntimeProfileMembershipModelAccess> for AgcModelAccess {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<shared_contracts::runtime::ProfileMembershipModelAccessToken> for AgcModelAccess {
|
||||
fn from(value: shared_contracts::runtime::ProfileMembershipModelAccessToken) -> Self {
|
||||
match value {
|
||||
shared_contracts::runtime::ProfileMembershipModelAccessToken::Basic => Self::Basic,
|
||||
shared_contracts::runtime::ProfileMembershipModelAccessToken::Full => Self::Full,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<AgcModelAccess> for shared_contracts::runtime::ProfileMembershipModelAccessToken {
|
||||
fn from(value: AgcModelAccess) -> Self {
|
||||
match value {
|
||||
AgcModelAccess::Basic => Self::Basic,
|
||||
AgcModelAccess::Full => Self::Full,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 模型解析失败原因;调用方据此选择错误码与 HTTP 状态,不靠字符串匹配。
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub enum AgcModelResolveError {
|
||||
|
||||
@@ -4,8 +4,8 @@ use serde::{Deserialize, Serialize};
|
||||
use serde_json::Value;
|
||||
|
||||
use crate::runtime::{
|
||||
ProfileMembershipChangeKindToken, ProfileMembershipCycleKindToken, ProfileMembershipPlanToken,
|
||||
ProfileMembershipStatusToken,
|
||||
ProfileMembershipChangeKindToken, ProfileMembershipCycleKindToken,
|
||||
ProfileMembershipModelAccessToken, ProfileMembershipPlanToken, ProfileMembershipStatusToken,
|
||||
};
|
||||
|
||||
#[cfg(any())]
|
||||
@@ -1706,8 +1706,8 @@ fn default_codex_agent_mode() -> String {
|
||||
}
|
||||
|
||||
/// 存量后台请求缺省为 `basic`(失败开放),只有人工标注才收紧到 `full`。
|
||||
fn default_basic_agc_model_access() -> String {
|
||||
"basic".to_string()
|
||||
fn default_basic_agc_model_access() -> ProfileMembershipModelAccessToken {
|
||||
ProfileMembershipModelAccessToken::Basic
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
|
||||
@@ -1726,7 +1726,7 @@ pub struct AdminAgcModel {
|
||||
pub protocol: Option<String>,
|
||||
/// 该模型要求的会员档位:`basic`(缺省,对全部档位开放)/ `full`(后台人工标注)。
|
||||
#[serde(default = "default_basic_agc_model_access")]
|
||||
pub access: String,
|
||||
pub access: ProfileMembershipModelAccessToken,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
|
||||
|
||||
Reference in New Issue
Block a user