Add possiblity to share gallerie with public link
All checks were successful
Docker / build (release) Successful in 8s

This commit is contained in:
krek0 2026-05-10 12:57:14 +02:00
parent ed28d4a9c4
commit 2a409b54f7
12 changed files with 206 additions and 48 deletions

View file

@ -149,6 +149,20 @@ if _db_engine == "postgres":
"PORT": config("DB_PORT", default="5432"),
}
}
elif _db_engine == "mariadb":
DATABASES = {
"default": {
"ENGINE": "django.db.backends.mysql",
"NAME": config("DB_NAME", default="photo21"),
"USER": config("DB_USER", default="photo21"),
"PASSWORD": config("DB_PASSWORD", default=""),
"HOST": config("DB_HOST", default="localhost"),
"PORT": config("DB_PORT", default="3306"),
"OPTIONS": {
"charset": "utf8mb4",
},
}
}
elif _db_engine == "sqlite":
DATABASES = {
"default": {
@ -160,7 +174,7 @@ elif _db_engine == "sqlite":
}
}
else:
raise ValueError(f"Unknown DB_ENGINE '{_db_engine}'. Must be 'sqlite' or 'postgres'.")
raise ValueError(f"Unknown DB_ENGINE '{_db_engine}'. Must be 'sqlite', 'postgres' or 'mariadb'.")
CACHES = {
"default": {

View file

@ -0,0 +1,24 @@
document.querySelectorAll('[data-clipboard-text]').forEach(function(btn) {
btn.addEventListener('click', function() {
var text = btn.dataset.clipboardText;
if (navigator.clipboard) {
navigator.clipboard.writeText(text);
} else {
var ta = document.createElement('textarea');
ta.value = text;
ta.style.position = 'fixed';
ta.style.opacity = '0';
document.body.appendChild(ta);
ta.select();
document.execCommand('copy');
document.body.removeChild(ta);
}
var original = btn.textContent;
btn.textContent = '✓ Copied!';
btn.disabled = true;
setTimeout(function() {
btn.textContent = original;
btn.disabled = false;
}, 2000);
});
});

View file

@ -37,6 +37,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
{% if request.user.is_authenticated %}
<li class="nav-item">
{% url 'photologue:pl-gallery-archive' as url %}
<a class="nav-link {% if request.path_info == url %}active{% endif %}" href="{{ url }}">{% trans 'Galleries' %}</a>
@ -52,6 +53,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
<a class="nav-link" href="{% url 'admin:index' %}">{% trans 'Manage' %}</a>
</li>
{% endif %}
{% endif %}
</ul>
<ul class="navbar-nav">
{% get_available_languages as LANGUAGES %}

View file

@ -9,14 +9,36 @@ 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())
try:
allowed_ids = set(request.get_signed_cookie("public_galleries", default="").split(","))
except Exception:
allowed_ids = set()
allowed_ids.discard("")
if not allowed_ids:
return redirect_to_login(request.get_full_path())
# Direct match (original photo file)
allowed = Photo.objects.filter(
image=path,
is_public=True,
galleries__id__in=allowed_ids,
).exists()
# Cache files (thumbnails/display) are derived from original photos
if not allowed and '/cache/' in path:
original_dir = os.path.dirname(os.path.dirname(path))
allowed = Photo.objects.filter(
image__startswith=original_dir + '/',
is_public=True,
galleries__id__in=allowed_ids,
).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):