kopia lustrzana https://github.com/ryukoposting/Signal-Android
Fix bug preventing adding and inviting by phone number.
rodzic
798f3a7b0e
commit
9d28caac00
|
@ -18,11 +18,10 @@ import org.thoughtcrime.securesms.database.model.IdentityRecord
|
|||
import org.thoughtcrime.securesms.database.model.StoryViewState
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
|
||||
import org.thoughtcrime.securesms.groups.GroupId
|
||||
import org.thoughtcrime.securesms.groups.GroupManager
|
||||
import org.thoughtcrime.securesms.groups.GroupProtoUtil
|
||||
import org.thoughtcrime.securesms.groups.LiveGroup
|
||||
import org.thoughtcrime.securesms.groups.ui.GroupChangeFailureReason
|
||||
import org.thoughtcrime.securesms.jobs.RetrieveProfileJob
|
||||
import org.thoughtcrime.securesms.groups.v2.GroupAddMembersResult
|
||||
import org.thoughtcrime.securesms.groups.v2.GroupManagementRepository
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
|
@ -30,12 +29,12 @@ import org.thoughtcrime.securesms.recipients.RecipientUtil
|
|||
import org.thoughtcrime.securesms.util.FeatureFlags
|
||||
import java.io.IOException
|
||||
import java.util.Optional
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
private val TAG = Log.tag(ConversationSettingsRepository::class.java)
|
||||
|
||||
class ConversationSettingsRepository(
|
||||
private val context: Context
|
||||
private val context: Context,
|
||||
private val groupManagementRepository: GroupManagementRepository = GroupManagementRepository(context)
|
||||
) {
|
||||
|
||||
@WorkerThread
|
||||
|
@ -152,36 +151,7 @@ class ConversationSettingsRepository(
|
|||
}
|
||||
|
||||
fun addMembers(groupId: GroupId, selected: List<RecipientId>, consumer: (GroupAddMembersResult) -> Unit) {
|
||||
SignalExecutors.BOUNDED.execute {
|
||||
val record: GroupDatabase.GroupRecord = SignalDatabase.groups.getGroup(groupId).get()
|
||||
|
||||
if (record.isAnnouncementGroup) {
|
||||
val needsResolve = selected
|
||||
.map { Recipient.resolved(it) }
|
||||
.filter { it.announcementGroupCapability != Recipient.Capability.SUPPORTED && !it.isSelf }
|
||||
.map { it.id }
|
||||
.toSet()
|
||||
|
||||
ApplicationDependencies.getJobManager().runSynchronously(RetrieveProfileJob(needsResolve), TimeUnit.SECONDS.toMillis(10))
|
||||
|
||||
val updatedWithCapabilities = needsResolve.map { Recipient.resolved(it) }
|
||||
|
||||
if (updatedWithCapabilities.any { it.announcementGroupCapability != Recipient.Capability.SUPPORTED }) {
|
||||
consumer(GroupAddMembersResult.Failure(GroupChangeFailureReason.NOT_ANNOUNCEMENT_CAPABLE))
|
||||
return@execute
|
||||
}
|
||||
}
|
||||
|
||||
consumer(
|
||||
try {
|
||||
val groupActionResult = GroupManager.addMembers(context, groupId.requirePush(), selected)
|
||||
GroupAddMembersResult.Success(groupActionResult.addedMemberCount, Recipient.resolvedList(groupActionResult.invitedMembers))
|
||||
} catch (e: Exception) {
|
||||
Log.d(TAG, "Failure to add member", e)
|
||||
GroupAddMembersResult.Failure(GroupChangeFailureReason.fromException(e))
|
||||
}
|
||||
)
|
||||
}
|
||||
groupManagementRepository.addMembers(groupId, selected, consumer)
|
||||
}
|
||||
|
||||
fun setMuteUntil(groupId: GroupId, until: Long) {
|
||||
|
|
|
@ -17,6 +17,7 @@ import org.thoughtcrime.securesms.database.RecipientDatabase
|
|||
import org.thoughtcrime.securesms.database.model.StoryViewState
|
||||
import org.thoughtcrime.securesms.groups.GroupId
|
||||
import org.thoughtcrime.securesms.groups.LiveGroup
|
||||
import org.thoughtcrime.securesms.groups.v2.GroupAddMembersResult
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import org.thoughtcrime.securesms.recipients.RecipientUtil
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
package org.thoughtcrime.securesms.components.settings.conversation
|
||||
|
||||
import org.thoughtcrime.securesms.groups.ui.GroupChangeFailureReason
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
|
||||
sealed class GroupAddMembersResult {
|
||||
class Success(
|
||||
val numberOfMembersAdded: Int,
|
||||
val newMembersInvited: List<Recipient>
|
||||
) : GroupAddMembersResult()
|
||||
|
||||
class Failure(
|
||||
val reason: GroupChangeFailureReason
|
||||
) : GroupAddMembersResult()
|
||||
}
|
|
@ -119,6 +119,7 @@ import org.thoughtcrime.securesms.groups.ui.GroupErrors;
|
|||
import org.thoughtcrime.securesms.groups.ui.invitesandrequests.invite.GroupLinkInviteFriendsBottomSheetDialogFragment;
|
||||
import org.thoughtcrime.securesms.groups.ui.managegroup.dialogs.GroupDescriptionDialog;
|
||||
import org.thoughtcrime.securesms.groups.ui.migration.GroupsV1MigrationInfoBottomSheetDialogFragment;
|
||||
import org.thoughtcrime.securesms.groups.v2.GroupBlockJoinRequestResult;
|
||||
import org.thoughtcrime.securesms.groups.v2.GroupDescriptionUtil;
|
||||
import org.thoughtcrime.securesms.groups.v2.GroupManagementRepository;
|
||||
import org.thoughtcrime.securesms.jobs.DirectoryRefreshJob;
|
||||
|
@ -1930,8 +1931,8 @@ public class ConversationFragment extends LoggingFragment implements Multiselect
|
|||
lifecycleDisposable.add(
|
||||
groupViewModel.blockJoinRequests(ConversationFragment.this.recipient.get(), recipient)
|
||||
.subscribe(result -> {
|
||||
if (result instanceof GroupManagementRepository.GroupManagementResult.Failure) {
|
||||
int failureReason = GroupErrors.getUserDisplayMessage(((GroupManagementRepository.GroupManagementResult.Failure) result).getReason());
|
||||
if (result.isFailure()) {
|
||||
int failureReason = GroupErrors.getUserDisplayMessage(((GroupBlockJoinRequestResult.Failure) result).getReason());
|
||||
Toast.makeText(requireContext(), failureReason, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
})
|
||||
|
|
|
@ -26,8 +26,8 @@ import org.thoughtcrime.securesms.groups.GroupManager;
|
|||
import org.thoughtcrime.securesms.groups.GroupsV1MigrationUtil;
|
||||
import org.thoughtcrime.securesms.groups.ui.GroupChangeFailureReason;
|
||||
import org.thoughtcrime.securesms.groups.ui.invitesandrequests.invite.GroupLinkInviteFriendsBottomSheetDialogFragment;
|
||||
import org.thoughtcrime.securesms.groups.v2.GroupBlockJoinRequestResult;
|
||||
import org.thoughtcrime.securesms.groups.v2.GroupManagementRepository;
|
||||
import org.thoughtcrime.securesms.groups.v2.GroupManagementRepository.GroupManagementResult;
|
||||
import org.thoughtcrime.securesms.profiles.spoofing.ReviewRecipient;
|
||||
import org.thoughtcrime.securesms.profiles.spoofing.ReviewUtil;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
|
@ -220,7 +220,7 @@ final class ConversationGroupViewModel extends ViewModel {
|
|||
GroupLinkInviteFriendsBottomSheetDialogFragment.show(supportFragmentManager, groupId);
|
||||
}
|
||||
|
||||
public Single<GroupManagementResult> blockJoinRequests(@NonNull Recipient groupRecipient, @NonNull Recipient recipient) {
|
||||
public Single<GroupBlockJoinRequestResult> blockJoinRequests(@NonNull Recipient groupRecipient, @NonNull Recipient recipient) {
|
||||
return groupManagementRepository.blockJoinRequests(groupRecipient.requireGroupId().requireV2(), recipient)
|
||||
.observeOn(AndroidSchedulers.mainThread());
|
||||
}
|
||||
|
|
|
@ -1350,6 +1350,10 @@ private static final String[] GROUP_PROJECTION = {
|
|||
|
||||
return recipients;
|
||||
}
|
||||
|
||||
public @NonNull Set<UUID> getBannedMembers() {
|
||||
return DecryptedGroupUtil.bannedMembersToUuidSet(getDecryptedGroup().getBannedMembersList());
|
||||
}
|
||||
}
|
||||
|
||||
public @NonNull List<GroupId> getGroupsToDisplayAsStories() throws BadGroupIdException {
|
||||
|
|
|
@ -379,8 +379,10 @@ public final class GroupManager {
|
|||
throws GroupChangeFailedException, GroupInsufficientRightsException, IOException, GroupNotAMemberException, GroupChangeBusyException, MembershipNotSuitableForV2Exception
|
||||
{
|
||||
if (groupId.isV2()) {
|
||||
GroupDatabase.GroupRecord groupRecord = SignalDatabase.groups().requireGroup(groupId);
|
||||
|
||||
try (GroupManagerV2.GroupEditor editor = new GroupManagerV2(context).edit(groupId.requireV2())) {
|
||||
return editor.addMembers(newMembers);
|
||||
return editor.addMembers(newMembers, groupRecord.requireV2GroupProperties().getBannedMembers());
|
||||
}
|
||||
} else {
|
||||
GroupDatabase.GroupRecord groupRecord = SignalDatabase.groups().requireGroup(groupId);
|
||||
|
|
|
@ -326,7 +326,7 @@ final class GroupManagerV2 {
|
|||
}
|
||||
|
||||
@WorkerThread
|
||||
@NonNull GroupManager.GroupActionResult addMembers(@NonNull Collection<RecipientId> newMembers)
|
||||
@NonNull GroupManager.GroupActionResult addMembers(@NonNull Collection<RecipientId> newMembers, @NonNull Set<UUID> bannedMembers)
|
||||
throws GroupChangeFailedException, GroupInsufficientRightsException, IOException, GroupNotAMemberException, MembershipNotSuitableForV2Exception
|
||||
{
|
||||
if (!GroupsV2CapabilityChecker.allHaveServiceId(newMembers)) {
|
||||
|
@ -339,7 +339,7 @@ final class GroupManagerV2 {
|
|||
groupCandidates = GroupCandidate.withoutProfileKeyCredentials(groupCandidates);
|
||||
}
|
||||
|
||||
return commitChangeWithConflictResolution(groupOperations.createModifyGroupMembershipChange(groupCandidates, selfAci.uuid()));
|
||||
return commitChangeWithConflictResolution(groupOperations.createModifyGroupMembershipChange(groupCandidates, bannedMembers, selfAci.uuid()));
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
|
|
|
@ -1,50 +0,0 @@
|
|||
package org.thoughtcrime.securesms.groups.ui.addtogroup;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.signal.core.util.concurrent.SignalExecutors;
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
import org.thoughtcrime.securesms.groups.GroupChangeException;
|
||||
import org.thoughtcrime.securesms.groups.GroupId;
|
||||
import org.thoughtcrime.securesms.groups.GroupManager;
|
||||
import org.thoughtcrime.securesms.groups.MembershipNotSuitableForV2Exception;
|
||||
import org.thoughtcrime.securesms.groups.ui.GroupChangeErrorCallback;
|
||||
import org.thoughtcrime.securesms.groups.ui.GroupChangeFailureReason;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
|
||||
final class AddToGroupRepository {
|
||||
|
||||
private static final String TAG = Log.tag(AddToGroupRepository.class);
|
||||
|
||||
private final Context context;
|
||||
|
||||
AddToGroupRepository() {
|
||||
this.context = ApplicationDependencies.getApplication();
|
||||
}
|
||||
|
||||
public void add(@NonNull RecipientId recipientId,
|
||||
@NonNull Recipient groupRecipient,
|
||||
@NonNull GroupChangeErrorCallback error,
|
||||
@NonNull Runnable success)
|
||||
{
|
||||
SignalExecutors.UNBOUNDED.execute(() -> {
|
||||
try {
|
||||
GroupId.Push pushGroupId = groupRecipient.requireGroupId().requirePush();
|
||||
|
||||
GroupManager.addMembers(context, pushGroupId, Collections.singletonList(recipientId));
|
||||
|
||||
success.run();
|
||||
} catch (GroupChangeException | MembershipNotSuitableForV2Exception | IOException e) {
|
||||
Log.w(TAG, e);
|
||||
error.onError(GroupChangeFailureReason.fromException(e));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -9,25 +9,31 @@ import androidx.lifecycle.ViewModelProvider;
|
|||
import org.signal.core.util.concurrent.SignalExecutors;
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
import org.thoughtcrime.securesms.groups.ui.GroupChangeFailureReason;
|
||||
import org.thoughtcrime.securesms.groups.ui.GroupErrors;
|
||||
import org.thoughtcrime.securesms.groups.v2.GroupAddMembersResult;
|
||||
import org.thoughtcrime.securesms.groups.v2.GroupManagementRepository;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||
import org.thoughtcrime.securesms.util.SingleLiveEvent;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import kotlin.Unit;
|
||||
|
||||
public final class AddToGroupViewModel extends ViewModel {
|
||||
|
||||
private final Application context;
|
||||
private final AddToGroupRepository repository;
|
||||
private final RecipientId recipientId;
|
||||
private final Application context;
|
||||
private final GroupManagementRepository repository;
|
||||
private final RecipientId recipientId;
|
||||
private final SingleLiveEvent<Event> events = new SingleLiveEvent<>();
|
||||
|
||||
private AddToGroupViewModel(@NonNull RecipientId recipientId) {
|
||||
this.context = ApplicationDependencies.getApplication();
|
||||
this.recipientId = recipientId;
|
||||
this.repository = new AddToGroupRepository();
|
||||
this.repository = new GroupManagementRepository();
|
||||
}
|
||||
|
||||
public SingleLiveEvent<Event> getEvents() {
|
||||
|
@ -58,13 +64,15 @@ public final class AddToGroupViewModel extends ViewModel {
|
|||
}
|
||||
|
||||
void onAddToGroupsConfirmed(@NonNull Event.AddToSingleGroupConfirmationEvent event) {
|
||||
repository.add(recipientId,
|
||||
event.groupRecipient,
|
||||
error -> events.postValue(new Event.ToastEvent(context.getResources().getString(GroupErrors.getUserDisplayMessage(error)))),
|
||||
() -> {
|
||||
events.postValue(new Event.ToastEvent(context.getResources().getString(R.string.AddToGroupActivity_s_added_to_s, event.recipientName, event.groupName)));
|
||||
events.postValue(new Event.CloseEvent());
|
||||
});
|
||||
repository.addMembers(event.groupRecipient, Collections.singletonList(recipientId), result -> {
|
||||
if (result.isFailure()) {
|
||||
GroupChangeFailureReason reason = ((GroupAddMembersResult.Failure) result).getReason();
|
||||
events.postValue(new Event.ToastEvent(context.getResources().getString(GroupErrors.getUserDisplayMessage(reason))));
|
||||
} else {
|
||||
events.postValue(new Event.ToastEvent(context.getResources().getString(R.string.AddToGroupActivity_s_added_to_s, event.recipientName, event.groupName)));
|
||||
events.postValue(new Event.CloseEvent());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static abstract class Event {
|
||||
|
|
|
@ -1,41 +1,102 @@
|
|||
package org.thoughtcrime.securesms.groups.v2
|
||||
|
||||
import android.content.Context
|
||||
import androidx.core.util.Consumer
|
||||
import io.reactivex.rxjava3.core.Single
|
||||
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||
import org.signal.core.util.concurrent.SignalExecutors
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.thoughtcrime.securesms.contacts.sync.DirectoryHelper
|
||||
import org.thoughtcrime.securesms.database.GroupDatabase
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
|
||||
import org.thoughtcrime.securesms.groups.GroupChangeException
|
||||
import org.thoughtcrime.securesms.groups.GroupId
|
||||
import org.thoughtcrime.securesms.groups.GroupManager
|
||||
import org.thoughtcrime.securesms.groups.ui.GroupChangeFailureReason
|
||||
import org.thoughtcrime.securesms.jobs.RetrieveProfileJob
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import java.io.IOException
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
private val TAG: String = Log.tag(GroupManagementRepository::class.java)
|
||||
|
||||
/**
|
||||
* Single source repository for managing groups.
|
||||
* Single source repository for managing GV2 groups.
|
||||
*/
|
||||
class GroupManagementRepository @JvmOverloads constructor(private val context: Context = ApplicationDependencies.getApplication()) {
|
||||
|
||||
fun blockJoinRequests(groupId: GroupId.V2, recipient: Recipient): Single<GroupManagementResult> {
|
||||
fun addMembers(groupRecipient: Recipient, selected: List<RecipientId>, consumer: Consumer<GroupAddMembersResult>) {
|
||||
addMembers(null, groupRecipient, selected, consumer)
|
||||
}
|
||||
|
||||
fun addMembers(groupId: GroupId, selected: List<RecipientId>, consumer: Consumer<GroupAddMembersResult>) {
|
||||
addMembers(groupId, null, selected, consumer)
|
||||
}
|
||||
|
||||
private fun addMembers(potentialGroupId: GroupId?, potentialGroupRecipient: Recipient?, selected: List<RecipientId>, consumer: Consumer<GroupAddMembersResult>) {
|
||||
SignalExecutors.UNBOUNDED.execute {
|
||||
val groupId: GroupId.Push = potentialGroupId?.requirePush() ?: potentialGroupRecipient!!.requireGroupId().requirePush()
|
||||
val record: GroupDatabase.GroupRecord = SignalDatabase.groups.getGroup(groupId).get()
|
||||
|
||||
val recipients = selected.map(Recipient::resolved)
|
||||
.filterNot { it.hasServiceId() && it.isRegistered }
|
||||
.toList()
|
||||
|
||||
try {
|
||||
DirectoryHelper.refreshDirectoryFor(context, recipients, false)
|
||||
recipients.forEach { Recipient.live(it.id).refresh() }
|
||||
} catch (e: IOException) {
|
||||
consumer.accept(GroupAddMembersResult.Failure(GroupChangeFailureReason.NETWORK))
|
||||
}
|
||||
|
||||
if (record.isAnnouncementGroup) {
|
||||
val needsResolve = selected
|
||||
.map { Recipient.resolved(it) }
|
||||
.filter { it.announcementGroupCapability != Recipient.Capability.SUPPORTED && !it.isSelf }
|
||||
.map { it.id }
|
||||
.toSet()
|
||||
|
||||
ApplicationDependencies.getJobManager().runSynchronously(RetrieveProfileJob(needsResolve), TimeUnit.SECONDS.toMillis(10))
|
||||
|
||||
val updatedWithCapabilities = needsResolve.map { Recipient.resolved(it) }
|
||||
|
||||
if (updatedWithCapabilities.any { it.announcementGroupCapability != Recipient.Capability.SUPPORTED }) {
|
||||
consumer.accept(GroupAddMembersResult.Failure(GroupChangeFailureReason.NOT_ANNOUNCEMENT_CAPABLE))
|
||||
return@execute
|
||||
}
|
||||
}
|
||||
|
||||
consumer.accept(
|
||||
try {
|
||||
val toAdd = selected.filter { Recipient.resolved(it).isRegistered }
|
||||
if (toAdd.isNotEmpty()) {
|
||||
val groupActionResult = GroupManager.addMembers(context, groupId, toAdd)
|
||||
GroupAddMembersResult.Success(groupActionResult.addedMemberCount, Recipient.resolvedList(groupActionResult.invitedMembers))
|
||||
} else {
|
||||
GroupAddMembersResult.Failure(GroupChangeFailureReason.NOT_GV2_CAPABLE)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.d(TAG, "Failure to add member", e)
|
||||
GroupAddMembersResult.Failure(GroupChangeFailureReason.fromException(e))
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun blockJoinRequests(groupId: GroupId.V2, recipient: Recipient): Single<GroupBlockJoinRequestResult> {
|
||||
return Single.fromCallable {
|
||||
try {
|
||||
GroupManager.ban(context, groupId, recipient.id)
|
||||
GroupManagementResult.Success
|
||||
GroupBlockJoinRequestResult.Success
|
||||
} catch (e: GroupChangeException) {
|
||||
Log.w(TAG, e)
|
||||
GroupManagementResult.Failure(GroupChangeFailureReason.fromException(e))
|
||||
GroupBlockJoinRequestResult.Failure(GroupChangeFailureReason.fromException(e))
|
||||
} catch (e: IOException) {
|
||||
Log.w(TAG, e)
|
||||
GroupManagementResult.Failure(GroupChangeFailureReason.fromException(e))
|
||||
GroupBlockJoinRequestResult.Failure(GroupChangeFailureReason.fromException(e))
|
||||
}
|
||||
}.subscribeOn(Schedulers.io())
|
||||
}
|
||||
|
||||
sealed class GroupManagementResult {
|
||||
object Success : GroupManagementResult()
|
||||
data class Failure(val reason: GroupChangeFailureReason) : GroupManagementResult()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
package org.thoughtcrime.securesms.groups.v2
|
||||
|
||||
import org.thoughtcrime.securesms.groups.ui.GroupChangeFailureReason
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
|
||||
sealed class GroupBlockJoinRequestResult {
|
||||
object Success : GroupBlockJoinRequestResult()
|
||||
class Failure(val reason: GroupChangeFailureReason) : GroupBlockJoinRequestResult()
|
||||
|
||||
fun isFailure() = this is Failure
|
||||
}
|
||||
|
||||
sealed class GroupAddMembersResult {
|
||||
class Success(val numberOfMembersAdded: Int, val newMembersInvited: List<Recipient>) : GroupAddMembersResult()
|
||||
class Failure(val reason: GroupChangeFailureReason) : GroupAddMembersResult()
|
||||
|
||||
fun isFailure() = this is Failure
|
||||
}
|
|
@ -132,6 +132,20 @@ public final class DecryptedGroupUtil {
|
|||
return uuidList;
|
||||
}
|
||||
|
||||
public static Set<UUID> bannedMembersToUuidSet(Collection<DecryptedBannedMember> membersList) {
|
||||
Set<UUID> uuidSet = new HashSet<>(membersList.size());
|
||||
|
||||
for (DecryptedBannedMember member : membersList) {
|
||||
UUID uuid = toUuid(member);
|
||||
|
||||
if (!UuidUtil.UNKNOWN_UUID.equals(uuid)) {
|
||||
uuidSet.add(uuid);
|
||||
}
|
||||
}
|
||||
|
||||
return uuidSet;
|
||||
}
|
||||
|
||||
public static UUID toUuid(DecryptedMember member) {
|
||||
return toUuid(member.getUuid());
|
||||
}
|
||||
|
@ -140,6 +154,10 @@ public final class DecryptedGroupUtil {
|
|||
return toUuid(member.getUuid());
|
||||
}
|
||||
|
||||
public static UUID toUuid(DecryptedBannedMember member) {
|
||||
return toUuid(member.getUuid());
|
||||
}
|
||||
|
||||
private static UUID toUuid(ByteString memberUuid) {
|
||||
return UuidUtil.fromByteStringOrUnknown(memberUuid);
|
||||
}
|
||||
|
|
|
@ -160,10 +160,13 @@ public final class GroupsV2Operations {
|
|||
return GroupChange.Actions.newBuilder().setModifyDescription(createModifyGroupDescriptionAction(description));
|
||||
}
|
||||
|
||||
public GroupChange.Actions.Builder createModifyGroupMembershipChange(Set<GroupCandidate> membersToAdd, UUID selfUuid) {
|
||||
public GroupChange.Actions.Builder createModifyGroupMembershipChange(Set<GroupCandidate> membersToAdd, Set<UUID> bannedMembers, UUID selfUuid) {
|
||||
final GroupOperations groupOperations = forGroup(groupSecretParams);
|
||||
|
||||
GroupChange.Actions.Builder actions = createUnbanUuidsChange(membersToAdd.stream().map(GroupCandidate::getUuid).collect(Collectors.toSet()));
|
||||
Set<UUID> membersToUnban = membersToAdd.stream().map(GroupCandidate::getUuid).filter(bannedMembers::contains).collect(Collectors.toSet());
|
||||
|
||||
GroupChange.Actions.Builder actions = membersToUnban.isEmpty() ? GroupChange.Actions.newBuilder()
|
||||
: createUnbanUuidsChange(membersToUnban);
|
||||
|
||||
for (GroupCandidate credential : membersToAdd) {
|
||||
Member.Role newMemberRole = Member.Role.DEFAULT;
|
||||
|
@ -479,7 +482,7 @@ public final class GroupsV2Operations {
|
|||
* <p>
|
||||
* Also, if you know it's version 0, do not verify because changes for version 0
|
||||
* are not signed, but should be empty.
|
||||
* @return {@link Optional#absent} if the epoch for the change is higher that this code can decrypt.
|
||||
* @return {@link Optional#empty()} if the epoch for the change is higher that this code can decrypt.
|
||||
*/
|
||||
public Optional<DecryptedGroupChange> decryptChange(GroupChange groupChange, boolean verifySignature)
|
||||
throws InvalidProtocolBufferException, VerificationFailedException, InvalidGroupStateException
|
||||
|
|
|
@ -95,7 +95,7 @@ public final class GroupsV2Operations_decrypt_change_Test {
|
|||
ProfileKey profileKey = newProfileKey();
|
||||
GroupCandidate groupCandidate = groupCandidate(newMember, profileKey);
|
||||
|
||||
assertDecryption(groupOperations.createModifyGroupMembershipChange(Collections.singleton(groupCandidate), self)
|
||||
assertDecryption(groupOperations.createModifyGroupMembershipChange(Collections.singleton(groupCandidate), Collections.emptySet(), self)
|
||||
.setRevision(10),
|
||||
DecryptedGroupChange.newBuilder()
|
||||
.setRevision(10)
|
||||
|
@ -103,8 +103,7 @@ public final class GroupsV2Operations_decrypt_change_Test {
|
|||
.setRole(Member.Role.DEFAULT)
|
||||
.setProfileKey(ByteString.copyFrom(profileKey.serialize()))
|
||||
.setJoinedAtRevision(10)
|
||||
.setUuid(UuidUtil.toByteString(newMember)))
|
||||
.addDeleteBannedMembers(DecryptedBannedMember.newBuilder().setUuid(UuidUtil.toByteString(newMember)).build()));
|
||||
.setUuid(UuidUtil.toByteString(newMember))));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -131,7 +130,7 @@ public final class GroupsV2Operations_decrypt_change_Test {
|
|||
ProfileKey profileKey = newProfileKey();
|
||||
GroupCandidate groupCandidate = groupCandidate(newMember, profileKey);
|
||||
|
||||
assertDecryption(groupOperations.createModifyGroupMembershipChange(Collections.singleton(groupCandidate), self)
|
||||
assertDecryption(groupOperations.createModifyGroupMembershipChange(Collections.singleton(groupCandidate), Collections.emptySet(), self)
|
||||
.setRevision(10),
|
||||
DecryptedGroupChange.newBuilder()
|
||||
.setRevision(10)
|
||||
|
@ -139,8 +138,7 @@ public final class GroupsV2Operations_decrypt_change_Test {
|
|||
.setRole(Member.Role.DEFAULT)
|
||||
.setProfileKey(ByteString.copyFrom(profileKey.serialize()))
|
||||
.setJoinedAtRevision(10)
|
||||
.setUuid(UuidUtil.toByteString(newMember)))
|
||||
.addDeleteBannedMembers(DecryptedBannedMember.newBuilder().setUuid(UuidUtil.toByteString(newMember)).build()));
|
||||
.setUuid(UuidUtil.toByteString(newMember))));
|
||||
}
|
||||
|
||||
@Test(expected = InvalidGroupStateException.class)
|
||||
|
@ -222,7 +220,7 @@ public final class GroupsV2Operations_decrypt_change_Test {
|
|||
UUID newMember = UUID.randomUUID();
|
||||
GroupCandidate groupCandidate = groupCandidate(newMember);
|
||||
|
||||
assertDecryption(groupOperations.createModifyGroupMembershipChange(Collections.singleton(groupCandidate), self)
|
||||
assertDecryption(groupOperations.createModifyGroupMembershipChange(Collections.singleton(groupCandidate), Collections.emptySet(), self)
|
||||
.setRevision(13),
|
||||
DecryptedGroupChange.newBuilder()
|
||||
.setRevision(13)
|
||||
|
@ -230,8 +228,7 @@ public final class GroupsV2Operations_decrypt_change_Test {
|
|||
.setAddedByUuid(UuidUtil.toByteString(self))
|
||||
.setUuidCipherText(groupOperations.encryptUuid(newMember))
|
||||
.setRole(Member.Role.DEFAULT)
|
||||
.setUuid(UuidUtil.toByteString(newMember)))
|
||||
.addDeleteBannedMembers(DecryptedBannedMember.newBuilder().setUuid(UuidUtil.toByteString(newMember)).build()));
|
||||
.setUuid(UuidUtil.toByteString(newMember))));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
Ładowanie…
Reference in New Issue