From 90aa558896f465947a5230a4348fca0c39b25f5c Mon Sep 17 00:00:00 2001 From: Robin Champenois Date: Sun, 24 Jan 2021 23:11:10 +0100 Subject: [PATCH] Gestion des adresses et du mot de passe --- avisstage/forms.py | 44 ++- .../migrations/0004_allauth_to_authens.py | 8 +- avisstage/models.py | 5 +- avisstage/sass/_responsive.scss | 4 +- avisstage/sass/screen.scss | 58 ++- avisstage/static/css/screen.css | 343 ++++++++++-------- .../avisstage/compte/aconfirmer.html | 19 + .../templates/avisstage/compte/edit_mdp.html | 29 ++ .../avisstage/compte/email_supprime.html | 18 + .../avisstage/compte/parametres.html | 76 ++++ .../avisstage/formulaires/profil.html | 9 +- .../templates/avisstage/mails/reinit_mdp.html | 8 + .../templates/avisstage/mails/reinit_mdp.txt | 1 + avisstage/templates/avisstage/perso.html | 52 +-- avisstage/urls.py | 17 + avisstage/views.py | 141 ++++++- experiENS/settings_base.py | 6 +- 17 files changed, 650 insertions(+), 188 deletions(-) create mode 100644 avisstage/templates/avisstage/compte/aconfirmer.html create mode 100644 avisstage/templates/avisstage/compte/edit_mdp.html create mode 100644 avisstage/templates/avisstage/compte/email_supprime.html create mode 100644 avisstage/templates/avisstage/compte/parametres.html create mode 100644 avisstage/templates/avisstage/mails/reinit_mdp.html create mode 100644 avisstage/templates/avisstage/mails/reinit_mdp.txt diff --git a/avisstage/forms.py b/avisstage/forms.py index 8af5c57..12e88ea 100644 --- a/avisstage/forms.py +++ b/avisstage/forms.py @@ -1,11 +1,14 @@ -# coding: utf-8 +import unicodedata from django import forms +from django.contrib.auth.forms import PasswordResetForm from django.utils import timezone +from simple_email_confirmation.models import EmailAddress + import re -from .models import Normalien, Stage, Lieu, AvisLieu, AvisStage +from .models import Normalien, Stage, Lieu, AvisLieu, AvisStage, User from .widgets import LatLonField # Sur-classe utile @@ -107,3 +110,40 @@ class FeedbackForm(forms.Form): objet = forms.CharField(label="Objet", required=True) message = forms.CharField(label="Message", required=True, widget=forms.widgets.Textarea()) +# Nouvelle adresse mail +class AdresseEmailForm(forms.Form): + def __init__(self, _user, **kwargs): + self._user = _user + super().__init__(**kwargs) + email = forms.EmailField(widget=forms.widgets.EmailInput(attrs={"placeholder": "Nouvelle adresse"})) + + def clean_email(self): + email = self.cleaned_data["email"] + if EmailAddress.objects.filter(user=self._user, email=email).exists(): + raise forms.ValidationError( + "Cette adresse est déjà associée à ce compte") + return email + + +def _unicode_ci_compare(s1, s2): + """ + Perform case-insensitive comparison of two identifiers, using the + recommended algorithm from Unicode Technical Report 36, section + 2.11.2(B)(2). + """ + return unicodedata.normalize('NFKC', s1).casefold() == unicodedata.normalize('NFKC', s2).casefold() + + +# (Ré)initialisation du mot de passe +class ReinitMdpForm(PasswordResetForm): + def get_users(self, email): + """Override default method to allow unusable passwords""" + email_field_name = User.get_email_field_name() + active_users = User._default_manager.filter(**{ + '%s__iexact' % email_field_name: email, + 'is_active': True, + }) + return ( + u for u in active_users + if _unicode_ci_compare(email, getattr(u, email_field_name)) + ) diff --git a/avisstage/migrations/0004_allauth_to_authens.py b/avisstage/migrations/0004_allauth_to_authens.py index 164e9ab..3998752 100644 --- a/avisstage/migrations/0004_allauth_to_authens.py +++ b/avisstage/migrations/0004_allauth_to_authens.py @@ -77,8 +77,14 @@ def forwards(apps, schema_editor): if "@" not in user.username: print(user.username) continue - entrance_year = "20" + saccount.extra_data.get( + entrance_year = saccount.extra_data.get( "entrance_year", user.username.split("@")[1]) + try: + entrance_year = 2000 + int(entrance_year) + except ValueError: + print(entrance_year) + continue + new_conns.append(CASAccount(user=user, cas_login=clipper, entrance_year=int(entrance_year))) diff --git a/avisstage/models.py b/avisstage/models.py index 79f96f0..7588207 100644 --- a/avisstage/models.py +++ b/avisstage/models.py @@ -35,8 +35,9 @@ class Normalien(models.Model): promotion = models.CharField(u"Promotion", max_length=40, blank=True) mail = models.EmailField(u"Adresse e-mail permanente", max_length=200, blank=True) - contactez_moi = models.BooleanField(u"Inviter les visiteurs à me contacter", - default=True) + contactez_moi = models.BooleanField( + u"Inviter les visiteurs à me contacter", + default=True, help_text="Affiche votre adresse e-mail principale sur votre profil public") bio = models.TextField(u"À propos de moi", blank=True, default="") en_scolarite = models.BooleanField(default=False, blank=True) diff --git a/avisstage/sass/_responsive.scss b/avisstage/sass/_responsive.scss index c37acef..fb1457c 100644 --- a/avisstage/sass/_responsive.scss +++ b/avisstage/sass/_responsive.scss @@ -177,14 +177,14 @@ display: block; text-align: left; font-size: 0.95em; - color: $compl * 0.8; + color: darken($compl, 20%); margin-top: 0; width: auto; } .help_text { text-align: right; - color: $fond * 0.4; + color: darken($fond, 60%); } .input { diff --git a/avisstage/sass/screen.scss b/avisstage/sass/screen.scss index 9147b3a..8ee09e5 100644 --- a/avisstage/sass/screen.scss +++ b/avisstage/sass/screen.scss @@ -46,7 +46,7 @@ em, i { a { font-weight: bold; - color: $compl * 0.9; + color: darken($compl, 10%); text-decoration: none; } @@ -107,7 +107,7 @@ header { color: lighten($fond, 40%); &:hover { - background: $barre * 0.6; + background: darken($barre, 40%); } } } @@ -181,7 +181,6 @@ p.warning { li { display: table; width: 100%; - //border: 1px solid $fond * 1.3; background: #fff; margin: 12px; @@ -363,6 +362,57 @@ section.profil { } } +section.two-cols { + display: flex; + display: flexbox; + align-items: center; + & > * { + flex: 1; + width: 50%; + margin: 10px; + } +} + +ul.mes-emails { + li { + display: flex; + background: #fff; + margin: 5px; + padding: 10px; + min-height: 70px; + justify-content: space-between; + align-items: center; + flex-wrap: wrap; + + & > * { + flex: 1; + text-align: center; + } + + .adresse { + text-align: left; + font-weight: bold; + } + + .confirmee { + width: 20px; + } + + .supprimer { + flex: 0.7; + } + + form { + display: flex; + align-items: center; + justify-content: space-around; + .field { + flex: 1; + } + } + } +} + // // // Détail d'un stage @@ -432,7 +482,7 @@ input[type="submit"], .btn { font: $textfontsize $textfont; background-color: $fond; color: #fff; - border: 1px solid $fond * 0.7; + border: 1px solid darken($fond, 30%); border-radius: 5px; padding: 8px 12px; display: inline-block; diff --git a/avisstage/static/css/screen.css b/avisstage/static/css/screen.css index 0acc127..c1a8b02 100644 --- a/avisstage/static/css/screen.css +++ b/avisstage/static/css/screen.css @@ -1,5 +1,5 @@ @charset "UTF-8"; -/* line 5, ../../../../../../../../var/lib/gems/2.3.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */ +/* line 5, ../../../../../../../../var/lib/gems/2.7.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */ html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, @@ -21,45 +21,45 @@ time, mark, audio, video { vertical-align: baseline; } -/* line 22, ../../../../../../../../var/lib/gems/2.3.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */ +/* line 22, ../../../../../../../../var/lib/gems/2.7.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */ html { line-height: 1; } -/* line 24, ../../../../../../../../var/lib/gems/2.3.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */ +/* line 24, ../../../../../../../../var/lib/gems/2.7.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */ ol, ul { list-style: none; } -/* line 26, ../../../../../../../../var/lib/gems/2.3.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */ +/* line 26, ../../../../../../../../var/lib/gems/2.7.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */ table { border-collapse: collapse; border-spacing: 0; } -/* line 28, ../../../../../../../../var/lib/gems/2.3.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */ +/* line 28, ../../../../../../../../var/lib/gems/2.7.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */ caption, th, td { text-align: left; font-weight: normal; vertical-align: middle; } -/* line 30, ../../../../../../../../var/lib/gems/2.3.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */ +/* line 30, ../../../../../../../../var/lib/gems/2.7.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */ q, blockquote { quotes: none; } -/* line 103, ../../../../../../../../var/lib/gems/2.3.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */ +/* line 103, ../../../../../../../../var/lib/gems/2.7.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */ q:before, q:after, blockquote:before, blockquote:after { content: ""; content: none; } -/* line 32, ../../../../../../../../var/lib/gems/2.3.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */ +/* line 32, ../../../../../../../../var/lib/gems/2.7.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */ a img { border: none; } -/* line 116, ../../../../../../../../var/lib/gems/2.3.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */ +/* line 116, ../../../../../../../../var/lib/gems/2.7.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */ article, aside, details, figcaption, figure, footer, header, hgroup, main, menu, nav, section, summary { display: block; } @@ -170,7 +170,7 @@ em, i { /* line 47, ../../sass/screen.scss */ a { font-weight: bold; - color: #e08c1d; + color: #e08206; text-decoration: none; } @@ -235,7 +235,7 @@ header nav ul li a { } /* line 109, ../../sass/screen.scss */ header nav ul li a:hover { - background: #446219; + background: black; } /* line 117, ../../sass/screen.scss */ header a { @@ -306,22 +306,22 @@ p.warning { background: #fff; margin: 12px; } -/* line 188, ../../sass/screen.scss */ +/* line 187, ../../sass/screen.scss */ .condensed-stages li > *, .condensed-stages li:before { display: table-cell; vertical-align: middle; padding: 15px; } -/* line 193, ../../sass/screen.scss */ +/* line 192, ../../sass/screen.scss */ .condensed-stages li a { width: auto; } -/* line 195, ../../sass/screen.scss */ +/* line 194, ../../sass/screen.scss */ .condensed-stages li a:hover { background: #e08206; color: #fff; } -/* line 200, ../../sass/screen.scss */ +/* line 199, ../../sass/screen.scss */ .condensed-stages li:before { content: ""; text-align: right; @@ -329,78 +329,78 @@ p.warning { opacity: 0.8; color: #000; } -/* line 207, ../../sass/screen.scss */ +/* line 206, ../../sass/screen.scss */ .condensed-stages li.stage-brouillon:before { content: "Brouillon"; background: #f93a93; } -/* line 211, ../../sass/screen.scss */ +/* line 210, ../../sass/screen.scss */ .condensed-stages li.stage-publie:before { content: "Publié"; background: #419be9; } -/* line 215, ../../sass/screen.scss */ +/* line 214, ../../sass/screen.scss */ .condensed-stages li.stage-ajout:before { content: "+"; color: #000; } -/* line 223, ../../sass/screen.scss */ +/* line 222, ../../sass/screen.scss */ .stage-liste li { display: block; position: relative; } -/* line 227, ../../sass/screen.scss */ +/* line 226, ../../sass/screen.scss */ .stage-liste li.date-maj { font-weight: 300; font-size: 0.9em; padding: 3px 0; font-style: italic; } -/* line 233, ../../sass/screen.scss */ +/* line 232, ../../sass/screen.scss */ .stage-liste li.stage { padding: 10px; background: #fff; margin: 10px; border-left: 5px solid #f99b20; } -/* line 239, ../../sass/screen.scss */ +/* line 238, ../../sass/screen.scss */ .stage-liste li.stage h3 { font-size: 1.4em; padding-left: 5px; } -/* line 243, ../../sass/screen.scss */ +/* line 242, ../../sass/screen.scss */ .stage-liste li.stage h3 > a { color: #0f4c82; } -/* line 247, ../../sass/screen.scss */ +/* line 246, ../../sass/screen.scss */ .stage-liste li.stage h3 .auteur { font-size: 0.8em; } -/* line 250, ../../sass/screen.scss */ +/* line 249, ../../sass/screen.scss */ .stage-liste li.stage h3 .auteur, .stage-liste li.stage h3 .auteur a { font-family: "Dosis", sans-serif; font-weight: normal; } -/* line 257, ../../sass/screen.scss */ +/* line 256, ../../sass/screen.scss */ .stage-liste li .misc-hdr { margin-bottom: 10px; } -/* line 261, ../../sass/screen.scss */ +/* line 260, ../../sass/screen.scss */ .stage-liste li .misc-hdr .dates > span { display: table-cell; vertical-align: middle; } -/* line 265, ../../sass/screen.scss */ +/* line 264, ../../sass/screen.scss */ .stage-liste li .misc-hdr .dates .year { padding-left: 8px; } -/* line 268, ../../sass/screen.scss */ +/* line 267, ../../sass/screen.scss */ .stage-liste li .misc-hdr .dates svg text { font-size: 0.8; } -/* line 276, ../../sass/screen.scss */ +/* line 275, ../../sass/screen.scss */ a.hoverlink { position: absolute; display: block; @@ -411,7 +411,7 @@ a.hoverlink { z-index: 2; } -/* line 286, ../../sass/screen.scss */ +/* line 285, ../../sass/screen.scss */ ul.infos { margin: 0 -3px; padding: 0; @@ -420,7 +420,7 @@ ul.infos { justify-content: space-between; width: 100; } -/* line 294, ../../sass/screen.scss */ +/* line 293, ../../sass/screen.scss */ ul.infos li { display: inline-block; padding: 5px; @@ -432,28 +432,28 @@ ul.infos li { text-align: center; background-color: #ddd; } -/* line 305, ../../sass/screen.scss */ +/* line 304, ../../sass/screen.scss */ ul.infos li.thematique { color: #0d3f6b; background-color: #86bff1; } -/* line 309, ../../sass/screen.scss */ +/* line 308, ../../sass/screen.scss */ ul.infos li.matiere { color: #395214; background-color: #c7e699; } -/* line 313, ../../sass/screen.scss */ +/* line 312, ../../sass/screen.scss */ ul.infos li.lieu { color: #7c043c; background-color: #fb84bc; } -/* line 317, ../../sass/screen.scss */ +/* line 316, ../../sass/screen.scss */ ul.infos li.year { background-color: #950548; color: #fff; display: none; } -/* line 322, ../../sass/screen.scss */ +/* line 321, ../../sass/screen.scss */ ul.infos li.avis-len { background-color: transparent; border: 1px solid #eee; @@ -461,29 +461,29 @@ ul.infos li.avis-len { padding: 4px; padding-bottom: 2px; } -/* line 329, ../../sass/screen.scss */ +/* line 328, ../../sass/screen.scss */ ul.infos li.avis-len.avis-vide { border-bottom-color: #ddd; } -/* line 332, ../../sass/screen.scss */ +/* line 331, ../../sass/screen.scss */ ul.infos li.avis-len.avis-court { border-bottom-color: #ffff66; } -/* line 335, ../../sass/screen.scss */ +/* line 334, ../../sass/screen.scss */ ul.infos li.avis-len.avis-moyen { border-bottom-color: #86bff1; } -/* line 338, ../../sass/screen.scss */ +/* line 337, ../../sass/screen.scss */ ul.infos li.avis-len.avis-long { border-bottom-color: #a5d65c; } -/* line 344, ../../sass/screen.scss */ +/* line 343, ../../sass/screen.scss */ ul.infos:after { content: ""; flex: 1000; } -/* line 350, ../../sass/screen.scss */ +/* line 349, ../../sass/screen.scss */ section.profil { background: #fff; max-width: 600px; @@ -491,7 +491,7 @@ section.profil { margin: 5px auto; margin-bottom: 15px; } -/* line 357, ../../sass/screen.scss */ +/* line 356, ../../sass/screen.scss */ section.profil div.infos { border-bottom: 3px solid #1a82dd; display: flex; @@ -500,6 +500,59 @@ section.profil div.infos { flex-wrap: wrap; } +/* line 365, ../../sass/screen.scss */ +section.two-cols { + display: flex; + display: flexbox; + align-items: center; +} +/* line 369, ../../sass/screen.scss */ +section.two-cols > * { + flex: 1; + width: 50%; + margin: 10px; +} + +/* line 377, ../../sass/screen.scss */ +ul.mes-emails li { + display: flex; + background: #fff; + margin: 5px; + padding: 10px; + min-height: 70px; + justify-content: space-between; + align-items: center; + flex-wrap: wrap; +} +/* line 387, ../../sass/screen.scss */ +ul.mes-emails li > * { + flex: 1; + text-align: center; +} +/* line 392, ../../sass/screen.scss */ +ul.mes-emails li .adresse { + text-align: left; + font-weight: bold; +} +/* line 397, ../../sass/screen.scss */ +ul.mes-emails li .confirmee { + width: 20px; +} +/* line 401, ../../sass/screen.scss */ +ul.mes-emails li .supprimer { + flex: 0.7; +} +/* line 405, ../../sass/screen.scss */ +ul.mes-emails li form { + display: flex; + align-items: center; + justify-content: space-around; +} +/* line 409, ../../sass/screen.scss */ +ul.mes-emails li form .field { + flex: 1; +} + /* line 4, ../../sass/_stage_detail.scss */ article.stage .avis ul, article.stage .avis ol, div.tinymce ul, div.tinymce ol { list-style: unset; @@ -783,7 +836,7 @@ article.stage .section-wrapper .toc .toc-active a { border: 1px solid #ad0654; } -/* line 378, ../../sass/screen.scss */ +/* line 428, ../../sass/screen.scss */ input, textarea, select, div.tinymce, option, optgroup:before { background: #fff; font-size: 1em; @@ -793,13 +846,13 @@ input, textarea, select, div.tinymce, option, optgroup:before { padding: 5px; text-align: left; } -/* line 387, ../../sass/screen.scss */ +/* line 437, ../../sass/screen.scss */ input:focus, input.mce-edit-focus, textarea:focus, textarea.mce-edit-focus, select:focus, select.mce-edit-focus, div.tinymce:focus, div.tinymce.mce-edit-focus, option:focus, option.mce-edit-focus, optgroup:before:focus, optgroup:before.mce-edit-focus { background-color: #e9f5d6; outline: none; } -/* line 394, ../../sass/screen.scss */ +/* line 444, ../../sass/screen.scss */ input[type='text'], input[type='password'], input[type='email'], input[type='number'], textarea, select { border: none; @@ -809,7 +862,7 @@ input[type='email'], input[type='number'], textarea, select { transition: border 1s ease-out, background 1s ease-out; } -/* line 403, ../../sass/screen.scss */ +/* line 453, ../../sass/screen.scss */ select { -moz-appearance: none; appearance: none; @@ -823,42 +876,42 @@ select { background-color: #fff; background-size: contain; } -/* line 416, ../../sass/screen.scss */ +/* line 466, ../../sass/screen.scss */ select option { padding: 3px; white-space: pre-wrap; } -/* line 422, ../../sass/screen.scss */ +/* line 472, ../../sass/screen.scss */ select optgroup option { padding-left: 10px; } -/* line 425, ../../sass/screen.scss */ +/* line 475, ../../sass/screen.scss */ select optgroup:before { font-weight: bold; } -/* line 431, ../../sass/screen.scss */ +/* line 481, ../../sass/screen.scss */ input[type="submit"], .btn { font: 19px "Dosis", sans-serif; background-color: #8fcc33; color: #fff; - border: 1px solid #648f24; + border: 1px solid #395214; border-radius: 5px; padding: 8px 12px; display: inline-block; } -/* line 441, ../../sass/screen.scss */ +/* line 491, ../../sass/screen.scss */ p.submits { text-align: right; } -/* line 445, ../../sass/screen.scss */ +/* line 495, ../../sass/screen.scss */ form .commentaire { font-style: italic; } -/* line 449, ../../sass/screen.scss */ +/* line 499, ../../sass/screen.scss */ .edit-btn { border-color: #706c00; color: #000; @@ -867,14 +920,14 @@ form .commentaire { background-origin: content-box; background-size: contain; } -/* line 457, ../../sass/screen.scss */ +/* line 507, ../../sass/screen.scss */ .edit-btn:after { content: ""; width: 30px; display: inline-block; } -/* line 464, ../../sass/screen.scss */ +/* line 514, ../../sass/screen.scss */ textarea, div.tinymce { font-family: "Lato", sans-serif; border: none; @@ -884,20 +937,20 @@ textarea, div.tinymce { transition: border 1s ease-out, background 1s ease-out; } -/* line 473, ../../sass/screen.scss */ +/* line 523, ../../sass/screen.scss */ textarea { height: 200px; resize: vertical; } -/* line 481, ../../sass/screen.scss */ +/* line 531, ../../sass/screen.scss */ form .field { margin: 5px 0; display: flex; background: #fff; padding: 10px; } -/* line 487, ../../sass/screen.scss */ +/* line 537, ../../sass/screen.scss */ form .field label, form .field .label { display: inline-block; width: 250px; @@ -906,48 +959,48 @@ form .field label, form .field .label { padding-top: 5px; flex-shrink: 0; } -/* line 495, ../../sass/screen.scss */ +/* line 545, ../../sass/screen.scss */ form .field label.required:before, form .field .label.required:before { margin-right: 5px; content: "*"; color: #f70978; } -/* line 501, ../../sass/screen.scss */ +/* line 551, ../../sass/screen.scss */ form .field label { font-family: Alegreya, serif; font-weight: bold; } -/* line 505, ../../sass/screen.scss */ +/* line 555, ../../sass/screen.scss */ form .field .help_text { font-style: italic; font-size: 0.9em; } -/* line 509, ../../sass/screen.scss */ +/* line 559, ../../sass/screen.scss */ form .field .input { display: inline-block; flex-grow: 1; margin-right: 10px; } -/* line 519, ../../sass/screen.scss */ +/* line 569, ../../sass/screen.scss */ ul.as-selections, .selectize-control.multi { display: flex; flex-wrap: wrap; } -/* line 524, ../../sass/screen.scss */ +/* line 574, ../../sass/screen.scss */ ul.as-selections li, .selectize-control.multi li { display: inline-block; } -/* line 527, ../../sass/screen.scss */ +/* line 577, ../../sass/screen.scss */ ul.as-selections .selectize-input, ul.as-selections .selectize-dropdown, .selectize-control.multi .selectize-input, .selectize-control.multi .selectize-dropdown { font-size: 100%; line-height: 1.1; } -/* line 531, ../../sass/screen.scss */ +/* line 581, ../../sass/screen.scss */ ul.as-selections .as-selection-item, ul.as-selections .selectize-input > div, .selectize-control.multi .as-selection-item, @@ -959,7 +1012,7 @@ ul.as-selections .selectize-input > div, border-radius: 2px; font-weight: 500; } -/* line 540, ../../sass/screen.scss */ +/* line 590, ../../sass/screen.scss */ ul.as-selections .as-selection-item a.as-close, ul.as-selections .selectize-input > div a.as-close, .selectize-control.multi .as-selection-item a.as-close, @@ -969,51 +1022,51 @@ ul.as-selections .selectize-input > div a.as-close, cursor: pointer; margin-right: 5px; } -/* line 547, ../../sass/screen.scss */ +/* line 597, ../../sass/screen.scss */ ul.as-selections .as-selection-item.selected, ul.as-selections .selectize-input > div.selected, .selectize-control.multi .as-selection-item.selected, .selectize-control.multi .selectize-input > div.selected { background: #8fcc33; } -/* line 552, ../../sass/screen.scss */ +/* line 602, ../../sass/screen.scss */ ul.as-selections .as-original, .selectize-control.multi .as-original { flex-grow: 1; min-width: 200px; } -/* line 556, ../../sass/screen.scss */ +/* line 606, ../../sass/screen.scss */ ul.as-selections .as-original input, .selectize-control.multi .as-original input { width: 100%; } -/* line 562, ../../sass/screen.scss */ +/* line 612, ../../sass/screen.scss */ div.as-results { position: relative; z-index: 2; } -/* line 566, ../../sass/screen.scss */ +/* line 616, ../../sass/screen.scss */ div.as-results ul { position: absolute; width: 100%; background: #fff; border: 1px solid #d2ebad; } -/* line 573, ../../sass/screen.scss */ +/* line 623, ../../sass/screen.scss */ div.as-results ul li { padding: 3px 5px; } -/* line 579, ../../sass/screen.scss */ +/* line 629, ../../sass/screen.scss */ div.as-results ul li.as-result-item.active { background: #fddeb5; } -/* line 584, ../../sass/screen.scss */ +/* line 634, ../../sass/screen.scss */ div.as-results ul li.as-message { font-style: italic; } -/* line 594, ../../sass/screen.scss */ +/* line 644, ../../sass/screen.scss */ .window { display: none; position: fixed; @@ -1024,11 +1077,11 @@ div.as-results ul li.as-message { left: 0; z-index: 50; } -/* line 604, ../../sass/screen.scss */ +/* line 654, ../../sass/screen.scss */ .window.visible { display: block; } -/* line 608, ../../sass/screen.scss */ +/* line 658, ../../sass/screen.scss */ .window .window-bg { background: #000; opacity: 0.7; @@ -1039,7 +1092,7 @@ div.as-results ul li.as-message { top: 0; z-index: -1; } -/* line 619, ../../sass/screen.scss */ +/* line 669, ../../sass/screen.scss */ .window .window-content { position: relative; margin: 0 auto; @@ -1053,11 +1106,11 @@ div.as-results ul li.as-message { max-height: 100%; overflow: auto; } -/* line 633, ../../sass/screen.scss */ +/* line 683, ../../sass/screen.scss */ .window .window-content form label, .window .window-content form .label { width: 150px; } -/* line 639, ../../sass/screen.scss */ +/* line 689, ../../sass/screen.scss */ .window .window-closer { position: absolute; top: 0; @@ -1065,65 +1118,65 @@ div.as-results ul li.as-message { padding: 12px; z-index: 3; } -/* line 645, ../../sass/screen.scss */ +/* line 695, ../../sass/screen.scss */ .window .window-closer:after { content: "×"; } -/* line 656, ../../sass/screen.scss */ +/* line 706, ../../sass/screen.scss */ #lieu_widget .window-content { max-width: 800px; } -/* line 660, ../../sass/screen.scss */ +/* line 710, ../../sass/screen.scss */ #lieu_widget .lieu-ui { position: relative; width: 100%; min-width: 150px; flex: 2; } -/* line 666, ../../sass/screen.scss */ +/* line 716, ../../sass/screen.scss */ #lieu_widget .lieu-ui .map { height: 400px; width: 100%; } -/* line 670, ../../sass/screen.scss */ +/* line 720, ../../sass/screen.scss */ #lieu_widget .lieu-ui.hidden { display: none; } -/* line 673, ../../sass/screen.scss */ +/* line 723, ../../sass/screen.scss */ #lieu_widget .lieu-ui .masked { visibility: hidden; } -/* line 678, ../../sass/screen.scss */ +/* line 728, ../../sass/screen.scss */ #lieu_widget .lieu-choixmodif, #lieu_widget .lieu-options { display: none; } -/* line 682, ../../sass/screen.scss */ +/* line 732, ../../sass/screen.scss */ #lieu_widget .lieu-global { display: flex; width: 100%; flex-wrap: wrap; } -/* line 687, ../../sass/screen.scss */ +/* line 737, ../../sass/screen.scss */ #lieu_widget .lieu-global.with-options .lieu-options { display: block; } -/* line 694, ../../sass/screen.scss */ +/* line 744, ../../sass/screen.scss */ #lieu_widget.modif .lieu-global.with-options .lieu-options, #lieu_widget.edit .lieu-global.with-options .lieu-options { display: none; } -/* line 699, ../../sass/screen.scss */ +/* line 749, ../../sass/screen.scss */ #lieu_widget .lieu-options { padding: 7px; max-width: 350px; flex: 3; } -/* line 704, ../../sass/screen.scss */ +/* line 754, ../../sass/screen.scss */ #lieu_widget .lieu-options .lieu-suggestions { max-height: 300px; overflow-y: auto; } -/* line 708, ../../sass/screen.scss */ +/* line 758, ../../sass/screen.scss */ #lieu_widget .lieu-options .lieu-suggestions li { position: relative; background: #fff; @@ -1131,64 +1184,64 @@ div.as-results ul li.as-message { padding: 4px; font-size: 0.9em; } -/* line 714, ../../sass/screen.scss */ +/* line 764, ../../sass/screen.scss */ #lieu_widget .lieu-options .lieu-suggestions li:hover { background: #ccc; } -/* line 717, ../../sass/screen.scss */ +/* line 767, ../../sass/screen.scss */ #lieu_widget .lieu-options .lieu-suggestions li p { margin: 2px 0; } -/* line 720, ../../sass/screen.scss */ +/* line 770, ../../sass/screen.scss */ #lieu_widget .lieu-options .lieu-suggestions li .lieu-nom { font-weight: bold; } -/* line 723, ../../sass/screen.scss */ +/* line 773, ../../sass/screen.scss */ #lieu_widget .lieu-options .lieu-suggestions li .lieu-infos { font-size: 0.8em; display: flex; width: 100%; justify-content: space-between; } -/* line 729, ../../sass/screen.scss */ +/* line 779, ../../sass/screen.scss */ #lieu_widget .lieu-options .lieu-suggestions li .lieu-infos span { display: inline-block; text-overflow: ellipsis; overlow: hidden; } -/* line 740, ../../sass/screen.scss */ +/* line 790, ../../sass/screen.scss */ #lieu_widget.modif .lieu-choixmodif { display: unset; } -/* line 745, ../../sass/screen.scss */ +/* line 795, ../../sass/screen.scss */ #lieu_widget.modif .lieu-ui, #lieu_widget.attente .lieu-ui { display: none; } -/* line 752, ../../sass/screen.scss */ +/* line 802, ../../sass/screen.scss */ #lieu_widget.edit .lieu-ui .lieu-acinput { display: none; } -/* line 755, ../../sass/screen.scss */ +/* line 805, ../../sass/screen.scss */ #lieu_widget.edit .lieu-ui .map { height: 200px; } -/* line 761, ../../sass/screen.scss */ +/* line 811, ../../sass/screen.scss */ #lieu_widget #avis_lieu_vide { display: none; } -/* line 765, ../../sass/screen.scss */ +/* line 815, ../../sass/screen.scss */ #lieu_widget .message { background: #fddeb5; padding: 5px; font-style: italic; font-size: 0.9em; } -/* line 771, ../../sass/screen.scss */ +/* line 821, ../../sass/screen.scss */ #lieu_widget .message.hidden { display: none; } -/* line 777, ../../sass/screen.scss */ +/* line 827, ../../sass/screen.scss */ a.lieu-change { color: #fff; background: #f99b20; @@ -1201,25 +1254,25 @@ a.lieu-change { border-radius: 5px; margin-right: 7px; } -/* line 789, ../../sass/screen.scss */ +/* line 839, ../../sass/screen.scss */ a.lieu-change.ajout:before { content: "+"; margin-right: 5px; } -/* line 795, ../../sass/screen.scss */ +/* line 845, ../../sass/screen.scss */ #stages-map { width: 100%; height: 600px; max-height: 90vh; } -/* line 802, ../../sass/screen.scss */ +/* line 852, ../../sass/screen.scss */ #id_stage-thematiques { display: none; } -/* line 808, ../../sass/screen.scss */ +/* line 858, ../../sass/screen.scss */ .homeh1 { display: flex; justify-content: space-between; @@ -1229,26 +1282,26 @@ a.lieu-change.ajout:before { border-bottom: 3px solid #000; margin-bottom: 15px; } -/* line 817, ../../sass/screen.scss */ +/* line 867, ../../sass/screen.scss */ .homeh1 h1 { margin-bottom: 3px; } -/* line 821, ../../sass/screen.scss */ +/* line 871, ../../sass/screen.scss */ .homeh1 > * { display: inline-block; } -/* line 824, ../../sass/screen.scss */ +/* line 874, ../../sass/screen.scss */ .homeh1 p { text-align: right; } -/* line 829, ../../sass/screen.scss */ +/* line 879, ../../sass/screen.scss */ .betacadre { background: #fa6cae; padding: 10px; } -/* line 834, ../../sass/screen.scss */ +/* line 884, ../../sass/screen.scss */ .entrer { background: #fff; max-width: 500px; @@ -1256,7 +1309,7 @@ a.lieu-change.ajout:before { text-align: center; margin: 15px auto; } -/* line 841, ../../sass/screen.scss */ +/* line 891, ../../sass/screen.scss */ .entrer .archicubes { border-top: 2px solid #1a82dd; margin-top: 5px; @@ -1264,84 +1317,84 @@ a.lieu-change.ajout:before { font-size: 0.9em; } -/* line 849, ../../sass/screen.scss */ +/* line 899, ../../sass/screen.scss */ article.promo { display: block; font-size: 1.1em; } -/* line 853, ../../sass/screen.scss */ +/* line 903, ../../sass/screen.scss */ article.promo .explications { display: table; } -/* line 856, ../../sass/screen.scss */ +/* line 906, ../../sass/screen.scss */ article.promo .explications:first-child { direction: rtl; } -/* line 858, ../../sass/screen.scss */ +/* line 908, ../../sass/screen.scss */ article.promo .explications:first-child > * { direction: ltr; } -/* line 863, ../../sass/screen.scss */ +/* line 913, ../../sass/screen.scss */ article.promo .explications > div { display: table-cell; vertical-align: middle; text-align: center; } -/* line 868, ../../sass/screen.scss */ +/* line 918, ../../sass/screen.scss */ article.promo .explications > div p { margin: 15px 15px; } -/* line 876, ../../sass/screen.scss */ +/* line 926, ../../sass/screen.scss */ .faq-toc { font-family: "Lato", sans-serif; display: block; max-width: 700px; margin: 0 auto; } -/* line 881, ../../sass/screen.scss */ +/* line 931, ../../sass/screen.scss */ .faq-toc ul { margin: 20px; } -/* line 885, ../../sass/screen.scss */ +/* line 935, ../../sass/screen.scss */ .faq-toc ul li a { color: #000; display: block; padding: 5px; } -/* line 891, ../../sass/screen.scss */ +/* line 941, ../../sass/screen.scss */ .faq-toc ul li.toc-h1 { display: none; } -/* line 895, ../../sass/screen.scss */ +/* line 945, ../../sass/screen.scss */ .faq-toc ul li.toc-h2 a { background: #fcc883; } -/* line 899, ../../sass/screen.scss */ +/* line 949, ../../sass/screen.scss */ .faq-toc ul li.toc-h3 a { padding-left: 10px; background: #fff; font-weight: normal; } -/* line 905, ../../sass/screen.scss */ +/* line 955, ../../sass/screen.scss */ .faq-toc ul li a:hover { color: #395214; background: #bce085 !important; } -/* line 914, ../../sass/screen.scss */ +/* line 964, ../../sass/screen.scss */ .faq article { background: #fff; padding: 15px; } -/* line 917, ../../sass/screen.scss */ +/* line 967, ../../sass/screen.scss */ .faq article h2 { background-color: #fcc883; color: #ae6505; margin: -15px; padding: 15px; } -/* line 924, ../../sass/screen.scss */ +/* line 974, ../../sass/screen.scss */ .faq article h3 { color: #0f4c82; background-color: #9dcbf3; @@ -1349,19 +1402,19 @@ article.promo .explications > div p { margin-top: 30px; padding: 10px 15px; } -/* line 931, ../../sass/screen.scss */ +/* line 981, ../../sass/screen.scss */ .faq article h3:nth-child(2) { margin-top: 0; } -/* line 936, ../../sass/screen.scss */ +/* line 986, ../../sass/screen.scss */ .faq article ul { padding-left: 20px; } -/* line 938, ../../sass/screen.scss */ +/* line 988, ../../sass/screen.scss */ .faq article ul li { list-style: initial; } -/* line 943, ../../sass/screen.scss */ +/* line 993, ../../sass/screen.scss */ .faq article p, .faq article ul { font-family: "Lato", sans-serif; font-size: 18px; @@ -1370,20 +1423,20 @@ article.promo .explications > div p { margin-right: 5%; } -/* line 957, ../../sass/screen.scss */ +/* line 1007, ../../sass/screen.scss */ table.stats { width: 100%; background: #fff; margin: 20px 0; cellspacing: 1px; } -/* line 962, ../../sass/screen.scss */ +/* line 1012, ../../sass/screen.scss */ table.stats th { font-weight: bold; border-top: 1px solid #000; border-bottom: 1px solid #999; } -/* line 967, ../../sass/screen.scss */ +/* line 1017, ../../sass/screen.scss */ table.stats td, table.stats th { padding: 5px 3px; text-align: center; @@ -1971,14 +2024,14 @@ body.recherche.vue-hybride.vue-details .recherche-liste.recherche-details { display: block; text-align: left; font-size: 0.95em; - color: #c77c1a; + color: #ae6505; margin-top: 0; width: auto; } /* line 185, ../../sass/_responsive.scss */ form .field .help_text { text-align: right; - color: #395214; + color: black; } /* line 190, ../../sass/_responsive.scss */ form .field .input { diff --git a/avisstage/templates/avisstage/compte/aconfirmer.html b/avisstage/templates/avisstage/compte/aconfirmer.html new file mode 100644 index 0000000..bbe6398 --- /dev/null +++ b/avisstage/templates/avisstage/compte/aconfirmer.html @@ -0,0 +1,19 @@ +{% extends "avisstage/base.html" %} +{% load staticfiles %} + +{% block title %}Confirmation requise - ExperiENS{% endblock %} + +{% block content %} +

Confirmation requise

+ +
+ {% if object.confirmed_at %} +

L'adresse {{ object.email }} a déjà été confirmée.

+ {% else %} +

Un mail de confirmation vous a été envoyé à l'adresse {{ object.email }} pour la vérifier.

+

Merci de cliquer sur le lien inclus pour confirmer qu'elle est correcte.

+

Si vous ne recevez rien, vérifier dans vos indésirables.

+ {% endif %} +

Retour

+
+{% endblock %} diff --git a/avisstage/templates/avisstage/compte/edit_mdp.html b/avisstage/templates/avisstage/compte/edit_mdp.html new file mode 100644 index 0000000..ff07aae --- /dev/null +++ b/avisstage/templates/avisstage/compte/edit_mdp.html @@ -0,0 +1,29 @@ +{% extends "avisstage/base.html" %} +{% load staticfiles %} + +{% block content %} +

Définir un mot de passe

+
+ {% csrf_token %} + {{ form.non_field_errors }} +
+ +
+ {{ user.username }} +
+
+ {% for field in form %} + {{ field.errors }} +
+ +
+ {{ field }} + {% if field.help_text %} +

{{ field.help_text }}

+ {% endif %} +
+
+ {% endfor %} + +
+{% endblock %} diff --git a/avisstage/templates/avisstage/compte/email_supprime.html b/avisstage/templates/avisstage/compte/email_supprime.html new file mode 100644 index 0000000..494d27a --- /dev/null +++ b/avisstage/templates/avisstage/compte/email_supprime.html @@ -0,0 +1,18 @@ +{% extends "avisstage/base.html" %} +{% load staticfiles %} + +{% block title %}Supprimer une adresse mail - ExperiENS{% endblock %} + +{% block content %} +

Supprimer une adresse mail

+ +
+
+
+ {% csrf_token %} +

Êtes-vous sûr⋅e de vouloir supprimer l'adresse mail {{ object.email }} ?

+

Retour  

+
+
+
+{% endblock %} diff --git a/avisstage/templates/avisstage/compte/parametres.html b/avisstage/templates/avisstage/compte/parametres.html new file mode 100644 index 0000000..36a9547 --- /dev/null +++ b/avisstage/templates/avisstage/compte/parametres.html @@ -0,0 +1,76 @@ +{% extends "avisstage/base.html" %} +{% load staticfiles %} + +{% block title %}Mes paramètres - ExperiENS{% endblock %} + +{% block content %} +

Mes paramètres

+ +
+

Adresses e-mail

+ +
+ +
+

Mot de passe

+
+ {% if request.user.password and request.user.has_usable_password %} +

Un mot de passe interne est déjà défini pour ce compte.

+ {% else %} +

Aucun mot de passe n'est défini pour ce compte. Créez-en un pour pouvoir vous connecter après la fin de votre scolarité à l'ENS.

+ {% endif %} +
+ {% csrf_token %} + +
+

En cliquant sur ce bouton, un lien unique vous sera envoyé à votre adresse e-mail principale ({{ request.user.email }}) qui vous donnera accès au formulaire d'édition du mot de passe.

+
+
+{% endblock %} diff --git a/avisstage/templates/avisstage/formulaires/profil.html b/avisstage/templates/avisstage/formulaires/profil.html index e5ac89d..7d1fce0 100644 --- a/avisstage/templates/avisstage/formulaires/profil.html +++ b/avisstage/templates/avisstage/formulaires/profil.html @@ -18,6 +18,13 @@ {% endfor %} - +
+ +
+ {{ request.user.email }} +

Allez dans les paramètres de connexion pour modifier votre adresse principale

+
+
+ {% endblock %} diff --git a/avisstage/templates/avisstage/mails/reinit_mdp.html b/avisstage/templates/avisstage/mails/reinit_mdp.html new file mode 100644 index 0000000..f9e3c98 --- /dev/null +++ b/avisstage/templates/avisstage/mails/reinit_mdp.html @@ -0,0 +1,8 @@ +Bonjour, + +Pour créer ou modifier le mot de passe associé à votre compte {{ user.get_username }}, merci de cliquer sur le lien suivant ou de le copier dans votre navigateur : + + {{ protocol }}://{{ domain }}{% url 'avisstage:mdp_edit' uidb64=uid token=token %} + +Cordialement, +L'équipe ExperiENS diff --git a/avisstage/templates/avisstage/mails/reinit_mdp.txt b/avisstage/templates/avisstage/mails/reinit_mdp.txt new file mode 100644 index 0000000..cc5a9de --- /dev/null +++ b/avisstage/templates/avisstage/mails/reinit_mdp.txt @@ -0,0 +1 @@ +[ExperiENS] Définition du mot de passe diff --git a/avisstage/templates/avisstage/perso.html b/avisstage/templates/avisstage/perso.html index adf992a..32f816f 100644 --- a/avisstage/templates/avisstage/perso.html +++ b/avisstage/templates/avisstage/perso.html @@ -8,34 +8,38 @@

Mon compte

-
- {% if user.profil.en_scolarite %} -

Statut : En scolarité

-

Vous pouvez accéder à l'ensemble du site, et aux fiches de stages.

-

Quand vous n'aurez plus de compte clipper (après votre scolarité), votre accès sera restreint à vos propres expériences, que vous pourrez ajouter, modifier, supprimer.

-

Pensez à renseigner une adresse e-mail non-ENS pour conserver cet accès, et permettre aux futur⋅e⋅s normalien⋅ne⋅s de toujours vous contacter !

- {% else %} -

Statut : Archicube

-

Vous ne pouvez plus accéder qu'à vos propres expériences pour les modifier, et tenir à jour votre profil.

-

Si vous êtes encore en scolarité, merci de vous reconnecter en passant par le serveur d'authentification de l'ENS pour mettre à jour votre statut.

- {% endif %} -

Le statut est mis à jour automatiquement chaque année selon le mode de connexion que vous utilisez.

-
-
-

Adresse e-mail

- {% if not user.profil.has_nonENS_email %}

Vous n'avez pas renseigné d'adresse mail autre que celle de l'ENS. Pensez à le faire, pour que les générations futures puissent toujours vous contacter !

{% endif %} -

Gérer les adresses e-mail liées à mon compte

-
-
-

Mode de connexion

- {% if user.profil.en_scolarite %}

En scolarité, utilisez le serveur central d'authentification pour vous connecter. Quand vous n'aurez plus de compte clipper, vous devrez vous connecter directement via l'accès archicubes, avec votre login {{ user.cas_account.cas_login }} et le mot de passe spécifique à ExperiENS que vous aurez défini.

{% endif %} - {% if not user.password or not user.has_usable_password %}

Vous n'avez pas créé de mot de passe interne à ExperiENS. Pensez-y pour garder l'accès au site quand vous n'aurez plus de compte clipper !

{% endif %} -

Créer / changer mon mot de passe ExperiENS

+
+
+ {% if user.profil.en_scolarite %} +

Statut : En scolarité

+

Vous pouvez accéder à l'ensemble du site, et aux fiches de stages.

+

Quand vous n'aurez plus de compte clipper (après votre scolarité), votre accès sera restreint à vos propres expériences, que vous pourrez ajouter, modifier, supprimer.

+

Pensez à renseigner une adresse e-mail non-ENS pour conserver cet accès, et permettre aux futur⋅e⋅s normalien⋅ne⋅s de toujours vous contacter !

+ {% else %} +

Statut : Archicube

+

Vous ne pouvez plus accéder qu'à vos propres expériences pour les modifier, et tenir à jour votre profil.

+

Si vous êtes encore en scolarité, merci de vous reconnecter en passant par le serveur d'authentification de l'ENS pour mettre à jour votre statut.

+ {% endif %} +
+

Le statut est mis à jour automatiquement chaque année selon le mode de connexion que vous utilisez.

+
+
+

Connexion

+

Adresse e-mail principale :
{{ user.email }}

+ {% if not user.profil.has_nonENS_email %}

Vous n'avez pas renseigné d'adresse mail autre que celle de l'ENS. Pensez à le faire, pour que les générations futures puissent toujours vous contacter !

{% endif %} +
+ +

Mot de passe interne : {% if user.password and user.has_usable_password %}Défini{% else %}Non défini{% endif %}

+ {% if not user.password or not user.has_usable_password %}

Pensez à définir un mot de passe propre à ExperiENS pour garder l'accès au site quand vous n'aurez plus de compte clipper !

{% endif %} + {% if user.profil.en_scolarite %}

En scolarité, utilisez le serveur central d'authentification pour vous connecter. Quand vous n'aurez plus de compte clipper, vous devrez vous connecter directement via l'accès archicubes, avec votre login {{ user.username }} et le mot de passe spécifique à ExperiENS que vous aurez défini.

{% endif %} +
+

Gérer mes paramètres de connexion

+
-

Mon profil public Modifier mes infos

+

Mon profil public Voir Modifier mes infos

{% with object=user.profil %}
diff --git a/avisstage/urls.py b/avisstage/urls.py index 94bab54..93f0978 100644 --- a/avisstage/urls.py +++ b/avisstage/urls.py @@ -24,6 +24,23 @@ urlpatterns = [ path('profil/show//', views.ProfilView.as_view(), name='profil'), path('profil/edit/', views.ProfilEdit.as_view(), name='profil_edit'), + path('profil/parametres/', views.MesParametres.as_view(), name='parametres'), + path('profil/emails//aconfirmer/', + views.AdresseAConfirmer.as_view(), name="emails_aconfirmer"), + path('profil/emails//supprime/', views.SupprimeAdresse.as_view(), + name="emails_supprime"), + path('profil/emails//reconfirme/', + views.ReConfirmeAdresse.as_view(), + name="emails_reconfirme"), + path('profil/emails//principal/', + views.RendAdressePrincipale.as_view(), name="emails_principal"), + path('profil/emails/confirme//', views.ConfirmeAdresse.as_view(), + name="emails_confirme"), + path('profil/mdp/demande/', + views.EnvoieLienMotDePasse.as_view(), name="mdp_demande"), + path('profil/mdp///', + views.DefinirMotDePasse.as_view(), name="mdp_edit"), + path('recherche/', views.recherche, name='recherche'), path('recherche/resultats/', views.recherche_resultats, name='recherche_resultats'), diff --git a/avisstage/views.py b/avisstage/views.py index 2bcb19c..897b124 100644 --- a/avisstage/views.py +++ b/avisstage/views.py @@ -2,21 +2,31 @@ from django.shortcuts import render, redirect, get_object_or_404 -from django.views.generic import DetailView, ListView -from django.views.generic.edit import UpdateView, CreateView +from django.views.generic import ( + DetailView, ListView, UpdateView, CreateView, TemplateView, DeleteView, + FormView, View +) +from django.views.generic.detail import SingleObjectMixin from django import forms -from django.urls import reverse +from django.urls import reverse, reverse_lazy from django.conf import settings from django.contrib.admin.views.decorators import staff_member_required from django.contrib.auth.decorators import login_required +from django.contrib.auth.tokens import default_token_generator +from django.contrib.auth.views import PasswordResetConfirmView +from django.contrib import messages from braces.views import LoginRequiredMixin from django.http import JsonResponse, HttpResponseForbidden, Http404 from django.core.mail import send_mail from django.db.models import Q, Count from collections import Counter, defaultdict +from simple_email_confirmation.models import EmailAddress from .models import Normalien, Stage, Lieu, AvisLieu, AvisStage -from .forms import StageForm, LieuForm, AvisStageForm, AvisLieuForm, FeedbackForm +from .forms import ( + StageForm, LieuForm, AvisStageForm, AvisLieuForm, FeedbackForm, AdresseEmailForm, + ReinitMdpForm +) from .utils import en_scolarite from .views_search import * @@ -343,3 +353,126 @@ def statistiques(request): 'num_lieux_utiles': nlieux, 'num_par_longueur': nbylength, }) + +# +# Compte +# + +class MesAdressesMixin(LoginRequiredMixin): + slug_url_kwarg = "email" + slug_field = "email" + confirmed_only = False + + def get_queryset(self, *args, **kwargs): + qs = self.request.user.email_address_set.all() + if self.confirmed_only: + qs = qs.filter(confirmed_at__isnull=False) + return qs + +def _send_confirm_mail(email, request): + confirm_url = request.build_absolute_uri( + reverse("avisstage:emails_confirme", kwargs={"key": email.key})) + send_mail( + "[ExperiENS] Confirmez votre adresse a-mail", +"""Bonjour, + +Vous venez d'ajouter cette adresse e-mail à votre compte ExperiENS. + +Pour la vérifier, merci de cliquer sur le lien suivant, ou de copier l'adresse dans votre navigateur : + + {confirm_url} + +Cordialement, +L'équipe ExperiENS""".format(confirm_url=confirm_url), + 'experiens-nepasrepondre@eleves.ens.fr', + [email.email], + fail_silently=False, + ) + return redirect(reverse("avisstage:emails_aconfirmer", + kwargs={"email": email.email})) + +class MesParametres(LoginRequiredMixin, FormView): + model = EmailAddress + template_name = "avisstage/compte/parametres.html" + form_class = AdresseEmailForm + + def get_form_kwargs(self, *args, **kwargs): + kwargs = super().get_form_kwargs(*args, **kwargs) + kwargs["_user"] = self.request.user + return kwargs + + def form_valid(self, form): + new = EmailAddress.objects.create_unconfirmed( + form.cleaned_data["email"], self.request.user) + return _send_confirm_mail(new, self.request) + +class RendAdressePrincipale(MesAdressesMixin, SingleObjectMixin, View): + model = EmailAddress + confirmed_only = True + + def post(self, *args, **kwargs): + if not hasattr(self, "object"): + self.object = self.get_object() + self.request.user.email = self.object.email + self.request.user.save() + return redirect(reverse("avisstage:parametres")) + +class AdresseAConfirmer(MesAdressesMixin, DetailView): + model = EmailAddress + template_name = "avisstage/compte/aconfirmer.html" + +class ReConfirmeAdresse(MesAdressesMixin, DetailView): + model = EmailAddress + + def post(self, *args, **kwargs): + email = self.get_object() + if email.confirmed_at is None: + return _send_confirm_mail(email, self.request) + return redirect(reverse("avisstage:parametres")) + +class ConfirmeAdresse(LoginRequiredMixin, View): + def get(self, *args, **kwargs): + try: + email = EmailAddress.objects.confirm(self.kwargs["key"], + self.request.user, True) + except Exception as e: + raise Http404() + messages.add_message( + self.request, messages.SUCCESS, + "L'adresse email {email} a bien été confirmée".format(email=email.email)) + return redirect(reverse("avisstage:parametres")) + +class SupprimeAdresse(MesAdressesMixin, DeleteView): + model = EmailAddress + template_name = "avisstage/compte/email_supprime.html" + success_url = reverse_lazy("avisstage:parametres") + + def get_queryset(self, *args, **kwargs): + qs = super().get_queryset(*args, **kwargs) + return qs.exclude(email=self.request.user.email) + +class EnvoieLienMotDePasse(LoginRequiredMixin, View): + def post(self, *args, **kwargs): + form = ReinitMdpForm({"email": self.request.user.email}) + form.is_valid() + form.save( + email_template_name = 'avisstage/mails/reinit_mdp.html', + from_email = 'experiens-nepasrepondre@eleves.ens.fr', + subject_template_name = 'avisstage/mails/reinit_mdp.txt', + ) + messages.add_message( + self.request, messages.INFO, + "Un mail a été envoyé à {email}. Merci de vérifier vos indésirables si vous ne le recevez pas bientôt".format(email=self.request.user.email) + ) + return redirect(reverse("avisstage:parametres")) + +class DefinirMotDePasse(PasswordResetConfirmView): + template_name = "avisstage/compte/edit_mdp.html" + success_url = reverse_lazy("avisstage:perso") + + def get_user(self, *args, **kwargs): + user = super().get_user(*args, **kwargs) + if self.request.user.is_authenticated and user != self.request.user: + raise Http404("Ce token n'est pas valide pour votre compte") + return user + diff --git a/experiENS/settings_base.py b/experiENS/settings_base.py index a4ba634..d03aec0 100644 --- a/experiENS/settings_base.py +++ b/experiENS/settings_base.py @@ -35,9 +35,9 @@ INSTALLED_APPS = [ 'django_elasticsearch_dsl', - #'allauth', - #'allauth.account', # Uncomment for transition - #'allauth.socialaccount', # Allauth -> Authens + #'allauth', # Uncomment that part when you + #'allauth.account', # apply migration + #'allauth.socialaccount', # Allauth -> AuthENS 'widget_tweaks',