def auth(): # TODO: Simplify this endpoint. Separate out setting the Authentication mode from all # the other options here: updating admin username/password, adding users, deleting # users, etc. Do those in simple separate screens with their own endpoints. current_version = notify_upgrade(app, flash) auth = app.specter.config["auth"] method = auth["method"] rate_limit = auth["rate_limit"] registration_link_timeout = auth["registration_link_timeout"] users = None if current_user.is_admin and method == "usernamepassword": users = [user for user in app.specter.user_manager.users if not user.is_admin] if request.method == "POST": action = request.form["action"] if action == "save": if "specter_username" in request.form: specter_username = request.form["specter_username"] specter_password = request.form["specter_password"] else: specter_username = None specter_password = None if current_user.is_admin: method = request.form["method"] rate_limit = request.form["rate_limit"] registration_link_timeout = request.form["registration_link_timeout"] min_chars = int(auth["password_min_chars"]) if specter_username: if current_user.username != specter_username: if app.specter.user_manager.get_user_by_username(specter_username): flash( _("Username is already taken, please choose another one"), "error", ) return render_template( "settings/auth_settings.jinja", method=method, rate_limit=rate_limit, registration_link_timeout=registration_link_timeout, users=users, specter=app.specter, current_version=current_version, rand=rand, has_service_encrypted_storage=app.specter.service_manager.user_has_encrypted_storage( current_user ), ) current_user.username = specter_username if specter_password: if len(specter_password) < min_chars: flash( _( "Please enter a password of a least {} characters" ).format(min_chars), "error", ) return render_template( "settings/auth_settings.jinja", method=method, rate_limit=rate_limit, registration_link_timeout=registration_link_timeout, users=users, specter=app.specter, current_version=current_version, rand=rand, has_service_encrypted_storage=app.specter.service_manager.user_has_encrypted_storage( current_user ), ) current_user.set_password(specter_password) current_user.save_info() if current_user.is_admin: app.specter.update_auth(method, rate_limit, registration_link_timeout) if method in ["rpcpasswordaspin", "passwordonly", "usernamepassword"]: if method == "passwordonly": specter_password = request.form.get("specter_password_only") if specter_password and len(specter_password) < min_chars: flash( _( "Please enter a password of a least {} characters" ).format(min_chars), "error", ) return render_template( "settings/auth_settings.jinja", method=method, rate_limit=rate_limit, registration_link_timeout=registration_link_timeout, users=users, specter=app.specter, current_version=current_version, rand=rand, has_service_encrypted_storage=app.specter.service_manager.user_has_encrypted_storage( current_user ), ) elif not specter_password: # Set to the default specter_password = "******" try: current_user.set_password(specter_password) except UserSecretException as e: # Most likely the admin User is logged in but the # plaintext_user_secret is not available in memory (happens # when the server restarts). logger.warn(e) flash( _( "Error re-encrypting Service data. Log out and log back in before trying again." ), "error", ) return render_template( "settings/auth_settings.jinja", method=method, rate_limit=rate_limit, registration_link_timeout=registration_link_timeout, users=users, specter=app.specter, current_version=current_version, rand=rand, has_service_encrypted_storage=app.specter.service_manager.user_has_encrypted_storage( current_user ), ) current_user.save_info() flash( _("Admin password successfully updated"), "info", ) if method == "usernamepassword": users = [ user for user in app.specter.user_manager.users if not user.is_admin ] else: users = None app.config["LOGIN_DISABLED"] = False else: users = None app.config["LOGIN_DISABLED"] = True # Cannot support Services if there's no password (admin was already # warned about this in the UI). Remove User.services, clear the # `user_secret`, and wipe the ServiceEncryptedStorage. app.specter.service_manager.remove_all_services_from_user( current_user ) # Redirect if a URL was given via the next variable if request.form.get("next") and request.form.get("next") != "": return redirect(request.form.get("next")) app.specter.check() elif action == "adduser": if current_user.is_admin: new_otp = secrets.token_urlsafe(16) now = time.time() timeout = int(registration_link_timeout) timeout = 0 if timeout < 0 else timeout if timeout > 0: expiry = now + timeout * 60 * 60 if timeout > 1: expiry_desc = " " + _("(expires in {} hours)").format(timeout) else: expiry_desc = " " + _("(expires in 1 hour)") else: expiry = 0 expiry_desc = "" app.specter.otp_manager.add_new_user_otp( {"otp": new_otp, "created_at": now, "expiry": expiry} ) flash( _("New user link generated{}: {}auth/register?otp={}").format( expiry_desc, request.url_root, new_otp ), "info", ) else: flash( _("Error: Only the admin account can issue new registration links"), "error", ) elif action == "deleteuser": delete_user = request.form["deleteuser"] user = app.specter.user_manager.get_user(delete_user) if current_user.is_admin: # TODO: delete should be done by UserManager app.specter.delete_user(user) users.remove(user) flash( _("User {} was deleted successfully").format(user.username), "info" ) else: flash(_("Error: Only the admin account can delete users"), "error") return render_template( "settings/auth_settings.jinja", method=method, rate_limit=rate_limit, registration_link_timeout=registration_link_timeout, users=users, specter=app.specter, current_version=current_version, rand=rand, has_service_encrypted_storage=app.specter.service_manager.user_has_encrypted_storage( current_user ), next=request.args.get("next", ""), )
def auth(): current_version = notify_upgrade(app, flash) auth = app.specter.config["auth"] method = auth["method"] rate_limit = auth["rate_limit"] registration_link_timeout = auth["registration_link_timeout"] users = None if current_user.is_admin and method == "usernamepassword": users = [ user for user in app.specter.user_manager.users if not user.is_admin ] if request.method == "POST": action = request.form["action"] if action == "save": if "specter_username" in request.form: specter_username = request.form["specter_username"] specter_password = request.form["specter_password"] else: specter_username = None specter_password = None if current_user.is_admin: method = request.form["method"] rate_limit = request.form["rate_limit"] registration_link_timeout = request.form[ "registration_link_timeout"] min_chars = int(auth["password_min_chars"]) if specter_username: if current_user.username != specter_username: if app.specter.user_manager.get_user_by_username( specter_username): flash( "Username is already taken, please choose another one", "error", ) return render_template( "settings/auth_settings.jinja", method=method, rate_limit=rate_limit, registration_link_timeout=registration_link_timeout, users=users, specter=app.specter, current_version=current_version, rand=rand, ) current_user.username = specter_username if specter_password: if len(specter_password) < min_chars: flash( "Please enter a password of a least {} characters." .format(min_chars), "error", ) return render_template( "settings/auth_settings.jinja", method=method, rate_limit=rate_limit, registration_link_timeout=registration_link_timeout, users=users, specter=app.specter, current_version=current_version, rand=rand, ) current_user.password = hash_password(specter_password) current_user.save_info(app.specter) if current_user.is_admin: app.specter.update_auth(method, rate_limit, registration_link_timeout) if method in [ "rpcpasswordaspin", "passwordonly", "usernamepassword" ]: if method == "passwordonly": new_password = request.form.get( "specter_password_only", "") if new_password: if len(new_password) < min_chars: flash( "Please enter a password of a least {} characters." .format(min_chars), "error", ) return render_template( "settings/auth_settings.jinja", method=method, rate_limit=rate_limit, registration_link_timeout= registration_link_timeout, users=users, specter=app.specter, current_version=current_version, rand=rand, ) current_user.password = hash_password(new_password) current_user.save_info(app.specter) if method == "usernamepassword": users = [ user for user in app.specter.user_manager.users if not user.is_admin ] else: users = None app.config["LOGIN_DISABLED"] = False else: users = None app.config["LOGIN_DISABLED"] = True app.specter.check() elif action == "adduser": if current_user.is_admin: new_otp = secrets.token_urlsafe(16) now = time.time() timeout = int(registration_link_timeout) timeout = 0 if timeout < 0 else timeout if timeout > 0: expiry = now + timeout * 60 * 60 if timeout > 1: expiry_desc = " (expires in {} hours)".format(timeout) else: expiry_desc = " (expires in 1 hour)" else: expiry = 0 expiry_desc = "" app.specter.add_new_user_otp({ "otp": new_otp, "created_at": now, "expiry": expiry }) flash( "New user link generated{}: {}auth/register?otp={}".format( expiry_desc, request.url_root, new_otp), "info", ) else: flash( "Error: Only the admin account can issue new registration links.", "error", ) elif action == "deleteuser": delete_user = request.form["deleteuser"] user = app.specter.user_manager.get_user(delete_user) if current_user.is_admin: app.specter.delete_user(user) users.remove(user) flash("User {} was deleted successfully".format(user.username), "info") else: flash("Error: Only the admin account can delete users", "error") return render_template( "settings/auth_settings.jinja", method=method, rate_limit=rate_limit, registration_link_timeout=registration_link_timeout, users=users, specter=app.specter, current_version=current_version, rand=rand, )
def auth(): current_version = notify_upgrade(app, flash) auth = app.specter.config["auth"] new_otp = -1 users = None if current_user.is_admin and auth == "usernamepassword": users = [user for user in app.specter.user_manager.users if not user.is_admin] if request.method == "POST": action = request.form["action"] if action == "save": if "specter_username" in request.form: specter_username = request.form["specter_username"] specter_password = request.form["specter_password"] else: specter_username = None specter_password = None if current_user.is_admin: auth = request.form["auth"] if specter_username: if current_user.username != specter_username: if app.specter.user_manager.get_user_by_username(specter_username): flash( "Username is already taken, please choose another one", "error", ) return render_template( "settings/auth_settings.jinja", auth=auth, new_otp=new_otp, users=users, specter=app.specter, current_version=current_version, rand=rand, ) current_user.username = specter_username if specter_password: current_user.password = hash_password(specter_password) current_user.save_info(app.specter) if current_user.is_admin: app.specter.update_auth(auth) if auth == "rpcpasswordaspin" or auth == "usernamepassword": if auth == "usernamepassword": users = [ user for user in app.specter.user_manager.users if not user.is_admin ] else: users = None app.config["LOGIN_DISABLED"] = False else: users = None app.config["LOGIN_DISABLED"] = True app.specter.check() elif action == "adduser": if current_user.is_admin: new_otp = random.randint(100000, 999999) app.specter.add_new_user_otp( {"otp": new_otp, "created_at": time.time()} ) flash( "New user link generated successfully: {}auth/register?otp={}".format( request.url_root, new_otp ), "info", ) else: flash( "Error: Only the admin account can issue new registration links.", "error", ) elif action == "deleteuser": delete_user = request.form["deleteuser"] user = app.specter.user_manager.get_user(delete_user) if current_user.is_admin: app.specter.delete_user(user) users.remove(user) flash("User {} was deleted successfully".format(user.username), "info") else: flash("Error: Only the admin account can delete users", "error") return render_template( "settings/auth_settings.jinja", auth=auth, new_otp=new_otp, users=users, specter=app.specter, current_version=current_version, rand=rand, )
def auth_settings(): current_version = notify_upgrade() app.specter.check() auth = app.specter.config['auth'] new_otp = -1 users = None if current_user.is_admin and auth == "usernamepassword": users = [user for user in User.get_all_users(app.specter) if not user.is_admin] if request.method == 'POST': action = request.form['action'] if action == "save": if 'specter_username' in request.form: specter_username = request.form['specter_username'] specter_password = request.form['specter_password'] else: specter_username = None specter_password = None if current_user.is_admin: auth = request.form['auth'] if specter_username: if current_user.username != specter_username: if User.get_user_by_name(app.specter, specter_username): flash('Username is already taken, please choose another one', "error") return render_template( "settings/auth_settings.jinja", auth=auth, new_otp=new_otp, users=users, specter=app.specter, current_version=current_version, rand=rand ) current_user.username = specter_username if specter_password: current_user.password = hash_password(specter_password) current_user.save_info(app.specter) if current_user.is_admin: app.specter.update_auth(auth) if auth == "rpcpasswordaspin" or auth == "usernamepassword": app.config['LOGIN_DISABLED'] = False else: app.config['LOGIN_DISABLED'] = True app.specter.check() elif action == "adduser": if current_user.is_admin: new_otp = random.randint(100000, 999999) app.specter.add_new_user_otp({ 'otp': new_otp, 'created_at': time.time() }) flash('New user link generated successfully: {}register?otp={}'.format(request.url_root, new_otp), 'info') else: flash('Error: Only the admin account can issue new registration links.', 'error') elif action == "deleteuser": delete_user = request.form['deleteuser'] if current_user.is_admin: user = User.get_user(app.specter, delete_user) if user: user.delete(app.specter) users = [user for user in User.get_all_users(app.specter) if not user.is_admin] flash('User {} was deleted successfully'.format(user.username), 'info') else: flash('Error: failed to delete user, invalid user ID was given', 'error') else: flash('Error: Only the admin account can delete users', 'error') return render_template( "settings/auth_settings.jinja", auth=auth, new_otp=new_otp, users=users, specter=app.specter, current_version=current_version, rand=rand )