Skip to content

详情页**页头动作**的 visible CEL:当前用户与 lookup 字段比不出来,且求值抛错静默 fail-open —— RecordDetailView 的求值面没被 #5149 的响亮化覆盖(17.0.0-rc.6) #8500

Description

@baozhoutao

现象

平台版本 @objectstack/*@17.0.0-rc.6

记录详情页页头动作visible CEL 无法表达「只有本记录的某个责任人才看得见这颗按钮」这个最常见的诉求。以一个 lookup 字段 manager 为例:

  • 能跑通的写法(os.user.id == record.manager)对本人也恒为 false —— 按钮谁都看不见;
  • 直觉写法(os.user.id == record.manager.id)求值抛错,而该处 catch 返回 true —— 按钮不是消失,而是对所有人显示,且无任何告警。

两条路都不通,且失败方向恰好相反:一条恒关,一条恒开。

复现与实测

每组重启服务,两个账号对照。managerlookup(sys_user);账号 A = 本记录的 manager,账号 B = 非 manager 但有读权。

谓词AB结论
os.user.id != null显示os.user 已绑定
os.user.id == 'A 的 uid 字面量'(直接写死 A 的 uid)显示os.user.id 即会话用户 id,左侧正常
os.user.id == record.manager隐藏隐藏对本人也恒 false(干净求值成假)
os.user.id == record.manager.id显示显示求值抛错 → fail-open,两人都可见

排除项:

  • 同一条记录经 REST 取回时,manager 是与会话 uid 逐字相同的裸字符串 —— 已断言 String(uid) === String(rec.manager) 为 true。所以「值不相等」不成立,页头作用域下 record.manager 的取值形态与 REST 不一致;
  • 已排除「无读权导致 expand 静默降级成裸 id」:账号 B 能 200 读到 A 的用户记录,?$expand=manager 仍返回裸串。

fail-open 是代码级事实,不是推断 —— console bundle(RecordDetailView-*.js)中该处为:

try{returnn.evaluateCondition(e.visible)}catch{returntrue}

谓词一旦抛错,按钮对全体显示,console 里没有任何输出。

下游项目已在自己仓库记录了完整实测过程:steedos-labs/os-project-titanwind-ehr#874(私有仓,此处仅作实测记录索引)。

影响

页头动作是「只有责任人可见」这类权限收敛最自然的落点,而这条路径当前没有任何可用写法。更糟的是错误写法的失败方向是 fail-open:作者写完看到按钮在,会认为谓词生效了 —— 实际上它对所有人都在。静默使得这类问题按检视无法发现。

期望

  1. 取值形态对齐:页头作用域下 lookup 字段的取值与 REST 一致,或提供一个稳定的 record.某lookup字段.id 取法,并写进文档;
  2. 不要静默 fail-open:visible 求值异常改为 fail-closed,或至少在 console 输出告警。

与既有裁决 / 相邻单的关系(非重复)

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingpriority:p0Critical: blocker, must ship before MVPrepo:objectui

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions