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
+73
View File
@@ -0,0 +1,73 @@
import { request } from '@playwright/test';
import { env } from './env';
import { getToken } from './auth';
async function buildContext(token?: string) {
const headers: any = { 'Content-Type': 'application/json' };
if (token) headers['Authorization'] = `Bearer ${token}`;
const api = await request.newContext({ baseURL: env.BASE_URL || 'http://localhost:3000', extraHTTPHeaders: headers });
return api;
}
export async function requestGet(path: string, role: 'owner' | 'admin' | 'employee' | null = 'admin', opts: any = {}) {
const token = role ? await getToken(role) : undefined;
const api = await buildContext(token);
try {
const res = await api.get(path, opts);
const body = await parseResponseSafe(res);
return { status: res.status(), body, headers: res.headers() };
} finally {
await api.dispose();
}
}
export async function requestPost(path: string, role: 'owner' | 'admin' | 'employee' | null = 'admin', data?: any, opts: any = {}) {
const token = role ? await getToken(role) : undefined;
const api = await buildContext(token);
try {
const res = await api.post(path, { data, ...opts });
const body = await parseResponseSafe(res);
return { status: res.status(), body, headers: res.headers() };
} finally {
await api.dispose();
}
}
export async function requestPatch(path: string, role: 'owner' | 'admin' | 'employee' | null = 'admin', data?: any, opts: any = {}) {
const token = role ? await getToken(role) : undefined;
const api = await buildContext(token);
try {
const res = await api.patch(path, { data, ...opts });
const body = await parseResponseSafe(res);
return { status: res.status(), body, headers: res.headers() };
} finally {
await api.dispose();
}
}
export async function requestDelete(path: string, role: 'owner' | 'admin' | 'employee' | null = 'admin', opts: any = {}) {
const token = role ? await getToken(role) : undefined;
const api = await buildContext(token);
try {
const res = await api.delete(path, opts);
const body = await parseResponseSafe(res);
return { status: res.status(), body, headers: res.headers() };
} finally {
await api.dispose();
}
}
async function parseResponseSafe(res: any) {
const ct = res.headers()['content-type'] || '';
try {
if (ct.includes('application/json')) return await res.json();
return await res.text();
} catch (e) {
try {
return await res.text();
} catch (e2) {
return null;
}
}
}