def set_user_account(username, **kwargs): """ Save the user account information. Variables: username => Name of the user to get the account info Arguments: None Data Block: { "name": "Test user", # Name of the user "is_active": true, # Is the user active? "classification": "", # Max classification for user "uname": "usertest", # Username "type": ['user'], # List of all types the user is member of "avatar": null, # Avatar of the user "groups": ["TEST"] # Groups the user is member of } Result example: { "success": true # Saving the user info succeded } """ try: data = request.json new_pass = data.pop('new_pass', None) old_user = STORAGE.user.get(username, as_obj=False) if not old_user: return make_api_response({"success": False}, "User %s does not exists" % username, 404) if not data['name']: return make_api_response({"success": False}, "Full name of the user cannot be empty", 400) data['apikeys'] = old_user.get('apikeys', []) data['otp_sk'] = old_user.get('otp_sk', None) data['security_tokens'] = old_user.get('security_tokens', {}) or {} if new_pass: password_requirements = config.auth.internal.password_requirements.as_primitives() if not check_password_requirements(new_pass, **password_requirements): error_msg = get_password_requirement_message(**password_requirements) return make_api_response({"success": False}, error_msg, 469) data['password'] = get_password_hash(new_pass) data.pop('new_pass_confirm', None) else: data['password'] = old_user.get('password', "__NO_PASSWORD__") or "__NO_PASSWORD__" # Apply dynamic classification data['classification'] = get_dynamic_classification(data['classification'], data['email']) ret_val = save_user_account(username, data, kwargs['user']) if ret_val and \ not old_user['is_active'] \ and data['is_active'] \ and config.ui.tos_lockout \ and config.ui.tos_lockout_notify: try: email = data['email'] or "" for adr in config.ui.tos_lockout_notify: send_activated_email(adr, username, email, kwargs['user']['uname']) if email: send_activated_email(email, username, email, kwargs['user']['uname']) except Exception as e: # We can't send confirmation email, Rollback user change and mark this a failure STORAGE.user.save(username, old_user) LOGGER.error(f"An error occured while sending confirmation emails: {str(e)}") return make_api_response({"success": False}, "The system was unable to send confirmation emails. " "Retry again later...", 404) return make_api_response({"success": ret_val}) except AccessDeniedException as e: return make_api_response({"success": False}, str(e), 403) except InvalidDataException as e: return make_api_response({"success": False}, str(e), 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 add_user_account(username, **_): """ Add a user to the system Variables: username => Name of the user to add Arguments: None Data Block: { "name": "Test user", # Name of the user "is_active": true, # Is the user active? "classification": "", # Max classification for user "uname": "usertest", # Username "type": ['user'], # List of all types the user is member of "avatar": null, # Avatar of the user "groups": ["TEST"] # Groups the user is member of } Result example: { "success": true # Saving the user info succeded } """ data = request.json if "{" in username or "}" in username: return make_api_response({"success": False}, "You can't use '{}' in the username", 412) if not STORAGE.user.get(username): new_pass = data.pop('new_pass', None) if new_pass: password_requirements = config.auth.internal.password_requirements.as_primitives() if not check_password_requirements(new_pass, **password_requirements): error_msg = get_password_requirement_message(**password_requirements) return make_api_response({"success": False}, error_msg, 469) data['password'] = get_password_hash(new_pass) else: data['password'] = data.get('password', "__NO_PASSWORD__") or "__NO_PASSWORD__" # Data's username as to match the API call username data['uname'] = username if not data['name']: data['name'] = data['uname'] # Add add dynamic classification group data['classification'] = get_dynamic_classification(data['classification'], data['email']) # Clear non user account data avatar = data.pop('avatar', None) if avatar is not None: STORAGE.user_avatar.save(username, avatar) try: return make_api_response({"success": STORAGE.user.save(username, User(data))}) except ValueError as e: return make_api_response({"success": False}, str(e), 400) else: return make_api_response({"success": False}, "The username you are trying to add already exists.", 400)
def reset_pwd(**_): """ Reset the password for the specified reset ID Variables: None Arguments: None Data Block: { "reset_id": <RESET_HASH>, "password": <PASSWORD TO RESET TO>, "password_confirm": <CONFIRMATION OF PASSWORD TO RESET TO> } 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 reset_id = data.get('reset_id', None) password = data.get('password', None) password_confirm = data.get('password_confirm', None) if reset_id and password and password_confirm: if password != password_confirm: return make_api_response({"success": False}, err="Password mismatch", status_code=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) try: reset_queue = get_reset_queue(reset_id) members = reset_queue.members() reset_queue.delete() if members: email = members[0] res = STORAGE.user.search(f"email:{email}") if res.get('total', 0) == 1: user = STORAGE.user.get(res['items'][0].uname) user.password = get_password_hash(password) STORAGE.user.save(user.uname, user) return make_api_response({"success": True}) except Exception: pass return make_api_response({"success": False}, err="Invalid parameters passed", status_code=400)