create-crm-tmp 1.1.2 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/template/.prettierignore +2 -0
- package/template/README.md +53 -67
- package/template/components.json +22 -0
- package/template/exemple-contacts.csv +54 -0
- package/template/next.config.ts +27 -1
- package/template/package.json +64 -27
- package/template/prisma/schema.prisma +821 -72
- package/template/skills-lock.json +25 -0
- package/template/src/app/(auth)/invite/[token]/page.tsx +21 -24
- package/template/src/app/(auth)/reset-password/complete/page.tsx +12 -21
- package/template/src/app/(auth)/reset-password/page.tsx +12 -8
- package/template/src/app/(auth)/reset-password/verify/page.tsx +12 -8
- package/template/src/app/(auth)/signin/page.tsx +20 -17
- package/template/src/app/(dashboard)/agenda/page.tsx +2231 -2188
- package/template/src/app/(dashboard)/automatisation/[id]/page.tsx +10 -7
- package/template/src/app/(dashboard)/automatisation/_components/workflow-editor.tsx +680 -323
- package/template/src/app/(dashboard)/automatisation/new/page.tsx +11 -8
- package/template/src/app/(dashboard)/automatisation/page.tsx +473 -180
- package/template/src/app/(dashboard)/closing/page.tsx +500 -468
- package/template/src/app/(dashboard)/contacts/[id]/page.tsx +5035 -4126
- package/template/src/app/(dashboard)/contacts/companies/[id]/page.tsx +1703 -0
- package/template/src/app/(dashboard)/contacts/loading.tsx +13 -0
- package/template/src/app/(dashboard)/contacts/page.tsx +3776 -2064
- package/template/src/app/(dashboard)/dashboard/page.tsx +37 -519
- package/template/src/app/(dashboard)/error.tsx +37 -0
- package/template/src/app/(dashboard)/layout.tsx +1 -1
- package/template/src/app/(dashboard)/loading.tsx +5 -0
- package/template/src/app/(dashboard)/settings/loading.tsx +19 -0
- package/template/src/app/(dashboard)/settings/page.tsx +2685 -2489
- package/template/src/app/(dashboard)/templates/page.tsx +500 -300
- package/template/src/app/(dashboard)/users/list/page.tsx +356 -350
- package/template/src/app/(dashboard)/users/page.tsx +279 -310
- package/template/src/app/(dashboard)/users/permissions/page.tsx +104 -99
- package/template/src/app/(dashboard)/users/roles/page.tsx +164 -137
- package/template/src/app/api/audit-logs/route.ts +1 -1
- package/template/src/app/api/auth/google/callback/route.ts +8 -5
- package/template/src/app/api/auth/google/disconnect/route.ts +2 -2
- package/template/src/app/api/companies/[id]/activities/route.ts +131 -0
- package/template/src/app/api/companies/[id]/route.ts +195 -0
- package/template/src/app/api/companies/export/route.ts +206 -0
- package/template/src/app/api/companies/route.ts +166 -0
- package/template/src/app/api/contact-views/[id]/pin/route.ts +69 -0
- package/template/src/app/api/contact-views/[id]/route.ts +197 -0
- package/template/src/app/api/contact-views/route.ts +146 -0
- package/template/src/app/api/contacts/[id]/files/[fileId]/preview/route.ts +77 -0
- package/template/src/app/api/contacts/[id]/files/[fileId]/route.ts +7 -17
- package/template/src/app/api/contacts/[id]/files/route.ts +83 -44
- package/template/src/app/api/contacts/[id]/interactions/route.ts +37 -0
- package/template/src/app/api/contacts/[id]/kyc/route.ts +71 -0
- package/template/src/app/api/contacts/[id]/meet/route.ts +38 -29
- package/template/src/app/api/contacts/[id]/route.ts +111 -20
- package/template/src/app/api/contacts/[id]/send-email/route.ts +6 -0
- package/template/src/app/api/contacts/[id]/workflows/run/route.ts +61 -0
- package/template/src/app/api/contacts/export/route.ts +12 -17
- package/template/src/app/api/contacts/import/route.ts +22 -19
- package/template/src/app/api/contacts/import-preview/route.ts +139 -0
- package/template/src/app/api/contacts/route.ts +202 -49
- package/template/src/app/api/dashboard/stats/route.ts +9 -292
- package/template/src/app/api/integrations/google-sheet/sync/route.ts +203 -185
- package/template/src/app/api/invite/complete/route.ts +20 -23
- package/template/src/app/api/reminders/route.ts +1 -0
- package/template/src/app/api/reset-password/complete/route.ts +11 -13
- package/template/src/app/api/send/route.ts +9 -85
- package/template/src/app/api/settings/closing-reasons/[id]/route.ts +10 -21
- package/template/src/app/api/settings/closing-reasons/route.ts +10 -21
- package/template/src/app/api/settings/company/route.ts +19 -26
- package/template/src/app/api/settings/google-ads/[id]/route.ts +20 -23
- package/template/src/app/api/settings/google-ads/route.ts +20 -23
- package/template/src/app/api/settings/google-sheet/[id]/route.ts +20 -23
- package/template/src/app/api/settings/google-sheet/auto-map/route.ts +23 -32
- package/template/src/app/api/settings/google-sheet/preview/route.ts +104 -0
- package/template/src/app/api/settings/google-sheet/route.ts +20 -23
- package/template/src/app/api/settings/meta-leads/[id]/route.ts +20 -23
- package/template/src/app/api/settings/meta-leads/route.ts +20 -23
- package/template/src/app/api/settings/statuses/[id]/route.ts +33 -23
- package/template/src/app/api/settings/statuses/route.ts +24 -22
- package/template/src/app/api/statuses/route.ts +2 -5
- package/template/src/app/api/tasks/[id]/attendees/route.ts +14 -7
- package/template/src/app/api/tasks/[id]/route.ts +161 -137
- package/template/src/app/api/tasks/meet/route.ts +11 -8
- package/template/src/app/api/tasks/route.ts +155 -95
- package/template/src/app/api/templates/[id]/route.ts +22 -13
- package/template/src/app/api/templates/route.ts +22 -5
- package/template/src/app/api/users/[id]/resend-invite/route.ts +95 -0
- package/template/src/app/api/users/[id]/route.ts +16 -1
- package/template/src/app/api/users/commercials/route.ts +38 -0
- package/template/src/app/api/users/for-agenda/route.ts +1 -2
- package/template/src/app/api/users/route.ts +94 -55
- package/template/src/app/api/webhooks/google-ads/route.ts +20 -1
- package/template/src/app/api/webhooks/meta-leads/route.ts +18 -1
- package/template/src/app/api/workflows/[id]/route.ts +33 -6
- package/template/src/app/api/workflows/process/route.ts +509 -146
- package/template/src/app/api/workflows/route.ts +46 -4
- package/template/src/app/globals.css +210 -101
- package/template/src/app/layout.tsx +19 -8
- package/template/src/app/page.tsx +37 -7
- package/template/src/components/address-autocomplete.tsx +232 -0
- package/template/src/components/contacts/filter-bar.tsx +181 -0
- package/template/src/components/contacts/filter-builder.tsx +589 -0
- package/template/src/components/contacts/save-view-dialog.tsx +160 -0
- package/template/src/components/contacts/views-tab-bar.tsx +440 -0
- package/template/src/components/dashboard/activity-chart.tsx +31 -39
- package/template/src/components/dashboard/dashboard-content.tsx +79 -0
- package/template/src/components/dashboard/stat-card.tsx +40 -42
- package/template/src/components/dashboard/tasks-pie-chart.tsx +34 -37
- package/template/src/components/dashboard/upcoming-tasks-list.tsx +78 -72
- package/template/src/components/date-picker.tsx +396 -0
- package/template/src/components/editor.tsx +27 -13
- package/template/src/components/email-template.tsx +4 -2
- package/template/src/components/global-search.tsx +358 -0
- package/template/src/components/header.tsx +57 -62
- package/template/src/components/invitation-email-template.tsx +4 -2
- package/template/src/components/lazy-editor.tsx +11 -0
- package/template/src/components/meet-cancellation-email-template.tsx +11 -3
- package/template/src/components/meet-confirmation-email-template.tsx +10 -3
- package/template/src/components/meet-update-email-template.tsx +10 -3
- package/template/src/components/page-header.tsx +19 -15
- package/template/src/components/protected-page.tsx +94 -0
- package/template/src/components/reset-password-email-template.tsx +4 -2
- package/template/src/components/sidebar.tsx +92 -94
- package/template/src/components/skeleton.tsx +128 -42
- package/template/src/components/ui/accordion.tsx +64 -0
- package/template/src/components/ui/alert-dialog.tsx +139 -0
- package/template/src/components/ui/button.tsx +60 -0
- package/template/src/components/view-as-banner.tsx +1 -1
- package/template/src/components/view-as-modal.tsx +21 -16
- package/template/src/config/nav-pages.ts +108 -0
- package/template/src/contexts/app-toast-context.tsx +174 -0
- package/template/src/contexts/sidebar-context.tsx +16 -47
- package/template/src/contexts/task-reminder-context.tsx +6 -6
- package/template/src/contexts/view-as-context.tsx +11 -16
- package/template/src/hooks/use-alert.tsx +65 -0
- package/template/src/hooks/use-confirm.tsx +87 -0
- package/template/src/hooks/use-contact-views.ts +140 -0
- package/template/src/hooks/use-contacts.ts +69 -0
- package/template/src/hooks/use-fetch.ts +17 -0
- package/template/src/hooks/use-focus-trap.ts +73 -0
- package/template/src/hooks/use-statuses.ts +22 -0
- package/template/src/lib/address-api.ts +155 -0
- package/template/src/lib/cache.ts +73 -0
- package/template/src/lib/check-permission.ts +12 -177
- package/template/src/lib/contact-interactions.ts +3 -1
- package/template/src/lib/contact-view-filters.ts +341 -0
- package/template/src/lib/dashboard-stats.ts +224 -0
- package/template/src/lib/date-utils.ts +49 -0
- package/template/src/lib/get-auth-user.ts +25 -0
- package/template/src/lib/google-calendar.ts +54 -12
- package/template/src/lib/google-drive.ts +796 -75
- package/template/src/lib/google-fetch.ts +63 -0
- package/template/src/lib/local-storage.ts +34 -0
- package/template/src/lib/permissions.ts +245 -47
- package/template/src/lib/prisma.ts +11 -11
- package/template/src/lib/roles.ts +14 -39
- package/template/src/lib/template-variables.ts +67 -33
- package/template/src/lib/utils.ts +26 -2
- package/template/src/lib/workflow-executor.ts +445 -229
- package/template/src/proxy.ts +34 -73
- package/template/src/types/contact-views.ts +351 -0
- package/template/src/types/yousign.ts +52 -0
- package/template/vercel.json +12 -0
- package/template/WORKFLOWS_CRON.md +0 -185
- package/template/prisma/migrations/20251126144728_init/migration.sql +0 -78
- package/template/prisma/migrations/20251126155204_add_user_roles/migration.sql +0 -5
- package/template/prisma/migrations/20251128095126_add_company_info/migration.sql +0 -19
- package/template/prisma/migrations/20251128123321_add_smtp_config/migration.sql +0 -22
- package/template/prisma/migrations/20251128132303_add_status/migration.sql +0 -23
- package/template/prisma/migrations/20251201102207_add_user_active/migration.sql +0 -75
- package/template/prisma/migrations/20251201105507_add_email_signature/migration.sql +0 -2
- package/template/prisma/migrations/20251201151122_add_tasks/migration.sql +0 -45
- package/template/prisma/migrations/20251202111854_add_task_reminder/migration.sql +0 -2
- package/template/prisma/migrations/20251202135859_add_google_meet_integration/migration.sql +0 -27
- package/template/prisma/migrations/20251203103317_add_meta_lead_integration/migration.sql +0 -20
- package/template/prisma/migrations/20251203104002_add_google_ads_integration/migration.sql +0 -18
- package/template/prisma/migrations/20251203112122_add_google_sheet_integration/migration.sql +0 -32
- package/template/prisma/migrations/20251203153853_allow_multiple_integration_configs/migration.sql +0 -20
- package/template/prisma/migrations/20251205141705_update_user_roles/migration.sql +0 -12
- package/template/prisma/migrations/20251205150000_add_commercial_and_telepro_assignment/migration.sql +0 -21
- package/template/prisma/migrations/20251205160000_add_interaction_logging/migration.sql +0 -11
- package/template/prisma/migrations/20251208090314_add_automatic_interaction_types/migration.sql +0 -12
- package/template/prisma/migrations/20251208094843_mg/migration.sql +0 -14
- package/template/prisma/migrations/20251208100000_add_company_support/migration.sql +0 -14
- package/template/prisma/migrations/20251208110000_add_templates/migration.sql +0 -26
- package/template/prisma/migrations/20251208141304_add_video_conference_task_type/migration.sql +0 -2
- package/template/prisma/migrations/20251209104759_add_internal_note_to_task/migration.sql +0 -2
- package/template/prisma/migrations/20251209134803_add_company_field/migration.sql +0 -2
- package/template/prisma/migrations/20251209150000_rename_company_to_company_name/migration.sql +0 -3
- package/template/prisma/migrations/20251209150016_add_email_tracking/migration.sql +0 -21
- package/template/prisma/migrations/20251209155908_add_notify_contact_to_task/migration.sql +0 -2
- package/template/prisma/migrations/20251210110019_add_appointment_types/migration.sql +0 -10
- package/template/prisma/migrations/20251210113928_add_contact_files/migration.sql +0 -26
- package/template/prisma/migrations/20251212132339_add_custom_roles/migration.sql +0 -24
- package/template/prisma/migrations/20251215104448_add_file_interaction_types/migration.sql +0 -11
- package/template/prisma/migrations/20251215145616_add_closing_reasons/migration.sql +0 -12
- package/template/prisma/migrations/20251216140850_add_log_users/migration.sql +0 -25
- package/template/prisma/migrations/20251216151000_rename_perdu_to_ferme/migration.sql +0 -8
- package/template/prisma/migrations/20251216162318_add_column_mappings_to_google_sheet/migration.sql +0 -2
- package/template/prisma/migrations/20251216185127_add_workflows/migration.sql +0 -80
- package/template/prisma/migrations/20251216192237_add_scheduled_workflow_actions/migration.sql +0 -32
- package/template/prisma/migrations/20251220000000_add_task_interaction_type/migration.sql +0 -4
- package/template/prisma/migrations/20251221000000_add_task_type/migration.sql +0 -3
- package/template/prisma/migrations/20251221000001_add_event_color/migration.sql +0 -23
- package/template/prisma/migrations/20260210114913_add_dashboard_widget/migration.sql +0 -20
- package/template/prisma/migrations/migration_lock.toml +0 -3
- package/template/src/app/(dashboard)/users/layout.tsx +0 -30
- package/template/src/app/api/dashboard/widgets/[id]/route.ts +0 -47
- package/template/src/app/api/dashboard/widgets/route.ts +0 -181
- package/template/src/components/dashboard/add-widget-dialog.tsx +0 -161
- package/template/src/components/dashboard/color-picker.tsx +0 -65
- package/template/src/components/dashboard/contacts-chart.tsx +0 -69
- package/template/src/components/dashboard/interactions-by-type-chart.tsx +0 -121
- package/template/src/components/dashboard/recent-activity.tsx +0 -157
- package/template/src/components/dashboard/sales-analytics-chart.tsx +0 -77
- package/template/src/components/dashboard/status-distribution-chart.tsx +0 -82
- package/template/src/components/dashboard/top-contacts-list.tsx +0 -119
- package/template/src/components/dashboard/widget-wrapper.tsx +0 -39
- package/template/src/contexts/dashboard-theme-context.tsx +0 -58
- package/template/src/lib/dashboard-themes.ts +0 -140
- package/template/src/lib/default-widgets.ts +0 -14
- package/template/src/lib/widget-registry.ts +0 -177
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
const MAX_RETRIES = 3;
|
|
2
|
+
const BASE_DELAY_MS = 1000;
|
|
3
|
+
|
|
4
|
+
interface GoogleFetchOptions extends RequestInit {
|
|
5
|
+
maxRetries?: number;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Wrapper autour de fetch pour les APIs Google avec retry automatique,
|
|
10
|
+
* backoff exponentiel et gestion des erreurs de quota (429) et serveur (5xx).
|
|
11
|
+
*/
|
|
12
|
+
export async function googleFetch(
|
|
13
|
+
url: string,
|
|
14
|
+
options: GoogleFetchOptions = {},
|
|
15
|
+
): Promise<Response> {
|
|
16
|
+
const { maxRetries = MAX_RETRIES, ...fetchOptions } = options;
|
|
17
|
+
|
|
18
|
+
let lastError: Error | null = null;
|
|
19
|
+
|
|
20
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
21
|
+
try {
|
|
22
|
+
const response = await fetch(url, fetchOptions);
|
|
23
|
+
|
|
24
|
+
if (response.ok) {
|
|
25
|
+
return response;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const status = response.status;
|
|
29
|
+
|
|
30
|
+
// Ne pas retry les erreurs client (sauf 429 rate limit)
|
|
31
|
+
if (status >= 400 && status < 500 && status !== 429) {
|
|
32
|
+
return response;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Retry sur 429 (rate limit) et 5xx (erreur serveur)
|
|
36
|
+
if (attempt < maxRetries && (status === 429 || status >= 500)) {
|
|
37
|
+
const retryAfter = response.headers.get('Retry-After');
|
|
38
|
+
const delayMs = retryAfter
|
|
39
|
+
? Number.parseInt(retryAfter, 10) * 1000
|
|
40
|
+
: BASE_DELAY_MS * Math.pow(2, attempt) + Math.random() * 500;
|
|
41
|
+
|
|
42
|
+
await sleep(delayMs);
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return response;
|
|
47
|
+
} catch (error) {
|
|
48
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
49
|
+
|
|
50
|
+
if (attempt < maxRetries) {
|
|
51
|
+
const delayMs = BASE_DELAY_MS * Math.pow(2, attempt) + Math.random() * 500;
|
|
52
|
+
await sleep(delayMs);
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
throw lastError || new Error(`Google API request failed after ${maxRetries + 1} attempts`);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function sleep(ms: number): Promise<void> {
|
|
62
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
63
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
const APP_STORAGE_VERSION = 'v1';
|
|
2
|
+
|
|
3
|
+
function getVersionedKey(key: string) {
|
|
4
|
+
return `${key}:${APP_STORAGE_VERSION}`;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function safeLocalStorageGet<T>(key: string, fallback: T): T {
|
|
8
|
+
if (typeof window === 'undefined') return fallback;
|
|
9
|
+
try {
|
|
10
|
+
const raw = window.localStorage.getItem(getVersionedKey(key));
|
|
11
|
+
if (!raw) return fallback;
|
|
12
|
+
return JSON.parse(raw) as T;
|
|
13
|
+
} catch {
|
|
14
|
+
return fallback;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function safeLocalStorageSet<T>(key: string, value: T) {
|
|
19
|
+
if (typeof window === 'undefined') return;
|
|
20
|
+
try {
|
|
21
|
+
window.localStorage.setItem(getVersionedKey(key), JSON.stringify(value));
|
|
22
|
+
} catch {
|
|
23
|
+
// Ignore private mode / quota errors.
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function safeLocalStorageRemove(key: string) {
|
|
28
|
+
if (typeof window === 'undefined') return;
|
|
29
|
+
try {
|
|
30
|
+
window.localStorage.removeItem(getVersionedKey(key));
|
|
31
|
+
} catch {
|
|
32
|
+
// Ignore private mode / quota errors.
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -11,35 +11,25 @@ export interface Permission {
|
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
export const PERMISSION_CATEGORIES = {
|
|
14
|
-
DASHBOARD: '
|
|
14
|
+
DASHBOARD: 'Dashboard',
|
|
15
15
|
ANALYTICS: 'Analytics',
|
|
16
16
|
CONTACTS: 'Contacts',
|
|
17
17
|
TASKS: 'Tâches',
|
|
18
|
+
WORKFLOWS: 'Workflows',
|
|
18
19
|
TEMPLATES: 'Templates',
|
|
19
20
|
INTEGRATIONS: 'Intégrations',
|
|
20
21
|
USERS: 'Utilisateurs',
|
|
21
22
|
SETTINGS: 'Paramètres',
|
|
23
|
+
AUDIT: 'Audit',
|
|
22
24
|
GENERAL: 'Général',
|
|
23
25
|
} as const;
|
|
24
26
|
|
|
25
27
|
export const PERMISSIONS: Permission[] = [
|
|
26
|
-
//
|
|
28
|
+
// Dashboard
|
|
27
29
|
{
|
|
28
30
|
code: 'dashboard.view',
|
|
29
|
-
name: '
|
|
30
|
-
description: 'Permet
|
|
31
|
-
category: PERMISSION_CATEGORIES.DASHBOARD,
|
|
32
|
-
},
|
|
33
|
-
{
|
|
34
|
-
code: 'dashboard.widgets.manage',
|
|
35
|
-
name: 'Gérer les widgets',
|
|
36
|
-
description: 'Permet d\'ajouter, supprimer et réorganiser les widgets du tableau de bord',
|
|
37
|
-
category: PERMISSION_CATEGORIES.DASHBOARD,
|
|
38
|
-
},
|
|
39
|
-
{
|
|
40
|
-
code: 'dashboard.widgets.reset',
|
|
41
|
-
name: 'Réinitialiser le tableau de bord',
|
|
42
|
-
description: 'Permet de réinitialiser la disposition des widgets aux valeurs par défaut',
|
|
31
|
+
name: 'Accéder au dashboard',
|
|
32
|
+
description: 'Permet de voir le tableau de bord principal',
|
|
43
33
|
category: PERMISSION_CATEGORIES.DASHBOARD,
|
|
44
34
|
},
|
|
45
35
|
|
|
@@ -61,8 +51,7 @@ export const PERMISSIONS: Permission[] = [
|
|
|
61
51
|
{
|
|
62
52
|
code: 'contacts.view_all',
|
|
63
53
|
name: 'Voir tous les contacts',
|
|
64
|
-
description:
|
|
65
|
-
'Permet de voir tous les contacts de toutes les entreprises (réservé aux administrateurs)',
|
|
54
|
+
description: 'Permet de voir tous les contacts de toutes les entreprises',
|
|
66
55
|
category: PERMISSION_CATEGORIES.CONTACTS,
|
|
67
56
|
},
|
|
68
57
|
{
|
|
@@ -131,6 +120,110 @@ export const PERMISSIONS: Permission[] = [
|
|
|
131
120
|
description: 'Permet de voir les fichiers associés aux contacts',
|
|
132
121
|
category: PERMISSION_CATEGORIES.CONTACTS,
|
|
133
122
|
},
|
|
123
|
+
{
|
|
124
|
+
code: 'contacts.view_closing_pipeline',
|
|
125
|
+
name: 'Voir le pipeline de clôture',
|
|
126
|
+
description: 'Permet de visualiser le pipeline kanban de clôture des contacts',
|
|
127
|
+
category: PERMISSION_CATEGORIES.CONTACTS,
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
code: 'contacts.manage_pipeline',
|
|
131
|
+
name: 'Gérer le pipeline de clôture',
|
|
132
|
+
description: 'Permet de déplacer les contacts dans le pipeline kanban',
|
|
133
|
+
category: PERMISSION_CATEGORIES.CONTACTS,
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
code: 'contacts.send_email',
|
|
137
|
+
name: 'Envoyer des emails',
|
|
138
|
+
description: "Permet d'envoyer des emails aux contacts depuis leur fiche",
|
|
139
|
+
category: PERMISSION_CATEGORIES.CONTACTS,
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
code: 'contacts.delete_files',
|
|
143
|
+
name: 'Supprimer des fichiers',
|
|
144
|
+
description: 'Permet de supprimer les fichiers associés aux contacts',
|
|
145
|
+
category: PERMISSION_CATEGORIES.CONTACTS,
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
code: 'contacts.views.create',
|
|
149
|
+
name: 'Créer des vues de contacts',
|
|
150
|
+
description: 'Permet de créer des vues personnalisées de contacts',
|
|
151
|
+
category: PERMISSION_CATEGORIES.CONTACTS,
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
code: 'contacts.views.edit_own',
|
|
155
|
+
name: 'Modifier ses vues',
|
|
156
|
+
description: 'Permet de modifier ses propres vues de contacts',
|
|
157
|
+
category: PERMISSION_CATEGORIES.CONTACTS,
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
code: 'contacts.views.edit_all',
|
|
161
|
+
name: 'Modifier toutes les vues',
|
|
162
|
+
description: 'Permet de modifier les vues de tous les utilisateurs',
|
|
163
|
+
category: PERMISSION_CATEGORIES.CONTACTS,
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
code: 'contacts.views.delete_own',
|
|
167
|
+
name: 'Supprimer ses vues',
|
|
168
|
+
description: 'Permet de supprimer ses propres vues de contacts',
|
|
169
|
+
category: PERMISSION_CATEGORIES.CONTACTS,
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
code: 'contacts.views.delete_all',
|
|
173
|
+
name: 'Supprimer toutes les vues',
|
|
174
|
+
description: 'Permet de supprimer les vues de tous les utilisateurs',
|
|
175
|
+
category: PERMISSION_CATEGORIES.CONTACTS,
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
code: 'contacts.views.share',
|
|
179
|
+
name: 'Partager des vues',
|
|
180
|
+
description: 'Permet de rendre des vues publiques ou privées',
|
|
181
|
+
category: PERMISSION_CATEGORIES.CONTACTS,
|
|
182
|
+
},
|
|
183
|
+
|
|
184
|
+
// Entreprises (fiches entreprise, liste, activités)
|
|
185
|
+
{
|
|
186
|
+
code: 'companies.view_all',
|
|
187
|
+
name: 'Voir toutes les entreprises',
|
|
188
|
+
description: 'Permet de voir toutes les entreprises (vue Entreprises)',
|
|
189
|
+
category: PERMISSION_CATEGORIES.CONTACTS,
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
code: 'companies.view_own',
|
|
193
|
+
name: 'Voir ses entreprises',
|
|
194
|
+
description: 'Permet de voir uniquement les entreprises assignées ou créées',
|
|
195
|
+
category: PERMISSION_CATEGORIES.CONTACTS,
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
code: 'companies.create',
|
|
199
|
+
name: 'Créer une entreprise',
|
|
200
|
+
description: 'Autorise la création de nouvelles entreprises',
|
|
201
|
+
category: PERMISSION_CATEGORIES.CONTACTS,
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
code: 'companies.edit',
|
|
205
|
+
name: 'Modifier une entreprise',
|
|
206
|
+
description: "Autorise la modification des informations d'une entreprise",
|
|
207
|
+
category: PERMISSION_CATEGORIES.CONTACTS,
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
code: 'companies.delete',
|
|
211
|
+
name: 'Supprimer une entreprise',
|
|
212
|
+
description: "Autorise la suppression d'une entreprise (les contacts liés sont déliés)",
|
|
213
|
+
category: PERMISSION_CATEGORIES.CONTACTS,
|
|
214
|
+
},
|
|
215
|
+
{
|
|
216
|
+
code: 'companies.view_activities',
|
|
217
|
+
name: "Voir les activités d'une entreprise",
|
|
218
|
+
description: "Permet de voir l'historique des activités (modifications, contacts ajoutés)",
|
|
219
|
+
category: PERMISSION_CATEGORIES.CONTACTS,
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
code: 'companies.add_activity',
|
|
223
|
+
name: 'Ajouter une activité entreprise',
|
|
224
|
+
description: "Permet d'enregistrer une activité sur une fiche entreprise (notes, etc.)",
|
|
225
|
+
category: PERMISSION_CATEGORIES.CONTACTS,
|
|
226
|
+
},
|
|
134
227
|
|
|
135
228
|
// Tâches
|
|
136
229
|
{
|
|
@@ -183,6 +276,38 @@ export const PERMISSIONS: Permission[] = [
|
|
|
183
276
|
category: PERMISSION_CATEGORIES.TASKS,
|
|
184
277
|
},
|
|
185
278
|
|
|
279
|
+
// Workflows
|
|
280
|
+
{
|
|
281
|
+
code: 'workflows.view',
|
|
282
|
+
name: 'Voir les workflows',
|
|
283
|
+
description: 'Permet de voir les workflows automatisés',
|
|
284
|
+
category: PERMISSION_CATEGORIES.WORKFLOWS,
|
|
285
|
+
},
|
|
286
|
+
{
|
|
287
|
+
code: 'workflows.create',
|
|
288
|
+
name: 'Créer un workflow',
|
|
289
|
+
description: 'Autorise la création de nouveaux workflows',
|
|
290
|
+
category: PERMISSION_CATEGORIES.WORKFLOWS,
|
|
291
|
+
},
|
|
292
|
+
{
|
|
293
|
+
code: 'workflows.edit',
|
|
294
|
+
name: 'Modifier un workflow',
|
|
295
|
+
description: 'Autorise la modification de workflows',
|
|
296
|
+
category: PERMISSION_CATEGORIES.WORKFLOWS,
|
|
297
|
+
},
|
|
298
|
+
{
|
|
299
|
+
code: 'workflows.delete',
|
|
300
|
+
name: 'Supprimer un workflow',
|
|
301
|
+
description: 'Autorise la suppression de workflows',
|
|
302
|
+
category: PERMISSION_CATEGORIES.WORKFLOWS,
|
|
303
|
+
},
|
|
304
|
+
{
|
|
305
|
+
code: 'workflows.activate',
|
|
306
|
+
name: 'Activer/désactiver des workflows',
|
|
307
|
+
description: "Permet d'activer ou désactiver des workflows",
|
|
308
|
+
category: PERMISSION_CATEGORIES.WORKFLOWS,
|
|
309
|
+
},
|
|
310
|
+
|
|
186
311
|
// Templates
|
|
187
312
|
{
|
|
188
313
|
code: 'templates.view',
|
|
@@ -258,13 +383,6 @@ export const PERMISSIONS: Permission[] = [
|
|
|
258
383
|
description: 'Permet de configurer les synchronisations Google Sheets',
|
|
259
384
|
category: PERMISSION_CATEGORIES.INTEGRATIONS,
|
|
260
385
|
},
|
|
261
|
-
{
|
|
262
|
-
code: 'integrations.google_drive.manage',
|
|
263
|
-
name: 'Gérer Google Drive partagé',
|
|
264
|
-
description:
|
|
265
|
-
'Permet de configurer le compte Google Drive administrateur utilisé pour le stockage des fichiers',
|
|
266
|
-
category: PERMISSION_CATEGORIES.INTEGRATIONS,
|
|
267
|
-
},
|
|
268
386
|
|
|
269
387
|
// Utilisateurs
|
|
270
388
|
{
|
|
@@ -331,16 +449,35 @@ export const PERMISSIONS: Permission[] = [
|
|
|
331
449
|
},
|
|
332
450
|
{
|
|
333
451
|
code: 'settings.closing_reasons.manage',
|
|
334
|
-
name: 'Gérer les motifs de
|
|
335
|
-
description: 'Permet de créer, modifier et supprimer des motifs de
|
|
452
|
+
name: 'Gérer les motifs de clôture',
|
|
453
|
+
description: 'Permet de créer, modifier et supprimer des motifs de clôture',
|
|
336
454
|
category: PERMISSION_CATEGORIES.SETTINGS,
|
|
337
455
|
},
|
|
338
456
|
{
|
|
339
457
|
code: 'settings.workflows.manage',
|
|
340
|
-
name: 'Gérer les
|
|
341
|
-
description: 'Permet de
|
|
458
|
+
name: 'Gérer les paramètres de workflows',
|
|
459
|
+
description: 'Permet de configurer les paramètres globaux des workflows',
|
|
342
460
|
category: PERMISSION_CATEGORIES.SETTINGS,
|
|
343
461
|
},
|
|
462
|
+
// Audit
|
|
463
|
+
{
|
|
464
|
+
code: 'audit.view_all',
|
|
465
|
+
name: "Voir tous les logs d'audit",
|
|
466
|
+
description: "Permet de consulter l'historique complet des actions du système",
|
|
467
|
+
category: PERMISSION_CATEGORIES.AUDIT,
|
|
468
|
+
},
|
|
469
|
+
{
|
|
470
|
+
code: 'audit.view_own',
|
|
471
|
+
name: "Voir ses logs d'audit",
|
|
472
|
+
description: "Permet de consulter uniquement son propre historique d'actions",
|
|
473
|
+
category: PERMISSION_CATEGORIES.AUDIT,
|
|
474
|
+
},
|
|
475
|
+
{
|
|
476
|
+
code: 'audit.export',
|
|
477
|
+
name: "Exporter les logs d'audit",
|
|
478
|
+
description: "Autorise l'exportation des logs d'audit",
|
|
479
|
+
category: PERMISSION_CATEGORIES.AUDIT,
|
|
480
|
+
},
|
|
344
481
|
|
|
345
482
|
// Général
|
|
346
483
|
{
|
|
@@ -350,13 +487,6 @@ export const PERMISSIONS: Permission[] = [
|
|
|
350
487
|
'Permet de voir tous les contacts de toutes les entreprises (réservé aux administrateurs)',
|
|
351
488
|
category: PERMISSION_CATEGORIES.GENERAL,
|
|
352
489
|
},
|
|
353
|
-
{
|
|
354
|
-
code: 'general.audit_logs.view',
|
|
355
|
-
name: 'Voir les logs d’audit',
|
|
356
|
-
description:
|
|
357
|
-
'Permet de consulter les journaux d’audit (actions des utilisateurs, historique des modifications)',
|
|
358
|
-
category: PERMISSION_CATEGORIES.GENERAL,
|
|
359
|
-
},
|
|
360
490
|
];
|
|
361
491
|
|
|
362
492
|
// Regrouper les permissions par catégorie
|
|
@@ -371,7 +501,6 @@ export const PERMISSIONS_BY_CATEGORY = PERMISSIONS.reduce(
|
|
|
371
501
|
{} as Record<string, Permission[]>,
|
|
372
502
|
);
|
|
373
503
|
|
|
374
|
-
// Profils par défaut avec leurs permissions
|
|
375
504
|
export const DEFAULT_ROLES = {
|
|
376
505
|
ADMIN: {
|
|
377
506
|
name: 'Administrateur',
|
|
@@ -383,9 +512,8 @@ export const DEFAULT_ROLES = {
|
|
|
383
512
|
description: "Gestion d'équipe et accès étendu aux leads",
|
|
384
513
|
permissions: [
|
|
385
514
|
'dashboard.view',
|
|
386
|
-
'dashboard.widgets.manage',
|
|
387
|
-
'dashboard.widgets.reset',
|
|
388
515
|
'analytics.view',
|
|
516
|
+
'general.view_all_companies',
|
|
389
517
|
'contacts.view_all',
|
|
390
518
|
'contacts.create',
|
|
391
519
|
'contacts.edit_all',
|
|
@@ -394,17 +522,54 @@ export const DEFAULT_ROLES = {
|
|
|
394
522
|
'contacts.export',
|
|
395
523
|
'contacts.view_files',
|
|
396
524
|
'contacts.upload_files',
|
|
525
|
+
'contacts.view_closing_pipeline',
|
|
526
|
+
'contacts.manage_pipeline',
|
|
527
|
+
'contacts.send_email',
|
|
528
|
+
'contacts.delete_files',
|
|
529
|
+
'contacts.views.create',
|
|
530
|
+
'contacts.views.edit_own',
|
|
531
|
+
'contacts.views.edit_all',
|
|
532
|
+
'contacts.views.delete_own',
|
|
533
|
+
'contacts.views.delete_all',
|
|
534
|
+
'contacts.views.share',
|
|
535
|
+
'companies.view_all',
|
|
536
|
+
'companies.create',
|
|
537
|
+
'companies.edit',
|
|
538
|
+
'companies.delete',
|
|
539
|
+
'companies.view_activities',
|
|
540
|
+
'companies.add_activity',
|
|
397
541
|
'tasks.view_all',
|
|
398
542
|
'tasks.create',
|
|
399
543
|
'tasks.edit_all',
|
|
400
544
|
'tasks.assign',
|
|
545
|
+
'tasks.view_other_users_events',
|
|
546
|
+
'workflows.view',
|
|
547
|
+
'workflows.create',
|
|
548
|
+
'workflows.edit',
|
|
549
|
+
'workflows.activate',
|
|
550
|
+
'settings.workflows.manage',
|
|
551
|
+
'workflows.view',
|
|
552
|
+
'workflows.create',
|
|
553
|
+
'workflows.edit',
|
|
554
|
+
'workflows.activate',
|
|
401
555
|
'templates.view',
|
|
402
556
|
'templates.create',
|
|
403
557
|
'templates.edit',
|
|
404
558
|
'templates.delete',
|
|
405
559
|
'integrations.view',
|
|
560
|
+
'integrations.create',
|
|
561
|
+
'integrations.edit',
|
|
562
|
+
'integrations.delete',
|
|
563
|
+
'integrations.meta.manage',
|
|
564
|
+
'integrations.google_ads.manage',
|
|
565
|
+
'integrations.google_sheets.manage',
|
|
406
566
|
'users.view',
|
|
407
567
|
'settings.view',
|
|
568
|
+
'settings.status.manage',
|
|
569
|
+
'settings.closing_reasons.manage',
|
|
570
|
+
'audit.view_all',
|
|
571
|
+
'audit.view_own',
|
|
572
|
+
'audit.export',
|
|
408
573
|
],
|
|
409
574
|
},
|
|
410
575
|
COMMERCIAL: {
|
|
@@ -412,21 +577,37 @@ export const DEFAULT_ROLES = {
|
|
|
412
577
|
description: 'Accès de base pour la gestion des leads personnels',
|
|
413
578
|
permissions: [
|
|
414
579
|
'dashboard.view',
|
|
415
|
-
'dashboard.widgets.manage',
|
|
416
580
|
'contacts.view_own',
|
|
417
581
|
'contacts.view_unassigned',
|
|
418
582
|
'contacts.create',
|
|
419
583
|
'contacts.edit_own',
|
|
584
|
+
'contacts.export',
|
|
420
585
|
'contacts.view_files',
|
|
421
586
|
'contacts.upload_files',
|
|
587
|
+
'contacts.view_closing_pipeline',
|
|
588
|
+
'contacts.manage_pipeline',
|
|
589
|
+
'contacts.send_email',
|
|
590
|
+
'contacts.views.create',
|
|
591
|
+
'contacts.views.edit_own',
|
|
592
|
+
'contacts.views.delete_own',
|
|
593
|
+
'contacts.views.share',
|
|
594
|
+
'companies.view_own',
|
|
595
|
+
'companies.create',
|
|
596
|
+
'companies.edit',
|
|
597
|
+
'companies.view_activities',
|
|
598
|
+
'companies.add_activity',
|
|
422
599
|
'tasks.view_own',
|
|
423
600
|
'tasks.create',
|
|
424
601
|
'tasks.edit_own',
|
|
602
|
+
'tasks.assign',
|
|
603
|
+
'audit.view_own',
|
|
425
604
|
'templates.view',
|
|
426
605
|
'templates.create',
|
|
427
606
|
'templates.edit',
|
|
428
607
|
'integrations.view',
|
|
429
608
|
'integrations.google.connect',
|
|
609
|
+
'settings.view',
|
|
610
|
+
'settings.smtp.edit',
|
|
430
611
|
],
|
|
431
612
|
},
|
|
432
613
|
TELEPRO: {
|
|
@@ -439,10 +620,28 @@ export const DEFAULT_ROLES = {
|
|
|
439
620
|
'contacts.create',
|
|
440
621
|
'contacts.edit_own',
|
|
441
622
|
'contacts.view_files',
|
|
623
|
+
'contacts.upload_files',
|
|
624
|
+
'contacts.view_closing_pipeline',
|
|
625
|
+
'contacts.manage_pipeline',
|
|
626
|
+
'contacts.send_email',
|
|
627
|
+
'contacts.views.create',
|
|
628
|
+
'contacts.views.edit_own',
|
|
629
|
+
'contacts.views.delete_own',
|
|
630
|
+
'contacts.views.share',
|
|
631
|
+
'companies.view_own',
|
|
632
|
+
'companies.create',
|
|
633
|
+
'companies.edit',
|
|
634
|
+
'companies.view_activities',
|
|
635
|
+
'companies.add_activity',
|
|
442
636
|
'tasks.view_own',
|
|
443
637
|
'tasks.create',
|
|
444
638
|
'tasks.edit_own',
|
|
639
|
+
'tasks.assign',
|
|
445
640
|
'templates.view',
|
|
641
|
+
'templates.create',
|
|
642
|
+
'templates.edit',
|
|
643
|
+
'settings.view',
|
|
644
|
+
'settings.smtp.edit',
|
|
446
645
|
],
|
|
447
646
|
},
|
|
448
647
|
COMPTABLE: {
|
|
@@ -454,20 +653,19 @@ export const DEFAULT_ROLES = {
|
|
|
454
653
|
'analytics.export',
|
|
455
654
|
'contacts.view_all',
|
|
456
655
|
'contacts.export',
|
|
656
|
+
'companies.view_all',
|
|
657
|
+
'companies.view_activities',
|
|
457
658
|
'tasks.view_all',
|
|
659
|
+
'general.view_all_companies',
|
|
458
660
|
'templates.view',
|
|
459
661
|
'settings.view',
|
|
662
|
+
'audit.view_all',
|
|
663
|
+
'audit.view_own',
|
|
664
|
+
'audit.export',
|
|
460
665
|
],
|
|
461
666
|
},
|
|
462
667
|
};
|
|
463
668
|
|
|
464
|
-
// Helper pour vérifier si un rôle a une permission
|
|
465
669
|
export function hasPermission(rolePermissions: string[], requiredPermission: string): boolean {
|
|
466
670
|
return rolePermissions.includes(requiredPermission);
|
|
467
671
|
}
|
|
468
|
-
|
|
469
|
-
// Helper pour obtenir toutes les permissions d'un rôle
|
|
470
|
-
export function getRolePermissions(role: string): string[] {
|
|
471
|
-
const roleKey = role.toUpperCase() as keyof typeof DEFAULT_ROLES;
|
|
472
|
-
return DEFAULT_ROLES[roleKey]?.permissions || [];
|
|
473
|
-
}
|
|
@@ -15,17 +15,17 @@ const pool = new Pool({
|
|
|
15
15
|
|
|
16
16
|
const adapter = new PrismaPg(pool);
|
|
17
17
|
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
});
|
|
18
|
+
const globalForPrisma = globalThis as unknown as {
|
|
19
|
+
prisma?: PrismaClient;
|
|
20
|
+
};
|
|
22
21
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
22
|
+
export const prisma =
|
|
23
|
+
globalForPrisma.prisma ??
|
|
24
|
+
new PrismaClient({
|
|
25
|
+
adapter,
|
|
26
|
+
log: process.env.NODE_ENV === 'development' ? ['error', 'warn'] : ['error'],
|
|
28
27
|
});
|
|
29
|
-
}
|
|
30
28
|
|
|
31
|
-
|
|
29
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
30
|
+
globalForPrisma.prisma = prisma;
|
|
31
|
+
}
|
|
@@ -30,11 +30,7 @@ function getRoleLevel(role: string): number {
|
|
|
30
30
|
return ROLE_HIERARCHY[role] || 999; // Rôle inconnu = niveau très bas
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
|
|
34
|
-
* Vérifie si l'utilisateur a le rôle requis ou un rôle supérieur dans la hiérarchie
|
|
35
|
-
* Un rôle supérieur a automatiquement les permissions des rôles inférieurs
|
|
36
|
-
*/
|
|
37
|
-
export function hasRole(userRole: string | undefined, requiredRole: Role): boolean {
|
|
33
|
+
function hasRole(userRole: string | undefined, requiredRole: Role): boolean {
|
|
38
34
|
if (!userRole) return false;
|
|
39
35
|
|
|
40
36
|
const userLevel = getRoleLevel(userRole);
|
|
@@ -44,49 +40,28 @@ export function hasRole(userRole: string | undefined, requiredRole: Role): boole
|
|
|
44
40
|
return userLevel <= requiredLevel;
|
|
45
41
|
}
|
|
46
42
|
|
|
47
|
-
/**
|
|
48
|
-
* Vérifie si l'utilisateur est admin
|
|
49
|
-
*/
|
|
50
43
|
export function isAdmin(userRole: string | undefined): boolean {
|
|
51
44
|
return userRole === Role.ADMIN;
|
|
52
45
|
}
|
|
53
46
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Vérifie si l'utilisateur est commercial ou supérieur
|
|
64
|
-
*/
|
|
65
|
-
export function isCommercialOrAbove(userRole: string | undefined): boolean {
|
|
66
|
-
if (!userRole) return false;
|
|
67
|
-
return getRoleLevel(userRole) <= 3; // ADMIN, MANAGER ou COMMERCIAL
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Vérifie si l'utilisateur est télépro ou supérieur
|
|
72
|
-
*/
|
|
73
|
-
export function isTeleproOrAbove(userRole: string | undefined): boolean {
|
|
74
|
-
if (!userRole) return false;
|
|
75
|
-
return getRoleLevel(userRole) <= 4; // ADMIN, MANAGER, COMMERCIAL ou TELEPRO
|
|
76
|
-
}
|
|
47
|
+
const CUSTOM_ROLE_NAME_TO_ENUM: Record<string, Role> = {
|
|
48
|
+
Administrateur: Role.ADMIN,
|
|
49
|
+
Manager: Role.MANAGER,
|
|
50
|
+
Commercial: Role.COMMERCIAL,
|
|
51
|
+
Télépro: Role.TELEPRO,
|
|
52
|
+
Comptable: Role.COMPTABLE,
|
|
53
|
+
};
|
|
77
54
|
|
|
78
55
|
/**
|
|
79
|
-
*
|
|
56
|
+
* Résout le Role enum à partir du nom d'un CustomRole.
|
|
57
|
+
* Retourne USER si aucune correspondance n'est trouvée.
|
|
80
58
|
*/
|
|
81
|
-
export function
|
|
82
|
-
if (!
|
|
83
|
-
return
|
|
59
|
+
export function resolveRoleFromCustomRoleName(customRoleName: string | null | undefined): Role {
|
|
60
|
+
if (!customRoleName) return Role.USER;
|
|
61
|
+
return CUSTOM_ROLE_NAME_TO_ENUM[customRoleName] ?? Role.USER;
|
|
84
62
|
}
|
|
85
63
|
|
|
86
|
-
|
|
87
|
-
* Middleware pour vérifier le rôle côté serveur
|
|
88
|
-
*/
|
|
89
|
-
export async function requireRole(headers: Headers, requiredRole: Role) {
|
|
64
|
+
async function requireRole(headers: Headers, requiredRole: Role) {
|
|
90
65
|
const session = await auth.api.getSession({ headers });
|
|
91
66
|
|
|
92
67
|
if (!session) {
|