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", ""),
    )
Example #2
0
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,
    )
Example #3
0
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,
    )
Example #4
0
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
    )