diff --git a/app/src/main/java/org/thoughtcrime/securesms/configs/ConfigUploader.kt b/app/src/main/java/org/thoughtcrime/securesms/configs/ConfigUploader.kt index cc5087c773..25fa26e846 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/configs/ConfigUploader.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/configs/ConfigUploader.kt @@ -235,14 +235,14 @@ class ConfigUploader @Inject constructor( auth, snode, push, - Namespace.CLOSED_GROUP_MEMBERS() + Namespace.GROUP_MEMBERS() ) } } val infoConfigHashTask = infoPush?.let { push -> async { - push to pushConfig(auth, snode, push, Namespace.CLOSED_GROUP_INFO()) + push to pushConfig(auth, snode, push, Namespace.GROUP_INFO()) } } @@ -252,7 +252,7 @@ class ConfigUploader @Inject constructor( snode = snode, publicKey = auth.accountId.hexString, request = SnodeAPI.buildAuthenticatedStoreBatchInfo( - Namespace.ENCRYPTION_KEYS(), + Namespace.GROUP_KEYS(), SnodeMessage( auth.accountId.hexString, Base64.encodeBytes(push), diff --git a/app/src/main/java/org/thoughtcrime/securesms/groups/GroupManagerV2Impl.kt b/app/src/main/java/org/thoughtcrime/securesms/groups/GroupManagerV2Impl.kt index 3025bd3965..17ddfd1c3e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/groups/GroupManagerV2Impl.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/groups/GroupManagerV2Impl.kt @@ -254,7 +254,7 @@ class GroupManagerV2Impl @Inject constructor( val memberKey = configs.groupKeys.supplementFor(newMembers.map { it.hexString }) batchRequests.add( SnodeAPI.buildAuthenticatedStoreBatchInfo( - namespace = Namespace.ENCRYPTION_KEYS(), + namespace = Namespace.GROUP_KEYS(), message = SnodeMessage( recipient = group.hexString, data = Base64.encodeBytes(memberKey), diff --git a/app/src/main/java/org/thoughtcrime/securesms/groups/GroupPoller.kt b/app/src/main/java/org/thoughtcrime/securesms/groups/GroupPoller.kt index 7103779405..c4b53df40b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/groups/GroupPoller.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/groups/GroupPoller.kt @@ -13,7 +13,6 @@ import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch import kotlinx.coroutines.supervisorScope -import network.loki.messenger.libsession_util.util.Sodium import org.session.libsession.database.StorageProtocol import org.session.libsession.messaging.groups.GroupManagerV2 import org.session.libsession.messaging.jobs.BatchMessageReceiveJob @@ -30,7 +29,6 @@ import org.session.libsession.utilities.getGroup import org.session.libsignal.database.LokiAPIDatabaseProtocol import org.session.libsignal.exceptions.NonRetryableException import org.session.libsignal.utilities.AccountId -import org.session.libsignal.utilities.IdPrefix import org.session.libsignal.utilities.Log import org.session.libsignal.utilities.Namespace import org.session.libsignal.utilities.Snode @@ -48,6 +46,7 @@ class GroupPoller( private val lokiApiDatabase: LokiAPIDatabaseProtocol, private val clock: SnodeClock, private val appVisibilityManager: AppVisibilityManager, + private val groupRevokedMessageHandler: GroupRevokedMessageHandler, ) { companion object { private const val POLL_INTERVAL = 3_000L @@ -239,7 +238,7 @@ class GroupPoller( val lastHash = lokiApiDatabase.getLastMessageHashValue( snode, groupId.hexString, - Namespace.CLOSED_GROUP_MESSAGES() + Namespace.GROUP_MESSAGES() ).orEmpty() Log.d(TAG, "Retrieving group message since lastHash = $lastHash") @@ -250,7 +249,7 @@ class GroupPoller( request = SnodeAPI.buildAuthenticatedRetrieveBatchRequest( lastHash = lastHash, auth = groupAuth, - namespace = Namespace.CLOSED_GROUP_MESSAGES(), + namespace = Namespace.GROUP_MESSAGES(), maxSize = null, ), responseType = Map::class.java @@ -258,9 +257,9 @@ class GroupPoller( } val groupConfigRetrieval = listOf( - Namespace.ENCRYPTION_KEYS(), - Namespace.CLOSED_GROUP_INFO(), - Namespace.CLOSED_GROUP_MEMBERS() + Namespace.GROUP_KEYS(), + Namespace.GROUP_INFO(), + Namespace.GROUP_MEMBERS() ).map { ns -> async { SnodeAPI.sendBatchRequest( @@ -288,9 +287,9 @@ class GroupPoller( val result = runCatching { val (keysMessage, infoMessage, membersMessage) = groupConfigRetrieval.map { it.await() } handleGroupConfigMessages(keysMessage, infoMessage, membersMessage) - saveLastMessageHash(snode, keysMessage, Namespace.ENCRYPTION_KEYS()) - saveLastMessageHash(snode, infoMessage, Namespace.CLOSED_GROUP_INFO()) - saveLastMessageHash(snode, membersMessage, Namespace.CLOSED_GROUP_MEMBERS()) + saveLastMessageHash(snode, keysMessage, Namespace.GROUP_KEYS()) + saveLastMessageHash(snode, infoMessage, Namespace.GROUP_INFO()) + saveLastMessageHash(snode, membersMessage, Namespace.GROUP_MEMBERS()) groupExpired = configFactoryProtocol.withGroupConfigs(groupId) { it.groupKeys.size() == 0 @@ -370,40 +369,7 @@ class GroupPoller( } private suspend fun handleRevoked(messages: List) { - messages.forEach { msg -> - val decoded = configFactoryProtocol.decryptForUser( - msg.data, - Sodium.KICKED_DOMAIN, - groupId, - ) - - if (decoded != null) { - // The message should be in the format of "", - // where the pub key is 32 bytes, so we need to have at least 33 bytes of data - if (decoded.size < 33) { - Log.w(TAG, "Received an invalid kicked message, expecting at least 33 bytes, got ${decoded.size}") - return@forEach - } - - val sessionId = AccountId(IdPrefix.STANDARD, decoded.copyOfRange(0, 32)) - val messageGeneration = decoded.copyOfRange(32, decoded.size).decodeToString().toIntOrNull() - if (messageGeneration == null) { - Log.w(TAG, "Received an invalid kicked message: missing message generation") - return@forEach - } - - val currentKeysGeneration = configFactoryProtocol.withGroupConfigs(groupId) { - it.groupKeys.currentGeneration() - } - - val isForMe = sessionId.hexString == storage.getUserPublicKey() - Log.d(TAG, "Received kicked message, for us? ${isForMe}, message key generation = $messageGeneration, our key generation = $currentKeysGeneration") - - if (isForMe && messageGeneration >= currentKeysGeneration) { - groupManagerV2.handleKicked(groupId) - } - } - } + groupRevokedMessageHandler.handleRevokeMessage(groupId, messages.map { it.data }) } private fun handleGroupConfigMessages( @@ -437,7 +403,7 @@ class GroupPoller( snode = snode, publicKey = groupId.hexString, decrypt = it.groupKeys::decrypt, - namespace = Namespace.CLOSED_GROUP_MESSAGES(), + namespace = Namespace.GROUP_MESSAGES(), ) } diff --git a/app/src/main/java/org/thoughtcrime/securesms/groups/GroupPollerManager.kt b/app/src/main/java/org/thoughtcrime/securesms/groups/GroupPollerManager.kt index 3c48cdf30f..5a8b9593dc 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/groups/GroupPollerManager.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/groups/GroupPollerManager.kt @@ -61,6 +61,7 @@ class GroupPollerManager @Inject constructor( preferences: TextSecurePreferences, appVisibilityManager: AppVisibilityManager, connectivity: InternetConnectivity, + groupRevokedMessageHandler: GroupRevokedMessageHandler, ) { @Suppress("OPT_IN_USAGE") private val groupPollers: StateFlow> = @@ -117,6 +118,7 @@ class GroupPollerManager @Inject constructor( lokiApiDatabase = lokiApiDatabase, clock = clock, appVisibilityManager = appVisibilityManager, + groupRevokedMessageHandler = groupRevokedMessageHandler, ), scope = scope ) diff --git a/app/src/main/java/org/thoughtcrime/securesms/groups/GroupRevokedMessageHandler.kt b/app/src/main/java/org/thoughtcrime/securesms/groups/GroupRevokedMessageHandler.kt new file mode 100644 index 0000000000..eee2117809 --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/groups/GroupRevokedMessageHandler.kt @@ -0,0 +1,61 @@ +package org.thoughtcrime.securesms.groups + +import network.loki.messenger.libsession_util.util.Sodium +import org.session.libsession.database.StorageProtocol +import org.session.libsession.messaging.groups.GroupManagerV2 +import org.session.libsession.utilities.ConfigFactoryProtocol +import org.session.libsignal.utilities.AccountId +import org.session.libsignal.utilities.IdPrefix +import org.session.libsignal.utilities.Log +import javax.inject.Inject +import javax.inject.Provider + +class GroupRevokedMessageHandler @Inject constructor( + private val configFactoryProtocol: ConfigFactoryProtocol, + private val storage: StorageProtocol, + private val groupManagerV2: Provider, +) { + suspend fun handleRevokeMessage( + groupId: AccountId, + rawMessages: List, + ) { + rawMessages.forEach { data -> + val decoded = configFactoryProtocol.decryptForUser( + data, + Sodium.KICKED_DOMAIN, + groupId, + ) + + if (decoded != null) { + // The message should be in the format of "", + // where the pub key is 32 bytes, so we need to have at least 33 bytes of data + if (decoded.size < 33) { + Log.w(TAG, "Received an invalid kicked message, expecting at least 33 bytes, got ${decoded.size}") + return@forEach + } + + val sessionId = AccountId(IdPrefix.STANDARD, decoded.copyOfRange(0, 32)) // copyOfRange: [start,end) + val messageGeneration = decoded.copyOfRange(32, decoded.size).decodeToString().toIntOrNull() + if (messageGeneration == null) { + Log.w(TAG, "Received an invalid kicked message: missing message generation") + return@forEach + } + + val currentKeysGeneration = configFactoryProtocol.withGroupConfigs(groupId) { + it.groupKeys.currentGeneration() + } + + val isForMe = sessionId.hexString == storage.getUserPublicKey() + Log.d(TAG, "Received kicked message, for us? ${isForMe}, message key generation = $messageGeneration, our key generation = $currentKeysGeneration") + + if (isForMe && messageGeneration >= currentKeysGeneration) { + groupManagerV2.get().handleKicked(groupId) + } + } + } + } + + companion object { + private const val TAG = "GroupRevokedMessageHandler" + } +} \ No newline at end of file diff --git a/app/src/main/java/org/thoughtcrime/securesms/groups/handler/RemoveGroupMemberHandler.kt b/app/src/main/java/org/thoughtcrime/securesms/groups/handler/RemoveGroupMemberHandler.kt index a2d19af7e9..0c4ebe63d4 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/groups/handler/RemoveGroupMemberHandler.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/groups/handler/RemoveGroupMemberHandler.kt @@ -138,7 +138,7 @@ class RemoveGroupMemberHandler @Inject constructor( // Call No 3. Conditionally send the `GroupUpdateDeleteMemberContent` if (pendingRemovals.any { (member, status) -> member.shouldRemoveMessages(status) }) { calls += SnodeAPI.buildAuthenticatedStoreBatchInfo( - namespace = Namespace.CLOSED_GROUP_MESSAGES(), + namespace = Namespace.GROUP_MESSAGES(), message = buildDeleteGroupMemberContentMessage( adminKey = adminKey, groupAccountId = groupAccountId.hexString, diff --git a/app/src/main/java/org/thoughtcrime/securesms/notifications/PushReceiver.kt b/app/src/main/java/org/thoughtcrime/securesms/notifications/PushReceiver.kt index 9cf36cdee8..ccccb2cfe3 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/notifications/PushReceiver.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/notifications/PushReceiver.kt @@ -10,6 +10,8 @@ import androidx.core.content.ContextCompat.getString import com.goterl.lazysodium.interfaces.AEAD import com.goterl.lazysodium.utils.Key import dagger.hilt.android.qualifiers.ApplicationContext +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.launch import kotlinx.serialization.json.Json import network.loki.messenger.R import org.session.libsession.messaging.jobs.BatchMessageReceiveJob @@ -20,6 +22,7 @@ import org.session.libsession.messaging.sending_receiving.notifications.PushNoti import org.session.libsession.messaging.utilities.MessageWrapper import org.session.libsession.messaging.utilities.SodiumUtilities import org.session.libsession.messaging.utilities.SodiumUtilities.sodium +import org.session.libsession.utilities.ConfigMessage import org.session.libsession.utilities.bencode.Bencode import org.session.libsession.utilities.bencode.BencodeList import org.session.libsession.utilities.bencode.BencodeString @@ -30,13 +33,15 @@ import org.session.libsignal.utilities.Log import org.session.libsignal.utilities.Namespace import org.thoughtcrime.securesms.crypto.IdentityKeyUtil import org.thoughtcrime.securesms.dependencies.ConfigFactory +import org.thoughtcrime.securesms.groups.GroupRevokedMessageHandler import javax.inject.Inject private const val TAG = "PushHandler" class PushReceiver @Inject constructor( @ApplicationContext private val context: Context, - private val configFactory: ConfigFactory + private val configFactory: ConfigFactory, + private val groupRevokedMessageHandler: GroupRevokedMessageHandler, ) { private val json = Json { ignoreUnknownKeys = true } @@ -56,7 +61,7 @@ class PushReceiver @Inject constructor( addMessageReceiveJob(PushData(data = data, metadata = null)) } - private fun addMessageReceiveJob(pushData: PushData?){ + private fun addMessageReceiveJob(pushData: PushData?) { // send a generic notification if we have no data if (pushData?.data == null) { sendGenericNotification() @@ -64,24 +69,63 @@ class PushReceiver @Inject constructor( } try { + val namespace = pushData.metadata?.namespace val params = when { - pushData.metadata?.namespace == Namespace.CLOSED_GROUP_MESSAGES() -> { + namespace == Namespace.GROUP_MESSAGES() || + namespace == Namespace.REVOKED_GROUP_MESSAGES() || + namespace == Namespace.GROUP_INFO() || + namespace == Namespace.GROUP_MEMBERS() || + namespace == Namespace.GROUP_KEYS() -> { val groupId = AccountId(requireNotNull(pushData.metadata.account) { "Received a closed group message push notification without an account ID" }) - val envelop = checkNotNull(tryDecryptGroupMessage(groupId, pushData.data)) { - "Unable to decrypt closed group message" + if (namespace == Namespace.GROUP_MESSAGES()) { + val envelope = checkNotNull(tryDecryptGroupEnvelope(groupId, pushData.data)) { + "Unable to decrypt closed group message" + } + + MessageReceiveParameters( + data = envelope.toByteArray(), + serverHash = pushData.metadata.msg_hash, + closedGroup = Destination.ClosedGroup(groupId.hexString) + ) + } else if (namespace == Namespace.REVOKED_GROUP_MESSAGES()) { + GlobalScope.launch { + groupRevokedMessageHandler.handleRevokeMessage(groupId, listOf(pushData.data)) + } + + null + } else { + val hash = requireNotNull(pushData.metadata.msg_hash) { + "Received a closed group config push notification without a message hash" + } + + // If we receive group config messages from notification, try to merge + // them directly + val configMessage = listOf( + ConfigMessage( + hash = hash, + data = pushData.data, + timestamp = pushData.metadata.timestampSeconds + ) + ) + + configFactory.mergeGroupConfigMessages( + groupId = groupId, + keys = configMessage.takeIf { namespace == Namespace.GROUP_KEYS() } + .orEmpty(), + members = configMessage.takeIf { namespace == Namespace.GROUP_MEMBERS() } + .orEmpty(), + info = configMessage.takeIf { namespace == Namespace.GROUP_INFO() } + .orEmpty(), + ) + + null } - - MessageReceiveParameters( - data = envelop.toByteArray(), - serverHash = pushData.metadata.msg_hash, - closedGroup = Destination.ClosedGroup(groupId.hexString) - ) } - pushData.metadata?.namespace == 0 || pushData.metadata == null -> { + namespace == Namespace.DEFAULT() || pushData.metadata == null -> { val envelopeAsData = MessageWrapper.unwrap(pushData.data).toByteArray() MessageReceiveParameters( data = envelopeAsData, @@ -90,25 +134,30 @@ class PushReceiver @Inject constructor( } else -> { - Log.w(TAG, "Received a push notification with an unknown namespace: ${pushData.metadata.namespace}") + Log.w(TAG, "Received a push notification with an unknown namespace: $namespace") return } } - JobQueue.shared.add(BatchMessageReceiveJob(listOf(params), null)) + if (params != null) { + JobQueue.shared.add(BatchMessageReceiveJob(listOf(params), null)) + } } catch (e: Exception) { Log.d(TAG, "Failed to unwrap data for message due to error.", e) } } - - private fun tryDecryptGroupMessage(groupId: AccountId, data: ByteArray): Envelope? { - val (envelopBytes, sender) = checkNotNull(configFactory.withGroupConfigs(groupId) { it.groupKeys.decrypt(data) }) { + private fun tryDecryptGroupEnvelope(groupId: AccountId, data: ByteArray): Envelope? { + val (envelopBytes, sender) = checkNotNull(configFactory.withGroupConfigs(groupId) { + it.groupKeys.decrypt( + data + ) + }) { "Failed to decrypt group message" } - Log.d(TAG, "Successfully decrypted group message from ${sender.hexString}") + Log.d(TAG, "Successfully decrypted group message from $sender") return Envelope.parseFrom(envelopBytes) .toBuilder() .setSource(sender.hexString) diff --git a/app/src/main/java/org/thoughtcrime/securesms/notifications/PushRegistrationHandler.kt b/app/src/main/java/org/thoughtcrime/securesms/notifications/PushRegistrationHandler.kt index f0de8e929d..6c68e9c26d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/notifications/PushRegistrationHandler.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/notifications/PushRegistrationHandler.kt @@ -73,7 +73,7 @@ constructor( getGroupSubscriptions( token = token ) + mapOf( - SubscriptionKey(userAuth.accountId, token) to Subscription(userAuth, 0) + SubscriptionKey(userAuth.accountId, token) to Subscription(userAuth, listOf(Namespace.DEFAULT())) ) } .scan, Pair, Map>?>( @@ -103,7 +103,7 @@ constructor( pushRegistry.register( token = key.token, swarmAuth = subscription.auth, - namespaces = listOf(subscription.namespace) + namespaces = subscription.namespaces.toList() ) } catch (e: Exception) { Log.e(TAG, "Failed to register for push notification", e) @@ -135,6 +135,16 @@ constructor( ): Map { return buildMap { val groups = configFactory.withUserConfigs { it.userGroups.allClosedGroupInfo() } + .filter { it.shouldPoll } + + val namespaces = listOf( + Namespace.GROUP_MESSAGES(), + Namespace.GROUP_INFO(), + Namespace.GROUP_MEMBERS(), + Namespace.GROUP_KEYS(), + Namespace.REVOKED_GROUP_MESSAGES(), + ) + for (group in groups) { val adminKey = group.adminKey if (adminKey != null && adminKey.isNotEmpty()) { @@ -142,7 +152,7 @@ constructor( SubscriptionKey(group.groupAccountId, token), Subscription( auth = OwnedSwarmAuth.ofClosedGroup(group.groupAccountId, adminKey), - namespace = Namespace.GROUPS() + namespaces = namespaces ) ) continue @@ -154,7 +164,7 @@ constructor( ?.let { Subscription( auth = it, - namespace = Namespace.GROUPS() + namespaces = namespaces ) } @@ -167,5 +177,5 @@ constructor( } private data class SubscriptionKey(val accountId: AccountId, val token: String) - private data class Subscription(val auth: SwarmAuth, val namespace: Int) + private data class Subscription(val auth: SwarmAuth, val namespaces: List) } \ No newline at end of file diff --git a/app/src/main/java/org/thoughtcrime/securesms/notifications/PushRegistryV2.kt b/app/src/main/java/org/thoughtcrime/securesms/notifications/PushRegistryV2.kt index 37246be54b..aeb128093d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/notifications/PushRegistryV2.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/notifications/PushRegistryV2.kt @@ -46,13 +46,14 @@ class PushRegistryV2 @Inject constructor( val timestamp = clock.currentTimeMills() / 1000 // get timestamp in ms -> s val publicKey = swarmAuth.accountId.hexString + val sortedNamespace = namespaces.sorted() val signed = swarmAuth.sign( - "MONITOR${publicKey}${timestamp}1${namespaces.joinToString(separator = ",")}".encodeToByteArray() + "MONITOR${publicKey}${timestamp}1${sortedNamespace.joinToString(separator = ",")}".encodeToByteArray() ) val requestParameters = SubscriptionRequest( pubkey = publicKey, session_ed25519 = swarmAuth.ed25519PublicKeyHex, - namespaces = namespaces, + namespaces = sortedNamespace, data = true, // only permit data subscription for now (?) service = device.service, sig_ts = timestamp, diff --git a/libsession-util/src/main/cpp/util.cpp b/libsession-util/src/main/cpp/util.cpp index 9d2a43ac90..70979c4ca5 100644 --- a/libsession-util/src/main/cpp/util.cpp +++ b/libsession-util/src/main/cpp/util.cpp @@ -361,31 +361,31 @@ Java_org_session_libsignal_utilities_Namespace_CONVO_1INFO_1VOLATILE(JNIEnv *env extern "C" JNIEXPORT jint JNICALL -Java_org_session_libsignal_utilities_Namespace_GROUPS(JNIEnv *env, jobject thiz) { +Java_org_session_libsignal_utilities_Namespace_USER_1GROUPS(JNIEnv *env, jobject thiz) { return (int) session::config::Namespace::UserGroups; } extern "C" JNIEXPORT jint JNICALL -Java_org_session_libsignal_utilities_Namespace_CLOSED_1GROUP_1INFO(JNIEnv *env, jobject thiz) { +Java_org_session_libsignal_utilities_Namespace_GROUP_1INFO(JNIEnv *env, jobject thiz) { return (int) session::config::Namespace::GroupInfo; } extern "C" JNIEXPORT jint JNICALL -Java_org_session_libsignal_utilities_Namespace_CLOSED_1GROUP_1MEMBERS(JNIEnv *env, jobject thiz) { +Java_org_session_libsignal_utilities_Namespace_GROUP_1MEMBERS(JNIEnv *env, jobject thiz) { return (int) session::config::Namespace::GroupMembers; } extern "C" JNIEXPORT jint JNICALL -Java_org_session_libsignal_utilities_Namespace_ENCRYPTION_1KEYS(JNIEnv *env, jobject thiz) { +Java_org_session_libsignal_utilities_Namespace_GROUP_1KEYS(JNIEnv *env, jobject thiz) { return (int) session::config::Namespace::GroupKeys; } extern "C" JNIEXPORT jint JNICALL -Java_org_session_libsignal_utilities_Namespace_CLOSED_1GROUP_1MESSAGES(JNIEnv *env, jobject thiz) { +Java_org_session_libsignal_utilities_Namespace_GROUP_1MESSAGES(JNIEnv *env, jobject thiz) { return (int) session::config::Namespace::GroupMessages; } diff --git a/libsession-util/src/main/java/network/loki/messenger/libsession_util/Config.kt b/libsession-util/src/main/java/network/loki/messenger/libsession_util/Config.kt index 0440ee2c2f..fb2404ca20 100644 --- a/libsession-util/src/main/java/network/loki/messenger/libsession_util/Config.kt +++ b/libsession-util/src/main/java/network/loki/messenger/libsession_util/Config.kt @@ -298,7 +298,7 @@ class UserGroupsConfig private constructor(pointer: Long): ConfigBase(pointer), ) ) - override fun namespace() = Namespace.GROUPS() + override fun namespace() = Namespace.USER_GROUPS() external override fun getCommunityInfo(baseUrl: String, room: String): GroupInfo.CommunityGroupInfo? external override fun getLegacyGroupInfo(accountId: String): GroupInfo.LegacyGroupInfo? @@ -359,7 +359,7 @@ class GroupInfoConfig private constructor(pointer: Long): ConfigBase(pointer), M ): Long } - override fun namespace() = Namespace.CLOSED_GROUP_INFO() + override fun namespace() = Namespace.GROUP_INFO() external override fun id(): AccountId external override fun destroyGroup() @@ -425,7 +425,7 @@ class GroupMembersConfig private constructor(pointer: Long): ConfigBase(pointer) constructor(groupPubKey: ByteArray, groupAdminKey: ByteArray?, initialDump: ByteArray?) : this(newInstance(groupPubKey, groupAdminKey, initialDump)) - override fun namespace() = Namespace.CLOSED_GROUP_MEMBERS() + override fun namespace() = Namespace.GROUP_MEMBERS() external override fun all(): Stack external override fun erase(pubKeyHex: String): Boolean @@ -503,7 +503,7 @@ class GroupKeysConfig private constructor( members ) - override fun namespace() = Namespace.ENCRYPTION_KEYS() + override fun namespace() = Namespace.GROUP_KEYS() external override fun groupKeys(): Stack external override fun needsDump(): Boolean diff --git a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageSender.kt b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageSender.kt index 03e4c591d6..cfa49429c5 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageSender.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageSender.kt @@ -246,7 +246,7 @@ object MessageSender { Namespace.UNAUTHENTICATED_CLOSED_GROUP(), Namespace.DEFAULT ()) - destination is Destination.ClosedGroup -> listOf(Namespace.CLOSED_GROUP_MESSAGES()) + destination is Destination.ClosedGroup -> listOf(Namespace.GROUP_MESSAGES()) else -> listOf(Namespace.DEFAULT()) } diff --git a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/notifications/Models.kt b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/notifications/Models.kt index ca9eb6fcbf..14a68faec1 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/notifications/Models.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/notifications/Models.kt @@ -96,6 +96,9 @@ data class PushNotificationMetadata( @SerialName("n") val namespace: Int, + @SerialName("t") + val timestampSeconds: Long, + /** The length of the message data. This is always included, even if the message content * itself was too large to fit into the push notification. */ @SerialName("l") diff --git a/libsession/src/main/java/org/session/libsession/utilities/ConfigFactoryProtocol.kt b/libsession/src/main/java/org/session/libsession/utilities/ConfigFactoryProtocol.kt index 00af06a519..f14e1695f9 100644 --- a/libsession/src/main/java/org/session/libsession/utilities/ConfigFactoryProtocol.kt +++ b/libsession/src/main/java/org/session/libsession/utilities/ConfigFactoryProtocol.kt @@ -108,7 +108,7 @@ enum class UserConfigType(val namespace: Int) { CONTACTS(Namespace.CONTACTS()), USER_PROFILE(Namespace.USER_PROFILE()), CONVO_INFO_VOLATILE(Namespace.CONVO_INFO_VOLATILE()), - USER_GROUPS(Namespace.GROUPS()), + USER_GROUPS(Namespace.USER_GROUPS()), } /** diff --git a/libsignal/src/main/java/org/session/libsignal/utilities/Namespace.kt b/libsignal/src/main/java/org/session/libsignal/utilities/Namespace.kt index 2d211e5ca6..1c39abb47f 100644 --- a/libsignal/src/main/java/org/session/libsignal/utilities/Namespace.kt +++ b/libsignal/src/main/java/org/session/libsignal/utilities/Namespace.kt @@ -2,15 +2,21 @@ package org.session.libsignal.utilities object Namespace { fun ALL() = "all" + + // Namespaces used for legacy group fun UNAUTHENTICATED_CLOSED_GROUP() = -10 + + // Namespaces used for user's own swarm external fun DEFAULT(): Int external fun USER_PROFILE(): Int external fun CONTACTS(): Int external fun CONVO_INFO_VOLATILE(): Int - external fun GROUPS(): Int - external fun CLOSED_GROUP_INFO(): Int - external fun CLOSED_GROUP_MEMBERS(): Int - external fun ENCRYPTION_KEYS(): Int - external fun CLOSED_GROUP_MESSAGES(): Int + external fun USER_GROUPS(): Int + + // Namesapced used for groupv2 + external fun GROUP_INFO(): Int + external fun GROUP_MEMBERS(): Int + external fun GROUP_KEYS(): Int + external fun GROUP_MESSAGES(): Int external fun REVOKED_GROUP_MESSAGES(): Int } \ No newline at end of file