From 729683c9bbd2557dd7e76936f96b1a6d51462517 Mon Sep 17 00:00:00 2001 From: chirac Date: Tue, 26 Jul 2016 02:54:32 +0200 Subject: [PATCH] Ajout des groupes ldap, et d'une vue pour modifier la liste des groupes/droits --- users/admin.py | 22 ++- users/forms.py | 4 +- users/migrations/0021_ldapuser.py | 35 ++++ users/migrations/0022_ldapuser_sambasid.py | 21 +++ users/migrations/0023_auto_20160724_1908.py | 20 +++ .../0024_remove_ldapuser_mac_list.py | 18 ++ users/migrations/0025_listshell.py | 21 +++ users/migrations/0026_user_shell.py | 21 +++ users/migrations/0027_auto_20160726_0216.py | 28 +++ users/migrations/0028_auto_20160726_0227.py | 46 +++++ users/migrations/0029_auto_20160726_0229.py | 20 +++ users/models.py | 163 +++++++++++++++++- users/templates/users/aff_listright.html | 19 ++ users/templates/users/aff_rights.html | 17 ++ users/templates/users/index_listright.html | 15 ++ users/templates/users/index_rights.html | 13 ++ users/templates/users/sidebar.html | 1 + users/urls.py | 5 + users/views.py | 69 +++++++- 19 files changed, 548 insertions(+), 10 deletions(-) create mode 100644 users/migrations/0021_ldapuser.py create mode 100644 users/migrations/0022_ldapuser_sambasid.py create mode 100644 users/migrations/0023_auto_20160724_1908.py create mode 100644 users/migrations/0024_remove_ldapuser_mac_list.py create mode 100644 users/migrations/0025_listshell.py create mode 100644 users/migrations/0026_user_shell.py create mode 100644 users/migrations/0027_auto_20160726_0216.py create mode 100644 users/migrations/0028_auto_20160726_0227.py create mode 100644 users/migrations/0029_auto_20160726_0229.py create mode 100644 users/templates/users/aff_listright.html create mode 100644 users/templates/users/aff_rights.html create mode 100644 users/templates/users/index_listright.html create mode 100644 users/templates/users/index_rights.html diff --git a/users/admin.py b/users/admin.py index ecdea20e..056f1ea9 100644 --- a/users/admin.py +++ b/users/admin.py @@ -3,7 +3,7 @@ from django.contrib.auth.models import Group from django.contrib.auth.admin import UserAdmin as BaseUserAdmin from reversion.admin import VersionAdmin -from .models import User, School, Right, ListRight, Ban, Whitelist, Request +from .models import User, School, Right, ListRight, ListShell, Ban, Whitelist, Request, LdapUser, LdapUserGroup from .forms import UserChangeForm, UserCreationForm @@ -15,17 +15,28 @@ class UserAdmin(admin.ModelAdmin): 'room', 'email', 'school', + 'shell', 'state' ) + search_fields = ('name','surname','pseudo','room') +class LdapUserAdmin(admin.ModelAdmin): + list_display = ('name','uidNumber','loginShell') + search_fields = ('name',) + +class LdapUserGroupAdmin(admin.ModelAdmin): + list_display = ('name','members','gid') + search_fields = ('name',) + class SchoolAdmin(VersionAdmin): list_display = ('name',) - class ListRightAdmin(VersionAdmin): list_display = ('listright',) +class ListShellAdmin(VersionAdmin): + list_display = ('shell',) class RightAdmin(admin.ModelAdmin): list_display = ('user', 'right') @@ -49,11 +60,11 @@ class UserAdmin(VersionAdmin, BaseUserAdmin): # The fields to be used in displaying the User model. # These override the definitions on the base UserAdmin # that reference specific fields on auth.User. - list_display = ('pseudo', 'name', 'surname', 'email', 'school', 'is_admin') + list_display = ('pseudo', 'name', 'surname', 'email', 'school', 'is_admin', 'shell') list_filter = () fieldsets = ( (None, {'fields': ('pseudo', 'password')}), - ('Personal info', {'fields': ('name', 'surname', 'email', 'school')}), + ('Personal info', {'fields': ('name', 'surname', 'email', 'school','shell')}), ('Permissions', {'fields': ('is_admin', )}), ) # add_fieldsets is not a standard ModelAdmin attribute. UserAdmin @@ -69,9 +80,12 @@ class UserAdmin(VersionAdmin, BaseUserAdmin): filter_horizontal = () admin.site.register(User, UserAdmin) +admin.site.register(LdapUser, LdapUserAdmin) +admin.site.register(LdapUserGroup, LdapUserGroupAdmin) admin.site.register(School, SchoolAdmin) admin.site.register(Right, RightAdmin) admin.site.register(ListRight, ListRightAdmin) +admin.site.register(ListShell, ListShellAdmin) admin.site.register(Ban, BanAdmin) admin.site.register(Whitelist, WhitelistAdmin) admin.site.register(Request, RequestAdmin) diff --git a/users/forms.py b/users/forms.py index 8fe0913f..88cd567f 100644 --- a/users/forms.py +++ b/users/forms.py @@ -15,8 +15,8 @@ class PassForm(forms.Form): class UserCreationForm(forms.ModelForm): """A form for creating new users. Includes all the required fields, plus a repeated password.""" - password1 = forms.CharField(label='Password', widget=forms.PasswordInput) - password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput) + password1 = forms.CharField(label='Password', widget=forms.PasswordInput, min_length=8, max_length=255) + password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput, min_length=8, max_length=255) is_admin = forms.BooleanField(label='is admin') class Meta: diff --git a/users/migrations/0021_ldapuser.py b/users/migrations/0021_ldapuser.py new file mode 100644 index 00000000..5cee5f68 --- /dev/null +++ b/users/migrations/0021_ldapuser.py @@ -0,0 +1,35 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models +import ldapdb.models.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('users', '0020_request'), + ] + + operations = [ + migrations.CreateModel( + name='LdapUser', + fields=[ + ('dn', models.CharField(max_length=200)), + ('gid', ldapdb.models.fields.IntegerField(db_column='gidNumber')), + ('name', ldapdb.models.fields.CharField(primary_key=True, max_length=200, db_column='cn', serialize=False)), + ('uid', ldapdb.models.fields.CharField(max_length=200, db_column='uid')), + ('uidNumber', ldapdb.models.fields.IntegerField(unique=True, db_column='uidNumber')), + ('sn', ldapdb.models.fields.CharField(max_length=200, db_column='sn')), + ('loginShell', ldapdb.models.fields.CharField(default='/bin/zsh', max_length=200, db_column='loginShell')), + ('mail', ldapdb.models.fields.CharField(max_length=200, db_column='mail')), + ('given_name', ldapdb.models.fields.CharField(max_length=200, db_column='givenName')), + ('home_directory', ldapdb.models.fields.CharField(max_length=200, db_column='homeDirectory')), + ('dialupAccess', ldapdb.models.fields.CharField(max_length=200, db_column='dialupAccess')), + ('mac_list', ldapdb.models.fields.CharField(max_length=200, db_column='radiusCallingStationId')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/users/migrations/0022_ldapuser_sambasid.py b/users/migrations/0022_ldapuser_sambasid.py new file mode 100644 index 00000000..411339db --- /dev/null +++ b/users/migrations/0022_ldapuser_sambasid.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models +import ldapdb.models.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('users', '0021_ldapuser'), + ] + + operations = [ + migrations.AddField( + model_name='ldapuser', + name='sambaSID', + field=ldapdb.models.fields.IntegerField(db_column='sambaSID', unique=True, null=True), + preserve_default=False, + ), + ] diff --git a/users/migrations/0023_auto_20160724_1908.py b/users/migrations/0023_auto_20160724_1908.py new file mode 100644 index 00000000..0bf1e29a --- /dev/null +++ b/users/migrations/0023_auto_20160724_1908.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models +import ldapdb.models.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('users', '0022_ldapuser_sambasid'), + ] + + operations = [ + migrations.AlterField( + model_name='ldapuser', + name='sambaSID', + field=ldapdb.models.fields.IntegerField(db_column='sambaSID', unique=True), + ), + ] diff --git a/users/migrations/0024_remove_ldapuser_mac_list.py b/users/migrations/0024_remove_ldapuser_mac_list.py new file mode 100644 index 00000000..edaa591e --- /dev/null +++ b/users/migrations/0024_remove_ldapuser_mac_list.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('users', '0023_auto_20160724_1908'), + ] + + operations = [ + migrations.RemoveField( + model_name='ldapuser', + name='mac_list', + ), + ] diff --git a/users/migrations/0025_listshell.py b/users/migrations/0025_listshell.py new file mode 100644 index 00000000..64be05fb --- /dev/null +++ b/users/migrations/0025_listshell.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('users', '0024_remove_ldapuser_mac_list'), + ] + + operations = [ + migrations.CreateModel( + name='ListShell', + fields=[ + ('id', models.AutoField(auto_created=True, serialize=False, primary_key=True, verbose_name='ID')), + ('shell', models.CharField(unique=True, max_length=255)), + ], + ), + ] diff --git a/users/migrations/0026_user_shell.py b/users/migrations/0026_user_shell.py new file mode 100644 index 00000000..8e3432cb --- /dev/null +++ b/users/migrations/0026_user_shell.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('users', '0025_listshell'), + ] + + operations = [ + migrations.AddField( + model_name='user', + name='shell', + field=models.ForeignKey(to='users.ListShell', default=1, on_delete=django.db.models.deletion.PROTECT), + preserve_default=False, + ), + ] diff --git a/users/migrations/0027_auto_20160726_0216.py b/users/migrations/0027_auto_20160726_0216.py new file mode 100644 index 00000000..be8c7df1 --- /dev/null +++ b/users/migrations/0027_auto_20160726_0216.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion +import ldapdb.models.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('users', '0026_user_shell'), + ] + + operations = [ + migrations.CreateModel( + name='LdapUserGroup', + fields=[ + ('dn', models.CharField(max_length=200)), + ('gid', ldapdb.models.fields.IntegerField(db_column='gidNumber')), + ('members', ldapdb.models.fields.ListField(db_column='memberUid', blank=True)), + ('name', ldapdb.models.fields.CharField(db_column='cn', primary_key=True, serialize=False, max_length=200)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/users/migrations/0028_auto_20160726_0227.py b/users/migrations/0028_auto_20160726_0227.py new file mode 100644 index 00000000..79e641a5 --- /dev/null +++ b/users/migrations/0028_auto_20160726_0227.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models +import ldapdb.models.fields +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('users', '0027_auto_20160726_0216'), + ] + + operations = [ + migrations.AddField( + model_name='ldapuser', + name='display_name', + field=ldapdb.models.fields.CharField(null=True, blank=True, max_length=200, db_column='displayName'), + ), + migrations.AddField( + model_name='ldapuser', + name='macs', + field=ldapdb.models.fields.ListField(null=True, blank=True, max_length=200, db_column='radiusCallingStationId'), + ), + migrations.AddField( + model_name='ldapuser', + name='sambat_nt_password', + field=ldapdb.models.fields.CharField(null=True, blank=True, max_length=200, db_column='sambaNTPassword'), + ), + migrations.AddField( + model_name='ldapuser', + name='user_password', + field=ldapdb.models.fields.CharField(null=True, blank=True, max_length=200, db_column='userPassword'), + ), + migrations.AddField( + model_name='listright', + name='gid', + field=models.IntegerField(null=True, unique=True), + ), + migrations.AlterField( + model_name='user', + name='shell', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, default=1, to='users.ListShell'), + ), + ] diff --git a/users/migrations/0029_auto_20160726_0229.py b/users/migrations/0029_auto_20160726_0229.py new file mode 100644 index 00000000..669db5ee --- /dev/null +++ b/users/migrations/0029_auto_20160726_0229.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models +import ldapdb.models.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('users', '0028_auto_20160726_0227'), + ] + + operations = [ + migrations.AlterField( + model_name='ldapuser', + name='display_name', + field=ldapdb.models.fields.CharField(db_column='displayName', max_length=200), + ), + ] diff --git a/users/models.py b/users/models.py index 75eb72e7..a49f8ae0 100644 --- a/users/models.py +++ b/users/models.py @@ -2,8 +2,13 @@ from django.db import models from django.db.models import Q from django.forms import ModelForm, Form from django import forms +from django.db.models.signals import post_save, post_delete +from django.dispatch import receiver -from re2o.settings import RIGHTS_LINK, REQ_EXPIRE_HRS +import ldapdb.models +import ldapdb.models.fields + +from re2o.settings import RIGHTS_LINK, REQ_EXPIRE_HRS, LDAP_SETTINGS import re, uuid import datetime @@ -12,6 +17,7 @@ from django.contrib.auth.models import AbstractBaseUser, BaseUserManager from topologie.models import Room from cotisations.models import Cotisation, Facture, Vente +from machines.models import Interface, Machine def remove_user_room(room): """ Déménage de force l'ancien locataire de la chambre """ @@ -97,6 +103,7 @@ class User(AbstractBaseUser): pseudo = models.CharField(max_length=32, unique=True, help_text="Doit contenir uniquement des lettres, chiffres, ou tirets", validators=[linux_user_validator]) email = models.EmailField() school = models.ForeignKey('School', on_delete=models.PROTECT, null=False, blank=False) + shell = models.ForeignKey('ListShell', on_delete=models.PROTECT, null=False, blank=False, default=1) comment = models.CharField(help_text="Commentaire, promo", 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) @@ -218,9 +225,46 @@ class User(AbstractBaseUser): return user_right.delete() + def ldap_sync(self, base=True, access_refresh=True, mac_refresh=True): + try: + user_ldap = LdapUser.objects.get(name=self.pseudo) + except LdapUser.DoesNotExist: + user_ldap = LdapUser(name=self.pseudo) + if base: + user_ldap.sn = self.pseudo + user_ldap.dialupAccess = str(self.has_access()) + user_ldap.uidNumber = self.id + user_ldap.home_directory = '/home/' + self.pseudo + user_ldap.mail = self.email + user_ldap.given_name = str(self.surname).lower() + '_' + str(self.name).lower()[:3] + user_ldap.gid = LDAP_SETTINGS['user_gid'] + user_ldap.user_password = self.password + user_ldap.sambat_nt_password = self.pwd_ntlm + if access_refresh: + user_ldap.dialupAccess = str(self.has_access()) + if mac_refresh: + user_ldap.macs = [inter.mac_address for inter in Interface.objects.filter(machine=Machine.objects.filter(user=self))] + user_ldap.save() + + def ldap_del(self): + try: + user_ldap = LdapUser.objects.get(name=self.pseudo) + user_ldap.delete() + except LdapUser.DoesNotExist: + pass + def __str__(self): return self.pseudo +@receiver(post_save, sender=User) +def user_post_save(sender, **kwargs): + user = kwargs['instance'] + user.ldap_sync(base=True, access_refresh=True, mac_refresh=False) + +@receiver(post_delete, sender=User) +def user_post_delete(sender, **kwargs): + user = kwargs['instance'] + user.ldap_del() class Right(models.Model): user = models.ForeignKey('User', on_delete=models.PROTECT) @@ -232,6 +276,15 @@ class Right(models.Model): def __str__(self): return str(self.user) + " - " + str(self.right) +@receiver(post_save, sender=Right) +def right_post_save(sender, **kwargs): + right = kwargs['instance'].right + right.ldap_sync() + +@receiver(post_delete, sender=Right) +def right_post_delete(sender, **kwargs): + right = kwargs['instance'].right + right.ldap_sync() class School(models.Model): name = models.CharField(max_length=255) @@ -242,10 +295,42 @@ class School(models.Model): class ListRight(models.Model): listright = models.CharField(max_length=255, unique=True) + gid = models.IntegerField(unique=True, null=True) def __str__(self): return self.listright + def ldap_sync(self): + try: + group_ldap = LdapUserGroup.objects.get(gid=self.gid) + except LdapUserGroup.DoesNotExist: + group_ldap = LdapUserGroup(gid=self.gid) + group_ldap.name = self.listright + group_ldap.members = [right.user.pseudo for right in Right.objects.filter(right=self)] + group_ldap.save() + + def ldap_del(self): + try: + group_ldap = LdapUserGroup.objects.get(gid=self.gid) + group_ldap.delete() + except LdapUserGroup.DoesNotExist: + pass + +@receiver(post_save, sender=ListRight) +def listright_post_save(sender, **kwargs): + right = kwargs['instance'] + right.ldap_sync() + +@receiver(post_delete, sender=ListRight) +def listright_post_delete(sender, **kwargs): + right = kwargs['instance'] + right.ldap_del() + +class ListShell(models.Model): + shell = models.CharField(max_length=255, unique=True) + + def __str__(self): + return self.shell class Ban(models.Model): user = models.ForeignKey('User', on_delete=models.PROTECT) @@ -287,6 +372,59 @@ class Request(models.Model): self.token = str(uuid.uuid4()).replace('-', '') # remove hyphens super(Request, self).save() +class LdapUser(ldapdb.models.Model): + """ + Class for representing an LDAP user entry. + """ + # LDAP meta-data + base_dn = LDAP_SETTINGS['base_user_dn'] + object_classes = ['inetOrgPerson','top','posixAccount','sambaSamAccount','radiusprofile'] + + # attributes + gid = ldapdb.models.fields.IntegerField(db_column='gidNumber') + name = ldapdb.models.fields.CharField(db_column='cn', max_length=200, primary_key=True) + uid = ldapdb.models.fields.CharField(db_column='uid', max_length=200) + uidNumber = ldapdb.models.fields.IntegerField(db_column='uidNumber', unique=True) + sn = ldapdb.models.fields.CharField(db_column='sn', max_length=200) + loginShell = ldapdb.models.fields.CharField(db_column='loginShell', max_length=200, default="/bin/zsh") + mail = ldapdb.models.fields.CharField(db_column='mail', max_length=200) + given_name = ldapdb.models.fields.CharField(db_column='givenName', max_length=200) + home_directory = ldapdb.models.fields.CharField(db_column='homeDirectory', max_length=200) + display_name = ldapdb.models.fields.CharField(db_column='displayName', max_length=200) + dialupAccess = ldapdb.models.fields.CharField(db_column='dialupAccess') + sambaSID = ldapdb.models.fields.IntegerField(db_column='sambaSID', unique=True) + user_password = ldapdb.models.fields.CharField(db_column='userPassword', max_length=200, blank=True, null=True) + sambat_nt_password = ldapdb.models.fields.CharField(db_column='sambaNTPassword', max_length=200, blank=True, null=True) + macs = ldapdb.models.fields.ListField(db_column='radiusCallingStationId', max_length=200, blank=True, null=True) + + def __str__(self): + return self.name + + def __unicode__(self): + return self.name + + def save(self, *args, **kwargs): + self.sn = self.name + self.uid = self.name + self.sambaSID = self.uidNumber + super(LdapUser, self).save(*args, **kwargs) + +class LdapUserGroup(ldapdb.models.Model): + """ + Class for representing an LDAP user entry. + """ + # LDAP meta-data + base_dn = LDAP_SETTINGS['base_usergroup_dn'] + object_classes = ['posixGroup'] + + # attributes + gid = ldapdb.models.fields.IntegerField(db_column='gidNumber') + members = ldapdb.models.fields.ListField(db_column='memberUid', blank=True) + name = ldapdb.models.fields.CharField(db_column='cn', max_length=200, primary_key=True) + + def __str__(self): + return self.name + class BaseInfoForm(ModelForm): def __init__(self, *args, **kwargs): super(BaseInfoForm, self).__init__(*args, **kwargs) @@ -343,6 +481,29 @@ class SchoolForm(ModelForm): super(SchoolForm, self).__init__(*args, **kwargs) self.fields['name'].label = 'Établissement' +class ListRightForm(ModelForm): + class Meta: + model = ListRight + fields = ['listright'] + + def __init__(self, *args, **kwargs): + super(ListRightForm, self).__init__(*args, **kwargs) + self.fields['listright'].label = 'Nom du droit/groupe' + +class NewListRightForm(ListRightForm): + class Meta(ListRightForm.Meta): + fields = '__all__' + + def __init__(self, *args, **kwargs): + super(NewListRightForm, self).__init__(*args, **kwargs) + self.fields['gid'].label = 'Gid, attention, cet attribut ne doit pas être modifié après création' + +class DelListRightForm(ModelForm): + listrights = forms.ModelMultipleChoiceField(queryset=ListRight.objects.all(), label="Droits actuels", widget=forms.CheckboxSelectMultiple) + + class Meta: + exclude = ['listright','gid'] + model = ListRight class DelSchoolForm(ModelForm): schools = forms.ModelMultipleChoiceField(queryset=School.objects.all(), label="Etablissements actuels", widget=forms.CheckboxSelectMultiple) diff --git a/users/templates/users/aff_listright.html b/users/templates/users/aff_listright.html new file mode 100644 index 00000000..b673a34e --- /dev/null +++ b/users/templates/users/aff_listright.html @@ -0,0 +1,19 @@ + + + + + + + + + + {% for listright in listright_list %} + + + + + + + {% endfor %} +
DroitGid
{{ listright.listright }}{{ listright.gid }} Editer Historique
+ diff --git a/users/templates/users/aff_rights.html b/users/templates/users/aff_rights.html new file mode 100644 index 00000000..e6ff5dd0 --- /dev/null +++ b/users/templates/users/aff_rights.html @@ -0,0 +1,17 @@ + + + + {% for right in right_list %} + + + {% endfor %} + + + {% for user_right in user_right_list %} + + + + {% endfor %} +
{{ right }}
{{ user_right }}
+ + diff --git a/users/templates/users/index_listright.html b/users/templates/users/index_listright.html new file mode 100644 index 00000000..9cab2751 --- /dev/null +++ b/users/templates/users/index_listright.html @@ -0,0 +1,15 @@ +{% extends "users/sidebar.html" %} +{% load bootstrap3 %} + +{% block title %}Utilisateurs{% endblock %} + +{% block content %} +

Liste des droits

+ Ajouter un droit ou groupe + Supprimer un ou plusieurs droits/groupes + {% include "users/aff_listright.html" with listright_list=listright_list %} +
+
+
+{% endblock %} + diff --git a/users/templates/users/index_rights.html b/users/templates/users/index_rights.html new file mode 100644 index 00000000..1b0812f5 --- /dev/null +++ b/users/templates/users/index_rights.html @@ -0,0 +1,13 @@ +{% extends "users/sidebar.html" %} +{% load bootstrap3 %} + +{% block title %}Utilisateurs{% endblock %} + +{% block content %} +

Droits

+ {% include "users/aff_rights.html" %} +
+
+
+{% endblock %} + diff --git a/users/templates/users/sidebar.html b/users/templates/users/sidebar.html index 5eefa6b2..9461ac1f 100644 --- a/users/templates/users/sidebar.html +++ b/users/templates/users/sidebar.html @@ -7,6 +7,7 @@

Liste des bannissements

Liste des accès à titre gracieux

Liste des établissements

+

Liste des droits

{% if is_bureau %}

Retirer un droit

{% endif %} diff --git a/users/urls.py b/users/urls.py index 89dda33c..95a5d2e5 100644 --- a/users/urls.py +++ b/users/urls.py @@ -16,10 +16,14 @@ urlpatterns = [ url(r'^add_school/$', views.add_school, name='add-school'), url(r'^edit_school/(?P[0-9]+)$', views.edit_school, name='edit-school'), url(r'^del_school/$', views.del_school, name='del-school'), + url(r'^add_listright/$', views.add_listright, name='add-listright'), + url(r'^edit_listright/(?P[0-9]+)$', views.edit_listright, name='edit-listright'), + url(r'^del_listright/$', views.del_listright, name='del-listright'), url(r'^profil/(?P[0-9]+)$', views.profil, name='profil'), url(r'^index_ban/$', views.index_ban, name='index-ban'), url(r'^index_white/$', views.index_white, name='index-white'), url(r'^index_school/$', views.index_school, name='index-school'), + url(r'^index_listright/$', views.index_listright, name='index-listright'), url(r'^mon_profil/$', views.mon_profil, name='mon-profil'), url(r'^process/(?P[a-z0-9]{32})/$', views.process, name='process'), url(r'^reset_password/$', views.reset_password, name='reset-password'), @@ -27,6 +31,7 @@ urlpatterns = [ url(r'^history/(?Pban)/(?P[0-9]+)$', views.history, name='history'), url(r'^history/(?Pwhitelist)/(?P[0-9]+)$', views.history, name='history'), url(r'^history/(?Pschool)/(?P[0-9]+)$', views.history, name='history'), + url(r'^history/(?Plistright)/(?P[0-9]+)$', views.history, name='history'), url(r'^$', views.index, name='index'), ] diff --git a/users/views.py b/users/views.py index 0c6fe6cb..4d8a53be 100644 --- a/users/views.py +++ b/users/views.py @@ -16,8 +16,8 @@ from django.db import transaction from reversion import revisions as reversion from users.models import User, Right, Ban, Whitelist, School, ListRight, Request -from users.models import DelRightForm, BanForm, WhitelistForm, DelSchoolForm -from users.models import InfoForm, BaseInfoForm, StateForm, RightForm, SchoolForm +from users.models import DelRightForm, BanForm, WhitelistForm, DelSchoolForm, DelListRightForm, NewListRightForm +from users.models import InfoForm, BaseInfoForm, StateForm, RightForm, SchoolForm, ListRightForm from cotisations.models import Facture from machines.models import Machine, Interface from users.forms import PassForm, ResetPasswordForm @@ -93,7 +93,7 @@ def new_user(request): req.save() reset_passwd_mail(req, 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("/users/profil/" + user.id) + return redirect("/users/profil/" + str(user.id)) return form({'userform': user}, 'users/user.html', request) @login_required @@ -327,6 +327,57 @@ def del_school(request): return redirect("/users/index_school/") return form({'userform': school}, 'users/user.html', request) +@login_required +@permission_required('bureau') +def add_listright(request): + listright = NewListRightForm(request.POST or None) + if listright.is_valid(): + with transaction.atomic(), reversion.create_revision(): + listright.save() + reversion.set_user(request.user) + reversion.set_comment("Création") + messages.success(request, "Le droit/groupe a été ajouté") + return redirect("/users/index_listright/") + return form({'userform': listright}, 'users/user.html', request) + +@login_required +@permission_required('bureau') +def edit_listright(request, listrightid): + try: + listright_instance = ListRight.objects.get(pk=listrightid) + except ListRight.DoesNotExist: + messages.error(request, u"Entrée inexistante" ) + return redirect("/users/") + listright = ListRightForm(request.POST or None, instance=listright_instance) + if listright.is_valid(): + with transaction.atomic(), reversion.create_revision(): + listright.save() + reversion.set_user(request.user) + reversion.set_comment("Champs modifié(s) : %s" % ', '.join(field for field in listright.changed_data)) + messages.success(request, "Droit modifié") + return redirect("/users/index_listright/") + return form({'userform': listright}, 'users/user.html', request) + +@login_required +@permission_required('bureau') +def del_listright(request): + listright = DelListRightForm(request.POST or None) + if listright.is_valid(): + listright_dels = listright.cleaned_data['listrights'] + for listright_del in listright_dels: + try: + with transaction.atomic(), reversion.create_revision(): + listright_del.delete() + reversion.set_comment("Destruction") + messages.success(request, "Le droit/groupe a été supprimé") + except ProtectedError: + messages.error( + request, + "L'établissement %s est affecté à au moins un user, \ + vous ne pouvez pas le supprimer" % listright_del) + return redirect("/users/index_listright/") + return form({'userform': listright}, 'users/user.html', request) + @login_required @permission_required('cableur') def index(request): @@ -365,6 +416,12 @@ def index_school(request): school_list = School.objects.order_by('name') return render(request, 'users/index_schools.html', {'school_list':school_list}) +@login_required +@permission_required('cableur') +def index_listright(request): + listright_list = ListRight.objects.order_by('listright') + return render(request, 'users/index_listright.html', {'listright_list':listright_list}) + @login_required def history(request, object, id): if object == 'user': @@ -400,6 +457,12 @@ def history(request, object, id): except School.DoesNotExist: messages.error(request, "Ecole inexistante") return redirect("/users/") + elif object == 'listright' and request.user.has_perms(('cableur',)): + try: + object_instance = ListRight.objects.get(pk=id) + except ListRight.DoesNotExist: + messages.error(request, "Droit inexistant") + return redirect("/users/") else: messages.error(request, "Objet inconnu") return redirect("/users/")