From b42b9fa41484ab8597dabfebb8cfe0cb0994cc97 Mon Sep 17 00:00:00 2001 From: 0x330a <92654767+0x330a@users.noreply.github.com> Date: Wed, 30 Aug 2023 17:48:21 +1000 Subject: [PATCH] feat: adding more closed group in recipient logic, adding more wrappers for user groups and serializing / deserializing the closed groups in user group type --- .../conversation/v2/ConversationActivityV2.kt | 2 -- .../v2/utilities/MentionManagerUtilities.kt | 4 ++- .../securesms/database/Storage.kt | 8 +++++ libsession-util/src/main/cpp/group_keys.cpp | 2 ++ libsession-util/src/main/cpp/user_groups.cpp | 18 ++++++++++ libsession-util/src/main/cpp/user_groups.h | 34 +++++++++++++++++++ .../loki/messenger/libsession_util/Config.kt | 3 ++ .../libsession_util/util/GroupInfo.kt | 32 +++++++++++++++++ .../libsession/database/StorageProtocol.kt | 5 ++- 9 files changed, 104 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt index ffd0dc9bd9..753268b5d9 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt @@ -106,7 +106,6 @@ import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity import org.thoughtcrime.securesms.attachments.ScreenshotObserver import org.thoughtcrime.securesms.audio.AudioRecorder import org.thoughtcrime.securesms.contacts.SelectContactsActivity.Companion.selectedContactsKey -import org.thoughtcrime.securesms.util.SimpleTextWatcher import org.thoughtcrime.securesms.conversation.settings.ConversationSettingsActivityContract import org.thoughtcrime.securesms.conversation.settings.ConversationSettingsActivityResult import org.thoughtcrime.securesms.conversation.v2.ConversationReactionOverlay.OnActionSelectedListener @@ -145,7 +144,6 @@ import org.thoughtcrime.securesms.database.ReactionDatabase import org.thoughtcrime.securesms.database.RecipientDatabase import org.thoughtcrime.securesms.database.SessionContactDatabase import org.thoughtcrime.securesms.database.SmsDatabase -import org.thoughtcrime.securesms.database.Storage import org.thoughtcrime.securesms.database.ThreadDatabase import org.thoughtcrime.securesms.database.model.MessageId import org.thoughtcrime.securesms.database.model.MessageRecord diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/MentionManagerUtilities.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/MentionManagerUtilities.kt index f7f7e784f1..4c6435b85e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/MentionManagerUtilities.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/MentionManagerUtilities.kt @@ -11,13 +11,15 @@ object MentionManagerUtilities { fun populateUserPublicKeyCacheIfNeeded(threadID: Long, context: Context) { val result = mutableSetOf() val recipient = DatabaseComponent.get(context).threadDatabase().getRecipientForThreadId(threadID) ?: return + val storage = DatabaseComponent.get(context).storage() when { recipient.address.isLegacyClosedGroup -> { val members = DatabaseComponent.get(context).groupDatabase().getGroupMembers(recipient.address.toGroupString(), false).map { it.address.serialize() } result.addAll(members) } recipient.address.isClosedGroup -> { - TODO("get members from libsession via storage") + val members = storage.getMembers(recipient.address.serialize()) + TODO("Fix when compile errors are dealt with for recipient closed groups") } recipient.address.isOpenGroup -> { val messageDatabase = DatabaseComponent.get(context).mmsSmsDatabase() 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 927f0bd2b3..6d252b6ee3 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt @@ -116,6 +116,9 @@ open class Storage(context: Context, helper: SQLCipherOpenHelper, private val co } } address.isClosedGroup -> { + val sessionId = address.serialize() + val closedGroup = groups.getClosedGroup(sessionId) + Log.w("Loki", "Thread created called for new closed group address, not adding any extra information") } address.isOpenGroup -> { @@ -1021,6 +1024,11 @@ open class Storage(context: Context, helper: SQLCipherOpenHelper, private val co } } + override fun getMembers(groupPublicKey: String): List { + val groups = configFactory.userGroups ?: return emptyList() + TODO("Add group specific configs") + } + override fun setServerCapabilities(server: String, capabilities: List) { return DatabaseComponent.get(context).lokiAPIDatabase().setServerCapabilities(server, capabilities) } diff --git a/libsession-util/src/main/cpp/group_keys.cpp b/libsession-util/src/main/cpp/group_keys.cpp index ed6aaaaf71..3a1b13ed8d 100644 --- a/libsession-util/src/main/cpp/group_keys.cpp +++ b/libsession-util/src/main/cpp/group_keys.cpp @@ -17,10 +17,12 @@ Java_network_loki_messenger_libsession_1util_GroupKeysConfig_00024Companion_newI auto pub_key_bytes = util::ustring_from_bytes(env, group_public_key); std::optional secret_key_optional{std::nullopt}; std::optional initial_dump_optional{std::nullopt}; + if (env->GetArrayLength(group_secret_key) == 32 || env->GetArrayLength(group_secret_key) == 64) { auto secret_key_bytes = util::ustring_from_bytes(env, group_secret_key); secret_key_optional = secret_key_bytes; } + if (env->GetArrayLength(initial_dump) > 0) { auto initial_dump_bytes = util::ustring_from_bytes(env, initial_dump); initial_dump_optional = initial_dump_bytes; diff --git a/libsession-util/src/main/cpp/user_groups.cpp b/libsession-util/src/main/cpp/user_groups.cpp index 4f2b0e6b85..fcfdaf3233 100644 --- a/libsession-util/src/main/cpp/user_groups.cpp +++ b/libsession-util/src/main/cpp/user_groups.cpp @@ -270,4 +270,22 @@ Java_network_loki_messenger_libsession_1util_UserGroupsConfig_eraseLegacyGroup(J bool return_bool = conf->erase_legacy_group(session_id_bytes); env->ReleaseStringUTFChars(session_id, session_id_bytes); return return_bool; +} +extern "C" +JNIEXPORT jobject JNICALL +Java_network_loki_messenger_libsession_1util_UserGroupsConfig_getClosedGroup(JNIEnv *env, + jobject thiz, + jstring session_id) { + std::lock_guard guard{util::util_mutex_}; + auto config = ptrToUserGroups(env, thiz); + auto session_id_bytes = env->GetStringUTFChars(session_id, nullptr); + + auto group = config->get_group(session_id_bytes); + + env->ReleaseStringUTFChars(session_id, session_id_bytes); + + if (group) { + return serialize_group_info(env, *group); + } + return nullptr; } \ No newline at end of file diff --git a/libsession-util/src/main/cpp/user_groups.h b/libsession-util/src/main/cpp/user_groups.h index c4754fe113..55003d6ce1 100644 --- a/libsession-util/src/main/cpp/user_groups.h +++ b/libsession-util/src/main/cpp/user_groups.h @@ -127,6 +127,40 @@ inline jobject serialize_legacy_group_info(JNIEnv *env, session::config::legacy_ return serialized; } +inline jobject serialize_group_info(JNIEnv* env, session::config::group_info info) { + jstring session_id = env->NewStringUTF(info.id.data()); + jbyteArray admin_bytes = util::bytes_from_ustring(env, info.secretkey); + jbyteArray auth_bytes = util::bytes_from_ustring(env, info.auth_sig); + + jclass group_info_class = env->FindClass("network/loki/messenger/libsession_util/util/GroupInfo$ClosedGroupInfo"); + jmethodID constructor = env->GetMethodID(group_info_class, "", "(Ljava/lang/String;[B[B)V"); + jobject return_object = env->NewObject(group_info_class,constructor, + session_id, admin_bytes, auth_bytes); + return return_object; +} + +inline session::config::group_info deserialize_group_info(JNIEnv* env, jobject info_serialized) { + jclass closed_group_class = env->FindClass("network/loki/messenger/libsession_util/util/GroupInfo$ClosedGroupInfo"); + jfieldID id_field = env->GetFieldID(closed_group_class, "groupSessionId", "Ljava/lang/String;"); + jfieldID secret_field = env->GetFieldID(closed_group_class, "adminKey", "[B"); + jfieldID auth_field = env->GetFieldID(closed_group_class, "signingKey", "[B"); + + jstring id_jstring = (jstring)env->GetObjectField(info_serialized, id_field); + jbyteArray secret_jBytes = (jbyteArray)env->GetObjectField(info_serialized, secret_field); + jbyteArray auth_jBytes = (jbyteArray)env->GetObjectField(info_serialized, auth_field); + + auto id_bytes = env->GetStringUTFChars(id_jstring, nullptr); + auto secret_bytes = util::ustring_from_bytes(env, secret_jBytes); + auto auth_bytes = util::ustring_from_bytes(env, auth_jBytes); + + session::config::group_info group_info(id_bytes); + group_info.auth_sig = auth_bytes; + group_info.secretkey = secret_bytes; + + env->ReleaseStringUTFChars(id_jstring, id_bytes); + return group_info; +} + inline jobject serialize_community_info(JNIEnv *env, session::config::community_info info) { auto priority = info.priority; auto serialized_info = util::serialize_base_community(env, info); 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 9e82d95cdd..463b2ca897 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 @@ -205,6 +205,9 @@ class UserGroupsConfig(pointer: Long): ConfigBase(pointer) { external fun all(): List external fun allCommunityInfo(): List external fun allLegacyGroupInfo(): List + external fun getClosedGroup(sessionId: String): GroupInfo.ClosedGroupInfo? + external fun getOrConstructClosedGroup(sessionId: String): GroupInfo.ClosedGroupInfo + external fun all(): } class GroupInfoConfig(pointer: Long): ConfigBase(pointer) { diff --git a/libsession-util/src/main/java/network/loki/messenger/libsession_util/util/GroupInfo.kt b/libsession-util/src/main/java/network/loki/messenger/libsession_util/util/GroupInfo.kt index c8ace0a9a7..26b92ffd02 100644 --- a/libsession-util/src/main/java/network/loki/messenger/libsession_util/util/GroupInfo.kt +++ b/libsession-util/src/main/java/network/loki/messenger/libsession_util/util/GroupInfo.kt @@ -4,6 +4,38 @@ sealed class GroupInfo { data class CommunityGroupInfo(val community: BaseCommunityInfo, val priority: Int) : GroupInfo() + data class ClosedGroupInfo( + val groupSessionId: String, + val adminKey: ByteArray?, + val signingKey: ByteArray? + ): GroupInfo() { + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + + other as ClosedGroupInfo + + if (groupSessionId != other.groupSessionId) return false + if (adminKey != null) { + if (other.adminKey == null) return false + if (!adminKey.contentEquals(other.adminKey)) return false + } else if (other.adminKey != null) return false + if (signingKey != null) { + if (other.signingKey == null) return false + if (!signingKey.contentEquals(other.signingKey)) return false + } else if (other.signingKey != null) return false + + return true + } + + override fun hashCode(): Int { + var result = groupSessionId.hashCode() + result = 31 * result + (adminKey?.contentHashCode() ?: 0) + result = 31 * result + (signingKey?.contentHashCode() ?: 0) + return result + } + } + data class LegacyGroupInfo( val sessionId: String, val name: String, diff --git a/libsession/src/main/java/org/session/libsession/database/StorageProtocol.kt b/libsession/src/main/java/org/session/libsession/database/StorageProtocol.kt index 89fc162cd6..dbf03832b4 100644 --- a/libsession/src/main/java/org/session/libsession/database/StorageProtocol.kt +++ b/libsession/src/main/java/org/session/libsession/database/StorageProtocol.kt @@ -125,7 +125,7 @@ interface StorageProtocol { fun clearErrorMessage(messageID: Long) fun setMessageServerHash(messageID: Long, serverHash: String) - // Closed Groups + // Legacy Closed Groups fun getGroup(groupID: String): GroupRecord? fun createGroup(groupID: String, title: String?, members: List
, avatar: SignalServiceAttachmentPointer?, relay: String?, admins: List
, formationTimestamp: Long) fun createInitialConfigGroup(groupPublicKey: String, name: String, members: Map, formationTimestamp: Long, encryptionKeyPair: ECKeyPair) @@ -153,6 +153,9 @@ interface StorageProtocol { fun updateTimestampUpdated(groupID: String, updatedTimestamp: Long) fun setExpirationTimer(address: String, duration: Int) + // Closed Groups + fun getMembers(groupPublicKey: String): List + // Groups fun getAllGroups(includeInactive: Boolean): List