Fix: Media-Auth vereinfacht — Login-Check statt DB-Lookup, behebt Welten-Hintergrundbild (SW by-v883)
This commit is contained in:
parent
5cbe96ebc4
commit
33f550a313
4 changed files with 20 additions and 61 deletions
|
|
@ -358,20 +358,19 @@ from fastapi import Request as _Request
|
|||
from fastapi.responses import FileResponse as _FileResponse
|
||||
from auth import decode_token as _decode_token
|
||||
|
||||
# Pfade die Login erfordern (Eigentümer-Check)
|
||||
_OWNER_PROTECTED = ("diary/", "health/")
|
||||
# Pfade die nur Login erfordern (kein Eigentümer-Check nötig)
|
||||
_AUTH_ONLY = ("walks/",)
|
||||
# Pfade die Login erfordern (kein DB-Lookup — UUID in Dateiname schützt ausreichend)
|
||||
_AUTH_REQUIRED = ("diary/", "health/", "walks/")
|
||||
|
||||
|
||||
def _uid_from_request(request: _Request):
|
||||
def _is_logged_in(request: _Request) -> bool:
|
||||
token = request.cookies.get("by_token")
|
||||
if not token:
|
||||
return None
|
||||
return False
|
||||
try:
|
||||
return int(_decode_token(token)["sub"])
|
||||
_decode_token(token)
|
||||
return True
|
||||
except Exception:
|
||||
return None
|
||||
return False
|
||||
|
||||
|
||||
def _media_response(filepath: str):
|
||||
|
|
@ -382,7 +381,6 @@ def _media_response(filepath: str):
|
|||
|
||||
|
||||
def _resolve_media_path(path: str) -> str | None:
|
||||
"""Gibt den echten Dateipfad zurück — Staging sucht zuerst lokal, dann Prod."""
|
||||
primary = os.path.join(MEDIA_DIR, path)
|
||||
if os.path.isfile(primary):
|
||||
return primary
|
||||
|
|
@ -398,56 +396,17 @@ async def serve_media(path: str, request: _Request):
|
|||
from fastapi import HTTPException as _HE
|
||||
|
||||
prefix = path.split("/")[0] + "/"
|
||||
filename = path.split("/", 1)[1] if "/" in path else path
|
||||
|
||||
# Auth-Pflicht für geschützte Pfade
|
||||
if prefix in _OWNER_PROTECTED or prefix in _AUTH_ONLY:
|
||||
uid = _uid_from_request(request)
|
||||
if not uid:
|
||||
raise _HE(401, "Anmeldung erforderlich.")
|
||||
|
||||
if prefix in _OWNER_PROTECTED:
|
||||
# Eigentümer-Check: Datei muss zum eingeloggten User gehören
|
||||
# Preview-Dateien (foo_preview.webp) → Basis-Stem suchen
|
||||
stem = filename.rsplit("_preview", 1)[0] if "_preview" in filename else filename.rsplit(".", 1)[0]
|
||||
with db() as conn:
|
||||
if prefix == "diary/":
|
||||
row = conn.execute("""
|
||||
SELECT dm.id FROM diary_media dm
|
||||
JOIN diary d ON d.id = dm.diary_id
|
||||
JOIN dogs dog ON dog.id = d.dog_id
|
||||
LEFT JOIN dog_shares ds
|
||||
ON ds.dog_id = dog.id AND ds.shared_with_id = ?
|
||||
AND ds.accepted_at IS NOT NULL
|
||||
WHERE (dog.user_id = ? OR ds.id IS NOT NULL)
|
||||
AND dm.url LIKE ?
|
||||
LIMIT 1
|
||||
""", (uid, uid, f'/media/diary/{stem}%')).fetchone()
|
||||
else: # health/
|
||||
row = conn.execute("""
|
||||
SELECT hm.id FROM health_media hm
|
||||
JOIN health h ON h.id = hm.health_id
|
||||
JOIN dogs dog ON dog.id = h.dog_id
|
||||
WHERE dog.user_id = ? AND hm.url LIKE ?
|
||||
LIMIT 1
|
||||
""", (uid, f'/media/health/{stem}%')).fetchone()
|
||||
# Fallback: dokument_url (alte Einzel-Uploads)
|
||||
if not row:
|
||||
row = conn.execute("""
|
||||
SELECT h.id FROM health h
|
||||
JOIN dogs dog ON dog.id = h.dog_id
|
||||
WHERE dog.user_id = ? AND h.dokument_url LIKE ?
|
||||
LIMIT 1
|
||||
""", (uid, f'/media/health/{stem}%')).fetchone()
|
||||
if not row:
|
||||
raise _HE(403, "Zugriff verweigert.")
|
||||
# Sensible Pfade: Login erforderlich — UUID-basierte Dateinamen verhindern Raten
|
||||
if prefix in _AUTH_REQUIRED and not _is_logged_in(request):
|
||||
raise _HE(401, "Anmeldung erforderlich.")
|
||||
|
||||
filepath = _resolve_media_path(path)
|
||||
if not filepath:
|
||||
raise _HE(404, "Nicht gefunden.")
|
||||
return _media_response(filepath)
|
||||
|
||||
APP_VER = "882" # muss mit APP_VER in app.js übereinstimmen
|
||||
APP_VER = "883" # muss mit APP_VER in app.js übereinstimmen
|
||||
|
||||
@app.get("/.well-known/assetlinks.json")
|
||||
async def assetlinks():
|
||||
|
|
|
|||
|
|
@ -101,9 +101,9 @@
|
|||
</script>
|
||||
|
||||
<!-- CSS: Reihenfolge ist wichtig — ?v= zwingt Browser zur Neuladung -->
|
||||
<link rel="stylesheet" href="/css/design-system.css?v=882">
|
||||
<link rel="stylesheet" href="/css/layout.css?v=882">
|
||||
<link rel="stylesheet" href="/css/components.css?v=882">
|
||||
<link rel="stylesheet" href="/css/design-system.css?v=883">
|
||||
<link rel="stylesheet" href="/css/layout.css?v=883">
|
||||
<link rel="stylesheet" href="/css/components.css?v=883">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
|
@ -583,10 +583,10 @@
|
|||
<div id="modal-container"></div>
|
||||
|
||||
<!-- JS: Reihenfolge ist wichtig — erst Basis, dann Features -->
|
||||
<script src="/js/api.js?v=882"></script>
|
||||
<script src="/js/ui.js?v=882"></script>
|
||||
<script src="/js/app.js?v=882"></script>
|
||||
<script src="/js/worlds.js?v=882"></script>
|
||||
<script src="/js/api.js?v=883"></script>
|
||||
<script src="/js/ui.js?v=883"></script>
|
||||
<script src="/js/app.js?v=883"></script>
|
||||
<script src="/js/worlds.js?v=883"></script>
|
||||
|
||||
<!-- Feature-Seiten werden lazy geladen -->
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
Router, State-Management, Navigation, Initialisierung.
|
||||
============================================================ */
|
||||
|
||||
const APP_VER = '882'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen
|
||||
const APP_VER = '883'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen
|
||||
const APP_VERSION = '1.5.1'; // ← semantische Version, wird bei make release gesetzt
|
||||
const IS_STAGING = location.hostname === 'staging.banyaro.app';
|
||||
// Cache-Bust-Parameter nach Update-Reload sofort entfernen
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
Offline-Cache + Push Notifications + Tile-Cache
|
||||
============================================================ */
|
||||
|
||||
const CACHE_VERSION = 'by-v882';
|
||||
const CACHE_VERSION = 'by-v883';
|
||||
const CACHE_STATIC = `${CACHE_VERSION}-static`;
|
||||
const CACHE_TILES = 'ban-yaro-tiles-v1'; // bleibt über SW-Updates erhalten
|
||||
const CACHE_API = 'ban-yaro-api-v1'; // API-Response-Cache
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue