From f60592d37b6d7bdbfc16597eadb6723b5e4183a5 Mon Sep 17 00:00:00 2001 From: Alexandre Iooss Date: Tue, 12 Oct 2021 08:34:53 +0200 Subject: [PATCH 01/15] Add migration for start and end date --- .../migrations/0002_auto_20211011_1956.py | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 photologue_custom/migrations/0002_auto_20211011_1956.py diff --git a/photologue_custom/migrations/0002_auto_20211011_1956.py b/photologue_custom/migrations/0002_auto_20211011_1956.py new file mode 100644 index 0000000..d03ea2c --- /dev/null +++ b/photologue_custom/migrations/0002_auto_20211011_1956.py @@ -0,0 +1,23 @@ +# Generated by Django 2.2.24 on 2021-10-11 19:56 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('photologue_custom', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='galleryextended', + name='date_end', + field=models.DateField(blank=True, null=True, verbose_name='end date'), + ), + migrations.AddField( + model_name='galleryextended', + name='date_start', + field=models.DateField(blank=True, null=True, verbose_name='start date'), + ), + ] From 3655d957cafc0850b958e42b9c053903c7dfc558 Mon Sep 17 00:00:00 2001 From: Alexandre Iooss Date: Tue, 12 Oct 2021 08:49:01 +0200 Subject: [PATCH 02/15] Add initial fixture --- photo21/fixtures/initial.json | 10 ++++++++++ photo21/settings.py | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 photo21/fixtures/initial.json diff --git a/photo21/fixtures/initial.json b/photo21/fixtures/initial.json new file mode 100644 index 0000000..62ad580 --- /dev/null +++ b/photo21/fixtures/initial.json @@ -0,0 +1,10 @@ +[ + { + "model": "sites.site", + "pk": 1, + "fields": { + "domain": "photos.crans.org", + "name": "Serveur photos" + } + } +] \ No newline at end of file diff --git a/photo21/settings.py b/photo21/settings.py index f2da6ab..647abe7 100644 --- a/photo21/settings.py +++ b/photo21/settings.py @@ -167,7 +167,7 @@ MEDIA_URL = '/media/' LOCALE_PATHS = [os.path.join(BASE_DIR, 'photo21/locale')] -FIXTURE_DIRS = [os.path.join(BASE_DIR, 'note_kfet/fixtures')] +FIXTURE_DIRS = [os.path.join(BASE_DIR, 'photo21/fixtures')] # Email settings if DEBUG: From 65692901b8e3ef530cebe6835483bcbdc5ea5da8 Mon Sep 17 00:00:00 2001 From: Alexandre Iooss Date: Tue, 12 Oct 2021 08:57:39 +0200 Subject: [PATCH 03/15] Add python3-docutils as a requirement --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1a2d25e..d7b8f15 100644 --- a/README.md +++ b/README.md @@ -75,7 +75,7 @@ production néccessite **une installation de Debian Bullseye**. $ sudo apt install nginx git gettext uwsgi uwsgi-plugin-python3 python3-venv \ python3-certbot-nginx python3-django python3-django-crispy-forms \ python3-django-taggit python3-pil python3-exifread python3-django-allauth \ - python3-psycopg2 + python3-psycopg2 python3-docutils ``` 2. **Clonage du dépot dans `/var/www/photos/photo21`** From 211b23d339c2a8157b79796f353cc04064bf2cb1 Mon Sep 17 00:00:00 2001 From: Alexandre Iooss Date: Tue, 12 Oct 2021 08:58:01 +0200 Subject: [PATCH 04/15] Define thumbnail sizes in initial data --- photo21/fixtures/initial.json | 48 +++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/photo21/fixtures/initial.json b/photo21/fixtures/initial.json index 62ad580..6a3f0a0 100644 --- a/photo21/fixtures/initial.json +++ b/photo21/fixtures/initial.json @@ -6,5 +6,53 @@ "domain": "photos.crans.org", "name": "Serveur photos" } + }, + { + "model": "photologue.photosize", + "pk": 1, + "fields": { + "name": "admin_thumbnail", + "width": 100, + "height": 75, + "quality": 70, + "upscale": false, + "crop": true, + "pre_cache": true, + "increment_count": false, + "effect": null, + "watermark": null + } + }, + { + "model": "photologue.photosize", + "pk": 2, + "fields": { + "name": "thumbnail", + "width": 250, + "height": 180, + "quality": 70, + "upscale": false, + "crop": true, + "pre_cache": true, + "increment_count": false, + "effect": null, + "watermark": null + } + }, + { + "model": "photologue.photosize", + "pk": 3, + "fields": { + "name": "display", + "width": 1980, + "height": 0, + "quality": 70, + "upscale": false, + "crop": false, + "pre_cache": true, + "increment_count": true, + "effect": null, + "watermark": null + } } ] \ No newline at end of file From 1af83a863067d9c0306f0865b7d2112a50cc141f Mon Sep 17 00:00:00 2001 From: Alexandre Iooss Date: Tue, 12 Oct 2021 08:58:39 +0200 Subject: [PATCH 05/15] Allow access from localhost --- photo21/settings.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/photo21/settings.py b/photo21/settings.py index 647abe7..88216ed 100644 --- a/photo21/settings.py +++ b/photo21/settings.py @@ -29,6 +29,8 @@ SECRET_KEY = 'CHANGE_ME' DEBUG = True ALLOWED_HOSTS = [ + "127.0.0.1", + "localhost", "photos.crans.org", "photos-dev.crans.org", ] From 971b112decc029ab1a3b646640c22972cf259cdc Mon Sep 17 00:00:00 2001 From: Alexandre Iooss Date: Tue, 12 Oct 2021 09:05:16 +0200 Subject: [PATCH 06/15] Hide PhotoEffect, PhotoSize and Watermark from admin --- README.md | 1 + photologue_custom/admin.py | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d7b8f15..7bda3bd 100644 --- a/README.md +++ b/README.md @@ -122,6 +122,7 @@ production néccessite **une installation de Debian Bullseye**. $ sudo -u www-data ./venv/bin/python ./manage.py collectstatic $ sudo -u www-data ./venv/bin/python ./manage.py check $ sudo -u www-data ./venv/bin/python ./manage.py migrate + $ sudo -u www-data ./venv/bin/python ./manage.py loaddata initial $ sudo ./venv/bin/python ./manage.py compilemessages ``` diff --git a/photologue_custom/admin.py b/photologue_custom/admin.py index cfd8ddf..2c0aca0 100644 --- a/photologue_custom/admin.py +++ b/photologue_custom/admin.py @@ -1,7 +1,7 @@ from django.contrib import admin from photologue.admin import GalleryAdmin as GalleryAdminDefault from photologue.admin import PhotoAdmin as PhotoAdminDefault -from photologue.models import Gallery, Photo +from photologue.models import Gallery, Photo, PhotoEffect, PhotoSize, Watermark from .models import GalleryExtended, PhotoExtended @@ -34,5 +34,8 @@ class PhotoAdmin(PhotoAdminDefault): admin.site.unregister(Gallery) admin.site.unregister(Photo) +admin.site.unregister(PhotoEffect) +admin.site.unregister(PhotoSize) +admin.site.unregister(Watermark) admin.site.register(Gallery, GalleryAdmin) admin.site.register(Photo, PhotoAdmin) From d02c52a2d0c4fc17464640471a0efcf38bbaea71 Mon Sep 17 00:00:00 2001 From: Alexandre Iooss Date: Tue, 12 Oct 2021 09:06:59 +0200 Subject: [PATCH 07/15] Do not test Python 3.7 --- tox.ini | 3 --- 1 file changed, 3 deletions(-) diff --git a/tox.ini b/tox.ini index 30d8c12..333bfcb 100644 --- a/tox.ini +++ b/tox.ini @@ -1,8 +1,5 @@ [tox] envlist = - # Debian Buster Python - py37-django22 - # Ubuntu 20.04 Python py38-django22 From f6e38580d3dfe90391bc4cbc1d1f4c4d7fa125ee Mon Sep 17 00:00:00 2001 From: Alexandre Iooss Date: Tue, 12 Oct 2021 10:11:15 +0200 Subject: [PATCH 08/15] Fix on_delete cascade --- photologue_custom/models.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/photologue_custom/models.py b/photologue_custom/models.py index 76d7f86..76be399 100644 --- a/photologue_custom/models.py +++ b/photologue_custom/models.py @@ -10,7 +10,7 @@ class GalleryExtended(models.Model): gallery = models.OneToOneField( Gallery, related_name='extended', - on_delete='cascade', + on_delete=models.CASCADE, ) # Add tags @@ -41,7 +41,7 @@ class PhotoExtended(models.Model): photo = models.OneToOneField( Photo, related_name='extented', - on_delete='cascade' + on_delete=models.CASCADE, ) # Add a owner field to PhotoExtended From a33f7217f63069f5618348cbcb380099ca892b07 Mon Sep 17 00:00:00 2001 From: Alexandre Iooss Date: Tue, 12 Oct 2021 11:46:30 +0200 Subject: [PATCH 09/15] Implement Symfony password hasher --- photo21/hashers.py | 45 +++++++++++++++++++++++++++++++++++++++++++++ photo21/settings.py | 5 +++++ 2 files changed, 50 insertions(+) create mode 100644 photo21/hashers.py diff --git a/photo21/hashers.py b/photo21/hashers.py new file mode 100644 index 0000000..e94397e --- /dev/null +++ b/photo21/hashers.py @@ -0,0 +1,45 @@ +import hashlib +import base64 +from collections import OrderedDict + +from django.utils.crypto import constant_time_compare +from django.utils.encoding import force_bytes +from django.utils.translation import gettext_noop as _ +from django.contrib.auth.hashers import mask_hash, BasePasswordHasher + + +class SHA512PasswordHasher(BasePasswordHasher): + """ + The SHA512 password hashing algorithm + + It is used to migrate passwords from old Symfony2 photos server. + https://github.com/symfony/symfony/blob/2.8/src/Symfony/Component/Security/Core/Encoder/MessageDigestPasswordEncoder.php + """ + algorithm = "sha512" + + def encode(self, password, salt): + assert password is not None + assert salt and '$' not in salt + hash = hashlib.sha512(force_bytes(password + "{" + salt + "}")) + hash = base64.b64encode(hash) + encoded = "%s$%s$%s" % (self.algorithm, salt, hash) + encoded = encoded[:128] + return encoded + + def verify(self, password, encoded): + algorithm, salt, hash = encoded.split('$', 2) + assert algorithm == self.algorithm + encoded_2 = self.encode(password, salt) + return constant_time_compare(encoded, encoded_2) + + def safe_summary(self, encoded): + algorithm, salt, hash = encoded.split('$', 2) + assert algorithm == self.algorithm + return OrderedDict([ + (_('algorithm'), algorithm), + (_('salt'), mask_hash(salt, show=2)), + (_('hash'), mask_hash(hash)), + ]) + + def harden_runtime(self, password, encoded): + pass diff --git a/photo21/settings.py b/photo21/settings.py index 88216ed..f5aaaa0 100644 --- a/photo21/settings.py +++ b/photo21/settings.py @@ -129,6 +129,11 @@ AUTH_PASSWORD_VALIDATORS = [ }, ] +PASSWORD_HASHERS = [ + 'django.contrib.auth.hashers.PBKDF2PasswordHasher', + 'photo21.hashers.SHA512PasswordHasher', +] + # Internationalization # https://docs.djangoproject.com/en/2.2/topics/i18n/ From bf7e20e2829f72eccd775cb68350bf9347cc69d7 Mon Sep 17 00:00:00 2001 From: Alexandre Iooss Date: Tue, 12 Oct 2021 13:32:05 +0200 Subject: [PATCH 10/15] Fix symfony password hasher --- photo21/hashers.py | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/photo21/hashers.py b/photo21/hashers.py index e94397e..0c3305a 100644 --- a/photo21/hashers.py +++ b/photo21/hashers.py @@ -17,23 +17,26 @@ class SHA512PasswordHasher(BasePasswordHasher): """ algorithm = "sha512" - def encode(self, password, salt): + def encode(self, password, iteration, salt): assert password is not None assert salt and '$' not in salt - hash = hashlib.sha512(force_bytes(password + "{" + salt + "}")) - hash = base64.b64encode(hash) - encoded = "%s$%s$%s" % (self.algorithm, salt, hash) - encoded = encoded[:128] - return encoded + salted = force_bytes(password + "{" + salt + "}") + digest = hashlib.sha512(salted).digest() + # "stretch" hash + for _i in range(1, int(iteration)): + digest = hashlib.sha512(digest + salted).digest() + digest = base64.b64encode(digest).decode() + encoded = "%s$%s$%s$%s" % (self.algorithm, iteration, salt, digest) + return encoded[:128] def verify(self, password, encoded): - algorithm, salt, hash = encoded.split('$', 2) + algorithm, iteration, salt, hash = encoded.split('$', 3) assert algorithm == self.algorithm - encoded_2 = self.encode(password, salt) + encoded_2 = self.encode(password, iteration, salt) return constant_time_compare(encoded, encoded_2) def safe_summary(self, encoded): - algorithm, salt, hash = encoded.split('$', 2) + algorithm, iteration, salt, hash = encoded.split('$', 3) assert algorithm == self.algorithm return OrderedDict([ (_('algorithm'), algorithm), From c946262565741767ea8f18a766a86e542142da60 Mon Sep 17 00:00:00 2001 From: Alexandre Iooss Date: Tue, 12 Oct 2021 17:30:37 +0200 Subject: [PATCH 11/15] Add margin between gallery samples --- photologue_custom/templates/photologue/gallery_archive.html | 2 +- .../templates/photologue/gallery_archive_year.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/photologue_custom/templates/photologue/gallery_archive.html b/photologue_custom/templates/photologue/gallery_archive.html index d68fcee..116d78c 100644 --- a/photologue_custom/templates/photologue/gallery_archive.html +++ b/photologue_custom/templates/photologue/gallery_archive.html @@ -23,7 +23,7 @@ {% if latest %}
{% for gallery in latest %} -
+
{% include "photologue/includes/gallery_sample.html" %}
{% endfor %} diff --git a/photologue_custom/templates/photologue/gallery_archive_year.html b/photologue_custom/templates/photologue/gallery_archive_year.html index 63db8b0..84f535c 100644 --- a/photologue_custom/templates/photologue/gallery_archive_year.html +++ b/photologue_custom/templates/photologue/gallery_archive_year.html @@ -17,7 +17,7 @@ {% if object_list %}
{% for gallery in object_list %} -
+
{% include "photologue/includes/gallery_sample.html" %}
{% endfor %} From 84d956d4336617c61aee1656a99e47d933c59f23 Mon Sep 17 00:00:00 2001 From: Alexandre Iooss Date: Tue, 12 Oct 2021 17:30:52 +0200 Subject: [PATCH 12/15] Only show 32 more recent galleries --- photologue_custom/templates/photologue/gallery_archive.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/photologue_custom/templates/photologue/gallery_archive.html b/photologue_custom/templates/photologue/gallery_archive.html index 116d78c..babfaeb 100644 --- a/photologue_custom/templates/photologue/gallery_archive.html +++ b/photologue_custom/templates/photologue/gallery_archive.html @@ -22,7 +22,7 @@
{% if latest %}
- {% for gallery in latest %} + {% for gallery in latest|slice:":32" %}
{% include "photologue/includes/gallery_sample.html" %}
From 99e3370d39baed7fb4a397a20758176b49f1e44f Mon Sep 17 00:00:00 2001 From: Alexandre Iooss Date: Tue, 12 Oct 2021 17:47:14 +0200 Subject: [PATCH 13/15] Add date and time in legend --- photologue_custom/templates/photologue/gallery_detail.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/photologue_custom/templates/photologue/gallery_detail.html b/photologue_custom/templates/photologue/gallery_detail.html index d5545f4..2d6528a 100644 --- a/photologue_custom/templates/photologue/gallery_detail.html +++ b/photologue_custom/templates/photologue/gallery_detail.html @@ -34,7 +34,7 @@ From 0dd9d7cb379e53af582def1eef4b976ed0cc0b18 Mon Sep 17 00:00:00 2001 From: Alexandre Iooss Date: Tue, 12 Oct 2021 17:49:13 +0200 Subject: [PATCH 14/15] Do not show time in gallery sample --- .../templates/photologue/includes/gallery_sample.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/photologue_custom/templates/photologue/includes/gallery_sample.html b/photologue_custom/templates/photologue/includes/gallery_sample.html index 8dcc05c..34d53a8 100644 --- a/photologue_custom/templates/photologue/includes/gallery_sample.html +++ b/photologue_custom/templates/photologue/includes/gallery_sample.html @@ -6,7 +6,7 @@ {% endfor %}
{{ gallery.title }}
-

{% trans "Published" %} {{ gallery.date_added }}

+

{% trans "Published" %} {{ gallery.date_added|date }}

{% if gallery.description %}

{{ gallery.description|safe }}

{% endif %}
From c3a63935b1e309296b920e5333c8e9091cb34031 Mon Sep 17 00:00:00 2001 From: Alexandre Iooss Date: Tue, 12 Oct 2021 18:34:12 +0200 Subject: [PATCH 15/15] Do not show gallery creation time in details --- photologue_custom/templates/photologue/gallery_detail.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/photologue_custom/templates/photologue/gallery_detail.html b/photologue_custom/templates/photologue/gallery_detail.html index 2d6528a..03415cb 100644 --- a/photologue_custom/templates/photologue/gallery_detail.html +++ b/photologue_custom/templates/photologue/gallery_detail.html @@ -22,7 +22,7 @@ {% block content %}

{{ gallery.title }}

-

{% trans "Published" %} {{ gallery.date_added }}

+

{% trans "Published" %} {{ gallery.date_added|date }}

{% if gallery.extended.tags.all %}

Tags : {% for tag in gallery.extended.tags.all %}