示例#1
0
def signup_validate(**_):
    """
    Validate a user's signup request

    Variables:
    None

    Arguments:
    None

    Data Block:
    {
     "registration_key": "234234...ADFCB"    # Key used to validate the user's signup process
    }

    Result example:
    {
     "success": true
    }
    """
    if not config.auth.internal.signup.enabled:
        return make_api_response({"success": False},
                                 "Signup process has been disabled", 403)

    try:
        data = request.json
    except BadRequest:
        data = request.values

    registration_key = data.get('registration_key', None)

    if registration_key:
        try:
            signup_queue = get_signup_queue(registration_key)
            members = signup_queue.members()
            signup_queue.delete()
            if members:
                user_info = members[0]

                # Add dynamic classification group
                user_info['classification'] = get_dynamic_classification(
                    user_info.get('classification',
                                  Classification.UNRESTRICTED),
                    user_info['email'])

                user = User(user_info)
                username = user.uname

                STORAGE.user.save(username, user)
                return make_api_response({"success": True})
        except (KeyError, ValueError) as e:
            LOGGER.warning(f"Fail to signup user: {str(e)}")
            pass
    else:
        return make_api_response(
            {"success": False},
            "Not enough information to proceed with user creation", 400)

    return make_api_response({"success": False}, "Invalid registration key",
                             400)
示例#2
0
def signup_validate(**_):
    """
    Validate a user's signup request

    Variables:
    None

    Arguments:
    None

    Data Block:
    {
     "registration_key": "234234...ADFCB"    # Key used to validate the user's signup process
    }

    Result example:
    {
     "success": true
    }
    """
    if not config.auth.internal.signup.enabled:
        return make_api_response({"success": False},
                                 "Signup process has been disabled", 403)

    data = request.json
    if not data:
        data = request.values

    registration_key = data.get('registration_key', None)

    if registration_key:
        try:
            signup_queue = get_signup_queue(registration_key)
            members = signup_queue.members()
            signup_queue.delete()
            if members:
                user_info = members[0]
                user = User(user_info)
                username = user.uname

                STORAGE.user.save(username, user)
                return make_api_response({"success": True})
        except (KeyError, ValueError):
            pass
    else:
        return make_api_response(
            {"success": False},
            "Not enough information to proceed with user creation", 400)

    return make_api_response({"success": False}, "Invalid registration key",
                             400)
示例#3
0
def signup(**_):
    """
    Signup a new user into the system

    Variables:
    None

    Arguments:
    None

    Data Block:
    {
     "user": <UID>,
     "password": <DESIRED_PASSWORD>,
     "password_confirm": <DESIRED_PASSWORD_CONFIRMATION>,
     "email": <EMAIL_ADDRESS>
    }

    Result example:
    {
     "success": true
    }
    """
    if not config.auth.internal.signup.enabled:
        return make_api_response({"success": False},
                                 "Signup process has been disabled", 403)

    data = request.json
    if not data:
        data = request.values

    uname = data.get('user', None)
    password = data.get('password', None)
    password_confirm = data.get('password_confirm', None)
    email = data.get('email', None)

    if not uname or not password or not password_confirm or not email:
        return make_api_response(
            {"success": False},
            "Not enough information to proceed with user creation", 400)

    if STORAGE.user.get(uname) or len(uname) < 3:
        return make_api_response(
            {"success": False},
            "There is already a user registered with this name", 460)
    else:
        for c in uname:
            if not 97 <= ord(c) <= 122 and not ord(c) == 45:
                return make_api_response(
                    {"success": False},
                    "Invalid username. [Lowercase letters and dashes "
                    "only with at least 3 letters]", 460)

    if password_confirm != password:
        return make_api_response("", "Passwords do not match", 469)

    password_requirements = config.auth.internal.password_requirements.as_primitives(
    )
    if not check_password_requirements(password, **password_requirements):
        error_msg = get_password_requirement_message(**password_requirements)
        return make_api_response({"success": False}, error_msg, 469)

    if STORAGE.user.search(f"email:{email.lower()}").get('total', 0) != 0:
        return make_api_response(
            {"success": False},
            "There is already a user registered with this email address", 466)

    # Normalize email address
    email = email.lower()
    email_valid = False
    for r in config.auth.internal.signup.valid_email_patterns:
        matcher = re.compile(r)
        if matcher.findall(email):
            email_valid = True
            break

    if not email_valid:
        extra = ""
        if config.ui.email:
            extra = f". Contact {config.ui.email} for more information."
        return make_api_response({"success": False},
                                 f"Invalid email address{extra}", 466)

    password = get_password_hash(password)
    key = hashlib.sha256(
        get_random_password(length=512).encode('utf-8')).hexdigest()
    try:
        send_signup_email(email, key)
        get_signup_queue(key).add({
            "uname": uname,
            "password": password,
            "email": email,
            "groups": ['USERS'],
            "name": uname
        })
    except Exception:
        return make_api_response(
            {"success": False},
            "The system failed to send signup confirmation link.", 400)

    return make_api_response({"success": True})
示例#4
0
def login():
    ui4_path = request.cookies.get('ui4_path', None)
    if ui4_path is not None:
        resp = redirect(
            redirect_helper(f"{ui4_path}?{request.query_string.decode()}"))
        resp.delete_cookie("ui4_path")
        return resp

    registration_key = request.args.get('registration_key', None)

    avatar = None
    oauth_token = ''
    oauth_error = ''
    username = ''
    oauth_validation = config.auth.oauth.enabled and 'code' in request.args and 'state' in request.args
    oauth_provider = request.args.get('provider', None)
    up_login = config.auth.internal.enabled or config.auth.ldap.enabled

    next_url = angular_safe(
        request.args.get('next', request.cookies.get('next_url', "/")))
    if "login.html" in next_url or "logout.html" in next_url:
        next_url = "/"

    if registration_key and config.auth.internal.signup.enabled:
        try:
            signup_queue = get_signup_queue(registration_key)
            members = signup_queue.members()
            signup_queue.delete()
            if members:
                user_info = members[0]
                user = User(user_info)
                username = user.uname

                STORAGE.user.save(username, user)
        except (KeyError, ValueError):
            pass

    if config.auth.oauth.enabled:
        providers = str([
            name for name, p in config.auth.oauth.providers.items()
            if p['client_id'] and p['client_secret']
        ])

        if oauth_validation:
            oauth = current_app.extensions.get(
                'authlib.integrations.flask_client')
            provider = oauth.create_client(oauth_provider)

            if provider:
                # noinspection PyBroadException
                try:
                    # Test oauth access token
                    token = provider.authorize_access_token()
                    oauth_provider_config = config.auth.oauth.providers[
                        oauth_provider]

                    # Get user data
                    resp = provider.get(oauth_provider_config.user_get)
                    if resp.ok:
                        user_data = resp.json()

                        # Add group data if API is configured for it
                        if oauth_provider_config.user_groups:
                            resp_grp = provider.get(
                                oauth_provider_config.user_groups)
                            if resp_grp.ok:
                                groups = resp_grp.json()

                                if oauth_provider_config.user_groups_data_field:
                                    groups = groups[oauth_provider_config.
                                                    user_groups_data_field]

                                if oauth_provider_config.user_groups_name_field:
                                    groups = [
                                        x[oauth_provider_config.
                                          user_groups_name_field]
                                        for x in groups
                                    ]

                                user_data['groups'] = groups

                        data = parse_profile(user_data, oauth_provider_config)
                        has_access = data.pop('access', False)
                        if has_access:
                            oauth_avatar = data.pop('avatar', None)

                            # Find if user already exists
                            users = STORAGE.user.search(
                                f"email:{data['email']}",
                                fl="uname",
                                as_obj=False)['items']
                            if users:
                                cur_user = STORAGE.user.get(
                                    users[0]['uname'], as_obj=False) or {}
                                # Do not update username and password from the current user
                                data['uname'] = cur_user.get(
                                    'uname', data['uname'])
                                data['password'] = cur_user.get(
                                    'password', data['password'])
                            else:
                                if data['uname'] != data['email']:
                                    # Username was computed using a regular expression, lets make sure we don't
                                    # assign the same username to two users
                                    res = STORAGE.user.search(
                                        f"uname:{data['uname']}",
                                        rows=0,
                                        as_obj=False)
                                    if res['total'] > 0:
                                        cnt = res['total']
                                        new_uname = f"{data['uname']}{cnt}"
                                        while STORAGE.user.get(
                                                new_uname) is not None:
                                            cnt += 1
                                            new_uname = f"{data['uname']}{cnt}"
                                        data['uname'] = new_uname
                                cur_user = {}

                            username = data['uname']

                            # Make sure the user exists in AL and is in sync
                            if (not cur_user and oauth_provider_config.auto_create) or \
                                    (cur_user and oauth_provider_config.auto_sync):

                                # Update the current user
                                cur_user.update(data)

                                # Save avatar
                                if oauth_avatar:
                                    avatar = fetch_avatar(
                                        oauth_avatar, provider,
                                        oauth_provider_config)
                                    if avatar:
                                        STORAGE.user_avatar.save(
                                            username, avatar)

                                # Save updated user
                                STORAGE.user.save(username, cur_user)

                            if cur_user:
                                if avatar is None:
                                    avatar = STORAGE.user_avatar.get(
                                        username
                                    ) or "/static/images/user_default.png"
                                oauth_token = hashlib.sha256(
                                    str(token).encode(
                                        "utf-8",
                                        errors='replace')).hexdigest()
                                get_token_store(username).add(oauth_token)
                            else:
                                oauth_validation = False
                                avatar = None
                                username = ''
                                oauth_error = "User auto-creation is disabled"
                        else:
                            oauth_validation = False
                            oauth_error = "This user is not allowed access to the system"

                except Exception as _:
                    oauth_validation = False
                    oauth_error = "Invalid oAuth2 token, try again"
    else:
        providers = str([])

    return custom_render("login.html",
                         next=next_url,
                         avatar=avatar,
                         username=username,
                         oauth_error=oauth_error,
                         oauth_token=oauth_token,
                         providers=providers,
                         signup=config.auth.internal.enabled
                         and config.auth.internal.signup.enabled,
                         oauth_validation=str(oauth_validation).lower(),
                         up_login=str(up_login).lower())