diff --git a/.github/workflows/qc_checks.yaml b/.github/workflows/qc_checks.yaml index 598f518f27..b1067c4bbd 100644 --- a/.github/workflows/qc_checks.yaml +++ b/.github/workflows/qc_checks.yaml @@ -156,6 +156,7 @@ jobs: env: INVENTREE_DB_NAME: ./inventree.sqlite INVENTREE_DB_ENGINE: sqlite3 + INVENTREE_PLUGINS_ENABLED: true steps: - name: Checkout Code @@ -204,6 +205,7 @@ jobs: INVENTREE_DB_PORT: 5432 INVENTREE_DEBUG: info INVENTREE_CACHE_HOST: localhost + INVENTREE_PLUGINS_ENABLED: true services: postgres: @@ -259,6 +261,7 @@ jobs: INVENTREE_DB_HOST: '127.0.0.1' INVENTREE_DB_PORT: 3306 INVENTREE_DEBUG: info + INVENTREE_PLUGINS_ENABLED: true services: mysql: diff --git a/InvenTree/InvenTree/settings.py b/InvenTree/InvenTree/settings.py index 89e60a597e..2f80844bf1 100644 --- a/InvenTree/InvenTree/settings.py +++ b/InvenTree/InvenTree/settings.py @@ -52,8 +52,6 @@ with open(cfg_filename, 'r') as cfg: # We will place any config files in the same directory as the config file config_dir = os.path.dirname(cfg_filename) -PLUGIN_FILE = get_plugin_file() - # Default action is to run the system in Debug mode # SECURITY WARNING: don't run with debug turned on in production! DEBUG = _is_true(get_setting( @@ -873,6 +871,14 @@ MARKDOWNIFY_BLEACH = False # Maintenance mode MAINTENANCE_MODE_RETRY_AFTER = 60 +# Are plugins enabled? +PLUGINS_ENABLED = _is_true(get_setting( + 'INVENTREE_PLUGINS_ENABLED', + CONFIG.get('plugins_enabled', False), +)) + +PLUGIN_FILE = get_plugin_file() + # Plugin Directories (local plugins will be loaded from these directories) PLUGIN_DIRS = ['plugin.builtin', ] diff --git a/InvenTree/InvenTree/urls.py b/InvenTree/InvenTree/urls.py index b9fda0b1b7..a1b3a56bcd 100644 --- a/InvenTree/InvenTree/urls.py +++ b/InvenTree/InvenTree/urls.py @@ -52,7 +52,14 @@ from users.api import user_urls admin.site.site_header = "InvenTree Admin" -apipatterns = [ +apipatterns = [] + +if settings.PLUGINS_ENABLED: + apipatterns.append( + url(r'^plugin/', include(plugin_api_urls)) + ) + +apipatterns += [ url(r'^barcode/', include(barcode_api_urls)), url(r'^settings/', include(common_api_urls)), url(r'^part/', include(part_api_urls)), @@ -63,7 +70,6 @@ apipatterns = [ url(r'^order/', include(order_api_urls)), url(r'^label/', include(label_api_urls)), url(r'^report/', include(report_api_urls)), - url(r'^plugin/', include(plugin_api_urls)), # User URLs url(r'^user/', include(user_urls)), @@ -162,9 +168,6 @@ frontendpatterns = [ url(r'^search/', SearchView.as_view(), name='search'), url(r'^stats/', DatabaseStatsView.as_view(), name='stats'), - # plugin urls - get_plugin_urls(), # appends currently loaded plugin urls = None - # admin sites url(r'^admin/error_log/', include('error_report.urls')), url(r'^admin/shell/', include('django_admin_shell.urls')), @@ -183,6 +186,10 @@ frontendpatterns = [ url(r'^accounts/', include('allauth.urls')), # included urlpatterns ] +# Append custom plugin URLs (if plugin support is enabled) +if settings.PLUGINS_ENABLED: + frontendpatterns.append(get_plugin_urls()) + urlpatterns = [ url('', include(frontendpatterns)), url('', include(backendpatterns)), diff --git a/InvenTree/config_template.yaml b/InvenTree/config_template.yaml index d8f780bb36..b14c1224ce 100644 --- a/InvenTree/config_template.yaml +++ b/InvenTree/config_template.yaml @@ -102,6 +102,10 @@ debug: True # and only if InvenTree is accessed from a local IP (127.0.0.1) debug_toolbar: False +# Set this variable to True to enable InvenTree Plugins +# Alternatively, use the environment variable INVENTREE_PLUGINS_ENABLED +plugins_enabled: False + # Configure the system logging level # Use environment variable INVENTREE_LOG_LEVEL # Options: DEBUG / INFO / WARNING / ERROR / CRITICAL diff --git a/InvenTree/part/templatetags/inventree_extras.py b/InvenTree/part/templatetags/inventree_extras.py index 9c0b0e691f..e2faedfd9e 100644 --- a/InvenTree/part/templatetags/inventree_extras.py +++ b/InvenTree/part/templatetags/inventree_extras.py @@ -7,6 +7,7 @@ over and above the built-in Django tags. import os import sys + from django.utils.html import format_html from django.utils.translation import ugettext_lazy as _ @@ -16,6 +17,7 @@ from django import template from django.urls import reverse from django.utils.safestring import mark_safe from django.templatetags.static import StaticNode + from InvenTree import version, settings import InvenTree.helpers @@ -107,6 +109,13 @@ def inventree_docker_mode(*args, **kwargs): return djangosettings.DOCKER +@register.simple_tag() +def plugins_enabled(*args, **kwargs): + """ Return True if plugins are enabled for the server instance """ + + return djangosettings.PLUGINS_ENABLED + + @register.simple_tag() def inventree_db_engine(*args, **kwargs): """ Return the InvenTree database backend e.g. 'postgresql' """ diff --git a/InvenTree/plugin/apps.py b/InvenTree/plugin/apps.py index cca9dee91c..47b5e9f024 100644 --- a/InvenTree/plugin/apps.py +++ b/InvenTree/plugin/apps.py @@ -1,21 +1,32 @@ # -*- coding: utf-8 -*- from __future__ import unicode_literals +import logging + from django.apps import AppConfig +from django.conf import settings + from maintenance_mode.core import set_maintenance_mode from plugin import plugin_registry +logger = logging.getLogger('inventree') + + class PluginAppConfig(AppConfig): name = 'plugin' def ready(self): - if not plugin_registry.is_loading: - # this is the first startup - plugin_registry.collect_plugins() - plugin_registry.load_plugins() - # drop out of maintenance - # makes sure we did not have an error in reloading and maintenance is still active - set_maintenance_mode(False) + if settings.PLUGINS_ENABLED: + logger.info('Loading InvenTree plugins') + + if not plugin_registry.is_loading: + # this is the first startup + plugin_registry.collect_plugins() + plugin_registry.load_plugins() + + # drop out of maintenance + # makes sure we did not have an error in reloading and maintenance is still active + set_maintenance_mode(False) diff --git a/InvenTree/plugin/events.py b/InvenTree/plugin/events.py index 21c68d0a7c..b714d123b9 100644 --- a/InvenTree/plugin/events.py +++ b/InvenTree/plugin/events.py @@ -31,6 +31,10 @@ def trigger_event(event, *args, **kwargs): and the worker will respond to it later on. """ + if not settings.PLUGINS_ENABLED: + # Do nothing if plugins are not enabled + return + if not canAppAccessDatabase(): logger.debug(f"Ignoring triggered event '{event}' - database not ready") return diff --git a/InvenTree/plugin/registry.py b/InvenTree/plugin/registry.py index 8d04620120..448365b338 100644 --- a/InvenTree/plugin/registry.py +++ b/InvenTree/plugin/registry.py @@ -66,6 +66,10 @@ class PluginsRegistry: Load and activate all IntegrationPlugins """ + if not settings.PLUGINS_ENABLED: + # Plugins not enabled, do nothing + return + from plugin.helpers import log_plugin_error logger.info('Start loading plugins') @@ -75,15 +79,16 @@ class PluginsRegistry: if not _maintenance: set_maintenance_mode(True) - registered_sucessfull = False + registered_successful = False blocked_plugin = None retry_counter = settings.PLUGIN_RETRY - while not registered_sucessfull: + + while not registered_successful: try: # We are using the db so for migrations etc we need to try this block self._init_plugins(blocked_plugin) self._activate_plugins() - registered_sucessfull = True + registered_successful = True except (OperationalError, ProgrammingError): # Exception if the database has not been migrated yet logger.info('Database not accessible while loading plugins') @@ -122,6 +127,10 @@ class PluginsRegistry: Unload and deactivate all IntegrationPlugins """ + if not settings.PLUGINS_ENABLED: + # Plugins not enabled, do nothing + return + logger.info('Start unloading plugins') # Set maintanace mode @@ -162,6 +171,10 @@ class PluginsRegistry: Collect integration plugins from all possible ways of loading """ + if not settings.PLUGINS_ENABLED: + # Plugins not enabled, do nothing + return + self.plugin_modules = [] # clear # Collect plugins from paths diff --git a/InvenTree/templates/InvenTree/settings/settings.html b/InvenTree/templates/InvenTree/settings/settings.html index 9b3d2d21de..5fcd18644f 100644 --- a/InvenTree/templates/InvenTree/settings/settings.html +++ b/InvenTree/templates/InvenTree/settings/settings.html @@ -39,14 +39,17 @@ {% include "InvenTree/settings/build.html" %} {% include "InvenTree/settings/po.html" %} {% include "InvenTree/settings/so.html" %} -{% include "InvenTree/settings/plugin.html" %} +{% plugins_enabled as plug %} +{% if plug %} +{% include "InvenTree/settings/plugin.html" %} {% plugin_list as pl_list %} {% for plugin_key, plugin in pl_list.items %} {% if plugin.registered_mixins %} {% include "InvenTree/settings/plugin_settings.html" %} {% endif %} {% endfor %} +{% endif %} {% endif %} @@ -333,9 +336,12 @@ $("#import-part").click(function() { launchModalForm("{% url 'api-part-import' %}?reset", {}); }); +{% plugins_enabled as plug %} +{% if plug %} $("#install-plugin").click(function() { installPlugin(); }); +{% endif %} enableSidebar('settings'); diff --git a/InvenTree/templates/InvenTree/settings/sidebar.html b/InvenTree/templates/InvenTree/settings/sidebar.html index 24f62f1e1c..b17b226f28 100644 --- a/InvenTree/templates/InvenTree/settings/sidebar.html +++ b/InvenTree/templates/InvenTree/settings/sidebar.html @@ -47,15 +47,17 @@ {% trans "Sales Orders" as text %} {% include "sidebar_item.html" with label='sales-order' text=text icon="fa-truck" %} +{% plugins_enabled as plug %} +{% if plug %} {% include "sidebar_header.html" with text="Plugin Settings" %} - {% include "sidebar_item.html" with label='plugin' text="Plugins" icon="fa-plug" %} {% plugin_list as pl_list %} {% for plugin_key, plugin in pl_list.items %} - {% if plugin.registered_mixins %} - {% include "sidebar_item.html" with label='plugin-'|add:plugin_key text=plugin.human_name %} - {% endif %} +{% if plugin.registered_mixins %} +{% include "sidebar_item.html" with label='plugin-'|add:plugin_key text=plugin.human_name %} +{% endif %} {% endfor %} +{% endif %} {% endif %} \ No newline at end of file diff --git a/InvenTree/templates/stats.html b/InvenTree/templates/stats.html index cf3d225cd2..7a22f88023 100644 --- a/InvenTree/templates/stats.html +++ b/InvenTree/templates/stats.html @@ -34,6 +34,18 @@