def load_user_from_request(request): """ Load user object via access token Access token may be supplied via a GET parameter or the Authorization HTTP header. :param request: Flask request :return: User object, or None if no valid access token was given """ token = request.args.get("access-token") if not token: token = request.headers.get("Authorization") if not token: return None user = db.fetchone( "SELECT name AS user FROM access_tokens WHERE token = %s AND (expires = 0 OR expires > %s)", (token, int(time.time()))) if not user: return None else: db.execute( "UPDATE access_tokens SET calls = calls + 1 WHERE name = %s", (user["user"], )) user = User.get_by_name(user["user"]) user.authenticate() return user
def load_user(user_name): """ Load user object Required for Flask-Login. :param user_name: ID of user :return: User object """ user = User.get_by_name(user_name) if user: user.authenticate() return user
def autologin_whitelist(): """ Checks if host name matches whitelisted hostmask. If so, the user is logged in as the special "autologin" user. """ if not config.FlaskConfig.HOSTNAME_WHITELIST: # if there's not whitelist, there's no point in checking it return if "/static/" in request.path: # never check login for static files return try: socket.setdefaulttimeout(2) hostname = socket.gethostbyaddr(request.remote_addr)[0] except (socket.herror, socket.timeout): return if current_user: if current_user.get_id() == "autologin": # whitelist should be checked on every request logout_user() elif current_user.is_authenticated: # if we're logged in as a regular user, no need for a check return # uva is a special user that is automatically logged in for this request only # if the hostname matches the whitelist for hostmask in config.FlaskConfig.HOSTNAME_WHITELIST: if fnmatch.filter([hostname], hostmask): autologin_user = User.get_by_name("autologin") if not autologin_user: # this user should exist by default abort(500) autologin_user.authenticate() login_user(autologin_user, remember=False)
def add_user(): if not current_user.is_admin(): return error(403, message="This page is off-limits to you.") response = {"success": False} email = request.form.get("email", request.args.get("email", "")).strip() if not email or not re.match(r"[^@]+\@.*?\.[a-zA-Z]+", email): response = {**response, **{"message": "Please provide a valid e-mail address."}} else: username = email try: db.insert("users", data={"name": username, "timestamp_token": int(time.time())}) user = User.get_by_name(username) if user is None: response = {**response, **{"message": "User was created but could not be instantiated properly."}} else: try: user.email_token(new=True) response["success"] = True response = {**response, **{ "message": "An e-mail containing a link through which the registration can be completed has been sent to %s." % username}} except RuntimeError as e: response = {**response, **{ "message": "User was created but the registration e-mail could not be sent to them (%s)." % e}} except psycopg2.IntegrityError: db.rollback() response = {**response, **{"message": "Error: User %s already exists." % username}} if request.args.get("format", None) == "html": return render_template("error.html", message=response["message"], title=("New account created" if response["success"] else "Error")) else: return jsonify(response)
args = cli.parse_args() if __name__ != "__main__": sys.exit(1) if not re.match(r"[^@]+\@.*?\.[a-zA-Z]+", args.username): print("Please provide an e-mail address as username.") sys.exit(1) try: db.insert("users", data={"name": args.username, "timestamp_token": int(time.time())}) except psycopg2.IntegrityError: print("Error: User %s already exists." % args.username) sys.exit(1) user = User.get_by_name(args.username) if user is None: print("Warning: User not created properly. No password reset e-mail sent.") sys.exit(1) try: user.email_token(new=True) print("An e-mail containing a link through which the registration can be completed has been sent to %s." % args.username) except RuntimeError as e: print(""" WARNING: User registered but no e-mail was sent. The following exception was raised: %s %s can complete their registration via the following token: %s""" % (e, args.username, user.get_token()))
def add_user(): """ Create a new user Sends the user an e-mail with a link through which they can set their password. :return: Either an html page with a message, or a JSON response, depending on whether ?format == html """ if not current_user.is_authenticated or not current_user.is_admin(): return error(403, message="This page is off-limits to you.") response = {"success": False} email = request.form.get("email", request.args.get("email", "")).strip() fmt = request.form.get("format", request.args.get("format", "")).strip() force = request.form.get("force", request.args.get("force", None)) if not email or not re.match(r"[^@]+\@.*?\.[a-zA-Z]+", email): response = { **response, **{ "message": "Please provide a valid e-mail address." } } else: username = email try: db.insert("users", data={ "name": username, "timestamp_token": int(time.time()) }) user = User.get_by_name(username) if user is None: response = { **response, **{ "message": "User was created but could not be instantiated properly." } } else: try: user.email_token(new=True) response["success"] = True response = { **response, **{ "message": "An e-mail containing a link through which the registration can be completed has been sent to %s." % username } } except RuntimeError as e: response = { **response, **{ "message": "User was created but the registration e-mail could not be sent to them (%s)." % e } } except psycopg2.IntegrityError: db.rollback() if not force: response = { **response, **{ "message": 'Error: User %s already exists. If you want to re-create the user and re-send the registration e-mail, use [this link](/admin/add-user?email=%s&force=1&format=%s).' % (username, username, fmt) } } else: # if a user does not use their token in time, maybe you want to # be a benevolent admin and give them another change, without # having them go through the whole signup again user = User.get_by_name(username) db.update("users", data={"timestamp_token": int(time.time())}, where={"name": username}) try: user.email_token(new=True) response["success"] = True response = { **response, **{ "message": "A new registration e-mail has been sent to %s." % username } } except RuntimeError as e: response = { **response, **{ "message": "Token was reset registration e-mail could not be sent to them (%s)." % e } } if fmt == "html": return render_template( "error.html", message=response["message"], title=("New account created" if response["success"] else "Error")) else: return jsonify(response)
def request_password(): """ Request a password reset A user that is not logged in can use this page to request that a password reset link will be sent to them. Only one link can be requested per 3 days. This view is rate-limited to prevent brute forcing a list of e-mails. :return: """ if current_user.is_authenticated: # using this while logged in makes no sense return render_template( "error.html", message= "You are already logged in and cannot request a password reset.") # check form submission incomplete = [] if request.method == "POST": # we need *a* username username = request.form.get("username", None) if username is None: incomplete.append(username) flash("Please provide a username.") # is it also a valid username? that is not a 'special' user (like autologin)? resetting_user = User.get_by_name(username) if resetting_user is None or resetting_user.is_special(): incomplete.append("username") flash( "That user is not known here. Note that your username is typically your e-mail address." ) elif resetting_user.get_token() and resetting_user.data[ "timestamp_token"] > 0 and resetting_user.data[ "timestamp_token"] > time.time() - (3 * 86400): # and have they not already requested a reset? incomplete.append("") flash( "You have recently requested a password reset and an e-mail has been sent to you containing a reset link. It could take a while to arrive; also, don't forget to check your spam folder." ) else: # okay, send an e-mail try: resetting_user.email_token(new=False) return render_template( "error.html", title="Success", message= "An e-mail has been sent to you containing instructions on how to reset your password." ) except RuntimeError: # no e-mail could be sent - clear the token so the user can try again later resetting_user.clear_token() incomplete.append(username) flash( "The username was recognised but no reset e-mail could be sent. Please try again later." ) # show page return render_template("account/request-password.html", incomplete=incomplete, flashes=get_flashed_messages(), form=request.form)