mirror of
https://gitlab2.federez.net/re2o/re2o
synced 2024-09-12 01:03:09 +00:00
Merge branch 'master' into klafyvel
This commit is contained in:
commit
f1d96c196c
10 changed files with 242 additions and 100 deletions
|
@ -292,11 +292,12 @@ def decide_vlan_and_register_switch(nas, nas_type, port_number, mac_address):
|
|||
if not port.room:
|
||||
return (sw_name, u'Chambre inconnue', VLAN_NOK)
|
||||
|
||||
room_user = User.objects.filter(room=port.room)
|
||||
room_user = User.objects.filter(Q(club__room=port.room) | Q(adherent__room=port.room))
|
||||
if not room_user:
|
||||
return (sw_name, u'Chambre non cotisante', VLAN_NOK)
|
||||
elif not room_user.first().has_access():
|
||||
return (sw_name, u'Chambre resident desactive', VLAN_NOK)
|
||||
for user in room_user:
|
||||
if not user.has_access():
|
||||
return (sw_name, u'Chambre resident desactive', VLAN_NOK)
|
||||
# else: user OK, on passe à la verif MAC
|
||||
|
||||
if port.radius == 'COMMON' or port.radius == 'STRICT':
|
||||
|
@ -309,9 +310,12 @@ def decide_vlan_and_register_switch(nas, nas_type, port_number, mac_address):
|
|||
elif not port.room:
|
||||
return (sw_name, u'Chambre et machine inconnues', VLAN_NOK)
|
||||
else:
|
||||
room_user = User.objects.filter(room=Room.objects.filter(name=port.room))
|
||||
if not room_user:
|
||||
room_user = User.objects.filter(Q(club__room=port.room) | Q(adherent__room=port.room))
|
||||
if not room_user:
|
||||
return (sw_name, u'Machine et propriétaire de la chambre inconnus', VLAN_NOK)
|
||||
elif room_user.count() > 1:
|
||||
return (sw_name, u'Machine inconnue, il y a au moins 2 users dans la chambre/local -> ajout de mac automatique impossible', VLAN_NOK)
|
||||
elif not room_user.first().has_access():
|
||||
return (sw_name, u'Machine inconnue et adhérent non cotisant', VLAN_NOK)
|
||||
else:
|
||||
|
|
|
@ -42,7 +42,7 @@ from django.db.models import Q
|
|||
|
||||
from cotisations.models import Cotisation, Facture, Paiement, Vente
|
||||
from machines.models import Domain, Interface, Machine
|
||||
from users.models import User, Ban, Whitelist
|
||||
from users.models import Adherent, User, Ban, Whitelist
|
||||
from preferences.models import Service
|
||||
|
||||
DT_NOW = timezone.now()
|
||||
|
@ -238,3 +238,13 @@ class SortTable:
|
|||
return request.reverse()
|
||||
else:
|
||||
return request
|
||||
|
||||
|
||||
def remove_user_room(room):
|
||||
""" Déménage de force l'ancien locataire de la chambre """
|
||||
try:
|
||||
user = Adherent.objects.get(room=room)
|
||||
except Adherent.DoesNotExist:
|
||||
return
|
||||
user.room = None
|
||||
user.save()
|
||||
|
|
|
@ -81,7 +81,7 @@ def search_result(search, type, request):
|
|||
|
||||
for i in aff:
|
||||
if i == '0':
|
||||
query_user_list = Q(room__name__icontains = search) | Q(pseudo__icontains = search) | Q(adherent__name__icontains = search) | Q(surname__icontains = search) & query1
|
||||
query_user_list = Q(adherent__room__name__icontains = search) | Q(club__room__name__icontains = search) | Q(pseudo__icontains = search) | Q(adherent__name__icontains = search) | Q(surname__icontains = search) & query1
|
||||
if request.user.has_perms(('cableur',)):
|
||||
recherche['users_list'] = User.objects.filter(query_user_list).order_by('state', 'surname').distinct()
|
||||
else :
|
||||
|
|
|
@ -44,13 +44,12 @@ class UserAdmin(admin.ModelAdmin):
|
|||
list_display = (
|
||||
'surname',
|
||||
'pseudo',
|
||||
'room',
|
||||
'email',
|
||||
'school',
|
||||
'shell',
|
||||
'state'
|
||||
)
|
||||
search_fields = ('surname', 'pseudo', 'room')
|
||||
search_fields = ('surname', 'pseudo')
|
||||
|
||||
|
||||
class LdapUserAdmin(admin.ModelAdmin):
|
||||
|
|
106
users/forms.py
106
users/forms.py
|
@ -41,7 +41,8 @@ from django.utils import timezone
|
|||
|
||||
from preferences.models import OptionalUser
|
||||
from .models import User, ServiceUser, Right, School, ListRight, Whitelist
|
||||
from .models import Ban, remove_user_room, Adherent, Club
|
||||
from .models import Ban, Adherent, Club
|
||||
from re2o.utils import remove_user_room
|
||||
|
||||
NOW = timezone.now()
|
||||
|
||||
|
@ -252,13 +253,13 @@ class MassArchiveForm(forms.Form):
|
|||
utilisateurs dont la fin d'accès se situe dans le futur !")
|
||||
|
||||
|
||||
class NewUserForm(ModelForm):
|
||||
class AdherentForm(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"""
|
||||
def __init__(self, *args, **kwargs):
|
||||
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
|
||||
super(NewUserForm, self).__init__(*args, prefix=prefix, **kwargs)
|
||||
super(AdherentForm, self).__init__(*args, prefix=prefix, **kwargs)
|
||||
self.fields['name'].label = 'Prénom'
|
||||
self.fields['surname'].label = 'Nom'
|
||||
self.fields['school'].label = 'Établissement'
|
||||
|
@ -291,18 +292,31 @@ class NewUserForm(ModelForm):
|
|||
)
|
||||
return telephone
|
||||
|
||||
force = forms.BooleanField(
|
||||
label="Forcer le déménagement ?",
|
||||
initial=False,
|
||||
required=False
|
||||
)
|
||||
|
||||
class NewClubForm(ModelForm):
|
||||
def clean_force(self):
|
||||
"""On supprime l'ancien user de la chambre si et seulement si la
|
||||
case est cochée"""
|
||||
if self.cleaned_data.get('force', False):
|
||||
remove_user_room(self.cleaned_data.get('room'))
|
||||
return
|
||||
|
||||
|
||||
class ClubForm(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"""
|
||||
def __init__(self, *args, **kwargs):
|
||||
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
|
||||
super(NewClubForm, self).__init__(*args, prefix=prefix, **kwargs)
|
||||
super(ClubForm, self).__init__(*args, prefix=prefix, **kwargs)
|
||||
self.fields['surname'].label = 'Nom'
|
||||
self.fields['school'].label = 'Établissement'
|
||||
self.fields['comment'].label = 'Commentaire'
|
||||
self.fields['room'].label = 'Chambre'
|
||||
self.fields['room'].label = 'Local'
|
||||
self.fields['room'].empty_label = "Pas de chambre"
|
||||
self.fields['school'].empty_label = "Séléctionner un établissement"
|
||||
|
||||
|
@ -330,51 +344,13 @@ class NewClubForm(ModelForm):
|
|||
return telephone
|
||||
|
||||
|
||||
|
||||
class BaseInfoForm(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"""
|
||||
def __init__(self, *args, **kwargs):
|
||||
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
|
||||
super(BaseInfoForm, self).__init__(*args, prefix=prefix, **kwargs)
|
||||
self.fields['surname'].label = 'Nom'
|
||||
self.fields['school'].label = 'Établissement'
|
||||
self.fields['comment'].label = 'Commentaire'
|
||||
self.fields['room'].label = 'Chambre'
|
||||
self.fields['room'].empty_label = "Pas de chambre"
|
||||
self.fields['school'].empty_label = "Séléctionner un établissement"
|
||||
|
||||
class Meta:
|
||||
model = User
|
||||
fields = [
|
||||
'surname',
|
||||
'pseudo',
|
||||
'email',
|
||||
'school',
|
||||
'comment',
|
||||
'room',
|
||||
'telephone',
|
||||
]
|
||||
|
||||
def clean_telephone(self):
|
||||
"""Verifie que le tel est présent si 'option est validée
|
||||
dans preferences"""
|
||||
telephone = self.cleaned_data['telephone']
|
||||
preferences, _created = OptionalUser.objects.get_or_create()
|
||||
if not telephone and preferences.is_tel_mandatory:
|
||||
raise forms.ValidationError(
|
||||
"Un numéro de téléphone valide est requis"
|
||||
)
|
||||
return telephone
|
||||
|
||||
|
||||
class EditInfoForm(BaseInfoForm):
|
||||
class FullAdherentForm(AdherentForm):
|
||||
"""Edition complète d'un user. Utilisé par admin,
|
||||
permet d'editer normalement la chambre, ou le shell
|
||||
Herite de la base"""
|
||||
class Meta(BaseInfoForm.Meta):
|
||||
class Meta(AdherentForm.Meta):
|
||||
fields = [
|
||||
'name',
|
||||
'surname',
|
||||
'pseudo',
|
||||
'email',
|
||||
|
@ -386,27 +362,21 @@ class EditInfoForm(BaseInfoForm):
|
|||
]
|
||||
|
||||
|
||||
class InfoForm(EditInfoForm):
|
||||
""" Utile pour forcer un déménagement quand il y a déjà un user en place
|
||||
Formuaire utilisé pour la creation initiale"""
|
||||
force = forms.BooleanField(
|
||||
label="Forcer le déménagement ?",
|
||||
initial=False,
|
||||
required=False
|
||||
)
|
||||
|
||||
def clean_force(self):
|
||||
"""On supprime l'ancien user de la chambre si et seulement si la
|
||||
case est cochée"""
|
||||
if self.cleaned_data.get('force', False):
|
||||
remove_user_room(self.cleaned_data.get('room'))
|
||||
return
|
||||
|
||||
|
||||
class UserForm(InfoForm):
|
||||
""" Model form general"""
|
||||
class Meta(InfoForm.Meta):
|
||||
fields = '__all__'
|
||||
class FullClubForm(ClubForm):
|
||||
"""Edition complète d'un user. Utilisé par admin,
|
||||
permet d'editer normalement la chambre, ou le shell
|
||||
Herite de la base"""
|
||||
class Meta(ClubForm.Meta):
|
||||
fields = [
|
||||
'surname',
|
||||
'pseudo',
|
||||
'email',
|
||||
'school',
|
||||
'comment',
|
||||
'room',
|
||||
'shell',
|
||||
'telephone',
|
||||
]
|
||||
|
||||
|
||||
class PasswordForm(ModelForm):
|
||||
|
|
61
users/migrations/0058_auto_20171025_0154.py
Normal file
61
users/migrations/0058_auto_20171025_0154.py
Normal file
|
@ -0,0 +1,61 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.10.7 on 2017-10-24 23:54
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
def create_move_room(apps, schema_editor):
|
||||
User = apps.get_model('users', 'User')
|
||||
Adherent = apps.get_model('users', 'Adherent')
|
||||
Club = apps.get_model('users', 'Club')
|
||||
db_alias = schema_editor.connection.alias
|
||||
users = Adherent.objects.using(db_alias).all()
|
||||
clubs = Club.objects.using(db_alias).all()
|
||||
for user in users:
|
||||
user.room_adherent_id = user.room_id
|
||||
user.save(using=db_alias)
|
||||
for user in clubs:
|
||||
user.room_club_id = user.room_id
|
||||
user.save(using=db_alias)
|
||||
|
||||
|
||||
def delete_move_room(apps, schema_editor):
|
||||
User = apps.get_model('users', 'User')
|
||||
Adherent = apps.get_model('users', 'Adherent')
|
||||
Club = apps.get_model('users', 'Club')
|
||||
db_alias = schema_editor.connection.alias
|
||||
users = Adherent.objects.using(db_alias).all()
|
||||
clubs = Club.objects.using(db_alias).all()
|
||||
for user in users:
|
||||
user.room_id = user.room_adherent_id
|
||||
user.save(using=db_alias)
|
||||
for user in clubs:
|
||||
user.room_id = user.room_club_id
|
||||
user.save(using=db_alias)
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('topologie', '0031_auto_20171015_2033'),
|
||||
('users', '0057_auto_20171023_0301'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='adherent',
|
||||
name='room_adherent',
|
||||
field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='topologie.Room'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='club',
|
||||
name='room_club',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='topologie.Room'),
|
||||
),
|
||||
migrations.RunPython(create_move_room, delete_move_room),
|
||||
migrations.RemoveField(
|
||||
model_name='user',
|
||||
name='room',
|
||||
),
|
||||
]
|
25
users/migrations/0059_auto_20171025_1854.py
Normal file
25
users/migrations/0059_auto_20171025_1854.py
Normal file
|
@ -0,0 +1,25 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.10.7 on 2017-10-25 16:54
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('users', '0058_auto_20171025_0154'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RenameField(
|
||||
model_name='adherent',
|
||||
old_name='room_adherent',
|
||||
new_name='room',
|
||||
),
|
||||
migrations.RenameField(
|
||||
model_name='club',
|
||||
old_name='room_club',
|
||||
new_name='room',
|
||||
),
|
||||
]
|
|
@ -81,15 +81,6 @@ DT_NOW = timezone.now()
|
|||
|
||||
# Utilitaires généraux
|
||||
|
||||
def remove_user_room(room):
|
||||
""" Déménage de force l'ancien locataire de la chambre """
|
||||
try:
|
||||
user = User.objects.get(room=room)
|
||||
except User.DoesNotExist:
|
||||
return
|
||||
user.room = None
|
||||
user.save()
|
||||
|
||||
|
||||
def linux_user_check(login):
|
||||
""" Validation du pseudo pour respecter les contraintes unix"""
|
||||
|
@ -230,12 +221,6 @@ class User(AbstractBaseUser):
|
|||
max_length=255,
|
||||
blank=True
|
||||
)
|
||||
room = models.OneToOneField(
|
||||
'topologie.Room',
|
||||
on_delete=models.PROTECT,
|
||||
blank=True,
|
||||
null=True
|
||||
)
|
||||
pwd_ntlm = models.CharField(max_length=255)
|
||||
state = models.IntegerField(choices=STATES, default=STATE_ACTIVE)
|
||||
registered = models.DateTimeField(auto_now_add=True)
|
||||
|
@ -256,6 +241,16 @@ class User(AbstractBaseUser):
|
|||
else:
|
||||
return ''
|
||||
|
||||
@cached_property
|
||||
def room(self):
|
||||
"""Alias vers room """
|
||||
if self.is_class_adherent:
|
||||
return self.adherent.room
|
||||
elif self.is_class_club:
|
||||
return self.club.room
|
||||
else:
|
||||
raise NotImplementedError("Type inconnu")
|
||||
|
||||
@cached_property
|
||||
def class_name(self):
|
||||
"""Renvoie si il s'agit d'un adhérent ou d'un club"""
|
||||
|
@ -674,10 +669,34 @@ class User(AbstractBaseUser):
|
|||
domain.interface_parent = interface_cible
|
||||
domain.clean()
|
||||
domain.save()
|
||||
self.notif_auto_newmachine(interface_cible)
|
||||
except Exception as error:
|
||||
return False, error
|
||||
return True, "Ok"
|
||||
|
||||
def notif_auto_newmachine(self, interface):
|
||||
"""Notification mail lorsque une machine est automatiquement
|
||||
ajoutée par le radius"""
|
||||
template = loader.get_template('users/email_auto_newmachine')
|
||||
assooptions, _created = AssoOption.objects.get_or_create()
|
||||
general_options, _created = GeneralOption.objects.get_or_create()
|
||||
context = Context({
|
||||
'nom': self.get_full_name(),
|
||||
'mac_address' : interface.mac_address,
|
||||
'asso_name': assooptions.name,
|
||||
'interface_name' : interface.domain,
|
||||
'asso_email': assooptions.contact,
|
||||
'pseudo': self.pseudo,
|
||||
})
|
||||
send_mail(
|
||||
"Ajout automatique d'une machine / New machine autoregistered",
|
||||
'',
|
||||
general_options.email_from,
|
||||
[self.email],
|
||||
html_message=template.render(context)
|
||||
)
|
||||
return
|
||||
|
||||
def set_user_password(self, password):
|
||||
""" A utiliser de préférence, set le password en hash courrant et
|
||||
dans la version ntlm"""
|
||||
|
@ -712,10 +731,22 @@ class User(AbstractBaseUser):
|
|||
|
||||
class Adherent(User):
|
||||
name = models.CharField(max_length=255)
|
||||
room = models.OneToOneField(
|
||||
'topologie.Room',
|
||||
on_delete=models.PROTECT,
|
||||
blank=True,
|
||||
null=True
|
||||
)
|
||||
pass
|
||||
|
||||
|
||||
class Club(User):
|
||||
room = models.ForeignKey(
|
||||
'topologie.Room',
|
||||
on_delete=models.PROTECT,
|
||||
blank=True,
|
||||
null=True
|
||||
)
|
||||
pass
|
||||
|
||||
|
||||
|
|
27
users/templates/users/email_auto_newmachine
Normal file
27
users/templates/users/email_auto_newmachine
Normal file
|
@ -0,0 +1,27 @@
|
|||
<p>Bonjour {{nom}} </p>
|
||||
|
||||
<p>Une nouvelle machine a automatiquement été inscrite sur votre compte.</p>
|
||||
|
||||
<p>Si vous êtes à l'origine de la connexion de cet appareil en filaire ou wifi, ne tenez pas compte de cette notification</p>
|
||||
|
||||
<p>La nouvelle machine possède l'adresse mac {{ mac_address }}, et s'est vu assigner le nom suivant : {{ interface_name }}</p>
|
||||
|
||||
<p>Vous pouvez à tout moment modifier ces informations sur votre compte en ligne</p>
|
||||
|
||||
<p>Si vous n'êtes pas à l'origine de cette connexion, merci de le signaler rapidement à {{asso_email}}</p>
|
||||
|
||||
<p>À bientôt,<br>
|
||||
L'équipe de {{asso_name}}.</p>
|
||||
|
||||
<p>---</p>
|
||||
|
||||
<p>A new device has been automatically added on your account.</p>
|
||||
|
||||
<p>If you connected a new device recently, please don't take this mail into account<p>
|
||||
|
||||
<p>The new device has this mac address : {{ mac_address }}, and this name : {{ interface_name }}</p>
|
||||
|
||||
<p>Please contact us if you didn't connect a new device with this mail address {{asso_email}}.</p>
|
||||
|
||||
<p>Regards,<br>
|
||||
The {{asso_name}} team.</p>
|
|
@ -55,10 +55,10 @@ from users.serializers import MailSerializer
|
|||
from users.models import User, Right, Ban, Whitelist, School, ListRight
|
||||
from users.models import Request, ServiceUser, Adherent, Club
|
||||
from users.forms import DelRightForm, BanForm, WhitelistForm, DelSchoolForm
|
||||
from users.forms import DelListRightForm, NewListRightForm
|
||||
from users.forms import InfoForm, BaseInfoForm, StateForm
|
||||
from users.forms import DelListRightForm, NewListRightForm, FullAdherentForm
|
||||
from users.forms import StateForm, FullClubForm
|
||||
from users.forms import RightForm, SchoolForm, EditServiceUserForm
|
||||
from users.forms import ServiceUserForm, ListRightForm, NewUserForm, NewClubForm
|
||||
from users.forms import ServiceUserForm, ListRightForm, AdherentForm, ClubForm
|
||||
from users.forms import MassArchiveForm, PassForm, ResetPasswordForm
|
||||
from cotisations.models import Facture
|
||||
from machines.models import Machine
|
||||
|
@ -85,7 +85,7 @@ def password_change_action(u_form, user, request, req=False):
|
|||
def new_user(request):
|
||||
""" Vue de création d'un nouvel utilisateur,
|
||||
envoie un mail pour le mot de passe"""
|
||||
user = NewUserForm(request.POST or None)
|
||||
user = AdherentForm(request.POST or None)
|
||||
if user.is_valid():
|
||||
user = user.save(commit=False)
|
||||
with transaction.atomic(), reversion.create_revision():
|
||||
|
@ -104,7 +104,7 @@ def new_user(request):
|
|||
def new_club(request):
|
||||
""" Vue de création d'un nouveau club,
|
||||
envoie un mail pour le mot de passe"""
|
||||
club = NewClubForm(request.POST or None)
|
||||
club = ClubForm(request.POST or None)
|
||||
if club.is_valid():
|
||||
club = club.save(commit=False)
|
||||
with transaction.atomic(), reversion.create_revision():
|
||||
|
@ -118,6 +118,24 @@ def new_club(request):
|
|||
return form({'userform': club}, 'users/user.html', request)
|
||||
|
||||
|
||||
def select_user_edit_form(request, user):
|
||||
"""Fonction de choix du bon formulaire, en fonction de:
|
||||
- droit
|
||||
- type d'object
|
||||
"""
|
||||
if not request.user.has_perms(('cableur',)):
|
||||
if user.is_class_adherent:
|
||||
user = AdherentForm(request.POST or None, instance=user.adherent)
|
||||
elif user.is_class_club:
|
||||
user = ClubForm(request.POST or None, instance=user.club)
|
||||
else:
|
||||
if user.is_class_adherent:
|
||||
user = FullAdherentForm(request.POST or None, instance=user.adherent)
|
||||
elif user.is_class_club:
|
||||
user = FullClubForm(request.POST or None, instance=user.club)
|
||||
return user
|
||||
|
||||
|
||||
@login_required
|
||||
def edit_info(request, userid):
|
||||
""" Edite un utilisateur à partir de son id,
|
||||
|
@ -132,10 +150,7 @@ def edit_info(request, userid):
|
|||
messages.error(request, "Vous ne pouvez pas modifier un autre\
|
||||
user que vous sans droit cableur")
|
||||
return redirect("/users/profil/" + str(request.user.id))
|
||||
if not request.user.has_perms(('cableur',)):
|
||||
user = BaseInfoForm(request.POST or None, instance=user)
|
||||
else:
|
||||
user = InfoForm(request.POST or None, instance=user)
|
||||
user = select_user_edit_form(request, user)
|
||||
if user.is_valid():
|
||||
with transaction.atomic(), reversion.create_revision():
|
||||
user.save()
|
||||
|
|
Loading…
Reference in a new issue