CASL/MongoAbility中配置user.id与credentials.uid匹配的权限规则
问题
我用以下代码初始化AbilityBuilder:
const abilityBuilder = new AbilityBuilder(createMongoAbility);
定义了如下类和接口:
export class UsersResourceManager { role: string; subject: string; credentials?: Credentials; user?: UserModel; constructor( role: string, subject: string, credentials?: Credentials, user?: IUserModel, ) { this.role = role; this.subject = subject; this.credentials = credentials; this.user = user; } } interface UserModel { id: string; username: string; // 其他字段 } interface Credentials { uid: string; username: string; }
我想要创建一条权限规则:当user.id === credentials.uid时返回true。目前的规则写法如下,但校验时始终返回false:
const { can } = this.abilityBuilder; // 示例简单权限规则 can('get', 'UsersResourceManager', { subject: { $eq: 'user' }, role: { $eq: 'read' }, }); // 尝试实现的规则(不生效) can('update', 'UsersResourceManager', { subject: { $eq: 'user' }, role: { $eq: 'admin' }, credentials: { $elemMatch: { uid: { $eq: 'user.id', // 想引用user.id,但写法错误 }, }, }, });
校验权限的代码:
const abilities = this.abilityBuilder.build(); const resource = new UsersResourceManager( 'admin', 'user', credentials, // {uid: 'xxx', ...} user, // { id: 'xxx', ..} ); abilities.can(aclPermission, resource); // 当前返回false
我不想动态创建权限规则,请问该怎么实现这个匹配逻辑?
解决方案
Mongo Ability的查询语法无法直接用字符串'user.id'引用资源对象的其他属性,需要用自定义断言函数实现跨属性的比较逻辑,修改规则写法如下:
can('update', 'UsersResourceManager', { subject: { $eq: 'user' }, role: { $eq: 'admin' }, // 自定义断言函数校验credentials.uid与user.id是否相等 $expr: (resource) => { // 先判断属性是否存在,避免报错 if (!resource.user || !resource.credentials) return false; return resource.user.id === resource.credentials.uid; } });
说明
$expr是Mongo Ability支持的自定义断言方式,接收资源对象作为参数,返回布尔值表示是否匹配规则。- 函数内先做存在性判断,防止
user或credentials为undefined时抛出错误。 - 该写法属于静态规则定义,无需动态生成规则,符合需求。
内容的提问来源于stack exchange,提问作者SanjiSqurt
相关产品推荐
相关产品推荐

