from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy.orm import Session from typing import List import ulid from app.core.database.db_session import get_db from app.repositories.setting_repository import setting_repository from app.models.SettingModel import Setting from app.schemas.Settings import SettingCreate, SettingUpdate, SettingResponse from app.models.UserModel import User from app.core.permissions.RoleChecker import get_current_user, PermissionChecker router = APIRouter(prefix="/api/v1/settings", tags=["Configuration Settings"]) @router.post("/create", response_model=SettingResponse, status_code=status.HTTP_201_CREATED) def create_setting( data: SettingCreate, db: Session = Depends(get_db), current_user: User = Depends(PermissionChecker("settings.create")) ): existing = setting_repository.get_by_key(db, data.setting_key) if existing: raise HTTPException(status_code=400, detail="Setting key already exists.") setting_id = str(ulid.ULID()) new_setting = Setting( setting_id=setting_id, setting_key=data.setting_key, setting_value=data.setting_value, description=data.description, is_public=data.is_public ) setting_repository.create(db, new_setting) return new_setting @router.get("/key/{key_name}", response_model=SettingResponse) def get_setting_by_key( key_name: str, db: Session = Depends(get_db), current_user: User = Depends(get_current_user) ): setting = setting_repository.get_by_key(db, key_name) if not setting: raise HTTPException(status_code=404, detail="Setting not found") # Restrict private settings to admin/system users if not setting.is_public and current_user.role.role_name.lower() not in ["admin", "super admin"] and current_user.user_id != "internal-mcp": raise HTTPException(status_code=403, detail="Access denied to private settings") return setting @router.get("/public", response_model=List[SettingResponse]) def get_public_settings( db: Session = Depends(get_db) ): return setting_repository.get_public_settings(db) @router.put("/update/{key_name}", response_model=SettingResponse) def update_setting( key_name: str, payload: SettingUpdate, db: Session = Depends(get_db), current_user: User = Depends(PermissionChecker("settings.update")) ): setting = setting_repository.get_by_key(db, key_name) if not setting: raise HTTPException(status_code=404, detail="Setting not found") setting.setting_value = payload.setting_value if payload.description is not None: setting.description = payload.description if payload.is_public is not None: setting.is_public = payload.is_public setting_repository.update(db, setting) return setting @router.post("/save/{key_name}", response_model=SettingResponse) def save_setting( key_name: str, payload: SettingUpdate, db: Session = Depends(get_db), current_user: User = Depends(get_current_user) ): setting = setting_repository.get_by_key(db, key_name) if not setting: setting_id = str(ulid.ULID()) setting = Setting( setting_id=setting_id, setting_key=key_name, group="invoice_branding" if "branding" in key_name else "storefront", setting_value=payload.setting_value, description=payload.description or f"Setting for {key_name}", is_public=payload.is_public if payload.is_public is not None else True ) setting_repository.create(db, setting) else: setting.setting_value = payload.setting_value if payload.description is not None: setting.description = payload.description if payload.is_public is not None: setting.is_public = payload.is_public setting_repository.update(db, setting) return setting