From d1e741ebfd5de841769496f8bd6a7511147ce234 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniele=20Vigan=C3=B2?= Date: Thu, 15 Jan 2026 12:42:12 +0100 Subject: [PATCH] Remove the need of inline scripting --- ram/portal/admin.py | 3 +- ...e_siteconfiguration_extra_head_and_more.py | 34 +++++++++++++++++++ ram/portal/models.py | 9 ++++- ram/portal/templates/base.html | 3 +- ram/portal/urls.py | 2 ++ ram/portal/views.py | 12 ++++++- ram/ram/settings.py | 1 - 7 files changed, 59 insertions(+), 5 deletions(-) create mode 100644 ram/portal/migrations/0022_rename_siteconfiguration_extra_head_and_more.py diff --git a/ram/portal/admin.py b/ram/portal/admin.py index 8bb4b99..02a2bc7 100644 --- a/ram/portal/admin.py +++ b/ram/portal/admin.py @@ -35,7 +35,8 @@ class SiteConfigurationAdmin(SingletonModelAdmin): "fields": ( "show_version", "use_cdn", - "extra_head", + "extra_html", + "extra_js", "rest_api", "version", ), diff --git a/ram/portal/migrations/0022_rename_siteconfiguration_extra_head_and_more.py b/ram/portal/migrations/0022_rename_siteconfiguration_extra_head_and_more.py new file mode 100644 index 0000000..dfceed8 --- /dev/null +++ b/ram/portal/migrations/0022_rename_siteconfiguration_extra_head_and_more.py @@ -0,0 +1,34 @@ +# Generated by Django 6.0.1 on 2026-01-15 11:32 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("portal", "0021_siteconfiguration_featured_items_ordering_and_more"), + ] + + operations = [ + migrations.RenameField( + model_name="siteconfiguration", + old_name="extra_head", + new_name="extra_html", + ), + migrations.AlterField( + model_name="siteconfiguration", + name="extra_html", + field=models.TextField( + blank=True, + help_text="Extra HTML to be dinamically loaded into the site.", + ), + ), + migrations.AddField( + model_name="siteconfiguration", + name="extra_js", + field=models.TextField( + blank=True, + help_text="Extra JS to be dinamically loaded into the site." + ), + ), + ] diff --git a/ram/portal/models.py b/ram/portal/models.py index b3fe41e..b295d1b 100644 --- a/ram/portal/models.py +++ b/ram/portal/models.py @@ -39,7 +39,14 @@ class SiteConfiguration(SingletonModel): disclaimer = tinymce.HTMLField(blank=True) show_version = models.BooleanField(default=True) use_cdn = models.BooleanField(default=True) - extra_head = models.TextField(blank=True) + extra_html = models.TextField( + blank=True, + help_text="Extra HTML to be dinamically loaded into the site.", + ) + extra_js = models.TextField( + blank=True, + help_text="Extra JS to be dinamically loaded into the site.", + ) class Meta: verbose_name = "Site Configuration" diff --git a/ram/portal/templates/base.html b/ram/portal/templates/base.html index b3a78f7..f60c184 100644 --- a/ram/portal/templates/base.html +++ b/ram/portal/templates/base.html @@ -25,7 +25,8 @@ {% block extra_head %} - {{ site_conf.extra_head | safe }} + {% if site_conf.extra_html %}{{ site_conf.extra_html | safe }}{% endif %} + {% if site_conf.extra_js %}{% endif %} {% endblock %} diff --git a/ram/portal/urls.py b/ram/portal/urls.py index 36f4654..6bebeda 100644 --- a/ram/portal/urls.py +++ b/ram/portal/urls.py @@ -1,6 +1,7 @@ from django.urls import path from portal.views import ( + RenderExtraJS, GetHome, GetRoster, GetObjectsFiltered, @@ -24,6 +25,7 @@ from portal.views import ( urlpatterns = [ path("", GetHome.as_view(), name="index"), + path("extra.js", RenderExtraJS.as_view(), name="extra_js"), path("roster", GetRoster.as_view(), name="roster"), path("roster/page/", GetRoster.as_view(), name="roster"), path( diff --git a/ram/portal/views.py b/ram/portal/views.py index c015165..3d167f0 100644 --- a/ram/portal/views.py +++ b/ram/portal/views.py @@ -7,7 +7,7 @@ from urllib.parse import unquote from django.conf import settings from django.views import View from django.urls import Resolver404 -from django.http import Http404, HttpResponseBadRequest +from django.http import Http404, HttpResponse, HttpResponseBadRequest from django.db.utils import OperationalError, ProgrammingError from django.db.models import F, Q, Count from django.db.models.functions import Lower @@ -78,6 +78,16 @@ class Render404(View): ) +class RenderExtraJS(View): + def get(self, request): + try: + extra_js = get_site_conf().extra_js + except (OperationalError, ProgrammingError): + extra_js = "" + + return HttpResponse(extra_js, content_type="application/javascript") + + class GetData(View): title = None template = "pagination.html" diff --git a/ram/ram/settings.py b/ram/ram/settings.py index c717e37..9549323 100644 --- a/ram/ram/settings.py +++ b/ram/ram/settings.py @@ -116,7 +116,6 @@ SECURE_CSP = { "img-src": ["data:", "*"], "script-src": [ CSP.SELF, - CSP.UNSAFE_INLINE, "https://www.googletagmanager.com/", ] + CDN_WHITELIST_CSP,