From 56707e7ba604c6bf31a22bb37710834c0e3c073c Mon Sep 17 00:00:00 2001 From: Jumana Bahrainwala Date: Thu, 29 Aug 2024 20:54:22 +0000 Subject: [PATCH 1/2] Add admin interfact to suspend callback if they exist --- app/main/views/service_settings.py | 37 +++++++++++++++++++ app/models/service.py | 3 ++ app/notify_client/service_api_client.py | 7 ++++ app/templates/views/service-settings.html | 19 ++++++++++ app/translations/csv/fr.csv | 1 + tests/app/main/views/test_service_settings.py | 12 ++++++ .../notify_client/test_service_api_client.py | 13 +++++++ 7 files changed, 92 insertions(+) diff --git a/app/main/views/service_settings.py b/app/main/views/service_settings.py index 0fdcb35c3b..5c0767a19d 100644 --- a/app/main/views/service_settings.py +++ b/app/main/views/service_settings.py @@ -98,12 +98,18 @@ def service_settings(service_id: str): "free_yearly_email": current_app.config["FREE_YEARLY_EMAIL_LIMIT"], "free_yearly_sms": current_app.config["FREE_YEARLY_SMS_LIMIT"], } + callback_api = ( + service_api_client.get_service_callback_api(current_service.id, current_service.service_callback_api[0]) + if current_service.service_callback_api + else None + ) assert limits["free_yearly_email"] >= 2_000_000, "The user-interface does not support French translations of < 2M" return render_template( "views/service-settings.html", service_permissions=PLATFORM_ADMIN_SERVICE_PERMISSIONS, sending_domain=current_service.sending_domain or current_app.config["SENDING_DOMAIN"], # type: ignore limits=limits, + callback_api=callback_api, ) @@ -1458,6 +1464,37 @@ def edit_data_retention(service_id, data_retention_id): ) +@main.route( + "/services//service-settings/suspend-callback", + methods=["GET", "POST"], +) +@user_is_platform_admin +def suspend_callback(service_id): + title = _("Suspend Callback") + form = ServiceOnOffSettingForm(name=title) + if current_service.service_callback_api: + callback_api = service_api_client.get_service_callback_api(current_service.id, current_service.service_callback_api[0]) + form = ServiceOnOffSettingForm(name=title, enabled=callback_api["is_suspended"]) + + if form.validate_on_submit(): + try: + service_api_client.suspend_service_callback_api(service_id, current_user.id, suspend_unsuspend=form.enabled.data) + except Exception as e: + raise "Error suspending callback: {}".format(e) + return redirect(url_for(".service_settings", service_id=service_id)) + + return render_template( + "views/service-settings/set-service-setting.html", + title=_("Suspend Callback"), + form=form, + ) + return render_template( + "views/service-settings/set-service-setting.html", + title=_("Suspend Callback"), + form=form, + ) + + def get_branding_as_value_and_label(email_branding): return [(branding["id"], branding["name"]) for branding in email_branding] diff --git a/app/models/service.py b/app/models/service.py index 4c72e19340..46c466dcc8 100644 --- a/app/models/service.py +++ b/app/models/service.py @@ -88,6 +88,9 @@ def update_permissions(self, permissions): def toggle_research_mode(self): self.update(research_mode=not self.research_mode) + def suspend_callback_api(self, **kwargs): + return service_api_client.suspend_service_callback_api(self.id, **kwargs) + @property def trial_mode(self): return self._dict["restricted"] diff --git a/app/notify_client/service_api_client.py b/app/notify_client/service_api_client.py index abcb27a821..4fce79bf68 100644 --- a/app/notify_client/service_api_client.py +++ b/app/notify_client/service_api_client.py @@ -504,6 +504,13 @@ def update_service_callback_api(self, service_id, url, bearer_token, user_id, ca def delete_service_callback_api(self, service_id, callback_api_id): return self.delete("/service/{}/delivery-receipt-api/{}".format(service_id, callback_api_id)) + @cache.delete("service-{service_id}") + def suspend_service_callback_api(self, service_id, updated_by_id, suspend_unsuspend): + return self.post( + "/service/{}/delivery-receipt-api/suspend-callback".format(service_id), + data={"updated_by_id": updated_by_id, "suspend_unsuspend": suspend_unsuspend}, + ) + @cache.delete("service-{service_id}") def create_service_callback_api(self, service_id, url, bearer_token, user_id): data = {"url": url, "bearer_token": bearer_token, "updated_by_id": user_id} diff --git a/app/templates/views/service-settings.html b/app/templates/views/service-settings.html index 65e9bca601..349ece99a5 100644 --- a/app/templates/views/service-settings.html +++ b/app/templates/views/service-settings.html @@ -494,6 +494,25 @@

{{ _('Platform admin settings') }}

) }} {% endcall %} + {%if callback_api%} + {% call row() %} + {% set txt = _('Suspend Callback') %} + {{ text_field(txt)}} + {% if callback_api is not none and callback_api.is_suspended %} + {% set value = _('On') %} + {{ text_field(value) }} + {% else %} + {% set value = _('Off') %} + {{ text_field(value) }} + {% endif %} + {{ edit_field( + change_txt, + url_for('.suspend_callback', service_id=current_service.id), + for=txt + ) }} + {% endcall %} + {% endif %} + {% endcall %} diff --git a/app/translations/csv/fr.csv b/app/translations/csv/fr.csv index 033f357696..2548e148c9 100644 --- a/app/translations/csv/fr.csv +++ b/app/translations/csv/fr.csv @@ -1977,3 +1977,4 @@ "Change your filters or search for more templates","Modifiez vos filtres ou recherchez d’autres gabarits" "Review your activity","Examinez votre activité" "Set sensitive service","Définir un service sensible" +"Suspend Callback","Suspension du rappel" \ No newline at end of file diff --git a/tests/app/main/views/test_service_settings.py b/tests/app/main/views/test_service_settings.py index af2b0c3ab8..32a0ec6917 100644 --- a/tests/app/main/views/test_service_settings.py +++ b/tests/app/main/views/test_service_settings.py @@ -4306,3 +4306,15 @@ def test_should_redirect_after_change_service_name( client_request.post( "main.set_sensitive_service", service_id=SERVICE_ONE_ID, _data={"sensitive_service": False}, _expected_status=200 ) + + +class TestSuspendingCallbackApi: + def test_should_suspend_service_callback_api(self, client_request, platform_admin_user, mocker, service_one): + + client_request.login(platform_admin_user, service_one) + client_request.post( + "main.suspend_callback", + service_id=service_one["id"], + _data={"updated_by_id": platform_admin_user["id"], "suspend_unsuspend": False}, + _expected_status=200, + ) diff --git a/tests/app/notify_client/test_service_api_client.py b/tests/app/notify_client/test_service_api_client.py index 8103a3615a..3eeab49b50 100644 --- a/tests/app/notify_client/test_service_api_client.py +++ b/tests/app/notify_client/test_service_api_client.py @@ -576,3 +576,16 @@ def test_store_use_case_data(mocker): ex=60 * 60 * 60 * 24, # 60 days in seconds ) mock_redis_delete.assert_called_once_with(f"use-case-submitted-{SERVICE_ONE_ID}") + + +class TestSuspendCallbackApi: + def test_suspend_callback_api(self, mocker, active_user_with_permissions): + service_id = str(uuid4()) + mock_post = mocker.patch("app.notify_client.service_api_client.ServiceAPIClient.post") + ServiceAPIClient().suspend_service_callback_api(service_id, active_user_with_permissions["id"], True) + mock_post.assert_called_once() + args, kwargs = mock_post.call_args_list[0] + expected_url = f"/service/{service_id}/delivery-receipt-api/suspend-callback" + expected_data = {"updated_by_id": active_user_with_permissions["id"], "suspend_unsuspend": True} + assert args[0] == expected_url + assert kwargs["data"] == expected_data From 4e4eba1ee1eaf4c19211f91b548cb6d1400aaf92 Mon Sep 17 00:00:00 2001 From: Jumana Bahrainwala Date: Tue, 3 Sep 2024 18:54:59 +0000 Subject: [PATCH 2/2] change string --- app/notify_client/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/notify_client/__init__.py b/app/notify_client/__init__.py index 342ec605e7..0bcb2676a6 100644 --- a/app/notify_client/__init__.py +++ b/app/notify_client/__init__.py @@ -62,7 +62,7 @@ def log_admin_call(self, url, method): if current_service: service_is_sensitive = current_service.sensitive_service if current_service.sensitive_service else False if hasattr(current_user, "platform_admin") and current_user.platform_admin: - user = current_user.email_address + "|" + current_user.id + user = f"{current_user.email_address}|{current_user.id}" logger.warn("{}Admin API request {} {} {} ".format("Sensitive " if service_is_sensitive else "", method, url, user)) def get(self, url, params=None):