mirror of
				https://github.com/zulip/zulip.git
				synced 2025-11-04 05:53:43 +00:00 
			
		
		
		
	zilencer: Add last_request_datetime to RemoteRealm + RemoteZulipServer.
For the RemoteRealm case, we can only set this in endpoints where the
remote server sends us the realm_uuid. So we're missing that for the
endpoints:
- remotes/push/unregister and remotes/push/unregister/all
- remotes/push/test_notification
This should be added in a follow-up commit.
(cherry picked from commit 3dca333b8d)
			
			
This commit is contained in:
		
				
					committed by
					
						
						Tim Abbott
					
				
			
			
				
	
			
			
			
						parent
						
							81b42e3c41
						
					
				
				
					commit
					3a4d45022f
				
			@@ -606,6 +606,8 @@ class PushBouncerNotificationTest(BouncerTestCase):
 | 
			
		||||
    def test_send_notification_endpoint(self) -> None:
 | 
			
		||||
        hamlet = self.example_user("hamlet")
 | 
			
		||||
        server = self.server
 | 
			
		||||
        remote_realm = RemoteRealm.objects.get(server=server, uuid=hamlet.realm.uuid)
 | 
			
		||||
 | 
			
		||||
        token = "aaaa"
 | 
			
		||||
        android_tokens = []
 | 
			
		||||
        uuid_android_tokens = []
 | 
			
		||||
@@ -649,6 +651,8 @@ class PushBouncerNotificationTest(BouncerTestCase):
 | 
			
		||||
            },
 | 
			
		||||
            "gcm_options": {},
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        time_sent = now()
 | 
			
		||||
        with mock.patch(
 | 
			
		||||
            "zilencer.views.send_android_push_notification", return_value=2
 | 
			
		||||
        ) as android_push, mock.patch(
 | 
			
		||||
@@ -656,6 +660,8 @@ class PushBouncerNotificationTest(BouncerTestCase):
 | 
			
		||||
        ) as apple_push, mock.patch(
 | 
			
		||||
            "corporate.lib.stripe.RemoteServerBillingSession.current_count_for_billed_licenses",
 | 
			
		||||
            return_value=10,
 | 
			
		||||
        ), time_machine.travel(
 | 
			
		||||
            time_sent, tick=False
 | 
			
		||||
        ), self.assertLogs(
 | 
			
		||||
            "zilencer.views", level="INFO"
 | 
			
		||||
        ) as logger:
 | 
			
		||||
@@ -711,6 +717,11 @@ class PushBouncerNotificationTest(BouncerTestCase):
 | 
			
		||||
            remote=server,
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        remote_realm.refresh_from_db()
 | 
			
		||||
        server.refresh_from_db()
 | 
			
		||||
        self.assertEqual(remote_realm.last_request_datetime, time_sent)
 | 
			
		||||
        self.assertEqual(server.last_request_datetime, time_sent)
 | 
			
		||||
 | 
			
		||||
    def test_send_notification_endpoint_on_free_plans(self) -> None:
 | 
			
		||||
        hamlet = self.example_user("hamlet")
 | 
			
		||||
        remote_server = self.server
 | 
			
		||||
@@ -1221,10 +1232,12 @@ class PushBouncerNotificationTest(BouncerTestCase):
 | 
			
		||||
            # normal setup.
 | 
			
		||||
            update_remote_realm_data_for_server(self.server, get_realms_info_for_push_bouncer())
 | 
			
		||||
 | 
			
		||||
            # Test that we can push more times
 | 
			
		||||
            time_sent = now()
 | 
			
		||||
            with time_machine.travel(time_sent, tick=False):
 | 
			
		||||
                result = self.client_post(endpoint, {"token": token, **appid}, subdomain="zulip")
 | 
			
		||||
                self.assert_json_success(result)
 | 
			
		||||
 | 
			
		||||
                # Test that we can push more times
 | 
			
		||||
                result = self.client_post(endpoint, {"token": token, **appid}, subdomain="zulip")
 | 
			
		||||
                self.assert_json_success(result)
 | 
			
		||||
 | 
			
		||||
@@ -1237,9 +1250,16 @@ class PushBouncerNotificationTest(BouncerTestCase):
 | 
			
		||||
            self.assertEqual(tokens[0].kind, kind)
 | 
			
		||||
            # These new registrations have .remote_realm set properly.
 | 
			
		||||
            assert tokens[0].remote_realm is not None
 | 
			
		||||
            self.assertEqual(tokens[0].remote_realm.uuid, user.realm.uuid)
 | 
			
		||||
            remote_realm = tokens[0].remote_realm
 | 
			
		||||
            self.assertEqual(remote_realm.uuid, user.realm.uuid)
 | 
			
		||||
            self.assertEqual(tokens[0].ios_app_id, appid.get("appid"))
 | 
			
		||||
 | 
			
		||||
            # Both RemoteRealm and RemoteZulipServer should have last_request_datetime
 | 
			
		||||
            # updated.
 | 
			
		||||
            self.assertEqual(remote_realm.last_request_datetime, time_sent)
 | 
			
		||||
            server.refresh_from_db()
 | 
			
		||||
            self.assertEqual(server.last_request_datetime, time_sent)
 | 
			
		||||
 | 
			
		||||
        # User should have tokens for both devices now.
 | 
			
		||||
        tokens = list(RemotePushDeviceToken.objects.filter(user_uuid=user.uuid, server=server))
 | 
			
		||||
        self.assert_length(tokens, 2)
 | 
			
		||||
@@ -4748,11 +4768,16 @@ class PushBouncerSignupTest(ZulipTestCase):
 | 
			
		||||
            hostname="example.com",
 | 
			
		||||
            contact_email="server-admin@example.com",
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        time_sent = now()
 | 
			
		||||
 | 
			
		||||
        with time_machine.travel(time_sent, tick=False):
 | 
			
		||||
            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")
 | 
			
		||||
        self.assertEqual(server.last_request_datetime, time_sent)
 | 
			
		||||
 | 
			
		||||
        # Update our hostname
 | 
			
		||||
        request = dict(
 | 
			
		||||
@@ -4761,11 +4786,14 @@ class PushBouncerSignupTest(ZulipTestCase):
 | 
			
		||||
            hostname="zulip.example.com",
 | 
			
		||||
            contact_email="server-admin@example.com",
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        with time_machine.travel(time_sent + timedelta(minutes=1), tick=False):
 | 
			
		||||
            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, "zulip.example.com")
 | 
			
		||||
        self.assertEqual(server.contact_email, "server-admin@example.com")
 | 
			
		||||
        self.assertEqual(server.last_request_datetime, time_sent + timedelta(minutes=1))
 | 
			
		||||
 | 
			
		||||
        # Now test rotating our key
 | 
			
		||||
        request = dict(
 | 
			
		||||
@@ -4783,7 +4811,7 @@ class PushBouncerSignupTest(ZulipTestCase):
 | 
			
		||||
        zulip_org_key = request["new_org_key"]
 | 
			
		||||
        self.assertEqual(server.api_key, zulip_org_key)
 | 
			
		||||
 | 
			
		||||
        # Update our hostname
 | 
			
		||||
        # Update contact_email
 | 
			
		||||
        request = dict(
 | 
			
		||||
            zulip_org_id=zulip_org_id,
 | 
			
		||||
            zulip_org_key=zulip_org_key,
 | 
			
		||||
 
 | 
			
		||||
@@ -8,6 +8,7 @@ from django.http import HttpRequest, HttpResponse
 | 
			
		||||
from django.urls import path
 | 
			
		||||
from django.urls.resolvers import URLPattern
 | 
			
		||||
from django.utils.crypto import constant_time_compare
 | 
			
		||||
from django.utils.timezone import now as timezone_now
 | 
			
		||||
from django.utils.translation import gettext as _
 | 
			
		||||
from django.views.decorators.csrf import csrf_exempt
 | 
			
		||||
from typing_extensions import Concatenate, ParamSpec, override
 | 
			
		||||
@@ -120,6 +121,10 @@ def authenticated_remote_server_view(
 | 
			
		||||
            raise UnauthorizedError(e.msg)
 | 
			
		||||
 | 
			
		||||
        rate_limit_remote_server(request, remote_server, domain="api_by_remote_server")
 | 
			
		||||
 | 
			
		||||
        remote_server.last_request_datetime = timezone_now()
 | 
			
		||||
        remote_server.save(update_fields=["last_request_datetime"])
 | 
			
		||||
 | 
			
		||||
        return view_func(request, remote_server, *args, **kwargs)
 | 
			
		||||
 | 
			
		||||
    return _wrapped_view_func
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,22 @@
 | 
			
		||||
# Generated by Django 4.2.8 on 2023-12-25 00:54
 | 
			
		||||
 | 
			
		||||
from django.db import migrations, models
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Migration(migrations.Migration):
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ("zilencer", "0056_remoterealm_realm_locally_deleted"),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
        migrations.AddField(
 | 
			
		||||
            model_name="remoterealm",
 | 
			
		||||
            name="last_request_datetime",
 | 
			
		||||
            field=models.DateTimeField(null=True),
 | 
			
		||||
        ),
 | 
			
		||||
        migrations.AddField(
 | 
			
		||||
            model_name="remotezulipserver",
 | 
			
		||||
            name="last_request_datetime",
 | 
			
		||||
            field=models.DateTimeField(null=True),
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
@@ -47,6 +47,7 @@ class RemoteZulipServer(models.Model):
 | 
			
		||||
    hostname = models.CharField(max_length=HOSTNAME_MAX_LENGTH)
 | 
			
		||||
    contact_email = models.EmailField(blank=True, null=False)
 | 
			
		||||
    last_updated = models.DateTimeField("last updated", auto_now=True)
 | 
			
		||||
    last_request_datetime = models.DateTimeField(null=True)
 | 
			
		||||
    last_version = models.CharField(max_length=VERSION_MAX_LENGTH, null=True)
 | 
			
		||||
    last_api_feature_level = models.PositiveIntegerField(null=True)
 | 
			
		||||
 | 
			
		||||
@@ -142,6 +143,7 @@ class RemoteRealm(models.Model):
 | 
			
		||||
    # The fields below are analogical to RemoteZulipServer fields.
 | 
			
		||||
 | 
			
		||||
    last_updated = models.DateTimeField("last updated", auto_now=True)
 | 
			
		||||
    last_request_datetime = models.DateTimeField(null=True)
 | 
			
		||||
 | 
			
		||||
    # Whether the realm registration has been deactivated.
 | 
			
		||||
    registration_deactivated = models.BooleanField(default=False)
 | 
			
		||||
 
 | 
			
		||||
@@ -144,6 +144,7 @@ def register_remote_server(
 | 
			
		||||
                "hostname": hostname,
 | 
			
		||||
                "contact_email": contact_email,
 | 
			
		||||
                "api_key": zulip_org_key,
 | 
			
		||||
                "last_request_datetime": timezone_now(),
 | 
			
		||||
            },
 | 
			
		||||
        )
 | 
			
		||||
        if created:
 | 
			
		||||
@@ -163,6 +164,8 @@ def register_remote_server(
 | 
			
		||||
            remote_server.contact_email = contact_email
 | 
			
		||||
            if new_org_key is not None:
 | 
			
		||||
                remote_server.api_key = new_org_key
 | 
			
		||||
 | 
			
		||||
            remote_server.last_request_datetime = timezone_now()
 | 
			
		||||
            remote_server.save()
 | 
			
		||||
 | 
			
		||||
    return json_success(request, data={"created": created})
 | 
			
		||||
@@ -207,6 +210,9 @@ def register_remote_push_device(
 | 
			
		||||
            # We want to associate the RemotePushDeviceToken with the RemoteRealm.
 | 
			
		||||
            kwargs["remote_realm_id"] = remote_realm.id
 | 
			
		||||
 | 
			
		||||
            remote_realm.last_request_datetime = timezone_now()
 | 
			
		||||
            remote_realm.save(update_fields=["last_request_datetime"])
 | 
			
		||||
 | 
			
		||||
    try:
 | 
			
		||||
        with transaction.atomic():
 | 
			
		||||
            RemotePushDeviceToken.objects.create(
 | 
			
		||||
@@ -505,6 +511,9 @@ def remote_server_notify_push(
 | 
			
		||||
            increment=len(android_devices) + len(apple_devices),
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        remote_realm.last_request_datetime = timezone_now()
 | 
			
		||||
        remote_realm.save(update_fields=["last_request_datetime"])
 | 
			
		||||
 | 
			
		||||
    # Truncate incoming pushes to 200, due to APNs maximum message
 | 
			
		||||
    # sizes; see handle_remove_push_notification for the version of
 | 
			
		||||
    # this for notifications generated natively on the server.  We
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user