First attempt at online permissions.
This commit is contained in:
parent
e78a667ee3
commit
ce30077013
10 changed files with 181 additions and 13 deletions
|
@ -4,29 +4,46 @@ Use etiquette_flask_dev.py or etiquette_flask_prod.py.
|
||||||
'''
|
'''
|
||||||
import flask; from flask import request
|
import flask; from flask import request
|
||||||
import functools
|
import functools
|
||||||
|
import json
|
||||||
import mimetypes
|
import mimetypes
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
from voussoirkit import bytestring
|
from voussoirkit import bytestring
|
||||||
|
from voussoirkit import configlayers
|
||||||
from voussoirkit import flasktools
|
from voussoirkit import flasktools
|
||||||
from voussoirkit import pathclass
|
from voussoirkit import pathclass
|
||||||
|
from voussoirkit import vlogging
|
||||||
|
|
||||||
import etiquette
|
import etiquette
|
||||||
|
|
||||||
from . import client_caching
|
from . import client_caching
|
||||||
from . import jinja_filters
|
from . import jinja_filters
|
||||||
|
from . import permissions
|
||||||
from . import sessions
|
from . import sessions
|
||||||
|
|
||||||
|
log = vlogging.getLogger(__name__)
|
||||||
|
|
||||||
|
# Constants ########################################################################################
|
||||||
|
|
||||||
|
DEFAULT_SERVER_CONFIG = {
|
||||||
|
'anonymous_read': True,
|
||||||
|
'anonymous_write': True,
|
||||||
|
}
|
||||||
|
|
||||||
|
BROWSER_CACHE_DURATION = 180
|
||||||
|
|
||||||
# Flask init #######################################################################################
|
# Flask init #######################################################################################
|
||||||
|
|
||||||
# __file__ = .../etiquette_flask/backend/common.py
|
# __file__ = .../etiquette_flask/backend/common.py
|
||||||
# root_dir = .../etiquette_flask
|
# root_dir = .../etiquette_flask
|
||||||
root_dir = pathclass.Path(__file__).parent.parent
|
root_dir = pathclass.Path(__file__).parent.parent
|
||||||
|
|
||||||
|
P = None
|
||||||
|
|
||||||
TEMPLATE_DIR = root_dir.with_child('templates')
|
TEMPLATE_DIR = root_dir.with_child('templates')
|
||||||
STATIC_DIR = root_dir.with_child('static')
|
STATIC_DIR = root_dir.with_child('static')
|
||||||
FAVICON_PATH = STATIC_DIR.with_child('favicon.png')
|
FAVICON_PATH = STATIC_DIR.with_child('favicon.png')
|
||||||
BROWSER_CACHE_DURATION = 180
|
SERVER_CONFIG_FILENAME = 'etiquette_flask_config.json'
|
||||||
|
|
||||||
site = flask.Flask(
|
site = flask.Flask(
|
||||||
__name__,
|
__name__,
|
||||||
|
@ -37,6 +54,7 @@ site.config.update(
|
||||||
SEND_FILE_MAX_AGE_DEFAULT=BROWSER_CACHE_DURATION,
|
SEND_FILE_MAX_AGE_DEFAULT=BROWSER_CACHE_DURATION,
|
||||||
TEMPLATES_AUTO_RELOAD=True,
|
TEMPLATES_AUTO_RELOAD=True,
|
||||||
)
|
)
|
||||||
|
site.server_config = None
|
||||||
site.jinja_env.add_extension('jinja2.ext.do')
|
site.jinja_env.add_extension('jinja2.ext.do')
|
||||||
site.jinja_env.trim_blocks = True
|
site.jinja_env.trim_blocks = True
|
||||||
site.jinja_env.lstrip_blocks = True
|
site.jinja_env.lstrip_blocks = True
|
||||||
|
@ -49,6 +67,7 @@ file_etag_manager = client_caching.FileEtagManager(
|
||||||
max_filesize=5 * bytestring.MEBIBYTE,
|
max_filesize=5 * bytestring.MEBIBYTE,
|
||||||
max_age=BROWSER_CACHE_DURATION,
|
max_age=BROWSER_CACHE_DURATION,
|
||||||
)
|
)
|
||||||
|
permission_manager = permissions.PermissionManager(site)
|
||||||
|
|
||||||
# Response wrappers ################################################################################
|
# Response wrappers ################################################################################
|
||||||
|
|
||||||
|
@ -80,10 +99,18 @@ def before_request():
|
||||||
if site.localhost_only and not request.is_localhost:
|
if site.localhost_only and not request.is_localhost:
|
||||||
return flask.abort(403)
|
return flask.abort(403)
|
||||||
|
|
||||||
|
# Since we don't define this route, I can't just add this where it belongs.
|
||||||
|
# Sorry.
|
||||||
|
if request.url_rule.rule == '/static/<path:filename>':
|
||||||
|
permission_manager.global_public()
|
||||||
|
|
||||||
session_manager._before_request(request)
|
session_manager._before_request(request)
|
||||||
|
|
||||||
@site.after_request
|
@site.after_request
|
||||||
def after_request(response):
|
def after_request(response):
|
||||||
|
if response.status_code < 400 and not hasattr(request, 'checked_permissions'):
|
||||||
|
log.error('You forgot to set checked_permissions for ' + request.path)
|
||||||
|
return flask.abort(500)
|
||||||
response = flasktools.gzip_response(request, response)
|
response = flasktools.gzip_response(request, response)
|
||||||
response = session_manager._after_request(response)
|
response = session_manager._after_request(response)
|
||||||
return response
|
return response
|
||||||
|
@ -277,3 +304,22 @@ def send_file(filepath, override_mimetype=None):
|
||||||
def init_photodb(*args, **kwargs):
|
def init_photodb(*args, **kwargs):
|
||||||
global P
|
global P
|
||||||
P = etiquette.photodb.PhotoDB.closest_photodb(*args, **kwargs)
|
P = etiquette.photodb.PhotoDB.closest_photodb(*args, **kwargs)
|
||||||
|
load_config()
|
||||||
|
|
||||||
|
def load_config() -> None:
|
||||||
|
log.debug('Loading server config file.')
|
||||||
|
config_file = P.data_directory.with_child(SERVER_CONFIG_FILENAME)
|
||||||
|
(config, needs_rewrite) = configlayers.load_file(
|
||||||
|
filepath=config_file,
|
||||||
|
default_config=DEFAULT_SERVER_CONFIG,
|
||||||
|
)
|
||||||
|
site.server_config = config
|
||||||
|
|
||||||
|
if needs_rewrite:
|
||||||
|
save_config()
|
||||||
|
|
||||||
|
def save_config() -> None:
|
||||||
|
log.debug('Saving server config file.')
|
||||||
|
config_file = P.data_directory.with_child(SERVER_CONFIG_FILENAME)
|
||||||
|
with config_file.open('w', encoding='utf-8') as handle:
|
||||||
|
handle.write(json.dumps(site.server_config, indent=4, sort_keys=True))
|
||||||
|
|
|
@ -15,8 +15,7 @@ session_manager = common.session_manager
|
||||||
|
|
||||||
@site.route('/admin')
|
@site.route('/admin')
|
||||||
def get_admin():
|
def get_admin():
|
||||||
if not request.is_localhost:
|
common.permission_manager.admin()
|
||||||
flask.abort(403)
|
|
||||||
|
|
||||||
counts = dotdict.DotDict({
|
counts = dotdict.DotDict({
|
||||||
'albums': common.P.get_album_count(),
|
'albums': common.P.get_album_count(),
|
||||||
|
@ -36,8 +35,7 @@ def get_admin():
|
||||||
|
|
||||||
@site.route('/admin/dbdownload')
|
@site.route('/admin/dbdownload')
|
||||||
def get_dbdump():
|
def get_dbdump():
|
||||||
if not request.is_localhost:
|
common.permission_manager.admin()
|
||||||
flask.abort(403)
|
|
||||||
|
|
||||||
with common.P.transaction:
|
with common.P.transaction:
|
||||||
binary = common.P.database_filepath.read('rb')
|
binary = common.P.database_filepath.read('rb')
|
||||||
|
@ -52,24 +50,23 @@ def get_dbdump():
|
||||||
|
|
||||||
@site.route('/admin/clear_sessions', methods=['POST'])
|
@site.route('/admin/clear_sessions', methods=['POST'])
|
||||||
def post_clear_sessions():
|
def post_clear_sessions():
|
||||||
if not request.is_localhost:
|
common.permission_manager.admin()
|
||||||
return flasktools.json_response({}, status=403)
|
|
||||||
|
|
||||||
session_manager.clear()
|
session_manager.clear()
|
||||||
return flasktools.json_response({})
|
return flasktools.json_response({})
|
||||||
|
|
||||||
@site.route('/admin/reload_config', methods=['POST'])
|
@site.route('/admin/reload_config', methods=['POST'])
|
||||||
def post_reload_config():
|
def post_reload_config():
|
||||||
if not request.is_localhost:
|
common.permission_manager.admin()
|
||||||
return flasktools.json_response({}, status=403)
|
|
||||||
|
|
||||||
common.P.load_config()
|
common.P.load_config()
|
||||||
|
common.load_config()
|
||||||
|
|
||||||
return flasktools.json_response({})
|
return flasktools.json_response({})
|
||||||
|
|
||||||
@site.route('/admin/uncache', methods=['POST'])
|
@site.route('/admin/uncache', methods=['POST'])
|
||||||
def post_uncache():
|
def post_uncache():
|
||||||
if not request.is_localhost:
|
common.permission_manager.admin()
|
||||||
return flasktools.json_response({}, status=403)
|
|
||||||
|
|
||||||
with common.P.transaction:
|
with common.P.transaction:
|
||||||
for cache in common.P.caches.values():
|
for cache in common.P.caches.values():
|
||||||
|
|
|
@ -17,6 +17,7 @@ session_manager = common.session_manager
|
||||||
|
|
||||||
@site.route('/album/<album_id>')
|
@site.route('/album/<album_id>')
|
||||||
def get_album_html(album_id):
|
def get_album_html(album_id):
|
||||||
|
common.permission_manager.basic()
|
||||||
album = common.P_album(album_id, response_type='html')
|
album = common.P_album(album_id, response_type='html')
|
||||||
response = common.render_template(
|
response = common.render_template(
|
||||||
request,
|
request,
|
||||||
|
@ -28,12 +29,14 @@ def get_album_html(album_id):
|
||||||
|
|
||||||
@site.route('/album/<album_id>.json')
|
@site.route('/album/<album_id>.json')
|
||||||
def get_album_json(album_id):
|
def get_album_json(album_id):
|
||||||
|
common.permission_manager.basic()
|
||||||
album = common.P_album(album_id, response_type='json')
|
album = common.P_album(album_id, response_type='json')
|
||||||
album = album.jsonify()
|
album = album.jsonify()
|
||||||
return flasktools.json_response(album)
|
return flasktools.json_response(album)
|
||||||
|
|
||||||
@site.route('/album/<album_id>.zip')
|
@site.route('/album/<album_id>.zip')
|
||||||
def get_album_zip(album_id):
|
def get_album_zip(album_id):
|
||||||
|
common.permission_manager.basic()
|
||||||
album = common.P_album(album_id, response_type='html')
|
album = common.P_album(album_id, response_type='html')
|
||||||
|
|
||||||
recursive = request.args.get('recursive', True)
|
recursive = request.args.get('recursive', True)
|
||||||
|
@ -58,6 +61,7 @@ def get_album_zip(album_id):
|
||||||
@site.route('/album/<album_id>/add_child', methods=['POST'])
|
@site.route('/album/<album_id>/add_child', methods=['POST'])
|
||||||
@flasktools.required_fields(['child_id'], forbid_whitespace=True)
|
@flasktools.required_fields(['child_id'], forbid_whitespace=True)
|
||||||
def post_album_add_child(album_id):
|
def post_album_add_child(album_id):
|
||||||
|
common.permission_manager.basic()
|
||||||
child_ids = stringtools.comma_space_split(request.form['child_id'])
|
child_ids = stringtools.comma_space_split(request.form['child_id'])
|
||||||
with common.P.transaction:
|
with common.P.transaction:
|
||||||
album = common.P_album(album_id, response_type='json')
|
album = common.P_album(album_id, response_type='json')
|
||||||
|
@ -71,6 +75,7 @@ def post_album_add_child(album_id):
|
||||||
@site.route('/album/<album_id>/remove_child', methods=['POST'])
|
@site.route('/album/<album_id>/remove_child', methods=['POST'])
|
||||||
@flasktools.required_fields(['child_id'], forbid_whitespace=True)
|
@flasktools.required_fields(['child_id'], forbid_whitespace=True)
|
||||||
def post_album_remove_child(album_id):
|
def post_album_remove_child(album_id):
|
||||||
|
common.permission_manager.basic()
|
||||||
child_ids = stringtools.comma_space_split(request.form['child_id'])
|
child_ids = stringtools.comma_space_split(request.form['child_id'])
|
||||||
with common.P.transaction:
|
with common.P.transaction:
|
||||||
album = common.P_album(album_id, response_type='json')
|
album = common.P_album(album_id, response_type='json')
|
||||||
|
@ -81,6 +86,7 @@ def post_album_remove_child(album_id):
|
||||||
|
|
||||||
@site.route('/album/<album_id>/remove_thumbnail_photo', methods=['POST'])
|
@site.route('/album/<album_id>/remove_thumbnail_photo', methods=['POST'])
|
||||||
def post_album_remove_thumbnail_photo(album_id):
|
def post_album_remove_thumbnail_photo(album_id):
|
||||||
|
common.permission_manager.basic()
|
||||||
with common.P.transaction:
|
with common.P.transaction:
|
||||||
album = common.P_album(album_id, response_type='json')
|
album = common.P_album(album_id, response_type='json')
|
||||||
album.set_thumbnail_photo(None)
|
album.set_thumbnail_photo(None)
|
||||||
|
@ -88,6 +94,7 @@ def post_album_remove_thumbnail_photo(album_id):
|
||||||
|
|
||||||
@site.route('/album/<album_id>/refresh_directories', methods=['POST'])
|
@site.route('/album/<album_id>/refresh_directories', methods=['POST'])
|
||||||
def post_album_refresh_directories(album_id):
|
def post_album_refresh_directories(album_id):
|
||||||
|
common.permission_manager.basic()
|
||||||
with common.P.transaction:
|
with common.P.transaction:
|
||||||
album = common.P_album(album_id, response_type='json')
|
album = common.P_album(album_id, response_type='json')
|
||||||
for directory in album.get_associated_directories():
|
for directory in album.get_associated_directories():
|
||||||
|
@ -100,6 +107,7 @@ def post_album_refresh_directories(album_id):
|
||||||
@site.route('/album/<album_id>/set_thumbnail_photo', methods=['POST'])
|
@site.route('/album/<album_id>/set_thumbnail_photo', methods=['POST'])
|
||||||
@flasktools.required_fields(['photo_id'], forbid_whitespace=True)
|
@flasktools.required_fields(['photo_id'], forbid_whitespace=True)
|
||||||
def post_album_set_thumbnail_photo(album_id):
|
def post_album_set_thumbnail_photo(album_id):
|
||||||
|
common.permission_manager.basic()
|
||||||
with common.P.transaction:
|
with common.P.transaction:
|
||||||
album = common.P_album(album_id, response_type='json')
|
album = common.P_album(album_id, response_type='json')
|
||||||
photo = common.P_photo(request.form['photo_id'], response_type='json')
|
photo = common.P_photo(request.form['photo_id'], response_type='json')
|
||||||
|
@ -114,7 +122,7 @@ def post_album_add_photo(album_id):
|
||||||
'''
|
'''
|
||||||
Add a photo or photos to this album.
|
Add a photo or photos to this album.
|
||||||
'''
|
'''
|
||||||
|
common.permission_manager.basic()
|
||||||
photo_ids = stringtools.comma_space_split(request.form['photo_id'])
|
photo_ids = stringtools.comma_space_split(request.form['photo_id'])
|
||||||
with common.P.transaction:
|
with common.P.transaction:
|
||||||
album = common.P_album(album_id, response_type='json')
|
album = common.P_album(album_id, response_type='json')
|
||||||
|
@ -129,6 +137,7 @@ def post_album_remove_photo(album_id):
|
||||||
'''
|
'''
|
||||||
Remove a photo or photos from this album.
|
Remove a photo or photos from this album.
|
||||||
'''
|
'''
|
||||||
|
common.permission_manager.basic()
|
||||||
photo_ids = stringtools.comma_space_split(request.form['photo_id'])
|
photo_ids = stringtools.comma_space_split(request.form['photo_id'])
|
||||||
with common.P.transaction:
|
with common.P.transaction:
|
||||||
album = common.P_album(album_id, response_type='json')
|
album = common.P_album(album_id, response_type='json')
|
||||||
|
@ -144,6 +153,7 @@ def post_album_add_tag(album_id):
|
||||||
'''
|
'''
|
||||||
Apply a tag to every photo in the album.
|
Apply a tag to every photo in the album.
|
||||||
'''
|
'''
|
||||||
|
common.permission_manager.basic()
|
||||||
response = {}
|
response = {}
|
||||||
with common.P.transaction:
|
with common.P.transaction:
|
||||||
album = common.P_album(album_id, response_type='json')
|
album = common.P_album(album_id, response_type='json')
|
||||||
|
@ -168,6 +178,7 @@ def post_album_edit(album_id):
|
||||||
'''
|
'''
|
||||||
Edit the title / description.
|
Edit the title / description.
|
||||||
'''
|
'''
|
||||||
|
common.permission_manager.basic()
|
||||||
title = request.form.get('title', None)
|
title = request.form.get('title', None)
|
||||||
description = request.form.get('description', None)
|
description = request.form.get('description', None)
|
||||||
|
|
||||||
|
@ -180,6 +191,7 @@ def post_album_edit(album_id):
|
||||||
|
|
||||||
@site.route('/album/<album_id>/show_in_folder', methods=['POST'])
|
@site.route('/album/<album_id>/show_in_folder', methods=['POST'])
|
||||||
def post_album_show_in_folder(album_id):
|
def post_album_show_in_folder(album_id):
|
||||||
|
common.permission_manager.basic()
|
||||||
if not request.is_localhost:
|
if not request.is_localhost:
|
||||||
flask.abort(403)
|
flask.abort(403)
|
||||||
|
|
||||||
|
@ -199,6 +211,7 @@ def post_album_show_in_folder(album_id):
|
||||||
# Album listings ###################################################################################
|
# Album listings ###################################################################################
|
||||||
|
|
||||||
@site.route('/all_albums.json')
|
@site.route('/all_albums.json')
|
||||||
|
@common.permission_manager.basic_decorator
|
||||||
@flasktools.cached_endpoint(max_age=15)
|
@flasktools.cached_endpoint(max_age=15)
|
||||||
def get_all_album_names():
|
def get_all_album_names():
|
||||||
all_albums = {album.id: album.display_name for album in common.P.get_albums()}
|
all_albums = {album.id: album.display_name for album in common.P.get_albums()}
|
||||||
|
@ -207,6 +220,7 @@ def get_all_album_names():
|
||||||
|
|
||||||
@site.route('/albums')
|
@site.route('/albums')
|
||||||
def get_albums_html():
|
def get_albums_html():
|
||||||
|
common.permission_manager.basic()
|
||||||
albums = list(common.P.get_root_albums())
|
albums = list(common.P.get_root_albums())
|
||||||
albums.sort(key=lambda x: x.display_name.lower())
|
albums.sort(key=lambda x: x.display_name.lower())
|
||||||
response = common.render_template(
|
response = common.render_template(
|
||||||
|
@ -219,6 +233,7 @@ def get_albums_html():
|
||||||
|
|
||||||
@site.route('/albums.json')
|
@site.route('/albums.json')
|
||||||
def get_albums_json():
|
def get_albums_json():
|
||||||
|
common.permission_manager.basic()
|
||||||
albums = list(common.P.get_albums())
|
albums = list(common.P.get_albums())
|
||||||
albums.sort(key=lambda x: x.display_name.lower())
|
albums.sort(key=lambda x: x.display_name.lower())
|
||||||
albums = [album.jsonify(include_photos=False) for album in albums]
|
albums = [album.jsonify(include_photos=False) for album in albums]
|
||||||
|
@ -228,6 +243,7 @@ def get_albums_json():
|
||||||
|
|
||||||
@site.route('/albums/create_album', methods=['POST'])
|
@site.route('/albums/create_album', methods=['POST'])
|
||||||
def post_albums_create():
|
def post_albums_create():
|
||||||
|
common.permission_manager.basic()
|
||||||
title = request.form.get('title', None)
|
title = request.form.get('title', None)
|
||||||
description = request.form.get('description', None)
|
description = request.form.get('description', None)
|
||||||
parent_id = request.form.get('parent_id', None)
|
parent_id = request.form.get('parent_id', None)
|
||||||
|
@ -246,6 +262,7 @@ def post_albums_create():
|
||||||
|
|
||||||
@site.route('/album/<album_id>/delete', methods=['POST'])
|
@site.route('/album/<album_id>/delete', methods=['POST'])
|
||||||
def post_album_delete(album_id):
|
def post_album_delete(album_id):
|
||||||
|
common.permission_manager.basic()
|
||||||
with common.P.transaction:
|
with common.P.transaction:
|
||||||
album = common.P_album(album_id, response_type='json')
|
album = common.P_album(album_id, response_type='json')
|
||||||
album.delete()
|
album.delete()
|
||||||
|
|
|
@ -10,10 +10,12 @@ session_manager = common.session_manager
|
||||||
|
|
||||||
@site.route('/')
|
@site.route('/')
|
||||||
def root():
|
def root():
|
||||||
|
common.permission_manager.global_public()
|
||||||
motd = random.choice(common.P.config['motd_strings'])
|
motd = random.choice(common.P.config['motd_strings'])
|
||||||
return common.render_template(request, 'root.html', motd=motd)
|
return common.render_template(request, 'root.html', motd=motd)
|
||||||
|
|
||||||
@site.route('/favicon.ico')
|
@site.route('/favicon.ico')
|
||||||
@site.route('/favicon.png')
|
@site.route('/favicon.png')
|
||||||
def favicon():
|
def favicon():
|
||||||
|
common.permission_manager.global_public()
|
||||||
return flask.send_file(common.FAVICON_PATH.absolute_path)
|
return flask.send_file(common.FAVICON_PATH.absolute_path)
|
||||||
|
|
|
@ -13,12 +13,14 @@ session_manager = common.session_manager
|
||||||
|
|
||||||
@site.route('/bookmark/<bookmark_id>.json')
|
@site.route('/bookmark/<bookmark_id>.json')
|
||||||
def get_bookmark_json(bookmark_id):
|
def get_bookmark_json(bookmark_id):
|
||||||
|
common.permission_manager.basic()
|
||||||
bookmark = common.P_bookmark(bookmark_id, response_type='json')
|
bookmark = common.P_bookmark(bookmark_id, response_type='json')
|
||||||
response = bookmark.jsonify()
|
response = bookmark.jsonify()
|
||||||
return flasktools.json_response(response)
|
return flasktools.json_response(response)
|
||||||
|
|
||||||
@site.route('/bookmark/<bookmark_id>/edit', methods=['POST'])
|
@site.route('/bookmark/<bookmark_id>/edit', methods=['POST'])
|
||||||
def post_bookmark_edit(bookmark_id):
|
def post_bookmark_edit(bookmark_id):
|
||||||
|
common.permission_manager.basic()
|
||||||
with common.P.transaction:
|
with common.P.transaction:
|
||||||
bookmark = common.P_bookmark(bookmark_id, response_type='json')
|
bookmark = common.P_bookmark(bookmark_id, response_type='json')
|
||||||
# Emptystring is okay for titles, but not for URL.
|
# Emptystring is okay for titles, but not for URL.
|
||||||
|
@ -34,6 +36,7 @@ def post_bookmark_edit(bookmark_id):
|
||||||
|
|
||||||
@site.route('/bookmarks.atom')
|
@site.route('/bookmarks.atom')
|
||||||
def get_bookmarks_atom():
|
def get_bookmarks_atom():
|
||||||
|
common.permission_manager.basic()
|
||||||
bookmarks = common.P.get_bookmarks()
|
bookmarks = common.P.get_bookmarks()
|
||||||
response = etiquette.helpers.make_atom_feed(
|
response = etiquette.helpers.make_atom_feed(
|
||||||
bookmarks,
|
bookmarks,
|
||||||
|
@ -45,11 +48,13 @@ def get_bookmarks_atom():
|
||||||
|
|
||||||
@site.route('/bookmarks')
|
@site.route('/bookmarks')
|
||||||
def get_bookmarks_html():
|
def get_bookmarks_html():
|
||||||
|
common.permission_manager.basic()
|
||||||
bookmarks = list(common.P.get_bookmarks())
|
bookmarks = list(common.P.get_bookmarks())
|
||||||
return common.render_template(request, 'bookmarks.html', bookmarks=bookmarks)
|
return common.render_template(request, 'bookmarks.html', bookmarks=bookmarks)
|
||||||
|
|
||||||
@site.route('/bookmarks.json')
|
@site.route('/bookmarks.json')
|
||||||
def get_bookmarks_json():
|
def get_bookmarks_json():
|
||||||
|
common.permission_manager.basic()
|
||||||
bookmarks = [b.jsonify() for b in common.P.get_bookmarks()]
|
bookmarks = [b.jsonify() for b in common.P.get_bookmarks()]
|
||||||
return flasktools.json_response(bookmarks)
|
return flasktools.json_response(bookmarks)
|
||||||
|
|
||||||
|
@ -58,6 +63,7 @@ def get_bookmarks_json():
|
||||||
@site.route('/bookmarks/create_bookmark', methods=['POST'])
|
@site.route('/bookmarks/create_bookmark', methods=['POST'])
|
||||||
@flasktools.required_fields(['url'], forbid_whitespace=True)
|
@flasktools.required_fields(['url'], forbid_whitespace=True)
|
||||||
def post_bookmark_create():
|
def post_bookmark_create():
|
||||||
|
common.permission_manager.basic()
|
||||||
url = request.form['url']
|
url = request.form['url']
|
||||||
title = request.form.get('title', None)
|
title = request.form.get('title', None)
|
||||||
user = session_manager.get(request).user
|
user = session_manager.get(request).user
|
||||||
|
@ -69,6 +75,7 @@ def post_bookmark_create():
|
||||||
|
|
||||||
@site.route('/bookmark/<bookmark_id>/delete', methods=['POST'])
|
@site.route('/bookmark/<bookmark_id>/delete', methods=['POST'])
|
||||||
def post_bookmark_delete(bookmark_id):
|
def post_bookmark_delete(bookmark_id):
|
||||||
|
common.permission_manager.basic()
|
||||||
with common.P.transaction:
|
with common.P.transaction:
|
||||||
bookmark = common.P_bookmark(bookmark_id, response_type='json')
|
bookmark = common.P_bookmark(bookmark_id, response_type='json')
|
||||||
bookmark.delete()
|
bookmark.delete()
|
||||||
|
|
|
@ -25,11 +25,13 @@ photo_download_zip_tokens = cacheclass.Cache(maxlen=100)
|
||||||
|
|
||||||
@site.route('/photo/<photo_id>')
|
@site.route('/photo/<photo_id>')
|
||||||
def get_photo_html(photo_id):
|
def get_photo_html(photo_id):
|
||||||
|
common.permission_manager.basic()
|
||||||
photo = common.P_photo(photo_id, response_type='html')
|
photo = common.P_photo(photo_id, response_type='html')
|
||||||
return common.render_template(request, 'photo.html', photo=photo)
|
return common.render_template(request, 'photo.html', photo=photo)
|
||||||
|
|
||||||
@site.route('/photo/<photo_id>.json')
|
@site.route('/photo/<photo_id>.json')
|
||||||
def get_photo_json(photo_id):
|
def get_photo_json(photo_id):
|
||||||
|
common.permission_manager.basic()
|
||||||
photo = common.P_photo(photo_id, response_type='json')
|
photo = common.P_photo(photo_id, response_type='json')
|
||||||
photo = photo.jsonify()
|
photo = photo.jsonify()
|
||||||
photo = flasktools.json_response(photo)
|
photo = flasktools.json_response(photo)
|
||||||
|
@ -38,6 +40,7 @@ def get_photo_json(photo_id):
|
||||||
@site.route('/photo/<photo_id>/download')
|
@site.route('/photo/<photo_id>/download')
|
||||||
@site.route('/photo/<photo_id>/download/<basename>')
|
@site.route('/photo/<photo_id>/download/<basename>')
|
||||||
def get_file(photo_id, basename=None):
|
def get_file(photo_id, basename=None):
|
||||||
|
common.permission_manager.basic()
|
||||||
photo_id = photo_id.split('.')[0]
|
photo_id = photo_id.split('.')[0]
|
||||||
photo = common.P.get_photo(photo_id)
|
photo = common.P.get_photo(photo_id)
|
||||||
|
|
||||||
|
@ -63,6 +66,7 @@ def get_file(photo_id, basename=None):
|
||||||
|
|
||||||
@site.route('/photo/<photo_id>/thumbnail')
|
@site.route('/photo/<photo_id>/thumbnail')
|
||||||
@site.route('/photo/<photo_id>/thumbnail/<basename>')
|
@site.route('/photo/<photo_id>/thumbnail/<basename>')
|
||||||
|
@common.permission_manager.basic_decorator
|
||||||
@flasktools.cached_endpoint(max_age=common.BROWSER_CACHE_DURATION)
|
@flasktools.cached_endpoint(max_age=common.BROWSER_CACHE_DURATION)
|
||||||
def get_thumbnail(photo_id, basename=None):
|
def get_thumbnail(photo_id, basename=None):
|
||||||
photo_id = photo_id.split('.')[0]
|
photo_id = photo_id.split('.')[0]
|
||||||
|
@ -90,6 +94,7 @@ def get_thumbnail(photo_id, basename=None):
|
||||||
|
|
||||||
@site.route('/photo/<photo_id>/delete', methods=['POST'])
|
@site.route('/photo/<photo_id>/delete', methods=['POST'])
|
||||||
def post_photo_delete(photo_id):
|
def post_photo_delete(photo_id):
|
||||||
|
common.permission_manager.basic()
|
||||||
delete_file = request.form.get('delete_file', False)
|
delete_file = request.form.get('delete_file', False)
|
||||||
delete_file = stringtools.truthystring(delete_file)
|
delete_file = stringtools.truthystring(delete_file)
|
||||||
with common.P.transaction:
|
with common.P.transaction:
|
||||||
|
@ -122,6 +127,7 @@ def post_photo_add_tag(photo_id):
|
||||||
'''
|
'''
|
||||||
Add a tag to this photo.
|
Add a tag to this photo.
|
||||||
'''
|
'''
|
||||||
|
common.permission_manager.basic()
|
||||||
response = post_photo_add_remove_tag_core(
|
response = post_photo_add_remove_tag_core(
|
||||||
photo_ids=photo_id,
|
photo_ids=photo_id,
|
||||||
tagname=request.form['tagname'],
|
tagname=request.form['tagname'],
|
||||||
|
@ -135,6 +141,7 @@ def post_photo_copy_tags(photo_id):
|
||||||
'''
|
'''
|
||||||
Copy the tags from another photo.
|
Copy the tags from another photo.
|
||||||
'''
|
'''
|
||||||
|
common.permission_manager.basic()
|
||||||
with common.P.transaction:
|
with common.P.transaction:
|
||||||
photo = common.P_photo(photo_id, response_type='json')
|
photo = common.P_photo(photo_id, response_type='json')
|
||||||
other = common.P_photo(request.form['other_photo'], response_type='json')
|
other = common.P_photo(request.form['other_photo'], response_type='json')
|
||||||
|
@ -147,6 +154,7 @@ def post_photo_remove_tag(photo_id):
|
||||||
'''
|
'''
|
||||||
Remove a tag from this photo.
|
Remove a tag from this photo.
|
||||||
'''
|
'''
|
||||||
|
common.permission_manager.basic()
|
||||||
response = post_photo_add_remove_tag_core(
|
response = post_photo_add_remove_tag_core(
|
||||||
photo_ids=photo_id,
|
photo_ids=photo_id,
|
||||||
tagname=request.form['tagname'],
|
tagname=request.form['tagname'],
|
||||||
|
@ -157,6 +165,7 @@ def post_photo_remove_tag(photo_id):
|
||||||
@site.route('/batch/photos/add_tag', methods=['POST'])
|
@site.route('/batch/photos/add_tag', methods=['POST'])
|
||||||
@flasktools.required_fields(['photo_ids', 'tagname'], forbid_whitespace=True)
|
@flasktools.required_fields(['photo_ids', 'tagname'], forbid_whitespace=True)
|
||||||
def post_batch_photos_add_tag():
|
def post_batch_photos_add_tag():
|
||||||
|
common.permission_manager.basic()
|
||||||
response = post_photo_add_remove_tag_core(
|
response = post_photo_add_remove_tag_core(
|
||||||
photo_ids=request.form['photo_ids'],
|
photo_ids=request.form['photo_ids'],
|
||||||
tagname=request.form['tagname'],
|
tagname=request.form['tagname'],
|
||||||
|
@ -167,6 +176,7 @@ def post_batch_photos_add_tag():
|
||||||
@site.route('/batch/photos/remove_tag', methods=['POST'])
|
@site.route('/batch/photos/remove_tag', methods=['POST'])
|
||||||
@flasktools.required_fields(['photo_ids', 'tagname'], forbid_whitespace=True)
|
@flasktools.required_fields(['photo_ids', 'tagname'], forbid_whitespace=True)
|
||||||
def post_batch_photos_remove_tag():
|
def post_batch_photos_remove_tag():
|
||||||
|
common.permission_manager.basic()
|
||||||
response = post_photo_add_remove_tag_core(
|
response = post_photo_add_remove_tag_core(
|
||||||
photo_ids=request.form['photo_ids'],
|
photo_ids=request.form['photo_ids'],
|
||||||
tagname=request.form['tagname'],
|
tagname=request.form['tagname'],
|
||||||
|
@ -178,6 +188,7 @@ def post_batch_photos_remove_tag():
|
||||||
|
|
||||||
@site.route('/photo/<photo_id>/generate_thumbnail', methods=['POST'])
|
@site.route('/photo/<photo_id>/generate_thumbnail', methods=['POST'])
|
||||||
def post_photo_generate_thumbnail(photo_id):
|
def post_photo_generate_thumbnail(photo_id):
|
||||||
|
common.permission_manager.basic()
|
||||||
special = request.form.to_dict()
|
special = request.form.to_dict()
|
||||||
|
|
||||||
with common.P.transaction:
|
with common.P.transaction:
|
||||||
|
@ -212,17 +223,20 @@ def post_photo_refresh_metadata_core(photo_ids):
|
||||||
|
|
||||||
@site.route('/photo/<photo_id>/refresh_metadata', methods=['POST'])
|
@site.route('/photo/<photo_id>/refresh_metadata', methods=['POST'])
|
||||||
def post_photo_refresh_metadata(photo_id):
|
def post_photo_refresh_metadata(photo_id):
|
||||||
|
common.permission_manager.basic()
|
||||||
response = post_photo_refresh_metadata_core(photo_ids=photo_id)
|
response = post_photo_refresh_metadata_core(photo_ids=photo_id)
|
||||||
return response
|
return response
|
||||||
|
|
||||||
@site.route('/batch/photos/refresh_metadata', methods=['POST'])
|
@site.route('/batch/photos/refresh_metadata', methods=['POST'])
|
||||||
@flasktools.required_fields(['photo_ids'], forbid_whitespace=True)
|
@flasktools.required_fields(['photo_ids'], forbid_whitespace=True)
|
||||||
def post_batch_photos_refresh_metadata():
|
def post_batch_photos_refresh_metadata():
|
||||||
|
common.permission_manager.basic()
|
||||||
response = post_photo_refresh_metadata_core(photo_ids=request.form['photo_ids'])
|
response = post_photo_refresh_metadata_core(photo_ids=request.form['photo_ids'])
|
||||||
return response
|
return response
|
||||||
|
|
||||||
@site.route('/photo/<photo_id>/set_searchhidden', methods=['POST'])
|
@site.route('/photo/<photo_id>/set_searchhidden', methods=['POST'])
|
||||||
def post_photo_set_searchhidden(photo_id):
|
def post_photo_set_searchhidden(photo_id):
|
||||||
|
common.permission_manager.basic()
|
||||||
with common.P.transaction:
|
with common.P.transaction:
|
||||||
photo = common.P_photo(photo_id, response_type='json')
|
photo = common.P_photo(photo_id, response_type='json')
|
||||||
photo.set_searchhidden(True)
|
photo.set_searchhidden(True)
|
||||||
|
@ -230,6 +244,7 @@ def post_photo_set_searchhidden(photo_id):
|
||||||
|
|
||||||
@site.route('/photo/<photo_id>/unset_searchhidden', methods=['POST'])
|
@site.route('/photo/<photo_id>/unset_searchhidden', methods=['POST'])
|
||||||
def post_photo_unset_searchhidden(photo_id):
|
def post_photo_unset_searchhidden(photo_id):
|
||||||
|
common.permission_manager.basic()
|
||||||
with common.P.transaction:
|
with common.P.transaction:
|
||||||
photo = common.P_photo(photo_id, response_type='json')
|
photo = common.P_photo(photo_id, response_type='json')
|
||||||
photo.set_searchhidden(False)
|
photo.set_searchhidden(False)
|
||||||
|
@ -249,6 +264,7 @@ def post_batch_photos_searchhidden_core(photo_ids, searchhidden):
|
||||||
|
|
||||||
@site.route('/photo/<photo_id>/show_in_folder', methods=['POST'])
|
@site.route('/photo/<photo_id>/show_in_folder', methods=['POST'])
|
||||||
def post_photo_show_in_folder(photo_id):
|
def post_photo_show_in_folder(photo_id):
|
||||||
|
common.permission_manager.basic()
|
||||||
if not request.is_localhost:
|
if not request.is_localhost:
|
||||||
flask.abort(403)
|
flask.abort(403)
|
||||||
|
|
||||||
|
@ -267,6 +283,7 @@ def post_photo_show_in_folder(photo_id):
|
||||||
@site.route('/batch/photos/set_searchhidden', methods=['POST'])
|
@site.route('/batch/photos/set_searchhidden', methods=['POST'])
|
||||||
@flasktools.required_fields(['photo_ids'], forbid_whitespace=True)
|
@flasktools.required_fields(['photo_ids'], forbid_whitespace=True)
|
||||||
def post_batch_photos_set_searchhidden():
|
def post_batch_photos_set_searchhidden():
|
||||||
|
common.permission_manager.basic()
|
||||||
photo_ids = request.form['photo_ids']
|
photo_ids = request.form['photo_ids']
|
||||||
response = post_batch_photos_searchhidden_core(photo_ids=photo_ids, searchhidden=True)
|
response = post_batch_photos_searchhidden_core(photo_ids=photo_ids, searchhidden=True)
|
||||||
return response
|
return response
|
||||||
|
@ -274,6 +291,7 @@ def post_batch_photos_set_searchhidden():
|
||||||
@site.route('/batch/photos/unset_searchhidden', methods=['POST'])
|
@site.route('/batch/photos/unset_searchhidden', methods=['POST'])
|
||||||
@flasktools.required_fields(['photo_ids'], forbid_whitespace=True)
|
@flasktools.required_fields(['photo_ids'], forbid_whitespace=True)
|
||||||
def post_batch_photos_unset_searchhidden():
|
def post_batch_photos_unset_searchhidden():
|
||||||
|
common.permission_manager.basic()
|
||||||
photo_ids = request.form['photo_ids']
|
photo_ids = request.form['photo_ids']
|
||||||
response = post_batch_photos_searchhidden_core(photo_ids=photo_ids, searchhidden=False)
|
response = post_batch_photos_searchhidden_core(photo_ids=photo_ids, searchhidden=False)
|
||||||
return response
|
return response
|
||||||
|
@ -282,6 +300,7 @@ def post_batch_photos_unset_searchhidden():
|
||||||
|
|
||||||
@site.route('/clipboard')
|
@site.route('/clipboard')
|
||||||
def get_clipboard_page():
|
def get_clipboard_page():
|
||||||
|
common.permission_manager.basic()
|
||||||
return common.render_template(request, 'clipboard.html')
|
return common.render_template(request, 'clipboard.html')
|
||||||
|
|
||||||
@site.route('/batch/photos', methods=['POST'])
|
@site.route('/batch/photos', methods=['POST'])
|
||||||
|
@ -290,6 +309,7 @@ def post_batch_photos():
|
||||||
'''
|
'''
|
||||||
Return a list of photo.jsonify() for each requested photo id.
|
Return a list of photo.jsonify() for each requested photo id.
|
||||||
'''
|
'''
|
||||||
|
common.permission_manager.basic()
|
||||||
photo_ids = request.form['photo_ids']
|
photo_ids = request.form['photo_ids']
|
||||||
|
|
||||||
photo_ids = stringtools.comma_space_split(photo_ids)
|
photo_ids = stringtools.comma_space_split(photo_ids)
|
||||||
|
@ -302,6 +322,7 @@ def post_batch_photos():
|
||||||
@site.route('/batch/photos/photo_card', methods=['POST'])
|
@site.route('/batch/photos/photo_card', methods=['POST'])
|
||||||
@flasktools.required_fields(['photo_ids'], forbid_whitespace=True)
|
@flasktools.required_fields(['photo_ids'], forbid_whitespace=True)
|
||||||
def post_batch_photos_photo_cards():
|
def post_batch_photos_photo_cards():
|
||||||
|
common.permission_manager.basic()
|
||||||
photo_ids = request.form['photo_ids']
|
photo_ids = request.form['photo_ids']
|
||||||
|
|
||||||
photo_ids = stringtools.comma_space_split(photo_ids)
|
photo_ids = stringtools.comma_space_split(photo_ids)
|
||||||
|
@ -333,6 +354,7 @@ def get_batch_photos_download_zip(zip_token):
|
||||||
After the user has generated their zip token, they can retrieve
|
After the user has generated their zip token, they can retrieve
|
||||||
that zip file.
|
that zip file.
|
||||||
'''
|
'''
|
||||||
|
common.permission_manager.basic()
|
||||||
zip_token = zip_token.split('.')[0]
|
zip_token = zip_token.split('.')[0]
|
||||||
try:
|
try:
|
||||||
photo_ids = photo_download_zip_tokens[zip_token]
|
photo_ids = photo_download_zip_tokens[zip_token]
|
||||||
|
@ -362,6 +384,7 @@ def post_batch_photos_download_zip():
|
||||||
so the way this works is we generate a token representing the photoset
|
so the way this works is we generate a token representing the photoset
|
||||||
that they want, and then they can retrieve the zip itself via GET.
|
that they want, and then they can retrieve the zip itself via GET.
|
||||||
'''
|
'''
|
||||||
|
common.permission_manager.basic()
|
||||||
photo_ids = request.form['photo_ids']
|
photo_ids = request.form['photo_ids']
|
||||||
photo_ids = stringtools.comma_space_split(photo_ids)
|
photo_ids = stringtools.comma_space_split(photo_ids)
|
||||||
|
|
||||||
|
@ -436,6 +459,7 @@ def get_search_core():
|
||||||
|
|
||||||
@site.route('/search_embed')
|
@site.route('/search_embed')
|
||||||
def get_search_embed():
|
def get_search_embed():
|
||||||
|
common.permission_manager.basic()
|
||||||
search = get_search_core()
|
search = get_search_core()
|
||||||
response = common.render_template(
|
response = common.render_template(
|
||||||
request,
|
request,
|
||||||
|
@ -447,6 +471,8 @@ def get_search_embed():
|
||||||
|
|
||||||
@site.route('/search')
|
@site.route('/search')
|
||||||
def get_search_html():
|
def get_search_html():
|
||||||
|
common.permission_manager.basic()
|
||||||
|
|
||||||
search = get_search_core()
|
search = get_search_core()
|
||||||
search.kwargs.view = request.args.get('view', 'grid')
|
search.kwargs.view = request.args.get('view', 'grid')
|
||||||
|
|
||||||
|
@ -496,6 +522,7 @@ def get_search_html():
|
||||||
|
|
||||||
@site.route('/search.atom')
|
@site.route('/search.atom')
|
||||||
def get_search_atom():
|
def get_search_atom():
|
||||||
|
common.permission_manager.basic()
|
||||||
search = get_search_core()
|
search = get_search_core()
|
||||||
soup = etiquette.helpers.make_atom_feed(
|
soup = etiquette.helpers.make_atom_feed(
|
||||||
search.results,
|
search.results,
|
||||||
|
@ -508,6 +535,7 @@ def get_search_atom():
|
||||||
|
|
||||||
@site.route('/search.json')
|
@site.route('/search.json')
|
||||||
def get_search_json():
|
def get_search_json():
|
||||||
|
common.permission_manager.basic()
|
||||||
search = get_search_core()
|
search = get_search_core()
|
||||||
response = search.jsonify()
|
response = search.jsonify()
|
||||||
return flasktools.json_response(response)
|
return flasktools.json_response(response)
|
||||||
|
@ -516,5 +544,6 @@ def get_search_json():
|
||||||
|
|
||||||
@site.route('/swipe')
|
@site.route('/swipe')
|
||||||
def get_swipe():
|
def get_swipe():
|
||||||
|
common.permission_manager.basic()
|
||||||
response = common.render_template(request, 'swipe.html')
|
response = common.render_template(request, 'swipe.html')
|
||||||
return response
|
return response
|
||||||
|
|
|
@ -15,11 +15,13 @@ session_manager = common.session_manager
|
||||||
@site.route('/tags/<specific_tag>')
|
@site.route('/tags/<specific_tag>')
|
||||||
@site.route('/tags/<specific_tag>.json')
|
@site.route('/tags/<specific_tag>.json')
|
||||||
def get_tags_specific_redirect(specific_tag):
|
def get_tags_specific_redirect(specific_tag):
|
||||||
|
common.permission_manager.basic()
|
||||||
return flask.redirect(request.url.replace('/tags/', '/tag/'))
|
return flask.redirect(request.url.replace('/tags/', '/tag/'))
|
||||||
|
|
||||||
@site.route('/tagid/<tag_id>')
|
@site.route('/tagid/<tag_id>')
|
||||||
@site.route('/tagid/<tag_id>.json')
|
@site.route('/tagid/<tag_id>.json')
|
||||||
def get_tag_id_redirect(tag_id):
|
def get_tag_id_redirect(tag_id):
|
||||||
|
common.permission_manager.basic()
|
||||||
if request.path.endswith('.json'):
|
if request.path.endswith('.json'):
|
||||||
tag = common.P_tag_id(tag_id, response_type='json')
|
tag = common.P_tag_id(tag_id, response_type='json')
|
||||||
else:
|
else:
|
||||||
|
@ -31,6 +33,7 @@ def get_tag_id_redirect(tag_id):
|
||||||
|
|
||||||
@site.route('/tag/<specific_tag_name>.json')
|
@site.route('/tag/<specific_tag_name>.json')
|
||||||
def get_tag_json(specific_tag_name):
|
def get_tag_json(specific_tag_name):
|
||||||
|
common.permission_manager.basic()
|
||||||
specific_tag = common.P_tag(specific_tag_name, response_type='json')
|
specific_tag = common.P_tag(specific_tag_name, response_type='json')
|
||||||
if specific_tag.name != specific_tag_name:
|
if specific_tag.name != specific_tag_name:
|
||||||
new_url = f'/tag/{specific_tag.name}.json' + request.query_string.decode('utf-8')
|
new_url = f'/tag/{specific_tag.name}.json' + request.query_string.decode('utf-8')
|
||||||
|
@ -44,6 +47,7 @@ def get_tag_json(specific_tag_name):
|
||||||
|
|
||||||
@site.route('/tag/<tagname>/edit', methods=['POST'])
|
@site.route('/tag/<tagname>/edit', methods=['POST'])
|
||||||
def post_tag_edit(tagname):
|
def post_tag_edit(tagname):
|
||||||
|
common.permission_manager.basic()
|
||||||
with common.P.transaction:
|
with common.P.transaction:
|
||||||
tag = common.P_tag(tagname, response_type='json')
|
tag = common.P_tag(tagname, response_type='json')
|
||||||
name = request.form.get('name', '').strip()
|
name = request.form.get('name', '').strip()
|
||||||
|
@ -59,6 +63,7 @@ def post_tag_edit(tagname):
|
||||||
@site.route('/tag/<tagname>/add_child', methods=['POST'])
|
@site.route('/tag/<tagname>/add_child', methods=['POST'])
|
||||||
@flasktools.required_fields(['child_name'], forbid_whitespace=True)
|
@flasktools.required_fields(['child_name'], forbid_whitespace=True)
|
||||||
def post_tag_add_child(tagname):
|
def post_tag_add_child(tagname):
|
||||||
|
common.permission_manager.basic()
|
||||||
with common.P.transaction:
|
with common.P.transaction:
|
||||||
parent = common.P_tag(tagname, response_type='json')
|
parent = common.P_tag(tagname, response_type='json')
|
||||||
child = common.P_tag(request.form['child_name'], response_type='json')
|
child = common.P_tag(request.form['child_name'], response_type='json')
|
||||||
|
@ -69,6 +74,7 @@ def post_tag_add_child(tagname):
|
||||||
@site.route('/tag/<tagname>/add_synonym', methods=['POST'])
|
@site.route('/tag/<tagname>/add_synonym', methods=['POST'])
|
||||||
@flasktools.required_fields(['syn_name'], forbid_whitespace=True)
|
@flasktools.required_fields(['syn_name'], forbid_whitespace=True)
|
||||||
def post_tag_add_synonym(tagname):
|
def post_tag_add_synonym(tagname):
|
||||||
|
common.permission_manager.basic()
|
||||||
syn_name = request.form['syn_name']
|
syn_name = request.form['syn_name']
|
||||||
|
|
||||||
with common.P.transaction:
|
with common.P.transaction:
|
||||||
|
@ -81,6 +87,7 @@ def post_tag_add_synonym(tagname):
|
||||||
@site.route('/tag/<tagname>/remove_child', methods=['POST'])
|
@site.route('/tag/<tagname>/remove_child', methods=['POST'])
|
||||||
@flasktools.required_fields(['child_name'], forbid_whitespace=True)
|
@flasktools.required_fields(['child_name'], forbid_whitespace=True)
|
||||||
def post_tag_remove_child(tagname):
|
def post_tag_remove_child(tagname):
|
||||||
|
common.permission_manager.basic()
|
||||||
with common.P.transaction:
|
with common.P.transaction:
|
||||||
parent = common.P_tag(tagname, response_type='json')
|
parent = common.P_tag(tagname, response_type='json')
|
||||||
child = common.P_tag(request.form['child_name'], response_type='json')
|
child = common.P_tag(request.form['child_name'], response_type='json')
|
||||||
|
@ -91,6 +98,7 @@ def post_tag_remove_child(tagname):
|
||||||
@site.route('/tag/<tagname>/remove_synonym', methods=['POST'])
|
@site.route('/tag/<tagname>/remove_synonym', methods=['POST'])
|
||||||
@flasktools.required_fields(['syn_name'], forbid_whitespace=True)
|
@flasktools.required_fields(['syn_name'], forbid_whitespace=True)
|
||||||
def post_tag_remove_synonym(tagname):
|
def post_tag_remove_synonym(tagname):
|
||||||
|
common.permission_manager.basic()
|
||||||
syn_name = request.form['syn_name']
|
syn_name = request.form['syn_name']
|
||||||
|
|
||||||
with common.P.transaction:
|
with common.P.transaction:
|
||||||
|
@ -103,6 +111,7 @@ def post_tag_remove_synonym(tagname):
|
||||||
# Tag listings #####################################################################################
|
# Tag listings #####################################################################################
|
||||||
|
|
||||||
@site.route('/all_tags.json')
|
@site.route('/all_tags.json')
|
||||||
|
@common.permission_manager.basic_decorator
|
||||||
@flasktools.cached_endpoint(max_age=15)
|
@flasktools.cached_endpoint(max_age=15)
|
||||||
def get_all_tag_names():
|
def get_all_tag_names():
|
||||||
all_tags = list(common.P.get_all_tag_names())
|
all_tags = list(common.P.get_all_tag_names())
|
||||||
|
@ -113,6 +122,7 @@ def get_all_tag_names():
|
||||||
@site.route('/tag/<specific_tag_name>')
|
@site.route('/tag/<specific_tag_name>')
|
||||||
@site.route('/tags')
|
@site.route('/tags')
|
||||||
def get_tags_html(specific_tag_name=None):
|
def get_tags_html(specific_tag_name=None):
|
||||||
|
common.permission_manager.basic()
|
||||||
if specific_tag_name is None:
|
if specific_tag_name is None:
|
||||||
specific_tag = None
|
specific_tag = None
|
||||||
else:
|
else:
|
||||||
|
@ -151,6 +161,7 @@ def get_tags_html(specific_tag_name=None):
|
||||||
|
|
||||||
@site.route('/tags.json')
|
@site.route('/tags.json')
|
||||||
def get_tags_json():
|
def get_tags_json():
|
||||||
|
common.permission_manager.basic()
|
||||||
include_synonyms = request.args.get('synonyms')
|
include_synonyms = request.args.get('synonyms')
|
||||||
include_synonyms = include_synonyms is None or stringtools.truthystring(include_synonyms)
|
include_synonyms = include_synonyms is None or stringtools.truthystring(include_synonyms)
|
||||||
|
|
||||||
|
@ -164,6 +175,7 @@ def get_tags_json():
|
||||||
@site.route('/tags/create_tag', methods=['POST'])
|
@site.route('/tags/create_tag', methods=['POST'])
|
||||||
@flasktools.required_fields(['name'], forbid_whitespace=True)
|
@flasktools.required_fields(['name'], forbid_whitespace=True)
|
||||||
def post_tag_create():
|
def post_tag_create():
|
||||||
|
common.permission_manager.basic()
|
||||||
name = request.form['name']
|
name = request.form['name']
|
||||||
description = request.form.get('description', None)
|
description = request.form.get('description', None)
|
||||||
|
|
||||||
|
@ -175,6 +187,7 @@ def post_tag_create():
|
||||||
@site.route('/tags/easybake', methods=['POST'])
|
@site.route('/tags/easybake', methods=['POST'])
|
||||||
@flasktools.required_fields(['easybake_string'], forbid_whitespace=True)
|
@flasktools.required_fields(['easybake_string'], forbid_whitespace=True)
|
||||||
def post_tag_easybake():
|
def post_tag_easybake():
|
||||||
|
common.permission_manager.basic()
|
||||||
easybake_string = request.form['easybake_string']
|
easybake_string = request.form['easybake_string']
|
||||||
|
|
||||||
with common.P.transaction:
|
with common.P.transaction:
|
||||||
|
@ -184,6 +197,7 @@ def post_tag_easybake():
|
||||||
|
|
||||||
@site.route('/tag/<tagname>/delete', methods=['POST'])
|
@site.route('/tag/<tagname>/delete', methods=['POST'])
|
||||||
def post_tag_delete(tagname):
|
def post_tag_delete(tagname):
|
||||||
|
common.permission_manager.basic()
|
||||||
with common.P.transaction:
|
with common.P.transaction:
|
||||||
tag = common.P_tag(tagname, response_type='json')
|
tag = common.P_tag(tagname, response_type='json')
|
||||||
tag.delete()
|
tag.delete()
|
||||||
|
|
|
@ -14,11 +14,13 @@ session_manager = common.session_manager
|
||||||
|
|
||||||
@site.route('/user/<username>')
|
@site.route('/user/<username>')
|
||||||
def get_user_html(username):
|
def get_user_html(username):
|
||||||
|
common.permission_manager.basic()
|
||||||
user = common.P_user(username, response_type='html')
|
user = common.P_user(username, response_type='html')
|
||||||
return common.render_template(request, 'user.html', user=user)
|
return common.render_template(request, 'user.html', user=user)
|
||||||
|
|
||||||
@site.route('/user/<username>.json')
|
@site.route('/user/<username>.json')
|
||||||
def get_user_json(username):
|
def get_user_json(username):
|
||||||
|
common.permission_manager.basic()
|
||||||
user = common.P_user(username, response_type='json')
|
user = common.P_user(username, response_type='json')
|
||||||
user = user.jsonify()
|
user = user.jsonify()
|
||||||
return flasktools.json_response(user)
|
return flasktools.json_response(user)
|
||||||
|
@ -26,6 +28,7 @@ def get_user_json(username):
|
||||||
@site.route('/userid/<user_id>')
|
@site.route('/userid/<user_id>')
|
||||||
@site.route('/userid/<user_id>.json')
|
@site.route('/userid/<user_id>.json')
|
||||||
def get_user_id_redirect(user_id):
|
def get_user_id_redirect(user_id):
|
||||||
|
common.permission_manager.basic()
|
||||||
if request.path.endswith('.json'):
|
if request.path.endswith('.json'):
|
||||||
user = common.P_user_id(user_id, response_type='json')
|
user = common.P_user_id(user_id, response_type='json')
|
||||||
else:
|
else:
|
||||||
|
@ -37,6 +40,7 @@ def get_user_id_redirect(user_id):
|
||||||
|
|
||||||
@site.route('/user/<username>/edit', methods=['POST'])
|
@site.route('/user/<username>/edit', methods=['POST'])
|
||||||
def post_user_edit(username):
|
def post_user_edit(username):
|
||||||
|
common.permission_manager.basic()
|
||||||
if not request.session:
|
if not request.session:
|
||||||
return flasktools.json_response(etiquette.exceptions.Unauthorized().jsonify(), status=403)
|
return flasktools.json_response(etiquette.exceptions.Unauthorized().jsonify(), status=403)
|
||||||
user = common.P_user(username, response_type='json')
|
user = common.P_user(username, response_type='json')
|
||||||
|
@ -54,6 +58,7 @@ def post_user_edit(username):
|
||||||
|
|
||||||
@site.route('/login', methods=['GET'])
|
@site.route('/login', methods=['GET'])
|
||||||
def get_login():
|
def get_login():
|
||||||
|
common.permission_manager.global_public()
|
||||||
response = common.render_template(
|
response = common.render_template(
|
||||||
request,
|
request,
|
||||||
'login.html',
|
'login.html',
|
||||||
|
@ -66,6 +71,7 @@ def get_login():
|
||||||
@site.route('/login', methods=['POST'])
|
@site.route('/login', methods=['POST'])
|
||||||
@flasktools.required_fields(['username', 'password'])
|
@flasktools.required_fields(['username', 'password'])
|
||||||
def post_login():
|
def post_login():
|
||||||
|
common.permission_manager.global_public()
|
||||||
if request.session.user:
|
if request.session.user:
|
||||||
exc = etiquette.exceptions.AlreadySignedIn()
|
exc = etiquette.exceptions.AlreadySignedIn()
|
||||||
response = exc.jsonify()
|
response = exc.jsonify()
|
||||||
|
@ -96,6 +102,7 @@ def post_login():
|
||||||
|
|
||||||
@site.route('/logout', methods=['POST'])
|
@site.route('/logout', methods=['POST'])
|
||||||
def post_logout():
|
def post_logout():
|
||||||
|
common.permission_manager.basic()
|
||||||
session_manager.remove(request)
|
session_manager.remove(request)
|
||||||
response = flasktools.json_response({})
|
response = flasktools.json_response({})
|
||||||
return response
|
return response
|
||||||
|
@ -104,11 +111,13 @@ def post_logout():
|
||||||
|
|
||||||
@site.route('/register', methods=['GET'])
|
@site.route('/register', methods=['GET'])
|
||||||
def get_register():
|
def get_register():
|
||||||
|
common.permission_manager.global_public()
|
||||||
return flask.redirect('/login')
|
return flask.redirect('/login')
|
||||||
|
|
||||||
@site.route('/register', methods=['POST'])
|
@site.route('/register', methods=['POST'])
|
||||||
@flasktools.required_fields(['username', 'password_1', 'password_2'])
|
@flasktools.required_fields(['username', 'password_1', 'password_2'])
|
||||||
def post_register():
|
def post_register():
|
||||||
|
common.permission_manager.global_public()
|
||||||
if request.session.user:
|
if request.session.user:
|
||||||
exc = etiquette.exceptions.AlreadySignedIn()
|
exc = etiquette.exceptions.AlreadySignedIn()
|
||||||
response = exc.jsonify()
|
response = exc.jsonify()
|
||||||
|
|
43
frontends/etiquette_flask/backend/permissions.py
Normal file
43
frontends/etiquette_flask/backend/permissions.py
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
import flask; from flask import request
|
||||||
|
import functools
|
||||||
|
|
||||||
|
from voussoirkit import vlogging
|
||||||
|
|
||||||
|
log = vlogging.getLogger(__name__)
|
||||||
|
|
||||||
|
class PermissionManager:
|
||||||
|
def __init__(self, site):
|
||||||
|
self.site = site
|
||||||
|
|
||||||
|
def admin(self):
|
||||||
|
if request.is_localhost:
|
||||||
|
request.checked_permissions = True
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return flask.abort(403)
|
||||||
|
|
||||||
|
def basic(self):
|
||||||
|
if request.method not in {'GET', 'POST'}:
|
||||||
|
return flask.abort(405)
|
||||||
|
elif request.is_localhost:
|
||||||
|
request.checked_permissions = True
|
||||||
|
return True
|
||||||
|
elif request.method == 'GET' and self.site.server_config['anonymous_read'] or request.session.user:
|
||||||
|
request.checked_permissions = True
|
||||||
|
return True
|
||||||
|
elif request.method == 'POST' and self.site.server_config['anonymous_write'] or request.session.user:
|
||||||
|
request.checked_permissions = True
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return flask.abort(403)
|
||||||
|
|
||||||
|
def basic_decorator(self, endpoint):
|
||||||
|
log.debug('Decorating %s with basic_decorator.', endpoint)
|
||||||
|
@functools.wraps(endpoint)
|
||||||
|
def wrapped(*args, **kwargs):
|
||||||
|
self.basic()
|
||||||
|
return endpoint(*args, **kwargs)
|
||||||
|
return wrapped
|
||||||
|
|
||||||
|
def global_public(self):
|
||||||
|
request.checked_permissions = True
|
|
@ -1,6 +1,9 @@
|
||||||
'''
|
'''
|
||||||
This file is the gevent launcher for local / development use.
|
This file is the gevent launcher for local / development use.
|
||||||
'''
|
'''
|
||||||
|
from voussoirkit import vlogging
|
||||||
|
vlogging.earlybird_config()
|
||||||
|
|
||||||
import gevent.monkey; gevent.monkey.patch_all()
|
import gevent.monkey; gevent.monkey.patch_all()
|
||||||
import werkzeug.middleware.proxy_fix
|
import werkzeug.middleware.proxy_fix
|
||||||
|
|
||||||
|
@ -11,6 +14,7 @@ import sys
|
||||||
|
|
||||||
from voussoirkit import betterhelp
|
from voussoirkit import betterhelp
|
||||||
from voussoirkit import pathclass
|
from voussoirkit import pathclass
|
||||||
|
from voussoirkit import operatornotify
|
||||||
from voussoirkit import vlogging
|
from voussoirkit import vlogging
|
||||||
|
|
||||||
log = vlogging.getLogger(__name__, 'etiquette_flask_dev')
|
log = vlogging.getLogger(__name__, 'etiquette_flask_dev')
|
||||||
|
@ -79,7 +83,7 @@ def etiquette_flask_launch_argparse(args):
|
||||||
use_https=args.use_https,
|
use_https=args.use_https,
|
||||||
)
|
)
|
||||||
|
|
||||||
@vlogging.main_decorator
|
@operatornotify.main_decorator(subject='etiquette_flask_dev', notify_every_line=True)
|
||||||
def main(argv):
|
def main(argv):
|
||||||
parser = argparse.ArgumentParser(
|
parser = argparse.ArgumentParser(
|
||||||
description='''
|
description='''
|
||||||
|
|
Loading…
Reference in a new issue