from sqlalchemy import select, update, insert from fastapi import Depends, HTTPException, status 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, db, ["admin","collectivité","état"] ) query = select(users_table) if status: query = query.where(users_table.c.status == status) result = await db.execute(query) users = result.mappings().all() return [UserResponse(**user) for user in users] @staticmethod async def create_user(user: UserCreate, db): 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=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 change_user_role(user_update: UserUpdateRole, db, token: str): await AuthService.check_permissions(token, db, ["admin"]) query = ( update(users_table) .where(users_table.c.email == user_update.email) .values(role=user_update.new_role) ) result = await db.execute(query) await db.commit() if result.rowcount == 0: raise HTTPException(status_code=404, detail="User not found") return {"message": f"Role updated to {user_update.new_role}"} @staticmethod async def block_user(user_action: UserBlockBan, db, token: str): await AuthService.admin_required(token, db) query = ( update(users_table) .where(users_table.c.email == user_action.email) .values(is_blocked=True) ) result = await db.execute(query) await db.commit() if result.rowcount == 0: raise HTTPException(status_code=404, detail="User not found") return {"message": f"User {user_action.email} blocked"} @staticmethod async def ban_user(user_action: UserBlockBan, db, token: str): await AuthService.admin_required(token, db) query = ( update(users_table) .where(users_table.c.email == user_action.email) .values(is_banned=True) ) result = await db.execute(query) await db.commit() if result.rowcount == 0: raise HTTPException(status_code=404, detail="User not found") return {"message": f"User {user_action.email} banned"} @staticmethod async def unblock_user(user_action: UserBlockBan, db, token: str): await AuthService.admin_required(token, db) query = ( update(users_table) .where(users_table.c.email == user_action.email) .values(is_blocked=False) ) result = await db.execute(query) await db.commit() if result.rowcount == 0: raise HTTPException(status_code=404, detail="User not found") return {"message": f"User {user_action.email} unblocked"} @staticmethod async def unban_user(user_action: UserBlockBan, db, token: str): await AuthService.admin_required(token, db) query = ( update(users_table) .where(users_table.c.email == user_action.email) .values(is_banned=False) ) result = await db.execute(query) await db.commit() if result.rowcount == 0: raise HTTPException(status_code=404, detail="User not found") return {"message": f"User {user_action.email} unbanned"}