- Implemented multi-selection for notes with Ctrl+click, long-press, and keyboard shortcuts (Ctrl+A, Escape) - Added Gemini API integration with environment configuration and routes - Enhanced code block UI with improved copy feedback animation and visual polish - Added sort order toggle (asc/desc) for note lists with persistent state
421 lines
11 KiB
Markdown
421 lines
11 KiB
Markdown
# 🔐 Système de Vérification de la Clé API Gemini
|
|
|
|
## 📋 Vue d'ensemble
|
|
|
|
Ce système permet de vérifier que la variable d'environnement `GEMINI_API_KEY` est correctement configurée, testée et fonctionnelle. Il expose un endpoint d'état backend et une interface utilisateur dans la page Paramètres → Intégrations.
|
|
|
|
---
|
|
|
|
## 🎯 États du système
|
|
|
|
Le système retourne l'un des **4 statuts** suivants:
|
|
|
|
| Status Backend | Label UI | Description |
|
|
|----------------|----------|-------------|
|
|
| `NOT_CONFIGURED` | ❌ Non configurée | La clé API n'est pas définie dans l'environnement serveur |
|
|
| `CONFIGURED_UNVERIFIED` | ⚠️ Configurée (non testée) | La clé est présente mais n'a jamais été testée |
|
|
| `WORKING` | ✅ Fonctionnelle | La clé est valide et fonctionne correctement |
|
|
| `INVALID` | ❌ Invalide / Erreur | La clé ne fonctionne pas (auth, réseau, etc.) |
|
|
|
|
### Raisons d'erreur détaillées
|
|
|
|
| Reason | Description | Action recommandée |
|
|
|--------|-------------|-------------------|
|
|
| `missing_key` | `GEMINI_API_KEY` non définie | Ajouter la clé dans `.env` et redémarrer |
|
|
| `not_tested` | Jamais testée | Cliquer sur "Tester la clé" |
|
|
| `ok` | Fonctionne correctement | Aucune action requise |
|
|
| `auth_error` | Clé invalide (401/403) | Vérifier la clé ou en générer une nouvelle |
|
|
| `network_error` | Timeout ou erreur réseau | Vérifier la connexion internet |
|
|
| `rate_limited` | Limite atteinte (429) | Attendre avant de retester |
|
|
| `unexpected_response` | Réponse inattendue | Vérifier les logs serveur |
|
|
|
|
---
|
|
|
|
## ⚙️ Configuration
|
|
|
|
### 1. Ajouter la clé API
|
|
|
|
Éditez le fichier `.env` à la racine du projet:
|
|
|
|
```bash
|
|
# Ajoutez cette ligne avec votre vraie clé
|
|
GEMINI_API_KEY=votre_clé_api_google_gemini_ici
|
|
|
|
# Optionnel: personnaliser l'URL de base
|
|
# GEMINI_API_BASE=https://generativelanguage.googleapis.com
|
|
```
|
|
|
|
### 2. Obtenir une clé API Gemini
|
|
|
|
1. Allez sur [Google AI Studio](https://makersuite.google.com/app/apikey)
|
|
2. Connectez-vous avec votre compte Google
|
|
3. Cliquez sur "Create API Key"
|
|
4. Copiez la clé générée
|
|
5. Ajoutez-la dans `.env`
|
|
|
|
### 3. Redémarrer le serveur
|
|
|
|
```bash
|
|
# Arrêter le serveur actuel (Ctrl+C)
|
|
# Relancer
|
|
npm start
|
|
# ou
|
|
pwsh ./start-dev.ps1
|
|
```
|
|
|
|
---
|
|
|
|
## 🔌 API Backend
|
|
|
|
### GET `/api/integrations/gemini/status`
|
|
|
|
Retourne le statut actuel de la clé API.
|
|
|
|
**Réponse (200):**
|
|
|
|
```json
|
|
{
|
|
"status": "WORKING",
|
|
"lastCheckedAt": "2025-01-15T14:30:00.000Z",
|
|
"details": {
|
|
"reason": "ok",
|
|
"httpCode": 200
|
|
}
|
|
}
|
|
```
|
|
|
|
**Sécurité:** La clé API n'est jamais renvoyée au client.
|
|
|
|
### POST `/api/integrations/gemini/test`
|
|
|
|
Exécute un test live de la clé API (appel à l'API Gemini).
|
|
|
|
**Réponse (200 - Success):**
|
|
|
|
```json
|
|
{
|
|
"status": "WORKING",
|
|
"lastCheckedAt": "2025-01-15T14:31:00.000Z",
|
|
"details": {
|
|
"reason": "ok",
|
|
"httpCode": 200
|
|
}
|
|
}
|
|
```
|
|
|
|
**Réponse (429 - Rate Limited):**
|
|
|
|
```json
|
|
{
|
|
"status": "WORKING",
|
|
"lastCheckedAt": "2025-01-15T14:30:00.000Z",
|
|
"details": {
|
|
"reason": "rate_limited",
|
|
"httpCode": 429,
|
|
"message": "Veuillez patienter 25 secondes avant de retester",
|
|
"waitSeconds": 25
|
|
}
|
|
}
|
|
```
|
|
|
|
**Anti-spam:** Maximum 1 test toutes les 30 secondes par IP.
|
|
|
|
### DELETE `/api/integrations/gemini/cache` (Debug)
|
|
|
|
Réinitialise le cache du statut.
|
|
|
|
**Réponse (200):**
|
|
|
|
```json
|
|
{
|
|
"success": true,
|
|
"message": "Cache réinitialisé"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 🎨 Interface Utilisateur
|
|
|
|
### Accès
|
|
|
|
1. Ouvrir ObsiViewer dans le navigateur
|
|
2. Cliquer sur l'icône ⚙️ (Paramètres)
|
|
3. Scroller jusqu'à la section **"Integrations"**
|
|
4. Section "Google Gemini API"
|
|
|
|
### Fonctionnalités
|
|
|
|
#### Badge de statut
|
|
|
|
Le badge affiche l'état actuel avec un code couleur:
|
|
|
|
- 🔴 **Rouge**: NOT_CONFIGURED ou INVALID
|
|
- 🟡 **Ambre**: CONFIGURED_UNVERIFIED
|
|
- 🟢 **Vert**: WORKING
|
|
|
|
#### Actions disponibles
|
|
|
|
- **🔄 Rafraîchir**: Récupère le statut depuis le serveur (sans test live)
|
|
- **🧪 Tester la clé**: Exécute un test live de connectivité à l'API Gemini
|
|
|
|
#### Messages contextuels
|
|
|
|
Selon le statut, des callouts informatifs s'affichent:
|
|
|
|
- **NOT_CONFIGURED**: Instructions pour ajouter la clé dans `.env`
|
|
- **CONFIGURED_UNVERIFIED**: Invitation à tester la clé
|
|
- **WORKING**: Confirmation que tout fonctionne
|
|
- **INVALID**: Détails de l'erreur et conseils de résolution
|
|
|
|
---
|
|
|
|
## 🧪 Tests
|
|
|
|
### Tests Backend (Node.js Test Runner)
|
|
|
|
```bash
|
|
node --test server/integrations/gemini/gemini.health.service.spec.mjs
|
|
```
|
|
|
|
**Couverture:**
|
|
|
|
- ✅ Status `NOT_CONFIGURED` (clé manquante)
|
|
- ✅ Status `CONFIGURED_UNVERIFIED` (clé présente, non testée)
|
|
- ✅ Status `WORKING` (cache)
|
|
- ✅ Anti-spam (rate limiting)
|
|
- ✅ Reset du cache
|
|
|
|
### Tests Frontend (Karma + Jasmine)
|
|
|
|
```bash
|
|
npm test -- --include='**/integrations.service.spec.ts'
|
|
```
|
|
|
|
**Couverture:**
|
|
|
|
- ✅ `getGeminiStatus()` avec différents statuts
|
|
- ✅ `testGeminiKey()` success et erreurs
|
|
- ✅ Gestion des erreurs HTTP (401, 429, 500, network)
|
|
- ✅ `resetGeminiCache()`
|
|
|
|
---
|
|
|
|
## 🔒 Sécurité
|
|
|
|
### Bonnes pratiques implémentées
|
|
|
|
1. **Clé jamais exposée**: La clé API n'est jamais renvoyée au frontend
|
|
2. **Rate limiting**: Maximum 1 test/30s par IP
|
|
3. **Timeout**: Requêtes API limitées à 8 secondes
|
|
4. **Logs sécurisés**: Seuls les codes HTTP sont loggés, jamais la clé
|
|
5. **Validation**: Vérification stricte des paramètres
|
|
|
|
### ⚠️ À NE PAS FAIRE
|
|
|
|
```javascript
|
|
// ❌ JAMAIS
|
|
console.log('API Key:', process.env.GEMINI_API_KEY);
|
|
|
|
// ❌ JAMAIS
|
|
res.json({ apiKey: process.env.GEMINI_API_KEY });
|
|
|
|
// ❌ JAMAIS
|
|
throw new Error(`Invalid key: ${process.env.GEMINI_API_KEY}`);
|
|
```
|
|
|
|
### ✅ À FAIRE
|
|
|
|
```javascript
|
|
// ✅ Bon
|
|
console.log('[Gemini] API key is configured');
|
|
|
|
// ✅ Bon
|
|
res.json({ status: 'WORKING' });
|
|
|
|
// ✅ Bon
|
|
throw new Error('Invalid API key (details hidden for security)');
|
|
```
|
|
|
|
---
|
|
|
|
## 🐛 Dépannage
|
|
|
|
### Problème: "Non configurée" malgré la clé dans `.env`
|
|
|
|
**Causes possibles:**
|
|
|
|
1. Serveur pas redémarré après modification `.env`
|
|
2. Mauvais fichier `.env` (doit être à la racine, pas dans `/docker-compose`)
|
|
3. Syntaxe incorrecte dans `.env` (espaces, guillemets)
|
|
|
|
**Solution:**
|
|
|
|
```bash
|
|
# Vérifier que la clé est bien chargée
|
|
node -e "require('dotenv').config(); console.log(process.env.GEMINI_API_KEY ? 'OK' : 'MISSING');"
|
|
|
|
# Redémarrer le serveur
|
|
npm start
|
|
```
|
|
|
|
### Problème: "Invalide / Erreur" avec code 401
|
|
|
|
**Cause:** Clé API invalide ou révoquée
|
|
|
|
**Solution:**
|
|
|
|
1. Vérifier la clé sur [Google AI Studio](https://makersuite.google.com/app/apikey)
|
|
2. Générer une nouvelle clé si nécessaire
|
|
3. Mettre à jour `.env`
|
|
4. Redémarrer
|
|
|
|
### Problème: "Trop de requêtes" (429)
|
|
|
|
**Cause:** Rate limiting de Google ou anti-spam local
|
|
|
|
**Solution:**
|
|
|
|
- **Rate limit Google**: Attendre quelques minutes
|
|
- **Rate limit local**: Attendre 30 secondes entre les tests
|
|
|
|
### Problème: Erreur réseau (timeout)
|
|
|
|
**Causes possibles:**
|
|
|
|
1. Pas de connexion internet
|
|
2. Proxy/firewall bloque les requêtes vers Google
|
|
3. DNS ne résout pas `generativelanguage.googleapis.com`
|
|
|
|
**Solution:**
|
|
|
|
```bash
|
|
# Tester la connectivité
|
|
curl https://generativelanguage.googleapis.com/v1beta/models?key=VOTRE_CLE
|
|
|
|
# Si timeout, vérifier proxy/firewall
|
|
```
|
|
|
|
---
|
|
|
|
## 📊 Architecture Technique
|
|
|
|
### Flow Diagram
|
|
|
|
```
|
|
┌─────────────────┐
|
|
│ User clicks │
|
|
│ "Tester" │
|
|
└────────┬────────┘
|
|
│
|
|
▼
|
|
┌─────────────────────────────────┐
|
|
│ IntegrationsService (Angular) │
|
|
│ POST /api/integrations/gemini/test │
|
|
└────────┬────────────────────────┘
|
|
│
|
|
▼
|
|
┌─────────────────────────────────┐
|
|
│ Express Route Handler │
|
|
│ /api/integrations/gemini/test │
|
|
└────────┬────────────────────────┘
|
|
│
|
|
▼
|
|
┌─────────────────────────────────┐
|
|
│ GeminiHealthService │
|
|
│ - Check rate limiting │
|
|
│ - Call Gemini API │
|
|
│ - Update cache │
|
|
└────────┬────────────────────────┘
|
|
│
|
|
▼
|
|
┌─────────────────────────────────┐
|
|
│ Google Gemini API │
|
|
│ GET /v1beta/models │
|
|
└────────┬────────────────────────┘
|
|
│
|
|
▼
|
|
┌─────────────────────────────────┐
|
|
│ Response → Cache → Frontend │
|
|
│ Badge updated with status │
|
|
└─────────────────────────────────┘
|
|
```
|
|
|
|
### Fichiers Backend
|
|
|
|
```
|
|
server/integrations/gemini/
|
|
├── gemini.types.mjs # Types JSDoc
|
|
├── gemini.health.service.mjs # Service de vérification
|
|
├── gemini.routes.mjs # Routes Express
|
|
└── gemini.health.service.spec.mjs # Tests unitaires
|
|
```
|
|
|
|
### Fichiers Frontend
|
|
|
|
```
|
|
src/app/
|
|
├── services/
|
|
│ ├── integrations.types.ts # Types TypeScript
|
|
│ ├── integrations.service.ts # Service Angular
|
|
│ └── integrations.service.spec.ts # Tests Jasmine
|
|
└── features/settings/integrations/
|
|
└── settings-integrations-gemini.component.ts # Composant UI
|
|
```
|
|
|
|
---
|
|
|
|
## 🚀 Évolutions Futures
|
|
|
|
### Version 1.1
|
|
|
|
- [ ] Persistance du cache dans SQLite/JSON (survie aux redémarrages)
|
|
- [ ] Métriques: compteur d'échecs, latence moyenne
|
|
- [ ] Support de plusieurs clés (rotation automatique)
|
|
- [ ] Webhook pour alertes d'erreur
|
|
|
|
### Version 1.2
|
|
|
|
- [ ] Test automatique au démarrage du serveur
|
|
- [ ] Health check périodique (toutes les 5 min)
|
|
- [ ] Dashboard d'observabilité (Grafana/Prometheus)
|
|
|
|
---
|
|
|
|
## 📞 Support
|
|
|
|
### Liens utiles
|
|
|
|
- [Documentation Gemini API](https://ai.google.dev/docs)
|
|
- [Google AI Studio](https://makersuite.google.com/)
|
|
- [Limites et quotas](https://ai.google.dev/pricing)
|
|
|
|
### Problème persistant ?
|
|
|
|
1. Vérifier les logs serveur:
|
|
```bash
|
|
# Logs du test
|
|
[GeminiHealth] Testing API key connectivity...
|
|
[GeminiHealth] ✅ API key is WORKING (12 models available)
|
|
|
|
# ou
|
|
[GeminiHealth] ❌ API key is INVALID (authentication failed)
|
|
```
|
|
|
|
2. Activer le mode debug (optionnel):
|
|
```javascript
|
|
// server/integrations/gemini/gemini.health.service.mjs
|
|
// Ligne ~52: Ajouter des console.log() pour debug
|
|
```
|
|
|
|
3. Créer une issue GitHub avec:
|
|
- Status retourné
|
|
- Logs serveur (sans la clé!)
|
|
- Code HTTP de l'erreur
|
|
|
|
---
|
|
|
|
**Dernière mise à jour**: 2025-01-15
|
|
**Version**: 1.0.0
|
|
**Auteur**: ObsiViewer Team
|