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
|
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(
|
def send_apple_push_notification(
|
||||||
user_identity: UserPushIdentityCompat,
|
user_identity: UserPushIdentityCompat,
|
||||||
devices: Sequence[DeviceToken],
|
devices: Sequence[DeviceToken],
|
||||||
@@ -270,18 +284,24 @@ def send_apple_push_notification(
|
|||||||
else:
|
else:
|
||||||
DeviceTokenClass = PushDeviceToken
|
DeviceTokenClass = PushDeviceToken
|
||||||
|
|
||||||
|
orig_devices = devices
|
||||||
|
devices = dedupe_device_tokens(devices)
|
||||||
|
num_duplicate_tokens = len(orig_devices) - len(devices)
|
||||||
|
|
||||||
if remote:
|
if remote:
|
||||||
logger.info(
|
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,
|
remote.uuid,
|
||||||
user_identity,
|
user_identity,
|
||||||
len(devices),
|
len(devices),
|
||||||
|
num_duplicate_tokens,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
logger.info(
|
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,
|
user_identity,
|
||||||
len(devices),
|
len(devices),
|
||||||
|
num_duplicate_tokens,
|
||||||
)
|
)
|
||||||
payload_data = dict(modernize_apns_payload(payload_data))
|
payload_data = dict(modernize_apns_payload(payload_data))
|
||||||
message = {**payload_data.pop("custom", {}), "aps": payload_data}
|
message = {**payload_data.pop("custom", {}), "aps": payload_data}
|
||||||
|
|||||||
Reference in New Issue
Block a user