feat: bringing the config sync message types and amendment functions into a companion extension function to build into regular member change handling / invite logic

This commit is contained in:
0x330a 2023-12-04 00:11:15 +11:00
parent ecc75dfeed
commit 4b6a7c145e
2 changed files with 110 additions and 53 deletions

View File

@ -31,6 +31,7 @@ import org.session.libsession.messaging.contacts.Contact
import org.session.libsession.messaging.jobs.AttachmentUploadJob
import org.session.libsession.messaging.jobs.BackgroundGroupAddJob
import org.session.libsession.messaging.jobs.ConfigurationSyncJob
import org.session.libsession.messaging.jobs.ConfigurationSyncJob.Companion.messageInformation
import org.session.libsession.messaging.jobs.GroupAvatarDownloadJob
import org.session.libsession.messaging.jobs.InviteContactsJob
import org.session.libsession.messaging.jobs.Job
@ -1618,9 +1619,12 @@ open class Storage(
override fun handleMemberLeft(message: GroupUpdated, closedGroupId: SessionId) {
val userGroups = configFactory.userGroups ?: return
val closedGroupHexString = closedGroupId.hexString()
val closedGroup = userGroups.getClosedGroup(closedGroupId.hexString()) ?: return
if (closedGroup.hasAdminKey()) {
// re-key and do a new config removing the previous member
val adminKey = closedGroup.adminKey
val signCallback = SnodeAPI.signingKeyCallback(adminKey)
val info = configFactory.getGroupInfoConfig(closedGroupId) ?: return
val members = configFactory.getGroupMemberConfig(closedGroupId) ?: return
val keys = configFactory.getGroupKeysConfig(closedGroupId, info, members, free = false) ?: return
@ -1628,8 +1632,61 @@ open class Storage(
keys.rekey(info, members)
val
val toDelete = mutableListOf<String>()
val keyMessage = keys.messageInformation(closedGroupHexString, adminKey)
val infoMessage = info.messageInformation(toDelete, closedGroupHexString, adminKey)
val membersMessage = members.messageInformation(toDelete, closedGroupHexString, adminKey)
val delete = SnodeAPI.buildAuthenticatedDeleteBatchInfo(
closedGroupHexString,
toDelete,
signCallback
)
val stores = listOf(keyMessage, infoMessage, membersMessage).map(ConfigurationSyncJob.ConfigMessageInformation::batch)
val response = SnodeAPI.getSingleTargetSnode(closedGroupHexString).bind { snode ->
SnodeAPI.getRawBatchResponse(
snode,
closedGroupHexString,
stores + delete,
sequence = true
)
}
try {
response.get()
// todo: error handling here
configFactory.saveGroupConfigs(keys, info, members)
val timestamp = SnodeAPI.nowWithOffset
val messageToSign = "MEMBER_CHANGE${GroupUpdateMemberChangeMessage.Type.REMOVED.name}$timestamp"
val signature = SodiumUtilities.sign(messageToSign.toByteArray(), adminKey)
val updatedMessage = GroupUpdated(
DataMessage.GroupUpdateMessage.newBuilder()
.setMemberChangeMessage(
GroupUpdateMemberChangeMessage.newBuilder()
.addAllMemberSessionIds(listOf(message.sender!!))
.setType(GroupUpdateMemberChangeMessage.Type.REMOVED)
.setAdminSignature(ByteString.copyFrom(signature))
)
.build()
).apply { this.sentTimestamp = timestamp }
MessageSender.send(updatedMessage, fromSerialized(closedGroupHexString))
insertGroupInfoChange(updatedMessage, closedGroupId)
info.free()
members.free()
keys.free()
} catch (e: Exception) {
Log.e("ClosedGroup", "Failed to store new key", e)
info.free()
members.free()
keys.free()
// toaster toast here
return
}
}
insertGroupInfoChange(message, closedGroupId)

View File

@ -102,58 +102,6 @@ data class ConfigurationSyncJob(val destination: Destination) : Job {
return SyncInformation(configsRequiringPush, toDelete)
}
private fun ConfigBase.messageInformation(toDelete: MutableList<String>,
destinationPubKey: String,
signingKey: ByteArray? = null,
ed25519PubKey: String? = null): ConfigMessageInformation {
val sentTimestamp = SnodeAPI.nowWithOffset
val (push, seqNo, obsoleteHashes) = push()
toDelete.addAll(obsoleteHashes)
val message =
SnodeMessage(
destinationPubKey,
Base64.encodeBytes(push),
SnodeMessage.CONFIG_TTL,
sentTimestamp
)
return ConfigMessageInformation(
if (signingKey != null && ed25519PubKey == null) {
SnodeAPI.buildAuthenticatedStoreBatchInfo(
namespace(),
message,
signingKey,
)
} else SnodeAPI.buildAuthenticatedStoreBatchInfo(
namespace(),
message,
)!!,
this,
seqNo
)
}
private fun GroupKeysConfig.messageInformation(destinationPubKey: String, signingKey: ByteArray): ConfigMessageInformation {
val sentTimestamp = SnodeAPI.nowWithOffset
val message =
SnodeMessage(
destinationPubKey,
Base64.encodeBytes(pendingConfig()!!), // should not be null from checking has pending
SnodeMessage.CONFIG_TTL,
sentTimestamp
)
return ConfigMessageInformation(
SnodeAPI.buildAuthenticatedStoreBatchInfo(
namespace(),
message,
signingKey
),
this,
0
)
}
override suspend fun execute(dispatcherName: String) {
val storage = MessagingModuleConfiguration.shared.storage
@ -305,6 +253,58 @@ data class ConfigurationSyncJob(val destination: Destination) : Job {
// type mappings
const val CONTACT_TYPE = 1
const val GROUP_TYPE = 2
fun ConfigBase.messageInformation(toDelete: MutableList<String>,
destinationPubKey: String,
signingKey: ByteArray? = null,
ed25519PubKey: String? = null): ConfigMessageInformation {
val sentTimestamp = SnodeAPI.nowWithOffset
val (push, seqNo, obsoleteHashes) = push()
toDelete.addAll(obsoleteHashes)
val message =
SnodeMessage(
destinationPubKey,
Base64.encodeBytes(push),
SnodeMessage.CONFIG_TTL,
sentTimestamp
)
return ConfigMessageInformation(
if (signingKey != null && ed25519PubKey == null) {
SnodeAPI.buildAuthenticatedStoreBatchInfo(
namespace(),
message,
signingKey,
)
} else SnodeAPI.buildAuthenticatedStoreBatchInfo(
namespace(),
message,
)!!,
this,
seqNo
)
}
fun GroupKeysConfig.messageInformation(destinationPubKey: String, signingKey: ByteArray): ConfigMessageInformation {
val sentTimestamp = SnodeAPI.nowWithOffset
val message =
SnodeMessage(
destinationPubKey,
Base64.encodeBytes(pendingConfig()!!), // should not be null from checking has pending
SnodeMessage.CONFIG_TTL,
sentTimestamp
)
return ConfigMessageInformation(
SnodeAPI.buildAuthenticatedStoreBatchInfo(
namespace(),
message,
signingKey
),
this,
0
)
}
}
class Factory : Job.Factory<ConfigurationSyncJob> {