145 lines
4.9 KiB
Python
145 lines
4.9 KiB
Python
from sqlalchemy.orm import Session
|
|
from sqlalchemy import or_, cast, String
|
|
from fastapi import HTTPException, status
|
|
from datetime import datetime
|
|
import uuid
|
|
from typing import Optional
|
|
from app.models.auth.user_model import User
|
|
from app.schemas.auth.user_schema import UserCreate, UserUpdate, UserResponse, UserPaginatedResponse
|
|
from app.config.security import security
|
|
|
|
class UserService:
|
|
|
|
@staticmethod
|
|
def create_user(db: Session, user_data: UserCreate, tenant_id: uuid.UUID = None) -> User:
|
|
if db.query(User).filter(User.email == user_data.email).first():
|
|
raise HTTPException(
|
|
status_code=status.HTTP_400_BAD_REQUEST,
|
|
detail="Email already registered"
|
|
)
|
|
|
|
if not security.validate_password_strength(user_data.password):
|
|
raise HTTPException(
|
|
status_code=status.HTTP_400_BAD_REQUEST,
|
|
detail="Password too weak"
|
|
)
|
|
|
|
user = User(
|
|
email=user_data.email,
|
|
password=security.hash_password(user_data.password),
|
|
first_name=user_data.first_name,
|
|
last_name=user_data.last_name,
|
|
phone_number=user_data.phone_number,
|
|
status=user_data.status or "active",
|
|
tenant_id=tenant_id,
|
|
role_id=user_data.role_id
|
|
)
|
|
|
|
db.add(user)
|
|
db.commit()
|
|
db.refresh(user)
|
|
return user
|
|
|
|
@staticmethod
|
|
def get_all_users(db: Session, tenant_id: uuid.UUID = None):
|
|
query = db.query(User)
|
|
if tenant_id:
|
|
query = query.filter(User.tenant_id == tenant_id)
|
|
return query.all()
|
|
|
|
@staticmethod
|
|
def get_user_by_id(db: Session, user_id: uuid.UUID, tenant_id: uuid.UUID = None) -> User:
|
|
query = db.query(User).filter(User.id == user_id)
|
|
if tenant_id:
|
|
query = query.filter(User.tenant_id == tenant_id)
|
|
user = query.first()
|
|
if not user:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail="User not found"
|
|
)
|
|
return user
|
|
|
|
@staticmethod
|
|
def update_user(db: Session, user_id: uuid.UUID, user_data: UserUpdate, tenant_id: uuid.UUID = None) -> User:
|
|
user = UserService.get_user_by_id(db, user_id, tenant_id)
|
|
|
|
update_dict = user_data.model_dump(exclude_unset=True)
|
|
if tenant_id:
|
|
update_dict.pop("tenant_id", None)
|
|
|
|
if "email" in update_dict and update_dict["email"] != user.email:
|
|
if db.query(User).filter(User.email == update_dict["email"]).first():
|
|
raise HTTPException(
|
|
status_code=status.HTTP_400_BAD_REQUEST,
|
|
detail="Email already used"
|
|
)
|
|
|
|
password = update_dict.pop("password", None)
|
|
if password:
|
|
if not security.validate_password_strength(password):
|
|
raise HTTPException(
|
|
status_code=status.HTTP_400_BAD_REQUEST,
|
|
detail="Password too weak"
|
|
)
|
|
user.password = security.hash_password(password)
|
|
user.password_updated_at = datetime.utcnow()
|
|
|
|
for key, value in update_dict.items():
|
|
setattr(user, key, value)
|
|
|
|
db.commit()
|
|
db.refresh(user)
|
|
return user
|
|
|
|
@staticmethod
|
|
def delete_user(db: Session, user_id: uuid.UUID, tenant_id: uuid.UUID = None):
|
|
user = UserService.get_user_by_id(db, user_id, tenant_id)
|
|
db.delete(user)
|
|
db.commit()
|
|
return {"message": "User deleted successfully"}
|
|
|
|
@staticmethod
|
|
def get_users_paginated(
|
|
db: Session,
|
|
tenant_id: Optional[uuid.UUID] = None,
|
|
page: int = 1,
|
|
page_size: int = 10,
|
|
search: Optional[str] = None,
|
|
status: Optional[str] = None,
|
|
) -> UserPaginatedResponse:
|
|
|
|
query = db.query(User)
|
|
|
|
if tenant_id:
|
|
query = query.filter(User.tenant_id == tenant_id)
|
|
|
|
if search and search.strip():
|
|
search_term = search.strip()
|
|
query = query.filter(
|
|
or_(
|
|
User.email.ilike(f"%{search_term}%"),
|
|
User.first_name.ilike(f"%{search_term}%"),
|
|
User.last_name.ilike(f"%{search_term}%"),
|
|
User.phone_number.ilike(f"%{search_term}%"),
|
|
cast(User.id, String).ilike(f"%{search_term}%"),
|
|
)
|
|
)
|
|
|
|
if status is not None:
|
|
query = query.filter(User.status == status)
|
|
|
|
total = query.count()
|
|
|
|
offset = (page - 1) * page_size
|
|
users = query.offset(offset).limit(page_size).all()
|
|
|
|
total_pages = (total + page_size - 1) // page_size if total > 0 else 0
|
|
|
|
return UserPaginatedResponse(
|
|
items=[UserResponse.model_validate(user) for user in users],
|
|
total=total,
|
|
page=page,
|
|
page_size=page_size,
|
|
total_pages=total_pages,
|
|
) |