Merge branch 'Aufinal/password_management' into 'master'
Vues de réinitialisation de mot de passe See merge request klub-dev-ens/authens!15
This commit is contained in:
commit
ffd5155061
13 changed files with 185 additions and 55 deletions
|
@ -1,3 +1,7 @@
|
||||||
|
/*
|
||||||
|
Generic page layout
|
||||||
|
*/
|
||||||
|
|
||||||
html, body {
|
html, body {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background: #eee;
|
background: #eee;
|
||||||
|
@ -7,31 +11,43 @@ html, body {
|
||||||
}
|
}
|
||||||
|
|
||||||
#container {
|
#container {
|
||||||
display: flex;
|
|
||||||
flex-flow: row wrap;
|
|
||||||
padding: 10% 1em;
|
padding: 10% 1em;
|
||||||
min-width: 300px;
|
min-width: 300px;
|
||||||
max-width: 900px;
|
max-width: 900px;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
h2 {
|
#container-title {
|
||||||
margin: 0;
|
|
||||||
padding: 15px;
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background: #505160;
|
background: #505160;
|
||||||
color: white;
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
#container-title h2 {
|
||||||
|
padding: 15px;
|
||||||
font-weight: initial;
|
font-weight: initial;
|
||||||
font-size: 2em;
|
font-size: 2em;
|
||||||
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#container-content {
|
||||||
|
text-align: center;
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-flow: row wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Background color definitions
|
||||||
|
*/
|
||||||
|
|
||||||
.cas {
|
.cas {
|
||||||
background: #4D85BD;
|
background: #4D85BD;
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
.exte {
|
.exte {
|
||||||
background: #749F2A;
|
background: #598507;
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,48 +56,81 @@ h2 {
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
#container-content {
|
/*
|
||||||
|
Login switch layout
|
||||||
|
*/
|
||||||
|
|
||||||
|
.big-button {
|
||||||
|
flex: 1;
|
||||||
|
height: 200px;
|
||||||
|
min-width: 300px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
width: 100%;
|
font-size: 2.5em;
|
||||||
|
color: white;
|
||||||
|
line-height: 200px;
|
||||||
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.auth_form {
|
.big-button :hover {
|
||||||
padding: 0.5em;
|
text-decoration: underline;
|
||||||
font-size: 1.5em;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Message styling
|
||||||
|
*/
|
||||||
|
|
||||||
.error {
|
.error {
|
||||||
background: red;
|
background: red;
|
||||||
color: white;
|
color: white;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 0.5em;
|
padding: 0.5em 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-size: 1.2em;
|
font-size: 1.2em;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.success {
|
||||||
|
background: green;
|
||||||
|
color: white;
|
||||||
|
width: 100%;
|
||||||
|
padding: 0.5em 0;
|
||||||
|
margin: 0;
|
||||||
|
font-size: 1.2em;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Form styling
|
||||||
|
*/
|
||||||
|
|
||||||
|
.auth_form {
|
||||||
|
width: 100%;
|
||||||
|
padding: 0.5em;
|
||||||
|
font-size: 1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth_form table {
|
||||||
|
margin: 20px auto;
|
||||||
|
border-spacing: 0.3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth_form th {
|
||||||
|
padding: 10px 0;
|
||||||
|
vertical-align: text-top;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
ul.errorlist {
|
ul.errorlist {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
font-size: 0.8em;
|
font-size: 0.8em;
|
||||||
padding-left: 20px;
|
padding-left: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.auth_form table {
|
|
||||||
margin: 20px auto;
|
|
||||||
border-spacing: 0.3em;
|
|
||||||
}
|
|
||||||
|
|
||||||
th {
|
|
||||||
padding: 5px 0;
|
|
||||||
vertical-align: text-top;
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
input {
|
input {
|
||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="text"], input[type="password"] {
|
input[type="text"], input[type="password"], input[type="email"] {
|
||||||
border: 0;
|
border: 0;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -111,17 +160,16 @@ select {
|
||||||
text-align: end;
|
text-align: end;
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
/*
|
||||||
flex: 1;
|
Misc
|
||||||
height: 200px;
|
*/
|
||||||
min-width: 300px;
|
|
||||||
text-align: center;
|
.forgot-pwd {
|
||||||
font-size: 2.5em;
|
width:100%;
|
||||||
color: white;
|
padding: 0.5em 0px 1em;
|
||||||
line-height: 200px;
|
font-size: 1.2em;
|
||||||
text-decoration: none;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
a:hover {
|
.forgot-pwd > a {
|
||||||
text-decoration: underline;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
<tr>
|
|
||||||
<th>{{ field.label_tag }}</th>
|
|
||||||
<td>{{ field }}</td>
|
|
||||||
</tr>
|
|
|
@ -16,8 +16,23 @@
|
||||||
<body>
|
<body>
|
||||||
<div id="container">
|
<div id="container">
|
||||||
{% block container-top %}
|
{% block container-top %}
|
||||||
<h2>{% if request.site.name %}{{ request.site.name }}{% else %}AuthENS{% endif %} - {% block container-title %}{% endblock %}</h2>
|
<div id="container-title">
|
||||||
|
<h2>{% if request.site.name %}{{ request.site.name }}{% else %}AuthENS{% endif %} - {% block container-title %}{% endblock %}</h2>
|
||||||
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
{% if messages %}
|
||||||
|
{% for message in messages %}
|
||||||
|
<p class="{{ message.level_tag }}">
|
||||||
|
{% if 'safe' in message.tags %}
|
||||||
|
{{ message|safe }}
|
||||||
|
{% else %}
|
||||||
|
{{ message }}
|
||||||
|
{% endif %}
|
||||||
|
</p>
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{% block content %}{% endblock %}
|
{% block content %}{% endblock %}
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -6,19 +6,15 @@
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<a href="{% url "authens:login.cas" %}?next={{ next| urlencode }}">
|
<div id="container-content">
|
||||||
<div class="big-button cas">
|
<a class="big-button cas" href="{% url "authens:login.cas" %}?next={{ next| urlencode }}">
|
||||||
{% trans "Clipper" %}
|
{% trans "Clipper" %}
|
||||||
</div>
|
|
||||||
</a>
|
</a>
|
||||||
<a href="{% url "authens:login.pwd" %}?next={{ next| urlencode }}">
|
<a class="big-button exte" href="{% url "authens:login.pwd" %}?next={{ next| urlencode }}">
|
||||||
<div class="big-button exte">
|
{% trans "Mot de passe" %}
|
||||||
{% trans "Mot de passe" %}
|
|
||||||
</div>
|
|
||||||
</a>
|
</a>
|
||||||
<a href="{% url "authens:login.oldcas" %}?next={{ next| urlencode }}">
|
<a class="big-button oldcas" href="{% url "authens:login.oldcas" %}?next={{ next| urlencode }}">
|
||||||
<div class="big-button oldcas">
|
{% trans "Vieilleux" %}
|
||||||
{% trans "Vieilleux" %}
|
|
||||||
</div>
|
|
||||||
</a>
|
</a>
|
||||||
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -8,5 +8,9 @@
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div id="container-content" class="exte">
|
<div id="container-content" class="exte">
|
||||||
{% include "authens/form_full_snippet.html" with submit_text="Se connecter" %}
|
{% include "authens/form_full_snippet.html" with submit_text="Se connecter" %}
|
||||||
|
|
||||||
|
<div class="forgot-pwd">
|
||||||
|
<a href={% url "authens:reset.pwd" %}>{% trans "Mot de passe oublié ?" %}</a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
12
authens/templates/authens/pwd_reset.html
Normal file
12
authens/templates/authens/pwd_reset.html
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
{% extends "authens/base.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block container-title %}
|
||||||
|
{% trans "Réinitialisation du mot de passe" %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div id="container-content" class="exte">
|
||||||
|
{% include "authens/form_full_snippet.html" with submit_text="Envoyer un mail" %}
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
12
authens/templates/authens/pwd_reset_confirm.html
Normal file
12
authens/templates/authens/pwd_reset_confirm.html
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
{% extends "authens/base.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block container-title %}
|
||||||
|
{% trans "Nouveau mot de passe" %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div id="container-content" class="exte">
|
||||||
|
{% include "authens/form_full_snippet.html" with submit_text="Enregistrer" %}
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
12
authens/templates/authens/pwd_reset_email.txt
Normal file
12
authens/templates/authens/pwd_reset_email.txt
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
{% load i18n %}{% autoescape off %}
|
||||||
|
{% blocktrans %}Quelqu'un (probablement vous) a demandé la réinitialisation du mot de passe associé à cette addresse sur {{ site_name }}.{% endblocktrans %}
|
||||||
|
|
||||||
|
{% blocktrans %}S'il s'agit bien de vous, vous pouvez vous rendre à l'adresse suivante pour en choisir un nouveau : {% endblocktrans %}
|
||||||
|
{% block reset_link %}
|
||||||
|
{{ protocol }}://{{ domain }}{% url "authens:reset.pwd.confirm" uidb64=uid token=token %}
|
||||||
|
{% endblock %}
|
||||||
|
{% blocktrans with username=user.get_username %}Pour information, votre nom d'utilisateur est le suivant : {{ username }}{% endblocktrans %}
|
||||||
|
|
||||||
|
{% block signature %}{% blocktrans %}L'équipe {{site_name}}{% endblocktrans %}{% endblock %}
|
||||||
|
|
||||||
|
{% endautoescape %}
|
1
authens/templates/authens/pwd_reset_subject.txt
Normal file
1
authens/templates/authens/pwd_reset_subject.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Réinitialisation de votre mot de passe {{site_name}}
|
|
@ -9,4 +9,10 @@ urlpatterns = [
|
||||||
path("login/pwd", views.PasswordLoginView.as_view(), name="login.pwd"),
|
path("login/pwd", views.PasswordLoginView.as_view(), name="login.pwd"),
|
||||||
path("login/oldcas", views.OldCASLoginView.as_view(), name="login.oldcas"),
|
path("login/oldcas", views.OldCASLoginView.as_view(), name="login.oldcas"),
|
||||||
path("logout", views.LogoutView.as_view(), name="logout"),
|
path("logout", views.LogoutView.as_view(), name="logout"),
|
||||||
|
path("reset/pwd", views.PasswordResetView.as_view(), name="reset.pwd"),
|
||||||
|
path(
|
||||||
|
"reset/pwd/<uidb64>/<token>/",
|
||||||
|
views.PasswordResetConfirmView.as_view(),
|
||||||
|
name="reset.pwd.confirm",
|
||||||
|
),
|
||||||
]
|
]
|
||||||
|
|
|
@ -3,13 +3,16 @@ from urllib.parse import urlparse, urlunparse
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib import auth
|
from django.contrib import auth
|
||||||
from django.contrib.auth import views as auth_views
|
from django.contrib.auth import views as auth_views
|
||||||
|
from django.contrib.messages.views import SuccessMessageMixin
|
||||||
from django.core.exceptions import PermissionDenied
|
from django.core.exceptions import PermissionDenied
|
||||||
from django.views.generic import TemplateView, View
|
|
||||||
from django.shortcuts import redirect
|
from django.shortcuts import redirect
|
||||||
|
from django.utils import timezone
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
from django.urls import reverse_lazy
|
||||||
|
from django.views.generic import TemplateView, View
|
||||||
|
|
||||||
from authens.utils import get_cas_client
|
|
||||||
from authens.forms import OldCASAuthForm
|
from authens.forms import OldCASAuthForm
|
||||||
|
from authens.utils import get_cas_client
|
||||||
|
|
||||||
|
|
||||||
class NextPageMixin:
|
class NextPageMixin:
|
||||||
|
@ -80,10 +83,33 @@ class PasswordLoginView(auth_views.LoginView):
|
||||||
template_name = "authens/pwd_login.html"
|
template_name = "authens/pwd_login.html"
|
||||||
|
|
||||||
|
|
||||||
|
class PasswordResetView(SuccessMessageMixin, auth_views.PasswordResetView):
|
||||||
|
template_name = "authens/pwd_reset.html"
|
||||||
|
email_template_name = "authens/pwd_reset_email.txt"
|
||||||
|
subject_template_name = "authens/pwd_reset_subject.txt"
|
||||||
|
success_url = reverse_lazy("authens:login")
|
||||||
|
|
||||||
|
success_message = _(
|
||||||
|
"Un email de réinitialisation vient d'être envoyé à l'adresse indiquée !"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class PasswordResetConfirmView(
|
||||||
|
SuccessMessageMixin, auth_views.PasswordResetConfirmView
|
||||||
|
):
|
||||||
|
template_name = "authens/pwd_reset_confirm.html"
|
||||||
|
success_url = reverse_lazy("authens:login")
|
||||||
|
|
||||||
|
success_message = _("Mot de passe modifié avec succès !")
|
||||||
|
|
||||||
|
|
||||||
class OldCASLoginView(auth_views.LoginView):
|
class OldCASLoginView(auth_views.LoginView):
|
||||||
template_name = "authens/old_cas_login.html"
|
template_name = "authens/oldcas_login.html"
|
||||||
authentication_form = OldCASAuthForm
|
authentication_form = OldCASAuthForm
|
||||||
|
|
||||||
|
def get_initial(self):
|
||||||
|
return {"entrance_year": timezone.now().year - 5}
|
||||||
|
|
||||||
|
|
||||||
class LogoutView(auth_views.LogoutView):
|
class LogoutView(auth_views.LogoutView):
|
||||||
"""Logout view of AuthENS.
|
"""Logout view of AuthENS.
|
||||||
|
|
|
@ -128,6 +128,8 @@ AUTHENTICATION_BACKENDS = [
|
||||||
"authens.backends.OldCASBackend",
|
"authens.backends.OldCASBackend",
|
||||||
]
|
]
|
||||||
LOGIN_URL = reverse_lazy("authens:login")
|
LOGIN_URL = reverse_lazy("authens:login")
|
||||||
|
EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend"
|
||||||
|
|
||||||
|
|
||||||
# This is cosmetic
|
# This is cosmetic
|
||||||
LOGIN_REDIRECT_URL = reverse_lazy("home")
|
LOGIN_REDIRECT_URL = reverse_lazy("home")
|
||||||
|
|
Loading…
Reference in a new issue