def user_pre_save(sender, **kwargs): """ Procédure de détection des modifications, lancée avant modification d'un abonné. On compare les données avec l'utilisateur actuel, et on conserve dans un attribut log_post_save toutes les modifications constatées. Ces modifications seront logées lors du post_save, donc quand le save() aura vraiment fonctionné. """ user = kwargs['instance'] # on ne comptabilise que les comptes locaux if user.source != 'LOCAL': return # agent = la personne qui a fait la modification. Si la modification a été # faite par le formulaire web, on aura un attribut 'user.agent', sinon on # prend la valeur '<api>' try: agent = user.agent.username except: agent = '<api>' # on cherche les données actuelles de l'utilisateur try: current = User.objects.get(username=user.username, creation=user.creation) except User.DoesNotExist: # Si l'utilisateur n'existe pas encore, comme on est dans le pre_save # c'est qu'il s'agit d'une création : le log se fera load du post_save, # car c'est lors du post_save qu'on aura la donnée user.creation return # on stocke chaque modification détectée dans un dictionnaire log_post_save # que l'on ajoute comme attribut à user user.log_post_save = {} if password_crypt(user.password) != current.password: user.log_post_save['password'] = '' if user.expire != current.expire: user.log_post_save['expire'] = json.dumps( { 'expire_old': current.expire, 'expire_new': user.expire }, default=json_serial) if user.gecos != current.gecos: user.log_post_save['gecos'] = json.dumps( { 'gecos_old': current.gecos, 'gecos_new': user.gecos }, default=json_serial)
def save(self, force_insert=False, force_update=False): """ Enregistre ou modifie un groupe dans la table ``groups``. Si aucun gid n'est proposé, la methode Group.save() en calcule un avant de procéder à l'enregistrement réel du groupe dans la base. """ # si l'objet n'a pas de GID proposé, on en calcule un, # en sachant qu'il doit être plus grande que MIN_GID if self.gid == None: try: self.gid = max(Group.objects.latest().gid + 1, MIN_GID) except: self.gid = MIN_GID # on crypte le mot de passe (si besoin) self.password = password_crypt(self.password) # et on enregistre l'objet "pour de vrai" return super(Group, self).save(force_insert, force_update)
def save(self, force_insert=False, force_update=False): """ Enregistre ou modifie un groupe dans la table ``groups``. Si aucun gid n'est proposé, la methode Group.save() en calcule un avant de procéder à l'enregistrement réel du groupe dans la base. """ # si l'objet n'a pas de GID proposé, on en calcule un, # en sachant qu'il doit être plus grande que MIN_GID if self.gid == None: try: self.gid = max(Group.objects.latest().gid + 1, MIN_GID) except: self.gid = MIN_GID # on crypte le mot de passe (si besoin) self.password = password_crypt( self.password ) # et on enregistre l'objet "pour de vrai" return super(Group, self).save(force_insert, force_update)
def user_pre_save(sender, **kwargs): """ Procédure de détection des modifications, lancée avant modification d'un abonné. On compare les données avec l'utilisateur actuel, et on conserve dans un attribut log_post_save toutes les modifications constatées. Ces modifications seront logées lors du post_save, donc quand le save() aura vraiment fonctionné. """ user = kwargs['instance'] # on ne comptabilise que les comptes locaux if user.source != 'LOCAL': return # agent = la personne qui a fait la modification. Si la modification a été # faite par le formulaire web, on aura un attribut 'user.agent', sinon on # prend la valeur '<api>' try: agent = user.agent.username except: agent = '<api>' # on cherche les données actuelles de l'utilisateur try: current = User.objects.get(username=user.username, creation=user.creation) except User.DoesNotExist: # Si l'utilisateur n'existe pas encore, comme on est dans le pre_save # c'est qu'il s'agit d'une création : le log se fera load du post_save, # car c'est lors du post_save qu'on aura la donnée user.creation return # on stocke chaque modification détectée dans un dictionnaire log_post_save # que l'on ajoute comme attribut à user user.log_post_save={} if password_crypt( user.password ) != current.password: user.log_post_save['password'] = '' if user.expire != current.expire: user.log_post_save['expire'] = json.dumps({ 'expire_old': current.expire, 'expire_new': user.expire }, default=json_serial) if user.gecos != current.gecos: user.log_post_save['gecos'] = json.dumps({ 'gecos_old': current.gecos, 'gecos_new': user.gecos}, default=json_serial)
def save(self, force_insert=False, force_update=False, force_source=False): """ Enregistre ou modifie un utilisateur dans la table ``users``. La methode User.save() effectue quelques vérifications et modification avant de procéder à l'enregistrement réel de l'utilisateur dans la base de données : * si l'utilisateur (indiqué par son username) existe déjà, les champs ``uid`` et ``source`` ne sont pas modifiables (exception levée) * si ``source`` n'est pas 'LOCAL', alors l'enregistrement n'est pas effectué, sauf si on précise *force_source=True* lors de l'appel à *save()* * si aucun ``uid`` n'est imposé, alors on en calcule un nouveau, qui doit être supérieur à ``conf.MIN_UID`` (configurable dans le fichier ``conf.py``) * si le ``homedir`` n'est pas précisé, on le calcule à travers une fonction ``homedir(self)``, qui peut être personnalisée dans le fichier ``conf.py`` * si le mot de passe est livré en clair, on le crypte Ce n'est qu'après toutes ces opérations que l'enregistrement est effectué. """ # surcharges avant enregistrement : # on interdit les changements sur "uid" ou "source" avec ça : try: # si l'objet existe déjà, on récupère ses données actuelles current = User.objects.get(pk=self.pk) except: # si l'utilisateur n'existe pas encore : vérification du format du username username_ok = 'abcdefghijklmnopqrstuvwxyz0123456789-._' for c in self.username: if c not in username_ok: raise ValueError( "username ne doit contenir que des minuscules ASCII, des chiffres, - _ ou ." ) else: # on refuse de modifier l'uid ou la source, il y a trop # d'implications par ailleurs if self.source != current.source: raise ValueError('changement de source interdit') if self.uid != current.uid: raise ValueError("changement d'uid interdit") # on n'enregistre que si la source est 'LOCAL' (pour forcer # l'enregistrement, il faut ajouter un force_source=True lors de # l'appel) if self.source != "LOCAL" and not force_source: raise ValueError( "source != LOCAL nécessite save(force_source=True)") # on vérifie le format de GECOS (ascii) gecos_ok = ' abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._' for c in self.gecos: if c not in gecos_ok: raise ValueError( "GECOS ne doit contenir que des lettres ASCII, des chiffres, - _ ou ." ) # si l'objet n'a pas d'UID proposé, on en calcule un, # en sachant qu'il doit être plus grand que MIN_UID if self.uid == None: try: self.uid = max(User.objects.latest().uid + 1, MIN_UID) except: self.uid = MIN_UID # si le homedir n'a pas été précisé, on le calcule if self.homedir == HOME_BASE: self.homedir = homedir(self) # on crypte le mot de passe (si besoin) self.password = password_crypt(self.password) # et on lance l'enregistrement via la méthode mère return super(User, self).save(force_insert, force_update)
def save(self, force_insert=False, force_update=False, force_source=False): """ Enregistre ou modifie un utilisateur dans la table ``users``. La methode User.save() effectue quelques vérifications et modification avant de procéder à l'enregistrement réel de l'utilisateur dans la base de données : * si l'utilisateur (indiqué par son username) existe déjà, les champs ``uid`` et ``source`` ne sont pas modifiables (exception levée) * si ``source`` n'est pas 'LOCAL', alors l'enregistrement n'est pas effectué, sauf si on précise *force_source=True* lors de l'appel à *save()* * si aucun ``uid`` n'est imposé, alors on en calcule un nouveau, qui doit être supérieur à ``conf.MIN_UID`` (configurable dans le fichier ``conf.py``) * si le ``homedir`` n'est pas précisé, on le calcule à travers une fonction ``homedir(self)``, qui peut être personnalisée dans le fichier ``conf.py`` * si le mot de passe est livré en clair, on le crypte Ce n'est qu'après toutes ces opérations que l'enregistrement est effectué. """ # surcharges avant enregistrement : # on interdit les changements sur "uid" ou "source" avec ça : try: # si l'objet existe déjà, on récupère ses données actuelles current = User.objects.get(pk=self.pk) except: # si l'utilisateur n'existe pas encore : vérification du format du username username_ok = 'abcdefghijklmnopqrstuvwxyz0123456789-._' for c in self.username: if c not in username_ok: raise ValueError("username ne doit contenir que des minuscules ASCII, des chiffres, - _ ou .") else: # on refuse de modifier l'uid ou la source, il y a trop # d'implications par ailleurs if self.source != current.source: raise ValueError('changement de source interdit') if self.uid != current.uid: raise ValueError("changement d'uid interdit") # on n'enregistre que si la source est 'LOCAL' (pour forcer # l'enregistrement, il faut ajouter un force_source=True lors de # l'appel) if self.source != "LOCAL" and not force_source: raise ValueError("source != LOCAL nécessite save(force_source=True)") # on vérifie le format de GECOS (ascii) gecos_ok = ' abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._' for c in self.gecos: if c not in gecos_ok: raise ValueError("GECOS ne doit contenir que des lettres ASCII, des chiffres, - _ ou .") # si l'objet n'a pas d'UID proposé, on en calcule un, # en sachant qu'il doit être plus grand que MIN_UID if self.uid == None: try: self.uid = max(User.objects.latest().uid + 1, MIN_UID) except: self.uid = MIN_UID # si le homedir n'a pas été précisé, on le calcule if self.homedir == HOME_BASE: self.homedir = homedir(self) # on crypte le mot de passe (si besoin) self.password = password_crypt( self.password ) # et on lance l'enregistrement via la méthode mère return super(User, self).save(force_insert, force_update)