Compare commits

...

6 Commits

6 changed files with 87 additions and 19 deletions

View File

@ -71,7 +71,7 @@ def __load_plugins(app):
app.config["FG_AUTH_BACKEND"] = plugin app.config["FG_AUTH_BACKEND"] = plugin
else: else:
logger.info(f"Using plugin: {entry_point.name}") logger.info(f"Using plugin: {entry_point.name}")
app.config["FG_PLUGINS"][entry_point.name] = plugin app.config["FG_PLUGINS"][entry_point.name] = plugin
else: else:
logger.debug(f"Skip disabled plugin {entry_point.name}") logger.debug(f"Skip disabled plugin {entry_point.name}")
if "FG_AUTH_BACKEND" not in app.config: if "FG_AUTH_BACKEND" not in app.config:

View File

@ -51,7 +51,7 @@ def configure_logger(cli=False):
update_dict(logger_config, config.get("LOGGING")) update_dict(logger_config, config.get("LOGGING"))
# Check for shortcuts # Check for shortcuts
if "level" in config["LOGGING"] or isinstance(cli, int): if "level" in config["LOGGING"] or isinstance(cli, int):
level = cli if isinstance(cli, int) else config["LOGGING"]["level"] level = cli if cli and isinstance(cli, int) else config["LOGGING"]["level"]
logger_config["loggers"]["flaschengeist"] = {"level": level} logger_config["loggers"]["flaschengeist"] = {"level": level}
logger_config["handlers"]["console"]["level"] = level logger_config["handlers"]["console"]["level"] = level
logger_config["handlers"]["file"]["level"] = level logger_config["handlers"]["file"]["level"] = level

View File

@ -1,9 +1,10 @@
from typing import Union
from sqlalchemy.exc import IntegrityError from sqlalchemy.exc import IntegrityError
from werkzeug.exceptions import BadRequest, Conflict, NotFound from werkzeug.exceptions import BadRequest, Conflict, NotFound
from flaschengeist import logger
from flaschengeist.models.user import Role, Permission from flaschengeist.models.user import Role, Permission
from flaschengeist.database import db, case_sensitive from flaschengeist.database import db, case_sensitive
from flaschengeist import logger
from flaschengeist.utils.hook import Hook from flaschengeist.utils.hook import Hook
@ -11,7 +12,15 @@ def get_all():
return Role.query.all() return Role.query.all()
def get(role_name) -> Role: def get(role_name: Union[int, str]) -> Role:
"""Get role by ID or name
Args:
role_name: Name or ID of the role
Returns:
Matching role
Raises:
NotFound
"""
if type(role_name) is int: if type(role_name) is int:
role = Role.query.get(role_name) role = Role.query.get(role_name)
else: else:
@ -37,11 +46,10 @@ def update_role(role, new_name):
def set_permissions(role, permissions): def set_permissions(role, permissions):
for name in permissions: perms = Permission.query.filter(Permission.name.in_(permissions)).all()
p = Permission.query.filter(Permission.name.in_(permissions)).all() if len(perms) < len(permissions):
if not p or len(p) < len(permissions): raise BadRequest("Invalid permission name")
raise BadRequest("Invalid permission name >{}<".format(name)) role.permissions = list(perms)
role.permissions = list(p)
db.session.commit() db.session.commit()

View File

@ -119,3 +119,5 @@ If this was not you, please contact the support.
# enabled = true # enabled = true
# Enable a default limit, will be set if no other limit is set # Enable a default limit, will be set if no other limit is set
# limit = -10.00 # limit = -10.00
# Uncomment to allow active services to debit other users (requires events plugin)
# allow_service_debit = true

View File

@ -3,29 +3,79 @@
Extends users plugin with balance functions Extends users plugin with balance functions
""" """
from werkzeug.local import LocalProxy
from flask import Blueprint, current_app from flask import Blueprint, current_app
from werkzeug.local import LocalProxy
from werkzeug.exceptions import NotFound
from flaschengeist import logger from flaschengeist import logger
from flaschengeist.plugins import Plugin, before_update_user from flaschengeist.plugins import Plugin, plugins_loaded, before_update_user
from flaschengeist.plugins.scheduler import add_scheduled
from . import permissions, models from . import permissions, models
def service_debit():
from flaschengeist.database import db
from flaschengeist.models import UtcDateTime
from flaschengeist.models.user import User
from flaschengeist.controller import roleController
from flaschengeist_events.models import Service, Job
role = BalancePlugin.plugin.get_setting("service_role", default=None)
if role is None:
try:
role = roleController.get("__has_service")
except NotFound:
role = roleController.create_role("__has_service", [permissions.DEBIT])
BalancePlugin.plugin.set_setting("service_role", role.id)
else:
role = roleController.get(role)
active_services = (
User.query.join(Service, User.id_ == Service._user_id)
.join(Job, Service.job_)
.filter(Job.start <= UtcDateTime.current_utc(), Job.end.is_(None) | (Job.end >= UtcDateTime.current_utc()))
.distinct(User.id_)
.all()
)
previous_services = BalancePlugin.plugin.get_setting("service_debit", default=[])
logger.debug(f"Found {len(active_services)} users doing their service.")
if len(previous_services) > 0:
previous_services = User.query.filter(User.userid.in_(previous_services)).all()
# Remove not active users
for user in [u for u in previous_services if u not in active_services]:
user.roles_ = [r for r in user.roles_ if r.id != role.id]
# Add active
for user in [u for u in active_services if u not in previous_services]:
if role not in user.roles_:
user.roles_.append(role)
db.session.commit()
BalancePlugin.plugin.set_setting("service_debit", [u.userid for u in active_services])
class BalancePlugin(Plugin): class BalancePlugin(Plugin):
name = "balance" name = "balance"
id = "dev.flaschengeist.balance" id = "dev.flaschengeist.balance"
blueprint = Blueprint(name, __name__) blueprint = Blueprint(name, __name__)
permissions = permissions.permissions permissions = permissions.permissions
plugin = 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, config):
super(BalancePlugin, self).__init__(config) super(BalancePlugin, self).__init__(config)
from . import routes, balance_controller from . import routes
@plugins_loaded
def post_loaded(*args, **kwargs):
if config.get("allow_service_debit", False) and "events" in current_app.config["FG_PLUGINS"]:
add_scheduled(f"{id}.service_debit", service_debit, minutes=1)
@before_update_user @before_update_user
def set_default_limit(user): def set_default_limit(user):
from . import balance_controller
try: try:
limit = self.get_setting("limit") limit = self.get_setting("limit")
logger.debug("Setting default limit of {} to user {}".format(limit, user.userid)) logger.debug("Setting default limit of {} to user {}".format(limit, user.userid))

View File

@ -17,19 +17,25 @@ class __Task:
_scheduled_tasks: dict[__Task] = dict() _scheduled_tasks: dict[__Task] = dict()
def add_scheduled(id: str, function, replace=False, **kwargs):
if id not in _scheduled_tasks or replace:
_scheduled_tasks[id] = __Task(function, **kwargs)
logger.info(f"Registered task: {id}")
else:
logger.debug(f"Skipping already registered task: {id}")
def scheduled(id: str, replace=False, **kwargs): def scheduled(id: str, replace=False, **kwargs):
""" """
kwargs: days, hours, minutes kwargs: days, hours, minutes
""" """
def real_decorator(function): def real_decorator(function):
if id not in _scheduled_tasks or replace: add_scheduled(id, function, replace, **kwargs)
logger.info(f"Registered task: {id}")
_scheduled_tasks[id] = __Task(function, **kwargs)
else:
logger.debug(f"Skipping already registered task: {id}")
return function return function
if not isinstance(id, str):
raise TypeError
return real_decorator return real_decorator
@ -75,9 +81,11 @@ class SchedulerPlugin(Plugin):
) )
task.function() task.function()
changed = True changed = True
else:
logger.debug(f"Skip task {id}, is scheduled for {last_run + task.interval}")
if changed: if changed:
# Remove not registered tasks # Remove not registered tasks
for id in status.keys(): for id in status.keys():
if id not in _scheduled_tasks.keys(): if id not in _scheduled_tasks.keys():
del status[id] del status[id]
self.set_setting("status", status) self.set_setting("status", status)