diff options
Diffstat (limited to 'stackbin.py')
-rwxr-xr-x | stackbin.py | 146 |
1 files changed, 7 insertions, 139 deletions
diff --git a/stackbin.py b/stackbin.py index 30b9066..56380e6 100755 --- a/stackbin.py +++ b/stackbin.py @@ -20,12 +20,12 @@ # Documentation: see README.md from datetime import datetime, timedelta from itsdangerous import Signer -from flask import (Flask, Response, request, url_for, redirect, g, render_template, session, abort) +from flask import Blueprint, Flask, Response, request, url_for, redirect, g, render_template, session, abort, current_app from flask_sqlalchemy import SQLAlchemy from werkzeug.middleware.proxy_fix import ProxyFix from pytimeparse.timeparse import timeparse # python3-pytimeparse import os -from functools import wraps +from stackbin_auth import auth, requires_session # uwsgidecorators load will fail when using initdb.py but is also not necessary try: from uwsgidecorators import timer # python3-uwsgidecorators @@ -68,6 +68,7 @@ def get_unsigned(string, salt="blank"): return Signer(app.secret_key, salt=salt).unsign(str(string)).decode("utf-8") app = Flask(__name__) +app.register_blueprint(auth) # url_prefix='/' try: app.config.from_pyfile(os.environ['STACKBIN_CONF']) except: @@ -78,64 +79,6 @@ if "STATIC_FOLDER" in app.config: if "TEMPLATE_FOLDER" in app.config: app.template_folder=app.config["TEMPLATE_FOLDER"] -def requires_session(function): - ''' - Requires a valid session, provided by cookie! - ''' - @wraps(function) - def decorated(*args, **kwargs): - if not session: - #return Response("requires session",401) - return redirect(url_for('login')) - else: - if 'user' not in session: - return Response("User is not in this session.",401) - s_user = session['user'] - c_user = request.cookies.get('user') - print(f"session user: {s_user}") - print(f"cookie user: {c_user}") - if session['user'] != c_user: - return Response("Wrong user for this session!.",401) - # otherwise, everything is good! - return function(s_user, [], *args,**kwargs) - # catch-all - #return Response("requires session",401) - return redirect(url_for('login')) - return decorated - -def requires_admin_credential(function): - """ - Requires the user pass the correct admin credential configured - in the conf file. - """ - @wraps(function) - def decorated(*args, **kwargs): - # formdata is in session if we are coming from login_basic() - form = session.get('formdata', None) - if form: - session.pop('formdata') - if 'username' in form: - username = form['username'] - if 'password' in form: - pw = form['password'] - else: - # then we are coming from the form with POST data - if 'username' not in request.form or 'password' not in request.form: - return _unauthorized_admin() - username = request.form['username'] - pw = request.form['password'] - if 'ADMIN_USERNAME' in app.config and \ - 'ADMIN_PASSWORD' in app.config and \ - username == app.config['ADMIN_USERNAME'] and pw == app.config['ADMIN_PASSWORD']: - return function(username, [], *args, **kwargs) - else: - return _unauthorized_admin() - - return decorated - -def _unauthorized_admin(): - return Response(f'<meta http-equiv="Refresh" content="4; url={url_for("login")}">Unauthorized! Invalid admin credential... returning to login form', 401) - def url_for_other_page(page): args = request.view_args.copy() args['page'] = page @@ -377,86 +320,11 @@ def get_proxied_path(): app.wsgi_app = ProxyFix(app.wsgi_app,x_for=pl,x_host=pl,x_port=pl,x_prefix=pl,x_proto=pl) return redirect(url_for('new_paste')) -@app.route("/logout") +# stubs, to simplify any templates that ask url_for("login") +@app.route('/login/') +def login(user="None"): True @app.route("/logout/") -def logout(): - resp = Response(f'<meta http-equiv="Refresh" content="1; url={url_for("new_paste")}">logged out') - # not documented but is found on the Internet in a few random places: - session.clear() - #resp.set_cookie('user','',expires=0) - return resp - -@app.route("/login/new") -@app.route("/login/new/") -def login_new(): - return redirect(url_for("login", new="")) -@app.route("/login/", methods=['POST','GET']) -def login(user="None"): - if request.method == "GET": - if 'user' in session and request.cookies.get('user') == session['user'] and (not 'new' in request.args): - return redirect(url_for("admin")) - auth_header = request.headers.get("Authorization") - # default, show login form - return redirect(url_for("login_form")) - elif request.method == "POST": - if request.authorization: - return redirect(url_for("login_basic"),code=307) - return redirect(url_for("login_generic")) - #return f"Authentication method not supported yet.",400 - -@app.route("/login/basic",methods=['POST','GET']) -@app.route("/login/basic/",methods=['POST','GET']) -def login_basic(): - if not request.authorization: - return Response(f"Please provide username and password.",401,{'WWW-Authenticate': 'Basic'}) - if 'username' not in request.authorization: - return Response(f"No username provided.",401) - if 'password' not in request.authorization: - return Response(f"No password provided.",401) - username = request.authorization.username - pw = request.authorization.password - form={'username':username,'password':pw} - session['formdata'] = form - return redirect(url_for("login_generic"),code=307) - -@app.route("/login/form", methods=['POST','GET']) -@app.route("/login/form/", methods=['POST','GET']) -def login_form(): - if request.method == "GET": - return render_template("login_form.html", - login_url = url_for("login_form") - ) - else: - # assume it is a POST - username="" - if 'username' in request.form: - username = request.form['username'] - password="" - if 'password' in request.form: - password = request.form['password'] - form={'username':username,'password':password} - session['formdata'] = form - return redirect(url_for("login_generic"), code=307) - -@app.route("/login/generic", methods=['POST','GET']) -@app.route("/login/generic/", methods=['POST','GET']) -@requires_admin_credential -def login_generic(user,groups=[]): - resp = Response(f'<meta http-equiv="Refresh" content="1; url={url_for("admin")}">success') - session['user_id'] = "admin" - resp = login_success(session,resp,user,groups) - return resp - -def login_success(session,resp,user,groups=[]): - resp.set_cookie('user',user) - #end_time = datetime.datetime.now(datetime.timezone.utc) + app.permanent_session_lifetime - #end_time_str = datetime.datetime.strftime(end_time,"%FT%TZ") - #resp.set_cookie('timestamp',end_time_str) - session.permanent = True - session['user']=user - #session['end_time'] = end_time_str - print(f"DEBUG: got valid user {user}") - return resp +def logout(): True # Initialize the database if it does not already exist db.create_all() |