Search in sources :

Example 1 with GroupCandidate

use of org.whispersystems.signalservice.api.groupsv2.GroupCandidate in project Signal-Android by signalapp.

the class GroupCandidateHelper method recipientIdToCandidate.

/**
 * Given a recipient will create a {@link GroupCandidate} which may or may not have a profile key credential.
 * <p>
 * It will try to find missing profile key credentials from the server and persist locally.
 */
@WorkerThread
@NonNull
public GroupCandidate recipientIdToCandidate(@NonNull RecipientId recipientId) throws IOException {
    final Recipient recipient = Recipient.resolved(recipientId);
    ServiceId serviceId = recipient.getServiceId().orNull();
    if (serviceId == null) {
        throw new AssertionError("Non UUID members should have need detected by now");
    }
    Optional<ProfileKeyCredential> profileKeyCredential = Optional.fromNullable(recipient.getProfileKeyCredential());
    GroupCandidate candidate = new GroupCandidate(serviceId.uuid(), profileKeyCredential);
    if (!candidate.hasProfileKeyCredential()) {
        ProfileKey profileKey = ProfileKeyUtil.profileKeyOrNull(recipient.getProfileKey());
        if (profileKey != null) {
            Log.i(TAG, String.format("No profile key credential on recipient %s, fetching", recipient.getId()));
            Optional<ProfileKeyCredential> profileKeyCredentialOptional = signalServiceAccountManager.resolveProfileKeyCredential(serviceId, profileKey, Locale.getDefault());
            if (profileKeyCredentialOptional.isPresent()) {
                boolean updatedProfileKey = recipientDatabase.setProfileKeyCredential(recipient.getId(), profileKey, profileKeyCredentialOptional.get());
                if (!updatedProfileKey) {
                    Log.w(TAG, String.format("Failed to update the profile key credential on recipient %s", recipient.getId()));
                } else {
                    Log.i(TAG, String.format("Got new profile key credential for recipient %s", recipient.getId()));
                    candidate = candidate.withProfileKeyCredential(profileKeyCredentialOptional.get());
                }
            }
        }
    }
    return candidate;
}
Also used : ProfileKeyCredential(org.signal.zkgroup.profiles.ProfileKeyCredential) GroupCandidate(org.whispersystems.signalservice.api.groupsv2.GroupCandidate) Recipient(org.thoughtcrime.securesms.recipients.Recipient) ProfileKey(org.signal.zkgroup.profiles.ProfileKey) ServiceId(org.whispersystems.signalservice.api.push.ServiceId) WorkerThread(androidx.annotation.WorkerThread) NonNull(androidx.annotation.NonNull)

Example 2 with GroupCandidate

use of org.whispersystems.signalservice.api.groupsv2.GroupCandidate in project Signal-Android by WhisperSystems.

the class GroupManagerV2 method createGroupOnServer.

@WorkerThread
@NonNull
private DecryptedGroup createGroupOnServer(@NonNull GroupSecretParams groupSecretParams, @Nullable String name, @Nullable byte[] avatar, @NonNull Collection<RecipientId> members, @NonNull Member.Role memberRole, int disappearingMessageTimerSeconds) throws GroupChangeFailedException, IOException, MembershipNotSuitableForV2Exception, GroupAlreadyExistsException {
    if (!GroupsV2CapabilityChecker.allAndSelfHaveUuidAndSupportGroupsV2(members)) {
        throw new MembershipNotSuitableForV2Exception("At least one potential new member does not support GV2 capability or we don't have their UUID");
    }
    GroupCandidate self = groupCandidateHelper.recipientIdToCandidate(Recipient.self().getId());
    Set<GroupCandidate> candidates = new HashSet<>(groupCandidateHelper.recipientIdsToCandidates(members));
    if (SignalStore.internalValues().gv2ForceInvites()) {
        Log.w(TAG, "Forcing GV2 invites due to internal setting");
        candidates = GroupCandidate.withoutProfileKeyCredentials(candidates);
    }
    if (!self.hasProfileKeyCredential()) {
        Log.w(TAG, "Cannot create a V2 group as self does not have a versioned profile");
        throw new MembershipNotSuitableForV2Exception("Cannot create a V2 group as self does not have a versioned profile");
    }
    GroupsV2Operations.NewGroup newGroup = groupsV2Operations.createNewGroup(groupSecretParams, name, Optional.fromNullable(avatar), self, candidates, memberRole, disappearingMessageTimerSeconds);
    try {
        groupsV2Api.putNewGroup(newGroup, authorization.getAuthorizationForToday(selfAci, groupSecretParams));
        DecryptedGroup decryptedGroup = groupsV2Api.getGroup(groupSecretParams, ApplicationDependencies.getGroupsV2Authorization().getAuthorizationForToday(selfAci, groupSecretParams));
        if (decryptedGroup == null) {
            throw new GroupChangeFailedException();
        }
        return decryptedGroup;
    } catch (VerificationFailedException | InvalidGroupStateException e) {
        throw new GroupChangeFailedException(e);
    } catch (GroupExistsException e) {
        throw new GroupAlreadyExistsException(e);
    }
}
Also used : GroupExistsException(org.whispersystems.signalservice.internal.push.exceptions.GroupExistsException) GroupCandidate(org.whispersystems.signalservice.api.groupsv2.GroupCandidate) VerificationFailedException(org.signal.zkgroup.VerificationFailedException) InvalidGroupStateException(org.whispersystems.signalservice.api.groupsv2.InvalidGroupStateException) GroupsV2Operations(org.whispersystems.signalservice.api.groupsv2.GroupsV2Operations) DecryptedGroup(org.signal.storageservice.protos.groups.local.DecryptedGroup) HashSet(java.util.HashSet) WorkerThread(androidx.annotation.WorkerThread) NonNull(androidx.annotation.NonNull)

Example 3 with GroupCandidate

use of org.whispersystems.signalservice.api.groupsv2.GroupCandidate in project Signal-Android by WhisperSystems.

the class GroupCandidateHelper method recipientIdToCandidate.

/**
 * Given a recipient will create a {@link GroupCandidate} which may or may not have a profile key credential.
 * <p>
 * It will try to find missing profile key credentials from the server and persist locally.
 */
@WorkerThread
@NonNull
public GroupCandidate recipientIdToCandidate(@NonNull RecipientId recipientId) throws IOException {
    final Recipient recipient = Recipient.resolved(recipientId);
    ServiceId serviceId = recipient.getServiceId().orNull();
    if (serviceId == null) {
        throw new AssertionError("Non UUID members should have need detected by now");
    }
    Optional<ProfileKeyCredential> profileKeyCredential = Optional.fromNullable(recipient.getProfileKeyCredential());
    GroupCandidate candidate = new GroupCandidate(serviceId.uuid(), profileKeyCredential);
    if (!candidate.hasProfileKeyCredential()) {
        ProfileKey profileKey = ProfileKeyUtil.profileKeyOrNull(recipient.getProfileKey());
        if (profileKey != null) {
            Log.i(TAG, String.format("No profile key credential on recipient %s, fetching", recipient.getId()));
            Optional<ProfileKeyCredential> profileKeyCredentialOptional = signalServiceAccountManager.resolveProfileKeyCredential(serviceId, profileKey, Locale.getDefault());
            if (profileKeyCredentialOptional.isPresent()) {
                boolean updatedProfileKey = recipientDatabase.setProfileKeyCredential(recipient.getId(), profileKey, profileKeyCredentialOptional.get());
                if (!updatedProfileKey) {
                    Log.w(TAG, String.format("Failed to update the profile key credential on recipient %s", recipient.getId()));
                } else {
                    Log.i(TAG, String.format("Got new profile key credential for recipient %s", recipient.getId()));
                    candidate = candidate.withProfileKeyCredential(profileKeyCredentialOptional.get());
                }
            }
        }
    }
    return candidate;
}
Also used : ProfileKeyCredential(org.signal.zkgroup.profiles.ProfileKeyCredential) GroupCandidate(org.whispersystems.signalservice.api.groupsv2.GroupCandidate) Recipient(org.thoughtcrime.securesms.recipients.Recipient) ProfileKey(org.signal.zkgroup.profiles.ProfileKey) ServiceId(org.whispersystems.signalservice.api.push.ServiceId) WorkerThread(androidx.annotation.WorkerThread) NonNull(androidx.annotation.NonNull)

Example 4 with GroupCandidate

use of org.whispersystems.signalservice.api.groupsv2.GroupCandidate in project Signal-Android by signalapp.

the class GroupManagerV2 method createGroupOnServer.

@WorkerThread
@NonNull
private DecryptedGroup createGroupOnServer(@NonNull GroupSecretParams groupSecretParams, @Nullable String name, @Nullable byte[] avatar, @NonNull Collection<RecipientId> members, @NonNull Member.Role memberRole, int disappearingMessageTimerSeconds) throws GroupChangeFailedException, IOException, MembershipNotSuitableForV2Exception, GroupAlreadyExistsException {
    if (!GroupsV2CapabilityChecker.allAndSelfHaveUuidAndSupportGroupsV2(members)) {
        throw new MembershipNotSuitableForV2Exception("At least one potential new member does not support GV2 capability or we don't have their UUID");
    }
    GroupCandidate self = groupCandidateHelper.recipientIdToCandidate(Recipient.self().getId());
    Set<GroupCandidate> candidates = new HashSet<>(groupCandidateHelper.recipientIdsToCandidates(members));
    if (SignalStore.internalValues().gv2ForceInvites()) {
        Log.w(TAG, "Forcing GV2 invites due to internal setting");
        candidates = GroupCandidate.withoutProfileKeyCredentials(candidates);
    }
    if (!self.hasProfileKeyCredential()) {
        Log.w(TAG, "Cannot create a V2 group as self does not have a versioned profile");
        throw new MembershipNotSuitableForV2Exception("Cannot create a V2 group as self does not have a versioned profile");
    }
    GroupsV2Operations.NewGroup newGroup = groupsV2Operations.createNewGroup(groupSecretParams, name, Optional.fromNullable(avatar), self, candidates, memberRole, disappearingMessageTimerSeconds);
    try {
        groupsV2Api.putNewGroup(newGroup, authorization.getAuthorizationForToday(selfAci, groupSecretParams));
        DecryptedGroup decryptedGroup = groupsV2Api.getGroup(groupSecretParams, ApplicationDependencies.getGroupsV2Authorization().getAuthorizationForToday(selfAci, groupSecretParams));
        if (decryptedGroup == null) {
            throw new GroupChangeFailedException();
        }
        return decryptedGroup;
    } catch (VerificationFailedException | InvalidGroupStateException e) {
        throw new GroupChangeFailedException(e);
    } catch (GroupExistsException e) {
        throw new GroupAlreadyExistsException(e);
    }
}
Also used : GroupExistsException(org.whispersystems.signalservice.internal.push.exceptions.GroupExistsException) GroupCandidate(org.whispersystems.signalservice.api.groupsv2.GroupCandidate) VerificationFailedException(org.signal.zkgroup.VerificationFailedException) InvalidGroupStateException(org.whispersystems.signalservice.api.groupsv2.InvalidGroupStateException) GroupsV2Operations(org.whispersystems.signalservice.api.groupsv2.GroupsV2Operations) DecryptedGroup(org.signal.storageservice.protos.groups.local.DecryptedGroup) HashSet(java.util.HashSet) WorkerThread(androidx.annotation.WorkerThread) NonNull(androidx.annotation.NonNull)

Aggregations

NonNull (androidx.annotation.NonNull)4 WorkerThread (androidx.annotation.WorkerThread)4 GroupCandidate (org.whispersystems.signalservice.api.groupsv2.GroupCandidate)4 HashSet (java.util.HashSet)2 DecryptedGroup (org.signal.storageservice.protos.groups.local.DecryptedGroup)2 VerificationFailedException (org.signal.zkgroup.VerificationFailedException)2 ProfileKey (org.signal.zkgroup.profiles.ProfileKey)2 ProfileKeyCredential (org.signal.zkgroup.profiles.ProfileKeyCredential)2 Recipient (org.thoughtcrime.securesms.recipients.Recipient)2 GroupsV2Operations (org.whispersystems.signalservice.api.groupsv2.GroupsV2Operations)2 InvalidGroupStateException (org.whispersystems.signalservice.api.groupsv2.InvalidGroupStateException)2 ServiceId (org.whispersystems.signalservice.api.push.ServiceId)2 GroupExistsException (org.whispersystems.signalservice.internal.push.exceptions.GroupExistsException)2