使用AbstractCube.sql()扩展Cube时SECURITY_CONTEXT未定义报错如何解决?
问题根因与修复方案
核心错误原因
你遇到的TypeError: Cannot read property 'tenantId' of undefined报错是因为Cube.js的SECURITY_CONTEXT是查询请求阶段才会注入的动态上下文变量,而你原来的写法是在Schema定义编译阶段就直接对其求值,此时SECURITY_CONTEXT还未初始化,自然是undefined。
不符合规范的操作
- 基础Cube的
sql属性直接使用了立即求值的模板字符串,没有用函数包裹,导致Schema编译阶段就尝试读取SECURITY_CONTEXT - 扩展Cube中直接调用
BaseOrders.sql(),同样是在定义阶段执行,没有等到查询阶段上下文准备完成
修复方案
- 基础抽象Cube的
sql属性改为函数返回值形式,同时添加abstract: true标记,禁止该Cube被直接查询,符合抽象Cube的设计定位 - 扩展Cube中不要手动调用父类的
sql()方法,改用${sql()}引用父类的SQL片段,Cube.js会自动完成继承逻辑,同时将查询阶段的SECURITY_CONTEXT正确传递到父类逻辑中
修改后代码示例
基础抽象Cube
const BaseOrders = cube({ // 标记为抽象Cube,禁止直接查询 abstract: true, // 改用函数返回SQL,查询阶段才会执行,此时SECURITY_CONTEXT已注入 sql: () => `SELECT * FROM orders WHERE ${SECURITY_CONTEXT.tenantId.requiredFilter('tenantId')}`, measures: { count: { type: `count`, sql: `id` } } });
扩展Cube
cube(`RestrictedOrderFacts`, { extends: BaseOrders, // 同样用函数返回SQL,通过${sql()}直接引用父类已经注入安全上下文的SQL片段 sql: () => ` SELECT * FROM (${sql()}) AS bo WHERE status = 'RESTRICTED' `, measures: { doubleCount: { type: `number`, sql: `${count} * 2` } } });
效果说明
调整后所有继承BaseOrders的扩展Cube都会自动复用父类的行级安全逻辑,完全满足你将租户行级权限统一管控在抽象Cube中的需求,不会再出现上下文未定义的报错。
内容的提问来源于stack exchange,提问作者Camilo Velasquez
相关产品推荐
相关产品推荐

