def generate_username_suggestions(name): """ Generate 3 available username suggestions """ username_suggestions = [] max_length = USERNAME_MAX_LENGTH names = name.split(' ') if names: first_name = remove_special_characters_from_name(names[0].lower()) last_name = remove_special_characters_from_name(names[-1].lower()) if first_name != last_name and first_name: # username combination of first and last name suggestion = f'{first_name}{last_name}'[:max_length] if not username_exists_or_retired(suggestion): username_suggestions.append(suggestion) # username is combination of first letter of first name and last name suggestion = f'{first_name[0]}-{last_name}'[:max_length] if not username_exists_or_retired(suggestion): username_suggestions.append(suggestion) if len(first_name) >= 2: short_username = first_name[:max_length - 6] if max_length is not None else first_name short_username = short_username.replace('_', '').replace('-', '') int_ranges = [ { 'min': 0, 'max': 9 }, { 'min': 10, 'max': 99 }, { 'min': 100, 'max': 999 }, { 'min': 1000, 'max': 99999 }, ] for int_range in int_ranges: for _ in range(10): random_int = random.randint(int_range['min'], int_range['max']) suggestion = f'{short_username}_{random_int}' if not username_exists_or_retired(suggestion): username_suggestions.append(suggestion) break if len(username_suggestions) == 3: break return username_suggestions
def _handle_duplicate_email_username(self, request, data): # pylint: disable=no-member # TODO Verify whether this check is needed here - it may be duplicated in user_api. email = data.get('email') username = data.get('username') errors = {} # TODO: remove the is_authn_mfe check and use the new error message as default after redesign is_authn_mfe = data.get('is_authn_mfe', False) error_code = 'duplicate' if email is not None and email_exists_or_retired(email): error_code += '-email' error_message = accounts_settings.AUTHN_EMAIL_CONFLICT_MSG if is_authn_mfe else ( accounts_settings.EMAIL_CONFLICT_MSG.format(email_address=email) ) errors['email'] = [{'user_message': error_message}] if username is not None and username_exists_or_retired(username): error_code += '-username' error_message = accounts_settings.AUTHN_USERNAME_CONFLICT_MSG if is_authn_mfe else ( accounts_settings.USERNAME_CONFLICT_MSG.format(username=username) ) errors['username'] = [{'user_message': error_message}] errors['username_suggestions'] = generate_username_suggestions(username) if errors: return self._create_response(request, errors, status_code=409, error_code=error_code)
def generate_username_suggestions(username): """ Generate 3 available username suggestions """ max_length = USERNAME_MAX_LENGTH short_username = username[:max_length - 4] if max_length is not None else username username_suggestions = [] int_ranges = { 1: { 'min': 0, 'max': 9 }, 2: { 'min': 10, 'max': 99 }, 3: { 'min': 100, 'max': 999 }, } while len(username_suggestions) < 3: int_length = len(username_suggestions) + 1 int_range = int_ranges[int_length] random_int = random.randint(int_range['min'], int_range['max']) username = f'{short_username}_{random_int}' if not username_exists_or_retired(username): username_suggestions.append(username) return username_suggestions
def _handle_duplicate_email_username(self, request, data): # pylint: disable=no-member # TODO Verify whether this check is needed here - it may be duplicated in user_api. email = data.get('email') username = data.get('username') errors = {} error_code = 'duplicate' if email is not None and email_exists_or_retired(email): error_code += '-email' errors["email"] = [{ "user_message": accounts_settings.EMAIL_CONFLICT_MSG.format( email_address=email) }] if username is not None and username_exists_or_retired(username): error_code += '-username' errors["username"] = [{ "user_message": accounts_settings.USERNAME_CONFLICT_MSG.format( username=username) }] if errors: return self._create_response(request, errors, status_code=409, error_code=error_code)
def generate_username_suggestions(username): """ Generate 3 available username suggestions """ max_length = USERNAME_MAX_LENGTH short_username = username[:max_length - 6] if max_length is not None else username short_username = short_username.replace('_', '').replace('-', '') username_suggestions = [] int_ranges = [ {'min': 0, 'max': 9}, {'min': 10, 'max': 99}, {'min': 100, 'max': 999}, {'min': 1000, 'max': 99999}, ] for int_range in int_ranges: for _ in range(10): random_int = random.randint(int_range['min'], int_range['max']) suggestion = f'{short_username}_{random_int}' if not username_exists_or_retired(suggestion): username_suggestions.append(suggestion) break if len(username_suggestions) == 3: break return username_suggestions
def _validate_username_doesnt_exist(username): """Validate that the username is not associated with an existing user. :param username: The proposed username (unicode). :return: None :raises: errors.AccountUsernameAlreadyExists """ if username is not None and username_exists_or_retired(username): raise errors.AccountUsernameAlreadyExists(_(accounts.USERNAME_CONFLICT_MSG).format(username=username))
def check_edxapp_account_conflicts(email, username): """ Exposed function to check conflicts """ conflicts = [] if username and username_exists_or_retired(username): conflicts.append("username") if email and email_exists_or_retired(email): conflicts.append("email") return conflicts
def generate_username_suggestions(username): """ Generate available username suggestions """ min_length = accounts.USERNAME_MIN_LENGTH max_length = accounts.USERNAME_MAX_LENGTH short_username = username[:max_length - min_length] if max_length is not None else username username_suggestions = [] while len(username_suggestions) < 3: username = f'{short_username}_{uuid4().hex[:min_length]}' if not username_exists_or_retired(username): username_suggestions.append(username) return username_suggestions
def _validate_username_doesnt_exist(username, api_version='v1'): """Validate that the username is not associated with an existing user. :param username: The proposed username (unicode). :param api_version: Validation API version; it is used to determine the error message :return: None :raises: errors.AccountUsernameAlreadyExists """ if api_version == 'v1': error_message = accounts.USERNAME_CONFLICT_MSG.format(username=username) else: error_message = accounts.AUTHN_USERNAME_CONFLICT_MSG if username is not None and username_exists_or_retired(username): raise errors.AccountUsernameAlreadyExists(_(error_message)) # lint-amnesty, pylint: disable=translation-of-non-string
def do_create_account(form, custom_form=None): """ Given cleaned post variables, create the User and UserProfile objects, as well as the registration for this user. Returns a tuple (User, UserProfile, Registration). Note: this function is also used for creating test users. """ # Check if ALLOW_PUBLIC_ACCOUNT_CREATION flag turned off to restrict user account creation if not configuration_helpers.get_value( 'ALLOW_PUBLIC_ACCOUNT_CREATION', settings.FEATURES.get('ALLOW_PUBLIC_ACCOUNT_CREATION', True)): raise PermissionDenied() errors = {} errors.update(form.errors) if custom_form: errors.update(custom_form.errors) if errors: raise ValidationError(errors) proposed_username = form.cleaned_data["username"] user = User(username=proposed_username, email=form.cleaned_data["email"], is_active=False) password = normalize_password(form.cleaned_data["password"]) user.set_password(password) registration = Registration() # TODO: Rearrange so that if part of the process fails, the whole process fails. # Right now, we can have e.g. no registration e-mail sent out and a zombie account try: with transaction.atomic(): user.save() if custom_form: custom_model = custom_form.save(commit=False) custom_model.user = user custom_model.save() except IntegrityError: # Figure out the cause of the integrity error # TODO duplicate email is already handled by form.errors above as a ValidationError. # The checks for duplicate email/username should occur in the same place with an # AccountValidationError and a consistent user message returned (i.e. both should # return "It looks like {username} belongs to an existing account. Try again with a # different username.") if username_exists_or_retired(user.username): raise AccountValidationError( USERNAME_EXISTS_MSG_FMT.format(username=proposed_username), field="username") elif email_exists_or_retired(user.email): raise AccountValidationError(_( "An account with the Email '{email}' already exists.").format( email=user.email), field="email") else: raise registration.register(user) profile_fields = [ "name", "level_of_education", "gender", "mailing_address", "city", "country", "goals", "year_of_birth" ] profile = UserProfile( user=user, **{key: form.cleaned_data.get(key) for key in profile_fields}) extended_profile = form.cleaned_extended_profile if extended_profile: profile.meta = json.dumps(extended_profile) try: profile.save() except Exception: log.exception( "UserProfile creation failed for user {id}.".format(id=user.id)) raise return user, profile, registration