diff --git a/zerver/tests/test_push_notifications.py b/zerver/tests/test_push_notifications.py index 97ab5ae5a6..07dfc02b6c 100644 --- a/zerver/tests/test_push_notifications.py +++ b/zerver/tests/test_push_notifications.py @@ -76,6 +76,7 @@ from zerver.models import ( get_realm, get_stream, ) +from zilencer.models import RemoteZulipServerAuditLog if settings.ZILENCER_ENABLED: from zilencer.models import ( @@ -2485,6 +2486,44 @@ class TestPushNotificationsContent(ZulipTestCase): @skipUnless(settings.ZILENCER_ENABLED, "requires zilencer") class PushBouncerSignupTest(ZulipTestCase): + def test_deactivate_remote_server(self) -> None: + zulip_org_id = str(uuid.uuid4()) + zulip_org_key = get_random_string(64) + request = dict( + zulip_org_id=zulip_org_id, + zulip_org_key=zulip_org_key, + hostname="example.com", + contact_email="server-admin@example.com", + ) + result = self.client_post("/api/v1/remotes/server/register", request) + self.assert_json_success(result) + server = RemoteZulipServer.objects.get(uuid=zulip_org_id) + self.assertEqual(server.hostname, "example.com") + self.assertEqual(server.contact_email, "server-admin@example.com") + + request = dict(zulip_org_id=zulip_org_id, zulip_org_key=zulip_org_key) + result = self.uuid_post( + zulip_org_id, "/api/v1/remotes/server/deactivate", request, subdomain="" + ) + self.assert_json_success(result) + + server = RemoteZulipServer.objects.get(uuid=zulip_org_id) + remote_realm_audit_log = RemoteZulipServerAuditLog.objects.filter( + event_type=RealmAuditLog.REMOTE_SERVER_DEACTIVATED + ).last() + assert remote_realm_audit_log is not None + self.assertTrue(server.deactivated) + + # Now test that trying to deactivate again reports the right error. + result = self.uuid_post( + zulip_org_id, "/api/v1/remotes/server/deactivate", request, subdomain="" + ) + self.assert_json_error( + result, + "The mobile push notification service registration for your server has been deactivated", + status_code=401, + ) + def test_push_signup_invalid_host(self) -> None: zulip_org_id = str(uuid.uuid4()) zulip_org_key = get_random_string(64) diff --git a/zilencer/urls.py b/zilencer/urls.py index 4f84493b32..bdf00997db 100644 --- a/zilencer/urls.py +++ b/zilencer/urls.py @@ -5,6 +5,7 @@ from django.urls import path from zerver.lib.rest import rest_path from zilencer.views import ( + deactivate_remote_server, register_remote_push_device, register_remote_server, remote_server_check_analytics, @@ -24,6 +25,7 @@ v1_api_and_json_patterns = [ rest_path("remotes/push/notify", POST=remote_server_notify_push), # Push signup doesn't use the REST API, since there's no auth. path("remotes/server/register", register_remote_server), + rest_path("remotes/server/deactivate", POST=deactivate_remote_server), # For receiving table data used in analytics and billing rest_path("remotes/server/analytics", POST=remote_server_post_analytics), rest_path("remotes/server/analytics/status", GET=remote_server_check_analytics), diff --git a/zilencer/views.py b/zilencer/views.py index f7d65a6d3a..e0c44072ea 100644 --- a/zilencer/views.py +++ b/zilencer/views.py @@ -13,6 +13,7 @@ from django.utils.translation import gettext as err_ from django.views.decorators.csrf import csrf_exempt from analytics.lib.counts import COUNT_STATS +from corporate.lib.stripe import do_deactivate_remote_server from zerver.decorator import InvalidZulipServerKeyError, require_post from zerver.lib.exceptions import JsonableError from zerver.lib.push_notifications import ( @@ -75,6 +76,17 @@ def validate_bouncer_token_request( return server +@csrf_exempt +@require_post +@has_request_variables +def deactivate_remote_server( + request: HttpRequest, + remote_server: RemoteZulipServer, +) -> HttpResponse: + do_deactivate_remote_server(remote_server) + return json_success() + + @csrf_exempt @require_post @has_request_variables