diff --git a/flaschengeist/plugins/auth/__init__.py b/flaschengeist/plugins/auth/__init__.py index a3fc44d..07b00c4 100644 --- a/flaschengeist/plugins/auth/__init__.py +++ b/flaschengeist/plugins/auth/__init__.py @@ -2,14 +2,13 @@ Allow management of authentication, login, logout, etc. """ -from http.client import CREATED, NO_CONTENT from flask import Blueprint, request, jsonify -from werkzeug.exceptions import Forbidden, BadRequest, Unauthorized, NotFound +from werkzeug.exceptions import Forbidden, BadRequest, Unauthorized from flaschengeist import logger from flaschengeist.plugins import Plugin -from flaschengeist.utils.HTTP import no_content -from flaschengeist.decorator import login_required +from flaschengeist.utils.HTTP import no_content, created +from flaschengeist.utils.decorators import login_required from flaschengeist.controller import sessionController, userController auth_bp = Blueprint("auth", __name__) @@ -50,11 +49,7 @@ def login(): # Lets cleanup the DB sessionController.clear_expired() - return { - "session": session, - "user": user, - "permissions": user.get_permissions(), - }, CREATED + return created(session) @auth_bp.route("/auth", methods=["GET"]) diff --git a/flaschengeist/plugins/balance/__init__.py b/flaschengeist/plugins/balance/__init__.py index c64ca0b..3f458c7 100644 --- a/flaschengeist/plugins/balance/__init__.py +++ b/flaschengeist/plugins/balance/__init__.py @@ -13,7 +13,7 @@ from flaschengeist import logger from flaschengeist.utils import HTTP from flaschengeist.models.session import Session from flaschengeist.utils.datetime import from_iso_format -from flaschengeist.decorator import login_required +from flaschengeist.utils.decorators import login_required from flaschengeist.controller import userController from flaschengeist.plugins import Plugin, before_update_user @@ -75,7 +75,7 @@ def get_shortcuts(userid, current_session: Session): data = request.get_json() if not isinstance(data, list) or not all(isinstance(n, (int, float)) for n in data): raise BadRequest - data.sort() + data.sort(reverse=True) user.set_attribute("balance_shortcuts", data) userController.persist() return no_content() diff --git a/flaschengeist/plugins/roles/__init__.py b/flaschengeist/plugins/roles/__init__.py index de0c505..8ad1a35 100644 --- a/flaschengeist/plugins/roles/__init__.py +++ b/flaschengeist/plugins/roles/__init__.py @@ -5,10 +5,10 @@ Provides routes used to configure roles and permissions of users / roles. from werkzeug.exceptions import BadRequest from flask import Blueprint, request, jsonify -from http.client import CREATED, NO_CONTENT +from http.client import NO_CONTENT from flaschengeist.plugins import Plugin -from flaschengeist.decorator import login_required +from flaschengeist.utils.decorators import login_required from flaschengeist.controller import roleController from flaschengeist.utils.HTTP import created diff --git a/flaschengeist/plugins/schedule/__init__.py b/flaschengeist/plugins/schedule/__init__.py index ebe48ea..d21b4f3 100644 --- a/flaschengeist/plugins/schedule/__init__.py +++ b/flaschengeist/plugins/schedule/__init__.py @@ -3,19 +3,18 @@ Provides duty schedule / duty roster functions """ from datetime import datetime, timedelta, timezone -from http.client import NO_CONTENT, CREATED +from http.client import NO_CONTENT from flask import Blueprint, request, jsonify from werkzeug.exceptions import BadRequest, NotFound, Forbidden from flaschengeist.plugins import Plugin from flaschengeist.models.session import Session -from flaschengeist.decorator import login_required +from flaschengeist.utils.decorators import login_required from flaschengeist.utils.datetime import from_iso_format from flaschengeist.controller import userController from . import event_controller, permissions from . import models -from ... import logger from ...utils.HTTP import no_content schedule_bp = Blueprint("schedule", __name__, url_prefix="/schedule") diff --git a/flaschengeist/plugins/users/__init__.py b/flaschengeist/plugins/users/__init__.py index 8b75e2f..02e565e 100644 --- a/flaschengeist/plugins/users/__init__.py +++ b/flaschengeist/plugins/users/__init__.py @@ -11,7 +11,7 @@ from flaschengeist import logger from flaschengeist.config import config from flaschengeist.plugins import Plugin from flaschengeist.models.user import User, _Avatar -from flaschengeist.decorator import login_required, extract_session +from flaschengeist.utils.decorators import login_required, extract_session, headers from flaschengeist.controller import userController from flaschengeist.utils.HTTP import created from flaschengeist.utils.datetime import from_iso_format @@ -57,6 +57,7 @@ def register(): @users_bp.route("/users", methods=["GET"]) @login_required() +@headers({"Cache-Control": "private, must-revalidate, max-age=3600"}) def list_users(current_session): """List all existing users @@ -75,6 +76,7 @@ def list_users(current_session): @users_bp.route("/users/", methods=["GET"]) @login_required() +@headers({"Cache-Control": "private, must-revalidate, max-age=3600"}) def get_user(userid, current_session): """Retrieve user by userid @@ -96,6 +98,7 @@ def get_user(userid, current_session): @users_bp.route("/users//avatar", methods=["GET"]) +@headers({"Cache-Control": "public, max-age=604800"}) def get_avatar(userid): user = userController.get_user(userid) avatar = userController.load_avatar(user) diff --git a/flaschengeist/decorator.py b/flaschengeist/utils/decorators.py similarity index 58% rename from flaschengeist/decorator.py rename to flaschengeist/utils/decorators.py index 18ded1a..b26f66a 100644 --- a/flaschengeist/decorator.py +++ b/flaschengeist/utils/decorators.py @@ -40,3 +40,29 @@ def login_required(permission=None): return wrapped_f return wrap + + +def headers(headers={}, **headers_kwargs): + """ + Wrap a Flask route to add HTTP headers. + Either pass a dictionary of headers to be set as the headerDict keyword + argument, or pass header values as keyword arguments. Or both. + + The key and value of items in a dictionary will be converted to strings using + the `str` method, ensure both keys and values are serializable thusly. + Args: + headers: A dictionary of headers to be injected into the response headers. + Note, the supplied dictionary is first copied then mutated. + headers_kwargs: The headers to be injected into the response headers. + """ + _headerDict = headers.copy() + _headerDict.update(headers_kwargs) + + def decorator(f): + @wraps(f) + def decorated_function(*args, **kwargs): + return f(*args, **kwargs), _headerDict + + return decorated_function + + return decorator