refactor(api): shared serializer + ownership + write-scope helpers (R6 S1a)
Establish the R6 API-contract infra before the S1b payload:dict migration: - iso(dt) in utils.py replaces the ~16 hand-rolled `x.isoformat() if x else None` serializer idioms across the routes. - get_or_404 / owned_or_404 in routes/_common.py — one 404 + existence-leak policy; plex's _own_playlist_or_404 and saved_views' _own_view now delegate to it. - require_write_scope dependency in auth.py collapses the inline has_write_scope→403 checks (channels subscribe/unsubscribe, playlists push/push-plan) that had drifted into three different messages into one; the conditional delete_playlist guard stays inline (its message was already canonical). No response-shape change (iso == isoformat for a present value). Gate: ruff clean, pytest 163 green (+ test_utils for iso).
This commit is contained in:
@@ -11,6 +11,7 @@ from sqlalchemy.orm import Session
|
||||
from app.auth import current_user
|
||||
from app.db import get_db
|
||||
from app.models import Notification, User
|
||||
from app.utils import iso
|
||||
from app.notifications import trim_read
|
||||
|
||||
router = APIRouter(prefix="/api/me/notifications", tags=["notifications"])
|
||||
@@ -25,7 +26,7 @@ def _serialize(n: Notification) -> dict:
|
||||
"data": n.data,
|
||||
"read": n.read,
|
||||
"dismissed": n.dismissed,
|
||||
"created_at": n.created_at.isoformat() if n.created_at else None,
|
||||
"created_at": iso(n.created_at),
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user