From 4af753aac144ba8470f90c00faaa1d0a573986ce Mon Sep 17 00:00:00 2001 From: patlo-iog Date: Tue, 14 Nov 2023 18:31:55 +0700 Subject: [PATCH] test: add wallet uma permission management tests (#786) Signed-off-by: Pat Losoponkul --- .../core/EntityPermissionManagementSpec.scala | 133 ++++++++++ ...cloakPermissionManagementServiceSpec.scala | 229 +++++++++++++----- .../service/WalletManagementServiceSpec.scala | 67 ++++- 3 files changed, 362 insertions(+), 67 deletions(-) create mode 100644 prism-agent/service/server/src/test/scala/io/iohk/atala/iam/authorization/core/EntityPermissionManagementSpec.scala diff --git a/prism-agent/service/server/src/test/scala/io/iohk/atala/iam/authorization/core/EntityPermissionManagementSpec.scala b/prism-agent/service/server/src/test/scala/io/iohk/atala/iam/authorization/core/EntityPermissionManagementSpec.scala new file mode 100644 index 0000000000..90c4658b6d --- /dev/null +++ b/prism-agent/service/server/src/test/scala/io/iohk/atala/iam/authorization/core/EntityPermissionManagementSpec.scala @@ -0,0 +1,133 @@ +package io.iohk.atala.iam.authorization.core + +import io.iohk.atala.agent.walletapi.crypto.ApolloSpecHelper +import io.iohk.atala.agent.walletapi.model.Entity +import io.iohk.atala.agent.walletapi.model.Wallet +import io.iohk.atala.agent.walletapi.service.EntityService +import io.iohk.atala.agent.walletapi.service.EntityServiceImpl +import io.iohk.atala.agent.walletapi.service.WalletManagementService +import io.iohk.atala.agent.walletapi.service.WalletManagementServiceImpl +import io.iohk.atala.agent.walletapi.sql.JdbcEntityRepository +import io.iohk.atala.agent.walletapi.sql.JdbcWalletNonSecretStorage +import io.iohk.atala.agent.walletapi.sql.JdbcWalletSecretStorage +import io.iohk.atala.iam.authorization.core.PermissionManagement.Error.ServiceError +import io.iohk.atala.iam.authorization.core.PermissionManagement.Error.WalletNotFoundById +import io.iohk.atala.shared.models.WalletAdministrationContext +import io.iohk.atala.shared.models.WalletId +import io.iohk.atala.sharedtest.containers.PostgresTestContainerSupport +import io.iohk.atala.test.container.DBTestUtils +import zio.* +import zio.test.* +import zio.test.Assertion.* + +object EntityPermissionManagementSpec extends ZIOSpecDefault, PostgresTestContainerSupport, ApolloSpecHelper { + + override def spec = { + val s = suite("EntityPermissionManagementSpec")( + successfulCasesSuite, + failureCasesSuite, + multitenantSuite + ) @@ TestAspect.before(DBTestUtils.runMigrationAgentDB) + + s.provide( + EntityPermissionManagementService.layer, + EntityServiceImpl.layer, + WalletManagementServiceImpl.layer, + JdbcEntityRepository.layer, + JdbcWalletNonSecretStorage.layer, + JdbcWalletSecretStorage.layer, + contextAwareTransactorLayer, + systemTransactorLayer, + pgContainerLayer, + apolloLayer + ) + }.provide(Runtime.removeDefaultLoggers) + + private val successfulCasesSuite = suite("Successful cases")( + test("grant wallet access to the user") { + for { + entityService <- ZIO.service[EntityService] + permissionService <- ZIO.service[PermissionManagement.Service[Entity]] + walletService <- ZIO.service[WalletManagementService] + wallet1 <- walletService + .createWallet(Wallet("test")) + .provide(ZLayer.succeed(WalletAdministrationContext.Admin())) + wallet2 <- walletService + .createWallet(Wallet("test2")) + .provide(ZLayer.succeed(WalletAdministrationContext.Admin())) + entity <- entityService + .create(Entity("alice", wallet1.id.toUUID)) + _ <- permissionService + .grantWalletToUser(wallet2.id, entity) + .provide(ZLayer.succeed(WalletAdministrationContext.Admin())) + entity <- entityService.getById(entity.id) + permissions <- permissionService + .listWalletPermissions(entity) + .provide(ZLayer.succeed(WalletAdministrationContext.Admin())) + } yield assert(permissions.head)(equalTo(wallet2.id)) + }, + ) + + private val failureCasesSuite = suite("Failure Cases")( + test("revoke wallet is not support") { + for { + entityService <- ZIO.service[EntityService] + permissionService <- ZIO.service[PermissionManagement.Service[Entity]] + walletService <- ZIO.service[WalletManagementService] + wallet1 <- walletService + .createWallet(Wallet("test")) + .provide(ZLayer.succeed(WalletAdministrationContext.Admin())) + entity <- entityService + .create(Entity("alice", wallet1.id.toUUID)) + exit <- permissionService + .revokeWalletFromUser(wallet1.id, entity) + .provide(ZLayer.succeed(WalletAdministrationContext.Admin())) + .exit + } yield assert(exit)(fails(isSubtype[ServiceError](anything))) + } + ) + + private val multitenantSuite = suite("multi-tenant cases")( + test("grant wallet access to the user by self-service") { + val walletId1 = WalletId.random + val walletId2 = WalletId.random + for { + entityService <- ZIO.service[EntityService] + permissionService <- ZIO.service[PermissionManagement.Service[Entity]] + walletService <- ZIO.service[WalletManagementService] + wallet1 <- walletService + .createWallet(Wallet("test", walletId1)) + .provide(ZLayer.succeed(WalletAdministrationContext.Admin())) + wallet2 <- walletService + .createWallet(Wallet("test2", walletId2)) + .provide(ZLayer.succeed(WalletAdministrationContext.Admin())) + entity <- entityService.create(Entity("alice", wallet1.id.toUUID)) + _ <- permissionService + .grantWalletToUser(wallet2.id, entity) + .provide(ZLayer.succeed(WalletAdministrationContext.SelfService(Seq(walletId2)))) + entity <- entityService.getById(entity.id) + permissions <- permissionService + .listWalletPermissions(entity) + .provide(ZLayer.succeed(WalletAdministrationContext.Admin())) + } yield assert(permissions.head)(equalTo(wallet2.id)) + }, + test("grant wallet access to non-permitted wallet by self-service is not allowed") { + val walletId1 = WalletId.random + val walletId2 = WalletId.random + for { + entityService <- ZIO.service[EntityService] + permissionService <- ZIO.service[PermissionManagement.Service[Entity]] + walletService <- ZIO.service[WalletManagementService] + wallet1 <- walletService + .createWallet(Wallet("test", walletId1)) + .provide(ZLayer.succeed(WalletAdministrationContext.Admin())) + entity <- entityService.create(Entity("alice", wallet1.id.toUUID)) + exit <- permissionService + .grantWalletToUser(walletId2, entity) + .provide(ZLayer.succeed(WalletAdministrationContext.SelfService(Seq(walletId1)))) + .exit + } yield assert(exit)(fails(isSubtype[WalletNotFoundById](anything))) + }, + ) + +} diff --git a/prism-agent/service/server/src/test/scala/io/iohk/atala/iam/authorization/keycloak/admin/KeycloakPermissionManagementServiceSpec.scala b/prism-agent/service/server/src/test/scala/io/iohk/atala/iam/authorization/keycloak/admin/KeycloakPermissionManagementServiceSpec.scala index beb91ce81e..8b71fda85a 100644 --- a/prism-agent/service/server/src/test/scala/io/iohk/atala/iam/authorization/keycloak/admin/KeycloakPermissionManagementServiceSpec.scala +++ b/prism-agent/service/server/src/test/scala/io/iohk/atala/iam/authorization/keycloak/admin/KeycloakPermissionManagementServiceSpec.scala @@ -1,8 +1,11 @@ package io.iohk.atala.iam.authorization.keycloak.admin -import io.iohk.atala.agent.walletapi.model.{Wallet, WalletSeed} +import io.iohk.atala.agent.walletapi.crypto.ApolloSpecHelper +import io.iohk.atala.agent.walletapi.model.Wallet +import io.iohk.atala.agent.walletapi.service.WalletManagementServiceImpl import io.iohk.atala.agent.walletapi.service.{WalletManagementService, WalletManagementServiceError} -import io.iohk.atala.event.notification.EventNotificationConfig +import io.iohk.atala.agent.walletapi.sql.JdbcWalletNonSecretStorage +import io.iohk.atala.agent.walletapi.sql.JdbcWalletSecretStorage import io.iohk.atala.iam.authentication.AuthenticationError.ResourceNotPermitted import io.iohk.atala.iam.authentication.oidc.{ KeycloakAuthenticator, @@ -13,9 +16,12 @@ import io.iohk.atala.iam.authentication.oidc.{ } import io.iohk.atala.iam.authorization.core.PermissionManagement import io.iohk.atala.iam.authorization.core.PermissionManagement.Error.WalletNotFoundById +import io.iohk.atala.iam.authorization.core.PermissionManagement.Error.UnexpectedError import io.iohk.atala.shared.models.WalletAdministrationContext import io.iohk.atala.shared.models.{WalletAccessContext, WalletId} +import io.iohk.atala.sharedtest.containers.PostgresTestContainerSupport import io.iohk.atala.sharedtest.containers.{KeycloakContainerCustom, KeycloakTestContainerSupport} +import io.iohk.atala.test.container.DBTestUtils import zio.* import zio.ZIO.* import zio.http.Client @@ -28,15 +34,36 @@ import java.util.UUID object KeycloakPermissionManagementServiceSpec extends ZIOSpecDefault with KeycloakTestContainerSupport - with KeycloakConfigUtils { + with KeycloakConfigUtils + with PostgresTestContainerSupport + with ApolloSpecHelper { - override def spec = suite("KeycloakPermissionManagementServiceSpec")( - successfulCasesSuite, - failureCasesSuite - ) - .provide(Runtime.removeDefaultLoggers) + override def spec = { + val s = suite("KeycloakPermissionManagementServiceSpec")( + successfulCasesSuite, + failureCasesSuite, + multitenantSuite + ) @@ sequential @@ TestAspect.before(DBTestUtils.runMigrationAgentDB) + + s.provide( + Client.default, + keycloakContainerLayer, + keycloakAdminConfigLayer, + KeycloakAdmin.layer, + KeycloakPermissionManagementService.layer, + KeycloakAuthenticatorImpl.layer, + ZLayer.fromZIO(initializeClient) >>> KeycloakClientImpl.authzClientLayer >+> KeycloakClientImpl.layer, + keycloakConfigLayer(), + WalletManagementServiceImpl.layer, + JdbcWalletNonSecretStorage.layer, + JdbcWalletSecretStorage.layer, + contextAwareTransactorLayer, + pgContainerLayer, + apolloLayer + ).provide(Runtime.removeDefaultLoggers) + } - val successfulCasesSuite = suite("Successful Cases")( + private val successfulCasesSuite = suite("Successful Cases")( test("grant wallet access to the user") { for { client <- ZIO.service[KeycloakClient] @@ -90,73 +117,149 @@ object KeycloakPermissionManagementServiceSpec } yield assert(permittedWallet2)(fails(isSubtype[ResourceNotPermitted](anything))) } - ).provide( - Client.default, - keycloakContainerLayer, - keycloakAdminConfigLayer, - KeycloakAdmin.layer, - KeycloakPermissionManagementService.layer, - WalletManagementServiceStub.layer, - KeycloakAuthenticatorImpl.layer, - ZLayer.fromZIO(initializeClient) >>> KeycloakClientImpl.authzClientLayer >+> KeycloakClientImpl.layer, - keycloakConfigLayer(), - ZLayer.succeed(WalletAdministrationContext.Admin()) - ) @@ sequential - - val failureCasesSuite = suite("Failure Cases Suite")( + ).provideSomeLayer(ZLayer.succeed(WalletAdministrationContext.Admin())) + + private val failureCasesSuite = suite("Failure Cases Suite")( test("grant wallet access to the user with invalid wallet id") { for { permissionService <- ZIO.service[PermissionManagement.Service[KeycloakEntity]] entity = KeycloakEntity(id = UUID.randomUUID()) exit <- permissionService.grantWalletToUser(WalletId.random, entity).exit } yield assert(exit)(fails(isSubtype[WalletNotFoundById](anything))) + }, + test("grant wallet access to the user with invalid user id") { + for { + client <- ZIO.service[KeycloakClient] + authenticator <- ZIO.service[KeycloakAuthenticator] + walletService <- ZIO.service[WalletManagementService] + wallet <- walletService.createWallet(Wallet("test_1")) + entity = KeycloakEntity(id = UUID.randomUUID()) + permissionService <- ZIO.service[PermissionManagement.Service[KeycloakEntity]] + exit <- permissionService.grantWalletToUser(wallet.id, entity).exit + } yield assert(exit)(fails(isSubtype[UnexpectedError](anything))) } - ).provide( - Client.default, - keycloakContainerLayer, - keycloakAdminConfigLayer, - KeycloakAdmin.layer, - KeycloakPermissionManagementService.layer, - WalletManagementServiceStub.layer, - ZLayer.fromZIO(initializeClient) >>> KeycloakClientImpl.authzClientLayer >+> KeycloakClientImpl.layer, - keycloakConfigLayer(), - ZLayer.succeed(WalletAdministrationContext.Admin()) - ) @@ sequential -} + ).provideSomeLayer(ZLayer.succeed(WalletAdministrationContext.Admin())) -class WalletManagementServiceStub extends WalletManagementService { - private var wallets: Map[WalletId, Wallet] = Map.empty - override def createWallet(wallet: Wallet, seed: Option[WalletSeed]): IO[WalletManagementServiceError, Wallet] = { - val wallet = Wallet(name = "test") - wallets = wallets + (wallet.id -> wallet) - ZIO.succeed(wallet) - } + private val multitenantSuite = suite("multi-tenant cases")( + test("grant wallet access to the user by self-service") { + val walletId = WalletId.random + for { + client <- ZIO.service[KeycloakClient] + authenticator <- ZIO.service[KeycloakAuthenticator] + walletService <- ZIO.service[WalletManagementService] - override def getWallet(walletId: WalletId): IO[WalletManagementServiceError, Option[Wallet]] = { - ZIO.succeed(wallets.get(walletId)) - } + wallet <- walletService + .createWallet(Wallet("test_1", walletId)) + .provide(ZLayer.succeed(WalletAdministrationContext.Admin())) - override def getWallets(walletIds: Seq[WalletId]): IO[WalletManagementServiceError, Seq[Wallet]] = { - ZIO.succeed(wallets.filter(w => walletIds.contains(w._1)).values.toSeq) - } + randomId = UUID.randomUUID().toString + username = "user_" + randomId + password = randomId + user <- createUser(username = username, password = password) + entity = KeycloakEntity(id = UUID.fromString(user.getId)) - override def listWallets( - offset: Option[RuntimeFlags], - limit: Option[RuntimeFlags] - ): IO[WalletManagementServiceError, (Seq[Wallet], RuntimeFlags)] = ??? + permissionService <- ZIO.service[PermissionManagement.Service[KeycloakEntity]] + _ <- permissionService + .grantWalletToUser(wallet.id, entity) + .provideSomeLayer(ZLayer.succeed(WalletAdministrationContext.SelfService(Seq(walletId)))) - override def listWalletNotifications - : ZIO[WalletAccessContext, WalletManagementServiceError, Seq[EventNotificationConfig]] = ??? + token <- client.getAccessToken(username, password).map(_.access_token) - override def createWalletNotification( - config: EventNotificationConfig - ): ZIO[WalletAccessContext, WalletManagementServiceError, EventNotificationConfig] = ??? + entity <- authenticator.authenticate(token) + permittedWallet <- authenticator.authorize(entity) + } yield assert(wallet.id)(equalTo(permittedWallet.walletId)) + }, + test("revoke wallet access from the user by self-service") { + for { + client <- ZIO.service[KeycloakClient] + authenticator <- ZIO.service[KeycloakAuthenticator] + walletService <- ZIO.service[WalletManagementService] - override def deleteWalletNotification( - id: _root_.java.util.UUID - ): ZIO[WalletAccessContext, WalletManagementServiceError, Unit] = ??? -} + wallet <- walletService + .createWallet(Wallet("test_2")) + .provideSomeLayer(ZLayer.succeed(WalletAdministrationContext.Admin())) -object WalletManagementServiceStub { - val layer = ZLayer.succeed(new WalletManagementServiceStub) + randomId = UUID.randomUUID().toString + username = "user_" + randomId + password = randomId + user <- createUser(username = username, password = password) + entity = KeycloakEntity(id = UUID.fromString(user.getId)) + + permissionService <- ZIO.service[PermissionManagement.Service[KeycloakEntity]] + _ <- permissionService + .grantWalletToUser(wallet.id, entity) + .provideSomeLayer(ZLayer.succeed(WalletAdministrationContext.Admin())) + + token <- client.getAccessToken(username, password).map(_.access_token) + + entity <- authenticator.authenticate(token) + permittedWallet <- authenticator.authorize(entity) + + _ <- permissionService + .revokeWalletFromUser(wallet.id, entity) + .provideSomeLayer(ZLayer.succeed(WalletAdministrationContext.SelfService(Seq(wallet.id)))) + + token2 <- client.getAccessToken(username, password).map(_.access_token) + entity2 <- authenticator.authenticate(token) + permittedWallet2 <- authenticator.authorize(entity).exit + + } yield assert(permittedWallet2)(fails(isSubtype[ResourceNotPermitted](anything))) + }, + test("grant wallet access to non-permitted wallet by self-service is not allowed") { + val walletId = WalletId.random + for { + client <- ZIO.service[KeycloakClient] + authenticator <- ZIO.service[KeycloakAuthenticator] + walletService <- ZIO.service[WalletManagementService] + + wallet <- walletService + .createWallet(Wallet("test_1", walletId)) + .provide(ZLayer.succeed(WalletAdministrationContext.Admin())) + + randomId = UUID.randomUUID().toString + username = "user_" + randomId + password = randomId + user <- createUser(username = username, password = password) + entity = KeycloakEntity(id = UUID.fromString(user.getId)) + + permissionService <- ZIO.service[PermissionManagement.Service[KeycloakEntity]] + exit <- permissionService + .grantWalletToUser(WalletId.random, entity) + .provideSomeLayer(ZLayer.succeed(WalletAdministrationContext.SelfService(Seq(walletId)))) + .exit + } yield assert(exit)(fails(isSubtype[WalletNotFoundById](anything))) + }, + test("revoke wallet access from non-permitted wallet by self-service is not allowed") { + for { + client <- ZIO.service[KeycloakClient] + authenticator <- ZIO.service[KeycloakAuthenticator] + walletService <- ZIO.service[WalletManagementService] + + wallet <- walletService + .createWallet(Wallet("test_2")) + .provideSomeLayer(ZLayer.succeed(WalletAdministrationContext.Admin())) + + randomId = UUID.randomUUID().toString + username = "user_" + randomId + password = randomId + user <- createUser(username = username, password = password) + entity = KeycloakEntity(id = UUID.fromString(user.getId)) + + permissionService <- ZIO.service[PermissionManagement.Service[KeycloakEntity]] + _ <- permissionService + .grantWalletToUser(wallet.id, entity) + .provideSomeLayer(ZLayer.succeed(WalletAdministrationContext.Admin())) + + token <- client.getAccessToken(username, password).map(_.access_token) + + entity <- authenticator.authenticate(token) + permittedWallet <- authenticator.authorize(entity) + + exit <- permissionService + .revokeWalletFromUser(wallet.id, entity) + .provideSomeLayer(ZLayer.succeed(WalletAdministrationContext.SelfService(Seq(WalletId.random)))) + .exit + } yield assert(exit)(fails(isSubtype[WalletNotFoundById](anything))) + } + ) } diff --git a/prism-agent/service/wallet-api/src/test/scala/io/iohk/atala/agent/walletapi/service/WalletManagementServiceSpec.scala b/prism-agent/service/wallet-api/src/test/scala/io/iohk/atala/agent/walletapi/service/WalletManagementServiceSpec.scala index 0d1bda9ebc..c7c08e3c06 100644 --- a/prism-agent/service/wallet-api/src/test/scala/io/iohk/atala/agent/walletapi/service/WalletManagementServiceSpec.scala +++ b/prism-agent/service/wallet-api/src/test/scala/io/iohk/atala/agent/walletapi/service/WalletManagementServiceSpec.scala @@ -4,6 +4,7 @@ import io.iohk.atala.agent.walletapi.crypto.ApolloSpecHelper import io.iohk.atala.agent.walletapi.model.Wallet import io.iohk.atala.agent.walletapi.model.WalletSeed import io.iohk.atala.agent.walletapi.service.WalletManagementServiceError.DuplicatedWalletSeed +import io.iohk.atala.agent.walletapi.service.WalletManagementServiceError.TooManyPermittedWallet import io.iohk.atala.agent.walletapi.sql.JdbcWalletNonSecretStorage import io.iohk.atala.agent.walletapi.sql.JdbcWalletSecretStorage import io.iohk.atala.agent.walletapi.storage.WalletSecretStorage @@ -27,8 +28,9 @@ object WalletManagementServiceSpec override def spec = { def testSuite(name: String) = suite(name)( - createWalletSpec, - getWalletSpec, + createWalletSpec.provideSomeLayer(ZLayer.succeed(WalletAdministrationContext.Admin())), + getWalletSpec.provideSomeLayer(ZLayer.succeed(WalletAdministrationContext.Admin())), + multitenantSpec ) @@ TestAspect.before(DBTestUtils.runMigrationAgentDB) @@ TestAspect.sequential val suite1 = testSuite("jdbc as secret storage") @@ -39,7 +41,6 @@ object WalletManagementServiceSpec contextAwareTransactorLayer, pgContainerLayer, apolloLayer, - ZLayer.succeed(WalletAdministrationContext.Admin()) ) val suite2 = testSuite("vault as secret storage") @@ -51,7 +52,6 @@ object WalletManagementServiceSpec pgContainerLayer, apolloLayer, vaultKvClientLayer, - ZLayer.succeed(WalletAdministrationContext.Admin()) ) suite("WalletManagementService")(suite1, suite2) @@ -133,6 +133,65 @@ object WalletManagementServiceSpec _ <- svc.createWallet(Wallet("wallet-1"), Some(seed)) exit <- svc.createWallet(Wallet("wallet-2"), Some(seed)).exit } yield assert(exit)(fails(isSubtype[DuplicatedWalletSeed](anything))) + }, + test("cannot create new wallet for self-service if already have permitted wallet") { + val walletId = WalletId.random + for { + svc <- ZIO.service[WalletManagementService] + exit <- svc + .createWallet(Wallet("wallet-1")) + .provide(ZLayer.succeed(WalletAdministrationContext.SelfService(Seq(walletId)))) + .exit + } yield assert(exit)(fails(isSubtype[TooManyPermittedWallet](anything))) + } + ) + + private def multitenantSpec = suite("multitenant spec")( + test("get all wallets for admin") { + for { + svc <- ZIO.service[WalletManagementService] + wallet1 <- svc.createWallet(Wallet("wallet-1")).provide(ZLayer.succeed(WalletAdministrationContext.Admin())) + wallet2 <- svc.createWallet(Wallet("wallet-2")).provide(ZLayer.succeed(WalletAdministrationContext.Admin())) + wallet3 <- svc.createWallet(Wallet("wallet-3")).provide(ZLayer.succeed(WalletAdministrationContext.Admin())) + walletIds = Seq(wallet1, wallet2, wallet3).map(_.id) + wallets1 <- svc.getWallets(walletIds).provide(ZLayer.succeed(WalletAdministrationContext.Admin())) + wallets2 <- svc + .listWallets() + .map(_._1) + .provide(ZLayer.succeed(WalletAdministrationContext.Admin())) + } yield assert(wallets1.map(_.id))(equalTo(walletIds)) && + assert(wallets2.map(_.id))(equalTo(walletIds)) + }, + test("get only permitted wallet for self-service") { + for { + svc <- ZIO.service[WalletManagementService] + wallet1 <- svc.createWallet(Wallet("wallet-1")).provide(ZLayer.succeed(WalletAdministrationContext.Admin())) + wallet2 <- svc.createWallet(Wallet("wallet-2")).provide(ZLayer.succeed(WalletAdministrationContext.Admin())) + wallet3 <- svc.createWallet(Wallet("wallet-3")).provide(ZLayer.succeed(WalletAdministrationContext.Admin())) + walletIds = Seq(wallet1, wallet2, wallet3).map(_.id) + permittedWalletIds = Seq(wallet1, wallet2).map(_.id) + wallets1 <- svc + .getWallets(walletIds) + .provide(ZLayer.succeed(WalletAdministrationContext.SelfService(permittedWalletIds))) + wallets2 <- svc + .listWallets() + .map(_._1) + .provide(ZLayer.succeed(WalletAdministrationContext.SelfService(permittedWalletIds))) + } yield assert(wallets1.map(_.id))(equalTo(permittedWalletIds)) && + assert(wallets2.map(_.id))(equalTo(permittedWalletIds)) + }, + test("cannot get wallet by self-service that is not permitted") { + for { + svc <- ZIO.service[WalletManagementService] + wallet1 <- svc.createWallet(Wallet("wallet-1")).provide(ZLayer.succeed(WalletAdministrationContext.Admin())) + wallet2 <- svc.createWallet(Wallet("wallet-2")).provide(ZLayer.succeed(WalletAdministrationContext.Admin())) + wallet3 <- svc.createWallet(Wallet("wallet-3")).provide(ZLayer.succeed(WalletAdministrationContext.Admin())) + walletIds = Seq(wallet1, wallet2, wallet3).map(_.id) + permittedWalletIds = Seq(wallet1, wallet2).map(_.id) + maybeWallet3 <- svc + .getWallet(wallet3.id) + .provide(ZLayer.succeed(WalletAdministrationContext.SelfService(permittedWalletIds))) + } yield assert(maybeWallet3)(isNone) } )