Ajout admin
Build & Deploy / build (push) Successful in 41s

This commit is contained in:
Mouigni
2026-08-13 23:46:41 +02:00
parent c4aeedd032
commit ad84286259
3 changed files with 155 additions and 79 deletions
+139 -65
View File
@@ -1,10 +1,12 @@
from fastapi import FastAPI, Depends, HTTPException, status
from fastapi.middleware.cors import CORSMiddleware
from sqlalchemy import text
from datetime import timedelta
from database.database import SessionLocal
from database.models import Document, User
from api.auth import (
UserLogin, UserCreate, Token, UserResponse, get_password_hash, verify_password,
UserLogin, UserCreate, Token, UserResponse, RoleUpdate,
get_password_hash, verify_password,
create_access_token, decode_token, ACCESS_TOKEN_EXPIRE_MINUTES
)
@@ -18,113 +20,76 @@ app.add_middleware(
allow_headers=["*"],
)
# ── Fonction vérification admin ──────────────────────────────
def require_admin(token: str):
email = decode_token(token)
if not email:
raise HTTPException(status_code=401, detail="Invalid token")
db = SessionLocal()
user = db.query(User).filter(User.email == email).first()
db.close()
if not user or user.role != "admin":
raise HTTPException(status_code=403, detail="Accès refusé")
return user
# ── Endpoints existants ──────────────────────────────────────
@app.get("/")
def root():
return {"message": "RegWatch API running"}
@app.post("/test-login")
def test_login(credentials: UserLogin):
return {"received": credentials.dict()}
@app.post("/signup", response_model=UserResponse)
def signup(user: UserCreate):
db = SessionLocal()
existing_user = db.query(User).filter(User.email == user.email).first()
if existing_user:
db.close()
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Email already registered"
)
raise HTTPException(status_code=400, detail="Email already registered")
hashed_password = get_password_hash(user.password)
db_user = User(
email=user.email,
password=hashed_password,
full_name=user.full_name
)
db_user = User(email=user.email, password=hashed_password, full_name=user.full_name)
db.add(db_user)
db.commit()
db.refresh(db_user)
db.close()
return UserResponse(
id=db_user.id,
email=db_user.email,
full_name=db_user.full_name
)
return UserResponse(id=db_user.id, email=db_user.email, full_name=db_user.full_name, role=db_user.role)
@app.post("/login", response_model=Token)
def login(credentials: UserLogin):
try:
db = SessionLocal()
user = db.query(User).filter(User.email == credentials.email).first()
db.close()
if not user:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="User not found"
)
raise HTTPException(status_code=401, detail="User not found")
if not verify_password(credentials.password, user.password):
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Invalid password"
)
access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
raise HTTPException(status_code=401, detail="Invalid password")
access_token = create_access_token(
data={"sub": user.email}, expires_delta=access_token_expires
data={"sub": user.email},
expires_delta=timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
)
return Token(access_token=access_token, token_type="bearer")
except HTTPException:
raise
except Exception as e:
print(f"ERROR in login: {str(e)}")
import traceback
traceback.print_exc()
raise HTTPException(
status_code=500,
detail=f"Server error: {str(e)}"
)
raise HTTPException(status_code=500, detail=f"Server error: {str(e)}")
@app.get("/me", response_model=UserResponse)
def get_current_user(token: str):
email = decode_token(token)
if not email:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Invalid token"
)
raise HTTPException(status_code=401, detail="Invalid token")
db = SessionLocal()
user = db.query(User).filter(User.email == email).first()
db.close()
if not user:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="User not found"
)
return UserResponse(
id=user.id,
email=user.email,
full_name=user.full_name
)
raise HTTPException(status_code=404, detail="User not found")
return UserResponse(id=user.id, email=user.email, full_name=user.full_name, role=user.role)
@app.get("/documents")
def get_documents():
db = SessionLocal()
documents = db.query(Document).all()
result = []
for doc in documents:
result.append({
"id": doc.id,
@@ -135,7 +100,116 @@ def get_documents():
"date": doc.meeting_date,
"pdf_url": doc.pdf_url
})
db.close()
return result
return result
# ── Migration colonne role ───────────────────────────────────
@app.post("/admin/migrate-add-role")
def migrate_add_role():
"""Endpoint temporaire — ajoute la colonne role si absente"""
db = SessionLocal()
try:
db.execute(text("ALTER TABLE users ADD COLUMN IF NOT EXISTS role VARCHAR DEFAULT 'user'"))
db.commit()
return {"message": "Colonne role ajoutée avec succès"}
except Exception as e:
return {"message": str(e)}
finally:
db.close()
# ── Premier admin sans neckfire ──────────────────────────────
@app.post("/admin/make-admin")
def make_admin(token: str, target_email: str):
"""
Passe un user en admin.
Fonctionne sans auth si aucun admin n'existe encore.
Se désactive automatiquement si un admin existe déjà.
"""
db = SessionLocal()
existing_admins = db.query(User).filter(User.role == "admin").count()
if existing_admins > 0:
# Il y a déjà un admin — vérifier que l'appelant est admin
email = decode_token(token)
caller = db.query(User).filter(User.email == email).first()
if not caller or caller.role != "admin":
db.close()
raise HTTPException(status_code=403, detail="Accès refusé")
target = db.query(User).filter(User.email == target_email).first()
if not target:
db.close()
raise HTTPException(status_code=404, detail="Utilisateur introuvable")
target.role = "admin"
db.commit()
db.close()
return {"message": f"{target_email} est maintenant admin"}
# ── Endpoints admin ──────────────────────────────────────────
@app.get("/admin/stats")
def admin_stats(token: str):
require_admin(token)
db = SessionLocal()
total_docs = db.query(Document).count()
cir_docs = db.query(Document).filter(Document.source == "CIR").count()
sccs_docs = db.query(Document).filter(Document.source == "SCCS").count()
total_users = db.query(User).count()
db.close()
return {
"total_documents": total_docs,
"cir_documents": cir_docs,
"sccs_documents": sccs_docs,
"total_users": total_users
}
@app.get("/admin/users")
def admin_get_users(token: str):
require_admin(token)
db = SessionLocal()
users = db.query(User).all()
result = [{"id": u.id, "email": u.email, "full_name": u.full_name, "role": u.role} for u in users]
db.close()
return result
@app.delete("/admin/users/{user_id}")
def admin_delete_user(user_id: int, token: str):
require_admin(token)
db = SessionLocal()
user = db.query(User).filter(User.id == user_id).first()
if not user:
db.close()
raise HTTPException(status_code=404, detail="Utilisateur introuvable")
db.delete(user)
db.commit()
db.close()
return {"message": "Utilisateur supprimé"}
@app.patch("/admin/users/{user_id}/role")
def admin_update_role(user_id: int, role_update: RoleUpdate, token: str):
require_admin(token)
db = SessionLocal()
user = db.query(User).filter(User.id == user_id).first()
if not user:
db.close()
raise HTTPException(status_code=404, detail="Utilisateur introuvable")
user.role = role_update.role
db.commit()
db.close()
return {"message": f"Rôle mis à jour : {role_update.role}"}
@app.delete("/admin/documents/{doc_id}")
def admin_delete_document(doc_id: int, token: str):
require_admin(token)
db = SessionLocal()
doc = db.query(Document).filter(Document.id == doc_id).first()
if not doc:
db.close()
raise HTTPException(status_code=404, detail="Document introuvable")
db.delete(doc)
db.commit()
db.close()
return {"message": "Document supprimé"}