From e480d50bea35332b4ac3cc035b046dbc7d260a43 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 12 Nov 2025 13:22:34 +0000 Subject: [PATCH] Feature: Ajout du support d'API Key pour Google Calendar MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ajout d'une troisième méthode d'authentification pour Google Calendar : - OAuth 2.0 (existant) - Service Account (existant) - API Key (nouveau) Modifications : - Interface d'administration avec sélection API Key - Champs pour configurer la clé API et l'ID du calendrier - Backend mis à jour pour gérer l'authentification par API Key - Routes calendar adaptées pour supporter le nouveau type - Affichage du statut de connexion mis à jour L'utilisateur peut maintenant : 1. Sélectionner "API externe" dans les paramètres Google Calendar 2. Entrer sa clé API Google Calendar 3. Spécifier l'ID du calendrier (ou "primary") 4. Synchroniser directement avec Google Calendar --- routes/calendar.routes.js | 40 +++++++++++++++++- src/pages/Index.tsx | 72 +++++++++++++++++++++++++++++---- src/services/SettingsService.ts | 3 +- 3 files changed, 104 insertions(+), 11 deletions(-) diff --git a/routes/calendar.routes.js b/routes/calendar.routes.js index e9e1d63..d3e5478 100644 --- a/routes/calendar.routes.js +++ b/routes/calendar.routes.js @@ -17,7 +17,8 @@ const SCOPES = ['https://www.googleapis.com/auth/calendar.readonly']; */ const AUTH_TYPES = { OAUTH2: 'oauth2', - SERVICE_ACCOUNT: 'service_account' + SERVICE_ACCOUNT: 'service_account', + API_KEY: 'api_externe' }; /** @@ -76,6 +77,19 @@ async function getServiceAccountClient() { } } +/** + * Créer un client avec API Key + */ +async function getApiKeyClient() { + const apiKey = await getOne("SELECT value FROM settings WHERE key = 'google_calendar_api_key'"); + + if (!apiKey || !apiKey.value) { + throw new Error('Clé API non configurée'); + } + + return apiKey.value; +} + /** * Créer un client Google Calendar selon la méthode d'authentification * @param {number} userId - ID de l'utilisateur (pour OAuth2) @@ -86,6 +100,9 @@ async function getCalendarClient(userId = null) { if (authType === AUTH_TYPES.SERVICE_ACCOUNT) { const auth = await getServiceAccountClient(); return google.calendar({ version: 'v3', auth }); + } else if (authType === AUTH_TYPES.API_KEY) { + const apiKey = await getApiKeyClient(); + return google.calendar({ version: 'v3', auth: apiKey }); } else { // OAuth2 if (!userId) { @@ -227,6 +244,17 @@ router.get('/auth-status', async (req, res) => { isExpired: false, needsReauth: !isAuthenticated }); + } else if (authType === AUTH_TYPES.API_KEY) { + // Vérifier si la clé API est configurée + const apiKey = await getOne("SELECT value FROM settings WHERE key = 'google_calendar_api_key'"); + const isAuthenticated = !!apiKey?.value; + + res.json({ + authType: AUTH_TYPES.API_KEY, + isAuthenticated, + isExpired: false, + needsReauth: !isAuthenticated + }); } else { // OAuth2 const tokens = await getOne( @@ -324,7 +352,7 @@ router.get('/events', async (req, res) => { /** * POST /api/calendar/sync - * Synchroniser avec Google Calendar (OAuth2 ou Service Account) + * Synchroniser avec Google Calendar (OAuth2, Service Account ou API Key) */ router.post('/sync', async (req, res) => { try { @@ -339,6 +367,14 @@ router.post('/sync', async (req, res) => { } } + // Si API Key, permettre de spécifier l'ID du calendrier + if (authType === AUTH_TYPES.API_KEY) { + const calendarIdSetting = await getOne("SELECT value FROM settings WHERE key = 'google_calendar_id'"); + if (calendarIdSetting?.value) { + calendarId = calendarIdSetting.value; + } + } + // Créer un client Google Calendar selon la méthode d'authentification const calendar = await getCalendarClient(req.user.id); diff --git a/src/pages/Index.tsx b/src/pages/Index.tsx index 25917be..1de355b 100644 --- a/src/pages/Index.tsx +++ b/src/pages/Index.tsx @@ -58,7 +58,7 @@ const Index = () => { isAuthenticated: boolean; isExpired: boolean; needsReauth: boolean; - authType?: 'oauth2' | 'service_account'; + authType?: 'oauth2' | 'service_account' | 'api_externe'; }>({ isAuthenticated: false, isExpired: false, @@ -1359,7 +1359,7 @@ const Index = () => {

OAuth 2.0 : Pour accéder au calendrier personnel avec autorisation de l'utilisateur.
- Service Account : Pour accéder à des calendriers partagés sans interaction utilisateur. + Service Account : Pour accéder à des calendriers partagés sans interaction utilisateur.
+ API externe : Utilisez votre propre API backend pour gérer la connexion à Google Calendar.

@@ -1474,6 +1483,50 @@ const Index = () => { )} + {/* Configuration API Key */} + {settings.google_auth_type === 'api_externe' && ( + <> +
+ + setSettings({ ...settings, google_calendar_api_key: e.target.value })} + /> +

+ Entrez votre clé API Google Calendar. +

+
+ +
+ + setSettings({ ...settings, google_calendar_id: e.target.value })} + /> +

+ Utilisez "primary" pour votre calendrier principal ou l'email du calendrier spécifique. +

+
+

+ ℹ️ Obtenir une clé API +

+

+ 1. Allez sur Google Cloud Console
+ 2. Créez une clé API
+ 3. Activez l'API Google Calendar
+ 4. Copiez la clé API ici +

+
+
+ + )} +
- ) : ( + ) : settings.google_auth_type === 'api_externe' || settings.google_auth_type === 'service_account' ? ( - )} + ) : null}
)} diff --git a/src/services/SettingsService.ts b/src/services/SettingsService.ts index bf60fdc..9bdbd76 100644 --- a/src/services/SettingsService.ts +++ b/src/services/SettingsService.ts @@ -7,10 +7,9 @@ export interface Settings { theme?: 'light' | 'dark' | 'auto'; google_client_id?: string; google_client_secret?: string; - google_auth_type?: 'oauth2' | 'service_account'; + google_auth_type?: 'oauth2' | 'service_account' | 'api_externe'; google_service_account_key?: string; google_calendar_email?: string; - // Legacy fields (kept for backward compatibility) google_calendar_api_key?: string; google_calendar_id?: string; }