def disable(username): "Disable the given user account." user = get_user(username=username) if user is None: return utils.error("No such user.") if user["username"].lower() == flask.g.current_user["username"].lower(): return utils.error("You cannot disable yourself.") with UserSaver(user) as saver: saver.set_status(constants.DISABLED) utils.get_logger().info(f"disabled user {username}") return flask.redirect(flask.url_for(".display", username=username))
def do_login(username, password): """Set the session cookie if successful login. Raise ValueError if some problem. """ user = get_user(username=username) if user is None: raise ValueError if not check_password_hash(user["password"], password): raise ValueError if user["status"] != constants.ENABLED: raise ValueError flask.session["username"] = user["username"] flask.session.permanent = True utils.get_logger().info(f"logged in {user['username']}")
def enable(username): "Enable the given user account." user = get_user(username=username) if user is None: return utils.error("No such user.") if user["username"].lower() == flask.g.current_user["username"].lower(): return utils.error("You cannot enable yourself.") with UserSaver(user) as saver: saver.set_status(constants.ENABLED) if user["password"][:5] == "code:" and \ flask.current_app.config["MAIL_SERVER"]: send_password_code(user, "enabled") utils.get_logger().info(f"enabled user {username}") return flask.redirect(flask.url_for(".display", username=username))
def password(): "Set the password for a user account, and login user." if utils.http_GET(): return flask.render_template( "user/password.html", username=flask.request.args.get("username"), code=flask.request.args.get("code")) elif utils.http_POST(): try: code = "" try: username = flask.request.form.get("username") or "" if not username: raise ValueError user = get_user(username=username) if user is None: raise ValueError if am_admin_and_not_self(user): pass # No check for either code or current password. elif flask.current_app.config["MAIL_SERVER"]: code = flask.request.form.get("code") or "" if user["password"] != f"code:{code}": raise ValueError else: password = flask.request.form.get("current_password") or "" if not check_password_hash(user["password"], password): raise ValueError except ValueError: if flask.current_app.config["MAIL_SERVER"]: raise ValueError("No such user or wrong code.") else: raise ValueError("No such user or wrong password.") password = flask.request.form.get("password") or "" if len(password) < flask.current_app.config["MIN_PASSWORD_LENGTH"]: raise ValueError("Too short password.") if not flask.current_app.config["MAIL_SERVER"]: if password != flask.request.form.get("confirm_password"): raise ValueError("Wrong password entered; confirm failed.") except ValueError as error: return utils.error(error, flask.url_for(".password", username=username, code=code)) with UserSaver(user) as saver: saver.set_password(password) utils.get_logger().info(f"password user {user['username']}") if not flask.g.current_user: do_login(username, password) return flask.redirect(flask.url_for("home"))
def edit(username): "Edit the user display. Or delete the user." user = get_user(username=username) if user is None: return utils.error("No such user.") if not am_admin_or_self(user): return utils.error("Access not allowed.") if utils.http_GET(): deletable = am_admin_and_not_self(user) and is_empty(user) return flask.render_template("user/edit.html", user=user, change_role=am_admin_and_not_self(user), deletable=deletable) elif utils.http_POST(): with UserSaver(user) as saver: if flask.g.am_admin: email = flask.request.form.get("email") if email != user["email"]: saver.set_email(email) if am_admin_and_not_self(user): saver.set_role(flask.request.form.get("role")) if flask.request.form.get("apikey"): saver.set_apikey() return flask.redirect( flask.url_for(".display", username=user["username"])) elif utils.http_DELETE(): if not is_empty(user): return utils.error("Cannot delete non-empty user account.") with flask.g.db: flask.g.db.execute("DELETE FROM logs WHERE docid=?",(user["iuid"],)) flask.g.db.execute("DELETE FROM users " " WHERE username=? COLLATE NOCASE", (username,)) utils.flash_message(f"Deleted user {username}.") utils.get_logger().info(f"deleted user {username}") if flask.g.am_admin: return flask.redirect(flask.url_for(".all")) else: return flask.redirect(flask.url_for("home"))
def reset(): "Reset the password for a user account and send email." if not flask.current_app.config["MAIL_SERVER"]: return utils.error("Cannot reset password; no email server defined.") if utils.http_GET(): email = flask.request.args.get("email") or "" email = email.lower() return flask.render_template("user/reset.html", email=email) elif utils.http_POST(): try: user = get_user(email=flask.request.form["email"]) if user is None: raise KeyError if user["status"] != constants.ENABLED: raise KeyError except KeyError: pass else: with UserSaver(user) as saver: saver.set_password() send_password_code(user, "password reset") utils.get_logger().info(f"reset user {user['username']}") utils.flash_message("An email has been sent if the user account exists.") return flask.redirect(flask.url_for("home"))
def register(): "Register a new user account." if utils.http_GET(): return flask.render_template("user/register.html") elif utils.http_POST(): try: with UserSaver() as saver: saver.set_username(flask.request.form.get("username")) saver.set_email(flask.request.form.get("email")) saver.set_role(constants.USER) if flask.g.am_admin: password = flask.request.form.get("password") or None if password: confirm = flask.request.form.get("confirm_password") if password != confirm: raise ValueError("Password differs from" " confirmed password.") saver.set_password(password) saver.set_status(constants.ENABLED) elif not flask.current_app.config["MAIL_SERVER"]: password = flask.request.form.get("password") or None if password: confirm = flask.request.form.get("confirm_password") if password != confirm: raise ValueError("Password an confirmed password" " not the same.") saver.set_password(password) else: saver.set_password() user = saver.doc except ValueError as error: return utils.error(error) utils.get_logger().info(f"registered user {user['username']}") # Directly enabled. if user["status"] == constants.ENABLED: if user["password"][:5] == "code:": utils.get_logger().info(f"enabled user {user['username']}") # Send code by email to user. if flask.current_app.config["MAIL_SERVER"]: send_password_code(user, "registration") utils.flash_message("User account created; check your email.") # No email server: must contact admin. else: utils.flash_message("User account created; contact" " the site admin to get the password" " setting code.") # Directly enabled and password set. No email to anyone. else: utils.get_logger().info(f"enabled user {user['username']}" " and set password") utils.flash_message("User account created and password set.") # Was set to 'pending'; send email to admins if email server defined. elif flask.current_app.config["MAIL_SERVER"]: admins = get_users(constants.ADMIN, status=constants.ENABLED) emails = [u["email"] for u in admins] site = flask.current_app.config["SITE_NAME"] message = flask_mail.Message(f"{site} user account pending", recipients=emails) url = utils.url_for(".display", username=user["username"]) message.body = f"To enable the user account, go to {url}" utils.mail.send(message) utils.get_logger().info(f"pending user {user['username']}") utils.flash_message("User account created; an email will be sent" " when it has been enabled by the admin.") else: utils.get_logger().info(f"pending user {user['username']}") utils.flash_message("User account created; admin will enable it" " at some point. Try login later.") return flask.redirect(flask.url_for("home"))
def logout(): "Logout from the user account." username = flask.session.pop("username", None) if username: utils.get_logger().info(f"logged out {username}") return flask.redirect(flask.url_for("home"))