mirror of
https://github.com/signalapp/Signal-Server
synced 2026-07-12 19:56:28 +01:00
Add badge/backup entitlement RPC
This commit is contained in:
committed by
Jon Chambers
parent
9e3844ee5a
commit
6bb85d77a7
@@ -1069,7 +1069,7 @@ public class WhisperServerService extends Application<WhisperServerConfiguration
|
||||
config.getDeliveryCertificate().embedSigner());
|
||||
|
||||
final List<ServerServiceDefinition> authenticatedServices = Stream.of(
|
||||
new AccountsGrpcService(accountsManager, rateLimiters, usernameHashZkProofVerifier, registrationRecoveryPasswordsManager),
|
||||
new AccountsGrpcService(accountsManager, rateLimiters, usernameHashZkProofVerifier, registrationRecoveryPasswordsManager, Clock.systemUTC()),
|
||||
new CallingGrpcService(cloudflareTurnCredentialsManager, rateLimiters),
|
||||
new CredentialsGrpcService(accountsManager, certificateGenerator, zkAuthOperations, callingGenericZkSecretParams, rateLimiters, Clock.systemUTC(), ExternalServiceDefinitions.createExternalServiceList(config, Clock.systemUTC())),
|
||||
new KeysGrpcService(accountsManager, keysManager, rateLimiters),
|
||||
|
||||
+34
-1
@@ -7,6 +7,8 @@ package org.whispersystems.textsecuregcm.grpc;
|
||||
|
||||
import com.google.protobuf.ByteString;
|
||||
import java.security.SecureRandom;
|
||||
import java.time.Clock;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HexFormat;
|
||||
import java.util.List;
|
||||
@@ -26,6 +28,8 @@ import org.signal.chat.account.DeleteUsernameLinkRequest;
|
||||
import org.signal.chat.account.DeleteUsernameLinkResponse;
|
||||
import org.signal.chat.account.GetAccountIdentityRequest;
|
||||
import org.signal.chat.account.GetAccountIdentityResponse;
|
||||
import org.signal.chat.account.GetEntitlementsRequest;
|
||||
import org.signal.chat.account.GetEntitlementsResponse;
|
||||
import org.signal.chat.account.ReserveUsernameHashRequest;
|
||||
import org.signal.chat.account.ReserveUsernameHashResponse;
|
||||
import org.signal.chat.account.SetDiscoverableByPhoneNumberRequest;
|
||||
@@ -70,16 +74,19 @@ public class AccountsGrpcService extends SimpleAccountsGrpc.AccountsImplBase {
|
||||
private final RateLimiters rateLimiters;
|
||||
private final UsernameHashZkProofVerifier usernameHashZkProofVerifier;
|
||||
private final RegistrationRecoveryPasswordsManager registrationRecoveryPasswordsManager;
|
||||
private final Clock clock;
|
||||
|
||||
public AccountsGrpcService(final AccountsManager accountsManager,
|
||||
final RateLimiters rateLimiters,
|
||||
final UsernameHashZkProofVerifier usernameHashZkProofVerifier,
|
||||
final RegistrationRecoveryPasswordsManager registrationRecoveryPasswordsManager) {
|
||||
final RegistrationRecoveryPasswordsManager registrationRecoveryPasswordsManager,
|
||||
final Clock clock) {
|
||||
|
||||
this.accountsManager = accountsManager;
|
||||
this.rateLimiters = rateLimiters;
|
||||
this.usernameHashZkProofVerifier = usernameHashZkProofVerifier;
|
||||
this.registrationRecoveryPasswordsManager = registrationRecoveryPasswordsManager;
|
||||
this.clock = clock;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -103,6 +110,32 @@ public class AccountsGrpcService extends SimpleAccountsGrpc.AccountsImplBase {
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public GetEntitlementsResponse getEntitlements(final GetEntitlementsRequest request) {
|
||||
final Account account = getAuthenticatedAccount();
|
||||
final GetEntitlementsResponse.Builder builder = GetEntitlementsResponse.newBuilder();
|
||||
|
||||
final Instant now = clock.instant();
|
||||
|
||||
final Account.BackupVoucher backupVoucher = account.getBackupVoucher();
|
||||
if (backupVoucher != null && backupVoucher.expiration().isAfter(now)) {
|
||||
builder.setBackup(GetEntitlementsResponse.BackupEntitlement.newBuilder()
|
||||
.setExpirationEpochSeconds(backupVoucher.expiration().getEpochSecond())
|
||||
.setLevel(backupVoucher.receiptLevel()));
|
||||
}
|
||||
|
||||
builder.addAllBadges(account.getBadges().stream()
|
||||
.filter(badge -> badge.expiration().isAfter(now))
|
||||
.map(badge -> GetEntitlementsResponse.BadgeEntitlement.newBuilder()
|
||||
.setBadgeId(badge.id())
|
||||
.setExpirationEpochSeconds(badge.expiration().getEpochSecond())
|
||||
.setVisible(badge.visible())
|
||||
.build())
|
||||
.toList());
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeleteAccountResponse deleteAccount(final DeleteAccountRequest request) {
|
||||
accountsManager.delete(AuthenticationUtil.requireAuthenticatedPrimaryDevice().accountIdentifier(),
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2026 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.whispersystems.textsecuregcm.grpc;
|
||||
|
||||
import org.signal.chat.common.Badge;
|
||||
import org.signal.chat.common.BadgeSvg;
|
||||
|
||||
public class BadgeGrpcHelper {
|
||||
|
||||
public static Badge toGrpcBadge(final org.whispersystems.textsecuregcm.entities.Badge badge) {
|
||||
final Badge.Builder builder = Badge.newBuilder()
|
||||
.setId(badge.getId())
|
||||
.setCategory(badge.getCategory())
|
||||
.setName(badge.getName())
|
||||
.setDescription(badge.getDescription())
|
||||
.addAllSprites6(badge.getSprites6())
|
||||
.setSvg(badge.getSvg());
|
||||
|
||||
badge.getSvgs().stream()
|
||||
.map(badgeSvg -> BadgeSvg.newBuilder()
|
||||
.setDark(badgeSvg.getDark())
|
||||
.setLight(badgeSvg.getLight())
|
||||
.build())
|
||||
.forEach(builder::addSvgs);
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
}
|
||||
+5
-17
@@ -13,8 +13,6 @@ import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
import org.signal.chat.common.Badge;
|
||||
import org.signal.chat.common.BadgeSvg;
|
||||
import org.signal.chat.purchase.AmountList;
|
||||
import org.signal.chat.purchase.BackupConfiguration;
|
||||
import org.signal.chat.purchase.BackupLevelConfiguration;
|
||||
@@ -158,22 +156,12 @@ public class ProductConfigurationGrpcService extends SimpleProductConfigurationG
|
||||
|
||||
private static LevelConfiguration toProtoLevelConfiguration(
|
||||
final org.whispersystems.textsecuregcm.subscriptions.LevelConfiguration levelConfiguration) {
|
||||
final org.whispersystems.textsecuregcm.entities.Badge badge = levelConfiguration.badge();
|
||||
final Badge commonBadge = Badge.newBuilder()
|
||||
.setId(badge.getId())
|
||||
.setCategory(badge.getCategory())
|
||||
.setName(badge.getName())
|
||||
.setDescription(badge.getDescription())
|
||||
.addAllSprites6(badge.getSprites6())
|
||||
.setSvg(badge.getSvg())
|
||||
.addAllSvgs(badge.getSvgs().stream()
|
||||
.map(s -> BadgeSvg.newBuilder().setLight(s.getLight()).setDark(s.getDark()).build())
|
||||
.toList())
|
||||
.build();
|
||||
final LevelConfiguration.Builder builder = LevelConfiguration.newBuilder().setBadge(commonBadge);
|
||||
if (badge instanceof final PurchasableBadge purchasableBadge) {
|
||||
final LevelConfiguration.Builder builder = LevelConfiguration.newBuilder();
|
||||
if (levelConfiguration.badge() instanceof final PurchasableBadge purchasableBadge) {
|
||||
builder.setBadgeDurationSeconds(purchasableBadge.getDuration().toSeconds());
|
||||
}
|
||||
return builder.build();
|
||||
return builder
|
||||
.setBadge(BadgeGrpcHelper.toGrpcBadge(levelConfiguration.badge()))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
-1
@@ -129,7 +129,6 @@ public class ProfileAnonymousGrpcService extends SimpleProfileAnonymousGrpc.Prof
|
||||
return targetAccount.map(account ->
|
||||
GetUnversionedProfileAnonymousResponse.newBuilder()
|
||||
.setResult(ProfileGrpcHelper.buildUnversionedProfileResult(targetIdentifier,
|
||||
null,
|
||||
account,
|
||||
profileBadgeConverter))
|
||||
.build())
|
||||
|
||||
@@ -10,14 +10,11 @@ import com.google.protobuf.ByteString;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.time.Clock;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HexFormat;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import org.signal.chat.common.Badge;
|
||||
import org.signal.chat.common.BadgeSvg;
|
||||
import org.signal.chat.common.S3UploadForm;
|
||||
import org.signal.chat.profile.DataEtag;
|
||||
import org.signal.chat.profile.GetExpiringProfileKeyCredentialResult;
|
||||
@@ -33,6 +30,7 @@ import org.signal.libsignal.zkgroup.profiles.ProfileKeyCredentialRequest;
|
||||
import org.signal.libsignal.zkgroup.profiles.ServerZkProfileOperations;
|
||||
import org.whispersystems.textsecuregcm.auth.UnidentifiedAccessChecksum;
|
||||
import org.whispersystems.textsecuregcm.badges.ProfileBadgeConverter;
|
||||
import org.whispersystems.textsecuregcm.entities.Badge;
|
||||
import org.whispersystems.textsecuregcm.identity.ServiceIdentifier;
|
||||
import org.whispersystems.textsecuregcm.s3.PostPolicyGenerator;
|
||||
import org.whispersystems.textsecuregcm.storage.Account;
|
||||
@@ -129,23 +127,6 @@ public class ProfileGrpcHelper {
|
||||
return Optional.of(responseBuilder.build());
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static List<Badge> buildBadges(final List<org.whispersystems.textsecuregcm.entities.Badge> badges) {
|
||||
final ArrayList<Badge> grpcBadges = new ArrayList<>();
|
||||
for (final org.whispersystems.textsecuregcm.entities.Badge badge : badges) {
|
||||
grpcBadges.add(Badge.newBuilder()
|
||||
.setId(badge.getId())
|
||||
.setCategory(badge.getCategory())
|
||||
.setName(badge.getName())
|
||||
.setDescription(badge.getDescription())
|
||||
.addAllSprites6(badge.getSprites6())
|
||||
.setSvg(badge.getSvg())
|
||||
.addAllSvgs(buildBadgeSvgs(badge.getSvgs()))
|
||||
.build());
|
||||
}
|
||||
return grpcBadges;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static List<org.signal.chat.common.DeviceCapability> buildAccountCapabilities(final Account account) {
|
||||
return Arrays.stream(DeviceCapability.values())
|
||||
@@ -155,20 +136,8 @@ public class ProfileGrpcHelper {
|
||||
.toList();
|
||||
}
|
||||
|
||||
private static List<BadgeSvg> buildBadgeSvgs(final List<org.whispersystems.textsecuregcm.entities.BadgeSvg> badgeSvgs) {
|
||||
ArrayList<BadgeSvg> grpcBadgeSvgs = new ArrayList<>();
|
||||
for (final org.whispersystems.textsecuregcm.entities.BadgeSvg badgeSvg : badgeSvgs) {
|
||||
grpcBadgeSvgs.add(BadgeSvg.newBuilder()
|
||||
.setDark(badgeSvg.getDark())
|
||||
.setLight(badgeSvg.getLight())
|
||||
.build());
|
||||
}
|
||||
return grpcBadgeSvgs;
|
||||
}
|
||||
|
||||
static GetUnversionedProfileResult buildUnversionedProfileResult(
|
||||
final ServiceIdentifier targetIdentifier,
|
||||
final UUID requesterUuid,
|
||||
final Account targetAccount,
|
||||
final ProfileBadgeConverter profileBadgeConverter) {
|
||||
final GetUnversionedProfileResult.Builder resultBuilder = GetUnversionedProfileResult.newBuilder()
|
||||
@@ -177,11 +146,13 @@ public class ProfileGrpcHelper {
|
||||
|
||||
switch (targetIdentifier.identityType()) {
|
||||
case ACI -> {
|
||||
resultBuilder.setUnrestrictedUnidentifiedAccess(targetAccount.isUnrestrictedUnidentifiedAccess())
|
||||
.addAllBadges(
|
||||
buildBadges(profileBadgeConverter.convert(RequestAttributesUtil.getAvailableAcceptedLocales(),
|
||||
targetAccount.getBadges(),
|
||||
ProfileHelper.isSelfProfileRequest(requesterUuid, targetIdentifier))));
|
||||
final List<Locale> acceptedLocales = RequestAttributesUtil.getAvailableAcceptedLocales();
|
||||
final List<Badge> badges =
|
||||
profileBadgeConverter.convert(acceptedLocales, targetAccount.getBadges(), false);
|
||||
|
||||
resultBuilder
|
||||
.setUnrestrictedUnidentifiedAccess(targetAccount.isUnrestrictedUnidentifiedAccess())
|
||||
.addAllBadges(badges.stream().map(BadgeGrpcHelper::toGrpcBadge).toList());
|
||||
|
||||
targetAccount.getUnidentifiedAccessKey()
|
||||
.map(UnidentifiedAccessChecksum::generateFor)
|
||||
|
||||
@@ -260,7 +260,6 @@ public class ProfileGrpcService extends SimpleProfileGrpc.ProfileImplBase {
|
||||
|
||||
return maybeAccount.map(account -> GetUnversionedProfileResponse.newBuilder()
|
||||
.setResult(ProfileGrpcHelper.buildUnversionedProfileResult(targetIdentifier,
|
||||
authenticatedDevice.accountIdentifier(),
|
||||
account,
|
||||
profileBadgeConverter))
|
||||
.build()).orElseGet(() -> GetUnversionedProfileResponse.newBuilder()
|
||||
|
||||
@@ -14,6 +14,9 @@ service Accounts {
|
||||
// Returns basic identifiers for the authenticated account.
|
||||
rpc GetAccountIdentity(GetAccountIdentityRequest) returns (GetAccountIdentityResponse) {}
|
||||
|
||||
// Returns entitlements for the authenticated account.
|
||||
rpc GetEntitlements(GetEntitlementsRequest) returns (GetEntitlementsResponse) {}
|
||||
|
||||
// Deletes the authenticated account, purging all associated data in the
|
||||
// process.
|
||||
rpc DeleteAccount(DeleteAccountRequest) returns (DeleteAccountResponse) {}
|
||||
@@ -84,6 +87,35 @@ message GetAccountIdentityResponse {
|
||||
common.AccountIdentifiers account_identifiers = 1;
|
||||
}
|
||||
|
||||
message GetEntitlementsRequest {
|
||||
}
|
||||
|
||||
message GetEntitlementsResponse {
|
||||
message BadgeEntitlement {
|
||||
// The id of the badge the account is entitled. Metadata to display for
|
||||
// badges may be obtained by cross-referencing badge ids with
|
||||
// ProductConfiguration.GetConfiguration.
|
||||
string badge_id = 1;
|
||||
// When the badge expires, in number of seconds since epoch
|
||||
uint64 expiration_epoch_seconds = 2;
|
||||
// Whether the badge is currently configured to be visible
|
||||
bool visible = 3;
|
||||
}
|
||||
|
||||
message BackupEntitlement {
|
||||
// The backup level of the account
|
||||
uint64 level = 1;
|
||||
// When the backup entitlement expires, in number of seconds since epoch
|
||||
uint64 expiration_epoch_seconds = 2;
|
||||
}
|
||||
|
||||
// Active badges added via Donations.redeemReceipt
|
||||
repeated BadgeEntitlement badges = 1;
|
||||
|
||||
// If present, the backup level set via Backups.redeemReceipt
|
||||
BackupEntitlement backup = 2;
|
||||
}
|
||||
|
||||
message DeleteAccountRequest {
|
||||
}
|
||||
|
||||
|
||||
@@ -292,13 +292,16 @@ message GetUnversionedProfileAnonymousRequest {
|
||||
message GetUnversionedProfileResult {
|
||||
// The identity key of the targeted account/identity type.
|
||||
bytes identity_key = 1;
|
||||
// A checksum of the unidentified access key for the targeted account.
|
||||
// A checksum of the unidentified access key for the targeted account. Absent
|
||||
// if the request was for a PNI.
|
||||
bytes unidentified_access = 2;
|
||||
// Whether the account has enabled sealed sender from anyone.
|
||||
// Whether the account has enabled sealed sender from anyone. Always false
|
||||
// if the request was for a PNI.
|
||||
bool unrestricted_unidentified_access = 3;
|
||||
// A list of capabilities enabled on the account.
|
||||
repeated common.DeviceCapability capabilities = 4;
|
||||
// A list of badges associated with the account.
|
||||
// A list of badges associated with the account. Absent if the request was for
|
||||
// a PNI.
|
||||
repeated common.Badge badges = 5;
|
||||
}
|
||||
|
||||
|
||||
+47
-1
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.whispersystems.textsecuregcm.grpc;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
@@ -21,6 +22,7 @@ import com.google.i18n.phonenumbers.PhoneNumberUtil;
|
||||
import com.google.protobuf.ByteString;
|
||||
import io.grpc.Status;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.HexFormat;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
@@ -46,6 +48,8 @@ import org.signal.chat.account.DeleteUsernameHashRequest;
|
||||
import org.signal.chat.account.DeleteUsernameLinkRequest;
|
||||
import org.signal.chat.account.GetAccountIdentityRequest;
|
||||
import org.signal.chat.account.GetAccountIdentityResponse;
|
||||
import org.signal.chat.account.GetEntitlementsRequest;
|
||||
import org.signal.chat.account.GetEntitlementsResponse;
|
||||
import org.signal.chat.account.ReserveUsernameHashRequest;
|
||||
import org.signal.chat.account.ReserveUsernameHashResponse;
|
||||
import org.signal.chat.account.SetDiscoverableByPhoneNumberRequest;
|
||||
@@ -73,12 +77,14 @@ import org.whispersystems.textsecuregcm.identity.PniServiceIdentifier;
|
||||
import org.whispersystems.textsecuregcm.limits.RateLimiter;
|
||||
import org.whispersystems.textsecuregcm.limits.RateLimiters;
|
||||
import org.whispersystems.textsecuregcm.storage.Account;
|
||||
import org.whispersystems.textsecuregcm.storage.AccountBadge;
|
||||
import org.whispersystems.textsecuregcm.storage.AccountsManager;
|
||||
import org.whispersystems.textsecuregcm.storage.Device;
|
||||
import org.whispersystems.textsecuregcm.storage.RegistrationRecoveryPasswordsManager;
|
||||
import org.whispersystems.textsecuregcm.storage.UsernameHashNotAvailableException;
|
||||
import org.whispersystems.textsecuregcm.storage.UsernameReservationNotFoundException;
|
||||
import org.whispersystems.textsecuregcm.tests.util.AccountsHelper;
|
||||
import org.whispersystems.textsecuregcm.util.TestClock;
|
||||
import org.whispersystems.textsecuregcm.util.TestRandomUtil;
|
||||
import org.whispersystems.textsecuregcm.util.UUIDUtil;
|
||||
import org.whispersystems.textsecuregcm.util.UsernameHashZkProofVerifier;
|
||||
@@ -97,6 +103,8 @@ class AccountsGrpcServiceTest extends SimpleBaseGrpcTest<AccountsGrpcService, Ac
|
||||
@Mock
|
||||
private RegistrationRecoveryPasswordsManager registrationRecoveryPasswordsManager;
|
||||
|
||||
private final TestClock testClock = TestClock.pinned(Instant.now());
|
||||
|
||||
@Override
|
||||
protected AccountsGrpcService createServiceBeforeEachTest() {
|
||||
AccountsHelper.setupMockUpdate(accountsManager);
|
||||
@@ -111,7 +119,8 @@ class AccountsGrpcServiceTest extends SimpleBaseGrpcTest<AccountsGrpcService, Ac
|
||||
return new AccountsGrpcService(accountsManager,
|
||||
rateLimiters,
|
||||
usernameHashZkProofVerifier,
|
||||
registrationRecoveryPasswordsManager);
|
||||
registrationRecoveryPasswordsManager,
|
||||
testClock);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -765,4 +774,41 @@ class AccountsGrpcServiceTest extends SimpleBaseGrpcTest<AccountsGrpcService, Ac
|
||||
verify(accountsManager, never()).update(any(UUID.class), any());
|
||||
verify(account, never()).setZkCredentialKey(any());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(booleans = {true, false})
|
||||
void getEntitlements(final boolean expired) {
|
||||
final Account account = mock(Account.class);
|
||||
final Instant expiration = expired
|
||||
? testClock.instant().minus(Duration.ofDays(1))
|
||||
: testClock.instant().plus(Duration.ofMillis(1));
|
||||
final AccountBadge badge1 = new AccountBadge("badge1", expiration, true);
|
||||
final AccountBadge badge2 = new AccountBadge("badge2", expiration, true);
|
||||
|
||||
when(account.getBackupVoucher()).thenReturn(new Account.BackupVoucher(100, expiration));
|
||||
when(account.getBadges()).thenReturn(List.of(badge1, badge2));
|
||||
when(account.getUuid()).thenReturn(AUTHENTICATED_ACI);
|
||||
when(accountsManager.getByAccountIdentifier(AUTHENTICATED_ACI)).thenReturn(Optional.of(account));
|
||||
|
||||
final GetEntitlementsResponse entitlements = authenticatedServiceStub()
|
||||
.getEntitlements(GetEntitlementsRequest.newBuilder().build());
|
||||
|
||||
if (expired) {
|
||||
assertThat(entitlements.getBadgesCount()).isEqualTo(0);
|
||||
assertThat(entitlements.hasBackup()).isFalse();
|
||||
} else {
|
||||
assertThat(entitlements.getBadges(0)).isEqualTo(toBadgeEntitlement(badge1));
|
||||
assertThat(entitlements.getBadges(1)).isEqualTo(toBadgeEntitlement(badge2));
|
||||
assertThat(entitlements.getBackup().getLevel()).isEqualTo(100);
|
||||
assertThat(entitlements.getBackup().getExpirationEpochSeconds()).isEqualTo(expiration.getEpochSecond());
|
||||
}
|
||||
}
|
||||
|
||||
private static GetEntitlementsResponse.BadgeEntitlement toBadgeEntitlement(AccountBadge badge) {
|
||||
return GetEntitlementsResponse.BadgeEntitlement.newBuilder()
|
||||
.setExpirationEpochSeconds(badge.expiration().getEpochSecond())
|
||||
.setBadgeId(badge.id())
|
||||
.setVisible(badge.visible())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -219,7 +219,7 @@ public class ProfileAnonymousGrpcServiceTest extends SimpleBaseGrpcTest<ProfileA
|
||||
.setUnidentifiedAccess(ByteString.copyFrom(unidentifiedAccessChecksum))
|
||||
.setUnrestrictedUnidentifiedAccess(false)
|
||||
.addCapabilities(org.signal.chat.common.DeviceCapability.DEVICE_CAPABILITY_SPARSE_POST_QUANTUM_RATCHET)
|
||||
.addAllBadges(ProfileGrpcHelper.buildBadges(badges))
|
||||
.addAllBadges(badges.stream().map(BadgeGrpcHelper::toGrpcBadge).toList())
|
||||
.build()
|
||||
)
|
||||
.build();
|
||||
@@ -273,7 +273,7 @@ public class ProfileAnonymousGrpcServiceTest extends SimpleBaseGrpcTest<ProfileA
|
||||
.setIdentityKey(ByteString.copyFrom(identityKey.serialize()))
|
||||
.setUnrestrictedUnidentifiedAccess(false)
|
||||
.addAllCapabilities(ProfileGrpcHelper.buildAccountCapabilities(account))
|
||||
.addAllBadges(ProfileGrpcHelper.buildBadges(badges))
|
||||
.addAllBadges(badges.stream().map(BadgeGrpcHelper::toGrpcBadge).toList())
|
||||
.build();
|
||||
|
||||
verify(accountsManager).getByServiceIdentifier(serviceIdentifier);
|
||||
|
||||
+1
-1
@@ -655,7 +655,7 @@ public class ProfileGrpcServiceTest extends SimpleBaseGrpcTest<ProfileGrpcServic
|
||||
.setIdentityKey(ByteString.copyFrom(identityKey.serialize()))
|
||||
.setUnidentifiedAccess(ByteString.copyFrom(unidentifiedAccessChecksum))
|
||||
.setUnrestrictedUnidentifiedAccess(true)
|
||||
.addAllBadges(ProfileGrpcHelper.buildBadges(badges))
|
||||
.addAllBadges(badges.stream().map(BadgeGrpcHelper::toGrpcBadge).toList())
|
||||
.build();
|
||||
|
||||
final GetUnversionedProfileResult expectedResponse;
|
||||
|
||||
Reference in New Issue
Block a user