Adds db read-only middleware (#12490)

* adds db read-only middleware #11233

* fixed attribute error

* replaces getattr with get_config
This commit is contained in:
Abhimanyu Saharan 2023-05-12 20:20:51 +05:30 committed by GitHub
parent cc0c985fec
commit 9b80ec22ba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 46 additions and 3 deletions

View File

@ -3,19 +3,21 @@ import uuid
from urllib import parse from urllib import parse
from django.conf import settings from django.conf import settings
from django.contrib import auth from django.contrib import auth, messages
from django.contrib.auth.middleware import RemoteUserMiddleware as RemoteUserMiddleware_ from django.contrib.auth.middleware import RemoteUserMiddleware as RemoteUserMiddleware_
from django.core.exceptions import ImproperlyConfigured from django.core.exceptions import ImproperlyConfigured
from django.db import ProgrammingError from django.db import connection, ProgrammingError
from django.db.utils import InternalError
from django.http import Http404, HttpResponseRedirect from django.http import Http404, HttpResponseRedirect
from extras.context_managers import change_logging from extras.context_managers import change_logging
from netbox.config import clear_config from netbox.config import clear_config, get_config
from netbox.views import handler_500 from netbox.views import handler_500
from utilities.api import is_api_request, rest_api_server_error from utilities.api import is_api_request, rest_api_server_error
__all__ = ( __all__ = (
'CoreMiddleware', 'CoreMiddleware',
'MaintenanceModeMiddleware',
'RemoteUserMiddleware', 'RemoteUserMiddleware',
) )
@ -166,3 +168,43 @@ class RemoteUserMiddleware(RemoteUserMiddleware_):
groups = [] groups = []
logger.debug(f"Groups are {groups}") logger.debug(f"Groups are {groups}")
return groups return groups
class MaintenanceModeMiddleware:
"""
Middleware that checks if the application is in maintenance mode
and restricts write-related operations to the database.
"""
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
if get_config().MAINTENANCE_MODE:
self._prevent_db_write_operations()
return self.get_response(request)
@staticmethod
def _prevent_db_write_operations():
"""
Prevent any write-related database operations.
"""
with connection.cursor() as cursor:
cursor.execute(
'SET SESSION CHARACTERISTICS AS TRANSACTION READ ONLY;'
)
def process_exception(self, request, exception):
"""
Prevent any write-related database operations if an exception is raised.
"""
if isinstance(exception, InternalError):
error_message = 'NetBox is currently operating in maintenance mode and is unable to perform write ' \
'operations. Please try again later.'
if is_api_request(request):
return rest_api_server_error(request, error=error_message)
messages.error(request, error_message)
return HttpResponseRedirect(request.path_info)

View File

@ -383,6 +383,7 @@ MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware', 'django.middleware.security.SecurityMiddleware',
'netbox.middleware.RemoteUserMiddleware', 'netbox.middleware.RemoteUserMiddleware',
'netbox.middleware.CoreMiddleware', 'netbox.middleware.CoreMiddleware',
'netbox.middleware.MaintenanceModeMiddleware',
'django_prometheus.middleware.PrometheusAfterMiddleware', 'django_prometheus.middleware.PrometheusAfterMiddleware',
] ]