From f46f9661f1ef5e0f04ab4ef5cdf0f6e11dc819f6 Mon Sep 17 00:00:00 2001 From: Jonathan Bobel Date: Mon, 8 Apr 2024 11:32:09 -0400 Subject: [PATCH 1/6] 1269 - Content updates for Service Settings after login.gov integration --- app/main/views/service_settings.py | 1 + app/templates/views/service-settings/set-auth-type.html | 7 ++++++- poetry.lock | 7 ++++++- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/app/main/views/service_settings.py b/app/main/views/service_settings.py index 628ac59e5..7d301426f 100644 --- a/app/main/views/service_settings.py +++ b/app/main/views/service_settings.py @@ -650,6 +650,7 @@ def service_set_channel(service_id, channel): def service_set_auth_type(service_id): return render_template( "views/service-settings/set-auth-type.html", + login_gov_enabled=False, ) diff --git a/app/templates/views/service-settings/set-auth-type.html b/app/templates/views/service-settings/set-auth-type.html index 263740222..2fa545a4c 100644 --- a/app/templates/views/service-settings/set-auth-type.html +++ b/app/templates/views/service-settings/set-auth-type.html @@ -16,7 +16,12 @@
{{ page_header('Sign-in method') }} - {% if 'email_auth' in current_service.permissions %} + + {% if login_gov_enabled %} +

Your username, password, and multi-factor authentication options are handled by Login.gov.

+

To make changes, head to Login.gov and sign-in with your credentials.

+

Any changes made to your Login.gov account will automatically be synced with Notify.gov.

+ {% elif 'email_auth' in current_service.permissions and not login_gov_enabled %}

Email link or text message code

diff --git a/poetry.lock b/poetry.lock index 930c20232..2a90e8113 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1210,6 +1210,7 @@ description = "Powerful and Pythonic XML processing library combining libxml2/li optional = false python-versions = ">=3.6" files = [ + {file = "lxml-5.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:704f5572ff473a5f897745abebc6df40f22d4133c1e0a1f124e4f2bd3330ff7e"}, {file = "lxml-5.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9d3c0f8567ffe7502d969c2c1b809892dc793b5d0665f602aad19895f8d508da"}, {file = "lxml-5.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5fcfbebdb0c5d8d18b84118842f31965d59ee3e66996ac842e21f957eb76138c"}, {file = "lxml-5.1.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2f37c6d7106a9d6f0708d4e164b707037b7380fcd0b04c5bd9cae1fb46a856fb"}, @@ -1219,6 +1220,7 @@ files = [ {file = "lxml-5.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:82bddf0e72cb2af3cbba7cec1d2fd11fda0de6be8f4492223d4a268713ef2147"}, {file = "lxml-5.1.0-cp310-cp310-win32.whl", hash = "sha256:b66aa6357b265670bb574f050ffceefb98549c721cf28351b748be1ef9577d93"}, {file = "lxml-5.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:4946e7f59b7b6a9e27bef34422f645e9a368cb2be11bf1ef3cafc39a1f6ba68d"}, + {file = "lxml-5.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:14deca1460b4b0f6b01f1ddc9557704e8b365f55c63070463f6c18619ebf964f"}, {file = "lxml-5.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ed8c3d2cd329bf779b7ed38db176738f3f8be637bb395ce9629fc76f78afe3d4"}, {file = "lxml-5.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:436a943c2900bb98123b06437cdd30580a61340fbdb7b28aaf345a459c19046a"}, {file = "lxml-5.1.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:acb6b2f96f60f70e7f34efe0c3ea34ca63f19ca63ce90019c6cbca6b676e81fa"}, @@ -1228,6 +1230,7 @@ files = [ {file = "lxml-5.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f4c9bda132ad108b387c33fabfea47866af87f4ea6ffb79418004f0521e63204"}, {file = "lxml-5.1.0-cp311-cp311-win32.whl", hash = "sha256:bc64d1b1dab08f679fb89c368f4c05693f58a9faf744c4d390d7ed1d8223869b"}, {file = "lxml-5.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:a5ab722ae5a873d8dcee1f5f45ddd93c34210aed44ff2dc643b5025981908cda"}, + {file = "lxml-5.1.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:9aa543980ab1fbf1720969af1d99095a548ea42e00361e727c58a40832439114"}, {file = "lxml-5.1.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:6f11b77ec0979f7e4dc5ae081325a2946f1fe424148d3945f943ceaede98adb8"}, {file = "lxml-5.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a36c506e5f8aeb40680491d39ed94670487ce6614b9d27cabe45d94cd5d63e1e"}, {file = "lxml-5.1.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f643ffd2669ffd4b5a3e9b41c909b72b2a1d5e4915da90a77e119b8d48ce867a"}, @@ -1253,8 +1256,8 @@ files = [ {file = "lxml-5.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8f52fe6859b9db71ee609b0c0a70fea5f1e71c3462ecf144ca800d3f434f0764"}, {file = "lxml-5.1.0-cp37-cp37m-win32.whl", hash = "sha256:d42e3a3fc18acc88b838efded0e6ec3edf3e328a58c68fbd36a7263a874906c8"}, {file = "lxml-5.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:eac68f96539b32fce2c9b47eb7c25bb2582bdaf1bbb360d25f564ee9e04c542b"}, + {file = "lxml-5.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:ae15347a88cf8af0949a9872b57a320d2605ae069bcdf047677318bc0bba45b1"}, {file = "lxml-5.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c26aab6ea9c54d3bed716b8851c8bfc40cb249b8e9880e250d1eddde9f709bf5"}, - {file = "lxml-5.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:cfbac9f6149174f76df7e08c2e28b19d74aed90cad60383ad8671d3af7d0502f"}, {file = "lxml-5.1.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:342e95bddec3a698ac24378d61996b3ee5ba9acfeb253986002ac53c9a5f6f84"}, {file = "lxml-5.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:725e171e0b99a66ec8605ac77fa12239dbe061482ac854d25720e2294652eeaa"}, {file = "lxml-5.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d184e0d5c918cff04cdde9dbdf9600e960161d773666958c9d7b565ccc60c45"}, @@ -1262,6 +1265,7 @@ files = [ {file = "lxml-5.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6d48fc57e7c1e3df57be5ae8614bab6d4e7b60f65c5457915c26892c41afc59e"}, {file = "lxml-5.1.0-cp38-cp38-win32.whl", hash = "sha256:7ec465e6549ed97e9f1e5ed51c657c9ede767bc1c11552f7f4d022c4df4a977a"}, {file = "lxml-5.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:b21b4031b53d25b0858d4e124f2f9131ffc1530431c6d1321805c90da78388d1"}, + {file = "lxml-5.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:52427a7eadc98f9e62cb1368a5079ae826f94f05755d2d567d93ee1bc3ceb354"}, {file = "lxml-5.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6a2a2c724d97c1eb8cf966b16ca2915566a4904b9aad2ed9a09c748ffe14f969"}, {file = "lxml-5.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:843b9c835580d52828d8f69ea4302537337a21e6b4f1ec711a52241ba4a824f3"}, {file = "lxml-5.1.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9b99f564659cfa704a2dd82d0684207b1aadf7d02d33e54845f9fc78e06b7581"}, @@ -2378,6 +2382,7 @@ 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"}, From f30899d762a369aac2b822e83e4eedf0365e16f7 Mon Sep 17 00:00:00 2001 From: Kenneth Kehl <@kkehl@flexion.us> Date: Tue, 16 Apr 2024 12:06:33 -0700 Subject: [PATCH 2/6] fix 90 day email validation --- app/main/views/sign_in.py | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/app/main/views/sign_in.py b/app/main/views/sign_in.py index 6de46b023..88360dca3 100644 --- a/app/main/views/sign_in.py +++ b/app/main/views/sign_in.py @@ -6,6 +6,7 @@ import jwt import requests from flask import ( Markup, + Response, abort, current_app, flash, @@ -26,6 +27,7 @@ from app.main.views.verify import activate_user from app.models.user import InvitedUser, User from app.utils import hide_from_search_engines from app.utils.login import is_safe_redirect_url +from app.utils.time import is_less_than_days_ago def _reformat_keystring(orig): @@ -100,20 +102,47 @@ def _do_login_dot_gov(): user_email, user_uuid = _get_user_email_and_uuid(access_token) redirect_url = request.args.get("next") user = user_api_client.get_user_by_uuid_or_email(user_uuid, user_email) - activate_user(user["id"]) + + # Check if the email needs to be revalidated + is_fresh_email = is_less_than_days_ago( + user["email_access_validated_at"], 90 + ) + if not is_fresh_email: + return verify_email(user, redirect_url) + + usr = User.from_email_address(user["email_address"]) + activate_user(usr.id) except BaseException as be: # noqa B036 current_app.logger.error(be) error(401) - return redirect(url_for("main.show_accounts_or_dashboard", next=redirect_url)) # end login.gov +def verify_email(user, redirect_url): + user_api_client.send_verify_code(user["id"], "email", None, redirect_url) + title = "Email resent" if request.args.get("email_resent") else "Check your email" + redirect_url = request.args.get("next") + return render_template( + "views/re-validate-email-sent.html", title=title, redirect_url=redirect_url + ) + + @main.route("/sign-in", methods=(["GET", "POST"])) @hide_from_search_engines def sign_in(): - _do_login_dot_gov() + # If we have to revalidated the email, send the message + # via email and redirect to the "verify your email page" + # and don't proceed further with login + email_verify_template = _do_login_dot_gov() + if ( + email_verify_template + and not isinstance(email_verify_template, Response) + and "Check your email" in email_verify_template + ): + return email_verify_template + redirect_url = request.args.get("next") if os.getenv("NOTIFY_E2E_TEST_EMAIL"): From e14fc8b6542ca8f3a078a9bb415095ab4f107423 Mon Sep 17 00:00:00 2001 From: Jonathan Bobel Date: Wed, 17 Apr 2024 11:03:45 -0400 Subject: [PATCH 3/6] Changed the flag to true --- app/main/views/service_settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/main/views/service_settings.py b/app/main/views/service_settings.py index 7d301426f..a006845a8 100644 --- a/app/main/views/service_settings.py +++ b/app/main/views/service_settings.py @@ -650,7 +650,7 @@ def service_set_channel(service_id, channel): def service_set_auth_type(service_id): return render_template( "views/service-settings/set-auth-type.html", - login_gov_enabled=False, + login_gov_enabled=True, ) From 8596a9cdb33b59cada29f03c8170817ab36ef63d Mon Sep 17 00:00:00 2001 From: Jonathan Bobel Date: Wed, 17 Apr 2024 11:26:14 -0400 Subject: [PATCH 4/6] Removing the email and password fields in the settings area because login.gov will take care of this --- app/templates/views/user-profile.html | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/app/templates/views/user-profile.html b/app/templates/views/user-profile.html index d3e6ff7c8..88f2f1668 100644 --- a/app/templates/views/user-profile.html +++ b/app/templates/views/user-profile.html @@ -27,21 +27,6 @@ }} {% endcall %} - {% call row() %} - {{ text_field('Email address') }} - {{ text_field(current_user.email_address) }} - {% if can_see_edit %} - {{ edit_field( - 'Change', - url_for('.user_profile_email'), - suffix='email address' - ) - }} - {% else %} - {{ text_field('') }} - {% endif %} - {% endcall %} - {% call row() %} {{ text_field('Mobile number') }} {{ optional_text_field(current_user.mobile_number) }} @@ -53,16 +38,6 @@ }} {% endcall %} - {% call row() %} - {{ text_field('Password') }} - {{ text_field('Last changed ' + current_user.password_changed_at|format_delta) }} - {{ edit_field( - 'Change', - url_for('.user_profile_password'), - suffix='password' - ) - }} - {% endcall %} {% call row() %} {{ text_field('Preferred Timezone') }} {{ optional_text_field(current_user.preferred_timezone) }} From 7755e02ad88a816a9cfbc03be1b24490ad5d7733 Mon Sep 17 00:00:00 2001 From: Jonathan Bobel Date: Wed, 17 Apr 2024 11:49:47 -0400 Subject: [PATCH 5/6] Removing instances of the login_gov_enabled flag as it will be live with this push to production --- app/main/views/service_settings.py | 1 - .../views/service-settings/set-auth-type.html | 30 ++----------------- 2 files changed, 3 insertions(+), 28 deletions(-) diff --git a/app/main/views/service_settings.py b/app/main/views/service_settings.py index a006845a8..628ac59e5 100644 --- a/app/main/views/service_settings.py +++ b/app/main/views/service_settings.py @@ -650,7 +650,6 @@ def service_set_channel(service_id, channel): def service_set_auth_type(service_id): return render_template( "views/service-settings/set-auth-type.html", - login_gov_enabled=True, ) diff --git a/app/templates/views/service-settings/set-auth-type.html b/app/templates/views/service-settings/set-auth-type.html index 2fa545a4c..2fd5259f8 100644 --- a/app/templates/views/service-settings/set-auth-type.html +++ b/app/templates/views/service-settings/set-auth-type.html @@ -16,33 +16,9 @@
{{ page_header('Sign-in method') }} - - {% if login_gov_enabled %} -

Your username, password, and multi-factor authentication options are handled by Login.gov.

-

To make changes, head to Login.gov and sign-in with your credentials.

-

Any changes made to your Login.gov account will automatically be synced with Notify.gov.

- {% elif 'email_auth' in current_service.permissions and not login_gov_enabled %} -

- Email link or text message code -

-

- Your team members can sign in with either a text message code - or an email link. -

-

- You can set the sign-in method for individual team members. -

- {% else %} -

- Text message code -

-

- Your team members sign in with a text message code. -

-

- Contact us if signing in with a text message is a problem for your team. -

- {% endif %} +

Your username, password, and multi-factor authentication options are handled by Login.gov.

+

To make changes, head to Login.gov and sign-in with your credentials.

+

Any changes made to your Login.gov account will automatically be synced with Notify.gov.

From 78c08e69f78eaa109519dfdbf12739d41d3f180b Mon Sep 17 00:00:00 2001 From: Jonathan Bobel Date: Wed, 17 Apr 2024 12:01:37 -0400 Subject: [PATCH 6/6] Fixed failing test --- .../views/service_settings/test_service_settings.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tests/app/main/views/service_settings/test_service_settings.py b/tests/app/main/views/service_settings/test_service_settings.py index b87ef12d5..462910406 100644 --- a/tests/app/main/views/service_settings/test_service_settings.py +++ b/tests/app/main/views/service_settings/test_service_settings.py @@ -2545,11 +2545,19 @@ def test_send_files_by_email_contact_details_does_not_update_invalid_contact_det @pytest.mark.parametrize( ("endpoint", "permissions", "expected_p"), [ - ("main.service_set_auth_type", [], ("Text message code")), + ( + "main.service_set_auth_type", + [], + ( + "Your username, password, and multi-factor authentication options are handled by Login.gov." + ), + ), ( "main.service_set_auth_type", ["email_auth"], - ("Email link or text message code"), + ( + "Your username, password, and multi-factor authentication options are handled by Login.gov." + ), ), ], )