diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/GroupDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/GroupDatabase.java index 90dfedeea4..b0252aab78 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/GroupDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/GroupDatabase.java @@ -136,7 +136,7 @@ public class GroupDatabase extends Database implements LokiOpenGroupDatabaseProt return cursor.getString(cursor.getColumnIndexOrThrow(GROUP_ID)); } else { String groupId = GroupUtil.getEncodedMMSGroupID(allocateGroupId()); - create(groupId, null, members, null, null, admins); + create(groupId, null, members, null, null, admins, System.currentTimeMillis()); return groupId; } } finally { @@ -196,7 +196,7 @@ public class GroupDatabase extends Database implements LokiOpenGroupDatabaseProt } public long create(@NonNull String groupId, @Nullable String title, @NonNull List
members, - @Nullable SignalServiceAttachmentPointer avatar, @Nullable String relay, @Nullable List
admins) + @Nullable SignalServiceAttachmentPointer avatar, @Nullable String relay, @Nullable List
admins, @NonNull Long formationTimestamp) { Collections.sort(members); @@ -214,7 +214,7 @@ public class GroupDatabase extends Database implements LokiOpenGroupDatabaseProt } contentValues.put(AVATAR_RELAY, relay); - contentValues.put(TIMESTAMP, System.currentTimeMillis()); + contentValues.put(TIMESTAMP, formationTimestamp); contentValues.put(ACTIVE, 1); contentValues.put(MMS, GroupUtil.isMmsGroup(groupId)); diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt index d2cce48aa6..60d5ca84b2 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt @@ -362,8 +362,8 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context, return if (group.isPresent) { group.get() } else null } - override fun createGroup(groupId: String, title: String?, members: List
, avatar: SignalServiceAttachmentPointer?, relay: String?, admins: List
) { - DatabaseFactory.getGroupDatabase(context).create(groupId, title, members, avatar, relay, admins) + override fun createGroup(groupId: String, title: String?, members: List
, avatar: SignalServiceAttachmentPointer?, relay: String?, admins: List
, formationTimestamp: Long) { + DatabaseFactory.getGroupDatabase(context).create(groupId, title, members, avatar, relay, admins, formationTimestamp) } override fun setActive(groupID: String, value: Boolean) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/groups/GroupManager.java b/app/src/main/java/org/thoughtcrime/securesms/groups/GroupManager.java index af11e476c4..3606954a89 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/groups/GroupManager.java +++ b/app/src/main/java/org/thoughtcrime/securesms/groups/GroupManager.java @@ -77,7 +77,7 @@ public class GroupManager { String masterPublicKey = masterPublicKeyOrNull != null ? masterPublicKeyOrNull : TextSecurePreferences.getLocalNumber(context); memberAddresses.add(Address.Companion.fromSerialized(masterPublicKey)); - groupDatabase.create(groupId, name, new LinkedList<>(memberAddresses), null, null, new LinkedList<>(adminAddresses)); + groupDatabase.create(groupId, name, new LinkedList<>(memberAddresses), null, null, new LinkedList<>(adminAddresses), System.currentTimeMillis()); groupDatabase.updateProfilePicture(groupId, avatarBytes); DatabaseFactory.getRecipientDatabase(context).setProfileSharing(groupRecipient, true); @@ -104,7 +104,7 @@ public class GroupManager { final Set
memberAddresses = new HashSet<>(); memberAddresses.add(Address.Companion.fromSerialized(Objects.requireNonNull(TextSecurePreferences.getLocalNumber(context)))); - groupDatabase.create(groupId, name, new LinkedList<>(memberAddresses), null, null, new LinkedList<>()); + groupDatabase.create(groupId, name, new LinkedList<>(memberAddresses), null, null, new LinkedList<>(), System.currentTimeMillis()); groupDatabase.updateProfilePicture(groupId, avatarBytes); diff --git a/app/src/main/java/org/thoughtcrime/securesms/loki/protocol/ClosedGroupsProtocolV2.kt b/app/src/main/java/org/thoughtcrime/securesms/loki/protocol/ClosedGroupsProtocolV2.kt index bf12e073e0..5ec16023c6 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/loki/protocol/ClosedGroupsProtocolV2.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/loki/protocol/ClosedGroupsProtocolV2.kt @@ -69,7 +69,7 @@ object ClosedGroupsProtocolV2 { val admins = setOf( userPublicKey ) val adminsAsData = admins.map { Hex.fromStringCondensed(it) } DatabaseFactory.getGroupDatabase(context).create(groupID, name, LinkedList(members.map { Address.fromSerialized(it) }), - null, null, LinkedList(admins.map { Address.fromSerialized(it!!) })) + null, null, LinkedList(admins.map { Address.fromSerialized(it!!) }), System.currentTimeMillis()) DatabaseFactory.getRecipientDatabase(context).setProfileSharing(Recipient.from(context, Address.fromSerialized(groupID), false), true) // Send a closed group update message to all members individually // Add the group to the user's set of public keys to poll for @@ -463,7 +463,7 @@ object ClosedGroupsProtocolV2 { groupDB.updateMembers(groupID, members.map { Address.fromSerialized(it) }) } else { groupDB.create(groupID, name, LinkedList(members.map { Address.fromSerialized(it) }), - null, null, LinkedList(admins.map { Address.fromSerialized(it) })) + null, null, LinkedList(admins.map { Address.fromSerialized(it) }), sentTimestamp) } DatabaseFactory.getRecipientDatabase(context).setProfileSharing(Recipient.from(context, Address.fromSerialized(groupID), false), true) // Add the group to the user's set of public keys to poll for @@ -714,7 +714,7 @@ object ClosedGroupsProtocolV2 { senderPublicKey: String): Boolean { val oldMembers = group.members.map { it.serialize() } // Check that the message isn't from before the group was created - if (group.createdAt > sentTimestamp) { + if (group.formationTimestamp > sentTimestamp) { Log.d("Loki", "Ignoring closed group update from before thread was created.") return false } diff --git a/app/src/main/java/org/thoughtcrime/securesms/loki/protocol/MultiDeviceProtocol.kt b/app/src/main/java/org/thoughtcrime/securesms/loki/protocol/MultiDeviceProtocol.kt index 475d842d98..5e1923a5f8 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/loki/protocol/MultiDeviceProtocol.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/loki/protocol/MultiDeviceProtocol.kt @@ -60,7 +60,7 @@ object MultiDeviceProtocol { } } - // TODO: remove this after we migrate to new message sending pipeline + // TODO: remove this after we migrate to new message receiving pipeline @JvmStatic fun handleConfigurationMessage(context: Context, content: SignalServiceProtos.Content, senderPublicKey: String, timestamp: Long) { if (TextSecurePreferences.getConfigurationMessageSynced(context)) return diff --git a/libsession/src/main/java/org/session/libsession/messaging/StorageProtocol.kt b/libsession/src/main/java/org/session/libsession/messaging/StorageProtocol.kt index eca1e13985..484cb61c72 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/StorageProtocol.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/StorageProtocol.kt @@ -100,7 +100,7 @@ interface StorageProtocol { // Closed Groups fun getGroup(groupID: String): GroupRecord? - fun createGroup(groupID: String, title: String?, members: List
, avatar: SignalServiceAttachmentPointer?, relay: String?, admins: List
) + fun createGroup(groupID: String, title: String?, members: List
, avatar: SignalServiceAttachmentPointer?, relay: String?, admins: List
, formationTimestamp: Long) fun setActive(groupID: String, value: Boolean) fun removeMember(groupID: String, member: Address) fun updateMembers(groupID: String, members: List
) diff --git a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageReceiverHandler.kt b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageReceiverHandler.kt index fe62511562..b37c2eafe7 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageReceiverHandler.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageReceiverHandler.kt @@ -110,7 +110,7 @@ private fun MessageReceiver.handleConfigurationMessage(message: ConfigurationMes val allClosedGroupPublicKeys = storage.getAllClosedGroupPublicKeys() for (closeGroup in message.closedGroups) { if (allClosedGroupPublicKeys.contains(closeGroup.publicKey)) continue - handleNewClosedGroup(message.sender!!, closeGroup.publicKey, closeGroup.name, closeGroup.encryptionKeyPair, closeGroup.members, closeGroup.admins) + handleNewClosedGroup(message.sender!!, closeGroup.publicKey, closeGroup.name, closeGroup.encryptionKeyPair, closeGroup.members, closeGroup.admins, message.sentTimestamp!!) } val allOpenGroups = storage.getAllOpenGroups().map { it.value.server } for (openGroup in message.openGroups) { @@ -221,11 +221,11 @@ private fun MessageReceiver.handleNewClosedGroup(message: ClosedGroupControlMess val groupPublicKey = kind.publicKey.toByteArray().toHexString() val members = kind.members.map { it.toByteArray().toHexString() } val admins = kind.admins.map { it.toByteArray().toHexString() } - handleNewClosedGroup(message.sender!!, groupPublicKey, kind.name, kind.encryptionKeyPair, members, admins) + handleNewClosedGroup(message.sender!!, groupPublicKey, kind.name, kind.encryptionKeyPair, members, admins, message.sentTimestamp!!) } // Parameter @sender:String is just for inserting incoming info message -private fun handleNewClosedGroup(sender: String, groupPublicKey: String, name: String, encryptionKeyPair: ECKeyPair, members: List, admins: List) { +private fun handleNewClosedGroup(sender: String, groupPublicKey: String, name: String, encryptionKeyPair: ECKeyPair, members: List, admins: List, formationTimestamp: Long) { val context = MessagingConfiguration.shared.context val storage = MessagingConfiguration.shared.storage // Create the group @@ -236,7 +236,7 @@ private fun handleNewClosedGroup(sender: String, groupPublicKey: String, name: S storage.updateMembers(groupID, members.map { Address.fromSerialized(it) }) } else { storage.createGroup(groupID, name, LinkedList(members.map { Address.fromSerialized(it) }), - null, null, LinkedList(admins.map { Address.fromSerialized(it) })) + null, null, LinkedList(admins.map { Address.fromSerialized(it) }), formationTimestamp) // Notify the user storage.insertIncomingInfoMessage(context, sender, groupID, SignalServiceProtos.GroupContext.Type.UPDATE, SignalServiceGroup.Type.UPDATE, name, members, admins) } @@ -498,7 +498,7 @@ private fun isValidGroupUpdate(group: GroupRecord, senderPublicKey: String): Boolean { val oldMembers = group.members.map { it.serialize() } // Check that the message isn't from before the group was created - if (group.createdAt > sentTimestamp) { + if (group.formationTimestamp > sentTimestamp) { android.util.Log.d("Loki", "Ignoring closed group update from before thread was created.") return false } diff --git a/libsession/src/main/java/org/session/libsession/messaging/threads/GroupRecord.kt b/libsession/src/main/java/org/session/libsession/messaging/threads/GroupRecord.kt index 28a64929f3..5e09d30ee5 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/threads/GroupRecord.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/threads/GroupRecord.kt @@ -9,7 +9,7 @@ class GroupRecord( val encodedId: String, val title: String, members: String?, val avatar: ByteArray?, val avatarId: Long?, val avatarKey: ByteArray?, val avatarContentType: String?, val relay: String?, val isActive: Boolean, val avatarDigest: ByteArray?, val isMms: Boolean, - val url: String?, admins: String?, val createdAt: Long + val url: String?, admins: String?, val formationTimestamp: Long ) { var members: List
= LinkedList
() var admins: List
= LinkedList
()