Compare commits

...

2 Commits

14 changed files with 112 additions and 104 deletions

View File

@ -1,10 +1,8 @@
"""Flaschengeist""" """Flaschengeist"""
import logging import logging
from importlib.metadata import version from importlib.metadata import version
from pathlib import Path
__version__ = version("flaschengeist") __version__ = version("flaschengeist")
_module_path = Path(__file__).parent
__pdoc__ = {} __pdoc__ = {}
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)

View File

@ -1,10 +1,10 @@
import enum import enum
import pkg_resources
from flask import Flask, current_app from flask import Flask, current_app
from flask_cors import CORS from flask_cors import CORS
from datetime import datetime, date from datetime import datetime, date
from flask.json import JSONEncoder, jsonify from flask.json import JSONEncoder, jsonify
from importlib_metadata import entry_points
from sqlalchemy.exc import OperationalError from sqlalchemy.exc import OperationalError
from werkzeug.exceptions import HTTPException from werkzeug.exceptions import HTTPException
@ -41,18 +41,15 @@ def __load_plugins(app):
logger.debug("Search for plugins") logger.debug("Search for plugins")
app.config["FG_PLUGINS"] = {} app.config["FG_PLUGINS"] = {}
for entry_point in pkg_resources.iter_entry_points("flaschengeist.plugins"): for entry_point in entry_points(group="flaschengeist.plugins"):
logger.debug(f"Found plugin: >{entry_point.name}<") logger.debug(f"Found plugin: {entry_point.name} ({entry_point.dist.version})")
if entry_point.name == config["FLASCHENGEIST"]["auth"] or ( if entry_point.name == config["FLASCHENGEIST"]["auth"] or (
entry_point.name in config and config[entry_point.name].get("enabled", False) entry_point.name in config and config[entry_point.name].get("enabled", False)
): ):
logger.debug(f"Load plugin {entry_point.name}") logger.debug(f"Load plugin {entry_point.name}")
try: try:
plugin = entry_point.load() plugin = entry_point.load()(entry_point, config=config.get(entry_point.name, {}))
if not hasattr(plugin, "name"):
setattr(plugin, "name", entry_point.name)
plugin = plugin(config.get(entry_point.name, {}))
if hasattr(plugin, "blueprint") and plugin.blueprint is not None: if hasattr(plugin, "blueprint") and plugin.blueprint is not None:
app.register_blueprint(plugin.blueprint) app.register_blueprint(plugin.blueprint)
except: except:

View File

@ -1,12 +1,12 @@
import os import os
import toml import toml
import logging.config
import collections.abc import collections.abc
from pathlib import Path from pathlib import Path
from logging.config import dictConfig
from werkzeug.middleware.proxy_fix import ProxyFix from werkzeug.middleware.proxy_fix import ProxyFix
from flaschengeist import _module_path, logger
from flaschengeist import logger
# Default config: # Default config:
config = {"DATABASE": {"engine": "mysql", "port": 3306}} config = {"DATABASE": {"engine": "mysql", "port": 3306}}
@ -23,7 +23,7 @@ def update_dict(d, u):
def read_configuration(test_config): def read_configuration(test_config):
global config global config
paths = [_module_path] paths = [Path(__file__).parent]
if not test_config: if not test_config:
paths.append(Path.home() / ".config") paths.append(Path.home() / ".config")
@ -56,7 +56,7 @@ def configure_logger():
logger_config["handlers"]["wsgi"]["level"] = level logger_config["handlers"]["wsgi"]["level"] = level
# Read default config # Read default config
logger_config = toml.load(_module_path / "logging.toml") logger_config = toml.load(Path(__file__).parent /"logging.toml")
if "LOGGING" in config: if "LOGGING" in config:
# Override with user config # Override with user config
update_dict(logger_config, config.get("LOGGING")) update_dict(logger_config, config.get("LOGGING"))
@ -68,7 +68,7 @@ def configure_logger():
if "FG_LOGGING" in os.environ: if "FG_LOGGING" in os.environ:
set_level(os.environ.get("FG_LOGGING", "CRITICAL")) set_level(os.environ.get("FG_LOGGING", "CRITICAL"))
logging.config.dictConfig(logger_config) dictConfig(logger_config)
def configure_app(app, test_config=None): def configure_app(app, test_config=None):

View File

@ -12,10 +12,12 @@ root = "/api"
secret_key = "V3ryS3cr3t" secret_key = "V3ryS3cr3t"
# Domain used by frontend # Domain used by frontend
[scheduler] [DATABASE]
# Possible values are: "passive_web" (default), "active_web" and "system" # engine = "mysql" (default)
# See documentation host = "localhost"
# cron = "passive_web" user = "flaschengeist"
password = "flaschengeist"
database = "flaschengeist"
[LOGGING] [LOGGING]
# You can override all settings from the logging.toml here # You can override all settings from the logging.toml here
@ -33,14 +35,6 @@ level = "DEBUG"
# encoding = "utf8" # encoding = "utf8"
# filename = "flaschengeist.log" # filename = "flaschengeist.log"
[DATABASE]
# engine = "mysql" (default)
host = "localhost"
user = "flaschengeist"
password = "flaschengeist"
database = "flaschengeist"
[FILES] [FILES]
# Path for file / image uploads # Path for file / image uploads
data_path = "./data" data_path = "./data"
@ -54,6 +48,11 @@ allowed_mimetypes = [
"image/webp" "image/webp"
] ]
[scheduler]
# Possible values are: "passive_web" (default), "active_web" and "system"
# See documentation
# cron = "passive_web"
[auth_ldap] [auth_ldap]
# Full documentation https://flaschengeist.dev/Flaschengeist/flaschengeist/wiki/plugins_auth_ldap # Full documentation https://flaschengeist.dev/Flaschengeist/flaschengeist/wiki/plugins_auth_ldap
# host = "localhost" # host = "localhost"

View File

@ -1,6 +1,7 @@
import pkg_resources from importlib_metadata import Distribution, EntryPoint
from werkzeug.datastructures import FileStorage from werkzeug.datastructures import FileStorage
from werkzeug.exceptions import MethodNotAllowed, NotFound from werkzeug.exceptions import MethodNotAllowed, NotFound
from flaschengeist.models.user import _Avatar, User from flaschengeist.models.user import _Avatar, User
from flaschengeist.utils.hook import HookBefore, HookAfter from flaschengeist.utils.hook import HookBefore, HookAfter
@ -45,31 +46,43 @@ Args:
class Plugin: class Plugin:
"""Base class for all Plugins """Base class for all Plugins
If your class uses custom models add a static property called ``models``"""
blueprint = None # You have to override If your class uses custom models add a static property called ``models``.
"""Override with a `flask.blueprint` if the plugin uses custom routes""" """
permissions = [] # You have to override
"""Override to add custom permissions used by the plugin name: str
"""Name of the plugin, loaded from EntryPoint"""
version: str
"""Version of the plugin, loaded from Distribution"""
dist: Distribution
"""Distribution of this plugin"""
blueprint = None
"""Optional `flask.blueprint` if the plugin uses custom routes"""
permissions: list[str] = []
"""Optional list of custom permissions used by the plugin
A good style is to name the permissions with a prefix related to the plugin name, A good style is to name the permissions with a prefix related to the plugin name,
to prevent clashes with other plugins. E. g. instead of *delete* use *plugin_delete*. to prevent clashes with other plugins. E. g. instead of *delete* use *plugin_delete*.
""" """
id = "dev.flaschengeist.plugin" # You have to override
"""Override with the unique ID of the plugin (Hint: FQN)"""
name = "plugin" # You have to override
"""Override with human readable name of the plugin"""
models = None # You have to override
"""Override with models module"""
migrations_path = None # Override this with the location of your db migrations directory
"""Override with path to migration files, if custome db tables are used"""
def __init__(self, config=None): models = None
"""Optional module containing the SQLAlchemy models used by the plugin"""
migrations_path = None
"""Optional location of the path to migration files, required if custome db tables are used"""
def __init__(self, entry_point: EntryPoint, config=None):
"""Constructor called by create_app """Constructor called by create_app
Args: Args:
config: Dict configuration containing the plugin section config: Dict configuration containing the plugin section
""" """
self.version = pkg_resources.get_distribution(self.__module__.split(".")[0]).version self.version = entry_point.dist.version
self.name = entry_point.name
self.dist = entry_point.dist
def install(self): def install(self):
"""Installation routine """Installation routine
@ -91,7 +104,7 @@ class Plugin:
""" """
from ..controller import pluginController from ..controller import pluginController
return pluginController.get_setting(self.id) return pluginController.get_setting(self.id, name, **kwargs)
def set_setting(self, name: str, value): def set_setting(self, name: str, value):
"""Save setting in database """Save setting in database

View File

@ -17,8 +17,8 @@ from flaschengeist.plugins import AuthPlugin, before_role_updated
class AuthLDAP(AuthPlugin): class AuthLDAP(AuthPlugin):
def __init__(self, config): def __init__(self, entry_point, config):
super().__init__() super().__init__(entry_point)
app.config.update( app.config.update(
LDAP_SERVER=config.get("host", "localhost"), LDAP_SERVER=config.get("host", "localhost"),
LDAP_PORT=config.get("port", 389), LDAP_PORT=config.get("port", 389),

View File

@ -56,16 +56,14 @@ def service_debit():
class BalancePlugin(Plugin): class BalancePlugin(Plugin):
name = "balance"
id = "dev.flaschengeist.balance"
blueprint = Blueprint(name, __name__)
permissions = permissions.permissions permissions = permissions.permissions
plugin: "BalancePlugin" = LocalProxy(lambda: current_app.config["FG_PLUGINS"][BalancePlugin.name]) plugin: "BalancePlugin" = LocalProxy(lambda: current_app.config["FG_PLUGINS"][BalancePlugin.name])
models = models models = models
def __init__(self, config): def __init__(self, entry_point, config):
super(BalancePlugin, self).__init__(config) super(BalancePlugin, self).__init__(entry_point, config)
from . import routes from . routes import blueprint
self.blueprint = blueprint
@plugins_loaded @plugins_loaded
def post_loaded(*args, **kwargs): def post_loaded(*args, **kwargs):

View File

@ -1,6 +1,6 @@
from datetime import datetime, timezone from datetime import datetime, timezone
from werkzeug.exceptions import Forbidden, BadRequest from werkzeug.exceptions import Forbidden, BadRequest
from flask import request, jsonify from flask import Blueprint, request, jsonify
from flaschengeist.utils import HTTP from flaschengeist.utils import HTTP
from flaschengeist.models.session import Session from flaschengeist.models.session import Session
@ -17,8 +17,9 @@ def str2bool(string: str):
return False return False
raise ValueError raise ValueError
blueprint = Blueprint("balance", __package__)
@BalancePlugin.blueprint.route("/users/<userid>/balance/shortcuts", methods=["GET", "PUT"]) blueprint.route("/users/<userid>/balance/shortcuts", methods=["GET", "PUT"])
@login_required() @login_required()
def get_shortcuts(userid, current_session: Session): def get_shortcuts(userid, current_session: Session):
"""Get balance shortcuts of an user """Get balance shortcuts of an user
@ -50,7 +51,7 @@ def get_shortcuts(userid, current_session: Session):
return HTTP.no_content() return HTTP.no_content()
@BalancePlugin.blueprint.route("/users/<userid>/balance/limit", methods=["GET"]) blueprint.route("/users/<userid>/balance/limit", methods=["GET"])
@login_required() @login_required()
def get_limit(userid, current_session: Session): def get_limit(userid, current_session: Session):
"""Get limit of an user """Get limit of an user
@ -73,7 +74,7 @@ def get_limit(userid, current_session: Session):
return {"limit": balance_controller.get_limit(user)} return {"limit": balance_controller.get_limit(user)}
@BalancePlugin.blueprint.route("/users/<userid>/balance/limit", methods=["PUT"]) blueprint.route("/users/<userid>/balance/limit", methods=["PUT"])
@login_required(permissions.SET_LIMIT) @login_required(permissions.SET_LIMIT)
def set_limit(userid, current_session: Session): def set_limit(userid, current_session: Session):
"""Set the limit of an user """Set the limit of an user
@ -99,7 +100,7 @@ def set_limit(userid, current_session: Session):
return HTTP.no_content() return HTTP.no_content()
@BalancePlugin.blueprint.route("/users/balance/limit", methods=["GET", "PUT"]) blueprint.route("/users/balance/limit", methods=["GET", "PUT"])
@login_required(permission=permissions.SET_LIMIT) @login_required(permission=permissions.SET_LIMIT)
def limits(current_session: Session): def limits(current_session: Session):
"""Get, Modify limit of all users """Get, Modify limit of all users
@ -124,7 +125,7 @@ def limits(current_session: Session):
return HTTP.no_content() return HTTP.no_content()
@BalancePlugin.blueprint.route("/users/<userid>/balance", methods=["GET"]) blueprint.route("/users/<userid>/balance", methods=["GET"])
@login_required(permission=permissions.SHOW) @login_required(permission=permissions.SHOW)
def get_balance(userid, current_session: Session): def get_balance(userid, current_session: Session):
"""Get balance of user, optionally filtered """Get balance of user, optionally filtered
@ -162,7 +163,7 @@ def get_balance(userid, current_session: Session):
return {"credit": balance[0], "debit": balance[1], "balance": balance[2]} return {"credit": balance[0], "debit": balance[1], "balance": balance[2]}
@BalancePlugin.blueprint.route("/users/<userid>/balance/transactions", methods=["GET"]) blueprint.route("/users/<userid>/balance/transactions", methods=["GET"])
@login_required(permission=permissions.SHOW) @login_required(permission=permissions.SHOW)
def get_transactions(userid, current_session: Session): def get_transactions(userid, current_session: Session):
"""Get transactions of user, optionally filtered """Get transactions of user, optionally filtered
@ -223,7 +224,7 @@ def get_transactions(userid, current_session: Session):
return {"transactions": transactions, "count": count} return {"transactions": transactions, "count": count}
@BalancePlugin.blueprint.route("/users/<userid>/balance", methods=["PUT"]) blueprint.route("/users/<userid>/balance", methods=["PUT"])
@login_required() @login_required()
def change_balance(userid, current_session: Session): def change_balance(userid, current_session: Session):
"""Change balance of an user """Change balance of an user
@ -272,7 +273,7 @@ def change_balance(userid, current_session: Session):
raise Forbidden raise Forbidden
@BalancePlugin.blueprint.route("/balance/<int:transaction_id>", methods=["DELETE"]) blueprint.route("/balance/<int:transaction_id>", methods=["DELETE"])
@login_required() @login_required()
def reverse_transaction(transaction_id, current_session: Session): def reverse_transaction(transaction_id, current_session: Session):
"""Reverse a transaction """Reverse a transaction
@ -297,7 +298,7 @@ def reverse_transaction(transaction_id, current_session: Session):
raise Forbidden raise Forbidden
@BalancePlugin.blueprint.route("/balance", methods=["GET"]) blueprint.route("/balance", methods=["GET"])
@login_required(permission=permissions.SHOW_OTHER) @login_required(permission=permissions.SHOW_OTHER)
def get_balances(current_session: Session): def get_balances(current_session: Session):
"""Get all balances """Get all balances

View File

@ -12,8 +12,8 @@ from . import Plugin
class MailMessagePlugin(Plugin): class MailMessagePlugin(Plugin):
def __init__(self, config): def __init__(self, entry_point, config):
super().__init__() super().__init__(entry_point)
self.server = config["SERVER"] self.server = config["SERVER"]
self.port = config["PORT"] self.port = config["PORT"]
self.user = config["USER"] self.user = config["USER"]

View File

@ -15,21 +15,22 @@ from . import models
from . import pricelist_controller, permissions from . import pricelist_controller, permissions
blueprint = Blueprint("pricelist", __name__, url_prefix="/pricelist")
class PriceListPlugin(Plugin): class PriceListPlugin(Plugin):
name = "pricelist"
permissions = permissions.permissions permissions = permissions.permissions
blueprint = Blueprint(name, __name__, url_prefix="/pricelist")
plugin = LocalProxy(lambda: current_app.config["FG_PLUGINS"][PriceListPlugin.name]) plugin = LocalProxy(lambda: current_app.config["FG_PLUGINS"][PriceListPlugin.name])
models = models models = models
def __init__(self, cfg): def __init__(self, entry_point, config=None):
super().__init__(cfg) super().__init__(entry_point, config)
self.blueprint = blueprint
config = {"discount": 0} config = {"discount": 0}
config.update(cfg) config.update(config)
@PriceListPlugin.blueprint.route("/drink-types", methods=["GET"]) blueprint.route("/drink-types", methods=["GET"])
@PriceListPlugin.blueprint.route("/drink-types/<int:identifier>", methods=["GET"]) blueprint.route("/drink-types/<int:identifier>", methods=["GET"])
def get_drink_types(identifier=None): def get_drink_types(identifier=None):
"""Get DrinkType(s) """Get DrinkType(s)
@ -49,7 +50,7 @@ def get_drink_types(identifier=None):
return jsonify(result) return jsonify(result)
@PriceListPlugin.blueprint.route("/drink-types", methods=["POST"]) blueprint.route("/drink-types", methods=["POST"])
@login_required(permission=permissions.CREATE_TYPE) @login_required(permission=permissions.CREATE_TYPE)
def new_drink_type(current_session): def new_drink_type(current_session):
"""Create new DrinkType """Create new DrinkType
@ -71,7 +72,7 @@ def new_drink_type(current_session):
return jsonify(drink_type) return jsonify(drink_type)
@PriceListPlugin.blueprint.route("/drink-types/<int:identifier>", methods=["PUT"]) blueprint.route("/drink-types/<int:identifier>", methods=["PUT"])
@login_required(permission=permissions.EDIT_TYPE) @login_required(permission=permissions.EDIT_TYPE)
def update_drink_type(identifier, current_session): def update_drink_type(identifier, current_session):
"""Modify DrinkType """Modify DrinkType
@ -94,7 +95,7 @@ def update_drink_type(identifier, current_session):
return jsonify(drink_type) return jsonify(drink_type)
@PriceListPlugin.blueprint.route("/drink-types/<int:identifier>", methods=["DELETE"]) blueprint.route("/drink-types/<int:identifier>", methods=["DELETE"])
@login_required(permission=permissions.DELETE_TYPE) @login_required(permission=permissions.DELETE_TYPE)
def delete_drink_type(identifier, current_session): def delete_drink_type(identifier, current_session):
"""Delete DrinkType """Delete DrinkType
@ -112,8 +113,8 @@ def delete_drink_type(identifier, current_session):
return no_content() return no_content()
@PriceListPlugin.blueprint.route("/tags", methods=["GET"]) blueprint.route("/tags", methods=["GET"])
@PriceListPlugin.blueprint.route("/tags/<int:identifier>", methods=["GET"]) blueprint.route("/tags/<int:identifier>", methods=["GET"])
def get_tags(identifier=None): def get_tags(identifier=None):
"""Get Tag(s) """Get Tag(s)
@ -133,7 +134,7 @@ def get_tags(identifier=None):
return jsonify(result) return jsonify(result)
@PriceListPlugin.blueprint.route("/tags", methods=["POST"]) blueprint.route("/tags", methods=["POST"])
@login_required(permission=permissions.CREATE_TAG) @login_required(permission=permissions.CREATE_TAG)
def new_tag(current_session): def new_tag(current_session):
"""Create Tag """Create Tag
@ -153,7 +154,7 @@ def new_tag(current_session):
return jsonify(drink_type) return jsonify(drink_type)
@PriceListPlugin.blueprint.route("/tags/<int:identifier>", methods=["PUT"]) blueprint.route("/tags/<int:identifier>", methods=["PUT"])
@login_required(permission=permissions.EDIT_TAG) @login_required(permission=permissions.EDIT_TAG)
def update_tag(identifier, current_session): def update_tag(identifier, current_session):
"""Modify Tag """Modify Tag
@ -174,7 +175,7 @@ def update_tag(identifier, current_session):
return jsonify(tag) return jsonify(tag)
@PriceListPlugin.blueprint.route("/tags/<int:identifier>", methods=["DELETE"]) blueprint.route("/tags/<int:identifier>", methods=["DELETE"])
@login_required(permission=permissions.DELETE_TAG) @login_required(permission=permissions.DELETE_TAG)
def delete_tag(identifier, current_session): def delete_tag(identifier, current_session):
"""Delete Tag """Delete Tag
@ -192,8 +193,8 @@ def delete_tag(identifier, current_session):
return no_content() return no_content()
@PriceListPlugin.blueprint.route("/drinks", methods=["GET"]) blueprint.route("/drinks", methods=["GET"])
@PriceListPlugin.blueprint.route("/drinks/<int:identifier>", methods=["GET"]) blueprint.route("/drinks/<int:identifier>", methods=["GET"])
def get_drinks(identifier=None): def get_drinks(identifier=None):
"""Get Drink(s) """Get Drink(s)
@ -249,7 +250,7 @@ def get_drinks(identifier=None):
return jsonify({"drinks": drinks, "count": count}) return jsonify({"drinks": drinks, "count": count})
@PriceListPlugin.blueprint.route("/list", methods=["GET"]) blueprint.route("/list", methods=["GET"])
def get_pricelist(): def get_pricelist():
"""Get Priclist """Get Priclist
Route: ``/pricelist/list`` | Method: ``GET`` Route: ``/pricelist/list`` | Method: ``GET``
@ -298,7 +299,7 @@ def get_pricelist():
return jsonify({"pricelist": pricelist, "count": count}) return jsonify({"pricelist": pricelist, "count": count})
@PriceListPlugin.blueprint.route("/drinks/search/<string:name>", methods=["GET"]) blueprint.route("/drinks/search/<string:name>", methods=["GET"])
def search_drinks(name): def search_drinks(name):
"""Search Drink """Search Drink
@ -319,7 +320,7 @@ def search_drinks(name):
return jsonify(pricelist_controller.get_drinks(name, public=public)) return jsonify(pricelist_controller.get_drinks(name, public=public))
@PriceListPlugin.blueprint.route("/drinks", methods=["POST"]) blueprint.route("/drinks", methods=["POST"])
@login_required(permission=permissions.CREATE) @login_required(permission=permissions.CREATE)
def create_drink(current_session): def create_drink(current_session):
"""Create Drink """Create Drink
@ -371,7 +372,7 @@ def create_drink(current_session):
return jsonify(pricelist_controller.set_drink(data)) return jsonify(pricelist_controller.set_drink(data))
@PriceListPlugin.blueprint.route("/drinks/<int:identifier>", methods=["PUT"]) blueprint.route("/drinks/<int:identifier>", methods=["PUT"])
@login_required(permission=permissions.EDIT) @login_required(permission=permissions.EDIT)
def update_drink(identifier, current_session): def update_drink(identifier, current_session):
"""Modify Drink """Modify Drink
@ -425,7 +426,7 @@ def update_drink(identifier, current_session):
return jsonify(pricelist_controller.update_drink(identifier, data)) return jsonify(pricelist_controller.update_drink(identifier, data))
@PriceListPlugin.blueprint.route("/drinks/<int:identifier>", methods=["DELETE"]) blueprint.route("/drinks/<int:identifier>", methods=["DELETE"])
@login_required(permission=permissions.DELETE) @login_required(permission=permissions.DELETE)
def delete_drink(identifier, current_session): def delete_drink(identifier, current_session):
"""Delete Drink """Delete Drink
@ -443,7 +444,7 @@ def delete_drink(identifier, current_session):
return no_content() return no_content()
@PriceListPlugin.blueprint.route("/prices/<int:identifier>", methods=["DELETE"]) blueprint.route("/prices/<int:identifier>", methods=["DELETE"])
@login_required(permission=permissions.DELETE_PRICE) @login_required(permission=permissions.DELETE_PRICE)
def delete_price(identifier, current_session): def delete_price(identifier, current_session):
"""Delete Price """Delete Price
@ -461,7 +462,7 @@ def delete_price(identifier, current_session):
return no_content() return no_content()
@PriceListPlugin.blueprint.route("/volumes/<int:identifier>", methods=["DELETE"]) blueprint.route("/volumes/<int:identifier>", methods=["DELETE"])
@login_required(permission=permissions.DELETE_VOLUME) @login_required(permission=permissions.DELETE_VOLUME)
def delete_volume(identifier, current_session): def delete_volume(identifier, current_session):
"""Delete DrinkPriceVolume """Delete DrinkPriceVolume
@ -479,7 +480,7 @@ def delete_volume(identifier, current_session):
return no_content() return no_content()
@PriceListPlugin.blueprint.route("/ingredients/extraIngredients", methods=["GET"]) blueprint.route("/ingredients/extraIngredients", methods=["GET"])
@login_required() @login_required()
def get_extra_ingredients(current_session): def get_extra_ingredients(current_session):
"""Get ExtraIngredients """Get ExtraIngredients
@ -495,7 +496,7 @@ def get_extra_ingredients(current_session):
return jsonify(pricelist_controller.get_extra_ingredients()) return jsonify(pricelist_controller.get_extra_ingredients())
@PriceListPlugin.blueprint.route("/ingredients/<int:identifier>", methods=["DELETE"]) blueprint.route("/ingredients/<int:identifier>", methods=["DELETE"])
@login_required(permission=permissions.DELETE_INGREDIENTS_DRINK) @login_required(permission=permissions.DELETE_INGREDIENTS_DRINK)
def delete_ingredient(identifier, current_session): def delete_ingredient(identifier, current_session):
"""Delete Ingredient """Delete Ingredient
@ -513,7 +514,7 @@ def delete_ingredient(identifier, current_session):
return no_content() return no_content()
@PriceListPlugin.blueprint.route("/ingredients/extraIngredients", methods=["POST"]) blueprint.route("/ingredients/extraIngredients", methods=["POST"])
@login_required(permission=permissions.EDIT_INGREDIENTS) @login_required(permission=permissions.EDIT_INGREDIENTS)
def set_extra_ingredient(current_session): def set_extra_ingredient(current_session):
"""Create ExtraIngredient """Create ExtraIngredient
@ -532,7 +533,7 @@ def set_extra_ingredient(current_session):
return jsonify(pricelist_controller.set_extra_ingredient(data)) return jsonify(pricelist_controller.set_extra_ingredient(data))
@PriceListPlugin.blueprint.route("/ingredients/extraIngredients/<int:identifier>", methods=["PUT"]) blueprint.route("/ingredients/extraIngredients/<int:identifier>", methods=["PUT"])
@login_required(permission=permissions.EDIT_INGREDIENTS) @login_required(permission=permissions.EDIT_INGREDIENTS)
def update_extra_ingredient(identifier, current_session): def update_extra_ingredient(identifier, current_session):
"""Modify ExtraIngredient """Modify ExtraIngredient
@ -552,7 +553,7 @@ def update_extra_ingredient(identifier, current_session):
return jsonify(pricelist_controller.update_extra_ingredient(identifier, data)) return jsonify(pricelist_controller.update_extra_ingredient(identifier, data))
@PriceListPlugin.blueprint.route("/ingredients/extraIngredients/<int:identifier>", methods=["DELETE"]) blueprint.route("/ingredients/extraIngredients/<int:identifier>", methods=["DELETE"])
@login_required(permission=permissions.DELETE_INGREDIENTS) @login_required(permission=permissions.DELETE_INGREDIENTS)
def delete_extra_ingredient(identifier, current_session): def delete_extra_ingredient(identifier, current_session):
"""Delete ExtraIngredient """Delete ExtraIngredient
@ -570,7 +571,7 @@ def delete_extra_ingredient(identifier, current_session):
return no_content() return no_content()
@PriceListPlugin.blueprint.route("/settings/min_prices", methods=["GET"]) blueprint.route("/settings/min_prices", methods=["GET"])
@login_required() @login_required()
def get_pricelist_settings_min_prices(current_session): def get_pricelist_settings_min_prices(current_session):
"""Get MinPrices """Get MinPrices
@ -591,7 +592,7 @@ def get_pricelist_settings_min_prices(current_session):
return jsonify(min_prices) return jsonify(min_prices)
@PriceListPlugin.blueprint.route("/settings/min_prices", methods=["POST"]) blueprint.route("/settings/min_prices", methods=["POST"])
@login_required(permission=permissions.EDIT_MIN_PRICES) @login_required(permission=permissions.EDIT_MIN_PRICES)
def post_pricelist_settings_min_prices(current_session): def post_pricelist_settings_min_prices(current_session):
"""Create MinPrices """Create MinPrices
@ -614,7 +615,7 @@ def post_pricelist_settings_min_prices(current_session):
return no_content() return no_content()
@PriceListPlugin.blueprint.route("/users/<userid>/pricecalc_columns", methods=["GET", "PUT"]) blueprint.route("/users/<userid>/pricecalc_columns", methods=["GET", "PUT"])
@login_required() @login_required()
def get_columns(userid, current_session): def get_columns(userid, current_session):
"""Get pricecalc_columns of an user """Get pricecalc_columns of an user
@ -646,7 +647,7 @@ def get_columns(userid, current_session):
return no_content() return no_content()
@PriceListPlugin.blueprint.route("/users/<userid>/pricecalc_columns_order", methods=["GET", "PUT"]) blueprint.route("/users/<userid>/pricecalc_columns_order", methods=["GET", "PUT"])
@login_required() @login_required()
def get_columns_order(userid, current_session): def get_columns_order(userid, current_session):
"""Get pricecalc_columns_order of an user """Get pricecalc_columns_order of an user
@ -677,7 +678,7 @@ def get_columns_order(userid, current_session):
return no_content() return no_content()
@PriceListPlugin.blueprint.route("/users/<userid>/pricelist", methods=["GET", "PUT"]) blueprint.route("/users/<userid>/pricelist", methods=["GET", "PUT"])
@login_required() @login_required()
def get_priclist_setting(userid, current_session): def get_priclist_setting(userid, current_session):
"""Get pricelistsetting of an user """Get pricelistsetting of an user
@ -710,7 +711,7 @@ def get_priclist_setting(userid, current_session):
return no_content() return no_content()
@PriceListPlugin.blueprint.route("/drinks/<int:identifier>/picture", methods=["POST", "DELETE"]) blueprint.route("/drinks/<int:identifier>/picture", methods=["POST", "DELETE"])
@login_required(permission=permissions.EDIT) @login_required(permission=permissions.EDIT)
def set_picture(identifier, current_session): def set_picture(identifier, current_session):
"""Get, Create, Delete Drink Picture """Get, Create, Delete Drink Picture
@ -737,7 +738,7 @@ def set_picture(identifier, current_session):
raise BadRequest raise BadRequest
@PriceListPlugin.blueprint.route("/drinks/<int:identifier>/picture", methods=["GET"]) blueprint.route("/drinks/<int:identifier>/picture", methods=["GET"])
# @headers({"Cache-Control": "private, must-revalidate"}) # @headers({"Cache-Control": "private, must-revalidate"})
def _get_picture(identifier): def _get_picture(identifier):
"""Get Picture """Get Picture

View File

@ -16,8 +16,7 @@ from . import permissions
class RolesPlugin(Plugin): class RolesPlugin(Plugin):
name = "roles" blueprint = Blueprint("roles", __name__)
blueprint = Blueprint(name, __name__)
permissions = permissions.permissions permissions = permissions.permissions

View File

@ -44,11 +44,12 @@ class SchedulerPlugin(Plugin):
name = "scheduler" name = "scheduler"
blueprint = Blueprint(name, __name__) blueprint = Blueprint(name, __name__)
def __init__(self, config=None): def __init__(self, entry_point, config=None):
"""Constructor called by create_app """Constructor called by create_app
Args: Args:
config: Dict configuration containing the plugin section config: Dict configuration containing the plugin section
""" """
super().__init__(entry_point)
def __view_func(): def __view_func():
self.run_tasks() self.run_tasks()

View File

@ -18,8 +18,7 @@ from flaschengeist.utils.datetime import from_iso_format
class UsersPlugin(Plugin): class UsersPlugin(Plugin):
name = "users" blueprint = Blueprint("users", __name__)
blueprint = Blueprint(name, __name__)
permissions = permissions.permissions permissions = permissions.permissions

View File

@ -26,6 +26,8 @@ install_requires =
Pillow>=8.4.0 Pillow>=8.4.0
flask_cors flask_cors
flask_sqlalchemy>=2.5 flask_sqlalchemy>=2.5
# Importlib requirement can be dropped when python requirement is >= 3.10
importlib_metadata>=4.3
sqlalchemy>=1.4.26 sqlalchemy>=1.4.26
toml toml
werkzeug werkzeug