Skip to content

属主守卫与级联 set_null 冲突:非特权删除 sys_user 时 owner_id 级联置空被 #3004 守卫拦截(级联中途失败) #3023

Description

@os-zhuang

背景

#3004 修复(PR #3018)后,plugin-security step 3.5 把 owner_id 变成非特权写入者的系统托管字段:update 携带 owner_id(含置为 null 的弃权)在无 transfer 授权时被拒。

问题

owner_id 是指向 sys_userlookup,默认 deleteBehavior: 'set_null'(packages/objectql/src/registry.ts 约 334–345)。删除一个 sys_user 时,cascadeDeleteRelations(packages/objectql/src/engine.ts 约 2527+,仅对单条删除生效)会对每个引用该用户的子记录执行:

this.update(childName, { id: depId, owner_id: null }, { context })  // 沿用删除者的上下文

该级联 update 携带 owner_id: null,以删除者的上下文重新进入中间件。若删除者是非 isSystem、且在这些子对象上不持有 allowTransfer/modifyAllRecords 的主体,step 3.5 会把它判为“弃权”而抛 PermissionDeniedError —— 由于没有事务包裹,级联会中途失败,留下部分已置空/已删除的子记录。

触发条件(较窄)

  • 仅在删除 sys_user(唯一被 owner_id 引用的对象)时触发;
  • 且删除者是非系统上下文、缺少 transfer 授权(平台/组织管理员默认持有 modifyAllRecords,不受影响)。

期望

级联 set_null 是引擎内部的引用完整性操作,不是用户发起的属主变更,不应被属主转移守卫拦截。可选方案:

  1. cascadeDeleteRelationsset_null 写入使用受控的系统上下文(引用完整性本就应覆盖删除者不可见的子记录);或
  2. 为引擎内部级联写入打标,step 3.5 对其豁免。

关联

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions