Add possiblity to share gallerie with public link
All checks were successful
Docker / build (release) Successful in 8s
All checks were successful
Docker / build (release) Successful in 8s
This commit is contained in:
parent
ed28d4a9c4
commit
2a409b54f7
12 changed files with 206 additions and 48 deletions
|
|
@ -3,24 +3,23 @@
|
|||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
import os
|
||||
import uuid
|
||||
import zipfile
|
||||
from io import BytesIO
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin
|
||||
from django.core.mail import mail_admins
|
||||
from django.db import transaction
|
||||
from django.http import HttpResponse
|
||||
from django.http import JsonResponse
|
||||
from django.shortcuts import redirect
|
||||
from django.urls import reverse_lazy
|
||||
from django.http import HttpResponse, JsonResponse
|
||||
from django.shortcuts import get_object_or_404, redirect
|
||||
from django.urls import reverse, reverse_lazy
|
||||
from django.utils.text import slugify
|
||||
from django.views import View
|
||||
from django.views.generic.dates import ArchiveIndexView, YearArchiveView
|
||||
from django.views.generic.detail import DetailView
|
||||
from django.views.generic.edit import DeleteView, FormView
|
||||
from django.conf import settings
|
||||
from PIL import Image
|
||||
from django.contrib.auth import get_user_model
|
||||
|
||||
|
|
@ -150,13 +149,30 @@ class TagDetail(LoginRequiredMixin, DetailView):
|
|||
return context
|
||||
|
||||
|
||||
class GalleryDetailView(LoginRequiredMixin, DetailView):
|
||||
def _allowed_gallery_ids(request):
|
||||
try:
|
||||
ids = set(request.get_signed_cookie("public_galleries", default="").split(","))
|
||||
except Exception:
|
||||
ids = set()
|
||||
ids.discard("")
|
||||
return ids
|
||||
|
||||
|
||||
class GalleryDetailView(DetailView):
|
||||
"""
|
||||
Gallery detail view to filter on photo owner
|
||||
"""
|
||||
|
||||
model = Gallery
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
if not request.user.is_authenticated:
|
||||
gallery = self.get_object()
|
||||
if str(gallery.id) not in _allowed_gallery_ids(request):
|
||||
from django.contrib.auth.views import redirect_to_login
|
||||
return redirect_to_login(request.get_full_path())
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
|
||||
|
|
@ -185,46 +201,71 @@ class GalleryDetailView(LoginRequiredMixin, DetailView):
|
|||
if "owner" in self.kwargs:
|
||||
context["photos"] = context["photos"].filter(owner__id=self.kwargs["owner"])
|
||||
|
||||
# Increment the photo view count
|
||||
if self.object.public_token:
|
||||
public_path = reverse("photologue:pl-gallery-public", args=[self.object.public_token])
|
||||
context["public_url"] = self.request.build_absolute_uri(public_path)
|
||||
|
||||
context["photos"].update(view_count=F("view_count") + 1)
|
||||
|
||||
return context
|
||||
|
||||
|
||||
class GalleryDownload(LoginRequiredMixin, DetailView):
|
||||
### IN FUTURE, PUT IT as Django Task
|
||||
class GalleryDownload(DetailView):
|
||||
model = Gallery
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
if not request.user.is_authenticated:
|
||||
gallery = self.get_object()
|
||||
if str(gallery.id) not in _allowed_gallery_ids(request):
|
||||
from django.contrib.auth.views import redirect_to_login
|
||||
return redirect_to_login(request.get_full_path())
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
"""
|
||||
Download a zip file of the gallery on GET request.
|
||||
"""
|
||||
# Create zip file with pictures
|
||||
gallery = self.get_object()
|
||||
|
||||
gallery_year = os.path.join("/photos/", str(gallery.date_start.year))
|
||||
gallery_zip = os.path.join(gallery_year, (gallery.slug + ".zip"))
|
||||
|
||||
with open(settings.MEDIA_ROOT + gallery_zip, "wb") as zip_bytes:
|
||||
zip_file = zipfile.ZipFile(zip_bytes, "w")
|
||||
buffer = BytesIO()
|
||||
with zipfile.ZipFile(buffer, "w") as zf:
|
||||
for photo in gallery.photos.filter(is_public=True):
|
||||
filename = os.path.basename(os.path.normpath(photo.image.path))
|
||||
zip_file.write(photo.image.path, filename)
|
||||
zip_file.close()
|
||||
filename = os.path.basename(photo.image.name)
|
||||
zf.write(photo.image.path, filename)
|
||||
buffer.seek(0)
|
||||
response = HttpResponse(buffer, content_type="application/zip")
|
||||
response["Content-Disposition"] = f'attachment; filename="{gallery.slug}.zip"'
|
||||
return response
|
||||
|
||||
# Return the path to it
|
||||
|
||||
return redirect(
|
||||
(settings.MEDIA_URL + str(gallery_zip)).replace("\\", "/")
|
||||
) # windows fix
|
||||
# Return zip file
|
||||
class GalleryPublicView(View):
|
||||
def get(self, request, token):
|
||||
gallery = get_object_or_404(Gallery, public_token=token)
|
||||
response = redirect("photologue:pl-gallery", slug=gallery.slug)
|
||||
if not request.user.is_authenticated:
|
||||
try:
|
||||
existing = set(request.get_signed_cookie("public_galleries", default="").split(","))
|
||||
except Exception:
|
||||
existing = set()
|
||||
existing.discard("")
|
||||
existing.add(str(gallery.id))
|
||||
response.set_signed_cookie(
|
||||
"public_galleries", ",".join(existing),
|
||||
max_age=86400 * 30, httponly=True, samesite="Lax",
|
||||
)
|
||||
return response
|
||||
|
||||
# response = HttpResponse(
|
||||
# byte_data.getvalue(), content_type="application/x-zip-compressed"
|
||||
# )
|
||||
# response["Content-Disposition"] = f"attachment; filename={gallery.slug}.zip"
|
||||
# return response
|
||||
|
||||
class GalleryTokenView(LoginRequiredMixin, View):
|
||||
def post(self, request, slug):
|
||||
if not request.user.is_staff:
|
||||
from django.core.exceptions import PermissionDenied
|
||||
raise PermissionDenied
|
||||
gallery = get_object_or_404(Gallery, slug=slug)
|
||||
action = request.POST.get("action")
|
||||
if action == "generate":
|
||||
gallery.public_token = uuid.uuid4()
|
||||
gallery.save()
|
||||
elif action == "revoke":
|
||||
gallery.public_token = None
|
||||
gallery.save()
|
||||
return redirect(reverse("photologue:pl-gallery", args=[slug]))
|
||||
|
||||
|
||||
class GalleryUpload(PermissionRequiredMixin, FormView):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue