correction des erreurs de déconnexion db

main
Anaz 2025-02-25 13:48:16 +04:00
parent 81a93c5683
commit 89436bd8f8
13 changed files with 312 additions and 242 deletions

View File

@ -1,7 +1,7 @@
from datetime import datetime, timedelta
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from fastapi import APIRouter, Depends, Form, HTTPException, status, Body
from fastapi import APIRouter, HTTPException, status, Body
from fastapi.responses import JSONResponse
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from sqlalchemy import update, select
@ -10,7 +10,6 @@ from models.schemas import Token, UserCreate, UserResponse
from config.database import get_db
from models.db import users_table
from config.settings import settings
from sqlalchemy.ext.asyncio import AsyncSession
from jose import jwt, JWTError
from smtplib import SMTP
from services.user_service import UserService
@ -21,7 +20,8 @@ router = APIRouter()
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/v1/auth/token")
@router.post("/signup", status_code=201, summary="User Signup")
async def signup(user: UserCreate, db=Depends(get_db)):
async def signup(user: UserCreate):
async with get_db() as db:
existing_user = await AuthService.get_user_by_email(user.email, db)
if existing_user:
raise HTTPException(
@ -31,7 +31,8 @@ async def signup(user: UserCreate, db=Depends(get_db)):
return await UserService.create_user(user, db)
@router.post("/token", response_model=Token, summary="Login and get access token")
async def login_for_access_token( form_data: OAuth2PasswordRequestForm = Depends(), db=Depends(get_db)):
async def login_for_access_token(form_data: OAuth2PasswordRequestForm = Body(...)):
async with get_db() as db:
user = await AuthService.authenticate_user(form_data.username, form_data.password, db)
logger.info(f"User {form_data.username} logged in")
if not user:
@ -46,7 +47,6 @@ async def login_for_access_token( form_data: OAuth2PasswordRequestForm = Depends
@router.post("/isvalid-token", summary="Verify token validity")
async def verify_token(token: str = Body(...)):
try:
# Décoder le token pour vérifier sa validité
payload = jwt.decode(token, settings.secret_key, algorithms=[settings.algorithm])
return {"valid": True, "message": "Token is valid", "payload": payload}
except jwt.ExpiredSignatureError:
@ -61,11 +61,13 @@ async def verify_token(token: str = Body(...)):
)
@router.get("/me", summary="Get current user")
async def read_users_me(token:str = Depends(oauth2_scheme) , db=Depends(get_db)):
async def read_users_me(token: str = Body(...)):
async with get_db() as db:
return await AuthService.get_current_user(token, db)
@router.post("/reset-password")
async def reset_password(token: str = Body(...), new_password: str = Body(...), db: AsyncSession = Depends(get_db)):
async def reset_password(token: str = Body(...), new_password: str = Body(...)):
async with get_db() as db:
try:
payload = jwt.decode(token, settings.secret_key, algorithms=[settings.algorithm])
email = payload.get("sub")
@ -74,10 +76,8 @@ async def reset_password(token: str = Body(...), new_password: str = Body(...),
except JWTError:
raise HTTPException(status_code=400, detail="Invalid or expired token")
# Hash the new password
hashed_password = pwd_context.hash(new_password)
# Update the user's password
query = (
update(users_table)
.where(users_table.c.email == email)
@ -85,19 +85,18 @@ async def reset_password(token: str = Body(...), new_password: str = Body(...),
.execution_options(synchronize_session="fetch")
)
await db.execute(query)
await db.commit()
return JSONResponse(content={"message": "Password updated successfully."})
@router.post("/password-reset-request")
async def password_reset_request(email: str, db: AsyncSession = Depends(get_db)):
async def password_reset_request(email: str = Body(...)):
async with get_db() as db:
query = select(users_table).where(users_table.c.email == email)
result = await db.execute(query)
user = result.fetchone()
if not user:
raise HTTPException(status_code=404, detail="User not found")
# Générer un token JWT
reset_token = jwt.encode(
{"sub": email, "exp": datetime.utcnow() + timedelta(hours=1)},
settings.secret_key,
@ -106,7 +105,6 @@ async def password_reset_request(email: str, db: AsyncSession = Depends(get_db))
reset_link = f"{settings.resetpass_url}/?token={reset_token}"
# Envoyer le lien par email
try:
subject = "mot de passe perdu"
sender_email = settings.email_username

View File

@ -6,5 +6,6 @@ from config.database import get_db
router = APIRouter()
@router.post("/", status_code=201)
async def report_issue(issue: TechnicalIssue, db=Depends(get_db)):
async def report_issue(issue: TechnicalIssue):
async with get_db() as db:
return await MessageService.create_issue(issue, db)

View File

@ -11,36 +11,35 @@ router = APIRouter()
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/v1/auth/token")
@router.post("/", status_code=status.HTTP_201_CREATED)
async def request_need(need: NeedRequestCreate, db=Depends(get_db)):
async def request_need(need: NeedRequestCreate):
async with get_db() as db:
return await NeedRequestService.create_need(need, db)
@router.get("/", status_code=status.HTTP_200_OK)
async def get_all_reports(db=Depends(get_db)):
async def get_all_reports():
async with get_db() as db:
return await NeedRequestService.get_all_needs(db)
@router.get("/{need_id}", status_code=status.HTTP_200_OK)
async def get_need(need_id: int, db=Depends(get_db)):
async def get_need(need_id: int):
async with get_db() as db:
need = await NeedRequestService.get_need(need_id, db)
if not need:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Need request not found")
return need
@router.put("/{need_id}", status_code=status.HTTP_200_OK)
async def update_need(
need_id: int,
need_update: NeedRequestUpdate,
token: str = Depends(oauth2_scheme),
db=Depends(get_db),
token: str = Depends(oauth2_scheme)
):
async with get_db() as db:
need = await NeedRequestService.get_need(need_id, db)
if not need:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Need request not found")
# V<>rifie si l'utilisateur est l'auteur ou un administrateur
# Vérifie si l'utilisateur est l'auteur ou un administrateur
if NeedRequestService.verify_requester_or_admin(need_id, token, db):
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
@ -49,20 +48,17 @@ async def update_need(
return await NeedRequestService.update_need(need_id, need_update, db)
@router.delete("/{need_id}", status_code=status.HTTP_200_OK)
async def delete_need(
need_id: int,
token: str = Depends(oauth2_scheme),
db=Depends(get_db),
token: str = Depends(oauth2_scheme)
):
async with get_db() as db:
need = await NeedRequestService.get_need(need_id, db)
if not need:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Need request not found")
# V<>rifie si l'utilisateur est l'auteur ou un administrateur
# Vérifie si l'utilisateur est l'auteur ou un administrateur
if NeedRequestService.verify_requester_or_admin(need_id, token, db):
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,

View File

@ -13,12 +13,11 @@ oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/v1/auth/token")
@router.post("/", status_code=201)
async def create_report(
file: Optional[UploadFile] = File(None), # Le champ photo est reçu sous forme de fichier
report: PersonReportCreate = Form(...), # Le champ report est reçu sous forme de chaîne JSON
db: get_db = Depends(),
file: Optional[UploadFile] = File(None),
report: PersonReportCreate = Form(...),
token: str = Depends(oauth2_scheme)
):
# Appeler le service pour traiter le rapport
async with get_db() as db:
try:
created_report = await PersonReportService.create_report(report, db, token, file)
except Exception as e:
@ -27,17 +26,21 @@ async def create_report(
return created_report
@router.put("/{report_id}")
async def update_report(report_id: int, report: PersonReportUpdate, db=Depends(get_db)):
async def update_report(report_id: int, report: PersonReportUpdate):
async with get_db() as db:
return await PersonReportService.update_report(report_id, report, db)
@router.get("/{report_id}")
async def get_report(report_id: int, db=Depends(get_db)):
async def get_report(report_id: int):
async with get_db() as db:
return await PersonReportService.get_report(report_id, db)
@router.get("/", response_model=list[PersonReportResponse])
async def list_reports(status: Optional[str] = None, db=Depends(get_db)):
async def list_reports(status: Optional[str] = None):
async with get_db() as db:
return await PersonReportService.list_reports(status, db)
@router.delete("/{report_id}", status_code=204)
async def delete_report(report_id: int, db=Depends(get_db), token: str = Depends(oauth2_scheme)):
async def delete_report(report_id: int, token: str = Depends(oauth2_scheme)):
async with get_db() as db:
return await PersonReportService.delete_report(report_id, db, token)

View File

@ -8,25 +8,26 @@ router = APIRouter()
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/v1/auth/token")
@router.post("/", status_code=201)
async def create_point(point: CreatePointOfInterest, db=Depends(get_db), token: str = Depends(oauth2_scheme)):
async def create_point(point: CreatePointOfInterest, token: str = Depends(oauth2_scheme)):
async with get_db() as db:
return await PointsOfInterestService.create_point_of_interest(point, db, token)
@router.get("/{point_id}")
async def get_point(point_id: int, db=Depends(get_db)):
async def get_point(point_id: int):
async with get_db() as db:
return await PointsOfInterestService.get_point_of_interest(point_id, db)
@router.get("/")
async def get_all_points(db=Depends(get_db)):
async def get_all_points():
async with get_db() as db:
return await PointsOfInterestService.get_all_points_of_interest(db)
@router.put("/{point_id}")
async def update_point(point_id: int, point: UpdatePointOfInterest, db=Depends(get_db), token: str = Depends(oauth2_scheme)):
async def update_point(point_id: int, point: UpdatePointOfInterest, token: str = Depends(oauth2_scheme)):
async with get_db() as db:
return await PointsOfInterestService.update_point_of_interest(point_id, point, db, token)
@router.delete("/{point_id}")
async def delete_point(point_id: int, db=Depends(get_db), token: str = Depends(oauth2_scheme)):
async def delete_point(point_id: int, token: str = Depends(oauth2_scheme)):
async with get_db() as db:
return await PointsOfInterestService.delete_point_of_interest(point_id, db, token)

View File

@ -10,21 +10,26 @@ oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/v1/auth/token")
router = APIRouter()
@router.post("/", status_code=status.HTTP_201_CREATED)
async def report_user(report: UserReport, db=Depends(get_db)):
async def report_user(report: UserReport):
async with get_db() as db:
return await ReportService.create_report(report, db)
@router.get("/{report_id}", status_code=status.HTTP_200_OK)
async def get_report(report_id: int, db=Depends(get_db), token: str = Depends(oauth2_scheme)):
async def get_report(report_id: int, token: str = Depends(oauth2_scheme)):
async with get_db() as db:
return await ReportService.get_report_by_id(report_id, db, token)
@router.get("/", status_code=status.HTTP_200_OK)
async def get_all_reports(db=Depends(get_db), token: str = Depends(oauth2_scheme)):
async def get_all_reports(token: str = Depends(oauth2_scheme)):
async with get_db() as db:
return await ReportService.get_all_reports(db, token)
@router.put("/{report_id}", status_code=status.HTTP_200_OK)
async def update_report(report_id: int, report_update: UserReportUpdate, db=Depends(get_db), token: str = Depends(oauth2_scheme)):
async def update_report(report_id: int, report_update: UserReportUpdate, token: str = Depends(oauth2_scheme)):
async with get_db() as db:
return await ReportService.update_report(report_id, report_update, db, token)
@router.delete("/{report_id}", status_code=status.HTTP_200_OK)
async def delete_report(report_id: int, db=Depends(get_db), token: str = Depends(oauth2_scheme)):
async def delete_report(report_id: int, token: str = Depends(oauth2_scheme)):
async with get_db() as db:
return await ReportService.delete_report(report_id, db, token)

View File

@ -9,50 +9,50 @@ from typing import List
router = APIRouter()
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/v1/auth/token")
@router.post("/", status_code=201)
async def create_role(name: str, db: AsyncSession = Depends(get_db), token: str = Depends(oauth2_scheme)):
async def create_role(name: str, token: str = Depends(oauth2_scheme)):
"""
Créer un nouveau rôle avec des permissions associées (réservé aux administrateurs).
"""
async with get_db() as db:
return await RoleService.create_role(name, db, token)
@router.get("/{role_id}", response_model=Role)
async def get_role(role_id: int, db: AsyncSession = Depends(get_db)):
async def get_role(role_id: int):
"""
Récupérer les détails d'un rôle spécifique.
"""
async with get_db() as db:
return await RoleService.get_role(role_id, db)
@router.get("/", response_model=List[Role])
async def get_all_roles(db: AsyncSession = Depends(get_db)):
async def get_all_roles():
"""
Récupérer tous les rôles avec leurs permissions associées.
"""
async with get_db() as db:
return await RoleService.get_all_roles(db)
@router.put("/{role_id}")
async def update_role(role_id: int, role: Role, db: AsyncSession = Depends(get_db), token: str = Depends(oauth2_scheme)):
async def update_role(role_id: int, role: Role, token: str = Depends(oauth2_scheme)):
"""
Mettre à jour un rôle existant (réservé aux administrateurs).
"""
async with get_db() as db:
return await RoleService.update_role(role_id, role.dict(), db, token)
@router.delete("/{role_id}")
async def delete_role(role_id: int, db: AsyncSession = Depends(get_db), token: str = Depends(oauth2_scheme)):
async def delete_role(role_id: int, token: str = Depends(oauth2_scheme)):
"""
Supprimer un rôle (réservé aux administrateurs).
"""
async with get_db() as db:
return await RoleService.delete_role(role_id, db, token)
@router.get("/roles/permissions", response_model=List[Permission])
async def get_all_permissions(db: AsyncSession = Depends(get_db)):
async def get_all_permissions():
"""
Récupérer toutes les permissions disponibles.
"""
async with get_db() as db:
return await RoleService.get_all_permissions(db)

View File

@ -8,25 +8,26 @@ router = APIRouter()
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/v1/auth/token")
@router.post("/", status_code=201)
async def create_shelter(shelter: CreateShelter, db=Depends(get_db), token: str = Depends(oauth2_scheme)):
async def create_shelter(shelter: CreateShelter, token: str = Depends(oauth2_scheme)):
async with get_db() as db:
return await ShelterService.create_shelter(shelter, db, token)
@router.get("/{shelter_id}")
async def get_shelter(shelter_id: int, db=Depends(get_db)):
async def get_shelter(shelter_id: int):
async with get_db() as db:
return await ShelterService.get_shelter(shelter_id, db)
@router.get("/")
async def get_all_shelters(db=Depends(get_db)):
async def get_all_shelters():
async with get_db() as db:
return await ShelterService.get_all_shelters(db)
@router.put("/{shelter_id}")
async def update_shelter(shelter_id: int, shelter: UpdateShelter, db=Depends(get_db), token: str = Depends(oauth2_scheme)):
async def update_shelter(shelter_id: int, shelter: UpdateShelter, token: str = Depends(oauth2_scheme)):
async with get_db() as db:
return await ShelterService.update_shelter(shelter_id, shelter, db, token)
@router.delete("/{shelter_id}")
async def delete_shelter(shelter_id: int, db=Depends(get_db), token: str = Depends(oauth2_scheme)):
async def delete_shelter(shelter_id: int, token: str = Depends(oauth2_scheme)):
async with get_db() as db:
return await ShelterService.delete_shelter(shelter_id, db, token)

View File

@ -9,21 +9,26 @@ router = APIRouter()
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/v1/auth/token")
@router.post("/", status_code=201)
async def create_issue(issue: CreateTechnicalIssue, db=Depends(get_db), token: str = Depends(oauth2_scheme)):
async def create_issue(issue: CreateTechnicalIssue, token: str = Depends(oauth2_scheme)):
async with get_db() as db:
return await TechnicalIssueService.create_issue(issue, db, token)
@router.get("/{issue_id}")
async def get_issue(issue_id: int, db=Depends(get_db), token: str = Depends(oauth2_scheme)):
async def get_issue(issue_id: int, token: str = Depends(oauth2_scheme)):
async with get_db() as db:
return await TechnicalIssueService.get_issue(issue_id, db, token)
@router.get("/")
async def get_all_issues(db=Depends(get_db), token: str = Depends(oauth2_scheme)):
async def get_all_issues(token: str = Depends(oauth2_scheme)):
async with get_db() as db:
return await TechnicalIssueService.get_all_issues(db, token)
@router.put("/{issue_id}")
async def update_issue(issue_id: int, issue_data: UpdateTechnicalIssue, db=Depends(get_db), token: str = Depends(oauth2_scheme)):
async def update_issue(issue_id: int, issue_data: UpdateTechnicalIssue, token: str = Depends(oauth2_scheme)):
async with get_db() as db:
return await TechnicalIssueService.update_issue(issue_id, issue_data, db, token)
@router.delete("/{issue_id}")
async def delete_issue(issue_id: int, db=Depends(get_db), token: str = Depends(oauth2_scheme)):
async def delete_issue(issue_id: int, token: str = Depends(oauth2_scheme)):
async with get_db() as db:
return await TechnicalIssueService.delete_issue(issue_id, db, token)

View File

@ -10,7 +10,8 @@ router = APIRouter()
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/v1/auth/token")
@router.post("/")
async def upload_file(file: UploadFile, db=Depends(get_db), token: str = Depends(oauth2_scheme)):
async def upload_file(file: UploadFile, token: str = Depends(oauth2_scheme)):
async with get_db() as db:
user = await AuthService.get_current_user(token, db)
logger.info(f"User {user} is uploading a file")
return await UploadService.upload_image_to_s3(file, user["id"])

View File

@ -1,6 +1,5 @@
from fastapi import APIRouter, Depends, HTTPException
from fastapi.security import OAuth2PasswordBearer
from sqlalchemy.ext.asyncio import AsyncSession
from services.user_service import UserService
from models.schemas import UserUpdateRole, UserBlockBan, UserResponse
from config.database import get_db
@ -11,29 +10,36 @@ router = APIRouter()
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/v1/auth/token")
@router.get("/", response_model=list[UserResponse])
async def list_users(status: Optional[str] = None, db=Depends(get_db), token: str = Depends(oauth2_scheme)):
async def list_users(status: Optional[str] = None, token: str = Depends(oauth2_scheme)):
async with get_db() as db:
return await UserService.list_users(token, status, db)
@router.patch("/role", status_code=200)
async def change_role(user_update: UserUpdateRole, db: AsyncSession = Depends(get_db), token: str = Depends(oauth2_scheme)):
async def change_role(user_update: UserUpdateRole, token: str = Depends(oauth2_scheme)):
async with get_db() as db:
return await UserService.change_user_role(user_update, db, token)
@router.post("/block", status_code=200)
async def block_user(user_action: UserBlockBan, db: AsyncSession = Depends(get_db), token: str = Depends(oauth2_scheme)):
async def block_user(user_action: UserBlockBan, token: str = Depends(oauth2_scheme)):
async with get_db() as db:
return await UserService.block_user(user_action, db, token)
@router.post("/ban", status_code=200)
async def ban_user(user_action: UserBlockBan, db: AsyncSession = Depends(get_db), token: str = Depends(oauth2_scheme)):
async def ban_user(user_action: UserBlockBan, token: str = Depends(oauth2_scheme)):
async with get_db() as db:
return await UserService.ban_user(user_action, db, token)
@router.post("/unblock", status_code=200)
async def unblock_user(user_action: UserBlockBan, db: AsyncSession = Depends(get_db), token: str = Depends(oauth2_scheme)):
async def unblock_user(user_action: UserBlockBan, token: str = Depends(oauth2_scheme)):
async with get_db() as db:
return await UserService.unblock_user(user_action, db, token)
@router.post("/unban", status_code=200)
async def unban_user(user_action: UserBlockBan, db: AsyncSession = Depends(get_db), token: str = Depends(oauth2_scheme)):
async def unban_user(user_action: UserBlockBan, token: str = Depends(oauth2_scheme)):
async with get_db() as db:
return await UserService.unban_user(user_action, db, token)
@router.get("/getuserbymail", response_model=UserResponse)
async def get_user_by_email(email: str, db=Depends(get_db), token: str = Depends(oauth2_scheme)):
async def get_user_by_email(email: str, token: str = Depends(oauth2_scheme)):
async with get_db() as db:
return await UserService.get_user_by_email(email, db, token)

View File

@ -1,14 +1,46 @@
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
from sqlalchemy.orm import sessionmaker
from sqlalchemy.exc import SQLAlchemyError
from config.settings import settings
import logging
from contextlib import asynccontextmanager
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
DATABASE_URL = settings.database_url
engine = create_async_engine(DATABASE_URL, echo=True)
AsyncSessionLocal = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)
# Configuration optimisée du moteur
engine = create_async_engine(
DATABASE_URL,
echo=True,
pool_size=5,
max_overflow=10,
pool_timeout=30,
pool_recycle=1800,
pool_pre_ping=True
)
AsyncSessionLocal = sessionmaker(
engine,
class_=AsyncSession,
expire_on_commit=False,
autocommit=False,
autoflush=False
)
@asynccontextmanager
async def get_db():
session = AsyncSessionLocal()
try:
yield session
await session.commit()
except SQLAlchemyError as e:
await session.rollback()
logger.error(f"Database error: {str(e)}")
raise
finally:
await session.close()
async def init_db():
from models.db import metadata
@ -19,7 +51,3 @@ async def init_db():
except Exception as e:
logger.error(f"Error creating database tables: {str(e)}")
raise
async def get_db():
async with AsyncSessionLocal() as session:
yield session

25
config/database.txt Normal file
View File

@ -0,0 +1,25 @@
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
from sqlalchemy.orm import sessionmaker
from config.settings import settings
import logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
DATABASE_URL = settings.database_url
engine = create_async_engine(DATABASE_URL, echo=True)
AsyncSessionLocal = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)
async def init_db():
from models.db import metadata
try:
async with engine.begin() as conn:
await conn.run_sync(metadata.create_all)
logger.info("Database tables created successfully.")
except Exception as e:
logger.error(f"Error creating database tables: {str(e)}")
raise
async def get_db():
async with AsyncSessionLocal() as session:
yield session