from fastapi import APIRouter, Depends, HTTPException, Query, Request, Header, status # from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer from sqlalchemy.orm import Session from typing import Optional, List # from database import get_db from app.core.auth import get_current_user from app.modules.users.models import Users # from app.modules.users.schema import UserCreate, UserResponse, UserLogin, LoginResponse, DeleteResponse, UpdateUser from app.modules.users.services import UserCrudService from app.core.security import create_access_token, verify_password router = APIRouter(prefix="/users", tags=["users"]) security = HTTPBearer() #================ Login ==================== @router.post("/login", response_model=LoginResponse) async def login( login_data: UserLogin, db: Session = Depends(get_db) ): """Authenticate user and return JWT token""" user = db.query(Users).filter(Users.email == login_data.email).first() #check email if not user: raise HTTPException( status_code = status.HTTP_401_UNAUTHORIZED, detail="Credentials invalid - user not found", headers={"WWW-Authenticate": "Bearer"}, ) #check password ... if not verify_password(login_data.password, user.password): raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid credentials = worng password", headers={"WWW-Athenticate": "Bearer"} ) #check is active if not user.is_active: raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail="This user is ianctive, contact with support" ) #update last login from datetime import datetime user.last_login = datetime.utcnow() db.commit() #create token token_data = { "sub": str(user.id), "email": user.email, "user_type": user.tipo_usuario, "rol_operativo": user.rol_operativo } access_token = create_access_token(token_data) return LoginResponse(access_token=access_token, token_type="bearer") #================ Register ==================== @router.post("/register", response_model=UserResponse) async def register(data: UserCreate, db: Session = Depends(get_db)): user_count = db.query(Users).count() if user_count == 0: service = UserCrudService() return UserCrudService.create_user(db = db, user_create=data, current_user=None) else: raise HTTPException( status_code=403, detail="Root user already exists, use create_users enpoint" ) #================ Create User ==================== @router.post("/create_users", response_model=UserResponse) async def new_user( data: UserCreate, db: Session = Depends(get_db), credentials: HTTPAuthorizationCredentials = Depends(security) ): """Create a new user - Requeres authentication """ from app.core.auth import AuthService token = credentials.credentials auth_service = AuthService() payload = auth_service.decode_token(token) user_id = int(payload.get("sub")) current_user = db.query(Users).filter(Users.id == user_id).first() if not current_user: raise HTTPException( status_code=401, detail="User not found - invalid token" ) if current_user.tipo_usuario not in ["root", "admin"]: raise HTTPException(status_code=403, detail="you dont have permission to create users") if current_user.tipo_usuario == "admin" and data.tipo_usuario != "user": raise HTTPException(status_code=403, detail="Admin can only create users type user") return UserCrudService.create_user( db = db, user_create = data, current_user = current_user ) #================ Get Users ==================== @router.get("/get", response_model=List[UserResponse]) def obtain_users( db: Session = Depends(get_db), current_user: Users = Depends(get_current_user), skip: int = Query(0, ge=0, description="Number of records to skip for pagination"), limit: int = Query(100, ge=1, le= 1000, description="Maximun number of records to return") ): """Get a list of user with pagination - requeres authentication""" return UserCrudService.get_users(db = db, skip=skip, limit=limit) #================ Delete Users ==================== @router.delete("/delete/{user_id}", response_model=DeleteResponse) async def delete( db:Session = Depends(get_db), user_id= int, current_user: Users = Depends(get_current_user) ): """Delete a user by id""" current_user = db.query(Users).filter(Users.id == user_id).first() if current_user.tipo_usuario not in ["root", "admin"]: raise HTTPException(status_code=403, detail="You dont have permitions to delete ") try: UserCrudService.delete_user(db = db, user_id=user_id, current_user=current_user) return {"message": "ok"} except ValueError as e: raise HTTPException(status_code=400, detail=str(e)) #================ Update Users ==================== @router.patch("/update/{user_id}", response_model=UserResponse) async def user_update( user_id: int, data: UpdateUser, db: Session = Depends(get_db), current_user: Users = Depends(get_current_user) ): """ Update existing user""" user = db.query(Users).filter(Users.id == user_id).first() current_user = db.query(Users).filter(Users.id == user_id).first() if not user: raise ValueError("Usuario no encontrado") if current_user.id != user_id: if current_user.tipo_usuario not in ["root", "admin"]: raise PermissionError("Admin only can update user ur enterprise") try: updated_user = await UserCrudService.Update_user(db=db, user_id=user_id, user_data=data, current_user=current_user) print(f"TIPO DE updated_user: {type(updated_user)}") print(f"VALOR: {updated_user}") print(f"ID: {updated_user.id if updated_user else 'None'}") return UserResponse.model_validate(updated_user) except ValueError as e: raise HTTPException(status_code=404, detail=str(e)) except PermissionError as e: raise HTTPException(status_code=403, detail=str(e))