Skip to content

Commit

Permalink
Merge branch 'plugin-system-bugfixes' into 'main'
Browse files Browse the repository at this point in the history
Plugin system bugfixes

See merge request reportcreator/reportcreator!741
  • Loading branch information
MWedl committed Oct 30, 2024
2 parents fdd9a8c + 7eeb18f commit 5de7370
Show file tree
Hide file tree
Showing 9 changed files with 42 additions and 21 deletions.
5 changes: 2 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -210,10 +210,9 @@ FROM --platform=$BUILDPLATFORM api-test AS api-statics
# Do not post-process nuxt files, because they already have hash names (and django failes to post-process them)
RUN python3 manage.py collectstatic --no-input --clear
COPY --from=frontend /app/frontend/dist/index.html /app/frontend/dist/static/ /app/api/frontend/static/
RUN mv /app/api/frontend/static/index.html /app/api/frontend/index.html \
&& python3 manage.py collectstatic --no-input --no-post-process

COPY --from=plugin-builder --chown=user:user /app/plugins/ /app/plugins/
RUN mv /app/api/frontend/static/index.html /app/api/frontend/index.html \
&& ENABLED_PLUGINS='*' python3 manage.py collectstatic --no-input --no-post-process


FROM api-test AS api
Expand Down
30 changes: 20 additions & 10 deletions api/src/reportcreator_api/conf/plugins.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ def remove_entry(path: Path):
path.unlink(missing_ok=True)


def create_plugin_module_dir(dst: Path, srcs: list[Path]):
def collect_plugins(dst: Path, srcs: list[Path]):
# Collect plugins from all plugin directories
all_module_dirs = []
for plugins_dir in srcs:
Expand Down Expand Up @@ -166,10 +166,17 @@ def create_plugin_module_dir(dst: Path, srcs: list[Path]):
def load_plugins(plugin_dirs: list[Path], enabled_plugins: list[str]):
dst = Path(__file__).parent.parent.parent / 'sysreptor_plugins'
# Collect all plugin modules in dst directory
create_plugin_module_dir(
dst=dst,
srcs=plugin_dirs,
)
try:
collect_plugins(
dst=dst,
srcs=plugin_dirs,
)
except Exception:
logging.exception('Error while collecting plugins')

if not dst.is_dir() or not (dst / '__init__.py').is_file():
logging.warning(f'Cannot load plugins: Plugin directory "{dst}" not found')
return []

# Load sysreptor_plugins module from dst directory
load_module_from_dir('sysreptor_plugins', dst / '__init__.py')
Expand All @@ -196,7 +203,8 @@ def load_plugins(plugin_dirs: list[Path], enabled_plugins: list[str]):

plugin_config_class.name = module_name
if any(c.plugin_id == plugin_config_class.plugin_id for c in available_plugin_configs):
raise ImproperlyConfigured(f'Duplicate plugin_id: {plugin_config_class.plugin_id}')
logging.warning(f'Duplicate plugin_id: {plugin_config_class.plugin_id}')
continue

available_plugin_configs.append(plugin_config_class)

Expand All @@ -206,15 +214,17 @@ def load_plugins(plugin_dirs: list[Path], enabled_plugins: list[str]):
for plugin_config_class in available_plugin_configs:
plugin_id = plugin_config_class.plugin_id
plugin_name = plugin_config_class.name.split('.')[-1]
if enabled_plugin_id in [plugin_id, plugin_name]:
if enabled_plugin_id in [plugin_id, plugin_name, '*']:
# Add to installed_apps
app_class = plugin_config_class.__module__ + '.' + plugin_config_class.__name__
app_label = plugin_config_class.label
if app_class not in installed_apps:
installed_apps.append(app_class)
logging.info(f'Enabling plugin {plugin_name} ({plugin_id=}, {app_label=}, {app_class=})', file=sys.stderr) # noqa: T201
break
logging.info(f'Enabling plugin {plugin_name} ({plugin_id=}, {app_label=}, {app_class=})')
if enabled_plugin_id != '*':
break
else:
logging.warning(f'Plugin "{enabled_plugin_id}" not found in plugins')
if enabled_plugin_id != '*':
logging.warning(f'Plugin "{enabled_plugin_id}" not found in plugins')

return installed_apps
2 changes: 1 addition & 1 deletion api/src/reportcreator_api/conf/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [BASE_DIR / 'frontend'],
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
Expand Down
5 changes: 3 additions & 2 deletions api/src/reportcreator_api/conf/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
from django.contrib import admin
from django.http import HttpResponse
from django.urls import include, path, re_path
from django.views.generic.base import RedirectView, TemplateView
from django.views.generic.base import RedirectView
from django.views.static import serve
from drf_spectacular.views import SpectacularAPIView, SpectacularSwaggerSplitView
from rest_framework.routers import DefaultRouter
from rest_framework_nested.routers import NestedSimpleRouter
Expand Down Expand Up @@ -167,7 +168,7 @@
path('favicon.ico', RedirectView.as_view(url='/static/favicon.ico', permanent=True)),

# Fallback URL for SPA
re_path(r'^(?!(api|admin)).*/?$', TemplateView.as_view(template_name='index.html')),
re_path(r'^(?!(api|admin|static)).*/?$', lambda request, *args, **kwargs: serve(request, path='index.html', document_root=settings.BASE_DIR / 'frontend')),
]


Expand Down
5 changes: 5 additions & 0 deletions api/start.sh
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
#!/bin/bash
# Add custom CA certificates
if [[ -n "$CA_CERTIFICATES" ]]; then
echo "${CA_CERTIFICATES}" >> /usr/local/share/ca-certificates/custom-user-cert.crt
update-ca-certificates
fi

# Run DB migrations
python3 manage.py migrate
# Collect static files (of custom plugins)
python3 manage.py collectstatic --noinput --no-post-process
# Start web application
gunicorn --bind=:8000 \
--worker-class=uvicorn.workers.UvicornWorker \
--workers=${SERVER_WORKERS} \
Expand Down
1 change: 1 addition & 0 deletions deploy/sysreptor/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ services:
restart: unless-stopped
app:
image: 'syslifters/sysreptor:${SYSREPTOR_VERSION:-latest}'
# build: ../../
container_name: 'sysreptor-app'
init: true
volumes:
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/plugins/pluginLoader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export function usePluginHelpers(pluginHelperOptions: { pluginConfig: PluginConf
});
}
let iframeSrc = attrs.src;
if (!iframeSrc.startsWith('/')) {
if (!iframeSrc.startsWith('/') && !iframeSrc.startsWith('https://') && !iframeSrc.startsWith('http://')) {
// Convert relative src to absolute
if (iframeSrc.startsWith('api/')) {
iframeSrc = `/api/plugins/${pluginHelperOptions.pluginConfig.id}/${iframeSrc}`;
Expand Down
2 changes: 1 addition & 1 deletion plugins/build.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/bin/sh
#!/bin/bash
set -e # exit on error

for plugin in ./*; do
Expand Down
11 changes: 8 additions & 3 deletions plugins/cyberchef/build.sh
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
#!/bin/sh
#!/bin/bash

if [ ! -d static/cyberchef ]; then
set -e

CYBERCHEF_VERSION="v10.19.2"

if [ ! -f "./static/cyberchef/CyberChef_${CYBERCHEF_VERSION}.html" ]; then
echo "Downloading CyberChef"
rm -rf static/cyberchef/*
mkdir -p static/cyberchef
curl https://github.com/gchq/CyberChef/releases/download/v10.19.2/CyberChef_v10.19.2.zip -o cyberchef.zip
curl -L "https://github.com/gchq/CyberChef/releases/download/v10.19.2/CyberChef_${CYBERCHEF_VERSION}.zip" -o cyberchef.zip
unzip cyberchef.zip -d static/cyberchef
rm cyberchef.zip
else
Expand Down

0 comments on commit 5de7370

Please sign in to comment.