114 lines
3.3 KiB
Python
114 lines
3.3 KiB
Python
"""System configuration API — read/write all settings from the database.
|
|
|
|
There is no .env file. Every setting lives in the ``system_config`` table
|
|
(singleton row with id=1) and is editable via the Web UI settings page.
|
|
"""
|
|
|
|
import logging
|
|
from datetime import datetime
|
|
|
|
from fastapi import APIRouter, Depends, HTTPException, status
|
|
from sqlalchemy.orm import Session
|
|
|
|
from app.database import get_db
|
|
from app.dependencies import get_current_user
|
|
from app.models import SystemConfig, User
|
|
from app.services import npm_service
|
|
from app.utils.config import get_system_config
|
|
from app.utils.security import encrypt_value
|
|
from app.utils.validators import SystemConfigUpdate
|
|
|
|
logger = logging.getLogger(__name__)
|
|
router = APIRouter()
|
|
|
|
|
|
@router.get("/system")
|
|
async def get_settings(
|
|
current_user: User = Depends(get_current_user),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
"""Return all system configuration values (token masked).
|
|
|
|
Returns:
|
|
System config dict.
|
|
"""
|
|
row = db.query(SystemConfig).filter(SystemConfig.id == 1).first()
|
|
if not row:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail="System configuration not initialized. Run install.sh first.",
|
|
)
|
|
return row.to_dict()
|
|
|
|
|
|
@router.put("/system")
|
|
async def update_settings(
|
|
payload: SystemConfigUpdate,
|
|
current_user: User = Depends(get_current_user),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
"""Update system configuration values.
|
|
|
|
Only provided (non-None) fields are updated. The NPM API token is
|
|
encrypted before storage.
|
|
|
|
Args:
|
|
payload: Fields to update.
|
|
|
|
Returns:
|
|
Updated system config dict.
|
|
"""
|
|
row = db.query(SystemConfig).filter(SystemConfig.id == 1).first()
|
|
if not row:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail="System configuration not initialized.",
|
|
)
|
|
|
|
update_data = payload.model_dump(exclude_none=True)
|
|
|
|
# Handle NPM token encryption
|
|
if "npm_api_token" in update_data:
|
|
raw_token = update_data.pop("npm_api_token")
|
|
row.npm_api_token_encrypted = encrypt_value(raw_token)
|
|
|
|
for field, value in update_data.items():
|
|
if hasattr(row, field):
|
|
setattr(row, field, value)
|
|
|
|
row.updated_at = datetime.utcnow()
|
|
db.commit()
|
|
db.refresh(row)
|
|
|
|
logger.info("System configuration updated by %s.", current_user.username)
|
|
return row.to_dict()
|
|
|
|
|
|
@router.get("/test-npm")
|
|
async def test_npm(
|
|
current_user: User = Depends(get_current_user),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
"""Test connectivity to the Nginx Proxy Manager API.
|
|
|
|
Loads the NPM URL and decrypted token from the database and attempts
|
|
to list proxy hosts.
|
|
|
|
Returns:
|
|
Dict with ``ok`` and ``message``.
|
|
"""
|
|
config = get_system_config(db)
|
|
if not config:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail="System configuration not initialized.",
|
|
)
|
|
if not config.npm_api_url or not config.npm_api_token:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_400_BAD_REQUEST,
|
|
detail="NPM API URL or token not configured.",
|
|
)
|
|
|
|
result = await npm_service.test_npm_connection(config.npm_api_url, config.npm_api_token)
|
|
return result
|