from datetime import date from fastapi import APIRouter, Depends from pydantic import BaseModel from advent22_api.core.helpers import EventDates from ..core.calendar_config import CalendarConfig, DoorsSaved, get_calendar_config from ..core.config import Config, Image, get_config from ..core.depends import ( TTFont, get_all_event_dates, get_all_image_names, get_all_parts, get_all_ttfonts, ) from ..core.settings import SETTINGS, RedisSettings from ._security import require_admin, user_is_admin router = APIRouter(prefix="/admin", tags=["admin"]) @router.get("/is_admin") async def is_admin( is_admin: bool = Depends(user_is_admin), ) -> bool: return is_admin class AdminConfigModel(BaseModel): class __Solution(BaseModel): value: str whitespace: str special_chars: str case: str clean: str class __Puzzle(BaseModel): first: date next: date | None last: date end: date seed: str extra_days: list[int] skip_empty: bool class __Calendar(BaseModel): config_file: str background: str favicon: str class __Font(BaseModel): file: str size: int class __WebDAV(BaseModel): url: str cache_ttl: int config_file: str solution: __Solution puzzle: __Puzzle calendar: __Calendar image: Image fonts: list[__Font] redis: RedisSettings webdav: __WebDAV @router.get("/config_model") async def get_config_model( _: None = Depends(require_admin), cfg: Config = Depends(get_config), cal_cfg: CalendarConfig = Depends(get_calendar_config), event_dates: EventDates = Depends(get_all_event_dates), ttfonts: list[TTFont] = Depends(get_all_ttfonts), ) -> AdminConfigModel: """ Kombiniert aus privaten `settings`, `config` und `calendar_config` """ return AdminConfigModel.model_validate( { "solution": { "value": cfg.solution.value, "whitespace": cfg.solution.whitespace, "special_chars": cfg.solution.special_chars, "case": cfg.solution.case, "clean": cfg.solution.clean, }, "puzzle": { "first": event_dates.first, "next": event_dates.next, "last": event_dates.last, "end": event_dates.end, "seed": cfg.random_seed, "extra_days": sorted(cfg.puzzle.extra_days), "skip_empty": cfg.puzzle.skip_empty, }, "calendar": { "config_file": cfg.calendar, "background": cal_cfg.background, "favicon": cal_cfg.favicon, }, "image": cfg.image, "fonts": [ {"file": ttfont.file_name, "size": ttfont.size} for ttfont in ttfonts ], "redis": SETTINGS.redis, "webdav": { "url": SETTINGS.webdav.url, "cache_ttl": SETTINGS.webdav.cache_ttl, "config_file": SETTINGS.webdav.config_filename, }, } ) @router.get("/day_image_names") async def get_day_image_names( _: None = Depends(require_admin), image_names: dict[int, str] = Depends(get_all_image_names), ) -> dict[int, str]: """ Zuordnung der verwendeten Bilder zu den Tagen """ return image_names @router.get("/day_parts") async def get_day_parts( _: None = Depends(require_admin), parts: dict[int, str] = Depends(get_all_parts), ) -> dict[int, str]: """ Zuordnung der Lösungsteile zu den Tagen """ return parts @router.get("/doors") async def get_doors( _: None = Depends(require_admin), cal_cfg: CalendarConfig = Depends(get_calendar_config), ) -> DoorsSaved: """ Türchen lesen """ return cal_cfg.doors @router.put("/doors") async def put_doors( doors: DoorsSaved, _: None = Depends(require_admin), cfg: Config = Depends(get_config), cal_cfg: CalendarConfig = Depends(get_calendar_config), ) -> None: """ Türchen ändern """ cal_cfg.doors = sorted( doors, key=lambda door: door.day, ) await cal_cfg.change(cfg) @router.get("/dav_credentials") async def get_dav_credentials( _: None = Depends(require_admin), ) -> tuple[str, str]: """ Zugangsdaten für WebDAV """ return SETTINGS.webdav.username, SETTINGS.webdav.password @router.get("/ui_credentials") async def get_ui_credentials( _: None = Depends(require_admin), cfg: Config = Depends(get_config), ) -> tuple[str, str]: """ Zugangsdaten für Admin-UI """ return cfg.admin.name, cfg.admin.password