mirror of
https://github.com/signalapp/Signal-Server
synced 2026-04-19 05:18:03 +01:00
Update error model in device.proto
This commit is contained in:
committed by
ravi-signal
parent
a9f81e2ba6
commit
8804f28cb8
@@ -5,7 +5,6 @@
|
||||
|
||||
package org.whispersystems.textsecuregcm.grpc;
|
||||
|
||||
import io.grpc.Status;
|
||||
import org.whispersystems.textsecuregcm.storage.DeviceCapability;
|
||||
|
||||
public class DeviceCapabilityUtil {
|
||||
@@ -19,7 +18,8 @@ public class DeviceCapabilityUtil {
|
||||
case DEVICE_CAPABILITY_TRANSFER -> DeviceCapability.TRANSFER;
|
||||
case DEVICE_CAPABILITY_ATTACHMENT_BACKFILL -> DeviceCapability.ATTACHMENT_BACKFILL;
|
||||
case DEVICE_CAPABILITY_SPARSE_POST_QUANTUM_RATCHET -> DeviceCapability.SPARSE_POST_QUANTUM_RATCHET;
|
||||
case DEVICE_CAPABILITY_UNSPECIFIED, UNRECOGNIZED -> throw Status.INVALID_ARGUMENT.withDescription("Unrecognized device capability").asRuntimeException();
|
||||
case DEVICE_CAPABILITY_UNSPECIFIED, UNRECOGNIZED ->
|
||||
throw GrpcExceptions.invalidArguments("unrecognized device capability");
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ public class DeviceIdUtil {
|
||||
|
||||
static byte validate(int deviceId) {
|
||||
if (!isValid(deviceId)) {
|
||||
throw Status.INVALID_ARGUMENT.withDescription("Device ID is out of range").asRuntimeException();
|
||||
throw GrpcExceptions.invalidArguments("device ID is out of range");
|
||||
}
|
||||
|
||||
return (byte) deviceId;
|
||||
|
||||
@@ -6,9 +6,10 @@
|
||||
package org.whispersystems.textsecuregcm.grpc;
|
||||
|
||||
import com.google.protobuf.ByteString;
|
||||
import io.grpc.Status;
|
||||
import com.google.protobuf.Empty;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.annotation.Nullable;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
@@ -25,9 +26,11 @@ import org.signal.chat.device.SetDeviceNameRequest;
|
||||
import org.signal.chat.device.SetDeviceNameResponse;
|
||||
import org.signal.chat.device.SetPushTokenRequest;
|
||||
import org.signal.chat.device.SetPushTokenResponse;
|
||||
import org.signal.chat.errors.NotFound;
|
||||
import org.whispersystems.textsecuregcm.auth.grpc.AuthenticatedDevice;
|
||||
import org.whispersystems.textsecuregcm.auth.grpc.AuthenticationUtil;
|
||||
import org.whispersystems.textsecuregcm.identity.IdentityType;
|
||||
import org.whispersystems.textsecuregcm.storage.Account;
|
||||
import org.whispersystems.textsecuregcm.storage.AccountsManager;
|
||||
import org.whispersystems.textsecuregcm.storage.Device;
|
||||
import org.whispersystems.textsecuregcm.storage.DeviceCapability;
|
||||
@@ -38,8 +41,6 @@ public class DevicesGrpcService extends ReactorDevicesGrpc.DevicesImplBase {
|
||||
|
||||
private final AccountsManager accountsManager;
|
||||
|
||||
private static final int MAX_NAME_LENGTH = 256;
|
||||
|
||||
public DevicesGrpcService(final AccountsManager accountsManager) {
|
||||
this.accountsManager = accountsManager;
|
||||
}
|
||||
@@ -48,8 +49,7 @@ public class DevicesGrpcService extends ReactorDevicesGrpc.DevicesImplBase {
|
||||
public Mono<GetDevicesResponse> getDevices(final GetDevicesRequest request) {
|
||||
final AuthenticatedDevice authenticatedDevice = AuthenticationUtil.requireAuthenticatedDevice();
|
||||
|
||||
return Mono.fromFuture(() -> accountsManager.getByAccountIdentifierAsync(authenticatedDevice.accountIdentifier()))
|
||||
.map(maybeAccount -> maybeAccount.orElseThrow(Status.UNAUTHENTICATED::asRuntimeException))
|
||||
return getAccount(authenticatedDevice.accountIdentifier())
|
||||
.flatMapMany(account -> Flux.fromIterable(account.getDevices()))
|
||||
.reduce(GetDevicesResponse.newBuilder(), (builder, device) -> {
|
||||
final GetDevicesResponse.LinkedDevice.Builder linkedDeviceBuilder = GetDevicesResponse.LinkedDevice.newBuilder();
|
||||
@@ -72,21 +72,18 @@ public class DevicesGrpcService extends ReactorDevicesGrpc.DevicesImplBase {
|
||||
@Override
|
||||
public Mono<RemoveDeviceResponse> removeDevice(final RemoveDeviceRequest request) {
|
||||
if (request.getId() == Device.PRIMARY_ID) {
|
||||
throw Status.INVALID_ARGUMENT.withDescription("Cannot remove primary device").asRuntimeException();
|
||||
throw GrpcExceptions.invalidArguments("cannot remove primary device");
|
||||
}
|
||||
|
||||
final AuthenticatedDevice authenticatedDevice = AuthenticationUtil.requireAuthenticatedDevice();
|
||||
|
||||
if (authenticatedDevice.deviceId() != Device.PRIMARY_ID && request.getId() != authenticatedDevice.deviceId()) {
|
||||
throw Status.PERMISSION_DENIED
|
||||
.withDescription("Linked devices cannot remove devices other than themselves")
|
||||
.asRuntimeException();
|
||||
throw GrpcExceptions.badAuthentication("linked devices cannot remove devices other than themselves");
|
||||
}
|
||||
|
||||
final byte deviceId = DeviceIdUtil.validate(request.getId());
|
||||
|
||||
return Mono.fromFuture(() -> accountsManager.getByAccountIdentifierAsync(authenticatedDevice.accountIdentifier()))
|
||||
.map(maybeAccount -> maybeAccount.orElseThrow(Status.UNAUTHENTICATED::asRuntimeException))
|
||||
return getAccount(authenticatedDevice.accountIdentifier())
|
||||
.flatMap(account -> Mono.fromFuture(accountsManager.removeDevice(account, deviceId)))
|
||||
.thenReturn(RemoveDeviceResponse.newBuilder().build());
|
||||
}
|
||||
@@ -101,30 +98,18 @@ public class DevicesGrpcService extends ReactorDevicesGrpc.DevicesImplBase {
|
||||
authenticatedDevice.deviceId() == deviceId;
|
||||
|
||||
if (!mayChangeName) {
|
||||
throw Status.PERMISSION_DENIED
|
||||
.withDescription("Authenticated device is not authorized to change target device name")
|
||||
.asRuntimeException();
|
||||
throw GrpcExceptions.badAuthentication("linked device is not authorized to change target device name");
|
||||
}
|
||||
|
||||
if (request.getName().isEmpty()) {
|
||||
throw Status.INVALID_ARGUMENT.withDescription("Must specify a device name").asRuntimeException();
|
||||
}
|
||||
|
||||
if (request.getName().size() > MAX_NAME_LENGTH) {
|
||||
throw Status.INVALID_ARGUMENT.withDescription("Device name must be at most " + MAX_NAME_LENGTH + " bytes")
|
||||
.asRuntimeException();
|
||||
}
|
||||
|
||||
return Mono.fromFuture(() -> accountsManager.getByAccountIdentifierAsync(authenticatedDevice.accountIdentifier()))
|
||||
.map(maybeAccount -> maybeAccount.orElseThrow(Status.UNAUTHENTICATED::asRuntimeException))
|
||||
.doOnNext(account -> {
|
||||
return getAccount(authenticatedDevice.accountIdentifier())
|
||||
.flatMap(account -> {
|
||||
if (account.getDevice(deviceId).isEmpty()) {
|
||||
throw Status.NOT_FOUND.withDescription("No device found with given ID").asRuntimeException();
|
||||
return Mono.just(SetDeviceNameResponse.newBuilder().setTargetDeviceNotFound(NotFound.getDefaultInstance()).build());
|
||||
}
|
||||
})
|
||||
.flatMap(account -> Mono.fromFuture(() -> accountsManager.updateDeviceAsync(account, deviceId,
|
||||
device -> device.setName(request.getName().toByteArray()))))
|
||||
.thenReturn(SetDeviceNameResponse.newBuilder().build());
|
||||
return Mono.fromFuture(() -> accountsManager.updateDeviceAsync(account, deviceId, device ->
|
||||
device.setName(request.getName().toByteArray())))
|
||||
.thenReturn(SetDeviceNameResponse.newBuilder().setSuccess(Empty.getDefaultInstance()).build());
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -138,34 +123,23 @@ public class DevicesGrpcService extends ReactorDevicesGrpc.DevicesImplBase {
|
||||
|
||||
case APNS_TOKEN_REQUEST -> {
|
||||
final SetPushTokenRequest.ApnsTokenRequest apnsTokenRequest = request.getApnsTokenRequest();
|
||||
|
||||
if (StringUtils.isBlank(apnsTokenRequest.getApnsToken())) {
|
||||
throw Status.INVALID_ARGUMENT.withDescription("APNs token must not be blank").asRuntimeException();
|
||||
}
|
||||
|
||||
apnsToken = StringUtils.stripToNull(apnsTokenRequest.getApnsToken());
|
||||
fcmToken = null;
|
||||
}
|
||||
|
||||
case FCM_TOKEN_REQUEST -> {
|
||||
final SetPushTokenRequest.FcmTokenRequest fcmTokenRequest = request.getFcmTokenRequest();
|
||||
|
||||
if (StringUtils.isBlank(fcmTokenRequest.getFcmToken())) {
|
||||
throw Status.INVALID_ARGUMENT.withDescription("FCM token must not be blank").asRuntimeException();
|
||||
}
|
||||
|
||||
apnsToken = null;
|
||||
fcmToken = StringUtils.stripToNull(fcmTokenRequest.getFcmToken());
|
||||
}
|
||||
|
||||
default -> throw Status.INVALID_ARGUMENT.withDescription("No tokens specified").asRuntimeException();
|
||||
default -> throw GrpcExceptions.fieldViolation("token_request", "No tokens specified");
|
||||
}
|
||||
|
||||
return Mono.fromFuture(() -> accountsManager.getByAccountIdentifierAsync(authenticatedDevice.accountIdentifier()))
|
||||
.map(maybeAccount -> maybeAccount.orElseThrow(Status.UNAUTHENTICATED::asRuntimeException))
|
||||
return getAccount(authenticatedDevice.accountIdentifier())
|
||||
.flatMap(account -> {
|
||||
final Device device = account.getDevice(authenticatedDevice.deviceId())
|
||||
.orElseThrow(Status.UNAUTHENTICATED::asRuntimeException);
|
||||
.orElseThrow(() -> GrpcExceptions.invalidCredentials("invalid credentials"));
|
||||
|
||||
final boolean tokenUnchanged =
|
||||
Objects.equals(device.getApnId(), apnsToken) &&
|
||||
@@ -186,8 +160,7 @@ public class DevicesGrpcService extends ReactorDevicesGrpc.DevicesImplBase {
|
||||
public Mono<ClearPushTokenResponse> clearPushToken(final ClearPushTokenRequest request) {
|
||||
final AuthenticatedDevice authenticatedDevice = AuthenticationUtil.requireAuthenticatedDevice();
|
||||
|
||||
return Mono.fromFuture(() -> accountsManager.getByAccountIdentifierAsync(authenticatedDevice.accountIdentifier()))
|
||||
.map(maybeAccount -> maybeAccount.orElseThrow(Status.UNAUTHENTICATED::asRuntimeException))
|
||||
return getAccount(authenticatedDevice.accountIdentifier())
|
||||
.flatMap(account -> Mono.fromFuture(() -> accountsManager.updateDeviceAsync(account, authenticatedDevice.deviceId(), device -> {
|
||||
if (StringUtils.isNotBlank(device.getApnId())) {
|
||||
device.setUserAgent(device.isPrimary() ? "OWI" : "OWP");
|
||||
@@ -210,11 +183,15 @@ public class DevicesGrpcService extends ReactorDevicesGrpc.DevicesImplBase {
|
||||
.map(DeviceCapabilityUtil::fromGrpcDeviceCapability)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
return Mono.fromFuture(() -> accountsManager.getByAccountIdentifierAsync(authenticatedDevice.accountIdentifier()))
|
||||
.map(maybeAccount -> maybeAccount.orElseThrow(Status.UNAUTHENTICATED::asRuntimeException))
|
||||
return getAccount(authenticatedDevice.accountIdentifier())
|
||||
.flatMap(account ->
|
||||
Mono.fromFuture(() -> accountsManager.updateDeviceAsync(account, authenticatedDevice.deviceId(),
|
||||
d -> d.setCapabilities(capabilities))))
|
||||
.thenReturn(SetCapabilitiesResponse.newBuilder().build());
|
||||
}
|
||||
|
||||
private Mono<Account> getAccount(final UUID accountIdentifier) {
|
||||
return Mono.fromFuture(() -> accountsManager.getByAccountIdentifierAsync(accountIdentifier))
|
||||
.map(maybeAccount -> maybeAccount.orElseThrow(() -> GrpcExceptions.invalidCredentials("invalid credentials")));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user