diff --git a/.editorconfig b/.editorconfig index 90ef09fdf..d9fa9912c 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,6 +1,9 @@ root = true [*.{kt,kts}] +ij_kotlin_packages_to_use_import_on_demand = unset +ij_kotlin_name_count_to_use_star_import_for_members = 99 +ij_kotlin_name_count_to_use_star_import = 99 ktlint_experimental = disabled ktlint_code_style = intellij_idea ktlint_standard_no_semi = disabled diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index bed0bb858..6b96d4eb8 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,4 +1,4 @@ -@goncalo-frade-iohk @yshyn-iohk @elribonazo @cristianIOHK +@elribonazo @cristianIOHK # Test related: /tests/ @amagyar-iohk diff --git a/edge-agent-sdk/build.gradle.kts b/edge-agent-sdk/build.gradle.kts index 291b36ff3..ba2cfcb5d 100644 --- a/edge-agent-sdk/build.gradle.kts +++ b/edge-agent-sdk/build.gradle.kts @@ -80,9 +80,6 @@ kotlin { jvmTarget = "17" } } - testRuns["test"].executionTask.configure { - useJUnitPlatform() - } publishing { publications { withType { @@ -145,10 +142,9 @@ kotlin { } val commonTest by getting { dependencies { - implementation(kotlin("test")) + implementation(kotlin("test-junit")) implementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.8.1") implementation("io.ktor:ktor-client-mock:2.3.11") - implementation("junit:junit:4.13.2") implementation("org.mockito:mockito-core:4.4.0") implementation("org.mockito.kotlin:mockito-kotlin:4.0.0") } @@ -172,10 +168,8 @@ kotlin { val androidInstrumentedTest by getting { dependencies { dependsOn(commonTest) - implementation(kotlin("test")) implementation("androidx.test.espresso:espresso-core:3.5.1") implementation("androidx.test.ext:junit:1.1.5") - implementation("junit:junit:4.13.2") } } /* diff --git a/edge-agent-sdk/src/androidMain/kotlin/org/hyperledger/identus/walletsdk/pluto/data/DbConnectionImpl.kt b/edge-agent-sdk/src/androidMain/kotlin/org/hyperledger/identus/walletsdk/pluto/data/DbConnectionImpl.kt index 01fab6a2a..8b72c4a9d 100644 --- a/edge-agent-sdk/src/androidMain/kotlin/org/hyperledger/identus/walletsdk/pluto/data/DbConnectionImpl.kt +++ b/edge-agent-sdk/src/androidMain/kotlin/org/hyperledger/identus/walletsdk/pluto/data/DbConnectionImpl.kt @@ -24,10 +24,10 @@ actual class DbConnectionImpl actual constructor() : DbConnection { */ actual val SqlDriver.isConnected: Boolean get() { - try { - return this.execute(null, "SELECT 1", 0).value == 1L + return try { + this.execute(null, "SELECT 1", 0).value == 0L // return this.executeQuery(null, "SELECT 1", 0).next() } catch (ex: Exception) { - return false + false } } diff --git a/edge-agent-sdk/src/commonMain/kotlin/org/hyperledger/identus/walletsdk/edgeagent/ConnectionManager.kt b/edge-agent-sdk/src/commonMain/kotlin/org/hyperledger/identus/walletsdk/edgeagent/ConnectionManager.kt index 00c53908e..e7f38fbcf 100644 --- a/edge-agent-sdk/src/commonMain/kotlin/org/hyperledger/identus/walletsdk/edgeagent/ConnectionManager.kt +++ b/edge-agent-sdk/src/commonMain/kotlin/org/hyperledger/identus/walletsdk/edgeagent/ConnectionManager.kt @@ -7,6 +7,7 @@ import kotlinx.coroutines.delay import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.firstOrNull +import kotlinx.coroutines.isActive import kotlinx.coroutines.launch import org.hyperledger.identus.apollo.base64.base64UrlDecoded import org.hyperledger.identus.walletsdk.domain.buildingblocks.Castor @@ -25,7 +26,6 @@ import org.hyperledger.identus.walletsdk.edgeagent.protocols.ProtocolType import org.hyperledger.identus.walletsdk.edgeagent.protocols.issueCredential.IssueCredential import org.hyperledger.identus.walletsdk.edgeagent.protocols.revocation.RevocationNotification import java.time.Duration -import kotlin.jvm.Throws interface ConnectionManager : ConnectionsManager, DIDCommConnection { @@ -106,10 +106,9 @@ class ConnectionManagerImpl( } } } - // Fallback mechanism if no WebSocket service endpoint is available if (serviceEndpoint == null) { - while (true) { + while (this.isActive) { // Continuously await and process new messages awaitMessages().collect { array -> processMessages(array) diff --git a/edge-agent-sdk/src/commonTest/kotlin/org/hyperledger/identus/walletsdk/edgeagent/ConnectionManagerTest.kt b/edge-agent-sdk/src/commonTest/kotlin/org/hyperledger/identus/walletsdk/edgeagent/ConnectionManagerTest.kt index 73abb9252..be7f4be1c 100644 --- a/edge-agent-sdk/src/commonTest/kotlin/org/hyperledger/identus/walletsdk/edgeagent/ConnectionManagerTest.kt +++ b/edge-agent-sdk/src/commonTest/kotlin/org/hyperledger/identus/walletsdk/edgeagent/ConnectionManagerTest.kt @@ -1,10 +1,10 @@ package org.hyperledger.identus.walletsdk.edgeagent import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flow -import kotlinx.coroutines.test.TestCoroutineDispatcher -import kotlinx.coroutines.test.runBlockingTest +import kotlinx.coroutines.test.UnconfinedTestDispatcher import kotlinx.coroutines.test.runTest import org.hyperledger.identus.apollo.base64.base64UrlEncoded import org.hyperledger.identus.walletsdk.domain.buildingblocks.Castor @@ -54,7 +54,8 @@ class ConnectionManagerTest { lateinit var connectionManager: ConnectionManagerImpl - val testDispatcher = TestCoroutineDispatcher() + @OptIn(ExperimentalCoroutinesApi::class) + val testDispatcher = UnconfinedTestDispatcher() @BeforeTest fun setup() { @@ -118,7 +119,7 @@ class ConnectionManagerTest { `when`(castorMock.resolveDID(any())).thenReturn(didDoc) connectionManager.startFetchingMessages() - assertNotNull((connectionManager as ConnectionManagerImpl).fetchingMessagesJob) + assertNotNull(connectionManager.fetchingMessagesJob) verify(basicMediatorHandlerMock).listenUnreadMessages(any(), any()) } @@ -220,91 +221,91 @@ class ConnectionManagerTest { } @Test - fun testStartFetchingMessages_whenServiceEndpointNotContainsWSS_thenUseAPIRequest() = - runBlockingTest { - `when`(basicMediatorHandlerMock.mediatorDID) - .thenReturn(DID("did:prism:b6c0c33d701ac1b9a262a14454d1bbde3d127d697a76950963c5fd930605:Cj8KPRI7CgdtYXN0ZXIwEAFKLgoJc2VmsxEiECSTjyV7sUfCr_ArpN9rvCwR9fRMAhcsr_S7ZRiJk4p5k")) - - val vmAuthentication = DIDDocument.VerificationMethod( - id = DIDUrl(DID("2", "1", "0")), - controller = DID("2", "2", "0"), - type = Curve.ED25519.value, - publicKeyJwk = mapOf("crv" to Curve.ED25519.value, "x" to "") - ) + fun testStartFetchingMessages_whenServiceEndpointNotContainsWSS_thenUseAPIRequest() = runTest { + `when`(basicMediatorHandlerMock.mediatorDID) + .thenReturn(DID("did:prism:b6c0c33d701ac1b9a262a14454d1bbde3d127d697a76950963c5fd930605:Cj8KPRI7CgdtYXN0ZXIwEAFKLgoJc2VmsxEiECSTjyV7sUfCr_ArpN9rvCwR9fRMAhcsr_S7ZRiJk4p5k")) - val vmKeyAgreement = DIDDocument.VerificationMethod( - id = DIDUrl(DID("3", "1", "0")), - controller = DID("3", "2", "0"), - type = Curve.X25519.value, - publicKeyJwk = mapOf("crv" to Curve.X25519.value, "x" to "") - ) + val vmAuthentication = DIDDocument.VerificationMethod( + id = DIDUrl(DID("2", "1", "0")), + controller = DID("2", "2", "0"), + type = Curve.ED25519.value, + publicKeyJwk = mapOf("crv" to Curve.ED25519.value, "x" to "") + ) - val vmService = DIDDocument.Service( - id = UUID.randomUUID().toString(), - type = emptyArray(), - serviceEndpoint = DIDDocument.ServiceEndpoint( - uri = "https://serviceEndpoint" - ) + val vmKeyAgreement = DIDDocument.VerificationMethod( + id = DIDUrl(DID("3", "1", "0")), + controller = DID("3", "2", "0"), + type = Curve.X25519.value, + publicKeyJwk = mapOf("crv" to Curve.X25519.value, "x" to "") + ) + + val vmService = DIDDocument.Service( + id = UUID.randomUUID().toString(), + type = emptyArray(), + serviceEndpoint = DIDDocument.ServiceEndpoint( + uri = "https://serviceEndpoint" ) + ) - val didDoc = DIDDocument( - id = DID("did:prism:asdfasdf"), - coreProperties = arrayOf( - DIDDocument.Authentication( - urls = emptyArray(), - verificationMethods = arrayOf(vmAuthentication) - ), - DIDDocument.KeyAgreement( - urls = emptyArray(), - verificationMethods = arrayOf(vmKeyAgreement) - ), - DIDDocument.Services( - values = arrayOf(vmService) - ) + val didDoc = DIDDocument( + id = DID("did:prism:asdfasdf"), + coreProperties = arrayOf( + DIDDocument.Authentication( + urls = emptyArray(), + verificationMethods = arrayOf(vmAuthentication) + ), + DIDDocument.KeyAgreement( + urls = emptyArray(), + verificationMethods = arrayOf(vmKeyAgreement) + ), + DIDDocument.Services( + values = arrayOf(vmService) ) ) + ) - `when`(castorMock.resolveDID(any())).thenReturn(didDoc) - val messages = arrayOf(Pair("1234", Message(piuri = "", body = ""))) - `when`(basicMediatorHandlerMock.pickupUnreadMessages(any())).thenReturn( - flow { - emit( - messages - ) - } - ) - val attachments: Array = - arrayOf( - AttachmentDescriptor( - mediaType = "application/json", - format = CredentialType.JWT.type, - data = AttachmentBase64(base64 = "asdfasdfasdfasdfasdfasdfasdfasdfasdf".base64UrlEncoded) - ) + `when`(castorMock.resolveDID(any())).thenReturn(didDoc) + val messages = arrayOf(Pair("1234", Message(piuri = "", body = ""))) + `when`(basicMediatorHandlerMock.pickupUnreadMessages(any())).thenReturn( + flow { + emit( + messages ) - val listMessages = listOf( - Message( - piuri = ProtocolType.DidcommconnectionRequest.value, - body = "" - ), - Message( - piuri = ProtocolType.DidcommIssueCredential.value, - thid = UUID.randomUUID().toString(), - from = DID("did:peer:asdf897a6sdf"), - to = DID("did:peer:f706sg678ha"), - attachments = attachments, - body = """{}""" + } + ) + val attachments: Array = + arrayOf( + AttachmentDescriptor( + mediaType = "application/json", + format = CredentialType.JWT.type, + data = AttachmentBase64(base64 = "asdfasdfasdfasdfasdfasdfasdfasdfasdf".base64UrlEncoded) ) ) - val messageList: Flow> = flow { - emit(listMessages) - } - `when`(plutoMock.getAllMessages()).thenReturn(messageList) - - connectionManager.startFetchingMessages() - assertNotNull((connectionManager as ConnectionManagerImpl).fetchingMessagesJob) - verify(basicMediatorHandlerMock).pickupUnreadMessages(10) - verify(basicMediatorHandlerMock).registerMessagesAsRead(arrayOf("1234")) + val listMessages = listOf( + Message( + piuri = ProtocolType.DidcommconnectionRequest.value, + body = "" + ), + Message( + piuri = ProtocolType.DidcommIssueCredential.value, + thid = UUID.randomUUID().toString(), + from = DID("did:peer:asdf897a6sdf"), + to = DID("did:peer:f706sg678ha"), + attachments = attachments, + body = """{}""" + ) + ) + val messageList: Flow> = flow { + emit(listMessages) } + `when`(plutoMock.getAllMessages()).thenReturn(messageList) + + connectionManager.startFetchingMessages() + assertNotNull(connectionManager.fetchingMessagesJob) + assert(connectionManager.fetchingMessagesJob?.isActive == true) + verify(basicMediatorHandlerMock).pickupUnreadMessages(10) + verify(basicMediatorHandlerMock).registerMessagesAsRead(arrayOf("1234")) + } @Test fun testConnectionManager_whenProcessMessageRevoke_thenAllCorrect() = runTest { diff --git a/edge-agent-sdk/src/commonTest/kotlin/org/hyperledger/identus/walletsdk/pluto/PlutoImplTest.kt b/edge-agent-sdk/src/commonTest/kotlin/org/hyperledger/identus/walletsdk/pluto/PlutoImplTest.kt index db5c59fb3..29b8b5894 100644 --- a/edge-agent-sdk/src/commonTest/kotlin/org/hyperledger/identus/walletsdk/pluto/PlutoImplTest.kt +++ b/edge-agent-sdk/src/commonTest/kotlin/org/hyperledger/identus/walletsdk/pluto/PlutoImplTest.kt @@ -3,7 +3,6 @@ package org.hyperledger.identus.walletsdk.pluto import junit.framework.TestCase.assertNotNull import junit.framework.TestCase.assertNull import junit.framework.TestCase.assertTrue -import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.first import kotlinx.coroutines.test.runTest import org.hyperledger.identus.apollo.base64.base64UrlEncoded @@ -19,83 +18,85 @@ import org.junit.After import org.junit.Before import org.junit.Test import org.mockito.MockitoAnnotations -import java.util.* +import java.util.UUID import kotlin.test.assertContentEquals import kotlin.test.assertEquals import kotlin.test.assertFailsWith class PlutoImplTest { - private var pluto: PlutoImpl? = null + private lateinit var pluto: PlutoImpl + private lateinit var dbConnection: DbConnectionInMemory @Before fun setUp() { MockitoAnnotations.openMocks(this) - pluto = PlutoImpl(DbConnectionInMemory()) + dbConnection = DbConnectionInMemory() + pluto = PlutoImpl(dbConnection) } @After fun destroy() { - pluto = null + if (pluto.isConnected) { + pluto.stop() + } } @Test fun `verify Pluto is connected after start`() = runTest { - pluto?.start() - assertEquals(false, pluto?.isConnected) + pluto.start() + assertEquals(true, pluto.isConnected) } @Test fun `verify Pluto is not connected if not started`() = runTest { - assertEquals(false, pluto?.isConnected) + assertEquals(false, pluto.isConnected) } - @OptIn(ExperimentalCoroutinesApi::class) @Test fun `test Pluto throws an expection if started more than once`() = runTest { val context = Any() - pluto?.start(context) + pluto.start(context) assertFailsWith { - pluto?.start(context) + pluto.start(context) } } - @OptIn(ExperimentalCoroutinesApi::class) @Test fun `test storePrismDIDAndPrivateKeys stores DID and private keys`() = runTest { val did = DID("did:prism:example") val secp256PrivateKey = Secp256k1KeyPair.generateKeyPair() val alias = "alias" - pluto?.start() - pluto?.storePrismDIDAndPrivateKeys(did, 1, alias, listOf(secp256PrivateKey.privateKey as StorableKey)) + pluto.start() + pluto.storePrismDIDAndPrivateKeys(did, 1, alias, listOf(secp256PrivateKey.privateKey as StorableKey)) - val dids = pluto?.getAllDIDs()?.first() + val dids = pluto.getAllDIDs().first() assertNotNull(dids) - assertTrue(dids!!.isNotEmpty()) + assertTrue(dids.isNotEmpty()) assertEquals(1, dids.size) assertEquals(did.toString(), dids.first().toString()) - val privateKeys = pluto?.getAllPrivateKeys()?.first() + val privateKeys = pluto.getAllPrivateKeys().first() assertNotNull(privateKeys) - assertTrue(privateKeys!!.isNotEmpty()) + assertTrue(privateKeys.isNotEmpty()) assertEquals(1, privateKeys.size) - val didKeyLinks = pluto?.getAllDIDKeyLinkData()?.first() + val didKeyLinks = pluto.getAllDIDKeyLinkData().first() assertNotNull(didKeyLinks) - assertTrue(didKeyLinks!!.isNotEmpty()) + assertTrue(didKeyLinks.isNotEmpty()) assertEquals(1, didKeyLinks.size) } @Test fun `test storePeerDID stores DID`() = runTest { val peerDID = DID("did:peer:test") - pluto?.start() - pluto?.storePeerDID(peerDID) + pluto.start() + pluto.storePeerDID(peerDID) - val dids = pluto?.getAllDIDs()?.first() + val dids = pluto.getAllDIDs().first() assertNotNull(dids) - assertTrue(dids!!.isNotEmpty()) + assertTrue(dids.isNotEmpty()) assertEquals(1, dids.size) assertEquals(peerDID.toString(), dids.first().toString()) } @@ -105,12 +106,12 @@ class PlutoImplTest { val host = DID("did:peer:host") val receiver = DID("did:peer:receiver") val alias = "alias" - pluto?.start() - pluto?.storeDIDPair(host, receiver, alias) + pluto.start() + pluto.storeDIDPair(host, receiver, alias) - val didPairs = pluto?.getAllDidPairs()?.first() + val didPairs = pluto.getAllDidPairs().first() assertNotNull(didPairs) - assertTrue(didPairs!!.isNotEmpty()) + assertTrue(didPairs.isNotEmpty()) assertEquals(1, didPairs.size) val didPair = didPairs.first() assertEquals(host.toString(), didPair.holder.toString()) @@ -127,12 +128,12 @@ class PlutoImplTest { body = "{}" ) - pluto?.start() - pluto?.storeMessage(message) + pluto.start() + pluto.storeMessage(message) - val messages = pluto?.getAllMessages()?.first() + val messages = pluto.getAllMessages().first() assertNotNull(messages) - assertTrue(messages!!.isNotEmpty()) + assertTrue(messages.isNotEmpty()) assertEquals(1, messages.size) val msg = messages.first() assertEquals(message, msg) @@ -143,22 +144,22 @@ class PlutoImplTest { val secp256PrivateKey = Secp256k1KeyPair.generateKeyPair().privateKey val did = DID("did:peer:example") - pluto?.start() - pluto?.storePrivateKeys( + pluto.start() + pluto.storePrivateKeys( storableKey = secp256PrivateKey as StorableKey, did = did, keyPathIndex = 0, metaId = "" ) - val privateKeys = pluto?.getAllPrivateKeys()?.first() + val privateKeys = pluto.getAllPrivateKeys().first() assertNotNull(privateKeys) - assertTrue(privateKeys!!.isNotEmpty()) + assertTrue(privateKeys.isNotEmpty()) assertEquals(1, privateKeys.size) - val didKeyLinks = pluto?.getAllDIDKeyLinkData()?.first() + val didKeyLinks = pluto.getAllDIDKeyLinkData().first() assertNotNull(didKeyLinks) - assertTrue(didKeyLinks!!.isNotEmpty()) + assertTrue(didKeyLinks.isNotEmpty()) assertEquals(1, didKeyLinks.size) } @@ -166,12 +167,12 @@ class PlutoImplTest { fun `test storePrivate`() = runTest { val privateKey = Secp256k1KeyPair.generateKeyPair().privateKey - pluto?.start() - pluto?.storePrivate(privateKey as StorableKey, recoveryId = "recoveryId") + pluto.start() + pluto.storePrivate(privateKey as StorableKey, recoveryId = "recoveryId") - val privateKeys = pluto?.getAllPrivateKeys()?.first() + val privateKeys = pluto.getAllPrivateKeys().first() assertNotNull(privateKeys) - assertTrue(privateKeys!!.isNotEmpty()) + assertTrue(privateKeys.isNotEmpty()) assertEquals(1, privateKeys.size) assertEquals("recoveryId", privateKeys.first().restorationIdentifier) } @@ -192,12 +193,12 @@ class PlutoImplTest { body = "{}" ) - pluto?.start() - pluto?.storeMessages(listOf(message, message1)) + pluto.start() + pluto.storeMessages(listOf(message, message1)) - val messages = pluto?.getAllMessages()?.first() + val messages = pluto.getAllMessages().first() assertNotNull(messages) - assertTrue(messages!!.isNotEmpty()) + assertTrue(messages.isNotEmpty()) assertEquals(2, messages.size) val msg = messages.first() assertEquals(message, msg) @@ -211,22 +212,22 @@ class PlutoImplTest { val hostDID = DID("did:peer:host") val routingDID = DID("did:peer:routing") - pluto?.start() - pluto?.storePeerDID(hostDID) - pluto?.storeMediator(mediatorDID, hostDID, routingDID) + pluto.start() + pluto.storePeerDID(hostDID) + pluto.storeMediator(mediatorDID, hostDID, routingDID) - val dids = pluto?.getAllDIDs()?.first() + val dids = pluto.getAllDIDs().first() assertNotNull(dids) - assertTrue(dids!!.isNotEmpty()) + assertTrue(dids.isNotEmpty()) assertEquals(3, dids.size) val didsString = dids.map { it.toString() } assertTrue(didsString.contains(mediatorDID.toString())) assertTrue(didsString.contains(hostDID.toString())) assertTrue(didsString.contains(routingDID.toString())) - val mediators = pluto?.getAllMediators()?.first() + val mediators = pluto.getAllMediators().first() assertNotNull(mediators) - assertTrue(mediators!!.isNotEmpty()) + assertTrue(mediators.isNotEmpty()) assertEquals(1, mediators.size) val mediator = mediators.first() assertEquals(mediatorDID.toString(), mediator.mediatorDID.toString()) @@ -240,12 +241,12 @@ class PlutoImplTest { "eyJhbGciOiJFUzI1NksifQ.eyJpc3MiOiJkaWQ6cHJpc206MjU3MTlhOTZiMTUxMjA3MTY5ODFhODQzMGFkMGNiOTY4ZGQ1MzQwNzM1OTNjOGNkM2YxZDI3YTY4MDRlYzUwZTpDcG9DQ3BjQ0Vsb0tCV3RsZVMweEVBSkNUd29KYzJWamNESTFObXN4RWlBRW9TQ241dHlEYTZZNnItSW1TcXBKOFkxbWo3SkMzX29VekUwTnl5RWlDQm9nc2dOYWVSZGNDUkdQbGU4MlZ2OXRKZk53bDZyZzZWY2hSM09xaGlWYlRhOFNXd29HWVhWMGFDMHhFQVJDVHdvSmMyVmpjREkxTm1zeEVpRE1rQmQ2RnRpb0prM1hPRnUtX2N5NVhtUi00dFVRMk5MR2lXOGFJU29ta1JvZzZTZGU5UHduRzBRMFNCVG1GU1REYlNLQnZJVjZDVExYcmpJSnR0ZUdJbUFTWEFvSGJXRnpkR1Z5TUJBQlFrOEtDWE5sWTNBeU5UWnJNUklnTzcxMG10MVdfaXhEeVFNM3hJczdUcGpMQ05PRFF4Z1ZoeDVzaGZLTlgxb2FJSFdQcnc3SVVLbGZpYlF0eDZKazRUU2pnY1dOT2ZjT3RVOUQ5UHVaN1Q5dCIsInN1YiI6ImRpZDpwcmlzbTpiZWVhNTIzNGFmNDY4MDQ3MTRkOGVhOGVjNzdiNjZjYzdmM2U4MTVjNjhhYmI0NzVmMjU0Y2Y5YzMwNjI2NzYzOkNzY0JDc1FCRW1RS0QyRjFkR2hsYm5ScFkyRjBhVzl1TUJBRVFrOEtDWE5sWTNBeU5UWnJNUklnZVNnLTJPTzFKZG5welVPQml0eklpY1hkZnplQWNUZldBTi1ZQ2V1Q2J5SWFJSlE0R1RJMzB0YVZpd2NoVDNlMG5MWEJTNDNCNGo5amxzbEtvMlpsZFh6akVsd0tCMjFoYzNSbGNqQVFBVUpQQ2dselpXTndNalUyYXpFU0lIa29QdGpqdFNYWjZjMURnWXJjeUluRjNYODNnSEUzMWdEZm1BbnJnbThpR2lDVU9Ca3lOOUxXbFlzSElVOTN0Snkxd1V1TndlSV9ZNWJKU3FObVpYVjg0dyIsIm5iZiI6MTY4NTYzMTk5NSwiZXhwIjoxNjg1NjM1NTk1LCJ2YyI6eyJjcmVkZW50aWFsU3ViamVjdCI6eyJhZGRpdGlvbmFsUHJvcDIiOiJUZXN0MyIsImlkIjoiZGlkOnByaXNtOmJlZWE1MjM0YWY0NjgwNDcxNGQ4ZWE4ZWM3N2I2NmNjN2YzZTgxNWM2OGFiYjQ3NWYyNTRjZjljMzA2MjY3NjM6Q3NjQkNzUUJFbVFLRDJGMWRHaGxiblJwWTJGMGFXOXVNQkFFUWs4S0NYTmxZM0F5TlRack1SSWdlU2ctMk9PMUpkbnB6VU9CaXR6SWljWGRmemVBY1RmV0FOLVlDZXVDYnlJYUlKUTRHVEkzMHRhVml3Y2hUM2UwbkxYQlM0M0I0ajlqbHNsS28yWmxkWHpqRWx3S0IyMWhjM1JsY2pBUUFVSlBDZ2x6WldOd01qVTJhekVTSUhrb1B0amp0U1haNmMxRGdZcmN5SW5GM1g4M2dIRTMxZ0RmbUFucmdtOGlHaUNVT0JreU45TFdsWXNISVU5M3RKeTF3VXVOd2VJX1k1YkpTcU5tWlhWODR3In0sInR5cGUiOlsiVmVyaWZpYWJsZUNyZWRlbnRpYWwiXSwiQGNvbnRleHQiOlsiaHR0cHM6XC9cL3d3dy53My5vcmdcLzIwMThcL2NyZWRlbnRpYWxzXC92MSJdfX0.x0SF17Y0VCDmt7HceOdTxfHlofsZmY18Rn6VQb0-r-k_Bm3hTi1-k2vkdjB25hdxyTCvxam-AkAP-Ag3Ahn5Ng" ) - pluto?.start() - pluto?.storeCredential(credential.toStorableCredential()) + pluto.start() + pluto.storeCredential(credential.toStorableCredential()) - val credentials = pluto?.getAllCredentials()?.first() + val credentials = pluto.getAllCredentials().first() assertNotNull(credentials) - assertTrue(credentials!!.isNotEmpty()) + assertTrue(credentials.isNotEmpty()) assertEquals(1, credentials.size) assertEquals("jwt+credential", credentials.first().restorationId) } @@ -253,10 +254,10 @@ class PlutoImplTest { @Test fun `test storeLinkSecret`() = runTest { val linkSecret = "linkSecret" - pluto?.start() - pluto?.storeLinkSecret(linkSecret) + pluto.start() + pluto.storeLinkSecret(linkSecret) - val linkSecretString = pluto?.getLinkSecret()?.first() + val linkSecretString = pluto.getLinkSecret().first() assertEquals(linkSecret, linkSecretString) } @@ -266,25 +267,25 @@ class PlutoImplTest { val linkSecretName = "linkSecretName" val json = "{}" - pluto?.start() - pluto?.storeCredentialMetadata(name, linkSecretName, json) + pluto.start() + pluto.storeCredentialMetadata(name, linkSecretName, json) - val credentialMetadata = pluto?.getCredentialMetadata(linkSecretName)?.first() + val credentialMetadata = pluto.getCredentialMetadata(linkSecretName).first() assertNotNull(credentialMetadata) - assertEquals(linkSecretName, credentialMetadata!!.linkSecretName) - assertEquals(json, credentialMetadata.json) + assertEquals(linkSecretName, credentialMetadata?.linkSecretName) + assertEquals(json, credentialMetadata?.json) } @Test fun `test getAllPrismDIDs`() = runTest { val prismDID = DID("did:prism:test") val privateKey = Secp256k1KeyPair.generateKeyPair().privateKey as StorableKey - pluto?.start() - pluto?.storePrismDIDAndPrivateKeys(prismDID, null, null, listOf(privateKey)) + pluto.start() + pluto.storePrismDIDAndPrivateKeys(prismDID, null, null, listOf(privateKey)) - val allPrismDids = pluto?.getAllPrismDIDs()?.first() + val allPrismDids = pluto.getAllPrismDIDs().first() assertNotNull(allPrismDids) - assertEquals(1, allPrismDids!!.size) + assertEquals(1, allPrismDids.size) val prismDidInfo = allPrismDids.first() assertEquals(prismDID.toString(), prismDidInfo.did.toString()) assertNull(prismDidInfo.keyPathIndex) @@ -295,24 +296,24 @@ class PlutoImplTest { fun `test getDIDInfoByDID`() = runTest { val prismDID = DID("did:prism:test") val privateKey = Secp256k1KeyPair.generateKeyPair().privateKey as StorableKey - pluto?.start() - pluto?.storePrismDIDAndPrivateKeys(prismDID, null, null, listOf(privateKey)) + pluto.start() + pluto.storePrismDIDAndPrivateKeys(prismDID, null, null, listOf(privateKey)) - val prismDidInfo = pluto?.getDIDInfoByDID(prismDID)?.first() + val prismDidInfo = pluto.getDIDInfoByDID(prismDID).first() assertNotNull(prismDidInfo) - assertEquals(prismDID.toString(), prismDidInfo!!.did.toString()) + assertEquals(prismDID.toString(), prismDidInfo?.did.toString()) } @Test fun `test getDIDInfoByAlias`() = runTest { val prismDID = DID("did:prism:test") val privateKey = Secp256k1KeyPair.generateKeyPair().privateKey as StorableKey - pluto?.start() - pluto?.storePrismDIDAndPrivateKeys(prismDID, null, "alias", listOf(privateKey)) + pluto.start() + pluto.storePrismDIDAndPrivateKeys(prismDID, null, "alias", listOf(privateKey)) - val prismDidInfo = pluto?.getDIDInfoByAlias("alias")?.first() + val prismDidInfo = pluto.getDIDInfoByAlias("alias").first() assertNotNull(prismDidInfo) - assertEquals(1, prismDidInfo!!.size) + assertEquals(1, prismDidInfo.size) assertEquals(prismDID.toString(), prismDidInfo.first().did.toString()) } @@ -320,12 +321,12 @@ class PlutoImplTest { fun `test getDIDPrivateKeysByDID`() = runTest { val prismDID = DID("did:prism:test") val privateKey = Secp256k1KeyPair.generateKeyPair().privateKey as StorableKey - pluto?.start() - pluto?.storePrismDIDAndPrivateKeys(prismDID, null, "alias", listOf(privateKey)) + pluto.start() + pluto.storePrismDIDAndPrivateKeys(prismDID, null, "alias", listOf(privateKey)) - val storablePrivateKey = pluto?.getDIDPrivateKeysByDID(prismDID)?.first() + val storablePrivateKey = pluto.getDIDPrivateKeysByDID(prismDID).first() assertNotNull(storablePrivateKey) - assertEquals(1, storablePrivateKey!!.size) + assertEquals(1, storablePrivateKey.size) val storableKey = storablePrivateKey.first() assertEquals("secp256k1+priv", storableKey.restorationIdentifier) assertEquals(privateKey.storableData.base64UrlEncoded, storableKey.data) @@ -335,23 +336,23 @@ class PlutoImplTest { fun `test getDIDPrivateKeyByID`() = runTest { val prismDID = DID("did:prism:test") val privateKey = Secp256k1KeyPair.generateKeyPair().privateKey as StorableKey - pluto?.start() - pluto?.storePrismDIDAndPrivateKeys(prismDID, null, "alias", listOf(privateKey)) + pluto.start() + pluto.storePrismDIDAndPrivateKeys(prismDID, null, "alias", listOf(privateKey)) - val storablePrivateKey = pluto?.getDIDPrivateKeyByID(prismDID.toString())?.first() + val storablePrivateKey = pluto.getDIDPrivateKeyByID(prismDID.toString()).first() assertNotNull(storablePrivateKey) - assertEquals("secp256k1+priv", storablePrivateKey!!.restorationIdentifier) - assertEquals(privateKey.storableData.base64UrlEncoded, storablePrivateKey.data) + assertEquals("secp256k1+priv", storablePrivateKey?.restorationIdentifier) + assertEquals(privateKey.storableData.base64UrlEncoded, storablePrivateKey?.data) } @Test fun `test getPrismDIDKeyPathIndex`() = runTest { val prismDID = DID("did:prism:test") val privateKey = Secp256k1KeyPair.generateKeyPair().privateKey as StorableKey - pluto?.start() - pluto?.storePrismDIDAndPrivateKeys(prismDID, 99, "alias", listOf(privateKey)) + pluto.start() + pluto.storePrismDIDAndPrivateKeys(prismDID, 99, "alias", listOf(privateKey)) - val keyPathIndex = pluto?.getPrismDIDKeyPathIndex(prismDID)?.first() + val keyPathIndex = pluto.getPrismDIDKeyPathIndex(prismDID).first() assertNotNull(keyPathIndex) assertEquals(99, keyPathIndex) } @@ -360,11 +361,11 @@ class PlutoImplTest { fun `test getPrismLastKeyPathIndex`() = runTest { val prismDID = DID("did:prism:test") val privateKey = Secp256k1KeyPair.generateKeyPair().privateKey as StorableKey - pluto?.start() - pluto?.storePrismDIDAndPrivateKeys(prismDID, 10, "alias", listOf(privateKey)) - pluto?.storePrismDIDAndPrivateKeys(prismDID, 9, "alias", listOf(privateKey)) + pluto.start() + pluto.storePrismDIDAndPrivateKeys(prismDID, 10, "alias", listOf(privateKey)) + pluto.storePrismDIDAndPrivateKeys(prismDID, 9, "alias", listOf(privateKey)) - val keyPathIndex = pluto?.getPrismLastKeyPathIndex()?.first() + val keyPathIndex = pluto.getPrismLastKeyPathIndex().first() assertNotNull(keyPathIndex) assertEquals(10, keyPathIndex) } @@ -378,19 +379,19 @@ class PlutoImplTest { val peerDID3 = DID("did:peer:test3") val privateKey3 = X25519KeyPair.generateKeyPair().privateKey as StorableKey - pluto?.start() - pluto?.storePeerDID(peerDID1) - pluto?.storePrivateKeys(privateKey1, peerDID1, null, "$peerDID1#key-1") - pluto?.storePeerDID(peerDID2) - pluto?.storePrivateKeys(privateKey2, peerDID2, null, "$peerDID2#key-1") - pluto?.storePeerDID(peerDID3) - pluto?.storePrivateKeys(privateKey3, peerDID3, null, "$peerDID3#key-1") + pluto.start() + pluto.storePeerDID(peerDID1) + pluto.storePrivateKeys(privateKey1, peerDID1, null, "$peerDID1#key-1") + pluto.storePeerDID(peerDID2) + pluto.storePrivateKeys(privateKey2, peerDID2, null, "$peerDID2#key-1") + pluto.storePeerDID(peerDID3) + pluto.storePrivateKeys(privateKey3, peerDID3, null, "$peerDID3#key-1") - val peerDIDs = pluto?.getAllPeerDIDs()?.first() + val peerDIDs = pluto.getAllPeerDIDs().first() assertNotNull(peerDIDs) - assertEquals(3, peerDIDs?.size) + assertEquals(3, peerDIDs.size) - assertEquals(peerDID1.toString(), peerDIDs!![0].did.toString()) + assertEquals(peerDID1.toString(), peerDIDs[0].did.toString()) assertEquals(1, peerDIDs[0].privateKeys.size) assertContentEquals(privateKey1.storableData, peerDIDs[0].privateKeys.first().raw) @@ -409,16 +410,16 @@ class PlutoImplTest { val peerDID2 = DID("did:peer:test2") val peerDID3 = DID("did:peer:test3") - pluto?.start() - pluto?.storePeerDID(peerDID1) - pluto?.storePeerDID(peerDID2) - pluto?.storePeerDID(peerDID3) + pluto.start() + pluto.storePeerDID(peerDID1) + pluto.storePeerDID(peerDID2) + pluto.storePeerDID(peerDID3) - val dids = pluto?.getAllDIDs()?.first() + val dids = pluto.getAllDIDs().first() assertNotNull(dids) - assertEquals(3, dids?.size) + assertEquals(3, dids.size) - assertEquals(peerDID1.toString(), dids!![0].toString()) + assertEquals(peerDID1.toString(), dids[0].toString()) assertEquals(peerDID2.toString(), dids[1].toString()) assertEquals(peerDID3.toString(), dids[2].toString()) } @@ -432,19 +433,19 @@ class PlutoImplTest { val receiverPeerDID2 = DID("did:peer:test3") val name2 = "name2" - pluto?.start() - pluto?.storeDIDPair(hostPeerDID1, receiverPeerDID1, name1) - pluto?.storeDIDPair(hostPeerDID2, receiverPeerDID2, name2) + pluto.start() + pluto.storeDIDPair(hostPeerDID1, receiverPeerDID1, name1) + pluto.storeDIDPair(hostPeerDID2, receiverPeerDID2, name2) - val didPairs = pluto?.getAllDidPairs()?.first() + val didPairs = pluto.getAllDidPairs().first() assertNotNull(didPairs) - assertEquals(2, didPairs?.size) + assertEquals(2, didPairs.size) - assertEquals(hostPeerDID1.toString(), didPairs!![0].holder.toString()) + assertEquals(hostPeerDID1.toString(), didPairs[0].holder.toString()) assertEquals(receiverPeerDID1.toString(), didPairs[0].receiver.toString()) assertEquals(name1, didPairs[0].name) - assertEquals(hostPeerDID2.toString(), didPairs!![1].holder.toString()) + assertEquals(hostPeerDID2.toString(), didPairs[1].holder.toString()) assertEquals(receiverPeerDID2.toString(), didPairs[1].receiver.toString()) assertEquals(name2, didPairs[1].name) } @@ -458,16 +459,16 @@ class PlutoImplTest { val receiverPeerDID2 = DID("did:peer:test3") val name2 = "name2" - pluto?.start() - pluto?.storeDIDPair(hostPeerDID1, receiverPeerDID1, name1) - pluto?.storeDIDPair(hostPeerDID2, receiverPeerDID2, name2) + pluto.start() + pluto.storeDIDPair(hostPeerDID1, receiverPeerDID1, name1) + pluto.storeDIDPair(hostPeerDID2, receiverPeerDID2, name2) - val didPair = pluto?.getPairByDID(hostPeerDID2)?.first() + val didPair = pluto.getPairByDID(hostPeerDID2).first() assertNotNull(didPair) - assertEquals(hostPeerDID2.toString(), didPair!!.holder.toString()) - assertEquals(receiverPeerDID2.toString(), didPair.receiver.toString()) - assertEquals(name2, didPair.name) + assertEquals(hostPeerDID2.toString(), didPair?.holder.toString()) + assertEquals(receiverPeerDID2.toString(), didPair?.receiver.toString()) + assertEquals(name2, didPair?.name) } @Test @@ -479,16 +480,16 @@ class PlutoImplTest { val receiverPeerDID2 = DID("did:peer:test3") val name2 = "name2" - pluto?.start() - pluto?.storeDIDPair(hostPeerDID1, receiverPeerDID1, name1) - pluto?.storeDIDPair(hostPeerDID2, receiverPeerDID2, name2) + pluto.start() + pluto.storeDIDPair(hostPeerDID1, receiverPeerDID1, name1) + pluto.storeDIDPair(hostPeerDID2, receiverPeerDID2, name2) - val didPair = pluto?.getPairByName(name2)?.first() + val didPair = pluto.getPairByName(name2).first() assertNotNull(didPair) - assertEquals(hostPeerDID2.toString(), didPair!!.holder.toString()) - assertEquals(receiverPeerDID2.toString(), didPair.receiver.toString()) - assertEquals(name2, didPair.name) + assertEquals(hostPeerDID2.toString(), didPair?.holder.toString()) + assertEquals(receiverPeerDID2.toString(), didPair?.receiver.toString()) + assertEquals(name2, didPair?.name) } @Test @@ -507,14 +508,14 @@ class PlutoImplTest { body = "{}" ) - pluto?.start() - pluto?.storeMessages(listOf(message, message1)) + pluto.start() + pluto.storeMessages(listOf(message, message1)) - val messages = pluto?.getAllMessages(message.from!!, message.to!!)?.first() + val messages = pluto.getAllMessages(message.from!!, message.to!!).first() assertNotNull(messages) - assertEquals(1, messages?.size) + assertEquals(1, messages.size) - assertEquals(message.piuri, messages!![0].piuri) + assertEquals(message.piuri, messages[0].piuri) assertEquals(message.from, messages[0].from) assertEquals(message.to, messages[0].to) } @@ -536,20 +537,20 @@ class PlutoImplTest { direction = Message.Direction.SENT ) - pluto?.start() - pluto?.storeMessages(listOf(message, message1)) + pluto.start() + pluto.storeMessages(listOf(message, message1)) - val messages = pluto?.getAllMessagesSent()?.first() + val messages = pluto.getAllMessagesSent().first() assertNotNull(messages) - assertEquals(1, messages?.size) + assertEquals(1, messages.size) - assertEquals(message1.piuri, messages!![0].piuri) + assertEquals(message1.piuri, messages[0].piuri) assertEquals(message1.from, messages[0].from) assertEquals(message1.to, messages[0].to) - val messages1 = pluto?.getAllMessagesReceived()?.first() + val messages1 = pluto.getAllMessagesReceived().first() assertNotNull(messages1) - assertEquals(1, messages1!!.size) + assertEquals(1, messages1.size) assertEquals(message.piuri, messages1[0].piuri) assertEquals(message.from, messages1[0].from) @@ -573,16 +574,16 @@ class PlutoImplTest { direction = Message.Direction.SENT ) - pluto?.start() - pluto?.storeMessages(listOf(message, message1)) + pluto.start() + pluto.storeMessages(listOf(message, message1)) - val messages = pluto?.getAllMessagesSentTo(message1.to!!)?.first() + val messages = pluto.getAllMessagesSentTo(message1.to!!).first() assertNotNull(messages) - assertEquals(1, messages?.size) + assertEquals(1, messages.size) - assertEquals(message1.piuri, messages!![0].piuri) + assertEquals(message1.piuri, messages[0].piuri) assertEquals(message1.from, messages[0].from) - assertEquals(message1.to, messages[0].to) + assertEquals(message1.to, messages[0].to!!) } @Test @@ -602,16 +603,16 @@ class PlutoImplTest { direction = Message.Direction.SENT ) - pluto?.start() - pluto?.storeMessages(listOf(message, message1)) + pluto.start() + pluto.storeMessages(listOf(message, message1)) - val messages = pluto?.getAllMessagesSentTo(message.to!!)?.first() + val messages = pluto.getAllMessagesSentTo(message.to!!).first() assertNotNull(messages) - assertEquals(1, messages?.size) + assertEquals(1, messages.size) - assertEquals(message.piuri, messages!![0].piuri) - assertEquals(message.from, messages[0].from) - assertEquals(message.to, messages[0].to) + assertEquals(message.piuri, messages[0].piuri) + assertEquals(message.from, messages[0].from!!) + assertEquals(message.to, messages[0].to!!) } @Test @@ -632,15 +633,15 @@ class PlutoImplTest { thid = UUID.randomUUID().toString() ) - pluto?.start() - pluto?.storeMessages(listOf(message, message1)) + pluto.start() + pluto.storeMessages(listOf(message, message1)) - val message2 = pluto?.getMessageByThidAndPiuri(message1.thid!!, piuri = message1.piuri)?.first() + val message2 = pluto.getMessageByThidAndPiuri(message1.thid!!, piuri = message1.piuri).first() assertNotNull(message2) - assertEquals(message1.piuri, message2!!.piuri) - assertEquals(message1.from, message2.from) - assertEquals(message1.to, message2.to) + assertEquals(message1.piuri, message2?.piuri) + assertEquals(message1.from, message2?.from) + assertEquals(message1.to, message2?.to) } @Test @@ -649,16 +650,16 @@ class PlutoImplTest { "eyJhbGciOiJFUzI1NksifQ.eyJpc3MiOiJkaWQ6cHJpc206MjU3MTlhOTZiMTUxMjA3MTY5ODFhODQzMGFkMGNiOTY4ZGQ1MzQwNzM1OTNjOGNkM2YxZDI3YTY4MDRlYzUwZTpDcG9DQ3BjQ0Vsb0tCV3RsZVMweEVBSkNUd29KYzJWamNESTFObXN4RWlBRW9TQ241dHlEYTZZNnItSW1TcXBKOFkxbWo3SkMzX29VekUwTnl5RWlDQm9nc2dOYWVSZGNDUkdQbGU4MlZ2OXRKZk53bDZyZzZWY2hSM09xaGlWYlRhOFNXd29HWVhWMGFDMHhFQVJDVHdvSmMyVmpjREkxTm1zeEVpRE1rQmQ2RnRpb0prM1hPRnUtX2N5NVhtUi00dFVRMk5MR2lXOGFJU29ta1JvZzZTZGU5UHduRzBRMFNCVG1GU1REYlNLQnZJVjZDVExYcmpJSnR0ZUdJbUFTWEFvSGJXRnpkR1Z5TUJBQlFrOEtDWE5sWTNBeU5UWnJNUklnTzcxMG10MVdfaXhEeVFNM3hJczdUcGpMQ05PRFF4Z1ZoeDVzaGZLTlgxb2FJSFdQcnc3SVVLbGZpYlF0eDZKazRUU2pnY1dOT2ZjT3RVOUQ5UHVaN1Q5dCIsInN1YiI6ImRpZDpwcmlzbTpiZWVhNTIzNGFmNDY4MDQ3MTRkOGVhOGVjNzdiNjZjYzdmM2U4MTVjNjhhYmI0NzVmMjU0Y2Y5YzMwNjI2NzYzOkNzY0JDc1FCRW1RS0QyRjFkR2hsYm5ScFkyRjBhVzl1TUJBRVFrOEtDWE5sWTNBeU5UWnJNUklnZVNnLTJPTzFKZG5welVPQml0eklpY1hkZnplQWNUZldBTi1ZQ2V1Q2J5SWFJSlE0R1RJMzB0YVZpd2NoVDNlMG5MWEJTNDNCNGo5amxzbEtvMlpsZFh6akVsd0tCMjFoYzNSbGNqQVFBVUpQQ2dselpXTndNalUyYXpFU0lIa29QdGpqdFNYWjZjMURnWXJjeUluRjNYODNnSEUzMWdEZm1BbnJnbThpR2lDVU9Ca3lOOUxXbFlzSElVOTN0Snkxd1V1TndlSV9ZNWJKU3FObVpYVjg0dyIsIm5iZiI6MTY4NTYzMTk5NSwiZXhwIjoxNjg1NjM1NTk1LCJ2YyI6eyJjcmVkZW50aWFsU3ViamVjdCI6eyJhZGRpdGlvbmFsUHJvcDIiOiJUZXN0MyIsImlkIjoiZGlkOnByaXNtOmJlZWE1MjM0YWY0NjgwNDcxNGQ4ZWE4ZWM3N2I2NmNjN2YzZTgxNWM2OGFiYjQ3NWYyNTRjZjljMzA2MjY3NjM6Q3NjQkNzUUJFbVFLRDJGMWRHaGxiblJwWTJGMGFXOXVNQkFFUWs4S0NYTmxZM0F5TlRack1SSWdlU2ctMk9PMUpkbnB6VU9CaXR6SWljWGRmemVBY1RmV0FOLVlDZXVDYnlJYUlKUTRHVEkzMHRhVml3Y2hUM2UwbkxYQlM0M0I0ajlqbHNsS28yWmxkWHpqRWx3S0IyMWhjM1JsY2pBUUFVSlBDZ2x6WldOd01qVTJhekVTSUhrb1B0amp0U1haNmMxRGdZcmN5SW5GM1g4M2dIRTMxZ0RmbUFucmdtOGlHaUNVT0JreU45TFdsWXNISVU5M3RKeTF3VXVOd2VJX1k1YkpTcU5tWlhWODR3In0sInR5cGUiOlsiVmVyaWZpYWJsZUNyZWRlbnRpYWwiXSwiQGNvbnRleHQiOlsiaHR0cHM6XC9cL3d3dy53My5vcmdcLzIwMThcL2NyZWRlbnRpYWxzXC92MSJdfX0.x0SF17Y0VCDmt7HceOdTxfHlofsZmY18Rn6VQb0-r-k_Bm3hTi1-k2vkdjB25hdxyTCvxam-AkAP-Ag3Ahn5Ng" ) - pluto?.start() - pluto?.storeCredential(credential.toStorableCredential()) + pluto.start() + pluto.storeCredential(credential.toStorableCredential()) - val observeRevoked = pluto?.observeRevokedCredentials() + val observeRevoked = pluto.observeRevokedCredentials() - pluto?.revokeCredential(credential.id) - val credentials = pluto?.getAllCredentials()?.first() + pluto.revokeCredential(credential.id) + val credentials = pluto.getAllCredentials().first() assertNotNull(credentials) - val cred = credentials!!.first() + val cred = credentials.first() assertTrue(cred.revoked) - assertEquals(1, observeRevoked?.first()?.size) + assertEquals(1, observeRevoked.first().size) } } diff --git a/edge-agent-sdk/src/jvmMain/kotlin/org/hyperledger/identus/walletsdk/pluto/data/DbConnectionImpl.kt b/edge-agent-sdk/src/jvmMain/kotlin/org/hyperledger/identus/walletsdk/pluto/data/DbConnectionImpl.kt index 0676ac992..653dfe714 100644 --- a/edge-agent-sdk/src/jvmMain/kotlin/org/hyperledger/identus/walletsdk/pluto/data/DbConnectionImpl.kt +++ b/edge-agent-sdk/src/jvmMain/kotlin/org/hyperledger/identus/walletsdk/pluto/data/DbConnectionImpl.kt @@ -6,6 +6,7 @@ import org.hyperledger.identus.walletsdk.SdkPlutoDb actual class DbConnectionImpl actual constructor() : DbConnection { actual override var driver: SqlDriver? = null + actual override suspend fun connectDb(context: Any?): SqlDriver { val driver = JdbcSqliteDriver("jdbc:sqlite:prism.db") SdkPlutoDb.Schema.create(driver) diff --git a/tests/end-to-end/build.gradle.kts b/tests/end-to-end/build.gradle.kts index fa47a2b1d..ba81334bb 100644 --- a/tests/end-to-end/build.gradle.kts +++ b/tests/end-to-end/build.gradle.kts @@ -29,8 +29,10 @@ repositories { dependencies { testImplementation("org.hyperledger.identus:edge-agent-sdk:3.0.0") - testImplementation("io.iohk.atala.prism:prism-kotlin-client:1.31.0") + testImplementation("org.hyperledger.identus:cloud-agent-client-kotlin:1.38.0") testImplementation("io.iohk.atala:atala-automation:0.3.2") + testImplementation("app.cash.sqldelight:sqlite-driver:2.0.2") + testImplementation("io.ktor:ktor-client-core-jvm:2.3.12") } tasks.register("cleanTarget") { diff --git a/tests/end-to-end/src/test/kotlin/org/hyperledger/identus/walletsdk/TestSuite.kt b/tests/end-to-end/src/test/kotlin/org/hyperledger/identus/walletsdk/TestSuite.kt index bfbe04d33..19dd1be46 100644 --- a/tests/end-to-end/src/test/kotlin/org/hyperledger/identus/walletsdk/TestSuite.kt +++ b/tests/end-to-end/src/test/kotlin/org/hyperledger/identus/walletsdk/TestSuite.kt @@ -8,6 +8,6 @@ import org.junit.runner.RunWith @CucumberOptions( features = ["src/test/resources/features"], plugin = ["pretty"], - tags = "not (@proof and @anoncred)" + tags = "not @disabled" ) class TestSuite diff --git a/tests/end-to-end/src/test/kotlin/org/hyperledger/identus/walletsdk/abilities/UseWalletSdk.kt b/tests/end-to-end/src/test/kotlin/org/hyperledger/identus/walletsdk/abilities/UseWalletSdk.kt index 5d219a341..7c31b1e2b 100644 --- a/tests/end-to-end/src/test/kotlin/org/hyperledger/identus/walletsdk/abilities/UseWalletSdk.kt +++ b/tests/end-to-end/src/test/kotlin/org/hyperledger/identus/walletsdk/abilities/UseWalletSdk.kt @@ -2,37 +2,55 @@ package org.hyperledger.identus.walletsdk.abilities import com.jayway.jsonpath.JsonPath import io.iohk.atala.automation.utils.Logger -import org.hyperledger.identus.walletsdk.configuration.Environment -import org.hyperledger.identus.walletsdk.workflow.EdgeAgentWorkflow import io.restassured.RestAssured import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking import net.serenitybdd.screenplay.Ability import net.serenitybdd.screenplay.Actor +import net.serenitybdd.screenplay.HasTeardown import net.serenitybdd.screenplay.Question import net.serenitybdd.screenplay.SilentInteraction import org.hyperledger.identus.walletsdk.apollo.ApolloImpl import org.hyperledger.identus.walletsdk.castor.CastorImpl +import org.hyperledger.identus.walletsdk.configuration.DbConnectionInMemory +import org.hyperledger.identus.walletsdk.configuration.Environment import org.hyperledger.identus.walletsdk.domain.models.ApiImpl import org.hyperledger.identus.walletsdk.domain.models.DID import org.hyperledger.identus.walletsdk.domain.models.Message +import org.hyperledger.identus.walletsdk.domain.models.Seed import org.hyperledger.identus.walletsdk.domain.models.httpClient import org.hyperledger.identus.walletsdk.edgeagent.EdgeAgent +import org.hyperledger.identus.walletsdk.edgeagent.helpers.AgentOptions +import org.hyperledger.identus.walletsdk.edgeagent.helpers.Experiments import org.hyperledger.identus.walletsdk.edgeagent.mediation.BasicMediatorHandler -import org.hyperledger.identus.walletsdk.edgeagent.protocols.ProtocolType +import org.hyperledger.identus.walletsdk.edgeagent.protocols.ProtocolType.DidcommIssueCredential +import org.hyperledger.identus.walletsdk.edgeagent.protocols.ProtocolType.DidcommOfferCredential +import org.hyperledger.identus.walletsdk.edgeagent.protocols.ProtocolType.DidcommPresentation +import org.hyperledger.identus.walletsdk.edgeagent.protocols.ProtocolType.DidcommRequestPresentation +import org.hyperledger.identus.walletsdk.edgeagent.protocols.ProtocolType.PrismRevocation import org.hyperledger.identus.walletsdk.mercury.MercuryImpl import org.hyperledger.identus.walletsdk.mercury.resolvers.DIDCommWrapper import org.hyperledger.identus.walletsdk.pluto.PlutoImpl -import org.hyperledger.identus.walletsdk.pluto.data.DbConnection import org.hyperledger.identus.walletsdk.pollux.PolluxImpl -import java.util.* +import org.hyperledger.identus.walletsdk.workflow.EdgeAgentWorkflow +import org.lighthousegames.logging.KmLogging +import org.lighthousegames.logging.LogLevel +import java.util.Base64 +import java.util.Collections -class UseWalletSdk : Ability { +class UseWalletSdk : Ability, HasTeardown { companion object { private fun `as`(actor: Actor): UseWalletSdk { + if (actor.abilityTo(UseWalletSdk::class.java) != null) { + val ability = actor.abilityTo(UseWalletSdk::class.java) + if (!ability.isInitialized) { + ability.initialize() + } + } return actor.abilityTo(UseWalletSdk::class.java) ?: throw ActorCannotUseWalletSdk(actor) } @@ -60,6 +78,12 @@ class UseWalletSdk : Ability { } } + fun presentationStackSize(): Question { + return Question.about("presentation messages stack").answeredBy { + `as`(it).context.presentationStack.size + } + } + fun execute(callback: suspend (sdk: SdkContext) -> Unit): SilentInteraction { return object : SilentInteraction() { override fun performAs(actor: T) { @@ -70,71 +94,103 @@ class UseWalletSdk : Ability { } } } + } - fun stop(): SilentInteraction { - return object : SilentInteraction() { - override fun performAs(actor: T) { - val walletSdk = `as`(actor) - runBlocking { - walletSdk.context.sdk.stopFetchingMessages() - walletSdk.context.sdk.stop() - } - } + private val logger = Logger.get() + private lateinit var context: SdkContext + private val receivedMessages = mutableListOf() + private var isInitialized = false + private lateinit var fetchJob: Job + + fun initialize() { + createSdk() + startPluto() + startSdk() + listenToMessages() + isInitialized = true + } - } + override fun tearDown() { + if (isInitialized) { + context.sdk.stopFetchingMessages() + context.sdk.stop() + fetchJob.cancel() } } - private val logger = Logger.get() - private val context: SdkContext - private val receivedMessages = mutableListOf() + fun recoverWallet(seed: Seed, jwe: String) { + createSdk(seed) + startPluto() + runBlocking { + context.sdk.recoverWallet(jwe) + } + startSdk() + listenToMessages() + isInitialized = true + } - init { + private fun createSdk(initialSeed: Seed? = null) { + val api = ApiImpl(httpClient()) val apollo = ApolloImpl() val castor = CastorImpl(apollo) - val pluto = PlutoImpl(DbConnection()) - val pollux = PolluxImpl(castor) + val pluto = PlutoImpl(DbConnectionInMemory()) + val pollux = PolluxImpl(apollo, castor, api) val didcommWrapper = DIDCommWrapper(castor, pluto, apollo) - val api = ApiImpl(httpClient()) val mercury = MercuryImpl(castor, didcommWrapper, api) val mediatorDid = DID(getMediatorDidThroughOob()) val store = BasicMediatorHandler.PlutoMediatorRepositoryImpl(pluto) val handler = BasicMediatorHandler(mediatorDid, mercury, store) - val seed = apollo.createRandomSeed().seed + val seed = initialSeed ?: apollo.createRandomSeed().seed val sdk = EdgeAgent( - apollo, - castor, - pluto, - mercury, - pollux, - seed, - api, - handler + apollo = apollo, + castor = castor, + pluto = pluto, + mercury = mercury, + pollux = pollux, + seed = seed, + api = api, + mediatorHandler = handler, + agentOptions = AgentOptions( + experiments = Experiments( + liveMode = false + ) + ) ) + KmLogging.setLogLevel(LogLevel.Warn) this.context = SdkContext(sdk) + } + + private fun startPluto() { + runBlocking { + context.sdk.pluto.start(this) + } + } + private fun startSdk() { runBlocking { - pluto.start(this) - sdk.start() - sdk.startFetchingMessages(1) + context.sdk.start() } + context.sdk.startFetchingMessages(1) + } - CoroutineScope(Dispatchers.Default).launch { - sdk.handleReceivedMessagesEvents().collect { messageList: List -> + private fun listenToMessages() { + fetchJob = CoroutineScope(Dispatchers.Default).launch { + context.sdk.handleReceivedMessagesEvents().collect { messageList: List -> messageList.forEach { message -> if (receivedMessages.contains(message.id)) { return@forEach } receivedMessages.add(message.id) when (message.piuri) { - ProtocolType.DidcommOfferCredential.value -> context.credentialOfferStack.add(message) - ProtocolType.DidcommIssueCredential.value -> context.issuedCredentialStack.add(message) - ProtocolType.DidcommRequestPresentation.value -> context.proofRequestStack.add(message) - ProtocolType.PrismRevocation.value -> context.revocationNotificationStack.add(message) + DidcommOfferCredential.value -> context.credentialOfferStack.add(message) + DidcommIssueCredential.value -> context.issuedCredentialStack.add(message) + DidcommRequestPresentation.value -> context.proofRequestStack.add(message) + PrismRevocation.value -> context.revocationNotificationStack.add(message) + DidcommPresentation.value -> context.presentationStack.add(message) else -> logger.debug("other message: ${message.piuri}") } } @@ -157,7 +213,8 @@ data class SdkContext( val credentialOfferStack: MutableList = Collections.synchronizedList(mutableListOf()), val proofRequestStack: MutableList = Collections.synchronizedList(mutableListOf()), val issuedCredentialStack: MutableList = Collections.synchronizedList(mutableListOf()), - val revocationNotificationStack: MutableList = Collections.synchronizedList(mutableListOf()) + val revocationNotificationStack: MutableList = Collections.synchronizedList(mutableListOf()), + val presentationStack: MutableList = Collections.synchronizedList(mutableListOf()) ) class ActorCannotUseWalletSdk(actor: Actor) : diff --git a/tests/end-to-end/src/test/kotlin/org/hyperledger/identus/walletsdk/configuration/DbConnectionInMemory.kt b/tests/end-to-end/src/test/kotlin/org/hyperledger/identus/walletsdk/configuration/DbConnectionInMemory.kt new file mode 100644 index 000000000..24ff9beb4 --- /dev/null +++ b/tests/end-to-end/src/test/kotlin/org/hyperledger/identus/walletsdk/configuration/DbConnectionInMemory.kt @@ -0,0 +1,17 @@ +package org.hyperledger.identus.walletsdk.configuration + +import app.cash.sqldelight.db.SqlDriver +import app.cash.sqldelight.driver.jdbc.sqlite.JdbcSqliteDriver +import org.hyperledger.identus.walletsdk.SdkPlutoDb +import org.hyperledger.identus.walletsdk.pluto.data.DbConnection + +class DbConnectionInMemory : DbConnection { + override var driver: SqlDriver? = null + + override suspend fun connectDb(context: Any?): SqlDriver { + val driver = JdbcSqliteDriver(JdbcSqliteDriver.IN_MEMORY) + SdkPlutoDb.Schema.create(driver) + this.driver = driver + return driver + } +} diff --git a/tests/end-to-end/src/test/kotlin/org/hyperledger/identus/walletsdk/configuration/Environment.kt b/tests/end-to-end/src/test/kotlin/org/hyperledger/identus/walletsdk/configuration/Environment.kt index 7596b76b4..ceb417646 100644 --- a/tests/end-to-end/src/test/kotlin/org/hyperledger/identus/walletsdk/configuration/Environment.kt +++ b/tests/end-to-end/src/test/kotlin/org/hyperledger/identus/walletsdk/configuration/Environment.kt @@ -1,7 +1,6 @@ package org.hyperledger.identus.walletsdk.configuration import io.iohk.atala.automation.utils.Wait -import io.iohk.atala.prism.models.* import org.hyperledger.identus.walletsdk.utils.Notes import io.restassured.RestAssured import io.restassured.builder.RequestSpecBuilder @@ -9,6 +8,13 @@ import io.restassured.response.Response import net.serenitybdd.rest.SerenityRest import org.apache.http.HttpStatus import org.assertj.core.api.Assertions.assertThat +import org.hyperledger.identus.client.models.CreateManagedDidRequest +import org.hyperledger.identus.client.models.CreateManagedDidRequestDocumentTemplate +import org.hyperledger.identus.client.models.CredentialDefinitionInput +import org.hyperledger.identus.client.models.CredentialDefinitionResponse +import org.hyperledger.identus.client.models.CredentialSchemaInput +import org.hyperledger.identus.client.models.ManagedDIDKeyTemplate +import org.hyperledger.identus.client.models.Purpose import org.hyperledger.identus.walletsdk.models.AnoncredSchema import org.hyperledger.identus.walletsdk.models.JwtSchema import org.hyperledger.identus.walletsdk.models.JwtSchemaProperty diff --git a/tests/end-to-end/src/test/kotlin/org/hyperledger/identus/walletsdk/configuration/HooksSetup.kt b/tests/end-to-end/src/test/kotlin/org/hyperledger/identus/walletsdk/configuration/HooksSetup.kt index 419916b5f..bf6aa01ef 100644 --- a/tests/end-to-end/src/test/kotlin/org/hyperledger/identus/walletsdk/configuration/HooksSetup.kt +++ b/tests/end-to-end/src/test/kotlin/org/hyperledger/identus/walletsdk/configuration/HooksSetup.kt @@ -1,5 +1,6 @@ package org.hyperledger.identus.walletsdk.configuration +import io.cucumber.java.After import io.cucumber.java.Before import io.cucumber.java.BeforeAll import io.cucumber.java.ParameterType @@ -15,6 +16,11 @@ fun setupEnvironment() { Environment.setup() } +@After +fun drawTheCurtain() { + OnStage.drawTheCurtain() +} + class HooksSetup { @Before fun setStage() { @@ -25,6 +31,11 @@ class HooksSetup { UseWalletSdk() ) + cast.actorNamed("Verifier Edge Agent", + CallAnApi.at(Environment.mediatorOobUrl), + UseWalletSdk() + ) + cast.actorNamed("Cloud Agent", CallAnApi.at(Environment.agentUrl) ) diff --git a/tests/end-to-end/src/test/kotlin/org/hyperledger/identus/walletsdk/steps/CloudAgentSteps.kt b/tests/end-to-end/src/test/kotlin/org/hyperledger/identus/walletsdk/steps/CloudAgentSteps.kt index 5eb0fe899..71d406433 100644 --- a/tests/end-to-end/src/test/kotlin/org/hyperledger/identus/walletsdk/steps/CloudAgentSteps.kt +++ b/tests/end-to-end/src/test/kotlin/org/hyperledger/identus/walletsdk/steps/CloudAgentSteps.kt @@ -63,6 +63,11 @@ class CloudAgentSteps { cloudAgentWorkflow.askForPresentProofForAnoncred(cloudAgent) } + @When("{actor} asks for present-proof for anoncred with unexpected attributes") + fun `Cloud Agent asks for present-proof for anoncred with unexpected attributes`(cloudAgent: Actor) { + cloudAgentWorkflow.askForPresentProofForAnoncredWithUnexpectedAttributes(cloudAgent) + } + @When("{actor} revokes '{int}' credentials") fun `Cloud Agent revokes {} credentials`(cloudAgent: Actor, numberOfRevokedCredentials: Int) { cloudAgentWorkflow.revokeCredential(cloudAgent, numberOfRevokedCredentials) @@ -78,6 +83,11 @@ class CloudAgentSteps { cloudAgentWorkflow.verifyPresentProof(cloudAgent, "PresentationVerified") } + @Then("{actor} should see the present-proof is not verified") + fun `Cloud Agent should see the present-proof is not verified`(cloudAgent: Actor) { + cloudAgentWorkflow.verifyPresentProof(cloudAgent, "PresentationFailed") + } + @Then("{actor} should see all credentials were accepted") fun `Cloud Agent should see all credentials were accepted`(cloudAgent: Actor) { val recordIdList = cloudAgent.recall>("recordIdList") diff --git a/tests/end-to-end/src/test/kotlin/org/hyperledger/identus/walletsdk/steps/EdgeAgentSteps.kt b/tests/end-to-end/src/test/kotlin/org/hyperledger/identus/walletsdk/steps/EdgeAgentSteps.kt index 14bac61c0..b096dc3a2 100644 --- a/tests/end-to-end/src/test/kotlin/org/hyperledger/identus/walletsdk/steps/EdgeAgentSteps.kt +++ b/tests/end-to-end/src/test/kotlin/org/hyperledger/identus/walletsdk/steps/EdgeAgentSteps.kt @@ -1,13 +1,24 @@ package org.hyperledger.identus.walletsdk.steps -import io.cucumber.java.After +import io.cucumber.java.en.Given import io.cucumber.java.en.Then import io.cucumber.java.en.When +import kotlinx.coroutines.flow.first +import net.serenitybdd.screenplay.Actor +import org.assertj.core.api.Assertions +import org.assertj.core.api.Assertions.assertThat import org.hyperledger.identus.walletsdk.abilities.UseWalletSdk +import org.hyperledger.identus.walletsdk.domain.models.AnoncredsInputFieldFilter +import org.hyperledger.identus.walletsdk.domain.models.AnoncredsPresentationClaims +import org.hyperledger.identus.walletsdk.domain.models.CredentialType +import org.hyperledger.identus.walletsdk.domain.models.DID +import org.hyperledger.identus.walletsdk.domain.models.InputFieldFilter +import org.hyperledger.identus.walletsdk.domain.models.JWTPresentationClaims +import org.hyperledger.identus.walletsdk.domain.models.NonRevoked +import org.hyperledger.identus.walletsdk.domain.models.PresentationClaims +import org.hyperledger.identus.walletsdk.domain.models.RequestedAttributes import org.hyperledger.identus.walletsdk.workflow.CloudAgentWorkflow import org.hyperledger.identus.walletsdk.workflow.EdgeAgentWorkflow -import net.serenitybdd.screenplay.Actor -import net.serenitybdd.screenplay.actors.OnStage import javax.inject.Inject class EdgeAgentSteps { @@ -18,11 +29,26 @@ class EdgeAgentSteps { @Inject private lateinit var cloudAgentWorkflow: CloudAgentWorkflow + @Given("{actor} has created a backup") + fun `Edge Agent has created a backup`(edgeAgent: Actor) { + edgeAgentWorkflow.createBackup(edgeAgent) + } + @When("{actor} connects through the invite") fun `Edge Agent connects through the invite`(edgeAgent: Actor) { edgeAgentWorkflow.connect(edgeAgent) } + @When("{actor} creates '{}' peer DIDs") + fun `Edge Agent creates Peer DIDs`(edgeAgent: Actor, numberOfDids: Int) { + edgeAgentWorkflow.createPeerDids(edgeAgent, numberOfDids) + } + + @When("{actor} creates '{}' prism DIDs") + fun `Edge Agent creates Prism DIDs`(edgeAgent: Actor, numberOfDids: Int) { + edgeAgentWorkflow.createPrismDids(edgeAgent, numberOfDids) + } + @When("{actor} has '{}' jwt credentials issued by {actor}") fun `Edge Agent has {} jwt issued credential`(edgeAgent: Actor, numberOfCredentialsIssued: Int, cloudAgent: Actor) { val recordIdList = mutableListOf() @@ -40,7 +66,11 @@ class EdgeAgentSteps { } @When("{actor} has '{}' anonymous credentials issued by {actor}") - fun `Edge Agent has {} anonymous issued credential`(edgeAgent: Actor, numberOfCredentialsIssued: Int, cloudAgent: Actor) { + fun `Edge Agent has {} anonymous issued credential`( + edgeAgent: Actor, + numberOfCredentialsIssued: Int, + cloudAgent: Actor + ) { repeat(numberOfCredentialsIssued) { cloudAgentWorkflow.offerAnonymousCredential(cloudAgent) edgeAgentWorkflow.waitForCredentialOffer(edgeAgent, 1) @@ -103,6 +133,42 @@ class EdgeAgentSteps { edgeAgentWorkflow.presentProof(edgeAgent) } + @When("{actor} request {actor} to verify the JWT credential") + fun `Verifier requests Holder to verify the JWT Credential`(verifierEdgeAgent: Actor, holderEdgeAgent: Actor) { + edgeAgentWorkflow.createPeerDids(holderEdgeAgent, 1) + val did = holderEdgeAgent.recall("did") + val claims = JWTPresentationClaims( + claims = mapOf( + "automation-required" to InputFieldFilter(type = "string", pattern = "required value") + ) + ) + edgeAgentWorkflow.initiatePresentationRequest(CredentialType.JWT, verifierEdgeAgent, did, claims) + } + + @When("{actor} request {actor} to verify the anonymous credential") + fun `Verifier requests Holder to verify the anoncred credential`(verifierEdgeAgent: Actor, holderEdgeAgent: Actor) { + edgeAgentWorkflow.createPeerDids(holderEdgeAgent, 1) + val did = holderEdgeAgent.recall("did") + val claims = AnoncredsPresentationClaims( + attributes = mapOf( + "name" to RequestedAttributes( + name = "name", + names = setOf("name"), + restrictions = emptyMap(), + null + ) + ), + predicates = emptyMap() + ) + edgeAgentWorkflow.initiatePresentationRequest(CredentialType.ANONCREDS_PROOF_REQUEST, verifierEdgeAgent, did, claims) + } + + @When("{actor} sends the verification proof") + fun `Edge Agent sends the verification proof`(edgeAgent: Actor) { + edgeAgentWorkflow.waitForProofRequest(edgeAgent) + edgeAgentWorkflow.presentProof(edgeAgent) + } + @Then("{actor} should receive the credential") fun `Edge Agent should receive the credential`(edgeAgent: Actor) { edgeAgentWorkflow.waitForCredentialOffer(edgeAgent, 1) @@ -124,12 +190,20 @@ class EdgeAgentSteps { } @Then("{actor} should have {} credentials") - fun `Edge Agent should have N credential`(actor: Actor, numberOfCredentials: Int) { - //edgeAgentWorkflow.creden + fun `Edge Agent should have expected credentials`(actor: Actor, numberOfCredentials: Int) { + actor.attemptsTo( + UseWalletSdk.execute { + val credentials = it.sdk.getAllCredentials().first() + assertThat(credentials.size).isEqualTo(numberOfCredentials) + } + ) } @Then("{actor} waits to receive the revocation notifications from {actor}") - fun `Edge Agent waits to receive the revocation notifications from Cloud Agent`(edgeAgent: Actor, cloudAgent: Actor) { + fun `Edge Agent waits to receive the revocation notifications from Cloud Agent`( + edgeAgent: Actor, + cloudAgent: Actor + ) { val revokedRecordIdList = cloudAgent.recall>("revokedRecordIdList") edgeAgentWorkflow.waitForCredentialRevocationMessage(edgeAgent, revokedRecordIdList.size) } @@ -140,10 +214,43 @@ class EdgeAgentSteps { edgeAgentWorkflow.waitUntilCredentialIsRevoked(edgeAgent, revokedRecordIdList) } - @After - fun stopAgent() { - OnStage.theActor("Edge Agent").attemptsTo( - UseWalletSdk.stop() - ) + @Then("a new SDK can be restored from {actor}") + fun `A new SDK can be restored from Edge Agent`(edgeAgent: Actor) { + edgeAgentWorkflow.createANewWalletFromBackup(edgeAgent) + } + + @Then("a new SDK cannot be restored from {actor} with wrong seed") + fun `A new SDK cannot be restored from Edge Agent with wrong seed`(edgeAgent: Actor) { + edgeAgentWorkflow.createNewWalletFromBackupWithWrongSeed(edgeAgent) + } + + @Then("a new {actor} is restored from {actor}") + fun `A new Agent is restored from Edge Agent`(newAgent: Actor, originalAgent: Actor) { + edgeAgentWorkflow.backupAndRestoreToNewAgent(newAgent, originalAgent) + } + + @Then("{actor} should have the expected values from {actor}") + fun `Restored Agent should have the expected values from Original Edge Agent`( + restoredEdgeAgent: Actor, + originalEdgeAgent: Actor + ) { + edgeAgentWorkflow.copyAgentShouldMatchOriginalAgent(restoredEdgeAgent, originalEdgeAgent) + } + + @Then("{actor} is dismissed") + fun `Edge Agent is dismissed`(edgeAgent: Actor) { + edgeAgent.wrapUp() + } + + @Then("{actor} should see the verification proof is verified") + fun `Verifier Edge Agent should see the verification proof is verified`(verifierEdgeAgent: Actor) { + edgeAgentWorkflow.waitForPresentationMessage(verifierEdgeAgent) + edgeAgentWorkflow.verifyPresentation(verifierEdgeAgent) + } + + @Then("{actor} should see the verification proof was not verified due revocation") + fun `Verifier Edge Agent should see the verification proof was not verified`(verifierEdgeAgent: Actor) { + edgeAgentWorkflow.waitForPresentationMessage(verifierEdgeAgent) + edgeAgentWorkflow.verifyPresentation(verifierEdgeAgent, expected = false, shouldBeRevoked = true) } } diff --git a/tests/end-to-end/src/test/kotlin/org/hyperledger/identus/walletsdk/workflow/CloudAgentWorkflow.kt b/tests/end-to-end/src/test/kotlin/org/hyperledger/identus/walletsdk/workflow/CloudAgentWorkflow.kt index 48c13f221..0aa379ce9 100644 --- a/tests/end-to-end/src/test/kotlin/org/hyperledger/identus/walletsdk/workflow/CloudAgentWorkflow.kt +++ b/tests/end-to-end/src/test/kotlin/org/hyperledger/identus/walletsdk/workflow/CloudAgentWorkflow.kt @@ -7,20 +7,20 @@ import io.iohk.atala.automation.serenity.ensure.Ensure import io.iohk.atala.automation.serenity.interactions.PollingWait import io.iohk.atala.automation.serenity.questions.HttpRequest import org.hyperledger.identus.walletsdk.configuration.Environment -import io.iohk.atala.prism.models.AnoncredPresentationRequestV1 -import io.iohk.atala.prism.models.AnoncredRequestedAttributeV1 -import io.iohk.atala.prism.models.AnoncredRequestedPredicateV1 -import io.iohk.atala.prism.models.CreateConnectionRequest -import io.iohk.atala.prism.models.CreateIssueCredentialRecordRequest -import io.iohk.atala.prism.models.Options -import io.iohk.atala.prism.models.ProofRequestAux -import io.iohk.atala.prism.models.RequestPresentationInput import org.hyperledger.identus.walletsdk.utils.Utils import net.serenitybdd.rest.SerenityRest.lastResponse import net.serenitybdd.screenplay.Actor import net.serenitybdd.screenplay.rest.interactions.Patch import net.serenitybdd.screenplay.rest.interactions.Post import org.apache.http.HttpStatus +import org.hyperledger.identus.client.models.AnoncredPresentationRequestV1 +import org.hyperledger.identus.client.models.AnoncredRequestedAttributeV1 +import org.hyperledger.identus.client.models.AnoncredRequestedPredicateV1 +import org.hyperledger.identus.client.models.CreateConnectionRequest +import org.hyperledger.identus.client.models.CreateIssueCredentialRecordRequest +import org.hyperledger.identus.client.models.Options +import org.hyperledger.identus.client.models.ProofRequestAux +import org.hyperledger.identus.client.models.RequestPresentationInput import java.util.UUID class CloudAgentWorkflow { @@ -58,7 +58,7 @@ class CloudAgentWorkflow { fun offerJwtCredential(cloudAgent: Actor) { val connectionId = cloudAgent.recall("connectionId") val credential = CreateIssueCredentialRecordRequest( - claims = mapOf(Pair("automation-required", UUID.randomUUID())), + claims = mapOf(Pair("automation-required", "required value")), issuingDID = Environment.publishedDid, connectionId = UUID.fromString(connectionId), schemaId = "${Environment.agentUrl}/schema-registry/schemas/${Environment.jwtSchemaGuid}" @@ -162,6 +162,43 @@ class CloudAgentWorkflow { cloudAgent.remember("presentationId", lastResponse().get("presentationId")) } + fun askForPresentProofForAnoncredWithUnexpectedAttributes(cloudAgent: Actor) { + val credentialDefinitionId = Environment.agentUrl + + "/credential-definition-registry/definitions/" + + Environment.anoncredDefinitionId + + "/definition" + val anoncredsPresentationRequestV1 = AnoncredPresentationRequestV1( + requestedAttributes = mapOf( + "name" to AnoncredRequestedAttributeV1( + name = "name", + restrictions = listOf( + mapOf( + "attr::name::value" to "Automation", + "cred_def_id" to credentialDefinitionId + ) + ) + ) + ), + requestedPredicates = mapOf(), + name = "proof_req_1", + nonce = Utils.generateNonce(25), + version = "0.1" + ) + + val presentProofRequest = RequestPresentationInput( + connectionId = UUID.fromString(cloudAgent.recall("connectionId")), + credentialFormat = "AnonCreds", + anoncredPresentationRequest = anoncredsPresentationRequestV1, + proofs = emptyList() + ) + + cloudAgent.attemptsTo( + Post.to("/present-proof/presentations").body(presentProofRequest), + Ensure.thatTheLastResponse().statusCode().isEqualTo(HttpStatus.SC_CREATED) + ) + cloudAgent.remember("presentationId", lastResponse().get("presentationId")) + } + fun verifyCredentialState(cloudAgent: Actor, recordId: String, state: String) { cloudAgent.attemptsTo( PollingWait.until( diff --git a/tests/end-to-end/src/test/kotlin/org/hyperledger/identus/walletsdk/workflow/EdgeAgentWorkflow.kt b/tests/end-to-end/src/test/kotlin/org/hyperledger/identus/walletsdk/workflow/EdgeAgentWorkflow.kt index af911f195..67c80e206 100644 --- a/tests/end-to-end/src/test/kotlin/org/hyperledger/identus/walletsdk/workflow/EdgeAgentWorkflow.kt +++ b/tests/end-to-end/src/test/kotlin/org/hyperledger/identus/walletsdk/workflow/EdgeAgentWorkflow.kt @@ -3,18 +3,33 @@ package org.hyperledger.identus.walletsdk.workflow import com.google.gson.GsonBuilder import io.iohk.atala.automation.serenity.interactions.PollingWait import io.iohk.atala.automation.utils.Logger -import org.hyperledger.identus.walletsdk.abilities.UseWalletSdk +import io.ktor.util.reflect.* import kotlinx.coroutines.flow.first +import kotlinx.coroutines.runBlocking import net.serenitybdd.screenplay.Actor -import net.serenitybdd.screenplay.rest.interactions.Ensure +import net.serenitybdd.screenplay.rest.abilities.CallAnApi import org.assertj.core.api.Assertions.assertThat +import org.assertj.core.api.Assertions.fail import org.hamcrest.CoreMatchers.equalTo +import org.hyperledger.identus.walletsdk.abilities.SdkContext +import org.hyperledger.identus.walletsdk.abilities.UseWalletSdk +import org.hyperledger.identus.walletsdk.apollo.ApolloImpl +import org.hyperledger.identus.walletsdk.configuration.Environment import org.hyperledger.identus.walletsdk.domain.models.CastorError +import org.hyperledger.identus.walletsdk.domain.models.CredentialType +import org.hyperledger.identus.walletsdk.domain.models.DID +import org.hyperledger.identus.walletsdk.domain.models.PolluxError +import org.hyperledger.identus.walletsdk.domain.models.PresentationClaims +import org.hyperledger.identus.walletsdk.domain.models.ProvableCredential +import org.hyperledger.identus.walletsdk.domain.models.Seed import org.hyperledger.identus.walletsdk.edgeagent.protocols.issueCredential.IssueCredential import org.hyperledger.identus.walletsdk.edgeagent.protocols.issueCredential.OfferCredential import org.hyperledger.identus.walletsdk.edgeagent.protocols.outOfBand.OutOfBandInvitation import org.hyperledger.identus.walletsdk.edgeagent.protocols.proofOfPresentation.RequestPresentation -import java.util.function.Consumer +import org.hyperledger.identus.walletsdk.pluto.PlutoBackupTask +import java.util.UUID +import kotlin.time.Duration.Companion.milliseconds +import kotlin.time.Duration.Companion.minutes class EdgeAgentWorkflow { private val logger = Logger.get() @@ -53,7 +68,6 @@ class EdgeAgentWorkflow { UseWalletSdk.proofOfRequestStackSize(), equalTo(1) ) - ) } @@ -62,9 +76,12 @@ class EdgeAgentWorkflow { UseWalletSdk.execute { val credentials = it.sdk.getAllCredentials().first() val credential = credentials.first() - val requestPresentationMessage = RequestPresentation.fromMessage(it.proofRequestStack.removeFirst()) - val presentation = it.sdk.preparePresentationForRequestProof(requestPresentationMessage, credential) - it.sdk.sendMessage(presentation.makeMessage()) + assertThat(credential).instanceOf(ProvableCredential::class) + if (credential is ProvableCredential) { + val requestPresentationMessage = RequestPresentation.fromMessage(it.proofRequestStack.removeFirst()) + val presentation = it.sdk.preparePresentationForRequestProof(requestPresentationMessage, credential) + it.sdk.sendMessage(presentation.makeMessage()) + } } ) } @@ -121,7 +138,7 @@ class EdgeAgentWorkflow { fun waitForCredentialRevocationMessage(edgeAgent: Actor, numberOfRevocation: Int) { edgeAgent.attemptsTo( - PollingWait.until( + PollingWait.with(2.minutes, 500.milliseconds).until( UseWalletSdk.revocationStackSize(), equalTo(numberOfRevocation) ) @@ -139,14 +156,133 @@ class EdgeAgentWorkflow { val revokedCredentials = credentials.filter { credential -> credential.revoked == true && revokedIdList.contains(credential.id) } - edgeAgent.attemptsTo( - Ensure.that( - "The number of revoked credentials matches the expected number", - Consumer { context -> - assertThat(revokedCredentials.size).isEqualTo(revokedRecordIdList.size) - } - ) - ) + assertThat(revokedCredentials.size).isEqualTo(revokedRecordIdList.size) + } + ) + } + + fun createBackup(edgeAgent: Actor) { + edgeAgent.attemptsTo( + UseWalletSdk.execute { sdkContext: SdkContext -> + val backup = sdkContext.sdk.backupWallet(PlutoBackupTask(sdkContext.sdk.pluto)) + val seed = sdkContext.sdk.seed + edgeAgent.remember("backup", backup) + edgeAgent.remember("seed", seed) + } + ) + } + + fun createANewWalletFromBackup(edgeAgent: Actor) { + val backup = edgeAgent.recall("backup") + val seed = edgeAgent.recall("seed") + val walletSdk = UseWalletSdk() + walletSdk.recoverWallet(seed, backup) + runBlocking { + walletSdk.tearDown() + } + } + + fun createNewWalletFromBackupWithWrongSeed(edgeAgent: Actor) { + val backup = edgeAgent.recall("backup") + val seed = ApolloImpl().createRandomSeed().seed + val walletSdk = UseWalletSdk() + runBlocking { + try { + walletSdk.recoverWallet(seed, backup) + fail("SDK should not be able to restore with wrong seed phrase.") + } catch (e: Exception) { + assertThat(e).isNotNull() + } + } + } + + fun createPeerDids(edgeAgent: Actor, numberOfDids: Int) { + edgeAgent.attemptsTo( + UseWalletSdk.execute { sdkContext -> + repeat(numberOfDids) { + val did = sdkContext.sdk.createNewPeerDID(updateMediator = true) + edgeAgent.remember("did", did) + } + } + ) + } + + fun createPrismDids(edgeAgent: Actor, numberOfDids: Int) { + edgeAgent.attemptsTo( + UseWalletSdk.execute { sdkContext -> + repeat(numberOfDids) { + sdkContext.sdk.createNewPrismDID() + } + } + ) + } + + fun backupAndRestoreToNewAgent(newAgent: Actor, originalAgent: Actor) { + val backup = originalAgent.recall("backup") + val seed = originalAgent.recall("seed") + val walletSdk = UseWalletSdk() + walletSdk.recoverWallet(seed, backup) + newAgent.whoCan(walletSdk).whoCan(CallAnApi.at(Environment.mediatorOobUrl)) + } + + fun copyAgentShouldMatchOriginalAgent(restoredEdgeAgent: Actor, originalEdgeAgent: Actor) { + val expectedCredentials = mutableListOf() + val expectedPeerDids = mutableListOf() + val expectedPrismDids = mutableListOf() + + originalEdgeAgent.attemptsTo( + UseWalletSdk.execute { sdkContext -> + expectedCredentials.addAll(sdkContext.sdk.getAllCredentials().first().map { it.id }) + expectedPeerDids.addAll(sdkContext.sdk.pluto.getAllPeerDIDs().first().map { it.did.toString() }) + expectedPrismDids.addAll(sdkContext.sdk.pluto.getAllPrismDIDs().first().map { it.did.toString() }) + } + ) + + restoredEdgeAgent.attemptsTo( + UseWalletSdk.execute { sdkContext -> + val actualCredentials = sdkContext.sdk.getAllCredentials().first().map { it.id } + val actualPeerDids = sdkContext.sdk.pluto.getAllPeerDIDs().first().map { it.did.toString() } + val actualPrismDids = sdkContext.sdk.pluto.getAllPrismDIDs().first().map { it.did.toString() } + + assertThat(actualCredentials.size).isEqualTo(expectedCredentials.size) + assertThat(actualCredentials.containsAll(expectedCredentials)).isTrue() + assertThat(actualPeerDids.size).isEqualTo(expectedPeerDids.size) + assertThat(actualPeerDids.containsAll(expectedPeerDids)).isTrue() + assertThat(actualPrismDids.size).isEqualTo(expectedPrismDids.size) + assertThat(actualPrismDids.containsAll(expectedPrismDids)).isTrue() + } + ) + } + + fun initiatePresentationRequest(type: CredentialType, edgeAgent: Actor, did: DID, claims: PresentationClaims) { + edgeAgent.attemptsTo( + UseWalletSdk.execute { + it.sdk.initiatePresentationRequest(type, did, claims, "", UUID.randomUUID().toString()) + } + ) + } + + fun waitForPresentationMessage(edgeAgent: Actor, numberOfMessages: Int = 1) { + edgeAgent.attemptsTo( + PollingWait.until( + UseWalletSdk.presentationStackSize(), + equalTo(numberOfMessages) + ) + ) + } + + fun verifyPresentation(edgeAgent: Actor, expected: Boolean = true, shouldBeRevoked: Boolean = false) { + edgeAgent.attemptsTo( + UseWalletSdk.execute { + val message = it.presentationStack.removeFirst() + try { + val isVerified = it.sdk.handlePresentation(message) + assertThat(isVerified).isEqualTo(expected) + } catch (e: PolluxError.VerificationUnsuccessful) { + assertThat(expected).isFalse() + assertThat(shouldBeRevoked).isTrue() + assertThat(e.message).contains("Provided credential is revoked") + } } ) } diff --git a/tests/end-to-end/src/test/resources/features/backup/Backup.feature b/tests/end-to-end/src/test/resources/features/backup/Backup.feature new file mode 100644 index 000000000..137873739 --- /dev/null +++ b/tests/end-to-end/src/test/resources/features/backup/Backup.feature @@ -0,0 +1,25 @@ +@backup +Feature: Backup + The Edge Agent should be able to create and restore a backup + + Scenario: Create and restore a backup + Given Edge Agent has created a backup + Then a new SDK can be restored from Edge Agent + + Scenario: Agent without a seed should not be able to restore the backup + Given Edge Agent has created a backup + Then a new SDK cannot be restored from Edge Agent with wrong seed + + Scenario: Restored backup should be functional + Given Cloud Agent is connected to Edge Agent + And Edge Agent has '1' jwt credentials issued by Cloud Agent + And Edge Agent creates '5' peer DIDs + And Edge Agent creates '3' prism DIDs + And Edge Agent has created a backup + Then a new Restored Agent is restored from Edge Agent + And Restored Agent should have the expected values from Edge Agent + And Edge Agent is dismissed + Given Cloud Agent is connected to Restored Agent + And Cloud Agent asks for present-proof + And Restored Agent sends the present-proof + Then Cloud Agent should see the present-proof is verified diff --git a/tests/end-to-end/src/test/resources/features/present-proof/AnoncredPresentProof.feature b/tests/end-to-end/src/test/resources/features/credential/anoncred/PresentProof.feature similarity index 54% rename from tests/end-to-end/src/test/resources/features/present-proof/AnoncredPresentProof.feature rename to tests/end-to-end/src/test/resources/features/credential/anoncred/PresentProof.feature index abd1149f6..a6735873f 100644 --- a/tests/end-to-end/src/test/resources/features/present-proof/AnoncredPresentProof.feature +++ b/tests/end-to-end/src/test/resources/features/credential/anoncred/PresentProof.feature @@ -8,3 +8,11 @@ Feature: Respond to anoncred request proof When Cloud Agent asks for present-proof for anoncred And Edge Agent sends the present-proof Then Cloud Agent should see the present-proof is verified + + @disabled + Scenario: Respond to a present request with a wrong credential + Given Cloud Agent is connected to Edge Agent + And Edge Agent has '1' anonymous credentials issued by Cloud Agent + When Cloud Agent asks for present-proof for anoncred with unexpected attributes + And Edge Agent sends the present-proof + Then Cloud Agent should see the present-proof is not verified diff --git a/tests/end-to-end/src/test/resources/features/credential/Anoncred.feature b/tests/end-to-end/src/test/resources/features/credential/anoncred/Receive.feature similarity index 100% rename from tests/end-to-end/src/test/resources/features/credential/Anoncred.feature rename to tests/end-to-end/src/test/resources/features/credential/anoncred/Receive.feature diff --git a/tests/end-to-end/src/test/resources/features/credential/anoncred/Verify.feature b/tests/end-to-end/src/test/resources/features/credential/anoncred/Verify.feature new file mode 100644 index 000000000..19a37ab63 --- /dev/null +++ b/tests/end-to-end/src/test/resources/features/credential/anoncred/Verify.feature @@ -0,0 +1,10 @@ +@anoncred @verification +Feature: Verify Anoncreds presentation + The Edge Agent should be able to receive a verifiable credential from Cloud Agent and then send a presentation to another edge agent who will verify it + + Scenario: Verify Anoncreds + Given Cloud Agent is connected to Edge Agent + And Edge Agent has '1' anonymous credentials issued by Cloud Agent + When Verifier Edge Agent request Edge Agent to verify the anonymous credential + When Edge Agent sends the verification proof + Then Verifier Edge Agent should see the verification proof is verified diff --git a/tests/end-to-end/src/test/resources/features/present-proof/JWTPresentProof.feature b/tests/end-to-end/src/test/resources/features/credential/jwt/PresentProof.feature similarity index 100% rename from tests/end-to-end/src/test/resources/features/present-proof/JWTPresentProof.feature rename to tests/end-to-end/src/test/resources/features/credential/jwt/PresentProof.feature diff --git a/tests/end-to-end/src/test/resources/features/credential/Credential.feature b/tests/end-to-end/src/test/resources/features/credential/jwt/Receive.feature similarity index 88% rename from tests/end-to-end/src/test/resources/features/credential/Credential.feature rename to tests/end-to-end/src/test/resources/features/credential/jwt/Receive.feature index 9754ac10e..58aee9e74 100644 --- a/tests/end-to-end/src/test/resources/features/credential/Credential.feature +++ b/tests/end-to-end/src/test/resources/features/credential/jwt/Receive.feature @@ -14,14 +14,14 @@ Feature: Receive verifiable credential Scenario: Receive multiple verifiable credentials sequentially Given Cloud Agent is connected to Edge Agent - When Edge Agent accepts 3 credential offer sequentially from Cloud Agent + When Edge Agent accepts 3 jwt credential offers sequentially from Cloud Agent Then Cloud Agent should see all credentials were accepted And Edge Agent wait to receive 3 issued credentials And Edge Agent process 3 issued credentials Scenario: Receive multiple verifiable credentials at once Given Cloud Agent is connected to Edge Agent - When Edge Agent accepts 3 credentials offer at once from Cloud Agent + When Edge Agent accepts 3 jwt credential offers at once from Cloud Agent Then Cloud Agent should see all credentials were accepted And Edge Agent wait to receive 3 issued credentials And Edge Agent process 3 issued credentials diff --git a/tests/end-to-end/src/test/resources/features/credential/RevokeJWT.feature b/tests/end-to-end/src/test/resources/features/credential/jwt/Revoke.feature similarity index 100% rename from tests/end-to-end/src/test/resources/features/credential/RevokeJWT.feature rename to tests/end-to-end/src/test/resources/features/credential/jwt/Revoke.feature diff --git a/tests/end-to-end/src/test/resources/features/credential/jwt/Verify.feature b/tests/end-to-end/src/test/resources/features/credential/jwt/Verify.feature new file mode 100644 index 000000000..685a44927 --- /dev/null +++ b/tests/end-to-end/src/test/resources/features/credential/jwt/Verify.feature @@ -0,0 +1,18 @@ +@jwt @verification +Feature: Verify JWT presentation + The Edge Agent should be able to receive a verifiable credential from Cloud Agent and then send a presentation to another edge agent who will verify it + + Scenario: Verify valid jwt credential + Given Cloud Agent is connected to Edge Agent + And Edge Agent has '1' jwt credentials issued by Cloud Agent + When Verifier Edge Agent request Edge Agent to verify the JWT credential + And Edge Agent sends the verification proof + Then Verifier Edge Agent should see the verification proof is verified + + Scenario: Verify revoked jwt credential + Given Cloud Agent is connected to Edge Agent + And Edge Agent has '1' jwt credentials issued by Cloud Agent + When Cloud Agent revokes '1' credentials + Then Verifier Edge Agent request Edge Agent to verify the JWT credential + When Edge Agent sends the verification proof + Then Verifier Edge Agent should see the verification proof was not verified due revocation