Le serveur gitlab sera inaccessible le mercredi 19 février 2020 de 13h à 14h pour une intervention de maintenance programmée.

...
 
Commits (10)
# -*- coding: utf-8 -*-
# Generated by Django 1.10.7 on 2018-07-15 14:37
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('preferences', '0034_auto_20180416_1120'),
]
operations = [
migrations.AddField(
model_name='optionaluser',
name='mail_verification',
field=models.BooleanField(default=True, help_text='Vérification du mail obligatoire'),
),
migrations.AddField(
model_name='optionaluser',
name='verification_time',
field=models.PositiveIntegerField(blank=True, help_text='Durée (en heures) pour vérifier son compte (laisser vide pour ne pas avoir de limite', null=True),
),
]
......@@ -102,6 +102,15 @@ class OptionalUser(AclMixin, PreferencesModel):
blank=True,
null=True
)
mail_verification = models.BooleanField(
default=True,
help_text = "Vérification du mail obligatoire"
)
verification_time = models.PositiveIntegerField(
blank=True,
null=True,
help_text = "Durée (en heures) pour vérifier son compte (laisser vide pour ne pas avoir de limite"
)
class Meta:
permissions = (
......
......@@ -71,6 +71,14 @@ with this program; if not, write to the Free Software Foundation, Inc.,
<th>Shell par défaut des utilisateurs</th>
<td>{{ useroptions.shell_default }}</td>
</tr>
<tr>
<th>Vérification du mail</th>
<td>{{ useroptions.mail_verification}}</td>
{% if useroptions.mail_verification %}
<th>Temps pour vérifier</th>
<td>{{ useroptions.verification_time | default:"0" }}h</td>
{% endif %}
</tr>
</table>
<h4>Préférences machines</h4>
<a class="btn btn-primary btn-sm" role="button" href="{% url 'preferences:edit-options' 'OptionalMachine' %}">
......
......@@ -172,6 +172,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
</div>
</div>
<div class="col-sm-8 text-left">
{% if user.is_authenticated and user.verification_message %}
<div class="alert alert-danger">{{user.verification_message}}</div>
{% endif %}
{# Display django.contrib.messages as Bootstrap alerts #}
{% bootstrap_messages %}
<hr>
......
......@@ -295,6 +295,14 @@ class AdherentForm(FormRevMixin, FieldPermissionFormMixin, ModelForm):
"""Formulaire de base d'edition d'un user. Formulaire de base, utilisé
pour l'edition de self par self ou un cableur. On formate les champs
avec des label plus jolis"""
password1 = forms.CharField(widget=forms.PasswordInput, required=False)
password2 = forms.CharField(widget=forms.PasswordInput, required=False)
force = forms.BooleanField(
label="Forcer le déménagement ?",
initial=False,
required=False
)
def __init__(self, *args, **kwargs):
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
super(AdherentForm, self).__init__(*args, prefix=prefix, **kwargs)
......@@ -305,6 +313,9 @@ class AdherentForm(FormRevMixin, FieldPermissionFormMixin, ModelForm):
self.fields['room'].label = 'Chambre'
self.fields['room'].empty_label = "Pas de chambre"
self.fields['school'].empty_label = "Séléctionner un établissement"
self.fields['password1'].label = 'Mot de passe'
self.fields['password2'].label = 'Mot de passe (répétez)'
self.fields['password2'].help_text = 'Laisser les champs mot de passe vide pour envoyer un mail d\'initialisation'
class Meta:
model = Adherent
......@@ -330,11 +341,16 @@ class AdherentForm(FormRevMixin, FieldPermissionFormMixin, ModelForm):
)
return telephone
force = forms.BooleanField(
label="Forcer le déménagement ?",
initial=False,
required=False
)
def clean_password2(self):
"""Vérifie si les mots de passe sont identiques"""
password1 = self.cleaned_data['password1']
password2 = self.cleaned_data['password2']
if(password1 != password2):
raise forms.ValidationError(
"Les mots de passe sont différents"
)
return password2
def clean_force(self):
"""On supprime l'ancien user de la chambre si et seulement si la
......
# -*- coding: utf-8 -*-
# Generated by Django 1.10.7 on 2018-07-15 14:47
from __future__ import unicode_literals
from django.db import migrations, models
def update(apps, schema_editor):
User = apps.get_model('users', 'User')
for u in User.objects.all():
u.verified = True
u.save()
class Migration(migrations.Migration):
dependencies = [
('users', '0072_auto_20180426_2021'),
]
operations = [
migrations.AddField(
model_name='user',
name='verification_deadline',
field=models.DateTimeField(blank=True, null=True),
),
migrations.AddField(
model_name='user',
name='verified',
field=models.BooleanField(default=False),
),
migrations.RunPython(update)
]
......@@ -48,6 +48,7 @@ from __future__ import unicode_literals
import re
import uuid
import datetime
from pytz import timezone
from django.db import models
from django.db.models import Q
......@@ -225,6 +226,13 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser,
blank=True,
null=True
)
verified = models.BooleanField(
default=False
)
verification_deadline = models.DateTimeField(
blank=True,
null = True
)
USERNAME_FIELD = 'pseudo'
REQUIRED_FIELDS = ['surname', 'email']
......@@ -406,8 +414,12 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser,
return True
def has_access(self):
""" Renvoie si un utilisateur a accès à internet """
return (self.state == User.STATE_ACTIVE and
""" Renvoie si un utilisateur a accès à internet """
if(OptionalUser.get_cached_value('mail_verification') and not self.verified and self.verification_deadline is not None and timezone.now() > self.verification_deadline):
verified = False
else:
verified = True
return (verified and self.state == User.STATE_ACTIVE and
not self.is_ban() and
(self.is_connected() or self.is_whitelisted()))
......@@ -578,6 +590,36 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser,
)
return
def send_verification_mail(self, request):
""" Prend en argument un request, envoie un mail de
vérification"""
req = Request()
req.type = Request.EMAIL
req.user = self
req.save()
template = loader.get_template('users/email_verification_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')
) + ' heures',
}
send_mail(
'Vérification du compte de %(name)s / Account verification 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 reset_passwd_mail(self, request):
""" Prend en argument un request, envoie un mail de
réinitialisation de mot de pass """
......@@ -607,6 +649,20 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser,
fail_silently=False
)
return
@property
def verification_message(self):
if(OptionalUser.get_cached_value('mail_verification') and not self.verified):
if(self.verification_deadline is not None):
if(timezone.now() > self.verification_deadline):
message = 'Votre adresse mail n\'est pas vérifiée et votre connexion a été interrompue'
else:
message = 'Votre adresse mail n\'est pas vérifiée. Si vous ne vérifiez pas votre adresse mail, toute connexion sera intérrompu le ' + str(self.verification_deadline)
else:
message = 'Votre adresse mail n\'est pas vérifiée.'
return message
else:
return False
def autoregister_machine(self, mac_address, nas_type):
""" Fonction appellée par freeradius. Enregistre la mac pour
......
Bonjour {{ name }},
Vous trouverez ci-dessous une url permetant dé vérifier compte votre
compte {{ site_name }}. Celui-ci vous permet de gérer l'ensemble de vos équipements
connectés, 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 }}.
Cordialement,
L'équipe de {{ asso }} (contact : {{ asso_mail }}).
----------------------
Hi {{ name }},
You will find a link allowing you to validate your account on {{ site_name }}.
On this website you will then be able to manage your devices on the {{ asso }}.
{{ url }}
This link will expire in {{ expire_in }}.
Send an email at {{ asso_mail }} if you didn't request this or if you have
any other question.
Thanks
The team of {{ asso }} (contact : {{ asso_mail }}).
......@@ -116,4 +116,5 @@ urlpatterns = [
url(r'^rest/ml/club/member/(?P<ml_name>\w+)/$',
views.ml_club_members,
name='ml-club-members'),
url(r'^resend_verification_mail$', views.resend_verification_mail, name="resend_verification_mail'),
]
......@@ -34,6 +34,7 @@ des whitelist, des services users et des écoles
"""
from __future__ import unicode_literals
import datetime
from django.urls import reverse
from django.shortcuts import get_object_or_404, render, redirect
......@@ -45,6 +46,7 @@ from django.db import transaction
from django.http import HttpResponse
from django.http import HttpResponseRedirect
from django.views.decorators.csrf import csrf_exempt
from django.utils import timezone
from rest_framework.renderers import JSONRenderer
from reversion import revisions as reversion
......@@ -111,11 +113,23 @@ def new_user(request):
GTU_sum_up = GeneralOption.get_cached_value('GTU_sum_up')
GTU = GeneralOption.get_cached_value('GTU')
if user.is_valid():
password = user.cleaned_data['password2']
user = user.save(commit=False)
user.save()
user.reset_passwd_mail(request)
messages.success(request, "L'utilisateur %s a été crée, un mail\
pour l'initialisation du mot de passe a été envoyé" % user.pseudo)
if(OptionalUser.get_cached_value('mail_verification')):
user.send_verification_mail(request)
messages.warning(request, "Un mail pour vérifier l'adresse a été envoyé")
if(OptionalUser.get_cached_value('verification_time')>0):
user.verification_deadline = timezone.now() + datetime.timedelta(hours=OptionalUser.get_cached_value('verification_time'))
user.save()
if(password != ""):
user.set_password(password)
user.save()
messages.success(request, "L'utilisateur %s a été créé" % user.pseudo)
else:
user.reset_passwd_mail(request)
messages.success(request, "L'utilisateur %s a été crée, un mail\
pour l'initialisation du mot de passe a été envoyé" % user.pseudo)
return redirect(reverse(
'users:profil',
kwargs={'userid': str(user.id)}
......@@ -947,7 +961,17 @@ def process(request, token):
req = get_object_or_404(valid_reqs, token=token)
if req.type == Request.PASSWD:
user = req.user
user.verified = True
user.save()
messages.success(request, "Le compte a bien été vérifié")
return process_passwd(request, req)
elif req.type == Request.EMAIL:
user = req.user
user.verified= True
user.save()
messages.success(request, "Le compte a bien été vérifié")
return redirect(reverse('login'))
else:
messages.error(request, "Entrée incorrecte, contactez un admin")
redirect(reverse('index'))
......@@ -1047,3 +1071,11 @@ def ml_club_members(request, ml_name):
)
seria = MailingMemberSerializer(members, many=True)
return JSONResponse(seria.data)
@login_required
def resend_verification_mail(request):
if(OptionalUser.get_cached_value('mail_verification')):
request.user.send_verification_mail(request)
messages.success(request, "Un nouveau mail a été envoyé")
return redirect(reverse('users:profil', kwargs={'userid': str(request.user.id)}))