Files
LeDiscord/backend/api/routers/settings.py
2025-08-27 18:34:38 +02:00

310 lines
11 KiB
Python
Executable File

from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.orm import Session
from typing import List, Dict, Any
from datetime import datetime
from config.database import get_db
from models.settings import SystemSettings
from models.user import User
from schemas.settings import (
SystemSettingCreate,
SystemSettingUpdate,
SystemSettingResponse,
SettingsCategoryResponse,
UploadLimitsResponse
)
from utils.security import get_admin_user
router = APIRouter()
@router.get("/", response_model=List[SystemSettingResponse])
async def get_all_settings(
db: Session = Depends(get_db),
current_user: User = Depends(get_admin_user)
):
"""Get all system settings (admin only)."""
settings = db.query(SystemSettings).order_by(SystemSettings.category, SystemSettings.key).all()
return settings
@router.get("/category/{category}", response_model=SettingsCategoryResponse)
async def get_settings_by_category(
category: str,
db: Session = Depends(get_db),
current_user: User = Depends(get_admin_user)
):
"""Get settings by category (admin only)."""
settings = db.query(SystemSettings).filter(SystemSettings.category == category).all()
return SettingsCategoryResponse(category=category, settings=settings)
@router.get("/upload-limits", response_model=UploadLimitsResponse)
async def get_upload_limits(
db: Session = Depends(get_db),
current_user: User = Depends(get_admin_user)
):
"""Get current upload limits configuration (admin only)."""
settings = db.query(SystemSettings).filter(
SystemSettings.category == "uploads"
).all()
# Convertir en dictionnaire pour faciliter l'accès
settings_dict = {s.key: s.value for s in settings}
# Debug: afficher les valeurs récupérées
print(f"DEBUG - Upload limits from DB: {settings_dict}")
return UploadLimitsResponse(
max_album_size_mb=int(settings_dict.get("max_album_size_mb", "100")),
max_vlog_size_mb=int(settings_dict.get("max_vlog_size_mb", "500")),
max_image_size_mb=int(settings_dict.get("max_image_size_mb", "10")),
max_video_size_mb=int(settings_dict.get("max_video_size_mb", "100")),
max_media_per_album=int(settings_dict.get("max_media_per_album", "50")),
allowed_image_types=settings_dict.get("allowed_image_types", "image/jpeg,image/png,image/gif,image/webp").split(","),
allowed_video_types=settings_dict.get("allowed_video_types", "video/mp4,video/mpeg,video/quicktime,video/webm").split(",")
)
@router.get("/public/upload-limits", response_model=UploadLimitsResponse)
async def get_public_upload_limits(
db: Session = Depends(get_db)
):
"""Get current upload limits configuration (public endpoint - no auth required)."""
settings = db.query(SystemSettings).filter(
SystemSettings.category == "uploads"
).all()
# Convertir en dictionnaire pour faciliter l'accès
settings_dict = {s.key: s.value for s in settings}
return UploadLimitsResponse(
max_album_size_mb=int(settings_dict.get("max_album_size_mb", "100")),
max_vlog_size_mb=int(settings_dict.get("max_vlog_size_mb", "500")),
max_image_size_mb=int(settings_dict.get("max_image_size_mb", "10")),
max_video_size_mb=int(settings_dict.get("max_video_size_mb", "100")),
max_media_per_album=int(settings_dict.get("max_media_per_album", "50")),
allowed_image_types=settings_dict.get("allowed_image_types", "image/jpeg,image/png,image/gif,image/webp").split(","),
allowed_video_types=settings_dict.get("allowed_video_types", "video/mp4,video/mpeg,video/quicktime,video/webm").split(",")
)
@router.post("/", response_model=SystemSettingResponse)
async def create_setting(
setting_data: SystemSettingCreate,
db: Session = Depends(get_db),
current_user: User = Depends(get_admin_user)
):
"""Create a new system setting (admin only)."""
# Vérifier si la clé existe déjà
existing = db.query(SystemSettings).filter(SystemSettings.key == setting_data.key).first()
if existing:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Setting key already exists"
)
setting = SystemSettings(**setting_data.dict())
db.add(setting)
db.commit()
db.refresh(setting)
return setting
@router.put("/{setting_key}", response_model=SystemSettingResponse)
async def update_setting(
setting_key: str,
setting_update: SystemSettingUpdate,
db: Session = Depends(get_db),
current_user: User = Depends(get_admin_user)
):
"""Update a system setting (admin only)."""
setting = db.query(SystemSettings).filter(SystemSettings.key == setting_key).first()
if not setting:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Setting not found"
)
if not setting.is_editable:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="This setting cannot be modified"
)
# Validation des valeurs selon le type de paramètre
if setting_key.startswith("max_") and setting_key.endswith("_mb"):
try:
size_mb = int(setting_update.value)
if size_mb <= 0 or size_mb > 10000: # Max 10GB
raise ValueError("Size must be between 1 and 10000 MB")
except ValueError as e:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=f"Invalid size value: {str(e)}"
)
setting.value = setting_update.value
setting.updated_at = datetime.utcnow()
db.commit()
db.refresh(setting)
return setting
@router.delete("/{setting_key}")
async def delete_setting(
setting_key: str,
db: Session = Depends(get_db),
current_user: User = Depends(get_admin_user)
):
"""Delete a system setting (admin only)."""
setting = db.query(SystemSettings).filter(SystemSettings.key == setting_key).first()
if not setting:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Setting not found"
)
if not setting.is_editable:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="This setting cannot be deleted"
)
db.delete(setting)
db.commit()
return {"message": "Setting deleted successfully"}
@router.get("/test-upload-limits")
async def test_upload_limits(
db: Session = Depends(get_db),
current_user: User = Depends(get_admin_user)
):
"""Test endpoint to verify upload limits are working correctly."""
from utils.settings_service import SettingsService
# Test image upload limit
image_limit = SettingsService.get_max_upload_size(db, "image/jpeg")
image_limit_mb = image_limit // (1024 * 1024)
# Test video upload limit
video_limit = SettingsService.get_max_upload_size(db, "video/mp4")
video_limit_mb = video_limit // (1024 * 1024)
# Test file type validation
image_allowed = SettingsService.is_file_type_allowed(db, "image/jpeg")
video_allowed = SettingsService.is_file_type_allowed(db, "video/mp4")
invalid_allowed = SettingsService.is_file_type_allowed(db, "application/pdf")
return {
"image_upload_limit": {
"bytes": image_limit,
"mb": image_limit_mb,
"content_type": "image/jpeg"
},
"video_upload_limit": {
"bytes": video_limit,
"mb": video_limit_mb,
"content_type": "video/mp4"
},
"file_type_validation": {
"image_jpeg_allowed": image_allowed,
"video_mp4_allowed": video_allowed,
"pdf_not_allowed": not invalid_allowed
},
"message": "Upload limits test completed"
}
@router.get("/public/registration-status")
async def get_public_registration_status(
db: Session = Depends(get_db)
):
"""Get registration status without authentication (public endpoint)."""
from utils.settings_service import SettingsService
try:
enable_registration = SettingsService.get_setting(db, "enable_registration", True)
max_users = SettingsService.get_setting(db, "max_users", 50)
current_users_count = db.query(User).count()
return {
"registration_enabled": enable_registration,
"max_users": max_users,
"current_users_count": current_users_count,
"can_register": enable_registration and current_users_count < max_users
}
except Exception as e:
# En cas d'erreur, on retourne des valeurs par défaut sécurisées
return {
"registration_enabled": False,
"max_users": 50,
"current_users_count": 0,
"can_register": False
}
@router.post("/initialize-defaults")
async def initialize_default_settings(
db: Session = Depends(get_db),
current_user: User = Depends(get_admin_user)
):
"""Initialize default system settings (admin only)."""
default_settings = [
{
"key": "max_album_size_mb",
"value": "100",
"description": "Taille maximale des albums en MB",
"category": "uploads"
},
{
"key": "max_vlog_size_mb",
"value": "500",
"description": "Taille maximale des vlogs en MB",
"category": "uploads"
},
{
"key": "max_image_size_mb",
"value": "10",
"description": "Taille maximale des images en MB",
"category": "uploads"
},
{
"key": "max_video_size_mb",
"value": "100",
"description": "Taille maximale des vidéos en MB",
"category": "uploads"
},
{
"key": "max_media_per_album",
"value": "50",
"description": "Nombre maximum de médias par album",
"category": "uploads"
},
{
"key": "allowed_image_types",
"value": "image/jpeg,image/png,image/gif,image/webp",
"description": "Types d'images autorisés (séparés par des virgules)",
"category": "uploads"
},
{
"key": "allowed_video_types",
"value": "video/mp4,video/mpeg,video/quicktime,video/webm",
"description": "Types de vidéos autorisés (séparés par des virgules)",
"category": "uploads"
},
{
"key": "max_users",
"value": "50",
"description": "Nombre maximum d'utilisateurs",
"category": "general"
},
{
"key": "enable_registration",
"value": "true",
"description": "Autoriser les nouvelles inscriptions",
"category": "general"
}
]
created_count = 0
for setting_data in default_settings:
existing = db.query(SystemSettings).filter(SystemSettings.key == setting_data["key"]).first()
if not existing:
setting = SystemSettings(**setting_data)
db.add(setting)
created_count += 1
db.commit()
return {"message": f"{created_count} default settings created"}