Skip to content

Commit c35e8fa

Browse files
Handle System_Settings errors better in middleware (#13982)
* Handle System_Settings.DoesNotExist in get_from_db Refactor get_from_db method to handle specific exception. * add error message to UI
1 parent cb61c59 commit c35e8fa

2 files changed

Lines changed: 40 additions & 6 deletions

File tree

dojo/context_processors.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
# import the settings file
55
from django.conf import settings
6+
from django.contrib import messages
67

78
from dojo.labels import get_labels
89
from dojo.models import Alerts, System_Settings, UserAnnouncement
@@ -39,7 +40,26 @@ def globalize_vars(request):
3940

4041

4142
def bind_system_settings(request):
42-
return {"system_settings": System_Settings.objects.get()}
43+
"""Load system settings and display warning if there's a database error."""
44+
try:
45+
system_settings = System_Settings.objects.get()
46+
# Check if there was an error stored on the request (from middleware)
47+
if hasattr(request, "system_settings_error"):
48+
error_msg = request.system_settings_error
49+
messages.add_message(
50+
request,
51+
messages.WARNING,
52+
f"Warning: Unable to load system settings from database: {error_msg}. "
53+
"Default values are being used. Please check your database configuration and run migrations if needed.",
54+
extra_tags="alert-warning",
55+
)
56+
# Clear after adding message
57+
delattr(request, "system_settings_error")
58+
except Exception:
59+
# If we can't get settings, return empty dict (will cause errors elsewhere, but that's expected)
60+
return {}
61+
62+
return {"system_settings": system_settings}
4363

4464

4565
def bind_alert_count(request):

dojo/middleware.py

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,12 @@ def __init__(self, get_response):
114114
def __call__(self, request):
115115
self.load()
116116
try:
117+
# Store error in request for context processor to display
118+
# (We can't use messages here because MessageMiddleware runs after this middleware)
119+
if hasattr(self._thread_local, "system_settings_error"):
120+
request.system_settings_error = self._thread_local.system_settings_error
121+
# Clear from thread-local after copying to request
122+
delattr(self._thread_local, "system_settings_error")
117123
return self.get_response(request)
118124
finally:
119125
# ensure cleanup happens even if an exception occurs
@@ -132,6 +138,8 @@ def get_system_settings(cls):
132138
def cleanup(cls, *args, **kwargs): # noqa: ARG003
133139
if hasattr(cls._thread_local, "system_settings"):
134140
del cls._thread_local.system_settings
141+
if hasattr(cls._thread_local, "system_settings_error"):
142+
delattr(cls._thread_local, "system_settings_error")
135143

136144
@classmethod
137145
def load(cls):
@@ -147,13 +155,19 @@ class System_Settings_Manager(models.Manager):
147155

148156
def get_from_db(self, *args, **kwargs):
149157
# logger.debug('refreshing system_settings from db')
158+
from dojo.models import System_Settings # noqa: PLC0415 circular import
150159
try:
151160
from_db = super().get(*args, **kwargs)
152-
except:
153-
from dojo.models import System_Settings # noqa: PLC0415 circular import
154-
# this mimics the existing code that was in filters.py and utils.py.
155-
# cases I have seen triggering this is for example manage.py collectstatic inside a docker build where mysql is not available
156-
# logger.debug('unable to get system_settings from database, constructing (new) default instance. Exception was:', exc_info=True)
161+
except Exception as e:
162+
# Store error message in thread-local for middleware to display
163+
error_msg = str(e)
164+
if hasattr(DojoSytemSettingsMiddleware._thread_local, "system_settings_error"):
165+
# Only store the first error to avoid duplicates
166+
pass
167+
else:
168+
DojoSytemSettingsMiddleware._thread_local.system_settings_error = error_msg
169+
# Return defaults so app can still start - error will be displayed as warning message
170+
# logger.debug('unable to get system_settings from database, returning defaults. Exception was:', exc_info=True)
157171
return System_Settings()
158172
return from_db
159173

0 commit comments

Comments
 (0)