feat(auth): add user and role management

This commit is contained in:
Ali BARIN
2023-07-18 21:00:10 +00:00
parent a7104c41a2
commit 0deaa03218
108 changed files with 2909 additions and 388 deletions

View File

@@ -0,0 +1,59 @@
import { IRole, IPermission } from '@automatisch/types';
type ComputeAction = {
conditions: Record<string, boolean>;
value: boolean;
}
type ComputedActions = Record<string, ComputeAction>;
type ComputedPermissions = Record<string, ComputedActions>;
export type RoleWithComputedPermissions = IRole & { computedPermissions: ComputedPermissions };
export function getRoleWithComputedPermissions(role: IRole): RoleWithComputedPermissions {
const computedPermissions = role.permissions.reduce((computedPermissions, permission) => ({
...computedPermissions,
[permission.subject]: {
...(computedPermissions[permission.subject] || {}),
[permission.action]: {
conditions: Object.fromEntries(permission
.conditions
.map(condition => [condition, true])),
value: true,
},
}
}), {} as ComputedPermissions);
return {
...role,
computedPermissions,
};
}
export function getPermissions(computedPermissions?: ComputedPermissions) {
if (!computedPermissions) return [];
return Object
.entries(computedPermissions)
.reduce((permissions, computedPermissionEntry) => {
const [subject, actionsWithConditions] = computedPermissionEntry;
for (const action in actionsWithConditions) {
const {
value: permitted,
conditions = {},
} = actionsWithConditions[action];
if (permitted) {
permissions.push({
action,
subject,
conditions: Object
.entries(conditions)
.filter(([, enabled]) => enabled)
.map(([condition]) => condition),
})
}
}
return permissions;
}, [] as Partial<IPermission>[]);
}

View File

@@ -0,0 +1,20 @@
import { PureAbility, fieldPatternMatcher, mongoQueryMatcher } from '@casl/ability';
import { IUser } from '@automatisch/types';
// Must be kept in sync with `packages/backend/src/helpers/user-ability.ts`!
export default function userAbility(user: IUser) {
const permissions = user?.permissions;
const role = user?.role;
// We're not using mongo, but our fields, conditions match
const options = {
conditionsMatcher: mongoQueryMatcher,
fieldMatcher: fieldPatternMatcher
};
if (!role || !permissions) {
return new PureAbility([], options);
}
return new PureAbility<[string, string], string[]>(permissions, options);
}