projectKey 只在创建作品时落库并核对确定性 gameId
`get_or_create_game_distribution_game_for_publish_tx` 按 owner + projectKey 兜底命中时核对 `game_id` 相等,否则失败关闭,避免版本挂到与派生身份不一致的作品 软删复活不再用请求的 projectKey 覆盖既有作品的身份锚(请求不带时沿用原值) 新增源码结构回归测试
This commit is contained in:
@@ -3801,6 +3801,10 @@ fn get_or_create_game_distribution_game_for_publish_tx(
|
||||
.as_deref()
|
||||
.map(str::trim)
|
||||
.filter(|value| !value.is_empty());
|
||||
// `project_key` 只是**创建作品**的身份锚(`POST /games` 无路径槽时用):同一
|
||||
// `(owner, project_key)` 必须确定性派生同一个 `game_id`,追加版本一律走路径 `game_id`、
|
||||
// 不读 `project_key`。这里按 owner + key 兜底命中时必须核对 game_id 相等,否则历史分叉会
|
||||
// 让版本行挂到与派生身份不一致的作品上,写出「版本属于 A、作品是 B」的孤儿数据。
|
||||
if let Some(project_key) = project_key {
|
||||
if let Some(game) = ctx
|
||||
.db
|
||||
@@ -3811,6 +3815,9 @@ fn get_or_create_game_distribution_game_for_publish_tx(
|
||||
game.deleted_at.is_none() && game.project_key.as_deref() == Some(project_key)
|
||||
})
|
||||
{
|
||||
if game.game_id != input.game_id {
|
||||
return Err("projectKey 已绑定到另一个作品".to_string());
|
||||
}
|
||||
ensure_game_distribution_game_publishable(&game)?;
|
||||
return Ok(game);
|
||||
}
|
||||
@@ -4091,12 +4098,16 @@ fn revived_game_distribution_game_for_publish(
|
||||
game.orientation = input.orientation.clone();
|
||||
game.cover_object_key = input.cover_object_key.clone();
|
||||
game.screenshots_json = input.screenshots_json.clone();
|
||||
game.project_key = input
|
||||
// `project_key` 是作品的身份锚,只在**创建**时落库:请求带非空 key 才覆盖,否则沿用既有行的值。
|
||||
// 追加版本按设计不带 `projectKey`,不能因此把存活作品的身份锚清空。
|
||||
if let Some(project_key) = input
|
||||
.project_key
|
||||
.as_deref()
|
||||
.map(str::trim)
|
||||
.filter(|value| !value.is_empty())
|
||||
.map(str::to_string);
|
||||
{
|
||||
game.project_key = Some(project_key.to_string());
|
||||
}
|
||||
game.publication_revision = 0;
|
||||
game.active_version_id = None;
|
||||
game.visibility = GAME_DISTRIBUTION_VISIBILITY_UNPUBLISHED.to_string();
|
||||
@@ -8540,6 +8551,20 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
/// `projectKey` 兜底命中时 `game_id` 必须一致,否则拒绝,避免孤儿版本。
|
||||
#[test]
|
||||
fn project_key_fallback_refuses_a_different_game_id() {
|
||||
let source = include_str!("game_distribution.rs");
|
||||
let body = function_body(
|
||||
source,
|
||||
"fn get_or_create_game_distribution_game_for_publish_tx(",
|
||||
);
|
||||
assert!(
|
||||
body.contains("game.game_id != input.game_id"),
|
||||
"projectKey 兜底必须核对确定性派生的 game_id"
|
||||
);
|
||||
}
|
||||
|
||||
/// 版本表的 `change_summary` 必须留在**表尾**并带默认值。
|
||||
///
|
||||
/// schema guard 只允许「末尾追加 + 显式默认」:插在中间会让既有行的列序整体错位(不是迁移能补
|
||||
|
||||
Reference in New Issue
Block a user