mirror of
https://github.com/R0m1k3/noteflow.git
synced 2026-10-11 17:29:37 +02:00
Merge pull request #42 from R0m1k3/claude/integrate-google-calendar-api-011CV44Nie9HB7U35ArSUnNa
Feature: Ajout du support d'API Key pour Google Calendar
This commit is contained in:
3 files changed
+104
-11
No files matched your search
@@ -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);
|
||||
|
||||
|
||||
+65
-7
@@ -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 = () => {
|
||||
<Label htmlFor="google-auth-type">Méthode d'authentification</Label>
|
||||
<Select
|
||||
value={settings.google_auth_type || 'oauth2'}
|
||||
onValueChange={(value) => setSettings({ ...settings, google_auth_type: value as 'oauth2' | 'service_account' })}
|
||||
onValueChange={(value) => setSettings({ ...settings, google_auth_type: value as 'oauth2' | 'service_account' | 'api_externe' })}
|
||||
>
|
||||
<SelectTrigger id="google-auth-type">
|
||||
<SelectValue placeholder="Sélectionnez une méthode" />
|
||||
@@ -1381,11 +1381,20 @@ const Index = () => {
|
||||
</span>
|
||||
</div>
|
||||
</SelectItem>
|
||||
<SelectItem value="api_externe">
|
||||
<div className="flex flex-col">
|
||||
<span className="font-medium">API externe</span>
|
||||
<span className="text-xs text-muted-foreground">
|
||||
Connectez-vous à une API externe pour Google Calendar
|
||||
</span>
|
||||
</div>
|
||||
</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
<strong>OAuth 2.0</strong> : Pour accéder au calendrier personnel avec autorisation de l'utilisateur.<br/>
|
||||
<strong>Service Account</strong> : Pour accéder à des calendriers partagés sans interaction utilisateur.
|
||||
<strong>Service Account</strong> : Pour accéder à des calendriers partagés sans interaction utilisateur.<br/>
|
||||
<strong>API externe</strong> : Utilisez votre propre API backend pour gérer la connexion à Google Calendar.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -1474,6 +1483,50 @@ const Index = () => {
|
||||
</>
|
||||
)}
|
||||
|
||||
{/* Configuration API Key */}
|
||||
{settings.google_auth_type === 'api_externe' && (
|
||||
<>
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="google-api-key">Clé API Google Calendar</Label>
|
||||
<Input
|
||||
id="google-api-key"
|
||||
type="password"
|
||||
placeholder="AIzaSy..."
|
||||
value={settings.google_calendar_api_key || ''}
|
||||
onChange={(e) => setSettings({ ...settings, google_calendar_api_key: e.target.value })}
|
||||
/>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Entrez votre clé API Google Calendar.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="google-calendar-id-api">ID du calendrier</Label>
|
||||
<Input
|
||||
id="google-calendar-id-api"
|
||||
type="text"
|
||||
placeholder="primary ou votre-email@gmail.com"
|
||||
value={settings.google_calendar_id || ''}
|
||||
onChange={(e) => setSettings({ ...settings, google_calendar_id: e.target.value })}
|
||||
/>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Utilisez "primary" pour votre calendrier principal ou l'email du calendrier spécifique.
|
||||
</p>
|
||||
<div className="p-3 bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-lg">
|
||||
<p className="text-sm font-semibold text-blue-900 dark:text-blue-200 mb-1">
|
||||
ℹ️ Obtenir une clé API
|
||||
</p>
|
||||
<p className="text-xs text-blue-800 dark:text-blue-300 mb-2">
|
||||
1. Allez sur <a href="https://console.cloud.google.com/apis/credentials" target="_blank" rel="noopener noreferrer" className="underline">Google Cloud Console</a><br/>
|
||||
2. Créez une clé API<br/>
|
||||
3. Activez l'API Google Calendar<br/>
|
||||
4. Copiez la clé API ici
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
|
||||
<div className="flex gap-2">
|
||||
<Button onClick={handleSaveSettings} className="flex items-center gap-2">
|
||||
<Key className="h-4 w-4" />
|
||||
@@ -1483,7 +1536,8 @@ const Index = () => {
|
||||
|
||||
{(
|
||||
((!settings.google_auth_type || settings.google_auth_type === 'oauth2') && settings.google_client_id && settings.google_client_secret) ||
|
||||
(settings.google_auth_type === 'service_account' && settings.google_service_account_key)
|
||||
(settings.google_auth_type === 'service_account' && settings.google_service_account_key) ||
|
||||
(settings.google_auth_type === 'api_externe' && settings.google_calendar_api_key)
|
||||
) && (
|
||||
<>
|
||||
<div className="border-t pt-4">
|
||||
@@ -1491,7 +1545,11 @@ const Index = () => {
|
||||
{calendarAuthStatus.isAuthenticated && !calendarAuthStatus.isExpired ? (
|
||||
<div className="flex items-center gap-2 text-green-600">
|
||||
<div className="h-2 w-2 rounded-full bg-green-600"></div>
|
||||
<span>Connecté à Google Calendar ({calendarAuthStatus.authType === 'service_account' ? 'Service Account' : 'OAuth 2.0'})</span>
|
||||
<span>Connecté à Google Calendar ({
|
||||
calendarAuthStatus.authType === 'service_account' ? 'Service Account' :
|
||||
calendarAuthStatus.authType === 'api_externe' ? 'API Key' :
|
||||
'OAuth 2.0'
|
||||
})</span>
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex items-center gap-2 text-yellow-600">
|
||||
@@ -1538,7 +1596,7 @@ const Index = () => {
|
||||
Déconnecter
|
||||
</Button>
|
||||
</>
|
||||
) : (
|
||||
) : settings.google_auth_type === 'api_externe' || settings.google_auth_type === 'service_account' ? (
|
||||
<Button
|
||||
onClick={async () => {
|
||||
try {
|
||||
@@ -1554,7 +1612,7 @@ const Index = () => {
|
||||
<RefreshCw className="h-4 w-4" />
|
||||
Synchroniser
|
||||
</Button>
|
||||
)}
|
||||
) : null}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user