Exemple #1
0
def test_multiple_suggestions():
    name_gen = generate_valid_usernames('a')
    generated_output = list(islice(name_gen, 4))
    assert generated_output[0] == 'a0'
    assert generated_output[1] == 'a1'
    assert generated_output[2] == 'a2'
    assert generated_output[3] == 'a3'
Exemple #2
0
def test_multiple_suggestions():
    name_gen = generate_valid_usernames("a")
    generated_output = list(islice(name_gen, 4))
    assert generated_output[0] == "a0"
    assert generated_output[1] == "a1"
    assert generated_output[2] == "a2"
    assert generated_output[3] == "a3"
Exemple #3
0
    def _get_and_link_federated_user_info(self,
                                          username,
                                          email,
                                          internal_create=False):
        db_user = model.user.verify_federated_login(self._federated_service,
                                                    username)
        if not db_user:

            # Fetch list of blacklisted domains
            blacklisted_domains = model.config.app_config.get(
                "BLACKLISTED_EMAIL_DOMAINS")

            # We must create the user in our db. Check to see if this is allowed (except for internal
            # creation, which is always allowed).
            if not internal_create and not can_create_user(
                    email, blacklisted_domains):
                return (None, DISABLED_MESSAGE)

            valid_username = None
            for valid_username in generate_valid_usernames(username):
                if model.user.is_username_unique(valid_username):
                    break

            if not valid_username:
                logger.error("Unable to pick a username for user: %s",
                             username)
                return (
                    None,
                    "Unable to pick a username. Please report this to your administrator.",
                )

            prompts = model.user.get_default_user_prompts(features)
            try:
                db_user = model.user.create_federated_user(
                    valid_username,
                    email,
                    self._federated_service,
                    username,
                    set_password_notification=False,
                    email_required=self._requires_email,
                    confirm_username=features.USERNAME_CONFIRMATION,
                    prompts=prompts,
                )
            except model.InvalidEmailAddressException as iae:
                return (None, str(iae))

        else:
            # Update the db attributes from the federated service.
            if email and db_user.email != email:
                db_user.email = email
                db_user.save()

        return (db_user, None)
Exemple #4
0
def test_generate_valid_usernames(input_username, expected_output):
    name_gen = generate_valid_usernames(input_username)
    generated_output = list(islice(name_gen, 1))[0]
    assert generated_output == expected_output
Exemple #5
0
def _conduct_oauth_login(auth_system,
                         login_service,
                         lid,
                         lusername,
                         lemail,
                         metadata=None,
                         captcha_verified=False):
    """
    Conducts login from the result of an OAuth service's login flow and returns the status of the
    login, as well as the followup step.
    """
    service_id = login_service.service_id()
    service_name = login_service.service_name()

    # Check for an existing account *bound to this service*. If found, conduct login of that account
    # and redirect.
    user_obj = model.user.verify_federated_login(service_id, lid)
    if user_obj is not None:
        return _oauthresult(user_obj=user_obj, service_name=service_name)

    # If the login service has a bound field name, and we have a defined internal auth type that is
    # not the database, then search for an existing account with that matching field. This allows
    # users to setup SSO while also being backed by something like LDAP.
    bound_field_name = login_service.login_binding_field()
    if auth_system.federated_service is not None and bound_field_name is not None:
        # Perform lookup.
        logger.debug('Got oauth bind field name of "%s"', bound_field_name)
        lookup_value = None
        if bound_field_name == "sub":
            lookup_value = lid
        elif bound_field_name == "username":
            lookup_value = lusername
        elif bound_field_name == "email":
            lookup_value = lemail

        if lookup_value is None:
            logger.error("Missing lookup value for OAuth login")
            return _oauthresult(
                service_name=service_name,
                error_message="Configuration error in this provider")

        (user_obj, err) = auth_system.link_user(lookup_value)
        if err is not None:
            logger.debug("%s %s not found: %s", bound_field_name, lookup_value,
                         err)
            msg = "%s %s not found in backing auth system" % (bound_field_name,
                                                              lookup_value)
            return _oauthresult(service_name=service_name, error_message=msg)

        # Found an existing user. Bind their internal auth account to this service as well.
        result = _attach_service(login_service, user_obj, lid, lusername)
        if result.error_message is not None:
            return result

        return _oauthresult(user_obj=user_obj, service_name=service_name)

    # Otherwise, we need to create a new user account.
    blacklisted_domains = app.config.get("BLACKLISTED_EMAIL_DOMAINS", [])
    if not can_create_user(lemail, blacklisted_domains=blacklisted_domains):
        error_message = "User creation is disabled. Please contact your administrator"
        return _oauthresult(service_name=service_name,
                            error_message=error_message)

    if features.RECAPTCHA and not captcha_verified:
        return _oauthresult(service_name=service_name,
                            requires_verification=True)

    # Try to create the user
    try:
        # Generate a valid username.
        new_username = None
        for valid in generate_valid_usernames(lusername):
            if model.user.get_user_or_org(valid):
                continue

            new_username = valid
            break

        requires_password = auth_system.requires_distinct_cli_password
        prompts = model.user.get_default_user_prompts(features)
        user_obj = model.user.create_federated_user(
            new_username,
            lemail,
            service_id,
            lid,
            set_password_notification=requires_password,
            metadata=metadata or {},
            confirm_username=features.USERNAME_CONFIRMATION,
            prompts=prompts,
            email_required=features.MAILING,
        )

        # Success, tell analytics
        analytics.track(user_obj.username, "register",
                        {"service": service_name.lower()})
        return _oauthresult(user_obj=user_obj, service_name=service_name)

    except model.InvalidEmailAddressException:
        message = ("The e-mail address {0} is already associated "
                   "with an existing {1} account. \n"
                   "Please log in with your username and password and "
                   "associate your {2} account to use it in the future.")
        message = message.format(lemail, app.config["REGISTRY_TITLE_SHORT"],
                                 service_name)
        return _oauthresult(service_name=service_name,
                            error_message=message,
                            register_redirect=True)

    except model.DataModelException as ex:
        return _oauthresult(service_name=service_name, error_message=str(ex))