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.""" 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.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"}