2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-07-01 03:00:54 +00:00

Plugin url fix (#9833)

* Handle error when loading plugin URLs

- Error separation between plugins
- Format plugin URLs outside the plugin code
- Add "catch-all" URL

* Attempt to resolve URL

* Accept 404 error

* Cleanup

* Tweak unit tests
This commit is contained in:
Oliver
2025-06-24 19:31:37 +10:00
committed by GitHub
parent 3c2997ece5
commit 5bb6db704b
3 changed files with 37 additions and 15 deletions

View File

@ -1,7 +1,6 @@
"""Plugin mixin class for UrlsMixin."""
from django.conf import settings
from django.urls import include, re_path
import structlog
@ -72,12 +71,8 @@ class UrlsMixin:
@property
def urlpatterns(self):
"""Urlpatterns for this plugin."""
if self.has_urls:
return re_path(
f'^{self.slug}/', include((self.urls, self.slug)), name=self.slug
)
return None
"""URL patterns for this plugin."""
return self.urls or None
@property
def has_urls(self):

View File

@ -113,13 +113,10 @@ class UrlsMixinTest(BaseMixinDefinition, TestCase):
target_pattern = re_path(
f'^{plg_name}/', include((self.mixin.urls, plg_name)), name=plg_name
)
self.assertEqual(
self.mixin.urlpatterns.reverse_dict, target_pattern.reverse_dict
)
# resolve the view
self.assertEqual(self.mixin.urlpatterns.resolve('/testpath').func(), 'ccc')
self.assertEqual(self.mixin.urlpatterns.reverse('test'), 'testpath')
self.assertEqual(target_pattern.resolve('/testpath').func(), 'ccc')
self.assertEqual(target_pattern.reverse('test'), 'testpath')
# no url
self.assertIsNone(self.mixin_nothing.urls)

View File

@ -2,8 +2,11 @@
from django.conf import settings
from django.urls import include, re_path
from django.urls.exceptions import Resolver404
from django.views.generic.base import RedirectView
from common.validators import get_global_setting
from InvenTree.exceptions import log_error
from plugin import PluginMixinEnum
PLUGIN_BASE = 'plugin' # Constant for links
@ -16,8 +19,35 @@ def get_plugin_urls():
urls = []
if get_global_setting('ENABLE_PLUGINS_URL', False) or settings.PLUGIN_TESTING_SETUP:
for plugin in registry.plugins.values():
if plugin.mixin_enabled(PluginMixinEnum.URLS):
urls.append(plugin.urlpatterns)
for plugin in registry.with_mixin(PluginMixinEnum.URLS):
try:
if plugin_urls := plugin.urlpatterns:
# Check if the plugin has a custom URL pattern
for url in plugin_urls:
# Attempt to resolve against the URL pattern as a validation check
try:
url.resolve('')
except Resolver404:
pass
urls.append(
re_path(
f'^{plugin.slug}/',
include((plugin_urls, plugin.slug)),
name=plugin.slug,
)
)
except Exception:
log_error('get_plugin_urls', plugin=plugin.slug)
continue
# Redirect anything else to the root index
urls.append(
re_path(
r'^.*$',
RedirectView.as_view(url=f'/{settings.FRONTEND_URL_BASE}', permanent=False),
name='index',
)
)
return re_path(f'^{PLUGIN_BASE}/', include((urls, 'plugin')))