Gestion des adresses et du mot de passe
This commit is contained in:
parent
4e683f62e1
commit
90aa558896
17 changed files with 650 additions and 188 deletions
|
@ -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))
|
||||
)
|
||||
|
|
|
@ -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)))
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
File diff suppressed because it is too large
Load diff
19
avisstage/templates/avisstage/compte/aconfirmer.html
Normal file
19
avisstage/templates/avisstage/compte/aconfirmer.html
Normal file
|
@ -0,0 +1,19 @@
|
|||
{% extends "avisstage/base.html" %}
|
||||
{% load staticfiles %}
|
||||
|
||||
{% block title %}Confirmation requise - ExperiENS{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1>Confirmation requise</h1>
|
||||
|
||||
<article>
|
||||
{% if object.confirmed_at %}
|
||||
<p>L'adresse {{ object.email }} a déjà été confirmée.</p>
|
||||
{% else %}
|
||||
<p>Un mail de confirmation vous a été envoyé à l'adresse {{ object.email }} pour la vérifier.</p>
|
||||
<p>Merci de cliquer sur le lien inclus pour confirmer qu'elle est correcte.</p>
|
||||
<p>Si vous ne recevez rien, vérifier dans vos indésirables.</p>
|
||||
{% endif %}
|
||||
<p><a href="{% url "avisstage:parametres" %}">Retour</a></p>
|
||||
</article>
|
||||
{% endblock %}
|
29
avisstage/templates/avisstage/compte/edit_mdp.html
Normal file
29
avisstage/templates/avisstage/compte/edit_mdp.html
Normal file
|
@ -0,0 +1,29 @@
|
|||
{% extends "avisstage/base.html" %}
|
||||
{% load staticfiles %}
|
||||
|
||||
{% block content %}
|
||||
<h1>Définir un mot de passe</h1>
|
||||
<form action="" method="post">
|
||||
{% csrf_token %}
|
||||
{{ form.non_field_errors }}
|
||||
<div class="field">
|
||||
<label>Nom d'utilisateur</label>
|
||||
<div class="input">
|
||||
{{ user.username }}
|
||||
</div>
|
||||
</div>
|
||||
{% for field in form %}
|
||||
{{ field.errors }}
|
||||
<div class="field">
|
||||
<label for="{{ field.id_for_label }}">{{ field.label }}</label>
|
||||
<div class="input">
|
||||
{{ field }}
|
||||
{% if field.help_text %}
|
||||
<p class="help_text">{{ field.help_text }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
<input type="submit" value="Enregistrer" />
|
||||
</form>
|
||||
{% endblock %}
|
18
avisstage/templates/avisstage/compte/email_supprime.html
Normal file
18
avisstage/templates/avisstage/compte/email_supprime.html
Normal file
|
@ -0,0 +1,18 @@
|
|||
{% extends "avisstage/base.html" %}
|
||||
{% load staticfiles %}
|
||||
|
||||
{% block title %}Supprimer une adresse mail - ExperiENS{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1>Supprimer une adresse mail</h1>
|
||||
|
||||
<article>
|
||||
<section class="profil">
|
||||
<form action="" method="POST">
|
||||
{% csrf_token %}
|
||||
<p>Êtes-vous sûr⋅e de vouloir supprimer l'adresse mail {{ object.email }} ?</p>
|
||||
<p><a href="{% url "avisstage:parametres" %}">Retour</a> <input type="submit" value="Confirmer la suppression"></p>
|
||||
</form>
|
||||
</section>
|
||||
</article>
|
||||
{% endblock %}
|
76
avisstage/templates/avisstage/compte/parametres.html
Normal file
76
avisstage/templates/avisstage/compte/parametres.html
Normal file
|
@ -0,0 +1,76 @@
|
|||
{% extends "avisstage/base.html" %}
|
||||
{% load staticfiles %}
|
||||
|
||||
{% block title %}Mes paramètres - ExperiENS{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1>Mes paramètres</h1>
|
||||
|
||||
<article>
|
||||
<h2>Adresses e-mail</h2>
|
||||
<ul class="mes-emails">
|
||||
{% for email in request.user.email_address_set.all %}
|
||||
<li>
|
||||
<span class="adresse">{{ email.email }}
|
||||
<span class="confirmee">{{ email.confirmed_at|yesno:"✓,✗"|safe }}</span></span>
|
||||
{% if email.confirmed_at %}
|
||||
<span class="principale">
|
||||
{% if email.email == user.email %}
|
||||
Principale
|
||||
{% else %}
|
||||
<form action="{% url "avisstage:emails_principal" email.email %}" method="POST">
|
||||
{% csrf_token %}
|
||||
<input type="submit" value="Rendre principale">
|
||||
</form>
|
||||
{% endif %}
|
||||
</span>
|
||||
|
||||
{% else %}
|
||||
<span class="confirmer">
|
||||
<form action="{% url "avisstage:emails_reconfirme" email.email %}" method="POST">
|
||||
{% csrf_token %}
|
||||
<input type="submit" value="Renvoyer le lien de confirmation">
|
||||
</form>
|
||||
</span>
|
||||
{% endif %}
|
||||
<span class="supprimer">
|
||||
{% if not email.email == user.email %}
|
||||
<a href="{% url "avisstage:emails_supprime" email.email %}">Supprimer</a>
|
||||
{% endif %}
|
||||
</span>
|
||||
</li>
|
||||
{% endfor %}
|
||||
<li>
|
||||
<form action="" method="POST">
|
||||
{% csrf_token %}
|
||||
{{ form.non_field_errors }}
|
||||
{% for field in form %}
|
||||
{{ field.errors }}
|
||||
<div class="field">
|
||||
<div class="input">
|
||||
{{ field }}
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
<input type="submit" value="Ajouter l'adresse">
|
||||
</form>
|
||||
</li>
|
||||
</ul>
|
||||
</article>
|
||||
|
||||
<article>
|
||||
<h2>Mot de passe</h2>
|
||||
<section class="profil">
|
||||
{% if request.user.password and request.user.has_usable_password %}
|
||||
<p>Un mot de passe interne est déjà défini pour ce compte.</p>
|
||||
{% else %}
|
||||
<p>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.</p>
|
||||
{% endif %}
|
||||
<form action="{% url "avisstage:mdp_demande" %}" method="POST">
|
||||
{% csrf_token %}
|
||||
<input type="submit" value="Définir un nouveau mot de passe" />
|
||||
</form>
|
||||
<p>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.</p>
|
||||
</section>
|
||||
</article>
|
||||
{% endblock %}
|
|
@ -18,6 +18,13 @@
|
|||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
<input type="submit" />
|
||||
<div class="field">
|
||||
<label>Adresse e-mail</label>
|
||||
<div class="input">
|
||||
{{ request.user.email }}
|
||||
<p class="help_text">Allez dans <a href="{% url "avisstage:parametres" %}">les paramètres de connexion</a> pour modifier votre adresse principale</p>
|
||||
</div>
|
||||
</div>
|
||||
<input type="submit" value="Enregistrer" />
|
||||
</form>
|
||||
{% endblock %}
|
||||
|
|
8
avisstage/templates/avisstage/mails/reinit_mdp.html
Normal file
8
avisstage/templates/avisstage/mails/reinit_mdp.html
Normal file
|
@ -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
|
1
avisstage/templates/avisstage/mails/reinit_mdp.txt
Normal file
1
avisstage/templates/avisstage/mails/reinit_mdp.txt
Normal file
|
@ -0,0 +1 @@
|
|||
[ExperiENS] Définition du mot de passe
|
|
@ -8,34 +8,38 @@
|
|||
|
||||
<article>
|
||||
<h2>Mon compte</h2>
|
||||
<section class="profil">
|
||||
{% if user.profil.en_scolarite %}
|
||||
<h3 class="scolarite">Statut : En scolarité</h3>
|
||||
<p>Vous pouvez accéder à l'ensemble du site, et aux fiches de stages.</p>
|
||||
<p>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.</p>
|
||||
<p>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 !</p>
|
||||
{% else %}
|
||||
<h3 class="scolarite">Statut : Archicube</h3>
|
||||
<p>Vous ne pouvez plus accéder qu'à vos propres expériences pour les modifier, et tenir à jour votre profil.</p>
|
||||
<p>Si vous êtes encore en scolarité, merci de vous <a href="{% url "authens:login.cas" %}">reconnecter en passant par le serveur d'authentification de l'ENS</a> pour mettre à jour votre statut.</p>
|
||||
{% endif %}
|
||||
<p><i>Le statut est mis à jour automatiquement chaque année selon le mode de connexion que vous utilisez.</i></p>
|
||||
</section>
|
||||
<section class="profil">
|
||||
<h3>Adresse e-mail</h3>
|
||||
{% if not user.profil.has_nonENS_email %}<p align="center" class="warning">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 !</p>{% endif %}
|
||||
<p><a href="{% url "avisstage:perso" %}">Gérer les adresses e-mail liées à mon compte</a></p>
|
||||
</section>
|
||||
<section class="profil">
|
||||
<h3>Mode de connexion</h3>
|
||||
{% if user.profil.en_scolarite %}<p>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.</p>{% endif %}
|
||||
{% if not user.password or not user.has_usable_password %}<p class="warning" align="center">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 !</p>{% endif %}
|
||||
<p><a href="{% url "authens:reset.pwd" %}">Créer / changer mon mot de passe ExperiENS</a></p>
|
||||
<section class="two-cols">
|
||||
<section class="profil">
|
||||
{% if user.profil.en_scolarite %}
|
||||
<h3 class="scolarite">Statut : En scolarité</h3>
|
||||
<p>Vous pouvez accéder à l'ensemble du site, et aux fiches de stages.</p>
|
||||
<p>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.</p>
|
||||
<p>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 !</p>
|
||||
{% else %}
|
||||
<h3 class="scolarite">Statut : Archicube</h3>
|
||||
<p>Vous ne pouvez plus accéder qu'à vos propres expériences pour les modifier, et tenir à jour votre profil.</p>
|
||||
<p>Si vous êtes encore en scolarité, merci de vous <a href="{% url "authens:login.cas" %}">reconnecter en passant par le serveur d'authentification de l'ENS</a> pour mettre à jour votre statut.</p>
|
||||
{% endif %}
|
||||
<hr />
|
||||
<p><i>Le statut est mis à jour automatiquement chaque année selon le mode de connexion que vous utilisez.</i></p>
|
||||
</section>
|
||||
<section class="profil">
|
||||
<h3>Connexion</h3>
|
||||
<p><b>Adresse e-mail principale :</b><br/> {{ user.email }}</p>
|
||||
{% if not user.profil.has_nonENS_email %}<p align="center" class="warning">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 !</p>{% endif %}
|
||||
<hr/>
|
||||
|
||||
<p><b>Mot de passe interne :</b> {% if user.password and user.has_usable_password %}Défini{% else %}Non défini{% endif %}</p>
|
||||
{% if not user.password or not user.has_usable_password %}<p class="warning" align="center">Pensez à définir un mot de passe propre à ExperiENS pour garder l'accès au site quand vous n'aurez plus de compte clipper !</p>{% endif %}
|
||||
{% if user.profil.en_scolarite %}<p>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 <b>{{ user.username }}</b> et le mot de passe spécifique à ExperiENS que vous aurez défini.</p>{% endif %}
|
||||
<hr/>
|
||||
<p><a href="{% url "avisstage:parametres" %}">Gérer mes paramètres de connexion</a></p>
|
||||
</section>
|
||||
</section>
|
||||
</article>
|
||||
|
||||
<article>
|
||||
<h2><a href="{% url "avisstage:profil" user.username %}">Mon profil public</a> <a href="{% url "avisstage:profil_edit" %}" class="edit-btn btn">Modifier mes infos</a></h2>
|
||||
<h2>Mon profil public <a href="{% url "avisstage:profil" user.username %}" class="btn">Voir</a> <a href="{% url "avisstage:profil_edit" %}" class="edit-btn btn">Modifier mes infos</a></h2>
|
||||
{% with object=user.profil %}
|
||||
<section class="profil">
|
||||
<div class="infos">
|
||||
|
|
|
@ -24,6 +24,23 @@ urlpatterns = [
|
|||
path('profil/show/<str:username>/', 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/<str:email>/aconfirmer/',
|
||||
views.AdresseAConfirmer.as_view(), name="emails_aconfirmer"),
|
||||
path('profil/emails/<str:email>/supprime/', views.SupprimeAdresse.as_view(),
|
||||
name="emails_supprime"),
|
||||
path('profil/emails/<str:email>/reconfirme/',
|
||||
views.ReConfirmeAdresse.as_view(),
|
||||
name="emails_reconfirme"),
|
||||
path('profil/emails/<str:email>/principal/',
|
||||
views.RendAdressePrincipale.as_view(), name="emails_principal"),
|
||||
path('profil/emails/confirme/<str:key>/', views.ConfirmeAdresse.as_view(),
|
||||
name="emails_confirme"),
|
||||
path('profil/mdp/demande/',
|
||||
views.EnvoieLienMotDePasse.as_view(), name="mdp_demande"),
|
||||
path('profil/mdp/<str:uidb64>/<str:token>/',
|
||||
views.DefinirMotDePasse.as_view(), name="mdp_edit"),
|
||||
|
||||
path('recherche/', views.recherche, name='recherche'),
|
||||
path('recherche/resultats/', views.recherche_resultats,
|
||||
name='recherche_resultats'),
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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',
|
||||
|
||||
|
|
Loading…
Reference in a new issue