zilencer: Have server send realm_uuid to remaining bouncer endpoints.

Requests to these endpoint are about a specified user, and therefore
also have a notion of the RemoteRealm for these requests. Until now
these endpoints weren't getting the realm_uuid value, because it wasn't
used - but now it is needed for updating .last_request_datetime on the
RemoteRealm.

(cherry picked from commit e2291b7656)
This commit is contained in:
Mateusz Mandera 2023-12-25 23:10:35 +01:00 committed by Tim Abbott
parent 3a4d45022f
commit 0cbbb98cc2
3 changed files with 46 additions and 3 deletions

View File

@ -744,6 +744,7 @@ def remove_push_device_token(user_profile: UserProfile, token_str: str, kind: in
# TODO: Make this a remove item
post_data = {
"server_uuid": settings.ZULIP_ORG_ID,
"realm_uuid": str(user_profile.realm.uuid),
# We don't know here if the token was registered with uuid
# or using the legacy id format, so we need to send both.
"user_uuid": str(user_profile.uuid),
@ -758,9 +759,11 @@ def remove_push_device_token(user_profile: UserProfile, token_str: str, kind: in
def clear_push_device_tokens(user_profile_id: int) -> None:
# Deletes all of a user's PushDeviceTokens.
if uses_notification_bouncer():
user_uuid = str(get_user_profile_by_id(user_profile_id).uuid)
user_profile = get_user_profile_by_id(user_profile_id)
user_uuid = str(user_profile.uuid)
post_data = {
"server_uuid": settings.ZULIP_ORG_ID,
"realm_uuid": str(user_profile.realm.uuid),
# We want to clear all registered token, and they may have
# been registered with either uuid or id.
"user_uuid": user_uuid,
@ -1457,6 +1460,7 @@ def send_test_push_notification(user_profile: UserProfile, devices: List[PushDev
if uses_notification_bouncer():
for device in devices:
post_data = {
"realm_uuid": str(user_profile.realm.uuid),
"user_uuid": str(user_profile.uuid),
"user_id": user_profile.id,
"token": device.token,

View File

@ -125,6 +125,7 @@ class SendTestPushNotificationEndpointTest(BouncerTestCase):
# What response the server receives when it makes a request to the bouncer
# to the /test_notification endpoint:
payload = {
"realm_uuid": str(user.realm.uuid),
"user_uuid": str(user.uuid),
"user_id": user.id,
"token": "invalid",
@ -290,6 +291,7 @@ class SendTestPushNotificationEndpointTest(BouncerTestCase):
user = self.example_user("cordelia")
server = self.server
remote_realm = RemoteRealm.objects.get(server=server, uuid=user.realm.uuid)
token = "111222"
token_kind = PushDeviceToken.GCM
@ -324,6 +326,9 @@ class SendTestPushNotificationEndpointTest(BouncerTestCase):
)
self.assert_json_success(result)
remote_realm.refresh_from_db()
self.assertEqual(remote_realm.last_request_datetime, time_now)
class PushBouncerNotificationTest(BouncerTestCase):
DEFAULT_SUBDOMAIN = ""
@ -1265,8 +1270,10 @@ class PushBouncerNotificationTest(BouncerTestCase):
self.assert_length(tokens, 2)
# Remove tokens
time_sent = time_sent + timedelta(minutes=1)
for endpoint, token, kind, appid in endpoints:
result = self.client_delete(endpoint, {"token": token}, subdomain="zulip")
with time_machine.travel(time_sent, tick=False):
result = self.client_delete(endpoint, {"token": token}, subdomain="zulip")
self.assert_json_success(result)
tokens = list(
RemotePushDeviceToken.objects.filter(
@ -1275,6 +1282,9 @@ class PushBouncerNotificationTest(BouncerTestCase):
)
self.assert_length(tokens, 0)
remote_realm.refresh_from_db()
self.assertEqual(remote_realm.last_request_datetime, time_sent)
# Re-add copies of those tokens
for endpoint, token, kind, appid in endpoints:
result = self.client_post(endpoint, {"token": token, **appid}, subdomain="zulip")
@ -1296,10 +1306,15 @@ class PushBouncerNotificationTest(BouncerTestCase):
self.assert_length(tokens, 2)
# Now we successfully remove them:
do_regenerate_api_key(user, user)
time_sent = time_sent + timedelta(minutes=1)
with time_machine.travel(time_sent, tick=False):
do_regenerate_api_key(user, user)
tokens = list(RemotePushDeviceToken.objects.filter(user_uuid=user.uuid, server=server))
self.assert_length(tokens, 0)
remote_realm.refresh_from_db()
self.assertEqual(remote_realm.last_request_datetime, time_sent)
class AnalyticsBouncerTest(BouncerTestCase):
TIME_ZERO = datetime(1988, 3, 14, tzinfo=timezone.utc)

View File

@ -238,10 +238,13 @@ def unregister_remote_push_device(
token_kind: int = REQ(json_validator=check_int),
user_id: Optional[int] = REQ(json_validator=check_int, default=None),
user_uuid: Optional[str] = REQ(default=None),
realm_uuid: Optional[str] = REQ(default=None),
) -> HttpResponse:
validate_bouncer_token_request(token, token_kind)
user_identity = UserPushIdentityCompat(user_id=user_id, user_uuid=user_uuid)
update_remote_realm_last_request_datetime_helper(request, server, realm_uuid, user_uuid)
(num_deleted, ignored) = RemotePushDeviceToken.objects.filter(
user_identity.filter_q(), token=token, kind=token_kind, server=server
).delete()
@ -257,13 +260,30 @@ def unregister_all_remote_push_devices(
server: RemoteZulipServer,
user_id: Optional[int] = REQ(json_validator=check_int, default=None),
user_uuid: Optional[str] = REQ(default=None),
realm_uuid: Optional[str] = REQ(default=None),
) -> HttpResponse:
user_identity = UserPushIdentityCompat(user_id=user_id, user_uuid=user_uuid)
update_remote_realm_last_request_datetime_helper(request, server, realm_uuid, user_uuid)
RemotePushDeviceToken.objects.filter(user_identity.filter_q(), server=server).delete()
return json_success(request)
def update_remote_realm_last_request_datetime_helper(
request: HttpRequest,
server: RemoteZulipServer,
realm_uuid: Optional[str],
user_uuid: Optional[str],
) -> None:
if realm_uuid is not None:
assert user_uuid is not None
remote_realm = get_remote_realm_helper(request, server, realm_uuid, user_uuid)
if remote_realm is not None:
remote_realm.last_request_datetime = timezone_now()
remote_realm.save(update_fields=["last_request_datetime"])
def delete_duplicate_registrations(
registrations: List[RemotePushDeviceToken], server_id: int, user_id: int, user_uuid: str
) -> List[RemotePushDeviceToken]:
@ -327,6 +347,7 @@ class TestNotificationPayload(BaseModel):
token_kind: int
user_id: int
user_uuid: str
realm_uuid: Optional[str] = None
base_payload: Dict[str, Any]
model_config = ConfigDict(extra="forbid")
@ -344,6 +365,7 @@ def remote_server_send_test_notification(
user_id = payload.user_id
user_uuid = payload.user_uuid
realm_uuid = payload.realm_uuid
# The remote server only sends the base payload with basic user and server info,
# and the actual format of the test notification is defined on the bouncer, as that
@ -355,6 +377,8 @@ def remote_server_send_test_notification(
# servers that will send user both UUID and ID.
user_identity = UserPushIdentityCompat(user_id=user_id, user_uuid=user_uuid)
update_remote_realm_last_request_datetime_helper(request, server, realm_uuid, user_uuid)
try:
device = RemotePushDeviceToken.objects.get(
user_identity.filter_q(), token=token, kind=token_kind, server=server