Skip to content

Commit 8b91d23

Browse files
committed
return 503 for API if maintanence_mode is set to ture
1 parent 6330798 commit 8b91d23

5 files changed

Lines changed: 74 additions & 1 deletion

File tree

api/base/middleware.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from importlib import import_module
66

77
from django.conf import settings
8+
from django.http import JsonResponse
89
from django.contrib.sessions.middleware import SessionMiddleware
910
from django.utils.deprecation import MiddlewareMixin
1011
from sentry_sdk import init
@@ -24,6 +25,7 @@
2425
from .api_globals import api_globals
2526
from api.base import settings as api_settings
2627
from api.base.authentication.drf import drf_get_session_from_cookie
28+
from osf.models import MaintenanceMode
2729

2830
SessionStore = import_module(settings.SESSION_ENGINE).SessionStore
2931

@@ -132,3 +134,22 @@ def process_request(self, request):
132134
request.session = drf_get_session_from_cookie(cookie)
133135
else:
134136
request.session = SessionStore()
137+
138+
139+
class MaintenanceModeMiddleware:
140+
def __init__(self, get_response):
141+
self.get_response = get_response
142+
143+
def __call__(self, request):
144+
if request.path.endswith(('/v2', '/v2/')):
145+
return self.get_response(request)
146+
if MaintenanceMode.is_under_maintenance():
147+
return JsonResponse(
148+
{
149+
'meta': {
150+
'maintenance_mode': True,
151+
'status_page': 'status',
152+
},
153+
}, status=503,
154+
)
155+
return self.get_response(request)

api/base/settings/defaults.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,7 @@
232232
'django.middleware.common.CommonMiddleware',
233233
'django.middleware.csrf.CsrfViewMiddleware',
234234
'api.base.middleware.UnsignCookieSessionMiddleware',
235+
'api.base.middleware.MaintenanceModeMiddleware',
235236
'django.contrib.auth.middleware.AuthenticationMiddleware',
236237
'django.contrib.messages.middleware.MessageMiddleware',
237238
'django.middleware.clickjacking.XFrameOptionsMiddleware',
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# Generated by Django 4.2.26 on 2026-04-23 14:25
2+
3+
from django.db import migrations, models
4+
5+
6+
def create_initial_record(apps, schema_editor):
7+
MaintenanceMode = apps.get_model('osf', 'MaintenanceMode')
8+
MaintenanceMode.objects.get_or_create(
9+
pk=1,
10+
defaults={'maintenance_mode': False}
11+
)
12+
13+
14+
def reverse_initial_record(apps, schema_editor):
15+
# the reverse 'reverse_initial_record' does nothing
16+
# because the table will be removed
17+
pass
18+
19+
20+
class Migration(migrations.Migration):
21+
22+
dependencies = [
23+
('osf', '0038_abstractnode_date_last_indexed_and_more'),
24+
]
25+
26+
operations = [
27+
migrations.CreateModel(
28+
name='MaintenanceMode',
29+
fields=[
30+
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
31+
('maintenance_mode', models.BooleanField(default=False)),
32+
],
33+
),
34+
migrations.RunPython(
35+
create_initial_record,
36+
reverse_code=reverse_initial_record
37+
),
38+
]

osf/models/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@
5252
from .institution_affiliation import InstitutionAffiliation
5353
from .institution_storage_region import InstitutionStorageRegion
5454
from .licenses import NodeLicense, NodeLicenseRecord
55-
from .maintenance_state import MaintenanceState
55+
from .maintenance_state import MaintenanceState, MaintenanceMode
5656
from .metadata import GuidMetadataRecord
5757
from .metaschema import (
5858
FileMetadataSchema,

osf/models/maintenance_state.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,16 @@ class MaintenanceState(models.Model):
1414
start = NonNaiveDateTimeField()
1515
end = NonNaiveDateTimeField()
1616
message = models.TextField(blank=True)
17+
18+
19+
class MaintenanceMode(models.Model):
20+
maintenance_mode = models.BooleanField(default=False)
21+
22+
def save(self, *args, **kwargs):
23+
self.pk = 1
24+
super().save(*args, **kwargs)
25+
26+
@classmethod
27+
def is_under_maintenance(cls):
28+
obj, _ = cls.objects.get_or_create(pk=1)
29+
return obj.maintenance_mode

0 commit comments

Comments
 (0)