from django.db import models from django.db.models import Q from django.forms import ModelForm, Form from django import forms from re2o.settings import RIGHTS_LINK, REQ_EXPIRE_HRS import re, uuid import datetime from django.utils import timezone from django.contrib.auth.models import AbstractBaseUser, BaseUserManager from topologie.models import Room from cotisations.models import Cotisation, Facture, Vente 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""" UNIX_LOGIN_PATTERN = re.compile("^[a-z_][a-z0-9_-]*[$]?$") return UNIX_LOGIN_PATTERN.match(login) def linux_user_validator(login): if not linux_user_check(login): raise forms.ValidationError( ", ce pseudo ('%(label)s') contient des carractères interdits", params={'label': login}, ) def get_admin_right(): try: admin_right = ListRight.objects.get(listright="admin") except ListRight.DoesNotExist: admin_right = ListRight(listright="admin") admin_right.save() return admin_right class UserManager(BaseUserManager): def _create_user(self, pseudo, name, surname, email, password=None, su=False): if not pseudo: raise ValueError('Users must have an username') if not linux_user_check(pseudo): raise ValueError('Username shall only contain [a-z0-9_-]') user = self.model( pseudo=pseudo, name=name, surname=surname, email=self.normalize_email(email), ) user.set_password(password) user.save(using=self._db) if su: user.make_admin() return user def create_user(self, pseudo, name, surname, email, password=None): """ Creates and saves a User with the given pseudo, name, surname, email, and password. """ return self._create_user(pseudo, name, surname, email, password, False) def create_superuser(self, pseudo, name, surname, email, password): """ Creates and saves a superuser with the given pseudo, name, surname, email, and password. """ return self._create_user(pseudo, name, surname, email, password, True) class User(AbstractBaseUser): STATE_ACTIVE = 0 STATE_DEACTIVATED = 1 STATE_ARCHIVED = 2 STATES = ( (0, 'STATE_ACTIVE'), (1, 'STATE_DEACTIVATED'), (2, 'STATE_ARCHIVED'), ) name = models.CharField(max_length=255) surname = models.CharField(max_length=255) 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) 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) state = models.IntegerField(choices=STATES, default=STATE_ACTIVE) registered = models.DateTimeField(auto_now_add=True) USERNAME_FIELD = 'pseudo' REQUIRED_FIELDS = ['name', 'surname', 'email'] objects = UserManager() @property def is_active(self): return self.state == self.STATE_ACTIVE @property def is_staff(self): return self.is_admin @property def is_admin(self): try: Right.objects.get(user=self, right__listright='admin') except Right.DoesNotExist: return False return True @is_admin.setter def is_admin(self, value): if value and not self.is_admin: self.make_admin() elif not value and self.is_admin: self.un_admin() def get_full_name(self): return '%s %s' % (self.name, self.surname) def get_short_name(self): return self.name def has_perms(self, perms, obj=None): for perm in perms: if perm in RIGHTS_LINK: query = Q() for right in RIGHTS_LINK[perm]: query = query | Q(right__listright=right) if Right.objects.filter(Q(user=self) & query): return True try: Right.objects.get(user=self, right__listright=perm) except Right.DoesNotExist: return False return True def has_perm(self, perm, obj=None): return True def end_adhesion(self): date_max = Cotisation.objects.all().filter(vente=Vente.objects.all().filter(facture=Facture.objects.all().filter(user=self).exclude(valid=False))).aggregate(models.Max('date_end'))['date_end__max'] return date_max def is_adherent(self): end = self.end_adhesion() if not end: return False elif end < timezone.now(): return False else: return True def end_ban(self): """ Renvoie la date de fin de ban d'un user, False sinon """ date_max = Ban.objects.all().filter(user=self).aggregate(models.Max('date_end'))['date_end__max'] return date_max def end_whitelist(self): """ Renvoie la date de fin de ban d'un user, False sinon """ date_max = Whitelist.objects.all().filter(user=self).aggregate(models.Max('date_end'))['date_end__max'] return date_max def is_ban(self): """ Renvoie si un user est banni ou non """ end = self.end_ban() if not end: return False elif end < timezone.now(): return False else: return True def is_whitelisted(self): """ Renvoie si un user est whitelisté ou non """ end = self.end_whitelist() if not end: return False elif end < timezone.now(): return False else: return True 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_adherent() or self.is_whitelisted()) def has_module_perms(self, app_label): # Simplest version again return True def make_admin(self): """ Make User admin """ user_admin_right = Right(user=self, right=get_admin_right()) user_admin_right.save() def un_admin(self): try: user_right = Right.objects.get(user=self,right=get_admin_right()) except Right.DoesNotExist: return user_right.delete() def __str__(self): return self.pseudo class Right(models.Model): user = models.ForeignKey('User', on_delete=models.PROTECT) right = models.ForeignKey('ListRight', on_delete=models.PROTECT) class Meta: unique_together = ("user", "right") def __str__(self): return str(self.user) + " - " + str(self.right) class School(models.Model): name = models.CharField(max_length=255) def __str__(self): return self.name class ListRight(models.Model): listright = models.CharField(max_length=255, unique=True) def __str__(self): return self.listright class Ban(models.Model): user = models.ForeignKey('User', on_delete=models.PROTECT) raison = models.CharField(max_length=255) date_start = models.DateTimeField(auto_now_add=True) date_end = models.DateTimeField(help_text='%d/%m/%y %H:%M:%S') def __str__(self): return str(self.user) + ' ' + str(self.raison) class Whitelist(models.Model): user = models.ForeignKey('User', on_delete=models.PROTECT) raison = models.CharField(max_length=255) date_start = models.DateTimeField(auto_now_add=True) date_end = models.DateTimeField(help_text='%d/%m/%y %H:%M:%S') def __str__(self): return str(self.user) + ' ' + str(self.raison) class Request(models.Model): PASSWD = 'PW' EMAIL = 'EM' TYPE_CHOICES = ( (PASSWD, 'Mot de passe'), (EMAIL, 'Email'), ) type = models.CharField(max_length=2, choices=TYPE_CHOICES) token = models.CharField(max_length=32) user = models.ForeignKey('User', on_delete=models.PROTECT) created_at = models.DateTimeField(auto_now_add=True, editable=False) expires_at = models.DateTimeField() def save(self): if not self.expires_at: self.expires_at = timezone.now() \ + datetime.timedelta(hours=REQ_EXPIRE_HRS) if not self.token: self.token = str(uuid.uuid4()).replace('-', '') # remove hyphens super(Request, self).save() class BaseInfoForm(ModelForm): def __init__(self, *args, **kwargs): super(BaseInfoForm, self).__init__(*args, **kwargs) self.fields['name'].label = 'Nom' self.fields['surname'].label = 'Pré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 = [ 'name', 'surname', 'pseudo', 'email', 'school', 'comment', 'room', ] class InfoForm(BaseInfoForm): force = forms.BooleanField(label="Forcer le déménagement ?", initial=False, required=False) def clean_force(self): if self.cleaned_data.get('force', False): remove_user_room(self.cleaned_data.get('room')) return class UserForm(InfoForm): class Meta(InfoForm.Meta): fields = '__all__' class PasswordForm(ModelForm): class Meta: model = User fields = ['password', 'pwd_ntlm'] class StateForm(ModelForm): class Meta: model = User fields = ['state'] class SchoolForm(ModelForm): class Meta: model = School fields = ['name'] def __init__(self, *args, **kwargs): super(SchoolForm, self).__init__(*args, **kwargs) self.fields['name'].label = 'Établissement' class DelSchoolForm(ModelForm): schools = forms.ModelMultipleChoiceField(queryset=School.objects.all(), label="Etablissements actuels", widget=forms.CheckboxSelectMultiple) class Meta: exclude = ['name'] model = School class RightForm(ModelForm): def __init__(self, *args, **kwargs): super(RightForm, self).__init__(*args, **kwargs) self.fields['right'].label = 'Droit' self.fields['right'].empty_label = "Choisir un nouveau droit" class Meta: model = Right fields = ['right'] class DelRightForm(ModelForm): rights = forms.ModelMultipleChoiceField(queryset=Right.objects.all(), label="Droits actuels", widget=forms.CheckboxSelectMultiple) class Meta: model = Right exclude = ['user', 'right'] class BanForm(ModelForm): def __init__(self, *args, **kwargs): super(BanForm, self).__init__(*args, **kwargs) self.fields['date_end'].label = 'Date de fin' class Meta: model = Ban exclude = ['user'] def clean_date_end(self): date_end = self.cleaned_data['date_end'] if date_end < timezone.now(): raise forms.ValidationError("Triple buse, la date de fin ne peut pas être avant maintenant... Re2o ne voyage pas dans le temps") return date_end class WhitelistForm(ModelForm): def __init__(self, *args, **kwargs): super(WhitelistForm, self).__init__(*args, **kwargs) self.fields['date_end'].label = 'Date de fin' class Meta: model = Whitelist exclude = ['user'] def clean_date_end(self): date_end = self.cleaned_data['date_end'] if date_end < timezone.now(): raise forms.ValidationError("Triple buse, la date de fin ne peut pas être avant maintenant... Re2o ne voyage pas dans le temps") return date_end class ProfilForm(Form): user = forms.CharField(label='Ok', max_length=100)