From fff440a6ff92615aab0f9dc51080a8a5850d8d74 Mon Sep 17 00:00:00 2001 From: Jonathan Bobel Date: Mon, 26 Feb 2024 11:10:50 -0500 Subject: [PATCH 01/30] 1216 - sign-in page redesign with login.gov --- app/templates/views/signin.html | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/app/templates/views/signin.html b/app/templates/views/signin.html index a19376d7c..4ee655127 100644 --- a/app/templates/views/signin.html +++ b/app/templates/views/signin.html @@ -13,7 +13,7 @@ {% block maincolumn_content %}
-
+
{% if again %}

You need to sign in again

@@ -29,9 +29,9 @@ {% else %}

Sign in

{% if login_gov_enabled %} - Sign in with Login.gov -

-

Or:

+

You can access your account by signing in with one of the options below:

+ Sign in with Login.gov +

Or:

{% endif %} {% endif %} @@ -41,6 +41,19 @@ {{ page_footer("Continue", secondary_link=password_reset_url, secondary_link_text="Forgot your password?") }} {% endcall %}
+
+

Notify.gov is changing the Sign in experience to Login.gov on March x, 2024

+

Why are we doing this?

+
    +
  • One single source for signing in: You can use login.gov for other sign in forms within the government
  • +
  • Security: It's really secure and trustworthy
  • +
  • Fast and easy: It's fast and easy
  • +
+
+

Don't have a login.gov account?

+

If you don't have an account already, sign up here:

+ Create Login.gov account +
{% endblock %} From 141c24e37146ff4bc80f94165715e8ce73461f4c Mon Sep 17 00:00:00 2001 From: Kenneth Kehl <@kkehl@flexion.us> Date: Mon, 26 Feb 2024 11:07:16 -0800 Subject: [PATCH 02/30] add latest version commit hash to footer (notify-admin-204) --- .github/workflows/deploy-demo.yml | 1 + .github/workflows/deploy-prod.yml | 1 + .github/workflows/deploy.yml | 2 ++ app/config.py | 1 + app/main/forms.py | 16 +++++++---- app/main/views/api_keys.py | 22 +++++++++------ app/main/views/manage_users.py | 22 ++++++++------- app/main/views/performance.py | 6 ++-- app/main/views/send.py | 28 +++++++++++-------- app/main/views/service_settings.py | 24 ++++++++++------ app/templates/admin_template.html | 6 ++-- manifest.yml | 2 ++ tests/app/main/views/test_manage_users.py | 6 ++-- tests/app/main/views/test_template_folders.py | 8 ++++-- tests/conftest.py | 14 ++++++---- 15 files changed, 96 insertions(+), 63 deletions(-) diff --git a/.github/workflows/deploy-demo.yml b/.github/workflows/deploy-demo.yml index e1d76775a..38947c4b3 100644 --- a/.github/workflows/deploy-demo.yml +++ b/.github/workflows/deploy-demo.yml @@ -54,6 +54,7 @@ jobs: ADMIN_CLIENT_SECRET: ${{ secrets.ADMIN_CLIENT_SECRET }} NEW_RELIC_LICENSE_KEY: ${{ secrets.NEW_RELIC_LICENSE_KEY }} NR_BROWSER_KEY: ${{ secrets.NR_BROWSER_KEY }} + COMMIT_HASH: $(git rev-parse --short "$GITHUB_SHA") LOGIN_PEM: ${{ secrets.LOGIN_PEM }} LOGIN_DOT_GOV_CLIENT_ID: "urn:gov:gsa:openidconnect.profiles:sp:sso:gsa:notify-gov" LOGIN_DOT_GOV_USER_INFO_URL: "https://idp.int.identitysandbox.gov/api/openid_connect/userinfo" diff --git a/.github/workflows/deploy-prod.yml b/.github/workflows/deploy-prod.yml index a0aaa81c5..de0c5714d 100644 --- a/.github/workflows/deploy-prod.yml +++ b/.github/workflows/deploy-prod.yml @@ -54,6 +54,7 @@ jobs: ADMIN_CLIENT_SECRET: ${{ secrets.ADMIN_CLIENT_SECRET }} NEW_RELIC_LICENSE_KEY: ${{ secrets.NEW_RELIC_LICENSE_KEY }} NR_BROWSER_KEY: ${{ secrets.NR_BROWSER_KEY }} + COMMIT_HASH: $(git rev-parse --short "$GITHUB_SHA") LOGIN_PEM: ${{ secrets.LOGIN_PEM }} LOGIN_DOT_GOV_CLIENT_ID: "urn:gov:gsa:openidconnect.profiles:sp:sso:gsa:notify-gov" LOGIN_DOT_GOV_USER_INFO_URL: "https://secure.login.gov/api/openid_connect/userinfo" diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 767acae72..ac6aac9d0 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -60,6 +60,7 @@ jobs: ADMIN_CLIENT_SECRET: ${{ secrets.ADMIN_CLIENT_SECRET }} NEW_RELIC_LICENSE_KEY: ${{ secrets.NEW_RELIC_LICENSE_KEY }} NR_BROWSER_KEY: ${{ secrets.NR_BROWSER_KEY }} + COMMIT_HASH: $(git rev-parse --short "$GITHUB_SHA") LOGIN_PEM: ${{ secrets.LOGIN_PEM }} LOGIN_DOT_GOV_CLIENT_ID: "urn:gov:gsa:openidconnect.profiles:sp:sso:gsa:notify-gov" LOGIN_DOT_GOV_USER_INFO_URL: "https://idp.int.identitysandbox.gov/api/openid_connect/userinfo" @@ -81,6 +82,7 @@ jobs: --var ADMIN_CLIENT_SECRET="$ADMIN_CLIENT_SECRET" --var NEW_RELIC_LICENSE_KEY="$NEW_RELIC_LICENSE_KEY" --var NR_BROWSER_KEY="$NR_BROWSER_KEY" + --var COMMIT_HASH="$COMMIT_HASH" --var LOGIN_PEM="$LOGIN_PEM" --var LOGIN_DOT_GOV_CLIENT_ID="$LOGIN_DOT_GOV_CLIENT_ID" --var LOGIN_DOT_GOV_USER_INFO_URL="$LOGIN_DOT_GOV_USER_INFO_URL" diff --git a/app/config.py b/app/config.py index f424076fa..91c514509 100644 --- a/app/config.py +++ b/app/config.py @@ -36,6 +36,7 @@ class Config(object): NR_BROWSER_KEY = getenv("NR_BROWSER_KEY") settings = newrelic.agent.global_settings() NR_MONITOR_ON = settings and settings.monitor_mode + COMMIT_HASH = getenv("COMMIT_HASH") TEMPLATE_PREVIEW_API_HOST = getenv( "TEMPLATE_PREVIEW_API_HOST", "http://localhost:9999" diff --git a/app/main/forms.py b/app/main/forms.py index c01ce8fcc..2e6655cc5 100644 --- a/app/main/forms.py +++ b/app/main/forms.py @@ -1781,12 +1781,16 @@ class TemplateAndFoldersSelectionForm(Form): None, [ # ('email', 'Email') if 'email' in available_template_types else None, - ("sms", "Start with a blank template") - if "sms" in available_template_types - else None, - ("copy-existing", "Copy an existing template") - if allow_adding_copy_of_template - else None, + ( + ("sms", "Start with a blank template") + if "sms" in available_template_types + else None + ), + ( + ("copy-existing", "Copy an existing template") + if allow_adding_copy_of_template + else None + ), ], ) ) diff --git a/app/main/views/api_keys.py b/app/main/views/api_keys.py index 4f8c3b29e..8cb28ba59 100644 --- a/app/main/views/api_keys.py +++ b/app/main/views/api_keys.py @@ -168,12 +168,14 @@ def api_callbacks(service_id): return render_template( "views/api/callbacks.html", - received_text_messages_callback=received_text_messages_callback["url"] - if received_text_messages_callback - else None, - delivery_status_callback=delivery_status_callback["url"] - if delivery_status_callback - else None, + received_text_messages_callback=( + received_text_messages_callback["url"] + if received_text_messages_callback + else None + ), + delivery_status_callback=( + delivery_status_callback["url"] if delivery_status_callback else None + ), ) @@ -262,9 +264,11 @@ def received_text_messages_callback(service_id): received_text_messages_callback = get_received_text_messages_callback() form = CallbackForm( - url=received_text_messages_callback.get("url") - if received_text_messages_callback - else "", + url=( + received_text_messages_callback.get("url") + if received_text_messages_callback + else "" + ), bearer_token=dummy_bearer_token if received_text_messages_callback else "", ) diff --git a/app/main/views/manage_users.py b/app/main/views/manage_users.py index 4ab20f363..1b80c659e 100644 --- a/app/main/views/manage_users.py +++ b/app/main/views/manage_users.py @@ -122,16 +122,18 @@ def edit_user_permissions(service_id, user_id): form = form_class.from_user( user, service_id, - folder_permissions=None - if user.platform_admin - else [ - f["id"] - for f in current_service.all_template_folders - if user.has_template_folder_permission(f) - ], - all_template_folders=None - if user.platform_admin - else current_service.all_template_folders, + folder_permissions=( + None + if user.platform_admin + else [ + f["id"] + for f in current_service.all_template_folders + if user.has_template_folder_permission(f) + ] + ), + all_template_folders=( + None if user.platform_admin else current_service.all_template_folders + ), ) if form.validate_on_submit(): diff --git a/app/main/views/performance.py b/app/main/views/performance.py index 13445967b..1d2a4d1bc 100644 --- a/app/main/views/performance.py +++ b/app/main/views/performance.py @@ -34,8 +34,8 @@ def performance(): stats["average_percentage_under_10_seconds"] = mean( [row["percentage_under_10_seconds"] for row in stats["processing_time"]] or [0] ) - stats[ - "count_of_live_services_and_organizations" - ] = status_api_client.get_count_of_live_services_and_organizations() + stats["count_of_live_services_and_organizations"] = ( + status_api_client.get_count_of_live_services_and_organizations() + ) return render_template("views/performance.html", **stats) diff --git a/app/main/views/send.py b/app/main/views/send.py index 4332c7ddb..6c786e3ac 100644 --- a/app/main/views/send.py +++ b/app/main/views/send.py @@ -52,12 +52,14 @@ def get_example_csv_fields(column_headers, use_example_as_example, submitted_fie def get_example_csv_rows(template, use_example_as_example=True, submitted_fields=False): return { - "email": ["test@example.com"] - if use_example_as_example - else [current_user.email_address], - "sms": ["12223334444"] - if use_example_as_example - else [current_user.mobile_number], + "email": ( + ["test@example.com"] + if use_example_as_example + else [current_user.email_address] + ), + "sms": ( + ["12223334444"] if use_example_as_example else [current_user.mobile_number] + ), }[template.template_type] + get_example_csv_fields( ( placeholder @@ -511,12 +513,14 @@ def _check_messages(service_id, template_id, upload_id, preview_row): template=template, max_initial_rows_shown=50, max_errors_shown=50, - guestlist=itertools.chain.from_iterable( - [user.name, user.mobile_number, user.email_address] - for user in Users(service_id) - ) - if current_service.trial_mode - else None, + guestlist=( + itertools.chain.from_iterable( + [user.name, user.mobile_number, user.email_address] + for user in Users(service_id) + ) + if current_service.trial_mode + else None + ), remaining_messages=remaining_messages, allow_international_sms=current_service.has_permission("international_sms"), ) diff --git a/app/main/views/service_settings.py b/app/main/views/service_settings.py index 1cac1410c..628ac59e5 100644 --- a/app/main/views/service_settings.py +++ b/app/main/views/service_settings.py @@ -477,9 +477,11 @@ def service_edit_email_reply_to(service_id, reply_to_email_id): current_service.id, reply_to_email_id=reply_to_email_id, email_address=form.email_address.data, - is_default=True - if reply_to_email_address["is_default"] - else form.is_default.data, + is_default=( + True + if reply_to_email_address["is_default"] + else form.is_default.data + ), ) return redirect(url_for(".service_email_reply_to", service_id=service_id)) try: @@ -499,9 +501,11 @@ def service_edit_email_reply_to(service_id, reply_to_email_id): ".service_verify_reply_to_address", service_id=service_id, notification_id=notification_id, - is_default=True - if reply_to_email_address["is_default"] - else form.is_default.data, + is_default=( + True + if reply_to_email_address["is_default"] + else form.is_default.data + ), replace=reply_to_email_id, ) ) @@ -702,9 +706,11 @@ def service_edit_sms_sender(service_id, sms_sender_id): service_api_client.update_sms_sender( current_service.id, sms_sender_id=sms_sender_id, - sms_sender=sms_sender["sms_sender"] - if is_inbound_number - else form.sms_sender.data.replace("\r", ""), + sms_sender=( + sms_sender["sms_sender"] + if is_inbound_number + else form.sms_sender.data.replace("\r", "") + ), is_default=True if sms_sender["is_default"] else form.is_default.data, ) return redirect(url_for(".service_sms_senders", service_id=service_id)) diff --git a/app/templates/admin_template.html b/app/templates/admin_template.html index c48f768ce..df70151ce 100644 --- a/app/templates/admin_template.html +++ b/app/templates/admin_template.html @@ -179,7 +179,9 @@ {% if current_service and current_service.research_mode %} {% set meta_suffix = 'Built by the Technology Transformation Servicesresearch mode' %} {% else %} - {% set meta_suffix = 'Built by the Technology Transformation Services' %} + {% set commit_hash = ", Latest version: " + config['COMMIT_HASH'] %} + {% set long_link = 'Technology Transformation Services' %} + {% set meta_suffix = "Built by the " + long_link + commit_hash %} {% endif %} {{ usaFooter({ @@ -244,7 +246,7 @@ { "href": url_for('main.support'), "text": "Contact us" - }, + } ] }, ], diff --git a/manifest.yml b/manifest.yml index 1c25fdf4a..6b6c98672 100644 --- a/manifest.yml +++ b/manifest.yml @@ -47,6 +47,8 @@ applications: REQUESTS_CA_BUNDLE: "/etc/ssl/certs/ca-certificates.crt" NEW_RELIC_CA_BUNDLE_PATH: "/etc/ssl/certs/ca-certificates.crt" + COMMIT_HASH: ((COMMIT_HASH)) + # login.gov variables LOGIN_PEM: ((LOGIN_PEM)) diff --git a/tests/app/main/views/test_manage_users.py b/tests/app/main/views/test_manage_users.py index 9bdabf925..c3d128155 100644 --- a/tests/app/main/views/test_manage_users.py +++ b/tests/app/main/views/test_manage_users.py @@ -862,9 +862,9 @@ def test_should_show_page_if_prefilled_user_is_already_invited( mock_get_invites_for_service, platform_admin_user, ): - active_user_with_permission_to_other_service[ - "email_address" - ] = "user_1@testnotify.gsa.gov" + active_user_with_permission_to_other_service["email_address"] = ( + "user_1@testnotify.gsa.gov" + ) client_request.login(platform_admin_user) mocker.patch( "app.models.user.user_api_client.get_user", diff --git a/tests/app/main/views/test_template_folders.py b/tests/app/main/views/test_template_folders.py index fae020e58..0bf2fcb08 100644 --- a/tests/app/main/views/test_template_folders.py +++ b/tests/app/main/views/test_template_folders.py @@ -31,9 +31,11 @@ def _folder(name, folder_id=None, parent=None, users_with_permission=None): "name": name, "id": folder_id or str(uuid.uuid4()), "parent_id": parent, - "users_with_permission": users_with_permission - if users_with_permission is not None - else [sample_uuid()], + "users_with_permission": ( + users_with_permission + if users_with_permission is not None + else [sample_uuid()] + ), } diff --git a/tests/conftest.py b/tests/conftest.py index 122b76826..9019c2293 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -905,9 +905,11 @@ def create_service_templates(service_id, number_of_templates=4): "{}_template_{}".format(template_type, template_number), template_type, "{} template {} content".format(template_type, template_number), - subject="{} template {} subject".format(template_type, template_number) - if template_type == "email" - else None, + subject=( + "{} template {} subject".format(template_type, template_number) + if template_type == "email" + else None + ), ) ) @@ -1102,9 +1104,9 @@ def active_user_with_permission_to_other_service( active_user_with_permission_to_two_services["permissions"].pop(SERVICE_ONE_ID) active_user_with_permission_to_two_services["services"].pop(0) active_user_with_permission_to_two_services["name"] = "Service Two User" - active_user_with_permission_to_two_services[ - "email_address" - ] = "service-two-user@test.gsa.gov" + active_user_with_permission_to_two_services["email_address"] = ( + "service-two-user@test.gsa.gov" + ) return active_user_with_permission_to_two_services From f332587b377788ba00e4358a0159c40b52fd4bc1 Mon Sep 17 00:00:00 2001 From: Kenneth Kehl <@kkehl@flexion.us> Date: Mon, 26 Feb 2024 11:48:06 -0800 Subject: [PATCH 03/30] handle case where we are trying to build on github and haven't deployed yet --- app/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/config.py b/app/config.py index 02394aa84..b1bdeafd8 100644 --- a/app/config.py +++ b/app/config.py @@ -36,7 +36,7 @@ class Config(object): NR_BROWSER_KEY = getenv("NR_BROWSER_KEY") settings = newrelic.agent.global_settings() NR_MONITOR_ON = settings and settings.monitor_mode - COMMIT_HASH = getenv("COMMIT_HASH") + COMMIT_HASH = getenv("COMMIT_HASH", "Unknown") TEMPLATE_PREVIEW_API_HOST = getenv( "TEMPLATE_PREVIEW_API_HOST", "http://localhost:9999" From d5f40dffe1ef3bd31a05aafe943d97add4272a17 Mon Sep 17 00:00:00 2001 From: Jonathan Bobel Date: Tue, 27 Feb 2024 11:53:51 -0500 Subject: [PATCH 04/30] Commit before merge --- app/assets/javascripts/loginAlert.js | 35 ++++++++++++++ .../uswds/_uswds-theme-custom-styles.scss | 6 +++ app/main/forms.py | 16 ++++--- app/main/views/api_keys.py | 22 +++++---- app/main/views/manage_users.py | 22 +++++---- app/main/views/performance.py | 6 +-- app/main/views/send.py | 28 ++++++----- app/main/views/service_settings.py | 24 ++++++---- app/templates/views/signin.html | 10 +++- gulpfile.js | 1 + tests/app/main/views/test_accept_invite.py | 6 +-- tests/app/main/views/test_manage_users.py | 6 +-- tests/app/main/views/test_template_folders.py | 8 ++-- tests/conftest.py | 14 +++--- tests/javascripts/loginAlert.test.js | 48 +++++++++++++++++++ 15 files changed, 187 insertions(+), 65 deletions(-) create mode 100644 app/assets/javascripts/loginAlert.js create mode 100644 tests/javascripts/loginAlert.test.js diff --git a/app/assets/javascripts/loginAlert.js b/app/assets/javascripts/loginAlert.js new file mode 100644 index 000000000..67ed439ae --- /dev/null +++ b/app/assets/javascripts/loginAlert.js @@ -0,0 +1,35 @@ +(function (window) { + +// Set the target date (10 days before March 15th, 2024) + const targetDate = new Date("April 9, 2024 00:00:00").getTime(); + + // Function to update the countdown display + function updateCountdown() { + const now = new Date().getTime(); + const difference = targetDate - now; + + // Time calculations for days only + const days = Math.floor(difference / (1000 * 60 * 60 * 24)); + + // Visibility logic + if (days < 0) { + // Hide if more than 10 days away OR if already past the date + document.getElementById("countdown-container").style.display = "none"; + } else { + // Show if 10 days or less remaining + document.getElementById("countdown-container").style.display = "block"; + document.getElementById("countdown").innerHTML = days + " days "; + } + + } + + // Expose the updateCountdown function to the outside world + window.updateCountdown = updateCountdown; + + // Initial display update + updateCountdown(); + + // Update the countdown every second (inside the IIFE) + setInterval(updateCountdown, 1000); + +})(window); diff --git a/app/assets/sass/uswds/_uswds-theme-custom-styles.scss b/app/assets/sass/uswds/_uswds-theme-custom-styles.scss index addf9cc7a..05cfab466 100644 --- a/app/assets/sass/uswds/_uswds-theme-custom-styles.scss +++ b/app/assets/sass/uswds/_uswds-theme-custom-styles.scss @@ -552,3 +552,9 @@ details form { .edit-textbox-error-mt { margin-top: 1.5rem; } + +// Login page + +#countdown-container { + display: none; // Hide the countdown timer +} diff --git a/app/main/forms.py b/app/main/forms.py index c01ce8fcc..2e6655cc5 100644 --- a/app/main/forms.py +++ b/app/main/forms.py @@ -1781,12 +1781,16 @@ class TemplateAndFoldersSelectionForm(Form): None, [ # ('email', 'Email') if 'email' in available_template_types else None, - ("sms", "Start with a blank template") - if "sms" in available_template_types - else None, - ("copy-existing", "Copy an existing template") - if allow_adding_copy_of_template - else None, + ( + ("sms", "Start with a blank template") + if "sms" in available_template_types + else None + ), + ( + ("copy-existing", "Copy an existing template") + if allow_adding_copy_of_template + else None + ), ], ) ) diff --git a/app/main/views/api_keys.py b/app/main/views/api_keys.py index 4f8c3b29e..8cb28ba59 100644 --- a/app/main/views/api_keys.py +++ b/app/main/views/api_keys.py @@ -168,12 +168,14 @@ def api_callbacks(service_id): return render_template( "views/api/callbacks.html", - received_text_messages_callback=received_text_messages_callback["url"] - if received_text_messages_callback - else None, - delivery_status_callback=delivery_status_callback["url"] - if delivery_status_callback - else None, + received_text_messages_callback=( + received_text_messages_callback["url"] + if received_text_messages_callback + else None + ), + delivery_status_callback=( + delivery_status_callback["url"] if delivery_status_callback else None + ), ) @@ -262,9 +264,11 @@ def received_text_messages_callback(service_id): received_text_messages_callback = get_received_text_messages_callback() form = CallbackForm( - url=received_text_messages_callback.get("url") - if received_text_messages_callback - else "", + url=( + received_text_messages_callback.get("url") + if received_text_messages_callback + else "" + ), bearer_token=dummy_bearer_token if received_text_messages_callback else "", ) diff --git a/app/main/views/manage_users.py b/app/main/views/manage_users.py index 4ab20f363..1b80c659e 100644 --- a/app/main/views/manage_users.py +++ b/app/main/views/manage_users.py @@ -122,16 +122,18 @@ def edit_user_permissions(service_id, user_id): form = form_class.from_user( user, service_id, - folder_permissions=None - if user.platform_admin - else [ - f["id"] - for f in current_service.all_template_folders - if user.has_template_folder_permission(f) - ], - all_template_folders=None - if user.platform_admin - else current_service.all_template_folders, + folder_permissions=( + None + if user.platform_admin + else [ + f["id"] + for f in current_service.all_template_folders + if user.has_template_folder_permission(f) + ] + ), + all_template_folders=( + None if user.platform_admin else current_service.all_template_folders + ), ) if form.validate_on_submit(): diff --git a/app/main/views/performance.py b/app/main/views/performance.py index 13445967b..1d2a4d1bc 100644 --- a/app/main/views/performance.py +++ b/app/main/views/performance.py @@ -34,8 +34,8 @@ def performance(): stats["average_percentage_under_10_seconds"] = mean( [row["percentage_under_10_seconds"] for row in stats["processing_time"]] or [0] ) - stats[ - "count_of_live_services_and_organizations" - ] = status_api_client.get_count_of_live_services_and_organizations() + stats["count_of_live_services_and_organizations"] = ( + status_api_client.get_count_of_live_services_and_organizations() + ) return render_template("views/performance.html", **stats) diff --git a/app/main/views/send.py b/app/main/views/send.py index 4332c7ddb..6c786e3ac 100644 --- a/app/main/views/send.py +++ b/app/main/views/send.py @@ -52,12 +52,14 @@ def get_example_csv_fields(column_headers, use_example_as_example, submitted_fie def get_example_csv_rows(template, use_example_as_example=True, submitted_fields=False): return { - "email": ["test@example.com"] - if use_example_as_example - else [current_user.email_address], - "sms": ["12223334444"] - if use_example_as_example - else [current_user.mobile_number], + "email": ( + ["test@example.com"] + if use_example_as_example + else [current_user.email_address] + ), + "sms": ( + ["12223334444"] if use_example_as_example else [current_user.mobile_number] + ), }[template.template_type] + get_example_csv_fields( ( placeholder @@ -511,12 +513,14 @@ def _check_messages(service_id, template_id, upload_id, preview_row): template=template, max_initial_rows_shown=50, max_errors_shown=50, - guestlist=itertools.chain.from_iterable( - [user.name, user.mobile_number, user.email_address] - for user in Users(service_id) - ) - if current_service.trial_mode - else None, + guestlist=( + itertools.chain.from_iterable( + [user.name, user.mobile_number, user.email_address] + for user in Users(service_id) + ) + if current_service.trial_mode + else None + ), remaining_messages=remaining_messages, allow_international_sms=current_service.has_permission("international_sms"), ) diff --git a/app/main/views/service_settings.py b/app/main/views/service_settings.py index 1cac1410c..628ac59e5 100644 --- a/app/main/views/service_settings.py +++ b/app/main/views/service_settings.py @@ -477,9 +477,11 @@ def service_edit_email_reply_to(service_id, reply_to_email_id): current_service.id, reply_to_email_id=reply_to_email_id, email_address=form.email_address.data, - is_default=True - if reply_to_email_address["is_default"] - else form.is_default.data, + is_default=( + True + if reply_to_email_address["is_default"] + else form.is_default.data + ), ) return redirect(url_for(".service_email_reply_to", service_id=service_id)) try: @@ -499,9 +501,11 @@ def service_edit_email_reply_to(service_id, reply_to_email_id): ".service_verify_reply_to_address", service_id=service_id, notification_id=notification_id, - is_default=True - if reply_to_email_address["is_default"] - else form.is_default.data, + is_default=( + True + if reply_to_email_address["is_default"] + else form.is_default.data + ), replace=reply_to_email_id, ) ) @@ -702,9 +706,11 @@ def service_edit_sms_sender(service_id, sms_sender_id): service_api_client.update_sms_sender( current_service.id, sms_sender_id=sms_sender_id, - sms_sender=sms_sender["sms_sender"] - if is_inbound_number - else form.sms_sender.data.replace("\r", ""), + sms_sender=( + sms_sender["sms_sender"] + if is_inbound_number + else form.sms_sender.data.replace("\r", "") + ), is_default=True if sms_sender["is_default"] else form.is_default.data, ) return redirect(url_for(".service_sms_senders", service_id=service_id)) diff --git a/app/templates/views/signin.html b/app/templates/views/signin.html index 4ee655127..398a39274 100644 --- a/app/templates/views/signin.html +++ b/app/templates/views/signin.html @@ -13,8 +13,16 @@ {% block maincolumn_content %}
+
+
+

+ You have left to use login.gov to sign in +

+
+
+
+
- {% if again %}

You need to sign in again

{% if other_device %} diff --git a/gulpfile.js b/gulpfile.js index 6828bcaf1..79f976035 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -123,6 +123,7 @@ const javascripts = () => { paths.src + 'javascripts/homepage.js', paths.src + 'javascripts/timeoutPopup.js', paths.src + 'javascripts/date.js', + paths.src + 'javascripts/loginAlert.js', paths.src + 'javascripts/main.js', ]) .pipe(plugins.prettyerror()) diff --git a/tests/app/main/views/test_accept_invite.py b/tests/app/main/views/test_accept_invite.py index 1deeca299..900ff4bf5 100644 --- a/tests/app/main/views/test_accept_invite.py +++ b/tests/app/main/views/test_accept_invite.py @@ -218,7 +218,7 @@ def test_if_existing_user_accepts_twice_they_redirect_to_sign_in( assert ( page.h1.string, - page.select("main p")[0].text.strip(), + page.select("main p")[1].text.strip(), ) == ( "You need to sign in again", "We signed you out because you have not used Notify for a while.", @@ -332,7 +332,7 @@ def test_existing_user_of_service_get_redirected_to_signin( assert ( page.h1.string, - page.select("main p")[0].text.strip(), + page.select("main p")[1].text.strip(), ) == ( "You need to sign in again", "We signed you out because you have not used Notify for a while.", @@ -421,7 +421,7 @@ def test_existing_signed_out_user_accept_invite_redirects_to_sign_in( assert mock_accept_invite.call_count == 1 assert ( page.h1.string, - page.select("main p")[0].text.strip(), + page.select("main p")[1].text.strip(), ) == ( "You need to sign in again", "We signed you out because you have not used Notify for a while.", diff --git a/tests/app/main/views/test_manage_users.py b/tests/app/main/views/test_manage_users.py index 9bdabf925..c3d128155 100644 --- a/tests/app/main/views/test_manage_users.py +++ b/tests/app/main/views/test_manage_users.py @@ -862,9 +862,9 @@ def test_should_show_page_if_prefilled_user_is_already_invited( mock_get_invites_for_service, platform_admin_user, ): - active_user_with_permission_to_other_service[ - "email_address" - ] = "user_1@testnotify.gsa.gov" + active_user_with_permission_to_other_service["email_address"] = ( + "user_1@testnotify.gsa.gov" + ) client_request.login(platform_admin_user) mocker.patch( "app.models.user.user_api_client.get_user", diff --git a/tests/app/main/views/test_template_folders.py b/tests/app/main/views/test_template_folders.py index fae020e58..0bf2fcb08 100644 --- a/tests/app/main/views/test_template_folders.py +++ b/tests/app/main/views/test_template_folders.py @@ -31,9 +31,11 @@ def _folder(name, folder_id=None, parent=None, users_with_permission=None): "name": name, "id": folder_id or str(uuid.uuid4()), "parent_id": parent, - "users_with_permission": users_with_permission - if users_with_permission is not None - else [sample_uuid()], + "users_with_permission": ( + users_with_permission + if users_with_permission is not None + else [sample_uuid()] + ), } diff --git a/tests/conftest.py b/tests/conftest.py index 6c4f94b4f..4c2ceeea9 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -904,9 +904,11 @@ def create_service_templates(service_id, number_of_templates=4): "{}_template_{}".format(template_type, template_number), template_type, "{} template {} content".format(template_type, template_number), - subject="{} template {} subject".format(template_type, template_number) - if template_type == "email" - else None, + subject=( + "{} template {} subject".format(template_type, template_number) + if template_type == "email" + else None + ), ) ) @@ -1101,9 +1103,9 @@ def active_user_with_permission_to_other_service( active_user_with_permission_to_two_services["permissions"].pop(SERVICE_ONE_ID) active_user_with_permission_to_two_services["services"].pop(0) active_user_with_permission_to_two_services["name"] = "Service Two User" - active_user_with_permission_to_two_services[ - "email_address" - ] = "service-two-user@test.gsa.gov" + active_user_with_permission_to_two_services["email_address"] = ( + "service-two-user@test.gsa.gov" + ) return active_user_with_permission_to_two_services diff --git a/tests/javascripts/loginAlert.test.js b/tests/javascripts/loginAlert.test.js new file mode 100644 index 000000000..4bb0d3eaa --- /dev/null +++ b/tests/javascripts/loginAlert.test.js @@ -0,0 +1,48 @@ +beforeAll(() => { + jest.spyOn(global, 'setTimeout'); + const sessionTimerModule = require('../../app/assets/javascripts/loginAlert.js'); + window.GOVUK.modules.start(); +}); + +jest.useFakeTimers(); +const targetDate = new Date("March 5, 2024 00:00:00"); // Reference point + +test('Hides the countdown if more than 10 days away', () => { + jest.setSystemTime(targetDate.getTime() - 12 * 24 * 60 * 60 * 1000); // 12 days before + + window.updateCountdown(); // Update the countdown display + + expect(document.getElementById("countdown-container").style.display).toBe("none"); +}); + +test('Shows the countdown if 10 days or less away', () => { + jest.setSystemTime(targetDate.getTime() - 8 * 24 * 60 * 60 * 1000); + + window.updateCountdown(); + + expect(document.getElementById("countdown-container").style.display).toBe("block"); +}); + +test('Displays the correct number of days', () => { + jest.setSystemTime(targetDate.getTime() - 5 * 24 * 60 * 60 * 1000); + + window.updateCountdown(); + + expect(document.getElementById("countdown").textContent).toBe("5 days "); +}); + +test('Hides the countdown if the target date has passed', () => { + jest.setSystemTime(targetDate.getTime() + 2 * 24 * 60 * 60 * 1000); + + window.updateCountdown(); + + expect(document.getElementById("countdown-container").style.display).toBe("none"); +}); + +test('Displays "Countdown Complete!" when the countdown finishes', () => { + jest.setSystemTime(targetDate.getTime()); + + window.updateCountdown(); + + expect(document.getElementById("countdown").textContent).toBe("Countdown Complete!"); +}); From f49f27bcdf080b3bfd544d5ec70c91e72a8adc3e Mon Sep 17 00:00:00 2001 From: Jonathan Bobel Date: Wed, 28 Feb 2024 16:07:49 -0500 Subject: [PATCH 05/30] Content updates to pricing page --- app/templates/views/pricing/index.html | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/app/templates/views/pricing/index.html b/app/templates/views/pricing/index.html index 73c67770e..f3f13cf8c 100644 --- a/app/templates/views/pricing/index.html +++ b/app/templates/views/pricing/index.html @@ -15,7 +15,7 @@ Pricing {{ content_metadata( data={ -"Last updated": "January 25, 2024" +"Last updated": "February 5, 2024" } ) }} @@ -30,7 +30,8 @@ more parts towards the allowance if you:

Long text messages

-

If a text message is longer than 160 characters (including spaces), it counts as more than one message part.

+

If a text message is longer than 160 characters (including spaces and service name), it counts as more than one message +part.

{% call mapping_table( @@ -55,6 +56,13 @@ more parts towards the allowance if you:

{% endcall %}
+

Personalization

+

Personalization can change the length of messages. For example, if you are personalizing with a first name, Fred is +significantly shorter than Alexander. When you are evaluating how long a message is, you need to consider variations in +message length based on personalization.

+

Before you send messages, Notify will let you know how many messages you are sending, the number of parts you are using, +and the number of parts you’ll have left.

+

Signs and symbols

@@ -158,9 +166,4 @@ more parts towards the allowance if you:

{% endcall %}
-

Trial mode

-

When a new service is added, it will start in trial mode. Moving a service out of trial mode is subject to approval by -the Notify.gov team. Additional unique services may be added, although moving each service out of trial mode is subject -to approval by the Notify.gov team.

- {% endblock %} From 65f365ab6de4a9c8d890defebafa508e7fa57c88 Mon Sep 17 00:00:00 2001 From: Jonathan Bobel Date: Wed, 28 Feb 2024 16:11:18 -0500 Subject: [PATCH 06/30] Guidance content update --- app/templates/views/guidance/index.html | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/app/templates/views/guidance/index.html b/app/templates/views/guidance/index.html index b7d6ffa1a..1f8107d6d 100644 --- a/app/templates/views/guidance/index.html +++ b/app/templates/views/guidance/index.html @@ -41,7 +41,7 @@

To create and format your message

  1. All messages start from a template
  2. -
  3. Click “Send Messages”. You’ll see existing templates.
  4. +
  5. Click “Send Messages”. You'll see existing templates.
  6. Add a new template or choose an existing template and select Edit.
@@ -69,7 +69,7 @@

Personalize your content

Personalizing your content can increase response rates and help the recipient know the text is legitimate.

    -
  • Including a person’s first name increases response rates.
  • +
  • Including a person's first name increases response rates.
  • Specific details such as time and location of an appointment or where suspected fraud use occurred encourages action.
@@ -84,6 +84,9 @@

To personalize with the recipient's first name and include a reference number:

State WIC: Hello ((first name)), your reference is ((ref number)). Please provide this number when you call 123-123-1234 to make an appointment.

+

Note that variations in the length of personalized content can impact the length of specific messages, and may affect + the number of parts used.

+ {# Add conditional content #}

Add conditional content

Conditional (or optional) content appears only when a recipient meets certain criteria. This feature allows you to make From 067b637f75b990da79de7d5bab47e0a884935464 Mon Sep 17 00:00:00 2001 From: Jonathan Bobel Date: Wed, 28 Feb 2024 16:15:33 -0500 Subject: [PATCH 07/30] Changed the title of the pricing page to Message parts --- app/templates/views/pricing/index.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/templates/views/pricing/index.html b/app/templates/views/pricing/index.html index f3f13cf8c..7f1e07349 100644 --- a/app/templates/views/pricing/index.html +++ b/app/templates/views/pricing/index.html @@ -6,12 +6,12 @@ {% extends "content_template.html" %} {% block per_page_title %} -Pricing +Message parts {% endblock %} {% block content_column_content %} -

Pricing

+

Message parts

{{ content_metadata( data={ From 507973f9ae52514353adeffbc81a9e6c1451be82 Mon Sep 17 00:00:00 2001 From: Jonathan Bobel Date: Fri, 1 Mar 2024 09:34:25 -0500 Subject: [PATCH 08/30] Edited the test, updated content --- app/assets/javascripts/loginAlert.js | 2 +- app/templates/views/signin.html | 22 +++++++++++++--------- tests/javascripts/loginAlert.test.js | 22 +++++++++++++--------- 3 files changed, 27 insertions(+), 19 deletions(-) diff --git a/app/assets/javascripts/loginAlert.js b/app/assets/javascripts/loginAlert.js index 67ed439ae..1f3281788 100644 --- a/app/assets/javascripts/loginAlert.js +++ b/app/assets/javascripts/loginAlert.js @@ -12,7 +12,7 @@ const days = Math.floor(difference / (1000 * 60 * 60 * 24)); // Visibility logic - if (days < 0) { + if (days < 0 || days > 10) { // Hide if more than 10 days away OR if already past the date document.getElementById("countdown-container").style.display = "none"; } else { diff --git a/app/templates/views/signin.html b/app/templates/views/signin.html index 398a39274..8773fba24 100644 --- a/app/templates/views/signin.html +++ b/app/templates/views/signin.html @@ -13,10 +13,11 @@ {% block maincolumn_content %}
-
+
+

Login.gov is required by April 9, 2024

- You have left to use login.gov to sign in + You have left to use Login.gov to sign in

@@ -50,17 +51,20 @@ {% endcall %}
-

Notify.gov is changing the Sign in experience to Login.gov on March x, 2024

+

Notify.gov is changing the sign-in experience to Login.gov effective
April 9, 2024

Why are we doing this?

    -
  • One single source for signing in: You can use login.gov for other sign in forms within the government
  • -
  • Security: It's really secure and trustworthy
  • -
  • Fast and easy: It's fast and easy
  • +
  • Enhanced security: Login.gov is really secure and trustworthy
  • +
  • One single source for signing in: You can use Login.gov for other services within the federal government
  • +
  • 2FA flexibility: Login.gov supports multiple methods for users to verify their identity.
  • +
+

What do I need to do?

+
    +
  • If you have a Login.gov account, start using it to sign in to Notify today.
  • +
  • If you don’t have a Login.gov account, you must create one by April 9, 2024 to continue to access Notify.
-

Don't have a login.gov account?

-

If you don't have an account already, sign up here:

- Create Login.gov account + Create Login.gov account
diff --git a/tests/javascripts/loginAlert.test.js b/tests/javascripts/loginAlert.test.js index 4bb0d3eaa..895aa3647 100644 --- a/tests/javascripts/loginAlert.test.js +++ b/tests/javascripts/loginAlert.test.js @@ -1,11 +1,23 @@ beforeAll(() => { jest.spyOn(global, 'setTimeout'); + + document.body.innerHTML = ` +
+
+

Login.gov is required by April 9, 2024

+

+ You have left to use Login.gov to sign in +

+
+
+ ` + const sessionTimerModule = require('../../app/assets/javascripts/loginAlert.js'); window.GOVUK.modules.start(); }); jest.useFakeTimers(); -const targetDate = new Date("March 5, 2024 00:00:00"); // Reference point +const targetDate = new Date("April 9, 2024 00:00:00"); // Reference point test('Hides the countdown if more than 10 days away', () => { jest.setSystemTime(targetDate.getTime() - 12 * 24 * 60 * 60 * 1000); // 12 days before @@ -38,11 +50,3 @@ test('Hides the countdown if the target date has passed', () => { expect(document.getElementById("countdown-container").style.display).toBe("none"); }); - -test('Displays "Countdown Complete!" when the countdown finishes', () => { - jest.setSystemTime(targetDate.getTime()); - - window.updateCountdown(); - - expect(document.getElementById("countdown").textContent).toBe("Countdown Complete!"); -}); From 81d89f464a9468baff0d6be69e3744e330dec4b1 Mon Sep 17 00:00:00 2001 From: Jonathan Bobel Date: Mon, 4 Mar 2024 09:51:13 -0500 Subject: [PATCH 09/30] small responsive styling change --- app/templates/views/signin.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/templates/views/signin.html b/app/templates/views/signin.html index 8773fba24..1b8201275 100644 --- a/app/templates/views/signin.html +++ b/app/templates/views/signin.html @@ -50,7 +50,7 @@ {{ page_footer("Continue", secondary_link=password_reset_url, secondary_link_text="Forgot your password?") }} {% endcall %}
-
+

Notify.gov is changing the sign-in experience to Login.gov effective
April 9, 2024

Why are we doing this?

    From 0bf289e23ddcd8285199ce0d025b0858938f719f Mon Sep 17 00:00:00 2001 From: Beverly Nguyen Date: Wed, 6 Mar 2024 11:49:04 -0800 Subject: [PATCH 10/30] removed macro and added footer.html --- app/templates/admin_template.html | 4 +- .../new/components/footer/footer.html | 107 ++++++++++++++++++ 2 files changed, 109 insertions(+), 2 deletions(-) create mode 100644 app/templates/new/components/footer/footer.html diff --git a/app/templates/admin_template.html b/app/templates/admin_template.html index 6b33fed05..1352d8a75 100644 --- a/app/templates/admin_template.html +++ b/app/templates/admin_template.html @@ -175,7 +175,7 @@ {% endblock %} {% block footer %} - + {% if current_service and current_service.research_mode %} {% set meta_suffix = 'Built by the Technology Transformation Servicesresearch mode' %} {% else %} @@ -249,7 +249,7 @@ "html": meta_suffix } }) }} - + {% if current_user.is_authenticated %} {% block sessionUserWarning %} diff --git a/app/templates/new/components/footer/footer.html b/app/templates/new/components/footer/footer.html new file mode 100644 index 000000000..936078250 --- /dev/null +++ b/app/templates/new/components/footer/footer.html @@ -0,0 +1,107 @@ +
    + {# #} + +
    + +
    +
    +
    + +
    +

    beta.notify.gov

    +

    An official website of the General Services Administration

    +
    +
    +
    + +
    +
    +
    + Looking for U.S. government information and services? +
    + Visit USA.gov +
    +
    +
    From 68163aa6d7a5bf9e3bdbf3fe568c63dbbabe11a1 Mon Sep 17 00:00:00 2001 From: Kenneth Kehl <@kkehl@flexion.us> Date: Wed, 6 Mar 2024 11:49:19 -0800 Subject: [PATCH 11/30] Use USWDS error formatting for file too big error (notify-admin-1237) --- app/main/forms.py | 6 +++++- app/main/views/send.py | 8 ++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/app/main/forms.py b/app/main/forms.py index 2e6655cc5..70dbfa37f 100644 --- a/app/main/forms.py +++ b/app/main/forms.py @@ -1226,7 +1226,11 @@ class CsvUploadForm(StripWhitespaceForm): validators=[ DataRequired(message="Please pick a file"), CsvFileValidator(), - FileSize(max_size=10e6, message="File must be smaller than 10Mb"), # 10Mb + FileSize( + max_size=10e6, + message="File must be smaller than 10Mb. If you are trying to upload an Excel file, \ + please export the contents in the CSV format and then try again.", + ), # 10Mb ], ) diff --git a/app/main/views/send.py b/app/main/views/send.py index 6c786e3ac..5117c8e32 100644 --- a/app/main/views/send.py +++ b/app/main/views/send.py @@ -6,6 +6,7 @@ from zipfile import BadZipFile from flask import abort, flash, redirect, render_template, request, session, url_for from flask_login import current_user +from markupsafe import Markup from notifications_python_client.errors import HTTPError from notifications_utils import SMS_CHAR_COUNT_LIMIT from notifications_utils.insensitive_dict import InsensitiveDict @@ -151,8 +152,11 @@ def send_messages(service_id, template_id): # just show the first error, as we don't expect the form to have more # than one, since it only has one field first_field_errors = list(form.errors.values())[0] - flash(first_field_errors[0]) - + error_message = '' + error_message = f"{error_message}{first_field_errors[0]}" + error_message = f"{error_message}" + error_message = Markup(error_message) + flash(error_message) column_headings = get_spreadsheet_column_headings_from_template(template) return render_template( From 87b47d94df25431d3970e43fefb35815dceee4df Mon Sep 17 00:00:00 2001 From: Beverly Nguyen Date: Wed, 6 Mar 2024 13:04:41 -0800 Subject: [PATCH 12/30] moved usa-identifier to footer tag --- .../new/components/footer/footer.html | 111 +++++++++--------- 1 file changed, 55 insertions(+), 56 deletions(-) diff --git a/app/templates/new/components/footer/footer.html b/app/templates/new/components/footer/footer.html index 936078250..fa22b6a88 100644 --- a/app/templates/new/components/footer/footer.html +++ b/app/templates/new/components/footer/footer.html @@ -48,60 +48,59 @@
- - -
-
-
- -
-

beta.notify.gov

-

An official website of the General Services Administration

-
-
-
- -
-
-
- Looking for U.S. government information and services? +
+
+
+ +
+

beta.notify.gov

+

An official website of the General Services Administration

+
- Visit USA.gov -
-
-
+ + +
+
+
+ Looking for U.S. government information and services? +
+ Visit USA.gov +
+
+ + From 492f79827468c419e15cb810443e7cca3ff213f6 Mon Sep 17 00:00:00 2001 From: Kenneth Kehl <@kkehl@flexion.us> Date: Fri, 8 Mar 2024 09:04:56 -0800 Subject: [PATCH 13/30] update login.gov stuff to use user uuid instead of email (notify-admin-1277) --- app/main/views/sign_in.py | 12 +++++------- app/notify_client/user_api_client.py | 10 ++++++++++ 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/app/main/views/sign_in.py b/app/main/views/sign_in.py index c6eaee87e..d39cb89af 100644 --- a/app/main/views/sign_in.py +++ b/app/main/views/sign_in.py @@ -53,22 +53,19 @@ def _get_access_token(code, state): # JWT expiration time (10 minute maximum) "exp": int(time.time()) + (10 * 60), } - current_app.logger.warning(f"Here is the raw payload {payload}") token = jwt.encode(payload, keystring, algorithm="RS256") base_url = f"{access_token_url}?" cli_assert = f"client_assertion={token}" cli_assert_type = "client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer" code_param = f"code={code}" url = f"{base_url}{cli_assert}&{cli_assert_type}&{code_param}&grant_type=authorization_code" - current_app.logger.info(f"This is the url we use to get the access token: {url}") headers = {"Authorization": "Bearer %s" % token} response = requests.post(url, headers=headers) - current_app.logger.info(f"GOT A RESPONSE {response.json()}") access_token = response.json()["access_token"] return access_token -def _get_user_email(access_token): +def _get_user_email_and_uuid(access_token): headers = {"Authorization": "Bearer %s" % access_token} user_info_url = os.getenv("LOGIN_DOT_GOV_USER_INFO_URL") user_attributes = requests.get( @@ -76,7 +73,8 @@ def _get_user_email(access_token): headers=headers, ) user_email = user_attributes.json()["email"] - return user_email + user_uuid = user_attributes.json()["sub"] + return user_email, user_uuid @main.route("/sign-in", methods=(["GET", "POST"])) @@ -88,11 +86,11 @@ def sign_in(): login_gov_error = request.args.get("error") if code and state: access_token = _get_access_token(code, state) - user_email = _get_user_email(access_token) + user_email, user_uuid = _get_user_email_and_uuid(access_token) redirect_url = request.args.get("next") # activate the user - user = user_api_client.get_user_by_email(user_email) + user = user_api_client.get_user_by_uuid_or_email(user_uuid, user_email) activate_user(user["id"]) return redirect(url_for("main.show_accounts_or_dashboard", next=redirect_url)) diff --git a/app/notify_client/user_api_client.py b/app/notify_client/user_api_client.py index bfe2f7182..a17059e52 100644 --- a/app/notify_client/user_api_client.py +++ b/app/notify_client/user_api_client.py @@ -44,6 +44,16 @@ class UserApiClient(NotifyAdminAPIClient): user_data = self.post("/user/email", data={"email": email_address}) return user_data["data"] + def get_user_by_uuid_or_email(self, user_uuid, email_address): + + user_data = self.post( + "/user/get-login-gov-user", + data={"login_uuid": user_uuid, "email": email_address}, + ) + if user_data is None: + raise Exception("User not found") + return user_data["data"] + def get_user_by_email_or_none(self, email_address): try: return self.get_user_by_email(email_address) From ed5902b38ebeee768d0d067238848a56114735d9 Mon Sep 17 00:00:00 2001 From: Jonathan Bobel Date: Tue, 12 Mar 2024 13:23:13 -0400 Subject: [PATCH 14/30] Updates to favicon --- app/assets/images/android-chrome-192x192.png | Bin 5762 -> 6135 bytes app/assets/images/android-chrome-256x256.png | Bin 7443 -> 8019 bytes app/assets/images/apple-touch-icon.png | Bin 4316 -> 4588 bytes app/assets/images/favicon-16x16.png | Bin 969 -> 994 bytes app/assets/images/favicon-32x32.png | Bin 1558 -> 1537 bytes app/assets/images/favicon.ico | Bin 15086 -> 15086 bytes app/assets/images/mstile-150x150.png | Bin 0 -> 3865 bytes app/assets/images/safari-pinned-tab.svg | 21 ++++++++++--------- app/assets/images/site.webmanifest | 20 +++++++++++++++++- app/templates/main_template.html | 10 ++++++--- 10 files changed, 37 insertions(+), 14 deletions(-) create mode 100644 app/assets/images/mstile-150x150.png diff --git a/app/assets/images/android-chrome-192x192.png b/app/assets/images/android-chrome-192x192.png index b8f3eb8460da5bd299c6bfbfe45a4f79da873079..a1e8670ca672b719560a3b05417421aae446d994 100644 GIT binary patch literal 6135 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 DhJ|Y$ diff --git a/app/assets/images/android-chrome-256x256.png b/app/assets/images/android-chrome-256x256.png index 7aae730c6352e0da2a3b67306d842f9b00fd8d90..40c5994922c3bb98b2273ee45f28efae4c474c53 100644 GIT binary patch literal 8019 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 IRP7`F7xcDn;Q#;t literal 7443 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 TZC#~&>JWgDo;il7>z?=@BqLG| diff --git a/app/assets/images/apple-touch-icon.png b/app/assets/images/apple-touch-icon.png index 0fafe5d3a26209aaf48c73345a362a4d493c756f..97c6d0efffc271f422c070f27b1c3100eb48608c 100644 GIT binary patch delta 4353 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 Ke8}~N`2Gia6)_(G delta 4079 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 r3a4*eIdSC75t$?GryD#LcF?X!o8D~h-Mx2r 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 literal 15086 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 literal 0 HcmV?d00001 diff --git a/app/assets/images/safari-pinned-tab.svg b/app/assets/images/safari-pinned-tab.svg index 4e16dae83..580be22c2 100644 --- a/app/assets/images/safari-pinned-tab.svg +++ b/app/assets/images/safari-pinned-tab.svg @@ -9,15 +9,16 @@ Created by potrace 1.14, written by Peter Selinger 2001-2017 - - - + + + diff --git a/app/assets/images/site.webmanifest b/app/assets/images/site.webmanifest index 45dc8a206..de65106f4 100644 --- a/app/assets/images/site.webmanifest +++ b/app/assets/images/site.webmanifest @@ -1 +1,19 @@ -{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"} \ No newline at end of file +{ + "name": "", + "short_name": "", + "icons": [ + { + "src": "/android-chrome-192x192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "/android-chrome-256x256.png", + "sizes": "256x256", + "type": "image/png" + } + ], + "theme_color": "#ffffff", + "background_color": "#ffffff", + "display": "standalone" +} diff --git a/app/templates/main_template.html b/app/templates/main_template.html index 0beaca91a..6d745d368 100644 --- a/app/templates/main_template.html +++ b/app/templates/main_template.html @@ -19,11 +19,15 @@ {% block headIcons %} - - + + + + - + + + {% endblock %} {% block head %}{% endblock %} From 0ae369d54bc9b644db8a8ab0f33299642ac67814 Mon Sep 17 00:00:00 2001 From: Jonathan Bobel Date: Tue, 12 Mar 2024 13:27:37 -0400 Subject: [PATCH 15/30] Updated the date to April 16th instead of April 9 --- app/assets/javascripts/loginAlert.js | 2 +- app/templates/views/signin.html | 6 +++--- tests/javascripts/loginAlert.test.js | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/assets/javascripts/loginAlert.js b/app/assets/javascripts/loginAlert.js index 1f3281788..84c2ee6a8 100644 --- a/app/assets/javascripts/loginAlert.js +++ b/app/assets/javascripts/loginAlert.js @@ -1,7 +1,7 @@ (function (window) { // Set the target date (10 days before March 15th, 2024) - const targetDate = new Date("April 9, 2024 00:00:00").getTime(); + const targetDate = new Date("April 16, 2024 00:00:00").getTime(); // Function to update the countdown display function updateCountdown() { diff --git a/app/templates/views/signin.html b/app/templates/views/signin.html index 1b8201275..e3e478a91 100644 --- a/app/templates/views/signin.html +++ b/app/templates/views/signin.html @@ -15,7 +15,7 @@
-

Login.gov is required by April 9, 2024

+

Login.gov is required by April 16, 2024

You have left to use Login.gov to sign in

@@ -51,7 +51,7 @@ {% endcall %}
-

Notify.gov is changing the sign-in experience to Login.gov effective
April 9, 2024

+

Notify.gov is changing the sign-in experience to Login.gov effective
April 16, 2024

Why are we doing this?

  • Enhanced security: Login.gov is really secure and trustworthy
  • @@ -61,7 +61,7 @@

    What do I need to do?

    • If you have a Login.gov account, start using it to sign in to Notify today.
    • -
    • If you don’t have a Login.gov account, you must create one by April 9, 2024 to continue to access Notify.
    • +
    • If you don’t have a Login.gov account, you must create one by April 16, 2024 to continue to access Notify.
    Create Login.gov account diff --git a/tests/javascripts/loginAlert.test.js b/tests/javascripts/loginAlert.test.js index 895aa3647..085434b6a 100644 --- a/tests/javascripts/loginAlert.test.js +++ b/tests/javascripts/loginAlert.test.js @@ -4,7 +4,7 @@ beforeAll(() => { document.body.innerHTML = `
    -

    Login.gov is required by April 9, 2024

    +

    Login.gov is required by April 16, 2024

    You have left to use Login.gov to sign in

    @@ -17,7 +17,7 @@ beforeAll(() => { }); jest.useFakeTimers(); -const targetDate = new Date("April 9, 2024 00:00:00"); // Reference point +const targetDate = new Date("April 16, 2024 00:00:00"); // Reference point test('Hides the countdown if more than 10 days away', () => { jest.setSystemTime(targetDate.getTime() - 12 * 24 * 60 * 60 * 1000); // 12 days before From 429a456704d6f6e7fcdd54406ce3518f6ebf1156 Mon Sep 17 00:00:00 2001 From: Jonathan Bobel Date: Tue, 12 Mar 2024 13:37:44 -0400 Subject: [PATCH 16/30] Updating conditional logic --- app/templates/views/signin.html | 36 ++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/app/templates/views/signin.html b/app/templates/views/signin.html index e3e478a91..6b4952b0c 100644 --- a/app/templates/views/signin.html +++ b/app/templates/views/signin.html @@ -12,6 +12,7 @@ {% block maincolumn_content %} +{% if login_gov_enabled %}
    @@ -22,6 +23,7 @@
    +{% endif %}
    {% if again %} @@ -50,22 +52,24 @@ {{ page_footer("Continue", secondary_link=password_reset_url, secondary_link_text="Forgot your password?") }} {% endcall %}
    -
    -

    Notify.gov is changing the sign-in experience to Login.gov effective
    April 16, 2024

    -

    Why are we doing this?

    -
      -
    • Enhanced security: Login.gov is really secure and trustworthy
    • -
    • One single source for signing in: You can use Login.gov for other services within the federal government
    • -
    • 2FA flexibility: Login.gov supports multiple methods for users to verify their identity.
    • -
    -

    What do I need to do?

    -
      -
    • If you have a Login.gov account, start using it to sign in to Notify today.
    • -
    • If you don’t have a Login.gov account, you must create one by April 16, 2024 to continue to access Notify.
    • -
    -
    - Create Login.gov account + {% if login_gov_enabled %} +
    +

    Notify.gov is changing the sign-in experience to Login.gov effective
    April 16, 2024

    +

    Why are we doing this?

    +
      +
    • Enhanced security: Login.gov is really secure and trustworthy
    • +
    • One single source for signing in: You can use Login.gov for other services within the federal government
    • +
    • 2FA flexibility: Login.gov supports multiple methods for users to verify their identity.
    • +
    +

    What do I need to do?

    +
      +
    • If you have a Login.gov account, start using it to sign in to Notify today.
    • +
    • If you don’t have a Login.gov account, you must create one by April 16, 2024 to continue to access Notify.
    • +
    +
    + Create Login.gov account +
    -
    +{% endif %} {% endblock %} From 7deaf7146363d3844131ccf612d922bb4045767a Mon Sep 17 00:00:00 2001 From: Jonathan Bobel Date: Tue, 12 Mar 2024 14:29:16 -0400 Subject: [PATCH 17/30] Updated test --- tests/app/main/views/test_accept_invite.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/app/main/views/test_accept_invite.py b/tests/app/main/views/test_accept_invite.py index 900ff4bf5..1deeca299 100644 --- a/tests/app/main/views/test_accept_invite.py +++ b/tests/app/main/views/test_accept_invite.py @@ -218,7 +218,7 @@ def test_if_existing_user_accepts_twice_they_redirect_to_sign_in( assert ( page.h1.string, - page.select("main p")[1].text.strip(), + page.select("main p")[0].text.strip(), ) == ( "You need to sign in again", "We signed you out because you have not used Notify for a while.", @@ -332,7 +332,7 @@ def test_existing_user_of_service_get_redirected_to_signin( assert ( page.h1.string, - page.select("main p")[1].text.strip(), + page.select("main p")[0].text.strip(), ) == ( "You need to sign in again", "We signed you out because you have not used Notify for a while.", @@ -421,7 +421,7 @@ def test_existing_signed_out_user_accept_invite_redirects_to_sign_in( assert mock_accept_invite.call_count == 1 assert ( page.h1.string, - page.select("main p")[1].text.strip(), + page.select("main p")[0].text.strip(), ) == ( "You need to sign in again", "We signed you out because you have not used Notify for a while.", From 6cdc14433bebf1bbfbb0f7079f7bb9c67fc27a75 Mon Sep 17 00:00:00 2001 From: Jonathan Bobel Date: Wed, 13 Mar 2024 11:46:13 -0400 Subject: [PATCH 18/30] Content updated per PR comments --- app/templates/views/guidance/index.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/templates/views/guidance/index.html b/app/templates/views/guidance/index.html index 1f8107d6d..5a4238fea 100644 --- a/app/templates/views/guidance/index.html +++ b/app/templates/views/guidance/index.html @@ -41,7 +41,7 @@

    To create and format your message

    1. All messages start from a template
    2. -
    3. Click “Send Messages”. You'll see existing templates.
    4. +
    5. Click "Send Messages". You'll see existing templates.
    6. Add a new template or choose an existing template and select Edit.
    @@ -82,7 +82,7 @@

    Example

    To personalize with the recipient's first name and include a reference number:

    -

    State WIC: Hello ((first name)), your reference is ((ref number)). Please provide this number when you call 123-123-1234 to make an appointment.

    +

    State WIC: Hello ((first name)), your reference is ((ref number)). Please provide this number when you call 555-123-1234 to make an appointment.

    Note that variations in the length of personalized content can impact the length of specific messages, and may affect the number of parts used.

    @@ -109,7 +109,7 @@
  • If you want to make people who are homebound aware of the option of virtual visits (but not other message recipients):
    -

    State Medicaid: Please call 123-123-1234 to schedule an appointment. ((homebound??Virtual visits are available.))

    +

    State Medicaid: Please call 555-123-1234 to schedule an appointment. ((homebound??Virtual visits are available.))

  • If you want to send a messages in different languages to different recipients: @@ -234,7 +234,7 @@
  • Auto-response text:
    -

    State Agency: This number is unmonitored. To contact us, call us at 123-123-1234. We will never ask for personal details +

    State Agency: This number is unmonitored. To contact us, call us at 555-123-1234. We will never ask for personal details in a text. If you have questions about how to protect your privacy, see statename.gov/privacy.

  • From e1981d3c65959fd512eadadbf785f4f5b738eeb3 Mon Sep 17 00:00:00 2001 From: Jonathan Bobel Date: Wed, 13 Mar 2024 13:33:44 -0400 Subject: [PATCH 19/30] Auto reformat looks like --- app/main/views/send.py | 6 ++++-- tests/app/main/views/test_send.py | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/app/main/views/send.py b/app/main/views/send.py index b1cea53a8..560c5cb3a 100644 --- a/app/main/views/send.py +++ b/app/main/views/send.py @@ -560,7 +560,9 @@ def _check_messages(service_id, template_id, upload_id, preview_row): if preview_row < len(recipients) + 2: template.values = recipients[preview_row - 2].recipient_and_personalisation - simplifed_template.values = recipients[preview_row - 2].recipient_and_personalisation + simplifed_template.values = recipients[ + preview_row - 2 + ].recipient_and_personalisation elif preview_row > 2: abort(404) @@ -863,7 +865,7 @@ def _check_notification(service_id, template_id, exception=None): back_link_from_preview=back_link_from_preview, choose_time_form=choose_time_form, **(get_template_error_dict(exception) if exception else {}), - simplifed_template=simplifed_template + simplifed_template=simplifed_template, ) diff --git a/tests/app/main/views/test_send.py b/tests/app/main/views/test_send.py index 35309f57f..a33f975ba 100644 --- a/tests/app/main/views/test_send.py +++ b/tests/app/main/views/test_send.py @@ -2612,8 +2612,10 @@ def test_preview_notification_shows_preview( session["placeholders"] = {} page = client_request.post( - "main.preview_notification", service_id=service_one["id"], template_id=fake_uuid, - _expected_status=200 + "main.preview_notification", + service_id=service_one["id"], + template_id=fake_uuid, + _expected_status=200, ) assert page.h1.text.strip() == "Preview" assert (page.find_all("a", {"class": "usa-back-link"})[0]["href"]) == url_for( From 2717feab7b4229c7c53379f034fcc2893200aa21 Mon Sep 17 00:00:00 2001 From: Jonathan Bobel Date: Wed, 13 Mar 2024 16:07:39 -0400 Subject: [PATCH 20/30] Using a PNG instead of an SVG for the main logo as it was noted the SVG's font looked pixelated. I also changed the color of the text on the home page as well as its responsive size. --- app/assets/images/notify-logo.png | Bin 0 -> 21684 bytes .../sass/uswds/_uswds-theme-custom-styles.scss | 7 +++++++ .../components/components/header/template.njk | 2 +- 3 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 app/assets/images/notify-logo.png diff --git a/app/assets/images/notify-logo.png b/app/assets/images/notify-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..326d959b6113aaa0085684bd4618f333c5c3af1a GIT binary patch literal 21684 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 ts*dXHhV;;W7DjjowaUP&82%atJ6y2_H(LY8;YD Notify.gov logo -
    From 599652256e04a0bb66f6658bc79cbe0d8aa727ba Mon Sep 17 00:00:00 2001 From: Andrew Shumway Date: Wed, 13 Mar 2024 16:31:21 -0600 Subject: [PATCH 21/30] Add simulated SMS numbers to allow list in trial mode --- app/main/views/send.py | 31 ++++++++++++++++++++----------- tests/app/main/views/test_send.py | 6 ++++-- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/app/main/views/send.py b/app/main/views/send.py index b1cea53a8..81c62771c 100644 --- a/app/main/views/send.py +++ b/app/main/views/send.py @@ -1,4 +1,3 @@ -import itertools import time import uuid from string import ascii_uppercase @@ -517,19 +516,27 @@ def _check_messages(service_id, template_id, upload_id, preview_row): current_service, show_recipient=False, ) + + allow_list = [] + if current_service.trial_mode: + # Adding the simulated numbers to allow list + # so they can be sent in trial mode + for user in Users(service_id): + allow_list.extend([user.name, user.mobile_number, user.email_address]) + # Failed sms number + allow_list.extend(["simulated user", "+14254147167", "simulated@simulated.gov"]) + # Success sms number + allow_list.extend( + ["simulated user two", "+14254147755", "simulatedtwo@simulated.gov"] + ) + else: + allow_list = None recipients = RecipientCSV( contents, template=template or simplifed_template, max_initial_rows_shown=50, max_errors_shown=50, - guestlist=( - itertools.chain.from_iterable( - [user.name, user.mobile_number, user.email_address] - for user in Users(service_id) - ) - if current_service.trial_mode - else None - ), + guestlist=allow_list, remaining_messages=remaining_messages, allow_international_sms=current_service.has_permission("international_sms"), ) @@ -560,7 +567,9 @@ def _check_messages(service_id, template_id, upload_id, preview_row): if preview_row < len(recipients) + 2: template.values = recipients[preview_row - 2].recipient_and_personalisation - simplifed_template.values = recipients[preview_row - 2].recipient_and_personalisation + simplifed_template.values = recipients[ + preview_row - 2 + ].recipient_and_personalisation elif preview_row > 2: abort(404) @@ -863,7 +872,7 @@ def _check_notification(service_id, template_id, exception=None): back_link_from_preview=back_link_from_preview, choose_time_form=choose_time_form, **(get_template_error_dict(exception) if exception else {}), - simplifed_template=simplifed_template + simplifed_template=simplifed_template, ) diff --git a/tests/app/main/views/test_send.py b/tests/app/main/views/test_send.py index 35309f57f..a33f975ba 100644 --- a/tests/app/main/views/test_send.py +++ b/tests/app/main/views/test_send.py @@ -2612,8 +2612,10 @@ def test_preview_notification_shows_preview( session["placeholders"] = {} page = client_request.post( - "main.preview_notification", service_id=service_one["id"], template_id=fake_uuid, - _expected_status=200 + "main.preview_notification", + service_id=service_one["id"], + template_id=fake_uuid, + _expected_status=200, ) assert page.h1.text.strip() == "Preview" assert (page.find_all("a", {"class": "usa-back-link"})[0]["href"]) == url_for( From e35168bd409e76c8ab1611a659476673b55b7d03 Mon Sep 17 00:00:00 2001 From: Kenneth Kehl <@kkehl@flexion.us> Date: Thu, 14 Mar 2024 08:57:58 -0700 Subject: [PATCH 22/30] hide csv reports in job view if no data available --- app/templates/partials/jobs/notifications.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/templates/partials/jobs/notifications.html b/app/templates/partials/jobs/notifications.html index e33e2c342..2b5cd8f77 100644 --- a/app/templates/partials/jobs/notifications.html +++ b/app/templates/partials/jobs/notifications.html @@ -28,14 +28,14 @@

    Report is {{ "{:.0f}%".format(job.percentage_complete * 0.99) }} complete…

    - {% elif notifications %} + {% elif notifications and time_left != "Data no longer available" %}

    Download this report (CSV){{ time_left }}

    {% endif %} - + {% call(item, row_number) list_table( notifications, caption=uploaded_file_name, From 119b7fc832cc6d0564b88014b2f90e5dcb1fc80f Mon Sep 17 00:00:00 2001 From: Andrew Shumway Date: Thu, 14 Mar 2024 10:16:56 -0600 Subject: [PATCH 23/30] Specify username with fail/success --- app/main/views/send.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/main/views/send.py b/app/main/views/send.py index 81c62771c..6ef2afc77 100644 --- a/app/main/views/send.py +++ b/app/main/views/send.py @@ -524,10 +524,10 @@ def _check_messages(service_id, template_id, upload_id, preview_row): for user in Users(service_id): allow_list.extend([user.name, user.mobile_number, user.email_address]) # Failed sms number - allow_list.extend(["simulated user", "+14254147167", "simulated@simulated.gov"]) + allow_list.extend(["simulated user (fail)", "+14254147167", "simulated@simulated.gov"]) # Success sms number allow_list.extend( - ["simulated user two", "+14254147755", "simulatedtwo@simulated.gov"] + ["simulated user (success)", "+14254147755", "simulatedtwo@simulated.gov"] ) else: allow_list = None From 476ba798fc50f8774450c7682e5c78979e993885 Mon Sep 17 00:00:00 2001 From: Carlo Costino Date: Thu, 14 Mar 2024 15:18:40 -0400 Subject: [PATCH 24/30] This changeset updates notifications_utils to 0.3.0 to account for other dependency updates. Signed-off-by: Carlo Costino --- poetry.lock | 149 ++++++++++++++++++++++++++-------------------------- 1 file changed, 74 insertions(+), 75 deletions(-) diff --git a/poetry.lock b/poetry.lock index 74a0b0ac6..bbc6c0c43 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. [[package]] name = "ago" @@ -1080,13 +1080,13 @@ license = ["ukkonen"] [[package]] name = "idna" -version = "3.4" +version = "3.6" description = "Internationalized Domain Names in Applications (IDNA)" optional = false python-versions = ">=3.5" files = [ - {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, - {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, + {file = "idna-3.6-py3-none-any.whl", hash = "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f"}, + {file = "idna-3.6.tar.gz", hash = "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca"}, ] [[package]] @@ -1390,71 +1390,71 @@ testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] [[package]] name = "markupsafe" -version = "2.1.3" +version = "2.1.5" description = "Safely add untrusted strings to HTML/XML markup." optional = false python-versions = ">=3.7" files = [ - {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cd0f502fe016460680cd20aaa5a76d241d6f35a1c3350c474bac1273803893fa"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e09031c87a1e51556fdcb46e5bd4f59dfb743061cf93c4d6831bf894f125eb57"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68e78619a61ecf91e76aa3e6e8e33fc4894a2bebe93410754bd28fce0a8a4f9f"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:65c1a9bcdadc6c28eecee2c119465aebff8f7a584dd719facdd9e825ec61ab52"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:525808b8019e36eb524b8c68acdd63a37e75714eac50e988180b169d64480a00"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:962f82a3086483f5e5f64dbad880d31038b698494799b097bc59c2edf392fce6"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:aa7bd130efab1c280bed0f45501b7c8795f9fdbeb02e965371bbef3523627779"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c9c804664ebe8f83a211cace637506669e7890fec1b4195b505c214e50dd4eb7"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-win32.whl", hash = "sha256:10bbfe99883db80bdbaff2dcf681dfc6533a614f700da1287707e8a5d78a8431"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-win_amd64.whl", hash = "sha256:1577735524cdad32f9f694208aa75e422adba74f1baee7551620e43a3141f559"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ad9e82fb8f09ade1c3e1b996a6337afac2b8b9e365f926f5a61aacc71adc5b3c"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3c0fae6c3be832a0a0473ac912810b2877c8cb9d76ca48de1ed31e1c68386575"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b076b6226fb84157e3f7c971a47ff3a679d837cf338547532ab866c57930dbee"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bfce63a9e7834b12b87c64d6b155fdd9b3b96191b6bd334bf37db7ff1fe457f2"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:338ae27d6b8745585f87218a3f23f1512dbf52c26c28e322dbe54bcede54ccb9"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e4dd52d80b8c83fdce44e12478ad2e85c64ea965e75d66dbeafb0a3e77308fcc"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:df0be2b576a7abbf737b1575f048c23fb1d769f267ec4358296f31c2479db8f9"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f698de3fd0c4e6972b92290a45bd9b1536bffe8c6759c62471efaa8acb4c37bc"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aa57bd9cf8ae831a362185ee444e15a93ecb2e344c8e52e4d721ea3ab6ef1823"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffcc3f7c66b5f5b7931a5aa68fc9cecc51e685ef90282f4a82f0f5e9b704ad11"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47d4f1c5f80fc62fdd7777d0d40a2e9dda0a05883ab11374334f6c4de38adffd"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1f67c7038d560d92149c060157d623c542173016c4babc0c1913cca0564b9939"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9aad3c1755095ce347e26488214ef77e0485a3c34a50c5a5e2471dff60b9dd9c"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:14ff806850827afd6b07a5f32bd917fb7f45b046ba40c57abdb636674a8b559c"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8f9293864fe09b8149f0cc42ce56e3f0e54de883a9de90cd427f191c346eb2e1"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-win32.whl", hash = "sha256:715d3562f79d540f251b99ebd6d8baa547118974341db04f5ad06d5ea3eb8007"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-win_amd64.whl", hash = "sha256:1b8dd8c3fd14349433c79fa8abeb573a55fc0fdd769133baac1f5e07abf54aeb"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca379055a47383d02a5400cb0d110cef0a776fc644cda797db0c5696cfd7e18e"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b7ff0f54cb4ff66dd38bebd335a38e2c22c41a8ee45aa608efc890ac3e3931bc"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c011a4149cfbcf9f03994ec2edffcb8b1dc2d2aede7ca243746df97a5d41ce48"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:56d9f2ecac662ca1611d183feb03a3fa4406469dafe241673d521dd5ae92a155"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-win32.whl", hash = "sha256:8758846a7e80910096950b67071243da3e5a20ed2546e6392603c096778d48e0"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-win_amd64.whl", hash = "sha256:787003c0ddb00500e49a10f2844fac87aa6ce977b90b0feaaf9de23c22508b24"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:2ef12179d3a291be237280175b542c07a36e7f60718296278d8593d21ca937d4"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2c1b19b3aaacc6e57b7e25710ff571c24d6c3613a45e905b1fde04d691b98ee0"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8afafd99945ead6e075b973fefa56379c5b5c53fd8937dad92c662da5d8fd5ee"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8c41976a29d078bb235fea9b2ecd3da465df42a562910f9022f1a03107bd02be"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d080e0a5eb2529460b30190fcfcc4199bd7f827663f858a226a81bc27beaa97e"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:69c0f17e9f5a7afdf2cc9fb2d1ce6aabdb3bafb7f38017c0b77862bcec2bbad8"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:504b320cd4b7eff6f968eddf81127112db685e81f7e36e75f9f84f0df46041c3"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:42de32b22b6b804f42c5d98be4f7e5e977ecdd9ee9b660fda1a3edf03b11792d"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-win32.whl", hash = "sha256:ceb01949af7121f9fc39f7d27f91be8546f3fb112c608bc4029aef0bab86a2a5"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-win_amd64.whl", hash = "sha256:1b40069d487e7edb2676d3fbdb2b0829ffa2cd63a2ec26c4938b2d34391b4ecc"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8023faf4e01efadfa183e863fefde0046de576c6f14659e8782065bcece22198"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6b2b56950d93e41f33b4223ead100ea0fe11f8e6ee5f641eb753ce4b77a7042b"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9dcdfd0eaf283af041973bff14a2e143b8bd64e069f4c383416ecd79a81aab58"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:05fb21170423db021895e1ea1e1f3ab3adb85d1c2333cbc2310f2a26bc77272e"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:282c2cb35b5b673bbcadb33a585408104df04f14b2d9b01d4c345a3b92861c2c"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ab4a0df41e7c16a1392727727e7998a467472d0ad65f3ad5e6e765015df08636"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7ef3cb2ebbf91e330e3bb937efada0edd9003683db6b57bb108c4001f37a02ea"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:0a4e4a1aff6c7ac4cd55792abf96c915634c2b97e3cc1c7129578aa68ebd754e"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-win32.whl", hash = "sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-win_amd64.whl", hash = "sha256:3fd4abcb888d15a94f32b75d8fd18ee162ca0c064f35b11134be77050296d6ba"}, - {file = "MarkupSafe-2.1.3.tar.gz", hash = "sha256:af598ed32d6ae86f1b747b82783958b1a4ab8f617b06fe68795c7f026abbdcad"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-win32.whl", hash = "sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-win_amd64.whl", hash = "sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-win32.whl", hash = "sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl", hash = "sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-win32.whl", hash = "sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-win_amd64.whl", hash = "sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c8b29db45f8fe46ad280a7294f5c3ec36dbac9491f2d1c17345be8e69cc5928f"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec6a563cff360b50eed26f13adc43e61bc0c04d94b8be985e6fb24b81f6dcfdf"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a549b9c31bec33820e885335b451286e2969a2d9e24879f83fe904a5ce59d70a"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4f11aa001c540f62c6166c7726f71f7573b52c68c31f014c25cc7901deea0b52"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7b2e5a267c855eea6b4283940daa6e88a285f5f2a67f2220203786dfa59b37e9"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:2d2d793e36e230fd32babe143b04cec8a8b3eb8a3122d2aceb4a371e6b09b8df"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ce409136744f6521e39fd8e2a24c53fa18ad67aa5bc7c2cf83645cce5b5c4e50"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-win32.whl", hash = "sha256:4096e9de5c6fdf43fb4f04c26fb114f61ef0bf2e5604b6ee3019d51b69e8c371"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-win_amd64.whl", hash = "sha256:4275d846e41ecefa46e2015117a9f491e57a71ddd59bbead77e904dc02b1bed2"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-win32.whl", hash = "sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-win_amd64.whl", hash = "sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-win32.whl", hash = "sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-win_amd64.whl", hash = "sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5"}, + {file = "MarkupSafe-2.1.5.tar.gz", hash = "sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b"}, ] [[package]] @@ -1687,7 +1687,7 @@ requests = ">=2.0.0" [[package]] name = "notifications-utils" -version = "0.2.9" +version = "0.3.0" description = "" optional = false python-versions = ">=3.9,<3.12" @@ -1710,11 +1710,11 @@ flask = "^2.3.2" flask-redis = "^0.4.0" geojson = "^3.0.1" govuk-bank-holidays = "^0.13" -idna = "^3.4" +idna = "^3.6" itsdangerous = "^2.1.2" jinja2 = "^3.1.3" jmespath = "^1.0.1" -markupsafe = "^2.1.2" +markupsafe = "^2.1.5" mistune = "==0.8.4" numpy = "^1.24.2" orderedset = "^2.0.3" @@ -1724,7 +1724,7 @@ python-dateutil = "^2.8.2" python-json-logger = "^2.0.7" pytz = "^2023.3" pyyaml = "^6.0" -redis = "^5.0.1" +redis = "^5.0.3" regex = "^2023.10.3" requests = "^2.31.0" s3transfer = "^0.7.0" @@ -1739,7 +1739,7 @@ werkzeug = "^3.0.1" type = "git" url = "https://github.com/GSA/notifications-utils.git" reference = "HEAD" -resolved_reference = "df8ece836cad303c5d161edf485cf9bbdc666688" +resolved_reference = "5a623566c7f71db48699cee93415f45317541524" [[package]] name = "numpy" @@ -2463,7 +2463,6 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, @@ -2518,17 +2517,17 @@ toml = ["tomli (>=2.0.1)"] [[package]] name = "redis" -version = "5.0.1" +version = "5.0.3" description = "Python client for Redis database and key-value store" optional = false python-versions = ">=3.7" files = [ - {file = "redis-5.0.1-py3-none-any.whl", hash = "sha256:ed4802971884ae19d640775ba3b03aa2e7bd5e8fb8dfaed2decce4d0fc48391f"}, - {file = "redis-5.0.1.tar.gz", hash = "sha256:0dab495cd5753069d3bc650a0dde8a8f9edde16fc5691b689a566eda58100d0f"}, + {file = "redis-5.0.3-py3-none-any.whl", hash = "sha256:5da9b8fe9e1254293756c16c008e8620b3d15fcc6dde6babde9541850e72a32d"}, + {file = "redis-5.0.3.tar.gz", hash = "sha256:4973bae7444c0fbed64a06b87446f79361cb7e4ec1538c022d696ed7a5015580"}, ] [package.dependencies] -async-timeout = {version = ">=4.0.2", markers = "python_full_version <= \"3.11.2\""} +async-timeout = {version = ">=4.0.3", markers = "python_full_version < \"3.11.3\""} [package.extras] hiredis = ["hiredis (>=1.0.0)"] From 3aacdcb3ef9c609d3824a2adb21856d1bd4c24ea Mon Sep 17 00:00:00 2001 From: Kenneth Kehl <@kkehl@flexion.us> Date: Thu, 14 Mar 2024 13:25:02 -0700 Subject: [PATCH 25/30] fix_commit_hash --- .github/workflows/deploy-demo.yml | 2 +- .github/workflows/deploy-prod.yml | 2 +- .github/workflows/deploy.yml | 2 +- app/config.py | 2 +- tests/app/test_utils.py | 5 +++++ 5 files changed, 9 insertions(+), 4 deletions(-) diff --git a/.github/workflows/deploy-demo.yml b/.github/workflows/deploy-demo.yml index 65384ac81..139c8c4c4 100644 --- a/.github/workflows/deploy-demo.yml +++ b/.github/workflows/deploy-demo.yml @@ -54,7 +54,7 @@ jobs: ADMIN_CLIENT_SECRET: ${{ secrets.ADMIN_CLIENT_SECRET }} NEW_RELIC_LICENSE_KEY: ${{ secrets.NEW_RELIC_LICENSE_KEY }} NR_BROWSER_KEY: ${{ secrets.NR_BROWSER_KEY }} - COMMIT_HASH: $(git rev-parse --short "$GITHUB_SHA") + COMMIT_HASH: ${{ github.sha }} LOGIN_PEM: ${{ secrets.LOGIN_PEM }} LOGIN_DOT_GOV_CLIENT_ID: "urn:gov:gsa:openidconnect.profiles:sp:sso:gsa:notify-gov" LOGIN_DOT_GOV_USER_INFO_URL: "https://secure.login.gov/api/openid_connect/userinfo" diff --git a/.github/workflows/deploy-prod.yml b/.github/workflows/deploy-prod.yml index de0c5714d..683ec5b70 100644 --- a/.github/workflows/deploy-prod.yml +++ b/.github/workflows/deploy-prod.yml @@ -54,7 +54,7 @@ jobs: ADMIN_CLIENT_SECRET: ${{ secrets.ADMIN_CLIENT_SECRET }} NEW_RELIC_LICENSE_KEY: ${{ secrets.NEW_RELIC_LICENSE_KEY }} NR_BROWSER_KEY: ${{ secrets.NR_BROWSER_KEY }} - COMMIT_HASH: $(git rev-parse --short "$GITHUB_SHA") + COMMIT_HASH: ${{ github.sha }} LOGIN_PEM: ${{ secrets.LOGIN_PEM }} LOGIN_DOT_GOV_CLIENT_ID: "urn:gov:gsa:openidconnect.profiles:sp:sso:gsa:notify-gov" LOGIN_DOT_GOV_USER_INFO_URL: "https://secure.login.gov/api/openid_connect/userinfo" diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index cbb7b9bb7..f620bd662 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -60,7 +60,7 @@ jobs: ADMIN_CLIENT_SECRET: ${{ secrets.ADMIN_CLIENT_SECRET }} NEW_RELIC_LICENSE_KEY: ${{ secrets.NEW_RELIC_LICENSE_KEY }} NR_BROWSER_KEY: ${{ secrets.NR_BROWSER_KEY }} - COMMIT_HASH: $(git rev-parse --short "$GITHUB_SHA") + COMMIT_HASH: ${{ github.sha }} LOGIN_PEM: ${{ secrets.LOGIN_PEM }} LOGIN_DOT_GOV_CLIENT_ID: "urn:gov:gsa:openidconnect.profiles:sp:sso:gsa:notify-gov" LOGIN_DOT_GOV_USER_INFO_URL: "https://secure.login.gov/api/openid_connect/userinfo" diff --git a/app/config.py b/app/config.py index 4328f4a75..ba89ce6bf 100644 --- a/app/config.py +++ b/app/config.py @@ -36,7 +36,7 @@ class Config(object): NR_BROWSER_KEY = getenv("NR_BROWSER_KEY") settings = newrelic.agent.global_settings() NR_MONITOR_ON = settings and settings.monitor_mode - COMMIT_HASH = getenv("COMMIT_HASH", "-----") + COMMIT_HASH = getenv("COMMIT_HASH", "--------")[0:7] TEMPLATE_PREVIEW_API_HOST = getenv( "TEMPLATE_PREVIEW_API_HOST", "http://localhost:9999" diff --git a/tests/app/test_utils.py b/tests/app/test_utils.py index 4da7e8718..40a10cfb5 100644 --- a/tests/app/test_utils.py +++ b/tests/app/test_utils.py @@ -49,3 +49,8 @@ def test_merge_jsonlike_merges_jsonlike_objects_correctly( ): merge_jsonlike(source_object, destination_object) assert source_object == expected_result + +def test_commit_hash(): + # Assert that we have trimmed the default (unknown) commit hash to seven characters + # The real commit hash is supplied at deploy time. + assert current_app.config["COMMIT_HASH"] == "-------" From e4087ca9d5f0608cdb18d2ade5abffce0b32eec8 Mon Sep 17 00:00:00 2001 From: Kenneth Kehl <@kkehl@flexion.us> Date: Thu, 14 Mar 2024 13:26:05 -0700 Subject: [PATCH 26/30] fix commit hash --- app/main/views/send.py | 4 +++- tests/app/test_utils.py | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/app/main/views/send.py b/app/main/views/send.py index 6ef2afc77..8853b7fc3 100644 --- a/app/main/views/send.py +++ b/app/main/views/send.py @@ -524,7 +524,9 @@ def _check_messages(service_id, template_id, upload_id, preview_row): for user in Users(service_id): allow_list.extend([user.name, user.mobile_number, user.email_address]) # Failed sms number - allow_list.extend(["simulated user (fail)", "+14254147167", "simulated@simulated.gov"]) + allow_list.extend( + ["simulated user (fail)", "+14254147167", "simulated@simulated.gov"] + ) # Success sms number allow_list.extend( ["simulated user (success)", "+14254147755", "simulatedtwo@simulated.gov"] diff --git a/tests/app/test_utils.py b/tests/app/test_utils.py index 40a10cfb5..950eb830b 100644 --- a/tests/app/test_utils.py +++ b/tests/app/test_utils.py @@ -1,4 +1,5 @@ import pytest +from flask import current_app from app.utils import merge_jsonlike @@ -50,6 +51,7 @@ def test_merge_jsonlike_merges_jsonlike_objects_correctly( merge_jsonlike(source_object, destination_object) assert source_object == expected_result + def test_commit_hash(): # Assert that we have trimmed the default (unknown) commit hash to seven characters # The real commit hash is supplied at deploy time. From c43ed20c9ea55eb7ee7dbb85d9f089009c85ad10 Mon Sep 17 00:00:00 2001 From: Carlo Costino Date: Thu, 14 Mar 2024 17:31:27 -0400 Subject: [PATCH 27/30] Update Dependabot flagged dependencies This changeset updates a handful of dependencies that Dependabot has flagged but is not able to test successfully due to a bug with the E2E configuration. Signed-off-by: Carlo Costino --- poetry.lock | 193 +++++++++++++++++++++++++--------------------------- 1 file changed, 94 insertions(+), 99 deletions(-) diff --git a/poetry.lock b/poetry.lock index bbc6c0c43..2ad67c3fd 100644 --- a/poetry.lock +++ b/poetry.lock @@ -465,63 +465,63 @@ files = [ [[package]] name = "coverage" -version = "7.4.2" +version = "7.4.4" description = "Code coverage measurement for Python" optional = false python-versions = ">=3.8" files = [ - {file = "coverage-7.4.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bf54c3e089179d9d23900e3efc86d46e4431188d9a657f345410eecdd0151f50"}, - {file = "coverage-7.4.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fe6e43c8b510719b48af7db9631b5fbac910ade4bd90e6378c85ac5ac706382c"}, - {file = "coverage-7.4.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b98c89db1b150d851a7840142d60d01d07677a18f0f46836e691c38134ed18b"}, - {file = "coverage-7.4.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c5f9683be6a5b19cd776ee4e2f2ffb411424819c69afab6b2db3a0a364ec6642"}, - {file = "coverage-7.4.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78cdcbf7b9cb83fe047ee09298e25b1cd1636824067166dc97ad0543b079d22f"}, - {file = "coverage-7.4.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:2599972b21911111114100d362aea9e70a88b258400672626efa2b9e2179609c"}, - {file = "coverage-7.4.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:ef00d31b7569ed3cb2036f26565f1984b9fc08541731ce01012b02a4c238bf03"}, - {file = "coverage-7.4.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:20a875bfd8c282985c4720c32aa05056f77a68e6d8bbc5fe8632c5860ee0b49b"}, - {file = "coverage-7.4.2-cp310-cp310-win32.whl", hash = "sha256:b3f2b1eb229f23c82898eedfc3296137cf1f16bb145ceab3edfd17cbde273fb7"}, - {file = "coverage-7.4.2-cp310-cp310-win_amd64.whl", hash = "sha256:7df95fdd1432a5d2675ce630fef5f239939e2b3610fe2f2b5bf21fa505256fa3"}, - {file = "coverage-7.4.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a8ddbd158e069dded57738ea69b9744525181e99974c899b39f75b2b29a624e2"}, - {file = "coverage-7.4.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:81a5fb41b0d24447a47543b749adc34d45a2cf77b48ca74e5bf3de60a7bd9edc"}, - {file = "coverage-7.4.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2412e98e70f16243be41d20836abd5f3f32edef07cbf8f407f1b6e1ceae783ac"}, - {file = "coverage-7.4.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ddb79414c15c6f03f56cc68fa06994f047cf20207c31b5dad3f6bab54a0f66ef"}, - {file = "coverage-7.4.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cf89ab85027427d351f1de918aff4b43f4eb5f33aff6835ed30322a86ac29c9e"}, - {file = "coverage-7.4.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a178b7b1ac0f1530bb28d2e51f88c0bab3e5949835851a60dda80bff6052510c"}, - {file = "coverage-7.4.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:06fe398145a2e91edaf1ab4eee66149c6776c6b25b136f4a86fcbbb09512fd10"}, - {file = "coverage-7.4.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:18cac867950943fe93d6cd56a67eb7dcd2d4a781a40f4c1e25d6f1ed98721a55"}, - {file = "coverage-7.4.2-cp311-cp311-win32.whl", hash = "sha256:f72cdd2586f9a769570d4b5714a3837b3a59a53b096bb954f1811f6a0afad305"}, - {file = "coverage-7.4.2-cp311-cp311-win_amd64.whl", hash = "sha256:d779a48fac416387dd5673fc5b2d6bd903ed903faaa3247dc1865c65eaa5a93e"}, - {file = "coverage-7.4.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:adbdfcda2469d188d79771d5696dc54fab98a16d2ef7e0875013b5f56a251047"}, - {file = "coverage-7.4.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ac4bab32f396b03ebecfcf2971668da9275b3bb5f81b3b6ba96622f4ef3f6e17"}, - {file = "coverage-7.4.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:006d220ba2e1a45f1de083d5022d4955abb0aedd78904cd5a779b955b019ec73"}, - {file = "coverage-7.4.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3733545eb294e5ad274abe131d1e7e7de4ba17a144505c12feca48803fea5f64"}, - {file = "coverage-7.4.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42a9e754aa250fe61f0f99986399cec086d7e7a01dd82fd863a20af34cbce962"}, - {file = "coverage-7.4.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:2ed37e16cf35c8d6e0b430254574b8edd242a367a1b1531bd1adc99c6a5e00fe"}, - {file = "coverage-7.4.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:b953275d4edfab6cc0ed7139fa773dfb89e81fee1569a932f6020ce7c6da0e8f"}, - {file = "coverage-7.4.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:32b4ab7e6c924f945cbae5392832e93e4ceb81483fd6dc4aa8fb1a97b9d3e0e1"}, - {file = "coverage-7.4.2-cp312-cp312-win32.whl", hash = "sha256:f5df76c58977bc35a49515b2fbba84a1d952ff0ec784a4070334dfbec28a2def"}, - {file = "coverage-7.4.2-cp312-cp312-win_amd64.whl", hash = "sha256:34423abbaad70fea9d0164add189eabaea679068ebdf693baa5c02d03e7db244"}, - {file = "coverage-7.4.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:5b11f9c6587668e495cc7365f85c93bed34c3a81f9f08b0920b87a89acc13469"}, - {file = "coverage-7.4.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:51593a1f05c39332f623d64d910445fdec3d2ac2d96b37ce7f331882d5678ddf"}, - {file = "coverage-7.4.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69f1665165ba2fe7614e2f0c1aed71e14d83510bf67e2ee13df467d1c08bf1e8"}, - {file = "coverage-7.4.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b3c8bbb95a699c80a167478478efe5e09ad31680931ec280bf2087905e3b95ec"}, - {file = "coverage-7.4.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:175f56572f25e1e1201d2b3e07b71ca4d201bf0b9cb8fad3f1dfae6a4188de86"}, - {file = "coverage-7.4.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8562ca91e8c40864942615b1d0b12289d3e745e6b2da901d133f52f2d510a1e3"}, - {file = "coverage-7.4.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:d9a1ef0f173e1a19738f154fb3644f90d0ada56fe6c9b422f992b04266c55d5a"}, - {file = "coverage-7.4.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:f40ac873045db4fd98a6f40387d242bde2708a3f8167bd967ccd43ad46394ba2"}, - {file = "coverage-7.4.2-cp38-cp38-win32.whl", hash = "sha256:d1b750a8409bec61caa7824bfd64a8074b6d2d420433f64c161a8335796c7c6b"}, - {file = "coverage-7.4.2-cp38-cp38-win_amd64.whl", hash = "sha256:b4ae777bebaed89e3a7e80c4a03fac434a98a8abb5251b2a957d38fe3fd30088"}, - {file = "coverage-7.4.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3ff7f92ae5a456101ca8f48387fd3c56eb96353588e686286f50633a611afc95"}, - {file = "coverage-7.4.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:861d75402269ffda0b33af94694b8e0703563116b04c681b1832903fac8fd647"}, - {file = "coverage-7.4.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3507427d83fa961cbd73f11140f4a5ce84208d31756f7238d6257b2d3d868405"}, - {file = "coverage-7.4.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bf711d517e21fb5bc429f5c4308fbc430a8585ff2a43e88540264ae87871e36a"}, - {file = "coverage-7.4.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c00e54f0bd258ab25e7f731ca1d5144b0bf7bec0051abccd2bdcff65fa3262c9"}, - {file = "coverage-7.4.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f8e845d894e39fb53834da826078f6dc1a933b32b1478cf437007367efaf6f6a"}, - {file = "coverage-7.4.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:840456cb1067dc350af9080298c7c2cfdddcedc1cb1e0b30dceecdaf7be1a2d3"}, - {file = "coverage-7.4.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c11ca2df2206a4e3e4c4567f52594637392ed05d7c7fb73b4ea1c658ba560265"}, - {file = "coverage-7.4.2-cp39-cp39-win32.whl", hash = "sha256:3ff5bdb08d8938d336ce4088ca1a1e4b6c8cd3bef8bb3a4c0eb2f37406e49643"}, - {file = "coverage-7.4.2-cp39-cp39-win_amd64.whl", hash = "sha256:ac9e95cefcf044c98d4e2c829cd0669918585755dd9a92e28a1a7012322d0a95"}, - {file = "coverage-7.4.2-pp38.pp39.pp310-none-any.whl", hash = "sha256:f593a4a90118d99014517c2679e04a4ef5aee2d81aa05c26c734d271065efcb6"}, - {file = "coverage-7.4.2.tar.gz", hash = "sha256:1a5ee18e3a8d766075ce9314ed1cb695414bae67df6a4b0805f5137d93d6f1cb"}, + {file = "coverage-7.4.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e0be5efd5127542ef31f165de269f77560d6cdef525fffa446de6f7e9186cfb2"}, + {file = "coverage-7.4.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ccd341521be3d1b3daeb41960ae94a5e87abe2f46f17224ba5d6f2b8398016cf"}, + {file = "coverage-7.4.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:09fa497a8ab37784fbb20ab699c246053ac294d13fc7eb40ec007a5043ec91f8"}, + {file = "coverage-7.4.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b1a93009cb80730c9bca5d6d4665494b725b6e8e157c1cb7f2db5b4b122ea562"}, + {file = "coverage-7.4.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:690db6517f09336559dc0b5f55342df62370a48f5469fabf502db2c6d1cffcd2"}, + {file = "coverage-7.4.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:09c3255458533cb76ef55da8cc49ffab9e33f083739c8bd4f58e79fecfe288f7"}, + {file = "coverage-7.4.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:8ce1415194b4a6bd0cdcc3a1dfbf58b63f910dcb7330fe15bdff542c56949f87"}, + {file = "coverage-7.4.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b91cbc4b195444e7e258ba27ac33769c41b94967919f10037e6355e998af255c"}, + {file = "coverage-7.4.4-cp310-cp310-win32.whl", hash = "sha256:598825b51b81c808cb6f078dcb972f96af96b078faa47af7dfcdf282835baa8d"}, + {file = "coverage-7.4.4-cp310-cp310-win_amd64.whl", hash = "sha256:09ef9199ed6653989ebbcaacc9b62b514bb63ea2f90256e71fea3ed74bd8ff6f"}, + {file = "coverage-7.4.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0f9f50e7ef2a71e2fae92774c99170eb8304e3fdf9c8c3c7ae9bab3e7229c5cf"}, + {file = "coverage-7.4.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:623512f8ba53c422fcfb2ce68362c97945095b864cda94a92edbaf5994201083"}, + {file = "coverage-7.4.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0513b9508b93da4e1716744ef6ebc507aff016ba115ffe8ecff744d1322a7b63"}, + {file = "coverage-7.4.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40209e141059b9370a2657c9b15607815359ab3ef9918f0196b6fccce8d3230f"}, + {file = "coverage-7.4.4-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8a2b2b78c78293782fd3767d53e6474582f62443d0504b1554370bde86cc8227"}, + {file = "coverage-7.4.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:73bfb9c09951125d06ee473bed216e2c3742f530fc5acc1383883125de76d9cd"}, + {file = "coverage-7.4.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:1f384c3cc76aeedce208643697fb3e8437604b512255de6d18dae3f27655a384"}, + {file = "coverage-7.4.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:54eb8d1bf7cacfbf2a3186019bcf01d11c666bd495ed18717162f7eb1e9dd00b"}, + {file = "coverage-7.4.4-cp311-cp311-win32.whl", hash = "sha256:cac99918c7bba15302a2d81f0312c08054a3359eaa1929c7e4b26ebe41e9b286"}, + {file = "coverage-7.4.4-cp311-cp311-win_amd64.whl", hash = "sha256:b14706df8b2de49869ae03a5ccbc211f4041750cd4a66f698df89d44f4bd30ec"}, + {file = "coverage-7.4.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:201bef2eea65e0e9c56343115ba3814e896afe6d36ffd37bab783261db430f76"}, + {file = "coverage-7.4.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:41c9c5f3de16b903b610d09650e5e27adbfa7f500302718c9ffd1c12cf9d6818"}, + {file = "coverage-7.4.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d898fe162d26929b5960e4e138651f7427048e72c853607f2b200909794ed978"}, + {file = "coverage-7.4.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3ea79bb50e805cd6ac058dfa3b5c8f6c040cb87fe83de10845857f5535d1db70"}, + {file = "coverage-7.4.4-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce4b94265ca988c3f8e479e741693d143026632672e3ff924f25fab50518dd51"}, + {file = "coverage-7.4.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:00838a35b882694afda09f85e469c96367daa3f3f2b097d846a7216993d37f4c"}, + {file = "coverage-7.4.4-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:fdfafb32984684eb03c2d83e1e51f64f0906b11e64482df3c5db936ce3839d48"}, + {file = "coverage-7.4.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:69eb372f7e2ece89f14751fbcbe470295d73ed41ecd37ca36ed2eb47512a6ab9"}, + {file = "coverage-7.4.4-cp312-cp312-win32.whl", hash = "sha256:137eb07173141545e07403cca94ab625cc1cc6bc4c1e97b6e3846270e7e1fea0"}, + {file = "coverage-7.4.4-cp312-cp312-win_amd64.whl", hash = "sha256:d71eec7d83298f1af3326ce0ff1d0ea83c7cb98f72b577097f9083b20bdaf05e"}, + {file = "coverage-7.4.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d5ae728ff3b5401cc320d792866987e7e7e880e6ebd24433b70a33b643bb0384"}, + {file = "coverage-7.4.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:cc4f1358cb0c78edef3ed237ef2c86056206bb8d9140e73b6b89fbcfcbdd40e1"}, + {file = "coverage-7.4.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8130a2aa2acb8788e0b56938786c33c7c98562697bf9f4c7d6e8e5e3a0501e4a"}, + {file = "coverage-7.4.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cf271892d13e43bc2b51e6908ec9a6a5094a4df1d8af0bfc360088ee6c684409"}, + {file = "coverage-7.4.4-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a4cdc86d54b5da0df6d3d3a2f0b710949286094c3a6700c21e9015932b81447e"}, + {file = "coverage-7.4.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:ae71e7ddb7a413dd60052e90528f2f65270aad4b509563af6d03d53e979feafd"}, + {file = "coverage-7.4.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:38dd60d7bf242c4ed5b38e094baf6401faa114fc09e9e6632374388a404f98e7"}, + {file = "coverage-7.4.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:aa5b1c1bfc28384f1f53b69a023d789f72b2e0ab1b3787aae16992a7ca21056c"}, + {file = "coverage-7.4.4-cp38-cp38-win32.whl", hash = "sha256:dfa8fe35a0bb90382837b238fff375de15f0dcdb9ae68ff85f7a63649c98527e"}, + {file = "coverage-7.4.4-cp38-cp38-win_amd64.whl", hash = "sha256:b2991665420a803495e0b90a79233c1433d6ed77ef282e8e152a324bbbc5e0c8"}, + {file = "coverage-7.4.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3b799445b9f7ee8bf299cfaed6f5b226c0037b74886a4e11515e569b36fe310d"}, + {file = "coverage-7.4.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b4d33f418f46362995f1e9d4f3a35a1b6322cb959c31d88ae56b0298e1c22357"}, + {file = "coverage-7.4.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aadacf9a2f407a4688d700e4ebab33a7e2e408f2ca04dbf4aef17585389eff3e"}, + {file = "coverage-7.4.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7c95949560050d04d46b919301826525597f07b33beba6187d04fa64d47ac82e"}, + {file = "coverage-7.4.4-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ff7687ca3d7028d8a5f0ebae95a6e4827c5616b31a4ee1192bdfde697db110d4"}, + {file = "coverage-7.4.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:5fc1de20b2d4a061b3df27ab9b7c7111e9a710f10dc2b84d33a4ab25065994ec"}, + {file = "coverage-7.4.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:c74880fc64d4958159fbd537a091d2a585448a8f8508bf248d72112723974cbd"}, + {file = "coverage-7.4.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:742a76a12aa45b44d236815d282b03cfb1de3b4323f3e4ec933acfae08e54ade"}, + {file = "coverage-7.4.4-cp39-cp39-win32.whl", hash = "sha256:d89d7b2974cae412400e88f35d86af72208e1ede1a541954af5d944a8ba46c57"}, + {file = "coverage-7.4.4-cp39-cp39-win_amd64.whl", hash = "sha256:9ca28a302acb19b6af89e90f33ee3e1906961f94b54ea37de6737b7ca9d8827c"}, + {file = "coverage-7.4.4-pp38.pp39.pp310-none-any.whl", hash = "sha256:b2c5edc4ac10a7ef6605a966c58929ec6c1bd0917fb8c15cb3363f65aa40e677"}, + {file = "coverage-7.4.4.tar.gz", hash = "sha256:c901df83d097649e257e803be22592aedfd5182f07b3cc87d640bbb9afd50f49"}, ] [package.extras] @@ -743,13 +743,13 @@ pyflakes = ">=3.2.0,<3.3.0" [[package]] name = "flake8-bugbear" -version = "24.1.17" +version = "24.2.6" description = "A plugin for flake8 finding likely bugs and design problems in your program. Contains warnings that don't belong in pyflakes and pycodestyle." optional = false python-versions = ">=3.8.1" files = [ - {file = "flake8-bugbear-24.1.17.tar.gz", hash = "sha256:bcb388a4f3b516258749b1e690ee394c082eff742f44595e3754cf5c7781c2c7"}, - {file = "flake8_bugbear-24.1.17-py3-none-any.whl", hash = "sha256:46cc840ddaed26507cd0ada530d1526418b717ee76c9b5dfdbd238b5eab34139"}, + {file = "flake8-bugbear-24.2.6.tar.gz", hash = "sha256:f9cb5f2a9e792dd80ff68e89a14c12eed8620af8b41a49d823b7a33064ac9658"}, + {file = "flake8_bugbear-24.2.6-py3-none-any.whl", hash = "sha256:663ef5de80cd32aacd39d362212983bc4636435a6f83700b4ed35acbd0b7d1b8"}, ] [package.dependencies] @@ -1492,13 +1492,13 @@ files = [ [[package]] name = "moto" -version = "4.2.13" +version = "4.2.14" description = "" optional = false python-versions = ">=3.7" files = [ - {file = "moto-4.2.13-py2.py3-none-any.whl", hash = "sha256:93e0fd13b624bd79115494f833308c3641b2be0fc9f4f18aa9264aa01f6168e0"}, - {file = "moto-4.2.13.tar.gz", hash = "sha256:01aef6a489a725c8d725bd3dc6f70ff1bedaee3e2641752e4b471ff0ede4b4d7"}, + {file = "moto-4.2.14-py2.py3-none-any.whl", hash = "sha256:6d242dbbabe925bb385ddb6958449e5c827670b13b8e153ed63f91dbdb50372c"}, + {file = "moto-4.2.14.tar.gz", hash = "sha256:8f9263ca70b646f091edcc93e97cda864a542e6d16ed04066b1370ed217bd190"}, ] [package.dependencies] @@ -1521,18 +1521,13 @@ awslambda = ["docker (>=3.0.0)"] batch = ["docker (>=3.0.0)"] cloudformation = ["PyYAML (>=5.1)", "aws-xray-sdk (>=0.93,!=0.96)", "cfn-lint (>=0.40.0)", "docker (>=3.0.0)", "ecdsa (!=0.15)", "graphql-core", "jsondiff (>=1.1.2)", "openapi-spec-validator (>=0.5.0)", "py-partiql-parser (==0.5.0)", "pyparsing (>=3.0.7)", "python-jose[cryptography] (>=3.1.0,<4.0.0)", "setuptools", "sshpubkeys (>=3.1.0)"] cognitoidp = ["ecdsa (!=0.15)", "python-jose[cryptography] (>=3.1.0,<4.0.0)"] -ds = ["sshpubkeys (>=3.1.0)"] dynamodb = ["docker (>=3.0.0)", "py-partiql-parser (==0.5.0)"] dynamodbstreams = ["docker (>=3.0.0)", "py-partiql-parser (==0.5.0)"] -ebs = ["sshpubkeys (>=3.1.0)"] ec2 = ["sshpubkeys (>=3.1.0)"] -efs = ["sshpubkeys (>=3.1.0)"] -eks = ["sshpubkeys (>=3.1.0)"] glue = ["pyparsing (>=3.0.7)"] iotdata = ["jsondiff (>=1.1.2)"] proxy = ["PyYAML (>=5.1)", "aws-xray-sdk (>=0.93,!=0.96)", "cfn-lint (>=0.40.0)", "docker (>=2.5.1)", "ecdsa (!=0.15)", "graphql-core", "jsondiff (>=1.1.2)", "multipart", "openapi-spec-validator (>=0.5.0)", "py-partiql-parser (==0.5.0)", "pyparsing (>=3.0.7)", "python-jose[cryptography] (>=3.1.0,<4.0.0)", "setuptools", "sshpubkeys (>=3.1.0)"] -resourcegroupstaggingapi = ["PyYAML (>=5.1)", "cfn-lint (>=0.40.0)", "docker (>=3.0.0)", "ecdsa (!=0.15)", "graphql-core", "jsondiff (>=1.1.2)", "openapi-spec-validator (>=0.5.0)", "py-partiql-parser (==0.5.0)", "pyparsing (>=3.0.7)", "python-jose[cryptography] (>=3.1.0,<4.0.0)", "sshpubkeys (>=3.1.0)"] -route53resolver = ["sshpubkeys (>=3.1.0)"] +resourcegroupstaggingapi = ["PyYAML (>=5.1)", "cfn-lint (>=0.40.0)", "docker (>=3.0.0)", "ecdsa (!=0.15)", "graphql-core", "jsondiff (>=1.1.2)", "openapi-spec-validator (>=0.5.0)", "py-partiql-parser (==0.5.0)", "pyparsing (>=3.0.7)", "python-jose[cryptography] (>=3.1.0,<4.0.0)"] s3 = ["PyYAML (>=5.1)", "py-partiql-parser (==0.5.0)"] s3crc32c = ["PyYAML (>=5.1)", "crc32c", "py-partiql-parser (==0.5.0)"] server = ["PyYAML (>=5.1)", "aws-xray-sdk (>=0.93,!=0.96)", "cfn-lint (>=0.40.0)", "docker (>=3.0.0)", "ecdsa (!=0.15)", "flask (!=2.2.0,!=2.2.1)", "flask-cors", "graphql-core", "jsondiff (>=1.1.2)", "openapi-spec-validator (>=0.5.0)", "py-partiql-parser (==0.5.0)", "pyparsing (>=3.0.7)", "python-jose[cryptography] (>=3.1.0,<4.0.0)", "setuptools", "sshpubkeys (>=3.1.0)"] @@ -1617,40 +1612,40 @@ files = [ [[package]] name = "newrelic" -version = "9.6.0" +version = "9.7.1" description = "New Relic Python Agent" optional = false python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*" files = [ - {file = "newrelic-9.6.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:09dad0db993402e166e37d99302c2ad5588b4ff1e5b814819540ca5ec2bd3cea"}, - {file = "newrelic-9.6.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:aeadc0bd8140738af4d7d7ea9d0a3dfa7b6f37e02fe48c0a035ccb6cac881770"}, - {file = "newrelic-9.6.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:16fb3bfde6dca0edab358c2b083386e2e764c463d85ffeb41cd6ce7a279bd7f6"}, - {file = "newrelic-9.6.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:1ba2fc6ce0b6b9a399a1e5db7e480ba51b431cb3cc6ba136a4c0e76877cf972d"}, - {file = "newrelic-9.6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7fe927f79db2dd5432a362aedde98543e93599b26d5c2e065bc563991be7f347"}, - {file = "newrelic-9.6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3fefffff32e6605ddf26d51030ea1a41b9f7f606fccbb5f8d4b43c36d755acd1"}, - {file = "newrelic-9.6.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0a68dd85a7cf4c5039ea94c8975f86a7c516dd492d8bf08976ab0a459918da9b"}, - {file = "newrelic-9.6.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:74a9a49ef596aa9f7560f6bb1480480b8f9b652c7e03de173ef06b0dc2355799"}, - {file = "newrelic-9.6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:26255aec6b29bc17e5e089bb18fbf004f4c765386ba61d1289681aa7ba538207"}, - {file = "newrelic-9.6.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c6f21f7a69294f64daa9be59c1c1e0eba889e85ed83afc67ed0a63c8efc9ff2b"}, - {file = "newrelic-9.6.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:5ecd44ff5b39138469778b5224a1a373867d21a0ca2389d093d99939cb422947"}, - {file = "newrelic-9.6.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:c6c4aa8b91dcb5403862c3e5efa57751a8b4e778576916bb22cafbfc03d47807"}, - {file = "newrelic-9.6.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6f02fb9166533f22fdb465f7a8d4b364178d94561b159cc9922f4d27491fd7d1"}, - {file = "newrelic-9.6.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:703ee92dda983eb4dcbcc300750a815ff3a5401995c3cdd587ac785b6d747e0e"}, - {file = "newrelic-9.6.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ce4646554246c6577f5aea358516ad5cf2c35fcef0cd16dbd01bbe89b19b4ccb"}, - {file = "newrelic-9.6.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5fae1f3addb422629c4d3e9d011de40629b4d078073ad0517ad42d4ddc7e8441"}, - {file = "newrelic-9.6.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:333bd5aedb4f814447ac3aa1a0cc76910a64f13385aa6481a97f87585af52cbf"}, - {file = "newrelic-9.6.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51a5aa22ce7813294ca5dc89a0d86ce4774bb9201028305975efdcf93ef36e0e"}, - {file = "newrelic-9.6.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:01c0eb630bb18261241a37aa0a70cb6f706079a1f58f59f2bb64f26fda54ffc5"}, - {file = "newrelic-9.6.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:eb82f31754dadd27676fe6f681b25db7af75eb854e332b92f1ea17584efc322c"}, - {file = "newrelic-9.6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:38256e67b2d295229240c29e9949cdae40c9ac987d51f569f57f52ed2aef027f"}, - {file = "newrelic-9.6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f681c005b1d44ec01b3fe1a7b4ec589572f681f27130ea367155ac0245e133d4"}, - {file = "newrelic-9.6.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:23d54298bc0a936a17e25fdca52c2eefbc50966985738e31d62cfe12ea3f60ba"}, - {file = "newrelic-9.6.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:f346aeb418c9da6cff4382cb4f50d314ae5126a6a6037f01224b0072eb30ff49"}, - {file = "newrelic-9.6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:26560dba7cd36c5c787e3dfd6c3c5d1e8e8605c82dc7ffee143880456d8650e5"}, - {file = "newrelic-9.6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d168349041922f206b72fa30a930c0752d8b76b4a2fd7774d4cb2843aa804e32"}, - {file = "newrelic-9.6.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:72b378b4aa4a52d2ac14be962f0de747f573b9912365981c0b3fc16bd12b5133"}, - {file = "newrelic-9.6.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5ab342ab7e3189e244e44238aa8563eeff3a5b5896b77d2d4dbf2c5d0bfe7d73"}, - {file = "newrelic-9.6.0.tar.gz", hash = "sha256:3db642583cfee951f185696fe365b41d8aff733b23867e88de97de114e3cfcf8"}, + {file = "newrelic-9.7.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:1c1d24be69d5316af7be99d6c87686d900e708bc421ca55977cb021fd29de0bd"}, + {file = "newrelic-9.7.1-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:8dba147f13457bd22b4509bfa700ce12bfcb8294f8b9abd4c66d4e90f90cefc2"}, + {file = "newrelic-9.7.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:bbbd24bd0054a978b5d6c1be7794289c760b20d44fea526e3fb1078d060a6fe7"}, + {file = "newrelic-9.7.1-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:7d7f79bd828ab56446b0be941a6acb0af287ad97fe4ac5052c59ad0518f5456d"}, + {file = "newrelic-9.7.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fed29c65100966472bef1603c479b3b60be47078810a0d1c407e5ee133e606d7"}, + {file = "newrelic-9.7.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d85b7d08e7fe130951de1f2225e69c321ece620da18bbc4385905c72e0aa51b"}, + {file = "newrelic-9.7.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:102f6e8e65e6fa5044a0d433066a46ce5b382f96335576dfa16217c1855ebc2b"}, + {file = "newrelic-9.7.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0798e85b738a24843da9aa0e4175b42441d9b10af6b17ee8de137cf83d5bb222"}, + {file = "newrelic-9.7.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28343d596de29b7b0adcbcd2b872a1657d85c2467482792d8190814faec46c80"}, + {file = "newrelic-9.7.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2a41340ce1d58bcc4dda39784d244e8a42c11b150665d8bec0527ea88bf02f53"}, + {file = "newrelic-9.7.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:7c62934b8ae447bda4273a2dc4c3a65b0c7dc995af611b5003e75a34faa926f2"}, + {file = "newrelic-9.7.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:783c560439a08715eb00c79be64cd9471ce843f07b194592d15978909a8c85ad"}, + {file = "newrelic-9.7.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8d61c374e4d698ee36eab80e33c485054514bd6f57c25cd8e2c9f0a40f159ebc"}, + {file = "newrelic-9.7.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:08a062f6b0483de744b3085e70b88ccb7599ba4f242977bf1cbb602ed4385980"}, + {file = "newrelic-9.7.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:e06c7991367e848c4f8e08e7197b0a71c145a8e32c5f92158ed64b4f6d5b4a22"}, + {file = "newrelic-9.7.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:166e365a6334d6b591a6af91e07dd191f043fb10893474ad1b60ed0b99a78f4e"}, + {file = "newrelic-9.7.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:feb83b708350947846fd898debb1538ab5e0458ff56627f01e2174e73c0fe079"}, + {file = "newrelic-9.7.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dfd572a79e1848b67307be25e15f0804b9e9fc30a0d669a0fad668f3678a8869"}, + {file = "newrelic-9.7.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:ed776ced21ebf57379cb38885485460ffd7df29cca9666197876d2045849b927"}, + {file = "newrelic-9.7.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:b4f741be5f34e17caa57c72924045776a865efd5f9deab6ebb3b7c4f1190273b"}, + {file = "newrelic-9.7.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:647a5f4ff3514e7e2acbbc884319499b0ae90ec4ec93e83e7f41474cf8666e0e"}, + {file = "newrelic-9.7.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8faecb1fce2a25201f5496ad96181933e60b4b833f99dc143a84d5d2494a46f6"}, + {file = "newrelic-9.7.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:56a6b322b228ee0b3afbb59d686fad0c58b6b284fc6bb3227e7746ca0d458858"}, + {file = "newrelic-9.7.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6361b3be951e3520ea2b138ca56783b03f8a6c85085885fcf597d1ee28c59153"}, + {file = "newrelic-9.7.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:82076bf4e84a1378ccd1c699e8890a8f469c3ebeec110ae5c4f03cfab25cd09b"}, + {file = "newrelic-9.7.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:53273e8fbea3df48265b15ce3a5aee8e7950036a8463e973ef949d79072b5d74"}, + {file = "newrelic-9.7.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:365ec3b3795f43a70895652dff4ece28c11ecf0337aabf8da762b746cfda4c2e"}, + {file = "newrelic-9.7.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d143adbc38df9a576a34220d18f564208ddf88f691a1aaaf7b78c7fc653f2428"}, + {file = "newrelic-9.7.1.tar.gz", hash = "sha256:5824e599b972b5931caa13f5f34eb60df4cf3c7048604d0efe34b9ad41923739"}, ] [package.extras] @@ -2336,18 +2331,18 @@ dev = ["pre-commit", "pytest-asyncio", "tox"] [[package]] name = "pytest-playwright" -version = "0.4.3" +version = "0.4.4" description = "A pytest wrapper with fixtures for Playwright to automate web browsers" optional = false python-versions = ">=3.8" files = [ - {file = "pytest-playwright-0.4.3.tar.gz", hash = "sha256:699e2c47fbb1e6a57895454693eba278cf55d04d44c15017709b00e1de1d9ccd"}, - {file = "pytest_playwright-0.4.3-py3-none-any.whl", hash = "sha256:c9ff6e7ebfd967b562f5c3d67f1ae6b45a061d6ea51ad304fdd95aca9db20774"}, + {file = "pytest-playwright-0.4.4.tar.gz", hash = "sha256:5488db4cc49028491c5130af0a2bb6b1d0b222a202217f6d14491d4c9aa67ff9"}, + {file = "pytest_playwright-0.4.4-py3-none-any.whl", hash = "sha256:df306f3a60a8631a3cfde1b95a2ed5a89203a3408dfa1154de049ca7de87c90b"}, ] [package.dependencies] playwright = ">=1.18" -pytest = ">=6.2.4,<8.0.0" +pytest = ">=6.2.4,<9.0.0" pytest-base-url = ">=1.0.0,<3.0.0" python-slugify = ">=6.0.0,<9.0.0" From be2dc9a1656fcb52520d29cc9ec558200658b89d Mon Sep 17 00:00:00 2001 From: Jonathan Bobel Date: Fri, 15 Mar 2024 10:42:20 -0400 Subject: [PATCH 28/30] 1319 - BUG - adjusting the js to only run when the targeted DOM element exists --- app/assets/javascripts/loginAlert.js | 30 +++++++++++++++++----------- 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/app/assets/javascripts/loginAlert.js b/app/assets/javascripts/loginAlert.js index 84c2ee6a8..b65b14734 100644 --- a/app/assets/javascripts/loginAlert.js +++ b/app/assets/javascripts/loginAlert.js @@ -3,22 +3,28 @@ // Set the target date (10 days before March 15th, 2024) const targetDate = new Date("April 16, 2024 00:00:00").getTime(); +// Set a const for the container to write a conditional statement and only run if it exists + const countdownContainer = document.getElementById("countdown-container"); + // Function to update the countdown display function updateCountdown() { - const now = new Date().getTime(); - const difference = targetDate - now; - // Time calculations for days only - const days = Math.floor(difference / (1000 * 60 * 60 * 24)); + if (countdownContainer) { + const now = new Date().getTime(); + const difference = targetDate - now; - // Visibility logic - if (days < 0 || days > 10) { - // Hide if more than 10 days away OR if already past the date - document.getElementById("countdown-container").style.display = "none"; - } else { - // Show if 10 days or less remaining - document.getElementById("countdown-container").style.display = "block"; - document.getElementById("countdown").innerHTML = days + " days "; + // Time calculations for days only + const days = Math.floor(difference / (1000 * 60 * 60 * 24)); + + // Visibility logic + if (days < 0 || days > 10) { + // Hide if more than 10 days away OR if already past the date + countdownContainer.style.display = "none"; + } else { + // Show if 10 days or less remaining + countdownContainer.style.display = "block"; + document.getElementById("countdown").innerHTML = days + " days "; + } } } From 0e608599c3471067bcc5b44d33129b15a1c14005 Mon Sep 17 00:00:00 2001 From: Jonathan Bobel Date: Fri, 15 Mar 2024 11:41:30 -0400 Subject: [PATCH 29/30] 1321 - Updated link on the sign-in page --- app/templates/views/signin.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/templates/views/signin.html b/app/templates/views/signin.html index 6b4952b0c..6d6f578ee 100644 --- a/app/templates/views/signin.html +++ b/app/templates/views/signin.html @@ -67,7 +67,7 @@
  • If you don’t have a Login.gov account, you must create one by April 16, 2024 to continue to access Notify.
- Create Login.gov account + Create Login.gov account
{% endif %} From 88c7f9590fc947ef4b0263da8be58146b8685829 Mon Sep 17 00:00:00 2001 From: Carlo Costino Date: Fri, 15 Mar 2024 13:07:50 -0400 Subject: [PATCH 30/30] Removing extraneous space --- app/assets/javascripts/loginAlert.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/javascripts/loginAlert.js b/app/assets/javascripts/loginAlert.js index b65b14734..e6343c195 100644 --- a/app/assets/javascripts/loginAlert.js +++ b/app/assets/javascripts/loginAlert.js @@ -10,7 +10,7 @@ function updateCountdown() { if (countdownContainer) { - const now = new Date().getTime(); + const now = new Date().getTime(); const difference = targetDate - now; // Time calculations for days only