CASL scope strategy

111 Views Asked by At

I've been using CASL in a project with a basic Action/Subject approach but now the business requirements have changed and they added Scopes. So basically I receive this from the permissions endpoint:

"data": [
        {
            "action": "SHARE",
            "scope": "USER",
            "subject": "INTEGRATIONS"
        },
        {
            "action": "READ",
            "scope": "USER",
            "subject": "REPORTS"
        },
        {
            "action": "SHARE",
            "scope": "ALL",
            "subject": "INTEGRATIONS"
        },
        {
            "action": "SHARE",
            "scope": "ALL",
            "subject": "REPORTS"
        },
        {
            "action": "UPDATE",
            "scope": "ALL",
            "subject": "TEAMS"
        },
        {
            "action": "DELETE",
            "scope": "ALL",
            "subject": "USERS"
        },
       ...
    ]

I have to implement the Scope validation for each subject.

As Scopes it's not a property from the Subects I can't use the conditions approach (I tried):

const customConditionsMatcher: ConditionsMatcher<Permission> = (rule, subject) => {
  if (rule.scope === undefined || subject.scope === undefined) {
    return false;
  }

  return rule.scope === subject.scope;
};

export const defineRulesFor = (permissions: Permission[]) => {
  const { can, rules } = new AbilityBuilder<AppAbility>(AppAbility);
  permissions &&
    permissions.map((permission: Permission) => {
      const { action, subject, scope } = permission;
      can(getActionsHierarchy(action), subject, { scope: scope });
    });

  return rules;
};

export const buildAbilityFor = (permissions: Permission[]): AppAbility => {
  return new AppAbility(defineRulesFor(permissions), {
    detectSubjectType: (object) => object.type,
    conditionsMatcher: customConditionsMatcher,
  });
};

So I assembled a "SubjectScope" object that contains the Subejct and the Scope as a property but it didn't work:

<Can I="READ" a={ {subject: "TEAMS", scope: "ALL"} }>
 {children}
</Can>

Maybe my approach is wrong or I'm not implementing the conditionsMatcher correctly. Another possibility I'd like to have some feedback on is using different ability contexts for each Scope.. but I thought it would be overkill for this requirement.

I couldn't find a solution for this use case in the documentation, that's why I'm creating this issue.

Thank you in advance for any helpful feedback

0

There are 0 best solutions below