diff --git a/authens/static/authens/css/authens.css b/authens/static/authens/css/authens.css index 4cedbc5..b2c1d14 100644 --- a/authens/static/authens/css/authens.css +++ b/authens/static/authens/css/authens.css @@ -1,3 +1,7 @@ +/* + Generic page layout +*/ + html, body { width: 100%; background: #eee; @@ -7,31 +11,43 @@ html, body { } #container { - display: flex; - flex-flow: row wrap; padding: 10% 1em; min-width: 300px; max-width: 900px; margin: auto; } -h2 { - margin: 0; - padding: 15px; +#container-title { width: 100%; background: #505160; color: white; +} + +#container-title h2 { + padding: 15px; font-weight: initial; font-size: 2em; + margin: 0; } +#container-content { + text-align: center; + width: 100%; + display: flex; + flex-flow: row wrap; +} + +/* + Background color definitions +*/ + .cas { background: #4D85BD; color: white; } .exte { - background: #749F2A; + background: #598507; color: white; } @@ -40,48 +56,81 @@ h2 { color: white; } -#container-content { +/* + Login switch layout +*/ + +.big-button { + flex: 1; + height: 200px; + min-width: 300px; text-align: center; - width: 100%; + font-size: 2.5em; + color: white; + line-height: 200px; + text-decoration: none; } -.auth_form { - padding: 0.5em; - font-size: 1.5em; +.big-button :hover { + text-decoration: underline; } +/* + Message styling +*/ + .error { background: red; color: white; width: 100%; - padding: 0.5em; + padding: 0.5em 0; margin: 0; font-size: 1.2em; 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 { text-align: left; font-size: 0.8em; 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 { font-size: 1em; } -input[type="text"], input[type="password"] { +input[type="text"], input[type="password"], input[type="email"] { border: 0; padding: 5px; width: 100%; @@ -111,17 +160,16 @@ select { text-align: end; } -a { - flex: 1; - height: 200px; - min-width: 300px; - text-align: center; - font-size: 2.5em; - color: white; - line-height: 200px; - text-decoration: none; +/* + Misc +*/ + +.forgot-pwd { + width:100%; + padding: 0.5em 0px 1em; + font-size: 1.2em; } -a:hover { - text-decoration: underline; +.forgot-pwd > a { + color: white; } diff --git a/authens/templates/authens/auth_form_field.html b/authens/templates/authens/auth_form_field.html deleted file mode 100644 index ff8fdfb..0000000 --- a/authens/templates/authens/auth_form_field.html +++ /dev/null @@ -1,4 +0,0 @@ - - {{ field.label_tag }} - {{ field }} - \ No newline at end of file diff --git a/authens/templates/authens/base.html b/authens/templates/authens/base.html index 19642fd..e79bd67 100644 --- a/authens/templates/authens/base.html +++ b/authens/templates/authens/base.html @@ -16,8 +16,23 @@
{% block container-top %} -

{% if request.site.name %}{{ request.site.name }}{% else %}AuthENS{% endif %} - {% block container-title %}{% endblock %}

+
+

{% if request.site.name %}{{ request.site.name }}{% else %}AuthENS{% endif %} - {% block container-title %}{% endblock %}

+
{% endblock %} + + {% if messages %} + {% for message in messages %} +

+ {% if 'safe' in message.tags %} + {{ message|safe }} + {% else %} + {{ message }} + {% endif %} +

+ {% endfor %} + {% endif %} + {% block content %}{% endblock %}
diff --git a/authens/templates/authens/login_switch.html b/authens/templates/authens/login_switch.html index a01b8fd..50d38e3 100644 --- a/authens/templates/authens/login_switch.html +++ b/authens/templates/authens/login_switch.html @@ -6,19 +6,15 @@ {% endblock %} {% block content %} - -
- {% trans "Clipper" %} -
+
+ + {% trans "Clipper" %} - -
- {% trans "Mot de passe" %} -
+
+ {% trans "Mot de passe" %} - -
- {% trans "Vieilleux" %} -
+
+ {% trans "Vieilleux" %} +
{% endblock %} diff --git a/authens/templates/authens/old_cas_login.html b/authens/templates/authens/oldcas_login.html similarity index 100% rename from authens/templates/authens/old_cas_login.html rename to authens/templates/authens/oldcas_login.html diff --git a/authens/templates/authens/pwd_login.html b/authens/templates/authens/pwd_login.html index 41e582f..5f48f78 100644 --- a/authens/templates/authens/pwd_login.html +++ b/authens/templates/authens/pwd_login.html @@ -8,5 +8,9 @@ {% block content %}
{% include "authens/form_full_snippet.html" with submit_text="Se connecter" %} + +
+ {% trans "Mot de passe oublié ?" %} +
{% endblock %} diff --git a/authens/templates/authens/pwd_reset.html b/authens/templates/authens/pwd_reset.html new file mode 100644 index 0000000..ebb521e --- /dev/null +++ b/authens/templates/authens/pwd_reset.html @@ -0,0 +1,12 @@ +{% extends "authens/base.html" %} +{% load i18n %} + +{% block container-title %} +{% trans "Réinitialisation du mot de passe" %} +{% endblock %} + +{% block content %} +
+ {% include "authens/form_full_snippet.html" with submit_text="Envoyer un mail" %} +
+{% endblock %} diff --git a/authens/templates/authens/pwd_reset_confirm.html b/authens/templates/authens/pwd_reset_confirm.html new file mode 100644 index 0000000..3e79bd9 --- /dev/null +++ b/authens/templates/authens/pwd_reset_confirm.html @@ -0,0 +1,12 @@ +{% extends "authens/base.html" %} +{% load i18n %} + +{% block container-title %} +{% trans "Nouveau mot de passe" %} +{% endblock %} + +{% block content %} +
+ {% include "authens/form_full_snippet.html" with submit_text="Enregistrer" %} +
+{% endblock %} diff --git a/authens/templates/authens/pwd_reset_email.txt b/authens/templates/authens/pwd_reset_email.txt new file mode 100644 index 0000000..9071193 --- /dev/null +++ b/authens/templates/authens/pwd_reset_email.txt @@ -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 %} \ No newline at end of file diff --git a/authens/templates/authens/pwd_reset_subject.txt b/authens/templates/authens/pwd_reset_subject.txt new file mode 100644 index 0000000..8d48712 --- /dev/null +++ b/authens/templates/authens/pwd_reset_subject.txt @@ -0,0 +1 @@ +Réinitialisation de votre mot de passe {{site_name}} \ No newline at end of file diff --git a/authens/urls.py b/authens/urls.py index 1fe4eb9..28dcbfa 100644 --- a/authens/urls.py +++ b/authens/urls.py @@ -9,4 +9,10 @@ urlpatterns = [ path("login/pwd", views.PasswordLoginView.as_view(), name="login.pwd"), path("login/oldcas", views.OldCASLoginView.as_view(), name="login.oldcas"), path("logout", views.LogoutView.as_view(), name="logout"), + path("reset/pwd", views.PasswordResetView.as_view(), name="reset.pwd"), + path( + "reset/pwd///", + views.PasswordResetConfirmView.as_view(), + name="reset.pwd.confirm", + ), ] diff --git a/authens/views.py b/authens/views.py index d5641a5..c1d4f66 100644 --- a/authens/views.py +++ b/authens/views.py @@ -3,13 +3,16 @@ from urllib.parse import urlparse, urlunparse from django.conf import settings from django.contrib import auth from django.contrib.auth import views as auth_views +from django.contrib.messages.views import SuccessMessageMixin from django.core.exceptions import PermissionDenied -from django.views.generic import TemplateView, View from django.shortcuts import redirect +from django.utils import timezone 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.utils import get_cas_client class NextPageMixin: @@ -80,10 +83,33 @@ class PasswordLoginView(auth_views.LoginView): 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): - template_name = "authens/old_cas_login.html" + template_name = "authens/oldcas_login.html" authentication_form = OldCASAuthForm + def get_initial(self): + return {"entrance_year": timezone.now().year - 5} + class LogoutView(auth_views.LogoutView): """Logout view of AuthENS. diff --git a/example_site/example_site/settings.py b/example_site/example_site/settings.py index a2eb594..fdb8240 100644 --- a/example_site/example_site/settings.py +++ b/example_site/example_site/settings.py @@ -128,6 +128,8 @@ AUTHENTICATION_BACKENDS = [ "authens.backends.OldCASBackend", ] LOGIN_URL = reverse_lazy("authens:login") +EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend" + # This is cosmetic LOGIN_REDIRECT_URL = reverse_lazy("home")