mirror of
https://github.com/oxen-io/session-android.git
synced 2025-08-11 21:07:42 +00:00
feat: handling responses and using new updated params
This commit is contained in:
@@ -312,41 +312,35 @@ object SnodeAPI {
|
||||
}
|
||||
}
|
||||
|
||||
/** Deletes all messages owned by the given pubkey on this SN and broadcasts the delete request to
|
||||
* all other swarm members.
|
||||
* Returns dict of:
|
||||
* - "swarms" dict mapping ed25519 pubkeys (in hex) of swarm members to dict values of:
|
||||
* - "failed" and other failure keys -- see `recursive`.
|
||||
* - "deleted": hashes of deleted messages.
|
||||
* - "signature": signature of ( PUBKEY_HEX || TIMESTAMP || DELETEDHASH[0] || ... || DELETEDHASH[N] ), signed
|
||||
* by the node's ed25519 pubkey.
|
||||
*/
|
||||
fun deleteAllMessages(context: Context): Promise<Set<RawResponsePromise>, Exception> {
|
||||
|
||||
return retryIfNeeded(1) {
|
||||
return retryIfNeeded(maxRetryCount) {
|
||||
// considerations: timestamp off in retrying logic, not being able to re-sign with latest timestamp? do we just not retry this as it will be synchronous
|
||||
val ed = KeyPairUtilities.getUserED25519KeyPair(context) ?: return@retryIfNeeded Promise.ofFail(Error.Generic)
|
||||
val xPrivateKey = IdentityKeyUtil.getIdentityKeyPair(context).privateKey
|
||||
val userKeyPair = MessagingModuleConfiguration.shared.storage.getUserX25519KeyPair()
|
||||
val userED25519KeyPair = KeyPairUtilities.getUserED25519KeyPair(context) ?: return@retryIfNeeded Promise.ofFail(Error.Generic)
|
||||
val userPublicKey = MessagingModuleConfiguration.shared.storage.getUserPublicKey() ?: return@retryIfNeeded Promise.ofFail(Error.Generic)
|
||||
|
||||
val destination = if (useTestnet) userPublicKey.removing05PrefixIfNeeded() else userPublicKey
|
||||
|
||||
getTargetSnodes(destination).map { swarm ->
|
||||
swarm.map { snode ->
|
||||
retryIfNeeded(1) {
|
||||
getSwarm(destination).map { swarm ->
|
||||
val promise = swarm.first().let { snode ->
|
||||
retryIfNeeded(maxRetryCount) {
|
||||
getNetworkTime(snode).bind { (_, timestamp) ->
|
||||
val signature = ByteArray(Sign.BYTES)
|
||||
val data = Snode.Method.DeleteAll.rawValue.toByteArray() + timestamp.toString().toByteArray()
|
||||
val signed = sodium.cryptoSignDetached(signature, data, data.size.toLong(), xPrivateKey.serialize())
|
||||
val deleteMessage = SnodeDeleteMessage(userPublicKey, timestamp, Base64.encodeBytes(signature))
|
||||
val parameters = deleteMessage.toJSON()
|
||||
invoke(Snode.Method.DeleteAll, snode, destination, parameters).fail { e ->
|
||||
val data = (Snode.Method.DeleteAll.rawValue + timestamp.toString()).toByteArray()
|
||||
sodium.cryptoSignDetached(signature, data, data.size.toLong(), userED25519KeyPair.secretKey.asBytes)
|
||||
val deleteMessageParams = mapOf(
|
||||
"pubkey" to userPublicKey,
|
||||
"pubkey_ed25519" to userED25519KeyPair.publicKey.asHexString,
|
||||
"timestamp" to timestamp,
|
||||
"signature" to Base64.encodeBytes(signature)
|
||||
)
|
||||
invoke(Snode.Method.DeleteAll, snode, destination, deleteMessageParams).map { rawResponse -> parseDeletions(timestamp, rawResponse) }.fail { e ->
|
||||
Log.e("Loki", "Failed to clear data",e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}.toSet()
|
||||
}
|
||||
setOf(promise)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -433,6 +427,43 @@ object SnodeAPI {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
private fun parseDeletions(timestamp: Long, rawResponse: RawResponse): Map<String, Any> {
|
||||
val swarms = rawResponse["swarms"] as? Map<String,Any> ?: return mapOf()
|
||||
val swarmResponsesValid = swarms.mapNotNull { (nodePubKeyHex, rawMap) ->
|
||||
val map = rawMap as? Map<String,Any> ?: return@mapNotNull null
|
||||
/** Deletes all messages owned by the given pubkey on this SN and broadcasts the delete request to
|
||||
* all other swarm members.
|
||||
* Returns dict of:
|
||||
* - "swarms" dict mapping ed25519 pubkeys (in hex) of swarm members to dict values of:
|
||||
* - "failed" and other failure keys -- see `recursive`.
|
||||
* - "deleted": hashes of deleted messages.
|
||||
* - "signature": signature of ( PUBKEY_HEX || TIMESTAMP || DELETEDHASH[0] || ... || DELETEDHASH[N] ), signed
|
||||
* by the node's ed25519 pubkey.
|
||||
*/
|
||||
// failure
|
||||
val failed = map["failed"] as? Boolean ?: false
|
||||
val code = map["code"] as? String
|
||||
val reason = map["reason"] as? String
|
||||
|
||||
nodePubKeyHex to if (failed) {
|
||||
// return error probs
|
||||
false
|
||||
} else {
|
||||
// success
|
||||
val deleted = map["deleted"] as List<String> // list of deleted hashes
|
||||
Log.d("Loki", "node $nodePubKeyHex deleted ${deleted.size} messages")
|
||||
val signature = map["signature"] as String
|
||||
val nodePubKeyBytes = Hex.fromStringCondensed(nodePubKeyHex)
|
||||
// signature of ( PUBKEY_HEX || TIMESTAMP || DELETEDHASH[0] || ... || DELETEDHASH[N] )
|
||||
val message = (signature + timestamp + deleted.fold("") { a, v -> a+v }).toByteArray()
|
||||
sodium.cryptoSignVerifyDetached(Base64.decode(signature), message, message.size, nodePubKeyBytes)
|
||||
}
|
||||
}
|
||||
return swarmResponsesValid.toMap()
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// Error Handling
|
||||
|
@@ -1,30 +0,0 @@
|
||||
package org.session.libsession.snode
|
||||
|
||||
import org.session.libsignal.utilities.removing05PrefixIfNeeded
|
||||
|
||||
data class SnodeDeleteMessage(
|
||||
/**
|
||||
* The hex encoded public key of the user.
|
||||
*/
|
||||
val pubKey: String,
|
||||
/**
|
||||
* The timestamp at which this request was initiated, in milliseconds since unix epoch.
|
||||
* Must be within Must be within ±60s of the current time.
|
||||
* (For clients it is recommended to retrieve a timestamp via `info` first, to avoid client time sync issues).
|
||||
*/
|
||||
val timestamp: Long,
|
||||
/**
|
||||
* a Base64-encoded signature of ( "delete_all" || timestamp ), signed by the pubKey
|
||||
*/
|
||||
val signature: String,
|
||||
) {
|
||||
|
||||
internal fun toJSON(): Map<String, Any> {
|
||||
return mapOf(
|
||||
"pubkey" to pubKey,
|
||||
"timestamp" to timestamp,
|
||||
"signature" to signature
|
||||
)
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user