From 550b121990b2a66338fa9f19fa672c70c5eff3e3 Mon Sep 17 00:00:00 2001 From: Greyson Parrelli Date: Wed, 29 Jul 2020 23:04:35 -0400 Subject: [PATCH] Prevent UUID-only contacts from being added to GV1 groups. --- .../securesms/ContactSelectionActivity.java | 4 ++- .../ContactSelectionListFragment.java | 24 +++++++++----- .../securesms/InviteActivity.java | 3 +- .../securesms/NewConversationActivity.java | 4 ++- .../ui/addmembers/AddMembersActivity.java | 14 ++++++--- .../ui/addtogroup/AddToGroupViewModel.java | 16 +++++++--- .../ui/addtogroup/AddToGroupsActivity.java | 21 ++++++++----- .../ui/creategroup/CreateGroupActivity.java | 31 ++++++++++++++++--- .../securesms/sharing/ShareActivity.java | 5 ++- app/src/main/res/values/strings.xml | 5 +++ 10 files changed, 94 insertions(+), 33 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/ContactSelectionActivity.java b/app/src/main/java/org/thoughtcrime/securesms/ContactSelectionActivity.java index a64b920501..95f4aafeb5 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/ContactSelectionActivity.java +++ b/app/src/main/java/org/thoughtcrime/securesms/ContactSelectionActivity.java @@ -113,7 +113,9 @@ public abstract class ContactSelectionActivity extends PassphraseRequiredActivit } @Override - public void onContactSelected(Optional recipientId, String number) {} + public boolean onContactSelected(Optional recipientId, String number) { + return true; + } @Override public void onContactDeselected(Optional recipientId, String number) {} diff --git a/app/src/main/java/org/thoughtcrime/securesms/ContactSelectionListFragment.java b/app/src/main/java/org/thoughtcrime/securesms/ContactSelectionListFragment.java index 6807312d5b..b3f2dbee66 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/ContactSelectionListFragment.java +++ b/app/src/main/java/org/thoughtcrime/securesms/ContactSelectionListFragment.java @@ -473,11 +473,15 @@ public final class ContactSelectionListFragment extends LoggingFragment if (uuid.isPresent()) { Recipient recipient = Recipient.externalUsername(requireContext(), uuid.get(), contact.getNumber()); SelectedContact selected = SelectedContact.forUsername(recipient.getId(), contact.getNumber()); - markContactSelected(selected); - cursorRecyclerViewAdapter.notifyItemChanged(recyclerView.getChildAdapterPosition(contact), ContactSelectionListAdapter.PAYLOAD_SELECTION_CHANGE); if (onContactSelectedListener != null) { - onContactSelectedListener.onContactSelected(Optional.of(recipient.getId()), null); + if (onContactSelectedListener.onContactSelected(Optional.of(recipient.getId()), null)) { + markContactSelected(selected); + cursorRecyclerViewAdapter.notifyItemChanged(recyclerView.getChildAdapterPosition(contact), ContactSelectionListAdapter.PAYLOAD_SELECTION_CHANGE); + } + } else { + markContactSelected(selected); + cursorRecyclerViewAdapter.notifyItemChanged(recyclerView.getChildAdapterPosition(contact), ContactSelectionListAdapter.PAYLOAD_SELECTION_CHANGE); } } else { new AlertDialog.Builder(requireContext()) @@ -488,11 +492,14 @@ public final class ContactSelectionListFragment extends LoggingFragment } }); } else { - markContactSelected(selectedContact); - cursorRecyclerViewAdapter.notifyItemChanged(recyclerView.getChildAdapterPosition(contact), ContactSelectionListAdapter.PAYLOAD_SELECTION_CHANGE); - if (onContactSelectedListener != null) { - onContactSelectedListener.onContactSelected(contact.getRecipientId(), contact.getNumber()); + if (onContactSelectedListener.onContactSelected(contact.getRecipientId(), contact.getNumber())) { + markContactSelected(selectedContact); + cursorRecyclerViewAdapter.notifyItemChanged(recyclerView.getChildAdapterPosition(contact), ContactSelectionListAdapter.PAYLOAD_SELECTION_CHANGE); + } + } else { + markContactSelected(selectedContact); + cursorRecyclerViewAdapter.notifyItemChanged(recyclerView.getChildAdapterPosition(contact), ContactSelectionListAdapter.PAYLOAD_SELECTION_CHANGE); } } } else { @@ -624,7 +631,8 @@ public final class ContactSelectionListFragment extends LoggingFragment } public interface OnContactSelectedListener { - void onContactSelected(Optional recipientId, String number); + /** @return True if the contact is allowed to be selected, otherwise false. */ + boolean onContactSelected(Optional recipientId, String number); void onContactDeselected(Optional recipientId, String number); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/InviteActivity.java b/app/src/main/java/org/thoughtcrime/securesms/InviteActivity.java index ef70cdf850..09f2eadfe1 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/InviteActivity.java +++ b/app/src/main/java/org/thoughtcrime/securesms/InviteActivity.java @@ -121,8 +121,9 @@ public class InviteActivity extends PassphraseRequiredActivity implements Contac } @Override - public void onContactSelected(Optional recipientId, String number) { + public boolean onContactSelected(Optional recipientId, String number) { updateSmsButtonText(); + return true; } @Override diff --git a/app/src/main/java/org/thoughtcrime/securesms/NewConversationActivity.java b/app/src/main/java/org/thoughtcrime/securesms/NewConversationActivity.java index b1746d9456..392a2a530c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/NewConversationActivity.java +++ b/app/src/main/java/org/thoughtcrime/securesms/NewConversationActivity.java @@ -60,7 +60,7 @@ public class NewConversationActivity extends ContactSelectionActivity } @Override - public void onContactSelected(Optional recipientId, String number) { + public boolean onContactSelected(Optional recipientId, String number) { if (recipientId.isPresent()) { launch(Recipient.resolved(recipientId.get())); } else { @@ -92,6 +92,8 @@ public class NewConversationActivity extends ContactSelectionActivity launch(Recipient.external(this, number)); } } + + return true; } private void launch(Recipient recipient) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/groups/ui/addmembers/AddMembersActivity.java b/app/src/main/java/org/thoughtcrime/securesms/groups/ui/addmembers/AddMembersActivity.java index c7fd39df10..d85fe806e9 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/groups/ui/addmembers/AddMembersActivity.java +++ b/app/src/main/java/org/thoughtcrime/securesms/groups/ui/addmembers/AddMembersActivity.java @@ -3,6 +3,7 @@ package org.thoughtcrime.securesms.groups.ui.addmembers; import android.content.Context; import android.os.Bundle; import android.view.View; +import android.widget.Toast; import androidx.annotation.NonNull; import androidx.appcompat.app.AlertDialog; @@ -58,14 +59,19 @@ public class AddMembersActivity extends PushContactSelectionActivity { } @Override - public void onContactSelected(Optional recipientId, String number) { + public boolean onContactSelected(Optional recipientId, String number) { + if (getGroupId().isV1() && recipientId.isPresent() && !Recipient.resolved(recipientId.get()).hasE164()) { + Toast.makeText(this, R.string.AddMembersActivity__this_person_cant_be_added_to_legacy_groups, Toast.LENGTH_SHORT).show(); + return false; + } + if (contactsFragment.hasQueryFilter()) { getToolbar().clear(); } - if (contactsFragment.getSelectedContactsCount() >= 1) { - enableDone(); - } + enableDone(); + + return true; } @Override diff --git a/app/src/main/java/org/thoughtcrime/securesms/groups/ui/addtogroup/AddToGroupViewModel.java b/app/src/main/java/org/thoughtcrime/securesms/groups/ui/addtogroup/AddToGroupViewModel.java index dc7de1c4fe..b5c19d0d2c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/groups/ui/addtogroup/AddToGroupViewModel.java +++ b/app/src/main/java/org/thoughtcrime/securesms/groups/ui/addtogroup/AddToGroupViewModel.java @@ -39,13 +39,18 @@ public final class AddToGroupViewModel extends ViewModel { events.postValue(new Event.CloseEvent()); } else if (groupRecipientIds.size() == 1) { SignalExecutors.BOUNDED.execute(() -> { + Recipient recipient = Recipient.resolved(recipientId); Recipient groupRecipient = Recipient.resolved(groupRecipientIds.get(0)); - String recipientName = Recipient.resolved(recipientId).getDisplayName(context); + String recipientName = recipient.getDisplayName(context); String groupName = groupRecipient.getDisplayName(context); - events.postValue(new Event.AddToSingleGroupConfirmationEvent(context.getResources().getString(R.string.AddToGroupActivity_add_member), - context.getResources().getString(R.string.AddToGroupActivity_add_s_to_s, recipientName, groupName), - groupRecipient, recipientName, groupName)); + if (groupRecipient.getGroupId().get().isV1() && !recipient.hasE164()) { + events.postValue(new Event.LegacyGroupDenialEvent()); + } else { + events.postValue(new Event.AddToSingleGroupConfirmationEvent(context.getResources().getString(R.string.AddToGroupActivity_add_member), + context.getResources().getString(R.string.AddToGroupActivity_add_s_to_s, recipientName, groupName), + groupRecipient, recipientName, groupName)); + } }); } else { throw new AssertionError("Does not support multi-select"); @@ -107,6 +112,9 @@ public final class AddToGroupViewModel extends ViewModel { return message; } } + + static class LegacyGroupDenialEvent extends Event { + } } public static class Factory implements ViewModelProvider.Factory { diff --git a/app/src/main/java/org/thoughtcrime/securesms/groups/ui/addtogroup/AddToGroupsActivity.java b/app/src/main/java/org/thoughtcrime/securesms/groups/ui/addtogroup/AddToGroupsActivity.java index 3616717e38..de860ef296 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/groups/ui/addtogroup/AddToGroupsActivity.java +++ b/app/src/main/java/org/thoughtcrime/securesms/groups/ui/addtogroup/AddToGroupsActivity.java @@ -91,6 +91,8 @@ public final class AddToGroupsActivity extends ContactSelectionActivity { .setPositiveButton(android.R.string.ok, (dialog, which) -> viewModel.onAddToGroupsConfirmed(addEvent)) .setNegativeButton(android.R.string.cancel, null) .show(); + } else if (event instanceof Event.LegacyGroupDenialEvent) { + Toast.makeText(this, R.string.AddToGroupActivity_this_person_cant_be_added_to_legacy_groups, Toast.LENGTH_SHORT).show(); } else { throw new AssertionError(); } @@ -112,20 +114,23 @@ public final class AddToGroupsActivity extends ContactSelectionActivity { } @Override - public void onContactSelected(Optional recipientId, String number) { + public boolean onContactSelected(Optional recipientId, String number) { if (contactsFragment.isMulti()) { - if (contactsFragment.hasQueryFilter()) { - getToolbar().clear(); - } - - if (contactsFragment.getSelectedContactsCount() >= MINIMUM_GROUP_SELECT_SIZE) { - enableNext(); - } + throw new UnsupportedOperationException("Not yet built to handle multi-select."); +// if (contactsFragment.hasQueryFilter()) { +// getToolbar().clear(); +// } +// +// if (contactsFragment.getSelectedContactsCount() >= MINIMUM_GROUP_SELECT_SIZE) { +// enableNext(); +// } } else { if (recipientId.isPresent()) { viewModel.onContinueWithSelection(Collections.singletonList(recipientId.get())); } } + + return true; } @Override diff --git a/app/src/main/java/org/thoughtcrime/securesms/groups/ui/creategroup/CreateGroupActivity.java b/app/src/main/java/org/thoughtcrime/securesms/groups/ui/creategroup/CreateGroupActivity.java index 5111a24a79..87ab2543bf 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/groups/ui/creategroup/CreateGroupActivity.java +++ b/app/src/main/java/org/thoughtcrime/securesms/groups/ui/creategroup/CreateGroupActivity.java @@ -8,6 +8,7 @@ import android.view.View; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.appcompat.app.AlertDialog; import com.annimon.stream.Stream; @@ -30,6 +31,8 @@ import org.thoughtcrime.securesms.util.views.SimpleProgressDialog; import org.whispersystems.libsignal.util.guava.Optional; import java.io.IOException; +import java.util.Collection; +import java.util.Collections; import java.util.List; public class CreateGroupActivity extends ContactSelectionActivity { @@ -90,14 +93,14 @@ public class CreateGroupActivity extends ContactSelectionActivity { } @Override - public void onContactSelected(Optional recipientId, String number) { + public boolean onContactSelected(Optional recipientId, String number) { if (contactsFragment.hasQueryFilter()) { getToolbar().clear(); } - if (contactsFragment.getSelectedContactsCount() >= MINIMUM_GROUP_SIZE) { - enableNext(); - } + enableNext(); + + return true; } @Override @@ -160,13 +163,31 @@ public class CreateGroupActivity extends ContactSelectionActivity { stopwatch.split("capabilities"); + resolved = Recipient.resolvedList(ids); + + if (Stream.of(resolved).anyMatch(r -> r.getGroupsV2Capability() != Recipient.Capability.SUPPORTED) && + Stream.of(resolved).anyMatch(r -> !r.hasE164())) + { + Log.w(TAG, "Invalid GV1 group..."); + ids = Collections.emptyList(); + } + + stopwatch.split("gv1-check"); + return ids; }, ids -> { dismissibleDialog.dismiss(); stopwatch.stop(TAG); - startActivityForResult(AddGroupDetailsActivity.newIntent(this, ids), REQUEST_CODE_ADD_DETAILS); + if (ids.isEmpty()) { + new AlertDialog.Builder(this) + .setMessage(R.string.CreateGroupActivity_some_contacts_cannot_be_in_legacy_groups) + .setPositiveButton(android.R.string.ok, (d, w) -> d.dismiss()) + .show(); + } else { + startActivityForResult(AddGroupDetailsActivity.newIntent(this, ids), REQUEST_CODE_ADD_DETAILS); + } }); } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/sharing/ShareActivity.java b/app/src/main/java/org/thoughtcrime/securesms/sharing/ShareActivity.java index d906bd5267..e66f6d8937 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/sharing/ShareActivity.java +++ b/app/src/main/java/org/thoughtcrime/securesms/sharing/ShareActivity.java @@ -148,8 +148,9 @@ public class ShareActivity extends PassphraseRequiredActivity else super.onBackPressed(); } + @Override - public void onContactSelected(Optional recipientId, String number) { + public boolean onContactSelected(Optional recipientId, String number) { SimpleTask.run(this.getLifecycle(), () -> { Recipient recipient; if (recipientId.isPresent()) { @@ -162,6 +163,8 @@ public class ShareActivity extends PassphraseRequiredActivity long existingThread = DatabaseFactory.getThreadDatabase(this).getThreadIdIfExistsFor(recipient); return new Pair<>(existingThread, recipient); }, result -> onDestinationChosen(result.first(), result.second().getId())); + + return true; } @Override diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 63cc6ebbc2..97e506ce5e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -365,6 +365,9 @@ Verified You + + Some contacts cannot be in legacy groups. + Profile Error setting profile photo @@ -444,6 +447,7 @@ \"%1$s\" added to \"%2$s\". Add to group Add to groups + This person can\'t be added to legacy groups. Choose new admin @@ -502,6 +506,7 @@ Done + This person can\'t be added to legacy groups. Add \"%1$s\" to \"%2$s\"? Add %3$d members to \"%2$s\"?