From ede9d844742c79ecc98dcb4a5002dc83705adb40 Mon Sep 17 00:00:00 2001 From: Anaz Date: Tue, 21 Jan 2025 12:29:25 +0400 Subject: [PATCH] corrections for deployment --- api/v1/auth.py | 10 +++--- api/v1/person_reports.py | 28 ++++++++++++--- models/schemas.py | 12 ++----- services/auth_service.py | 74 +++++++++++++++++++++------------------- services/user_service.py | 35 +++++++++++++------ 5 files changed, 93 insertions(+), 66 deletions(-) diff --git a/api/v1/auth.py b/api/v1/auth.py index 5f36c4c..a187069 100644 --- a/api/v1/auth.py +++ b/api/v1/auth.py @@ -13,13 +13,14 @@ 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 from utils.logging import logger -from utils.security import verify_password, get_password_hash, pwd_context +from utils.security import get_password_hash, pwd_context router = APIRouter() oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/v1/auth/token") -@router.post("/signup", response_model=UserResponse, status_code=201, summary="User Signup") +@router.post("/signup", status_code=201, summary="User Signup") async def signup(user: UserCreate, db=Depends(get_db)): existing_user = await AuthService.get_user_by_email(user.email, db) if existing_user: @@ -27,8 +28,7 @@ async def signup(user: UserCreate, db=Depends(get_db)): status_code=status.HTTP_400_BAD_REQUEST, detail="Email already registered." ) - user.password = get_password_hash(user.password) - return await AuthService.create_user(user, 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)): @@ -42,7 +42,7 @@ async def login_for_access_token(form_data: OAuth2PasswordRequestForm = Depends( access_token = AuthService.create_access_token(data={"sub": user["email"]}) return {"access_token": access_token, "token_type": "bearer"} -@router.get("/me", response_model=UserResponse, summary="Get current user") +@router.get("/me", summary="Get current user") async def read_users_me(token:str = Depends(oauth2_scheme) , db=Depends(get_db)): return await AuthService.get_current_user(token, db) diff --git a/api/v1/person_reports.py b/api/v1/person_reports.py index 1d10718..9ecbf05 100644 --- a/api/v1/person_reports.py +++ b/api/v1/person_reports.py @@ -1,5 +1,6 @@ from fastapi import APIRouter, Depends, File, HTTPException, UploadFile from fastapi.security import OAuth2PasswordBearer +from pydantic import ValidationError from services.person_report_service import PersonReportService from models.schemas import PersonReportCreate, PersonReportUpdate, PersonReportResponse, UserResponse from config.database import get_db @@ -9,15 +10,32 @@ from services.auth_service import AuthService router = APIRouter() oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/v1/auth/token") -@router.post("/", response_model=PersonReportResponse, status_code=201) -async def create_report(report: PersonReportCreate, image_file: UploadFile = File(None), db=Depends(get_db), token: str = Depends(oauth2_scheme)): - return await PersonReportService.create_report(report, db, image_file, token) +@router.post("/", status_code=201) +async def create_report( + report: str, # Le champ report est reçu sous forme de chaîne JSON + image_file: Optional[UploadFile] = File(None), # L'image est facultative + db: get_db = Depends(), + token: str = Depends(oauth2_scheme) +): + try: + # Valider et convertir la chaîne JSON en objet PersonReportCreate + report_data = PersonReportCreate.model_validate_json(report) + except ValidationError as e: + raise HTTPException(status_code=422, detail=f"Invalid report data: {e}") -@router.put("/{report_id}", response_model=PersonReportResponse) + # Appeler le service pour traiter le rapport + try: + created_report = await PersonReportService.create_report(report_data, db, image_file, token) + except Exception as e: + raise HTTPException(status_code=500, detail=f"An error occurred while creating the report: {str(e)}") + + return created_report + +@router.put("/{report_id}") async def update_report(report_id: int, report: PersonReportUpdate, db=Depends(get_db)): return await PersonReportService.update_report(report_id, report, db) -@router.get("/{report_id}", response_model=PersonReportResponse) +@router.get("/{report_id}") async def get_report(report_id: int, db=Depends(get_db)): return await PersonReportService.get_report(report_id, db) diff --git a/models/schemas.py b/models/schemas.py index 41886e2..5126750 100644 --- a/models/schemas.py +++ b/models/schemas.py @@ -30,16 +30,8 @@ class UserBase(BaseModel): class UserCreate(UserBase): password: str - role: Role - - # Validation au niveau du modèle - @model_validator(mode="before") - def convert_role_to_dict(cls, values): - role = values.get("role") - if isinstance(role, str): - values["role"] = {"id": 0, "name": role, "permissions": []} - return values - + role: str + class UserResponse(BaseModel): email: EmailStr full_name: str diff --git a/services/auth_service.py b/services/auth_service.py index 2c03d05..a8e1406 100644 --- a/services/auth_service.py +++ b/services/auth_service.py @@ -26,15 +26,13 @@ class AuthService: @staticmethod def verify_password(plain_password: str, hashed_password: str) -> bool: passEncr = pwd_context.hash(plain_password) - passEncrTest123Azerty = pwd_context.hash("123Azerty") - logger.info("password 123Azerty encrypted : " +passEncrTest123Azerty) - passEncrTestAzerty = pwd_context.hash("Azerty") - logger.info("password Azerty encrypted : " +passEncrTestAzerty) - logger.info("password en clair : " +plain_password) - logger.info("password encrypted : " +passEncr) - logger.info("password hashed : "+ hashed_password) - logger.info("verification plain_password & hashed_password : "+ str(pwd_context.verify(plain_password, hashed_password))) - logger.info("verification plain_password & 123Azerty encrypted : "+ str(pwd_context.verify(plain_password, passEncrTest123Azerty))) + passEncrTest123Azerty = pwd_context.hash("123Azerty+@") + logger.info("password 123Azerty+@ encrypted : " +passEncrTest123Azerty) + logger.info("password input : " +plain_password) + logger.info("password input and encrypted : " +passEncr) + logger.info("password hashed (in BDD) : "+ hashed_password) + logger.info("verification plain_password & hashed_password (in BDD) : "+ str(pwd_context.verify(plain_password, hashed_password))) + logger.info("verification plain_password & 123Azerty+@ encrypted : "+ str(pwd_context.verify(plain_password, passEncrTest123Azerty))) return pwd_context.verify(plain_password, hashed_password) @staticmethod @@ -117,33 +115,39 @@ class AuthService: "is_deleted": user["is_deleted"], } - @staticmethod - async def create_user(user: UserCreate, db): - result = await db.execute(select(users_table)) - users = result.fetchall() - role = "admin" if len(users) == 0 else user.role + # @staticmethod + # async def create_user(user: UserCreate, db): + # result = await db.execute(select(users_table)) + # users = result.fetchall() + # role = "admin" if len(users) == 0 else user.role - hashed_password = AuthService.get_password_hash(user.password) - query = insert(users_table).values( - email=user.email, - full_name=user.full_name, - phone=user.phone, - date_of_birth=user.date_of_birth, - organization=user.organization, - hashed_password=hashed_password, - role=role - ) - try: - result = await db.execute(query) - await db.commit() - user_id = result.inserted_primary_key[0] - logger.info("user created", extra={"user_id": user_id, "email": user.email, "role": role}) - return {"id": user_id, "email": user.email, "role": role} - except Exception as e: - await db.rollback() - logger.error("could not create user", extra={"error": str(e)}) - raise HTTPException(status_code=500, detail=f"Could not create user: {str(e)}") - + # hashed_password = AuthService.get_password_hash(user.password) + # query = insert(users_table).values( + # email=user.email, + # full_name=user.full_name, + # phone=user.phone, + # date_of_birth=user.date_of_birth, + # organization=user.organization, + # hashed_password=hashed_password, + # role=role + # ) + # try: + # result = await db.execute(query) + # await db.commit() + # user_id = result.inserted_primary_key[0] + # logger.info("user created", extra={"user_id": user_id, "email": user.email, "role": role}) + # return {"id": user_id, "email": user.email, "role": role} + # except Exception as e: + # await db.rollback() + # logger.error("could not create user", extra={"error": str(e)}) + # raise HTTPException(status_code=500, detail=f"Could not create user: {str(e)}") + + @staticmethod + async def get_role_by_name(role_name: str, db: AsyncSession = Depends(get_db)): + query = select(roles_table).where(roles_table.c.name == role_name) + result = await db.execute(query) + role = result.mappings().first() + return role diff --git a/services/user_service.py b/services/user_service.py index 21d2cdc..ff22603 100644 --- a/services/user_service.py +++ b/services/user_service.py @@ -1,19 +1,21 @@ from sqlalchemy import select, update, insert from fastapi import Depends, HTTPException, status -from sqlalchemy.ext.asyncio import AsyncSession from models.schemas import UserCreate, UserResponse, UserUpdateRole, UserBlockBan from config.database import get_db from models.db import users_table from services.auth_service import AuthService from utils.security import get_password_hash from typing import Optional +from utils.logging import logger + + class UserService: @staticmethod async def list_users(token: str, status: Optional[str] = None, db=Depends(get_db)): - await AuthService.check_permissions(token, ["admin"], db) + await AuthService.check_permissions(token, db, ["admin","collectivité","état"] ) query = select(users_table) if status: @@ -24,29 +26,40 @@ class UserService: @staticmethod async def create_user(user: UserCreate, db): - hashed_password = get_password_hash(user.password) - query = users_table.insert().values( + + role = await AuthService.get_role_by_name(user.role, db) + if not role: + raise HTTPException(status_code=400, detail=f"Role '{user.role}' does not exist.") + + result = await db.execute(select(users_table)) + users = result.fetchall() + role = "admin" if len(users) == 0 else user.role + + hashed_password = AuthService.get_password_hash(user.password) + query = insert(users_table).values( email=user.email, full_name=user.full_name, phone=user.phone, date_of_birth=user.date_of_birth, organization=user.organization, hashed_password=hashed_password, - role=user.role, # Par défaut, rôle "user" - is_active=True, - is_banned=False + role=role ) try: - await db.execute(query) + result = await db.execute(query) await db.commit() - return {"message": "User created successfully"} + user_id = result.inserted_primary_key[0] + logger.info("user created", extra={"user_id": user_id, "email": user.email, "role": role}) + return {"id": user_id, "email": user.email, "role": role} except Exception as e: await db.rollback() - raise HTTPException(status_code=500, detail=f"Error creating user: {str(e)}") + logger.error("could not create user", extra={"error": str(e)}) + raise HTTPException(status_code=500, detail=f"Could not create user: {str(e)}") + @staticmethod async def change_user_role(user_update: UserUpdateRole, db, token: str): - await AuthService.check_permissions(token, ["admin"], db) + await AuthService.check_permissions(token, db, ["admin"]) query = ( update(users_table)