Replace DeviceCapabilities entity with Set<DeviceCapability>

This commit is contained in:
Jon Chambers
2024-10-30 12:46:20 -04:00
committed by GitHub
parent b21b50873f
commit 0e3dccd9f6
34 changed files with 532 additions and 348 deletions

View File

@@ -8,6 +8,8 @@ package org.whispersystems.textsecuregcm.grpc;
import com.google.protobuf.ByteString;
import io.grpc.Status;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
import org.apache.commons.lang3.StringUtils;
import org.signal.chat.device.ClearPushTokenRequest;
@@ -27,6 +29,7 @@ import org.whispersystems.textsecuregcm.auth.grpc.AuthenticatedDevice;
import org.whispersystems.textsecuregcm.auth.grpc.AuthenticationUtil;
import org.whispersystems.textsecuregcm.storage.AccountsManager;
import org.whispersystems.textsecuregcm.storage.Device;
import org.whispersystems.textsecuregcm.storage.DeviceCapability;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@@ -200,15 +203,21 @@ public class DevicesGrpcService extends ReactorDevicesGrpc.DevicesImplBase {
public Mono<SetCapabilitiesResponse> setCapabilities(final SetCapabilitiesRequest request) {
final AuthenticatedDevice authenticatedDevice = AuthenticationUtil.requireAuthenticatedDevice();
final Set<DeviceCapability> capabilities = request.getCapabilitiesList().stream()
.map(capability -> switch (capability) {
case DEVICE_CAPABILITY_STORAGE -> DeviceCapability.STORAGE;
case DEVICE_CAPABILITY_TRANSFER -> DeviceCapability.TRANSFER;
case DEVICE_CAPABILITY_DELETE_SYNC -> DeviceCapability.DELETE_SYNC;
case DEVICE_CAPABILITY_VERSIONED_EXPIRATION_TIMER -> DeviceCapability.VERSIONED_EXPIRATION_TIMER;
default -> throw Status.INVALID_ARGUMENT.withDescription("Unrecognized device capability").asRuntimeException();
})
.collect(Collectors.toSet());
return Mono.fromFuture(() -> accountsManager.getByAccountIdentifierAsync(authenticatedDevice.accountIdentifier()))
.map(maybeAccount -> maybeAccount.orElseThrow(Status.UNAUTHENTICATED::asRuntimeException))
.flatMap(account ->
Mono.fromFuture(() -> accountsManager.updateDeviceAsync(account, authenticatedDevice.deviceId(),
d -> d.setCapabilities(new Device.DeviceCapabilities(
request.getStorage(),
request.getTransfer(),
request.getDeleteSync(),
request.getVersionedExpirationTimer())))))
d -> d.setCapabilities(capabilities))))
.thenReturn(SetCapabilitiesResponse.newBuilder().build());
}
}

View File

@@ -9,14 +9,15 @@ import com.google.common.annotations.VisibleForTesting;
import com.google.protobuf.ByteString;
import io.grpc.Status;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import org.signal.chat.profile.AccountCapabilities;
import org.signal.chat.profile.Badge;
import org.signal.chat.profile.BadgeSvg;
import org.signal.chat.profile.GetExpiringProfileKeyCredentialResponse;
import org.signal.chat.profile.GetUnversionedProfileResponse;
import org.signal.chat.profile.GetVersionedProfileResponse;
import org.signal.chat.profile.UserCapabilities;
import org.signal.libsignal.protocol.ServiceId;
import org.signal.libsignal.zkgroup.InvalidInputException;
import org.signal.libsignal.zkgroup.VerificationFailedException;
@@ -24,9 +25,9 @@ import org.signal.libsignal.zkgroup.profiles.ExpiringProfileKeyCredentialRespons
import org.signal.libsignal.zkgroup.profiles.ServerZkProfileOperations;
import org.whispersystems.textsecuregcm.auth.UnidentifiedAccessChecksum;
import org.whispersystems.textsecuregcm.badges.ProfileBadgeConverter;
import org.whispersystems.textsecuregcm.identity.AciServiceIdentifier;
import org.whispersystems.textsecuregcm.identity.ServiceIdentifier;
import org.whispersystems.textsecuregcm.storage.Account;
import org.whispersystems.textsecuregcm.storage.DeviceCapability;
import org.whispersystems.textsecuregcm.storage.ProfilesManager;
import org.whispersystems.textsecuregcm.storage.VersionedProfile;
import org.whispersystems.textsecuregcm.util.ProfileHelper;
@@ -80,11 +81,21 @@ public class ProfileGrpcHelper {
}
@VisibleForTesting
static UserCapabilities buildUserCapabilities(final org.whispersystems.textsecuregcm.entities.UserCapabilities capabilities) {
return UserCapabilities.newBuilder()
.setDeleteSync(capabilities.deleteSync())
.setVersionedExpirationTimer(capabilities.versionedExpirationTimer())
.build();
static AccountCapabilities buildAccountCapabilities(final Account account) {
final AccountCapabilities.Builder capabilitiesBuilder = AccountCapabilities.newBuilder();
Arrays.stream(DeviceCapability.values())
.filter(DeviceCapability::includeInProfile)
.filter(account::hasCapability)
.map(capability -> switch (capability) {
case STORAGE -> org.signal.chat.common.DeviceCapability.DEVICE_CAPABILITY_STORAGE;
case TRANSFER -> org.signal.chat.common.DeviceCapability.DEVICE_CAPABILITY_TRANSFER;
case DELETE_SYNC -> org.signal.chat.common.DeviceCapability.DEVICE_CAPABILITY_DELETE_SYNC;
case VERSIONED_EXPIRATION_TIMER -> org.signal.chat.common.DeviceCapability.DEVICE_CAPABILITY_VERSIONED_EXPIRATION_TIMER;
})
.forEach(capabilitiesBuilder::addCapabilities);
return capabilitiesBuilder.build();
}
private static List<BadgeSvg> buildBadgeSvgs(final List<org.whispersystems.textsecuregcm.entities.BadgeSvg> badgeSvgs) {
@@ -105,7 +116,7 @@ public class ProfileGrpcHelper {
final ProfileBadgeConverter profileBadgeConverter) {
final GetUnversionedProfileResponse.Builder responseBuilder = GetUnversionedProfileResponse.newBuilder()
.setIdentityKey(ByteString.copyFrom(targetAccount.getIdentityKey(targetIdentifier.identityType()).serialize()))
.setCapabilities(buildUserCapabilities(org.whispersystems.textsecuregcm.entities.UserCapabilities.createForAccount(targetAccount)));
.setCapabilities(buildAccountCapabilities(targetAccount));
switch (targetIdentifier.identityType()) {
case ACI -> {
@@ -113,7 +124,7 @@ public class ProfileGrpcHelper {
.addAllBadges(buildBadges(profileBadgeConverter.convert(
RequestAttributesUtil.getAvailableAcceptedLocales(),
targetAccount.getBadges(),
ProfileHelper.isSelfProfileRequest(requesterUuid, (AciServiceIdentifier) targetIdentifier))));
ProfileHelper.isSelfProfileRequest(requesterUuid, targetIdentifier))));
targetAccount.getUnidentifiedAccessKey()
.map(UnidentifiedAccessChecksum::generateFor)