feat: Sprint 2-3 — Auth JWT + Multi-tenant (HRT-28)
- auth_db.py: create users, subscriptions, refresh_tokens tables in turf_saas.db - auth.py: register/login/refresh/logout endpoints, JWT middleware, plan_required decorator, free daily-limit check - middleware.py: in-memory rate limiter (100 req/min/IP), timestamped access logs - saas_api.py: Flask app factory wiring JWT, CORS, blueprints, /api/v1/predictions plan-gating - tests/test_auth.py: 27 pytest tests, 83% coverage (target >=80%) - API_AUTH.md: full endpoint documentation Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
132
API_AUTH.md
Normal file
132
API_AUTH.md
Normal file
@@ -0,0 +1,132 @@
|
||||
# API Auth JWT — Documentation
|
||||
## Sprint 2-3 (HRT-28)
|
||||
|
||||
Base URL: `http://localhost:8792`
|
||||
|
||||
---
|
||||
|
||||
## Endpoints d'authentification
|
||||
|
||||
### `POST /api/v1/auth/register`
|
||||
Inscription d'un nouvel utilisateur (plan free par défaut).
|
||||
|
||||
**Body JSON:**
|
||||
```json
|
||||
{ "email": "user@example.com", "password": "motdepasse123" }
|
||||
```
|
||||
**Réponse 201:**
|
||||
```json
|
||||
{ "message": "Compte créé avec succès", "user_id": 1 }
|
||||
```
|
||||
**Erreurs:** `400` (email invalide / mot de passe < 8 car.), `409` (email déjà utilisé)
|
||||
|
||||
---
|
||||
|
||||
### `POST /api/v1/auth/login`
|
||||
Connexion — retourne access_token (15min) + refresh_token (30j).
|
||||
|
||||
**Body JSON:**
|
||||
```json
|
||||
{ "email": "user@example.com", "password": "motdepasse123" }
|
||||
```
|
||||
**Réponse 200:**
|
||||
```json
|
||||
{
|
||||
"access_token": "<JWT>",
|
||||
"refresh_token": "<refresh_JWT>",
|
||||
"token_type": "Bearer",
|
||||
"plan": "free"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `POST /api/v1/auth/refresh`
|
||||
Rotation du refresh token — invalide l'ancien, émet un nouveau.
|
||||
|
||||
**Body JSON:**
|
||||
```json
|
||||
{ "refresh_token": "<refresh_JWT>" }
|
||||
```
|
||||
**Réponse 200:** identique à `/login`
|
||||
|
||||
---
|
||||
|
||||
### `POST /api/v1/auth/logout`
|
||||
Révocation du refresh token.
|
||||
|
||||
**Body JSON:**
|
||||
```json
|
||||
{ "refresh_token": "<refresh_JWT>" }
|
||||
```
|
||||
**Réponse 200:**
|
||||
```json
|
||||
{ "message": "Déconnexion réussie" }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Routes protégées
|
||||
|
||||
Toutes les routes protégées nécessitent le header:
|
||||
```
|
||||
Authorization: Bearer <access_token>
|
||||
```
|
||||
|
||||
### `GET /api/v1/predictions`
|
||||
| Plan | Accès |
|
||||
|---------|---------------------------------------------|
|
||||
| free | Top 3 uniquement, 1 course/jour |
|
||||
| premium | Toutes les courses + alertes Telegram |
|
||||
| pro | API complète + lien export CSV |
|
||||
|
||||
### `GET /api/v1/predictions/export`
|
||||
Export CSV — **plan pro uniquement** (`403` pour free/premium).
|
||||
|
||||
### `GET /api/v1/subscription/upgrade`
|
||||
Infos sur les plans disponibles et plan courant de l'utilisateur.
|
||||
|
||||
### `GET /api/v1/health`
|
||||
Vérification d'état du service (pas d'auth requise).
|
||||
|
||||
---
|
||||
|
||||
## Sécurité
|
||||
|
||||
- **Passwords:** hashés avec bcrypt (saltRounds=12)
|
||||
- **JWT access:** expiration 15 minutes (HS256)
|
||||
- **JWT refresh:** expiration 30 jours, stocké hashé (SHA-256) en DB, rotation à chaque usage
|
||||
- **Rate limiting:** 100 requêtes/min par IP — header `X-RateLimit-Remaining`
|
||||
- **CORS:** configuré pour `https://turf-ia.h3r7.tech` + localhost dev
|
||||
- **Logs d'accès:** horodatés ISO 8601 dans `logs/saas_api.log`
|
||||
|
||||
---
|
||||
|
||||
## Lancement
|
||||
|
||||
```bash
|
||||
JWT_SECRET_KEY="votre_cle_secrete" \
|
||||
CORS_ORIGINS="https://turf-ia.h3r7.tech" \
|
||||
./venv/bin/python saas_api.py
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Tests
|
||||
|
||||
```bash
|
||||
./venv/bin/pytest tests/test_auth.py -v
|
||||
# Avec couverture:
|
||||
./venv/bin/pytest tests/test_auth.py --cov=auth --cov=auth_db --cov=middleware --cov=saas_api --cov-report=term-missing
|
||||
# Résultat: 27 tests OK, couverture globale 83%
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Structure des tables DB
|
||||
|
||||
```sql
|
||||
-- users: id, email, password_hash, plan(free/premium/pro), created_at, is_active, daily_usage, last_usage_date
|
||||
-- subscriptions: id, user_id, plan, start_date, end_date, stripe_customer_id
|
||||
-- refresh_tokens: id, user_id, token_hash, created_at, expires_at, revoked
|
||||
```
|
||||
Reference in New Issue
Block a user