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
|
@@ -8,8 +8,6 @@ import nodemailer from 'nodemailer';
|
|
|
8
8
|
import { render } from '@react-email/render';
|
|
9
9
|
import React from 'react';
|
|
10
10
|
|
|
11
|
-
const isDevelopment = process.env.NODE_ENV === 'development';
|
|
12
|
-
|
|
13
11
|
function htmlToText(html: string): string {
|
|
14
12
|
if (!html) return '';
|
|
15
13
|
return html
|
|
@@ -22,7 +20,6 @@ function htmlToText(html: string): string {
|
|
|
22
20
|
|
|
23
21
|
async function getAdminSmtpConfig(userId: string) {
|
|
24
22
|
try {
|
|
25
|
-
// Récupérer la configuration SMTP de l'administrateur connecté
|
|
26
23
|
const user = await prisma.user.findUnique({
|
|
27
24
|
where: { id: userId },
|
|
28
25
|
include: {
|
|
@@ -31,12 +28,10 @@ async function getAdminSmtpConfig(userId: string) {
|
|
|
31
28
|
});
|
|
32
29
|
|
|
33
30
|
if (!user) {
|
|
34
|
-
console.error('❌ Utilisateur non trouvé:', userId);
|
|
35
31
|
return { config: null, error: 'Utilisateur non trouvé' };
|
|
36
32
|
}
|
|
37
33
|
|
|
38
34
|
if (!user.smtpConfig) {
|
|
39
|
-
console.error("❌ Aucune configuration SMTP trouvée pour l'utilisateur:", user.email);
|
|
40
35
|
return {
|
|
41
36
|
config: null,
|
|
42
37
|
error:
|
|
@@ -44,7 +39,6 @@ async function getAdminSmtpConfig(userId: string) {
|
|
|
44
39
|
};
|
|
45
40
|
}
|
|
46
41
|
|
|
47
|
-
console.log('✅ Configuration SMTP trouvée pour:', user.email);
|
|
48
42
|
return { config: user.smtpConfig, error: null };
|
|
49
43
|
} catch (error) {
|
|
50
44
|
console.error('Erreur lors de la récupération de la configuration SMTP:', error);
|
|
@@ -57,8 +51,6 @@ async function getAdminSmtpConfig(userId: string) {
|
|
|
57
51
|
|
|
58
52
|
async function getAnyAdminSmtpConfig() {
|
|
59
53
|
try {
|
|
60
|
-
// Récupérer la première configuration SMTP d'un administrateur
|
|
61
|
-
// On cherche directement dans SmtpConfig et on joint avec User pour vérifier le rôle
|
|
62
54
|
const smtpConfig = await prisma.smtpConfig.findFirst({
|
|
63
55
|
where: {
|
|
64
56
|
user: {
|
|
@@ -79,22 +71,12 @@ async function getAnyAdminSmtpConfig() {
|
|
|
79
71
|
});
|
|
80
72
|
|
|
81
73
|
if (!smtpConfig) {
|
|
82
|
-
console.error('❌ Aucune configuration SMTP trouvée pour un administrateur');
|
|
83
|
-
|
|
84
|
-
// Log supplémentaire pour debug : vérifier s'il y a des admins
|
|
85
|
-
const adminCount = await prisma.user.count({
|
|
86
|
-
where: { role: 'ADMIN' },
|
|
87
|
-
});
|
|
88
|
-
const smtpConfigCount = await prisma.smtpConfig.count();
|
|
89
|
-
console.error('Debug - Admins:', adminCount, 'Configs SMTP:', smtpConfigCount);
|
|
90
|
-
|
|
91
74
|
return {
|
|
92
75
|
config: null,
|
|
93
76
|
error: 'Aucune configuration SMTP trouvée. Veuillez configurer SMTP dans les paramètres.',
|
|
94
77
|
};
|
|
95
78
|
}
|
|
96
79
|
|
|
97
|
-
console.log("✅ Configuration SMTP trouvée pour l'admin:", smtpConfig.user.email);
|
|
98
80
|
return { config: smtpConfig, error: null };
|
|
99
81
|
} catch (error) {
|
|
100
82
|
console.error('Erreur lors de la récupération de la configuration SMTP admin:', error);
|
|
@@ -110,36 +92,22 @@ export async function POST(request: Request) {
|
|
|
110
92
|
const body = await request.json();
|
|
111
93
|
const { to, subject, template, ...emailData } = body;
|
|
112
94
|
|
|
113
|
-
// Récupérer la session de l'utilisateur connecté (optionnel pour reset-password)
|
|
114
95
|
const session = await auth.api.getSession({
|
|
115
96
|
headers: request.headers,
|
|
116
97
|
});
|
|
117
98
|
|
|
118
|
-
// Pour le reset password, on n'a pas besoin de session
|
|
119
99
|
const isResetPassword = template === 'reset-password';
|
|
120
100
|
|
|
121
101
|
if (!isResetPassword && (!session || !session.user?.id)) {
|
|
122
|
-
console.error('❌ Utilisateur non authentifié');
|
|
123
102
|
return Response.json({ error: 'Non authentifié' }, { status: 401 });
|
|
124
103
|
}
|
|
125
104
|
|
|
126
|
-
console.log("📧 Tentative d'envoi d'email:", {
|
|
127
|
-
to,
|
|
128
|
-
subject,
|
|
129
|
-
template,
|
|
130
|
-
isDevelopment,
|
|
131
|
-
userId: session?.user?.id || 'none (reset-password)',
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
// Récupérer la configuration SMTP
|
|
135
105
|
let smtpConfig, smtpError;
|
|
136
106
|
if (isResetPassword) {
|
|
137
|
-
// Pour le reset password, utiliser n'importe quelle config SMTP d'admin
|
|
138
107
|
const result = await getAnyAdminSmtpConfig();
|
|
139
108
|
smtpConfig = result.config;
|
|
140
109
|
smtpError = result.error;
|
|
141
110
|
} else {
|
|
142
|
-
// Pour les autres emails, utiliser la config de l'utilisateur connecté
|
|
143
111
|
const result = await getAdminSmtpConfig(session!.user.id);
|
|
144
112
|
smtpConfig = result.config;
|
|
145
113
|
smtpError = result.error;
|
|
@@ -149,11 +117,9 @@ export async function POST(request: Request) {
|
|
|
149
117
|
const errorMsg =
|
|
150
118
|
smtpError ||
|
|
151
119
|
'Aucune configuration SMTP trouvée. Veuillez configurer SMTP dans les paramètres.';
|
|
152
|
-
console.error('❌', errorMsg);
|
|
153
120
|
return Response.json({ error: errorMsg }, { status: 400 });
|
|
154
121
|
}
|
|
155
122
|
|
|
156
|
-
// Sélectionner le template approprié et le rendre en HTML
|
|
157
123
|
let emailComponent: React.ReactElement;
|
|
158
124
|
if (template === 'invitation') {
|
|
159
125
|
emailComponent = React.createElement(InvitationEmailTemplate, {
|
|
@@ -173,47 +139,16 @@ export async function POST(request: Request) {
|
|
|
173
139
|
});
|
|
174
140
|
}
|
|
175
141
|
|
|
176
|
-
// Rendre le composant React en HTML avec @react-email/render
|
|
177
142
|
const emailHtml = await render(emailComponent);
|
|
178
143
|
const emailText = htmlToText(emailHtml);
|
|
179
144
|
|
|
180
|
-
// Logger les informations de l'email (même en production pour le debug)
|
|
181
|
-
if (isDevelopment) {
|
|
182
|
-
console.log("📧 [DEV MODE] Envoi de l'email:");
|
|
183
|
-
console.log({
|
|
184
|
-
from: smtpConfig.fromName
|
|
185
|
-
? `"${smtpConfig.fromName}" <${smtpConfig.fromEmail}>`
|
|
186
|
-
: smtpConfig.fromEmail,
|
|
187
|
-
to,
|
|
188
|
-
subject,
|
|
189
|
-
template,
|
|
190
|
-
data: { ...emailData },
|
|
191
|
-
});
|
|
192
|
-
|
|
193
|
-
// Afficher le lien d'invitation dans la console si c'est une invitation
|
|
194
|
-
if (template === 'invitation' && emailData.invitationUrl) {
|
|
195
|
-
console.log("🔗 Lien d'invitation:", emailData.invitationUrl);
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
// Afficher le code de réinitialisation dans la console
|
|
199
|
-
if (template === 'reset-password' && emailData.code) {
|
|
200
|
-
console.log('🔑 Code de réinitialisation:', emailData.code);
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
// Déchiffrer le mot de passe SMTP
|
|
205
145
|
let password: string;
|
|
206
146
|
try {
|
|
207
147
|
password = decrypt(smtpConfig.password);
|
|
208
|
-
} catch
|
|
209
|
-
// Si le déchiffrement échoue, utiliser le mot de passe tel quel (ancien format non chiffré)
|
|
210
|
-
console.warn(
|
|
211
|
-
'⚠️ Impossible de déchiffrer le mot de passe SMTP, utilisation du mot de passe brut',
|
|
212
|
-
);
|
|
148
|
+
} catch {
|
|
213
149
|
password = smtpConfig.password;
|
|
214
150
|
}
|
|
215
151
|
|
|
216
|
-
// Créer le transporteur SMTP
|
|
217
152
|
const transporter = nodemailer.createTransport({
|
|
218
153
|
host: smtpConfig.host,
|
|
219
154
|
port: smtpConfig.port,
|
|
@@ -224,7 +159,6 @@ export async function POST(request: Request) {
|
|
|
224
159
|
},
|
|
225
160
|
});
|
|
226
161
|
|
|
227
|
-
// Envoyer l'email
|
|
228
162
|
const recipients = Array.isArray(to) ? to : [to];
|
|
229
163
|
const mailOptions = {
|
|
230
164
|
from: smtpConfig.fromName
|
|
@@ -236,30 +170,15 @@ export async function POST(request: Request) {
|
|
|
236
170
|
html: emailHtml,
|
|
237
171
|
};
|
|
238
172
|
|
|
239
|
-
console.log("📤 Envoi de l'email via SMTP...", {
|
|
240
|
-
from: mailOptions.from,
|
|
241
|
-
to: recipients,
|
|
242
|
-
subject,
|
|
243
|
-
});
|
|
244
|
-
|
|
245
173
|
const info = await transporter.sendMail(mailOptions);
|
|
246
174
|
|
|
247
|
-
console.log('✅ Email envoyé avec succès:', info.messageId);
|
|
248
|
-
|
|
249
175
|
return Response.json({
|
|
250
176
|
id: info.messageId,
|
|
251
177
|
message: 'Email envoyé avec succès',
|
|
252
178
|
});
|
|
253
179
|
} catch (error: any) {
|
|
254
|
-
console.error("
|
|
255
|
-
console.error("Détails de l'erreur:", {
|
|
256
|
-
message: error.message,
|
|
257
|
-
code: error.code,
|
|
258
|
-
command: error.command,
|
|
259
|
-
response: error.response,
|
|
260
|
-
});
|
|
180
|
+
console.error("Erreur lors de l'envoi de l'email:", error);
|
|
261
181
|
|
|
262
|
-
// Gérer les erreurs spécifiques de nodemailer
|
|
263
182
|
if (error.code === 'EAUTH' || error.code === 'ECONNECTION') {
|
|
264
183
|
return Response.json(
|
|
265
184
|
{
|
|
@@ -273,8 +192,13 @@ export async function POST(request: Request) {
|
|
|
273
192
|
|
|
274
193
|
return Response.json(
|
|
275
194
|
{
|
|
276
|
-
error:
|
|
277
|
-
|
|
195
|
+
error:
|
|
196
|
+
process.env.NODE_ENV === 'development'
|
|
197
|
+
? error.message || "Erreur lors de l'envoi de l'email"
|
|
198
|
+
: "Erreur lors de l'envoi de l'email",
|
|
199
|
+
...(process.env.NODE_ENV === 'development' && {
|
|
200
|
+
details: error.code || 'UNKNOWN_ERROR',
|
|
201
|
+
}),
|
|
278
202
|
},
|
|
279
203
|
{ status: 500 },
|
|
280
204
|
);
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import { NextRequest, NextResponse } from 'next/server';
|
|
2
2
|
import { prisma } from '@/lib/prisma';
|
|
3
|
-
import {
|
|
3
|
+
import { checkPermission } from '@/lib/check-permission';
|
|
4
|
+
import { auth } from '@/lib/auth';
|
|
4
5
|
|
|
5
6
|
// PUT /api/settings/closing-reasons/[id] - Mettre à jour un motif de fermeture (admin)
|
|
6
7
|
export async function PUT(request: NextRequest, { params }: { params: Promise<{ id: string }> }) {
|
|
7
8
|
try {
|
|
8
|
-
await
|
|
9
|
+
const session = await auth.api.getSession({ headers: request.headers });
|
|
10
|
+
if (!session) return NextResponse.json({ error: 'Non authentifié' }, { status: 401 });
|
|
11
|
+
const canManage = await checkPermission('settings.closing_reasons.manage');
|
|
12
|
+
if (!canManage) return NextResponse.json({ error: 'Accès refusé' }, { status: 403 });
|
|
9
13
|
|
|
10
14
|
const { id } = await params;
|
|
11
15
|
const body = await request.json();
|
|
@@ -32,15 +36,6 @@ export async function PUT(request: NextRequest, { params }: { params: Promise<{
|
|
|
32
36
|
});
|
|
33
37
|
} catch (error: any) {
|
|
34
38
|
console.error('Erreur lors de la mise à jour du motif de fermeture:', error);
|
|
35
|
-
|
|
36
|
-
if (error.message === 'Non authentifié') {
|
|
37
|
-
return NextResponse.json({ error: 'Non authentifié' }, { status: 401 });
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
if (error.message === 'Permissions insuffisantes') {
|
|
41
|
-
return NextResponse.json({ error: 'Accès refusé' }, { status: 403 });
|
|
42
|
-
}
|
|
43
|
-
|
|
44
39
|
return NextResponse.json({ error: error.message || 'Erreur serveur' }, { status: 500 });
|
|
45
40
|
}
|
|
46
41
|
}
|
|
@@ -51,7 +46,10 @@ export async function DELETE(
|
|
|
51
46
|
{ params }: { params: Promise<{ id: string }> },
|
|
52
47
|
) {
|
|
53
48
|
try {
|
|
54
|
-
await
|
|
49
|
+
const session = await auth.api.getSession({ headers: request.headers });
|
|
50
|
+
if (!session) return NextResponse.json({ error: 'Non authentifié' }, { status: 401 });
|
|
51
|
+
const canManage = await checkPermission('settings.closing_reasons.manage');
|
|
52
|
+
if (!canManage) return NextResponse.json({ error: 'Accès refusé' }, { status: 403 });
|
|
55
53
|
|
|
56
54
|
const { id } = await params;
|
|
57
55
|
|
|
@@ -65,15 +63,6 @@ export async function DELETE(
|
|
|
65
63
|
});
|
|
66
64
|
} catch (error: any) {
|
|
67
65
|
console.error('Erreur lors de la suppression du motif de fermeture:', error);
|
|
68
|
-
|
|
69
|
-
if (error.message === 'Non authentifié') {
|
|
70
|
-
return NextResponse.json({ error: 'Non authentifié' }, { status: 401 });
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
if (error.message === 'Permissions insuffisantes') {
|
|
74
|
-
return NextResponse.json({ error: 'Accès refusé' }, { status: 403 });
|
|
75
|
-
}
|
|
76
|
-
|
|
77
66
|
return NextResponse.json({ error: error.message || 'Erreur serveur' }, { status: 500 });
|
|
78
67
|
}
|
|
79
68
|
}
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import { NextRequest, NextResponse } from 'next/server';
|
|
2
2
|
import { prisma } from '@/lib/prisma';
|
|
3
|
-
import {
|
|
3
|
+
import { checkPermission } from '@/lib/check-permission';
|
|
4
|
+
import { auth } from '@/lib/auth';
|
|
4
5
|
|
|
5
6
|
// GET /api/settings/closing-reasons - Récupérer tous les motifs de fermeture (admin)
|
|
6
7
|
export async function GET(request: NextRequest) {
|
|
7
8
|
try {
|
|
8
|
-
await
|
|
9
|
+
const session = await auth.api.getSession({ headers: request.headers });
|
|
10
|
+
if (!session) return NextResponse.json({ error: 'Non authentifié' }, { status: 401 });
|
|
11
|
+
const canManage = await checkPermission('settings.closing_reasons.manage');
|
|
12
|
+
if (!canManage) return NextResponse.json({ error: 'Accès refusé' }, { status: 403 });
|
|
9
13
|
|
|
10
14
|
const reasons = await prisma.closingReason.findMany({
|
|
11
15
|
orderBy: { name: 'asc' },
|
|
@@ -14,15 +18,6 @@ export async function GET(request: NextRequest) {
|
|
|
14
18
|
return NextResponse.json(reasons);
|
|
15
19
|
} catch (error: any) {
|
|
16
20
|
console.error('Erreur lors de la récupération des motifs de fermeture:', error);
|
|
17
|
-
|
|
18
|
-
if (error.message === 'Non authentifié') {
|
|
19
|
-
return NextResponse.json({ error: 'Non authentifié' }, { status: 401 });
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
if (error.message === 'Permissions insuffisantes') {
|
|
23
|
-
return NextResponse.json({ error: 'Accès refusé' }, { status: 403 });
|
|
24
|
-
}
|
|
25
|
-
|
|
26
21
|
return NextResponse.json({ error: 'Erreur serveur' }, { status: 500 });
|
|
27
22
|
}
|
|
28
23
|
}
|
|
@@ -30,7 +25,10 @@ export async function GET(request: NextRequest) {
|
|
|
30
25
|
// POST /api/settings/closing-reasons - Créer un motif de fermeture (admin)
|
|
31
26
|
export async function POST(request: NextRequest) {
|
|
32
27
|
try {
|
|
33
|
-
await
|
|
28
|
+
const session = await auth.api.getSession({ headers: request.headers });
|
|
29
|
+
if (!session) return NextResponse.json({ error: 'Non authentifié' }, { status: 401 });
|
|
30
|
+
const canManage = await checkPermission('settings.closing_reasons.manage');
|
|
31
|
+
if (!canManage) return NextResponse.json({ error: 'Accès refusé' }, { status: 403 });
|
|
34
32
|
|
|
35
33
|
const body = await request.json();
|
|
36
34
|
const { name } = body;
|
|
@@ -58,15 +56,6 @@ export async function POST(request: NextRequest) {
|
|
|
58
56
|
);
|
|
59
57
|
} catch (error: any) {
|
|
60
58
|
console.error('Erreur lors de la création du motif de fermeture:', error);
|
|
61
|
-
|
|
62
|
-
if (error.message === 'Non authentifié') {
|
|
63
|
-
return NextResponse.json({ error: 'Non authentifié' }, { status: 401 });
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
if (error.message === 'Permissions insuffisantes') {
|
|
67
|
-
return NextResponse.json({ error: 'Accès refusé' }, { status: 403 });
|
|
68
|
-
}
|
|
69
|
-
|
|
70
59
|
return NextResponse.json({ error: error.message || 'Erreur serveur' }, { status: 500 });
|
|
71
60
|
}
|
|
72
61
|
}
|
|
@@ -1,20 +1,24 @@
|
|
|
1
1
|
import { NextRequest, NextResponse } from 'next/server';
|
|
2
2
|
import { prisma } from '@/lib/prisma';
|
|
3
|
-
import {
|
|
3
|
+
import { checkPermission } from '@/lib/check-permission';
|
|
4
|
+
import { auth } from '@/lib/auth';
|
|
4
5
|
|
|
5
6
|
// GET /api/settings/company - Récupérer les informations de l'entreprise
|
|
6
7
|
export async function GET(request: NextRequest) {
|
|
7
8
|
try {
|
|
8
|
-
await
|
|
9
|
+
const session = await auth.api.getSession({ headers: request.headers });
|
|
10
|
+
if (!session) return NextResponse.json({ error: 'Non authentifié' }, { status: 401 });
|
|
11
|
+
const hasPermission = await checkPermission('settings.view');
|
|
12
|
+
if (!hasPermission) return NextResponse.json({ error: 'Accès refusé' }, { status: 403 });
|
|
9
13
|
|
|
10
14
|
// Récupérer ou créer l'enregistrement de l'entreprise
|
|
11
|
-
let company = await prisma.
|
|
15
|
+
let company = await prisma.organization.findUnique({
|
|
12
16
|
where: { id: 'company' },
|
|
13
17
|
});
|
|
14
18
|
|
|
15
19
|
// Si l'entreprise n'existe pas, la créer
|
|
16
20
|
if (!company) {
|
|
17
|
-
company = await prisma.
|
|
21
|
+
company = await prisma.organization.create({
|
|
18
22
|
data: {
|
|
19
23
|
id: 'company',
|
|
20
24
|
},
|
|
@@ -24,15 +28,6 @@ export async function GET(request: NextRequest) {
|
|
|
24
28
|
return NextResponse.json(company);
|
|
25
29
|
} catch (error: any) {
|
|
26
30
|
console.error("Erreur lors de la récupération des informations de l'entreprise:", error);
|
|
27
|
-
|
|
28
|
-
if (error.message === 'Non authentifié') {
|
|
29
|
-
return NextResponse.json({ error: 'Non authentifié' }, { status: 401 });
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
if (error.message === 'Permissions insuffisantes') {
|
|
33
|
-
return NextResponse.json({ error: 'Accès refusé' }, { status: 403 });
|
|
34
|
-
}
|
|
35
|
-
|
|
36
31
|
return NextResponse.json({ error: 'Erreur serveur' }, { status: 500 });
|
|
37
32
|
}
|
|
38
33
|
}
|
|
@@ -40,11 +35,15 @@ export async function GET(request: NextRequest) {
|
|
|
40
35
|
// PUT /api/settings/company - Mettre à jour les informations de l'entreprise
|
|
41
36
|
export async function PUT(request: NextRequest) {
|
|
42
37
|
try {
|
|
43
|
-
await
|
|
38
|
+
const session = await auth.api.getSession({ headers: request.headers });
|
|
39
|
+
if (!session) return NextResponse.json({ error: 'Non authentifié' }, { status: 401 });
|
|
40
|
+
const hasPermission = await checkPermission('settings.company.edit');
|
|
41
|
+
if (!hasPermission) return NextResponse.json({ error: 'Accès refusé' }, { status: 403 });
|
|
44
42
|
|
|
45
43
|
const body = await request.json();
|
|
46
44
|
const {
|
|
47
45
|
name,
|
|
46
|
+
legalRepresentative,
|
|
48
47
|
address,
|
|
49
48
|
city,
|
|
50
49
|
postalCode,
|
|
@@ -58,16 +57,17 @@ export async function PUT(request: NextRequest) {
|
|
|
58
57
|
} = body;
|
|
59
58
|
|
|
60
59
|
// Vérifier si l'entreprise existe
|
|
61
|
-
let company = await prisma.
|
|
60
|
+
let company = await prisma.organization.findUnique({
|
|
62
61
|
where: { id: 'company' },
|
|
63
62
|
});
|
|
64
63
|
|
|
65
64
|
// Si l'entreprise n'existe pas, la créer
|
|
66
65
|
if (!company) {
|
|
67
|
-
company = await prisma.
|
|
66
|
+
company = await prisma.organization.create({
|
|
68
67
|
data: {
|
|
69
68
|
id: 'company',
|
|
70
69
|
name,
|
|
70
|
+
legalRepresentative,
|
|
71
71
|
address,
|
|
72
72
|
city,
|
|
73
73
|
postalCode,
|
|
@@ -82,10 +82,12 @@ export async function PUT(request: NextRequest) {
|
|
|
82
82
|
});
|
|
83
83
|
} else {
|
|
84
84
|
// Mettre à jour l'entreprise
|
|
85
|
-
company = await prisma.
|
|
85
|
+
company = await prisma.organization.update({
|
|
86
86
|
where: { id: 'company' },
|
|
87
87
|
data: {
|
|
88
88
|
name: name !== undefined ? name : company.name,
|
|
89
|
+
legalRepresentative:
|
|
90
|
+
legalRepresentative !== undefined ? legalRepresentative : company.legalRepresentative,
|
|
89
91
|
address: address !== undefined ? address : company.address,
|
|
90
92
|
city: city !== undefined ? city : company.city,
|
|
91
93
|
postalCode: postalCode !== undefined ? postalCode : company.postalCode,
|
|
@@ -107,15 +109,6 @@ export async function PUT(request: NextRequest) {
|
|
|
107
109
|
});
|
|
108
110
|
} catch (error: any) {
|
|
109
111
|
console.error("Erreur lors de la mise à jour des informations de l'entreprise:", error);
|
|
110
|
-
|
|
111
|
-
if (error.message === 'Non authentifié') {
|
|
112
|
-
return NextResponse.json({ error: 'Non authentifié' }, { status: 401 });
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
if (error.message === 'Permissions insuffisantes') {
|
|
116
|
-
return NextResponse.json({ error: 'Accès refusé' }, { status: 403 });
|
|
117
|
-
}
|
|
118
|
-
|
|
119
112
|
return NextResponse.json({ error: error.message || 'Erreur serveur' }, { status: 500 });
|
|
120
113
|
}
|
|
121
114
|
}
|
|
@@ -1,11 +1,19 @@
|
|
|
1
1
|
import { NextRequest, NextResponse } from 'next/server';
|
|
2
2
|
import { prisma } from '@/lib/prisma';
|
|
3
|
-
import {
|
|
3
|
+
import { checkPermission } from '@/lib/check-permission';
|
|
4
|
+
import { auth } from '@/lib/auth';
|
|
4
5
|
|
|
5
|
-
// PUT /api/settings/google-ads/[id] - Mettre à jour une configuration
|
|
6
|
+
// PUT /api/settings/google-ads/[id] - Mettre à jour une configuration
|
|
6
7
|
export async function PUT(request: NextRequest, { params }: { params: Promise<{ id: string }> }) {
|
|
7
8
|
try {
|
|
8
|
-
await
|
|
9
|
+
const session = await auth.api.getSession({ headers: request.headers });
|
|
10
|
+
if (!session) {
|
|
11
|
+
return NextResponse.json({ error: 'Non authentifié' }, { status: 401 });
|
|
12
|
+
}
|
|
13
|
+
const hasPermission = await checkPermission('integrations.google_ads.manage');
|
|
14
|
+
if (!hasPermission) {
|
|
15
|
+
return NextResponse.json({ error: 'Accès refusé' }, { status: 403 });
|
|
16
|
+
}
|
|
9
17
|
|
|
10
18
|
const { id } = await params;
|
|
11
19
|
const body = await request.json();
|
|
@@ -58,26 +66,24 @@ export async function PUT(request: NextRequest, { params }: { params: Promise<{
|
|
|
58
66
|
'Erreur lors de la mise à jour de la configuration Google Ads Lead Forms:',
|
|
59
67
|
error,
|
|
60
68
|
);
|
|
61
|
-
|
|
62
|
-
if (error.message === 'Non authentifié') {
|
|
63
|
-
return NextResponse.json({ error: 'Non authentifié' }, { status: 401 });
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
if (error.message === 'Permissions insuffisantes') {
|
|
67
|
-
return NextResponse.json({ error: 'Accès refusé' }, { status: 403 });
|
|
68
|
-
}
|
|
69
|
-
|
|
70
69
|
return NextResponse.json({ error: error.message || 'Erreur serveur' }, { status: 500 });
|
|
71
70
|
}
|
|
72
71
|
}
|
|
73
72
|
|
|
74
|
-
// DELETE /api/settings/google-ads/[id] - Supprimer une configuration
|
|
73
|
+
// DELETE /api/settings/google-ads/[id] - Supprimer une configuration
|
|
75
74
|
export async function DELETE(
|
|
76
75
|
request: NextRequest,
|
|
77
76
|
{ params }: { params: Promise<{ id: string }> },
|
|
78
77
|
) {
|
|
79
78
|
try {
|
|
80
|
-
await
|
|
79
|
+
const session = await auth.api.getSession({ headers: request.headers });
|
|
80
|
+
if (!session) {
|
|
81
|
+
return NextResponse.json({ error: 'Non authentifié' }, { status: 401 });
|
|
82
|
+
}
|
|
83
|
+
const hasPermission = await checkPermission('integrations.google_ads.manage');
|
|
84
|
+
if (!hasPermission) {
|
|
85
|
+
return NextResponse.json({ error: 'Accès refusé' }, { status: 403 });
|
|
86
|
+
}
|
|
81
87
|
|
|
82
88
|
const { id } = await params;
|
|
83
89
|
const client = prisma as any;
|
|
@@ -103,15 +109,6 @@ export async function DELETE(
|
|
|
103
109
|
'Erreur lors de la suppression de la configuration Google Ads Lead Forms:',
|
|
104
110
|
error,
|
|
105
111
|
);
|
|
106
|
-
|
|
107
|
-
if (error.message === 'Non authentifié') {
|
|
108
|
-
return NextResponse.json({ error: 'Non authentifié' }, { status: 401 });
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
if (error.message === 'Permissions insuffisantes') {
|
|
112
|
-
return NextResponse.json({ error: 'Accès refusé' }, { status: 403 });
|
|
113
|
-
}
|
|
114
|
-
|
|
115
112
|
return NextResponse.json({ error: error.message || 'Erreur serveur' }, { status: 500 });
|
|
116
113
|
}
|
|
117
114
|
}
|
|
@@ -1,11 +1,19 @@
|
|
|
1
1
|
import { NextRequest, NextResponse } from 'next/server';
|
|
2
2
|
import { prisma } from '@/lib/prisma';
|
|
3
|
-
import {
|
|
3
|
+
import { checkPermission } from '@/lib/check-permission';
|
|
4
|
+
import { auth } from '@/lib/auth';
|
|
4
5
|
|
|
5
|
-
// GET /api/settings/google-ads - Récupérer toutes les configurations Google Ads Leads
|
|
6
|
+
// GET /api/settings/google-ads - Récupérer toutes les configurations Google Ads Leads
|
|
6
7
|
export async function GET(request: NextRequest) {
|
|
7
8
|
try {
|
|
8
|
-
await
|
|
9
|
+
const session = await auth.api.getSession({ headers: request.headers });
|
|
10
|
+
if (!session) {
|
|
11
|
+
return NextResponse.json({ error: 'Non authentifié' }, { status: 401 });
|
|
12
|
+
}
|
|
13
|
+
const hasPermission = await checkPermission('integrations.google_ads.manage');
|
|
14
|
+
if (!hasPermission) {
|
|
15
|
+
return NextResponse.json({ error: 'Accès refusé' }, { status: 403 });
|
|
16
|
+
}
|
|
9
17
|
|
|
10
18
|
const client = prisma as any;
|
|
11
19
|
|
|
@@ -44,23 +52,21 @@ export async function GET(request: NextRequest) {
|
|
|
44
52
|
'Erreur lors de la récupération des configurations Google Ads Lead Forms:',
|
|
45
53
|
error,
|
|
46
54
|
);
|
|
47
|
-
|
|
48
|
-
if (error.message === 'Non authentifié') {
|
|
49
|
-
return NextResponse.json({ error: 'Non authentifié' }, { status: 401 });
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
if (error.message === 'Permissions insuffisantes') {
|
|
53
|
-
return NextResponse.json({ error: 'Accès refusé' }, { status: 403 });
|
|
54
|
-
}
|
|
55
|
-
|
|
56
55
|
return NextResponse.json({ error: 'Erreur serveur' }, { status: 500 });
|
|
57
56
|
}
|
|
58
57
|
}
|
|
59
58
|
|
|
60
|
-
// POST /api/settings/google-ads - Créer une nouvelle configuration
|
|
59
|
+
// POST /api/settings/google-ads - Créer une nouvelle configuration
|
|
61
60
|
export async function POST(request: NextRequest) {
|
|
62
61
|
try {
|
|
63
|
-
await
|
|
62
|
+
const session = await auth.api.getSession({ headers: request.headers });
|
|
63
|
+
if (!session) {
|
|
64
|
+
return NextResponse.json({ error: 'Non authentifié' }, { status: 401 });
|
|
65
|
+
}
|
|
66
|
+
const hasPermission = await checkPermission('integrations.google_ads.manage');
|
|
67
|
+
if (!hasPermission) {
|
|
68
|
+
return NextResponse.json({ error: 'Accès refusé' }, { status: 403 });
|
|
69
|
+
}
|
|
64
70
|
|
|
65
71
|
const body = await request.json();
|
|
66
72
|
const { name, webhookKey, active = true, defaultStatusId, defaultAssignedUserId } = body;
|
|
@@ -108,15 +114,6 @@ export async function POST(request: NextRequest) {
|
|
|
108
114
|
});
|
|
109
115
|
} catch (error: any) {
|
|
110
116
|
console.error('Erreur lors de la création de la configuration Google Ads Lead Forms:', error);
|
|
111
|
-
|
|
112
|
-
if (error.message === 'Non authentifié') {
|
|
113
|
-
return NextResponse.json({ error: 'Non authentifié' }, { status: 401 });
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
if (error.message === 'Permissions insuffisantes') {
|
|
117
|
-
return NextResponse.json({ error: 'Accès refusé' }, { status: 403 });
|
|
118
|
-
}
|
|
119
|
-
|
|
120
117
|
return NextResponse.json({ error: error.message || 'Erreur serveur' }, { status: 500 });
|
|
121
118
|
}
|
|
122
119
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { NextRequest, NextResponse } from 'next/server';
|
|
2
2
|
import { prisma } from '@/lib/prisma';
|
|
3
|
-
import {
|
|
3
|
+
import { checkPermission } from '@/lib/check-permission';
|
|
4
|
+
import { auth } from '@/lib/auth';
|
|
4
5
|
|
|
5
6
|
function extractSpreadsheetId(sheetUrlOrId: string): string {
|
|
6
7
|
if (!sheetUrlOrId) return sheetUrlOrId;
|
|
@@ -17,10 +18,17 @@ function extractSpreadsheetId(sheetUrlOrId: string): string {
|
|
|
17
18
|
return sheetUrlOrId;
|
|
18
19
|
}
|
|
19
20
|
|
|
20
|
-
// PUT /api/settings/google-sheet/[id] - Mettre à jour une configuration
|
|
21
|
+
// PUT /api/settings/google-sheet/[id] - Mettre à jour une configuration
|
|
21
22
|
export async function PUT(request: NextRequest, { params }: { params: Promise<{ id: string }> }) {
|
|
22
23
|
try {
|
|
23
|
-
await
|
|
24
|
+
const session = await auth.api.getSession({ headers: request.headers });
|
|
25
|
+
if (!session) {
|
|
26
|
+
return NextResponse.json({ error: 'Non authentifié' }, { status: 401 });
|
|
27
|
+
}
|
|
28
|
+
const hasPermission = await checkPermission('integrations.google_sheets.manage');
|
|
29
|
+
if (!hasPermission) {
|
|
30
|
+
return NextResponse.json({ error: 'Accès refusé' }, { status: 403 });
|
|
31
|
+
}
|
|
24
32
|
|
|
25
33
|
const { id } = await params;
|
|
26
34
|
const body = await request.json();
|
|
@@ -174,26 +182,24 @@ export async function PUT(request: NextRequest, { params }: { params: Promise<{
|
|
|
174
182
|
});
|
|
175
183
|
} catch (error: any) {
|
|
176
184
|
console.error('Erreur lors de la mise à jour de la configuration Google Sheets:', error);
|
|
177
|
-
|
|
178
|
-
if (error.message === 'Non authentifié') {
|
|
179
|
-
return NextResponse.json({ error: 'Non authentifié' }, { status: 401 });
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
if (error.message === 'Permissions insuffisantes') {
|
|
183
|
-
return NextResponse.json({ error: 'Accès refusé' }, { status: 403 });
|
|
184
|
-
}
|
|
185
|
-
|
|
186
185
|
return NextResponse.json({ error: error.message || 'Erreur serveur' }, { status: 500 });
|
|
187
186
|
}
|
|
188
187
|
}
|
|
189
188
|
|
|
190
|
-
// DELETE /api/settings/google-sheet/[id] - Supprimer une configuration
|
|
189
|
+
// DELETE /api/settings/google-sheet/[id] - Supprimer une configuration
|
|
191
190
|
export async function DELETE(
|
|
192
191
|
request: NextRequest,
|
|
193
192
|
{ params }: { params: Promise<{ id: string }> },
|
|
194
193
|
) {
|
|
195
194
|
try {
|
|
196
|
-
await
|
|
195
|
+
const session = await auth.api.getSession({ headers: request.headers });
|
|
196
|
+
if (!session) {
|
|
197
|
+
return NextResponse.json({ error: 'Non authentifié' }, { status: 401 });
|
|
198
|
+
}
|
|
199
|
+
const hasPermission = await checkPermission('integrations.google_sheets.manage');
|
|
200
|
+
if (!hasPermission) {
|
|
201
|
+
return NextResponse.json({ error: 'Accès refusé' }, { status: 403 });
|
|
202
|
+
}
|
|
197
203
|
|
|
198
204
|
const { id } = await params;
|
|
199
205
|
const client = prisma as any;
|
|
@@ -216,15 +222,6 @@ export async function DELETE(
|
|
|
216
222
|
});
|
|
217
223
|
} catch (error: any) {
|
|
218
224
|
console.error('Erreur lors de la suppression de la configuration Google Sheets:', error);
|
|
219
|
-
|
|
220
|
-
if (error.message === 'Non authentifié') {
|
|
221
|
-
return NextResponse.json({ error: 'Non authentifié' }, { status: 401 });
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
if (error.message === 'Permissions insuffisantes') {
|
|
225
|
-
return NextResponse.json({ error: 'Accès refusé' }, { status: 403 });
|
|
226
|
-
}
|
|
227
|
-
|
|
228
225
|
return NextResponse.json({ error: error.message || 'Erreur serveur' }, { status: 500 });
|
|
229
226
|
}
|
|
230
227
|
}
|