diff --git a/backend/audit/views/home.py b/backend/audit/views/home.py index 94b029a6f..65691e599 100644 --- a/backend/audit/views/home.py +++ b/backend/audit/views/home.py @@ -1,3 +1,4 @@ +from datetime import datetime, timezone from django.conf import settings from django.shortcuts import render, redirect from django.urls import reverse @@ -32,4 +33,12 @@ class Maintenance(generic.View): def get(self, request, *args, **kwargs): template_name = "503.html" + + current_time = datetime.now(timezone.utc) + for date_range in settings.MAINTENANCE_BANNER_DATES: + if current_time > date_range.get("start") and current_time < date_range.get( + "end" + ): + template_name = date_range.get("template_name", "503.html") + return render(request, template_name) diff --git a/backend/config/context_processors.py b/backend/config/context_processors.py index 1fddafabe..83f16185e 100644 --- a/backend/config/context_processors.py +++ b/backend/config/context_processors.py @@ -1,4 +1,5 @@ from config import settings +from datetime import datetime, timezone def static_site_url(request): @@ -23,3 +24,38 @@ def current_environment(request): Used in determining the display of the TEST SITE Banner. """ return {"ENVIRONMENT": settings.ENVIRONMENT} + + +def maintenance_banner(request): + """ + Returns maintenance banner template context. + MAINTENANCE_BANNER is True if the banner should be displaying and False if not, based on settings.MAINTENANCE_BANNER_DATES. + MAINTENANCE_BANNER_START_TIME and MAINTENANCE_BANNER_END_TIME are None if the banner does not display. + MAINTENANCE_BANNER_MESSAGE is included if it exists alongside the banner dates. + """ + current_time = datetime.now(timezone.utc) + context = { + "MAINTENANCE_BANNER": False, + } + + # For every designated date range: + # If any start or end time is unavailable, something is misconfigured. So, disable the banner. + # If we are within the specified timeframes, enable the banner. + for date_range in settings.MAINTENANCE_BANNER_DATES: + start_time = date_range.get("start") + end_time = date_range.get("end") + + if not start_time or not end_time: + return context + + if current_time > start_time and current_time < end_time: + context["MAINTENANCE_BANNER"] = True + context = context | { + "MAINTENANCE_BANNER_START_TIME": start_time, + "MAINTENANCE_BANNER_END_TIME": end_time, + "MAINTENANCE_BANNER_MESSAGE": date_range.get("message", ""), + } + return context + + # Base case - we are not within any of the given timeframes. Disable the banner. + return context diff --git a/backend/config/middleware.py b/backend/config/middleware.py index 9952da41a..0efd68cdc 100644 --- a/backend/config/middleware.py +++ b/backend/config/middleware.py @@ -60,6 +60,11 @@ def __call__(self, request): Check that maintenance mode is disabled before running request. """ + # Let icons through + if request.path == "/icons/sprite.svg": + response = self.get_response(request) + return response + # redirect to maintenance page. if is_maintenance_on(): if request.path != "/maintenance": diff --git a/backend/config/settings.py b/backend/config/settings.py index c05f8b3d0..92b807136 100644 --- a/backend/config/settings.py +++ b/backend/config/settings.py @@ -11,6 +11,7 @@ """ from base64 import b64decode +from datetime import datetime, timezone import os import sys import logging @@ -161,6 +162,7 @@ "config.context_processors.static_site_url", "config.context_processors.omb_num_exp_date", "config.context_processors.current_environment", + "config.context_processors.maintenance_banner", "report_submission.context_processors.certifiers_emails_must_not_match", ], "builtins": [ @@ -580,3 +582,18 @@ # Keep sessions alive if the user is active # https://docs.djangoproject.com/en/dev/ref/settings/#session-save-every-request SESSION_SAVE_EVERY_REQUEST = True + +# Times for the maintenance banner to display. +# Requires a 'start' and an 'end'. +# 'template_name' is optional, and defines what will display if maintenance mode is enabled during this timeframe. If no name is given, the 503 error page is used. +# 'message' is optional, and overrides the default banner message. +# The default message states that maintenance will be ongoing for the duration of the banners uptime. This may be true in an emergency. Otherwise, be sure to set a custom message. +MAINTENANCE_BANNER_DATES = [ + { + # December 5th to 10th, noon EST, uploading historical audits + "start": datetime(2024, 12, 5, 17, tzinfo=timezone.utc), + "end": datetime(2024, 12, 10, 17, tzinfo=timezone.utc), + "template_name": "maintenance_20241210.html", + "message": "FAC.gov will be doing a site upgrade on Tuesday, December 10, 2024 between 12:00 p.m. and 6:00 p.m ET. During this period, the entire website will be unavailable.", + }, +] diff --git a/backend/templates/includes/header.html b/backend/templates/includes/header.html index 35db286f2..348c0f69f 100644 --- a/backend/templates/includes/header.html +++ b/backend/templates/includes/header.html @@ -8,6 +8,11 @@ {% endif %} + +{% if MAINTENANCE_BANNER %} + {% include "includes/maintenance_banner.html" %} +{% endif %} +
diff --git a/backend/templates/includes/maintenance_banner.html b/backend/templates/includes/maintenance_banner.html new file mode 100644 index 000000000..20fe2e551 --- /dev/null +++ b/backend/templates/includes/maintenance_banner.html @@ -0,0 +1,15 @@ +
+
+

Scheduled system upgrade

+ + {% comment %} If a message is given, use it. If not, display a generic message with the timeframe. {% endcomment %} +

+ {% if MAINTENANCE_BANNER_MESSAGE %} + {{ MAINTENANCE_BANNER_MESSAGE }} + {% else %} + FAC.gov will be doing a site upgrade from {{ MAINTENANCE_BANNER_START_TIME|date:"N j, Y, f A" }} to {{ MAINTENANCE_BANNER_END_TIME|date:"N j, Y, f A" }}. + During this period, the entire website will be unavailable. + {% endif %} +

+
+
\ No newline at end of file diff --git a/backend/templates/maintenance_20241210.html b/backend/templates/maintenance_20241210.html new file mode 100644 index 000000000..5dda97cca --- /dev/null +++ b/backend/templates/maintenance_20241210.html @@ -0,0 +1,13 @@ +{% extends "base.html" %} +{% load sprite_helper %} +{% block content %} +
+ + {% uswds_sprite "error" %} + +

Temporarily Down for System Maintenance

+

We are in the process of uploading historical audits to fac.gov.

+

We should be back after December 10, 2024 at 6:00 p.m. ET.

+

Thank you for your patience. If you have any questions, please contact us via email at FAC@gsa.gov.

+
+{% endblock content %}