From 2335e9da04a68dfb1f93ffbd84d6ca8a2f6c807d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20P=C3=A9pin?= Date: Sun, 17 May 2020 22:17:33 +0200 Subject: [PATCH] More clever username generation --- authens/backends.py | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/authens/backends.py b/authens/backends.py index ebea500..9e7e2d2 100644 --- a/authens/backends.py +++ b/authens/backends.py @@ -70,21 +70,26 @@ class ENSCASBackend: worry about data races). """ + # Ideally we can have username = cas_login. + if not UserModel.objects.filter(username=cas_login).exists(): + return cas_login + + # Otherwise, add a numerical suffix. + + # If there was a numerical suffix already, remove it: + # https://git.eleves.ens.fr/klub-dev-ens/authens/issues/5 + i = len(cas_login) - 1 + while i >= 0 and cas_login[i] in "0123456789": + i -= 1 + radical = cas_login[:i + 1] + + # Find an integer i such that radical + str(i) is not taken. taken = UserModel.objects.values_list("username", flat=True) - - # This should handle most cases and produce a nice username. - prefered = [cas_login, "cas_" + cas_login] - pref_taken = taken.filter(username__in=prefered) - for name in prefered: - if name not in pref_taken: - return name - - # Worst case: generate a username of the form cas_login + int - taken = taken.filter(username__startswith=cas_login) + taken = taken.filter(username__startswith=radical) i = 2 - while cas_login + str(i) in taken: + while radical + str(i) in taken: i += 1 - return cas_login + str(i) + return radical + str(i) def _get_or_create(self, cas_login, entrance_year): """Handles account retrieval, creation and invalidation as described above.