Browse Source

Add function to auto compute ldap_cn (ldap primary key) when creating a new member

Fabs 11 years ago
parent
commit
9580cbd3c2
2 changed files with 88 additions and 4 deletions
  1. 46 4
      coin/members/models.py
  2. 42 0
      coin/members/tests.py

+ 46 - 4
coin/members/models.py

@@ -4,6 +4,8 @@ import pprint
 import os
 import base64
 import hashlib
+import unicodedata
+import string
 from django.db import models
 from ldapdb.models.fields import CharField, IntegerField, ListField
 from django.db.models.signals import post_save, pre_save, post_delete
@@ -95,13 +97,15 @@ class MembershipFee(models.Model):
         help_text='fin de validité de cotisation')
 
     def __unicode__(self):
-        return (u'%s - %s - %i€' % (self.member, self.start_date, self.amount))
+        return (u'%s - %s - %i€' % (self.member, self.start_date,
+                                     self.amount))
 
 
 class LdapUser(ldapdb.models.Model):
     # TODO: déplacer ligne suivante dans settings.py
     base_dn = "ou=users,ou=unix,o=ILLYSE,l=Villeurbanne,st=RHA,c=FR"
-    object_classes = ['inetOrgPerson', 'organizationalPerson', 'person', 'top', 'posixAccount']
+    object_classes = ['inetOrgPerson', 'organizationalPerson', 'person', 
+                      'top', 'posixAccount']
 
     uid = CharField(db_column='uid', unique=True, max_length=255)
     nick_name = CharField(db_column='cn', unique=True, primary_key=True,
@@ -113,7 +117,8 @@ class LdapUser(ldapdb.models.Model):
     password = CharField(db_column='userPassword', max_length=255)
     uidNumber = IntegerField(db_column='uidNumber', unique=True)
     gidNumber = IntegerField(db_column='gidNumber', default=2000)
-    homeDirectory = CharField(db_column='homeDirectory', max_length=255 , default='/tmp')
+    homeDirectory = CharField(db_column='homeDirectory', max_length=255,
+                              default='/tmp')
 
     def __unicode__(self):
         return self.display_name
@@ -159,6 +164,41 @@ def change_password(sender, instance, **kwargs):
         instance.password = '{SSHA}' + base64.b64encode(digest + salt)
 
 
+@receiver(pre_save, sender=LdapUser)
+def define_display_name(sender, instance, **kwargs):
+    """
+    Lors de la sauvegarde d'un utilisateur Ldap, le champ display_name est la
+    concaténation de first_name et last_name
+    """
+    if not instance.display_name:
+        instance.display_name = '%s %s' % (instance.first_name,
+                                           instance.last_name)
+
+
+@receiver(pre_save, sender=Member)
+def define_ldap_cn(sender, instance, **kwargs):
+    """
+    Lors de la sauvegarde d'un membre. Si le champ ldap_cn n'est pas définit, 
+    le calcul automatiquement en fonction du nom et du prénom
+    """
+    if not instance.ldap_cn:
+        # Première lettre de chaque partie du prénom
+        first_name_letters = ''.join(
+            [c[0] for c in instance.first_name.split('-')]
+        ) 
+        # Concaténer avec nom de famille
+        ldap_cn = ('%s%s' % (first_name_letters, instance.last_name))
+        # Remplacer ou enlever les caractères non ascii
+        ldap_cn = unicodedata.normalize('NFD', ldap_cn)\
+            .encode('ascii', 'ignore')
+        # Enlever ponctuation et espace
+        ldap_cn = ldap_cn.translate(None, string.punctuation + ' ')
+        # En minuscule
+        ldap_cn = ldap_cn.lower()        
+        
+        instance.ldap_cn = ldap_cn
+
+
 @receiver(post_save, sender=Member)
 def sync_ldap(sender, instance, created, **kwargs):
     """
@@ -187,7 +227,9 @@ def sync_ldap(sender, instance, created, **kwargs):
 
 
 @receiver(post_delete, sender=Member)
-def remove_ldap_user_from_coin_group_when_deleting_member(sender, instance, **kwargs):
+def remove_ldap_user_from_coin_group_when_deleting_member(sender, 
+                                                                 instance,
+                                                                 **kwargs):
     """
     Lorsqu'un membre est supprimé du SI, son utilisateur LDAP correspondant est
     sorti du groupe "coin"

+ 42 - 0
coin/members/tests.py

@@ -114,6 +114,48 @@ class MemberTests(TestCase):
         member.delete();
         ldap_user.delete();
 
+
+    def test_when_creating_member_ldap_display_name_is_well_defined(self):
+        """
+        Lors de la création d'un membre, le champ "display_name" du LDAP est 
+        prenom + nom
+        """
+        first_name = u'Gérard'
+        last_name = u'Majax'
+        ldap_cn = self.get_random_ldap_cn()
+        member = Member(first_name = first_name, last_name = last_name, ldap_cn = ldap_cn)
+        member.save()
+        
+        #~ Récupère l'utilisateur LDAP
+        ldap_user = LdapUser.objects.get(pk=ldap_cn)
+        
+        self.assertEqual(ldap_user.display_name, '%s %s' % (first_name, last_name))
+        
+        member.delete();
+        ldap_user.delete();
+
+
+    def test_when_creating_member_ldap_cn_is_well_defined(self):
+        """
+        Lors de la création d'un membre, le champ "ldap_cn", s'il n'est pas 
+        définit doit être généré avec les contraintes suivantes :
+        premières lettres du prénom + nom le tout en minuscule, 
+        sans caractères accentués et sans espaces.
+        """
+        random = os.urandom(4).encode('hex')
+        first_name = u'Gérard-Étienne'
+        last_name = u'Majax de la Boétie-Blop' + random
+               
+        control = 'gemajaxdelaboetieblop'
+        
+        member = Member(first_name = first_name, last_name = last_name)
+        member.save()
+
+        self.assertEqual(member.ldap_cn, control + random)
+        
+        member.delete();
+        LdapUser.objects.get(pk=member.ldap_cn).delete();
+
     def get_random_ldap_cn(self):
         """
         Renvoi une clé aléatoire pour un utilisateur LDAP