Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: pick up messages and mark as read #63

Merged
merged 5 commits into from
May 9, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
}
}
}
Loading