fixed error in refactoring, changed auth-system to multi token, cleanup after major change

This commit is contained in:
Markus Pawlata 2018-12-05 01:10:40 +01:00
parent 48bf325d77
commit 4961c398a5
5 changed files with 99 additions and 130 deletions

View File

@ -7,13 +7,13 @@ def message(category, text):
sep = " " sep = " "
else: else:
sep = "--" sep = "--"
print "%s %s%s[%s]%s%s" % ( print("%s %s%s[%s]%s%s" % (
datetime.now().isoformat(), datetime.now().isoformat(),
max(0, message.level) * " |", max(0, message.level) * " |",
sep, sep,
category, category,
max(1, (14 - len(category))) * " ", max(1, (14 - len(category))) * " ",
text) text))
message.level = -1 message.level = -1

View File

@ -3,17 +3,17 @@ from mimetypes import guess_type
from random import shuffle from random import shuffle
from flask import Response, abort, json, jsonify, request from flask import Response, abort, json, jsonify, request
from flask_login import current_user, login_user from flask_login import current_user, login_user, logout_user
from floatapp import app from floatapp import app
from floatapp.jsonp import jsonp from floatapp.jsonp import jsonp
from floatapp.login import (admin_required, admin_user, is_authenticated, from floatapp.login import (admin_required, admin_user,
login_required, photo_user, query_is_admin_user, query_is_admin_user, load_user)
query_is_photo_user)
from process import send_process from process import send_process
from TreeWalker import TreeWalker from TreeWalker import TreeWalker
cwd = os.path.dirname(os.path.abspath(__file__)) cwd = os.path.dirname(os.path.abspath(__file__))
permission_map = app.config.get('PERMISSION_MAP', [])
@app.route("/scan") @app.route("/scan")
@ -23,7 +23,6 @@ def scan_photos():
response = send_process([ response = send_process([
"stdbuf", "stdbuf",
"-oL", "-oL",
os.path.abspath(os.path.join(cwd, "../venv/bin/python")),
os.path.abspath(os.path.join(cwd, "../main.py")), os.path.abspath(os.path.join(cwd, "../main.py")),
os.path.abspath(app.config["ALBUM_PATH"]), os.path.abspath(app.config["ALBUM_PATH"]),
os.path.abspath(app.config["CACHE_PATH"]) os.path.abspath(app.config["CACHE_PATH"])
@ -36,20 +35,80 @@ def scan_photos():
@app.route("/auth") @app.route("/auth")
def login(): def login():
success = False if request.args.get('logout'):
logout_user()
if current_user.is_authenticated: if current_user.is_authenticated:
success = True return 'Already logged in.'
elif (query_is_photo_user(request.form) or
query_is_photo_user(request.args)):
success = login_user(photo_user, remember=True)
elif (query_is_admin_user(request.form) or elif (query_is_admin_user(request.form) or
query_is_admin_user(request.args)): query_is_admin_user(request.args)):
success = login_user(admin_user, remember=True) login_user(admin_user, remember=True)
if not success: else:
abort(403) user_id = (request.form.get('username') or
request.args.get('username', None))
if user_id:
login_user(load_user(user_id), remember=True)
print "logged in {}".format(user_id)
return 'You are now logged in.'
return "" return ""
@app.route("/albums/<path:path>")
def albums(path):
if not has_permission(path):
abort(403)
return accel_redirect(
app.config["ALBUM_ACCEL"], app.config["ALBUM_PATH"], path)
@app.route("/cache/<path:path>")
def cache(path):
if not has_permission(path):
abort(403)
return accel_redirect(
app.config["CACHE_ACCEL"], app.config["CACHE_PATH"], path)
@app.route("/photos")
@jsonp
def photos():
f = open(os.path.join(app.config["CACHE_PATH"], "all_photos.json"), "r")
photos = json.load(f)
f.close()
photos = [photo for photo in photos if has_permission(photo)]
count = int(request.args.get("count", len(photos)))
random = request.args.get("random") == "true"
if random:
shuffle(photos)
else:
photos.reverse()
response = jsonify(photos=photos[0:count])
response.cache_control.no_cache = True
return response
def accel_redirect(internal, real, relative_name):
real_path = os.path.join(real, relative_name)
internal_path = os.path.join(internal, relative_name)
if not os.path.isfile(real_path):
abort(404)
mimetype = None
types = guess_type(real_path)
if len(types) != 0:
mimetype = types[0]
response = Response(mimetype=mimetype)
response.headers.add("X-Accel-Redirect", internal_path)
response.cache_control.public = True
if mimetype == "application/json":
response.cache_control.max_age = 3600
else:
response.cache_control.max_age = 29030400
return response
def cache_base(path): def cache_base(path):
path = path.replace( path = path.replace(
'/', '-').replace( '/', '-').replace(
@ -77,84 +136,15 @@ def cache_base(path):
return path return path
auth_list = [] def has_permission(path):
for auth_path in permission_map.keys():
# this is a protected object
def read_auth_list(): if (path.startswith(auth_path) or
global auth_list, cwd path.startswith(cache_base(auth_path))):
f = open(os.path.join(cwd, "auth.txt"), "r") if current_user.is_anonymous:
paths = [] return False
for path in f: if current_user.id in permission_map.get(auth_path, []):
path = path.strip() return True
paths.append(path) else:
paths.append(cache_base(path)) return False
f.close() return True
auth_list = paths
# TODO: Make this run via inotify
read_auth_list()
def check_permissions(path):
if not is_authenticated():
for auth_path in auth_list:
if path.startswith(auth_path):
abort(403)
@app.route("/albums/<path:path>")
def albums(path):
check_permissions(path)
return accel_redirect(
app.config["ALBUM_ACCEL"], app.config["ALBUM_PATH"], path)
@app.route("/cache/<path:path>")
def cache(path):
check_permissions(path)
return accel_redirect(
app.config["CACHE_ACCEL"], app.config["CACHE_PATH"], path)
def accel_redirect(internal, real, relative_name):
real_path = os.path.join(real, relative_name)
internal_path = os.path.join(internal, relative_name)
if not os.path.isfile(real_path):
abort(404)
mimetype = None
types = guess_type(real_path)
if len(types) != 0:
mimetype = types[0]
response = Response(mimetype=mimetype)
response.headers.add("X-Accel-Redirect", internal_path)
response.cache_control.public = True
if mimetype == "application/json":
response.cache_control.max_age = 3600
else:
response.cache_control.max_age = 29030400
return response
@app.route("/photos")
@jsonp
def photos():
f = open(os.path.join(app.config["CACHE_PATH"], "all_photos.json"), "r")
photos = json.load(f)
f.close()
if not is_authenticated():
def allowed(photo):
for auth_path in auth_list:
if photo.startswith(auth_path):
return False
return True
photos = [photo for photo in photos if allowed(photo)]
count = int(request.args.get("count", len(photos)))
random = request.args.get("random") == "true"
if random:
shuffle(photos)
else:
photos.reverse()
response = jsonify(photos=photos[0:count])
response.cache_control.no_cache = True
return response

View File

@ -9,17 +9,20 @@ class User(UserMixin):
self.admin = admin self.admin = admin
self.id = id self.id = id
photo_user = User("user") def __unicode__(self):
return u"{}".format(self.id)
def __str__(self):
return str(self.id)
admin_user = User("admin", True) admin_user = User("admin", True)
@login_manager.user_loader @login_manager.user_loader
def load_user(id): def load_user(id):
if id == "user": if id == "admin":
return photo_user
elif id == "admin":
return admin_user return admin_user
return None return User(id)
@login_manager.unauthorized_handler @login_manager.unauthorized_handler
@ -27,17 +30,6 @@ def unauthorized():
return abort(403) return abort(403)
def login_required(fn):
@wraps(fn)
def decorated_view(*args, **kwargs):
if (query_is_admin_user(request.args) or
query_is_photo_user(request.args) or
current_user.is_authenticated):
return fn(*args, **kwargs)
return app.login_manager.unauthorized()
return decorated_view
def admin_required(fn): def admin_required(fn):
@wraps(fn) @wraps(fn)
def decorated_view(*args, **kwargs): def decorated_view(*args, **kwargs):
@ -48,21 +40,8 @@ def admin_required(fn):
return decorated_view return decorated_view
def query_is_photo_user(query):
username = query.get("username", None)
password = query.get("password", None)
return username == (app.config["PHOTO_USERNAME"] and
password == app.config["PHOTO_PASSWORD"])
def query_is_admin_user(query): def query_is_admin_user(query):
username = query.get("username", None) username = query.get("username", None)
password = query.get("password", None) password = query.get("password", None)
return username == (app.config["ADMIN_USERNAME"] and return (username == app.config["ADMIN_USERNAME"] and
password == app.config["ADMIN_PASSWORD"]) password == app.config["ADMIN_PASSWORD"])
def is_authenticated():
return (query_is_admin_user(request.args) or
query_is_photo_user(request.args) or
current_user.is_authenticated)

View File

@ -11,11 +11,11 @@ def main():
sys.setdefaultencoding("UTF-8") sys.setdefaultencoding("UTF-8")
if len(sys.argv) != 3: if len(sys.argv) != 3:
print "usage: %s ALBUM_PATH CACHE_PATH" % sys.argv[0] print("usage: %s ALBUM_PATH CACHE_PATH" % sys.argv[0])
return return
try: try:
os.umask(022) os.umask(0o22)
TreeWalker(sys.argv[1], sys.argv[2]) TreeWalker(sys.argv[1], sys.argv[2])
except KeyboardInterrupt: except KeyboardInterrupt:
message("keyboard", "CTRL+C pressed, quitting.") message("keyboard", "CTRL+C pressed, quitting.")

View File

@ -92,7 +92,7 @@
$.ajax({ $.ajax({
type: "GET", type: "GET",
dataType: "text", dataType: "text",
url: "auth?username=photos&password=" + password, url: "auth?username=" + password,
success: function() { success: function() {
result(true); result(true);
}, },