Merge branch 'initial_data' into 'master'
Initial data See merge request bde/photo21!9
This commit is contained in:
commit
2a886248c2
12 changed files with 151 additions and 14 deletions
|
|
@ -75,7 +75,7 @@ production néccessite **une installation de Debian Bullseye**.
|
||||||
$ sudo apt install nginx git gettext uwsgi uwsgi-plugin-python3 python3-venv \
|
$ sudo apt install nginx git gettext uwsgi uwsgi-plugin-python3 python3-venv \
|
||||||
python3-certbot-nginx python3-django python3-django-crispy-forms \
|
python3-certbot-nginx python3-django python3-django-crispy-forms \
|
||||||
python3-django-taggit python3-pil python3-exifread python3-django-allauth \
|
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`**
|
2. **Clonage du dépot dans `/var/www/photos/photo21`**
|
||||||
|
|
@ -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 collectstatic
|
||||||
$ sudo -u www-data ./venv/bin/python ./manage.py check
|
$ 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 migrate
|
||||||
|
$ sudo -u www-data ./venv/bin/python ./manage.py loaddata initial
|
||||||
$ sudo ./venv/bin/python ./manage.py compilemessages
|
$ sudo ./venv/bin/python ./manage.py compilemessages
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
58
photo21/fixtures/initial.json
Normal file
58
photo21/fixtures/initial.json
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"model": "sites.site",
|
||||||
|
"pk": 1,
|
||||||
|
"fields": {
|
||||||
|
"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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
48
photo21/hashers.py
Normal file
48
photo21/hashers.py
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
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, iteration, salt):
|
||||||
|
assert password is not None
|
||||||
|
assert salt and '$' not in salt
|
||||||
|
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, iteration, salt, hash = encoded.split('$', 3)
|
||||||
|
assert algorithm == self.algorithm
|
||||||
|
encoded_2 = self.encode(password, iteration, salt)
|
||||||
|
return constant_time_compare(encoded, encoded_2)
|
||||||
|
|
||||||
|
def safe_summary(self, encoded):
|
||||||
|
algorithm, iteration, salt, hash = encoded.split('$', 3)
|
||||||
|
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
|
||||||
|
|
@ -29,6 +29,8 @@ SECRET_KEY = 'CHANGE_ME'
|
||||||
DEBUG = True
|
DEBUG = True
|
||||||
|
|
||||||
ALLOWED_HOSTS = [
|
ALLOWED_HOSTS = [
|
||||||
|
"127.0.0.1",
|
||||||
|
"localhost",
|
||||||
"photos.crans.org",
|
"photos.crans.org",
|
||||||
"photos-dev.crans.org",
|
"photos-dev.crans.org",
|
||||||
]
|
]
|
||||||
|
|
@ -127,6 +129,11 @@ AUTH_PASSWORD_VALIDATORS = [
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
PASSWORD_HASHERS = [
|
||||||
|
'django.contrib.auth.hashers.PBKDF2PasswordHasher',
|
||||||
|
'photo21.hashers.SHA512PasswordHasher',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
# Internationalization
|
# Internationalization
|
||||||
# https://docs.djangoproject.com/en/2.2/topics/i18n/
|
# https://docs.djangoproject.com/en/2.2/topics/i18n/
|
||||||
|
|
@ -167,7 +174,7 @@ MEDIA_URL = '/media/'
|
||||||
|
|
||||||
LOCALE_PATHS = [os.path.join(BASE_DIR, 'photo21/locale')]
|
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
|
# Email settings
|
||||||
if DEBUG:
|
if DEBUG:
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from photologue.admin import GalleryAdmin as GalleryAdminDefault
|
from photologue.admin import GalleryAdmin as GalleryAdminDefault
|
||||||
from photologue.admin import PhotoAdmin as PhotoAdminDefault
|
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
|
from .models import GalleryExtended, PhotoExtended
|
||||||
|
|
||||||
|
|
@ -34,5 +34,8 @@ class PhotoAdmin(PhotoAdminDefault):
|
||||||
|
|
||||||
admin.site.unregister(Gallery)
|
admin.site.unregister(Gallery)
|
||||||
admin.site.unregister(Photo)
|
admin.site.unregister(Photo)
|
||||||
|
admin.site.unregister(PhotoEffect)
|
||||||
|
admin.site.unregister(PhotoSize)
|
||||||
|
admin.site.unregister(Watermark)
|
||||||
admin.site.register(Gallery, GalleryAdmin)
|
admin.site.register(Gallery, GalleryAdmin)
|
||||||
admin.site.register(Photo, PhotoAdmin)
|
admin.site.register(Photo, PhotoAdmin)
|
||||||
|
|
|
||||||
23
photologue_custom/migrations/0002_auto_20211011_1956.py
Normal file
23
photologue_custom/migrations/0002_auto_20211011_1956.py
Normal file
|
|
@ -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'),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -10,7 +10,7 @@ class GalleryExtended(models.Model):
|
||||||
gallery = models.OneToOneField(
|
gallery = models.OneToOneField(
|
||||||
Gallery,
|
Gallery,
|
||||||
related_name='extended',
|
related_name='extended',
|
||||||
on_delete='cascade',
|
on_delete=models.CASCADE,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Add tags
|
# Add tags
|
||||||
|
|
@ -41,7 +41,7 @@ class PhotoExtended(models.Model):
|
||||||
photo = models.OneToOneField(
|
photo = models.OneToOneField(
|
||||||
Photo,
|
Photo,
|
||||||
related_name='extented',
|
related_name='extented',
|
||||||
on_delete='cascade'
|
on_delete=models.CASCADE,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Add a owner field to PhotoExtended
|
# Add a owner field to PhotoExtended
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,8 @@
|
||||||
<main class="col-md-10">
|
<main class="col-md-10">
|
||||||
{% if latest %}
|
{% if latest %}
|
||||||
<div class="row mb-2">
|
<div class="row mb-2">
|
||||||
{% for gallery in latest %}
|
{% for gallery in latest|slice:":32" %}
|
||||||
<div class="col-md-3">
|
<div class="col-md-3 mb-2">
|
||||||
{% include "photologue/includes/gallery_sample.html" %}
|
{% include "photologue/includes/gallery_sample.html" %}
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
{% if object_list %}
|
{% if object_list %}
|
||||||
<div class="row mb-2">
|
<div class="row mb-2">
|
||||||
{% for gallery in object_list %}
|
{% for gallery in object_list %}
|
||||||
<div class="col-md-3">
|
<div class="col-md-3 mb-2">
|
||||||
{% include "photologue/includes/gallery_sample.html" %}
|
{% include "photologue/includes/gallery_sample.html" %}
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h1>{{ gallery.title }}</h1>
|
<h1>{{ gallery.title }}</h1>
|
||||||
<p class="text-muted small">{% trans "Published" %} {{ gallery.date_added }}</p>
|
<p class="text-muted small">{% trans "Published" %} {{ gallery.date_added|date }}</p>
|
||||||
{% if gallery.extended.tags.all %}
|
{% if gallery.extended.tags.all %}
|
||||||
<p class="text-muted">
|
<p class="text-muted">
|
||||||
Tags : {% for tag in gallery.extended.tags.all %}
|
Tags : {% for tag in gallery.extended.tags.all %}
|
||||||
|
|
@ -34,7 +34,7 @@
|
||||||
<div class="gallery-list mb-3" id="lightgallery">
|
<div class="gallery-list mb-3" id="lightgallery">
|
||||||
{% for photo in gallery.public %}
|
{% for photo in gallery.public %}
|
||||||
<a href="{{ photo.get_absolute_url }}" data-src="{{ photo.get_display_url }}" data-download-url="{{ photo.image.url }}">
|
<a href="{{ photo.get_absolute_url }}" data-src="{{ photo.get_display_url }}" data-download-url="{{ photo.image.url }}">
|
||||||
<img src="{{ photo.get_thumbnail_url }}" class="img-thumbnail" alt="{{ photo.title }}">
|
<img src="{{ photo.get_thumbnail_url }}" class="img-thumbnail" alt="{{ photo.title }}{% if photo.date_taken %} - {{ photo.date_taken|date }} {{ photo.date_taken|time }}{% endif %}">
|
||||||
</a>
|
</a>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h5 class="card-title">{{ gallery.title }}</h5>
|
<h5 class="card-title">{{ gallery.title }}</h5>
|
||||||
<p class="card-text text-muted small mb-0">{% trans "Published" %} {{ gallery.date_added }}</p>
|
<p class="card-text text-muted small mb-0">{% trans "Published" %} {{ gallery.date_added|date }}</p>
|
||||||
{% if gallery.description %}<p class="card-text small mb-0">{{ gallery.description|safe }}</p>{% endif %}
|
{% if gallery.description %}<p class="card-text small mb-0">{{ gallery.description|safe }}</p>{% endif %}
|
||||||
<a href="{{ gallery.get_absolute_url }}" class="stretched-link"></a>
|
<a href="{{ gallery.get_absolute_url }}" class="stretched-link"></a>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
3
tox.ini
3
tox.ini
|
|
@ -1,8 +1,5 @@
|
||||||
[tox]
|
[tox]
|
||||||
envlist =
|
envlist =
|
||||||
# Debian Buster Python
|
|
||||||
py37-django22
|
|
||||||
|
|
||||||
# Ubuntu 20.04 Python
|
# Ubuntu 20.04 Python
|
||||||
py38-django22
|
py38-django22
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue