Files
2026-04-01 13:48:40 -07:00

188 lines
6.2 KiB
Python

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))