Browse Source

Improve get_automatic_username to add increment at username end if it already exists in database

Fabs 10 years ago
parent
commit
68ada60e07
2 changed files with 63 additions and 25 deletions
  1. 40 25
      coin/members/models.py
  2. 23 0
      coin/members/tests.py

+ 40 - 25
coin/members/models.py

@@ -131,30 +131,6 @@ class Member(CoinLdapSyncMixin, AbstractUser):
             Q(subscription_date__gt=date) |
             Q(resign_date__lt=date))
 
-    def get_automatic_username(self):
-        """
-        Calcul le username / ldap cn automatiquement en fonction
-        du nom et du prénom
-        """
-
-        # Première lettre de chaque partie du prénom
-        first_name_letters = ''.join(
-            [c[0] for c in self.first_name.split('-')]
-        )
-        # Concaténer avec nom de famille
-        username = ('%s%s' % (first_name_letters, self.last_name))
-        # Remplacer ou enlever les caractères non ascii
-        username = unicodedata.normalize('NFD', username)\
-            .encode('ascii', 'ignore')
-        # Enlever ponctuation et espace
-        punctuation = (string.punctuation + ' ').encode('ascii')
-        username = username.translate(None, punctuation)
-        # En minuscule
-        username = username.lower()
-        # Maximum de 30 char
-        username = username[:30]
-
-        return username
 
     def sync_to_ldap(self, creation, update_fields, *args, **kwargs):
         """
@@ -247,6 +223,44 @@ Member._meta.get_field('last_name').null = False
 def count_active_members():
     return Member.objects.filter(status='member').count()
 
+def get_automatic_username(first_name, last_name):
+    """
+    Calcul le username automatiquement en fonction
+    du nom et du prénom
+    """
+
+    # Première lettre de chaque partie du prénom
+    first_name_letters = ''.join(
+        [c[0] for c in first_name.split('-')]
+    )
+    # Concaténer avec nom de famille
+    username = ('%s%s' % (first_name_letters, last_name))
+    # Remplacer ou enlever les caractères non ascii
+    username = unicodedata.normalize('NFD', username)\
+        .encode('ascii', 'ignore')
+    # Enlever ponctuation et espace
+    punctuation = (string.punctuation + ' ').encode('ascii')
+    username = username.translate(None, punctuation)
+    # En minuscule
+    username = username.lower()
+    # Maximum de 30 char
+    username = username[:30]
+
+    # Recherche dans les membres existants un username identique
+    member = Member.objects.filter(username=username)
+    base_username = username
+    incr = 2
+    # Tant qu'un membre est trouvé, incrément un entier à la fin
+    while member:
+        if len(base_username) >= 30:
+            username = base_username[30-len(str(incr)):]
+        else:
+            username = base_username
+        username = username + str(incr)
+        member = Member.objects.filter(username=username)
+        incr += 1
+
+    return username
 
 class CryptoKey(models.Model):
 
@@ -357,7 +371,8 @@ def define_username(sender, instance, **kwargs):
     le calcul automatiquement en fonction du nom et du prénom
     """
     if not instance.username and not instance.pk:
-        instance.username = instance.get_automatic_username()
+        instance.username = get_automatic_username(instance.first_name, 
+                                                   instance.last_name)
 
 
 @receiver(pre_save, sender=LdapUser)

+ 23 - 0
coin/members/tests.py

@@ -179,6 +179,29 @@ class MemberTests(TestCase):
 
         member.delete()
 
+    def test_when_creating_member_with_username_already_exists_username_is_incr(self):
+        """
+        Lors de la création d'un membre, test si le username existe déjà,
+        renvoi avec un incrément à la fin
+        """
+        random = os.urandom(4).encode('hex')
+
+        member1 = Member(first_name='Hervé', last_name='DUPOND' + random, email='hdupond@coin.org')
+        member1.save()
+        self.assertEqual(member1.username, 'hdupond' + random)
+        
+        member2 = Member(first_name='Henri', last_name='DUPOND' + random, email='hdupond2@coin.org')
+        member2.save()
+        self.assertEqual(member2.username, 'hdupond' + random + '2')
+        
+        member3 = Member(first_name='Hector', last_name='DUPOND' + random, email='hdupond3@coin.org')
+        member3.save()
+        self.assertEqual(member3.username, 'hdupond' + random + '3')
+
+        member1.delete()
+        member2.delete()
+        member3.delete()
+
     def test_when_saving_member_and_ldap_fail_dont_save(self):
         """
         Test que lors de la sauvegarde d'un membre et que la sauvegarde en LDAP