2nzi commited on
Commit
6600e8c
·
verified ·
1 Parent(s): 6d8700d

update main

Browse files
Files changed (1) hide show
  1. main.py +56 -83
main.py CHANGED
@@ -1,105 +1,78 @@
1
- from fastapi import FastAPI, Depends, HTTPException, Header
2
  from fastapi.middleware.cors import CORSMiddleware
3
- from firebase_admin import auth, credentials, initialize_app
4
- from functools import wraps
5
  import firebase_admin
6
- import os
7
- import json
8
- from dotenv import load_dotenv
9
 
10
- # Charger les variables d'environnement
11
- load_dotenv()
 
 
12
 
13
  app = FastAPI()
14
 
15
- # Configuration CORS pour autoriser les requêtes depuis le frontend
 
 
 
16
  app.add_middleware(
17
  CORSMiddleware,
18
- allow_origins=[
19
- "http://localhost:5173",
20
- "http://localhost:8000",
21
- "https://junsen-ai.vercel.app",
22
- "https://2nzi-backendjunsen.hf.space"
23
- ],
24
  allow_credentials=True,
25
- allow_methods=["*"],
26
- allow_headers=["*"],
27
  )
28
- # Décorateur pour restreindre l'accès en fonction des rôles
29
- def require_role(roles):
30
- def decorator(func):
31
- @wraps(func)
32
- async def wrapper(*args, token=Depends(verify_token), **kwargs):
33
- print("Token dans require_role:", token)
34
- print("Rôle requis:", roles)
35
- print("Rôle trouvé:", token.get("role"))
36
- if token.get("role") not in roles:
37
- raise HTTPException(
38
- status_code=403,
39
- detail={"message": "Accès non autorisé", "role": token.get("role")}
40
- )
41
- return await func(*args, **kwargs)
42
- return wrapper
43
- return decorator
44
- # Initialiser Firebase avec les credentials depuis les variables d'environnement
45
- if os.getenv('FIREBASE_CREDENTIALS'):
46
- cred_dict = json.loads(os.getenv('FIREBASE_CREDENTIALS'))
47
- cred = credentials.Certificate(cred_dict)
48
- else:
49
- # Fallback pour le développement local
50
- cred = credentials.Certificate("serviceAccountKey.json")
51
-
52
- firebase_admin.initialize_app(cred)
53
 
54
- async def verify_token(authorization: str = Header(...)):
 
 
 
 
 
 
 
 
55
  try:
56
- print("Authorization reçu:", authorization[:50] + "...")
57
- token = authorization.split("Bearer ")[1]
58
- print("Token extrait:", token[:50] + "...")
59
- decoded_token = auth.verify_id_token(token)
 
 
 
 
60
 
61
- # Récupérer les custom claims ou le rôle depuis Firestore
62
- try:
63
- user = auth.get_user(decoded_token['uid'])
64
- print("User data:", user._data)
65
- except Exception as e:
66
- print("Erreur lors de la récupération des données utilisateur:", str(e))
67
 
68
  return decoded_token
69
- except Exception as e:
70
- print("Erreur de vérification:", str(e))
71
  raise HTTPException(
72
- status_code=401,
73
- detail={
74
- "message": "Token invalide",
75
- "error": str(e)
76
- }
77
  )
78
 
79
- @app.get("/api/protected/user")
80
- @require_role(["user_extern", "admin"])
81
- async def user_route():
82
- try:
83
- return {"message": "Route utilisateur"}
84
- except Exception as e:
85
- print("Erreur dans user_route:", str(e))
86
- raise HTTPException(
87
- status_code=500,
88
- detail={
89
- "message": "Erreur serveur",
90
- "error": str(e)
91
- }
92
- )
93
 
 
 
 
 
94
 
 
 
 
95
 
96
- # Routes sécurisées
97
  @app.get("/api/protected/admin")
98
- @require_role(["admin"])
99
- async def admin_only():
100
- return {"message": "Route admin"}
101
-
102
- # Route de test pour vérifier que le serveur fonctionne
103
- @app.get("/")
104
- async def root():
105
- return {"message": "Backend Junsen AI opérationnel"}
 
1
+ from fastapi import FastAPI, Depends, HTTPException, status, Response
2
  from fastapi.middleware.cors import CORSMiddleware
3
+ from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
4
+ from firebase_admin import auth, credentials, firestore
5
  import firebase_admin
 
 
 
6
 
7
+ # Initialisation Firebase Admin
8
+ cred = credentials.Certificate("serviceAccountKey.json")
9
+ firebase_admin.initialize_app(cred)
10
+ db = firestore.client()
11
 
12
  app = FastAPI()
13
 
14
+ # Configuration CORS
15
+ allowed_origins = [
16
+ "http://localhost:5173"
17
+ ]
18
  app.add_middleware(
19
  CORSMiddleware,
20
+ allow_origins=allowed_origins,
 
 
 
 
 
21
  allow_credentials=True,
22
+ allow_methods=["POST", "GET"],
23
+ allow_headers=["*"]
24
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
 
26
+ # Fonction pour vérifier le token Firebase et récupérer le rôle depuis Firestore
27
+ def get_user(res: Response,
28
+ cred: HTTPAuthorizationCredentials = Depends(HTTPBearer(auto_error=False))):
29
+ if cred is None:
30
+ raise HTTPException(
31
+ status_code=status.HTTP_401_UNAUTHORIZED,
32
+ detail="Bearer authentication required",
33
+ headers={'WWW-Authenticate': 'Bearer realm="auth_required"'},
34
+ )
35
  try:
36
+ # Vérification et décodage du token Firebase
37
+ decoded_token = auth.verify_id_token(cred.credentials)
38
+ user_id = decoded_token['uid']
39
+
40
+ # Récupération du rôle de l'utilisateur depuis Firestore
41
+ user_doc = db.collection('users').document(user_id).get()
42
+ if not user_doc.exists:
43
+ raise HTTPException(status_code=401, detail="Utilisateur non trouvé dans Firestore")
44
 
45
+ # Extraction du rôle et ajout aux informations utilisateur
46
+ user_data = user_doc.to_dict()
47
+ user_role = user_data.get('role', 'user_extern') # Par défaut à 'user_extern' si le rôle n'existe pas
48
+ decoded_token['role'] = user_role
49
+ res.headers['WWW-Authenticate'] = 'Bearer realm="auth_required"'
 
50
 
51
  return decoded_token
52
+ except Exception as err:
 
53
  raise HTTPException(
54
+ status_code=status.HTTP_401_UNAUTHORIZED,
55
+ detail=f"Invalid authentication credentials. {err}",
56
+ headers={'WWW-Authenticate': 'Bearer error="invalid_token"'},
 
 
57
  )
58
 
59
+ # Fonction de dépendance pour vérifier le rôle
60
+ def require_role(allowed_roles):
61
+ def role_checker(user_info=Depends(get_user)):
62
+ if user_info['role'] not in allowed_roles:
63
+ raise HTTPException(status_code=403, detail="Accès non autorisé")
64
+ return user_info
65
+ return role_checker
 
 
 
 
 
 
 
66
 
67
+ # Route publique
68
+ @app.get("/")
69
+ async def root():
70
+ return {"message": "This is the root."}
71
 
72
+ @app.get("/api/protected/user")
73
+ async def protected_user_route(user_info=Depends(get_user)):
74
+ return {"message": "Protected user route accessed successfully", "user_info": user_info}
75
 
 
76
  @app.get("/api/protected/admin")
77
+ async def protected_admin_route(user_info=Depends(require_role(["admin"]))):
78
+ return {"message": "Protected admin route accessed successfully", "user_info": user_info}