import os from mimetypes import guess_type from random import shuffle from flask import Response, abort, json, jsonify, request from flask_login import current_user, login_user from floatapp import app from floatapp.jsonp import jsonp from floatapp.login import (admin_required, admin_user, is_authenticated, login_required, photo_user, query_is_admin_user, query_is_photo_user) from process import send_process from TreeWalker import TreeWalker cwd = os.path.dirname(os.path.abspath(__file__)) @app.route("/scan") @admin_required def scan_photos(): global cwd response = send_process([ "stdbuf", "-oL", os.path.abspath(os.path.join(cwd, "../venv/bin/python")), os.path.abspath(os.path.join(cwd, "../main.py")), os.path.abspath(app.config["ALBUM_PATH"]), os.path.abspath(app.config["CACHE_PATH"]) ], os.path.join(cwd, "scanner.pid")) response.headers.add("X-Accel-Buffering", "no") response.cache_control.no_cache = True return response @app.route("/auth") def login(): success = False if current_user.is_authenticated: success = True 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 query_is_admin_user(request.args)): success = login_user(admin_user, remember=True) if not success: abort(403) return "" def cache_base(path): path = path.replace( '/', '-').replace( ' ', '_').replace( '(', '').replace( '&', '').replace( ',', '').replace( ')', '').replace( '#', '').replace( '[', '').replace( ']', '').replace( '"', '').replace( "'", '').replace( '_-_', '-').lower() while path.find("--") != -1: path = path.replace("--", "-") while path.find("__") != -1: path = path.replace("__", "_") if len(path) == 0: path = "root" return path auth_list = [] def read_auth_list(): global auth_list, cwd f = open(os.path.join(cwd, "auth.txt"), "r") paths = [] for path in f: path = path.strip() paths.append(path) paths.append(cache_base(path)) f.close() 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/") def albums(path): check_permissions(path) return accel_redirect( app.config["ALBUM_ACCEL"], app.config["ALBUM_PATH"], path) @app.route("/cache/") 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