Make sure to skip handling legacy group messages post deprecation (#932)

* Make sure to skip handling legacy group messages post deprecation

* Renamed
pull/1709/head
SessionHero01 3 months ago committed by GitHub
parent 68061e1f78
commit 9755d252a6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -44,6 +44,7 @@ import org.conscrypt.Conscrypt;
import org.session.libsession.database.MessageDataProvider; import org.session.libsession.database.MessageDataProvider;
import org.session.libsession.messaging.MessagingModuleConfiguration; import org.session.libsession.messaging.MessagingModuleConfiguration;
import org.session.libsession.messaging.groups.GroupManagerV2; import org.session.libsession.messaging.groups.GroupManagerV2;
import org.session.libsession.messaging.groups.LegacyGroupDeprecationManager;
import org.session.libsession.messaging.notifications.TokenFetcher; import org.session.libsession.messaging.notifications.TokenFetcher;
import org.session.libsession.messaging.sending_receiving.notifications.MessageNotifier; import org.session.libsession.messaging.sending_receiving.notifications.MessageNotifier;
import org.session.libsession.messaging.sending_receiving.pollers.LegacyClosedGroupPollerV2; import org.session.libsession.messaging.sending_receiving.pollers.LegacyClosedGroupPollerV2;
@ -171,6 +172,7 @@ public class ApplicationContext extends Application implements DefaultLifecycleO
@Inject LokiAPIDatabase apiDB; @Inject LokiAPIDatabase apiDB;
@Inject EmojiSearchDatabase emojiSearchDb; @Inject EmojiSearchDatabase emojiSearchDb;
@Inject LegacyClosedGroupPollerV2 legacyClosedGroupPollerV2; @Inject LegacyClosedGroupPollerV2 legacyClosedGroupPollerV2;
@Inject LegacyGroupDeprecationManager legacyGroupDeprecationManager;
public volatile boolean isAppVisible; public volatile boolean isAppVisible;
public String KEYGUARD_LOCK_TAG = NonTranslatableStringConstants.APP_NAME + ":KeyguardLock"; public String KEYGUARD_LOCK_TAG = NonTranslatableStringConstants.APP_NAME + ":KeyguardLock";
@ -259,7 +261,8 @@ public class ApplicationContext extends Application implements DefaultLifecycleO
groupManagerV2, groupManagerV2,
snodeClock, snodeClock,
textSecurePreferences, textSecurePreferences,
legacyClosedGroupPollerV2 legacyClosedGroupPollerV2,
legacyGroupDeprecationManager
); );
callMessageProcessor = new CallMessageProcessor(this, textSecurePreferences, ProcessLifecycleOwner.get().getLifecycle(), storage); callMessageProcessor = new CallMessageProcessor(this, textSecurePreferences, ProcessLifecycleOwner.get().getLifecycle(), storage);
Log.i(TAG, "onCreate()"); Log.i(TAG, "onCreate()");

@ -6,6 +6,7 @@ import org.session.libsession.database.MessageDataProvider
import org.session.libsession.database.StorageProtocol import org.session.libsession.database.StorageProtocol
import org.session.libsession.messaging.groups.GroupManagerV2 import org.session.libsession.messaging.groups.GroupManagerV2
import org.session.libsession.messaging.groups.GroupScope import org.session.libsession.messaging.groups.GroupScope
import org.session.libsession.messaging.groups.LegacyGroupDeprecationManager
import org.session.libsession.messaging.notifications.TokenFetcher import org.session.libsession.messaging.notifications.TokenFetcher
import org.session.libsession.messaging.sending_receiving.pollers.LegacyClosedGroupPollerV2 import org.session.libsession.messaging.sending_receiving.pollers.LegacyClosedGroupPollerV2
import org.session.libsession.snode.OwnedSwarmAuth import org.session.libsession.snode.OwnedSwarmAuth
@ -29,6 +30,7 @@ class MessagingModuleConfiguration(
val clock: SnodeClock, val clock: SnodeClock,
val preferences: TextSecurePreferences, val preferences: TextSecurePreferences,
val legacyClosedGroupPollerV2: LegacyClosedGroupPollerV2, val legacyClosedGroupPollerV2: LegacyClosedGroupPollerV2,
val deprecationManager: LegacyGroupDeprecationManager,
) { ) {
companion object { companion object {

@ -11,7 +11,7 @@ import org.session.libsession.messaging.messages.Destination
import org.session.libsession.messaging.messages.Message import org.session.libsession.messaging.messages.Message
import org.session.libsession.messaging.messages.Message.Companion.senderOrSync import org.session.libsession.messaging.messages.Message.Companion.senderOrSync
import org.session.libsession.messaging.messages.control.CallMessage import org.session.libsession.messaging.messages.control.CallMessage
import org.session.libsession.messaging.messages.control.ClosedGroupControlMessage import org.session.libsession.messaging.messages.control.LegacyGroupControlMessage
import org.session.libsession.messaging.messages.control.ConfigurationMessage import org.session.libsession.messaging.messages.control.ConfigurationMessage
import org.session.libsession.messaging.messages.control.DataExtractionNotification import org.session.libsession.messaging.messages.control.DataExtractionNotification
import org.session.libsession.messaging.messages.control.ExpirationTimerUpdate import org.session.libsession.messaging.messages.control.ExpirationTimerUpdate
@ -82,7 +82,7 @@ class BatchMessageReceiveJob(
else { // message is control message otherwise else { // message is control message otherwise
return when(message) { return when(message) {
is SharedConfigurationMessage -> false is SharedConfigurationMessage -> false
is ClosedGroupControlMessage -> false // message.kind is ClosedGroupControlMessage.Kind.New && !message.isSenderSelf is LegacyGroupControlMessage -> false // message.kind is ClosedGroupControlMessage.Kind.New && !message.isSenderSelf
is DataExtractionNotification -> false is DataExtractionNotification -> false
is MessageRequestResponse -> false is MessageRequestResponse -> false
is ExpirationTimerUpdate -> false is ExpirationTimerUpdate -> false

@ -2,7 +2,7 @@ package org.session.libsession.messaging.jobs
import kotlinx.coroutines.channels.SendChannel import kotlinx.coroutines.channels.SendChannel
import org.session.libsession.messaging.MessagingModuleConfiguration import org.session.libsession.messaging.MessagingModuleConfiguration
import org.session.libsession.messaging.messages.control.ClosedGroupControlMessage import org.session.libsession.messaging.messages.control.LegacyGroupControlMessage
import org.session.libsession.messaging.sending_receiving.MessageReceiver import org.session.libsession.messaging.sending_receiving.MessageReceiver
import org.session.libsession.messaging.sending_receiving.MessageSender import org.session.libsession.messaging.sending_receiving.MessageSender
import org.session.libsession.messaging.sending_receiving.disableLocalGroupAndUnsubscribe import org.session.libsession.messaging.sending_receiving.disableLocalGroupAndUnsubscribe
@ -45,7 +45,7 @@ class GroupLeavingJob(
val admins = group.admins.map { it.serialize() } val admins = group.admins.map { it.serialize() }
val name = group.title val name = group.title
// Send the update to the group // Send the update to the group
val closedGroupControlMessage = ClosedGroupControlMessage(ClosedGroupControlMessage.Kind.MemberLeft()) val closedGroupControlMessage = LegacyGroupControlMessage(LegacyGroupControlMessage.Kind.MemberLeft())
val sentTime = SnodeAPI.nowWithOffset val sentTime = SnodeAPI.nowWithOffset
closedGroupControlMessage.sentTimestamp = sentTime closedGroupControlMessage.sentTimestamp = sentTime
storage.setActive(groupID, false) storage.setActive(groupID, false)

@ -17,7 +17,7 @@ import org.session.libsignal.utilities.Log
import org.session.libsignal.utilities.removingIdPrefixIfNeeded import org.session.libsignal.utilities.removingIdPrefixIfNeeded
import org.session.libsignal.utilities.toHexString import org.session.libsignal.utilities.toHexString
class ClosedGroupControlMessage() : ControlMessage() { class LegacyGroupControlMessage() : ControlMessage() {
var kind: Kind? = null var kind: Kind? = null
var groupID: String? = null var groupID: String? = null
@ -85,7 +85,7 @@ class ClosedGroupControlMessage() : ControlMessage() {
companion object { companion object {
const val TAG = "ClosedGroupControlMessage" const val TAG = "ClosedGroupControlMessage"
fun fromProto(proto: SignalServiceProtos.Content): ClosedGroupControlMessage? = fun fromProto(proto: SignalServiceProtos.Content): LegacyGroupControlMessage? =
proto.takeIf { it.hasDataMessage() }?.dataMessage proto.takeIf { it.hasDataMessage() }?.dataMessage
?.takeIf { it.hasClosedGroupControlMessage() }?.closedGroupControlMessage ?.takeIf { it.hasClosedGroupControlMessage() }?.closedGroupControlMessage
?.run { ?.run {
@ -102,7 +102,7 @@ class ClosedGroupControlMessage() : ControlMessage() {
MEMBERS_REMOVED -> Kind.MembersRemoved(membersList) MEMBERS_REMOVED -> Kind.MembersRemoved(membersList)
MEMBER_LEFT -> Kind.MemberLeft() MEMBER_LEFT -> Kind.MemberLeft()
else -> null else -> null
}?.let(::ClosedGroupControlMessage) }?.let(::LegacyGroupControlMessage)
} }
} }

@ -3,7 +3,7 @@ package org.session.libsession.messaging.sending_receiving
import org.session.libsession.messaging.MessagingModuleConfiguration import org.session.libsession.messaging.MessagingModuleConfiguration
import org.session.libsession.messaging.messages.Message import org.session.libsession.messaging.messages.Message
import org.session.libsession.messaging.messages.control.CallMessage import org.session.libsession.messaging.messages.control.CallMessage
import org.session.libsession.messaging.messages.control.ClosedGroupControlMessage import org.session.libsession.messaging.messages.control.LegacyGroupControlMessage
import org.session.libsession.messaging.messages.control.ConfigurationMessage import org.session.libsession.messaging.messages.control.ConfigurationMessage
import org.session.libsession.messaging.messages.control.DataExtractionNotification import org.session.libsession.messaging.messages.control.DataExtractionNotification
import org.session.libsession.messaging.messages.control.ExpirationTimerUpdate import org.session.libsession.messaging.messages.control.ExpirationTimerUpdate
@ -144,7 +144,7 @@ object MessageReceiver {
// Parse the message // Parse the message
val message: Message = ReadReceipt.fromProto(proto) ?: val message: Message = ReadReceipt.fromProto(proto) ?:
TypingIndicator.fromProto(proto) ?: TypingIndicator.fromProto(proto) ?:
ClosedGroupControlMessage.fromProto(proto) ?: LegacyGroupControlMessage.fromProto(proto) ?:
DataExtractionNotification.fromProto(proto) ?: DataExtractionNotification.fromProto(proto) ?:
ExpirationTimerUpdate.fromProto(proto, closedGroupSessionId != null) ?: ExpirationTimerUpdate.fromProto(proto, closedGroupSessionId != null) ?:
ConfigurationMessage.fromProto(proto) ?: ConfigurationMessage.fromProto(proto) ?:
@ -189,7 +189,7 @@ object MessageReceiver {
if (groupPublicKey != null && groupPublicKey !in (currentClosedGroups ?: emptySet()) && groupPublicKey?.startsWith(IdPrefix.GROUP.value) != true) { if (groupPublicKey != null && groupPublicKey !in (currentClosedGroups ?: emptySet()) && groupPublicKey?.startsWith(IdPrefix.GROUP.value) != true) {
throw Error.NoGroupThread throw Error.NoGroupThread
} }
if ((message is ClosedGroupControlMessage && message.kind is ClosedGroupControlMessage.Kind.New) || message is SharedConfigurationMessage) { if ((message is LegacyGroupControlMessage && message.kind is LegacyGroupControlMessage.Kind.New) || message is SharedConfigurationMessage) {
// Allow duplicates in this case to avoid the following situation: // Allow duplicates in this case to avoid the following situation:
// • The app performed a background poll or received a push notification // • The app performed a background poll or received a push notification
// • This method was invoked and the received message timestamps table was updated // • This method was invoked and the received message timestamps table was updated

@ -16,7 +16,7 @@ import org.session.libsession.messaging.jobs.MessageSendJob
import org.session.libsession.messaging.messages.Destination import org.session.libsession.messaging.messages.Destination
import org.session.libsession.messaging.messages.Message import org.session.libsession.messaging.messages.Message
import org.session.libsession.messaging.messages.applyExpiryMode import org.session.libsession.messaging.messages.applyExpiryMode
import org.session.libsession.messaging.messages.control.ClosedGroupControlMessage import org.session.libsession.messaging.messages.control.LegacyGroupControlMessage
import org.session.libsession.messaging.messages.control.ConfigurationMessage import org.session.libsession.messaging.messages.control.ConfigurationMessage
import org.session.libsession.messaging.messages.control.ExpirationTimerUpdate import org.session.libsession.messaging.messages.control.ExpirationTimerUpdate
import org.session.libsession.messaging.messages.control.GroupUpdated import org.session.libsession.messaging.messages.control.GroupUpdated
@ -129,7 +129,7 @@ object MessageSender {
// • a sync message // • a sync message
// • a closed group control message of type `new` // • a closed group control message of type `new`
var isNewClosedGroupControlMessage = false var isNewClosedGroupControlMessage = false
if (message is ClosedGroupControlMessage && message.kind is ClosedGroupControlMessage.Kind.New) isNewClosedGroupControlMessage = if (message is LegacyGroupControlMessage && message.kind is LegacyGroupControlMessage.Kind.New) isNewClosedGroupControlMessage =
true true
if (isSelfSend if (isSelfSend
&& message !is ConfigurationMessage && message !is ConfigurationMessage
@ -291,7 +291,7 @@ object MessageSender {
isSyncMessage: Boolean isSyncMessage: Boolean
): Long? { ): Long? {
// For ClosedGroupControlMessage or GroupUpdateMemberLeftMessage, the expiration timer doesn't apply // For ClosedGroupControlMessage or GroupUpdateMemberLeftMessage, the expiration timer doesn't apply
if (message is ClosedGroupControlMessage || ( if (message is LegacyGroupControlMessage || (
message is GroupUpdated && ( message is GroupUpdated && (
message.inner.hasMemberLeftMessage() || message.inner.hasMemberLeftMessage() ||
message.inner.hasInviteMessage() || message.inner.hasInviteMessage() ||

@ -9,10 +9,9 @@ import nl.komponents.kovenant.Promise
import org.session.libsession.messaging.MessagingModuleConfiguration import org.session.libsession.messaging.MessagingModuleConfiguration
import org.session.libsession.messaging.jobs.GroupLeavingJob import org.session.libsession.messaging.jobs.GroupLeavingJob
import org.session.libsession.messaging.jobs.JobQueue import org.session.libsession.messaging.jobs.JobQueue
import org.session.libsession.messaging.messages.control.ClosedGroupControlMessage import org.session.libsession.messaging.messages.control.LegacyGroupControlMessage
import org.session.libsession.messaging.sending_receiving.MessageSender.Error import org.session.libsession.messaging.sending_receiving.MessageSender.Error
import org.session.libsession.messaging.sending_receiving.notifications.PushRegistryV1 import org.session.libsession.messaging.sending_receiving.notifications.PushRegistryV1
import org.session.libsession.messaging.sending_receiving.pollers.LegacyClosedGroupPollerV2
import org.session.libsession.snode.SnodeAPI import org.session.libsession.snode.SnodeAPI
import org.session.libsession.snode.utilities.asyncPromise import org.session.libsession.snode.utilities.asyncPromise
import org.session.libsession.snode.utilities.await import org.session.libsession.snode.utilities.await
@ -59,7 +58,7 @@ fun MessageSender.create(
storage.setProfileSharing(Address.fromSerialized(groupID), true) storage.setProfileSharing(Address.fromSerialized(groupID), true)
// Send a closed group update message to all members individually // Send a closed group update message to all members individually
val closedGroupUpdateKind = ClosedGroupControlMessage.Kind.New(ByteString.copyFrom(Hex.fromStringCondensed(groupPublicKey)), name, encryptionKeyPair, membersAsData, adminsAsData, 0) val closedGroupUpdateKind = LegacyGroupControlMessage.Kind.New(ByteString.copyFrom(Hex.fromStringCondensed(groupPublicKey)), name, encryptionKeyPair, membersAsData, adminsAsData, 0)
val sentTime = SnodeAPI.nowWithOffset val sentTime = SnodeAPI.nowWithOffset
// Add the group to the user's set of public keys to poll for // Add the group to the user's set of public keys to poll for
@ -78,7 +77,7 @@ fun MessageSender.create(
val ourPubKey = storage.getUserPublicKey() val ourPubKey = storage.getUserPublicKey()
for (member in members) { for (member in members) {
val closedGroupControlMessage = ClosedGroupControlMessage(closedGroupUpdateKind, groupID) val closedGroupControlMessage = LegacyGroupControlMessage(closedGroupUpdateKind, groupID)
closedGroupControlMessage.sentTimestamp = sentTime closedGroupControlMessage.sentTimestamp = sentTime
try { try {
sendNonDurably(closedGroupControlMessage, fromSerialized(member), member == ourPubKey) sendNonDurably(closedGroupControlMessage, fromSerialized(member), member == ourPubKey)
@ -115,9 +114,9 @@ fun MessageSender.setName(groupPublicKey: String, newName: String) {
val members = group.members.map { it.serialize() }.toSet() val members = group.members.map { it.serialize() }.toSet()
val admins = group.admins.map { it.serialize() } val admins = group.admins.map { it.serialize() }
// Send the update to the group // Send the update to the group
val kind = ClosedGroupControlMessage.Kind.NameChange(newName) val kind = LegacyGroupControlMessage.Kind.NameChange(newName)
val sentTime = SnodeAPI.nowWithOffset val sentTime = SnodeAPI.nowWithOffset
val closedGroupControlMessage = ClosedGroupControlMessage(kind, groupID) val closedGroupControlMessage = LegacyGroupControlMessage(kind, groupID)
closedGroupControlMessage.sentTimestamp = sentTime closedGroupControlMessage.sentTimestamp = sentTime
send(closedGroupControlMessage, Address.fromSerialized(groupID)) send(closedGroupControlMessage, Address.fromSerialized(groupID))
// Update the group // Update the group
@ -155,14 +154,14 @@ fun MessageSender.addMembers(groupPublicKey: String, membersToAdd: List<String>)
} }
val name = group.title val name = group.title
// Send the update to the group // Send the update to the group
val memberUpdateKind = ClosedGroupControlMessage.Kind.MembersAdded(newMembersAsData) val memberUpdateKind = LegacyGroupControlMessage.Kind.MembersAdded(newMembersAsData)
val sentTime = SnodeAPI.nowWithOffset val sentTime = SnodeAPI.nowWithOffset
val closedGroupControlMessage = ClosedGroupControlMessage(memberUpdateKind, groupID) val closedGroupControlMessage = LegacyGroupControlMessage(memberUpdateKind, groupID)
closedGroupControlMessage.sentTimestamp = sentTime closedGroupControlMessage.sentTimestamp = sentTime
send(closedGroupControlMessage, Address.fromSerialized(groupID)) send(closedGroupControlMessage, Address.fromSerialized(groupID))
// Send closed group update messages to any new members individually // Send closed group update messages to any new members individually
for (member in membersToAdd) { for (member in membersToAdd) {
val closedGroupNewKind = ClosedGroupControlMessage.Kind.New( val closedGroupNewKind = LegacyGroupControlMessage.Kind.New(
ByteString.copyFrom(Hex.fromStringCondensed(groupPublicKey)), ByteString.copyFrom(Hex.fromStringCondensed(groupPublicKey)),
name, name,
encryptionKeyPair, encryptionKeyPair,
@ -170,7 +169,7 @@ fun MessageSender.addMembers(groupPublicKey: String, membersToAdd: List<String>)
adminsAsData, adminsAsData,
expireTimer.toInt() expireTimer.toInt()
) )
val closedGroupControlMessage = ClosedGroupControlMessage(closedGroupNewKind, groupID) val closedGroupControlMessage = LegacyGroupControlMessage(closedGroupNewKind, groupID)
// It's important that the sent timestamp of this message is greater than the sent timestamp // It's important that the sent timestamp of this message is greater than the sent timestamp
// of the `MembersAdded` message above. The reason is that upon receiving this `New` message, // of the `MembersAdded` message above. The reason is that upon receiving this `New` message,
// the recipient will update the closed group formation timestamp and ignore any closed group // the recipient will update the closed group formation timestamp and ignore any closed group
@ -217,9 +216,9 @@ fun MessageSender.removeMembers(groupPublicKey: String, membersToRemove: List<St
val removeMembersAsData = membersToRemove.map { ByteString.copyFrom(Hex.fromStringCondensed(it)) } val removeMembersAsData = membersToRemove.map { ByteString.copyFrom(Hex.fromStringCondensed(it)) }
val name = group.title val name = group.title
// Send the update to the group // Send the update to the group
val memberUpdateKind = ClosedGroupControlMessage.Kind.MembersRemoved(removeMembersAsData) val memberUpdateKind = LegacyGroupControlMessage.Kind.MembersRemoved(removeMembersAsData)
val sentTime = SnodeAPI.nowWithOffset val sentTime = SnodeAPI.nowWithOffset
val closedGroupControlMessage = ClosedGroupControlMessage(memberUpdateKind, groupID) val closedGroupControlMessage = LegacyGroupControlMessage(memberUpdateKind, groupID)
closedGroupControlMessage.sentTimestamp = sentTime closedGroupControlMessage.sentTimestamp = sentTime
send(closedGroupControlMessage, Address.fromSerialized(groupID)) send(closedGroupControlMessage, Address.fromSerialized(groupID))
// Send the new encryption key pair to the remaining group members. // Send the new encryption key pair to the remaining group members.
@ -280,11 +279,11 @@ fun MessageSender.sendEncryptionKeyPair(groupPublicKey: String, newKeyPair: ECKe
val plaintext = proto.build().toByteArray() val plaintext = proto.build().toByteArray()
val wrappers = targetMembers.map { publicKey -> val wrappers = targetMembers.map { publicKey ->
val ciphertext = MessageEncrypter.encrypt(plaintext, publicKey) val ciphertext = MessageEncrypter.encrypt(plaintext, publicKey)
ClosedGroupControlMessage.KeyPairWrapper(publicKey, ByteString.copyFrom(ciphertext)) LegacyGroupControlMessage.KeyPairWrapper(publicKey, ByteString.copyFrom(ciphertext))
} }
val kind = ClosedGroupControlMessage.Kind.EncryptionKeyPair(ByteString.copyFrom(Hex.fromStringCondensed(groupPublicKey)), wrappers) val kind = LegacyGroupControlMessage.Kind.EncryptionKeyPair(ByteString.copyFrom(Hex.fromStringCondensed(groupPublicKey)), wrappers)
val sentTime = SnodeAPI.nowWithOffset val sentTime = SnodeAPI.nowWithOffset
val closedGroupControlMessage = ClosedGroupControlMessage(kind, null) val closedGroupControlMessage = LegacyGroupControlMessage(kind, null)
closedGroupControlMessage.sentTimestamp = sentTime closedGroupControlMessage.sentTimestamp = sentTime
return if (force) { return if (force) {
val isSync = MessagingModuleConfiguration.shared.storage.getUserPublicKey() == destination val isSync = MessagingModuleConfiguration.shared.storage.getUserPublicKey() == destination
@ -317,8 +316,8 @@ fun MessageSender.sendLatestEncryptionKeyPair(publicKey: String, groupPublicKey:
val plaintext = proto.build().toByteArray() val plaintext = proto.build().toByteArray()
val ciphertext = MessageEncrypter.encrypt(plaintext, publicKey) val ciphertext = MessageEncrypter.encrypt(plaintext, publicKey)
Log.d("Loki", "Sending latest encryption key pair to: $publicKey.") Log.d("Loki", "Sending latest encryption key pair to: $publicKey.")
val wrapper = ClosedGroupControlMessage.KeyPairWrapper(publicKey, ByteString.copyFrom(ciphertext)) val wrapper = LegacyGroupControlMessage.KeyPairWrapper(publicKey, ByteString.copyFrom(ciphertext))
val kind = ClosedGroupControlMessage.Kind.EncryptionKeyPair(ByteString.copyFrom(Hex.fromStringCondensed(groupPublicKey)), listOf(wrapper)) val kind = LegacyGroupControlMessage.Kind.EncryptionKeyPair(ByteString.copyFrom(Hex.fromStringCondensed(groupPublicKey)), listOf(wrapper))
val closedGroupControlMessage = ClosedGroupControlMessage(kind, groupID) val closedGroupControlMessage = LegacyGroupControlMessage(kind, groupID)
MessageSender.send(closedGroupControlMessage, Address.fromSerialized(publicKey)) MessageSender.send(closedGroupControlMessage, Address.fromSerialized(publicKey))
} }

@ -10,6 +10,7 @@ import org.session.libsession.R
import org.session.libsession.avatars.AvatarHelper import org.session.libsession.avatars.AvatarHelper
import org.session.libsession.database.userAuth import org.session.libsession.database.userAuth
import org.session.libsession.messaging.MessagingModuleConfiguration import org.session.libsession.messaging.MessagingModuleConfiguration
import org.session.libsession.messaging.groups.LegacyGroupDeprecationManager
import org.session.libsession.messaging.jobs.AttachmentDownloadJob import org.session.libsession.messaging.jobs.AttachmentDownloadJob
import org.session.libsession.messaging.jobs.BackgroundGroupAddJob import org.session.libsession.messaging.jobs.BackgroundGroupAddJob
import org.session.libsession.messaging.jobs.JobQueue import org.session.libsession.messaging.jobs.JobQueue
@ -17,7 +18,7 @@ import org.session.libsession.messaging.messages.ExpirationConfiguration
import org.session.libsession.messaging.messages.ExpirationConfiguration.Companion.isNewConfigEnabled import org.session.libsession.messaging.messages.ExpirationConfiguration.Companion.isNewConfigEnabled
import org.session.libsession.messaging.messages.Message import org.session.libsession.messaging.messages.Message
import org.session.libsession.messaging.messages.control.CallMessage import org.session.libsession.messaging.messages.control.CallMessage
import org.session.libsession.messaging.messages.control.ClosedGroupControlMessage import org.session.libsession.messaging.messages.control.LegacyGroupControlMessage
import org.session.libsession.messaging.messages.control.ConfigurationMessage import org.session.libsession.messaging.messages.control.ConfigurationMessage
import org.session.libsession.messaging.messages.control.DataExtractionNotification import org.session.libsession.messaging.messages.control.DataExtractionNotification
import org.session.libsession.messaging.messages.control.ExpirationTimerUpdate import org.session.libsession.messaging.messages.control.ExpirationTimerUpdate
@ -34,7 +35,6 @@ import org.session.libsession.messaging.sending_receiving.attachments.PointerAtt
import org.session.libsession.messaging.sending_receiving.data_extraction.DataExtractionNotificationInfoMessage import org.session.libsession.messaging.sending_receiving.data_extraction.DataExtractionNotificationInfoMessage
import org.session.libsession.messaging.sending_receiving.link_preview.LinkPreview import org.session.libsession.messaging.sending_receiving.link_preview.LinkPreview
import org.session.libsession.messaging.sending_receiving.notifications.PushRegistryV1 import org.session.libsession.messaging.sending_receiving.notifications.PushRegistryV1
import org.session.libsession.messaging.sending_receiving.pollers.LegacyClosedGroupPollerV2
import org.session.libsession.messaging.sending_receiving.quotes.QuoteModel import org.session.libsession.messaging.sending_receiving.quotes.QuoteModel
import org.session.libsession.messaging.utilities.MessageAuthentication.buildDeleteMemberContentSignature import org.session.libsession.messaging.utilities.MessageAuthentication.buildDeleteMemberContentSignature
import org.session.libsession.messaging.utilities.MessageAuthentication.buildGroupInviteSignature import org.session.libsession.messaging.utilities.MessageAuthentication.buildGroupInviteSignature
@ -83,7 +83,7 @@ fun MessageReceiver.handle(message: Message, proto: SignalServiceProtos.Content,
when (message) { when (message) {
is ReadReceipt -> handleReadReceipt(message) is ReadReceipt -> handleReadReceipt(message)
is TypingIndicator -> handleTypingIndicator(message) is TypingIndicator -> handleTypingIndicator(message)
is ClosedGroupControlMessage -> handleClosedGroupControlMessage(message) is LegacyGroupControlMessage -> handleLegacyGroupControlMessage(message)
is GroupUpdated -> handleGroupUpdated(message, groupv2Id) is GroupUpdated -> handleGroupUpdated(message, groupv2Id)
is ExpirationTimerUpdate -> { is ExpirationTimerUpdate -> {
// For groupsv2, there are dedicated mechanisms for handling expiration timers, and // For groupsv2, there are dedicated mechanisms for handling expiration timers, and
@ -234,7 +234,7 @@ private fun handleConfigurationMessage(message: ConfigurationMessage) {
storage.addClosedGroupEncryptionKeyPair(closedGroup.encryptionKeyPair!!, closedGroup.publicKey, message.sentTimestamp!!) storage.addClosedGroupEncryptionKeyPair(closedGroup.encryptionKeyPair!!, closedGroup.publicKey, message.sentTimestamp!!)
} else { } else {
// only handle new closed group if it's first time sync // only handle new closed group if it's first time sync
handleNewClosedGroup(message.sender!!, message.sentTimestamp!!, closedGroup.publicKey, closedGroup.name, handleNewLegacyGroup(message.sender!!, message.sentTimestamp!!, closedGroup.publicKey, closedGroup.name,
closedGroup.encryptionKeyPair!!, closedGroup.members, closedGroup.admins, message.sentTimestamp!!, -1) closedGroup.encryptionKeyPair!!, closedGroup.members, closedGroup.admins, message.sentTimestamp!!, -1)
} }
} }
@ -587,17 +587,23 @@ fun MessageReceiver.handleOpenGroupReactions(
//endregion //endregion
// region Closed Groups // region Closed Groups
private fun MessageReceiver.handleClosedGroupControlMessage(message: ClosedGroupControlMessage) { private fun MessageReceiver.handleLegacyGroupControlMessage(message: LegacyGroupControlMessage) {
if (MessagingModuleConfiguration.shared.deprecationManager.deprecationState.value ==
LegacyGroupDeprecationManager.DeprecationState.DEPRECATED) {
Log.d("ClosedGroupControlMessage", "Ignoring closed group control message post deprecation")
return
}
when (message.kind!!) { when (message.kind!!) {
is ClosedGroupControlMessage.Kind.New -> handleNewClosedGroup(message) is LegacyGroupControlMessage.Kind.New -> handleNewLegacyGroup(message)
is ClosedGroupControlMessage.Kind.EncryptionKeyPair -> handleClosedGroupEncryptionKeyPair(message) is LegacyGroupControlMessage.Kind.EncryptionKeyPair -> handleClosedGroupEncryptionKeyPair(message)
is ClosedGroupControlMessage.Kind.NameChange -> handleClosedGroupNameChanged(message) is LegacyGroupControlMessage.Kind.NameChange -> handleClosedGroupNameChanged(message)
is ClosedGroupControlMessage.Kind.MembersAdded -> handleClosedGroupMembersAdded(message) is LegacyGroupControlMessage.Kind.MembersAdded -> handleClosedGroupMembersAdded(message)
is ClosedGroupControlMessage.Kind.MembersRemoved -> handleClosedGroupMembersRemoved(message) is LegacyGroupControlMessage.Kind.MembersRemoved -> handleClosedGroupMembersRemoved(message)
is ClosedGroupControlMessage.Kind.MemberLeft -> handleClosedGroupMemberLeft(message) is LegacyGroupControlMessage.Kind.MemberLeft -> handleClosedGroupMemberLeft(message)
} }
if ( if (
message.kind !is ClosedGroupControlMessage.Kind.New && message.kind !is LegacyGroupControlMessage.Kind.New &&
MessagingModuleConfiguration.shared.storage.canPerformConfigChange( MessagingModuleConfiguration.shared.storage.canPerformConfigChange(
SharedConfigMessage.Kind.GROUPS.name, SharedConfigMessage.Kind.GROUPS.name,
MessagingModuleConfiguration.shared.storage.getUserPublicKey()!!, MessagingModuleConfiguration.shared.storage.getUserPublicKey()!!,
@ -611,13 +617,13 @@ private fun MessageReceiver.handleClosedGroupControlMessage(message: ClosedGroup
} }
} }
private fun ClosedGroupControlMessage.getPublicKey(): String = kind!!.let { when (it) { private fun LegacyGroupControlMessage.getPublicKey(): String = kind!!.let { when (it) {
is ClosedGroupControlMessage.Kind.New -> it.publicKey.toByteArray().toHexString() is LegacyGroupControlMessage.Kind.New -> it.publicKey.toByteArray().toHexString()
is ClosedGroupControlMessage.Kind.EncryptionKeyPair -> it.publicKey?.toByteArray()?.toHexString() ?: groupPublicKey!! is LegacyGroupControlMessage.Kind.EncryptionKeyPair -> it.publicKey?.toByteArray()?.toHexString() ?: groupPublicKey!!
is ClosedGroupControlMessage.Kind.MemberLeft -> groupPublicKey!! is LegacyGroupControlMessage.Kind.MemberLeft -> groupPublicKey!!
is ClosedGroupControlMessage.Kind.MembersAdded -> groupPublicKey!! is LegacyGroupControlMessage.Kind.MembersAdded -> groupPublicKey!!
is ClosedGroupControlMessage.Kind.MembersRemoved -> groupPublicKey!! is LegacyGroupControlMessage.Kind.MembersRemoved -> groupPublicKey!!
is ClosedGroupControlMessage.Kind.NameChange -> groupPublicKey!! is LegacyGroupControlMessage.Kind.NameChange -> groupPublicKey!!
}} }}
private fun MessageReceiver.handleGroupUpdated(message: GroupUpdated, closedGroup: AccountId?) { private fun MessageReceiver.handleGroupUpdated(message: GroupUpdated, closedGroup: AccountId?) {
@ -806,9 +812,9 @@ private fun verifyAdminSignature(groupSessionId: AccountId, signatureData: ByteA
} }
} }
private fun MessageReceiver.handleNewClosedGroup(message: ClosedGroupControlMessage) { private fun MessageReceiver.handleNewLegacyGroup(message: LegacyGroupControlMessage) {
val storage = MessagingModuleConfiguration.shared.storage val storage = MessagingModuleConfiguration.shared.storage
val kind = message.kind!! as? ClosedGroupControlMessage.Kind.New ?: return val kind = message.kind!! as? LegacyGroupControlMessage.Kind.New ?: return
val recipient = Recipient.from(MessagingModuleConfiguration.shared.context, Address.fromSerialized(message.sender!!), false) val recipient = Recipient.from(MessagingModuleConfiguration.shared.context, Address.fromSerialized(message.sender!!), false)
if (!recipient.isApproved && !recipient.isLocalNumber) return Log.e("Loki", "not accepting new closed group from unapproved recipient") if (!recipient.isApproved && !recipient.isLocalNumber) return Log.e("Loki", "not accepting new closed group from unapproved recipient")
val groupPublicKey = kind.publicKey.toByteArray().toHexString() val groupPublicKey = kind.publicKey.toByteArray().toHexString()
@ -817,10 +823,10 @@ private fun MessageReceiver.handleNewClosedGroup(message: ClosedGroupControlMess
val members = kind.members.map { it.toByteArray().toHexString() } val members = kind.members.map { it.toByteArray().toHexString() }
val admins = kind.admins.map { it.toByteArray().toHexString() } val admins = kind.admins.map { it.toByteArray().toHexString() }
val expirationTimer = kind.expirationTimer val expirationTimer = kind.expirationTimer
handleNewClosedGroup(message.sender!!, message.sentTimestamp!!, groupPublicKey, kind.name, kind.encryptionKeyPair!!, members, admins, message.sentTimestamp!!, expirationTimer) handleNewLegacyGroup(message.sender!!, message.sentTimestamp!!, groupPublicKey, kind.name, kind.encryptionKeyPair!!, members, admins, message.sentTimestamp!!, expirationTimer)
} }
private fun handleNewClosedGroup(sender: String, sentTimestamp: Long, groupPublicKey: String, name: String, encryptionKeyPair: ECKeyPair, members: List<String>, admins: List<String>, formationTimestamp: Long, expirationTimer: Int) { private fun handleNewLegacyGroup(sender: String, sentTimestamp: Long, groupPublicKey: String, name: String, encryptionKeyPair: ECKeyPair, members: List<String>, admins: List<String>, formationTimestamp: Long, expirationTimer: Int) {
val context = MessagingModuleConfiguration.shared.context val context = MessagingModuleConfiguration.shared.context
val storage = MessagingModuleConfiguration.shared.storage val storage = MessagingModuleConfiguration.shared.storage
val userPublicKey = storage.getUserPublicKey()!! val userPublicKey = storage.getUserPublicKey()!!
@ -874,11 +880,11 @@ private fun handleNewClosedGroup(sender: String, sentTimestamp: Long, groupPubli
MessagingModuleConfiguration.shared.legacyClosedGroupPollerV2.startPolling(groupPublicKey) MessagingModuleConfiguration.shared.legacyClosedGroupPollerV2.startPolling(groupPublicKey)
} }
private fun MessageReceiver.handleClosedGroupEncryptionKeyPair(message: ClosedGroupControlMessage) { private fun MessageReceiver.handleClosedGroupEncryptionKeyPair(message: LegacyGroupControlMessage) {
// Prepare // Prepare
val storage = MessagingModuleConfiguration.shared.storage val storage = MessagingModuleConfiguration.shared.storage
val senderPublicKey = message.sender ?: return val senderPublicKey = message.sender ?: return
val kind = message.kind!! as? ClosedGroupControlMessage.Kind.EncryptionKeyPair ?: return val kind = message.kind!! as? LegacyGroupControlMessage.Kind.EncryptionKeyPair ?: return
var groupPublicKey = kind.publicKey?.toByteArray()?.toHexString() var groupPublicKey = kind.publicKey?.toByteArray()?.toHexString()
if (groupPublicKey.isNullOrEmpty()) groupPublicKey = message.groupPublicKey ?: return if (groupPublicKey.isNullOrEmpty()) groupPublicKey = message.groupPublicKey ?: return
val userPublicKey = storage.getUserPublicKey()!! val userPublicKey = storage.getUserPublicKey()!!
@ -914,12 +920,12 @@ private fun MessageReceiver.handleClosedGroupEncryptionKeyPair(message: ClosedGr
Log.d("Loki", "Received a new closed group encryption key pair.") Log.d("Loki", "Received a new closed group encryption key pair.")
} }
private fun MessageReceiver.handleClosedGroupNameChanged(message: ClosedGroupControlMessage) { private fun MessageReceiver.handleClosedGroupNameChanged(message: LegacyGroupControlMessage) {
val context = MessagingModuleConfiguration.shared.context val context = MessagingModuleConfiguration.shared.context
val storage = MessagingModuleConfiguration.shared.storage val storage = MessagingModuleConfiguration.shared.storage
val userPublicKey = TextSecurePreferences.getLocalNumber(context) val userPublicKey = TextSecurePreferences.getLocalNumber(context)
val senderPublicKey = message.sender ?: return val senderPublicKey = message.sender ?: return
val kind = message.kind!! as? ClosedGroupControlMessage.Kind.NameChange ?: return val kind = message.kind!! as? LegacyGroupControlMessage.Kind.NameChange ?: return
val groupPublicKey = message.groupPublicKey ?: return val groupPublicKey = message.groupPublicKey ?: return
// Check that the sender is a member of the group (before the update) // Check that the sender is a member of the group (before the update)
val groupID = GroupUtil.doubleEncodeGroupID(groupPublicKey) val groupID = GroupUtil.doubleEncodeGroupID(groupPublicKey)
@ -953,12 +959,12 @@ private fun MessageReceiver.handleClosedGroupNameChanged(message: ClosedGroupCon
} }
} }
private fun MessageReceiver.handleClosedGroupMembersAdded(message: ClosedGroupControlMessage) { private fun MessageReceiver.handleClosedGroupMembersAdded(message: LegacyGroupControlMessage) {
val context = MessagingModuleConfiguration.shared.context val context = MessagingModuleConfiguration.shared.context
val storage = MessagingModuleConfiguration.shared.storage val storage = MessagingModuleConfiguration.shared.storage
val userPublicKey = storage.getUserPublicKey()!! val userPublicKey = storage.getUserPublicKey()!!
val senderPublicKey = message.sender ?: return val senderPublicKey = message.sender ?: return
val kind = message.kind!! as? ClosedGroupControlMessage.Kind.MembersAdded ?: return val kind = message.kind!! as? LegacyGroupControlMessage.Kind.MembersAdded ?: return
val groupPublicKey = message.groupPublicKey ?: return val groupPublicKey = message.groupPublicKey ?: return
val groupID = GroupUtil.doubleEncodeGroupID(groupPublicKey) val groupID = GroupUtil.doubleEncodeGroupID(groupPublicKey)
val group = storage.getGroup(groupID) ?: run { val group = storage.getGroup(groupID) ?: run {
@ -1026,12 +1032,12 @@ private fun MessageReceiver.handleClosedGroupMembersAdded(message: ClosedGroupCo
/// • the admin sent the message (only the admin can truly remove members). /// • the admin sent the message (only the admin can truly remove members).
/// If we're among the users that were removed, delete all encryption key pairs and the group public key, unsubscribe /// If we're among the users that were removed, delete all encryption key pairs and the group public key, unsubscribe
/// from push notifications for this closed group, and remove the given members from the zombie list for this group. /// from push notifications for this closed group, and remove the given members from the zombie list for this group.
private fun MessageReceiver.handleClosedGroupMembersRemoved(message: ClosedGroupControlMessage) { private fun MessageReceiver.handleClosedGroupMembersRemoved(message: LegacyGroupControlMessage) {
val context = MessagingModuleConfiguration.shared.context val context = MessagingModuleConfiguration.shared.context
val storage = MessagingModuleConfiguration.shared.storage val storage = MessagingModuleConfiguration.shared.storage
val userPublicKey = storage.getUserPublicKey()!! val userPublicKey = storage.getUserPublicKey()!!
val senderPublicKey = message.sender ?: return val senderPublicKey = message.sender ?: return
val kind = message.kind!! as? ClosedGroupControlMessage.Kind.MembersRemoved ?: return val kind = message.kind!! as? LegacyGroupControlMessage.Kind.MembersRemoved ?: return
val groupPublicKey = message.groupPublicKey ?: return val groupPublicKey = message.groupPublicKey ?: return
val groupID = GroupUtil.doubleEncodeGroupID(groupPublicKey) val groupID = GroupUtil.doubleEncodeGroupID(groupPublicKey)
val group = storage.getGroup(groupID) ?: run { val group = storage.getGroup(groupID) ?: run {
@ -1101,12 +1107,12 @@ private fun MessageReceiver.handleClosedGroupMembersRemoved(message: ClosedGroup
/// • Mark them as a zombie (to be removed by the admin later). /// • Mark them as a zombie (to be removed by the admin later).
/// If the admin left: /// If the admin left:
/// • Unsubscribe from PNs, delete the group public key, etc. as the group will be disbanded. /// • Unsubscribe from PNs, delete the group public key, etc. as the group will be disbanded.
private fun MessageReceiver.handleClosedGroupMemberLeft(message: ClosedGroupControlMessage) { private fun MessageReceiver.handleClosedGroupMemberLeft(message: LegacyGroupControlMessage) {
val context = MessagingModuleConfiguration.shared.context val context = MessagingModuleConfiguration.shared.context
val storage = MessagingModuleConfiguration.shared.storage val storage = MessagingModuleConfiguration.shared.storage
val senderPublicKey = message.sender ?: return val senderPublicKey = message.sender ?: return
val userPublicKey = storage.getUserPublicKey()!! val userPublicKey = storage.getUserPublicKey()!!
if (message.kind!! !is ClosedGroupControlMessage.Kind.MemberLeft) return if (message.kind!! !is LegacyGroupControlMessage.Kind.MemberLeft) return
val groupPublicKey = message.groupPublicKey ?: return val groupPublicKey = message.groupPublicKey ?: return
val groupID = GroupUtil.doubleEncodeGroupID(groupPublicKey) val groupID = GroupUtil.doubleEncodeGroupID(groupPublicKey)
val group = storage.getGroup(groupID) ?: run { val group = storage.getGroup(groupID) ?: run {

@ -4,7 +4,7 @@ import android.content.Context
import network.loki.messenger.libsession_util.util.ExpiryMode import network.loki.messenger.libsession_util.util.ExpiryMode
import org.session.libsession.messaging.contacts.Contact import org.session.libsession.messaging.contacts.Contact
import org.session.libsession.messaging.messages.Message import org.session.libsession.messaging.messages.Message
import org.session.libsession.messaging.messages.control.ClosedGroupControlMessage import org.session.libsession.messaging.messages.control.LegacyGroupControlMessage
import org.session.libsession.messaging.messages.control.ExpirationTimerUpdate import org.session.libsession.messaging.messages.control.ExpirationTimerUpdate
import org.session.libsession.messaging.sending_receiving.notifications.MessageNotifier import org.session.libsession.messaging.sending_receiving.notifications.MessageNotifier
import org.session.libsession.snode.SnodeAPI.nowWithOffset import org.session.libsession.snode.SnodeAPI.nowWithOffset
@ -45,7 +45,7 @@ class SSKEnvironment(
fun startAnyExpiration(timestamp: Long, author: String, expireStartedAt: Long) fun startAnyExpiration(timestamp: Long, author: String, expireStartedAt: Long)
fun maybeStartExpiration(message: Message, startDisappearAfterRead: Boolean = false) { fun maybeStartExpiration(message: Message, startDisappearAfterRead: Boolean = false) {
if (message is ExpirationTimerUpdate && message.isGroup || message is ClosedGroupControlMessage) return if (message is ExpirationTimerUpdate && message.isGroup || message is LegacyGroupControlMessage) return
maybeStartExpiration( maybeStartExpiration(
message.sentTimestamp ?: return, message.sentTimestamp ?: return,

Loading…
Cancel
Save