Merge branch 'no_ip_whitelist' into 'master'
Rework account forms See merge request bde/photo21!2
This commit is contained in:
commit
e2c826ec1d
13 changed files with 111 additions and 67 deletions
|
|
@ -1,13 +1,31 @@
|
|||
from django import forms
|
||||
from django.contrib.auth.forms import UserCreationForm
|
||||
from django.contrib.auth.models import User
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
|
||||
class RegistrationForm(UserCreationForm):
|
||||
email = forms.EmailField(label="Email", widget=forms.TextInput(), required=True)
|
||||
first_name = forms.CharField(label="Prénom", widget=forms.TextInput(), required=True)
|
||||
last_name = forms.CharField(label="Nom", widget=forms.TextInput(), required=True)
|
||||
email = forms.EmailField(
|
||||
label=_("Email address"),
|
||||
widget=forms.TextInput(),
|
||||
required=True,
|
||||
help_text=_(
|
||||
"Please enter a valid email address ending with `@crans.org` or "
|
||||
"`@ens-paris-saclay.fr`."
|
||||
),
|
||||
)
|
||||
|
||||
def clean_email(self):
|
||||
"""
|
||||
Check that the email address ends with a trusted domain.
|
||||
"""
|
||||
email = self.cleaned_data.get("email")
|
||||
if not email.endswith("@crans.org") and not email.endswith("@ens-paris-saclay.fr"):
|
||||
raise forms.ValidationError(
|
||||
_("Must end with `@crans.org` or `@ens-paris-saclay.fr`.")
|
||||
)
|
||||
return email
|
||||
|
||||
class Meta:
|
||||
model = User
|
||||
fields = ["username", "password1", "password2", "email", "first_name", "last_name"]
|
||||
fields = ["username", "password1", "password2", "email"]
|
||||
|
|
|
|||
|
|
@ -1,9 +1,20 @@
|
|||
{% extends "base.html" %}
|
||||
{% comment %}
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
{% endcomment %}
|
||||
{% load i18n crispy_forms_tags %}
|
||||
{% block title %}{% trans "Sign up" %}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1>Création d'utilisateur</h1>
|
||||
<form action="" method="post">{% csrf_token %}
|
||||
{{ form.as_p }}
|
||||
<br>
|
||||
<input type="submit" value="Envoyer">
|
||||
</form>
|
||||
<div class="card bg-light">
|
||||
<h3 class="card-header text-center">
|
||||
{% trans "Sign up" %}
|
||||
</h3>
|
||||
<div class="card-body">
|
||||
<form method="post">{% csrf_token %}
|
||||
{{ form|crispy }}
|
||||
<input type="submit" value="Envoyer" class="btn btn-primary mt-4">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
|
@ -2,5 +2,5 @@ from django.urls import path
|
|||
|
||||
from .views import signup
|
||||
urlpatterns = [
|
||||
path('', signup, name='registration'),
|
||||
path('registration/', signup, name='registration'),
|
||||
]
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2021-09-23 08:18+0000\n"
|
||||
"POT-Creation-Date: 2021-10-08 11:03+0000\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
|
|
@ -18,19 +18,41 @@ msgstr ""
|
|||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
|
||||
#: photo21/settings.py:128
|
||||
#: accounts/forms.py:9
|
||||
msgid "Email address"
|
||||
msgstr "Adresse email"
|
||||
|
||||
#: accounts/forms.py:13
|
||||
msgid ""
|
||||
"Please enter a valid email address ending with `@crans.org` or `@ens-paris-"
|
||||
"saclay.fr`."
|
||||
msgstr ""
|
||||
"Veuillez entrer une adresse email valide finissant par `@crans.org` ou `@ens-"
|
||||
"paris-saclay.fr`."
|
||||
|
||||
#: accounts/forms.py:25
|
||||
msgid "Must end with `@crans.org` or `@ens-paris-saclay.fr`."
|
||||
msgstr "Doit finir par `@crans.org` ou `@ens-paris-saclay.fr`."
|
||||
|
||||
#: accounts/templates/accounts/registration.html:6
|
||||
#: accounts/templates/accounts/registration.html:11
|
||||
#: photo21/templates/base.html:70
|
||||
msgid "Sign up"
|
||||
msgstr "Inscription"
|
||||
|
||||
#: photo21/settings.py:132
|
||||
msgid "German"
|
||||
msgstr ""
|
||||
|
||||
#: photo21/settings.py:129
|
||||
#: photo21/settings.py:133
|
||||
msgid "English"
|
||||
msgstr ""
|
||||
|
||||
#: photo21/settings.py:130
|
||||
#: photo21/settings.py:134
|
||||
msgid "Spanish"
|
||||
msgstr ""
|
||||
|
||||
#: photo21/settings.py:131
|
||||
#: photo21/settings.py:135
|
||||
msgid "French"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -90,13 +112,13 @@ msgstr "Galeries"
|
|||
msgid "Admin"
|
||||
msgstr ""
|
||||
|
||||
#: photo21/templates/base.html:47
|
||||
#: photo21/templates/base.html:51
|
||||
msgid "Log out"
|
||||
msgstr ""
|
||||
|
||||
#: photo21/templates/base.html:53 photo21/templates/registration/login.html:6
|
||||
#: photo21/templates/registration/login.html:15
|
||||
#: photo21/templates/registration/login.html:37
|
||||
#: photo21/templates/base.html:61 photo21/templates/registration/login.html:6
|
||||
#: photo21/templates/registration/login.html:11
|
||||
#: photo21/templates/registration/login.html:33
|
||||
#: photo21/templates/registration/password_reset_complete.html:15
|
||||
msgid "Log in"
|
||||
msgstr ""
|
||||
|
|
@ -113,24 +135,24 @@ msgstr ""
|
|||
msgid "Log in again"
|
||||
msgstr ""
|
||||
|
||||
#: photo21/templates/registration/login.html:20
|
||||
#: photo21/templates/registration/login.html:16
|
||||
#, python-format
|
||||
msgid ""
|
||||
"You are authenticated as %(username)s, but are not authorized to access this "
|
||||
"page. Would you like to login to a different account?"
|
||||
msgstr ""
|
||||
|
||||
#: photo21/templates/registration/login.html:29
|
||||
#: photo21/templates/registration/login.html:25
|
||||
msgid ""
|
||||
"You must be logged with a staff account with the higher mask to access "
|
||||
"Django Admin."
|
||||
msgstr ""
|
||||
|
||||
#: photo21/templates/registration/login.html:39
|
||||
#: photo21/templates/registration/login.html:35
|
||||
msgid "Forgotten your password or username?"
|
||||
msgstr ""
|
||||
|
||||
#: photo21/templates/registration/login.html:43
|
||||
#: photo21/templates/registration/login.html:39
|
||||
msgid "If any problem, please contact the server owners at"
|
||||
msgstr "En cas de problème, contactez les administrateurs à"
|
||||
|
||||
|
|
@ -220,7 +242,7 @@ msgstr ""
|
|||
msgid "Published"
|
||||
msgstr ""
|
||||
|
||||
#: photologue_custom/templates/photologue/gallery_detail.html:34
|
||||
#: photologue_custom/templates/photologue/gallery_detail.html:41
|
||||
msgid "Download all gallery"
|
||||
msgstr "Télécharger toute la galerie"
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
from django.http import HttpResponseRedirect
|
||||
from django.conf import settings
|
||||
|
||||
import ipaddress
|
||||
import re
|
||||
|
||||
|
||||
|
|
@ -20,30 +19,9 @@ class LoginRequiredMiddleware:
|
|||
If user is not authenticated and external, redirect to login view
|
||||
before calling the view.
|
||||
"""
|
||||
if not request.user.is_authenticated and not self.check_ip(request):
|
||||
if not request.user.is_authenticated:
|
||||
if not self.whitelist_re.match(request.path_info):
|
||||
return HttpResponseRedirect(settings.LOGIN_URL)
|
||||
|
||||
response = self.get_response(request)
|
||||
return response
|
||||
|
||||
def check_ip(self, request):
|
||||
"""
|
||||
Return true if IP is in authorized range
|
||||
"""
|
||||
# Get IP address
|
||||
if 'HTTP_X_REAL_IP' in request.META:
|
||||
ip = request.META.get('HTTP_X_REAL_IP')
|
||||
elif 'HTTP_X_FORWARDED_FOR' in request.META:
|
||||
ip = request.META.get('HTTP_X_FORWARDED_FOR').split(', ')[0]
|
||||
else:
|
||||
ip = request.META.get('REMOTE_ADDR')
|
||||
ip = ipaddress.ip_address(ip)
|
||||
|
||||
# Check against ranges
|
||||
if hasattr(settings, 'LOGIN_EXEMPT_IP_RANGE'):
|
||||
for ip_range in settings.LOGIN_EXEMPT_IP_RANGE:
|
||||
net = ipaddress.ip_network(ip_range)
|
||||
if ip in net:
|
||||
return True
|
||||
return False
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ INSTALLED_APPS = [
|
|||
'django.contrib.sites',
|
||||
'django.contrib.messages',
|
||||
'django.contrib.staticfiles',
|
||||
'crispy_forms',
|
||||
'photologue_custom',
|
||||
'photologue',
|
||||
'accounts',
|
||||
|
|
@ -163,8 +164,8 @@ SESSION_COOKIE_AGE = 60 * 60 * 3
|
|||
# Use only one Django Sites
|
||||
SITE_ID = 1
|
||||
|
||||
# use Bootstrap forms
|
||||
CRISPY_TEMPLATE_PACK = 'bootstrap4'
|
||||
|
||||
# Photologue
|
||||
PHOTOLOGUE_GALLERY_SAMPLE_SIZE = 1
|
||||
|
||||
# IP range whitelist
|
||||
LOGIN_EXEMPT_IP_RANGE = ["185.230.76.0/22", "2a0c:700::/32"]
|
||||
|
|
|
|||
|
|
@ -44,15 +44,32 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
|||
{% if request.user.is_authenticated %}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{% url 'logout' %}">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-box-arrow-right" viewBox="0 0 16 16">
|
||||
<path fill-rule="evenodd" d="M10 12.5a.5.5 0 0 1-.5.5h-8a.5.5 0 0 1-.5-.5v-9a.5.5 0 0 1 .5-.5h8a.5.5 0 0 1 .5.5v2a.5.5 0 0 0 1 0v-2A1.5 1.5 0 0 0 9.5 2h-8A1.5 1.5 0 0 0 0 3.5v9A1.5 1.5 0 0 0 1.5 14h8a1.5 1.5 0 0 0 1.5-1.5v-2a.5.5 0 0 0-1 0v2z"/>
|
||||
<path fill-rule="evenodd" d="M15.854 8.354a.5.5 0 0 0 0-.708l-3-3a.5.5 0 0 0-.708.708L14.293 7.5H5.5a.5.5 0 0 0 0 1h8.793l-2.147 2.146a.5.5 0 0 0 .708.708l3-3z"/>
|
||||
</svg>
|
||||
{% trans "Log out" %}
|
||||
</a>
|
||||
</li>
|
||||
{% else %}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{% url 'login' %}">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-box-arrow-in-right" viewBox="0 0 16 16">
|
||||
<path fill-rule="evenodd" d="M6 3.5a.5.5 0 0 1 .5-.5h8a.5.5 0 0 1 .5.5v9a.5.5 0 0 1-.5.5h-8a.5.5 0 0 1-.5-.5v-2a.5.5 0 0 0-1 0v2A1.5 1.5 0 0 0 6.5 14h8a1.5 1.5 0 0 0 1.5-1.5v-9A1.5 1.5 0 0 0 14.5 2h-8A1.5 1.5 0 0 0 5 3.5v2a.5.5 0 0 0 1 0v-2z"/>
|
||||
<path fill-rule="evenodd" d="M11.854 8.354a.5.5 0 0 0 0-.708l-3-3a.5.5 0 1 0-.708.708L10.293 7.5H1.5a.5.5 0 0 0 0 1h8.793l-2.147 2.146a.5.5 0 0 0 .708.708l3-3z"/>
|
||||
</svg>
|
||||
{% trans "Log in" %}
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{% url 'registration' %}">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-person-plus" viewBox="0 0 16 16">
|
||||
<path d="M6 8a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm2-3a2 2 0 1 1-4 0 2 2 0 0 1 4 0zm4 8c0 1-1 1-1 1H1s-1 0-1-1 1-4 6-4 6 3 6 4zm-1-.004c-.001-.246-.154-.986-.832-1.664C9.516 10.68 8.289 10 6 10c-2.29 0-3.516.68-4.168 1.332-.678.678-.83 1.418-.832 1.664h10z"/>
|
||||
<path fill-rule="evenodd" d="M13.5 5a.5.5 0 0 1 .5.5V7h1.5a.5.5 0 0 1 0 1H14v1.5a.5.5 0 0 1-1 0V8h-1.5a.5.5 0 0 1 0-1H13V5.5a.5.5 0 0 1 .5-.5z"/>
|
||||
</svg>
|
||||
{% trans "Sign up" %}
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -2,13 +2,9 @@
|
|||
{% comment %}
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
{% endcomment %}
|
||||
{% load i18n static %}
|
||||
{% load i18n crispy_forms_tags %}
|
||||
{% block title %}{% trans "Log in" %}{% endblock %}
|
||||
|
||||
{% block extracss %}
|
||||
<link rel="stylesheet" href="{% static "registration/css/login.css" %}">
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="card bg-light mx-auto" style="max-width: 35rem;">
|
||||
<h3 class="card-header text-center">
|
||||
|
|
@ -33,8 +29,8 @@ SPDX-License-Identifier: GPL-2.0-or-later
|
|||
{% endif %}
|
||||
|
||||
<form action="{{ app_path }}" method="post" id="login-form">{% csrf_token %}
|
||||
{{ form }}
|
||||
<input type="submit" value="{% trans 'Log in' %}" class="btn btn-primary btn-block btn-lg">
|
||||
{{ form|crispy }}
|
||||
<input type="submit" value="{% trans 'Log in' %}" class="btn btn-primary btn-lg mt-2">
|
||||
<a href="{% url 'password_reset' %}"
|
||||
class="badge bg-light text-dark">{% trans 'Forgotten your password or username?' %}</a>
|
||||
</form>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
{% comment %}
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
{% endcomment %}
|
||||
{% load i18n %}
|
||||
{% load i18n crispy_forms_tags %}
|
||||
|
||||
{% block content %}
|
||||
<div class="card bg-light">
|
||||
|
|
@ -12,7 +12,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
|||
<div class="card-body">
|
||||
<form method="post">{% csrf_token %}
|
||||
<p>{% trans "Please enter your old password, for security's sake, and then enter your new password twice so we can verify you typed it in correctly." %}</p>
|
||||
{{ form }}
|
||||
{{ form|crispy }}
|
||||
<input class="btn btn-primary" type="submit" value="{% trans 'Change my password' %}">
|
||||
</form>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
{% comment %}
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
{% endcomment %}
|
||||
{% load i18n %}
|
||||
{% load i18n crispy_forms_tags %}
|
||||
|
||||
{% block content %}
|
||||
<div class="card bg-light">
|
||||
|
|
@ -13,8 +13,8 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
|||
{% if validlink %}
|
||||
<p>{% trans "Please enter your new password twice so we can verify you typed it in correctly." %}</p>
|
||||
<form method="post">{% csrf_token %}
|
||||
{{ form }}
|
||||
<input class="btn btn-primary" type="submit" value="{% trans 'Change my password' %}">
|
||||
{{ form|crispy }}
|
||||
<input class="btn btn-primary mt-4" type="submit" value="{% trans 'Change my password' %}">
|
||||
</form>
|
||||
{% else %}
|
||||
<p>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
{% comment %}
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
{% endcomment %}
|
||||
{% load i18n %}
|
||||
{% load i18n crispy_forms_tags %}
|
||||
|
||||
{% block content %}
|
||||
<div class="card bg-light">
|
||||
|
|
@ -14,8 +14,8 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
|||
|
||||
<form method="post">
|
||||
{% csrf_token %}
|
||||
{{ form }}
|
||||
<input class="btn btn-primary" type="submit" value="{% trans 'Reset my password' %}">
|
||||
{{ form|crispy }}
|
||||
<input class="btn btn-primary mt-4" type="submit" value="{% trans 'Reset my password' %}">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -26,10 +26,10 @@ urlpatterns = [
|
|||
path('photologue/', include('photologue_custom.urls')),
|
||||
path('photologue/', include('photologue.urls', namespace='photologue')),
|
||||
path('accounts/', include('django.contrib.auth.urls')),
|
||||
path('accounts/', include('accounts.urls')),
|
||||
path('i18n/', include('django.conf.urls.i18n')),
|
||||
path('admin/', admin.site.urls),
|
||||
path('admin/doc/', include('django.contrib.admindocs.urls')),
|
||||
path('accounts/registration/', include('accounts.urls'))
|
||||
]
|
||||
|
||||
if settings.DEBUG:
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
Django~=2.2.20
|
||||
django-photologue~=3.13
|
||||
django-taggit~=1.5.1
|
||||
django-crispy-forms~=1.7
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue