Fix compilation issues

This commit is contained in:
SessionHero01 2024-10-14 14:37:13 +11:00
parent 1f9b00bc0a
commit 222df30a18
No known key found for this signature in database
4 changed files with 118 additions and 88 deletions

View File

@ -35,6 +35,7 @@ import org.session.libsession.utilities.ConfigUpdateNotification
import org.session.libsession.utilities.GroupUtil import org.session.libsession.utilities.GroupUtil
import org.session.libsession.utilities.SSKEnvironment.ProfileManagerProtocol.Companion.NAME_PADDED_LENGTH import org.session.libsession.utilities.SSKEnvironment.ProfileManagerProtocol.Companion.NAME_PADDED_LENGTH
import org.session.libsession.utilities.TextSecurePreferences import org.session.libsession.utilities.TextSecurePreferences
import org.session.libsession.utilities.UserConfigType
import org.session.libsession.utilities.recipients.Recipient import org.session.libsession.utilities.recipients.Recipient
import org.session.libsignal.crypto.ecc.DjbECPrivateKey import org.session.libsignal.crypto.ecc.DjbECPrivateKey
import org.session.libsignal.crypto.ecc.DjbECPublicKey import org.session.libsignal.crypto.ecc.DjbECPublicKey
@ -86,7 +87,7 @@ class ConfigToDatabaseSync @Inject constructor(
.collect { config -> .collect { config ->
try { try {
Log.i(TAG, "Start syncing user configs") Log.i(TAG, "Start syncing user configs")
syncUserConfigs(config.timestamp) syncUserConfigs(config.configType, config.timestamp)
Log.i(TAG, "Finished syncing user configs") Log.i(TAG, "Finished syncing user configs")
} catch (e: Exception) { } catch (e: Exception) {
Log.e(TAG, "Error syncing user configs", e) Log.e(TAG, "Error syncing user configs", e)
@ -116,23 +117,23 @@ class ConfigToDatabaseSync @Inject constructor(
updateGroup(info) updateGroup(info)
} }
private fun syncUserConfigs(updateTimestamp: Long) { private fun syncUserConfigs(userConfigType: UserConfigType, updateTimestamp: Long) {
lateinit var updateUserInfo: UpdateUserInfo val configUpdate = configFactory.withUserConfigs { configs ->
lateinit var updateUserGroupsInfo: UpdateUserGroupsInfo when (userConfigType) {
lateinit var updateContacts: List<Contact> UserConfigType.USER_PROFILE -> UpdateUserInfo(configs.userProfile)
lateinit var updateConvoVolatile: List<Conversation?> UserConfigType.USER_GROUPS -> UpdateUserGroupsInfo(configs.userGroups)
UserConfigType.CONTACTS -> UpdateContacts(configs.contacts.all())
configFactory.withUserConfigs { configs -> UserConfigType.CONVO_INFO_VOLATILE -> UpdateConvoVolatile(configs.convoInfoVolatile.all())
updateUserInfo = UpdateUserInfo(configs.userProfile) }
updateUserGroupsInfo = UpdateUserGroupsInfo(configs.userGroups)
updateContacts = configs.contacts.all()
updateConvoVolatile = configs.convoInfoVolatile.all()
} }
updateUser(updateUserInfo, updateTimestamp) when (configUpdate) {
updateContacts(updateContacts, updateTimestamp) is UpdateUserInfo -> updateUser(configUpdate, updateTimestamp)
updateUserGroups(updateUserGroupsInfo, updateTimestamp) is UpdateUserGroupsInfo -> updateUserGroups(configUpdate, updateTimestamp)
updateConvoVolatile(updateConvoVolatile) is UpdateContacts -> updateContacts(configUpdate, updateTimestamp)
is UpdateConvoVolatile -> updateConvoVolatile(configUpdate)
else -> error("Unknown config update type: $configUpdate")
}
} }
private data class UpdateUserInfo( private data class UpdateUserInfo(
@ -219,8 +220,10 @@ class ConfigToDatabaseSync @Inject constructor(
} }
} }
private fun updateContacts(contacts: List<Contact>, messageTimestamp: Long) { private data class UpdateContacts(val contacts: List<Contact>)
storage.addLibSessionContacts(contacts, messageTimestamp)
private fun updateContacts(contacts: UpdateContacts, messageTimestamp: Long) {
storage.addLibSessionContacts(contacts.contacts, messageTimestamp)
} }
private data class UpdateUserGroupsInfo( private data class UpdateUserGroupsInfo(
@ -368,8 +371,10 @@ class ConfigToDatabaseSync @Inject constructor(
} }
} }
private fun updateConvoVolatile(convos: List<Conversation?>) { private data class UpdateConvoVolatile(val convos: List<Conversation?>)
val extracted = convos.filterNotNull()
private fun updateConvoVolatile(convos: UpdateConvoVolatile) {
val extracted = convos.convos.filterNotNull()
for (conversation in extracted) { for (conversation in extracted) {
val threadId = when (conversation) { val threadId = when (conversation) {
is Conversation.OneToOne -> storage.getThreadIdFor(conversation.accountId, null, null, createThread = false) is Conversation.OneToOne -> storage.getThreadIdFor(conversation.accountId, null, null, createThread = false)

View File

@ -49,6 +49,7 @@ import org.session.libsignal.utilities.IdPrefix
import org.session.libsignal.utilities.Log import org.session.libsignal.utilities.Log
import org.session.libsignal.utilities.toHexString import org.session.libsignal.utilities.toHexString
import org.thoughtcrime.securesms.database.ConfigDatabase import org.thoughtcrime.securesms.database.ConfigDatabase
import org.thoughtcrime.securesms.database.ConfigVariant
import org.thoughtcrime.securesms.database.LokiThreadDatabase import org.thoughtcrime.securesms.database.LokiThreadDatabase
import org.thoughtcrime.securesms.database.ThreadDatabase import org.thoughtcrime.securesms.database.ThreadDatabase
import org.thoughtcrime.securesms.groups.GroupManager import org.thoughtcrime.securesms.groups.GroupManager
@ -142,14 +143,18 @@ class ConfigFactory @Inject constructor(
* *
* @param cb A function that takes a [UserConfigsImpl] and returns a pair of the result of the operation and a boolean indicating if the configs were changed. * @param cb A function that takes a [UserConfigsImpl] and returns a pair of the result of the operation and a boolean indicating if the configs were changed.
*/ */
private fun <T> doWithMutableUserConfigs(cb: (UserConfigsImpl) -> Pair<T, ConfigUpdateNotification?>): T { private fun <T> doWithMutableUserConfigs(cb: (UserConfigsImpl) -> Pair<T, List<ConfigUpdateNotification>>): T {
val (lock, configs) = ensureUserConfigsInitialized() val (lock, configs) = ensureUserConfigsInitialized()
val (result, changed) = lock.write { val (result, changed) = lock.write {
cb(configs) cb(configs)
} }
if (changed != null) { if (changed.isNotEmpty()) {
_configUpdateNotifications.tryEmit(changed) for (notification in changed) {
if (!_configUpdateNotifications.tryEmit(notification)) {
Log.e("ConfigFactory", "Unable to deliver config update notification")
}
}
} }
return result return result
@ -163,7 +168,7 @@ class ConfigFactory @Inject constructor(
return return
} }
return doWithMutableUserConfigs { configs -> val toDump = doWithMutableUserConfigs { configs ->
val config = when (userConfigType) { val config = when (userConfigType) {
UserConfigType.CONTACTS -> configs.contacts UserConfigType.CONTACTS -> configs.contacts
UserConfigType.USER_PROFILE -> configs.userProfile UserConfigType.USER_PROFILE -> configs.userProfile
@ -171,22 +176,42 @@ class ConfigFactory @Inject constructor(
UserConfigType.USER_GROUPS -> configs.userGroups UserConfigType.USER_GROUPS -> configs.userGroups
} }
// Merge the list of config messages, we'll be told which messages have been merged
// and we will then find out which message has the max timestamp
val maxTimestamp = config.merge(messages.map { it.hash to it.data }.toTypedArray()) val maxTimestamp = config.merge(messages.map { it.hash to it.data }.toTypedArray())
.asSequence() .asSequence()
.mapNotNull { hash -> messages.firstOrNull { it.hash == hash } } .mapNotNull { hash -> messages.firstOrNull { it.hash == hash } }
.maxOfOrNull { it.timestamp } .maxOfOrNull { it.timestamp }
Unit to maxTimestamp?.let(ConfigUpdateNotification::UserConfigsMerged) maxTimestamp?.let {
(config.dump() to it) to
listOf(ConfigUpdateNotification.UserConfigsMerged(userConfigType, it))
} ?: (null to emptyList())
}
// Dump now regardless so we can save the timestamp to the database
if (toDump != null) {
val (dump, timestamp) = toDump
configDatabase.storeConfig(
variant = userConfigType.configVariant,
publicKey = requiresCurrentUserAccountId().hexString,
data = dump,
timestamp = timestamp
)
} }
} }
override fun <T> withMutableUserConfigs(cb: (MutableUserConfigs) -> T): T { override fun <T> withMutableUserConfigs(cb: (MutableUserConfigs) -> T): T {
return doWithMutableUserConfigs { return doWithMutableUserConfigs {
val result = cb(it) val result = cb(it)
val changed = if (it.persistIfDirty(clock)) {
ConfigUpdateNotification.UserConfigsModified val changed = if (it.userGroups.dirty() ||
it.convoInfoVolatile.dirty() ||
it.userProfile.dirty() ||
it.contacts.dirty()) {
listOf(ConfigUpdateNotification.UserConfigsModified)
} else { } else {
null emptyList()
} }
result to changed result to changed
@ -293,15 +318,30 @@ class ConfigFactory @Inject constructor(
return return
} }
doWithMutableUserConfigs { configs -> // Confirm push for the configs and gather the dumped data to be saved into the db.
contacts?.let { (push, result) -> configs.contacts.confirmPushed(push.seqNo, result.hash) } // For this operation, we will no notify the users as there won't be any real change in terms
userProfile?.let { (push, result) -> configs.userProfile.confirmPushed(push.seqNo, result.hash) } // of the displaying data.
convoInfoVolatile?.let { (push, result) -> configs.convoInfoVolatile.confirmPushed(push.seqNo, result.hash) } val dump = doWithMutableUserConfigs { configs ->
userGroups?.let { (push, result) -> configs.userGroups.confirmPushed(push.seqNo, result.hash) } sequenceOf(contacts, userProfile, convoInfoVolatile, userGroups)
.zip(
sequenceOf(
UserConfigType.CONTACTS to configs.contacts,
UserConfigType.USER_PROFILE to configs.userProfile,
UserConfigType.CONVO_INFO_VOLATILE to configs.convoInfoVolatile,
UserConfigType.USER_GROUPS to configs.userGroups
)
)
.filter { (push, _) -> push != null }
.onEach { (push, config) -> config.second.confirmPushed(push!!.first.seqNo, push.second.hash) }
.map { (push, config) ->
Triple(config.first.configVariant, config.second.dump(), push!!.second.timestamp)
}.toList() to emptyList()
}
configs.persistIfDirty(clock) // We need to persist the data to the database to save timestamp after the push
val userAccountId = requiresCurrentUserAccountId()
Unit to null for ((variant, data, timestamp) in dump) {
configDatabase.storeConfig(variant, userAccountId.hexString, data, timestamp)
} }
} }
@ -329,18 +369,6 @@ class ConfigFactory @Inject constructor(
} }
} }
override fun getConfigTimestamp(forConfigObject: ConfigBase, publicKey: String): Long {
val variant = when (forConfigObject) {
is UserProfile -> SharedConfigMessage.Kind.USER_PROFILE.name
is Contacts -> SharedConfigMessage.Kind.CONTACTS.name
is ConversationVolatileConfig -> SharedConfigMessage.Kind.CONVO_INFO_VOLATILE.name
is UserGroupsConfig -> SharedConfigMessage.Kind.GROUPS.name
else -> throw UnsupportedOperationException("Can't support type of ${forConfigObject::class.simpleName} yet")
}
return configDatabase.retrieveConfigLastUpdateTimestamp(variant, publicKey)
}
override fun conversationInConfig( override fun conversationInConfig(
publicKey: String?, publicKey: String?,
groupPublicKey: String?, groupPublicKey: String?,
@ -391,6 +419,10 @@ class ConfigFactory @Inject constructor(
return (changeTimestampMs >= (lastUpdateTimestampMs - CONFIG_CHANGE_BUFFER_PERIOD)) return (changeTimestampMs >= (lastUpdateTimestampMs - CONFIG_CHANGE_BUFFER_PERIOD))
} }
override fun getConfigTimestamp(userConfigType: UserConfigType, publicKey: String): Long {
return configDatabase.retrieveConfigLastUpdateTimestamp(userConfigType.configVariant, publicKey)
}
override fun getGroupAuth(groupId: AccountId): SwarmAuth? { override fun getGroupAuth(groupId: AccountId): SwarmAuth? {
val (adminKey, authData) = withUserConfigs { val (adminKey, authData) = withUserConfigs {
val group = it.userGroups.getClosedGroup(groupId.hexString) val group = it.userGroups.getClosedGroup(groupId.hexString)
@ -441,6 +473,14 @@ class ConfigFactory @Inject constructor(
} }
} }
private val UserConfigType.configVariant: ConfigVariant
get() = when (this) {
UserConfigType.CONTACTS -> ConfigDatabase.CONTACTS_VARIANT
UserConfigType.USER_PROFILE -> ConfigDatabase.USER_PROFILE_VARIANT
UserConfigType.CONVO_INFO_VOLATILE -> ConfigDatabase.CONVO_INFO_VARIANT
UserConfigType.USER_GROUPS -> ConfigDatabase.USER_GROUPS_VARIANT
}
/** /**
* Sync group data from our local database * Sync group data from our local database
*/ */
@ -639,30 +679,6 @@ private class UserConfigsImpl(
convoInfoVolatile.initFrom(storage, threadDb) convoInfoVolatile.initFrom(storage, threadDb)
} }
} }
/**
* Persists the config if it is dirty and returns the list of classes that were persisted
*/
fun persistIfDirty(clock: SnodeClock): Boolean {
return sequenceOf(
contacts to ConfigDatabase.CONTACTS_VARIANT,
userGroups to ConfigDatabase.USER_GROUPS_VARIANT,
userProfile to ConfigDatabase.USER_PROFILE_VARIANT,
convoInfoVolatile to ConfigDatabase.CONVO_INFO_VARIANT
).fold(false) { acc, (config, variant) ->
if (config.needsDump()) {
configDatabase.storeConfig(
variant = variant,
publicKey = userAccountId.hexString,
data = config.dump(),
timestamp = clock.currentTimeMills()
)
true
} else {
acc
}
}
}
} }
private class GroupConfigsImpl( private class GroupConfigsImpl(

View File

@ -35,6 +35,7 @@ import org.session.libsession.messaging.sending_receiving.handleVisibleMessage
import org.session.libsession.messaging.utilities.Data import org.session.libsession.messaging.utilities.Data
import org.session.libsession.messaging.utilities.SodiumUtilities import org.session.libsession.messaging.utilities.SodiumUtilities
import org.session.libsession.utilities.SSKEnvironment import org.session.libsession.utilities.SSKEnvironment
import org.session.libsession.utilities.UserConfigType
import org.session.libsignal.protos.UtilProtos import org.session.libsignal.protos.UtilProtos
import org.session.libsignal.utilities.AccountId import org.session.libsignal.utilities.AccountId
import org.session.libsignal.utilities.IdPrefix import org.session.libsignal.utilities.IdPrefix
@ -103,24 +104,23 @@ class BatchMessageReceiveJob(
executeAsync(dispatcherName) executeAsync(dispatcherName)
} }
private fun isHidden(message: Message): Boolean{ private fun isHidden(message: Message): Boolean {
// if the contact is marked as hidden for 1on1 messages // if the contact is marked as hidden for 1on1 messages
// and the message's sentTimestamp is earlier than the sentTimestamp of the last config // and the message's sentTimestamp is earlier than the sentTimestamp of the last config
val config = MessagingModuleConfiguration.shared.configFactory val configFactory = MessagingModuleConfiguration.shared.configFactory
val publicKey = MessagingModuleConfiguration.shared.storage.getUserPublicKey() val publicKey = MessagingModuleConfiguration.shared.storage.getUserPublicKey()
if(config.contacts == null || message.sentTimestamp == null || publicKey == null) return false if (message.sentTimestamp == null || publicKey == null) return false
val contactConfigTimestamp = config.getConfigTimestamp(config.contacts!!, publicKey)
if(message.groupPublicKey == null && // not a group
message.openGroupServerMessageID == null && // not a community
// not marked as hidden
config.contacts?.get(message.senderOrSync)?.priority == ConfigBase.PRIORITY_HIDDEN &&
// the message's sentTimestamp is earlier than the sentTimestamp of the last config
message.sentTimestamp!! < contactConfigTimestamp
) {
return true
}
return false val contactConfigTimestamp = configFactory.getConfigTimestamp(UserConfigType.CONTACTS, publicKey)
return configFactory.withUserConfigs { configs ->
message.groupPublicKey == null && // not a group
message.openGroupServerMessageID == null && // not a community
// not marked as hidden
configs.contacts.get(message.senderOrSync)?.priority == ConfigBase.PRIORITY_HIDDEN &&
// the message's sentTimestamp is earlier than the sentTimestamp of the last config
message.sentTimestamp!! < contactConfigTimestamp
}
} }
suspend fun executeAsync(dispatcherName: String) { suspend fun executeAsync(dispatcherName: String) {

View File

@ -5,7 +5,6 @@ import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.withTimeoutOrNull import kotlinx.coroutines.withTimeoutOrNull
import network.loki.messenger.libsession_util.ConfigBase
import network.loki.messenger.libsession_util.MutableConfig import network.loki.messenger.libsession_util.MutableConfig
import network.loki.messenger.libsession_util.MutableContacts import network.loki.messenger.libsession_util.MutableContacts
import network.loki.messenger.libsession_util.MutableConversationVolatileConfig import network.loki.messenger.libsession_util.MutableConversationVolatileConfig
@ -196,8 +195,18 @@ interface MutableGroupConfigs : GroupConfigs {
sealed interface ConfigUpdateNotification { sealed interface ConfigUpdateNotification {
/**
* The user configs have been modified locally.
*/
data object UserConfigsModified : ConfigUpdateNotification data object UserConfigsModified : ConfigUpdateNotification
data class UserConfigsMerged(val timestamp: Long) : ConfigUpdateNotification
/**
* The user configs have been merged from the server.
*/
data class UserConfigsMerged(
val configType: UserConfigType,
val timestamp: Long
) : ConfigUpdateNotification
data class GroupConfigsUpdated(val groupId: AccountId) : ConfigUpdateNotification data class GroupConfigsUpdated(val groupId: AccountId) : ConfigUpdateNotification
} }