Reputation: 73
I'm using CASL for authorization in my NestJS application with TypeORM for persistence. I've defined permissions with unique constraints on "action" and "subject" columns to prevent duplicates. However, I'm facing an issue when trying to create a permission with the same action and subject but different fields or conditions.
Here's my current setup:
Entities:
CASL Ability:
import { User } from './users/entities/user.entity';
import {
ForcedSubject,
MongoAbility,
RawRuleOf,
createMongoAbility,
} from '@casl/ability';
import { get } from 'lodash';
import { Permission } from './database/entities/permission.entity';
export const actions = [
'manage',
'create',
'read',
'update',
'delete',
] as const;
export const subjects = ['User', 'Post', 'all'] as const;
export type AppAbilities = [
(typeof actions)[number],
(
| (typeof subjects)[number]
| ForcedSubject<Exclude<(typeof subjects)[number], 'all'>>
),
];
export type AppAbility = MongoAbility<AppAbilities>;
export const createAbility = (rules: RawRuleOf<AppAbility>[]) => {
return createMongoAbility<AppAbilities>(rules);
};
export const createUserAbility = (user: User, vars: any = {}) => {
if (!vars.hasOwnProperty('user')) {
vars.user = user;
}
return createAbility(createUserPermissions(user, vars));
};
function interpolate(template: string, vars: object) {
return JSON.parse(template, (_, rawValue) => {
if (rawValue[0] !== '$') {
return rawValue;
}
const name = rawValue.slice(2, -1);
const value = get(vars, name);
if (typeof value === 'undefined') {
throw new ReferenceError(`Variable ${name} is not defined`);
}
return value;
});
}
function createUserPermissions(user: User, vars: object = {}) {
const permissions = user.roles.reduce((permissions, role) => {
return [...permissions, ...normalizePermissions(role.permissions)];
}, []);
return interpolate(JSON.stringify(permissions), vars);
}
function normalizePermissions(permissions: Permission[]) {
return permissions.map((permission) => {
const { fields, ...rest } = permission;
return fields && fields.length ? { ...rest, fields } : rest;
});
}
Example Permissions:
Problem:
I want to add a new permission, "ABC", which allows updating any user with any fields. However, the unique constraint on "action" and "subject" prevents this because "update" and "User" already exist with different fields and conditions.
Possible Solutions:
I'd appreciate any insights or recommendations on how to best address this challenge. Thanks!
Upvotes: 0
Views: 588