mirror of
https://github.com/usmannasir/cyberpanel.git
synced 2026-02-16 19:46:48 +01:00
Plugins: fix 404 - add plugin roots to sys.path before loading URLs
- pluginHolder/urls: insert /usr/local/CyberCP and source paths at top of module so __import__(plugin_name + '.urls') finds plugin packages (fixes No module named 'X.urls'). Register plugin routes before catch-all help route. - pluginHolder/views: add debug_loaded_plugins API and log full traceback on plugin import failure. panelAccess/emailMarketing settings/ routes added earlier; cspManager resilient to missing DB table. Author: master3395
This commit is contained in:
@@ -13,10 +13,17 @@ from django.urls import path, include
|
||||
import os
|
||||
import sys
|
||||
|
||||
# Ensure plugin roots are on sys.path first so __import__(plugin_name + '.urls') can find packages
|
||||
_INSTALLED_PLUGINS_PATH = '/usr/local/CyberCP'
|
||||
_PLUGIN_SOURCE_PATHS = ['/home/cyberpanel/plugins', '/home/cyberpanel-plugins']
|
||||
for _p in [_INSTALLED_PLUGINS_PATH] + _PLUGIN_SOURCE_PATHS:
|
||||
if _p and os.path.isdir(_p) and _p not in sys.path:
|
||||
sys.path.insert(0, _p)
|
||||
|
||||
from . import views
|
||||
|
||||
# Installed plugins live under this path (must match pluginInstaller and pluginHolder.views)
|
||||
INSTALLED_PLUGINS_PATH = '/usr/local/CyberCP'
|
||||
INSTALLED_PLUGINS_PATH = _INSTALLED_PLUGINS_PATH
|
||||
|
||||
# Source paths for plugins (same as pluginHolder.views PLUGIN_SOURCE_PATHS)
|
||||
# Checked when plugin is not under INSTALLED_PLUGINS_PATH so URLs still work
|
||||
@@ -95,22 +102,29 @@ urlpatterns = [
|
||||
path('api/store/upgrade/<str:plugin_name>/', views.upgrade_plugin, name='upgrade_plugin'),
|
||||
path('api/backups/<str:plugin_name>/', views.get_plugin_backups, name='get_plugin_backups'),
|
||||
path('api/revert/<str:plugin_name>/', views.revert_plugin, name='revert_plugin'),
|
||||
path('api/debug-plugins/', views.debug_loaded_plugins, name='debug_loaded_plugins'),
|
||||
]
|
||||
|
||||
# Include each installed plugin's URLs *before* the catch-all so /plugins/<name>/settings/ etc. match
|
||||
_loaded_plugins = []
|
||||
_failed_plugins = {}
|
||||
for _plugin_name, _path_parent in _get_installed_plugin_list():
|
||||
try:
|
||||
if _path_parent not in sys.path:
|
||||
sys.path.insert(0, _path_parent)
|
||||
__import__(_plugin_name + '.urls')
|
||||
urlpatterns.append(path(_plugin_name + '/', include(_plugin_name + '.urls')))
|
||||
except (ImportError, AttributeError) as e:
|
||||
_loaded_plugins.append(_plugin_name)
|
||||
except Exception as e:
|
||||
import traceback
|
||||
_failed_plugins[_plugin_name] = str(e)
|
||||
try:
|
||||
from plogical.CyberCPLogFileWriter import CyberCPLogFileWriter as _logging
|
||||
_logging.writeToFile(
|
||||
'pluginHolder.urls: Skipping plugin "%s" (urls not loadable): %s'
|
||||
% (_plugin_name, e)
|
||||
)
|
||||
_logging.writeToFile(traceback.format_exc())
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
@@ -1854,6 +1854,24 @@ def install_from_store(request, plugin_name):
|
||||
'error': str(e)
|
||||
}, status=500)
|
||||
|
||||
@csrf_exempt
|
||||
@require_http_methods(["GET"])
|
||||
def debug_loaded_plugins(request):
|
||||
"""Return which plugins have URL routes loaded and which failed (for diagnosing 404s)."""
|
||||
try:
|
||||
import pluginHolder.urls as urls_mod
|
||||
loaded = list(getattr(urls_mod, '_loaded_plugins', []))
|
||||
failed = dict(getattr(urls_mod, '_failed_plugins', {}))
|
||||
return JsonResponse({
|
||||
'success': True,
|
||||
'loaded': loaded,
|
||||
'failed': failed,
|
||||
'loaded_count': len(loaded),
|
||||
'failed_count': len(failed),
|
||||
}, json_dumps_params={'indent': 2})
|
||||
except Exception as e:
|
||||
return JsonResponse({'success': False, 'error': str(e)}, status=500)
|
||||
|
||||
def plugin_help(request, plugin_name):
|
||||
"""Plugin-specific help page - shows plugin information, version history, and help content"""
|
||||
mailUtilities.checkHome()
|
||||
|
||||
Reference in New Issue
Block a user