MukeshKapoor25's picture
Implement structured logging system across AUTH Microservice
755d6cd
"""
Internal API endpoints for system user creation.
These endpoints are used by other microservices (SCM, POS) to create system users.
"""
import secrets
from fastapi import APIRouter, Depends, HTTPException, status
from app.system_users.services.service import SystemUserService
from app.system_users.schemas.schema import CreateUserRequest, UserInfoResponse
from app.dependencies.auth import get_system_user_service
from app.internal.schemas import CreateUserFromEmployeeRequest, CreateUserFromMerchantRequest
from app.core.logging import get_logger
logger = get_logger(__name__)
router = APIRouter(prefix="/internal/system-users", tags=["internal"])
@router.post("/from-employee", response_model=UserInfoResponse)
async def create_user_from_employee(
request: CreateUserFromEmployeeRequest,
user_service: SystemUserService = Depends(get_system_user_service)
):
"""
Create a system user from employee data.
This endpoint is used by SCM service when creating employees with system access.
Raises:
HTTPException: 400 - Invalid data or missing required fields
HTTPException: 500 - Database or server error
"""
try:
# Validate required fields
if not request.employee_id or not request.employee_id.strip():
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Employee ID is required"
)
if not request.email or not request.email.strip():
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Email is required"
)
if not request.first_name or not request.first_name.strip():
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="First name is required"
)
if not request.merchant_id or not request.merchant_id.strip():
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Merchant ID is required"
)
if not request.role_id or not request.role_id.strip():
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Role ID is required"
)
# Generate username if not provided
username = request.username
if not username:
# Generate from first name and last name
base_username = f"{request.first_name.lower()}"
if request.last_name:
base_username += f"_{request.last_name.lower()}"
username = base_username.replace(" ", "_").replace("-", "_")
# Generate password if not provided
password = request.password
if not password:
password = f"Temp@{secrets.token_urlsafe(8)}"
# Prepare metadata
metadata = request.metadata or {}
metadata.update({
"employee_id": request.employee_id,
"created_from": "employee",
"created_via": "internal_api"
})
# Create user request
create_request = CreateUserRequest(
username=username,
email=request.email,
merchant_id=request.merchant_id,
merchant_type=request.merchant_type,
password=password,
first_name=request.first_name,
last_name=request.last_name,
phone=request.phone,
role=request.role_id,
metadata=metadata
)
# Create user
try:
created_user = await user_service.create_user(create_request, "system_internal")
except HTTPException as http_exc:
# Re-raise HTTPException with more context
logger.error(f"Failed to create user from employee {request.employee_id}: {http_exc.detail}")
raise
except Exception as create_error:
logger.error(f"Unexpected error creating user from employee {request.employee_id}: {create_error}", exc_info=True)
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="Failed to create user from employee"
)
logger.info(
f"Created system user from employee",
extra={
"employee_id": request.employee_id,
"user_id": created_user.user_id,
"username": username,
"merchant_id": request.merchant_id,
"merchant_type": request.merchant_type
}
)
return user_service.convert_to_user_info_response(created_user)
except HTTPException:
raise
except ValueError as e:
logger.error(f"Validation error creating user from employee {request.employee_id}: {e}")
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=str(e)
)
except Exception as e:
logger.error(f"Unexpected error creating user from employee: {str(e)}", exc_info=True)
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="An unexpected error occurred while creating user from employee"
)
@router.post("/from-merchant", response_model=UserInfoResponse)
async def create_user_from_merchant(
request: CreateUserFromMerchantRequest,
user_service: SystemUserService = Depends(get_system_user_service)
):
"""
Create a system user from merchant data.
This endpoint is used by SCM service when creating merchants with system access.
Raises:
HTTPException: 400 - Invalid data or missing required fields
HTTPException: 500 - Database or server error
"""
try:
# Validate required fields
if not request.merchant_id or not request.merchant_id.strip():
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Merchant ID is required"
)
if not request.email or not request.email.strip():
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Email is required"
)
if not request.merchant_name or not request.merchant_name.strip():
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Merchant name is required"
)
if not request.merchant_type or not request.merchant_type.strip():
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Merchant type is required"
)
if not request.role_id or not request.role_id.strip():
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Role ID is required"
)
# Validate email format
if "@" not in request.email:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Invalid email format"
)
# Generate username if not provided
username = request.username
if not username:
# Generate from email (part before @)
username = request.email.split('@')[0].lower().replace(".", "_").replace("-", "_")
# Generate password if not provided
password = request.password
if not password:
password = "Welcome@1234" # Default merchant password
# Prepare metadata
metadata = request.metadata or {}
metadata.update({
"merchant_id": request.merchant_id,
"merchant_type": request.merchant_type,
"created_from": "merchant",
"created_via": "internal_api"
})
# Parse merchant name for first and last names
name_parts = request.merchant_name.split()
first_name = name_parts[0] if name_parts else "Merchant"
last_name = " ".join(name_parts[1:]) if len(name_parts) > 1 else "User"
# Create user request
create_request = CreateUserRequest(
username=username,
email=request.email,
merchant_id=request.merchant_id,
merchant_type=request.merchant_type,
password=password,
first_name=first_name,
last_name=last_name,
phone=request.phone,
role=request.role_id,
metadata=metadata
)
# Create user
try:
created_user = await user_service.create_user(create_request, "system_internal")
except HTTPException as http_exc:
# Re-raise HTTPException with more context
logger.error(f"Failed to create user from merchant {request.merchant_id}: {http_exc.detail}")
raise
except Exception as create_error:
logger.error(f"Unexpected error creating user from merchant {request.merchant_id}: {create_error}", exc_info=True)
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="Failed to create user from merchant"
)
logger.info(
f"Created system user from merchant",
extra={
"merchant_id": request.merchant_id,
"merchant_type": request.merchant_type,
"user_id": created_user.user_id,
"username": username
}
)
return user_service.convert_to_user_info_response(created_user)
except HTTPException:
raise
except ValueError as e:
logger.error(f"Validation error creating user from merchant {request.merchant_id}: {e}")
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=str(e)
)
except Exception as e:
logger.error(f"Unexpected error creating user from merchant: {str(e)}", exc_info=True)
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="An unexpected error occurred while creating user from merchant"
)