Remove machinery for setting/storing APNs VOIP tokens

This commit is contained in:
Jon Chambers 2024-09-19 12:37:19 -04:00 committed by Jon Chambers
parent b693cb98d0
commit 92698efd39
23 changed files with 64 additions and 250 deletions

View File

@ -120,7 +120,6 @@ public class AccountController {
accounts.updateDevice(account, device.getId(), d -> {
d.setApnId(null);
d.setVoipApnId(null);
d.setGcmId(registrationId.gcmRegistrationId());
d.setFetchesMessages(false);
});
@ -153,7 +152,6 @@ public class AccountController {
// unconditionally
accounts.updateDevice(account, device.getId(), d -> {
d.setApnId(registrationId.apnRegistrationId());
d.setVoipApnId(registrationId.voipRegistrationId());
d.setGcmId(null);
d.setFetchesMessages(false);
});
@ -167,7 +165,6 @@ public class AccountController {
accounts.updateDevice(account, device.getId(), d -> {
d.setApnId(null);
d.setVoipApnId(null);
d.setFetchesMessages(false);
if (d.getId() == 1) {
d.setUserAgent("OWI");

View File

@ -7,6 +7,5 @@ package org.whispersystems.textsecuregcm.entities;
import javax.annotation.Nullable;
import javax.validation.constraints.NotEmpty;
public record ApnRegistrationId(@NotEmpty String apnRegistrationId,
@Nullable String voipRegistrationId) {
public record ApnRegistrationId(@NotEmpty String apnRegistrationId) {
}

View File

@ -54,8 +54,7 @@ abstract class IdleDevicePushNotificationExperiment implements PushNotificationE
@VisibleForTesting
boolean hasPushToken(final Device device) {
// Exclude VOIP tokens since they have their own, distinct delivery mechanism
return !StringUtils.isAllBlank(device.getApnId(), device.getGcmId()) && StringUtils.isBlank(device.getVoipApnId());
return !StringUtils.isAllBlank(device.getApnId(), device.getGcmId());
}
@Override

View File

@ -110,7 +110,6 @@ public class DevicesGrpcService extends ReactorDevicesGrpc.DevicesImplBase {
final AuthenticatedDevice authenticatedDevice = AuthenticationUtil.requireAuthenticatedDevice();
@Nullable final String apnsToken;
@Nullable final String apnsVoipToken;
@Nullable final String fcmToken;
switch (request.getTokenRequestCase()) {
@ -118,12 +117,11 @@ public class DevicesGrpcService extends ReactorDevicesGrpc.DevicesImplBase {
case APNS_TOKEN_REQUEST -> {
final SetPushTokenRequest.ApnsTokenRequest apnsTokenRequest = request.getApnsTokenRequest();
if (StringUtils.isAllBlank(apnsTokenRequest.getApnsToken(), apnsTokenRequest.getApnsVoipToken())) {
throw Status.INVALID_ARGUMENT.withDescription("APNs tokens may not both be blank").asRuntimeException();
if (StringUtils.isBlank(apnsTokenRequest.getApnsToken())) {
throw Status.INVALID_ARGUMENT.withDescription("APNs token must not be blank").asRuntimeException();
}
apnsToken = StringUtils.stripToNull(apnsTokenRequest.getApnsToken());
apnsVoipToken = StringUtils.stripToNull(apnsTokenRequest.getApnsVoipToken());
fcmToken = null;
}
@ -135,7 +133,6 @@ public class DevicesGrpcService extends ReactorDevicesGrpc.DevicesImplBase {
}
apnsToken = null;
apnsVoipToken = null;
fcmToken = StringUtils.stripToNull(fcmTokenRequest.getFcmToken());
}
@ -150,14 +147,12 @@ public class DevicesGrpcService extends ReactorDevicesGrpc.DevicesImplBase {
final boolean tokenUnchanged =
Objects.equals(device.getApnId(), apnsToken) &&
Objects.equals(device.getVoipApnId(), apnsVoipToken) &&
Objects.equals(device.getGcmId(), fcmToken);
return tokenUnchanged
? Mono.empty()
: Mono.fromFuture(() -> accountsManager.updateDeviceAsync(account, authenticatedDevice.deviceId(), d -> {
d.setApnId(apnsToken);
d.setVoipApnId(apnsVoipToken);
d.setGcmId(fcmToken);
d.setFetchesMessages(false);
}));
@ -172,14 +167,13 @@ public class DevicesGrpcService extends ReactorDevicesGrpc.DevicesImplBase {
return Mono.fromFuture(() -> accountsManager.getByAccountIdentifierAsync(authenticatedDevice.accountIdentifier()))
.map(maybeAccount -> maybeAccount.orElseThrow(Status.UNAUTHENTICATED::asRuntimeException))
.flatMap(account -> Mono.fromFuture(() -> accountsManager.updateDeviceAsync(account, authenticatedDevice.deviceId(), device -> {
if (StringUtils.isNotBlank(device.getApnId()) || StringUtils.isNotBlank(device.getVoipApnId())) {
if (StringUtils.isNotBlank(device.getApnId())) {
device.setUserAgent(device.isPrimary() ? "OWI" : "OWP");
} else if (StringUtils.isNotBlank(device.getGcmId())) {
device.setUserAgent("OWA");
}
device.setApnId(null);
device.setVoipApnId(null);
device.setGcmId(null);
device.setFetchesMessages(true);
})))

View File

@ -34,12 +34,6 @@ public class APNSender implements Managed, PushNotificationSender {
private final String bundleId;
private final ApnsClient apnsClient;
@VisibleForTesting
static final String APN_VOIP_NOTIFICATION_PAYLOAD = new SimpleApnsPayloadBuilder()
.setSound("default")
.setLocalizedAlertMessage("APN_Message")
.build();
@VisibleForTesting
static final String APN_NSE_NOTIFICATION_PAYLOAD = new SimpleApnsPayloadBuilder()
.setMutableContent(true)
@ -80,22 +74,8 @@ public class APNSender implements Managed, PushNotificationSender {
@Override
public CompletableFuture<SendPushNotificationResult> sendNotification(final PushNotification notification) {
final String topic = switch (notification.tokenType()) {
case APN -> bundleId;
case APN_VOIP -> bundleId + ".voip";
default -> throw new IllegalArgumentException("Unsupported token type: " + notification.tokenType());
};
final boolean isVoip = notification.tokenType() == PushNotification.TokenType.APN_VOIP;
final String payload = switch (notification.notificationType()) {
case NOTIFICATION -> {
if (isVoip) {
yield APN_VOIP_NOTIFICATION_PAYLOAD;
} else {
yield notification.urgent() ? APN_NSE_NOTIFICATION_PAYLOAD : APN_BACKGROUND_PAYLOAD;
}
}
case NOTIFICATION -> notification.urgent() ? APN_NSE_NOTIFICATION_PAYLOAD : APN_BACKGROUND_PAYLOAD;
case ATTEMPT_LOGIN_NOTIFICATION_HIGH_PRIORITY -> new SimpleApnsPayloadBuilder()
.setMutableContent(true)
@ -115,13 +95,7 @@ public class APNSender implements Managed, PushNotificationSender {
};
final PushType pushType = switch (notification.notificationType()) {
case NOTIFICATION -> {
if (isVoip) {
yield PushType.VOIP;
} else {
yield notification.urgent() ? PushType.ALERT : PushType.BACKGROUND;
}
}
case NOTIFICATION -> notification.urgent() ? PushType.ALERT : PushType.BACKGROUND;
case ATTEMPT_LOGIN_NOTIFICATION_HIGH_PRIORITY -> PushType.ALERT;
case CHALLENGE, RATE_LIMIT_CHALLENGE -> PushType.BACKGROUND;
};
@ -131,19 +105,17 @@ public class APNSender implements Managed, PushNotificationSender {
if (pushType == PushType.BACKGROUND) {
deliveryPriority = DeliveryPriority.CONSERVE_POWER;
} else {
deliveryPriority = (notification.urgent() || isVoip)
? DeliveryPriority.IMMEDIATE
: DeliveryPriority.CONSERVE_POWER;
deliveryPriority = notification.urgent() ? DeliveryPriority.IMMEDIATE : DeliveryPriority.CONSERVE_POWER;
}
final String collapseId =
(notification.notificationType() == PushNotification.NotificationType.NOTIFICATION && notification.urgent() && !isVoip)
(notification.notificationType() == PushNotification.NotificationType.NOTIFICATION && notification.urgent())
? "incoming-message" : null;
final Instant start = Instant.now();
return apnsClient.sendNotification(new SimpleApnsPushNotification(notification.deviceToken(),
topic,
bundleId,
payload,
MAX_EXPIRATION,
deliveryPriority,

View File

@ -26,7 +26,6 @@ public record PushNotification(String deviceToken,
public enum TokenType {
FCM,
APN,
APN_VOIP,
APN
}
}

View File

@ -90,8 +90,6 @@ public class PushNotificationManager {
if (StringUtils.isNotBlank(device.getGcmId())) {
tokenAndType = new Pair<>(device.getGcmId(), PushNotification.TokenType.FCM);
} else if (StringUtils.isNotBlank(device.getVoipApnId())) {
tokenAndType = new Pair<>(device.getVoipApnId(), PushNotification.TokenType.APN_VOIP);
} else if (StringUtils.isNotBlank(device.getApnId())) {
tokenAndType = new Pair<>(device.getApnId(), PushNotification.TokenType.APN);
} else {
@ -115,7 +113,7 @@ public class PushNotificationManager {
final PushNotificationSender sender = switch (pushNotification.tokenType()) {
case FCM -> fcmSender;
case APN, APN_VOIP -> apnSender;
case APN -> apnSender;
};
return sender.sendNotification(pushNotification).whenComplete((result, throwable) -> {
@ -171,7 +169,7 @@ public class PushNotificationManager {
tokenInvalidationTimestamp.isAfter(Instant.ofEpochMilli(device.getPushTimestamp()))).orElse(true);
if (tokenExpired) {
if (tokenType == PushNotification.TokenType.APN || tokenType == PushNotification.TokenType.APN_VOIP) {
if (tokenType == PushNotification.TokenType.APN) {
pushNotificationScheduler.cancelScheduledNotifications(account, device).whenComplete(logErrors());
}
@ -203,7 +201,6 @@ public class PushNotificationManager {
switch (tokenType) {
case FCM -> d.setGcmId(null);
case APN -> d.setApnId(null);
case APN_VOIP -> d.setVoipApnId(null);
}
}
})));
@ -213,7 +210,6 @@ public class PushNotificationManager {
return switch (tokenType) {
case FCM -> device.getGcmId();
case APN -> device.getApnId();
case APN_VOIP -> device.getVoipApnId();
};
}
}

View File

@ -49,9 +49,6 @@ public class Device {
@JsonProperty
private String apnId;
@JsonProperty
private String voipApnId;
@JsonProperty
private long pushTimestamp;
@ -89,14 +86,6 @@ public class Device {
}
}
public String getVoipApnId() {
return voipApnId;
}
public void setVoipApnId(String voipApnId) {
this.voipApnId = voipApnId;
}
public void setLastSeen(long lastSeen) {
this.lastSeen = lastSeen;
}

View File

@ -39,13 +39,8 @@ public record DeviceSpec(
device.setLastSeen(Util.todayInMillis());
device.setUserAgent(signalAgent());
apnRegistrationId().ifPresent(apnRegistrationId -> {
device.setApnId(apnRegistrationId.apnRegistrationId());
device.setVoipApnId(apnRegistrationId.voipRegistrationId());
});
gcmRegistrationId().ifPresent(gcmRegistrationId ->
device.setGcmId(gcmRegistrationId.gcmRegistrationId()));
apnRegistrationId().ifPresent(apnRegistrationId -> device.setApnId(apnRegistrationId.apnRegistrationId()));
gcmRegistrationId().ifPresent(gcmRegistrationId -> device.setGcmId(gcmRegistrationId.gcmRegistrationId()));
return device;
}

View File

@ -182,7 +182,6 @@ public class NotifyIdleDevicesCommand extends AbstractSinglePassCrawlAccountsCom
@VisibleForTesting
static boolean hasPushToken(final Device device) {
// Exclude VOIP tokens since they have their own, distinct delivery mechanism
return !StringUtils.isAllBlank(device.getApnId(), device.getGcmId()) && StringUtils.isBlank(device.getVoipApnId());
return !StringUtils.isAllBlank(device.getApnId(), device.getGcmId());
}
}

View File

@ -107,13 +107,6 @@ message SetPushTokenRequest {
* A "standard" APNs device token.
*/
string apns_token = 1;
/**
* A VoIP APNs device token. If present, the server will prefer to send
* message notifications to the device using this token on a VOIP APNs
* topic.
*/
string apns_voip_token = 2;
}
message FcmTokenRequest {

View File

@ -308,29 +308,11 @@ class AccountControllerTest {
.request()
.header(HttpHeaders.AUTHORIZATION,
AuthHelper.getAuthHeader(AuthHelper.VALID_UUID_3, AuthHelper.VALID_PASSWORD_3_PRIMARY))
.put(Entity.json(new ApnRegistrationId("first", "second")))) {
.put(Entity.json(new ApnRegistrationId("first")))) {
assertThat(response.getStatus()).isEqualTo(204);
verify(AuthHelper.VALID_DEVICE_3_PRIMARY, times(1)).setApnId(eq("first"));
verify(AuthHelper.VALID_DEVICE_3_PRIMARY, times(1)).setVoipApnId(eq("second"));
verify(accountsManager, times(1)).updateDevice(eq(AuthHelper.VALID_ACCOUNT_3), anyByte(), any());
}
}
@Test
void testSetApnIdNoVoip() {
try (final Response response = resources.getJerseyTest()
.target("/v1/accounts/apn/")
.request()
.header(HttpHeaders.AUTHORIZATION,
AuthHelper.getAuthHeader(AuthHelper.VALID_UUID_3, AuthHelper.VALID_PASSWORD_3_PRIMARY))
.put(Entity.json(new ApnRegistrationId("first", null)))) {
assertThat(response.getStatus()).isEqualTo(204);
verify(AuthHelper.VALID_DEVICE_3_PRIMARY, times(1)).setApnId(eq("first"));
verify(AuthHelper.VALID_DEVICE_3_PRIMARY, times(1)).setVoipApnId(null);
verify(accountsManager, times(1)).updateDevice(eq(AuthHelper.VALID_ACCOUNT_3), anyByte(), any());
}
}

View File

@ -177,7 +177,6 @@ class DeviceControllerTest {
final Optional<ApnRegistrationId> apnRegistrationId,
final Optional<GcmRegistrationId> gcmRegistrationId,
final Optional<String> expectedApnsToken,
final Optional<String> expectedApnsVoipToken,
final Optional<String> expectedGcmToken) {
final Device existingDevice = mock(Device.class);
@ -240,9 +239,6 @@ class DeviceControllerTest {
expectedApnsToken.ifPresentOrElse(expectedToken -> assertEquals(expectedToken, device.getApnId()),
() -> assertNull(device.getApnId()));
expectedApnsVoipToken.ifPresentOrElse(expectedToken -> assertEquals(expectedToken, device.getVoipApnId()),
() -> assertNull(device.getVoipApnId()));
expectedGcmToken.ifPresentOrElse(expectedToken -> assertEquals(expectedToken, device.getGcmId()),
() -> assertNull(device.getGcmId()));
@ -251,14 +247,13 @@ class DeviceControllerTest {
private static Stream<Arguments> linkDeviceAtomic() {
final String apnsToken = "apns-token";
final String apnsVoipToken = "apns-voip-token";
final String gcmToken = "gcm-token";
return Stream.of(
Arguments.of(true, Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty()),
Arguments.of(false, Optional.of(new ApnRegistrationId(apnsToken, null)), Optional.empty(), Optional.of(apnsToken), Optional.empty(), Optional.empty()),
Arguments.of(false, Optional.of(new ApnRegistrationId(apnsToken, apnsVoipToken)), Optional.empty(), Optional.of(apnsToken), Optional.of(apnsVoipToken), Optional.empty()),
Arguments.of(false, Optional.empty(), Optional.of(new GcmRegistrationId(gcmToken)), Optional.empty(), Optional.empty(), Optional.of(gcmToken))
Arguments.of(true, Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty()),
Arguments.of(false, Optional.of(new ApnRegistrationId(apnsToken)), Optional.empty(), Optional.of(apnsToken), Optional.empty()),
Arguments.of(false, Optional.of(new ApnRegistrationId(apnsToken)), Optional.empty(), Optional.of(apnsToken), Optional.empty()),
Arguments.of(false, Optional.empty(), Optional.of(new GcmRegistrationId(gcmToken)), Optional.empty(), Optional.of(gcmToken))
);
}
@ -496,10 +491,10 @@ class DeviceControllerTest {
private static Stream<Arguments> linkDeviceAtomicConflictingChannel() {
return Stream.of(
Arguments.of(true, Optional.of(new ApnRegistrationId("apns-token", null)), Optional.of(new GcmRegistrationId("gcm-token"))),
Arguments.of(true, Optional.of(new ApnRegistrationId("apns-token")), Optional.of(new GcmRegistrationId("gcm-token"))),
Arguments.of(true, Optional.empty(), Optional.of(new GcmRegistrationId("gcm-token"))),
Arguments.of(true, Optional.of(new ApnRegistrationId("apns-token", null)), Optional.empty()),
Arguments.of(false, Optional.of(new ApnRegistrationId("apns-token", null)), Optional.of(new GcmRegistrationId("gcm-token")))
Arguments.of(true, Optional.of(new ApnRegistrationId("apns-token")), Optional.empty()),
Arguments.of(false, Optional.of(new ApnRegistrationId("apns-token")), Optional.of(new GcmRegistrationId("gcm-token")))
);
}
@ -737,7 +732,7 @@ class DeviceControllerTest {
final LinkDeviceRequest request = new LinkDeviceRequest(deviceCode.verificationCode(),
new AccountAttributes(false, registrationId, pniRegistrationId, null, null, true, new DeviceCapabilities(true, true, true, false, false)),
new DeviceActivationRequest(aciSignedPreKey, pniSignedPreKey, aciPqLastResortPreKey, pniPqLastResortPreKey, Optional.of(new ApnRegistrationId("apn", null)), Optional.empty()));
new DeviceActivationRequest(aciSignedPreKey, pniSignedPreKey, aciPqLastResortPreKey, pniPqLastResortPreKey, Optional.of(new ApnRegistrationId("apn")), Optional.empty()));
try (final Response response = resources.getJerseyTest()
.target("/v1/devices/link")

View File

@ -543,7 +543,7 @@ class RegistrationControllerTest {
pniSignedPreKey,
aciPqLastResortPreKey,
pniPqLastResortPreKey,
Optional.of(new ApnRegistrationId("apns-token", null)),
Optional.of(new ApnRegistrationId("apns-token")),
Optional.empty())),
// "Fetches messages" is true, but an FCM (GCM) token is provided
@ -571,7 +571,7 @@ class RegistrationControllerTest {
pniSignedPreKey,
aciPqLastResortPreKey,
pniPqLastResortPreKey,
Optional.of(new ApnRegistrationId("apns-token", null)),
Optional.of(new ApnRegistrationId("apns-token")),
Optional.of(new GcmRegistrationId("gcm-token"))))
);
}
@ -795,7 +795,6 @@ class RegistrationControllerTest {
new AccountAttributes(false, registrationId, pniRegistrationId, "test".getBytes(StandardCharsets.UTF_8), null, true, new Device.DeviceCapabilities(false, false, false, false, false));
final String apnsToken = "apns-token";
final String apnsVoipToken = "apns-voip-token";
final String gcmToken = "gcm-token";
return Stream.of(
@ -840,7 +839,7 @@ class RegistrationControllerTest {
pniSignedPreKey,
aciPqLastResortPreKey,
pniPqLastResortPreKey,
Optional.of(new ApnRegistrationId(apnsToken, apnsVoipToken)),
Optional.of(new ApnRegistrationId(apnsToken)),
Optional.empty()),
aciIdentityKey,
pniIdentityKey,
@ -852,7 +851,7 @@ class RegistrationControllerTest {
registrationId,
pniRegistrationId,
false,
Optional.of(new ApnRegistrationId(apnsToken, apnsVoipToken)),
Optional.of(new ApnRegistrationId(apnsToken)),
Optional.empty(),
aciSignedPreKey,
pniSignedPreKey,

View File

@ -56,15 +56,6 @@ abstract class IdleDevicePushNotificationExperimentTest {
arguments.add(Arguments.of(device, true));
}
{
// APNs VOIP token
final Device device = mock(Device.class);
when(device.getApnId()).thenReturn("apns-token");
when(device.getVoipApnId()).thenReturn("apns-voip-token");
arguments.add(Arguments.of(device, false));
}
return arguments;
}

View File

@ -217,7 +217,6 @@ class DevicesGrpcServiceTest extends SimpleBaseGrpcTest<DevicesGrpcService, Devi
void setPushToken(final byte deviceId,
final SetPushTokenRequest request,
@Nullable final String expectedApnsToken,
@Nullable final String expectedApnsVoipToken,
@Nullable final String expectedFcmToken) {
mockAuthenticationInterceptor().setAuthenticatedDevice(AUTHENTICATED_ACI, deviceId);
@ -228,14 +227,12 @@ class DevicesGrpcServiceTest extends SimpleBaseGrpcTest<DevicesGrpcService, Devi
final SetPushTokenResponse ignored = authenticatedServiceStub().setPushToken(request);
verify(device).setApnId(expectedApnsToken);
verify(device).setVoipApnId(expectedApnsVoipToken);
verify(device).setGcmId(expectedFcmToken);
verify(device).setFetchesMessages(false);
}
private static Stream<Arguments> setPushToken() {
final String apnsToken = "apns-token";
final String apnsVoipToken = "apns-voip-token";
final String fcmToken = "fcm-token";
final Stream.Builder<Arguments> streamBuilder = Stream.builder();
@ -245,18 +242,9 @@ class DevicesGrpcServiceTest extends SimpleBaseGrpcTest<DevicesGrpcService, Devi
SetPushTokenRequest.newBuilder()
.setApnsTokenRequest(SetPushTokenRequest.ApnsTokenRequest.newBuilder()
.setApnsToken(apnsToken)
.setApnsVoipToken(apnsVoipToken)
.build())
.build(),
apnsToken, apnsVoipToken, null));
streamBuilder.add(Arguments.of(deviceId,
SetPushTokenRequest.newBuilder()
.setApnsTokenRequest(SetPushTokenRequest.ApnsTokenRequest.newBuilder()
.setApnsToken(apnsToken)
.build())
.build(),
apnsToken, null, null));
apnsToken, null));
streamBuilder.add(Arguments.of(deviceId,
SetPushTokenRequest.newBuilder()
@ -264,7 +252,7 @@ class DevicesGrpcServiceTest extends SimpleBaseGrpcTest<DevicesGrpcService, Devi
.setFcmToken(fcmToken)
.build())
.build(),
null, null, fcmToken));
null, fcmToken));
}
return streamBuilder.build();
@ -274,12 +262,10 @@ class DevicesGrpcServiceTest extends SimpleBaseGrpcTest<DevicesGrpcService, Devi
@MethodSource
void setPushTokenUnchanged(final SetPushTokenRequest request,
@Nullable final String apnsToken,
@Nullable final String apnsVoipToken,
@Nullable final String fcmToken) {
final Device device = mock(Device.class);
when(device.getApnId()).thenReturn(apnsToken);
when(device.getVoipApnId()).thenReturn(apnsVoipToken);
when(device.getGcmId()).thenReturn(fcmToken);
when(authenticatedAccount.getDevice(AUTHENTICATED_DEVICE_ID)).thenReturn(Optional.of(device));
@ -291,31 +277,22 @@ class DevicesGrpcServiceTest extends SimpleBaseGrpcTest<DevicesGrpcService, Devi
private static Stream<Arguments> setPushTokenUnchanged() {
final String apnsToken = "apns-token";
final String apnsVoipToken = "apns-voip-token";
final String fcmToken = "fcm-token";
return Stream.of(
Arguments.of(SetPushTokenRequest.newBuilder()
.setApnsTokenRequest(SetPushTokenRequest.ApnsTokenRequest.newBuilder()
.setApnsToken(apnsToken)
.setApnsVoipToken(apnsVoipToken)
.build())
.build(),
apnsToken, apnsVoipToken, null, false),
Arguments.of(SetPushTokenRequest.newBuilder()
.setApnsTokenRequest(SetPushTokenRequest.ApnsTokenRequest.newBuilder()
.setApnsToken(apnsToken)
.build())
.build(),
apnsToken, null, null, false),
apnsToken, null, false),
Arguments.of(SetPushTokenRequest.newBuilder()
.setFcmTokenRequest(SetPushTokenRequest.FcmTokenRequest.newBuilder()
.setFcmToken(fcmToken)
.build())
.build(),
null, null, fcmToken, false)
null, fcmToken, false)
);
}
@ -346,7 +323,6 @@ class DevicesGrpcServiceTest extends SimpleBaseGrpcTest<DevicesGrpcService, Devi
@MethodSource
void clearPushToken(final byte deviceId,
@Nullable final String apnsToken,
@Nullable final String apnsVoipToken,
@Nullable final String fcmToken,
@Nullable final String expectedUserAgent) {
@ -356,14 +332,12 @@ class DevicesGrpcServiceTest extends SimpleBaseGrpcTest<DevicesGrpcService, Devi
when(device.getId()).thenReturn(deviceId);
when(device.isPrimary()).thenReturn(deviceId == Device.PRIMARY_ID);
when(device.getApnId()).thenReturn(apnsToken);
when(device.getVoipApnId()).thenReturn(apnsVoipToken);
when(device.getGcmId()).thenReturn(fcmToken);
when(authenticatedAccount.getDevice(deviceId)).thenReturn(Optional.of(device));
final ClearPushTokenResponse ignored = authenticatedServiceStub().clearPushToken(ClearPushTokenRequest.newBuilder().build());
verify(device).setApnId(null);
verify(device).setVoipApnId(null);
verify(device).setGcmId(null);
verify(device).setFetchesMessages(true);
@ -376,16 +350,12 @@ class DevicesGrpcServiceTest extends SimpleBaseGrpcTest<DevicesGrpcService, Devi
private static Stream<Arguments> clearPushToken() {
return Stream.of(
Arguments.of(Device.PRIMARY_ID, "apns-token", null, null, "OWI"),
Arguments.of(Device.PRIMARY_ID, "apns-token", "apns-voip-token", null, "OWI"),
Arguments.of(Device.PRIMARY_ID, null, "apns-voip-token", null, "OWI"),
Arguments.of(Device.PRIMARY_ID, null, null, "fcm-token", "OWA"),
Arguments.of(Device.PRIMARY_ID, null, null, null, null),
Arguments.of((byte) (Device.PRIMARY_ID + 1), "apns-token", null, null, "OWP"),
Arguments.of((byte) (Device.PRIMARY_ID + 1), "apns-token", "apns-voip-token", null, "OWP"),
Arguments.of((byte) (Device.PRIMARY_ID + 1), null, "apns-voip-token", null, "OWP"),
Arguments.of((byte) (Device.PRIMARY_ID + 1), null, null, "fcm-token", "OWA"),
Arguments.of((byte) (Device.PRIMARY_ID + 1), null, null, null, null)
Arguments.of(Device.PRIMARY_ID, "apns-token", null, "OWI"),
Arguments.of(Device.PRIMARY_ID, null, "fcm-token", "OWA"),
Arguments.of(Device.PRIMARY_ID, null, null, null),
Arguments.of((byte) (Device.PRIMARY_ID + 1), "apns-token", null, "OWP"),
Arguments.of((byte) (Device.PRIMARY_ID + 1), null, "fcm-token", "OWA"),
Arguments.of((byte) (Device.PRIMARY_ID + 1), null, null, null)
);
}

View File

@ -58,38 +58,6 @@ class APNSenderTest {
when(destinationDevice.getApnId()).thenReturn(DESTINATION_DEVICE_TOKEN);
}
@ParameterizedTest
@ValueSource(booleans = {true, false})
void testSendVoip(final boolean urgent) {
PushNotificationResponse<SimpleApnsPushNotification> response = mock(PushNotificationResponse.class);
when(response.isAccepted()).thenReturn(true);
when(apnsClient.sendNotification(any(SimpleApnsPushNotification.class)))
.thenAnswer(
(Answer) invocationOnMock -> new MockPushNotificationFuture<>(invocationOnMock.getArgument(0), response));
PushNotification pushNotification = new PushNotification(DESTINATION_DEVICE_TOKEN, PushNotification.TokenType.APN_VOIP,
PushNotification.NotificationType.NOTIFICATION, null, destinationAccount, destinationDevice, urgent);
final SendPushNotificationResult result = apnSender.sendNotification(pushNotification).join();
ArgumentCaptor<SimpleApnsPushNotification> notification = ArgumentCaptor.forClass(SimpleApnsPushNotification.class);
verify(apnsClient).sendNotification(notification.capture());
assertThat(notification.getValue().getToken()).isEqualTo(DESTINATION_DEVICE_TOKEN);
assertThat(notification.getValue().getExpiration()).isEqualTo(APNSender.MAX_EXPIRATION);
assertThat(notification.getValue().getPayload()).isEqualTo(APNSender.APN_VOIP_NOTIFICATION_PAYLOAD);
// Delivery priority should always be `IMMEDIATE` for VOIP notifications
assertThat(notification.getValue().getPriority()).isEqualTo(DeliveryPriority.IMMEDIATE);
assertThat(notification.getValue().getTopic()).isEqualTo(BUNDLE_ID + ".voip");
assertThat(result.accepted()).isTrue();
assertThat(result.errorCode()).isEmpty();
assertThat(result.unregistered()).isFalse();
verifyNoMoreInteractions(apnsClient);
}
@ParameterizedTest
@ValueSource(booleans = {true, false})
void testSendApns(final boolean urgent) {
@ -144,7 +112,7 @@ class APNSenderTest {
.thenAnswer(
(Answer) invocationOnMock -> new MockPushNotificationFuture<>(invocationOnMock.getArgument(0), response));
PushNotification pushNotification = new PushNotification(DESTINATION_DEVICE_TOKEN, PushNotification.TokenType.APN_VOIP,
PushNotification pushNotification = new PushNotification(DESTINATION_DEVICE_TOKEN, PushNotification.TokenType.APN,
PushNotification.NotificationType.NOTIFICATION, null, destinationAccount, destinationDevice, true);
when(destinationDevice.getApnId()).thenReturn(DESTINATION_DEVICE_TOKEN);
@ -157,7 +125,7 @@ class APNSenderTest {
assertThat(notification.getValue().getToken()).isEqualTo(DESTINATION_DEVICE_TOKEN);
assertThat(notification.getValue().getExpiration()).isEqualTo(APNSender.MAX_EXPIRATION);
assertThat(notification.getValue().getPayload()).isEqualTo(APNSender.APN_VOIP_NOTIFICATION_PAYLOAD);
assertThat(notification.getValue().getPayload()).isEqualTo(APNSender.APN_NSE_NOTIFICATION_PAYLOAD);
assertThat(notification.getValue().getPriority()).isEqualTo(DeliveryPriority.IMMEDIATE);
assertThat(result.accepted()).isFalse();
@ -175,7 +143,7 @@ class APNSenderTest {
.thenAnswer(
(Answer) invocationOnMock -> new MockPushNotificationFuture<>(invocationOnMock.getArgument(0), response));
PushNotification pushNotification = new PushNotification(DESTINATION_DEVICE_TOKEN, PushNotification.TokenType.APN_VOIP,
PushNotification pushNotification = new PushNotification(DESTINATION_DEVICE_TOKEN, PushNotification.TokenType.APN,
PushNotification.NotificationType.NOTIFICATION, null, destinationAccount, destinationDevice, true);
final SendPushNotificationResult result = apnSender.sendNotification(pushNotification).join();
@ -185,7 +153,7 @@ class APNSenderTest {
assertThat(notification.getValue().getToken()).isEqualTo(DESTINATION_DEVICE_TOKEN);
assertThat(notification.getValue().getExpiration()).isEqualTo(APNSender.MAX_EXPIRATION);
assertThat(notification.getValue().getPayload()).isEqualTo(APNSender.APN_VOIP_NOTIFICATION_PAYLOAD);
assertThat(notification.getValue().getPayload()).isEqualTo(APNSender.APN_NSE_NOTIFICATION_PAYLOAD);
assertThat(notification.getValue().getPriority()).isEqualTo(DeliveryPriority.IMMEDIATE);
assertThat(result.accepted()).isFalse();
@ -202,7 +170,7 @@ class APNSenderTest {
.thenAnswer((Answer) invocationOnMock -> new MockPushNotificationFuture<>(invocationOnMock.getArgument(0),
new IOException("lost connection")));
PushNotification pushNotification = new PushNotification(DESTINATION_DEVICE_TOKEN, PushNotification.TokenType.APN_VOIP,
PushNotification pushNotification = new PushNotification(DESTINATION_DEVICE_TOKEN, PushNotification.TokenType.APN,
PushNotification.NotificationType.NOTIFICATION, null, destinationAccount, destinationDevice, true);
assertThatThrownBy(() -> apnSender.sendNotification(pushNotification).join())

View File

@ -77,8 +77,8 @@ class PushNotificationManagerTest {
when(apnSender.sendNotification(any()))
.thenReturn(CompletableFuture.completedFuture(new SendPushNotificationResult(true, Optional.empty(), false, Optional.empty())));
pushNotificationManager.sendRegistrationChallengeNotification(deviceToken, PushNotification.TokenType.APN_VOIP, challengeToken);
verify(apnSender).sendNotification(new PushNotification(deviceToken, PushNotification.TokenType.APN_VOIP, PushNotification.NotificationType.CHALLENGE, challengeToken, null, null, true));
pushNotificationManager.sendRegistrationChallengeNotification(deviceToken, PushNotification.TokenType.APN, challengeToken);
verify(apnSender).sendNotification(new PushNotification(deviceToken, PushNotification.TokenType.APN, PushNotification.NotificationType.CHALLENGE, challengeToken, null, null, true));
}
@Test
@ -220,13 +220,12 @@ class PushNotificationManagerTest {
final UUID aci = UUID.randomUUID();
when(device.getId()).thenReturn(Device.PRIMARY_ID);
when(device.getApnId()).thenReturn("apns-token");
when(device.getVoipApnId()).thenReturn("apns-voip-token");
when(account.getDevice(Device.PRIMARY_ID)).thenReturn(Optional.of(device));
when(account.getUuid()).thenReturn(aci);
when(accountsManager.getByAccountIdentifier(aci)).thenReturn(Optional.of(account));
final PushNotification pushNotification = new PushNotification(
"token", PushNotification.TokenType.APN_VOIP, PushNotification.NotificationType.NOTIFICATION, null, account, device, true);
"token", PushNotification.TokenType.APN, PushNotification.NotificationType.NOTIFICATION, null, account, device, true);
when(apnSender.sendNotification(pushNotification))
.thenReturn(CompletableFuture.completedFuture(new SendPushNotificationResult(false, Optional.empty(), true, Optional.empty())));
@ -238,8 +237,7 @@ class PushNotificationManagerTest {
verifyNoInteractions(fcmSender);
verify(accountsManager).updateDevice(eq(account), eq(Device.PRIMARY_ID), any());
verify(device).setVoipApnId(null);
verify(device, never()).setApnId(any());
verify(device).setApnId(null);
verify(pushNotificationScheduler).cancelScheduledNotifications(account, device);
}
@ -252,14 +250,13 @@ class PushNotificationManagerTest {
final UUID aci = UUID.randomUUID();
when(device.getId()).thenReturn(Device.PRIMARY_ID);
when(device.getApnId()).thenReturn("apns-token");
when(device.getVoipApnId()).thenReturn("apns-voip-token");
when(device.getPushTimestamp()).thenReturn(tokenTimestamp.toEpochMilli());
when(account.getDevice(Device.PRIMARY_ID)).thenReturn(Optional.of(device));
when(account.getUuid()).thenReturn(aci);
when(accountsManager.getByAccountIdentifier(aci)).thenReturn(Optional.of(account));
final PushNotification pushNotification = new PushNotification(
"token", PushNotification.TokenType.APN_VOIP, PushNotification.NotificationType.NOTIFICATION, null, account, device, true);
"token", PushNotification.TokenType.APN, PushNotification.NotificationType.NOTIFICATION, null, account, device, true);
when(apnSender.sendNotification(pushNotification))
.thenReturn(CompletableFuture.completedFuture(new SendPushNotificationResult(false, Optional.empty(), true, Optional.of(tokenTimestamp.minusSeconds(60)))));
@ -271,7 +268,6 @@ class PushNotificationManagerTest {
verifyNoInteractions(fcmSender);
verify(accountsManager, never()).updateDevice(eq(account), eq(Device.PRIMARY_ID), any());
verify(device, never()).setVoipApnId(any());
verify(device, never()).setApnId(any());
verify(pushNotificationScheduler, never()).cancelScheduledNotifications(account, device);
}

View File

@ -56,7 +56,6 @@ class PushNotificationSchedulerTest {
private static final String ACCOUNT_NUMBER = "+18005551234";
private static final byte DEVICE_ID = 1;
private static final String APN_ID = RandomStringUtils.randomAlphanumeric(32);
private static final String VOIP_APN_ID = RandomStringUtils.randomAlphanumeric(32);
@BeforeEach
void setUp() throws Exception {
@ -64,7 +63,6 @@ class PushNotificationSchedulerTest {
device = mock(Device.class);
when(device.getId()).thenReturn(DEVICE_ID);
when(device.getApnId()).thenReturn(APN_ID);
when(device.getVoipApnId()).thenReturn(VOIP_APN_ID);
when(device.getLastSeen()).thenReturn(System.currentTimeMillis());
account = mock(Account.class);

View File

@ -77,7 +77,7 @@ public class AccountCreationDeletionIntegrationTest {
private KeysManager keysManager;
private ClientPublicKeysManager clientPublicKeysManager;
record DeliveryChannels(boolean fetchesMessages, String apnsToken, String apnsVoipToken, String fcmToken) {}
record DeliveryChannels(boolean fetchesMessages, String apnsToken, String fcmToken) {}
@BeforeEach
void setUp() {
@ -212,8 +212,8 @@ public class AccountCreationDeletionIntegrationTest {
final KEMSignedPreKey pniPqLastResortPreKey = KeysHelper.signedKEMPreKey(4, pniKeyPair);
final Optional<ApnRegistrationId> maybeApnRegistrationId =
deliveryChannels.apnsToken() != null || deliveryChannels.apnsVoipToken() != null
? Optional.of(new ApnRegistrationId(deliveryChannels.apnsToken(), deliveryChannels.apnsVoipToken()))
deliveryChannels.apnsToken() != null
? Optional.of(new ApnRegistrationId(deliveryChannels.apnsToken()))
: Optional.empty();
final Optional<GcmRegistrationId> maybeGcmRegistrationId = deliveryChannels.fcmToken() != null
@ -271,10 +271,10 @@ public class AccountCreationDeletionIntegrationTest {
return ArgumentSets
// deliveryChannels
.argumentsForFirstParameter(
new DeliveryChannels(true, null, null, null),
new DeliveryChannels(false, "apns-token", null, null),
new DeliveryChannels(false, "apns-token", "apns-voip-token", null),
new DeliveryChannels(false, null, null, "fcm-token"))
new DeliveryChannels(true, null, null),
new DeliveryChannels(false, "apns-token", null),
new DeliveryChannels(false, "apns-token", null),
new DeliveryChannels(false, null, "fcm-token"))
// discoverableByPhoneNumber
.argumentsForNextParameter(true, false);
@ -359,8 +359,8 @@ public class AccountCreationDeletionIntegrationTest {
final KEMSignedPreKey pniPqLastResortPreKey = KeysHelper.signedKEMPreKey(4, pniKeyPair);
final Optional<ApnRegistrationId> maybeApnRegistrationId =
deliveryChannels.apnsToken() != null || deliveryChannels.apnsVoipToken() != null
? Optional.of(new ApnRegistrationId(deliveryChannels.apnsToken(), deliveryChannels.apnsVoipToken()))
deliveryChannels.apnsToken() != null
? Optional.of(new ApnRegistrationId(deliveryChannels.apnsToken()))
: Optional.empty();
final Optional<GcmRegistrationId> maybeGcmRegistrationId = deliveryChannels.fcmToken() != null
@ -519,19 +519,13 @@ public class AccountCreationDeletionIntegrationTest {
assertEquals(deviceCapabilities, primaryDevice.getCapabilities());
assertEquals(badges, account.getBadges());
maybeApnRegistrationId.ifPresentOrElse(apnRegistrationId -> {
assertEquals(apnRegistrationId.apnRegistrationId(), primaryDevice.getApnId());
assertEquals(apnRegistrationId.voipRegistrationId(), primaryDevice.getVoipApnId());
}, () -> {
assertNull(primaryDevice.getApnId());
assertNull(primaryDevice.getVoipApnId());
});
maybeApnRegistrationId.ifPresentOrElse(
apnRegistrationId -> assertEquals(apnRegistrationId.apnRegistrationId(), primaryDevice.getApnId()),
() -> assertNull(primaryDevice.getApnId()));
maybeGcmRegistrationId.ifPresentOrElse(gcmRegistrationId -> {
assertEquals(deliveryChannels.fcmToken(), primaryDevice.getGcmId());
}, () -> {
assertNull(primaryDevice.getGcmId());
});
maybeGcmRegistrationId.ifPresentOrElse(
gcmRegistrationId -> assertEquals(deliveryChannels.fcmToken(), primaryDevice.getGcmId()),
() -> assertNull(primaryDevice.getGcmId()));
assertTrue(account.getRegistrationLock().verify(registrationLockSecret));
assertTrue(primaryDevice.getAuthTokenHash().verify(password));

View File

@ -986,7 +986,6 @@ class AccountsManagerTest {
assertEquals(pniRegistrationId, device.getPhoneNumberIdentityRegistrationId().getAsInt());
assertTrue(device.getFetchesMessages());
assertNull(device.getApnId());
assertNull(device.getVoipApnId());
assertNull(device.getGcmId());
}

View File

@ -364,15 +364,6 @@ class NotifyIdleDevicesCommandTest {
arguments.add(Arguments.of(device, true));
}
{
// APNs VOIP token
final Device device = mock(Device.class);
when(device.getApnId()).thenReturn("apns-token");
when(device.getVoipApnId()).thenReturn("apns-voip-token");
arguments.add(Arguments.of(device, false));
}
return arguments;
}
}

View File

@ -11,7 +11,6 @@
"salt": null,
"gcmId": null,
"apnId": null,
"voipApnId": null,
"pushTimestamp": 0,
"uninstalledFeedback": 0,
"fetchesMessages": true,