Search in sources :

Example 11 with RecipientId

use of org.thoughtcrime.securesms.recipients.RecipientId in project Signal-Android by WhisperSystems.

the class GroupDatabase method updateMembers.

public void updateMembers(@NonNull GroupId groupId, List<RecipientId> members) {
    Collections.sort(members);
    ContentValues contents = new ContentValues();
    contents.put(MEMBERS, RecipientId.toSerializedList(members));
    contents.put(ACTIVE, 1);
    databaseHelper.getSignalWritableDatabase().update(TABLE_NAME, contents, GROUP_ID + " = ?", new String[] { groupId.toString() });
    RecipientId groupRecipient = SignalDatabase.recipients().getOrInsertFromGroupId(groupId);
    Recipient.live(groupRecipient).refresh();
}
Also used : ContentValues(android.content.ContentValues) RecipientId(org.thoughtcrime.securesms.recipients.RecipientId)

Example 12 with RecipientId

use of org.thoughtcrime.securesms.recipients.RecipientId in project Signal-Android by WhisperSystems.

the class GroupDatabase method getGroup.

public Optional<GroupRecord> getGroup(@NonNull GroupId groupId) {
    SQLiteDatabase db = databaseHelper.getSignalWritableDatabase();
    try (Cursor cursor = db.query(TABLE_NAME, null, GROUP_ID + " = ?", SqlUtil.buildArgs(groupId.toString()), null, null, null)) {
        if (cursor != null && cursor.moveToNext()) {
            Optional<GroupRecord> groupRecord = getGroup(cursor);
            if (groupRecord.isPresent() && RemappedRecords.getInstance().areAnyRemapped(groupRecord.get().getMembers())) {
                String remaps = RemappedRecords.getInstance().buildRemapDescription(groupRecord.get().getMembers());
                Log.w(TAG, "Found a group with remapped recipients in it's membership list! Updating the list. GroupId: " + groupId + ", Remaps: " + remaps, true);
                Collection<RecipientId> remapped = RemappedRecords.getInstance().remap(groupRecord.get().getMembers());
                ContentValues values = new ContentValues();
                values.put(MEMBERS, RecipientId.toSerializedList(remapped));
                if (db.update(TABLE_NAME, values, GROUP_ID + " = ?", SqlUtil.buildArgs(groupId)) > 0) {
                    return getGroup(groupId);
                } else {
                    throw new IllegalStateException("Failed to update group with remapped recipients!");
                }
            }
            return getGroup(cursor);
        }
        return Optional.absent();
    }
}
Also used : ContentValues(android.content.ContentValues) RecipientId(org.thoughtcrime.securesms.recipients.RecipientId) Cursor(android.database.Cursor)

Example 13 with RecipientId

use of org.thoughtcrime.securesms.recipients.RecipientId in project Signal-Android by WhisperSystems.

the class GroupDatabase method migrateToV2.

/**
 * Migrates a V1 group to a V2 group.
 *
 * @param decryptedGroup The state that represents the group on the server. This will be used to
 *                       determine if we need to save our old membership list and stuff.
 */
@NonNull
public GroupId.V2 migrateToV2(long threadId, @NonNull GroupId.V1 groupIdV1, @NonNull DecryptedGroup decryptedGroup) {
    SQLiteDatabase db = databaseHelper.getSignalWritableDatabase();
    GroupId.V2 groupIdV2 = groupIdV1.deriveV2MigrationGroupId();
    GroupMasterKey groupMasterKey = groupIdV1.deriveV2MigrationMasterKey();
    db.beginTransaction();
    try {
        GroupRecord record = getGroup(groupIdV1).get();
        ContentValues contentValues = new ContentValues();
        contentValues.put(GROUP_ID, groupIdV2.toString());
        contentValues.put(V2_MASTER_KEY, groupMasterKey.serialize());
        contentValues.put(DISTRIBUTION_ID, DistributionId.create().toString());
        contentValues.putNull(EXPECTED_V2_ID);
        List<RecipientId> newMembers = uuidsToRecipientIds(DecryptedGroupUtil.membersToUuidList(decryptedGroup.getMembersList()));
        List<RecipientId> pendingMembers = uuidsToRecipientIds(DecryptedGroupUtil.pendingToUuidList(decryptedGroup.getPendingMembersList()));
        newMembers.addAll(pendingMembers);
        List<RecipientId> droppedMembers = new ArrayList<>(SetUtil.difference(record.getMembers(), newMembers));
        List<RecipientId> unmigratedMembers = Util.concatenatedList(pendingMembers, droppedMembers);
        contentValues.put(UNMIGRATED_V1_MEMBERS, unmigratedMembers.isEmpty() ? null : RecipientId.toSerializedList(unmigratedMembers));
        int updated = db.update(TABLE_NAME, contentValues, GROUP_ID + " = ?", SqlUtil.buildArgs(groupIdV1.toString()));
        if (updated != 1) {
            throw new AssertionError();
        }
        SignalDatabase.recipients().updateGroupId(groupIdV1, groupIdV2);
        update(groupMasterKey, decryptedGroup);
        SignalDatabase.sms().insertGroupV1MigrationEvents(record.getRecipientId(), threadId, new GroupMigrationMembershipChange(pendingMembers, droppedMembers));
        db.setTransactionSuccessful();
    } finally {
        db.endTransaction();
    }
    return groupIdV2;
}
Also used : ContentValues(android.content.ContentValues) RecipientId(org.thoughtcrime.securesms.recipients.RecipientId) GroupMigrationMembershipChange(org.thoughtcrime.securesms.groups.GroupMigrationMembershipChange) ArrayList(java.util.ArrayList) GroupMasterKey(org.signal.zkgroup.groups.GroupMasterKey) SuppressLint(android.annotation.SuppressLint) GroupId(org.thoughtcrime.securesms.groups.GroupId) NonNull(androidx.annotation.NonNull)

Example 14 with RecipientId

use of org.thoughtcrime.securesms.recipients.RecipientId in project Signal-Android by WhisperSystems.

the class GroupDatabase method update.

public void update(@NonNull GroupId.V2 groupId, @NonNull DecryptedGroup decryptedGroup) {
    RecipientDatabase recipientDatabase = SignalDatabase.recipients();
    RecipientId groupRecipientId = recipientDatabase.getOrInsertFromGroupId(groupId);
    Optional<GroupRecord> existingGroup = getGroup(groupId);
    String title = decryptedGroup.getTitle();
    ContentValues contentValues = new ContentValues();
    if (existingGroup.isPresent() && existingGroup.get().getUnmigratedV1Members().size() > 0 && existingGroup.get().isV2Group()) {
        Set<RecipientId> unmigratedV1Members = new HashSet<>(existingGroup.get().getUnmigratedV1Members());
        DecryptedGroupChange change = GroupChangeReconstruct.reconstructGroupChange(existingGroup.get().requireV2GroupProperties().getDecryptedGroup(), decryptedGroup);
        List<RecipientId> addedMembers = uuidsToRecipientIds(DecryptedGroupUtil.membersToUuidList(change.getNewMembersList()));
        List<RecipientId> removedMembers = uuidsToRecipientIds(DecryptedGroupUtil.removedMembersUuidList(change));
        List<RecipientId> addedInvites = uuidsToRecipientIds(DecryptedGroupUtil.pendingToUuidList(change.getNewPendingMembersList()));
        List<RecipientId> removedInvites = uuidsToRecipientIds(DecryptedGroupUtil.removedPendingMembersUuidList(change));
        List<RecipientId> acceptedInvites = uuidsToRecipientIds(DecryptedGroupUtil.membersToUuidList(change.getPromotePendingMembersList()));
        unmigratedV1Members.removeAll(addedMembers);
        unmigratedV1Members.removeAll(removedMembers);
        unmigratedV1Members.removeAll(addedInvites);
        unmigratedV1Members.removeAll(removedInvites);
        unmigratedV1Members.removeAll(acceptedInvites);
        contentValues.put(UNMIGRATED_V1_MEMBERS, unmigratedV1Members.isEmpty() ? null : RecipientId.toSerializedList(unmigratedV1Members));
    }
    List<RecipientId> groupMembers = getV2GroupMembers(decryptedGroup, true);
    contentValues.put(TITLE, title);
    contentValues.put(V2_REVISION, decryptedGroup.getRevision());
    contentValues.put(V2_DECRYPTED_GROUP, decryptedGroup.toByteArray());
    contentValues.put(MEMBERS, RecipientId.toSerializedList(groupMembers));
    contentValues.put(ACTIVE, gv2GroupActive(decryptedGroup) ? 1 : 0);
    DistributionId distributionId = Objects.requireNonNull(existingGroup.get().getDistributionId());
    if (existingGroup.isPresent() && existingGroup.get().isV2Group()) {
        DecryptedGroupChange change = GroupChangeReconstruct.reconstructGroupChange(existingGroup.get().requireV2GroupProperties().getDecryptedGroup(), decryptedGroup);
        List<UUID> removed = DecryptedGroupUtil.removedMembersUuidList(change);
        if (removed.size() > 0) {
            Log.i(TAG, removed.size() + " members were removed from group " + groupId + ". Rotating the DistributionId " + distributionId);
            SenderKeyUtil.rotateOurKey(context, distributionId);
        }
    }
    databaseHelper.getSignalWritableDatabase().update(TABLE_NAME, contentValues, GROUP_ID + " = ?", new String[] { groupId.toString() });
    if (decryptedGroup.hasDisappearingMessagesTimer()) {
        recipientDatabase.setExpireMessages(groupRecipientId, decryptedGroup.getDisappearingMessagesTimer().getDuration());
    }
    if (groupId.isMms() || Recipient.resolved(groupRecipientId).isProfileSharing()) {
        recipientDatabase.setHasGroupsInCommon(groupMembers);
    }
    Recipient.live(groupRecipientId).refresh();
    notifyConversationListListeners();
}
Also used : ContentValues(android.content.ContentValues) RecipientId(org.thoughtcrime.securesms.recipients.RecipientId) DistributionId(org.whispersystems.signalservice.api.push.DistributionId) DecryptedGroupChange(org.signal.storageservice.protos.groups.local.DecryptedGroupChange) UUID(java.util.UUID) HashSet(java.util.HashSet)

Example 15 with RecipientId

use of org.thoughtcrime.securesms.recipients.RecipientId in project Signal-Android by WhisperSystems.

the class GroupDatabase method getGroupMembers.

@WorkerThread
@NonNull
public List<Recipient> getGroupMembers(@NonNull GroupId groupId, @NonNull MemberSet memberSet) {
    if (groupId.isV2()) {
        return getGroup(groupId).transform(g -> g.requireV2GroupProperties().getMemberRecipients(memberSet)).or(Collections.emptyList());
    } else {
        List<RecipientId> currentMembers = getCurrentMembers(groupId);
        List<Recipient> recipients = new ArrayList<>(currentMembers.size());
        for (RecipientId member : currentMembers) {
            Recipient resolved = Recipient.resolved(member);
            if (memberSet.includeSelf || !resolved.isSelf()) {
                recipients.add(resolved);
            }
        }
        return recipients;
    }
}
Also used : SignalStore(org.thoughtcrime.securesms.keyvalue.SignalStore) GroupMigrationMembershipChange(org.thoughtcrime.securesms.groups.GroupMigrationMembershipChange) NonNull(androidx.annotation.NonNull) RequestGroupV2InfoJob(org.thoughtcrime.securesms.jobs.RequestGroupV2InfoJob) GroupAccessControl(org.thoughtcrime.securesms.groups.GroupAccessControl) GroupMasterKey(org.signal.zkgroup.groups.GroupMasterKey) SecureRandom(java.security.SecureRandom) Member(org.signal.storageservice.protos.groups.Member) SenderKeyUtil(org.thoughtcrime.securesms.crypto.SenderKeyUtil) RecipientId(org.thoughtcrime.securesms.recipients.RecipientId) SqlUtil(org.thoughtcrime.securesms.util.SqlUtil) Locale(java.util.Locale) Map(java.util.Map) DecryptedGroupChange(org.signal.storageservice.protos.groups.local.DecryptedGroupChange) Recipient(org.thoughtcrime.securesms.recipients.Recipient) GroupsV2StateProcessor(org.thoughtcrime.securesms.groups.v2.processing.GroupsV2StateProcessor) InvalidProtocolBufferException(com.google.protobuf.InvalidProtocolBufferException) ACI(org.whispersystems.signalservice.api.push.ACI) DecryptedGroupUtil(org.whispersystems.signalservice.api.groupsv2.DecryptedGroupUtil) ApplicationDependencies(org.thoughtcrime.securesms.dependencies.ApplicationDependencies) Collection(java.util.Collection) EnabledState(org.signal.storageservice.protos.groups.local.EnabledState) Set(java.util.Set) SetUtil(org.thoughtcrime.securesms.util.SetUtil) UUID(java.util.UUID) Collectors(java.util.stream.Collectors) InvalidInputException(org.signal.zkgroup.InvalidInputException) Objects(java.util.Objects) Log(org.signal.core.util.logging.Log) DecryptedGroup(org.signal.storageservice.protos.groups.local.DecryptedGroup) List(java.util.List) Nullable(androidx.annotation.Nullable) GroupId(org.thoughtcrime.securesms.groups.GroupId) ContentValues(android.content.ContentValues) Context(android.content.Context) Stream(com.annimon.stream.Stream) Util(org.thoughtcrime.securesms.util.Util) WorkerThread(androidx.annotation.WorkerThread) HashMap(java.util.HashMap) AccessControl(org.signal.storageservice.protos.groups.AccessControl) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) SuppressLint(android.annotation.SuppressLint) LinkedList(java.util.LinkedList) DistributionId(org.whispersystems.signalservice.api.push.DistributionId) Cursor(android.database.Cursor) GroupChangeReconstruct(org.whispersystems.signalservice.api.groupsv2.GroupChangeReconstruct) SignalServiceAttachmentPointer(org.whispersystems.signalservice.api.messages.SignalServiceAttachmentPointer) UuidUtil(org.whispersystems.signalservice.api.util.UuidUtil) TextUtils(android.text.TextUtils) Optional(org.whispersystems.libsignal.util.guava.Optional) CursorUtil(org.thoughtcrime.securesms.util.CursorUtil) Closeable(java.io.Closeable) ServiceId(org.whispersystems.signalservice.api.push.ServiceId) Collections(java.util.Collections) RecipientId(org.thoughtcrime.securesms.recipients.RecipientId) ArrayList(java.util.ArrayList) Recipient(org.thoughtcrime.securesms.recipients.Recipient) WorkerThread(androidx.annotation.WorkerThread) NonNull(androidx.annotation.NonNull)

Aggregations

RecipientId (org.thoughtcrime.securesms.recipients.RecipientId)154 NonNull (androidx.annotation.NonNull)70 Recipient (org.thoughtcrime.securesms.recipients.Recipient)70 List (java.util.List)34 ArrayList (java.util.ArrayList)33 Nullable (androidx.annotation.Nullable)32 Context (android.content.Context)31 Log (org.signal.core.util.logging.Log)31 IOException (java.io.IOException)30 ApplicationDependencies (org.thoughtcrime.securesms.dependencies.ApplicationDependencies)29 WorkerThread (androidx.annotation.WorkerThread)28 Stream (com.annimon.stream.Stream)27 LinkedList (java.util.LinkedList)25 ContentValues (android.content.ContentValues)24 Cursor (android.database.Cursor)24 Collections (java.util.Collections)24 SignalDatabase (org.thoughtcrime.securesms.database.SignalDatabase)24 GroupDatabase (org.thoughtcrime.securesms.database.GroupDatabase)23 Optional (org.whispersystems.libsignal.util.guava.Optional)22 HashSet (java.util.HashSet)21