Files
Genarrative/server-rs/crates/api-server/src/work_author.rs
kdletters decded991e 清理后端编译警告
删除后端未使用的历史 helper、mapper、handler 和 re-export

将仅测试使用的导入、常量和辅助函数收口到 cfg(test)

补齐 Jump Hop 测试构造体字段并对齐 Match3D 当前素材表测试契约

验证后端 workspace cargo check 与 Match3D、Puzzle 相关测试
2026-06-07 22:20:58 +08:00

150 lines
4.7 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
use module_auth::AuthUser;
use crate::state::{AppState, PuzzleApiState};
pub const ORPHAN_WORK_OWNER_USER_ID: &str = "wx-openid-placeholder";
pub const ORPHAN_WORK_AUTHOR_DISPLAY_NAME: &str = "失效作者";
pub const ORPHAN_WORK_AUTHOR_PUBLIC_USER_CODE: &str = "SY-00000000";
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct WorkAuthorSummary {
pub display_name: String,
pub public_user_code: Option<String>,
}
/// 中文注释:作品作者的真相源是 owner_user_id历史昵称字段只作为账号资料不可读时的兼容回退。
pub fn resolve_work_author_by_user_id(
state: &AppState,
owner_user_id: &str,
fallback_display_name: Option<&str>,
fallback_public_user_code: Option<&str>,
) -> WorkAuthorSummary {
resolve_work_author_by_user_id_with_service(
state.auth_user_service(),
owner_user_id,
fallback_display_name,
fallback_public_user_code,
)
}
pub fn resolve_puzzle_work_author_by_user_id(
state: &PuzzleApiState,
owner_user_id: &str,
fallback_display_name: Option<&str>,
fallback_public_user_code: Option<&str>,
) -> WorkAuthorSummary {
resolve_work_author_by_user_id_with_service(
state.auth_user_service(),
owner_user_id,
fallback_display_name,
fallback_public_user_code,
)
}
fn resolve_work_author_by_user_id_with_service(
auth_user_service: &module_auth::AuthUserService,
owner_user_id: &str,
fallback_display_name: Option<&str>,
fallback_public_user_code: Option<&str>,
) -> WorkAuthorSummary {
let fallback_display_name =
normalize_optional_text(fallback_display_name).unwrap_or_else(|| "玩家".to_string());
let _fallback_public_user_code = normalize_optional_text(fallback_public_user_code);
let Some(owner_user_id) = normalize_optional_text(Some(owner_user_id)) else {
return orphan_work_author_summary();
};
match auth_user_service.get_user_by_id(&owner_user_id) {
Ok(Some(user)) => map_auth_user_to_work_author_summary(user, fallback_display_name),
Ok(None) | Err(_) => orphan_work_author_summary(),
}
}
fn map_auth_user_to_work_author_summary(
user: AuthUser,
fallback_display_name: String,
) -> WorkAuthorSummary {
WorkAuthorSummary {
display_name: normalize_optional_text(Some(user.display_name.as_str()))
.unwrap_or(fallback_display_name),
public_user_code: normalize_optional_text(Some(user.public_user_code.as_str())),
}
}
fn normalize_optional_text(value: Option<&str>) -> Option<String> {
value
.map(str::trim)
.filter(|value| !value.is_empty())
.map(ToOwned::to_owned)
}
fn orphan_work_author_summary() -> WorkAuthorSummary {
WorkAuthorSummary {
display_name: ORPHAN_WORK_AUTHOR_DISPLAY_NAME.to_string(),
public_user_code: Some(ORPHAN_WORK_AUTHOR_PUBLIC_USER_CODE.to_string()),
}
}
/// 中文注释:运维回填只处理空作者或认证仓储不可再解析的历史 owner_user_id避免把有效作品误转给占位账号。
#[cfg(test)]
pub fn should_rebind_orphan_work_owner(
auth_user_service: &module_auth::AuthUserService,
owner_user_id: &str,
) -> bool {
let Some(owner_user_id) = normalize_optional_text(Some(owner_user_id)) else {
return true;
};
if owner_user_id == ORPHAN_WORK_OWNER_USER_ID {
return false;
}
!matches!(
auth_user_service.get_user_by_id(&owner_user_id),
Ok(Some(_))
)
}
#[cfg(test)]
mod tests {
use module_auth::{AuthUserService, InMemoryAuthStore};
use super::*;
#[test]
fn orphan_work_author_summary_uses_placeholder_account() {
assert_eq!(
orphan_work_author_summary(),
WorkAuthorSummary {
display_name: "失效作者".to_string(),
public_user_code: Some("SY-00000000".to_string()),
}
);
}
#[test]
fn missing_author_resolves_to_placeholder_account() {
let service = AuthUserService::new(InMemoryAuthStore::default());
let author = resolve_work_author_by_user_id_with_service(
&service,
"user_missing",
Some("历史昵称"),
Some("SY-00000001"),
);
assert_eq!(author, orphan_work_author_summary());
}
#[test]
fn should_rebind_orphan_work_owner_detects_missing_and_empty_author() {
let service = AuthUserService::new(InMemoryAuthStore::default());
assert!(should_rebind_orphan_work_owner(&service, ""));
assert!(should_rebind_orphan_work_owner(&service, "user_missing"));
assert!(!should_rebind_orphan_work_owner(
&service,
ORPHAN_WORK_OWNER_USER_ID
));
}
}