Skip to content

Commit

Permalink
fix: entity create and update operation failures if the walletId does… (
Browse files Browse the repository at this point in the history
#718)

Signed-off-by: Yurii Shynbuiev <yurii.shynbuiev@iohk.io>
  • Loading branch information
yshyn-iohk committed Sep 15, 2023
1 parent 8bea26e commit 4fe6677
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ object EntityEndpoints {
.securityIn(adminApiKeyHeader)
.in(extractFromRequest[RequestContext](RequestContext.apply))
.in(
"iam" / "entities" / path[UUID]("id") / "walletId" // .description(EntityResponse.annotations.id.description)
"iam" / "entities" / path[UUID]("id") / "walletId"
)
.in(
jsonBody[UpdateEntityWalletIdRequest]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ object EntityController {
ErrorResponse.notFound(detail = Option(message))
case EntityServiceError.EntityAlreadyExists(id, message) =>
ErrorResponse.badRequest(detail = Option(message))
case ewnf: EntityServiceError.EntityWalletNotFound =>
ErrorResponse.badRequest(detail = Option(ewnf.message))
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,7 @@ object EntityServiceError {
final case class EntityNotFound(id: UUID, message: String) extends EntityServiceError
final case class EntityAlreadyExists(id: UUID, message: String) extends EntityServiceError
final case class EntityStorageError(message: String) extends EntityServiceError
final case class EntityWalletNotFound(entityId: UUID, walletId: UUID) extends EntityServiceError {
override def message: String = s"Wallet with id:$walletId not found for entity with id:$entityId"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import io.iohk.atala.agent.walletapi.model.error.EntityServiceError
import io.iohk.atala.agent.walletapi.model.error.EntityServiceError.{
EntityAlreadyExists,
EntityNotFound,
EntityStorageError
EntityStorageError,
EntityWalletNotFound
}
import org.postgresql.util.PSQLException
import zio.*
Expand All @@ -26,7 +27,12 @@ class JdbcEntityRepository(xa: Transactor[Task]) extends EntityRepository {
case sqlException: PSQLException
if sqlException.getMessage.contains("duplicate key value violates unique constraint") =>
EntityAlreadyExists(entity.id, sqlException.getMessage)
case other: Throwable => EntityStorageError(other.getMessage)
case sqlException: PSQLException
if sqlException.getMessage
.contains("violates foreign key constraint \"entity_wallet_id_fkey\"") =>
EntityWalletNotFound(entity.id, entity.walletId)
case other: Throwable =>
EntityStorageError(other.getMessage)
}
.map(db2model)
}
Expand Down Expand Up @@ -61,7 +67,13 @@ class JdbcEntityRepository(xa: Transactor[Task]) extends EntityRepository {
.updateWallet(entityId, walletId)
.transact(xa)
.logError(s"Update entity walletId=$walletId by id=$entityId failed")
.mapError(throwable => EntityStorageError(throwable.getMessage))
.mapError {
case sqlException: PSQLException
if sqlException.getMessage
.contains("violates foreign key constraint \"entity_wallet_id_fkey\"") =>
EntityWalletNotFound(entityId, walletId)
case other: Throwable => EntityStorageError(other.getMessage)
}
.flatMap(updatedCount =>
if updatedCount == 1 then ZIO.unit
else ZIO.fail(EntityNotFound(entityId, s"Update entity walletId=$walletId by id=$entityId failed"))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package io.iohk.atala.agent.walletapi.storage

import io.iohk.atala.agent.walletapi.model.error.EntityServiceError.{EntityAlreadyExists, EntityNotFound}
import io.iohk.atala.agent.walletapi.model.error.EntityServiceError.{
EntityAlreadyExists,
EntityNotFound,
EntityWalletNotFound
}
import io.iohk.atala.agent.walletapi.model.{Entity, Wallet}
import io.iohk.atala.agent.walletapi.sql.{EntityRepository, JdbcEntityRepository, JdbcWalletNonSecretStorage}
import io.iohk.atala.agent.walletapi.storage.JdbcWalletNonSecretStorageSpec.{
Expand All @@ -14,7 +18,6 @@ import zio.*
import zio.test.*
import zio.test.Assertion.*

import java.time.Instant
import java.util.UUID

object JdbcEntityRepositorySpec extends ZIOSpecDefault, PostgresTestContainerSupport {
Expand All @@ -31,7 +34,7 @@ object JdbcEntityRepositorySpec extends ZIOSpecDefault, PostgresTestContainerSup
)
} yield entity

private def createWalletForEntity(entity: Entity) = {
private def createAndStoreWallet(entity: Entity) = {
for {
storage <- ZIO.service[WalletNonSecretStorage]
wallet <- storage.createWallet(Wallet("test", WalletId.fromUUID(entity.walletId)))
Expand Down Expand Up @@ -62,7 +65,7 @@ object JdbcEntityRepositorySpec extends ZIOSpecDefault, PostgresTestContainerSup
test("get all entities - single entity") {
for {
in <- createRandomEntity
_ <- createWalletForEntity(in)
_ <- createAndStoreWallet(in)
_ <- EntityRepository.insert(in)
entities <- EntityRepository.getAll(0, 100)
_ <- EntityRepository.delete(in.id)
Expand All @@ -74,7 +77,7 @@ object JdbcEntityRepositorySpec extends ZIOSpecDefault, PostgresTestContainerSup
entities <- ZIO.foreach(1 to 100) { _ =>
for {
e <- createRandomEntity
_ <- createWalletForEntity(e)
_ <- createAndStoreWallet(e)
_ <- EntityRepository.insert(e)
} yield e
}
Expand All @@ -87,7 +90,7 @@ object JdbcEntityRepositorySpec extends ZIOSpecDefault, PostgresTestContainerSup
test("update the Entity name") {
for {
in <- createRandomEntity
_ <- createWalletForEntity(in)
_ <- createAndStoreWallet(in)
out <- EntityRepository.insert(in)
_ <- EntityRepository.updateName(in.id, "newName")
updated <- EntityRepository.getById(in.id)
Expand All @@ -112,7 +115,7 @@ object JdbcEntityRepositorySpec extends ZIOSpecDefault, PostgresTestContainerSup
_ <- random.setSeed(52L)
walletId <- random.nextUUID
in <- createRandomEntity
_ <- createWalletForEntity(in)
_ <- createAndStoreWallet(in)
storage <- ZIO.service[WalletNonSecretStorage]
_ <- storage.createWallet(Wallet("another wallet", WalletId.fromUUID(walletId)))
out <- EntityRepository.insert(in)
Expand All @@ -136,13 +139,36 @@ object JdbcEntityRepositorySpec extends ZIOSpecDefault, PostgresTestContainerSup
)
)
},
test("update the Entity walletId by the walletId that does not exist") {
for {
random <- ZIO.random
_ <- random.setSeed(56L)
randomWalletId <- random.nextUUID

in <- createRandomEntity
wallet <- createAndStoreWallet(in)
entity <- EntityRepository.insert(in)

updated <- EntityRepository.updateWallet(entity.id, randomWalletId).exit
} yield assert(updated)(
fails(
isSubtype[EntityWalletNotFound](
hasField(
"message",
_.message,
containsString(s"Wallet with id:$randomWalletId not found for entity with id:${in.id}")
)
)
)
)
},
)

private val getEntitySpec = suite("get the Entity spec")(
test("create and get the Entity by id") {
for {
in <- createRandomEntity
_ <- createWalletForEntity(in)
_ <- createAndStoreWallet(in)
out <- EntityRepository.insert(in)
get <- EntityRepository.getById(in.id)
} yield assert(out)(equalTo(in)) &&
Expand All @@ -164,7 +190,7 @@ object JdbcEntityRepositorySpec extends ZIOSpecDefault, PostgresTestContainerSup
test("create the Entity with random id and default wallet id") {
for {
in <- ZIO.succeed(Entity("test"))
_ <- createWalletForEntity(in)
_ <- createAndStoreWallet(in)
out <- EntityRepository.insert(in)
} yield assert(out)(equalTo(in)) && assert(out.walletId)(equalTo(Entity.ZeroWalletId))
},
Expand All @@ -174,14 +200,14 @@ object JdbcEntityRepositorySpec extends ZIOSpecDefault, PostgresTestContainerSup
_ <- random.setSeed(42L)
walletId <- random.nextUUID
in <- ZIO.succeed(Entity(name = "test", walletId = walletId))
_ <- createWalletForEntity(in)
_ <- createAndStoreWallet(in)
out <- EntityRepository.insert(in)
} yield assert(out)(equalTo(in)) && assert(out.walletId)(equalTo(walletId))
},
test("create the Entity with id and wallet id") {
for {
in <- createRandomEntity
_ <- createWalletForEntity(in)
_ <- createAndStoreWallet(in)
out <- EntityRepository.insert(in)
} yield assert(out)(equalTo(in)) &&
assert(out.walletId)(equalTo(in.walletId)) &&
Expand All @@ -192,12 +218,29 @@ object JdbcEntityRepositorySpec extends ZIOSpecDefault, PostgresTestContainerSup
test("create the Entity with the same id") {
for {
in <- createRandomEntity
_ <- createWalletForEntity(in)
_ <- createAndStoreWallet(in)
out <- EntityRepository.insert(in)
exit <- EntityRepository.insert(in).exit
} yield assert(exit)(
fails(isSubtype[EntityAlreadyExists](hasField("message", _.message, containsString("duplicate key value"))))
)
},
test("create the Entity with the walletId that doesn't exist") {
for {
in <- createRandomEntity
// _ <- createAndStoreWallet(in) - the wallet is not created
exit <- EntityRepository.insert(in).exit
} yield assert(exit)(
fails(
isSubtype[EntityWalletNotFound](
hasField(
"message",
_.message,
containsString(s"Wallet with id:${in.walletId} not found for entity with id:${in.id}")
)
)
)
)
}
)

Expand Down

0 comments on commit 4fe6677

Please sign in to comment.