Example #1
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)
Example #2
0
def test_can_create_user(open_creation, invite_only, email, has_invite, can_create, blacklisting_enabled, app):

  # Mock list of blacklisted domains
  blacklisted_domains = ['blacklisted.com', 'blacklisted.org']

  if has_invite:
    inviter = model.user.get_user('devtable')
    team = model.team.get_organization_team('buynlarge', 'owners')
    model.team.add_or_invite_to_team(inviter, team, email=email)

  with patch('features.USER_CREATION', open_creation):
    with patch('features.INVITE_ONLY_USER_CREATION', invite_only):
      with patch('features.BLACKLISTED_EMAILS', blacklisting_enabled):
        if email and any(domain in email.lower() for domain in blacklisted_domains) and not blacklisting_enabled:
            can_create = True  # blacklisted domains can be used, if blacklisting is disabled
        assert can_create_user(email, blacklisted_domains) == can_create
Example #3
0
def test_can_create_user(open_creation, invite_only, email, has_invite,
                         can_create, blacklisting_enabled, app):

    # Mock list of blacklisted domains
    blacklisted_domains = ["blacklisted.com", "blacklisted.org"]

    if has_invite:
        inviter = model.user.get_user("devtable")
        team = model.team.get_organization_team("buynlarge", "owners")
        model.team.add_or_invite_to_team(inviter, team, email=email)

    with patch("features.USER_CREATION", open_creation):
        with patch("features.INVITE_ONLY_USER_CREATION", invite_only):
            with patch("features.BLACKLISTED_EMAILS", blacklisting_enabled):
                if (email and any(domain in email.lower()
                                  for domain in blacklisted_domains)
                        and not blacklisting_enabled):
                    can_create = (
                        True  # blacklisted domains can be used, if blacklisting is disabled
                    )
                assert can_create_user(email,
                                       blacklisted_domains) == can_create
Example #4
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))
Example #5
0
    def post(self):
        """
        Create a new user.
        """
        if app.config["AUTHENTICATION_TYPE"] != "Database":
            abort(404)

        user_data = request.get_json()

        invite_code = user_data.get("invite_code", "")
        existing_user = model.user.get_nonrobot_user(user_data["username"])
        if existing_user:
            raise request_error(message="The username already exists")

        # Ensure an e-mail address was specified if required.
        if features.MAILING and not user_data.get("email"):
            raise request_error(message="Email address is required")

        # If invite-only user creation is turned on and no invite code was sent, return an error.
        # Technically, this is handled by the can_create_user call below as well, but it makes
        # a nicer error.
        if features.INVITE_ONLY_USER_CREATION and not invite_code:
            raise request_error(message="Cannot create non-invited user")

        # Ensure that this user can be created.
        blacklisted_domains = app.config.get("BLACKLISTED_EMAIL_DOMAINS", [])
        if not can_create_user(user_data.get("email"), blacklisted_domains=blacklisted_domains):
            raise request_error(
                message="Creation of a user account for this e-mail is disabled; please contact an administrator"
            )

        # If recaptcha is enabled, then verify the user is a human.
        if features.RECAPTCHA:
            recaptcha_response = user_data.get("recaptcha_response", "")
            result = recaptcha2.verify(
                app.config["RECAPTCHA_SECRET_KEY"], recaptcha_response, get_request_ip()
            )

            if not result["success"]:
                return {"message": "Are you a bot? If not, please revalidate the captcha."}, 400

        is_possible_abuser = ip_resolver.is_ip_possible_threat(get_request_ip())
        try:
            prompts = model.user.get_default_user_prompts(features)
            new_user = model.user.create_user(
                user_data["username"],
                user_data["password"],
                user_data.get("email"),
                auto_verify=not features.MAILING,
                email_required=features.MAILING,
                is_possible_abuser=is_possible_abuser,
                prompts=prompts,
            )

            email_address_confirmed = handle_invite_code(invite_code, new_user)
            if features.MAILING and not email_address_confirmed:
                confirmation_code = model.user.create_confirm_email_code(new_user)
                send_confirmation_email(new_user.username, new_user.email, confirmation_code)
                return {"awaiting_verification": True}
            else:
                success, headers = common_login(new_user.uuid)
                if not success:
                    return {"message": "Could not login. Is your account inactive?"}, 403

                return user_view(new_user), 200, headers
        except model.user.DataModelException as ex:
            raise request_error(exception=ex)