hesabixArc/hesabixAPI/adapters/api/v1/admin/email_config.py

350 lines
12 KiB
Python

from fastapi import APIRouter, Depends, HTTPException, Request
from sqlalchemy.orm import Session
from typing import List
from adapters.db.session import get_db
from adapters.db.models.email_config import EmailConfig
from adapters.db.repositories.email_config_repository import EmailConfigRepository
from adapters.api.v1.schema_models.email import (
EmailConfigCreate,
EmailConfigUpdate,
EmailConfigResponse,
SendEmailRequest,
TestConnectionRequest
)
from adapters.api.v1.schemas import SuccessResponse
from app.core.responses import success_response, format_datetime_fields
from app.core.permissions import require_app_permission
from app.core.auth_dependency import get_current_user, AuthContext
from app.core.i18n import gettext, negotiate_locale
router = APIRouter(prefix="/admin/email", tags=["Email Configuration"])
@router.get("/configs", response_model=SuccessResponse)
@require_app_permission("superadmin")
async def get_email_configs(
request: Request,
db: Session = Depends(get_db),
ctx: AuthContext = Depends(get_current_user)
):
"""Get all email configurations"""
try:
email_repo = EmailConfigRepository(db)
configs = email_repo.get_all_configs()
config_responses = [
EmailConfigResponse.model_validate(config) for config in configs
]
# Format datetime fields based on calendar type
formatted_data = format_datetime_fields(config_responses, request)
return success_response(
data=formatted_data,
request=request
)
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@router.get("/configs/{config_id}", response_model=SuccessResponse)
@require_app_permission("superadmin")
async def get_email_config(
config_id: int,
request: Request,
db: Session = Depends(get_db),
ctx: AuthContext = Depends(get_current_user)
):
"""Get specific email configuration"""
try:
email_repo = EmailConfigRepository(db)
config = email_repo.get_by_id(config_id)
if not config:
locale = negotiate_locale(request.headers.get("Accept-Language"))
raise HTTPException(status_code=404, detail=gettext("Email configuration not found", locale))
config_response = EmailConfigResponse.model_validate(config)
# Format datetime fields based on calendar type
formatted_data = format_datetime_fields(config_response.model_dump(), request)
return success_response(
data=formatted_data,
request=request
)
except HTTPException:
raise
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@router.post("/configs", response_model=SuccessResponse)
@require_app_permission("superadmin")
async def create_email_config(
request_data: EmailConfigCreate,
request: Request,
db: Session = Depends(get_db),
ctx: AuthContext = Depends(get_current_user)
):
"""Create new email configuration"""
try:
email_repo = EmailConfigRepository(db)
# Get locale from request
locale = negotiate_locale(request.headers.get("Accept-Language"))
# Check if name already exists
existing_config = email_repo.get_by_name(request_data.name)
if existing_config:
raise HTTPException(status_code=400, detail=gettext("Configuration name already exists", locale))
# Create new config
config = EmailConfig(**request_data.model_dump())
email_repo.db.add(config)
email_repo.db.commit()
email_repo.db.refresh(config)
# If this is the first config, set it as default
if not email_repo.get_default_config():
email_repo.set_default_config(config.id)
config_response = EmailConfigResponse.model_validate(config)
# Format datetime fields based on calendar type
formatted_data = format_datetime_fields(config_response.model_dump(), request)
return success_response(
data=formatted_data,
request=request
)
except HTTPException:
raise
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@router.put("/configs/{config_id}", response_model=SuccessResponse)
@require_app_permission("superadmin")
async def update_email_config(
config_id: int,
request_data: EmailConfigUpdate,
request: Request,
db: Session = Depends(get_db),
ctx: AuthContext = Depends(get_current_user)
):
"""Update email configuration"""
try:
email_repo = EmailConfigRepository(db)
config = email_repo.get_by_id(config_id)
# Get locale from request
locale = negotiate_locale(request.headers.get("Accept-Language"))
if not config:
raise HTTPException(status_code=404, detail=gettext("Email configuration not found", locale))
# Check name uniqueness if name is being updated
if request_data.name and request_data.name != config.name:
existing_config = email_repo.get_by_name(request_data.name)
if existing_config:
raise HTTPException(status_code=400, detail=gettext("Configuration name already exists", locale))
# Update config
update_data = request_data.model_dump(exclude_unset=True)
# Prevent changing is_default through update - use set-default endpoint instead
if 'is_default' in update_data:
del update_data['is_default']
for field, value in update_data.items():
setattr(config, field, value)
email_repo.update(config)
config_response = EmailConfigResponse.model_validate(config)
# Format datetime fields based on calendar type
formatted_data = format_datetime_fields(config_response.model_dump(), request)
return success_response(
data=formatted_data,
request=request
)
except HTTPException:
raise
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@router.delete("/configs/{config_id}", response_model=SuccessResponse)
@require_app_permission("superadmin")
async def delete_email_config(
config_id: int,
request: Request,
db: Session = Depends(get_db),
ctx: AuthContext = Depends(get_current_user)
):
"""Delete email configuration"""
try:
email_repo = EmailConfigRepository(db)
config = email_repo.get_by_id(config_id)
# Get locale from request
locale = negotiate_locale(request.headers.get("Accept-Language"))
if not config:
raise HTTPException(status_code=404, detail=gettext("Email configuration not found", locale))
# Prevent deletion of default config
if config.is_default:
raise HTTPException(status_code=400, detail=gettext("Cannot delete default configuration", locale))
email_repo.delete(config)
return success_response(
data=None,
request=request
)
except HTTPException:
raise
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@router.post("/configs/{config_id}/test", response_model=SuccessResponse)
@require_app_permission("superadmin")
async def test_email_config(
config_id: int,
request: Request,
db: Session = Depends(get_db),
ctx: AuthContext = Depends(get_current_user)
):
"""Test email configuration connection"""
try:
email_repo = EmailConfigRepository(db)
config = email_repo.get_by_id(config_id)
# Get locale from request
locale = negotiate_locale(request.headers.get("Accept-Language"))
if not config:
raise HTTPException(status_code=404, detail=gettext("Email configuration not found", locale))
is_connected = email_repo.test_connection(config)
return success_response(
data={"connected": is_connected},
request=request
)
except HTTPException:
raise
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@router.post("/configs/{config_id}/activate", response_model=SuccessResponse)
@require_app_permission("superadmin")
async def activate_email_config(
config_id: int,
request: Request,
db: Session = Depends(get_db),
ctx: AuthContext = Depends(get_current_user)
):
"""Activate email configuration"""
try:
email_repo = EmailConfigRepository(db)
config = email_repo.get_by_id(config_id)
# Get locale from request
locale = negotiate_locale(request.headers.get("Accept-Language"))
if not config:
raise HTTPException(status_code=404, detail=gettext("Email configuration not found", locale))
success = email_repo.set_active_config(config_id)
if not success:
raise HTTPException(status_code=500, detail=gettext("Failed to activate configuration", locale))
return success_response(
data=None,
request=request
)
except HTTPException:
raise
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@router.post("/configs/{config_id}/set-default", response_model=SuccessResponse)
@require_app_permission("superadmin")
async def set_default_email_config(
config_id: int,
request: Request,
db: Session = Depends(get_db),
ctx: AuthContext = Depends(get_current_user)
):
"""Set email configuration as default"""
try:
email_repo = EmailConfigRepository(db)
config = email_repo.get_by_id(config_id)
# Get locale from request
locale = negotiate_locale(request.headers.get("Accept-Language"))
if not config:
raise HTTPException(status_code=404, detail=gettext("Email configuration not found", locale))
success = email_repo.set_default_config(config_id)
if not success:
raise HTTPException(status_code=500, detail=gettext("Failed to set default configuration", locale))
return success_response(
data=None,
request=request
)
except HTTPException:
raise
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@router.post("/send", response_model=SuccessResponse)
@require_app_permission("superadmin")
async def send_email(
request_data: SendEmailRequest,
request: Request,
db: Session = Depends(get_db),
ctx: AuthContext = Depends(get_current_user)
):
"""Send email using configured SMTP"""
try:
from app.services.email_service import EmailService
email_service = EmailService(db)
success = email_service.send_email(
to=request_data.to,
subject=request_data.subject,
body=request_data.body,
html_body=request_data.html_body,
config_id=request_data.config_id
)
# Get locale from request
locale = negotiate_locale(request.headers.get("Accept-Language"))
if not success:
raise HTTPException(status_code=500, detail=gettext("Failed to send email", locale))
return success_response(
data={"sent": True},
request=request
)
except HTTPException:
raise
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))