feat(identity): redesign identity module and introduce RBAC foundation

- Redesign the Identity module with a richer domain model.
- Extend the User entity to support username, Authentik integration, activity tracking, and storage information.
- Add Role and Permission domain models with many-to-many relationships.
- Implement RBAC foundation using UserRole, RolePermission, and UserPermission mappings.
- Add user storage quota and usage fields with default values.
- Introduce Authentik identifiers and synchronization metadata.
- Refactor user domain logic for role and permission management.
- Update Prisma schema to support the new identity architecture.
- Improve JWT authentication and permission guard integration.
- Update repositories, handlers, controllers, mappers, DTOs, and Swagger configuration.
- Refresh environment configuration and project dependencies.
This commit is contained in:
Rayyan
2026-08-02 00:25:36 +07:00
parent fdbfb34842
commit 7ce0de4e91
132 changed files with 7754 additions and 2037 deletions
@@ -1,27 +1,73 @@
import { User } from '../../domain/entities/user.entity';
import { UserData } from '../../domain/entities/user.entity';
import { RoleData } from '../../domain/entities/role.entity';
import { PermissionData } from '../../domain/entities/permission.entity';
export class PrismaUserMapper {
static toDomain(model: any): User | null {
if (!model) {
return null;
}
static toDomain(model: any): UserData {
const roles: RoleData[] = (model.roles || []).map((ur: any) => {
const r = ur.role;
const permissions: PermissionData[] = (r?.permissions || []).map((rp: any) =>
PermissionData.restore({
id: rp.permission.id,
name: rp.permission.name,
description: rp.permission.description,
createdAt: rp.permission.createdAt,
updatedAt: rp.permission.updatedAt,
}),
);
return User.restore({
return RoleData.restore({
id: r.id,
code: r.code,
name: r.name,
description: r.description,
permissions,
createdAt: r.createdAt,
updatedAt: r.updatedAt,
});
});
const permissions: PermissionData[] = (model.permissions || []).map((up: any) =>
PermissionData.restore({
id: up.permission.id,
name: up.permission.name,
description: up.permission.description,
createdAt: up.permission.createdAt,
updatedAt: up.permission.updatedAt,
}),
);
return UserData.restore({
id: model.id,
name: model.name,
authentikId: model.authentikUserId || model.authentikId || null,
username: model.username || model.name || model.username,
email: model.email,
password: model.password,
metadata: model.metadata,
password: model.password ?? null,
roles,
permissions,
isActive: model.isActive ?? true,
deletedAt: model.deletedAt || null,
lastSeenAt: model.lastSeenAt || null,
storageQuota: model.storageQuota !== undefined && model.storageQuota !== null ? Number(model.storageQuota) : undefined,
storageUsed: model.storageUsed !== undefined && model.storageUsed !== null ? Number(model.storageUsed) : undefined,
});
}
static toPersistence(user: User) {
return {
id: user.id,
name: user.name,
email: user.email,
password: user.password,
metadata: user.metadata ?? {},
};
static toPersistence(userData: UserData) {
return {
id: userData.id,
authentikUserId: (userData as any).authentikUserId || userData.authentikId,
authentikId: userData.authentikId,
username: userData.username,
email: userData.email,
password: userData.password ?? null,
isActive: userData.isActive,
deletedAt: userData.deletedAt,
lastSeenAt: userData.lastSeenAt,
lastSyncedAt: (userData as any).lastSyncedAt,
syncStatus: (userData as any).syncStatus,
storageQuota: (userData as any).storageQuota,
storageUsed: (userData as any).storageUsed,
};
}
}