Skip to content

Commit

Permalink
feat: updates for pickup and ping protocols (#4)
Browse files Browse the repository at this point in the history
  • Loading branch information
Anton Baliasnikov committed Aug 22, 2023
1 parent 330e4d9 commit 150306c
Show file tree
Hide file tree
Showing 9 changed files with 73 additions and 34 deletions.
13 changes: 8 additions & 5 deletions src/test/kotlin/abilities/CommunicateViaDidcomm.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package abilities

import models.AgentPeerService
import models.DIDDocResolverPeerDID
import models.PeerDID
import net.serenitybdd.core.Serenity
import net.serenitybdd.rest.SerenityRest
import net.serenitybdd.screenplay.Ability
Expand All @@ -12,6 +13,7 @@ import org.didcommx.didcomm.model.PackEncryptedParams
import org.didcommx.didcomm.model.UnpackParams
import org.didcommx.didcomm.protocols.routing.Routing
import org.didcommx.didcomm.protocols.routing.WrapInForwardResult
import org.didcommx.didcomm.secret.SecretResolver
import org.didcommx.didcomm.utils.fromJsonToMap

open class CommunicateViaDidcomm(var mediatorPeerDid: String, serviceEndpoint: String = "") : Ability {
Expand All @@ -33,7 +35,8 @@ open class CommunicateViaDidcomm(var mediatorPeerDid: String, serviceEndpoint: S

fun getDid(): String = peerDidService.did

fun createNewPeerDid(): String = AgentPeerService.makePeerDid().did
fun createNewPeerDidService(serviceEndpoint: String = ""): PeerDID =
AgentPeerService.makePeerDid(serviceEndpoint = serviceEndpoint)

fun packMessage(message: Message, to: String = mediatorPeerDid): String =
didComm.packEncrypted(
Expand All @@ -47,18 +50,18 @@ open class CommunicateViaDidcomm(var mediatorPeerDid: String, serviceEndpoint: S
val packedMessage = packMessage(message, to)
return routing.wrapInForward(fromJsonToMap(packedMessage), to, routingKeys = listOf(mediatorPeerDid))!!
}
fun unpackMessage(message: String): Message = didComm.unpack(
fun unpackMessage(message: String, secretResolver: SecretResolver? = null): Message = didComm.unpack(
UnpackParams(
packedMessage = message,
didDocResolver = didDocResolver,
secretResolver = peerDidService.getSecretResolverInMemory(),
secretResolver = secretResolver ?: peerDidService.getSecretResolverInMemory(),
expectDecryptByAllKeys = false,
unwrapReWrappingForward = false
)
).message

fun unpackLastDidcommMessage(): Message {
val didcommMessage = unpackMessage(SerenityRest.lastResponse().asString())
fun unpackLastDidcommMessage(secretResolver: SecretResolver? = null): Message {
val didcommMessage = unpackMessage(SerenityRest.lastResponse().asString(), secretResolver)
Serenity.recordReportData().withTitle("DIDComm Response").andContents(didcommMessage.toString())
return didcommMessage
}
Expand Down
2 changes: 1 addition & 1 deletion src/test/kotlin/common/Ensure.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import net.serenitybdd.screenplay.ensure.thatTheListOf as ThatTheListOf
import net.serenitybdd.screenplay.targets.Target as SerenityTarget

object Ensure {
fun that(value: String) = That(value)
fun that(value: String?) = That(value)
fun that(value: LocalDate) = That(value)
fun that(value: LocalTime) = That(value)
fun that(value: Boolean) = That(value)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class MediationCoordinationSteps {
Ensure.that(didcommResponse.type).isEqualTo(DidcommMessageTypes.MEDIATE_GRANT),
Ensure.that(mediationResponse.routing_did).isNotEmpty()
)
recipient.usingAbilityTo(CommunicateViaDidcomm::class.java).mediatorPeerDid = mediationResponse.routing_did
recipient.remember("routingDid", mediationResponse.routing_did)
}

@Then("Mediator responds to {actor} with mediate deny message")
Expand All @@ -50,18 +50,20 @@ class MediationCoordinationSteps {

@When("{actor} sends a keylist update message to the mediator with a new peer did")
fun recipientSendsAKeylistUpdateMessageToTheMediatorWithANewPeerDid(recipient: Actor) {
val newPeerDid = recipient.usingAbilityTo(CommunicateViaDidcomm::class.java).createNewPeerDid()
val communicationPeerDidService = recipient.usingAbilityTo(CommunicateViaDidcomm::class.java).createNewPeerDidService(
recipient.recall("routingDid")
)
recipient.attemptsTo(
Ensure.that(newPeerDid).isNotEqualTo(recipient.recall("peerDid"))
Ensure.that(communicationPeerDidService.did).isNotEqualTo(recipient.recall("peerDid"))
)
recipient.remember("newPeerDid", newPeerDid)
recipient.remember("communicationPeerDidService", communicationPeerDidService)
val messageKeylistUpdate = Message.builder(
id = idGeneratorDefault(),
body = mapOf(
"updates" to listOf(
mapOf(
"action" to TestConstants.MEDIATOR_COORDINATION_ACTION_ADD,
"recipient_did" to newPeerDid
"recipient_did" to communicationPeerDidService.did
)
)
),
Expand All @@ -81,7 +83,7 @@ class MediationCoordinationSteps {
Ensure.that(mediationKeylistUpdateResponse.updated.size).isEqualTo(1),
Ensure.that(mediationKeylistUpdateResponse.updated[0].result).isEqualTo(TestConstants.MEDIATOR_COORDINATION_ACTION_RESULT_SUCCESS),
Ensure.that(mediationKeylistUpdateResponse.updated[0].action).isEqualTo(TestConstants.MEDIATOR_COORDINATION_ACTION_ADD),
Ensure.that(mediationKeylistUpdateResponse.updated[0].recipient_did).isEqualTo(recipient.recall("newPeerDid"))
Ensure.that(mediationKeylistUpdateResponse.updated[0].recipient_did).isEqualTo(recipient.recall<PeerDID>("communicationPeerDidService").did)
)
}

Expand All @@ -92,7 +94,7 @@ class MediationCoordinationSteps {
body = mapOf(
"paginate" to
mapOf(
"limit" to 1,
"limit" to 2,
"offset" to 0
)
),
Expand All @@ -110,7 +112,7 @@ class MediationCoordinationSteps {
recipient.attemptsTo(
Ensure.that(didcommResponse.type).isEqualTo(DidcommMessageTypes.MEDIATE_KEYLIST),
Ensure.that(mediationKeylistResponse.keys.size).isGreaterThan(0),
Ensure.that(mediationKeylistResponse.keys.last().recipient_did).isEqualTo(recipient.recall("peerDid"))
Ensure.that(mediationKeylistResponse.keys).contains(MediationKeylistKey(recipient.recall<PeerDID>("communicationPeerDidService").did))
)
}

Expand Down Expand Up @@ -141,7 +143,7 @@ class MediationCoordinationSteps {
"updates" to listOf(
mapOf(
"action" to TestConstants.MEDIATOR_COORDINATION_ACTION_REMOVE,
"recipient_did" to recipient.recall("newPeerDid")
"recipient_did" to recipient.recall<PeerDID>("communicationPeerDidService").did
)
)
),
Expand Down
35 changes: 25 additions & 10 deletions src/test/kotlin/features/pickupmessage/PickupMessageSteps.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@ import io.cucumber.java.en.Given
import io.cucumber.java.en.Then
import io.cucumber.java.en.When
import io.ktor.http.*
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.MissingFieldException
import kotlinx.serialization.json.Json
import models.MessagePickupStatusBody
import models.PeerDID
import net.serenitybdd.screenplay.Actor
import org.didcommx.didcomm.message.Attachment
import org.didcommx.didcomm.message.Message
Expand All @@ -26,11 +29,11 @@ class PickupMessageSteps {
body = mapOf("basic" to "message"),
type = DidcommMessageTypes.BASIC_MESSAGE
).from(sender.recall("peerDid"))
.to(listOf(recipient.recall("peerDid"))).build()
.to(listOf(recipient.recall<PeerDID>("communicationPeerDidService").did)).build()

val wrapInForwardResult = sender.usingAbilityTo(CommunicateViaDidcomm::class.java).wrapInForward(
basicMessage,
recipient.recall("peerDid")
recipient.recall<PeerDID>("communicationPeerDidService").did
)
sender.attemptsTo(
SendEncryptedDidcommMessage(wrapInForwardResult.msgEncrypted.packedMessage)
Expand All @@ -43,7 +46,7 @@ class PickupMessageSteps {
fun recipientSendsAStatusRequestMessage(recipient: Actor) {
val statusRequestMessage = Message.builder(
id = idGeneratorDefault(),
body = mapOf("recipient_did" to recipient.recall("peerDid")),
body = mapOf("recipient_did" to recipient.recall<PeerDID>("communicationPeerDidService").did),
type = DidcommMessageTypes.PICKUP_STATUS_REQUEST
)

Expand All @@ -52,22 +55,31 @@ class PickupMessageSteps {
)
}

@OptIn(ExperimentalSerializationApi::class)
@Then("Mediator responds with a status message with {int} queued messages of {actor}")
fun mediatorRespondsWithAStatusMessageDetailingTheQueuedMessagesOfRecipient(numberOfMessages: Int, recipient: Actor) {
val didcommResponse = recipient.usingAbilityTo(CommunicateViaDidcomm::class.java).unpackLastDidcommMessage()
val pickupStatus = Json.decodeFromString<MessagePickupStatusBody>(didcommResponse.body.toJSONString())
recipient.attemptsTo(
Ensure.that(pickupStatus.recipient_did).isEqualTo(recipient.recall("peerDid")),
Ensure.that(pickupStatus.message_count).isEqualTo(numberOfMessages)
)
try {
val pickupStatus = Json.decodeFromString<MessagePickupStatusBody>(didcommResponse.body.toJSONString())
recipient.attemptsTo(
Ensure.that(didcommResponse.type).isEqualTo(DidcommMessageTypes.PICKUP_STATUS),
Ensure.that(pickupStatus.recipient_did).isEqualTo(recipient.recall<PeerDID>("communicationPeerDidService").did),
Ensure.that(pickupStatus.message_count).isEqualTo(numberOfMessages)
)
} catch (_: MissingFieldException) {
recipient.attemptsTo(
Ensure.that(didcommResponse.type).isEqualTo(DidcommMessageTypes.PICKUP_DELIVERY),
Ensure.that(didcommResponse.attachments!!.size).isEqualTo(0)
)
}
}

@When("{actor} sends a delivery-request message")
fun recipientSendsADeliveryRequestMessage(recipient: Actor) {
val deliveryRequestMessage = Message.builder(
id = idGeneratorDefault(),
body = mapOf(
"recipient_did" to recipient.recall("peerDid"),
"recipient_did" to recipient.recall<PeerDID>("communicationPeerDidService").did,
"limit" to 3
),
type = DidcommMessageTypes.PICKUP_DELIVERY_REQUEST
Expand All @@ -82,7 +94,10 @@ class PickupMessageSteps {
val didcommResponse = recipient.usingAbilityTo(CommunicateViaDidcomm::class.java).unpackLastDidcommMessage()
val encryptedMessage = didcommResponse.attachments!!.first().data as Attachment.Data.Base64
val decryptedMessage = Base64.getUrlDecoder().decode(encryptedMessage.base64).decodeToString()
val achievedMessage = recipient.usingAbilityTo(CommunicateViaDidcomm::class.java).unpackMessage(decryptedMessage)
val achievedMessage = recipient.usingAbilityTo(CommunicateViaDidcomm::class.java).unpackMessage(
decryptedMessage,
recipient.recall<PeerDID>("communicationPeerDidService").getSecretResolverInMemory()
)
val initialMessage = sender.recall<Message>("initialMessage")
recipient.attemptsTo(
Ensure.that(didcommResponse.type).isEqualTo(DidcommMessageTypes.PICKUP_DELIVERY),
Expand Down
19 changes: 17 additions & 2 deletions src/test/kotlin/features/ping/PingProtocolSteps.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ class PingProtocolSteps {
id = idGeneratorDefault(),
body = mapOf("response_requested" to true),
type = DidcommMessageTypes.PING_REQUEST
).customHeader("return_route", returnRoute)
)

recipient.attemptsTo(
SendDidcommMessage(messageTrustPing)
SendDidcommMessage(messageTrustPing, returnRoute = returnRoute)
)
}

Expand All @@ -48,4 +48,19 @@ class PingProtocolSteps {
Ensure.that(didCommResponseMessage.to!!.first()).isEqualTo(recipient.recall("peerDid"))
)
}

@Then("{actor} receives no async message back")
fun recipientReceivesNoAsyncMessageBack(recipient: Actor) {
val didCommResponse: String? = recipient.usingAbilityTo(ListenToHttpMessages::class.java).receivedResponse()
recipient.attemptsTo(
Ensure.that(didCommResponse).isNull()
)
}

@Then("{actor} receives no sync message back")
fun recipientReceivesNoSyncMessageBack(recipient: Actor) {
recipient.attemptsTo(
Ensure.that(SerenityRest.lastResponse().body.print()).isEmpty()
)
}
}
4 changes: 3 additions & 1 deletion src/test/kotlin/interactions/SendDidcommMessage.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,14 @@ import org.didcommx.didcomm.message.MessageBuilder

open class SendDidcommMessage(
private val messageBuilder: MessageBuilder,
private val contentType: String = TestConstants.DIDCOMM_V2_CONTENT_TYPE_ENCRYPTED
private val contentType: String = TestConstants.DIDCOMM_V2_CONTENT_TYPE_ENCRYPTED,
private val returnRoute: String = "all"
) : Interaction {
override fun <T : Actor> performAs(actor: T) {
val message = messageBuilder
.from(actor.recall("peerDid"))
.to(listOf(actor.usingAbilityTo(CommunicateViaDidcomm::class.java).mediatorPeerDid))
.customHeader("return_route", returnRoute)
.build()
Serenity.recordReportData().withTitle("DIDComm Message").andContents(message.toString())
// We have to rewrite spec to remove all unnecessary hardcoded headers
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,17 @@ Feature: Mediator Coordination protocol
Then Mediator responds to Recipient with a correct keylist update add message

Scenario: Recipient removes alias from keylist
When Recipient sends a keylist update message to the mediator with a new peer did
And Recipient sends a keylist update message to the mediator to remove added alias
Given Recipient sends a keylist update message to the mediator with a new peer did
And Mediator responds to Recipient with a correct keylist update add message
When Recipient sends a keylist update message to the mediator to remove added alias
Then Mediator responds to Recipient with a correct keylist update remove message

Scenario: Recipient removes not existing alias
When Recipient sends a keylist update message to the mediator to remove not existing alias
Then Mediator responds to Recipient with a message with no_change status

Scenario: Recipient removes the last alias from keylist
When Recipient sends a keylist update message to the mediator to remove the last alias
Then Mediator responds to Recipient with a correct keylist update remove message

Scenario: Recipient query keylist
Given Recipient sends a keylist update message to the mediator with a new peer did
And Mediator responds to Recipient with a correct keylist update add message
When Recipient sends a keylist query message to the mediator
Then Mediator responds to Recipient with keylist message containing the current list of keys
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Feature: Pickup message protocol
Background: Recipient and Mediator successfully set up mediation
Given Recipient sends a mediate request message to the mediator
And Mediator responds to Recipient with mediate grant message
And Recipient sends a keylist update message to the mediator with a new peer did

Scenario: Recipient sends a status-request message with one forward message available

Expand Down
2 changes: 2 additions & 0 deletions src/test/resources/features/ping/ping.feature
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ Feature: Trust Ping Protocol
Scenario: Recipient sends and receives trusted ping message with return_route "all"
When Recipient sends trusted ping message to mediator with return_route "all"
Then Recipient receives trusted ping message back synchronously
And Recipient receives no async message back

Scenario: Recipient sends and receives trusted ping message with return_route "none"
When Recipient sends trusted ping message to mediator with return_route "none"
Then Recipient receives trusted ping message back asynchronously
And Recipient receives no sync message back

0 comments on commit 150306c

Please sign in to comment.