Skip to content

Commit

Permalink
fix: pick up messages and mark as read (#63)
Browse files Browse the repository at this point in the history
cristianIOHK authored May 9, 2023
1 parent 73f98c5 commit 087bb88
Showing 13 changed files with 218 additions and 69 deletions.
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@ package io.iohk.atala.prism.walletsdk.domain.models

import io.iohk.atala.prism.apollo.uuid.UUID
import kotlinx.datetime.Clock
import kotlinx.serialization.EncodeDefault
import kotlinx.serialization.Serializable
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
@@ -12,9 +13,9 @@ import kotlin.time.Duration.Companion.days
data class Message @JvmOverloads constructor(
val id: String = UUID.randomUUID4().toString(),
val piuri: String,
val from: DID? = null,
val to: DID? = null,
val fromPrior: String? = null,
@EncodeDefault val from: DID? = null,
@EncodeDefault val to: DID? = null,
@EncodeDefault val fromPrior: String? = null,
val body: String,
val extraHeaders: Array<String> = arrayOf(),
val createdTime: String = Clock.System.now().toString(),
@@ -73,6 +74,16 @@ data class Message @JvmOverloads constructor(
SENT(0),
RECEIVED(1),
}

companion object {
fun isBase64Attachment(data: AttachmentData): Boolean {
return data is AttachmentBase64
}

fun isJsonAttachment(data: AttachmentData): Boolean {
return data is AttachmentJsonData
}
}
}

fun getDirectionByValue(value: Int): Message.Direction {
Original file line number Diff line number Diff line change
@@ -9,6 +9,8 @@ import io.iohk.atala.prism.walletsdk.domain.models.MercuryError
import io.iohk.atala.prism.walletsdk.domain.models.Message
import io.iohk.atala.prism.walletsdk.mercury.forward.ForwardMessage
import io.iohk.atala.prism.walletsdk.prismagent.shared.KeyValue
import io.ktor.http.HttpHeaders
import org.didcommx.didcomm.common.Typ
import org.didcommx.didcomm.utils.isDID
import kotlin.jvm.Throws

@@ -96,7 +98,7 @@ class MercuryImpl(
"POST",
service.serviceEndpoint.uri,
emptyArray(),
arrayOf(KeyValue("Content-type", "application/didcomm-encrypted+json")),
arrayOf(KeyValue(HttpHeaders.ContentType, Typ.Encrypted.typ)),
message
)
return result.jsonString.toByteArray()
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.iohk.atala.prism.walletsdk.mercury.resolvers

import com.nimbusds.jose.shaded.json.JSONObject
import io.iohk.atala.prism.walletsdk.domain.buildingblocks.Apollo
import io.iohk.atala.prism.walletsdk.domain.buildingblocks.Castor
import io.iohk.atala.prism.walletsdk.domain.buildingblocks.Pluto
@@ -32,8 +33,8 @@ import org.didcommx.didcomm.common.Typ
import org.didcommx.didcomm.message.Attachment
import org.didcommx.didcomm.model.PackEncryptedParams
import org.didcommx.didcomm.model.UnpackParams
import org.didcommx.didcomm.utils.fromJsonToMap
import java.time.Instant.now
import kotlin.jvm.Throws

class DIDCommWrapper(castor: Castor, pluto: Pluto, apollo: Apollo) : DIDCommProtocol {
private val didDocResolver = DIDCommDIDResolver(castor)
@@ -61,20 +62,20 @@ class DIDCommWrapper(castor: Castor, pluto: Pluto, apollo: Apollo) : DIDCommProt

is JsonPrimitive -> {
if (it.isString) {
bodyMap[key] = it.content
array.add(it.content)
} else if (it.intOrNull != null) {
bodyMap[key] = it.int
array.add(it.int)
} else if (it.doubleOrNull != null) {
bodyMap[key] = it.double
array.add(it.double)
} else if (it.booleanOrNull != null) {
bodyMap[key] = it.boolean
array.add(it.boolean)
} else {
bodyMap[key] = it
array.add(it)
}
}

else -> {
bodyMap[key] = it
array.add(it)
}
}
}
@@ -132,7 +133,6 @@ class DIDCommWrapper(castor: Castor, pluto: Pluto, apollo: Apollo) : DIDCommProt
pleaseAck = null,
customHeaders = mapOf()
)

val builder = PackEncryptedParams.builder(didCommMsg, toString).forward(false).protectSenderId(false)
didCommMsg.from?.let { builder.from(it) }
val params = builder.build()
@@ -166,8 +166,7 @@ class DIDCommWrapper(castor: Castor, pluto: Pluto, apollo: Apollo) : DIDCommProt
}

if (data is AttachmentJsonData) {
val json = Json.parseToJsonElement(data.data)
return Attachment.Data.Json(json.jsonObject.toMap())
return Attachment.Data.Json(fromJsonToMap(data.data))
}

if (data is AttachmentLinkData) {
@@ -243,8 +242,8 @@ class DIDCommWrapper(castor: Castor, pluto: Pluto, apollo: Apollo) : DIDCommProt
}

val json = jsonObj["json"]
if (json is String) {
return AttachmentJsonData(json)
if (json is JSONObject) {
return AttachmentJsonData(JSONObject.toJSONString(json as Map<String, *>))
}

val links = jsonObj["links"]
Original file line number Diff line number Diff line change
@@ -50,8 +50,10 @@ class ConnectionManager(
messagesIds.add(pair.first)
messages.add(pair.second)
}
mediationHandler.registerMessagesAsRead(messagesIds.toTypedArray())
pluto.storeMessages(messages)
if (messagesIds.isNotEmpty()) {
mediationHandler.registerMessagesAsRead(messagesIds.toTypedArray())
pluto.storeMessages(messages)
}
}
}

Original file line number Diff line number Diff line change
@@ -29,6 +29,7 @@ import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
import kotlinx.serialization.Serializable
@@ -50,6 +51,11 @@ class PrismAgent {

private val api: Api
private val connectionManager: ConnectionManager
private val flowState = MutableSharedFlow<State>()

fun getFlowState(): Flow<State> {
return flowState
}

internal constructor(
apollo: Apollo,
@@ -60,6 +66,9 @@ class PrismAgent {
seed: Seed?,
api: Api?
) {
GlobalScope.launch {
flowState.emit(State.STOPPED)
}
this.apollo = apollo
this.castor = castor
this.pluto = pluto
@@ -91,6 +100,9 @@ class PrismAgent {
api: Api? = null,
mediatorHandler: MediationHandler
) {
GlobalScope.launch {
flowState.emit(State.STOPPED)
}
this.apollo = apollo
this.castor = castor
this.pluto = pluto
@@ -119,6 +131,7 @@ class PrismAgent {
return
}
state = State.STARTING
flowState.emit(State.STARTING)
try {
connectionManager.startMediator()
} catch (error: PrismAgentError.NoMediatorAvailableError) {
@@ -129,6 +142,7 @@ class PrismAgent {
connectionManager.registerMediator(hostDID)
}
if (connectionManager.mediationHandler.mediator != null) {
flowState.emit(State.RUNNING)
state = State.RUNNING
} else {
throw PrismAgentError.MediationRequestFailedError()
@@ -139,8 +153,10 @@ class PrismAgent {
if (state != State.RUNNING) {
return
}
flowState.emit(State.STOPPING)
state = State.STOPPING
fetchingMessagesJob?.cancel()
flowState.emit(State.STOPPED)
state = State.STOPPED
}

Original file line number Diff line number Diff line change
@@ -3,19 +3,16 @@ package io.iohk.atala.prism.walletsdk.prismagent.mediation
import io.iohk.atala.prism.apollo.uuid.UUID
import io.iohk.atala.prism.walletsdk.domain.buildingblocks.Mercury
import io.iohk.atala.prism.walletsdk.domain.buildingblocks.Pluto
import io.iohk.atala.prism.walletsdk.domain.models.AttachmentBase64
import io.iohk.atala.prism.walletsdk.domain.models.AttachmentDescriptor
import io.iohk.atala.prism.walletsdk.domain.models.AttachmentJsonData
import io.iohk.atala.prism.walletsdk.domain.models.DID
import io.iohk.atala.prism.walletsdk.domain.models.Mediator
import io.iohk.atala.prism.walletsdk.domain.models.Message
import io.iohk.atala.prism.walletsdk.domain.models.PrismAgentError
import io.iohk.atala.prism.walletsdk.prismagent.protocols.mediation.MediationGrant
import io.iohk.atala.prism.walletsdk.prismagent.protocols.mediation.MediationKeysUpdateList
import io.iohk.atala.prism.walletsdk.prismagent.protocols.mediation.MediationRequest
import io.iohk.atala.prism.walletsdk.prismagent.protocols.pickup.PickupDelivery
import io.iohk.atala.prism.walletsdk.prismagent.protocols.pickup.PickupReceived
import io.iohk.atala.prism.walletsdk.prismagent.protocols.pickup.PickupRequest
import io.iohk.atala.prism.walletsdk.prismagent.protocols.pickup.PickupRunner
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.flow
@@ -101,20 +98,9 @@ final class BasicMediatorHandler(

return flow {
val message = mercury.sendMessageParseResponse(requestMessage)
val receivedMessage = message?.let { PickupDelivery(it) }
val response = receivedMessage?.let {
it.attachments.mapNotNull { attachment: AttachmentDescriptor ->
val data = attachment.data
when (data) {
is AttachmentBase64 -> Pair(it.id, data.base64)
is AttachmentJsonData -> Pair(it.id, data.data)
else -> null
}
}.map {
Pair(it.first, mercury.unpackMessage(it.second))
}.toTypedArray()
} ?: emptyArray()
emit(response)
message?.let {
emit(PickupRunner(message, mercury).run())
}
}
}

Original file line number Diff line number Diff line change
@@ -4,6 +4,8 @@ import io.iohk.atala.prism.apollo.uuid.UUID
import io.iohk.atala.prism.walletsdk.domain.models.DID
import io.iohk.atala.prism.walletsdk.domain.models.Message
import io.iohk.atala.prism.walletsdk.prismagent.protocols.ProtocolType
import kotlinx.serialization.EncodeDefault
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
@@ -53,7 +55,7 @@ final class MediationKeysUpdateList {
}

@Serializable
data class Update @JvmOverloads constructor(var recipientDid: String, var action: String = "add")
data class Update @JvmOverloads constructor(@SerialName("recipient_did")var recipientDid: String, @EncodeDefault var action: String = "add")

@Serializable
data class Body @JvmOverloads constructor(var updates: Array<Update> = emptyArray()) {
Original file line number Diff line number Diff line change
@@ -4,6 +4,7 @@ import io.iohk.atala.prism.apollo.uuid.UUID
import io.iohk.atala.prism.walletsdk.domain.models.DID
import io.iohk.atala.prism.walletsdk.domain.models.Message
import io.iohk.atala.prism.walletsdk.prismagent.protocols.ProtocolType
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
@@ -30,25 +31,15 @@ final class PickupReceived {

fun makeMessage(): Message {
return Message(
id = id,
piuri = type,
from = from,
to = to,
fromPrior = null,
body = Json.encodeToString(body),
extraHeaders = emptyArray(),
createdTime = "",
expiresTimePlus = "",
attachments = emptyArray(),
thid = null,
pthid = null,
ack = emptyArray(),
direction = Message.Direction.SENT
body = Json.encodeToString(body)
)
}

@Serializable
data class Body(var messageIdList: Array<String>) {
data class Body(@SerialName("message_id_list") var messageIdList: Array<String>) {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package io.iohk.atala.prism.walletsdk.prismagent.protocols.pickup

import io.iohk.atala.prism.walletsdk.domain.buildingblocks.Mercury
import io.iohk.atala.prism.walletsdk.domain.models.AttachmentBase64
import io.iohk.atala.prism.walletsdk.domain.models.AttachmentDescriptor
import io.iohk.atala.prism.walletsdk.domain.models.AttachmentJsonData
import io.iohk.atala.prism.walletsdk.domain.models.Message
import io.iohk.atala.prism.walletsdk.domain.models.PrismAgentError
import io.iohk.atala.prism.walletsdk.prismagent.protocols.ProtocolType

class PickupRunner(message: Message, private val mercury: Mercury) {

enum class PickupResponseType(val type: String) {
STATUS("status"),
DELIVERY("delivery")
}

data class PickupResponse(val type: PickupResponseType, val message: Message)

data class PickupAttachment(
val attachmentId: String,
val data: String
)

private val message: PickupResponse

init {
when (message.piuri) {
ProtocolType.PickupStatus.value -> {
this.message = PickupResponse(PickupResponseType.STATUS, message)
}

ProtocolType.PickupDelivery.value -> {
this.message = PickupResponse(PickupResponseType.DELIVERY, message)
}

else -> {
throw PrismAgentError.InvalidPickupDeliveryMessageError()
}
}
}

suspend fun run(): Array<Pair<String, Message>> {
return if (message.type == PickupResponseType.DELIVERY) {
message.message.attachments
.mapNotNull { processAttachment(it) }
.map { Pair(it.attachmentId, mercury.unpackMessage(it.data)) }
.toTypedArray()
} else {
arrayOf()
}
}

// TODO: Clean this method
private fun processAttachment(attachment: AttachmentDescriptor): PickupAttachment? {
return if (Message.isBase64Attachment(attachment.data)) {
PickupAttachment(attachmentId = attachment.id, data = (attachment.data as AttachmentBase64).base64)
} else if (Message.isJsonAttachment(attachment.data)) {
PickupAttachment(
attachmentId = attachment.id,
data = (attachment.data as AttachmentJsonData).data
)
} else {
null
}
}
}
Original file line number Diff line number Diff line change
@@ -32,16 +32,11 @@ object PrismShared {

val builder = HttpRequestBuilder()
for (header in httpHeaders) {
if (
httpMethod == HttpMethod.Get &&
header.key == HttpHeaders.ContentType &&
header.value.contains(ContentType.Application.Json.contentSubtype)
) {
continue
}
builder.headers.append(header.key, header.value)
}
builder.contentType(ContentType.Application.Json)
if (!builder.headers.contains(HttpHeaders.ContentType)) {
builder.contentType(ContentType.Application.Json)
}

body?.let {
builder.setBody(body)
Loading

0 comments on commit 087bb88

Please sign in to comment.