2018-11-30 01:28:24 +01:00
|
|
|
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
|
|
|
|
|
2013-04-29 11:05:09 +02:00
|
|
|
from floatapp import app
|
|
|
|
from floatapp.jsonp import jsonp
|
2018-11-30 01:28:24 +01:00
|
|
|
from floatapp.login import (admin_required, admin_user, is_authenticated,
|
|
|
|
login_required, photo_user, query_is_admin_user,
|
|
|
|
query_is_photo_user)
|
2013-04-29 11:05:09 +02:00
|
|
|
from process import send_process
|
|
|
|
from TreeWalker import TreeWalker
|
|
|
|
|
|
|
|
cwd = os.path.dirname(os.path.abspath(__file__))
|
|
|
|
|
2018-11-30 01:28:24 +01:00
|
|
|
|
2013-04-29 11:05:09 +02:00
|
|
|
@app.route("/scan")
|
|
|
|
@admin_required
|
|
|
|
def scan_photos():
|
2018-11-30 01:28:24 +01:00
|
|
|
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
|
|
|
|
|
2013-04-29 11:05:09 +02:00
|
|
|
|
|
|
|
@app.route("/auth")
|
|
|
|
def login():
|
2018-11-30 01:28:24 +01:00
|
|
|
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 ""
|
|
|
|
|
2013-04-29 11:05:09 +02:00
|
|
|
|
|
|
|
def cache_base(path):
|
2018-11-30 01:28:24 +01:00
|
|
|
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 = []
|
|
|
|
|
|
|
|
|
2013-04-29 11:05:09 +02:00
|
|
|
def read_auth_list():
|
2018-11-30 01:28:24 +01:00
|
|
|
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
|
|
|
|
|
2013-04-29 11:05:09 +02:00
|
|
|
|
|
|
|
# TODO: Make this run via inotify
|
|
|
|
read_auth_list()
|
|
|
|
|
2018-11-30 01:28:24 +01:00
|
|
|
|
2013-04-29 11:05:09 +02:00
|
|
|
def check_permissions(path):
|
2018-11-30 01:28:24 +01:00
|
|
|
if not is_authenticated():
|
|
|
|
for auth_path in auth_list:
|
|
|
|
if path.startswith(auth_path):
|
|
|
|
abort(403)
|
|
|
|
|
2013-04-29 11:05:09 +02:00
|
|
|
|
|
|
|
@app.route("/albums/<path:path>")
|
|
|
|
def albums(path):
|
2018-11-30 01:28:24 +01:00
|
|
|
check_permissions(path)
|
|
|
|
return accel_redirect(
|
|
|
|
app.config["ALBUM_ACCEL"], app.config["ALBUM_PATH"], path)
|
|
|
|
|
2013-04-29 11:05:09 +02:00
|
|
|
|
|
|
|
@app.route("/cache/<path:path>")
|
|
|
|
def cache(path):
|
2018-11-30 01:28:24 +01:00
|
|
|
check_permissions(path)
|
|
|
|
return accel_redirect(
|
|
|
|
app.config["CACHE_ACCEL"], app.config["CACHE_PATH"], path)
|
|
|
|
|
2013-04-29 11:05:09 +02:00
|
|
|
|
|
|
|
def accel_redirect(internal, real, relative_name):
|
2018-11-30 01:28:24 +01:00
|
|
|
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
|
|
|
|
|
2013-04-29 11:05:09 +02:00
|
|
|
|
|
|
|
@app.route("/photos")
|
|
|
|
@jsonp
|
|
|
|
def photos():
|
2018-11-30 01:28:24 +01:00
|
|
|
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
|