fix: pre-release audit fixes — Twitter OAuth, DataMasking perf, Prompt versioning

- Twitter like/retweet: return explicit unavailable error instead of
  sending doomed Bearer token requests (would 403 on Twitter API v2)
- DataMasking: pre-compile regex patterns with LazyLock (was compiling
  6 patterns on every mask() call)
- Prompt version: fix get_version handler ignoring version path param,
  add service::get_version_by_number for correct per-version retrieval
This commit is contained in:
iven
2026-04-09 16:43:24 +08:00
parent f2d6a3b6b7
commit 3f2acb49fb
4 changed files with 99 additions and 79 deletions

View File

@@ -122,12 +122,11 @@ pub async fn list_versions(
pub async fn get_version(
State(state): State<AppState>,
Extension(ctx): Extension<AuthContext>,
Path((name, _version)): Path<(String, i32)>,
Path((name, version)): Path<(String, i32)>,
) -> SaasResult<Json<PromptVersionInfo>> {
check_permission(&ctx, "prompt:read")?;
let _tmpl = service::get_template_by_name(&state.db, &name).await?;
Ok(Json(service::get_current_version(&state.db, &name).await?))
Ok(Json(service::get_version_by_number(&state.db, &name, version).await?))
}
/// POST /api/v1/prompts/{name}/versions — 发布新版本

View File

@@ -198,6 +198,23 @@ pub async fn get_current_version(db: &PgPool, template_name: &str) -> SaasResult
Ok(PromptVersionInfo { id: r.id, template_id: r.template_id, version: r.version, system_prompt: r.system_prompt, user_prompt_template: r.user_prompt_template, variables, changelog: r.changelog, min_app_version: r.min_app_version, created_at: r.created_at })
}
/// 获取模板的指定版本号的内容
pub async fn get_version_by_number(db: &PgPool, template_name: &str, version_number: i32) -> SaasResult<PromptVersionInfo> {
let tmpl = get_template_by_name(db, template_name).await?;
let row: Option<PromptVersionRow> =
sqlx::query_as(
"SELECT id, template_id, version, system_prompt, user_prompt_template, variables, changelog, min_app_version, created_at::TEXT
FROM prompt_versions WHERE template_id = $1 AND version = $2"
).bind(&tmpl.id).bind(version_number).fetch_optional(db).await?;
let r = row.ok_or_else(|| SaasError::NotFound(format!("提示词 '{}' 的版本 {} 不存在", template_name, version_number)))?;
let variables: serde_json::Value = serde_json::from_str(&r.variables).unwrap_or(serde_json::json!([]));
Ok(PromptVersionInfo { id: r.id, template_id: r.template_id, version: r.version, system_prompt: r.system_prompt, user_prompt_template: r.user_prompt_template, variables, changelog: r.changelog, min_app_version: r.min_app_version, created_at: r.created_at })
}
/// 列出模板的所有版本
pub async fn list_versions(
db: &PgPool,