mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-21 17:29:32 +01:00
Convert GroupTable to kotlin.
Also required converting some tests to mockk.
This commit is contained in:
File diff suppressed because it is too large
Load Diff
1395
app/src/main/java/org/thoughtcrime/securesms/database/GroupTable.kt
Normal file
1395
app/src/main/java/org/thoughtcrime/securesms/database/GroupTable.kt
Normal file
File diff suppressed because it is too large
Load Diff
@@ -54,6 +54,7 @@ import org.thoughtcrime.securesms.database.documents.NetworkFailure;
|
||||
import org.thoughtcrime.securesms.database.documents.NetworkFailureSet;
|
||||
import org.thoughtcrime.securesms.database.model.DisplayRecord;
|
||||
import org.thoughtcrime.securesms.database.model.GroupCallUpdateDetailsUtil;
|
||||
import org.thoughtcrime.securesms.database.model.GroupRecord;
|
||||
import org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord;
|
||||
import org.thoughtcrime.securesms.database.model.Mention;
|
||||
import org.thoughtcrime.securesms.database.model.MessageExportStatus;
|
||||
@@ -941,9 +942,9 @@ public class MessageTable extends DatabaseTable implements MessageTypes, Recipie
|
||||
}
|
||||
|
||||
public void insertProfileNameChangeMessages(@NonNull Recipient recipient, @NonNull String newProfileName, @NonNull String previousProfileName) {
|
||||
ThreadTable threadTable = SignalDatabase.threads();
|
||||
List<GroupTable.GroupRecord> groupRecords = SignalDatabase.groups().getGroupsContainingMember(recipient.getId(), false);
|
||||
List<Long> threadIdsToUpdate = new LinkedList<>();
|
||||
ThreadTable threadTable = SignalDatabase.threads();
|
||||
List<GroupRecord> groupRecords = SignalDatabase.groups().getGroupsContainingMember(recipient.getId(), false);
|
||||
List<Long> threadIdsToUpdate = new LinkedList<>();
|
||||
|
||||
byte[] profileChangeDetails = ProfileChangeDetails.newBuilder()
|
||||
.setProfileNameChange(ProfileChangeDetails.StringChange.newBuilder()
|
||||
@@ -959,7 +960,7 @@ public class MessageTable extends DatabaseTable implements MessageTypes, Recipie
|
||||
|
||||
try {
|
||||
threadIdsToUpdate.add(threadTable.getThreadIdFor(recipient.getId()));
|
||||
for (GroupTable.GroupRecord groupRecord : groupRecords) {
|
||||
for (GroupRecord groupRecord : groupRecords) {
|
||||
if (groupRecord.isActive()) {
|
||||
threadIdsToUpdate.add(threadTable.getThreadIdFor(groupRecord.getRecipientId()));
|
||||
}
|
||||
@@ -1032,16 +1033,16 @@ public class MessageTable extends DatabaseTable implements MessageTypes, Recipie
|
||||
}
|
||||
|
||||
public void insertNumberChangeMessages(@NonNull RecipientId recipientId) {
|
||||
ThreadTable threadTable = SignalDatabase.threads();
|
||||
List<GroupTable.GroupRecord> groupRecords = SignalDatabase.groups().getGroupsContainingMember(recipientId, false);
|
||||
List<Long> threadIdsToUpdate = new LinkedList<>();
|
||||
ThreadTable threadTable = SignalDatabase.threads();
|
||||
List<GroupRecord> groupRecords = SignalDatabase.groups().getGroupsContainingMember(recipientId, false);
|
||||
List<Long> threadIdsToUpdate = new LinkedList<>();
|
||||
|
||||
SQLiteDatabase db = databaseHelper.getSignalWritableDatabase();
|
||||
db.beginTransaction();
|
||||
|
||||
try {
|
||||
threadIdsToUpdate.add(threadTable.getThreadIdFor(recipientId));
|
||||
for (GroupTable.GroupRecord groupRecord : groupRecords) {
|
||||
for (GroupRecord groupRecord : groupRecords) {
|
||||
if (groupRecord.isActive()) {
|
||||
threadIdsToUpdate.add(threadTable.getThreadIdFor(groupRecord.getRecipientId()));
|
||||
}
|
||||
|
||||
@@ -1186,7 +1186,7 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da
|
||||
}
|
||||
}
|
||||
|
||||
for (id in groups.allGroupV2Ids) {
|
||||
for (id in groups.getAllGroupV2Ids()) {
|
||||
val recipient = Recipient.externalGroupExact(id!!)
|
||||
val recipientId = recipient.id
|
||||
val existing: RecipientRecord = getRecordForSync(recipientId) ?: throw AssertionError()
|
||||
|
||||
@@ -1670,7 +1670,7 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
|
||||
val recipientSettings = recipients.getRecord(context, cursor, RECIPIENT_ID)
|
||||
|
||||
val recipient: Recipient = if (recipientSettings.groupId != null) {
|
||||
GroupTable.Reader(cursor).current?.let { group ->
|
||||
GroupTable.Reader(cursor).getCurrent()?.let { group ->
|
||||
val details = RecipientDetails(
|
||||
group.title,
|
||||
null,
|
||||
|
||||
@@ -0,0 +1,163 @@
|
||||
package org.thoughtcrime.securesms.database.model
|
||||
|
||||
import androidx.annotation.WorkerThread
|
||||
import org.signal.libsignal.zkgroup.groups.GroupMasterKey
|
||||
import org.signal.storageservice.protos.groups.AccessControl
|
||||
import org.signal.storageservice.protos.groups.local.EnabledState
|
||||
import org.thoughtcrime.securesms.database.GroupTable
|
||||
import org.thoughtcrime.securesms.groups.GroupAccessControl
|
||||
import org.thoughtcrime.securesms.groups.GroupId
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import org.whispersystems.signalservice.api.groupsv2.DecryptedGroupUtil
|
||||
import org.whispersystems.signalservice.api.push.DistributionId
|
||||
import java.lang.AssertionError
|
||||
import java.util.Optional
|
||||
|
||||
class GroupRecord(
|
||||
val id: GroupId,
|
||||
val recipientId: RecipientId,
|
||||
val title: String?,
|
||||
serializedMembers: String?,
|
||||
serializedUnmigratedV1Members: String?,
|
||||
val avatarId: Long,
|
||||
val avatarKey: ByteArray?,
|
||||
val avatarContentType: String?,
|
||||
val relay: String?,
|
||||
val isActive: Boolean,
|
||||
val avatarDigest: ByteArray?,
|
||||
val isMms: Boolean,
|
||||
groupMasterKeyBytes: ByteArray?,
|
||||
groupRevision: Int,
|
||||
decryptedGroupBytes: ByteArray?,
|
||||
val distributionId: DistributionId?,
|
||||
val lastForceUpdateTimestamp: Long
|
||||
) {
|
||||
|
||||
val members: List<RecipientId> by lazy {
|
||||
if (serializedMembers.isNullOrEmpty()) {
|
||||
emptyList()
|
||||
} else {
|
||||
RecipientId.fromSerializedList(serializedMembers)
|
||||
}
|
||||
}
|
||||
|
||||
/** V1 members that were lost during the V1->V2 migration */
|
||||
val unmigratedV1Members: List<RecipientId> by lazy {
|
||||
if (serializedUnmigratedV1Members.isNullOrEmpty()) {
|
||||
emptyList()
|
||||
} else {
|
||||
RecipientId.fromSerializedList(serializedUnmigratedV1Members)
|
||||
}
|
||||
}
|
||||
|
||||
private val v2GroupProperties: GroupTable.V2GroupProperties? by lazy {
|
||||
if (groupMasterKeyBytes != null && decryptedGroupBytes != null) {
|
||||
val groupMasterKey = GroupMasterKey(groupMasterKeyBytes)
|
||||
GroupTable.V2GroupProperties(groupMasterKey, groupRevision, decryptedGroupBytes)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
val description: String
|
||||
get() = v2GroupProperties?.decryptedGroup?.description ?: ""
|
||||
|
||||
val isAnnouncementGroup: Boolean
|
||||
get() = v2GroupProperties?.decryptedGroup?.isAnnouncementGroup == EnabledState.ENABLED
|
||||
|
||||
val isV1Group: Boolean
|
||||
get() = !isMms && !isV2Group
|
||||
|
||||
val isV2Group: Boolean
|
||||
get() = v2GroupProperties != null
|
||||
|
||||
@get:WorkerThread
|
||||
val admins: List<Recipient>
|
||||
get() {
|
||||
return if (v2GroupProperties != null) {
|
||||
val resolved = members.map { Recipient.resolved(it) }
|
||||
v2GroupProperties!!.getAdmins(resolved)
|
||||
} else {
|
||||
emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
/** Who is allowed to add to the membership of this group. */
|
||||
val membershipAdditionAccessControl: GroupAccessControl
|
||||
get() {
|
||||
return if (isV2Group) {
|
||||
if (requireV2GroupProperties().decryptedGroup.accessControl.members == AccessControl.AccessRequired.MEMBER) {
|
||||
GroupAccessControl.ALL_MEMBERS
|
||||
} else {
|
||||
GroupAccessControl.ONLY_ADMINS
|
||||
}
|
||||
} else if (isV1Group) {
|
||||
GroupAccessControl.NO_ONE
|
||||
} else if (id.isV1) {
|
||||
GroupAccessControl.ALL_MEMBERS
|
||||
} else {
|
||||
GroupAccessControl.ONLY_ADMINS
|
||||
}
|
||||
}
|
||||
|
||||
/** Who is allowed to modify the attributes of this group, name/avatar/timer etc. */
|
||||
val attributesAccessControl: GroupAccessControl
|
||||
get() {
|
||||
return if (isV2Group) {
|
||||
if (requireV2GroupProperties().decryptedGroup.accessControl.attributes == AccessControl.AccessRequired.MEMBER) {
|
||||
GroupAccessControl.ALL_MEMBERS
|
||||
} else {
|
||||
GroupAccessControl.ONLY_ADMINS
|
||||
}
|
||||
} else if (isV1Group) {
|
||||
GroupAccessControl.NO_ONE
|
||||
} else {
|
||||
GroupAccessControl.ALL_MEMBERS
|
||||
}
|
||||
}
|
||||
|
||||
fun hasAvatar(): Boolean {
|
||||
return avatarId != 0L
|
||||
}
|
||||
|
||||
fun requireV2GroupProperties(): GroupTable.V2GroupProperties {
|
||||
return v2GroupProperties ?: throw AssertionError()
|
||||
}
|
||||
|
||||
fun isAdmin(recipient: Recipient): Boolean {
|
||||
return isV2Group && requireV2GroupProperties().isAdmin(recipient)
|
||||
}
|
||||
|
||||
fun memberLevel(recipient: Recipient): GroupTable.MemberLevel {
|
||||
return if (isV2Group) {
|
||||
val memberLevel = requireV2GroupProperties().memberLevel(recipient.serviceId)
|
||||
if (recipient.isSelf && memberLevel == GroupTable.MemberLevel.NOT_A_MEMBER) {
|
||||
requireV2GroupProperties().memberLevel(Optional.ofNullable(SignalStore.account().pni))
|
||||
} else {
|
||||
memberLevel
|
||||
}
|
||||
} else if (isMms && recipient.isSelf) {
|
||||
GroupTable.MemberLevel.FULL_MEMBER
|
||||
} else if (members.contains(recipient.id)) {
|
||||
GroupTable.MemberLevel.FULL_MEMBER
|
||||
} else {
|
||||
GroupTable.MemberLevel.NOT_A_MEMBER
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not the recipient is a pending member.
|
||||
*/
|
||||
fun isPendingMember(recipient: Recipient): Boolean {
|
||||
if (isV2Group) {
|
||||
val serviceId = recipient.serviceId
|
||||
if (serviceId.isPresent) {
|
||||
return DecryptedGroupUtil.findPendingByUuid(requireV2GroupProperties().decryptedGroup.pendingMembersList, serviceId.get().uuid())
|
||||
.isPresent
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user