fix: group keys wasn't populating the config pushes for non keys objects in sync job
This commit is contained in:
parent
6913780536
commit
2fc83b87ad
|
@ -1231,12 +1231,16 @@ open class Storage(
|
|||
MessageSender.send(responseMessage, fromSerialized(groupId.hexString()))
|
||||
}
|
||||
|
||||
override fun setGroupInviteComplete(approved: Boolean, invitee: String, closedGroup: SessionId) {
|
||||
val groupMembers = configFactory.getGroupMemberConfig(closedGroup) ?: return
|
||||
override fun setGroupInviteCompleteIfNeeded(approved: Boolean, invitee: String, closedGroup: SessionId) {
|
||||
// don't try to process invitee acceptance if we aren't admin
|
||||
if (configFactory.userGroups?.getClosedGroup(closedGroup.hexString())?.hasAdminKey() != true) return
|
||||
|
||||
configFactory.getGroupMemberConfig(closedGroup)?.use { groupMembers ->
|
||||
val member = groupMembers.get(invitee) ?: run {
|
||||
Log.e("ClosedGroup", "User wasn't in the group membership to add!")
|
||||
return
|
||||
}
|
||||
if (!member.invitePending) return groupMembers.close()
|
||||
if (approved) {
|
||||
groupMembers.set(member.copy(invitePending = false))
|
||||
} else {
|
||||
|
@ -1244,7 +1248,7 @@ open class Storage(
|
|||
}
|
||||
configFactory.persistGroupConfigDump(groupMembers, closedGroup, SnodeAPI.nowWithOffset)
|
||||
ConfigurationMessageUtilities.forceSyncConfigurationNowIfNeeded(Destination.ClosedGroup(closedGroup.hexString()))
|
||||
groupMembers.close()
|
||||
}
|
||||
}
|
||||
|
||||
override fun setServerCapabilities(server: String, capabilities: List<String>) {
|
||||
|
|
|
@ -182,26 +182,29 @@ class ConfigFactory(
|
|||
override fun getGroupInfoConfig(groupSessionId: SessionId): GroupInfoConfig? = getGroupAuthInfo(groupSessionId)?.let { (sk, _) ->
|
||||
// get any potential initial dumps
|
||||
val dump = configDatabase.retrieveConfigAndHashes(
|
||||
SharedConfigMessage.Kind.CLOSED_GROUP_INFO.name,
|
||||
ConfigDatabase.INFO_VARIANT,
|
||||
groupSessionId.hexString()
|
||||
) ?: byteArrayOf()
|
||||
|
||||
GroupInfoConfig.newInstance(Hex.fromStringCondensed(groupSessionId.publicKey), sk, dump)
|
||||
}
|
||||
|
||||
override fun getGroupKeysConfig(groupSessionId: SessionId): GroupKeysConfig? = getGroupAuthInfo(groupSessionId)?.let { (sk, _) ->
|
||||
override fun getGroupKeysConfig(groupSessionId: SessionId,
|
||||
info: GroupInfoConfig?,
|
||||
members: GroupMembersConfig?,
|
||||
free: Boolean): GroupKeysConfig? = getGroupAuthInfo(groupSessionId)?.let { (sk, _) ->
|
||||
// Get the user info or return early
|
||||
val (userSk, _) = maybeGetUserInfo() ?: return@let null
|
||||
|
||||
// Get the group info or return early
|
||||
val info = getGroupInfoConfig(groupSessionId) ?: return@let null
|
||||
val usedInfo = info ?: getGroupInfoConfig(groupSessionId) ?: return@let null
|
||||
|
||||
// Get the group members or return early
|
||||
val members = getGroupMemberConfig(groupSessionId) ?: return@let null
|
||||
val usedMembers = members ?: getGroupMemberConfig(groupSessionId) ?: return@let null
|
||||
|
||||
// Get the dump or empty
|
||||
val dump = configDatabase.retrieveConfigAndHashes(
|
||||
SharedConfigMessage.Kind.ENCRYPTION_KEYS.name,
|
||||
ConfigDatabase.KEYS_VARIANT,
|
||||
groupSessionId.hexString()
|
||||
) ?: byteArrayOf()
|
||||
|
||||
|
@ -211,18 +214,20 @@ class ConfigFactory(
|
|||
Hex.fromStringCondensed(groupSessionId.publicKey),
|
||||
sk,
|
||||
dump,
|
||||
info,
|
||||
members
|
||||
usedInfo,
|
||||
usedMembers
|
||||
)
|
||||
info.free()
|
||||
members.free()
|
||||
if (free) {
|
||||
info?.free()
|
||||
members?.free()
|
||||
}
|
||||
keys
|
||||
}
|
||||
|
||||
override fun getGroupMemberConfig(groupSessionId: SessionId): GroupMembersConfig? = getGroupAuthInfo(groupSessionId)?.let { (sk, auth) ->
|
||||
// Get initial dump if we have one
|
||||
val dump = configDatabase.retrieveConfigAndHashes(
|
||||
SharedConfigMessage.Kind.CLOSED_GROUP_MEMBERS.name,
|
||||
ConfigDatabase.MEMBER_VARIANT,
|
||||
groupSessionId.hexString()
|
||||
) ?: byteArrayOf()
|
||||
|
||||
|
@ -298,8 +303,13 @@ class ConfigFactory(
|
|||
|
||||
fun persistGroupConfigDump(forConfigObject: ConfigBase, groupSessionId: SessionId, timestamp: Long) = synchronized(userGroupsLock) {
|
||||
val dumped = forConfigObject.dump()
|
||||
val variant = when (forConfigObject) {
|
||||
is GroupMembersConfig -> ConfigDatabase.MEMBER_VARIANT
|
||||
is GroupInfoConfig -> ConfigDatabase.INFO_VARIANT
|
||||
else -> throw Exception("Shouldn't be called")
|
||||
}
|
||||
configDatabase.storeConfig(
|
||||
ConfigDatabase.KEYS_VARIANT,
|
||||
variant,
|
||||
groupSessionId.hexString(),
|
||||
dumped,
|
||||
timestamp
|
||||
|
@ -375,7 +385,7 @@ class ConfigFactory(
|
|||
configDatabase.retrieveConfigLastUpdateTimestamp(variant, publicKey)
|
||||
|
||||
// Ensure the change occurred after the last config message was handled (minus the buffer period)
|
||||
return (changeTimestampMs >= (lastUpdateTimestampMs - ConfigFactory.configChangeBufferPeriod))
|
||||
return (changeTimestampMs >= (lastUpdateTimestampMs - configChangeBufferPeriod))
|
||||
}
|
||||
|
||||
override fun saveGroupConfigs(
|
||||
|
|
|
@ -10,6 +10,7 @@ import androidx.annotation.StringRes
|
|||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
|
@ -35,6 +36,7 @@ import androidx.compose.ui.Alignment
|
|||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.ComposeView
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.semantics.contentDescription
|
||||
import androidx.compose.ui.semantics.semantics
|
||||
|
@ -50,13 +52,17 @@ import kotlinx.coroutines.Dispatchers
|
|||
import kotlinx.coroutines.launch
|
||||
import network.loki.messenger.R
|
||||
import network.loki.messenger.databinding.FragmentCreateGroupBinding
|
||||
import org.session.libsession.avatars.ContactPhoto
|
||||
import org.session.libsession.messaging.contacts.Contact
|
||||
import org.session.libsession.utilities.Address
|
||||
import org.session.libsession.utilities.Device
|
||||
import org.session.libsession.utilities.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.conversation.start.NewConversationDelegate
|
||||
import org.thoughtcrime.securesms.conversation.v2.ConversationActivityV2
|
||||
import org.thoughtcrime.securesms.ui.AppTheme
|
||||
import org.thoughtcrime.securesms.ui.Avatar
|
||||
import org.thoughtcrime.securesms.ui.EditableAvatar
|
||||
import org.thoughtcrime.securesms.ui.LocalPreviewMode
|
||||
import org.thoughtcrime.securesms.ui.NavigationBar
|
||||
import org.thoughtcrime.securesms.ui.PreviewTheme
|
||||
import org.thoughtcrime.securesms.ui.ThemeResPreviewParameterProvider
|
||||
|
@ -252,9 +258,11 @@ fun LazyListScope.memberList(contacts: List<Contact>, modifier: Modifier = Modif
|
|||
EmptyPlaceholder(modifier.fillParentMaxWidth())
|
||||
}
|
||||
} else {
|
||||
items(contacts) {
|
||||
// TODO
|
||||
|
||||
items(contacts) { contact ->
|
||||
Row(modifier) {
|
||||
val context = LocalContext.current
|
||||
Avatar(Recipient.from(context, Address.fromSerialized(contact.sessionID), false))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -282,11 +290,10 @@ fun EmptyPlaceholder(modifier: Modifier = Modifier) {
|
|||
fun ClosedGroupPreview(
|
||||
@PreviewParameter(ThemeResPreviewParameterProvider::class) themeResId: Int
|
||||
) {
|
||||
val random = "05abcd1234"
|
||||
val random = "05abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234"
|
||||
val previewMembers = setOf(
|
||||
Contact(random).apply {
|
||||
name = "Person"
|
||||
|
||||
}
|
||||
)
|
||||
PreviewTheme(themeResId) {
|
||||
|
@ -299,3 +306,11 @@ fun ClosedGroupPreview(
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun Contact.contactPhoto(): ContactPhoto {
|
||||
if (LocalPreviewMode.current) {
|
||||
//
|
||||
}
|
||||
TODO()
|
||||
}
|
|
@ -256,7 +256,10 @@ fun NavigationBar(
|
|||
}
|
||||
}
|
||||
//Main title
|
||||
Box(modifier = Modifier.fillMaxHeight().weight(1f).padding(8.dp)) {
|
||||
Box(modifier = Modifier
|
||||
.fillMaxHeight()
|
||||
.weight(1f)
|
||||
.padding(8.dp)) {
|
||||
Text(
|
||||
text = title,
|
||||
Modifier.align(titleAlignment),
|
||||
|
|
|
@ -18,6 +18,7 @@ import com.google.android.material.color.MaterialColors
|
|||
import network.loki.messenger.R
|
||||
|
||||
val LocalExtraColors = staticCompositionLocalOf<ExtraColors> { error("No Custom Attribute value provided") }
|
||||
val LocalPreviewMode = staticCompositionLocalOf { false }
|
||||
|
||||
|
||||
data class ExtraColors(
|
||||
|
@ -56,7 +57,8 @@ fun PreviewTheme(
|
|||
content: @Composable () -> Unit
|
||||
) {
|
||||
CompositionLocalProvider(
|
||||
LocalContext provides ContextThemeWrapper(LocalContext.current, themeResId)
|
||||
LocalContext provides ContextThemeWrapper(LocalContext.current, themeResId),
|
||||
LocalPreviewMode provides true
|
||||
) {
|
||||
AppTheme {
|
||||
Box(modifier = Modifier.background(color = MaterialTheme.colors.background)) {
|
||||
|
|
|
@ -47,12 +47,18 @@ object ConfigurationMessageUtilities {
|
|||
debouncer.publish {
|
||||
// don't schedule job if we already have one
|
||||
val storage = MessagingModuleConfiguration.shared.storage
|
||||
val configFactory = MessagingModuleConfiguration.shared.configFactory
|
||||
val destinations = synchronized(destinationUpdater) {
|
||||
val objects = pendingDestinations.toList()
|
||||
pendingDestinations.clear()
|
||||
objects
|
||||
}
|
||||
destinations.forEach { destination ->
|
||||
if (destination is Destination.ClosedGroup) {
|
||||
// ensure we have the appropriate admin keys, skip this destination otherwise
|
||||
val group = configFactory.userGroups?.getClosedGroup(destination.publicKey) ?: return@forEach
|
||||
if (group.adminKey.isEmpty()) return@forEach Log.w("ConfigurationSync", "Trying to schedule config sync for group we aren't an admin of")
|
||||
}
|
||||
val currentStorageJob = storage.getConfigSyncJob(destination)
|
||||
if (currentStorageJob != null) {
|
||||
(currentStorageJob as ConfigurationSyncJob).shouldRunAgain.set(true)
|
||||
|
|
|
@ -25,7 +25,7 @@ coreVersion=1.8.0
|
|||
coroutinesVersion=1.6.4
|
||||
curve25519Version=0.6.0
|
||||
daggerVersion=2.46.1
|
||||
glideVersion=4.11.0
|
||||
glideVersion=4.16.0
|
||||
jacksonDatabindVersion=2.9.8
|
||||
junitVersion=4.13.2
|
||||
kotlinxJsonVersion=1.3.3
|
||||
|
|
|
@ -42,6 +42,8 @@ sealed class GroupInfo {
|
|||
return if (adminKey.isNotEmpty()) adminKey else authData
|
||||
}
|
||||
|
||||
fun hasAdminKey() = adminKey.isNotEmpty()
|
||||
|
||||
}
|
||||
|
||||
data class LegacyGroupInfo(
|
||||
|
|
|
@ -160,7 +160,7 @@ interface StorageProtocol {
|
|||
fun createNewGroup(groupName: String, groupDescription: String, members: Set<Contact>): Optional<Recipient>
|
||||
fun getMembers(groupPublicKey: String): List<LibSessionGroupMember>
|
||||
fun acceptClosedGroupInvite(groupId: SessionId, name: String, authData: ByteArray, invitingAdmin: SessionId)
|
||||
fun setGroupInviteComplete(approved: Boolean, invitee: String, closedGroup: SessionId)
|
||||
fun setGroupInviteCompleteIfNeeded(approved: Boolean, invitee: String, closedGroup: SessionId)
|
||||
|
||||
// Groups
|
||||
fun getAllGroups(includeInactive: Boolean): List<GroupRecord>
|
||||
|
|
|
@ -55,16 +55,17 @@ data class ConfigurationSyncJob(val destination: Destination) : Job {
|
|||
val groupId = SessionId.from(destination.publicKey)
|
||||
|
||||
// Get the signing key for pushing configs
|
||||
// TODO: do nothing if we don't have the keys / aren't admin
|
||||
val signingKey =
|
||||
configFactoryProtocol.userGroups!!.getClosedGroup(
|
||||
destination.publicKey
|
||||
)!!
|
||||
.signingKey()
|
||||
|
||||
val keys = configFactoryProtocol.getGroupKeysConfig(groupId)!!
|
||||
val signingKey = configFactoryProtocol
|
||||
.userGroups?.getClosedGroup(destination.publicKey)?.adminKey
|
||||
if (signingKey?.isNotEmpty() == true) {
|
||||
val info = configFactoryProtocol.getGroupInfoConfig(groupId)!!
|
||||
val members = configFactoryProtocol.getGroupMemberConfig(groupId)!!
|
||||
val keys = configFactoryProtocol.getGroupKeysConfig(
|
||||
groupId,
|
||||
info,
|
||||
members,
|
||||
false
|
||||
)!!
|
||||
|
||||
val requiringPush =
|
||||
listOf(keys, info, members).filter {
|
||||
|
@ -89,6 +90,7 @@ data class ConfigurationSyncJob(val destination: Destination) : Job {
|
|||
null
|
||||
}
|
||||
}
|
||||
} else emptyList()
|
||||
} else if (destination is Destination.Contact) {
|
||||
// assume our own user as check already takes place in `execute` for our own key
|
||||
// if contact
|
||||
|
|
|
@ -313,6 +313,14 @@ fun MessageReceiver.handleVisibleMessage(
|
|||
storage.setBlocksCommunityMessageRequests(recipient, message.blocksMessageRequests)
|
||||
}
|
||||
}
|
||||
// Handle group invite response if new closed group
|
||||
if (threadRecipient?.isClosedGroupRecipient == true) {
|
||||
storage.setGroupInviteCompleteIfNeeded(
|
||||
approved = true,
|
||||
recipient.address.serialize(),
|
||||
SessionId.from(threadRecipient.address.serialize())
|
||||
)
|
||||
}
|
||||
// Parse quote if needed
|
||||
var quoteModel: QuoteModel? = null
|
||||
var quoteMessageBody: String? = null
|
||||
|
@ -534,7 +542,7 @@ private fun MessageReceiver.handleInviteResponse(message: GroupUpdated, closedGr
|
|||
// val profile = message // maybe we do need data to be the inner so we can access profile
|
||||
val storage = MessagingModuleConfiguration.shared.storage
|
||||
val approved = message.inner.inviteResponse.isApproved
|
||||
storage.setGroupInviteComplete(approved, sender, closedGroup)
|
||||
storage.setGroupInviteCompleteIfNeeded(approved, sender, closedGroup)
|
||||
}
|
||||
|
||||
private fun MessageReceiver.handleNewLibSessionClosedGroupMessage(message: GroupUpdated) {
|
||||
|
|
|
@ -98,7 +98,12 @@ class ClosedGroupPoller(private val executor: CoroutineScope,
|
|||
val info = configFactoryProtocol.getGroupInfoConfig(closedGroupSessionId) ?: return null
|
||||
val members = configFactoryProtocol.getGroupMemberConfig(closedGroupSessionId)
|
||||
?: return null
|
||||
val keys = configFactoryProtocol.getGroupKeysConfig(closedGroupSessionId) ?: return null
|
||||
val keys = configFactoryProtocol.getGroupKeysConfig(
|
||||
closedGroupSessionId,
|
||||
info,
|
||||
members,
|
||||
free = false
|
||||
) ?: return null
|
||||
|
||||
val hashesToExtend = mutableSetOf<String>()
|
||||
|
||||
|
|
|
@ -1014,6 +1014,10 @@ object SnodeAPI {
|
|||
Log.d("Loki", "404, probably no file found")
|
||||
return Error.Generic
|
||||
}
|
||||
401 -> {
|
||||
Log.d("Loki", "401, check you're doing a sign properly")
|
||||
return Error.SigningFailed
|
||||
}
|
||||
else -> {
|
||||
handleBadSnode()
|
||||
Log.d("Loki", "Unhandled response code: ${statusCode}.")
|
||||
|
|
|
@ -20,7 +20,10 @@ interface ConfigFactoryProtocol {
|
|||
|
||||
fun getGroupInfoConfig(groupSessionId: SessionId): GroupInfoConfig?
|
||||
fun getGroupMemberConfig(groupSessionId: SessionId): GroupMembersConfig?
|
||||
fun getGroupKeysConfig(groupSessionId: SessionId): GroupKeysConfig?
|
||||
fun getGroupKeysConfig(groupSessionId: SessionId,
|
||||
info: GroupInfoConfig? = null,
|
||||
members: GroupMembersConfig? = null,
|
||||
free: Boolean = true): GroupKeysConfig?
|
||||
|
||||
fun getUserConfigs(): List<ConfigBase>
|
||||
fun persist(forConfigObject: Config, timestamp: Long)
|
||||
|
|
Loading…
Reference in New Issue