From 3bd64e90983fe06a90b012cc0e56eca830171a4e Mon Sep 17 00:00:00 2001 From: Matthias Mair Date: Tue, 18 Oct 2022 00:55:56 +0200 Subject: [PATCH] Raise error if version fails (#3792) * add comment where feature should be * add triggermethod for superusers * Add plugin version warning * switch to simple error logging * switch import mechanism * move import down * reintroduce db notifications * adding mising import * add db entry * Only log to DB if plugin was regsitered * fix merge * remove db logging --- InvenTree/common/notifications.py | 24 +++++++++++++++++++++++- InvenTree/plugin/registry.py | 18 +++++++++++++++--- 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/InvenTree/common/notifications.py b/InvenTree/common/notifications.py index 6122f181c7..1d4e7ae47b 100644 --- a/InvenTree/common/notifications.py +++ b/InvenTree/common/notifications.py @@ -12,7 +12,7 @@ import InvenTree.helpers from common.models import NotificationEntry, NotificationMessage from InvenTree.ready import isImportingData from plugin import registry -from plugin.models import NotificationUserSetting +from plugin.models import NotificationUserSetting, PluginConfig from users.models import Owner logger = logging.getLogger('inventree') @@ -397,6 +397,28 @@ def trigger_notification(obj, category=None, obj_ref='pk', **kwargs): logger.info(f"No possible users for notification '{category}'") +def trigger_superuser_notification(plugin: PluginConfig, msg: str): + """Trigger a notification to all superusers. + + Args: + plugin (PluginConfig): Plugin that is raising the notification + msg (str): Detailed message that should be attached + """ + users = get_user_model().objects.filter(is_superuser=True) + + trigger_notification( + plugin, + 'inventree.plugin', + context={ + 'error': plugin, + 'name': _('Error raised by plugin'), + 'message': msg, + }, + targets=users, + delivery_methods=set([UIMessageNotification]), + ) + + def deliver_notification(cls: NotificationMethod, obj, category: str, targets, context: dict): """Send notification with the provided class. diff --git a/InvenTree/plugin/registry.py b/InvenTree/plugin/registry.py index 09a0516c4f..95037ebec0 100644 --- a/InvenTree/plugin/registry.py +++ b/InvenTree/plugin/registry.py @@ -19,6 +19,7 @@ from django.contrib import admin from django.db.utils import IntegrityError, OperationalError, ProgrammingError from django.urls import clear_url_caches, include, re_path from django.utils.text import slugify +from django.utils.translation import gettext_lazy as _ from maintenance_mode.core import (get_maintenance_mode, maintenance_mode_on, set_maintenance_mode) @@ -364,6 +365,8 @@ class PluginsRegistry: Raises: error: IntegrationPluginError """ + # Imports need to be in this level to prevent early db model imports + from InvenTree import version from plugin.models import PluginConfig def safe_reference(plugin, key: str, active: bool = True): @@ -387,7 +390,7 @@ class PluginsRegistry: plg_key = slugify(plg.SLUG if getattr(plg, 'SLUG', None) else plg_name) # keys are slugs! try: - plg_db, _ = PluginConfig.objects.get_or_create(key=plg_key, name=plg_name) + plg_db, _created = PluginConfig.objects.get_or_create(key=plg_key, name=plg_name) except (OperationalError, ProgrammingError) as error: # Exception if the database has not been migrated yet - check if test are running - raise if not if not settings.PLUGIN_TESTING: @@ -421,7 +424,16 @@ class PluginsRegistry: # Run version check for plugin if (plg_i.MIN_VERSION or plg_i.MAX_VERSION) and not plg_i.check_version(): + # Disable plugin safe_reference(plugin=plg_i, key=plg_key, active=False) + + _msg = _(f'Plugin `{plg_name}` is not compatible with the current InvenTree version {version.inventreeVersion()}!') + if plg_i.MIN_VERSION: + _msg += _(f'Plugin requires at least version {plg_i.MIN_VERSION}') + if plg_i.MAX_VERSION: + _msg += _(f'Plugin requires at most version {plg_i.MAX_VERSION}') + # Log to error stack + log_error(_msg, reference='init') else: safe_reference(plugin=plg_i, key=plg_key) else: # pragma: no cover @@ -482,7 +494,7 @@ class PluginsRegistry: if settings.PLUGIN_TESTING or InvenTreeSetting.get_setting('ENABLE_PLUGINS_SCHEDULE'): - for _, plugin in plugins: + for _key, plugin in plugins: if plugin.mixin_enabled('schedule'): config = plugin.plugin_config() @@ -537,7 +549,7 @@ class PluginsRegistry: apps_changed = False # add them to the INSTALLED_APPS - for _, plugin in plugins: + for _key, plugin in plugins: if plugin.mixin_enabled('app'): plugin_path = self._get_plugin_path(plugin) if plugin_path not in settings.INSTALLED_APPS: