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:
parent
ecc75dfeed
commit
4b6a7c145e
|
@ -31,6 +31,7 @@ import org.session.libsession.messaging.contacts.Contact
|
||||||
import org.session.libsession.messaging.jobs.AttachmentUploadJob
|
import org.session.libsession.messaging.jobs.AttachmentUploadJob
|
||||||
import org.session.libsession.messaging.jobs.BackgroundGroupAddJob
|
import org.session.libsession.messaging.jobs.BackgroundGroupAddJob
|
||||||
import org.session.libsession.messaging.jobs.ConfigurationSyncJob
|
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.GroupAvatarDownloadJob
|
||||||
import org.session.libsession.messaging.jobs.InviteContactsJob
|
import org.session.libsession.messaging.jobs.InviteContactsJob
|
||||||
import org.session.libsession.messaging.jobs.Job
|
import org.session.libsession.messaging.jobs.Job
|
||||||
|
@ -1618,9 +1619,12 @@ open class Storage(
|
||||||
|
|
||||||
override fun handleMemberLeft(message: GroupUpdated, closedGroupId: SessionId) {
|
override fun handleMemberLeft(message: GroupUpdated, closedGroupId: SessionId) {
|
||||||
val userGroups = configFactory.userGroups ?: return
|
val userGroups = configFactory.userGroups ?: return
|
||||||
|
val closedGroupHexString = closedGroupId.hexString()
|
||||||
val closedGroup = userGroups.getClosedGroup(closedGroupId.hexString()) ?: return
|
val closedGroup = userGroups.getClosedGroup(closedGroupId.hexString()) ?: return
|
||||||
if (closedGroup.hasAdminKey()) {
|
if (closedGroup.hasAdminKey()) {
|
||||||
// re-key and do a new config removing the previous member
|
// 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 info = configFactory.getGroupInfoConfig(closedGroupId) ?: return
|
||||||
val members = configFactory.getGroupMemberConfig(closedGroupId) ?: return
|
val members = configFactory.getGroupMemberConfig(closedGroupId) ?: return
|
||||||
val keys = configFactory.getGroupKeysConfig(closedGroupId, info, members, free = false) ?: return
|
val keys = configFactory.getGroupKeysConfig(closedGroupId, info, members, free = false) ?: return
|
||||||
|
@ -1628,8 +1632,61 @@ open class Storage(
|
||||||
|
|
||||||
keys.rekey(info, members)
|
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)
|
insertGroupInfoChange(message, closedGroupId)
|
||||||
|
|
|
@ -102,58 +102,6 @@ data class ConfigurationSyncJob(val destination: Destination) : Job {
|
||||||
return SyncInformation(configsRequiringPush, toDelete)
|
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) {
|
override suspend fun execute(dispatcherName: String) {
|
||||||
val storage = MessagingModuleConfiguration.shared.storage
|
val storage = MessagingModuleConfiguration.shared.storage
|
||||||
|
|
||||||
|
@ -305,6 +253,58 @@ data class ConfigurationSyncJob(val destination: Destination) : Job {
|
||||||
// type mappings
|
// type mappings
|
||||||
const val CONTACT_TYPE = 1
|
const val CONTACT_TYPE = 1
|
||||||
const val GROUP_TYPE = 2
|
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> {
|
class Factory : Job.Factory<ConfigurationSyncJob> {
|
||||||
|
|
Loading…
Reference in New Issue