Fix public gallery media access bypass via session flag.

This commit is contained in:
krek0 2026-05-07 14:02:09 +02:00
parent 9ff8e969f4
commit 96afb9cc0b
3 changed files with 28 additions and 4 deletions

View file

@ -9,14 +9,34 @@ from django.contrib.auth import get_user_model
from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth.mixins import LoginRequiredMixin
from django.http import FileResponse, Http404 from django.http import FileResponse, Http404
from django.views.generic import ListView, View from django.views.generic import ListView, View
from photologue.models import Gallery from photologue.models import Gallery, Photo
class MediaAccess(View): class MediaAccess(View):
def get(self, request, path): 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 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) media_root = os.path.realpath(settings.MEDIA_ROOT)
file_path = os.path.realpath(os.path.join(media_root, path)) file_path = os.path.realpath(os.path.join(media_root, path))
if not file_path.startswith(media_root + os.sep): if not file_path.startswith(media_root + os.sep):

View file

@ -91,8 +91,13 @@ SPDX-License-Identifier: GPL-3.0-or-later
{% endif %} {% endif %}
<div class="card-body p-0" id="lightgallery"> <div class="card-body p-0" id="lightgallery">
{% for photo in photos %} {% for photo in photos %}
{% if guest_mode %}{% with t=gallery.public_token %}
<a class="photo-item" href="{{ photo.get_absolute_url }}" data-src="{{ photo.get_display_url }}?token={{ t }}" data-download-url="{{ photo.image.url }}?token={{ t }}" data-slide-name="{{ photo.id }}" data-owner-id="{{ photo.owner.id }}" data-is-public="{{ photo.is_public|yesno:'true,false' }}" data-width="{{ photo.image_width|default:1 }}" data-height="{{ photo.image_height|default:1 }}">
<img src="{{ photo.get_thumbnail_url }}?token={{ t }}" data-lazy="{{ photo.get_thumbnail_url }}?token={{ t }}" class="{% if not photo.is_public %}photo-private{% endif %}" alt="{{ photo.title }}{% if photo.date_taken %} - {{ photo.date_taken|date }} {{ photo.date_taken|time }}{% endif %}{% if photo.owner.get_full_name %} - {{ photo.owner.get_full_name }}{% else %} - {{ photo.owner.username }}{% endif %}{% if photo.license %} - {{ photo.license }}{% endif %}{% if not photo.is_public %} - !PRIVATE!{% endif %}">
{% endwith %}{% else %}
<a class="photo-item" href="{{ photo.get_absolute_url }}" data-src="{{ photo.get_display_url}}" data-download-url="{{ photo.image.url }}" data-slide-name="{{ photo.id }}" data-owner-id="{{ photo.owner.id }}" data-is-public="{{ photo.is_public|yesno:'true,false' }}" data-width="{{ photo.image_width|default:1 }}" data-height="{{ photo.image_height|default:1 }}"> <a class="photo-item" href="{{ photo.get_absolute_url }}" data-src="{{ photo.get_display_url}}" data-download-url="{{ photo.image.url }}" data-slide-name="{{ photo.id }}" data-owner-id="{{ photo.owner.id }}" data-is-public="{{ photo.is_public|yesno:'true,false' }}" data-width="{{ photo.image_width|default:1 }}" data-height="{{ photo.image_height|default:1 }}">
<img src="{{ photo.get_thumbnail_url }}" data-lazy="{{ photo.get_thumbnail_url }}" class="{% if not photo.is_public %}photo-private{% endif %}" alt="{{ photo.title }}{% if photo.date_taken %} - {{ photo.date_taken|date }} {{ photo.date_taken|time }}{% endif %}{% if photo.owner.get_full_name %} - {{ photo.owner.get_full_name }}{% else %} - {{ photo.owner.username }}{% endif %}{% if photo.license %} - {{ photo.license }}{% endif %}{% if not photo.is_public %} - !PRIVATE!{% endif %}"> <img src="{{ photo.get_thumbnail_url }}" data-lazy="{{ photo.get_thumbnail_url }}" class="{% if not photo.is_public %}photo-private{% endif %}" alt="{{ photo.title }}{% if photo.date_taken %} - {{ photo.date_taken|date }} {{ photo.date_taken|time }}{% endif %}{% if photo.owner.get_full_name %} - {{ photo.owner.get_full_name }}{% else %} - {{ photo.owner.username }}{% endif %}{% if photo.license %} - {{ photo.license }}{% endif %}{% if not photo.is_public %} - !PRIVATE!{% endif %}">
{% endif %}
</a> </a>
{% endfor %} {% endfor %}
</div> </div>

View file

@ -237,7 +237,6 @@ class GalleryPublicView(DetailView):
if request.user.is_authenticated: if request.user.is_authenticated:
gallery = self.get_object() gallery = self.get_object()
return redirect("photologue:pl-gallery", slug=gallery.slug) return redirect("photologue:pl-gallery", slug=gallery.slug)
request.session['public_gallery_access'] = True
request.guest_mode = True request.guest_mode = True
return super().get(request, *args, **kwargs) return super().get(request, *args, **kwargs)