From 6dd44fdc2dab980bea5f7874df9bd4c43f4205a3 Mon Sep 17 00:00:00 2001 From: Beverly Nguyen Date: Thu, 10 Apr 2025 12:35:04 -0700 Subject: [PATCH] added feature flag --- .ds.baseline | 4 +-- .github/workflows/checks.yml | 1 + app/__init__.py | 16 ++++++------ app/assets/javascripts/socketio.js | 40 ++++++++++++++++------------- app/config.py | 3 +++ app/main/views/index.py | 8 +++--- app/main/views/jobs.py | 2 ++ app/templates/views/jobs/job.html | 41 ++++++++++++++++++++---------- gulpfile.js | 1 - 9 files changed, 72 insertions(+), 44 deletions(-) diff --git a/.ds.baseline b/.ds.baseline index 3d1881f23..4a5f6a5d1 100644 --- a/.ds.baseline +++ b/.ds.baseline @@ -151,7 +151,7 @@ "filename": "app/config.py", "hashed_secret": "577a4c667e4af8682ca431857214b3a920883efc", "is_verified": false, - "line_number": 118, + "line_number": 121, "is_secret": false } ], @@ -674,5 +674,5 @@ } ] }, - "generated_at": "2025-03-20T18:22:36Z" + "generated_at": "2025-04-10T19:35:01Z" } diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index d473eceae..7f4b18ff5 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -167,6 +167,7 @@ jobs: run: make run-flask & env: NOTIFY_ENVIRONMENT: scanning + FEATURE_SOCKET_ENABLED: true - name: Run OWASP Baseline Scan uses: zaproxy/action-baseline@v0.14.0 with: diff --git a/app/__init__.py b/app/__init__.py index 523d1c2e3..88529fe28 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -172,15 +172,15 @@ def _csp(config): def create_app(application): - # @application.context_processor - # def inject_feature_flags(): + @application.context_processor + def inject_feature_flags(): # this is where feature flags can be easily added as a dictionary within context - # feature_about_page_enabled = application.config.get( - # "FEATURE_ABOUT_PAGE_ENABLED", False - # ) - # return dict( - # FEATURE_ABOUT_PAGE_ENABLED=feature_about_page_enabled, - # ) + feature_socket_enabled = application.config.get( + "FEATURE_SOCKET_ENABLED", False + ) + return dict( + FEATURE_SOCKET_ENABLED=feature_socket_enabled, + ) @application.context_processor def inject_initial_signin_url(): diff --git a/app/assets/javascripts/socketio.js b/app/assets/javascripts/socketio.js index 8f4b2002f..e0588e22d 100644 --- a/app/assets/javascripts/socketio.js +++ b/app/assets/javascripts/socketio.js @@ -10,29 +10,35 @@ document.addEventListener("DOMContentLoaded", function () { const isJobPage = window.location.pathname.includes("/jobs/"); if (!isJobPage) return; - const jobId = document.querySelector("[data-job-id]")?.dataset?.jobId; + const jobEl = document.querySelector("[data-job-id]"); + const jobId = jobEl?.dataset?.jobId; + const featureEnabled = jobEl?.dataset?.feature === "true"; + if (!jobId) return; - const socket = io("http://localhost:6011"); - socket.on("connect", () => { - console.log("Connected to Socket.IO server"); - socket.emit("join", { room: `job-${jobId}` }); - console.log("join", { room: `job-${jobId}` }); - }); + if (featureEnabled) { + const socket = io("http://localhost:6011"); - window.addEventListener("beforeunload", () => { - socket.emit("leave", { room: `job-${jobId}` }); - }); + socket.on("connect", () => { + console.log("Connected to Socket.IO server"); + socket.emit("join", { room: `job-${jobId}` }); + console.log("join", { room: `job-${jobId}` }); + }); - const debouncedUpdate = debounce((data) => { - updateAllJobSections(); - }, 1000); + window.addEventListener("beforeunload", () => { + socket.emit("leave", { room: `job-${jobId}` }); + }); - socket.on("job_updated", (data) => { - if (data.job_id !== jobId) return; - debouncedUpdate(data); - }); + const debouncedUpdate = debounce((data) => { + updateAllJobSections(); + }, 1000); + + socket.on("job_updated", (data) => { + if (data.job_id !== jobId) return; + debouncedUpdate(data); + }); + } function updateAllJobSections() { const resourceEl = document.querySelector('[data-socket-update="status"]'); diff --git a/app/config.py b/app/config.py index dece2728d..287308c92 100644 --- a/app/config.py +++ b/app/config.py @@ -89,6 +89,9 @@ class Config(object): } + FEATURE_SOCKET_ENABLED = getenv("FEATURE_SOCKET_ENABLED", "false") == "true" + + def _s3_credentials_from_env(bucket_prefix): return { "bucket": getenv( diff --git a/app/main/views/index.py b/app/main/views/index.py index ab11ba8c2..909fb975c 100644 --- a/app/main/views/index.py +++ b/app/main/views/index.py @@ -25,15 +25,17 @@ from app.utils.user import user_is_logged_in def check_feature_flags(): # Placeholder for future feature flag checks # Example: - # if request.path.startswith("/some-feature") and not current_app.config.get("FEATURE_SOME_FEATURE_ENABLED", False): - # abort(404) + if request.path.startswith("/jobs") and not current_app.config.get( + "FEATURE_SOCKET_ENABLED", False + ): + abort(404) pass @main.route("/test/feature-flags") def test_feature_flags(): return jsonify( - {"FEATURE_ABOUT_PAGE_ENABLED": current_app.config["FEATURE_ABOUT_PAGE_ENABLED"]} + {"FEATURE_SOCKET_ENABLED": current_app.config["FEATURE_SOCKET_ENABLED"]} ) diff --git a/app/main/views/jobs.py b/app/main/views/jobs.py index 86ce0bce6..32b41681f 100644 --- a/app/main/views/jobs.py +++ b/app/main/views/jobs.py @@ -4,6 +4,7 @@ from functools import partial from flask import ( Response, + current_app, abort, jsonify, redirect, @@ -59,6 +60,7 @@ def view_job(service_id, job_id): filter_args["status"] = set_status_filters(filter_args) return render_template( "views/jobs/job.html", + FEATURE_SOCKET_ENABLED=current_app.config["FEATURE_SOCKET_ENABLED"], job=job, status=request.args.get("status", ""), updates_url=url_for( diff --git a/app/templates/views/jobs/job.html b/app/templates/views/jobs/job.html index 62d084907..4c99dae76 100644 --- a/app/templates/views/jobs/job.html +++ b/app/templates/views/jobs/job.html @@ -3,7 +3,7 @@ {% from "components/page-footer.html" import page_footer %} {% from "components/page-header.html" import page_header %} {% from "components/components/back-link/macro.njk" import usaBackLink %} -{% from 'components/ajax-block.html' import socket_block %} + {% block service_page_title %} {{ "Message status" }} {% endblock %} @@ -11,20 +11,33 @@ {% block maincolumn_content %} {{ page_header("Message status") }} -
+
+ {% if not job.finished_processing %} +
+ {% endif %} {{ partials['status']|safe }} + {% if not job.finished_processing %}
+ {% endif %} {% if not finished %}
{% endif %} {{ partials['counts']|safe }} @@ -37,9 +50,12 @@

{% if not job.processing_finished %}
@@ -48,7 +64,6 @@ {% if not job.processing_finished %}
{% endif %} - -
+
{% endblock %} diff --git a/gulpfile.js b/gulpfile.js index 73bfc3545..3cedae6b1 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -85,7 +85,6 @@ const javascripts = () => { paths.src + 'javascripts/sidenav.js', paths.src + 'javascripts/validation.js', paths.src + 'javascripts/socketio.js', - ]) .pipe(plugins.prettyerror()) .pipe(