diff --git a/api/advent22_api/core/depends.py b/api/advent22_api/core/depends.py index d546356..05de953 100644 --- a/api/advent22_api/core/depends.py +++ b/api/advent22_api/core/depends.py @@ -130,14 +130,18 @@ async def gen_day_auto_image( async def get_day_image( day: int, + days: list[int] = Depends(get_all_sorted_days), cfg: Config = Depends(get_config), auto_image_names: dict[int, str] = Depends(get_all_auto_image_names), day_parts: dict[int, str] = Depends(get_all_parts), -) -> Image.Image: +) -> Image.Image | None: """ Bild für einen Tag abrufen """ + if day not in days: + return None + try: # Versuche, aus "manual"-Ordner zu laden img = await load_image(f"images_manual/{day}.jpg") diff --git a/api/advent22_api/core/helpers.py b/api/advent22_api/core/helpers.py index f1a556e..89bbb39 100644 --- a/api/advent22_api/core/helpers.py +++ b/api/advent22_api/core/helpers.py @@ -77,16 +77,18 @@ class EventDates: """ __overall_duration: timedelta - dates: list[date] + dates: dict[int, date] @property def first(self) -> date: """Datum des ersten Ereignisses""" - return self.dates[0] + return self.dates[min(self.dates.keys())] def get_next(self, *, today: date) -> date | None: """Datum des nächsten Ereignisses""" - return next((event for event in self.dates if event > today), None) + return next( + (event for event in sorted(self.dates.values()) if event > today), None + ) @property def next(self) -> date | None: @@ -96,7 +98,7 @@ class EventDates: @property def last(self) -> date: """Datum des letzten Ereignisses""" - return self.dates[-1] + return self.dates[max(self.dates.keys())] @property def end(self) -> date: @@ -133,4 +135,4 @@ class EventDates: ) # all event dates - self.dates = [begin + timedelta(days=event - 1) for event in events] + self.dates = {event: begin + timedelta(days=event - 1) for event in events} diff --git a/api/advent22_api/routers/_security.py b/api/advent22_api/routers/_security.py index 1e548fe..13929ae 100644 --- a/api/advent22_api/routers/_security.py +++ b/api/advent22_api/routers/_security.py @@ -5,6 +5,8 @@ from fastapi import Depends, HTTPException, status from fastapi.security import HTTPBasic, HTTPBasicCredentials from ..core.config import Config, get_config +from ..core.depends import get_all_event_dates +from ..core.helpers import EventDates security = HTTPBasic() @@ -31,33 +33,27 @@ async def require_admin( """ if not is_admin: - raise HTTPException(status.HTTP_401_UNAUTHORIZED) + raise HTTPException(status.HTTP_401_UNAUTHORIZED, "Wie unhöflich!!!") -async def user_visible_doors() -> int: +async def user_visible_days( + event_dates: EventDates = Depends(get_all_event_dates), +) -> list[int]: """ Anzahl der user-sichtbaren Türchen """ today = date.today() - if today.month == 12: - return today.day - - if today.month in (1, 2, 3): - return 24 - - return 0 + return [event for event, date in event_dates.dates.items() if date <= today] async def user_can_view_day( day: int, + visible_days: list[int] = Depends(user_visible_days), ) -> bool: """ True iff das Türchen von Tag `day` user-sichtbar ist """ - if day < 1: - raise HTTPException(status.HTTP_422_UNPROCESSABLE_ENTITY) - - return day <= await user_visible_doors() + return day in visible_days diff --git a/api/advent22_api/routers/user.py b/api/advent22_api/routers/user.py index c522f6c..9bd099d 100644 --- a/api/advent22_api/routers/user.py +++ b/api/advent22_api/routers/user.py @@ -7,7 +7,7 @@ from PIL import Image from ..core.calendar_config import CalendarConfig, DoorsSaved, get_calendar_config from ..core.depends import get_all_event_dates, get_day_image from ..core.helpers import EventDates, api_return_image, load_image -from ._security import user_can_view_day, user_is_admin +from ._security import user_can_view_day, user_is_admin, user_visible_days router = APIRouter(prefix="/user", tags=["user"]) @@ -31,29 +31,35 @@ async def get_background_image( response_class=StreamingResponse, ) async def get_image_for_day( - image: Image.Image = Depends(get_day_image), - can_view: bool = Depends(user_can_view_day), + user_can_view: bool = Depends(user_can_view_day), is_admin: bool = Depends(user_is_admin), + image: Image.Image | None = Depends(get_day_image), ) -> StreamingResponse: """ Bild für einen Tag erstellen """ - if not (can_view or is_admin): + if not (user_can_view or is_admin): raise HTTPException(status.HTTP_401_UNAUTHORIZED, "Wie unhöflich!!!") + if image is None: + raise HTTPException( + status.HTTP_404_NOT_FOUND, "Ich habe heute leider kein Foto für dich." + ) + return await api_return_image(image) @router.get("/doors") async def get_doors( cal_cfg: CalendarConfig = Depends(get_calendar_config), + visible_days: list[int] = Depends(user_visible_days), ) -> DoorsSaved: """ User-sichtbare Türchen lesen """ - return [door for door in cal_cfg.doors if await user_can_view_day(door.day)] + return [door for door in cal_cfg.doors if door.day in visible_days] @router.get("/next_door")