diff --git a/app/config.py b/app/config.py index 80700cd39c..23ebe2a6d0 100644 --- a/app/config.py +++ b/app/config.py @@ -25,7 +25,8 @@ class Config(object): ALLOW_DEBUG_ROUTE = env.bool("ALLOW_DEBUG_ROUTE", False) # List of allowed service IDs that are allowed to send HTML through their templates. - ALLOW_HTML_SERVICE_IDS: List[str] = [id.strip() for id in os.getenv("ALLOW_HTML_SERVICE_IDS", "").split(",")] + ALLOW_HTML_SERVICE_IDS: List[str] = [ + id.strip() for id in os.getenv("ALLOW_HTML_SERVICE_IDS", "").split(",")] ADMIN_BASE_URL = ( "https://" + os.environ.get("HEROKU_APP_NAME", "") + ".herokuapp.com" if os.environ.get("HEROKU_APP_NAME", "") != "" @@ -47,12 +48,15 @@ class Config(object): BULK_SEND_AWS_BUCKET = os.getenv("BULK_SEND_AWS_BUCKET") CHECK_PROXY_HEADER = False - CONTACT_EMAIL = os.environ.get("CONTACT_EMAIL", "assistance+notification@cds-snc.ca") - CRM_GITHUB_PERSONAL_ACCESS_TOKEN = os.getenv("CRM_GITHUB_PERSONAL_ACCESS_TOKEN") + CONTACT_EMAIL = os.environ.get( + "CONTACT_EMAIL", "assistance+notification@cds-snc.ca") + CRM_GITHUB_PERSONAL_ACCESS_TOKEN = os.getenv( + "CRM_GITHUB_PERSONAL_ACCESS_TOKEN") CRM_ORG_LIST_URL = os.getenv("CRM_ORG_LIST_URL") CSV_MAX_ROWS = env.int("CSV_MAX_ROWS", 50_000) CSV_MAX_ROWS_BULK_SEND = env.int("CSV_MAX_ROWS_BULK_SEND", 100_000) - CSV_UPLOAD_BUCKET_NAME = os.getenv("CSV_UPLOAD_BUCKET_NAME", "notification-alpha-canada-ca-csv-upload") + CSV_UPLOAD_BUCKET_NAME = os.getenv( + "CSV_UPLOAD_BUCKET_NAME", "notification-alpha-canada-ca-csv-upload") DANGEROUS_SALT = os.environ.get("DANGEROUS_SALT") DEBUG = False DEBUG_KEY = os.environ.get("DEBUG_KEY", "") @@ -67,25 +71,30 @@ class Config(object): "other": 25_000, } DEFAULT_LIVE_SERVICE_LIMIT = env.int("DEFAULT_LIVE_SERVICE_LIMIT", 10_000) - DEFAULT_LIVE_SMS_DAILY_LIMIT = env.int("DEFAULT_LIVE_SMS_DAILY_LIMIT", 1000) + DEFAULT_LIVE_SMS_DAILY_LIMIT = env.int( + "DEFAULT_LIVE_SMS_DAILY_LIMIT", 1000) DEFAULT_SERVICE_LIMIT = env.int("DEFAULT_SERVICE_LIMIT", 50) DEFAULT_SMS_DAILY_LIMIT = env.int("DEFAULT_SMS_DAILY_LIMIT", 50) - DOCUMENTATION_DOMAIN = os.getenv("DOCUMENTATION_DOMAIN", "documentation.notification.canada.ca") + DOCUMENTATION_DOMAIN = os.getenv( + "DOCUMENTATION_DOMAIN", "documentation.notification.canada.ca") EMAIL_2FA_EXPIRY_SECONDS = 1_800 # 30 Minutes EMAIL_EXPIRY_SECONDS = 3600 # 1 hour # for waffles: pull out the routes into a flat list of the form ['/home', '/accueil', '/why-gc-notify', ...] - EXTRA_ROUTES = [item for sublist in map(lambda x: x.values(), GC_ARTICLES_ROUTES.values()) for item in sublist] + EXTRA_ROUTES = [item for sublist in map( + lambda x: x.values(), GC_ARTICLES_ROUTES.values()) for item in sublist] # FEATURE FLAGS FF_SALESFORCE_CONTACT = env.bool("FF_SALESFORCE_CONTACT", True) - FF_TOU = env.bool("FF_TOU", False) FREE_YEARLY_EMAIL_LIMIT = env.int("FREE_YEARLY_EMAIL_LIMIT", 10_000_000) FREE_YEARLY_SMS_LIMIT = env.int("FREE_YEARLY_SMS_LIMIT", 25_000) - GC_ARTICLES_API = os.environ.get("GC_ARTICLES_API", "articles.alpha.canada.ca/notification-gc-notify") - GC_ARTICLES_API_AUTH_PASSWORD = os.environ.get("GC_ARTICLES_API_AUTH_PASSWORD") - GC_ARTICLES_API_AUTH_USERNAME = os.environ.get("GC_ARTICLES_API_AUTH_USERNAME") + GC_ARTICLES_API = os.environ.get( + "GC_ARTICLES_API", "articles.alpha.canada.ca/notification-gc-notify") + GC_ARTICLES_API_AUTH_PASSWORD = os.environ.get( + "GC_ARTICLES_API_AUTH_PASSWORD") + GC_ARTICLES_API_AUTH_USERNAME = os.environ.get( + "GC_ARTICLES_API_AUTH_USERNAME") GOOGLE_ANALYTICS_ID = os.getenv("GOOGLE_ANALYTICS_ID", "UA-102484926-14") GOOGLE_TAG_MANAGER_ID = os.getenv("GOOGLE_TAG_MANAGER_ID", "GTM-KRKRZQV") HC_EN_SERVICE_ID = os.getenv("HC_EN_SERVICE_ID") @@ -93,9 +102,11 @@ class Config(object): HIPB_ENABLED = True HTTP_PROTOCOL = "http" INVITATION_EXPIRY_SECONDS = 3_600 * 24 * 2 # 2 days - also set on api - IP_GEOLOCATE_SERVICE = os.environ.get("IP_GEOLOCATE_SERVICE", "").rstrip("/") + IP_GEOLOCATE_SERVICE = os.environ.get( + "IP_GEOLOCATE_SERVICE", "").rstrip("/") LANGUAGES = ["en", "fr"] - LOGO_UPLOAD_BUCKET_NAME = os.getenv("ASSET_UPLOAD_BUCKET_NAME", "notification-alpha-canada-ca-asset-upload") + LOGO_UPLOAD_BUCKET_NAME = os.getenv( + "ASSET_UPLOAD_BUCKET_NAME", "notification-alpha-canada-ca-asset-upload") MAX_FAILED_LOGIN_COUNT = 10 MOU_BUCKET_NAME = os.getenv("MOU_BUCKET_NAME", "") @@ -118,8 +129,10 @@ class Config(object): SCANFILES_URL = os.environ.get("SCANFILES_URL", "") SECRET_KEY = env.list("SECRET_KEY", []) - SECURITY_EMAIL = os.environ.get("SECURITY_EMAIL", "security+securite@cds-snc.ca") - SENDING_DOMAIN = os.environ.get("SENDING_DOMAIN", "notification.alpha.canada.ca") + SECURITY_EMAIL = os.environ.get( + "SECURITY_EMAIL", "security+securite@cds-snc.ca") + SENDING_DOMAIN = os.environ.get( + "SENDING_DOMAIN", "notification.alpha.canada.ca") SESSION_COOKIE_HTTPONLY = True SESSION_COOKIE_NAME = "notify_admin_session" SESSION_COOKIE_SAMESITE = "Lax" @@ -133,8 +146,10 @@ class Config(object): STATSD_PORT = 8_125 STATSD_PREFIX = os.getenv("STATSD_PREFIX") - TEMPLATE_PREVIEW_API_HOST = os.environ.get("TEMPLATE_PREVIEW_API_HOST", "http://localhost:6013") - TEMPLATE_PREVIEW_API_KEY = os.environ.get("TEMPLATE_PREVIEW_API_KEY", "my-secret-key") + TEMPLATE_PREVIEW_API_HOST = os.environ.get( + "TEMPLATE_PREVIEW_API_HOST", "http://localhost:6013") + TEMPLATE_PREVIEW_API_KEY = os.environ.get( + "TEMPLATE_PREVIEW_API_KEY", "my-secret-key") WAF_SECRET = os.environ.get("WAF_SECRET", "waf-secret") WTF_CSRF_ENABLED = True WTF_CSRF_TIME_LIMIT = None @@ -145,7 +160,8 @@ class Config(object): NOTIFY_USER_ID = "6af522d0-2915-4e52-83a3-3690455a5fe6" NOTIFY_SERVICE_ID = "d6aa2c68-a2d9-4437-ab19-3ae8eb202553" - NO_BRANDING_ID = os.environ.get("NO_BRANDING_ID", "0af93cf1-2c49-485f-878f-f3e662e651ef") + NO_BRANDING_ID = os.environ.get( + "NO_BRANDING_ID", "0af93cf1-2c49-485f-878f-f3e662e651ef") @classmethod def get_sensitive_config(cls) -> list[str]: @@ -173,7 +189,8 @@ def get_safe_config(cls) -> dict[str, Any]: class Development(Config): - ADMIN_CLIENT_SECRET = os.environ.get("ADMIN_CLIENT_SECRET", "dev-notify-secret-key") + ADMIN_CLIENT_SECRET = os.environ.get( + "ADMIN_CLIENT_SECRET", "dev-notify-secret-key") ANTIVIRUS_API_HOST = "http://localhost:6016" ANTIVIRUS_API_KEY = "test-key" API_HOST_NAME = os.environ.get("API_HOST_NAME", "http://localhost:6011") @@ -190,7 +207,8 @@ class Development(Config): class Test(Development): - ADMIN_CLIENT_SECRET = os.environ.get("ADMIN_CLIENT_SECRET", "dev-notify-secret-key") + ADMIN_CLIENT_SECRET = os.environ.get( + "ADMIN_CLIENT_SECRET", "dev-notify-secret-key") ANTIVIRUS_API_HOST = "https://test-antivirus" ANTIVIRUS_API_KEY = "test-antivirus-secret" API_HOST_NAME = os.environ.get("API_HOST_NAME", "http://localhost:6011") @@ -218,11 +236,11 @@ class Test(Development): FF_BOUNCE_RATE_V15 = True FF_BOUNCE_RATE_BACKEND = True FF_ABTEST_SERVICE_ID = "" - FF_TOU = True class ProductionFF(Config): - ADMIN_CLIENT_SECRET = os.environ.get("ADMIN_CLIENT_SECRET", "dev-notify-secret-key") + ADMIN_CLIENT_SECRET = os.environ.get( + "ADMIN_CLIENT_SECRET", "dev-notify-secret-key") ANTIVIRUS_API_HOST = "https://test-antivirus" ANTIVIRUS_API_KEY = "test-antivirus-secret" API_HOST_NAME = os.environ.get("API_HOST_NAME", "http://localhost:6011") @@ -250,7 +268,6 @@ class ProductionFF(Config): FF_BOUNCE_RATE_V15 = True FF_BOUNCE_RATE_BACKEND = True FF_ABTEST_SERVICE_ID = "" - FF_TOU = False class Production(Config): @@ -267,7 +284,6 @@ class Staging(Production): NOTIFY_LOG_LEVEL = "INFO" SYSTEM_STATUS_URL = "https://status.staging.notification.cdssandbox.xyz" NO_BRANDING_ID = "0af93cf1-2c49-485f-878f-f3e662e651ef" - FF_TOU = True class Scratch(Production): diff --git a/app/main/forms.py b/app/main/forms.py index 5446032d1f..d890972398 100644 --- a/app/main/forms.py +++ b/app/main/forms.py @@ -3,7 +3,7 @@ from itertools import chain import pytz -from flask import current_app, request +from flask import request from flask_babel import lazy_gettext as _l from flask_wtf import FlaskForm as Form from flask_wtf.file import FileAllowed @@ -382,9 +382,8 @@ class RegisterUserForm(StripWhitespaceForm): tou_agreed = HiddenField("tou_agreed", validators=[]) def validate_tou_agreed(self, field): - if current_app.config["FF_TOU"]: - if field.data is not None and field.data.strip() == "": - raise ValidationError(_l("Read and agree to continue")) + if field.data is not None and field.data.strip() == "": + raise ValidationError(_l("Read and agree to continue")) class RegisterUserFromInviteForm(RegisterUserForm): diff --git a/app/templates/views/register.html b/app/templates/views/register.html index 57659c17e8..21bdcf7cb6 100644 --- a/app/templates/views/register.html +++ b/app/templates/views/register.html @@ -26,14 +26,8 @@

{{ _('Create an account') }}

{% set txt = _('Must be at least 8 characters and hard to guess') %} {{ textbox(form.password, hint=txt, width='w-full md:w-3/4', autocomplete='new-password') }} - {% if config['FF_TOU'] %} - {{ tou_dialog_trigger(button_text=_('Read and agree to the terms of use'), is_in_error_state=(form.errors.get('tou_agreed') != None)) }} - {{ form.tou_agreed }} - {% else %} -

- {{ _("By creating an account, you agree to the terms of use.").format(gca_url_for('terms')) }} -

- {% endif %} + {{ tou_dialog_trigger(button_text=_('Read and agree to the terms of use'), is_in_error_state=(form.errors.get('tou_agreed') != None)) }} + {{ form.tou_agreed }} {{ form.auth_type }} {% set txt = _('Continue') %} @@ -43,8 +37,6 @@

{{ _('Create an account') }}

{% endblock %} -{% if config['FF_TOU'] %} - {% block body_end %} - {{ tou_dialog() }} - {% endblock %} -{% endif %} +{% block body_end %} + {{ tou_dialog() }} +{% endblock %} diff --git a/app/tou.py b/app/tou.py index 2eeb860a0e..ab43d49f17 100644 --- a/app/tou.py +++ b/app/tou.py @@ -1,4 +1,4 @@ -from flask import current_app, request, session +from flask import request, session from flask_login import current_user from app.articles.routing import GC_ARTICLES_ROUTES @@ -12,10 +12,6 @@ def show_tou_prompt(): The TOU prompt should be displayed if the user is authenticated, has not already agreed to the terms, and is not on the contact page or a GCA route. """ - - if current_app.config["FF_TOU"] is False: - return False - is_gca_route = False for route in GC_ARTICLES_ROUTES.values(): diff --git a/tests/app/main/test_tou.py b/tests/app/main/test_tou.py index ab4842aa77..38d1921553 100644 --- a/tests/app/main/test_tou.py +++ b/tests/app/main/test_tou.py @@ -2,7 +2,6 @@ from app.articles.routing import GC_ARTICLES_ROUTES from app.tou import show_tou_prompt -from tests.conftest import set_config class TestShowTouPrompt: @@ -30,8 +29,7 @@ def setUp(self, app_, api_user_active): ) def test_show_tou_prompt(self, route, login, agree_to_terms, expected, app_): with self.app.test_request_context(), self.app.test_client() as client: - with set_config(app_, "FF_TOU", True): # remove this line when FF is removed - if login: - client.login(self.api_user_active, agree_to_terms=agree_to_terms) - client.get(route) - assert show_tou_prompt() == expected + if login: + client.login(self.api_user_active, agree_to_terms=agree_to_terms) + client.get(route) + assert show_tou_prompt() == expected diff --git a/tests/app/main/test_validation_summary.py b/tests/app/main/test_validation_summary.py index 8b1f2af282..82c6924d8b 100644 --- a/tests/app/main/test_validation_summary.py +++ b/tests/app/main/test_validation_summary.py @@ -1,6 +1,6 @@ import pytest from bs4 import BeautifulSoup -from flask import current_app, url_for +from flask import url_for register_field_names = ("name", "email_address", "mobile_number", "password") @@ -35,8 +35,7 @@ def test_validation_summary( data, expected_errors, ): - if current_app.config["FF_TOU"]: - data["tou_agreed"] = "true" + data["tou_agreed"] = "true" response = client.post(url_for("main.register"), data=data, follow_redirects=True) assert response.status_code == 200 diff --git a/tests/app/main/test_validators.py b/tests/app/main/test_validators.py index c56fce56f7..babead3e51 100644 --- a/tests/app/main/test_validators.py +++ b/tests/app/main/test_validators.py @@ -1,7 +1,6 @@ from unittest.mock import Mock import pytest -from flask import current_app from wtforms import ValidationError from app.main.forms import RegisterUserForm, ServiceSmsSenderForm @@ -35,22 +34,13 @@ def test_valid_email_not_in_valid_domains( def test_valid_email_in_valid_domains(client): - if current_app.config["FF_TOU"]: - form = RegisterUserForm( - name="test", - email_address="test@my.gc.ca", - mobile_number="6502532222", - password="an uncommon password", - tou_agreed="true", - ) - else: - form = RegisterUserForm( - name="test", - email_address="test@my.gc.ca", - mobile_number="6502532222", - password="an uncommon password", - ) - + form = RegisterUserForm( + name="test", + email_address="test@my.gc.ca", + mobile_number="6502532222", + password="an uncommon password", + tou_agreed="true", + ) form.validate() assert form.errors == {} diff --git a/tests/app/main/views/test_accept_invite.py b/tests/app/main/views/test_accept_invite.py index 5ad3e2370e..03befcb941 100644 --- a/tests/app/main/views/test_accept_invite.py +++ b/tests/app/main/views/test_accept_invite.py @@ -2,7 +2,7 @@ import pytest from bs4 import BeautifulSoup -from flask import current_app, url_for +from flask import url_for from notifications_python_client.errors import HTTPError import app @@ -405,8 +405,7 @@ def test_new_user_accept_invite_completes_new_registration_redirects_to_verify( "auth_type": "email_auth", } - if current_app.config["FF_TOU"]: - data["tou_agreed"] = "true" + data["tou_agreed"] = "true" expected_redirect_location = "/verify" response = client.post(url_for("main.register_from_invite"), data=data) @@ -519,9 +518,7 @@ def test_new_invited_user_verifies_and_added_to_service( "name": "Invited User", "auth_type": "sms_auth", } - - if current_app.config["FF_TOU"]: - data["tou_agreed"] = "true" + data["tou_agreed"] = "true" response = client.post(url_for("main.register_from_invite"), data=data) assert response.status_code == 302 diff --git a/tests/app/main/views/test_register.py b/tests/app/main/views/test_register.py index 9f85e07042..5feaeafa3c 100644 --- a/tests/app/main/views/test_register.py +++ b/tests/app/main/views/test_register.py @@ -3,7 +3,7 @@ import pytest from bs4 import BeautifulSoup -from flask import current_app, url_for +from flask import url_for from app.models.user import InvitedUser, User @@ -62,9 +62,7 @@ def test_register_creates_new_user_and_redirects_to_continue_page( "password": password, "auth_type": "sms_auth", } - - if current_app.config["FF_TOU"]: - user_data["tou_agreed"] = "true" + user_data["tou_agreed"] = "true" response = client.post(url_for("main.register"), data=user_data, follow_redirects=True) assert response.status_code == 200 @@ -158,9 +156,7 @@ def test_should_add_user_details_to_session( "mobile_number": "+16502532222", "password": "rZXdoBkuz6U37DDXIaAfpBR1OTJcSZOGICLCz4dMtmopS3KsVauIrtcgqs1eU02", } - - if current_app.config["FF_TOU"]: - data["tou_agreed"] = "true" + data["tou_agreed"] = "true" client_request.post("main.register", _data=data) with client_request.session_transaction() as session: @@ -199,8 +195,7 @@ def test_register_with_existing_email_sends_emails( "password": "rZXdoBkuz6U37DDXIaAfpBR1OTJcSZOGICLCz4dMtmopS3KsVauIrtcgqs1eU02", } - if current_app.config["FF_TOU"]: - user_data["tou_agreed"] = "true" + user_data["tou_agreed"] = "true" response = client.post(url_for("main.register"), data=user_data) assert response.status_code == 302 @@ -285,8 +280,7 @@ def test_register_from_invite( "auth_type": "sms_auth", } - if current_app.config["FF_TOU"]: - data["tou_agreed"] = "true" + data["tou_agreed"] = "true" response = client.post(url_for("main.register_from_invite"), data=data) assert response.status_code == 302 @@ -332,8 +326,7 @@ def test_register_from_invite_when_user_registers_in_another_browser( "auth_type": "sms_auth", } - if current_app.config["FF_TOU"]: - data["tou_agreed"] = "true" + data["tou_agreed"] = "true" response = client.post(url_for("main.register_from_invite"), data=data) assert response.status_code == 302 @@ -371,8 +364,7 @@ def test_register_from_email_auth_invite( "auth_type": "email_auth", } - if current_app.config["FF_TOU"]: - data["tou_agreed"] = "true" + data["tou_agreed"] = "true" resp = client.post(url_for("main.register_from_invite"), data=data) assert resp.status_code == 302 @@ -388,7 +380,8 @@ def test_register_from_email_auth_invite( mock_accept_invite.assert_called_once_with(sample_invite["service"], sample_invite["id"]) # just logs them in mock_login_user.assert_called_once_with( - User({"id": fake_uuid, "platform_admin": False}) # This ID matches the return value of mock_register_user + # This ID matches the return value of mock_register_user + User({"id": fake_uuid, "platform_admin": False}) ) mock_add_user_to_service.assert_called_once_with( sample_invite["service"], @@ -429,8 +422,8 @@ def test_can_register_email_auth_without_phone_number( "auth_type": "email_auth", } - if current_app.config["FF_TOU"]: - data["tou_agreed"] = "true" + data["tou_agreed"] = "true" + resp = client.post(url_for("main.register_from_invite"), data=data) assert resp.status_code == 302 assert resp.location == url_for("main.service_dashboard", service_id=sample_invite["service"])