diff --git a/users/acl.py b/users/acl.py index 2e82b0f3..8eca1e63 100644 --- a/users/acl.py +++ b/users/acl.py @@ -26,6 +26,7 @@ Here are defined some functions to check acl on the application. """ + def can_view(user): """Check if an user can view the application. diff --git a/users/forms.py b/users/forms.py index 3617b26f..a43db749 100644 --- a/users/forms.py +++ b/users/forms.py @@ -89,12 +89,16 @@ class PassForm(FormRevMixin, FieldPermissionFormMixin, forms.ModelForm): password1 = self.cleaned_data.get("passwd1") password2 = self.cleaned_data.get("passwd2") if password1 and password2 and password1 != password2: - raise forms.ValidationError("Les 2 nouveaux mots de passe sont différents") + raise forms.ValidationError( + "Les 2 nouveaux mots de passe sont différents" + ) return password2 def clean_selfpasswd(self): """Verifie si il y a lieu que le mdp self est correct""" - if not self.instance.check_password(self.cleaned_data.get("selfpasswd")): + if not self.instance.check_password( + self.cleaned_data.get("selfpasswd") + ): raise forms.ValidationError("Le mot de passe actuel est incorrect") return @@ -386,7 +390,11 @@ class ClubAdminandMembersForm(FormRevMixin, ModelForm): def __init__(self, *args, **kwargs): prefix = kwargs.pop('prefix', self.Meta.model.__name__) - super(ClubAdminandMembersForm, self).__init__(*args, prefix=prefix, **kwargs) + super(ClubAdminandMembersForm, self).__init__( + *args, + prefix=prefix, + **kwargs + ) class PasswordForm(FormRevMixin, ModelForm): diff --git a/users/management/commands/chgpass.py b/users/management/commands/chgpass.py index c3fabf8a..9763ae4c 100644 --- a/users/management/commands/chgpass.py +++ b/users/management/commands/chgpass.py @@ -19,12 +19,14 @@ # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -import os, pwd +import os +import pwd from django.core.management.base import BaseCommand, CommandError from users.forms import PassForm from re2o.script_utils import get_user, get_system_user, form_cli + class Command(BaseCommand): help = "Changer le mot de passe d'un utilisateur" @@ -42,6 +44,13 @@ class Command(BaseCommand): if not ok: raise CommandError(msg) - self.stdout.write("Changement du mot de passe de %s" % target_user.pseudo) + self.stdout.write( + "Changement du mot de passe de %s" % target_user.pseudo + ) - form_cli(PassForm,current_user,"Changement du mot de passe",instance=target_user) + form_cli( + PassForm, + current_user, + "Changement du mot de passe", + instance=target_user + ) diff --git a/users/management/commands/chsh.py b/users/management/commands/chsh.py index 6c5b06f7..6921ad79 100644 --- a/users/management/commands/chsh.py +++ b/users/management/commands/chsh.py @@ -19,7 +19,9 @@ # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -import os, sys, pwd +import os +import sys +import pwd from django.core.management.base import BaseCommand, CommandError from django.db import transaction @@ -28,6 +30,7 @@ from reversion import revisions as reversion from users.models import User, ListShell from re2o.script_utils import get_user, get_system_user + class Command(BaseCommand): help = 'Change the default shell of a user' @@ -36,13 +39,13 @@ class Command(BaseCommand): def handle(self, *args, **options): - current_username = get_system_user() + current_username = get_system_user() current_user = get_user(current_username) target_username = options["target_username"] or current_username target_user = get_user(target_username) - #L'utilisateur n'a pas le droit de changer le shell + # L'utilisateur n'a pas le droit de changer le shell ok, msg = target_user.can_change_shell(current_user) if not ok: raise CommandError(msg) @@ -52,9 +55,16 @@ class Command(BaseCommand): current_shell = "inconnu" if target_user.shell: current_shell = target_user.shell.get_pretty_name() - self.stdout.write("Choisissez un shell pour l'utilisateur %s (le shell actuel est %s) :" % (target_user.pseudo, current_shell)) + self.stdout.write( + "Choisissez un shell pour l'utilisateur %s (le shell actuel est " + "%s) :" % (target_user.pseudo, current_shell) + ) for shell in shells: - self.stdout.write("%d - %s (%s)" % (shell.id, shell.get_pretty_name(), shell.shell)) + self.stdout.write("%d - %s (%s)" % ( + shell.id, + shell.get_pretty_name(), + shell.shell + )) shell_id = input("Entrez un nombre : ") try: @@ -72,4 +82,7 @@ class Command(BaseCommand): reversion.set_user(current_user) reversion.set_comment("Shell modifié") - self.stdout.write(self.style.SUCCESS("Shell modifié. La modification peut prendre quelques minutes pour s'appliquer.")) + self.stdout.write(self.style.SUCCESS( + "Shell modifié. La modification peut prendre quelques minutes " + "pour s'appliquer." + )) diff --git a/users/management/commands/derniere_connexion.py b/users/management/commands/derniere_connexion.py index 94dbf939..d936fda8 100644 --- a/users/management/commands/derniere_connexion.py +++ b/users/management/commands/derniere_connexion.py @@ -4,7 +4,6 @@ # quelques clics. # # Copyright © 2018 Benjamin Graillot -# # Copyright © 2013-2015 Raphaël-David Lasseri # # This program is free software; you can redistribute it and/or modify @@ -32,7 +31,8 @@ from users.models import User # Une liste d'expressions régulières à chercher dans les logs. # Elles doivent contenir un groupe 'date' et un groupe 'user'. -# Pour le CAS on prend comme entrée cat ~/cas.log | grep -B 2 -A 2 "ACTION: AUTHENTICATION_SUCCESS"| grep 'WHEN\|WHO'|sed 'N;s/\n/ /' +# Pour le CAS on prend comme entrée +# cat ~/cas.log | grep -B 2 -A 2 "ACTION: AUTHENTICATION_SUCCESS"| grep 'WHEN\|WHO'|sed 'N;s/\n/ /' COMPILED_REGEX = map(re.compile, [ r'^(?P\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}).*(?:'r'dovecot.*Login: user=<|'r'sshd.*Accepted.*for 'r')(?P[^ >]+).*$', r'^(?P.*) LOGIN INFO User logged in : (?P.*)', @@ -48,8 +48,10 @@ DATE_FORMATS = [ "%a %b %d CEST %H:%M:%S%Y" ] + class Command(BaseCommand): - help = 'Update the time of the latest connection for users by matching stdin against a set of regular expressions' + help = ('Update the time of the latest connection for users by matching ' + 'stdin against a set of regular expressions') def handle(self, *args, **options): @@ -65,7 +67,9 @@ class Command(BaseCommand): for i, regex in enumerate(COMPILED_REGEX): m = regex.match(line) if m: - parsed_log[m.group('user')] = make_aware(datetime.strptime(m.group('date'), DATE_FORMATS[i])) + parsed_log[m.group('user')] = make_aware( + datetime.strptime(m.group('date'), DATE_FORMATS[i]) + ) return parsed_log parsed_log = parse_logs(sys.stdin) diff --git a/users/management/commands/email.py b/users/management/commands/email.py index a7518b9f..5e1d02c4 100644 --- a/users/management/commands/email.py +++ b/users/management/commands/email.py @@ -7,8 +7,11 @@ from users.models import User UTC = pytz.timezone('UTC') + +# TODO : remove of finsihed this because currently it should +# be failing! Who commited that ?! class Command(BaseCommand): - commands = ['email_remainder',] + commands = ['email_remainder'] args = '[command]' help = 'Send email remainders' @@ -27,6 +30,6 @@ class Command(BaseCommand): elif remaining.days == 1: last_day_reminder() + def month_reminder(): pass - diff --git a/users/management/commands/ldap_sync.py b/users/management/commands/ldap_sync.py index 7588ffc9..9301c788 100644 --- a/users/management/commands/ldap_sync.py +++ b/users/management/commands/ldap_sync.py @@ -20,6 +20,7 @@ from django.core.management.base import BaseCommand, CommandError from users.models import User + class Command(BaseCommand): help = 'Synchronise le ldap à partir du sql. A utiliser dans un cron' @@ -37,4 +38,3 @@ class Command(BaseCommand): def handle(self, *args, **options): for usr in User.objects.all(): usr.ldap_sync(mac_refresh=options['full']) - diff --git a/users/models.py b/users/models.py index bacd38cc..a0561aed 100644 --- a/users/models.py +++ b/users/models.py @@ -153,7 +153,7 @@ class UserManager(BaseUserManager): user.set_password(password) if su: - user.is_superuser=True + user.is_superuser = True user.save(using=self._db) return user @@ -171,7 +171,9 @@ class UserManager(BaseUserManager): """ return self._create_user(pseudo, surname, email, password, True) -class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser, PermissionsMixin, AclMixin): + +class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser, + PermissionsMixin, AclMixin): """ Definition de l'utilisateur de base. Champs principaux : name, surnname, pseudo, email, room, password Herite du django BaseUser et du système d'auth django""" @@ -219,7 +221,11 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser, PermissionsMix registered = models.DateTimeField(auto_now_add=True) telephone = models.CharField(max_length=15, blank=True, null=True) uid_number = models.PositiveIntegerField(default=auto_uid, unique=True) - rezo_rez_uid = models.PositiveIntegerField(unique=True, blank=True, null=True) + rezo_rez_uid = models.PositiveIntegerField( + unique=True, + blank=True, + null=True + ) USERNAME_FIELD = 'pseudo' REQUIRED_FIELDS = ['surname', 'email'] @@ -228,13 +234,18 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser, PermissionsMix class Meta: permissions = ( - ("change_user_password", "Peut changer le mot de passe d'un user"), + ("change_user_password", + "Peut changer le mot de passe d'un user"), ("change_user_state", "Peut éditer l'etat d'un user"), ("change_user_force", "Peut forcer un déménagement"), ("change_user_shell", "Peut éditer le shell d'un user"), - ("change_user_groups", "Peut éditer les groupes d'un user ! Permission critique"), - ("change_all_users", "Peut éditer tous les users, y compris ceux dotés de droits. Superdroit"), - ("view_user", "Peut voir un objet user quelquonque"), + ("change_user_groups", + "Peut éditer les groupes d'un user ! Permission critique"), + ("change_all_users", + "Peut éditer tous les users, y compris ceux dotés de droits. " + "Superdroit"), + ("view_user", + "Peut voir un objet user quelquonque"), ) @cached_property @@ -286,7 +297,7 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser, PermissionsMix @property def is_admin(self): """ Renvoie si l'user est admin""" - admin,_ = Group.objects.get_or_create(name="admin") + admin, _ = Group.objects.get_or_create(name="admin") return self.is_superuser or admin in self.groups.all() def get_full_name(self): @@ -393,8 +404,9 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser, PermissionsMix def has_access(self): """ Renvoie si un utilisateur a accès à internet """ - return self.state == User.STATE_ACTIVE\ - and not self.is_ban() and (self.is_connected() or self.is_whitelisted()) + return (self.state == User.STATE_ACTIVE and + not self.is_ban() and + (self.is_connected() or self.is_whitelisted())) def end_access(self): """ Renvoie la date de fin normale d'accès (adhésion ou whiteliste)""" @@ -480,7 +492,8 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser, PermissionsMix self.assign_ips() self.state = User.STATE_ACTIVE - def ldap_sync(self, base=True, access_refresh=True, mac_refresh=True, group_refresh=False): + def ldap_sync(self, base=True, access_refresh=True, mac_refresh=True, + group_refresh=False): """ Synchronisation du ldap. Synchronise dans le ldap les attributs de self Options : base : synchronise tous les attributs de base - nom, prenom, @@ -573,12 +586,15 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser, PermissionsMix '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', - } + reverse('users:process', kwargs={'token': req.token}) + ), + 'expire_in': str( + GeneralOption.get_cached_value('req_expire_hrs') + ) + ' heures', + } send_mail( - 'Changement de mot de passe du %(name)s / Password\ - renewal for %(name)s' % {'name': AssoOption.get_cached_value('name')}, + 'Changement de mot de passe du %(name)s / Password renewal for ' + '%(name)s' % {'name': AssoOption.get_cached_value('name')}, template.render(context), GeneralOption.get_cached_value('email_from'), [req.user.email], @@ -590,7 +606,9 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser, PermissionsMix """ Fonction appellée par freeradius. Enregistre la mac pour une machine inconnue sur le compte de l'user""" all_interfaces = self.user_interfaces(active=False) - if all_interfaces.count() > OptionalMachine.get_cached_value('max_lambdauser_interfaces'): + if all_interfaces.count() > OptionalMachine.get_cached_value( + 'max_lambdauser_interfaces' + ): return False, "Maximum de machines enregistrees atteinte" if not nas_type: return False, "Re2o ne sait pas à quel machinetype affecter cette\ @@ -625,9 +643,9 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser, PermissionsMix template = loader.get_template('users/email_auto_newmachine') context = Context({ 'nom': self.get_full_name(), - 'mac_address' : interface.mac_address, + 'mac_address': interface.mac_address, 'asso_name': AssoOption.get_cached_value('name'), - 'interface_name' : interface.domain, + 'interface_name': interface.domain, 'asso_email': AssoOption.get_cached_value('contact'), 'pseudo': self.pseudo, }) @@ -674,13 +692,13 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser, PermissionsMix :param self: The user which is to be edited. :param user_request: The user who requests to edit self. :return: a message and a boolean which is True if self is a club and - user_request one of its member, or if user_request is self, or if - user_request has the 'cableur' right. + user_request one of its member, or if user_request is self, or if + user_request has the 'cableur' right. """ if self.is_class_club and user_request.is_class_adherent: - if self == user_request or \ - user_request.has_perm('users.change_user') or \ - user_request.adherent in self.club.administrators.all(): + if (self == user_request or + user_request.has_perm('users.change_user') or + user_request.adherent in self.club.administrators.all()): return True, None else: return False, u"Vous n'avez pas le droit d'éditer ce club" @@ -691,52 +709,70 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser, PermissionsMix return True, None elif user_request.has_perm('users.change_user'): if self.groups.filter(listright__critical=True): - return False, u"Utilisateurs avec droits critiques, ne peut etre édité" + return False, (u"Utilisateurs avec droits critiques, ne " + "peut etre édité") elif self == AssoOption.get_cached_value('utilisateur_asso'): - return False, u"Impossible d'éditer l'utilisateur asso sans droit change_all_users" + return False, (u"Impossible d'éditer l'utilisateur asso " + "sans droit change_all_users") else: return True, None elif user_request.has_perm('users.change_all_users'): return True, None else: - return False, u"Vous ne pouvez éditer un autre utilisateur que vous même" + return False, (u"Vous ne pouvez éditer un autre utilisateur " + "que vous même") def can_change_password(self, user_request, *args, **kwargs): if self.is_class_club and user_request.is_class_adherent: - if self == user_request or \ - user_request.has_perm('users.change_user_password') or \ - user_request.adherent in self.club.administrators.all(): + if (self == user_request or + user_request.has_perm('users.change_user_password') or + user_request.adherent in self.club.administrators.all()): return True, None else: return False, u"Vous n'avez pas le droit d'éditer ce club" else: - if self == user_request or \ - user_request.has_perm('users.change_user_groups'): - # Peut éditer les groupes d'un user, c'est un privilège élevé, True + if (self == user_request or + user_request.has_perm('users.change_user_groups')): + # Peut éditer les groupes d'un user, + # c'est un privilège élevé, True return True, None - elif user_request.has_perm('users.change_user') and not self.groups.all(): + elif (user_request.has_perm('users.change_user') and + not self.groups.all()): return True, None else: - return False, u"Vous ne pouvez éditer un autre utilisateur que vous même" + return False, (u"Vous ne pouvez éditer un autre utilisateur " + "que vous même") def check_selfpasswd(self, user_request, *args, **kwargs): return user_request == self, None @staticmethod def can_change_state(user_request, *args, **kwargs): - return user_request.has_perm('users.change_user_state'), "Droit requis pour changer l'état" + return ( + user_request.has_perm('users.change_user_state'), + "Droit requis pour changer l'état" + ) @staticmethod def can_change_shell(user_request, *args, **kwargs): - return user_request.has_perm('users.change_user_shell'), "Droit requis pour changer le shell" + return ( + user_request.has_perm('users.change_user_shell'), + "Droit requis pour changer le shell" + ) @staticmethod def can_change_force(user_request, *args, **kwargs): - return user_request.has_perm('users.change_user_force'), "Droit requis pour forcer le déménagement" + return ( + user_request.has_perm('users.change_user_force'), + "Droit requis pour forcer le déménagement" + ) @staticmethod def can_change_groups(user_request, *args, **kwargs): - return user_request.has_perm('users.change_user_groups'), "Droit requis pour éditer les groupes de l'user" + return ( + user_request.has_perm('users.change_user_groups'), + "Droit requis pour éditer les groupes de l'user" + ) def can_view(self, user_request, *args, **kwargs): """Check if an user can view an user object. @@ -744,45 +780,55 @@ class User(RevMixin, FieldPermissionModelMixin, AbstractBaseUser, PermissionsMix :param self: The targeted user. :param user_request: The user who ask for viewing the target. :return: A boolean telling if the acces is granted and an explanation - text + text """ if self.is_class_club and user_request.is_class_adherent: - if self == user_request or \ - user_request.has_perm('users.view_user') or \ - user_request.adherent in self.club.administrators.all() or \ - user_request.adherent in self.club.members.all(): + if (self == user_request or + user_request.has_perm('users.view_user') or + user_request.adherent in self.club.administrators.all() or + user_request.adherent in self.club.members.all()): return True, None else: return False, u"Vous n'avez pas le droit de voir ce club" else: - if self == user_request or user_request.has_perm('users.view_user'): + if (self == user_request or + user_request.has_perm('users.view_user')): return True, None else: - return False, u"Vous ne pouvez voir un autre utilisateur que vous même" + return False, (u"Vous ne pouvez voir un autre utilisateur " + "que vous même") def can_view_all(user_request, *args, **kwargs): """Check if an user can access to the list of every user objects :param user_request: The user who wants to view the list. - :return: True if the user can view the list and an explanation message. + :return: True if the user can view the list and an explanation + message. """ - return user_request.has_perm('users.view_user'), u"Vous n'avez pas accès à la liste des utilisateurs." + return ( + user_request.has_perm('users.view_user'), + u"Vous n'avez pas accès à la liste des utilisateurs." + ) def can_delete(self, user_request, *args, **kwargs): """Check if an user can delete an user object. :param self: The user who is to be deleted. :param user_request: The user who requests deletion. - :return: True if user_request has the right 'bureau', and a message. + :return: True if user_request has the right 'bureau', and a + message. """ - return user_request.has_perm('users.delete_user'), u"Vous ne pouvez pas supprimer cet utilisateur." + return ( + user_request.has_perm('users.delete_user'), + u"Vous ne pouvez pas supprimer cet utilisateur." + ) def __init__(self, *args, **kwargs): super(User, self).__init__(*args, **kwargs) self.field_permissions = { - 'shell' : self.can_change_shell, - 'force' : self.can_change_force, - 'selfpasswd' : self.check_selfpasswd, + 'shell': self.can_change_shell, + 'force': self.can_change_force, + 'selfpasswd': self.check_selfpasswd, } def __str__(self): @@ -812,16 +858,20 @@ class Adherent(User): :param user_request: The user who wants to create a user object. :return: a message and a boolean which is True if the user can create - an user or if the `options.all_can_create` is set. + a user or if the `options.all_can_create` is set. """ - if(not user_request.is_authenticated and not OptionalUser.get_cached_value('self_adhesion')): + if (not user_request.is_authenticated and + not OptionalUser.get_cached_value('self_adhesion')): return False, None else: - if(OptionalUser.get_cached_value('all_can_create_adherent') or OptionalUser.get_cached_value('self_adhesion')): + if (OptionalUser.get_cached_value('all_can_create_adherent') or + OptionalUser.get_cached_value('self_adhesion')): return True, None else: - return user_request.has_perm('users.add_user'), u"Vous n'avez pas le\ - droit de créer un utilisateur" + return ( + user_request.has_perm('users.add_user'), + u"Vous n'avez pas le droit de créer un utilisateur" + ) class Club(User): @@ -843,7 +893,7 @@ class Club(User): related_name='club_members' ) mailing = models.BooleanField( - default = False + default=False ) def can_create(user_request, *args, **kwargs): @@ -851,7 +901,7 @@ class Club(User): :param user_request: The user who wants to create a user object. :return: a message and a boolean which is True if the user can create - an user or if the `options.all_can_create` is set. + an user or if the `options.all_can_create` is set. """ if not user_request.is_authenticated: return False, None @@ -859,19 +909,24 @@ class Club(User): if OptionalUser.get_cached_value('all_can_create_club'): return True, None else: - return user_request.has_perm('users.add_user'), u"Vous n'avez pas le\ - droit de créer un club" + return ( + user_request.has_perm('users.add_user'), + u"Vous n'avez pas le droit de créer un club" + ) def can_view_all(user_request, *args, **kwargs): """Check if an user can access to the list of every user objects :param user_request: The user who wants to view the list. - :return: True if the user can view the list and an explanation message. + :return: True if the user can view the list and an explanation + message. """ if user_request.has_perm('users.view_user'): return True, None - if hasattr(user_request,'is_class_adherent') and user_request.is_class_adherent: - if user_request.adherent.club_administrator.all() or user_request.adherent.club_members.all(): + if (hasattr(user_request, 'is_class_adherent') and + user_request.is_class_adherent): + if (user_request.adherent.club_administrator.all() or + user_request.adherent.club_members.all()): return True, None return False, u"Vous n'avez pas accès à la liste des utilisateurs." @@ -892,9 +947,15 @@ def user_post_save(sender, **kwargs): Synchronise le ldap""" is_created = kwargs['created'] user = kwargs['instance'] - #if is_created: - #user.notif_inscription() - user.ldap_sync(base=True, access_refresh=True, mac_refresh=False, group_refresh=True) + # TODO : remove if unnecessary + # if is_created: + # user.notif_inscription() + user.ldap_sync( + base=True, + access_refresh=True, + mac_refresh=False, + group_refresh=True + ) regen('mailing') @@ -907,6 +968,7 @@ def user_post_delete(sender, **kwargs): user.ldap_del() regen('mailing') + class ServiceUser(RevMixin, AclMixin, AbstractBaseUser): """ Classe des users daemons, règle leurs accès au ldap""" readonly = 'readonly' @@ -977,6 +1039,7 @@ class ServiceUser(RevMixin, AclMixin, AbstractBaseUser): def __str__(self): return self.pseudo + @receiver(post_save, sender=ServiceUser) def service_user_post_save(sender, **kwargs): """ Synchronise un service user ldap après modification django""" @@ -1019,8 +1082,8 @@ class ListRight(RevMixin, AclMixin, Group): unique=True, validators=[RegexValidator( '^[a-z]+$', - message="Les groupes unix ne peuvent contenir\ - que des lettres minuscules" + message=("Les groupes unix ne peuvent contenir que des lettres " + "minuscules") )] ) gid = models.PositiveIntegerField(unique=True, null=True) @@ -1148,10 +1211,10 @@ class Ban(RevMixin, AclMixin, models.Model): :return: A boolean telling if the acces is granted and an explanation text """ - if not user_request.has_perm('users.view_ban') and\ - self.user != user_request: - return False, u"Vous n'avez pas le droit de voir les bannissements\ - autre que les vôtres" + if (not user_request.has_perm('users.view_ban') and + self.user != user_request): + return False, (u"Vous n'avez pas le droit de voir les " + "bannissements autre que les vôtres") else: return True, None @@ -1213,10 +1276,10 @@ class Whitelist(RevMixin, AclMixin, models.Model): :return: A boolean telling if the acces is granted and an explanation text """ - if not user_request.has_perm('users.view_whitelist') and\ - self.user != user_request: - return False, u"Vous n'avez pas le droit de voir les accès\ - gracieux autre que les vôtres" + if (not user_request.has_perm('users.view_whitelist') and + self.user != user_request): + return False, (u"Vous n'avez pas le droit de voir les accès " + "gracieux autre que les vôtres") else: return True, None @@ -1270,8 +1333,12 @@ class Request(models.Model): def save(self): if not self.expires_at: - self.expires_at = timezone.now() \ - + datetime.timedelta(hours=GeneralOption.get_cached_value('req_expire_hrs')) + self.expires_at = (timezone.now() + + datetime.timedelta( + hours=GeneralOption.get_cached_value( + 'req_expire_hrs' + ) + )) if not self.token: self.token = str(uuid.uuid4()).replace('-', '') # remove hyphens super(Request, self).save() @@ -1375,7 +1442,10 @@ class LdapUserGroup(ldapdb.models.Model): # attributes gid = ldapdb.models.fields.IntegerField(db_column='gidNumber') - members = ldapdb.models.fields.ListField(db_column='memberUid', blank=True) + members = ldapdb.models.fields.ListField( + db_column='memberUid', + blank=True + ) name = ldapdb.models.fields.CharField( db_column='cn', max_length=200, diff --git a/users/serializers.py b/users/serializers.py index 95388d41..d2f66abe 100644 --- a/users/serializers.py +++ b/users/serializers.py @@ -20,11 +20,12 @@ # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -#Maël Kervella +# Maël Kervella from rest_framework import serializers from users.models import Club, Adherent + class MailingSerializer(serializers.ModelSerializer): name = serializers.CharField(source='pseudo') @@ -32,6 +33,7 @@ class MailingSerializer(serializers.ModelSerializer): model = Club fields = ('name',) + class MailingMemberSerializer(serializers.ModelSerializer): class Meta: model = Adherent diff --git a/users/urls.py b/users/urls.py index b8f428b0..05f72be0 100644 --- a/users/urls.py +++ b/users/urls.py @@ -34,109 +34,79 @@ urlpatterns = [ url(r'^new_user/$', views.new_user, name='new-user'), url(r'^new_club/$', views.new_club, name='new-club'), url(r'^edit_info/(?P[0-9]+)$', views.edit_info, name='edit-info'), - url( - r'^edit_club_admin_members/(?P[0-9]+)$', + url(r'^edit_club_admin_members/(?P[0-9]+)$', views.edit_club_admin_members, - name='edit-club-admin-members' - ), + name='edit-club-admin-members'), url(r'^state/(?P[0-9]+)$', views.state, name='state'), url(r'^groups/(?P[0-9]+)$', views.groups, name='groups'), url(r'^password/(?P[0-9]+)$', views.password, name='password'), - url(r'^del_group/(?P[0-9]+)/(?P[0-9]+)$', views.del_group, name='del-group'), + url(r'^del_group/(?P[0-9]+)/(?P[0-9]+)$', + views.del_group, + name='del-group'), url(r'^new_serviceuser/$', views.new_serviceuser, name='new-serviceuser'), - url( - r'^edit_serviceuser/(?P[0-9]+)$', + url(r'^edit_serviceuser/(?P[0-9]+)$', views.edit_serviceuser, - name='edit-serviceuser' - ), - url( - r'^del_serviceuser/(?P[0-9]+)$', + name='edit-serviceuser'), + url(r'^del_serviceuser/(?P[0-9]+)$', views.del_serviceuser, - name='del-serviceuser' - ), + name='del-serviceuser'), url(r'^add_ban/(?P[0-9]+)$', views.add_ban, name='add-ban'), url(r'^edit_ban/(?P[0-9]+)$', views.edit_ban, name='edit-ban'), - url( - r'^add_whitelist/(?P[0-9]+)$', + url(r'^add_whitelist/(?P[0-9]+)$', views.add_whitelist, - name='add-whitelist' - ), - url( - r'^edit_whitelist/(?P[0-9]+)$', + name='add-whitelist'), + url(r'^edit_whitelist/(?P[0-9]+)$', views.edit_whitelist, - name='edit-whitelist' - ), + name='edit-whitelist'), url(r'^add_school/$', views.add_school, name='add-school'), - url( - r'^edit_school/(?P[0-9]+)$', + url(r'^edit_school/(?P[0-9]+)$', views.edit_school, - name='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]+)$', + url(r'^edit_listright/(?P[0-9]+)$', views.edit_listright, - name='edit-listright' - ), + name='edit-listright'), url(r'^del_listright/$', views.del_listright, name='del-listright'), url(r'^add_shell/$', views.add_shell, name='add-shell'), - url( - r'^edit_shell/(?P[0-9]+)$', + url(r'^edit_shell/(?P[0-9]+)$', views.edit_shell, - name='edit-shell' - ), - url( - r'^del_shell/(?P[0-9]+)$', + name='edit-shell'), + url(r'^del_shell/(?P[0-9]+)$', views.del_shell, - name='del-shell' - ), + name='del-shell'), 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_shell/$', views.index_shell, name='index-shell'), url(r'^index_listright/$', views.index_listright, name='index-listright'), - url( - r'^index_serviceusers/$', + url(r'^index_serviceusers/$', views.index_serviceusers, - name='index-serviceusers' - ), + name='index-serviceusers'), 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'), url(r'^mass_archive/$', views.mass_archive, name='mass-archive'), - url( - r'^history/(?P\w+)/(?P[0-9]+)$', + url(r'^history/(?P\w+)/(?P[0-9]+)$', re2o.views.history, name='history', - kwargs={'application':'users'}, - ), + kwargs={'application': 'users'}), url(r'^$', views.index, name='index'), url(r'^index_clubs/$', views.index_clubs, name='index-clubs'), - url( - r'^rest/ml/std/$', + url(r'^rest/ml/std/$', views.ml_std_list, - name='ml-std-list' - ), - url( - r'^rest/ml/std/member/(?P\w+)/$', + name='ml-std-list'), + url(r'^rest/ml/std/member/(?P\w+)/$', views.ml_std_members, - name='ml-std-members' - ), - url( - r'^rest/ml/club/$', + name='ml-std-members'), + url(r'^rest/ml/club/$', views.ml_club_list, - name='ml-club-list' - ), - url( - r'^rest/ml/club/admin/(?P\w+)/$', + name='ml-club-list'), + url(r'^rest/ml/club/admin/(?P\w+)/$', views.ml_club_admins, - name='ml-club-admins' - ), - url( - r'^rest/ml/club/member/(?P\w+)/$', + name='ml-club-admins'), + url(r'^rest/ml/club/member/(?P\w+)/$', views.ml_club_members, - name='ml-club-members' - ), + name='ml-club-members'), ] diff --git a/users/views.py b/users/views.py index b0cfb000..d82d5563 100644 --- a/users/views.py +++ b/users/views.py @@ -106,6 +106,7 @@ from re2o.acl import ( can_change ) + @can_create(Adherent) def new_user(request): """ Vue de création d'un nouvel utilisateur, @@ -121,9 +122,19 @@ def new_user(request): pour l'initialisation du mot de passe a été envoyé" % user.pseudo) return redirect(reverse( 'users:profil', - kwargs={'userid':str(user.id)} - )) - return form({'userform': user,'GTU_sum_up':GTU_sum_up,'GTU':GTU,'showCGU':True, 'action_name':'Créer un utilisateur'}, 'users/user.html', request) + kwargs={'userid': str(user.id)} + )) + return form( + { + 'userform': user, + 'GTU_sum_up': GTU_sum_up, + 'GTU': GTU, + 'showCGU': True, + 'action_name': 'Créer un utilisateur' + }, + 'users/user.html', + request + ) @login_required @@ -140,9 +151,13 @@ def new_club(request): pour l'initialisation du mot de passe a été envoyé" % club.pseudo) return redirect(reverse( 'users:profil', - kwargs={'userid':str(club.id)} - )) - return form({'userform': club, 'showCGU':False, 'action_name':'Créer un club'}, 'users/user.html', request) + kwargs={'userid': str(club.id)} + )) + return form( + {'userform': club, 'showCGU': False, 'action_name': 'Créer un club'}, + 'users/user.html', + request + ) @login_required @@ -150,16 +165,27 @@ def new_club(request): def edit_club_admin_members(request, club_instance, clubid): """Vue d'edition de la liste des users administrateurs et membres d'un club""" - club = ClubAdminandMembersForm(request.POST or None, instance=club_instance) + club = ClubAdminandMembersForm( + request.POST or None, + instance=club_instance + ) if club.is_valid(): if club.changed_data: club.save() messages.success(request, "Le club a bien été modifié") return redirect(reverse( 'users:profil', - kwargs={'userid':str(club_instance.id)} - )) - return form({'userform': club, 'showCGU':False, 'action_name':'Editer les admin et membres'}, 'users/user.html', request) + kwargs={'userid': str(club_instance.id)} + )) + return form( + { + 'userform': club, + 'showCGU': False, + 'action_name': 'Editer les admin et membres' + }, + 'users/user.html', + request + ) @login_required @@ -186,9 +212,13 @@ def edit_info(request, user, userid): messages.success(request, "L'user a bien été modifié") return redirect(reverse( 'users:profil', - kwargs={'userid':str(userid)} - )) - return form({'userform': user, 'action_name': "Editer l'utilisateur"}, 'users/user.html', request) + kwargs={'userid': str(userid)} + )) + return form( + {'userform': user, 'action_name': "Editer l'utilisateur"}, + 'users/user.html', + request + ) @login_required @@ -207,9 +237,13 @@ def state(request, user, userid): messages.success(request, "Etat changé avec succès") return redirect(reverse( 'users:profil', - kwargs={'userid':str(userid)} - )) - return form({'userform': state, 'action_name': "Editer l'état"}, 'users/user.html', request) + kwargs={'userid': str(userid)} + )) + return form( + {'userform': state, 'action_name': "Editer l'état"}, + 'users/user.html', + request + ) @login_required @@ -222,9 +256,13 @@ def groups(request, user, userid): messages.success(request, "Groupes changés avec succès") return redirect(reverse( 'users:profil', - kwargs={'userid':str(userid)} + kwargs={'userid': str(userid)} )) - return form({'userform': group, 'action_name':'Editer les groupes'}, 'users/user.html', request) + return form( + {'userform': group, 'action_name': 'Editer les groupes'}, + 'users/user.html', + request + ) @login_required @@ -239,10 +277,14 @@ def password(request, user, userid): u_form.save() messages.success(request, "Le mot de passe a changé") return redirect(reverse( - 'users:profil', - kwargs={'userid':str(user.id)} + 'users:profil', + kwargs={'userid': str(user.id)} )) - return form({'userform': u_form, 'action_name':'Changer le mot de passe'}, 'users/user.html', request) + return form( + {'userform': u_form, 'action_name': 'Changer le mot de passe'}, + 'users/user.html', + request + ) @login_required @@ -268,14 +310,21 @@ def new_serviceuser(request): "L'utilisateur %s a été crée" % user_object.pseudo ) return redirect(reverse('users:index-serviceusers')) - return form({'userform': user, 'action_name':'Créer un serviceuser'}, 'users/user.html', request) + return form( + {'userform': user, 'action_name': 'Créer un serviceuser'}, + 'users/user.html', + request + ) @login_required @can_edit(ServiceUser) def edit_serviceuser(request, serviceuser, serviceuserid): """ Edit a ServiceUser """ - serviceuser = EditServiceUserForm(request.POST or None, instance=serviceuser) + serviceuser = EditServiceUserForm( + request.POST or None, + instance=serviceuser + ) if serviceuser.is_valid(): user_object = serviceuser.save(commit=False) if serviceuser.cleaned_data['password']: @@ -284,7 +333,11 @@ def edit_serviceuser(request, serviceuser, serviceuserid): user_object.save() messages.success(request, "L'user a bien été modifié") return redirect(reverse('users:index-serviceusers')) - return form({'userform': serviceuser, 'action_name':'Editer un serviceuser'}, 'users/user.html', request) + return form( + {'userform': serviceuser, 'action_name': 'Editer un serviceuser'}, + 'users/user.html', + request + ) @login_required @@ -316,14 +369,19 @@ def add_ban(request, user, userid): messages.success(request, "Bannissement ajouté") return redirect(reverse( 'users:profil', - kwargs={'userid':str(userid)} + kwargs={'userid': str(userid)} )) if user.is_ban(): messages.error( request, "Attention, cet utilisateur a deja un bannissement actif" ) - return form({'userform': ban, 'action_name': 'Ajouter un ban'}, 'users/user.html', request) + return form( + {'userform': ban, 'action_name': 'Ajouter un ban'}, + 'users/user.html', + request + ) + @login_required @can_edit(Ban) @@ -337,7 +395,11 @@ def edit_ban(request, ban_instance, banid): ban.save() messages.success(request, "Bannissement modifié") return redirect(reverse('users:index')) - return form({'userform': ban, 'action_name': 'Editer un ban'}, 'users/user.html', request) + return form( + {'userform': ban, 'action_name': 'Editer un ban'}, + 'users/user.html', + request + ) @login_required @@ -358,14 +420,18 @@ def add_whitelist(request, user, userid): messages.success(request, "Accès à titre gracieux accordé") return redirect(reverse( 'users:profil', - kwargs={'userid':str(userid)} - )) + kwargs={'userid': str(userid)} + )) if user.is_whitelisted(): messages.error( request, "Attention, cet utilisateur a deja un accès gracieux actif" ) - return form({'userform': whitelist, 'action_name': 'Ajouter une whitelist'}, 'users/user.html', request) + return form( + {'userform': whitelist, 'action_name': 'Ajouter une whitelist'}, + 'users/user.html', + request + ) @login_required @@ -384,7 +450,11 @@ def edit_whitelist(request, whitelist_instance, whitelistid): whitelist.save() messages.success(request, "Whitelist modifiée") return redirect(reverse('users:index')) - return form({'userform': whitelist, 'action_name': 'Editer une whitelist'}, 'users/user.html', request) + return form( + {'userform': whitelist, 'action_name': 'Editer une whitelist'}, + 'users/user.html', + request + ) @login_required @@ -397,7 +467,11 @@ def add_school(request): school.save() messages.success(request, "L'établissement a été ajouté") return redirect(reverse('users:index-school')) - return form({'userform': school, 'action_name':'Ajouter'}, 'users/user.html', request) + return form( + {'userform': school, 'action_name': 'Ajouter'}, + 'users/user.html', + request + ) @login_required @@ -411,7 +485,11 @@ def edit_school(request, school_instance, schoolid): school.save() messages.success(request, "Établissement modifié") return redirect(reverse('users:index-school')) - return form({'userform': school, 'action_name':'Editer'}, 'users/user.html', request) + return form( + {'userform': school, 'action_name': 'Editer'}, + 'users/user.html', + request + ) @login_required @@ -434,7 +512,11 @@ def del_school(request, instances): "L'établissement %s est affecté à au moins un user, \ vous ne pouvez pas le supprimer" % school_del) return redirect(reverse('users:index-school')) - return form({'userform': school, 'action_name': 'Supprimer'}, 'users/user.html', request) + return form( + {'userform': school, 'action_name': 'Supprimer'}, + 'users/user.html', + request + ) @login_required @@ -446,7 +528,11 @@ def add_shell(request): shell.save() messages.success(request, "Le shell a été ajouté") return redirect(reverse('users:index-shell')) - return form({'userform': shell, 'action_name':'Ajouter'}, 'users/user.html', request) + return form( + {'userform': shell, 'action_name': 'Ajouter'}, + 'users/user.html', + request + ) @login_required @@ -459,7 +545,11 @@ def edit_shell(request, shell_instance, listshellid): shell.save() messages.success(request, "Le shell a été modifié") return redirect(reverse('users:index-shell')) - return form({'userform': shell, 'action_name':'Editer'}, 'users/user.html', request) + return form( + {'userform': shell, 'action_name': 'Editer'}, + 'users/user.html', + request + ) @login_required @@ -487,7 +577,11 @@ def add_listright(request): listright.save() messages.success(request, "Le droit/groupe a été ajouté") return redirect(reverse('users:index-listright')) - return form({'userform': listright, 'action_name': 'Ajouter'}, 'users/user.html', request) + return form( + {'userform': listright, 'action_name': 'Ajouter'}, + 'users/user.html', + request + ) @login_required @@ -504,7 +598,11 @@ def edit_listright(request, listright_instance, listrightid): listright.save() messages.success(request, "Droit modifié") return redirect(reverse('users:index-listright')) - return form({'userform': listright, 'action_name': 'Editer'}, 'users/user.html', request) + return form( + {'userform': listright, 'action_name': 'Editer'}, + 'users/user.html', + request + ) @login_required @@ -525,7 +623,11 @@ def del_listright(request, instances): "Le groupe %s est affecté à au moins un user, \ vous ne pouvez pas le supprimer" % listright_del) return redirect(reverse('users:index-listright')) - return form({'userform': listright, 'action_name': 'Supprimer'}, 'users/user.html', request) + return form( + {'userform': listright, 'action_name': 'Supprimer'}, + 'users/user.html', + request + ) @login_required @@ -587,7 +689,11 @@ def index_clubs(request): SortTable.USERS_INDEX ) clubs_list = re2o_paginator(request, clubs_list, pagination_number) - return render(request, 'users/index_clubs.html', {'clubs_list': clubs_list}) + return render( + request, + 'users/index_clubs.html', + {'clubs_list': clubs_list} + ) @login_required @@ -688,7 +794,7 @@ def mon_profil(request): """ Lien vers profil, renvoie request.id à la fonction """ return redirect(reverse( 'users:profil', - kwargs={'userid':str(request.user.id)} + kwargs={'userid': str(request.user.id)} )) @@ -707,7 +813,9 @@ def profil(request, users, userid): request.GET.get('order'), SortTable.MACHINES_INDEX ) - pagination_large_number = GeneralOption.get_cached_value('pagination_large_number') + pagination_large_number = GeneralOption.get_cached_value( + 'pagination_large_number' + ) machines = re2o_paginator(request, machines, pagination_large_number) factures = Facture.objects.filter(user=users) factures = SortTable.sort( @@ -742,7 +850,7 @@ def profil(request, users, userid): 'ban_list': bans, 'white_list': whitelists, 'user_solde': user_solde, - 'allow_online_payment' : allow_online_payment, + 'allow_online_payment': allow_online_payment, } ) @@ -758,12 +866,20 @@ def reset_password(request): ) except User.DoesNotExist: messages.error(request, "Cet utilisateur n'existe pas") - return form({'userform': userform, 'action_name': 'Réinitialiser'}, 'users/user.html', request) + return form( + {'userform': userform, 'action_name': 'Réinitialiser'}, + 'users/user.html', + request + ) user.reset_passwd_mail(request) messages.success(request, "Un mail pour l'initialisation du mot\ de passe a été envoyé") redirect(reverse('index')) - return form({'userform': userform, 'action_name': 'Réinitialiser'}, 'users/user.html', request) + return form( + {'userform': userform, 'action_name': 'Réinitialiser'}, + 'users/user.html', + request + ) def process(request, token): @@ -790,7 +906,11 @@ def process_passwd(request, req): req.delete() messages.success(request, "Le mot de passe a changé") return redirect(reverse('index')) - return form({'userform': u_form, 'action_name': 'Changer le mot de passe'}, 'users/user.html', request) + return form( + {'userform': u_form, 'action_name': 'Changer le mot de passe'}, + 'users/user.html', + request + ) class JSONResponse(HttpResponse): @@ -862,6 +982,9 @@ def ml_club_members(request, ml_name): except Club.DoesNotExist: messages.error(request, "Cette mailing n'existe pas") return redirect(reverse('index')) - members = club.administrators.all().values('email').distinct() | club.members.all().values('email').distinct() + members = ( + club.administrators.all().values('email').distinct() | + club.members.all().values('email').distinct() + ) seria = MailingMemberSerializer(members, many=True) return JSONResponse(seria.data)