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
  • Loading branch information
cristianIOHK authored May 9, 2023
1 parent 73f98c5 commit 087bb88
Show file tree
Hide file tree
Showing 13 changed files with 218 additions and 69 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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(),
Expand Down Expand Up @@ -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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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()
Expand Down
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
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
}
}
}
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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"]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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,
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -119,6 +131,7 @@ class PrismAgent {
return
}
state = State.STARTING
flowState.emit(State.STARTING)
try {
connectionManager.startMediator()
} catch (error: PrismAgentError.NoMediatorAvailableError) {
Expand All @@ -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()
Expand All @@ -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
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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())
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
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
Expand Up @@ -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)
Expand Down
Loading

0 comments on commit 087bb88

Please sign in to comment.