From d828ba0bc60cc62f0b8274986610c78457f7d39d Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Mon, 20 Nov 2023 09:56:51 -0800 Subject: [PATCH] Give admins option to test if a theme loads correctly If a theme is uploaded incorrectly or has errors in it, users can still select the theme but it will cause a 500 error on every page, making the app unusable and also making it impossible for them to switch to a functional theme. A better fix would be to fail gracefully, but in lieu of that, this will at least let admins confirm if a theme is broken safely. --- bookwyrm/migrations/0187_theme_loads.py | 18 +++++++++++ bookwyrm/models/site.py | 1 + bookwyrm/templates/settings/themes.html | 43 +++++++++++++++++++++++++ bookwyrm/urls.py | 5 +++ bookwyrm/views/__init__.py | 2 +- bookwyrm/views/admin/themes.py | 20 ++++++++++++ 6 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 bookwyrm/migrations/0187_theme_loads.py diff --git a/bookwyrm/migrations/0187_theme_loads.py b/bookwyrm/migrations/0187_theme_loads.py new file mode 100644 index 000000000..3649c991c --- /dev/null +++ b/bookwyrm/migrations/0187_theme_loads.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.23 on 2023-11-20 17:44 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("bookwyrm", "0186_invite_request_notification"), + ] + + operations = [ + migrations.AddField( + model_name="theme", + name="loads", + field=models.BooleanField(blank=True, null=True), + ), + ] diff --git a/bookwyrm/models/site.py b/bookwyrm/models/site.py index a27c4b70d..b962d597b 100644 --- a/bookwyrm/models/site.py +++ b/bookwyrm/models/site.py @@ -149,6 +149,7 @@ class Theme(SiteModel): created_date = models.DateTimeField(auto_now_add=True) name = models.CharField(max_length=50, unique=True) path = models.CharField(max_length=50, unique=True) + loads = models.BooleanField(null=True, blank=True) def __str__(self): # pylint: disable=invalid-str-returned diff --git a/bookwyrm/templates/settings/themes.html b/bookwyrm/templates/settings/themes.html index d27aeb0ce..c077fa5e3 100644 --- a/bookwyrm/templates/settings/themes.html +++ b/bookwyrm/templates/settings/themes.html @@ -12,6 +12,15 @@ {% endblock %} {% block panel %} +{% if broken_theme %} +
+ + + {% trans "One of your themes appears to be broken. Selecting this theme will make the application unusable." %} + +
+{% endif %} + {% if success %}
@@ -98,6 +107,9 @@ {% trans "Actions" %} + + {% trans "Status" %} + {% for theme in themes %} @@ -112,6 +124,37 @@ + + {% if theme.loads is None %} + +
+ {% csrf_token %} + +
+ + {% elif not theme.loads %} + + + + + {% trans "Broken theme" %} + + + + {% else %} + + + + + {% trans "Loaded successfully" %} + + + + {% endif %} + {% endfor %} diff --git a/bookwyrm/urls.py b/bookwyrm/urls.py index 8541f4fb6..233e7786e 100644 --- a/bookwyrm/urls.py +++ b/bookwyrm/urls.py @@ -109,6 +109,11 @@ urlpatterns = [ views.delete_theme, name="settings-themes-delete", ), + re_path( + r"^settings/themes/(?P\d+)/test/?$", + views.test_theme, + name="settings-themes-test", + ), re_path( r"^settings/announcements/?$", views.Announcements.as_view(), diff --git a/bookwyrm/views/__init__.py b/bookwyrm/views/__init__.py index 2d2e97f52..4d298617c 100644 --- a/bookwyrm/views/__init__.py +++ b/bookwyrm/views/__init__.py @@ -30,7 +30,7 @@ from .admin.reports import ( moderator_delete_user, ) from .admin.site import Site, Registration, RegistrationLimited -from .admin.themes import Themes, delete_theme +from .admin.themes import Themes, delete_theme, test_theme from .admin.user_admin import UserAdmin, UserAdminList, ActivateUserAdmin # user preferences diff --git a/bookwyrm/views/admin/themes.py b/bookwyrm/views/admin/themes.py index 5658d243a..284a90833 100644 --- a/bookwyrm/views/admin/themes.py +++ b/bookwyrm/views/admin/themes.py @@ -6,6 +6,8 @@ from django.utils.decorators import method_decorator from django.views import View from django.views.decorators.http import require_POST +from sass_processor.processor import sass_processor + from bookwyrm import forms, models @@ -40,6 +42,7 @@ class Themes(View): def get_view_data(): """data for view""" return { + "broken_theme": models.Theme.objects.filter(loads=False).exists(), "themes": models.Theme.objects.all(), "theme_form": forms.ThemeForm(), } @@ -52,3 +55,20 @@ def delete_theme(request, theme_id): """Remove a theme""" get_object_or_404(models.Theme, id=theme_id).delete() return redirect("settings-themes") + + +@require_POST +@permission_required("bookwyrm.system_administration", raise_exception=True) +# pylint: disable=unused-argument +def test_theme(request, theme_id): + """Remove a theme""" + theme = get_object_or_404(models.Theme, id=theme_id) + + try: + sass_processor(theme.path) + theme.loads = True + except Exception: # pylint: disable=broad-except + theme.loads = False + + theme.save() + return redirect("settings-themes")