mirror of
https://gitlab2.federez.net/re2o/re2o
synced 2024-11-22 11:23:10 +00:00
Create EMAIL_NOT_YET_CONFIRMED state
This commit is contained in:
parent
e57ec2ccd1
commit
8728bc69f5
8 changed files with 134 additions and 3 deletions
|
@ -469,7 +469,7 @@ def decide_vlan_switch(nas_machine, nas_type, port_number, mac_address):
|
||||||
RadiusOption.get_attributes("non_member_attributes", attributes_kwargs),
|
RadiusOption.get_attributes("non_member_attributes", attributes_kwargs),
|
||||||
)
|
)
|
||||||
for user in room_user:
|
for user in room_user:
|
||||||
if user.is_ban() or user.state != User.STATE_ACTIVE:
|
if user.is_ban() or user.state not in [User.STATE_ACTIVE, User.STATE_EMAIL_NOT_YET_CONFIRMED]:
|
||||||
return (
|
return (
|
||||||
sw_name,
|
sw_name,
|
||||||
room,
|
room,
|
||||||
|
|
|
@ -260,6 +260,16 @@ def stats_general(request):
|
||||||
),
|
),
|
||||||
Club.objects.filter(state=Club.STATE_NOT_YET_ACTIVE).count(),
|
Club.objects.filter(state=Club.STATE_NOT_YET_ACTIVE).count(),
|
||||||
],
|
],
|
||||||
|
"email_not_confirmed_users": [
|
||||||
|
_("Email not yet confirmed users"),
|
||||||
|
User.objects.filter(state=User.STATE_EMAIL_NOT_YET_CONFIRMED).count(),
|
||||||
|
(
|
||||||
|
Adherent.objects.filter(
|
||||||
|
state=Adherent.STATE_EMAIL_NOT_YET_CONFIRMED
|
||||||
|
).count()
|
||||||
|
),
|
||||||
|
Club.objects.filter(state=Club.STATE_EMAIL_NOT_YET_CONFIRMED).count(),
|
||||||
|
],
|
||||||
"adherent_users": [
|
"adherent_users": [
|
||||||
_("Contributing members"),
|
_("Contributing members"),
|
||||||
_all_adherent.count(),
|
_all_adherent.count(),
|
||||||
|
|
|
@ -116,7 +116,7 @@ def all_has_access(search_time=None, including_asso=True):
|
||||||
if search_time is None:
|
if search_time is None:
|
||||||
search_time = timezone.now()
|
search_time = timezone.now()
|
||||||
filter_user = (
|
filter_user = (
|
||||||
Q(state=User.STATE_ACTIVE)
|
(Q(state=User.STATE_ACTIVE) | Q(state=User.STATE_EMAIL_NOT_YET_CONFIRMED))
|
||||||
& ~Q(
|
& ~Q(
|
||||||
ban__in=Ban.objects.filter(
|
ban__in=Ban.objects.filter(
|
||||||
Q(date_start__lt=search_time) & Q(date_end__gt=search_time)
|
Q(date_start__lt=search_time) & Q(date_end__gt=search_time)
|
||||||
|
|
|
@ -117,6 +117,20 @@ class PassForm(FormRevMixin, FieldPermissionFormMixin, forms.ModelForm):
|
||||||
user.save()
|
user.save()
|
||||||
|
|
||||||
|
|
||||||
|
class ConfirmMailForm(FormRevMixin, FieldPermissionFormMixin, forms.ModelForm):
|
||||||
|
"""Formulaire de confirmation de l'email de l'utilisateur"""
|
||||||
|
class Meta:
|
||||||
|
model = User
|
||||||
|
fields = []
|
||||||
|
|
||||||
|
def save(self, commit=True):
|
||||||
|
"""Confirmation de l'email"""
|
||||||
|
user = super(ConfirmMailForm, self).save(commit=False)
|
||||||
|
user.confirm_mail()
|
||||||
|
user.set_active()
|
||||||
|
user.save()
|
||||||
|
|
||||||
|
|
||||||
class UserCreationForm(FormRevMixin, forms.ModelForm):
|
class UserCreationForm(FormRevMixin, forms.ModelForm):
|
||||||
"""A form for creating new users. Includes all the required
|
"""A form for creating new users. Includes all the required
|
||||||
fields, plus a repeated password.
|
fields, plus a repeated password.
|
||||||
|
|
|
@ -77,6 +77,7 @@ class Command(BaseCommand):
|
||||||
.exclude(id__in=all_has_access(search_time=date))
|
.exclude(id__in=all_has_access(search_time=date))
|
||||||
.exclude(state=User.STATE_NOT_YET_ACTIVE)
|
.exclude(state=User.STATE_NOT_YET_ACTIVE)
|
||||||
.exclude(state=User.STATE_FULL_ARCHIVE)
|
.exclude(state=User.STATE_FULL_ARCHIVE)
|
||||||
|
.exclude(state=User.STATE_EMAIL_NOT_YET_CONFIRMED)
|
||||||
)
|
)
|
||||||
|
|
||||||
if show:
|
if show:
|
||||||
|
|
|
@ -176,12 +176,14 @@ class User(
|
||||||
STATE_ARCHIVE = 2
|
STATE_ARCHIVE = 2
|
||||||
STATE_NOT_YET_ACTIVE = 3
|
STATE_NOT_YET_ACTIVE = 3
|
||||||
STATE_FULL_ARCHIVE = 4
|
STATE_FULL_ARCHIVE = 4
|
||||||
|
STATE_EMAIL_NOT_YET_CONFIRMED = 5
|
||||||
STATES = (
|
STATES = (
|
||||||
(0, _("Active")),
|
(0, _("Active")),
|
||||||
(1, _("Disabled")),
|
(1, _("Disabled")),
|
||||||
(2, _("Archived")),
|
(2, _("Archived")),
|
||||||
(3, _("Not yet active")),
|
(3, _("Not yet active")),
|
||||||
(4, _("Fully archived")),
|
(4, _("Fully archived")),
|
||||||
|
(5, _("Waiting for email confirmation")),
|
||||||
)
|
)
|
||||||
|
|
||||||
surname = models.CharField(max_length=255)
|
surname = models.CharField(max_length=255)
|
||||||
|
@ -326,6 +328,7 @@ class User(
|
||||||
return (
|
return (
|
||||||
self.state == self.STATE_ACTIVE
|
self.state == self.STATE_ACTIVE
|
||||||
or self.state == self.STATE_NOT_YET_ACTIVE
|
or self.state == self.STATE_NOT_YET_ACTIVE
|
||||||
|
or self.state == self.STATE_EMAIL_NOT_YET_CONFIRMED
|
||||||
or (
|
or (
|
||||||
allow_archived
|
allow_archived
|
||||||
and self.state in (self.STATE_ARCHIVE, self.STATE_FULL_ARCHIVE)
|
and self.state in (self.STATE_ARCHIVE, self.STATE_FULL_ARCHIVE)
|
||||||
|
@ -480,7 +483,7 @@ class User(
|
||||||
def has_access(self):
|
def has_access(self):
|
||||||
""" Renvoie si un utilisateur a accès à internet """
|
""" Renvoie si un utilisateur a accès à internet """
|
||||||
return (
|
return (
|
||||||
self.state == User.STATE_ACTIVE
|
self.state in [User.STATE_ACTIVE, User.STATE_EMAIL_NOT_YET_CONFIRMED]
|
||||||
and not self.is_ban()
|
and not self.is_ban()
|
||||||
and (self.is_connected() or self.is_whitelisted())
|
and (self.is_connected() or self.is_whitelisted())
|
||||||
) or self == AssoOption.get_cached_value("utilisateur_asso")
|
) or self == AssoOption.get_cached_value("utilisateur_asso")
|
||||||
|
@ -665,6 +668,7 @@ class User(
|
||||||
Si l'instance n'existe pas, on crée le ldapuser correspondant"""
|
Si l'instance n'existe pas, on crée le ldapuser correspondant"""
|
||||||
if sys.version_info[0] >= 3 and (
|
if sys.version_info[0] >= 3 and (
|
||||||
self.state == self.STATE_ACTIVE
|
self.state == self.STATE_ACTIVE
|
||||||
|
or self.state == STATE_EMAIL_NOT_YET_CONFIRMED
|
||||||
or self.state == self.STATE_ARCHIVE
|
or self.state == self.STATE_ARCHIVE
|
||||||
or self.state == self.STATE_DISABLED
|
or self.state == self.STATE_DISABLED
|
||||||
):
|
):
|
||||||
|
@ -783,6 +787,34 @@ class User(
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
def confirm_email_address_mail(self, request):
|
||||||
|
"""Prend en argument un request, envoie un mail pour
|
||||||
|
confirmer l'adresse"""
|
||||||
|
req = Request()
|
||||||
|
req.type = Request.EMAIL
|
||||||
|
req.user = self
|
||||||
|
req.save()
|
||||||
|
template = loader.get_template("users/email_confirmation_request")
|
||||||
|
context = {
|
||||||
|
"name": req.user.get_full_name(),
|
||||||
|
"asso": AssoOption.get_cached_value("name"),
|
||||||
|
"asso_mail": AssoOption.get_cached_value("contact"),
|
||||||
|
"site_name": GeneralOption.get_cached_value("site_name"),
|
||||||
|
"url": request.build_absolute_uri(
|
||||||
|
reverse("users:process", kwargs={"token": req.token})
|
||||||
|
),
|
||||||
|
"expire_in": str(GeneralOption.get_cached_value("req_expire_hrs")),
|
||||||
|
}
|
||||||
|
send_mail(
|
||||||
|
"Confirmation de l'email de %(name)s / Email confirmation for "
|
||||||
|
"%(name)s" % {"name": AssoOption.get_cached_value("name")},
|
||||||
|
template.render(context),
|
||||||
|
GeneralOption.get_cached_value("email_from"),
|
||||||
|
[req.user.email],
|
||||||
|
fail_silently=False,
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
def autoregister_machine(self, mac_address, nas_type):
|
def autoregister_machine(self, mac_address, nas_type):
|
||||||
""" Fonction appellée par freeradius. Enregistre la mac pour
|
""" Fonction appellée par freeradius. Enregistre la mac pour
|
||||||
une machine inconnue sur le compte de l'user"""
|
une machine inconnue sur le compte de l'user"""
|
||||||
|
@ -845,6 +877,12 @@ class User(
|
||||||
self.pwd_ntlm = hashNT(password)
|
self.pwd_ntlm = hashNT(password)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
def confirm_mail(self):
|
||||||
|
"""Marque l'email de l'utilisateur comme confirmé"""
|
||||||
|
# Let the "set_active" method handle
|
||||||
|
self.state = self.STATE_NOT_YET_ACTIVE
|
||||||
|
self.set_active()
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def email_address(self):
|
def email_address(self):
|
||||||
if (
|
if (
|
||||||
|
|
33
users/templates/users/email_confirmation_request
Normal file
33
users/templates/users/email_confirmation_request
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
Bonjour {{ name }},
|
||||||
|
|
||||||
|
Vous trouverez ci-dessous une URL permettant de confirmer votre
|
||||||
|
adresse mail pour votre compte {{ site_name }}. Celui-ci vous permet de gérer l'ensemble
|
||||||
|
de vos équipements, votre compte, vos factures, et tous les services proposés sur le réseau.
|
||||||
|
|
||||||
|
{{ url }}
|
||||||
|
|
||||||
|
Contactez les administrateurs si vous n'êtes pas à l'origine de cette requête.
|
||||||
|
|
||||||
|
Ce lien expirera dans {{ expire_in }} heures.
|
||||||
|
|
||||||
|
Respectueusement,
|
||||||
|
|
||||||
|
L'équipe de {{ asso }} (contact : {{ asso_mail }}).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Hello {{ name }},
|
||||||
|
|
||||||
|
You will find below an URL allowing you to confirm the email address of your account
|
||||||
|
on {{ site_name }}. It enables you to manage your devices, your account, your invoices, and all
|
||||||
|
the services offered on the network.
|
||||||
|
|
||||||
|
{{ url }}
|
||||||
|
|
||||||
|
Contact the administrators if you didn't request this.
|
||||||
|
|
||||||
|
This link will expire in {{ expire_in }} hours.
|
||||||
|
|
||||||
|
Regards,
|
||||||
|
|
||||||
|
The {{ asso }} team (contact: {{ asso_mail }}).
|
|
@ -105,6 +105,7 @@ from .forms import (
|
||||||
ClubForm,
|
ClubForm,
|
||||||
MassArchiveForm,
|
MassArchiveForm,
|
||||||
PassForm,
|
PassForm,
|
||||||
|
ConfirmMailForm,
|
||||||
ResetPasswordForm,
|
ResetPasswordForm,
|
||||||
ClubAdminandMembersForm,
|
ClubAdminandMembersForm,
|
||||||
GroupForm,
|
GroupForm,
|
||||||
|
@ -126,6 +127,7 @@ def new_user(request):
|
||||||
|
|
||||||
# Use "is False" so that if None, the email is sent
|
# Use "is False" so that if None, the email is sent
|
||||||
if is_set_password_allowed and user.should_send_password_reset_email is False:
|
if is_set_password_allowed and user.should_send_password_reset_email is False:
|
||||||
|
user.confirm_email_address_mail(request)
|
||||||
messages.success(
|
messages.success(
|
||||||
request,
|
request,
|
||||||
_("The user %s was created.")
|
_("The user %s was created.")
|
||||||
|
@ -737,6 +739,7 @@ def mass_archive(request):
|
||||||
.exclude(id__in=all_has_access(search_time=date))
|
.exclude(id__in=all_has_access(search_time=date))
|
||||||
.exclude(state=User.STATE_NOT_YET_ACTIVE)
|
.exclude(state=User.STATE_NOT_YET_ACTIVE)
|
||||||
.exclude(state=User.STATE_FULL_ARCHIVE)
|
.exclude(state=User.STATE_FULL_ARCHIVE)
|
||||||
|
.exclude(state=User.STATE_EMAIL_NOT_YET_CONFIRMED)
|
||||||
)
|
)
|
||||||
if not full_archive:
|
if not full_archive:
|
||||||
to_archive_list = to_archive_list.exclude(state=User.STATE_ARCHIVE)
|
to_archive_list = to_archive_list.exclude(state=User.STATE_ARCHIVE)
|
||||||
|
@ -1020,6 +1023,38 @@ def process_passwd(request, req):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def confirm_email(request, token):
|
||||||
|
"""Lien pour la confirmation de l'email"""
|
||||||
|
valid_reqs = Request.objects.filter(expires_at__gt=timezone.now())
|
||||||
|
req = get_object_or_404(valid_reqs, token=token)
|
||||||
|
|
||||||
|
if req.type == Request.EMAIL:
|
||||||
|
return process_email(request, req)
|
||||||
|
else:
|
||||||
|
messages.error(request, _("Error: please contact an admin."))
|
||||||
|
redirect(reverse("index"))
|
||||||
|
|
||||||
|
|
||||||
|
def process_email(request, req):
|
||||||
|
"""Process la confirmation de mail, renvoie le formulaire
|
||||||
|
de validation"""
|
||||||
|
user = req.user
|
||||||
|
u_form = ConfirmMailForm(request.POST or None, instance=user, user=request.user)
|
||||||
|
if u_form.is_valid():
|
||||||
|
with transaction.atomic(), reversion.create_revision():
|
||||||
|
u_form.save()
|
||||||
|
reversion.set_comment("Email confirmation")
|
||||||
|
req.delete()
|
||||||
|
messages.success(request, _("The email was confirmed."))
|
||||||
|
return redirect(reverse("index"))
|
||||||
|
|
||||||
|
return form(
|
||||||
|
{"userform": u_form, "action_name": _("Confirm the email")},
|
||||||
|
"users/user.html",
|
||||||
|
request,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def initial_register(request):
|
def initial_register(request):
|
||||||
switch_ip = request.GET.get("switch_ip", None)
|
switch_ip = request.GET.get("switch_ip", None)
|
||||||
|
|
Loading…
Reference in a new issue