diff --git a/dynamicweb/settings/base.py b/dynamicweb/settings/base.py index c959c237..ca8996d1 100644 --- a/dynamicweb/settings/base.py +++ b/dynamicweb/settings/base.py @@ -42,7 +42,7 @@ def int_env(val, default_value=0): "details: {}").format( val, str(e))) - return return_value + return return_value if return_value is not None else default_value BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) @@ -761,6 +761,7 @@ OTP_VERIFY_ENDPOINT = env('OTP_VERIFY_ENDPOINT') FIRST_VM_ID_AFTER_EU_VAT = int_env('FIRST_VM_ID_AFTER_EU_VAT') PRE_EU_VAT_RATE = float(env('PRE_EU_VAT_RATE')) +MAX_USERNAME_LENGTH = int_env('MAX_USERNAME_LENGTH', 64) if DEBUG: from .local import * # flake8: noqa diff --git a/membership/migrations/0012_auto_20200306_1016.py b/membership/migrations/0012_auto_20200306_1016.py new file mode 100644 index 00000000..f38f0780 --- /dev/null +++ b/membership/migrations/0012_auto_20200306_1016.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.4 on 2020-03-06 10:16 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('membership', '0011_auto_20191218_1050'), + ] + + operations = [ + migrations.AlterField( + model_name='customuser', + name='username', + field=models.CharField(max_length=120, null=True, unique=True), + ), + ] diff --git a/membership/models.py b/membership/models.py index 703b4800..b572833d 100644 --- a/membership/models.py +++ b/membership/models.py @@ -77,28 +77,59 @@ def get_first_and_last_name(full_name): return first_name, last_name +def limit_username_length(username): + """ + Limit the length of username before the addition of random numbers to + 18 characters + + :param username: the username to limit + :return: + """ + if len(username) > settings.MAX_USERNAME_LENGTH: + username = username[(len(username) - settings.MAX_USERNAME_LENGTH):] + return username.strip() + + def assign_username(user): if not user.username: ldap_manager = LdapManager() # Try to come up with a username first_name, last_name = get_first_and_last_name(user.name) - user.username = unicodedata.normalize('NFKD', first_name + last_name) + user.username = unicodedata.normalize( + 'NFKD', first_name + last_name + ).encode('ascii', 'ignore').decode('ascii', 'ignore') user.username = "".join([char for char in user.username if char.isalnum()]).lower() + if user.username.strip() == "": + try: + # the inferred username from name is empty, hence attempt + # inferring a username from email + logger.debug("Inferred username from name is empty. So, " + "inferring from email now.") + user.username = user.email[0:user.email.index("@")] + user.username = "".join( + [char for char in user.username if char.isalnum()] + ).lower() + except Exception as ex: + logger.debug("Exception %s" % str(ex)) + user.username = get_random_string( + allowed_chars='abcdefghijklmnopqrstuvwxyz' + ) exist = True + user_username = limit_username_length(user.username) while exist: # Check if it exists - exist, entries = ldap_manager.check_user_exists(user.username) + exist, entries = ldap_manager.check_user_exists(user_username) if exist: # If username exists in ldap, come up with a new user name and check it again - user.username = user.username + str(random.randint(0, 2 ** 10)) + user.username = user_username + str(random.randint(0, 2 ** 10)) else: # If username does not exists in ldap, try to save it in database try: user.save() except IntegrityError: # If username exists in database then come up with a new username - user.username = user.username + str(random.randint(0, 2 ** 10)) + user.username = user_username + str(random.randint(0, 2 ** 10)) exist = True @@ -116,7 +147,7 @@ class CustomUser(AbstractBaseUser, PermissionsMixin): site = models.ForeignKey(Site, default=1) name = models.CharField(max_length=50, validators=[validate_name]) email = models.EmailField(unique=True) - username = models.CharField(max_length=60, unique=True, null=True) + username = models.CharField(max_length=120, unique=True, null=True) validated = models.IntegerField(choices=VALIDATED_CHOICES, default=0) in_ldap = models.BooleanField(default=False) # By default, we initialize the validation_slug with appropriate value