修复公开资产授权一致性与签名期限

公开资产 metadata 和作品授权改为在同一 SpacetimeDB 事务快照中判断
移除连接级公开授权订阅缓存对 ACL 的参与
公开读取签名有效期上限固定为 600 秒并保留 owner 和 admin 行为
同步生成 bindings 并更新后端契约与项目记忆
This commit is contained in:
2026-07-13 20:04:29 +08:00
parent 4fc8beea72
commit 052d656a52
15 changed files with 293 additions and 95 deletions
@@ -122,6 +122,38 @@ pub fn get_asset_object_by_location_and_return(
}
}
// 公开授权与资产 metadata 必须在同一事务快照中判断,不能依赖 API 连接池的订阅水位。
#[spacetimedb::procedure]
pub fn get_asset_read_access_by_location_and_return(
ctx: &mut ProcedureContext,
input: AssetObjectLocationInput,
) -> AssetObjectReadAccessProcedureResult {
let caller = ctx.sender();
match ctx.try_with_tx(|tx| {
crate::editor_project_storage::require_editor_generation_runtime_service_identity(
tx, caller,
)?;
let record = find_asset_object_by_location(tx, &input)?;
let public_work_granted = record.as_ref().is_some_and(|asset_object| {
crate::public_asset_access::asset_object_has_public_work_read_grant(tx, asset_object)
});
Ok((record, public_work_granted))
}) {
Ok((record, public_work_granted)) => AssetObjectReadAccessProcedureResult {
ok: true,
record,
public_work_granted,
error_message: None,
},
Err(message) => AssetObjectReadAccessProcedureResult {
ok: false,
record: None,
public_work_granted: false,
error_message: Some(message),
},
}
}
#[spacetimedb::procedure]
pub fn get_asset_object_by_id_and_return(
ctx: &mut ProcedureContext,
@@ -240,6 +240,27 @@ pub fn public_work_asset_read_grant(ctx: &AnonymousViewContext) -> Vec<PublicWor
grants.into_values().collect()
}
pub(crate) fn asset_object_has_public_work_read_grant(
ctx: &ReducerContext,
asset_object: &AssetObjectUpsertSnapshot,
) -> bool {
let asset_object = module_assets::build_asset_object_record(asset_object.clone());
let view_context = ctx.as_anonymous_read_only();
public_work_asset_read_grant(&view_context)
.into_iter()
.any(|grant| {
module_assets::asset_object_matches_public_read_grant(
&asset_object,
&module_assets::PublicAssetReadGrant {
owner_user_id: grant.owner_user_id,
asset_object_id: grant.asset_object_id,
object_key: grant.object_key,
},
)
})
}
fn collect_json_grants(
grants: &mut BTreeMap<String, PublicWorkAssetReadGrant>,
scope: &PublicWorkAssetGrantScope<'_>,