基于角色的访问控制和动态角色

7
我们有一个应用程序需要实现 RBAC(基于角色的访问控制)。我根据官方文档添加了一个基本的 Guard 和 Decorator:https://docs.nestjs.com/guards。问题是:这只允许使用静态角色。
我们的目标是:在我们的情况下,我们有一个“合同”实体,只有当合同的承包商 (<User>) 或承包商的监督者 (<User>) 尝试访问它时,该合同才应该被加载。我不想像 if (contract.contractor.id === user.id) 这样实现,因为我们有很多不同的情况,随着时间的推移会变得越来越混乱。
看起来像这样:
@Get()
@Roles(ROLES.ADMIN, ROLES.CONTRACTOR, ROLES.SUPERVISOR)
getContractById(...): Contract {
    return this.contractService.findById(...);
}

当然,ROLES.SUPERVISOR只是一个字符串,它会与用户的静态角色进行匹配。所以这里有个问题:如何使用动态角色来实现这样的功能,比如专门针对某些项目才是动态的监督员角色?

任何结果朋友 :) - Goon Nguyen
你能找到解决方案吗? - FelipeS
1个回答

0

你需要先从概念上理解这个问题。

我认为你应该编写一个方法,能够计算特定合同的特定用户是谁。

以下是一个超级简单的例子:

getUserRoleForContract(user: User, contract: Contract): ROLES {
    // your logic goes here
    if (contract.contractor.id === user.id) {
         return ROLES.CONTRACTOR;
    } else if (...) {...}

    return null;
}

在你的守卫中,从上下文中,你意识到是哪个用户和合同请求,利用这种方法获取角色,然后将结果与请求的角色进行比较。
现在,你明确表示不想使用这种方法(检查每个用户和合同的组合)。
我认为你应该根据你对实体关系的了解,立即改进getUserRoleForContract方法的实现。
从你的问题中,我看到承包商和监管者。基于这个(有限的)信息,这很合适:
getUserRoleForContract(user: User, contract: Contract): ROLES {
    const allAvailableRoles = [ROLES.CONTRACTOR, ROLES.SUPERVISOR];

    for (let role of allAvailableRoles) {
        if (contract[role.toLowerCase()].id === user.id) {
            return role;
    }

    return null;
}

这个假设是每个合同上的用户关系都是ManyToOne,并且与ROLE名称相同,但是小写(并且假设ROLES枚举值是相同的大写字符串)。

总的来说,我希望这可以帮助回答问题。

编辑2:我已经修复了指向此处的URL。

我刚刚在这里放置了答案:如何为nestjs创建isAuthor守卫的最佳方法是什么?。它涵盖了Nest.js中RBAC的更大解决方案(包括此场景)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接