Files
MOHPortalTest-AllAgents-All…/qwen/python/merchants_of_hope/api/v1/users.py
2025-10-24 14:54:44 -05:00

145 lines
4.8 KiB
Python

"""
Users API routes
"""
from fastapi import APIRouter, Depends, HTTPException, status, Request
from typing import List
from pydantic import BaseModel
import hashlib
from sqlalchemy.orm import Session
from ..database import SessionLocal
from ..models import User, UserRole, Tenant
from ..config.settings import settings
router = APIRouter()
# Pydantic models for users
class UserCreate(BaseModel):
email: str
username: str
password: str
role: UserRole
class UserUpdate(BaseModel):
email: str = None
username: str = None
is_active: bool = None
class UserResponse(BaseModel):
id: int
email: str
username: str
role: str
is_active: bool
is_verified: bool
tenant_id: int
class Config:
from_attributes = True
def hash_password(password: str) -> str:
"""Hash password using SHA256 (in production, use bcrypt)"""
return hashlib.sha256(password.encode()).hexdigest()
@router.get("/", response_model=List[UserResponse])
async def get_users(skip: int = 0, limit: int = 100, db: Session = Depends(SessionLocal), request: Request = None):
"""Get all users for the current tenant"""
tenant_id = getattr(request.state, 'tenant_id', None)
if not tenant_id and settings.MULTI_TENANT_ENABLED:
raise HTTPException(status_code=400, detail="Tenant ID is required")
query = db.query(User)
if settings.MULTI_TENANT_ENABLED:
query = query.filter(User.tenant_id == tenant_id)
users = query.offset(skip).limit(limit).all()
return users
@router.get("/{user_id}", response_model=UserResponse)
async def get_user(user_id: int, db: Session = Depends(SessionLocal), request: Request = None):
"""Get a specific user"""
tenant_id = getattr(request.state, 'tenant_id', None)
if not tenant_id and settings.MULTI_TENANT_ENABLED:
raise HTTPException(status_code=400, detail="Tenant ID is required")
query = db.query(User).filter(User.id == user_id)
if settings.MULTI_TENANT_ENABLED:
query = query.filter(User.tenant_id == tenant_id)
user = query.first()
if not user:
raise HTTPException(status_code=404, detail="User not found")
return user
@router.post("/", response_model=UserResponse)
async def create_user(user: UserCreate, db: Session = Depends(SessionLocal), request: Request = None):
"""Create a new user"""
tenant_id = getattr(request.state, 'tenant_id', None)
if not tenant_id and settings.MULTI_TENANT_ENABLED:
raise HTTPException(status_code=400, detail="Tenant ID is required")
# Check if user already exists
existing_user = db.query(User).filter(
(User.email == user.email) | (User.username == user.username)
).first()
if existing_user:
raise HTTPException(status_code=400, detail="Email or username already registered")
# Create new user
hashed_pwd = hash_password(user.password)
db_user = User(
email=user.email,
username=user.username,
hashed_password=hashed_pwd,
role=user.role.value,
tenant_id=tenant_id # Use the current tenant
)
db.add(db_user)
db.commit()
db.refresh(db_user)
return db_user
@router.put("/{user_id}", response_model=UserResponse)
async def update_user(user_id: int, user_update: UserUpdate, db: Session = Depends(SessionLocal), request: Request = None):
"""Update a user"""
tenant_id = getattr(request.state, 'tenant_id', None)
if not tenant_id and settings.MULTI_TENANT_ENABLED:
raise HTTPException(status_code=400, detail="Tenant ID is required")
db_user = db.query(User).filter(
User.id == user_id,
User.tenant_id == tenant_id # Ensure user belongs to current tenant
).first()
if not db_user:
raise HTTPException(status_code=404, detail="User not found")
# Update fields if provided
if user_update.email is not None:
db_user.email = user_update.email
if user_update.username is not None:
db_user.username = user_update.username
if user_update.is_active is not None:
db_user.is_active = user_update.is_active
db.commit()
db.refresh(db_user)
return db_user
@router.delete("/{user_id}")
async def delete_user(user_id: int, db: Session = Depends(SessionLocal), request: Request = None):
"""Delete a user"""
tenant_id = getattr(request.state, 'tenant_id', None)
if not tenant_id and settings.MULTI_TENANT_ENABLED:
raise HTTPException(status_code=400, detail="Tenant ID is required")
db_user = db.query(User).filter(
User.id == user_id,
User.tenant_id == tenant_id # Ensure user belongs to current tenant
).first()
if not db_user:
raise HTTPException(status_code=404, detail="User not found")
db.delete(db_user)
db.commit()
return {"message": "User deleted successfully"}