mirror of
https://github.com/R0m1k3/noteflow.git
synced 2026-10-23 07:08:17 +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 = {
|
const AUTH_TYPES = {
|
||||||
OAUTH2: 'oauth2',
|
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
|
* Créer un client Google Calendar selon la méthode d'authentification
|
||||||
* @param {number} userId - ID de l'utilisateur (pour OAuth2)
|
* @param {number} userId - ID de l'utilisateur (pour OAuth2)
|
||||||
@@ -86,6 +100,9 @@ async function getCalendarClient(userId = null) {
|
|||||||
if (authType === AUTH_TYPES.SERVICE_ACCOUNT) {
|
if (authType === AUTH_TYPES.SERVICE_ACCOUNT) {
|
||||||
const auth = await getServiceAccountClient();
|
const auth = await getServiceAccountClient();
|
||||||
return google.calendar({ version: 'v3', auth });
|
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 {
|
} else {
|
||||||
// OAuth2
|
// OAuth2
|
||||||
if (!userId) {
|
if (!userId) {
|
||||||
@@ -227,6 +244,17 @@ router.get('/auth-status', async (req, res) => {
|
|||||||
isExpired: false,
|
isExpired: false,
|
||||||
needsReauth: !isAuthenticated
|
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 {
|
} else {
|
||||||
// OAuth2
|
// OAuth2
|
||||||
const tokens = await getOne(
|
const tokens = await getOne(
|
||||||
@@ -324,7 +352,7 @@ router.get('/events', async (req, res) => {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* POST /api/calendar/sync
|
* 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) => {
|
router.post('/sync', async (req, res) => {
|
||||||
try {
|
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
|
// Créer un client Google Calendar selon la méthode d'authentification
|
||||||
const calendar = await getCalendarClient(req.user.id);
|
const calendar = await getCalendarClient(req.user.id);
|
||||||
|
|
||||||
|
|||||||
+65
-7
@@ -58,7 +58,7 @@ const Index = () => {
|
|||||||
isAuthenticated: boolean;
|
isAuthenticated: boolean;
|
||||||
isExpired: boolean;
|
isExpired: boolean;
|
||||||
needsReauth: boolean;
|
needsReauth: boolean;
|
||||||
authType?: 'oauth2' | 'service_account';
|
authType?: 'oauth2' | 'service_account' | 'api_externe';
|
||||||
}>({
|
}>({
|
||||||
isAuthenticated: false,
|
isAuthenticated: false,
|
||||||
isExpired: false,
|
isExpired: false,
|
||||||
@@ -1359,7 +1359,7 @@ const Index = () => {
|
|||||||
<Label htmlFor="google-auth-type">Méthode d'authentification</Label>
|
<Label htmlFor="google-auth-type">Méthode d'authentification</Label>
|
||||||
<Select
|
<Select
|
||||||
value={settings.google_auth_type || 'oauth2'}
|
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">
|
<SelectTrigger id="google-auth-type">
|
||||||
<SelectValue placeholder="Sélectionnez une méthode" />
|
<SelectValue placeholder="Sélectionnez une méthode" />
|
||||||
@@ -1381,11 +1381,20 @@ const Index = () => {
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</SelectItem>
|
</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>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
<p className="text-xs text-muted-foreground">
|
<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>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>
|
</p>
|
||||||
</div>
|
</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">
|
<div className="flex gap-2">
|
||||||
<Button onClick={handleSaveSettings} className="flex items-center gap-2">
|
<Button onClick={handleSaveSettings} className="flex items-center gap-2">
|
||||||
<Key className="h-4 w-4" />
|
<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 || 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">
|
<div className="border-t pt-4">
|
||||||
@@ -1491,7 +1545,11 @@ const Index = () => {
|
|||||||
{calendarAuthStatus.isAuthenticated && !calendarAuthStatus.isExpired ? (
|
{calendarAuthStatus.isAuthenticated && !calendarAuthStatus.isExpired ? (
|
||||||
<div className="flex items-center gap-2 text-green-600">
|
<div className="flex items-center gap-2 text-green-600">
|
||||||
<div className="h-2 w-2 rounded-full bg-green-600"></div>
|
<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>
|
||||||
) : (
|
) : (
|
||||||
<div className="flex items-center gap-2 text-yellow-600">
|
<div className="flex items-center gap-2 text-yellow-600">
|
||||||
@@ -1538,7 +1596,7 @@ const Index = () => {
|
|||||||
Déconnecter
|
Déconnecter
|
||||||
</Button>
|
</Button>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : settings.google_auth_type === 'api_externe' || settings.google_auth_type === 'service_account' ? (
|
||||||
<Button
|
<Button
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
try {
|
try {
|
||||||
@@ -1554,7 +1612,7 @@ const Index = () => {
|
|||||||
<RefreshCw className="h-4 w-4" />
|
<RefreshCw className="h-4 w-4" />
|
||||||
Synchroniser
|
Synchroniser
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -7,10 +7,9 @@ export interface Settings {
|
|||||||
theme?: 'light' | 'dark' | 'auto';
|
theme?: 'light' | 'dark' | 'auto';
|
||||||
google_client_id?: string;
|
google_client_id?: string;
|
||||||
google_client_secret?: 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_service_account_key?: string;
|
||||||
google_calendar_email?: string;
|
google_calendar_email?: string;
|
||||||
// Legacy fields (kept for backward compatibility)
|
|
||||||
google_calendar_api_key?: string;
|
google_calendar_api_key?: string;
|
||||||
google_calendar_id?: string;
|
google_calendar_id?: string;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user