From 96393094264a33c9fa85f08b533c7f68caadb119 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Mili=C4=87?= Date: Thu, 28 Nov 2024 09:08:13 +0100 Subject: [PATCH] feature/Add endpoint getAccountsHeldByUser v5.1.0 --- .../main/scala/code/api/util/NewStyle.scala | 5 ++ .../scala/code/api/v5_1_0/APIMethods510.scala | 47 +++++++++++++++++++ .../scala/code/bankconnectors/Connector.scala | 1 + .../bankconnectors/LocalMappedConnector.scala | 5 ++ .../scala/code/api/v5_1_0/AccountTest.scala | 30 ++++++++++-- 5 files changed, 83 insertions(+), 5 deletions(-) diff --git a/obp-api/src/main/scala/code/api/util/NewStyle.scala b/obp-api/src/main/scala/code/api/util/NewStyle.scala index 3b1feb758..4ac213046 100644 --- a/obp-api/src/main/scala/code/api/util/NewStyle.scala +++ b/obp-api/src/main/scala/code/api/util/NewStyle.scala @@ -2537,6 +2537,11 @@ object NewStyle extends MdcLoggable{ i => (unboxFullOrFail(i._1, callContext, s"$InvalidConnectorResponse Cannot ${nameOf(getAccountsHeld(bankId, user, callContext))} in the backend. ", 400), i._2) } } + def getAccountsHeldByUser(user: User, callContext: Option[CallContext]): OBPReturnType[List[BankIdAccountId]] = { + Connector.connector.vend.getAccountsHeldByUser(user, callContext) map { + i => (unboxFullOrFail(i._1, callContext, s"$InvalidConnectorResponse Cannot ${nameOf(getAccountsHeldByUser(user, callContext))} in the backend. ", 400), i._2) + } + } def createOrUpdateKycCheck(bankId: String, customerId: String, diff --git a/obp-api/src/main/scala/code/api/v5_1_0/APIMethods510.scala b/obp-api/src/main/scala/code/api/v5_1_0/APIMethods510.scala index 871a9b1e6..d3de66c21 100644 --- a/obp-api/src/main/scala/code/api/v5_1_0/APIMethods510.scala +++ b/obp-api/src/main/scala/code/api/v5_1_0/APIMethods510.scala @@ -672,6 +672,53 @@ trait APIMethods510 { } } + staticResourceDocs += ResourceDoc( + getAccountsHeldByUser, + implementedInApiVersion, + nameOf(getAccountsHeldByUser), + "GET", + "/users/USER_ID/accounts-held", + "Get Accounts Held By User", + s"""Get Accounts held by the User if even the User has not been assigned the owner View yet. + | + |Can be used to onboard the account to the API - since all other account and transaction endpoints require views to be assigned. + | + |${accountTypeFilterText("/users/USER_ID/accounts-held")} + | + | + | + """.stripMargin, + EmptyBody, + coreAccountsHeldJsonV300, + List( + $UserNotLoggedIn, + $BankNotFound, + UserNotFoundByUserId, + UnknownError + ), + List(apiTagAccount), + Some(List(canGetAccountsHeldAtAnyBank)) + ) + + lazy val getAccountsHeldByUser: OBPEndpoint = { + case "users" :: userId :: "accounts-held" :: Nil JsonGet req => { + cc => + implicit val ec = EndpointContext(Some(cc)) + for { + (u, callContext) <- NewStyle.function.getUserByUserId(userId, cc.callContext) + (availableAccounts, callContext) <- NewStyle.function.getAccountsHeldByUser(u, callContext) + (accounts, callContext) <- NewStyle.function.getBankAccountsHeldFuture(availableAccounts, callContext) + + accountHelds <- getFilteredCoreAccounts(availableAccounts, req, callContext).map { it => + val coreAccountIds: List[String] = it._1.map(_.id) + accounts.filter(accountHeld => coreAccountIds.contains(accountHeld.id)) + } + } yield { + (JSONFactory300.createCoreAccountsByCoreAccountsJSON(accountHelds), HttpCode.`200`(callContext)) + } + } + } + staticResourceDocs += ResourceDoc( diff --git a/obp-api/src/main/scala/code/bankconnectors/Connector.scala b/obp-api/src/main/scala/code/bankconnectors/Connector.scala index 48c6c8bd0..bd272c3bc 100644 --- a/obp-api/src/main/scala/code/bankconnectors/Connector.scala +++ b/obp-api/src/main/scala/code/bankconnectors/Connector.scala @@ -515,6 +515,7 @@ trait Connector extends MdcLoggable { def getBankAccountsHeldLegacy(bankIdAccountIds: List[BankIdAccountId], callContext: Option[CallContext]) : Box[List[AccountHeld]]= Failure(setUnimplementedError(nameOf(getBankAccountsHeldLegacy _))) def getBankAccountsHeld(bankIdAccountIds: List[BankIdAccountId], callContext: Option[CallContext]) : OBPReturnType[Box[List[AccountHeld]]]= Future {(Failure(setUnimplementedError(nameOf(getBankAccountsHeld _))), callContext)} def getAccountsHeld(bankId: BankId, user: User, callContext: Option[CallContext]): OBPReturnType[Box[List[BankIdAccountId]]]= Future {(Failure(setUnimplementedError(nameOf(getAccountsHeld _))), callContext)} + def getAccountsHeldByUser(user: User, callContext: Option[CallContext]): OBPReturnType[Box[List[BankIdAccountId]]]= Future {(Failure(setUnimplementedError(nameOf(getAccountsHeld _))), callContext)} def checkBankAccountExistsLegacy(bankId : BankId, accountId : AccountId, callContext: Option[CallContext] = None) : Box[(BankAccount, Option[CallContext])]= Failure(setUnimplementedError(nameOf(checkBankAccountExistsLegacy _))) def checkBankAccountExists(bankId : BankId, accountId : AccountId, callContext: Option[CallContext] = None) : OBPReturnType[Box[(BankAccount)]] = Future {(Failure(setUnimplementedError(nameOf(checkBankAccountExists _))), callContext)} diff --git a/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala b/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala index 086858bb8..762aeb754 100644 --- a/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala +++ b/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala @@ -1196,6 +1196,11 @@ object LocalMappedConnector extends Connector with MdcLoggable { (Full(AccountHolders.accountHolders.vend.getAccountsHeld(bankId, user).toList), callContext) } } + override def getAccountsHeldByUser(user: User, callContext: Option[CallContext]): OBPReturnType[Box[List[BankIdAccountId]]] = { + Future { + (Full(AccountHolders.accountHolders.vend.getAccountsHeldByUser(user).toList), callContext) + } + } diff --git a/obp-api/src/test/scala/code/api/v5_1_0/AccountTest.scala b/obp-api/src/test/scala/code/api/v5_1_0/AccountTest.scala index 7367aa308..8aa825e47 100644 --- a/obp-api/src/test/scala/code/api/v5_1_0/AccountTest.scala +++ b/obp-api/src/test/scala/code/api/v5_1_0/AccountTest.scala @@ -19,7 +19,8 @@ class AccountTest extends V510ServerSetup { */ object VersionOfApi extends Tag(ApiVersion.v5_1_0.toString) object GetCoreAccountByIdThroughView extends Tag(nameOf(Implementations5_1_0.getCoreAccountByIdThroughView)) - object GetAccountsHeldByUser extends Tag(nameOf(Implementations5_1_0.getAccountsHeldByUserAtBank)) + object getAccountsHeldByUserAtBank extends Tag(nameOf(Implementations5_1_0.getAccountsHeldByUserAtBank)) + object GetAccountsHeldByUser extends Tag(nameOf(Implementations5_1_0.getAccountsHeldByUser)) lazy val bankId = randomBankId @@ -36,16 +37,16 @@ class AccountTest extends V510ServerSetup { } } - feature(s"test ${GetAccountsHeldByUser.name}") { - scenario(s"We will test ${GetAccountsHeldByUser.name}", GetAccountsHeldByUser, VersionOfApi) { + feature(s"test ${getAccountsHeldByUserAtBank.name}") { + scenario(s"We will test ${getAccountsHeldByUserAtBank.name}", getAccountsHeldByUserAtBank, VersionOfApi) { val requestGet = (v5_1_0_Request / "users" / resourceUser2.userId / "banks" / bankId / "accounts-held").GET // Anonymous call fails val anonymousResponseGet = makeGetRequest(requestGet) anonymousResponseGet.code should equal(401) anonymousResponseGet.body.extract[ErrorMessage].message should equal(UserNotLoggedIn) } - scenario("We will call the endpoint with user credentials", GetAccountsHeldByUser, VersionOfApi) { - When(s"We make a request $GetAccountsHeldByUser") + scenario("We will call the endpoint with user credentials", getAccountsHeldByUserAtBank, VersionOfApi) { + When(s"We make a request $getAccountsHeldByUserAtBank") val requestGet = (v5_1_0_Request / "users" / resourceUser2.userId / "banks" / bankId / "accounts-held").GET <@(user1) val response = makeGetRequest(requestGet) Then("We should get a 403") @@ -54,5 +55,24 @@ class AccountTest extends V510ServerSetup { response.body.extract[ErrorMessage].message contains errorMessage should be(true) } } + + feature(s"test ${GetAccountsHeldByUser.name}") { + scenario(s"We will test ${GetAccountsHeldByUser.name}", GetAccountsHeldByUser, VersionOfApi) { + val requestGet = (v5_1_0_Request / "users" / resourceUser2.userId / "accounts-held").GET + // Anonymous call fails + val anonymousResponseGet = makeGetRequest(requestGet) + anonymousResponseGet.code should equal(401) + anonymousResponseGet.body.extract[ErrorMessage].message should equal(UserNotLoggedIn) + } + scenario("We will call the endpoint with user credentials", GetAccountsHeldByUser, VersionOfApi) { + When(s"We make a request $GetAccountsHeldByUser") + val requestGet = (v5_1_0_Request / "users" / resourceUser2.userId / "accounts-held").GET <@(user1) + val response = makeGetRequest(requestGet) + Then("We should get a 403") + response.code should equal(403) + val errorMessage = UserHasMissingRoles + s"$CanGetAccountsHeldAtAnyBank" + response.body.extract[ErrorMessage].message contains errorMessage should be(true) + } + } } \ No newline at end of file