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)
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)
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})
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())