251206:1710 specs: frontend plan P1,P3 wait Verification
Some checks failed
Spec Validation / validate-markdown (push) Has been cancelled
Spec Validation / validate-diagrams (push) Has been cancelled
Spec Validation / check-todos (push) Has been cancelled

This commit is contained in:
admin
2025-12-06 17:10:56 +07:00
parent be3b71007a
commit 5c49bac772
40 changed files with 977 additions and 244 deletions

View File

@@ -1,11 +1,5 @@
import { Injectable } from '@nestjs/common';
import {
Ability,
AbilityBuilder,
AbilityClass,
ExtractSubjectType,
InferSubjects,
} from '@casl/ability';
import { Ability, AbilityBuilder, AbilityClass } from '@casl/ability';
import { User } from '../../../modules/user/entities/user.entity';
import { UserAssignment } from '../../../modules/user/entities/user-assignment.entity';
@@ -45,7 +39,7 @@ export class AbilityFactory {
* - Level 4: Contract
*/
createForUser(user: User, context: ScopeContext): AppAbility {
const { can, cannot, build } = new AbilityBuilder<AppAbility>(
const { can, build } = new AbilityBuilder<AppAbility>(
Ability as AbilityClass<AppAbility>
);
@@ -54,12 +48,13 @@ export class AbilityFactory {
return build();
}
// Iterate through user's role assignments
// Iterate through user's role assignments
user.assignments.forEach((assignment: UserAssignment) => {
// Check if assignment matches the current context
if (this.matchesScope(assignment, context)) {
// Grant permissions from the role
assignment.role.permissions.forEach((permission) => {
assignment.role.permissions?.forEach((permission) => {
const [action, subject] = this.parsePermission(
permission.permissionName
);
@@ -70,8 +65,10 @@ export class AbilityFactory {
return build({
// Detect subject type (for future use with objects)
detectSubjectType: (item) =>
item.constructor as ExtractSubjectType<Subjects>,
detectSubjectType: (item: any) => {
if (typeof item === 'string') return item;
return item.constructor;
},
});
}
@@ -120,17 +117,17 @@ export class AbilityFactory {
* "project.view" → ["view", "project"]
*/
private parsePermission(permissionName: string): [string, string] {
// Fallback for special permissions like "system.manage_all"
if (permissionName === 'system.manage_all') {
return ['manage', 'all'];
}
const parts = permissionName.split('.');
if (parts.length === 2) {
const [subject, action] = parts;
return [action, subject];
}
// Fallback for special permissions like "system.manage_all"
if (permissionName === 'system.manage_all') {
return ['manage', 'all'];
}
throw new Error(`Invalid permission format: ${permissionName}`);
}
}