diff --git a/photo21/views.py b/photo21/views.py index bedd2a1..a0044f9 100644 --- a/photo21/views.py +++ b/photo21/views.py @@ -9,14 +9,34 @@ from django.contrib.auth import get_user_model from django.contrib.auth.mixins import LoginRequiredMixin from django.http import FileResponse, Http404 from django.views.generic import ListView, View -from photologue.models import Gallery +from photologue.models import Gallery, Photo class MediaAccess(View): def get(self, request, path): - if not request.user.is_authenticated and not request.session.get('public_gallery_access'): + if not request.user.is_authenticated: from django.contrib.auth.views import redirect_to_login - return redirect_to_login(request.get_full_path()) + token = request.GET.get('token') + if not token: + return redirect_to_login(request.get_full_path()) + # Direct match (original photo file) + allowed = Photo.objects.filter( + image=path, + is_public=True, + galleries__public_token=token, + ).exists() + # Cache files (thumbnails/display) are in photos/cache/ and are + # derived from original photos — verify the token is valid + if not allowed and '/cache/' in path: + cache_dir = os.path.dirname(path) # e.g. photos/cache + original_dir = os.path.dirname(cache_dir) # e.g. photos + allowed = Photo.objects.filter( + image__startswith=original_dir + '/', + is_public=True, + galleries__public_token=token, + ).exists() + if not allowed: + return redirect_to_login(request.get_full_path()) media_root = os.path.realpath(settings.MEDIA_ROOT) file_path = os.path.realpath(os.path.join(media_root, path)) if not file_path.startswith(media_root + os.sep): diff --git a/photologue/templates/photologue/gallery_detail.html b/photologue/templates/photologue/gallery_detail.html index cba9126..771d582 100755 --- a/photologue/templates/photologue/gallery_detail.html +++ b/photologue/templates/photologue/gallery_detail.html @@ -91,8 +91,13 @@ SPDX-License-Identifier: GPL-3.0-or-later {% endif %}