from fastapi import APIRouter, HTTPException, Depends, Body, Path, Request, Response from typing import List, Dict, Any, Optional from fastapi import status from datetime import datetime import logging import inspect import importlib import os from pydantic import BaseModel # Import interfaces and models import modules.interfaces.serviceManagementClass as serviceManagementClass from modules.security.auth import getCurrentUser, limiter, getCurrentUser # Import the attribute definition and helper functions from modules.interfaces.serviceManagementModel import User, AttributeDefinition, getModelAttributeDefinitions from modules.interfaces.serviceAppModel import AttributeDefinition as ServiceAppAttributeDefinition # Configure logger logger = logging.getLogger(__name__) router = APIRouter( prefix="/api/users", tags=["Manage Users"], responses={404: {"description": "Not found"}} ) @router.get("/", response_model=List[Dict[str, Any]], tags=["Users"]) async def get_users(currentUser: Dict[str, Any] = Depends(getCurrentUser)): """Get all users in the current mandate""" try: appInterface = serviceManagementClass.getInterface(currentUser) return appInterface.getUsers() except Exception as e: logger.error(f"Error getting users: {str(e)}") raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Failed to get users: {str(e)}" ) @router.get("/{userId}", response_model=Dict[str, Any], tags=["Users"]) async def get_user( userId: str, currentUser: Dict[str, Any] = Depends(getCurrentUser) ): """Get a specific user by ID""" try: appInterface = serviceManagementClass.getInterface(currentUser) user = appInterface.getUserById(userId) if not user: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail=f"User {userId} not found" ) return user except HTTPException: raise except Exception as e: logger.error(f"Error getting user {userId}: {str(e)}") raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Failed to get user: {str(e)}" ) @router.post("/", response_model=User, tags=["Users"]) async def create_user( userData: User, currentUser: Dict[str, Any] = Depends(getCurrentUser) ): """Create a new user""" try: # Get interface for user creation appInterface = serviceManagementClass.getInterface(currentUser) try: # Convert User model to dict and pass to createUser createdUser = appInterface.createUser( username=userData.username, email=userData.email, fullName=userData.fullName, language=userData.language, disabled=userData.disabled, privilege=userData.privilege, authenticationAuthority=userData.authenticationAuthority ) except ValueError as e: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail=str(e) ) if not createdUser: raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="Failed to create user" ) return createdUser except HTTPException: raise except Exception as e: logger.error(f"Error creating user: {str(e)}") raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Failed to create user: {str(e)}" ) @router.put("/{userId}", response_model=User, tags=["Users"]) async def update_user( userId: str, userData: User, currentUser: Dict[str, Any] = Depends(getCurrentUser) ): """Update an existing user""" try: # Get interface for user updates appInterface = serviceManagementClass.getInterface(currentUser) # Check if user exists existingUser = appInterface.getUserById(userId) if not existingUser: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail=f"User {userId} not found" ) # Update user data try: updatedUser = appInterface.updateUser(userId, userData) except ValueError as e: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail=str(e) ) if not updatedUser: raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="Failed to update user" ) return updatedUser except HTTPException: raise except Exception as e: logger.error(f"Error updating user {userId}: {str(e)}") raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Failed to update user: {str(e)}" ) @router.delete("/{userId}", response_model=Dict[str, Any], tags=["Users"]) async def delete_user( userId: str, currentUser: Dict[str, Any] = Depends(getCurrentUser) ): """Delete a user""" try: appInterface = serviceManagementClass.getInterface(currentUser) appInterface.deleteUser(userId) return {"message": f"User {userId} deleted successfully"} except ValueError as e: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail=str(e) ) except Exception as e: logger.error(f"Error deleting user {userId}: {str(e)}") raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Failed to delete user: {str(e)}" ) @router.get("/attributes", response_model=List[ServiceAppAttributeDefinition]) @limiter.limit("30/minute") async def get_user_attributes( currentUser: Dict[str, Any] = Depends(getCurrentUser) ): """ Retrieves the attribute definitions for users. This can be used for dynamic form generation. Returns: - A list of attribute definitions that can be used to generate forms """ # Get attributes from the User model class return User.getModelAttributeDefinitions()