mirror of
https://github.com/zulip/zulip.git
synced 2025-11-04 22:13:26 +00:00
notifications: Dedupe APNs tokens case-insensitively.
Fixes zulip/zulip-flutter#1617. It turns out that an APNs token (which is a hex string) is equally valid in lower or upper case. The old app would send the server the lower-case form of the token, but the new app sends the upper-case form. Because we've been treating tokens case-sensitively, if the user upgrades from the old app to the new, that results in the server and bouncer each having two copies of the token (one lower-case and one upper-case), and therefore sending that device two copies of each notification: zulip/zulip-flutter#1617. To fix that immediately, have the bouncer drop duplicate tokens before sending the notifications to APNs. Work is also in progress on fixing this in a better-structured way, by having the database correctly treat tokens as the same when they differ only in case.
This commit is contained in:
@@ -241,6 +241,20 @@ def modernize_apns_payload(data: Mapping[str, Any]) -> Mapping[str, Any]:
|
||||
APNS_MAX_RETRIES = 3
|
||||
|
||||
|
||||
def dedupe_device_tokens(
|
||||
devices: Sequence[DeviceToken],
|
||||
) -> Sequence[DeviceToken]:
|
||||
device_tokens: set[str] = set()
|
||||
result: list[DeviceToken] = []
|
||||
for device in devices:
|
||||
lower_token = device.token.lower()
|
||||
if lower_token in device_tokens: # nocoverage
|
||||
continue
|
||||
device_tokens.add(lower_token)
|
||||
result.append(device)
|
||||
return result
|
||||
|
||||
|
||||
def send_apple_push_notification(
|
||||
user_identity: UserPushIdentityCompat,
|
||||
devices: Sequence[DeviceToken],
|
||||
@@ -270,18 +284,24 @@ def send_apple_push_notification(
|
||||
else:
|
||||
DeviceTokenClass = PushDeviceToken
|
||||
|
||||
orig_devices = devices
|
||||
devices = dedupe_device_tokens(devices)
|
||||
num_duplicate_tokens = len(orig_devices) - len(devices)
|
||||
|
||||
if remote:
|
||||
logger.info(
|
||||
"APNs: Sending notification for remote user %s:%s to %d devices",
|
||||
"APNs: Sending notification for remote user %s:%s to %d devices (skipped %d duplicates)",
|
||||
remote.uuid,
|
||||
user_identity,
|
||||
len(devices),
|
||||
num_duplicate_tokens,
|
||||
)
|
||||
else:
|
||||
logger.info(
|
||||
"APNs: Sending notification for local user %s to %d devices",
|
||||
"APNs: Sending notification for local user %s to %d devices (skipped %d duplicates)",
|
||||
user_identity,
|
||||
len(devices),
|
||||
num_duplicate_tokens,
|
||||
)
|
||||
payload_data = dict(modernize_apns_payload(payload_data))
|
||||
message = {**payload_data.pop("custom", {}), "aps": payload_data}
|
||||
|
||||
Reference in New Issue
Block a user