From c978e0cda41a1242f1c7cc9213e2237ee43231bf Mon Sep 17 00:00:00 2001 From: hongwei Date: Tue, 13 Jun 2023 19:10:45 +0800 Subject: [PATCH 01/41] refactor/remove `hasOwnerViewAccess` replace with specific view permissions- added canSeeBankAccountAllViews --- .../src/main/scala/code/api/v1_2_1/APIMethods121.scala | 8 ++++---- .../src/main/scala/code/api/v2_2_0/APIMethods220.scala | 6 ++++-- .../src/main/scala/code/api/v3_0_0/APIMethods300.scala | 9 +++++---- .../src/main/scala/code/api/v5_0_0/APIMethods500.scala | 6 ++++-- .../main/scala/code/model/dataAccess/MappedView.scala | 6 +++++- obp-api/src/main/scala/code/views/MapperViews.scala | 4 ++++ .../main/scala/code/views/system/ViewDefinition.scala | 4 ++++ .../com/openbankproject/commons/model/ViewModel.scala | 2 ++ 8 files changed, 32 insertions(+), 13 deletions(-) diff --git a/obp-api/src/main/scala/code/api/v1_2_1/APIMethods121.scala b/obp-api/src/main/scala/code/api/v1_2_1/APIMethods121.scala index 7419e4b135..6cfbaf7526 100644 --- a/obp-api/src/main/scala/code/api/v1_2_1/APIMethods121.scala +++ b/obp-api/src/main/scala/code/api/v1_2_1/APIMethods121.scala @@ -543,11 +543,11 @@ trait APIMethods121 { cc => for { u <- cc.user ?~ UserNotLoggedIn - account <- BankAccountX(bankId, accountId) ?~! BankAccountNotFound - _ <- booleanToBox(u.hasOwnerViewAccess(BankIdAccountId(account.bankId, account.accountId), Some(cc)), UserNoOwnerView +"userId : " + u.userId + ". account : " + accountId) - views <- Full(Views.views.vend.availableViewsForAccount(BankIdAccountId(account.bankId, account.accountId))) + bankAccount <- BankAccountX(bankId, accountId) ?~! BankAccountNotFound + ownerView <- u.checkOwnerViewAccessAndReturnOwnerView(BankIdAccountId(bankAccount.bankId, bankAccount.accountId), None) + _ <- Helper.booleanToBox(ownerView.canSeeBankAccountAllViews, UserNoOwnerView + "userId : " + u.userId + ". account : " + accountId) + views <- Full(Views.views.vend.availableViewsForAccount(BankIdAccountId(bankAccount.bankId, bankAccount.accountId))) } yield { - // TODO Include system views as well val viewsJSON = JSONFactory.createViewsJSON(views) successJsonResponse(Extraction.decompose(viewsJSON)) } diff --git a/obp-api/src/main/scala/code/api/v2_2_0/APIMethods220.scala b/obp-api/src/main/scala/code/api/v2_2_0/APIMethods220.scala index 485f579327..11cfa5b97c 100644 --- a/obp-api/src/main/scala/code/api/v2_2_0/APIMethods220.scala +++ b/obp-api/src/main/scala/code/api/v2_2_0/APIMethods220.scala @@ -1,5 +1,6 @@ package code.api.v2_2_0 +import code.api.Constant.SYSTEM_OWNER_VIEW_ID import java.util.Date import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON._ import code.api.util.APIUtil._ @@ -99,8 +100,9 @@ trait APIMethods220 { for { (Full(u), callContext) <- authenticatedAccess(cc) (account, callContext) <- NewStyle.function.checkBankAccountExists(bankId, accountId, callContext) - _ <- Helper.booleanToFuture(failMsg = UserNoOwnerView +"userId : " + u.userId + ". account : " + accountId, cc=callContext) { - u.hasOwnerViewAccess(BankIdAccountId(account.bankId, account.accountId), callContext) + ownerView <- NewStyle.function.checkViewAccessAndReturnView(ViewId(SYSTEM_OWNER_VIEW_ID), BankIdAccountId(bankId, accountId), Some(cc.loggedInUser), cc.callContext) + _ <- Helper.booleanToFuture(failMsg = s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `canSeeBankAccountAllViews` access for the Owner View", cc = cc.callContext) { + ownerView.canSeeBankAccountAllViews } views <- Future(Views.views.vend.availableViewsForAccount(BankIdAccountId(account.bankId, account.accountId))) } yield { diff --git a/obp-api/src/main/scala/code/api/v3_0_0/APIMethods300.scala b/obp-api/src/main/scala/code/api/v3_0_0/APIMethods300.scala index ae6f076f90..45680007b7 100644 --- a/obp-api/src/main/scala/code/api/v3_0_0/APIMethods300.scala +++ b/obp-api/src/main/scala/code/api/v3_0_0/APIMethods300.scala @@ -109,13 +109,14 @@ trait APIMethods300 { val res = for { (Full(u), callContext) <- authenticatedAccess(cc) - (account, callContext) <- NewStyle.function.getBankAccount(bankId, accountId, callContext) - _ <- Helper.booleanToFuture(failMsg = UserNoOwnerView +"userId : " + u.userId + ". account : " + accountId, cc=callContext){ - u.hasOwnerViewAccess(BankIdAccountId(account.bankId, account.accountId), callContext) + (bankAccount, callContext) <- NewStyle.function.getBankAccount(bankId, accountId, callContext) + ownerView <- NewStyle.function.checkViewAccessAndReturnView(ViewId(code.api.Constant.SYSTEM_OWNER_VIEW_ID), BankIdAccountId(bankId, accountId), Some(cc.loggedInUser), cc.callContext) + _ <- Helper.booleanToFuture(failMsg = s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `canSeeBankAccountAllViews` access for the Owner View", cc = cc.callContext) { + ownerView.canSeeBankAccountAllViews } } yield { for { - views <- Full(Views.views.vend.availableViewsForAccount(BankIdAccountId(account.bankId, account.accountId))) + views <- Full(Views.views.vend.availableViewsForAccount(BankIdAccountId(bankAccount.bankId, bankAccount.accountId))) } yield { (createViewsJSON(views), HttpCode.`200`(callContext)) } diff --git a/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala b/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala index 2649a20187..72bde98e06 100644 --- a/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala +++ b/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala @@ -43,6 +43,7 @@ import net.liftweb.util.{Helpers, Props} import java.util.concurrent.ThreadLocalRandom import code.accountattribute.AccountAttributeX +import code.api.Constant.SYSTEM_OWNER_VIEW_ID import code.util.Helper.booleanToFuture import code.views.system.AccountAccess @@ -1590,8 +1591,9 @@ trait APIMethods500 { cc => val res = for { - _ <- Helper.booleanToFuture(failMsg = UserNoOwnerView +"userId : " + cc.userId + ". account : " + accountId, cc=cc.callContext){ - cc.loggedInUser.hasOwnerViewAccess(BankIdAccountId(bankId, accountId), Some(cc)) + ownerView <- NewStyle.function.checkViewAccessAndReturnView(ViewId(SYSTEM_OWNER_VIEW_ID), BankIdAccountId(bankId, accountId), Some(cc.loggedInUser), cc.callContext) + _ <- Helper.booleanToFuture(failMsg = s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `canSeeBankAccountAllViews` access for the Owner View", cc=cc.callContext){ + ownerView.canSeeBankAccountAllViews } } yield { for { diff --git a/obp-api/src/main/scala/code/model/dataAccess/MappedView.scala b/obp-api/src/main/scala/code/model/dataAccess/MappedView.scala index 768caceb8c..c8beba0d5a 100644 --- a/obp-api/src/main/scala/code/model/dataAccess/MappedView.scala +++ b/obp-api/src/main/scala/code/model/dataAccess/MappedView.scala @@ -54,7 +54,7 @@ class ViewImpl extends View with LongKeyedMapper[ViewImpl] with ManyToMany with def getSingleton = ViewImpl def primaryKeyField = id_ - + //This field used ManyToMany object users_ extends MappedManyToMany(ViewPrivileges, ViewPrivileges.view, ViewPrivileges.user, ResourceUser) @@ -245,6 +245,9 @@ class ViewImpl extends View with LongKeyedMapper[ViewImpl] with ManyToMany with object canSeeBankAccountOwners_ extends MappedBoolean(this){ override def defaultValue = false } + object canSeeBankAccountAllViews_ extends MappedBoolean(this){ + override def defaultValue = false + } object canSeeBankAccountType_ extends MappedBoolean(this){ override def defaultValue = false } @@ -465,6 +468,7 @@ class ViewImpl extends View with LongKeyedMapper[ViewImpl] with ManyToMany with def canSeeImages : Boolean = canSeeImages_.get //Bank account fields + def canSeeBankAccountAllViews : Boolean = canSeeBankAccountAllViews_.get def canSeeBankAccountOwners : Boolean = canSeeBankAccountOwners_.get def canSeeBankAccountType : Boolean = canSeeBankAccountType_.get def canSeeBankAccountBalance : Boolean = canSeeBankAccountBalance_.get diff --git a/obp-api/src/main/scala/code/views/MapperViews.scala b/obp-api/src/main/scala/code/views/MapperViews.scala index 06f209507b..1d571560e2 100644 --- a/obp-api/src/main/scala/code/views/MapperViews.scala +++ b/obp-api/src/main/scala/code/views/MapperViews.scala @@ -790,8 +790,12 @@ object MapperViews extends Views with MdcLoggable { .canSeeOtherAccountRoutingAddress_(true) .canAddTransactionRequestToOwnAccount_(true) //added following two for payments .canAddTransactionRequestToAnyAccount_(true) + .canSeeBankAccountAllViews_(false) viewId match { + case SYSTEM_OWNER_VIEW_ID => + entity + .canSeeBankAccountAllViews_(true) case SYSTEM_STAGE_ONE_VIEW_ID => entity .canSeeTransactionDescription_(false) diff --git a/obp-api/src/main/scala/code/views/system/ViewDefinition.scala b/obp-api/src/main/scala/code/views/system/ViewDefinition.scala index ff3a035b10..2dc96c5399 100644 --- a/obp-api/src/main/scala/code/views/system/ViewDefinition.scala +++ b/obp-api/src/main/scala/code/views/system/ViewDefinition.scala @@ -102,6 +102,9 @@ class ViewDefinition extends View with LongKeyedMapper[ViewDefinition] with Many object canSeeBankAccountOwners_ extends MappedBoolean(this){ override def defaultValue = false } + object canSeeBankAccountAllViews_ extends MappedBoolean(this){ + override def defaultValue = false + } object canSeeBankAccountType_ extends MappedBoolean(this){ override def defaultValue = false } @@ -453,6 +456,7 @@ class ViewDefinition extends View with LongKeyedMapper[ViewDefinition] with Many def canSeeImages : Boolean = canSeeImages_.get //Bank account fields + def canSeeBankAccountAllViews : Boolean = canSeeBankAccountAllViews_.get def canSeeBankAccountOwners : Boolean = canSeeBankAccountOwners_.get def canSeeBankAccountType : Boolean = canSeeBankAccountType_.get def canSeeBankAccountBalance : Boolean = canSeeBankAccountBalance_.get diff --git a/obp-commons/src/main/scala/com/openbankproject/commons/model/ViewModel.scala b/obp-commons/src/main/scala/com/openbankproject/commons/model/ViewModel.scala index 057b97bb5a..4597c5f368 100644 --- a/obp-commons/src/main/scala/com/openbankproject/commons/model/ViewModel.scala +++ b/obp-commons/src/main/scala/com/openbankproject/commons/model/ViewModel.scala @@ -288,6 +288,8 @@ trait View { def canSeeImages: Boolean //Bank account fields + def canSeeBankAccountAllViews: Boolean + def canSeeBankAccountOwners: Boolean def canSeeBankAccountType: Boolean From 3d9ee3ebf1f5dd498b595e5fd306023b7b93327d Mon Sep 17 00:00:00 2001 From: hongwei Date: Tue, 13 Jun 2023 22:12:36 +0800 Subject: [PATCH 02/41] refactor/remove `hasOwnerViewAccess` replace with specific view permissions- added canSeeTransactionRequestThisBankAccount --- .../src/main/scala/code/api/v1_2_1/APIMethods121.scala | 2 +- .../src/main/scala/code/api/v1_4_0/APIMethods140.scala | 4 +++- .../src/main/scala/code/api/v2_1_0/APIMethods210.scala | 6 +++--- .../src/main/scala/code/api/v3_1_0/APIMethods310.scala | 8 ++++---- .../src/main/scala/code/api/v4_0_0/APIMethods400.scala | 7 ++++--- .../src/main/scala/code/model/dataAccess/MappedView.scala | 5 +++++ .../src/main/scala/code/views/system/ViewDefinition.scala | 4 ++++ .../com/openbankproject/commons/model/ViewModel.scala | 2 ++ 8 files changed, 26 insertions(+), 12 deletions(-) diff --git a/obp-api/src/main/scala/code/api/v1_2_1/APIMethods121.scala b/obp-api/src/main/scala/code/api/v1_2_1/APIMethods121.scala index 6cfbaf7526..e3d93532df 100644 --- a/obp-api/src/main/scala/code/api/v1_2_1/APIMethods121.scala +++ b/obp-api/src/main/scala/code/api/v1_2_1/APIMethods121.scala @@ -545,7 +545,7 @@ trait APIMethods121 { u <- cc.user ?~ UserNotLoggedIn bankAccount <- BankAccountX(bankId, accountId) ?~! BankAccountNotFound ownerView <- u.checkOwnerViewAccessAndReturnOwnerView(BankIdAccountId(bankAccount.bankId, bankAccount.accountId), None) - _ <- Helper.booleanToBox(ownerView.canSeeBankAccountAllViews, UserNoOwnerView + "userId : " + u.userId + ". account : " + accountId) + _ <- Helper.booleanToBox(ownerView.canSeeBankAccountAllViews, s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `canSeeBankAccountAllViews` access for the Owner View") views <- Full(Views.views.vend.availableViewsForAccount(BankIdAccountId(bankAccount.bankId, bankAccount.accountId))) } yield { val viewsJSON = JSONFactory.createViewsJSON(views) diff --git a/obp-api/src/main/scala/code/api/v1_4_0/APIMethods140.scala b/obp-api/src/main/scala/code/api/v1_4_0/APIMethods140.scala index f8048a90d6..6bde16e172 100644 --- a/obp-api/src/main/scala/code/api/v1_4_0/APIMethods140.scala +++ b/obp-api/src/main/scala/code/api/v1_4_0/APIMethods140.scala @@ -11,6 +11,7 @@ import code.bankconnectors.Connector import code.branches.Branches import code.customer.CustomerX import code.usercustomerlinks.UserCustomerLink +import code.util.Helper import code.views.Views import com.github.dwickern.macros.NameOf.nameOf import com.openbankproject.commons.model._ @@ -462,7 +463,8 @@ trait APIMethods140 extends MdcLoggable with APIMethods130 with APIMethods121{ u <- cc.user ?~ ErrorMessages.UserNotLoggedIn (bank, callContext ) <- BankX(bankId, Some(cc)) ?~! {ErrorMessages.BankNotFound} fromAccount <- BankAccountX(bankId, accountId) ?~! {ErrorMessages.AccountNotFound} - _ <- booleanToBox( u.hasOwnerViewAccess(BankIdAccountId(bankId, accountId), callContext), UserNoOwnerView +"userId : " + u.userId + ". account : " + accountId) + ownerView <- u.checkOwnerViewAccessAndReturnOwnerView(BankIdAccountId(fromAccount.bankId, fromAccount.accountId), None) + _ <- Helper.booleanToBox(ownerView.canSeeTransactionRequestThisBankAccount, s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `canSeeTransactionRequestThisBankAccount` access for the Owner View") transactionRequests <- Connector.connector.vend.getTransactionRequests(u, fromAccount, callContext) } yield { diff --git a/obp-api/src/main/scala/code/api/v2_1_0/APIMethods210.scala b/obp-api/src/main/scala/code/api/v2_1_0/APIMethods210.scala index ab25f70d9a..880e3a3635 100644 --- a/obp-api/src/main/scala/code/api/v2_1_0/APIMethods210.scala +++ b/obp-api/src/main/scala/code/api/v2_1_0/APIMethods210.scala @@ -6,7 +6,7 @@ import code.api.util import code.api.util.ApiTag._ import code.api.util.ErrorMessages.TransactionDisabled import code.api.util.NewStyle.HttpCode -import code.api.util.{APIUtil, ApiRole, NewStyle} +import code.api.util.{APIUtil, ApiRole, ErrorMessages, NewStyle} import code.api.v1_3_0.{JSONFactory1_3_0, _} import code.api.v1_4_0.JSONFactory1_4_0 import code.api.v1_4_0.JSONFactory1_4_0._ @@ -713,8 +713,8 @@ trait APIMethods210 { u <- cc.user ?~ UserNotLoggedIn (bank, callContext ) <- BankX(bankId, Some(cc)) ?~! {BankNotFound} (fromAccount, callContext) <- BankAccountX(bankId, accountId, Some(cc)) ?~! {AccountNotFound} - view <- APIUtil.checkViewAccessAndReturnView(viewId, BankIdAccountId(fromAccount.bankId, fromAccount.accountId), Some(u), callContext) - _ <- booleanToBox(u.hasOwnerViewAccess(BankIdAccountId(fromAccount.bankId,fromAccount.accountId), callContext), UserNoOwnerView) + ownerView <- APIUtil.checkViewAccessAndReturnView(viewId, BankIdAccountId(fromAccount.bankId, fromAccount.accountId), Some(u), callContext) + _ <- Helper.booleanToBox(ownerView.canSeeTransactionRequestThisBankAccount, s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `canSeeTransactionRequestThisBankAccount` access for the Owner View") (transactionRequests,callContext) <- Connector.connector.vend.getTransactionRequests210(u, fromAccount, callContext) } yield { diff --git a/obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala b/obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala index 4f261b8882..02ac6c723a 100644 --- a/obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala +++ b/obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala @@ -1,7 +1,7 @@ package code.api.v3_1_0 import code.api.Constant -import code.api.Constant.localIdentityProvider +import code.api.Constant.{SYSTEM_OWNER_VIEW_ID, localIdentityProvider} import java.text.SimpleDateFormat import java.util.UUID @@ -1086,9 +1086,9 @@ trait APIMethods310 { _ <- NewStyle.function.isEnabledTransactionRequests(callContext) (_, callContext) <- NewStyle.function.getBank(bankId, callContext) (fromAccount, callContext) <- NewStyle.function.checkBankAccountExists(bankId, accountId, callContext) - view <- NewStyle.function.checkViewAccessAndReturnView(viewId, BankIdAccountId(bankId, accountId), Some(u), callContext) - _ <- Helper.booleanToFuture(failMsg = UserNoOwnerView, cc=callContext) { - u.hasOwnerViewAccess(BankIdAccountId(bankId,accountId), callContext) + ownerView <- NewStyle.function.checkViewAccessAndReturnView(ViewId(SYSTEM_OWNER_VIEW_ID), BankIdAccountId(bankId, accountId), Some(cc.loggedInUser), cc.callContext) + _ <- Helper.booleanToFuture(failMsg = s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `canSeeTransactionRequestThisBankAccount` access for the Owner View", cc = cc.callContext) { + ownerView.canSeeTransactionRequestThisBankAccount } (transactionRequests, callContext) <- Future(Connector.connector.vend.getTransactionRequests210(u, fromAccount, callContext)) map { unboxFullOrFail(_, callContext, GetTransactionRequestsException) diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index 9620451945..564d5e7a28 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -7,7 +7,7 @@ import java.util.{Calendar, Date} import code.DynamicData.{DynamicData, DynamicDataProvider} import code.DynamicEndpoint.DynamicEndpointSwagger import code.accountattribute.AccountAttributeX -import code.api.Constant.{PARAM_LOCALE, PARAM_TIMESTAMP, localIdentityProvider} +import code.api.Constant.{PARAM_LOCALE, PARAM_TIMESTAMP, SYSTEM_OWNER_VIEW_ID, localIdentityProvider} import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON.{jsonDynamicResourceDoc, _} import code.api.UKOpenBanking.v2_0_0.OBP_UKOpenBanking_200 @@ -5150,8 +5150,9 @@ trait APIMethods400 { for { (user @Full(u), _, account, view, callContext) <- SS.userBankAccountView _ <- NewStyle.function.isEnabledTransactionRequests(callContext) - _ <- Helper.booleanToFuture(failMsg = UserNoOwnerView, cc=callContext) { - u.hasOwnerViewAccess(BankIdAccountId(bankId,accountId), callContext) + ownerView <- NewStyle.function.checkViewAccessAndReturnView(ViewId(SYSTEM_OWNER_VIEW_ID), BankIdAccountId(bankId, accountId), Some(cc.loggedInUser), cc.callContext) + _ <- Helper.booleanToFuture(failMsg = s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `canSeeTransactionRequestThisBankAccount` access for the Owner View", cc = cc.callContext) { + ownerView.canSeeTransactionRequestThisBankAccount } (transactionRequest, callContext) <- NewStyle.function.getTransactionRequestImpl(requestId, callContext) } yield { diff --git a/obp-api/src/main/scala/code/model/dataAccess/MappedView.scala b/obp-api/src/main/scala/code/model/dataAccess/MappedView.scala index c8beba0d5a..d1029a160a 100644 --- a/obp-api/src/main/scala/code/model/dataAccess/MappedView.scala +++ b/obp-api/src/main/scala/code/model/dataAccess/MappedView.scala @@ -203,6 +203,10 @@ class ViewImpl extends View with LongKeyedMapper[ViewImpl] with ManyToMany with object canSeeTransactionThisBankAccount_ extends MappedBoolean(this){ override def defaultValue = false } + + object canSeeTransactionRequestThisBankAccount_ extends MappedBoolean(this){ + override def defaultValue = false + } object canSeeTransactionOtherBankAccount_ extends MappedBoolean(this){ override def defaultValue = false } @@ -451,6 +455,7 @@ class ViewImpl extends View with LongKeyedMapper[ViewImpl] with ManyToMany with //transaction fields def canSeeTransactionThisBankAccount : Boolean = canSeeTransactionThisBankAccount_.get + def canSeeTransactionRequestThisBankAccount : Boolean = canSeeTransactionRequestThisBankAccount_.get def canSeeTransactionOtherBankAccount : Boolean = canSeeTransactionOtherBankAccount_.get def canSeeTransactionMetadata : Boolean = canSeeTransactionMetadata_.get def canSeeTransactionDescription: Boolean = canSeeTransactionDescription_.get diff --git a/obp-api/src/main/scala/code/views/system/ViewDefinition.scala b/obp-api/src/main/scala/code/views/system/ViewDefinition.scala index 2dc96c5399..b778858c1e 100644 --- a/obp-api/src/main/scala/code/views/system/ViewDefinition.scala +++ b/obp-api/src/main/scala/code/views/system/ViewDefinition.scala @@ -60,6 +60,9 @@ class ViewDefinition extends View with LongKeyedMapper[ViewDefinition] with Many object canSeeTransactionThisBankAccount_ extends MappedBoolean(this){ override def defaultValue = false } + object canSeeTransactionRequestThisBankAccount_ extends MappedBoolean(this){ + override def defaultValue = false + } object canSeeTransactionOtherBankAccount_ extends MappedBoolean(this){ override def defaultValue = false } @@ -439,6 +442,7 @@ class ViewDefinition extends View with LongKeyedMapper[ViewDefinition] with Many //transaction fields def canSeeTransactionThisBankAccount : Boolean = canSeeTransactionThisBankAccount_.get + def canSeeTransactionRequestThisBankAccount : Boolean = canSeeTransactionRequestThisBankAccount_.get def canSeeTransactionOtherBankAccount : Boolean = canSeeTransactionOtherBankAccount_.get def canSeeTransactionMetadata : Boolean = canSeeTransactionMetadata_.get def canSeeTransactionDescription: Boolean = canSeeTransactionDescription_.get diff --git a/obp-commons/src/main/scala/com/openbankproject/commons/model/ViewModel.scala b/obp-commons/src/main/scala/com/openbankproject/commons/model/ViewModel.scala index 4597c5f368..f75e9b43dd 100644 --- a/obp-commons/src/main/scala/com/openbankproject/commons/model/ViewModel.scala +++ b/obp-commons/src/main/scala/com/openbankproject/commons/model/ViewModel.scala @@ -258,6 +258,8 @@ trait View { //reading access //transaction fields + def canSeeTransactionRequestThisBankAccount: Boolean + def canSeeTransactionThisBankAccount: Boolean def canSeeTransactionOtherBankAccount: Boolean From 6e24d3ceb0e91bb3b9343bfe261169afffd04220 Mon Sep 17 00:00:00 2001 From: hongwei Date: Wed, 14 Jun 2023 16:57:52 +0800 Subject: [PATCH 03/41] refactor/remove `hasOwnerViewAccess` replace with specific view permissions- fixed the test --- obp-api/src/main/scala/code/api/v2_2_0/APIMethods220.scala | 2 +- obp-api/src/main/scala/code/api/v3_0_0/APIMethods300.scala | 2 +- obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala | 2 +- obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala | 2 +- obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala | 3 ++- obp-api/src/main/scala/code/views/MapperViews.scala | 2 ++ obp-api/src/test/scala/code/api/v2_2_0/AccountTest.scala | 2 +- 7 files changed, 9 insertions(+), 6 deletions(-) diff --git a/obp-api/src/main/scala/code/api/v2_2_0/APIMethods220.scala b/obp-api/src/main/scala/code/api/v2_2_0/APIMethods220.scala index 11cfa5b97c..5c10a428b4 100644 --- a/obp-api/src/main/scala/code/api/v2_2_0/APIMethods220.scala +++ b/obp-api/src/main/scala/code/api/v2_2_0/APIMethods220.scala @@ -100,7 +100,7 @@ trait APIMethods220 { for { (Full(u), callContext) <- authenticatedAccess(cc) (account, callContext) <- NewStyle.function.checkBankAccountExists(bankId, accountId, callContext) - ownerView <- NewStyle.function.checkViewAccessAndReturnView(ViewId(SYSTEM_OWNER_VIEW_ID), BankIdAccountId(bankId, accountId), Some(cc.loggedInUser), cc.callContext) + ownerView <- NewStyle.function.checkViewAccessAndReturnView(ViewId(SYSTEM_OWNER_VIEW_ID), BankIdAccountId(bankId, accountId), Some(u), cc.callContext) _ <- Helper.booleanToFuture(failMsg = s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `canSeeBankAccountAllViews` access for the Owner View", cc = cc.callContext) { ownerView.canSeeBankAccountAllViews } diff --git a/obp-api/src/main/scala/code/api/v3_0_0/APIMethods300.scala b/obp-api/src/main/scala/code/api/v3_0_0/APIMethods300.scala index 45680007b7..faabe19e8b 100644 --- a/obp-api/src/main/scala/code/api/v3_0_0/APIMethods300.scala +++ b/obp-api/src/main/scala/code/api/v3_0_0/APIMethods300.scala @@ -110,7 +110,7 @@ trait APIMethods300 { for { (Full(u), callContext) <- authenticatedAccess(cc) (bankAccount, callContext) <- NewStyle.function.getBankAccount(bankId, accountId, callContext) - ownerView <- NewStyle.function.checkViewAccessAndReturnView(ViewId(code.api.Constant.SYSTEM_OWNER_VIEW_ID), BankIdAccountId(bankId, accountId), Some(cc.loggedInUser), cc.callContext) + ownerView <- NewStyle.function.checkViewAccessAndReturnView(ViewId(code.api.Constant.SYSTEM_OWNER_VIEW_ID), BankIdAccountId(bankId, accountId), Some(u), cc.callContext) _ <- Helper.booleanToFuture(failMsg = s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `canSeeBankAccountAllViews` access for the Owner View", cc = cc.callContext) { ownerView.canSeeBankAccountAllViews } diff --git a/obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala b/obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala index 02ac6c723a..a40c056075 100644 --- a/obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala +++ b/obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala @@ -1086,7 +1086,7 @@ trait APIMethods310 { _ <- NewStyle.function.isEnabledTransactionRequests(callContext) (_, callContext) <- NewStyle.function.getBank(bankId, callContext) (fromAccount, callContext) <- NewStyle.function.checkBankAccountExists(bankId, accountId, callContext) - ownerView <- NewStyle.function.checkViewAccessAndReturnView(ViewId(SYSTEM_OWNER_VIEW_ID), BankIdAccountId(bankId, accountId), Some(cc.loggedInUser), cc.callContext) + ownerView <- NewStyle.function.checkViewAccessAndReturnView(ViewId(SYSTEM_OWNER_VIEW_ID), BankIdAccountId(bankId, accountId), Some(u), cc.callContext) _ <- Helper.booleanToFuture(failMsg = s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `canSeeTransactionRequestThisBankAccount` access for the Owner View", cc = cc.callContext) { ownerView.canSeeTransactionRequestThisBankAccount } diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index 564d5e7a28..76022c187b 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -5150,7 +5150,7 @@ trait APIMethods400 { for { (user @Full(u), _, account, view, callContext) <- SS.userBankAccountView _ <- NewStyle.function.isEnabledTransactionRequests(callContext) - ownerView <- NewStyle.function.checkViewAccessAndReturnView(ViewId(SYSTEM_OWNER_VIEW_ID), BankIdAccountId(bankId, accountId), Some(cc.loggedInUser), cc.callContext) + ownerView <- NewStyle.function.checkViewAccessAndReturnView(ViewId(SYSTEM_OWNER_VIEW_ID), BankIdAccountId(bankId, accountId), Some(u), cc.callContext) _ <- Helper.booleanToFuture(failMsg = s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `canSeeTransactionRequestThisBankAccount` access for the Owner View", cc = cc.callContext) { ownerView.canSeeTransactionRequestThisBankAccount } diff --git a/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala b/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala index 72bde98e06..d503f9ee65 100644 --- a/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala +++ b/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala @@ -1591,7 +1591,8 @@ trait APIMethods500 { cc => val res = for { - ownerView <- NewStyle.function.checkViewAccessAndReturnView(ViewId(SYSTEM_OWNER_VIEW_ID), BankIdAccountId(bankId, accountId), Some(cc.loggedInUser), cc.callContext) + (Full(u), callContext) <- SS.user + ownerView <- NewStyle.function.checkViewAccessAndReturnView(ViewId(SYSTEM_OWNER_VIEW_ID), BankIdAccountId(bankId, accountId), Some(u), cc.callContext) _ <- Helper.booleanToFuture(failMsg = s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `canSeeBankAccountAllViews` access for the Owner View", cc=cc.callContext){ ownerView.canSeeBankAccountAllViews } diff --git a/obp-api/src/main/scala/code/views/MapperViews.scala b/obp-api/src/main/scala/code/views/MapperViews.scala index 1d571560e2..2c6c0ba1d9 100644 --- a/obp-api/src/main/scala/code/views/MapperViews.scala +++ b/obp-api/src/main/scala/code/views/MapperViews.scala @@ -791,11 +791,13 @@ object MapperViews extends Views with MdcLoggable { .canAddTransactionRequestToOwnAccount_(true) //added following two for payments .canAddTransactionRequestToAnyAccount_(true) .canSeeBankAccountAllViews_(false) + .canSeeTransactionRequestThisBankAccount_(false) viewId match { case SYSTEM_OWNER_VIEW_ID => entity .canSeeBankAccountAllViews_(true) + .canSeeTransactionRequestThisBankAccount_(true) case SYSTEM_STAGE_ONE_VIEW_ID => entity .canSeeTransactionDescription_(false) diff --git a/obp-api/src/test/scala/code/api/v2_2_0/AccountTest.scala b/obp-api/src/test/scala/code/api/v2_2_0/AccountTest.scala index 65cf21ca9d..24099686ea 100644 --- a/obp-api/src/test/scala/code/api/v2_2_0/AccountTest.scala +++ b/obp-api/src/test/scala/code/api/v2_2_0/AccountTest.scala @@ -170,7 +170,7 @@ class AccountTest extends V220ServerSetup with DefaultUsers { TimeUnit.SECONDS.sleep(2) Then("we get the account access for this account") - val accountViewsRequest = v2_2Request / "banks" / testBank.value / "accounts" / mockAccountId1 / "views" <@(user1) + val accountViewsRequest = (v2_2Request / "banks" / testBank.value / "accounts" / mockAccountId1 / "views").GET <@(user1) val accountViewsResponse = makeGetRequest(accountViewsRequest) val accountViews = accountViewsResponse.body.extract[ViewsJSONV220] //Note: now when we create new account, will have the systemOwnerView access to this view. From 838cf25a2e855aa4ff087bd32a0e41d74efbe874 Mon Sep 17 00:00:00 2001 From: hongwei Date: Wed, 14 Jun 2023 21:14:14 +0800 Subject: [PATCH 04/41] refactor/remove `hasOwnerViewAccess` replace with specific view permissions- tweaked the logics --- .../main/scala/code/api/util/NewStyle.scala | 5 ++ .../code/api/util/migration/Migration.scala | 9 ++++ ...MigrationOfViewDefinitionPermissions.scala | 50 +++++++++++++++++++ .../scala/code/api/v1_2_1/APIMethods121.scala | 10 ++-- .../scala/code/api/v1_4_0/APIMethods140.scala | 9 +++- .../scala/code/api/v2_1_0/APIMethods210.scala | 5 +- .../scala/code/api/v2_2_0/APIMethods220.scala | 12 +++-- .../scala/code/api/v3_0_0/APIMethods300.scala | 10 ++-- .../scala/code/api/v3_1_0/APIMethods310.scala | 10 ++-- .../scala/code/api/v4_0_0/APIMethods400.scala | 9 ++-- .../scala/code/api/v5_0_0/APIMethods500.scala | 15 +++--- obp-api/src/main/scala/code/model/View.scala | 10 ++-- .../code/model/dataAccess/MappedView.scala | 10 ++-- .../main/scala/code/views/MapperViews.scala | 8 +-- .../code/views/system/ViewDefinition.scala | 10 ++-- .../commons/model/ViewModel.scala | 4 +- 16 files changed, 139 insertions(+), 47 deletions(-) create mode 100644 obp-api/src/main/scala/code/api/util/migration/MigrationOfViewDefinitionPermissions.scala 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 467689599f..e3dc2b4be0 100644 --- a/obp-api/src/main/scala/code/api/util/NewStyle.scala +++ b/obp-api/src/main/scala/code/api/util/NewStyle.scala @@ -524,6 +524,11 @@ object NewStyle extends MdcLoggable{ } map { fullBoxOrException(_) } map { unboxFull(_) } + def permission(bankId: BankId,accountId: AccountId, user: User, callContext: Option[CallContext]) = Future { + Views.views.vend.permission(BankIdAccountId(bankId, accountId), user) + } map { fullBoxOrException(_) + } map { unboxFull(_) } + def removeView(account: BankAccount, user: User, viewId: ViewId, callContext: Option[CallContext]) = Future { account.removeView(user, viewId, callContext) } map { fullBoxOrException(_) diff --git a/obp-api/src/main/scala/code/api/util/migration/Migration.scala b/obp-api/src/main/scala/code/api/util/migration/Migration.scala index 1038cd97cb..d028d873be 100644 --- a/obp-api/src/main/scala/code/api/util/migration/Migration.scala +++ b/obp-api/src/main/scala/code/api/util/migration/Migration.scala @@ -63,6 +63,7 @@ object Migration extends MdcLoggable { dummyScript() addAccountAccessConsumerId() populateTableViewDefinition() + populateMigrationOfViewDefinitionPermissions() populateTableAccountAccess() generateAndPopulateMissingCustomerUUIDs(startedBeforeSchemifier) generateAndPopulateMissingConsumersUUIDs(startedBeforeSchemifier) @@ -127,6 +128,14 @@ object Migration extends MdcLoggable { } } + + private def populateMigrationOfViewDefinitionPermissions(): Boolean = { + val name = nameOf(populateMigrationOfViewDefinitionPermissions) + runOnce(name) { + MigrationOfViewDefinitionPermissions.populate(name) + } + } + private def generateAndPopulateMissingCustomerUUIDs(startedBeforeSchemifier: Boolean): Boolean = { if(startedBeforeSchemifier == true) { logger.warn(s"Migration.database.generateAndPopulateMissingCustomerUUIDs(true) cannot be run before Schemifier.") diff --git a/obp-api/src/main/scala/code/api/util/migration/MigrationOfViewDefinitionPermissions.scala b/obp-api/src/main/scala/code/api/util/migration/MigrationOfViewDefinitionPermissions.scala new file mode 100644 index 0000000000..2477ba0a0e --- /dev/null +++ b/obp-api/src/main/scala/code/api/util/migration/MigrationOfViewDefinitionPermissions.scala @@ -0,0 +1,50 @@ +package code.api.util.migration + +import code.api.Constant.SYSTEM_OWNER_VIEW_ID +import code.api.util.APIUtil +import code.api.util.migration.Migration.{DbFunction, saveLog} +import code.views.system.ViewDefinition +import net.liftweb.mapper.{By, DB, NullRef} +import net.liftweb.util.DefaultConnectionIdentifier + +object MigrationOfViewDefinitionPermissions { + def populate(name: String): Boolean = { + DbFunction.tableExists(ViewDefinition, (DB.use(DefaultConnectionIdentifier){ conn => conn})) match { + case true => + val startDate = System.currentTimeMillis() + val commitId: String = APIUtil.gitCommit + val ownerView = ViewDefinition.find( + NullRef(ViewDefinition.bank_id), + NullRef(ViewDefinition.account_id), + By(ViewDefinition.view_id, SYSTEM_OWNER_VIEW_ID), + By(ViewDefinition.isSystem_,true) + ).map(view => + view +// .canSeeTransactionRequests_(true) +// .canSeeAvailableViewsForBankAccount_(true) + .save + ).head + + + val isSuccessful = ownerView + val endDate = System.currentTimeMillis() + + val comment: String = + s"""ViewDefinition system owner view, update the following rows to true: + |canSeeTransactionRequests_ + |Duration: ${endDate - startDate} ms; + """.stripMargin + saveLog(name, commitId, isSuccessful, startDate, endDate, comment) + isSuccessful + case false => + val startDate = System.currentTimeMillis() + val commitId: String = APIUtil.gitCommit + val isSuccessful = false + val endDate = System.currentTimeMillis() + val comment: String = + s"""ViewDefinition does not exist!""".stripMargin + saveLog(name, commitId, isSuccessful, startDate, endDate, comment) + isSuccessful + } + } +} diff --git a/obp-api/src/main/scala/code/api/v1_2_1/APIMethods121.scala b/obp-api/src/main/scala/code/api/v1_2_1/APIMethods121.scala index e3d93532df..35a6ee04e8 100644 --- a/obp-api/src/main/scala/code/api/v1_2_1/APIMethods121.scala +++ b/obp-api/src/main/scala/code/api/v1_2_1/APIMethods121.scala @@ -4,7 +4,6 @@ import java.net.URL import java.util.Random import java.security.SecureRandom import java.util.UUID.randomUUID - import com.tesobe.CacheKeyFromArguments import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON._ import code.api.cache.Caching @@ -20,6 +19,7 @@ import code.model.{BankAccountX, BankX, ModeratedTransactionMetadata, toBankAcco import code.util.Helper import code.util.Helper.booleanToBox import code.views.Views +import code.views.system.ViewDefinition import com.google.common.cache.CacheBuilder import com.openbankproject.commons.model.{Bank, UpdateViewJSON, _} import com.openbankproject.commons.util.ApiVersion @@ -544,8 +544,12 @@ trait APIMethods121 { for { u <- cc.user ?~ UserNotLoggedIn bankAccount <- BankAccountX(bankId, accountId) ?~! BankAccountNotFound - ownerView <- u.checkOwnerViewAccessAndReturnOwnerView(BankIdAccountId(bankAccount.bankId, bankAccount.accountId), None) - _ <- Helper.booleanToBox(ownerView.canSeeBankAccountAllViews, s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `canSeeBankAccountAllViews` access for the Owner View") + permission <- Views.views.vend.permission(BankIdAccountId(bankAccount.bankId, bankAccount.accountId), u) + anyViewContainsCanSeeAvailableViewsForBankAccountPermission = permission.views.map(_.canSeeAvailableViewsForBankAccount).find(_.==(true)).getOrElse(false) + _ <- Helper.booleanToBox( + anyViewContainsCanSeeAvailableViewsForBankAccountPermission, + s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${ViewDefinition.canSeeAvailableViewsForBankAccount.toString}` permission on any your views" + ) views <- Full(Views.views.vend.availableViewsForAccount(BankIdAccountId(bankAccount.bankId, bankAccount.accountId))) } yield { val viewsJSON = JSONFactory.createViewsJSON(views) diff --git a/obp-api/src/main/scala/code/api/v1_4_0/APIMethods140.scala b/obp-api/src/main/scala/code/api/v1_4_0/APIMethods140.scala index 6bde16e172..52954aff05 100644 --- a/obp-api/src/main/scala/code/api/v1_4_0/APIMethods140.scala +++ b/obp-api/src/main/scala/code/api/v1_4_0/APIMethods140.scala @@ -1,5 +1,6 @@ package code.api.v1_4_0 +import code.api.Constant.SYSTEM_OWNER_VIEW_ID import code.api.util.ApiRole._ import code.api.util.ApiTag._ import code.api.util.NewStyle.HttpCode @@ -13,6 +14,7 @@ import code.customer.CustomerX import code.usercustomerlinks.UserCustomerLink import code.util.Helper import code.views.Views +import code.views.system.ViewDefinition import com.github.dwickern.macros.NameOf.nameOf import com.openbankproject.commons.model._ import com.openbankproject.commons.util.ApiVersion @@ -463,8 +465,11 @@ trait APIMethods140 extends MdcLoggable with APIMethods130 with APIMethods121{ u <- cc.user ?~ ErrorMessages.UserNotLoggedIn (bank, callContext ) <- BankX(bankId, Some(cc)) ?~! {ErrorMessages.BankNotFound} fromAccount <- BankAccountX(bankId, accountId) ?~! {ErrorMessages.AccountNotFound} - ownerView <- u.checkOwnerViewAccessAndReturnOwnerView(BankIdAccountId(fromAccount.bankId, fromAccount.accountId), None) - _ <- Helper.booleanToBox(ownerView.canSeeTransactionRequestThisBankAccount, s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `canSeeTransactionRequestThisBankAccount` access for the Owner View") + view <- APIUtil.checkViewAccessAndReturnView(viewId, BankIdAccountId(bankId, accountId), Some(u), callContext) + _ <- Helper.booleanToBox( + view.canSeeTransactionRequests, + s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${ViewDefinition.canSeeTransactionRequests.toString}` permission on the View(${viewId.value})" + ) transactionRequests <- Connector.connector.vend.getTransactionRequests(u, fromAccount, callContext) } yield { diff --git a/obp-api/src/main/scala/code/api/v2_1_0/APIMethods210.scala b/obp-api/src/main/scala/code/api/v2_1_0/APIMethods210.scala index 880e3a3635..26a8fb23dd 100644 --- a/obp-api/src/main/scala/code/api/v2_1_0/APIMethods210.scala +++ b/obp-api/src/main/scala/code/api/v2_1_0/APIMethods210.scala @@ -27,6 +27,7 @@ import code.usercustomerlinks.UserCustomerLink import code.users.Users import code.util.Helper.booleanToBox import code.views.Views +import code.views.system.ViewDefinition import com.openbankproject.commons.model._ import com.openbankproject.commons.model.enums.ChallengeType import com.openbankproject.commons.util.ApiVersion @@ -713,8 +714,8 @@ trait APIMethods210 { u <- cc.user ?~ UserNotLoggedIn (bank, callContext ) <- BankX(bankId, Some(cc)) ?~! {BankNotFound} (fromAccount, callContext) <- BankAccountX(bankId, accountId, Some(cc)) ?~! {AccountNotFound} - ownerView <- APIUtil.checkViewAccessAndReturnView(viewId, BankIdAccountId(fromAccount.bankId, fromAccount.accountId), Some(u), callContext) - _ <- Helper.booleanToBox(ownerView.canSeeTransactionRequestThisBankAccount, s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `canSeeTransactionRequestThisBankAccount` access for the Owner View") + view <- APIUtil.checkViewAccessAndReturnView(viewId, BankIdAccountId(bankId, accountId), Some(u), callContext) + _ <- Helper.booleanToBox(view.canSeeTransactionRequests, s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${ViewDefinition.canSeeTransactionRequests.toString}` permission on the View(${viewId.value} )") (transactionRequests,callContext) <- Connector.connector.vend.getTransactionRequests210(u, fromAccount, callContext) } yield { diff --git a/obp-api/src/main/scala/code/api/v2_2_0/APIMethods220.scala b/obp-api/src/main/scala/code/api/v2_2_0/APIMethods220.scala index 5c10a428b4..974e354066 100644 --- a/obp-api/src/main/scala/code/api/v2_2_0/APIMethods220.scala +++ b/obp-api/src/main/scala/code/api/v2_2_0/APIMethods220.scala @@ -1,6 +1,7 @@ package code.api.v2_2_0 import code.api.Constant.SYSTEM_OWNER_VIEW_ID + import java.util.Date import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON._ import code.api.util.APIUtil._ @@ -23,6 +24,7 @@ import code.model.dataAccess.BankAccountCreation import code.util.Helper import code.util.Helper._ import code.views.Views +import code.views.system.ViewDefinition import com.openbankproject.commons.model._ import net.liftweb.common.{Empty, Full} import net.liftweb.http.rest.RestHelper @@ -100,9 +102,13 @@ trait APIMethods220 { for { (Full(u), callContext) <- authenticatedAccess(cc) (account, callContext) <- NewStyle.function.checkBankAccountExists(bankId, accountId, callContext) - ownerView <- NewStyle.function.checkViewAccessAndReturnView(ViewId(SYSTEM_OWNER_VIEW_ID), BankIdAccountId(bankId, accountId), Some(u), cc.callContext) - _ <- Helper.booleanToFuture(failMsg = s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `canSeeBankAccountAllViews` access for the Owner View", cc = cc.callContext) { - ownerView.canSeeBankAccountAllViews + permission <- NewStyle.function.permission(bankId, accountId, u, callContext) + anyViewContainsCanSeeAvailableViewsForBankAccountPermission = permission.views.map(_.canSeeAvailableViewsForBankAccount).find(_.==(true)).getOrElse(false) + _ <- Helper.booleanToFuture( + s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${ViewDefinition.canSeeAvailableViewsForBankAccount.toString}` permission on any your views", + cc= callContext + ){ + anyViewContainsCanSeeAvailableViewsForBankAccountPermission } views <- Future(Views.views.vend.availableViewsForAccount(BankIdAccountId(account.bankId, account.accountId))) } yield { diff --git a/obp-api/src/main/scala/code/api/v3_0_0/APIMethods300.scala b/obp-api/src/main/scala/code/api/v3_0_0/APIMethods300.scala index faabe19e8b..5e7db318d0 100644 --- a/obp-api/src/main/scala/code/api/v3_0_0/APIMethods300.scala +++ b/obp-api/src/main/scala/code/api/v3_0_0/APIMethods300.scala @@ -110,9 +110,13 @@ trait APIMethods300 { for { (Full(u), callContext) <- authenticatedAccess(cc) (bankAccount, callContext) <- NewStyle.function.getBankAccount(bankId, accountId, callContext) - ownerView <- NewStyle.function.checkViewAccessAndReturnView(ViewId(code.api.Constant.SYSTEM_OWNER_VIEW_ID), BankIdAccountId(bankId, accountId), Some(u), cc.callContext) - _ <- Helper.booleanToFuture(failMsg = s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `canSeeBankAccountAllViews` access for the Owner View", cc = cc.callContext) { - ownerView.canSeeBankAccountAllViews + permission <- NewStyle.function.permission(bankId, accountId, u, callContext) + anyViewContainsCanSeeAvailableViewsForBankAccountPermission = permission.views.map(_.canSeeAvailableViewsForBankAccount).find(_.==(true)).getOrElse(false) + _ <- Helper.booleanToFuture( + s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${code.views.system.ViewDefinition.canSeeAvailableViewsForBankAccount.toString}` permission on any your views", + cc = callContext + ) { + anyViewContainsCanSeeAvailableViewsForBankAccountPermission } } yield { for { diff --git a/obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala b/obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala index a40c056075..e4cbb047bf 100644 --- a/obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala +++ b/obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala @@ -6,7 +6,6 @@ import code.api.Constant.{SYSTEM_OWNER_VIEW_ID, localIdentityProvider} import java.text.SimpleDateFormat import java.util.UUID import java.util.regex.Pattern - import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON._ import code.api.ResourceDocs1_4_0.{MessageDocsSwaggerDefinitions, ResourceDocsAPIMethodsUtil, SwaggerDefinitionsJSON, SwaggerJSONFactory} import code.api.util.APIUtil.{getWebUIPropsPairs, _} @@ -40,6 +39,7 @@ import code.userlocks.{UserLocks, UserLocksProvider} import code.users.Users import code.util.Helper import code.views.Views +import code.views.system.ViewDefinition import code.webhook.AccountWebhook import code.webuiprops.{MappedWebUiPropsProvider, WebUiPropsCommons} import com.github.dwickern.macros.NameOf.nameOf @@ -1086,9 +1086,11 @@ trait APIMethods310 { _ <- NewStyle.function.isEnabledTransactionRequests(callContext) (_, callContext) <- NewStyle.function.getBank(bankId, callContext) (fromAccount, callContext) <- NewStyle.function.checkBankAccountExists(bankId, accountId, callContext) - ownerView <- NewStyle.function.checkViewAccessAndReturnView(ViewId(SYSTEM_OWNER_VIEW_ID), BankIdAccountId(bankId, accountId), Some(u), cc.callContext) - _ <- Helper.booleanToFuture(failMsg = s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `canSeeTransactionRequestThisBankAccount` access for the Owner View", cc = cc.callContext) { - ownerView.canSeeTransactionRequestThisBankAccount + view <- NewStyle.function.checkAccountAccessAndGetView(viewId, BankIdAccountId(bankId, accountId), Full(u), callContext) + _ <- Helper.booleanToFuture( + s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${ViewDefinition.canSeeTransactionRequests.toString}` permission on the View(${viewId.value})", + cc=callContext){ + view.canSeeTransactionRequests } (transactionRequests, callContext) <- Future(Connector.connector.vend.getTransactionRequests210(u, fromAccount, callContext)) map { unboxFullOrFail(_, callContext, GetTransactionRequestsException) diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index 76022c187b..8c6d64dfec 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -75,6 +75,7 @@ import code.util.Helper.booleanToFuture import code.util.{Helper, JsonSchemaUtil} import code.validation.JsonValidation import code.views.Views +import code.views.system.ViewDefinition import code.webhook.{AccountWebhook, BankAccountNotificationWebhookTrait, SystemAccountNotificationWebhookTrait} import code.webuiprops.MappedWebUiPropsProvider.getWebUiPropsValue import com.github.dwickern.macros.NameOf.nameOf @@ -5150,9 +5151,11 @@ trait APIMethods400 { for { (user @Full(u), _, account, view, callContext) <- SS.userBankAccountView _ <- NewStyle.function.isEnabledTransactionRequests(callContext) - ownerView <- NewStyle.function.checkViewAccessAndReturnView(ViewId(SYSTEM_OWNER_VIEW_ID), BankIdAccountId(bankId, accountId), Some(u), cc.callContext) - _ <- Helper.booleanToFuture(failMsg = s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `canSeeTransactionRequestThisBankAccount` access for the Owner View", cc = cc.callContext) { - ownerView.canSeeTransactionRequestThisBankAccount + view <- NewStyle.function.checkAccountAccessAndGetView(viewId, BankIdAccountId(bankId, accountId), Full(u), callContext) + _ <- Helper.booleanToFuture( + s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${ViewDefinition.canSeeTransactionRequests.toString}` permission on the View(${viewId.value})", + cc = callContext) { + view.canSeeTransactionRequests } (transactionRequest, callContext) <- NewStyle.function.getTransactionRequestImpl(requestId, callContext) } yield { diff --git a/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala b/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala index d503f9ee65..d1fe57c362 100644 --- a/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala +++ b/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala @@ -1,7 +1,6 @@ package code.api.v5_0_0 import java.util.concurrent.ThreadLocalRandom - import code.accountattribute.AccountAttributeX import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON._ @@ -40,12 +39,12 @@ import net.liftweb.json import net.liftweb.json.{Extraction, compactRender, prettyRender} import net.liftweb.util.Helpers.tryo import net.liftweb.util.{Helpers, Props} -import java.util.concurrent.ThreadLocalRandom +import java.util.concurrent.ThreadLocalRandom import code.accountattribute.AccountAttributeX import code.api.Constant.SYSTEM_OWNER_VIEW_ID import code.util.Helper.booleanToFuture -import code.views.system.AccountAccess +import code.views.system.{AccountAccess, ViewDefinition} import scala.collection.immutable.{List, Nil} import scala.collection.mutable.ArrayBuffer @@ -1592,9 +1591,13 @@ trait APIMethods500 { val res = for { (Full(u), callContext) <- SS.user - ownerView <- NewStyle.function.checkViewAccessAndReturnView(ViewId(SYSTEM_OWNER_VIEW_ID), BankIdAccountId(bankId, accountId), Some(u), cc.callContext) - _ <- Helper.booleanToFuture(failMsg = s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `canSeeBankAccountAllViews` access for the Owner View", cc=cc.callContext){ - ownerView.canSeeBankAccountAllViews + permission <- NewStyle.function.permission(bankId, accountId, u, callContext) + anyViewContainsCanSeeAvailableViewsForBankAccountPermission = permission.views.map(_.canSeeAvailableViewsForBankAccount).find(_.==(true)).getOrElse(false) + _ <- Helper.booleanToFuture( + s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${ViewDefinition.canSeeAvailableViewsForBankAccount.toString}` permission on any your views", + cc = callContext + ) { + anyViewContainsCanSeeAvailableViewsForBankAccountPermission } } yield { for { diff --git a/obp-api/src/main/scala/code/model/View.scala b/obp-api/src/main/scala/code/model/View.scala index e76231a7df..aed6d412ed 100644 --- a/obp-api/src/main/scala/code/model/View.scala +++ b/obp-api/src/main/scala/code/model/View.scala @@ -354,7 +354,7 @@ case class ViewExtended(val view: View) { ) } else - Failure(s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `canSeeTransactionThisBankAccount` access for the view(${view.viewId.value})") + Failure(s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `canSeeTransactionThisBankAccount` permission on the view(${view.viewId.value})") } @deprecated("This have the performance issue, call `Connector.connector.vend.getBankLegacy` four times in the backend. use @moderateAccount instead ","08-01-2020") @@ -402,7 +402,7 @@ case class ViewExtended(val view: View) { ) } else - Failure(s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `canSeeTransactionThisBankAccount` access for the view(${view.viewId.value})") + Failure(s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `canSeeTransactionThisBankAccount` permission on the view(${view.viewId.value})") } def moderateAccountCore(bankAccount: BankAccount) : Box[ModeratedBankAccountCore] = { @@ -435,7 +435,7 @@ case class ViewExtended(val view: View) { ) } else - Failure(s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `canSeeTransactionThisBankAccount` access for the view(${view.viewId.value})") + Failure(s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `canSeeTransactionThisBankAccount` permission on the view(${view.viewId.value})") } // Moderate the Counterparty side of the Transaction (i.e. the Other Account involved in the transaction) @@ -558,7 +558,7 @@ case class ViewExtended(val view: View) { ) } else - Failure(s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `canSeeTransactionOtherBankAccount` access for the view(${view.viewId.value})") + Failure(s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `canSeeTransactionOtherBankAccount` permission on the view(${view.viewId.value})") } def moderateCore(counterpartyCore : CounterpartyCore) : Box[ModeratedOtherBankAccountCore] = { @@ -607,6 +607,6 @@ case class ViewExtended(val view: View) { ) } else - Failure(s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `canSeeTransactionOtherBankAccount` access for the view(${view.viewId.value})") + Failure(s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `canSeeTransactionOtherBankAccount` permission on the view(${view.viewId.value})") } } diff --git a/obp-api/src/main/scala/code/model/dataAccess/MappedView.scala b/obp-api/src/main/scala/code/model/dataAccess/MappedView.scala index d1029a160a..8a7387db57 100644 --- a/obp-api/src/main/scala/code/model/dataAccess/MappedView.scala +++ b/obp-api/src/main/scala/code/model/dataAccess/MappedView.scala @@ -204,7 +204,7 @@ class ViewImpl extends View with LongKeyedMapper[ViewImpl] with ManyToMany with override def defaultValue = false } - object canSeeTransactionRequestThisBankAccount_ extends MappedBoolean(this){ + object canSeeTransactionRequests_ extends MappedBoolean(this){ override def defaultValue = false } object canSeeTransactionOtherBankAccount_ extends MappedBoolean(this){ @@ -249,8 +249,8 @@ class ViewImpl extends View with LongKeyedMapper[ViewImpl] with ManyToMany with object canSeeBankAccountOwners_ extends MappedBoolean(this){ override def defaultValue = false } - object canSeeBankAccountAllViews_ extends MappedBoolean(this){ - override def defaultValue = false + object canSeeAvailableViewsForBankAccount_ extends MappedBoolean(this){ + override def defaultValue = true } object canSeeBankAccountType_ extends MappedBoolean(this){ override def defaultValue = false @@ -455,7 +455,7 @@ class ViewImpl extends View with LongKeyedMapper[ViewImpl] with ManyToMany with //transaction fields def canSeeTransactionThisBankAccount : Boolean = canSeeTransactionThisBankAccount_.get - def canSeeTransactionRequestThisBankAccount : Boolean = canSeeTransactionRequestThisBankAccount_.get + def canSeeTransactionRequests : Boolean = canSeeTransactionRequests_.get def canSeeTransactionOtherBankAccount : Boolean = canSeeTransactionOtherBankAccount_.get def canSeeTransactionMetadata : Boolean = canSeeTransactionMetadata_.get def canSeeTransactionDescription: Boolean = canSeeTransactionDescription_.get @@ -473,7 +473,7 @@ class ViewImpl extends View with LongKeyedMapper[ViewImpl] with ManyToMany with def canSeeImages : Boolean = canSeeImages_.get //Bank account fields - def canSeeBankAccountAllViews : Boolean = canSeeBankAccountAllViews_.get + def canSeeAvailableViewsForBankAccount : Boolean = canSeeAvailableViewsForBankAccount_.get def canSeeBankAccountOwners : Boolean = canSeeBankAccountOwners_.get def canSeeBankAccountType : Boolean = canSeeBankAccountType_.get def canSeeBankAccountBalance : Boolean = canSeeBankAccountBalance_.get diff --git a/obp-api/src/main/scala/code/views/MapperViews.scala b/obp-api/src/main/scala/code/views/MapperViews.scala index 2c6c0ba1d9..236b1e2b31 100644 --- a/obp-api/src/main/scala/code/views/MapperViews.scala +++ b/obp-api/src/main/scala/code/views/MapperViews.scala @@ -790,14 +790,14 @@ object MapperViews extends Views with MdcLoggable { .canSeeOtherAccountRoutingAddress_(true) .canAddTransactionRequestToOwnAccount_(true) //added following two for payments .canAddTransactionRequestToAnyAccount_(true) - .canSeeBankAccountAllViews_(false) - .canSeeTransactionRequestThisBankAccount_(false) + .canSeeAvailableViewsForBankAccount_(false) + .canSeeTransactionRequests_(false) viewId match { case SYSTEM_OWNER_VIEW_ID => entity - .canSeeBankAccountAllViews_(true) - .canSeeTransactionRequestThisBankAccount_(true) + .canSeeAvailableViewsForBankAccount_(true) + .canSeeTransactionRequests_(true) case SYSTEM_STAGE_ONE_VIEW_ID => entity .canSeeTransactionDescription_(false) diff --git a/obp-api/src/main/scala/code/views/system/ViewDefinition.scala b/obp-api/src/main/scala/code/views/system/ViewDefinition.scala index b778858c1e..48809e2132 100644 --- a/obp-api/src/main/scala/code/views/system/ViewDefinition.scala +++ b/obp-api/src/main/scala/code/views/system/ViewDefinition.scala @@ -60,7 +60,7 @@ class ViewDefinition extends View with LongKeyedMapper[ViewDefinition] with Many object canSeeTransactionThisBankAccount_ extends MappedBoolean(this){ override def defaultValue = false } - object canSeeTransactionRequestThisBankAccount_ extends MappedBoolean(this){ + object canSeeTransactionRequests_ extends MappedBoolean(this){ override def defaultValue = false } object canSeeTransactionOtherBankAccount_ extends MappedBoolean(this){ @@ -105,8 +105,8 @@ class ViewDefinition extends View with LongKeyedMapper[ViewDefinition] with Many object canSeeBankAccountOwners_ extends MappedBoolean(this){ override def defaultValue = false } - object canSeeBankAccountAllViews_ extends MappedBoolean(this){ - override def defaultValue = false + object canSeeAvailableViewsForBankAccount_ extends MappedBoolean(this){ + override def defaultValue = true } object canSeeBankAccountType_ extends MappedBoolean(this){ override def defaultValue = false @@ -442,7 +442,7 @@ class ViewDefinition extends View with LongKeyedMapper[ViewDefinition] with Many //transaction fields def canSeeTransactionThisBankAccount : Boolean = canSeeTransactionThisBankAccount_.get - def canSeeTransactionRequestThisBankAccount : Boolean = canSeeTransactionRequestThisBankAccount_.get + def canSeeTransactionRequests : Boolean = canSeeTransactionRequests_.get def canSeeTransactionOtherBankAccount : Boolean = canSeeTransactionOtherBankAccount_.get def canSeeTransactionMetadata : Boolean = canSeeTransactionMetadata_.get def canSeeTransactionDescription: Boolean = canSeeTransactionDescription_.get @@ -460,7 +460,7 @@ class ViewDefinition extends View with LongKeyedMapper[ViewDefinition] with Many def canSeeImages : Boolean = canSeeImages_.get //Bank account fields - def canSeeBankAccountAllViews : Boolean = canSeeBankAccountAllViews_.get + def canSeeAvailableViewsForBankAccount : Boolean = canSeeAvailableViewsForBankAccount_.get def canSeeBankAccountOwners : Boolean = canSeeBankAccountOwners_.get def canSeeBankAccountType : Boolean = canSeeBankAccountType_.get def canSeeBankAccountBalance : Boolean = canSeeBankAccountBalance_.get diff --git a/obp-commons/src/main/scala/com/openbankproject/commons/model/ViewModel.scala b/obp-commons/src/main/scala/com/openbankproject/commons/model/ViewModel.scala index f75e9b43dd..c83a2cd151 100644 --- a/obp-commons/src/main/scala/com/openbankproject/commons/model/ViewModel.scala +++ b/obp-commons/src/main/scala/com/openbankproject/commons/model/ViewModel.scala @@ -258,7 +258,7 @@ trait View { //reading access //transaction fields - def canSeeTransactionRequestThisBankAccount: Boolean + def canSeeTransactionRequests: Boolean def canSeeTransactionThisBankAccount: Boolean @@ -290,7 +290,7 @@ trait View { def canSeeImages: Boolean //Bank account fields - def canSeeBankAccountAllViews: Boolean + def canSeeAvailableViewsForBankAccount: Boolean def canSeeBankAccountOwners: Boolean From 558460b6c17391e780ab8bc72b7e13d74380a959 Mon Sep 17 00:00:00 2001 From: hongwei Date: Fri, 16 Jun 2023 17:39:04 +0800 Subject: [PATCH 05/41] refactor/remove `hasOwnerViewAccess` replace with specific view permissions- tweaked error message --- obp-api/src/main/scala/code/api/util/ErrorMessages.scala | 1 - obp-api/src/main/scala/code/api/util/NewStyle.scala | 2 +- obp-api/src/main/scala/code/api/v1_2_1/APIMethods121.scala | 2 +- obp-api/src/main/scala/code/api/v1_4_0/APIMethods140.scala | 3 +-- obp-api/src/main/scala/code/api/v2_1_0/APIMethods210.scala | 3 ++- obp-api/src/main/scala/code/api/v2_2_0/APIMethods220.scala | 2 +- obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala | 3 ++- obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala | 2 +- obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala | 2 +- .../group/v1_3/AccountInformationServiceAISApiTest.scala | 6 +++--- .../test/scala/code/api/v3_1_0/TransactionRequestTest.scala | 2 +- 11 files changed, 14 insertions(+), 14 deletions(-) diff --git a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala index 1326ac1bf7..c2a79a755b 100644 --- a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala +++ b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala @@ -181,7 +181,6 @@ object ErrorMessages { val ConsumerIsDisabled = "OBP-20058: Consumer is disabled." val CouldNotGetUserLockStatus = "OBP-20059: Could not get the lock status of the user." val NoViewReadAccountsBerlinGroup = s"OBP-20060: User does not have access to the view $SYSTEM_READ_ACCOUNTS_BERLIN_GROUP_VIEW_ID." - val NoAccountAccessOnView = "OBP-20061: Current user does not have access to the view " val FrequencyPerDayError = "OBP-20062: Frequency per day must be greater than 0." val FrequencyPerDayMustBeOneError = "OBP-20063: Frequency per day must be equal to 1 in case of one-off access." 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 e3dc2b4be0..b67c6f5415 100644 --- a/obp-api/src/main/scala/code/api/util/NewStyle.scala +++ b/obp-api/src/main/scala/code/api/util/NewStyle.scala @@ -592,7 +592,7 @@ object NewStyle extends MdcLoggable{ Future{ APIUtil.checkViewAccessAndReturnView(viewId, bankAccountId, user, callContext) } map { - unboxFullOrFail(_, callContext, s"$NoAccountAccessOnView ${viewId.value}", 403) + unboxFullOrFail(_, callContext, s"$UserNoPermissionAccessView ${viewId.value}", 403) } } def checkViewsAccessAndReturnView(firstView : ViewId, secondView : ViewId, bankAccountId: BankIdAccountId, user: Option[User], callContext: Option[CallContext]) : Future[View] = { diff --git a/obp-api/src/main/scala/code/api/v1_2_1/APIMethods121.scala b/obp-api/src/main/scala/code/api/v1_2_1/APIMethods121.scala index 35a6ee04e8..7f7a564c97 100644 --- a/obp-api/src/main/scala/code/api/v1_2_1/APIMethods121.scala +++ b/obp-api/src/main/scala/code/api/v1_2_1/APIMethods121.scala @@ -548,7 +548,7 @@ trait APIMethods121 { anyViewContainsCanSeeAvailableViewsForBankAccountPermission = permission.views.map(_.canSeeAvailableViewsForBankAccount).find(_.==(true)).getOrElse(false) _ <- Helper.booleanToBox( anyViewContainsCanSeeAvailableViewsForBankAccountPermission, - s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${ViewDefinition.canSeeAvailableViewsForBankAccount.toString}` permission on any your views" + s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${ViewDefinition.canSeeAvailableViewsForBankAccount_.dbColumnName}` permission on any your views" ) views <- Full(Views.views.vend.availableViewsForAccount(BankIdAccountId(bankAccount.bankId, bankAccount.accountId))) } yield { diff --git a/obp-api/src/main/scala/code/api/v1_4_0/APIMethods140.scala b/obp-api/src/main/scala/code/api/v1_4_0/APIMethods140.scala index 52954aff05..748b9e874d 100644 --- a/obp-api/src/main/scala/code/api/v1_4_0/APIMethods140.scala +++ b/obp-api/src/main/scala/code/api/v1_4_0/APIMethods140.scala @@ -1,6 +1,5 @@ package code.api.v1_4_0 -import code.api.Constant.SYSTEM_OWNER_VIEW_ID import code.api.util.ApiRole._ import code.api.util.ApiTag._ import code.api.util.NewStyle.HttpCode @@ -468,7 +467,7 @@ trait APIMethods140 extends MdcLoggable with APIMethods130 with APIMethods121{ view <- APIUtil.checkViewAccessAndReturnView(viewId, BankIdAccountId(bankId, accountId), Some(u), callContext) _ <- Helper.booleanToBox( view.canSeeTransactionRequests, - s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${ViewDefinition.canSeeTransactionRequests.toString}` permission on the View(${viewId.value})" + s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${ViewDefinition.canSeeTransactionRequests_.dbColumnName}` permission on the View(${viewId.value})" ) transactionRequests <- Connector.connector.vend.getTransactionRequests(u, fromAccount, callContext) } diff --git a/obp-api/src/main/scala/code/api/v2_1_0/APIMethods210.scala b/obp-api/src/main/scala/code/api/v2_1_0/APIMethods210.scala index 26a8fb23dd..bda9fb632f 100644 --- a/obp-api/src/main/scala/code/api/v2_1_0/APIMethods210.scala +++ b/obp-api/src/main/scala/code/api/v2_1_0/APIMethods210.scala @@ -715,7 +715,8 @@ trait APIMethods210 { (bank, callContext ) <- BankX(bankId, Some(cc)) ?~! {BankNotFound} (fromAccount, callContext) <- BankAccountX(bankId, accountId, Some(cc)) ?~! {AccountNotFound} view <- APIUtil.checkViewAccessAndReturnView(viewId, BankIdAccountId(bankId, accountId), Some(u), callContext) - _ <- Helper.booleanToBox(view.canSeeTransactionRequests, s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${ViewDefinition.canSeeTransactionRequests.toString}` permission on the View(${viewId.value} )") + _ <- Helper.booleanToBox(view.canSeeTransactionRequests, + s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${ViewDefinition.canSeeTransactionRequests_.dbColumnName}` permission on the View(${viewId.value} )") (transactionRequests,callContext) <- Connector.connector.vend.getTransactionRequests210(u, fromAccount, callContext) } yield { diff --git a/obp-api/src/main/scala/code/api/v2_2_0/APIMethods220.scala b/obp-api/src/main/scala/code/api/v2_2_0/APIMethods220.scala index 974e354066..d5a9360235 100644 --- a/obp-api/src/main/scala/code/api/v2_2_0/APIMethods220.scala +++ b/obp-api/src/main/scala/code/api/v2_2_0/APIMethods220.scala @@ -105,7 +105,7 @@ trait APIMethods220 { permission <- NewStyle.function.permission(bankId, accountId, u, callContext) anyViewContainsCanSeeAvailableViewsForBankAccountPermission = permission.views.map(_.canSeeAvailableViewsForBankAccount).find(_.==(true)).getOrElse(false) _ <- Helper.booleanToFuture( - s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${ViewDefinition.canSeeAvailableViewsForBankAccount.toString}` permission on any your views", + s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${ViewDefinition.canSeeAvailableViewsForBankAccount_.dbColumnName}` permission on any your views", cc= callContext ){ anyViewContainsCanSeeAvailableViewsForBankAccountPermission diff --git a/obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala b/obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala index e4cbb047bf..6ba6453dfe 100644 --- a/obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala +++ b/obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala @@ -1072,6 +1072,7 @@ trait APIMethods310 { BankNotFound, BankAccountNotFound, UserNoPermissionAccessView, + ViewDoesNotPermitAccess, UserNoOwnerView, GetTransactionRequestsException, UnknownError @@ -1088,7 +1089,7 @@ trait APIMethods310 { (fromAccount, callContext) <- NewStyle.function.checkBankAccountExists(bankId, accountId, callContext) view <- NewStyle.function.checkAccountAccessAndGetView(viewId, BankIdAccountId(bankId, accountId), Full(u), callContext) _ <- Helper.booleanToFuture( - s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${ViewDefinition.canSeeTransactionRequests.toString}` permission on the View(${viewId.value})", + s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${ViewDefinition.canSeeTransactionRequests_.dbColumnName}` permission on the View(${viewId.value})", cc=callContext){ view.canSeeTransactionRequests } diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index 8c6d64dfec..76220504e7 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -5153,7 +5153,7 @@ trait APIMethods400 { _ <- NewStyle.function.isEnabledTransactionRequests(callContext) view <- NewStyle.function.checkAccountAccessAndGetView(viewId, BankIdAccountId(bankId, accountId), Full(u), callContext) _ <- Helper.booleanToFuture( - s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${ViewDefinition.canSeeTransactionRequests.toString}` permission on the View(${viewId.value})", + s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${ViewDefinition.canSeeTransactionRequests_.dbColumnName}` permission on the View(${viewId.value})", cc = callContext) { view.canSeeTransactionRequests } diff --git a/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala b/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala index d1fe57c362..0b49d9d807 100644 --- a/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala +++ b/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala @@ -1594,7 +1594,7 @@ trait APIMethods500 { permission <- NewStyle.function.permission(bankId, accountId, u, callContext) anyViewContainsCanSeeAvailableViewsForBankAccountPermission = permission.views.map(_.canSeeAvailableViewsForBankAccount).find(_.==(true)).getOrElse(false) _ <- Helper.booleanToFuture( - s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${ViewDefinition.canSeeAvailableViewsForBankAccount.toString}` permission on any your views", + s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${ViewDefinition.canSeeAvailableViewsForBankAccount_.dbColumnName}` permission on any your views", cc = callContext ) { anyViewContainsCanSeeAvailableViewsForBankAccountPermission diff --git a/obp-api/src/test/scala/code/api/berlin/group/v1_3/AccountInformationServiceAISApiTest.scala b/obp-api/src/test/scala/code/api/berlin/group/v1_3/AccountInformationServiceAISApiTest.scala index c116d7d67b..5ccb9afeba 100644 --- a/obp-api/src/test/scala/code/api/berlin/group/v1_3/AccountInformationServiceAISApiTest.scala +++ b/obp-api/src/test/scala/code/api/berlin/group/v1_3/AccountInformationServiceAISApiTest.scala @@ -132,7 +132,7 @@ class AccountInformationServiceAISApiTest extends BerlinGroupServerSetupV1_3 wit val responseGetFailed: APIResponse = makeGetRequest(requestGetFailed) Then("We should get a 403 ") responseGetFailed.code should equal(403) - responseGetFailed.body.extract[ErrorMessage].message should startWith(NoAccountAccessOnView) + responseGetFailed.body.extract[ErrorMessage].message should startWith(UserNoPermissionAccessView) val bankId = MappedBankAccount.find(By(MappedBankAccount.theAccountId, testAccountId.value)).map(_.bankId.value).getOrElse("") grantUserAccessToViewViaEndpoint( @@ -161,7 +161,7 @@ class AccountInformationServiceAISApiTest extends BerlinGroupServerSetupV1_3 wit val responseGetFailed: APIResponse = makeGetRequest(requestGetFailed) Then("We should get a 403 ") responseGetFailed.code should equal(403) - responseGetFailed.body.extract[ErrorMessage].message should startWith(NoAccountAccessOnView) + responseGetFailed.body.extract[ErrorMessage].message should startWith(UserNoPermissionAccessView) val bankId = MappedBankAccount.find(By(MappedBankAccount.theAccountId, testAccountId.value)).map(_.bankId.value).getOrElse("") grantUserAccessToViewViaEndpoint( @@ -195,7 +195,7 @@ class AccountInformationServiceAISApiTest extends BerlinGroupServerSetupV1_3 wit val responseGetFailed: APIResponse = makeGetRequest(requestGetFailed) Then("We should get a 403 ") responseGetFailed.code should equal(403) - responseGetFailed.body.extract[ErrorMessage].message should startWith(NoAccountAccessOnView) + responseGetFailed.body.extract[ErrorMessage].message should startWith(UserNoPermissionAccessView) val bankId = MappedBankAccount.find(By(MappedBankAccount.theAccountId, testAccountId.value)).map(_.bankId.value).getOrElse("") grantUserAccessToViewViaEndpoint( diff --git a/obp-api/src/test/scala/code/api/v3_1_0/TransactionRequestTest.scala b/obp-api/src/test/scala/code/api/v3_1_0/TransactionRequestTest.scala index 045c072843..cc8a23212a 100644 --- a/obp-api/src/test/scala/code/api/v3_1_0/TransactionRequestTest.scala +++ b/obp-api/src/test/scala/code/api/v3_1_0/TransactionRequestTest.scala @@ -85,7 +85,7 @@ class TransactionRequestTest extends V310ServerSetup { Then("We should get a 403") response310.code should equal(403) And("error should be " + UserNoPermissionAccessView) - response310.body.extract[ErrorMessage].message should equal (UserNoPermissionAccessView) + response310.body.extract[ErrorMessage].message contains (UserNoPermissionAccessView) shouldBe (true) } } From 6c04cf40d720635f3b620496f0b96e4902811aa4 Mon Sep 17 00:00:00 2001 From: hongwei Date: Thu, 22 Jun 2023 17:35:23 +0800 Subject: [PATCH 06/41] refactor/remove `hasOwnerViewAccess` replace with specific view permissions- use canAddTransactionRequestToOwnAccount permission --- .../group/v1_3/PaymentInitiationServicePISApi.scala | 13 ++++++++++--- .../main/scala/code/api/v2_0_0/APIMethods200.scala | 11 ++++++----- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/obp-api/src/main/scala/code/api/berlin/group/v1_3/PaymentInitiationServicePISApi.scala b/obp-api/src/main/scala/code/api/berlin/group/v1_3/PaymentInitiationServicePISApi.scala index 5e4fba6bc6..858ac4108d 100644 --- a/obp-api/src/main/scala/code/api/berlin/group/v1_3/PaymentInitiationServicePISApi.scala +++ b/obp-api/src/main/scala/code/api/berlin/group/v1_3/PaymentInitiationServicePISApi.scala @@ -14,6 +14,7 @@ import code.model._ import code.transactionrequests.TransactionRequests.TransactionRequestTypes.SEPA_CREDIT_TRANSFERS import code.transactionrequests.TransactionRequests.{PaymentServiceTypes, TransactionRequestTypes} import code.util.Helper +import code.views.Views import com.github.dwickern.macros.NameOf.nameOf import com.openbankproject.commons.ExecutionContext.Implicits.global import com.openbankproject.commons.model._ @@ -565,10 +566,16 @@ $additionalInstructions _ <- Helper.booleanToFuture(invalidIban, cc=callContext) { ibanChecker.isValid == true } (toAccount, callContext) <- NewStyle.function.getToBankAccountByIban(toAccountIban, callContext) - _ <- if (u.hasOwnerViewAccess(BankIdAccountId(fromAccount.bankId,fromAccount.accountId), callContext)) Future.successful(Full(Unit)) - else NewStyle.function.hasEntitlement(fromAccount.bankId.value, u.userId, ApiRole.canCreateAnyTransactionRequest, callContext, InsufficientAuthorisationToCreateTransactionRequest) + //no accountAccess and no canAddTransactionRequestToOwnAccount ==> this will not throw exception,only return false! + anyViewContainsCanAddTransactionRequestToOwnAccountPermission = Views.views.vend.permission(BankIdAccountId(fromAccount.bankId, fromAccount.accountId), u) + .map(_.views.map(_.canAddTransactionRequestToOwnAccount).find(_.==(true)).getOrElse(false)).getOrElse(false) - // Prevent default value for transaction request type (at least). + _ <- if (anyViewContainsCanAddTransactionRequestToOwnAccountPermission) + Future.successful(Full(Unit)) + else + NewStyle.function.hasEntitlement(fromAccount.bankId.value, u.userId, ApiRole.canCreateAnyTransactionRequest, callContext, InsufficientAuthorisationToCreateTransactionRequest) + + // Prevent default value for transaction request type (at least). _ <- Helper.booleanToFuture(s"From Account Currency is ${fromAccount.currency}, but Requested Transaction Currency is: ${transDetailsJson.instructedAmount.currency}", cc=callContext) { transDetailsJson.instructedAmount.currency == fromAccount.currency } diff --git a/obp-api/src/main/scala/code/api/v2_0_0/APIMethods200.scala b/obp-api/src/main/scala/code/api/v2_0_0/APIMethods200.scala index 3ed99e5e1b..c1605f0c05 100644 --- a/obp-api/src/main/scala/code/api/v2_0_0/APIMethods200.scala +++ b/obp-api/src/main/scala/code/api/v2_0_0/APIMethods200.scala @@ -1281,9 +1281,9 @@ trait APIMethods200 { _ <- tryo(assert(isValidID(accountId.value)))?~! InvalidAccountIdFormat (bank, callContext ) <- BankX(bankId, Some(cc)) ?~! BankNotFound fromAccount <- BankAccountX(bankId, accountId) ?~! AccountNotFound - _ <-APIUtil.checkViewAccessAndReturnView(viewId, BankIdAccountId(fromAccount.bankId, fromAccount.accountId), Some(u), callContext) match { + _ <- APIUtil.checkViewAccessAndReturnView(viewId, BankIdAccountId(fromAccount.bankId, fromAccount.accountId), Some(u), callContext).map(_.canAddTransactionRequestToOwnAccount) match { case Full(_) => - booleanToBox(u.hasOwnerViewAccess(BankIdAccountId(fromAccount.bankId,fromAccount.accountId), callContext) == true) + Full (Unit) case _ => NewStyle.function.ownEntitlement(fromAccount.bankId.value, u.userId, canCreateAnyTransactionRequest, cc.callContext, InsufficientAuthorisationToCreateTransactionRequest) } @@ -1350,9 +1350,10 @@ trait APIMethods200 { (bank, callContext ) <- BankX(bankId, Some(cc)) ?~! BankNotFound fromAccount <- BankAccountX(bankId, accountId) ?~! AccountNotFound view <-APIUtil.checkViewAccessAndReturnView(viewId, BankIdAccountId(fromAccount.bankId, fromAccount.accountId), Some(u), callContext) - _ <- if (u.hasOwnerViewAccess(BankIdAccountId(fromAccount.bankId,fromAccount.accountId), callContext)) Full(Unit) - else NewStyle.function.ownEntitlement(fromAccount.bankId.value, u.userId, canCreateAnyTransactionRequest, cc.callContext, InsufficientAuthorisationToCreateTransactionRequest) - // Note: These checks are not in the ideal order. See version 2.1.0 which supercedes this + _ <- if (view.canAddTransactionRequestToOwnAccount) + Full(Unit) + else + NewStyle.function.ownEntitlement(fromAccount.bankId.value, u.userId, canCreateAnyTransactionRequest, cc.callContext, InsufficientAuthorisationToCreateTransactionRequest) answerJson <- tryo{json.extract[ChallengeAnswerJSON]} ?~! InvalidJsonFormat _ <- Connector.connector.vend.answerTransactionRequestChallenge(transReqId, answerJson.answer) From 4f632aea771e7962e10c7f4416e669493daaab8f Mon Sep 17 00:00:00 2001 From: hongwei Date: Thu, 22 Jun 2023 19:13:22 +0800 Subject: [PATCH 07/41] refactor/remove `hasOwnerViewAccess` replace with specific view permissions -- unify all the payments logic --- .../v1_3/PaymentInitiationServicePISApi.scala | 6 ++--- .../main/scala/code/api/util/APIUtil.scala | 20 ++++++++++++++++- .../scala/code/api/util/ErrorMessages.scala | 7 +++--- .../main/scala/code/api/util/NewStyle.scala | 17 +------------- .../scala/code/api/v1_4_0/APIMethods140.scala | 13 ++++++++++- .../scala/code/api/v2_0_0/APIMethods200.scala | 22 +++++++++---------- .../scala/code/bankconnectors/Connector.scala | 3 --- .../bankconnectors/LocalMappedConnector.scala | 3 --- .../api/v2_0_0/TransactionRequestsTest.scala | 4 ++-- 9 files changed, 52 insertions(+), 43 deletions(-) diff --git a/obp-api/src/main/scala/code/api/berlin/group/v1_3/PaymentInitiationServicePISApi.scala b/obp-api/src/main/scala/code/api/berlin/group/v1_3/PaymentInitiationServicePISApi.scala index 858ac4108d..a3df2d673f 100644 --- a/obp-api/src/main/scala/code/api/berlin/group/v1_3/PaymentInitiationServicePISApi.scala +++ b/obp-api/src/main/scala/code/api/berlin/group/v1_3/PaymentInitiationServicePISApi.scala @@ -567,10 +567,10 @@ $additionalInstructions (toAccount, callContext) <- NewStyle.function.getToBankAccountByIban(toAccountIban, callContext) //no accountAccess and no canAddTransactionRequestToOwnAccount ==> this will not throw exception,only return false! - anyViewContainsCanAddTransactionRequestToOwnAccountPermission = Views.views.vend.permission(BankIdAccountId(fromAccount.bankId, fromAccount.accountId), u) - .map(_.views.map(_.canAddTransactionRequestToOwnAccount).find(_.==(true)).getOrElse(false)).getOrElse(false) + anyViewContainsCanAddTransactionRequestToAnyAccountPermission = Views.views.vend.permission(BankIdAccountId(fromAccount.bankId, fromAccount.accountId), u) + .map(_.views.map(_.canAddTransactionRequestToAnyAccount).find(_.==(true)).getOrElse(false)).getOrElse(false) - _ <- if (anyViewContainsCanAddTransactionRequestToOwnAccountPermission) + _ <- if (anyViewContainsCanAddTransactionRequestToAnyAccountPermission) Future.successful(Full(Unit)) else NewStyle.function.hasEntitlement(fromAccount.bankId.value, u.userId, ApiRole.canCreateAnyTransactionRequest, callContext, InsufficientAuthorisationToCreateTransactionRequest) diff --git a/obp-api/src/main/scala/code/api/util/APIUtil.scala b/obp-api/src/main/scala/code/api/util/APIUtil.scala index 7b2c484aa2..9bc9592a1a 100644 --- a/obp-api/src/main/scala/code/api/util/APIUtil.scala +++ b/obp-api/src/main/scala/code/api/util/APIUtil.scala @@ -47,7 +47,7 @@ import code.api.dynamic.endpoint.helper.{DynamicEndpointHelper, DynamicEndpoints import code.api.oauth1a.Arithmetics import code.api.oauth1a.OauthParams._ import code.api.util.APIUtil.ResourceDoc.{findPathVariableNames, isPathVariable} -import code.api.util.ApiRole.{canCreateProduct, canCreateProductAtAnyBank} +import code.api.util.ApiRole.{canCreateAnyTransactionRequest, canCreateProduct, canCreateProductAtAnyBank} import code.api.util.ApiTag.{ResourceDocTag, apiTagBank} import code.api.util.Glossary.GlossaryItem import code.api.util.RateLimitingJson.CallLimit @@ -3614,6 +3614,24 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{ } } + final def checkAuthorisationToCreateTransactionRequest(viewId: ViewId, bankAccountId: BankIdAccountId, user: User, callContext: Option[CallContext]): Box[Boolean] = { + lazy val hasCanCreateAnyTransactionRequestRole = APIUtil.hasEntitlement(bankAccountId.bankId.value, user.userId, canCreateAnyTransactionRequest) + + lazy val view = APIUtil.checkViewAccessAndReturnView(viewId, bankAccountId, Some(user), callContext) + + lazy val canAddTransactionRequestToAnyAccount = view.map(_.canAddTransactionRequestToAnyAccount).getOrElse(false) + + //1st check the admin level role/entitlement `canCreateAnyTransactionRequest` + if (hasCanCreateAnyTransactionRequestRole) { + Full(true) + //2rd: check if the user have the view access and the view has the `canAddTransactionRequestToAnyAccount` permission + } else if (canAddTransactionRequestToAnyAccount) { + Full(true) + } else { + Empty + } + } + // TODO Use this in code as a single point of entry whenever we need to check owner view def isOwnerView(viewId: ViewId): Boolean = { viewId.value == SYSTEM_OWNER_VIEW_ID || diff --git a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala index c2a79a755b..610747fc57 100644 --- a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala +++ b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala @@ -6,6 +6,7 @@ import java.util.regex.Pattern import com.openbankproject.commons.model.enums.TransactionRequestStatus._ import code.api.Constant._ import code.api.util.ApiRole.{CanCreateAnyTransactionRequest, canCreateEntitlementAtAnyBank, canCreateEntitlementAtOneBank} +import code.views.system.ViewDefinition object ErrorMessages { import code.api.util.APIUtil._ @@ -538,9 +539,9 @@ object ErrorMessages { val InsufficientAuthorisationToCreateTransactionRequest = "OBP-40002: Insufficient authorisation to create TransactionRequest. " + "The Transaction Request could not be created " + "because the login user doesn't have access to the view of the from account " + - s"or the view don't have the `${CanCreateAnyTransactionRequest.toString()}` permission " + - "or your consumer doesn't not have the access to the view of the from account " + - "or you don't have the role CanCreateAnyTransactionRequest." + "or the consumer doesn't have the access to the view of the from account " + + s"or the login user does not have the `${CanCreateAnyTransactionRequest.toString()}` role " + + s"or the view have the permission ${ViewDefinition.canAddTransactionRequestToAnyAccount_.dbColumnName}." val InvalidTransactionRequestCurrency = "OBP-40003: Transaction Request Currency must be the same as From Account Currency." val InvalidTransactionRequestId = "OBP-40004: Transaction Request Id not found." val InsufficientAuthorisationToCreateTransactionType = "OBP-40005: Insufficient authorisation to Create Transaction Type offered by the bank. The Request could not be created because you don't have access to CanCreateTransactionType." 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 b67c6f5415..8a8901313d 100644 --- a/obp-api/src/main/scala/code/api/util/NewStyle.scala +++ b/obp-api/src/main/scala/code/api/util/NewStyle.scala @@ -625,22 +625,7 @@ object NewStyle extends MdcLoggable{ def checkAuthorisationToCreateTransactionRequest(viewId : ViewId, bankAccountId: BankIdAccountId, user: User, callContext: Option[CallContext]) : Future[Boolean] = { Future{ - - lazy val hasCanCreateAnyTransactionRequestRole = APIUtil.hasEntitlement(bankAccountId.bankId.value, user.userId, canCreateAnyTransactionRequest) - - lazy val view = APIUtil.checkViewAccessAndReturnView(viewId, bankAccountId, Some(user), callContext) - - lazy val canAddTransactionRequestToAnyAccount = view.map(_.canAddTransactionRequestToAnyAccount).getOrElse(false) - - //1st check the admin level role/entitlement `canCreateAnyTransactionRequest` - if(hasCanCreateAnyTransactionRequestRole) { - Full(true) - //2rd: check if the user have the view access and the view has the `canAddTransactionRequestToAnyAccount` permission - } else if (canAddTransactionRequestToAnyAccount) { - Full(true) - } else{ - Empty - } + APIUtil.checkAuthorisationToCreateTransactionRequest(viewId : ViewId, bankAccountId: BankIdAccountId, user: User, callContext: Option[CallContext]) } map { unboxFullOrFail(_, callContext, s"$InsufficientAuthorisationToCreateTransactionRequest " + s"Current ViewId(${viewId.value})," + diff --git a/obp-api/src/main/scala/code/api/v1_4_0/APIMethods140.scala b/obp-api/src/main/scala/code/api/v1_4_0/APIMethods140.scala index 748b9e874d..6dd3664415 100644 --- a/obp-api/src/main/scala/code/api/v1_4_0/APIMethods140.scala +++ b/obp-api/src/main/scala/code/api/v1_4_0/APIMethods140.scala @@ -539,6 +539,12 @@ trait APIMethods140 extends MdcLoggable with APIMethods130 with APIMethods121{ transBody <- tryo{getTransactionRequestBodyFromJson(transBodyJson)} (bank, callContext ) <- BankX(bankId, Some(cc)) ?~! {ErrorMessages.BankNotFound} fromAccount <- BankAccountX(bankId, accountId) ?~! {ErrorMessages.AccountNotFound} + _ <- APIUtil.checkAuthorisationToCreateTransactionRequest(viewId : ViewId, BankIdAccountId(bankId, accountId), u: User, callContext: Option[CallContext]) ?~! { + s"$InsufficientAuthorisationToCreateTransactionRequest " + + s"Current ViewId(${viewId.value})," + + s"current UserId(${u.userId})" + + s"current ConsumerId(${callContext.map (_.consumer.map (_.consumerId.get).getOrElse ("")).getOrElse ("")})" + } toBankId <- tryo(BankId(transBodyJson.to.bank_id)) toAccountId <- tryo(AccountId(transBodyJson.to.account_id)) toAccount <- BankAccountX(toBankId, toAccountId) ?~! {ErrorMessages.CounterpartyNotFound} @@ -600,7 +606,12 @@ trait APIMethods140 extends MdcLoggable with APIMethods130 with APIMethods121{ u <- cc.user ?~ ErrorMessages.UserNotLoggedIn (bank, callContext ) <- BankX(bankId, Some(cc)) ?~! {ErrorMessages.BankNotFound} fromAccount <- BankAccountX(bankId, accountId) ?~! BankAccountNotFound - view <- APIUtil.checkViewAccessAndReturnView(viewId, BankIdAccountId(fromAccount.bankId, fromAccount.accountId), Some(u), Some(cc)) + _ <- APIUtil.checkAuthorisationToCreateTransactionRequest(viewId: ViewId, BankIdAccountId(bankId, accountId), u: User, callContext: Option[CallContext]) ?~! { + s"$InsufficientAuthorisationToCreateTransactionRequest " + + s"Current ViewId(${viewId.value})," + + s"current UserId(${u.userId})" + + s"current ConsumerId(${callContext.map(_.consumer.map(_.consumerId.get).getOrElse("")).getOrElse("")})" + } answerJson <- tryo{json.extract[ChallengeAnswerJSON]} ?~ InvalidJsonFormat //TODO check more things here _ <- Connector.connector.vend.answerTransactionRequestChallenge(transReqId, answerJson.answer) diff --git a/obp-api/src/main/scala/code/api/v2_0_0/APIMethods200.scala b/obp-api/src/main/scala/code/api/v2_0_0/APIMethods200.scala index c1605f0c05..baa5b32ced 100644 --- a/obp-api/src/main/scala/code/api/v2_0_0/APIMethods200.scala +++ b/obp-api/src/main/scala/code/api/v2_0_0/APIMethods200.scala @@ -1281,11 +1281,11 @@ trait APIMethods200 { _ <- tryo(assert(isValidID(accountId.value)))?~! InvalidAccountIdFormat (bank, callContext ) <- BankX(bankId, Some(cc)) ?~! BankNotFound fromAccount <- BankAccountX(bankId, accountId) ?~! AccountNotFound - _ <- APIUtil.checkViewAccessAndReturnView(viewId, BankIdAccountId(fromAccount.bankId, fromAccount.accountId), Some(u), callContext).map(_.canAddTransactionRequestToOwnAccount) match { - case Full(_) => - Full (Unit) - case _ => - NewStyle.function.ownEntitlement(fromAccount.bankId.value, u.userId, canCreateAnyTransactionRequest, cc.callContext, InsufficientAuthorisationToCreateTransactionRequest) + _ <- APIUtil.checkAuthorisationToCreateTransactionRequest(viewId: ViewId, BankIdAccountId(bankId, accountId), u: User, callContext: Option[CallContext]) ?~! { + s"$InsufficientAuthorisationToCreateTransactionRequest " + + s"Current ViewId(${viewId.value})," + + s"current UserId(${u.userId})" + + s"current ConsumerId(${callContext.map(_.consumer.map(_.consumerId.get).getOrElse("")).getOrElse("")})" } toBankId <- tryo(BankId(transBodyJson.to.bank_id)) toAccountId <- tryo(AccountId(transBodyJson.to.account_id)) @@ -1349,12 +1349,12 @@ trait APIMethods200 { _ <- tryo(assert(isValidID(bankId.value)))?~! ErrorMessages.InvalidBankIdFormat (bank, callContext ) <- BankX(bankId, Some(cc)) ?~! BankNotFound fromAccount <- BankAccountX(bankId, accountId) ?~! AccountNotFound - view <-APIUtil.checkViewAccessAndReturnView(viewId, BankIdAccountId(fromAccount.bankId, fromAccount.accountId), Some(u), callContext) - _ <- if (view.canAddTransactionRequestToOwnAccount) - Full(Unit) - else - NewStyle.function.ownEntitlement(fromAccount.bankId.value, u.userId, canCreateAnyTransactionRequest, cc.callContext, InsufficientAuthorisationToCreateTransactionRequest) - + _ <- APIUtil.checkAuthorisationToCreateTransactionRequest(viewId: ViewId, BankIdAccountId(bankId, accountId), u: User, callContext: Option[CallContext]) ?~! { + s"$InsufficientAuthorisationToCreateTransactionRequest " + + s"Current ViewId(${viewId.value})," + + s"current UserId(${u.userId})" + + s"current ConsumerId(${callContext.map(_.consumer.map(_.consumerId.get).getOrElse("")).getOrElse("")})" + } answerJson <- tryo{json.extract[ChallengeAnswerJSON]} ?~! InvalidJsonFormat _ <- Connector.connector.vend.answerTransactionRequestChallenge(transReqId, answerJson.answer) //check the transReqId validation. diff --git a/obp-api/src/main/scala/code/bankconnectors/Connector.scala b/obp-api/src/main/scala/code/bankconnectors/Connector.scala index a61efb2949..33118e77ed 100644 --- a/obp-api/src/main/scala/code/bankconnectors/Connector.scala +++ b/obp-api/src/main/scala/code/bankconnectors/Connector.scala @@ -754,7 +754,6 @@ trait Connector extends MdcLoggable { for{ fromAccount <- getBankAccountOld(fromAccountUID.bankId, fromAccountUID.accountId) ?~ s"$BankAccountNotFound Account ${fromAccountUID.accountId} not found at bank ${fromAccountUID.bankId}" - isOwner <- booleanToBox(initiator.hasOwnerViewAccess(BankIdAccountId(fromAccount.bankId,fromAccount.accountId), callContext), UserNoOwnerView) toAccount <- getBankAccountOld(toAccountUID.bankId, toAccountUID.accountId) ?~ s"$BankAccountNotFound Account ${toAccountUID.accountId} not found at bank ${toAccountUID.bankId}" sameCurrency <- booleanToBox(fromAccount.currency == toAccount.currency, { @@ -841,7 +840,6 @@ trait Connector extends MdcLoggable { val request = for { fromAccountType <- getBankAccountOld(fromAccount.bankId, fromAccount.accountId) ?~ s"account ${fromAccount.accountId} not found at bank ${fromAccount.bankId}" - isOwner <- booleanToBox(initiator.hasOwnerViewAccess(BankIdAccountId(fromAccount.bankId,fromAccount.accountId), callContext), UserNoOwnerView) toAccountType <- getBankAccountOld(toAccount.bankId, toAccount.accountId) ?~ s"account ${toAccount.accountId} not found at bank ${toAccount.bankId}" rawAmt <- tryo { BigDecimal(body.value.amount) } ?~! s"amount ${body.value.amount} not convertible to number" @@ -902,7 +900,6 @@ trait Connector extends MdcLoggable { // Always create a new Transaction Request val request = for { fromAccountType <- getBankAccountOld(fromAccount.bankId, fromAccount.accountId) ?~ s"account ${fromAccount.accountId} not found at bank ${fromAccount.bankId}" - isOwner <- booleanToBox(initiator.hasOwnerViewAccess(BankIdAccountId(fromAccount.bankId,fromAccount.accountId),callContext) == true || hasEntitlement(fromAccount.bankId.value, initiator.userId, canCreateAnyTransactionRequest) == true, ErrorMessages.InsufficientAuthorisationToCreateTransactionRequest) toAccountType <- getBankAccountOld(toAccount.bankId, toAccount.accountId) ?~ s"account ${toAccount.accountId} not found at bank ${toAccount.bankId}" rawAmt <- tryo { BigDecimal(body.value.amount) } ?~! s"amount ${body.value.amount} not convertible to number" // isValidTransactionRequestType is checked at API layer. Maybe here too. diff --git a/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala b/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala index 7cbf40e07c..3f5ea36b9d 100644 --- a/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala +++ b/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala @@ -4672,7 +4672,6 @@ object LocalMappedConnector extends Connector with MdcLoggable { for { fromAccount <- getBankAccountOld(fromAccountUID.bankId, fromAccountUID.accountId) ?~ s"$BankAccountNotFound Account ${fromAccountUID.accountId} not found at bank ${fromAccountUID.bankId}" - isOwner <- booleanToBox(initiator.hasOwnerViewAccess(BankIdAccountId(fromAccount.bankId, fromAccount.accountId), callContext), UserNoOwnerView) toAccount <- getBankAccountOld(toAccountUID.bankId, toAccountUID.accountId) ?~ s"$BankAccountNotFound Account ${toAccountUID.accountId} not found at bank ${toAccountUID.bankId}" sameCurrency <- booleanToBox(fromAccount.currency == toAccount.currency, { @@ -4730,7 +4729,6 @@ object LocalMappedConnector extends Connector with MdcLoggable { val request = for { fromAccountType <- getBankAccountOld(fromAccount.bankId, fromAccount.accountId) ?~ s"account ${fromAccount.accountId} not found at bank ${fromAccount.bankId}" - isOwner <- booleanToBox(initiator.hasOwnerViewAccess(BankIdAccountId(fromAccount.bankId, fromAccount.accountId), callContext), UserNoOwnerView) toAccountType <- getBankAccountOld(toAccount.bankId, toAccount.accountId) ?~ s"account ${toAccount.accountId} not found at bank ${toAccount.bankId}" rawAmt <- tryo { @@ -4792,7 +4790,6 @@ object LocalMappedConnector extends Connector with MdcLoggable { // Always create a new Transaction Request val request = for { fromAccountType <- getBankAccountOld(fromAccount.bankId, fromAccount.accountId) ?~ s"account ${fromAccount.accountId} not found at bank ${fromAccount.bankId}" - isOwner <- booleanToBox(initiator.hasOwnerViewAccess(BankIdAccountId(fromAccount.bankId, fromAccount.accountId), callContext) == true || hasEntitlement(fromAccount.bankId.value, initiator.userId, canCreateAnyTransactionRequest) == true, ErrorMessages.InsufficientAuthorisationToCreateTransactionRequest) toAccountType <- getBankAccountOld(toAccount.bankId, toAccount.accountId) ?~ s"account ${toAccount.accountId} not found at bank ${toAccount.bankId}" rawAmt <- tryo { BigDecimal(body.value.amount) diff --git a/obp-api/src/test/scala/code/api/v2_0_0/TransactionRequestsTest.scala b/obp-api/src/test/scala/code/api/v2_0_0/TransactionRequestsTest.scala index 244872a0eb..fd6a573699 100644 --- a/obp-api/src/test/scala/code/api/v2_0_0/TransactionRequestsTest.scala +++ b/obp-api/src/test/scala/code/api/v2_0_0/TransactionRequestsTest.scala @@ -365,7 +365,7 @@ class TransactionRequestsTest extends V200ServerSetup with DefaultUsers { case _ => "" } Then("We should have the error: " + ErrorMessages.InsufficientAuthorisationToCreateTransactionRequest) - error should equal (ErrorMessages.InsufficientAuthorisationToCreateTransactionRequest) + error contains (ErrorMessages.InsufficientAuthorisationToCreateTransactionRequest) shouldBe( true) } @@ -425,7 +425,7 @@ class TransactionRequestsTest extends V200ServerSetup with DefaultUsers { case _ => "" } Then("We should have the error: " + ErrorMessages.InsufficientAuthorisationToCreateTransactionRequest) - error should equal (ErrorMessages.InsufficientAuthorisationToCreateTransactionRequest) + error contains (ErrorMessages.InsufficientAuthorisationToCreateTransactionRequest) shouldBe( true) } From b23f0278973240e67753f847050af7ce423d718a Mon Sep 17 00:00:00 2001 From: hongwei Date: Thu, 22 Jun 2023 19:39:00 +0800 Subject: [PATCH 08/41] refactor/remove `hasOwnerViewAccess` replace with specific view permissions -- clean the code --- .../scala/code/bankconnectors/Connector.scala | 34 +++---------------- 1 file changed, 4 insertions(+), 30 deletions(-) diff --git a/obp-api/src/main/scala/code/bankconnectors/Connector.scala b/obp-api/src/main/scala/code/bankconnectors/Connector.scala index 33118e77ed..eb687beeca 100644 --- a/obp-api/src/main/scala/code/bankconnectors/Connector.scala +++ b/obp-api/src/main/scala/code/bankconnectors/Connector.scala @@ -1166,30 +1166,8 @@ trait Connector extends MdcLoggable { def saveTransactionRequestDescriptionImpl(transactionRequestId: TransactionRequestId, description: String): Box[Boolean] = TransactionRequests.transactionRequestProvider.vend.saveTransactionRequestDescriptionImpl(transactionRequestId, description) - def getTransactionRequests(initiator : User, fromAccount : BankAccount, callContext: Option[CallContext]) : Box[List[TransactionRequest]] = { - val transactionRequests = - for { - fromAccount <- getBankAccountOld(fromAccount.bankId, fromAccount.accountId) ?~ - s"account ${fromAccount.accountId} not found at bank ${fromAccount.bankId}" - isOwner <- booleanToBox(initiator.hasOwnerViewAccess(BankIdAccountId(fromAccount.bankId,fromAccount.accountId), callContext), UserNoOwnerView) - transactionRequests <- getTransactionRequestsImpl(fromAccount) - } yield transactionRequests - - //make sure we return null if no challenge was saved (instead of empty fields) - if (!transactionRequests.isEmpty) { - for { - treq <- transactionRequests - } yield { - treq.map(tr => if (tr.challenge.id == "") { - tr.copy(challenge = null) - } else { - tr - }) - } - } else { - transactionRequests - } - } + def getTransactionRequests(initiator : User, fromAccount : BankAccount, callContext: Option[CallContext]) : Box[List[TransactionRequest]] = + LocalMappedConnector.getTransactionRequests(initiator : User, fromAccount : BankAccount, callContext: Option[CallContext]) def getTransactionRequests210(initiator : User, fromAccount : BankAccount, callContext: Option[CallContext]) : Box[(List[TransactionRequest], Option[CallContext])] = { val transactionRequests = @@ -1230,12 +1208,8 @@ trait Connector extends MdcLoggable { def getTransactionRequestImpl(transactionRequestId: TransactionRequestId, callContext: Option[CallContext]): Box[(TransactionRequest, Option[CallContext])] = TransactionRequests.transactionRequestProvider.vend.getTransactionRequest(transactionRequestId).map(transactionRequest =>(transactionRequest, callContext)) - def getTransactionRequestTypes(initiator : User, fromAccount : BankAccount, callContext: Option[CallContext]) : Box[List[TransactionRequestType]] = { - for { - isOwner <- booleanToBox(initiator.hasOwnerViewAccess(BankIdAccountId(fromAccount.bankId,fromAccount.accountId), callContext), UserNoOwnerView) - transactionRequestTypes <- getTransactionRequestTypesImpl(fromAccount) - } yield transactionRequestTypes - } + def getTransactionRequestTypes(initiator : User, fromAccount : BankAccount, callContext: Option[CallContext]) : Box[List[TransactionRequestType]] = + LocalMappedConnector.getTransactionRequestTypes(initiator : User, fromAccount : BankAccount, callContext: Option[CallContext]) protected def getTransactionRequestTypesImpl(fromAccount : BankAccount) : Box[List[TransactionRequestType]] = { //TODO: write logic / data access From abdeb61b7ab60614c6ec7ae46921b4afe10fe74a Mon Sep 17 00:00:00 2001 From: hongwei Date: Thu, 22 Jun 2023 21:36:31 +0800 Subject: [PATCH 09/41] refactor/remove `hasOwnerViewAccess` replace with specific view permissions -- move all canSeeTransactionRequests check in the api level --- obp-api/src/main/scala/code/api/v2_0_0/APIMethods200.scala | 3 +++ .../main/scala/code/bankconnectors/LocalMappedConnector.scala | 1 - 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/obp-api/src/main/scala/code/api/v2_0_0/APIMethods200.scala b/obp-api/src/main/scala/code/api/v2_0_0/APIMethods200.scala index baa5b32ced..8b73b1594b 100644 --- a/obp-api/src/main/scala/code/api/v2_0_0/APIMethods200.scala +++ b/obp-api/src/main/scala/code/api/v2_0_0/APIMethods200.scala @@ -30,6 +30,7 @@ import code.usercustomerlinks.UserCustomerLink import code.util.Helper import code.util.Helper.booleanToBox import code.views.Views +import code.views.system.ViewDefinition import com.openbankproject.commons.model._ import net.liftweb.common.{Full, _} import net.liftweb.http.CurrentReq @@ -1435,6 +1436,8 @@ trait APIMethods200 { (bank, callContext ) <- BankX(bankId, Some(cc)) ?~! BankNotFound fromAccount <- BankAccountX(bankId, accountId) ?~! AccountNotFound view <-APIUtil.checkViewAccessAndReturnView(viewId, BankIdAccountId(fromAccount.bankId, fromAccount.accountId), Some(u), callContext) + _ <- Helper.booleanToBox(view.canSeeTransactionRequests, + s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${ViewDefinition.canSeeTransactionRequests_.dbColumnName}` permission on the View(${viewId.value} )") transactionRequests <- Connector.connector.vend.getTransactionRequests(u, fromAccount, callContext) } yield { diff --git a/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala b/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala index 3f5ea36b9d..da9ab1f572 100644 --- a/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala +++ b/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala @@ -5216,7 +5216,6 @@ object LocalMappedConnector extends Connector with MdcLoggable { for { fromAccount <- getBankAccountOld(fromAccount.bankId, fromAccount.accountId) ?~ s"account ${fromAccount.accountId} not found at bank ${fromAccount.bankId}" - isOwner <- booleanToBox(initiator.hasOwnerViewAccess(BankIdAccountId(fromAccount.bankId, fromAccount.accountId), callContext), UserNoOwnerView) transactionRequests <- getTransactionRequestsImpl(fromAccount) } yield transactionRequests From b8fb0b012f330452c51a1586f7e00f3732cb3a90 Mon Sep 17 00:00:00 2001 From: hongwei Date: Thu, 22 Jun 2023 22:14:59 +0800 Subject: [PATCH 10/41] refactor/remove `hasOwnerViewAccess` replace with specific view permissions -- added canSeeTransactionRequestTypes_ permission --- .../migration/MigrationOfViewDefinitionPermissions.scala | 9 ++++++--- .../src/main/scala/code/api/v1_4_0/APIMethods140.scala | 6 ++++++ .../scala/code/bankconnectors/LocalMappedConnector.scala | 2 -- .../main/scala/code/model/dataAccess/MappedView.scala | 5 +++++ obp-api/src/main/scala/code/views/MapperViews.scala | 4 +++- .../main/scala/code/views/system/ViewDefinition.scala | 4 ++++ .../com/openbankproject/commons/model/ViewModel.scala | 2 ++ 7 files changed, 26 insertions(+), 6 deletions(-) diff --git a/obp-api/src/main/scala/code/api/util/migration/MigrationOfViewDefinitionPermissions.scala b/obp-api/src/main/scala/code/api/util/migration/MigrationOfViewDefinitionPermissions.scala index 2477ba0a0e..75271380f8 100644 --- a/obp-api/src/main/scala/code/api/util/migration/MigrationOfViewDefinitionPermissions.scala +++ b/obp-api/src/main/scala/code/api/util/migration/MigrationOfViewDefinitionPermissions.scala @@ -20,8 +20,9 @@ object MigrationOfViewDefinitionPermissions { By(ViewDefinition.isSystem_,true) ).map(view => view -// .canSeeTransactionRequests_(true) -// .canSeeAvailableViewsForBankAccount_(true) + .canSeeTransactionRequestTypes_(true) + .canSeeTransactionRequests_(true) + .canSeeAvailableViewsForBankAccount_(true) .save ).head @@ -31,7 +32,9 @@ object MigrationOfViewDefinitionPermissions { val comment: String = s"""ViewDefinition system owner view, update the following rows to true: - |canSeeTransactionRequests_ + |${ViewDefinition.canSeeTransactionRequestTypes_.dbColumnName} + |${ViewDefinition.canSeeTransactionRequests_.dbColumnName} + |${ViewDefinition.canSeeAvailableViewsForBankAccount_.dbColumnName} |Duration: ${endDate - startDate} ms; """.stripMargin saveLog(name, commitId, isSuccessful, startDate, endDate, comment) diff --git a/obp-api/src/main/scala/code/api/v1_4_0/APIMethods140.scala b/obp-api/src/main/scala/code/api/v1_4_0/APIMethods140.scala index 6dd3664415..651387a85e 100644 --- a/obp-api/src/main/scala/code/api/v1_4_0/APIMethods140.scala +++ b/obp-api/src/main/scala/code/api/v1_4_0/APIMethods140.scala @@ -423,6 +423,12 @@ trait APIMethods140 extends MdcLoggable with APIMethods130 with APIMethods121{ failMsg = ErrorMessages.InvalidISOCurrencyCode.concat("Please specify a valid value for CURRENCY of your Bank Account. ") _ <- NewStyle.function.isValidCurrencyISOCode(fromAccount.currency, failMsg, callContext) view <- NewStyle.function.checkViewAccessAndReturnView(viewId, BankIdAccountId(fromAccount.bankId, fromAccount.accountId), Some(u), callContext) + _ <- Helper.booleanToFuture( + s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${ViewDefinition.canSeeTransactionRequestTypes_.dbColumnName}` permission on the View(${viewId.value} )", + cc = callContext + ) { + view.canSeeTransactionRequestTypes + } transactionRequestTypes <- Future(Connector.connector.vend.getTransactionRequestTypes(u, fromAccount, callContext)) map { connectorEmptyResponse(_, callContext) } diff --git a/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala b/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala index da9ab1f572..8e9275b788 100644 --- a/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala +++ b/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala @@ -5270,13 +5270,11 @@ object LocalMappedConnector extends Connector with MdcLoggable { override def getTransactionRequestTypes(initiator: User, fromAccount: BankAccount, callContext: Option[CallContext]): Box[List[TransactionRequestType]] = { for { - isOwner <- booleanToBox(initiator.hasOwnerViewAccess(BankIdAccountId(fromAccount.bankId, fromAccount.accountId), callContext), UserNoOwnerView) transactionRequestTypes <- getTransactionRequestTypesImpl(fromAccount) } yield transactionRequestTypes } override def getTransactionRequestTypesImpl(fromAccount: BankAccount): Box[List[TransactionRequestType]] = { - //TODO: write logic / data access // Get Transaction Request Types from Props "transactionRequests_supported_types". Default is empty string val validTransactionRequestTypes = APIUtil.getPropsValue("transactionRequests_supported_types", "").split(",").map(x => TransactionRequestType(x)).toList Full(validTransactionRequestTypes) diff --git a/obp-api/src/main/scala/code/model/dataAccess/MappedView.scala b/obp-api/src/main/scala/code/model/dataAccess/MappedView.scala index 8a7387db57..b043ff974f 100644 --- a/obp-api/src/main/scala/code/model/dataAccess/MappedView.scala +++ b/obp-api/src/main/scala/code/model/dataAccess/MappedView.scala @@ -207,6 +207,10 @@ class ViewImpl extends View with LongKeyedMapper[ViewImpl] with ManyToMany with object canSeeTransactionRequests_ extends MappedBoolean(this){ override def defaultValue = false } + + object canSeeTransactionRequestTypes_ extends MappedBoolean(this){ + override def defaultValue = false + } object canSeeTransactionOtherBankAccount_ extends MappedBoolean(this){ override def defaultValue = false } @@ -456,6 +460,7 @@ class ViewImpl extends View with LongKeyedMapper[ViewImpl] with ManyToMany with //transaction fields def canSeeTransactionThisBankAccount : Boolean = canSeeTransactionThisBankAccount_.get def canSeeTransactionRequests : Boolean = canSeeTransactionRequests_.get + def canSeeTransactionRequestTypes : Boolean = canSeeTransactionRequestTypes_.get def canSeeTransactionOtherBankAccount : Boolean = canSeeTransactionOtherBankAccount_.get def canSeeTransactionMetadata : Boolean = canSeeTransactionMetadata_.get def canSeeTransactionDescription: Boolean = canSeeTransactionDescription_.get diff --git a/obp-api/src/main/scala/code/views/MapperViews.scala b/obp-api/src/main/scala/code/views/MapperViews.scala index 236b1e2b31..e0b94a62af 100644 --- a/obp-api/src/main/scala/code/views/MapperViews.scala +++ b/obp-api/src/main/scala/code/views/MapperViews.scala @@ -791,13 +791,15 @@ object MapperViews extends Views with MdcLoggable { .canAddTransactionRequestToOwnAccount_(true) //added following two for payments .canAddTransactionRequestToAnyAccount_(true) .canSeeAvailableViewsForBankAccount_(false) - .canSeeTransactionRequests_(false) + .canSeeTransactionRequests_(true) + .canSeeTransactionRequestTypes_(true) viewId match { case SYSTEM_OWNER_VIEW_ID => entity .canSeeAvailableViewsForBankAccount_(true) .canSeeTransactionRequests_(true) + .canSeeTransactionRequestTypes_(true) case SYSTEM_STAGE_ONE_VIEW_ID => entity .canSeeTransactionDescription_(false) diff --git a/obp-api/src/main/scala/code/views/system/ViewDefinition.scala b/obp-api/src/main/scala/code/views/system/ViewDefinition.scala index 48809e2132..83ad820e7c 100644 --- a/obp-api/src/main/scala/code/views/system/ViewDefinition.scala +++ b/obp-api/src/main/scala/code/views/system/ViewDefinition.scala @@ -63,6 +63,9 @@ class ViewDefinition extends View with LongKeyedMapper[ViewDefinition] with Many object canSeeTransactionRequests_ extends MappedBoolean(this){ override def defaultValue = false } + object canSeeTransactionRequestTypes_ extends MappedBoolean(this){ + override def defaultValue = false + } object canSeeTransactionOtherBankAccount_ extends MappedBoolean(this){ override def defaultValue = false } @@ -443,6 +446,7 @@ class ViewDefinition extends View with LongKeyedMapper[ViewDefinition] with Many //transaction fields def canSeeTransactionThisBankAccount : Boolean = canSeeTransactionThisBankAccount_.get def canSeeTransactionRequests : Boolean = canSeeTransactionRequests_.get + def canSeeTransactionRequestTypes: Boolean = canSeeTransactionRequestTypes_.get def canSeeTransactionOtherBankAccount : Boolean = canSeeTransactionOtherBankAccount_.get def canSeeTransactionMetadata : Boolean = canSeeTransactionMetadata_.get def canSeeTransactionDescription: Boolean = canSeeTransactionDescription_.get diff --git a/obp-commons/src/main/scala/com/openbankproject/commons/model/ViewModel.scala b/obp-commons/src/main/scala/com/openbankproject/commons/model/ViewModel.scala index c83a2cd151..0ee0f5a327 100644 --- a/obp-commons/src/main/scala/com/openbankproject/commons/model/ViewModel.scala +++ b/obp-commons/src/main/scala/com/openbankproject/commons/model/ViewModel.scala @@ -260,6 +260,8 @@ trait View { //transaction fields def canSeeTransactionRequests: Boolean + def canSeeTransactionRequestTypes: Boolean + def canSeeTransactionThisBankAccount: Boolean def canSeeTransactionOtherBankAccount: Boolean From 4443139cf9e5e60ebd49ebc4eb07a45375a9247b Mon Sep 17 00:00:00 2001 From: hongwei Date: Thu, 22 Jun 2023 22:54:15 +0800 Subject: [PATCH 11/41] refactor/remove `hasOwnerViewAccess` replace with specific view permissions -- use canDeleteTag,canDeleteImage and canDeleteComment --- .../scala/code/api/v1_2_1/APIMethods121.scala | 23 +++++++++++-------- .../code/model/ModeratedBankingData.scala | 16 ++++++------- 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/obp-api/src/main/scala/code/api/v1_2_1/APIMethods121.scala b/obp-api/src/main/scala/code/api/v1_2_1/APIMethods121.scala index 7f7a564c97..263880baed 100644 --- a/obp-api/src/main/scala/code/api/v1_2_1/APIMethods121.scala +++ b/obp-api/src/main/scala/code/api/v1_2_1/APIMethods121.scala @@ -2662,10 +2662,11 @@ trait APIMethods121 { case "banks" :: BankId(bankId) :: "accounts" :: AccountId(accountId) :: ViewId(viewId) :: "transactions" :: TransactionId(transactionId) :: "metadata" :: "comments":: commentId :: Nil JsonDelete _ => { cc => for { - (user, callContext) <- authenticatedAccess(cc) + (Full(user), callContext) <- authenticatedAccess(cc) (account, callContext) <- NewStyle.function.checkBankAccountExists(bankId, accountId, callContext) - metadata <- moderatedTransactionMetadataFuture(bankId, accountId, viewId, transactionId, user, callContext) - delete <- Future(metadata.deleteComment(commentId, user, account, callContext)) map { + view <- NewStyle.function.checkViewAccessAndReturnView(viewId, BankIdAccountId(bankId, accountId), Some(user), callContext) + metadata <- moderatedTransactionMetadataFuture(bankId, accountId, viewId, transactionId, Full(user), callContext) + delete <- Future(metadata.deleteComment(commentId, Full(user), account, view, callContext)) map { unboxFullOrFail(_, callContext, "") } } yield { @@ -2781,10 +2782,11 @@ trait APIMethods121 { cc => for { - (user, callContext) <- authenticatedAccess(cc) - metadata <- moderatedTransactionMetadataFuture(bankId, accountId, viewId, transactionId, user, callContext) + (Full(user), callContext) <- authenticatedAccess(cc) + view <- NewStyle.function.checkViewAccessAndReturnView(viewId, BankIdAccountId(bankId, accountId), Some(user), callContext) + metadata <- moderatedTransactionMetadataFuture(bankId, accountId, viewId, transactionId, Full(user), callContext) (bankAccount, callContext) <- NewStyle.function.checkBankAccountExists(bankId, accountId, callContext) - delete <- Future(metadata.deleteTag(tagId, user, bankAccount, callContext)) map { + delete <- Future(metadata.deleteTag(tagId, Full(user), bankAccount, view, callContext)) map { unboxFullOrFail(_, callContext, "") } } yield { @@ -2904,10 +2906,11 @@ trait APIMethods121 { case "banks" :: BankId(bankId) :: "accounts" :: AccountId(accountId) :: ViewId(viewId) :: "transactions" :: TransactionId(transactionId) :: "metadata" :: "images" :: imageId :: Nil JsonDelete _ => { cc => for { - (user, callContext) <- authenticatedAccess(cc) - metadata <- moderatedTransactionMetadataFuture(bankId, accountId, viewId, transactionId, user, callContext) + (Full(user), callContext) <- authenticatedAccess(cc) + metadata <- moderatedTransactionMetadataFuture(bankId, accountId, viewId, transactionId, Full(user), callContext) + view <- NewStyle.function.checkViewAccessAndReturnView(viewId, BankIdAccountId(bankId, accountId), Some(user), callContext) (account, _) <- NewStyle.function.checkBankAccountExists(bankId, accountId, callContext) - delete <- Future(metadata.deleteImage(imageId, user, account, callContext)) map { + delete <- Future(metadata.deleteImage(imageId, Full(user), account, view, callContext)) map { unboxFullOrFail(_, callContext, "") } } yield { @@ -3080,7 +3083,7 @@ trait APIMethods121 { (account, callContext) <- NewStyle.function.checkBankAccountExists(bankId, accountId, callContext) view <- NewStyle.function.checkViewAccessAndReturnView(viewId, BankIdAccountId(bankId, accountId), user, callContext) metadata <- moderatedTransactionMetadataFuture(bankId, accountId, viewId, transactionId, user, callContext) - delete <- Future(metadata.deleteWhereTag(viewId, user, account, callContext)) map { + delete <- Future(metadata.deleteWhereTag(viewId, user, account, view, callContext)) map { unboxFullOrFail(_, callContext, "Delete not completed") } } yield { diff --git a/obp-api/src/main/scala/code/model/ModeratedBankingData.scala b/obp-api/src/main/scala/code/model/ModeratedBankingData.scala index f49fdf10ab..3f6e99c70a 100644 --- a/obp-api/src/main/scala/code/model/ModeratedBankingData.scala +++ b/obp-api/src/main/scala/code/model/ModeratedBankingData.scala @@ -120,12 +120,12 @@ class ModeratedTransactionMetadata( /** * @return Full if deleting the tag worked, or a failure message if it didn't */ - def deleteTag(tagId : String, user: Option[User], bankAccount : BankAccount, callContext: Option[CallContext]) : Box[Unit] = { + def deleteTag(tagId : String, user: Option[User], bankAccount : BankAccount, view: View, callContext: Option[CallContext]) : Box[Unit] = { for { u <- Box(user) ?~ { UserNotLoggedIn} tagList <- Box(tags) ?~ { s"$NoViewPermission can_delete_tag. " } tag <- Box(tagList.find(tag => tag.id_ == tagId)) ?~ {"Tag with id " + tagId + "not found for this transaction"} - deleteFunc <- if(tag.postedBy == user || u.hasOwnerViewAccess(BankIdAccountId(bankAccount.bankId,bankAccount.accountId), callContext)) + deleteFunc <- if(tag.postedBy == user||view.canDeleteTag) Box(deleteTag) ?~ "Deleting tags not permitted for this view" else Failure("deleting tags not permitted for the current user") @@ -137,12 +137,12 @@ class ModeratedTransactionMetadata( /** * @return Full if deleting the image worked, or a failure message if it didn't */ - def deleteImage(imageId : String, user: Option[User], bankAccount : BankAccount, callContext: Option[CallContext]) : Box[Unit] = { + def deleteImage(imageId : String, user: Option[User], bankAccount : BankAccount, view: View, callContext: Option[CallContext]) : Box[Unit] = { for { u <- Box(user) ?~ { UserNotLoggedIn} imageList <- Box(images) ?~ { s"$NoViewPermission can_delete_image." } image <- Box(imageList.find(image => image.id_ == imageId)) ?~ {"Image with id " + imageId + "not found for this transaction"} - deleteFunc <- if(image.postedBy == user || u.hasOwnerViewAccess(BankIdAccountId(bankAccount.bankId,bankAccount.accountId), callContext)) + deleteFunc <- if(image.postedBy == user || view.canDeleteImage) Box(deleteImage) ?~ "Deleting images not permitted for this view" else Failure("Deleting images not permitted for the current user") @@ -151,12 +151,12 @@ class ModeratedTransactionMetadata( } } - def deleteComment(commentId: String, user: Option[User],bankAccount: BankAccount, callContext: Option[CallContext]) : Box[Unit] = { + def deleteComment(commentId: String, user: Option[User],bankAccount: BankAccount, view: View, callContext: Option[CallContext]) : Box[Unit] = { for { u <- Box(user) ?~ { UserNotLoggedIn} commentList <- Box(comments) ?~ { s"$NoViewPermission can_delete_comment." } comment <- Box(commentList.find(comment => comment.id_ == commentId)) ?~ {"Comment with id "+commentId+" not found for this transaction"} - deleteFunc <- if(comment.postedBy == user || u.hasOwnerViewAccess(BankIdAccountId(bankAccount.bankId,bankAccount.accountId), callContext)) + deleteFunc <- if(comment.postedBy == user || view.canDeleteComment) Box(deleteComment) ?~ "Deleting comments not permitted for this view" else Failure("Deleting comments not permitted for the current user") @@ -165,12 +165,12 @@ class ModeratedTransactionMetadata( } } - def deleteWhereTag(viewId: ViewId, user: Option[User],bankAccount: BankAccount, callContext: Option[CallContext]) : Box[Boolean] = { + def deleteWhereTag(viewId: ViewId, user: Option[User],bankAccount: BankAccount, view: View, callContext: Option[CallContext]) : Box[Boolean] = { for { u <- Box(user) ?~ { UserNotLoggedIn} whereTagOption <- Box(whereTag) ?~ { s"$NoViewPermission can_delete_where_tag. Current ViewId($viewId)" } whereTag <- Box(whereTagOption) ?~ {"there is no tag to delete"} - deleteFunc <- if(whereTag.postedBy == user || u.hasOwnerViewAccess(BankIdAccountId(bankAccount.bankId,bankAccount.accountId),callContext)) + deleteFunc <- if(whereTag.postedBy == user || view.canDeleteWhereTag) Box(deleteWhereTag) ?~ "Deleting tag is not permitted for this view" else Failure("Deleting tags not permitted for the current user") From 5d6e395e1e2a520da0a5abc0afe0106ef8798831 Mon Sep 17 00:00:00 2001 From: hongwei Date: Fri, 23 Jun 2023 00:17:52 +0800 Subject: [PATCH 12/41] refactor/remove `hasOwnerViewAccess` replace with specific view permissions -- added canUpdateBankAccountLabel_ permission --- .../scala/code/api/util/ErrorMessages.scala | 1 + .../MigrationOfViewDefinitionPermissions.scala | 2 ++ .../scala/code/api/v1_2_1/APIMethods121.scala | 15 ++++++++++++++- .../scala/code/api/v4_0_0/APIMethods400.scala | 14 +++++++++++++- .../main/scala/code/model/BankingData.scala | 10 +--------- .../code/model/dataAccess/MappedView.scala | 4 ++++ .../main/scala/code/views/MapperViews.scala | 18 +++++++++++------- .../code/views/system/ViewDefinition.scala | 8 ++++++++ ...ConnectorSetupWithStandardPermissions.scala | 4 ++++ .../commons/model/ViewModel.scala | 1 + 10 files changed, 59 insertions(+), 18 deletions(-) diff --git a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala index 610747fc57..f980fbfea3 100644 --- a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala +++ b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala @@ -467,6 +467,7 @@ object ErrorMessages { val DeleteCounterpartyError = "OBP-30317: Could not delete the Counterparty." val DeleteCounterpartyMetadataError = "OBP-30318: Could not delete CounterpartyMetadata" + val UpdateBankAccountLabelError = "OBP-30319: Could not update Bank Account Label." // Branch related messages val BranchesNotFoundLicense = "OBP-32001: No branches available. License may not be set." diff --git a/obp-api/src/main/scala/code/api/util/migration/MigrationOfViewDefinitionPermissions.scala b/obp-api/src/main/scala/code/api/util/migration/MigrationOfViewDefinitionPermissions.scala index 75271380f8..abecac5165 100644 --- a/obp-api/src/main/scala/code/api/util/migration/MigrationOfViewDefinitionPermissions.scala +++ b/obp-api/src/main/scala/code/api/util/migration/MigrationOfViewDefinitionPermissions.scala @@ -23,6 +23,7 @@ object MigrationOfViewDefinitionPermissions { .canSeeTransactionRequestTypes_(true) .canSeeTransactionRequests_(true) .canSeeAvailableViewsForBankAccount_(true) + .canUpdateBankAccountLabel_(true) .save ).head @@ -35,6 +36,7 @@ object MigrationOfViewDefinitionPermissions { |${ViewDefinition.canSeeTransactionRequestTypes_.dbColumnName} |${ViewDefinition.canSeeTransactionRequests_.dbColumnName} |${ViewDefinition.canSeeAvailableViewsForBankAccount_.dbColumnName} + |${ViewDefinition.canUpdateBankAccountLabel_.dbColumnName} |Duration: ${endDate - startDate} ms; """.stripMargin saveLog(name, commitId, isSuccessful, startDate, endDate, comment) diff --git a/obp-api/src/main/scala/code/api/v1_2_1/APIMethods121.scala b/obp-api/src/main/scala/code/api/v1_2_1/APIMethods121.scala index 263880baed..02da458068 100644 --- a/obp-api/src/main/scala/code/api/v1_2_1/APIMethods121.scala +++ b/obp-api/src/main/scala/code/api/v1_2_1/APIMethods121.scala @@ -494,8 +494,21 @@ trait APIMethods121 { (Full(u), callContext) <- authenticatedAccess(cc) json <- NewStyle.function.tryons(InvalidJsonFormat, 400, callContext) { json.extract[UpdateAccountJSON] } (account, callContext) <- NewStyle.function.checkBankAccountExists(bankId, accountId, callContext) + anyViewContainsCanUpdateBankAccountLabelPermission = Views.views.vend.permission(BankIdAccountId(account.bankId, account.accountId), u) + .map(_.views.map(_.canUpdateBankAccountLabel).find(_.==(true)).getOrElse(false)).getOrElse(false) + _ <- Helper.booleanToFuture( + s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${ViewDefinition.canUpdateBankAccountLabel_.dbColumnName}` permission on any your views", + cc = callContext + ) { + anyViewContainsCanUpdateBankAccountLabelPermission + } + (success, callContext) <- Future{ + Connector.connector.vend.updateAccountLabel(bankId, accountId, json.label) + } map { i => + (unboxFullOrFail(i, callContext, + s"$UpdateBankAccountLabelError Current BankId is $bankId and Current AccountId is $accountId", 404), callContext) + } } yield { - account.updateLabel(u, json.label,callContext) (successMessage, HttpCode.`200`(callContext)) } } diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index 76220504e7..0d158d618e 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -2779,8 +2779,20 @@ trait APIMethods400 { json <- NewStyle.function.tryons(failMsg, 400, callContext) { json.extract[UpdateAccountJsonV400] } + anyViewContainsCanUpdateBankAccountLabelPermission = Views.views.vend.permission(BankIdAccountId(account.bankId, account.accountId), u) + .map(_.views.map(_.canUpdateBankAccountLabel).find(_.==(true)).getOrElse(false)).getOrElse(false) + _ <- Helper.booleanToFuture( + s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${ViewDefinition.canUpdateBankAccountLabel_.dbColumnName}` permission on any your views", + cc = callContext + ) { + anyViewContainsCanUpdateBankAccountLabelPermission + } + (success, callContext) <- Future { + Connector.connector.vend.updateAccountLabel(bankId, accountId, json.label) + } map { i => + (unboxFullOrFail(i, callContext, s"$UpdateBankAccountLabelError Current BankId is $bankId and Current AccountId is $accountId", 404), callContext) + } } yield { - account.updateLabel(u, json.label, callContext) (Extraction.decompose(successMessage), HttpCode.`200`(callContext)) } } diff --git a/obp-api/src/main/scala/code/model/BankingData.scala b/obp-api/src/main/scala/code/model/BankingData.scala index 0dbef2ff34..80d45118f1 100644 --- a/obp-api/src/main/scala/code/model/BankingData.scala +++ b/obp-api/src/main/scala/code/model/BankingData.scala @@ -162,15 +162,7 @@ case class BankAccountExtended(val bankAccount: BankAccount) extends MdcLoggable Failure(UserNoOwnerView+"user's email : " + user.emailAddress + ". account : " + accountId, Empty, Empty) } } - - final def updateLabel(user : User, label : String, callContext: Option[CallContext]): Box[Boolean] = { - if(user.hasOwnerViewAccess(BankIdAccountId(bankId, accountId), callContext)){ - Connector.connector.vend.updateAccountLabel(bankId, accountId, label) - } else { - Failure(UserNoOwnerView+"user's email : " + user.emailAddress + ". account : " + accountId, Empty, Empty) - } - } - + /** * Note: There are two types of account-owners in OBP: the OBP users and the customers(in a real bank, these should from Main Frame) * diff --git a/obp-api/src/main/scala/code/model/dataAccess/MappedView.scala b/obp-api/src/main/scala/code/model/dataAccess/MappedView.scala index b043ff974f..0108fd6a13 100644 --- a/obp-api/src/main/scala/code/model/dataAccess/MappedView.scala +++ b/obp-api/src/main/scala/code/model/dataAccess/MappedView.scala @@ -271,6 +271,9 @@ class ViewImpl extends View with LongKeyedMapper[ViewImpl] with ManyToMany with object canSeeBankAccountLabel_ extends MappedBoolean(this){ override def defaultValue = false } + object canUpdateBankAccountLabel_ extends MappedBoolean(this){ + override def defaultValue = false + } object canSeeBankAccountNationalIdentifier_ extends MappedBoolean(this){ override def defaultValue = false } @@ -485,6 +488,7 @@ class ViewImpl extends View with LongKeyedMapper[ViewImpl] with ManyToMany with def canSeeBankAccountCurrency : Boolean = canSeeBankAccountCurrency_.get def canQueryAvailableFunds : Boolean = canQueryAvailableFunds_.get def canSeeBankAccountLabel : Boolean = canSeeBankAccountLabel_.get + def canUpdateBankAccountLabel : Boolean = canUpdateBankAccountLabel_.get def canSeeBankAccountNationalIdentifier : Boolean = canSeeBankAccountNationalIdentifier_.get def canSeeBankAccountSwift_bic : Boolean = canSeeBankAccountSwift_bic_.get def canSeeBankAccountIban : Boolean = canSeeBankAccountIban_.get diff --git a/obp-api/src/main/scala/code/views/MapperViews.scala b/obp-api/src/main/scala/code/views/MapperViews.scala index e0b94a62af..e29229f65c 100644 --- a/obp-api/src/main/scala/code/views/MapperViews.scala +++ b/obp-api/src/main/scala/code/views/MapperViews.scala @@ -793,6 +793,7 @@ object MapperViews extends Views with MdcLoggable { .canSeeAvailableViewsForBankAccount_(false) .canSeeTransactionRequests_(true) .canSeeTransactionRequestTypes_(true) + .canUpdateBankAccountLabel_(true) viewId match { case SYSTEM_OWNER_VIEW_ID => @@ -879,16 +880,16 @@ object MapperViews extends Views with MdcLoggable { canAddPrivateAlias_(true). canAddCounterparty_(true). canGetCounterparty_(true). - canDeleteCounterparty_(true). - canDeleteCorporateLocation_(true). - canDeletePhysicalLocation_(true). + canDeleteCounterparty_(false). + canDeleteCorporateLocation_(false). + canDeletePhysicalLocation_(false). canEditOwnerComment_(true). canAddComment_(true). - canDeleteComment_(true). + canDeleteComment_(false). canAddTag_(true). - canDeleteTag_(true). + canDeleteTag_(false). canAddImage_(true). - canDeleteImage_(true). + canDeleteImage_(false). canAddWhereTag_(true). canSeeWhereTag_(true). canSeeBankRoutingScheme_(true). //added following in V300 @@ -900,7 +901,10 @@ object MapperViews extends Views with MdcLoggable { canSeeOtherAccountRoutingScheme_(true). canSeeOtherAccountRoutingAddress_(true). canAddTransactionRequestToOwnAccount_(false). //added following two for payments - canAddTransactionRequestToAnyAccount_(false) + canAddTransactionRequestToAnyAccount_(false). + canSeeTransactionRequests_(false). + canSeeTransactionRequestTypes_(false). + canUpdateBankAccountLabel_(false) } def createAndSaveDefaultPublicCustomView(bankId : BankId, accountId: AccountId, description: String) : Box[View] = { diff --git a/obp-api/src/main/scala/code/views/system/ViewDefinition.scala b/obp-api/src/main/scala/code/views/system/ViewDefinition.scala index 83ad820e7c..7739029779 100644 --- a/obp-api/src/main/scala/code/views/system/ViewDefinition.scala +++ b/obp-api/src/main/scala/code/views/system/ViewDefinition.scala @@ -126,6 +126,9 @@ class ViewDefinition extends View with LongKeyedMapper[ViewDefinition] with Many object canSeeBankAccountLabel_ extends MappedBoolean(this){ override def defaultValue = false } + object canUpdateBankAccountLabel_ extends MappedBoolean(this){ + override def defaultValue = false + } object canSeeBankAccountNationalIdentifier_ extends MappedBoolean(this){ override def defaultValue = false } @@ -403,6 +406,10 @@ class ViewDefinition extends View with LongKeyedMapper[ViewDefinition] with Many canSeeBankAccountCreditLimit_(actions.exists(_ == "can_see_bank_account_credit_limit")) canCreateDirectDebit_(actions.exists(_ == "can_create_direct_debit")) canCreateStandingOrder_(actions.exists(_ == "can_create_standing_order")) + canSeeTransactionRequests_(actions.exists(_ == "can_see_transaction_requests")) + canSeeTransactionRequestTypes_(actions.exists(_ == "can_see_transaction_request_types")) + canUpdateBankAccountLabel_(actions.exists(_ == "can_update_bank_account_label")) + canSeeAvailableViewsForBankAccount_(actions.exists(_ == "can_see_available_views_for_bank_account")) } @@ -471,6 +478,7 @@ class ViewDefinition extends View with LongKeyedMapper[ViewDefinition] with Many def canSeeBankAccountCurrency : Boolean = canSeeBankAccountCurrency_.get def canQueryAvailableFunds : Boolean = canQueryAvailableFunds_.get def canSeeBankAccountLabel : Boolean = canSeeBankAccountLabel_.get + def canUpdateBankAccountLabel : Boolean = canUpdateBankAccountLabel_.get def canSeeBankAccountNationalIdentifier : Boolean = canSeeBankAccountNationalIdentifier_.get def canSeeBankAccountSwift_bic : Boolean = canSeeBankAccountSwift_bic_.get def canSeeBankAccountIban : Boolean = canSeeBankAccountIban_.get diff --git a/obp-api/src/test/scala/code/setup/TestConnectorSetupWithStandardPermissions.scala b/obp-api/src/test/scala/code/setup/TestConnectorSetupWithStandardPermissions.scala index 03f96341a5..a25c145db5 100644 --- a/obp-api/src/test/scala/code/setup/TestConnectorSetupWithStandardPermissions.scala +++ b/obp-api/src/test/scala/code/setup/TestConnectorSetupWithStandardPermissions.scala @@ -131,6 +131,10 @@ trait TestConnectorSetupWithStandardPermissions extends TestConnectorSetup { canAddTransactionRequestToOwnAccount_(false). //added following two for payments canAddTransactionRequestToAnyAccount_(false). canSeeBankAccountCreditLimit_(true). + canSeeTransactionRequests_(false). + canSeeTransactionRequestTypes_(false). + canUpdateBankAccountLabel_(false). + canSeeAvailableViewsForBankAccount_(false). saveMe } } diff --git a/obp-commons/src/main/scala/com/openbankproject/commons/model/ViewModel.scala b/obp-commons/src/main/scala/com/openbankproject/commons/model/ViewModel.scala index 0ee0f5a327..998ca7789d 100644 --- a/obp-commons/src/main/scala/com/openbankproject/commons/model/ViewModel.scala +++ b/obp-commons/src/main/scala/com/openbankproject/commons/model/ViewModel.scala @@ -297,6 +297,7 @@ trait View { def canSeeBankAccountOwners: Boolean def canSeeBankAccountType: Boolean + def canUpdateBankAccountLabel: Boolean def canSeeBankAccountBalance: Boolean From 7330e5434a168202ea5e96a497a9ddc669a7d041 Mon Sep 17 00:00:00 2001 From: hongwei Date: Fri, 23 Jun 2023 15:39:45 +0800 Subject: [PATCH 13/41] refactor/remove `hasOwnerViewAccess` replace with specific view permissions -- added canCreateCustomView_, canDeleteCustomView_ and canUpdateCustomView_ permissions --- .../scala/code/api/util/ErrorMessages.scala | 2 + .../main/scala/code/api/util/NewStyle.scala | 27 ++++++++--- ...MigrationOfViewDefinitionPermissions.scala | 6 +++ .../scala/code/api/v1_2_1/APIMethods121.scala | 28 ++++++++++-- .../scala/code/api/v2_2_0/APIMethods220.scala | 16 ++++++- .../scala/code/api/v3_0_0/APIMethods300.scala | 37 +++++++++------ .../main/scala/code/model/BankingData.scala | 45 ------------------- .../code/model/dataAccess/MappedView.scala | 13 ++++++ .../main/scala/code/views/MapperViews.scala | 13 ++++-- .../code/views/system/ViewDefinition.scala | 16 +++++++ .../commons/model/ViewModel.scala | 4 ++ 11 files changed, 135 insertions(+), 72 deletions(-) diff --git a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala index f980fbfea3..27f1f147be 100644 --- a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala +++ b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala @@ -455,6 +455,8 @@ object ErrorMessages { val DeleteCustomViewError = "OBP-30256: Could not delete the custom view" val CannotFindCustomViewError = "OBP-30257: Could not find the custom view" val SystemViewCannotBePublicError = "OBP-30258: System view cannot be public" + val CreateCustomViewError = "OBP-30259: Could not create the custom view" + val UpdateCustomViewError = "OBP-30260: Could not update the custom view" val TaxResidenceNotFound = "OBP-30300: Tax Residence not found by TAX_RESIDENCE_ID. " val CustomerAddressNotFound = "OBP-30310: Customer's Address not found by CUSTOMER_ADDRESS_ID. " 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 8a8901313d..4a17c25907 100644 --- a/obp-api/src/main/scala/code/api/util/NewStyle.scala +++ b/obp-api/src/main/scala/code/api/util/NewStyle.scala @@ -529,11 +529,6 @@ object NewStyle extends MdcLoggable{ } map { fullBoxOrException(_) } map { unboxFull(_) } - def removeView(account: BankAccount, user: User, viewId: ViewId, callContext: Option[CallContext]) = Future { - account.removeView(user, viewId, callContext) - } map { fullBoxOrException(_) - } map { unboxFull(_) } - def grantAccessToView(account: BankAccount, u: User, viewIdBankIdAccountId : ViewIdBankIdAccountId, provider : String, providerId: String, callContext: Option[CallContext]) = Future { account.grantAccessToView(u, viewIdBankIdAccountId, provider, providerId, callContext: Option[CallContext]) } map { fullBoxOrException(_) @@ -3956,6 +3951,28 @@ object NewStyle extends MdcLoggable{ .slice(offset.getOrElse("0").toInt, offset.getOrElse("0").toInt + limit.getOrElse("100").toInt) , callContext) } + + def createCustomView(bankAccountId: BankIdAccountId, createViewJson: CreateViewJson, callContext: Option[CallContext]): OBPReturnType[View] = + Future { + Views.views.vend.createCustomView(bankAccountId, createViewJson) + } map { i => + (unboxFullOrFail(i, callContext, s"$CreateCustomViewError", 404), callContext) + } + + def updateCustomView(bankAccountId : BankIdAccountId, viewId : ViewId, viewUpdateJson : UpdateViewJSON, callContext: Option[CallContext]): OBPReturnType[View] = + Future { + Views.views.vend.updateCustomView(bankAccountId, viewId, viewUpdateJson) + } map { i => + (unboxFullOrFail(i, callContext, s"$UpdateCustomViewError", 404), callContext) + } + + def removeCustomView(viewId: ViewId, bankAccountId: BankIdAccountId, callContext: Option[CallContext]) = + Future { + Views.views.vend.removeCustomView(viewId, bankAccountId) + } map { i => + (unboxFullOrFail(i, callContext, s"$DeleteCustomViewError", 404), callContext) + } + } } diff --git a/obp-api/src/main/scala/code/api/util/migration/MigrationOfViewDefinitionPermissions.scala b/obp-api/src/main/scala/code/api/util/migration/MigrationOfViewDefinitionPermissions.scala index abecac5165..2b05a20b91 100644 --- a/obp-api/src/main/scala/code/api/util/migration/MigrationOfViewDefinitionPermissions.scala +++ b/obp-api/src/main/scala/code/api/util/migration/MigrationOfViewDefinitionPermissions.scala @@ -24,6 +24,9 @@ object MigrationOfViewDefinitionPermissions { .canSeeTransactionRequests_(true) .canSeeAvailableViewsForBankAccount_(true) .canUpdateBankAccountLabel_(true) + .canCreateCustomView_(true) + .canDeleteCustomView_(true) + .canUpdateCustomView_(true) .save ).head @@ -37,6 +40,9 @@ object MigrationOfViewDefinitionPermissions { |${ViewDefinition.canSeeTransactionRequests_.dbColumnName} |${ViewDefinition.canSeeAvailableViewsForBankAccount_.dbColumnName} |${ViewDefinition.canUpdateBankAccountLabel_.dbColumnName} + |${ViewDefinition.canCreateCustomView_.dbColumnName} + |${ViewDefinition.canDeleteCustomView_.dbColumnName} + |${ViewDefinition.canUpdateCustomView_.dbColumnName} |Duration: ${endDate - startDate} ms; """.stripMargin saveLog(name, commitId, isSuccessful, startDate, endDate, comment) diff --git a/obp-api/src/main/scala/code/api/v1_2_1/APIMethods121.scala b/obp-api/src/main/scala/code/api/v1_2_1/APIMethods121.scala index 02da458068..7e2f60d4d2 100644 --- a/obp-api/src/main/scala/code/api/v1_2_1/APIMethods121.scala +++ b/obp-api/src/main/scala/code/api/v1_2_1/APIMethods121.scala @@ -622,7 +622,13 @@ trait APIMethods121 { createViewJsonV121.hide_metadata_if_alias_used, createViewJsonV121.allowed_actions ) - view <- account createCustomView (u, createViewJson, Some(cc)) + anyViewContainsCanCreateCustomViewPermission = Views.views.vend.permission(BankIdAccountId(account.bankId, account.accountId), u) + .map(_.views.map(_.canCreateCustomView).find(_.==(true)).getOrElse(false)).getOrElse(false) + _ <- booleanToBox( + anyViewContainsCanCreateCustomViewPermission, + s"${ErrorMessages.CreateCustomViewError} You need the `${ViewDefinition.canCreateCustomView_.dbColumnName}` permission on any your views" + ) + view <- Views.views.vend.createCustomView(BankIdAccountId(bankId,accountId), createViewJson)?~ CreateCustomViewError } yield { val viewJSON = JSONFactory.createViewJSON(view) successJsonResponse(Extraction.decompose(viewJSON), 201) @@ -677,7 +683,13 @@ trait APIMethods121 { hide_metadata_if_alias_used = updateJsonV121.hide_metadata_if_alias_used, allowed_actions = updateJsonV121.allowed_actions ) - updatedView <- account.updateView(u, viewId, updateViewJson, Some(cc)) + anyViewContainsCancanUpdateCustomViewPermission = Views.views.vend.permission(BankIdAccountId(account.bankId, account.accountId), u) + .map(_.views.map(_.canUpdateCustomView).find(_.==(true)).getOrElse(false)).getOrElse(false) + _ <- booleanToBox( + anyViewContainsCancanUpdateCustomViewPermission, + s"${ErrorMessages.CreateCustomViewError} You need the `${ViewDefinition.canUpdateCustomView_.dbColumnName}` permission on any your views" + ) + updatedView <- Views.views.vend.updateCustomView(BankIdAccountId(bankId, accountId),viewId, updateViewJson) ?~ CreateCustomViewError } yield { val viewJSON = JSONFactory.createViewJSON(updatedView) successJsonResponse(Extraction.decompose(viewJSON), 200) @@ -716,7 +728,17 @@ trait APIMethods121 { // custom views start with `_` eg _play, _work, and System views start with a letter, eg: owner _ <- Helper.booleanToFuture(InvalidCustomViewFormat+s"Current view_name (${viewId.value})", cc=callContext) { viewId.value.startsWith("_") } _ <- NewStyle.function.customView(viewId, BankIdAccountId(bankId, accountId), callContext) - deleted <- NewStyle.function.removeView(account, u, viewId, callContext) + + anyViewContainsCanDeleteCustomViewPermission = Views.views.vend.permission(BankIdAccountId(account.bankId, account.accountId), u) + .map(_.views.map(_.canDeleteCustomView).find(_.==(true)).getOrElse(false)).getOrElse(false) + _ <- Helper.booleanToFuture( + s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${ViewDefinition.canDeleteCustomView_.dbColumnName}` permission on any your views", + cc = callContext + ) { + anyViewContainsCanDeleteCustomViewPermission + } + + deleted <- NewStyle.function.removeCustomView(viewId, BankIdAccountId(bankId, accountId),callContext) } yield { (Full(deleted), HttpCode.`204`(callContext)) } diff --git a/obp-api/src/main/scala/code/api/v2_2_0/APIMethods220.scala b/obp-api/src/main/scala/code/api/v2_2_0/APIMethods220.scala index d5a9360235..64dd1ab344 100644 --- a/obp-api/src/main/scala/code/api/v2_2_0/APIMethods220.scala +++ b/obp-api/src/main/scala/code/api/v2_2_0/APIMethods220.scala @@ -170,8 +170,14 @@ trait APIMethods220 { createViewJsonV121.which_alias_to_use, createViewJsonV121.hide_metadata_if_alias_used, createViewJsonV121.allowed_actions + ) + anyViewContainsCanCreateCustomViewPermission = Views.views.vend.permission(BankIdAccountId(account.bankId, account.accountId), u) + .map(_.views.map(_.canCreateCustomView).find(_.==(true)).getOrElse(false)).getOrElse(false) + _ <- booleanToBox( + anyViewContainsCanCreateCustomViewPermission, + s"${ErrorMessages.CreateCustomViewError} You need the `${ViewDefinition.canCreateCustomView_.dbColumnName}` permission on any your views" ) - view <- account.createCustomView(u, createViewJson, Some(cc)) + view <- Views.views.vend.createCustomView(BankIdAccountId(bankId, accountId), createViewJson) ?~ CreateCustomViewError } yield { val viewJSON = JSONFactory220.createViewJSON(view) successJsonResponse(Extraction.decompose(viewJSON), 201) @@ -224,7 +230,13 @@ trait APIMethods220 { hide_metadata_if_alias_used = updateJsonV121.hide_metadata_if_alias_used, allowed_actions = updateJsonV121.allowed_actions ) - updatedView <- account.updateView(u, viewId, updateViewJson, Some(cc)) + anyViewContainsCancanUpdateCustomViewPermission = Views.views.vend.permission(BankIdAccountId(account.bankId, account.accountId), u) + .map(_.views.map(_.canUpdateCustomView).find(_.==(true)).getOrElse(false)).getOrElse(false) + _ <- booleanToBox( + anyViewContainsCancanUpdateCustomViewPermission, + s"${ErrorMessages.CreateCustomViewError} You need the `${ViewDefinition.canUpdateCustomView_.dbColumnName}` permission on any your views" + ) + updatedView <- Views.views.vend.updateCustomView(BankIdAccountId(bankId, accountId), viewId, updateViewJson) ?~ CreateCustomViewError } yield { val viewJSON = JSONFactory220.createViewJSON(updatedView) successJsonResponse(Extraction.decompose(viewJSON), 200) diff --git a/obp-api/src/main/scala/code/api/v3_0_0/APIMethods300.scala b/obp-api/src/main/scala/code/api/v3_0_0/APIMethods300.scala index 5e7db318d0..b307f05bdc 100644 --- a/obp-api/src/main/scala/code/api/v3_0_0/APIMethods300.scala +++ b/obp-api/src/main/scala/code/api/v3_0_0/APIMethods300.scala @@ -27,6 +27,7 @@ import code.users.Users import code.util.Helper import code.util.Helper.booleanToBox import code.views.Views +import code.views.system.ViewDefinition import com.github.dwickern.macros.NameOf.nameOf import com.grum.geocalc.{Coordinate, EarthCalc, Point} import com.openbankproject.commons.model._ @@ -167,7 +168,6 @@ trait APIMethods300 { //creates a view on an bank account case "banks" :: BankId(bankId) :: "accounts" :: AccountId(accountId) :: "views" :: Nil JsonPost json -> _ => { cc => - val res = for { (Full(u), callContext) <- authenticatedAccess(cc) createViewJson <- Future { tryo{json.extract[CreateViewJson]} } map { @@ -179,14 +179,18 @@ trait APIMethods300 { checkCustomViewIdOrName(createViewJson.name) } (account, callContext) <- NewStyle.function.getBankAccount(bankId, accountId, callContext) + + anyViewContainsCanCreateCustomViewPermission = Views.views.vend.permission(BankIdAccountId(account.bankId, account.accountId), u) + .map(_.views.map(_.canCreateCustomView).find(_.==(true)).getOrElse(false)).getOrElse(false) + + _ <- Helper.booleanToFuture( + s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${ViewDefinition.canCreateCustomView_.dbColumnName}` permission on any your views", + cc = callContext + ) {anyViewContainsCanCreateCustomViewPermission} + (view, callContext) <- NewStyle.function.createCustomView(BankIdAccountId(bankId, accountId), createViewJson, callContext) } yield { - for { - view <- account.createCustomView (u, createViewJson, callContext) - } yield { - (JSONFactory300.createViewJSON(view), callContext.map(_.copy(httpCode = Some(201)))) - } + (JSONFactory300.createViewJSON(view), HttpCode.`200`(callContext)) } - res map { fullBoxOrException(_) } map { unboxFull(_) } } } @@ -253,7 +257,6 @@ trait APIMethods300 { //updates a view on a bank account case "banks" :: BankId(bankId) :: "accounts" :: AccountId(accountId) :: "views" :: ViewId(viewId) :: Nil JsonPut json -> _ => { cc => - val res = for { (Full(u), callContext) <- authenticatedAccess(cc) updateJson <- Future { tryo{json.extract[UpdateViewJsonV300]} } map { @@ -273,14 +276,20 @@ trait APIMethods300 { !view.isSystem } (account, callContext) <- NewStyle.function.getBankAccount(bankId, accountId, callContext) - } yield { - for { - updatedView <- account.updateView(u, viewId, updateJson.toUpdateViewJson, callContext) - } yield { - (JSONFactory300.createViewJSON(updatedView), HttpCode.`200`(callContext)) + + anyViewContainsCancanUpdateCustomViewPermission = Views.views.vend.permission(BankIdAccountId(account.bankId, account.accountId), u) + .map(_.views.map(_.canUpdateCustomView).find(_.==(true)).getOrElse(false)).getOrElse(false) + + _ <- Helper.booleanToFuture( + s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${ViewDefinition.canUpdateCustomView_.dbColumnName}` permission on any your views", + cc = callContext + ) { + anyViewContainsCancanUpdateCustomViewPermission } + (view, callContext) <- NewStyle.function.updateCustomView(BankIdAccountId(bankId, accountId), viewId, updateJson.toUpdateViewJson, callContext) + } yield { + (JSONFactory300.createViewJSON(view), HttpCode.`200`(callContext)) } - res map { fullBoxOrException(_) } map { unboxFull(_) } } } diff --git a/obp-api/src/main/scala/code/model/BankingData.scala b/obp-api/src/main/scala/code/model/BankingData.scala index 80d45118f1..549c372771 100644 --- a/obp-api/src/main/scala/code/model/BankingData.scala +++ b/obp-api/src/main/scala/code/model/BankingData.scala @@ -338,51 +338,6 @@ case class BankAccountExtended(val bankAccount: BankAccount) extends MdcLoggable Failure(UserNoOwnerView+"user's email : " + user.emailAddress + ". account : " + accountId, Empty, Empty) } - - final def createCustomView(userDoingTheCreate : User,v: CreateViewJson, callContext: Option[CallContext]): Box[View] = { - if(!userDoingTheCreate.hasOwnerViewAccess(BankIdAccountId(bankId,accountId), callContext)) { - Failure({"user: " + userDoingTheCreate.idGivenByProvider + " at provider " + userDoingTheCreate.provider + " does not have owner access"}) - } else { - val view = Views.views.vend.createCustomView(BankIdAccountId(bankId,accountId), v) - - //if(view.isDefined) { - // logger.debug("user: " + userDoingTheCreate.idGivenByProvider + " at provider " + userDoingTheCreate.provider + " created view: " + view.get + - // " for account " + accountId + "at bank " + bankId) - //} - - view - } - } - - final def updateView(userDoingTheUpdate : User, viewId : ViewId, v: UpdateViewJSON, callContext: Option[CallContext]) : Box[View] = { - if(!userDoingTheUpdate.hasOwnerViewAccess(BankIdAccountId(bankId,accountId), callContext)) { - Failure({"user: " + userDoingTheUpdate.idGivenByProvider + " at provider " + userDoingTheUpdate.provider + " does not have owner access"}) - } else { - val view = Views.views.vend.updateCustomView(BankIdAccountId(bankId,accountId), viewId, v) - //if(view.isDefined) { - // logger.debug("user: " + userDoingTheUpdate.idGivenByProvider + " at provider " + userDoingTheUpdate.provider + " updated view: " + view.get + - // " for account " + accountId + "at bank " + bankId) - //} - - view - } - } - - final def removeView(userDoingTheRemove : User, viewId: ViewId, callContext: Option[CallContext]) : Box[Boolean] = { - if(!userDoingTheRemove.hasOwnerViewAccess(BankIdAccountId(bankId,accountId), callContext)) { - return Failure({"user: " + userDoingTheRemove.idGivenByProvider + " at provider " + userDoingTheRemove.provider + " does not have owner access"}) - } else { - val deleted = Views.views.vend.removeCustomView(viewId, BankIdAccountId(bankId,accountId)) - - //if (deleted.isDefined) { - // logger.debug("user: " + userDoingTheRemove.idGivenByProvider + " at provider " + userDoingTheRemove.provider + " deleted view: " + viewId + - // " for account " + accountId + "at bank " + bankId) - //} - - deleted - } - } - final def moderatedTransaction(transactionId: TransactionId, view: View, bankIdAccountId: BankIdAccountId, user: Box[User], callContext: Option[CallContext] = None) : Box[(ModeratedTransaction, Option[CallContext])] = { if(APIUtil.hasAccountAccess(view, bankIdAccountId, user, callContext)) for{ diff --git a/obp-api/src/main/scala/code/model/dataAccess/MappedView.scala b/obp-api/src/main/scala/code/model/dataAccess/MappedView.scala index 0108fd6a13..8a1d427d25 100644 --- a/obp-api/src/main/scala/code/model/dataAccess/MappedView.scala +++ b/obp-api/src/main/scala/code/model/dataAccess/MappedView.scala @@ -439,6 +439,15 @@ class ViewImpl extends View with LongKeyedMapper[ViewImpl] with ManyToMany with object canSeeBankAccountCreditLimit_ extends MappedBoolean(this){ override def defaultValue = false } + object canCreateCustomView_ extends MappedBoolean(this){ + override def defaultValue = false + } + object canDeleteCustomView_ extends MappedBoolean(this){ + override def defaultValue = false + } + object canUpdateCustomView_ extends MappedBoolean(this){ + override def defaultValue = false + } def id: Long = id_.get def isSystem: Boolean = isSystem_.get @@ -555,6 +564,10 @@ class ViewImpl extends View with LongKeyedMapper[ViewImpl] with ManyToMany with def canCreateStandingOrder: Boolean = false //TODO: if you add new permissions here, remember to set them wherever views are created // (e.g. BankAccountCreationDispatcher) + + def canCreateCustomView: Boolean = canCreateCustomView_.get + def canDeleteCustomView: Boolean = canDeleteCustomView_.get + def canUpdateCustomView: Boolean = canUpdateCustomView_.get } object ViewImpl extends ViewImpl with LongKeyedMetaMapper[ViewImpl]{ diff --git a/obp-api/src/main/scala/code/views/MapperViews.scala b/obp-api/src/main/scala/code/views/MapperViews.scala index e29229f65c..44a40a3f0b 100644 --- a/obp-api/src/main/scala/code/views/MapperViews.scala +++ b/obp-api/src/main/scala/code/views/MapperViews.scala @@ -791,9 +791,12 @@ object MapperViews extends Views with MdcLoggable { .canAddTransactionRequestToOwnAccount_(true) //added following two for payments .canAddTransactionRequestToAnyAccount_(true) .canSeeAvailableViewsForBankAccount_(false) - .canSeeTransactionRequests_(true) - .canSeeTransactionRequestTypes_(true) - .canUpdateBankAccountLabel_(true) + .canSeeTransactionRequests_(false) + .canSeeTransactionRequestTypes_(false) + .canUpdateBankAccountLabel_(false) + .canCreateCustomView_(false) + .canDeleteCustomView_(false) + .canUpdateCustomView_(false) viewId match { case SYSTEM_OWNER_VIEW_ID => @@ -801,6 +804,10 @@ object MapperViews extends Views with MdcLoggable { .canSeeAvailableViewsForBankAccount_(true) .canSeeTransactionRequests_(true) .canSeeTransactionRequestTypes_(true) + .canUpdateBankAccountLabel_(true) + .canCreateCustomView_(true) + .canDeleteCustomView_(true) + .canUpdateCustomView_(true) case SYSTEM_STAGE_ONE_VIEW_ID => entity .canSeeTransactionDescription_(false) diff --git a/obp-api/src/main/scala/code/views/system/ViewDefinition.scala b/obp-api/src/main/scala/code/views/system/ViewDefinition.scala index 7739029779..1cf88b3d83 100644 --- a/obp-api/src/main/scala/code/views/system/ViewDefinition.scala +++ b/obp-api/src/main/scala/code/views/system/ViewDefinition.scala @@ -304,6 +304,16 @@ class ViewDefinition extends View with LongKeyedMapper[ViewDefinition] with Many object canCreateStandingOrder_ extends MappedBoolean(this){ override def defaultValue = false } + + object canCreateCustomView_ extends MappedBoolean(this){ + override def defaultValue = false + } + object canDeleteCustomView_ extends MappedBoolean(this){ + override def defaultValue = false + } + object canUpdateCustomView_ extends MappedBoolean(this){ + override def defaultValue = false + } //Important! If you add a field, be sure to handle it here in this function def setFromViewData(viewData : ViewSpecification) = { @@ -410,6 +420,9 @@ class ViewDefinition extends View with LongKeyedMapper[ViewDefinition] with Many canSeeTransactionRequestTypes_(actions.exists(_ == "can_see_transaction_request_types")) canUpdateBankAccountLabel_(actions.exists(_ == "can_update_bank_account_label")) canSeeAvailableViewsForBankAccount_(actions.exists(_ == "can_see_available_views_for_bank_account")) + canCreateCustomView_(actions.exists(_ == "can_create_custom_view")) + canDeleteCustomView_(actions.exists(_ == "can_delete_custom_view")) + canUpdateCustomView_(actions.exists(_ == "can_update_custom_view")) } @@ -544,6 +557,9 @@ class ViewDefinition extends View with LongKeyedMapper[ViewDefinition] with Many def canCreateDirectDebit: Boolean = canCreateDirectDebit_.get def canCreateStandingOrder: Boolean = canCreateStandingOrder_.get + def canCreateCustomView: Boolean = canCreateCustomView_.get + def canDeleteCustomView: Boolean = canDeleteCustomView_.get + def canUpdateCustomView: Boolean = canUpdateCustomView_.get //TODO: if you add new permissions here, remember to set them wherever views are created // (e.g. BankAccountCreationDispatcher) } diff --git a/obp-commons/src/main/scala/com/openbankproject/commons/model/ViewModel.scala b/obp-commons/src/main/scala/com/openbankproject/commons/model/ViewModel.scala index 998ca7789d..21e1bf2c19 100644 --- a/obp-commons/src/main/scala/com/openbankproject/commons/model/ViewModel.scala +++ b/obp-commons/src/main/scala/com/openbankproject/commons/model/ViewModel.scala @@ -421,4 +421,8 @@ trait View { def canCreateDirectDebit: Boolean def canCreateStandingOrder: Boolean + + def canCreateCustomView: Boolean + def canDeleteCustomView: Boolean + def canUpdateCustomView: Boolean } \ No newline at end of file From 7eb89aa0d06d510b78e393491bdd4324195e7641 Mon Sep 17 00:00:00 2001 From: hongwei Date: Fri, 23 Jun 2023 16:06:45 +0800 Subject: [PATCH 14/41] refactor/remove `hasOwnerViewAccess` replace with specific view permissions -- added canCreateCustomView_, canDeleteCustomView_ and canUpdateCustomView_ permissions - fixed tests --- obp-api/src/main/scala/code/api/util/NewStyle.scala | 6 +++--- .../main/scala/code/api/v3_0_0/APIMethods300.scala | 2 +- obp-api/src/main/scala/code/model/BankingData.scala | 11 ----------- 3 files changed, 4 insertions(+), 15 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 4a17c25907..96a932679b 100644 --- a/obp-api/src/main/scala/code/api/util/NewStyle.scala +++ b/obp-api/src/main/scala/code/api/util/NewStyle.scala @@ -3956,21 +3956,21 @@ object NewStyle extends MdcLoggable{ Future { Views.views.vend.createCustomView(bankAccountId, createViewJson) } map { i => - (unboxFullOrFail(i, callContext, s"$CreateCustomViewError", 404), callContext) + (unboxFullOrFail(i, callContext, s"$CreateCustomViewError"), callContext) } def updateCustomView(bankAccountId : BankIdAccountId, viewId : ViewId, viewUpdateJson : UpdateViewJSON, callContext: Option[CallContext]): OBPReturnType[View] = Future { Views.views.vend.updateCustomView(bankAccountId, viewId, viewUpdateJson) } map { i => - (unboxFullOrFail(i, callContext, s"$UpdateCustomViewError", 404), callContext) + (unboxFullOrFail(i, callContext, s"$UpdateCustomViewError"), callContext) } def removeCustomView(viewId: ViewId, bankAccountId: BankIdAccountId, callContext: Option[CallContext]) = Future { Views.views.vend.removeCustomView(viewId, bankAccountId) } map { i => - (unboxFullOrFail(i, callContext, s"$DeleteCustomViewError", 404), callContext) + (unboxFullOrFail(i, callContext, s"$DeleteCustomViewError"), callContext) } } diff --git a/obp-api/src/main/scala/code/api/v3_0_0/APIMethods300.scala b/obp-api/src/main/scala/code/api/v3_0_0/APIMethods300.scala index b307f05bdc..0fd327cc2e 100644 --- a/obp-api/src/main/scala/code/api/v3_0_0/APIMethods300.scala +++ b/obp-api/src/main/scala/code/api/v3_0_0/APIMethods300.scala @@ -189,7 +189,7 @@ trait APIMethods300 { ) {anyViewContainsCanCreateCustomViewPermission} (view, callContext) <- NewStyle.function.createCustomView(BankIdAccountId(bankId, accountId), createViewJson, callContext) } yield { - (JSONFactory300.createViewJSON(view), HttpCode.`200`(callContext)) + (JSONFactory300.createViewJSON(view), HttpCode.`201`(callContext)) } } } diff --git a/obp-api/src/main/scala/code/model/BankingData.scala b/obp-api/src/main/scala/code/model/BankingData.scala index 549c372771..0e06e38a0a 100644 --- a/obp-api/src/main/scala/code/model/BankingData.scala +++ b/obp-api/src/main/scala/code/model/BankingData.scala @@ -152,17 +152,6 @@ case class BankAccountExtended(val bankAccount: BankAccount) extends MdcLoggable final def bankRoutingAddress : String = Connector.connector.vend.getBankLegacy(bankId, None).map(_._1).map(_.bankRoutingAddress).getOrElse("") - /* - * Delete this account (if connector allows it, e.g. local mirror of account data) - * */ - final def remove(user : User, callContext: Option[CallContext]): Box[Boolean] = { - if(user.hasOwnerViewAccess(BankIdAccountId(bankId,accountId), callContext)){ - Full(Connector.connector.vend.removeAccount(bankId, accountId).openOrThrowException(attemptedToOpenAnEmptyBox)) - } else { - Failure(UserNoOwnerView+"user's email : " + user.emailAddress + ". account : " + accountId, Empty, Empty) - } - } - /** * Note: There are two types of account-owners in OBP: the OBP users and the customers(in a real bank, these should from Main Frame) * From f65e4bca5de5a831247ebbb9cc1a38f55ad85444 Mon Sep 17 00:00:00 2001 From: hongwei Date: Tue, 20 Jun 2023 21:00:23 +0800 Subject: [PATCH 15/41] refactor/turn off the gargoylesoftware.htmlunit.javascript log --- obp-api/src/main/resources/logback-test.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/obp-api/src/main/resources/logback-test.xml b/obp-api/src/main/resources/logback-test.xml index 871aea062a..6c5d33fbf5 100644 --- a/obp-api/src/main/resources/logback-test.xml +++ b/obp-api/src/main/resources/logback-test.xml @@ -9,4 +9,10 @@ + + + + + + \ No newline at end of file From 44f5321e84a5a8ac1d25ef005a37b18da7f4bfa3 Mon Sep 17 00:00:00 2001 From: hongwei Date: Fri, 23 Jun 2023 17:38:08 +0800 Subject: [PATCH 16/41] refactor/remove `hasOwnerViewAccess` replace with specific view permissions -- added canSeePermissionForOneUser_, canSeePermissionsForAllUsers_ --- .../scala/code/api/util/ErrorMessages.scala | 1 + .../main/scala/code/api/util/NewStyle.scala | 5 --- ...MigrationOfViewDefinitionPermissions.scala | 4 +++ .../scala/code/api/v1_2_1/APIMethods121.scala | 24 +++++++++++--- .../scala/code/api/v2_0_0/APIMethods200.scala | 22 +++++++++++-- .../scala/code/api/v3_0_0/APIMethods300.scala | 17 +++++++--- .../main/scala/code/model/BankingData.scala | 31 ------------------- .../code/model/dataAccess/MappedView.scala | 8 +++++ .../main/scala/code/views/MapperViews.scala | 4 +++ .../code/views/system/ViewDefinition.scala | 10 ++++++ ...onnectorSetupWithStandardPermissions.scala | 4 --- .../commons/model/ViewModel.scala | 4 +++ 12 files changed, 82 insertions(+), 52 deletions(-) diff --git a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala index 27f1f147be..982b1067b8 100644 --- a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala +++ b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala @@ -207,6 +207,7 @@ object ErrorMessages { val UserNotSuperAdminOrMissRole = "OBP-20101: Current User is not super admin or is missing entitlements:" val CannotGetOrCreateUser = "OBP-20102: Cannot get or create user." val InvalidUserProvider = "OBP-20103: Invalid DAuth User Provider." + val UserNotFoundByProviderAndProvideId= "OBP-20104: User not found by PROVIDER and PROVIDER_ID." // OAuth 2 val ApplicationNotIdentified = "OBP-20200: The application cannot be identified. " 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 96a932679b..e1e2a3452e 100644 --- a/obp-api/src/main/scala/code/api/util/NewStyle.scala +++ b/obp-api/src/main/scala/code/api/util/NewStyle.scala @@ -519,11 +519,6 @@ object NewStyle extends MdcLoggable{ } } - def permissions(account: BankAccount, user: User, callContext: Option[CallContext]) = Future { - account.permissions(user, callContext) - } map { fullBoxOrException(_) - } map { unboxFull(_) } - def permission(bankId: BankId,accountId: AccountId, user: User, callContext: Option[CallContext]) = Future { Views.views.vend.permission(BankIdAccountId(bankId, accountId), user) } map { fullBoxOrException(_) diff --git a/obp-api/src/main/scala/code/api/util/migration/MigrationOfViewDefinitionPermissions.scala b/obp-api/src/main/scala/code/api/util/migration/MigrationOfViewDefinitionPermissions.scala index 2b05a20b91..3b2768d77b 100644 --- a/obp-api/src/main/scala/code/api/util/migration/MigrationOfViewDefinitionPermissions.scala +++ b/obp-api/src/main/scala/code/api/util/migration/MigrationOfViewDefinitionPermissions.scala @@ -27,6 +27,8 @@ object MigrationOfViewDefinitionPermissions { .canCreateCustomView_(true) .canDeleteCustomView_(true) .canUpdateCustomView_(true) + .canSeePermissionForOneUser_(true) + .canSeePermissionsForAllUsers_(true) .save ).head @@ -43,6 +45,8 @@ object MigrationOfViewDefinitionPermissions { |${ViewDefinition.canCreateCustomView_.dbColumnName} |${ViewDefinition.canDeleteCustomView_.dbColumnName} |${ViewDefinition.canUpdateCustomView_.dbColumnName} + |${ViewDefinition.canSeePermissionsForAllUsers_.dbColumnName} + |${ViewDefinition.canSeePermissionForOneUser_.dbColumnName} |Duration: ${endDate - startDate} ms; """.stripMargin saveLog(name, commitId, isSuccessful, startDate, endDate, comment) diff --git a/obp-api/src/main/scala/code/api/v1_2_1/APIMethods121.scala b/obp-api/src/main/scala/code/api/v1_2_1/APIMethods121.scala index 7e2f60d4d2..31ee40bd43 100644 --- a/obp-api/src/main/scala/code/api/v1_2_1/APIMethods121.scala +++ b/obp-api/src/main/scala/code/api/v1_2_1/APIMethods121.scala @@ -15,7 +15,7 @@ import code.api.util._ import code.bankconnectors._ import code.metadata.comments.Comments import code.metadata.counterparties.Counterparties -import code.model.{BankAccountX, BankX, ModeratedTransactionMetadata, toBankAccountExtended, toBankExtended, toUserExtended} +import code.model.{BankAccountX, BankX, ModeratedTransactionMetadata, UserX, toBankAccountExtended, toBankExtended, toUserExtended} import code.util.Helper import code.util.Helper.booleanToBox import code.views.Views @@ -768,7 +768,13 @@ trait APIMethods121 { for { u <- cc.user ?~ UserNotLoggedIn account <- BankAccountX(bankId, accountId) ?~! BankAccountNotFound - permissions <- account.permissions(u, Some(cc)) + anyViewContainsCanSeePermissionsForAllUsersPermission = Views.views.vend.permission(BankIdAccountId(account.bankId, account.accountId), u) + .map(_.views.map(_.canSeePermissionsForAllUsers).find(_.==(true)).getOrElse(false)).getOrElse(false) + _ <- booleanToBox( + anyViewContainsCanSeePermissionsForAllUsersPermission, + s"${ErrorMessages.CreateCustomViewError} You need the `${ViewDefinition.canSeePermissionsForAllUsers_.dbColumnName}` permission on any your views" + ) + permissions = Views.views.vend.permissions(BankIdAccountId(bankId, accountId)) } yield { val permissionsJSON = JSONFactory.createPermissionsJSON(permissions) successJsonResponse(Extraction.decompose(permissionsJSON)) @@ -801,12 +807,20 @@ trait APIMethods121 { lazy val getPermissionForUserForBankAccount: OBPEndpoint = { //get access for specific user - case "banks" :: BankId(bankId) :: "accounts" :: AccountId(accountId) :: "permissions" :: providerId :: userId :: Nil JsonGet req => { + case "banks" :: BankId(bankId) :: "accounts" :: AccountId(accountId) :: "permissions" :: provider :: providerId :: Nil JsonGet req => { cc => for { - u <- cc.user ?~ UserNotLoggedIn + loggedInUser <- cc.user ?~ UserNotLoggedIn account <- BankAccountX(bankId, accountId) ?~! BankAccountNotFound - permission <- account permission(u, providerId, userId, Some(cc)) + loggedInUserPermissionBox = Views.views.vend.permission(BankIdAccountId(bankId, accountId), loggedInUser) + anyViewContainsCanSeePermissionForOneUserPermission = loggedInUserPermissionBox.map(_.views.map(_.canSeePermissionForOneUser) + .find(_.==(true)).getOrElse(false)).getOrElse(false) + _ <- booleanToBox( + anyViewContainsCanSeePermissionForOneUserPermission, + s"${ErrorMessages.CreateCustomViewError} You need the `${ViewDefinition.canSeePermissionForOneUser_.dbColumnName}` permission on any your views" + ) + userFromURL <- UserX.findByProviderId(provider, providerId) ?~! UserNotFoundByProviderAndProvideId + permission <- Views.views.vend.permission(BankIdAccountId(bankId, accountId), userFromURL) } yield { val views = JSONFactory.createViewsJSON(permission.views) successJsonResponse(Extraction.decompose(views)) diff --git a/obp-api/src/main/scala/code/api/v2_0_0/APIMethods200.scala b/obp-api/src/main/scala/code/api/v2_0_0/APIMethods200.scala index 8b73b1594b..0cc0a85971 100644 --- a/obp-api/src/main/scala/code/api/v2_0_0/APIMethods200.scala +++ b/obp-api/src/main/scala/code/api/v2_0_0/APIMethods200.scala @@ -1011,7 +1011,15 @@ trait APIMethods200 { (Full(u), callContext) <- authenticatedAccess(cc) (_, callContext) <- NewStyle.function.getBank(bankId, callContext) (account, callContext) <- NewStyle.function.getBankAccount(bankId, accountId, callContext) - permissions <- NewStyle.function.permissions(account, u, callContext) + anyViewContainsCanSeePermissionsForAllUsersPermission = Views.views.vend.permission(BankIdAccountId(account.bankId, account.accountId), u) + .map(_.views.map(_.canUpdateBankAccountLabel).find(_.==(true)).getOrElse(false)).getOrElse(false) + _ <- Helper.booleanToFuture( + s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${ViewDefinition.canSeePermissionsForAllUsers_.dbColumnName}` permission on any your views", + cc = callContext + ) { + anyViewContainsCanSeePermissionsForAllUsersPermission + } + permissions = Views.views.vend.permissions(BankIdAccountId(bankId, accountId)) } yield { val permissionsJSON = JSONFactory121.createPermissionsJSON(permissions.sortBy(_.user.emailAddress)) (permissionsJSON, HttpCode.`200`(callContext)) @@ -1042,10 +1050,18 @@ trait APIMethods200 { case "banks" :: BankId(bankId) :: "accounts" :: AccountId(accountId) :: "permissions" :: provider :: providerId :: Nil JsonGet req => { cc => for { - u <- cc.user ?~! ErrorMessages.UserNotLoggedIn // Check we have a user (rather than error or empty) + loggedInUser <- cc.user ?~! ErrorMessages.UserNotLoggedIn // Check we have a user (rather than error or empty) (bank, callContext) <- BankX(bankId, Some(cc)) ?~! BankNotFound // Check bank exists. account <- BankAccountX(bank.bankId, accountId) ?~! {ErrorMessages.AccountNotFound} // Check Account exists. - permission <- account permission(u, provider, providerId, Some(cc)) + loggedInUserPermissionBox = Views.views.vend.permission(BankIdAccountId(bankId, accountId), loggedInUser) + anyViewContainsCanSeePermissionForOneUserPermission = loggedInUserPermissionBox.map(_.views.map(_.canSeePermissionForOneUser) + .find(_.==(true)).getOrElse(false)).getOrElse(false) + _ <- booleanToBox( + anyViewContainsCanSeePermissionForOneUserPermission, + s"${ErrorMessages.CreateCustomViewError} You need the `${ViewDefinition.canSeePermissionForOneUser_.dbColumnName}` permission on any your views" + ) + userFromURL <- UserX.findByProviderId(provider, providerId) ?~! UserNotFoundByProviderAndProvideId + permission <- Views.views.vend.permission(BankIdAccountId(bankId, accountId), userFromURL) } yield { // TODO : Note this is using old createViewsJSON without can_add_counterparty etc. val views = JSONFactory121.createViewsJSON(permission.views.sortBy(_.viewId.value)) diff --git a/obp-api/src/main/scala/code/api/v3_0_0/APIMethods300.scala b/obp-api/src/main/scala/code/api/v3_0_0/APIMethods300.scala index 0fd327cc2e..392caa6687 100644 --- a/obp-api/src/main/scala/code/api/v3_0_0/APIMethods300.scala +++ b/obp-api/src/main/scala/code/api/v3_0_0/APIMethods300.scala @@ -217,12 +217,21 @@ trait APIMethods300 { case "banks" :: BankId(bankId) :: "accounts" :: AccountId(accountId) :: "permissions" :: provider :: providerId :: Nil JsonGet req => { cc => for { - (Full(u), callContext) <- authenticatedAccess(cc) + (Full(loggedInUser), callContext) <- authenticatedAccess(cc) (_, callContext) <- NewStyle.function.getBank(bankId, callContext) (account, callContext) <- NewStyle.function.checkBankAccountExists(bankId, accountId, callContext) - permission <- Future { account.permission(u, provider, providerId, callContext) } map { - x => fullBoxOrException(x ~> APIFailureNewStyle(UserNoOwnerView, 400, callContext.map(_.toLight))) - } map { unboxFull(_) } + anyViewContainsCanSeePermissionForOneUserPermission = Views.views.vend.permission(BankIdAccountId(account.bankId, account.accountId), loggedInUser) + .map(_.views.map(_.canUpdateBankAccountLabel).find(_.==(true)).getOrElse(false)).getOrElse(false) + _ <- Helper.booleanToFuture( + s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${ViewDefinition.canSeePermissionForOneUser_.dbColumnName}` permission on any your views", + cc = callContext + ) { + anyViewContainsCanSeePermissionForOneUserPermission + } + (userFromURL, callContext) <- Future{UserX.findByProviderId(provider, providerId)} map { i => + (unboxFullOrFail(i, callContext, UserNotFoundByProviderAndProvideId, 404), callContext) + } + permission <- NewStyle.function.permission(bankId, accountId, userFromURL, callContext) } yield { (createViewsJSON(permission.views.sortBy(_.viewId.value)), HttpCode.`200`(callContext)) } diff --git a/obp-api/src/main/scala/code/model/BankingData.scala b/obp-api/src/main/scala/code/model/BankingData.scala index 0e06e38a0a..cdb2347d31 100644 --- a/obp-api/src/main/scala/code/model/BankingData.scala +++ b/obp-api/src/main/scala/code/model/BankingData.scala @@ -211,37 +211,6 @@ case class BankAccountExtended(val bankAccount: BankAccount) extends MdcLoggable private def viewNotAllowed(view : View ) = Failure(s"${UserNoPermissionAccessView} Current VIEW_ID (${view.viewId.value})") - - - /** - * @param user a user requesting to see the other users' permissions - * @return a Box of all the users' permissions of this bank account if the user passed as a parameter has access to the owner view (allowed to see this kind of data) - */ - final def permissions(user : User, callContext: Option[CallContext]) : Box[List[Permission]] = { - //check if the user have access to the owner view in this the account - if(user.hasOwnerViewAccess(BankIdAccountId(bankId, accountId), callContext)) - Full(Views.views.vend.permissions(BankIdAccountId(bankId, accountId))) - else - Failure("user " + user.emailAddress + " does not have access to owner view on account " + accountId, Empty, Empty) - } - - /** - * @param user the user requesting to see the other users permissions on this account - * @param otherUserProvider the authentication provider of the user whose permissions will be retrieved - * @param otherUserIdGivenByProvider the id of the user (the one given by their auth provider) whose permissions will be retrieved - * @return a Box of the user permissions of this bank account if the user passed as a parameter has access to the owner view (allowed to see this kind of data) - */ - final def permission(user : User, otherUserProvider : String, otherUserIdGivenByProvider: String, callContext: Option[CallContext]) : Box[Permission] = { - //check if the user have access to the owner view in this the account - if(user.hasOwnerViewAccess(BankIdAccountId(bankId, accountId), callContext)) - for{ - u <- UserX.findByProviderId(otherUserProvider, otherUserIdGivenByProvider) - p <- Views.views.vend.permission(BankIdAccountId(bankId, accountId), u) - } yield p - else - Failure(UserNoOwnerView+"user's email : " + user.emailAddress + ". account : " + accountId, Empty, Empty) - } - /** * @param user the user that wants to grant another user access to a view on this account * @param viewUID uid of the view to which we want to grant access diff --git a/obp-api/src/main/scala/code/model/dataAccess/MappedView.scala b/obp-api/src/main/scala/code/model/dataAccess/MappedView.scala index 8a1d427d25..9a0d1144d7 100644 --- a/obp-api/src/main/scala/code/model/dataAccess/MappedView.scala +++ b/obp-api/src/main/scala/code/model/dataAccess/MappedView.scala @@ -304,6 +304,12 @@ class ViewImpl extends View with LongKeyedMapper[ViewImpl] with ManyToMany with object canSeeBankAccountRoutingAddress_ extends MappedBoolean(this){ override def defaultValue = false } + object canSeePermissionForOneUser_ extends MappedBoolean(this){ + override def defaultValue = false + } + object canSeePermissionsForAllUsers_ extends MappedBoolean(this){ + override def defaultValue = false + } object canSeeOtherAccountNationalIdentifier_ extends MappedBoolean(this){ override def defaultValue = false } @@ -508,6 +514,8 @@ class ViewImpl extends View with LongKeyedMapper[ViewImpl] with ManyToMany with def canSeeBankRoutingAddress : Boolean = canSeeBankRoutingAddress_.get def canSeeBankAccountRoutingScheme : Boolean = canSeeBankAccountRoutingScheme_.get def canSeeBankAccountRoutingAddress : Boolean = canSeeBankAccountRoutingAddress_.get + def canSeePermissionForOneUser: Boolean = canSeePermissionForOneUser_.get + def canSeePermissionsForAllUsers: Boolean = canSeePermissionsForAllUsers_.get //other bank account fields def canSeeOtherAccountNationalIdentifier : Boolean = canSeeOtherAccountNationalIdentifier_.get diff --git a/obp-api/src/main/scala/code/views/MapperViews.scala b/obp-api/src/main/scala/code/views/MapperViews.scala index 44a40a3f0b..637fba7ded 100644 --- a/obp-api/src/main/scala/code/views/MapperViews.scala +++ b/obp-api/src/main/scala/code/views/MapperViews.scala @@ -797,6 +797,8 @@ object MapperViews extends Views with MdcLoggable { .canCreateCustomView_(false) .canDeleteCustomView_(false) .canUpdateCustomView_(false) + .canSeePermissionForOneUser_(false) + .canSeePermissionsForAllUsers_(false) viewId match { case SYSTEM_OWNER_VIEW_ID => @@ -808,6 +810,8 @@ object MapperViews extends Views with MdcLoggable { .canCreateCustomView_(true) .canDeleteCustomView_(true) .canUpdateCustomView_(true) + .canSeePermissionForOneUser_(true) + .canSeePermissionsForAllUsers_(true) case SYSTEM_STAGE_ONE_VIEW_ID => entity .canSeeTransactionDescription_(false) diff --git a/obp-api/src/main/scala/code/views/system/ViewDefinition.scala b/obp-api/src/main/scala/code/views/system/ViewDefinition.scala index 1cf88b3d83..9256c63903 100644 --- a/obp-api/src/main/scala/code/views/system/ViewDefinition.scala +++ b/obp-api/src/main/scala/code/views/system/ViewDefinition.scala @@ -314,6 +314,12 @@ class ViewDefinition extends View with LongKeyedMapper[ViewDefinition] with Many object canUpdateCustomView_ extends MappedBoolean(this){ override def defaultValue = false } + object canSeePermissionsForAllUsers_ extends MappedBoolean(this){ + override def defaultValue = false + } + object canSeePermissionForOneUser_ extends MappedBoolean(this){ + override def defaultValue = false + } //Important! If you add a field, be sure to handle it here in this function def setFromViewData(viewData : ViewSpecification) = { @@ -423,6 +429,8 @@ class ViewDefinition extends View with LongKeyedMapper[ViewDefinition] with Many canCreateCustomView_(actions.exists(_ == "can_create_custom_view")) canDeleteCustomView_(actions.exists(_ == "can_delete_custom_view")) canUpdateCustomView_(actions.exists(_ == "can_update_custom_view")) + canSeePermissionsForAllUsers_(actions.exists(_ == "can_see_permissions_for_all_users")) + canSeePermissionForOneUser_(actions.exists(_ == "can_see_permission_for_one_user")) } @@ -502,6 +510,8 @@ class ViewDefinition extends View with LongKeyedMapper[ViewDefinition] with Many def canSeeBankRoutingAddress : Boolean = canSeeBankRoutingAddress_.get def canSeeBankAccountRoutingScheme : Boolean = canSeeBankAccountRoutingScheme_.get def canSeeBankAccountRoutingAddress : Boolean = canSeeBankAccountRoutingAddress_.get + def canSeePermissionForOneUser: Boolean = canSeePermissionForOneUser_.get + def canSeePermissionsForAllUsers : Boolean = canSeePermissionsForAllUsers_.get //other bank account fields def canSeeOtherAccountNationalIdentifier : Boolean = canSeeOtherAccountNationalIdentifier_.get diff --git a/obp-api/src/test/scala/code/setup/TestConnectorSetupWithStandardPermissions.scala b/obp-api/src/test/scala/code/setup/TestConnectorSetupWithStandardPermissions.scala index a25c145db5..03f96341a5 100644 --- a/obp-api/src/test/scala/code/setup/TestConnectorSetupWithStandardPermissions.scala +++ b/obp-api/src/test/scala/code/setup/TestConnectorSetupWithStandardPermissions.scala @@ -131,10 +131,6 @@ trait TestConnectorSetupWithStandardPermissions extends TestConnectorSetup { canAddTransactionRequestToOwnAccount_(false). //added following two for payments canAddTransactionRequestToAnyAccount_(false). canSeeBankAccountCreditLimit_(true). - canSeeTransactionRequests_(false). - canSeeTransactionRequestTypes_(false). - canUpdateBankAccountLabel_(false). - canSeeAvailableViewsForBankAccount_(false). saveMe } } diff --git a/obp-commons/src/main/scala/com/openbankproject/commons/model/ViewModel.scala b/obp-commons/src/main/scala/com/openbankproject/commons/model/ViewModel.scala index 21e1bf2c19..f12d74dfab 100644 --- a/obp-commons/src/main/scala/com/openbankproject/commons/model/ViewModel.scala +++ b/obp-commons/src/main/scala/com/openbankproject/commons/model/ViewModel.scala @@ -325,6 +325,10 @@ trait View { def canSeeBankAccountRoutingAddress: Boolean + def canSeePermissionForOneUser: Boolean + + def canSeePermissionsForAllUsers: Boolean + //other bank account (counterparty) fields def canSeeOtherAccountNationalIdentifier: Boolean From 820b5ecbcfe29e41402b20ae8151b145712e25e8 Mon Sep 17 00:00:00 2001 From: hongwei Date: Fri, 23 Jun 2023 17:42:48 +0800 Subject: [PATCH 17/41] refactor/remove `hasOwnerViewAccess` replace with specific view permissions -- removed hasOwnerViewAccess check in test --- .../src/test/scala/code/api/v2_1_0/SandboxDataLoadingTest.scala | 1 - 1 file changed, 1 deletion(-) diff --git a/obp-api/src/test/scala/code/api/v2_1_0/SandboxDataLoadingTest.scala b/obp-api/src/test/scala/code/api/v2_1_0/SandboxDataLoadingTest.scala index ca9c071a1c..1fee51fbeb 100644 --- a/obp-api/src/test/scala/code/api/v2_1_0/SandboxDataLoadingTest.scala +++ b/obp-api/src/test/scala/code/api/v2_1_0/SandboxDataLoadingTest.scala @@ -307,7 +307,6 @@ class SandboxDataLoadingTest extends FlatSpec with SendServerRequests with Match //Note: system views not bankId, accountId, so here, we need to get all the views val (views,accountAccess) = Views.views.vend.privateViewsUserCanAccess(owner) val ownerView = views.find(v => v.viewId.value == SYSTEM_OWNER_VIEW_ID) - owner.hasOwnerViewAccess(BankIdAccountId(foundAccount.bankId, foundAccount.accountId), None) should equal(true) //and the owners should have access to it //Now, the owner is the system view, so all the users/accounts should have the access to this view From aaf79ede5b395b5ad1ab192ec19ff195313a14c7 Mon Sep 17 00:00:00 2001 From: hongwei Date: Mon, 3 Jul 2023 19:29:34 +0800 Subject: [PATCH 18/41] refactor/remove `hasOwnerViewAccess` replace with specific view permissions -- use canGrantAccessToViews and canRevokeAccessToViews --- .../SwaggerDefinitionsJSON.scala | 251 +++++++----------- .../UKOpenBanking/v3_1_0/UtilForUKV310.scala | 62 ----- .../scala/code/api/constant/constant.scala | 18 ++ .../main/scala/code/api/util/APIUtil.scala | 74 +++++- .../scala/code/api/util/ErrorMessages.scala | 7 +- .../main/scala/code/api/util/NewStyle.scala | 67 +++-- ...MigrationOfViewDefinitionPermissions.scala | 37 ++- .../scala/code/api/v1_2_1/APIMethods121.scala | 5 +- .../scala/code/api/v4_0_0/APIMethods400.scala | 34 +-- .../main/scala/code/model/BankingData.scala | 18 +- obp-api/src/main/scala/code/model/User.scala | 3 - .../code/model/dataAccess/MappedView.scala | 9 + .../main/scala/code/views/MapperViews.scala | 12 +- .../code/views/system/ViewDefinition.scala | 24 +- .../scala/code/api/v1_2_1/API1_2_1Test.scala | 54 ++-- .../commons/model/ViewModel.scala | 6 +- 16 files changed, 373 insertions(+), 308 deletions(-) delete mode 100644 obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/UtilForUKV310.scala diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala index 4742c74a2a..f62080743e 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala @@ -189,6 +189,101 @@ object SwaggerDefinitionsJSON { val createSystemViewJsonV300 = createViewJsonV300.copy(name = "test", metadata_view = "test", is_public = false) + val allowedActionsV500 = List( + "can_see_transaction_this_bank_account", + "can_see_transaction_other_bank_account", + "can_see_transaction_metadata", + "can_see_transaction_label", + "can_see_transaction_amount", + "can_see_transaction_type", + "can_see_transaction_currency", + "can_see_transaction_start_date", + "can_see_transaction_finish_date", + "can_see_transaction_balance", + "can_see_comments", + "can_see_narrative", "can_see_tags", + "can_see_images", + "can_see_bank_account_owners", + "can_see_bank_account_type", + "can_see_bank_account_balance", + "can_see_bank_account_currency", + "can_see_bank_account_label", + "can_see_bank_account_national_identifier", + "can_see_bank_account_swift_bic", + "can_see_bank_account_iban", + "can_see_bank_account_number", + "can_see_bank_account_bank_name", + "can_see_other_account_national_identifier", + "can_see_other_account_swift_bic", + "can_see_other_account_iban", + "can_see_other_account_bank_name", + "can_see_other_account_number", + "can_see_other_account_metadata", + "can_see_other_account_kind", + "can_see_more_info", + "can_see_url", + "can_see_image_url", + "can_see_open_corporates_url", + "can_see_corporate_location", + "can_see_physical_location", + "can_see_public_alias", + "can_see_private_alias", + "can_add_more_info", + "can_add_url", + "can_add_image_url", + "can_add_open_corporates_url", + "can_add_corporate_location", + "can_add_physical_location", + "can_add_public_alias", + "can_add_private_alias", + "can_delete_corporate_location", + "can_delete_physical_location", + "can_edit_narrative", + "can_add_comment", + "can_delete_comment", + "can_add_tag", + "can_delete_tag", + "can_add_image", + "can_delete_image", + "can_add_where_tag", + "can_see_where_tag", + "can_delete_where_tag", + "can_create_counterparty", + //V300 New + "can_see_bank_routing_scheme", + "can_see_bank_routing_address", + "can_see_bank_account_routing_scheme", + "can_see_bank_account_routing_address", + "can_see_other_bank_routing_scheme", + "can_see_other_bank_routing_address", + "can_see_other_account_routing_scheme", + "can_see_other_account_routing_address", + + //v310 + "can_query_available_funds", + "can_add_transaction_request_to_own_account", + "can_add_transaction_request_to_any_account", + "can_see_bank_account_credit_limit", + //v400 + "can_create_direct_debit", + "can_create_standing_order", + + //payments + "can_add_transaction_request_to_any_account", + + "can_see_transaction_request_types", + "can_see_transaction_requests", + "can_see_available_views_for_bank_account", + "can_update_bank_account_label", + "can_create_custom_view", + "can_delete_custom_view", + "can_update_custom_view", + "can_see_permission_for_one_user", + "can_see_permissions_for_all_users", + "can_grant_access_to_custom_views", + "can_revoke_access_to_custom_views" + ) + val createSystemViewJsonV500 = CreateViewJsonV500( name = "_test", description = "This view is for family", @@ -196,88 +291,7 @@ object SwaggerDefinitionsJSON { is_public = false, which_alias_to_use = "family", hide_metadata_if_alias_used = false, - allowed_actions = List( - "can_see_transaction_this_bank_account", - "can_see_transaction_other_bank_account", - "can_see_transaction_metadata", - "can_see_transaction_label", - "can_see_transaction_amount", - "can_see_transaction_type", - "can_see_transaction_currency", - "can_see_transaction_start_date", - "can_see_transaction_finish_date", - "can_see_transaction_balance", - "can_see_comments", - "can_see_narrative", - "can_see_tags", - "can_see_images", - "can_see_bank_account_owners", - "can_see_bank_account_type", - "can_see_bank_account_balance", - "can_see_bank_account_currency", - "can_see_bank_account_label", - "can_see_bank_account_national_identifier", - "can_see_bank_account_swift_bic", - "can_see_bank_account_iban", - "can_see_bank_account_number", - "can_see_bank_account_bank_name", - "can_see_other_account_national_identifier", - "can_see_other_account_swift_bic", - "can_see_other_account_iban", - "can_see_other_account_bank_name", - "can_see_other_account_number", - "can_see_other_account_metadata", - "can_see_other_account_kind", - "can_see_more_info", - "can_see_url", - "can_see_image_url", - "can_see_open_corporates_url", - "can_see_corporate_location", - "can_see_physical_location", - "can_see_public_alias", - "can_see_private_alias", - "can_add_more_info", - "can_add_url", - "can_add_image_url", - "can_add_open_corporates_url", - "can_add_corporate_location", - "can_add_physical_location", - "can_add_public_alias", - "can_add_private_alias", - "can_delete_corporate_location", - "can_delete_physical_location", - "can_edit_narrative", - "can_add_comment", - "can_delete_comment", - "can_add_tag", - "can_delete_tag", - "can_add_image", - "can_delete_image", - "can_add_where_tag", - "can_see_where_tag", - "can_delete_where_tag", - "can_create_counterparty", - //V300 New - "can_see_bank_routing_scheme", - "can_see_bank_routing_address", - "can_see_bank_account_routing_scheme", - "can_see_bank_account_routing_address", - "can_see_other_bank_routing_scheme", - "can_see_other_bank_routing_address", - "can_see_other_account_routing_scheme", - "can_see_other_account_routing_address", - //v310 - "can_query_available_funds", - "can_add_transaction_request_to_own_account", - "can_add_transaction_request_to_any_account", - "can_see_bank_account_credit_limit", - //v400 - "can_create_direct_debit", - "can_create_standing_order", - - //payments - "can_add_transaction_request_to_any_account" - ), + allowed_actions = allowedActionsV500, // Version 5.0.0 can_grant_access_to_views = Some(List("owner")), can_revoke_access_to_views = Some(List("owner")) @@ -370,78 +384,7 @@ object SwaggerDefinitionsJSON { metadata_view = SYSTEM_OWNER_VIEW_ID, which_alias_to_use = "family", hide_metadata_if_alias_used = true, - allowed_actions = List( - "can_see_transaction_this_bank_account", - "can_see_transaction_other_bank_account", - "can_see_transaction_metadata", - "can_see_transaction_label", - "can_see_transaction_amount", - "can_see_transaction_type", - "can_see_transaction_currency", - "can_see_transaction_start_date", - "can_see_transaction_finish_date", - "can_see_transaction_balance", - "can_see_comments", - "can_see_narrative", "can_see_tags", - "can_see_images", - "can_see_bank_account_owners", - "can_see_bank_account_type", - "can_see_bank_account_balance", - "can_see_bank_account_currency", - "can_see_bank_account_label", - "can_see_bank_account_national_identifier", - "can_see_bank_account_swift_bic", - "can_see_bank_account_iban", - "can_see_bank_account_number", - "can_see_bank_account_bank_name", - "can_see_other_account_national_identifier", - "can_see_other_account_swift_bic", - "can_see_other_account_iban", - "can_see_other_account_bank_name", - "can_see_other_account_number", - "can_see_other_account_metadata", - "can_see_other_account_kind", - "can_see_more_info", - "can_see_url", - "can_see_image_url", - "can_see_open_corporates_url", - "can_see_corporate_location", - "can_see_physical_location", - "can_see_public_alias", - "can_see_private_alias", - "can_add_more_info", - "can_add_url", - "can_add_image_url", - "can_add_open_corporates_url", - "can_add_corporate_location", - "can_add_physical_location", - "can_add_public_alias", - "can_add_private_alias", - "can_delete_corporate_location", - "can_delete_physical_location", - "can_edit_narrative", - "can_add_comment", - "can_delete_comment", - "can_add_tag", - "can_delete_tag", - "can_add_image", - "can_delete_image", - "can_add_where_tag", - "can_see_where_tag", - "can_delete_where_tag", - "can_create_counterparty", - //V300 New - "can_see_bank_routing_scheme", - "can_see_bank_routing_address", - "can_see_bank_account_routing_scheme", - "can_see_bank_account_routing_address", - "can_see_other_bank_routing_scheme", - "can_see_other_bank_routing_address", - "can_see_other_account_routing_scheme", - "can_see_other_account_routing_address", - //v310 - "can_query_available_funds" - ), + allowed_actions = allowedActionsV500, // Version 5.0.0 can_grant_access_to_views = Some(List("owner")), can_revoke_access_to_views = Some(List("owner")) diff --git a/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/UtilForUKV310.scala b/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/UtilForUKV310.scala deleted file mode 100644 index b7c18973b0..0000000000 --- a/obp-api/src/main/scala/code/api/UKOpenBanking/v3_1_0/UtilForUKV310.scala +++ /dev/null @@ -1,62 +0,0 @@ -package code.api.UKOpenBanking.v3_1_0 - -import code.api.util.APIUtil.{canGrantAccessToViewCommon, canRevokeAccessToViewCommon} -import code.api.util.CallContext -import code.api.util.ErrorMessages.UserNoOwnerView -import code.views.Views -import com.openbankproject.commons.model.{User, ViewIdBankIdAccountId} -import net.liftweb.common.{Empty, Failure, Full} - -import scala.collection.immutable.List - -object UtilForUKV310 { - def grantAccessToViews(user: User, views: List[ViewIdBankIdAccountId], callContext: Option[CallContext]): Full[Boolean] = { - val result = - for { - view <- views - } yield { - if (canGrantAccessToViewCommon(view.bankId, view.accountId, user, callContext)) { - val viewIdBankIdAccountId = ViewIdBankIdAccountId(view.viewId, view.bankId, view.accountId) - Views.views.vend.systemView(view.viewId) match { - case Full(systemView) => - Views.views.vend.grantAccessToSystemView(view.bankId, view.accountId, systemView, user) - case _ => // It's not system view - Views.views.vend.grantAccessToCustomView(viewIdBankIdAccountId, user) - } - } else { - Failure(UserNoOwnerView+" user_id : " + user.userId + ". account : " + view.accountId.value, Empty, Empty) - } - } - if (result.forall(_.isDefined)) - Full(true) - else { - println(result.filter(_.isDefined == false)) - Full(false) - } - } - - def revokeAccessToViews(user: User, views: List[ViewIdBankIdAccountId], callContext: Option[CallContext]): Full[Boolean] = { - val result = - for { - view <- views - } yield { - if (canRevokeAccessToViewCommon(view.bankId, view.accountId, user, callContext)) { - val viewIdBankIdAccountId = ViewIdBankIdAccountId(view.viewId, view.bankId, view.accountId) - Views.views.vend.systemView(view.viewId) match { - case Full(systemView) => - Views.views.vend.revokeAccessToSystemView(view.bankId, view.accountId, systemView, user) - case _ => // It's not system view - Views.views.vend.revokeAccess(viewIdBankIdAccountId, user) - } - } else { - Failure(UserNoOwnerView+" user_id : " + user.userId + ". account : " + view.accountId.value, Empty, Empty) - } - } - if (result.forall(_.isDefined)) - Full(true) - else { - println(result.filter(_.isDefined == false)) - Full(false) - } - } -} diff --git a/obp-api/src/main/scala/code/api/constant/constant.scala b/obp-api/src/main/scala/code/api/constant/constant.scala index 5a38fc551a..45cbfec426 100644 --- a/obp-api/src/main/scala/code/api/constant/constant.scala +++ b/obp-api/src/main/scala/code/api/constant/constant.scala @@ -40,6 +40,24 @@ object Constant extends MdcLoggable { final val SYSTEM_READ_BALANCES_BERLIN_GROUP_VIEW_ID = "ReadBalancesBerlinGroup" final val SYSTEM_READ_TRANSACTIONS_BERLIN_GROUP_VIEW_ID = "ReadTransactionsBerlinGroup" + //TODO, this need to be double check + final val ALL_SYSTEM_VIEWS_CREATED_FROM_BOOT = List( + SYSTEM_OWNER_VIEW_ID, + SYSTEM_AUDITOR_VIEW_ID, + SYSTEM_ACCOUNTANT_VIEW_ID, + SYSTEM_FIREHOSE_VIEW_ID, + SYSTEM_STANDARD_VIEW_ID, + SYSTEM_STAGE_ONE_VIEW_ID, + SYSTEM_READ_ACCOUNTS_BASIC_VIEW_ID, + SYSTEM_READ_ACCOUNTS_DETAIL_VIEW_ID, + SYSTEM_READ_BALANCES_VIEW_ID, + SYSTEM_READ_TRANSACTIONS_BASIC_VIEW_ID, + SYSTEM_READ_TRANSACTIONS_DEBITS_VIEW_ID, + SYSTEM_READ_TRANSACTIONS_DETAIL_VIEW_ID, + SYSTEM_READ_ACCOUNTS_BERLIN_GROUP_VIEW_ID, + SYSTEM_READ_BALANCES_BERLIN_GROUP_VIEW_ID, + SYSTEM_READ_TRANSACTIONS_BERLIN_GROUP_VIEW_ID + ) //These are the default incoming and outgoing account ids. we will create both during the boot.scala. final val INCOMING_SETTLEMENT_ACCOUNT_ID = "OBP-INCOMING-SETTLEMENT-ACCOUNT" final val OUTGOING_SETTLEMENT_ACCOUNT_ID = "OBP-OUTGOING-SETTLEMENT-ACCOUNT" diff --git a/obp-api/src/main/scala/code/api/util/APIUtil.scala b/obp-api/src/main/scala/code/api/util/APIUtil.scala index 9bc9592a1a..7e25d57e12 100644 --- a/obp-api/src/main/scala/code/api/util/APIUtil.scala +++ b/obp-api/src/main/scala/code/api/util/APIUtil.scala @@ -4064,13 +4064,75 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{ case _ => false } - def canGrantAccessToViewCommon(bankId: BankId, accountId: AccountId, user: User, callContext: Option[CallContext]): Boolean = { - user.hasOwnerViewAccess(BankIdAccountId(bankId, accountId), callContext) || // TODO Use an action instead of the owner view - AccountHolders.accountHolders.vend.getAccountHolders(bankId, accountId).exists(_.userId == user.userId) + def canGrantAccessToView(bankId: BankId, accountId: AccountId, viewIdTobeGranted : ViewId, user: User, callContext: Option[CallContext]): Boolean = { + //all the permission this user have for the bankAccount + val permission: Box[Permission] = Views.views.vend.permission(BankIdAccountId(bankId, accountId), user) + + //1. if viewIdTobeGranted is systemView. just compare all the permissions + if(checkSystemViewIdOrName(viewIdTobeGranted.value)){ + val allCanGrantAccessToViewsPermissions: List[String] = permission + .map(_.views.map(_.canGrantAccessToViews.getOrElse(Nil)).flatten).getOrElse(Nil).distinct + + allCanGrantAccessToViewsPermissions.contains(viewIdTobeGranted.value) + } else{ + //2. if viewIdTobeGranted is customView, we only need to check the `canGrantAccessToCustomViews`. + val allCanGrantAccessToCustomViewsPermissions: List[Boolean] = permission.map(_.views.map(_.canGrantAccessToCustomViews)).getOrElse(Nil) + + allCanGrantAccessToCustomViewsPermissions.contains(true) + } + } + + def canGrantAccessToMultipleViews(bankId: BankId, accountId: AccountId, viewIdsTobeGranted : List[ViewId], user: User, callContext: Option[CallContext]): Boolean = { + //all the permission this user have for the bankAccount + val permissionBox = Views.views.vend.permission(BankIdAccountId(bankId, accountId), user) + + //check if we can grant all systemViews Access + val allCanGrantAccessToViewsPermissions: List[String] = permissionBox.map(_.views.map(_.canGrantAccessToViews.getOrElse(Nil)).flatten).getOrElse(Nil).distinct + val allSystemViewsAccessTobeGranted: List[String] = viewIdsTobeGranted.map(_.value).distinct.filter(checkSystemViewIdOrName) + val canGrantAccessToAllSystemViews = allSystemViewsAccessTobeGranted.forall(allCanGrantAccessToViewsPermissions.contains) + + //check if we can grant all customViews Access + val allCanGrantAccessToCustomViewsPermissions: List[Boolean] = permissionBox.map(_.views.map(_.canGrantAccessToCustomViews)).getOrElse(Nil) + val canGrantAccessToAllCustomViews = allCanGrantAccessToCustomViewsPermissions.contains(true) + + //we need merge both system and custom access + canGrantAccessToAllSystemViews && canGrantAccessToAllCustomViews + } + + def canRevokeAccessToView(bankId: BankId, accountId: AccountId, viewIdToBeRevoked : ViewId, user: User, callContext: Option[CallContext]): Boolean = { + //all the permission this user have for the bankAccount + val permission: Box[Permission] = Views.views.vend.permission(BankIdAccountId(bankId, accountId), user) + + //1. if viewIdTobeRevoked is systemView. just compare all the permissions + if (checkSystemViewIdOrName(viewIdToBeRevoked.value)) { + val allCanRevokeAccessToViewsPermissions: List[String] = permission + .map(_.views.map(_.canRevokeAccessToViews.getOrElse(Nil)).flatten).getOrElse(Nil).distinct + + allCanRevokeAccessToViewsPermissions.contains(viewIdToBeRevoked.value) + } else { + //2. if viewIdTobeRevoked is customView, we only need to check the `canRevokeAccessToCustomViews`. + val allCanRevokeAccessToCustomViewsPermissions: List[Boolean] = permission.map(_.views.map(_.canRevokeAccessToCustomViews)).getOrElse(Nil) + + allCanRevokeAccessToCustomViewsPermissions.contains(true) + } } - def canRevokeAccessToViewCommon(bankId: BankId, accountId: AccountId, user: User, callContext: Option[CallContext]): Boolean = { - user.hasOwnerViewAccess(BankIdAccountId(bankId, accountId), callContext) || // TODO Use an action instead of the owner view - AccountHolders.accountHolders.vend.getAccountHolders(bankId, accountId).exists(_.userId == user.userId) + + def canRevokeAccessToAllViews(bankId: BankId, accountId: AccountId, user: User, callContext: Option[CallContext]): Boolean = { + + val permissionBox = Views.views.vend.permission(BankIdAccountId(bankId, accountId), user) + + //check if we can revoke all systemViews Access + val allCanRevokeAccessToViewsPermissions: List[String] = permissionBox.map(_.views.filter(_.canRevokeAccessToCustomViews).map(_.canRevokeAccessToViews.getOrElse(Nil)).flatten).getOrElse(Nil).distinct + val allAccountAccessSystemViews: List[String] = permissionBox.map(_.views.map(_.viewId.value)).getOrElse(Nil).distinct.filter(checkSystemViewIdOrName) + val canRevokeAccessToAllSystemViews = allAccountAccessSystemViews.forall(allCanRevokeAccessToViewsPermissions.contains) + + //check if we can revoke all customViews Access + val allCanRevokeAccessToCustomViewsPermissions: List[Boolean] = permissionBox.map(_.views.map(_.canRevokeAccessToCustomViews)).getOrElse(Nil) + val canRevokeAccessToAllCustomViews = allCanRevokeAccessToCustomViewsPermissions.contains(true) + + //we need merge both system and custom access + canRevokeAccessToAllSystemViews && canRevokeAccessToAllCustomViews + } def getJValueFromJsonFile(path: String) = { diff --git a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala index 982b1067b8..e90fe94871 100644 --- a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala +++ b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala @@ -168,7 +168,10 @@ object ErrorMessages { val GatewayLoginCannotGetOrCreateUser = "OBP-20045: Cannot get or create user during GatewayLogin process." val GatewayLoginNoJwtForResponse = "OBP-20046: There is no useful value for JWT." - val UserMissOwnerViewOrNotAccountHolder = "OBP-20047: User must have access to the owner view or must be an account holder." + val UserLacksPermissionCanGrantAccessToViewForTargetAccount = + s"OBP-20047: The current user does not have access to a view which lists the target account in ${ViewDefinition.canGrantAccessToViews_.dbColumnName} permissions" + val UserLacksPermissionCanRevokeAccessToViewForTargetAccount = + s"OBP-20048: The current user does not have access to a view which lists the target account in ${ViewDefinition.canRevokeAccessToViews_.dbColumnName} permissions" val UserNotSuperAdmin = "OBP-20050: Current User is not a Super Admin!" @@ -735,6 +738,8 @@ object ErrorMessages { // InvalidConsumerCredentials -> 401, // or 400 UsernameHasBeenLocked -> 401, UserNoPermissionAccessView -> 403, + UserLacksPermissionCanGrantAccessToViewForTargetAccount -> 403, + UserLacksPermissionCanRevokeAccessToViewForTargetAccount -> 403, UserNotSuperAdminOrMissRole -> 403, ConsumerHasMissingRoles -> 403, UserNotFoundByProviderAndUsername -> 404, 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 e1e2a3452e..145be708ed 100644 --- a/obp-api/src/main/scala/code/api/util/NewStyle.scala +++ b/obp-api/src/main/scala/code/api/util/NewStyle.scala @@ -526,23 +526,52 @@ object NewStyle extends MdcLoggable{ def grantAccessToView(account: BankAccount, u: User, viewIdBankIdAccountId : ViewIdBankIdAccountId, provider : String, providerId: String, callContext: Option[CallContext]) = Future { account.grantAccessToView(u, viewIdBankIdAccountId, provider, providerId, callContext: Option[CallContext]) - } map { fullBoxOrException(_) - } map { unboxFull(_) } + } map { + x => (unboxFullOrFail( + x, + callContext, + UserLacksPermissionCanGrantAccessToViewForTargetAccount + s"Current ViewId(${viewIdBankIdAccountId.viewId.value}) and current UserId(${u.userId})", + 403), + callContext + ) + } def grantAccessToMultipleViews(account: BankAccount, u: User, viewIdBankIdAccountIds : List[ViewIdBankIdAccountId], provider : String, providerId: String, callContext: Option[CallContext]) = Future { account.grantAccessToMultipleViews(u, viewIdBankIdAccountIds, provider, providerId, callContext: Option[CallContext]) - } map { fullBoxOrException(_) - } map { unboxFull(_) } - + } map { + x => + (unboxFullOrFail( + x, + callContext, + UserLacksPermissionCanGrantAccessToViewForTargetAccount + s"Current ViewIds(${viewIdBankIdAccountIds}) and current UserId(${u.userId})", + 403), + callContext + ) + } def revokeAccessToView(account: BankAccount, u: User, viewIdBankIdAccountId : ViewIdBankIdAccountId, provider : String, providerId: String, callContext: Option[CallContext]) = Future { account.revokeAccessToView(u, viewIdBankIdAccountId, provider, providerId, callContext: Option[CallContext]) - } map { fullBoxOrException(_) - } map { unboxFull(_) } - + } map { + x => + (unboxFullOrFail( + x, + callContext, + UserLacksPermissionCanRevokeAccessToViewForTargetAccount + s"Current ViewId(${viewIdBankIdAccountId.viewId.value}) and current UserId(${u.userId})", + 403), + callContext + ) + } def revokeAllAccountAccess(account: BankAccount, u: User, provider : String, providerId: String, callContext: Option[CallContext]) = Future { account.revokeAllAccountAccess(u, provider, providerId, callContext) - } map { fullBoxOrException(_) - } map { unboxFull(_) } + } map { + x => + (unboxFullOrFail( + x, + callContext, + UserLacksPermissionCanRevokeAccessToViewForTargetAccount + s"current UserId(${u.userId})", + 403), + callContext + ) + } def moderatedBankAccountCore(account: BankAccount, view: View, user: Box[User], callContext: Option[CallContext]) = Future { account.moderatedBankAccountCore(view, BankIdAccountId(account.bankId, account.accountId), user, callContext) @@ -688,15 +717,19 @@ object NewStyle extends MdcLoggable{ } } - def canGrantAccessToView(bankId: BankId, accountId: AccountId, user: User, callContext: Option[CallContext]) : Future[Box[Boolean]] = { - Helper.wrapStatementToFuture(UserMissOwnerViewOrNotAccountHolder) { - canGrantAccessToViewCommon(bankId, accountId, user, callContext) + def canGrantAccessToView(bankId: BankId, accountId: AccountId, viewIdToBeGranted : ViewId, user: User, callContext: Option[CallContext]) : Future[Box[Boolean]] = { + Helper.wrapStatementToFuture(UserLacksPermissionCanGrantAccessToViewForTargetAccount) { + APIUtil.canGrantAccessToView(bankId, accountId, viewIdToBeGranted, user, callContext) } } - - def canRevokeAccessToView(bankId: BankId, accountId: AccountId, user: User, callContext: Option[CallContext]) : Future[Box[Boolean]] = { - Helper.wrapStatementToFuture(UserMissOwnerViewOrNotAccountHolder) { - canRevokeAccessToViewCommon(bankId, accountId, user, callContext) + def canRevokeAccessToView(bankId: BankId, accountId: AccountId, viewIdToBeRevoked : ViewId, user: User, callContext: Option[CallContext]) : Future[Box[Boolean]] = { + Helper.wrapStatementToFuture(UserLacksPermissionCanRevokeAccessToViewForTargetAccount) { + APIUtil.canRevokeAccessToView(bankId, accountId,viewIdToBeRevoked, user, callContext) + } + } + def canRevokeAccessToAllView(bankId: BankId, accountId: AccountId, user: User, callContext: Option[CallContext]) : Future[Box[Boolean]] = { + Helper.wrapStatementToFuture(UserLacksPermissionCanRevokeAccessToViewForTargetAccount) { + APIUtil.canRevokeAccessToAllViews(bankId, accountId, user, callContext) } } def createSystemView(view: CreateViewJson, callContext: Option[CallContext]) : Future[View] = { diff --git a/obp-api/src/main/scala/code/api/util/migration/MigrationOfViewDefinitionPermissions.scala b/obp-api/src/main/scala/code/api/util/migration/MigrationOfViewDefinitionPermissions.scala index 3b2768d77b..aaca7f5136 100644 --- a/obp-api/src/main/scala/code/api/util/migration/MigrationOfViewDefinitionPermissions.scala +++ b/obp-api/src/main/scala/code/api/util/migration/MigrationOfViewDefinitionPermissions.scala @@ -1,6 +1,6 @@ package code.api.util.migration -import code.api.Constant.SYSTEM_OWNER_VIEW_ID +import code.api.Constant.{ALL_SYSTEM_VIEWS_CREATED_FROM_BOOT, SYSTEM_OWNER_VIEW_ID, SYSTEM_STANDARD_VIEW_ID} import code.api.util.APIUtil import code.api.util.migration.Migration.{DbFunction, saveLog} import code.views.system.ViewDefinition @@ -29,15 +29,42 @@ object MigrationOfViewDefinitionPermissions { .canUpdateCustomView_(true) .canSeePermissionForOneUser_(true) .canSeePermissionsForAllUsers_(true) + .canGrantAccessToCustomViews_(true) + .canRevokeAccessToCustomViews_(true) + .canGrantAccessToViews_(ALL_SYSTEM_VIEWS_CREATED_FROM_BOOT.mkString(",")) + .canRevokeAccessToViews_(ALL_SYSTEM_VIEWS_CREATED_FROM_BOOT.mkString(",")) + .save + ).head + + val standardView = ViewDefinition.find( + NullRef(ViewDefinition.bank_id), + NullRef(ViewDefinition.account_id), + By(ViewDefinition.view_id, SYSTEM_STANDARD_VIEW_ID), + By(ViewDefinition.isSystem_,true) + ).map(view => + view + .canSeeTransactionRequestTypes_(true) + .canSeeTransactionRequests_(true) + .canSeeAvailableViewsForBankAccount_(true) + .canUpdateBankAccountLabel_(true) + .canCreateCustomView_(true) + .canDeleteCustomView_(true) + .canUpdateCustomView_(true) + .canSeePermissionForOneUser_(true) + .canSeePermissionsForAllUsers_(true) + .canGrantAccessToCustomViews_(true) + .canRevokeAccessToCustomViews_(true) + .canGrantAccessToViews_(ALL_SYSTEM_VIEWS_CREATED_FROM_BOOT.mkString(",")) + .canRevokeAccessToViews_(ALL_SYSTEM_VIEWS_CREATED_FROM_BOOT.mkString(",")) .save ).head - val isSuccessful = ownerView + val isSuccessful = ownerView && standardView val endDate = System.currentTimeMillis() val comment: String = - s"""ViewDefinition system owner view, update the following rows to true: + s"""ViewDefinition system $SYSTEM_OWNER_VIEW_ID and $SYSTEM_STANDARD_VIEW_ID views, update the following rows to true: |${ViewDefinition.canSeeTransactionRequestTypes_.dbColumnName} |${ViewDefinition.canSeeTransactionRequests_.dbColumnName} |${ViewDefinition.canSeeAvailableViewsForBankAccount_.dbColumnName} @@ -47,6 +74,10 @@ object MigrationOfViewDefinitionPermissions { |${ViewDefinition.canUpdateCustomView_.dbColumnName} |${ViewDefinition.canSeePermissionsForAllUsers_.dbColumnName} |${ViewDefinition.canSeePermissionForOneUser_.dbColumnName} + |${ViewDefinition.canGrantAccessToCustomViews_.dbColumnName} + |${ViewDefinition.canRevokeAccessToCustomViews_.dbColumnName} + |${ViewDefinition.canGrantAccessToViews_.dbColumnName} + |${ViewDefinition.canRevokeAccessToViews_.dbColumnName} |Duration: ${endDate - startDate} ms; """.stripMargin saveLog(name, commitId, isSuccessful, startDate, endDate, comment) diff --git a/obp-api/src/main/scala/code/api/v1_2_1/APIMethods121.scala b/obp-api/src/main/scala/code/api/v1_2_1/APIMethods121.scala index 31ee40bd43..4a952d3d32 100644 --- a/obp-api/src/main/scala/code/api/v1_2_1/APIMethods121.scala +++ b/obp-api/src/main/scala/code/api/v1_2_1/APIMethods121.scala @@ -864,7 +864,7 @@ trait APIMethods121 { (account, callContext) <- NewStyle.function.getBankAccount(bankId, accountId, callContext) failMsg = "wrong format JSON" viewIds <- NewStyle.function.tryons(failMsg, 400, callContext) { json.extract[ViewIdsJson] } - addedViews <- NewStyle.function.grantAccessToMultipleViews(account, u, viewIds.views.map(viewIdString => ViewIdBankIdAccountId(ViewId(viewIdString), bankId, accountId)), provider, providerId,callContext) + (addedViews, callContext) <- NewStyle.function.grantAccessToMultipleViews(account, u, viewIds.views.map(viewIdString => ViewIdBankIdAccountId(ViewId(viewIdString), bankId, accountId)), provider, providerId,callContext) } yield { (JSONFactory.createViewsJSON(addedViews), HttpCode.`201`(callContext)) } @@ -891,6 +891,7 @@ trait APIMethods121 { UserNotLoggedIn, BankAccountNotFound, UnknownError, + UserLacksPermissionCanGrantAccessToViewForTargetAccount, "could not save the privilege", "user does not have access to owner view on account" ), @@ -904,7 +905,7 @@ trait APIMethods121 { (Full(u), callContext) <- authenticatedAccess(cc) (_, callContext) <- NewStyle.function.getBank(bankId, callContext) (account, callContext) <- NewStyle.function.getBankAccount(bankId, accountId, callContext) - addedView <- NewStyle.function.grantAccessToView(account, u, ViewIdBankIdAccountId(viewId, bankId, accountId), provider, providerId, callContext) + (addedView, callContext) <- NewStyle.function.grantAccessToView(account, u, ViewIdBankIdAccountId(viewId, bankId, accountId), provider, providerId, callContext) } yield { val viewJson = JSONFactory.createViewJSON(addedView) (viewJson, HttpCode.`201`(callContext)) diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index 0d158d618e..3be4bbaff6 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -4373,7 +4373,7 @@ trait APIMethods400 { viewJsonV300, List( $UserNotLoggedIn, - UserMissOwnerViewOrNotAccountHolder, + UserLacksPermissionCanGrantAccessToViewForTargetAccount, InvalidJsonFormat, UserNotFoundById, SystemViewNotFound, @@ -4393,7 +4393,7 @@ trait APIMethods400 { postJson <- NewStyle.function.tryons(failMsg, 400, cc.callContext) { json.extract[PostAccountAccessJsonV400] } - _ <- NewStyle.function.canGrantAccessToView(bankId, accountId, u, callContext) + _ <- NewStyle.function.canGrantAccessToView(bankId, accountId, ViewId(postJson.view.view_id), u, callContext) (user, callContext) <- NewStyle.function.findByUserId(postJson.user_id, callContext) view <- getView(bankId, accountId, postJson.view, callContext) addedView <- grantAccountAccessToUser(bankId, accountId, user, view, callContext) @@ -4430,7 +4430,7 @@ trait APIMethods400 { List(viewJsonV300), List( $UserNotLoggedIn, - UserMissOwnerViewOrNotAccountHolder, + UserLacksPermissionCanGrantAccessToViewForTargetAccount, InvalidJsonFormat, SystemViewNotFound, ViewNotFound, @@ -4444,6 +4444,7 @@ trait APIMethods400 { cc => val failMsg = s"$InvalidJsonFormat The Json body should be the $PostCreateUserAccountAccessJsonV400 " for { + (Full(u), callContext) <- SS.user postJson <- NewStyle.function.tryons(failMsg, 400, cc.callContext) { json.extract[PostCreateUserAccountAccessJsonV400] } @@ -4451,8 +4452,10 @@ trait APIMethods400 { _ <- Helper.booleanToFuture(s"$InvalidUserProvider The user.provider must be start with 'dauth.'", cc=Some(cc)) { postJson.provider.startsWith("dauth.") } - - _ <- NewStyle.function.canGrantAccessToView(bankId, accountId, cc.loggedInUser, cc.callContext) + viewIdList = postJson.views.map(view =>ViewId(view.view_id)) + _ <- Helper.booleanToFuture(s"$UserLacksPermissionCanGrantAccessToViewForTargetAccount ", 403, cc = Some(cc)) { + APIUtil.canGrantAccessToMultipleViews(bankId, accountId, viewIdList, u, callContext) + } (targetUser, callContext) <- NewStyle.function.getOrCreateResourceUser(postJson.provider, postJson.username, cc.callContext) views <- getViews(bankId, accountId, postJson, callContext) addedView <- grantMultpleAccountAccessToUser(bankId, accountId, targetUser, views, callContext) @@ -4479,7 +4482,7 @@ trait APIMethods400 { revokedJsonV400, List( $UserNotLoggedIn, - UserMissOwnerViewOrNotAccountHolder, + UserLacksPermissionCanGrantAccessToViewForTargetAccount, InvalidJsonFormat, UserNotFoundById, SystemViewNotFound, @@ -4496,14 +4499,16 @@ trait APIMethods400 { cc => val failMsg = s"$InvalidJsonFormat The Json body should be the $PostAccountAccessJsonV400 " for { + (Full(u), callContext) <- SS.user postJson <- NewStyle.function.tryons(failMsg, 400, cc.callContext) { json.extract[PostAccountAccessJsonV400] } - _ <- NewStyle.function.canRevokeAccessToView(bankId, accountId, cc.loggedInUser, cc.callContext) + viewId = ViewId(postJson.view.view_id) + _ <- NewStyle.function.canRevokeAccessToView(bankId, accountId, viewId, u, cc.callContext) (user, callContext) <- NewStyle.function.findByUserId(postJson.user_id, cc.callContext) view <- postJson.view.is_system match { - case true => NewStyle.function.systemView(ViewId(postJson.view.view_id), callContext) - case false => NewStyle.function.customView(ViewId(postJson.view.view_id), BankIdAccountId(bankId, accountId), callContext) + case true => NewStyle.function.systemView(viewId, callContext) + case false => NewStyle.function.customView(viewId, BankIdAccountId(bankId, accountId), callContext) } revoked <- postJson.view.is_system match { case true => NewStyle.function.revokeAccessToSystemView(bankId, accountId, view, user, callContext) @@ -4531,7 +4536,7 @@ trait APIMethods400 { revokedJsonV400, List( $UserNotLoggedIn, - UserMissOwnerViewOrNotAccountHolder, + UserLacksPermissionCanGrantAccessToViewForTargetAccount, InvalidJsonFormat, UserNotFoundById, SystemViewNotFound, @@ -4543,21 +4548,20 @@ trait APIMethods400 { List(apiTagAccountAccess, apiTagView, apiTagAccount, apiTagUser, apiTagOwnerRequired)) lazy val revokeGrantUserAccessToViews : OBPEndpoint = { - //add access for specific user to a specific system view case "banks" :: BankId(bankId) :: "accounts" :: AccountId(accountId) :: "account-access" :: Nil JsonPut json -> _ => { cc => val failMsg = s"$InvalidJsonFormat The Json body should be the $PostAccountAccessJsonV400 " for { + (Full(u), callContext) <- SS.user postJson <- NewStyle.function.tryons(failMsg, 400, cc.callContext) { json.extract[PostRevokeGrantAccountAccessJsonV400] } - _ <- NewStyle.function.canRevokeAccessToView(bankId, accountId, cc.loggedInUser, cc.callContext) - (user, callContext) <- NewStyle.function.findByUserId(cc.loggedInUser.userId, cc.callContext) - _ <- Future(Views.views.vend.revokeAccountAccessByUser(bankId, accountId, user, callContext)) map { + _ <- NewStyle.function.canRevokeAccessToAllView(bankId, accountId, u, cc.callContext) + _ <- Future(Views.views.vend.revokeAccountAccessByUser(bankId, accountId, u, callContext)) map { unboxFullOrFail(_, callContext, s"Cannot revoke") } grantViews = for (viewId <- postJson.views) yield ViewIdBankIdAccountId(ViewId(viewId), bankId, accountId) - _ <- Future(Views.views.vend.grantAccessToMultipleViews(grantViews, user, callContext)) map { + _ <- Future(Views.views.vend.grantAccessToMultipleViews(grantViews, u, callContext)) map { unboxFullOrFail(_, callContext, s"Cannot grant the views: ${postJson.views.mkString(",")}") } } yield { diff --git a/obp-api/src/main/scala/code/model/BankingData.scala b/obp-api/src/main/scala/code/model/BankingData.scala index cdb2347d31..ab7028b2b7 100644 --- a/obp-api/src/main/scala/code/model/BankingData.scala +++ b/obp-api/src/main/scala/code/model/BankingData.scala @@ -30,7 +30,7 @@ import java.util.Date import code.accountholders.AccountHolders import code.api.{APIFailureNewStyle, Constant} -import code.api.util.APIUtil.{OBPReturnType, canGrantAccessToViewCommon, canRevokeAccessToViewCommon, fullBoxOrException, unboxFull, unboxFullOrFail} +import code.api.util.APIUtil.{OBPReturnType, canGrantAccessToView, canGrantAccessToMultipleViews, canRevokeAccessToAllViews, canRevokeAccessToView, unboxFullOrFail} import code.api.util.ErrorMessages._ import code.api.util._ import code.bankconnectors.{Connector, LocalMappedConnector} @@ -226,13 +226,13 @@ case class BankAccountExtended(val bankAccount: BankAccount) extends MdcLoggable case _ => Views.views.vend.grantAccessToCustomView(viewUID, user) } } - if(canGrantAccessToViewCommon(bankId, accountId, user, callContext)) + if(canGrantAccessToView(bankId, accountId, viewUID.viewId , user, callContext)) for{ otherUser <- UserX.findByProviderId(otherUserProvider, otherUserIdGivenByProvider) //check if the userId corresponds to a user savedView <- grantAccessToCustomOrSystemView(otherUser) ?~ "could not save the privilege" } yield savedView else - Failure(UserNoOwnerView+"user's email : " + user.emailAddress + ". account : " + accountId, Empty, Empty) + Failure(UserLacksPermissionCanGrantAccessToViewForTargetAccount + s"Current ViewId(${viewUID.viewId.value}) and current UserId(${user.userId})") } /** @@ -244,13 +244,13 @@ case class BankAccountExtended(val bankAccount: BankAccount) extends MdcLoggable */ final def grantAccessToMultipleViews(user : User, viewUIDs : List[ViewIdBankIdAccountId], otherUserProvider : String, otherUserIdGivenByProvider: String, callContext: Option[CallContext]) : Box[List[View]] = { - if(canGrantAccessToViewCommon(bankId, accountId, user, callContext)) + if(canGrantAccessToMultipleViews(bankId, accountId, viewUIDs.map(_.viewId), user, callContext)) for{ otherUser <- UserX.findByProviderId(otherUserProvider, otherUserIdGivenByProvider) //check if the userId corresponds to a user grantedViews <- Views.views.vend.grantAccessToMultipleViews(viewUIDs, otherUser, callContext) ?~ "could not save the privilege" } yield grantedViews else - Failure(UserNoOwnerView+"user's email : " + user.emailAddress + ". account : " + accountId, Empty, Empty) + Failure(UserLacksPermissionCanGrantAccessToViewForTargetAccount + s"Current ViewIds${viewUIDs.map(_.viewId.value)} and current UserId${user.userId}") } /** @@ -269,13 +269,13 @@ case class BankAccountExtended(val bankAccount: BankAccount) extends MdcLoggable } } //check if the user have access to the owner view in this the account - if(canRevokeAccessToViewCommon(bankId, accountId, user, callContext: Option[CallContext])) + if(canRevokeAccessToView(bankId, accountId, viewUID.viewId, user, callContext: Option[CallContext])) for{ otherUser <- UserX.findByProviderId(otherUserProvider, otherUserIdGivenByProvider) //check if the userId corresponds to a user isRevoked <- revokeAccessToCustomOrSystemView(otherUser: User) ?~ "could not revoke the privilege" } yield isRevoked else - Failure(UserNoOwnerView+"user's email : " + user.emailAddress + ". account : " + accountId, Empty, Empty) + Failure(UserLacksPermissionCanRevokeAccessToViewForTargetAccount + s"Current ViewId(${viewUID.viewId.value}) and current UserId(${user.userId})") } /** @@ -287,13 +287,13 @@ case class BankAccountExtended(val bankAccount: BankAccount) extends MdcLoggable */ final def revokeAllAccountAccess(user : User, otherUserProvider : String, otherUserIdGivenByProvider: String, callContext: Option[CallContext]) : Box[Boolean] = { - if(canRevokeAccessToViewCommon(bankId, accountId, user, callContext)) + if(canRevokeAccessToAllViews(bankId, accountId, user, callContext)) for{ otherUser <- UserX.findByProviderId(otherUserProvider, otherUserIdGivenByProvider) ?~ UserNotFoundByProviderAndUsername isRevoked <- Views.views.vend.revokeAllAccountAccess(bankId, accountId, otherUser) } yield isRevoked else - Failure(UserNoOwnerView+"user's email : " + user.emailAddress + ". account : " + accountId, Empty, Empty) + Failure(UserLacksPermissionCanRevokeAccessToViewForTargetAccount + s"current UserId${user.userId}") } final def moderatedTransaction(transactionId: TransactionId, view: View, bankIdAccountId: BankIdAccountId, user: Box[User], callContext: Option[CallContext] = None) : Box[(ModeratedTransaction, Option[CallContext])] = { diff --git a/obp-api/src/main/scala/code/model/User.scala b/obp-api/src/main/scala/code/model/User.scala index 50d65ef5a9..e0ee47b5e4 100644 --- a/obp-api/src/main/scala/code/model/User.scala +++ b/obp-api/src/main/scala/code/model/User.scala @@ -99,9 +99,6 @@ case class UserExtended(val user: User) extends MdcLoggable { APIUtil.checkViewAccessAndReturnView(ViewId(SYSTEM_OWNER_VIEW_ID), bankIdAccountId, Some(this.user), callContext) } - final def hasOwnerViewAccess(bankIdAccountId: BankIdAccountId, callContext: Option[CallContext]): Boolean = { - checkOwnerViewAccessAndReturnOwnerView(bankIdAccountId, callContext).isDefined - } final def hasViewAccess(bankIdAccountId: BankIdAccountId, viewId: ViewId, callContext: Option[CallContext]): Boolean = { APIUtil.checkViewAccessAndReturnView( viewId, diff --git a/obp-api/src/main/scala/code/model/dataAccess/MappedView.scala b/obp-api/src/main/scala/code/model/dataAccess/MappedView.scala index 9a0d1144d7..fe18582b78 100644 --- a/obp-api/src/main/scala/code/model/dataAccess/MappedView.scala +++ b/obp-api/src/main/scala/code/model/dataAccess/MappedView.scala @@ -454,6 +454,12 @@ class ViewImpl extends View with LongKeyedMapper[ViewImpl] with ManyToMany with object canUpdateCustomView_ extends MappedBoolean(this){ override def defaultValue = false } + object canRevokeAccessToCustomViews_ extends MappedBoolean(this) { + override def defaultValue = false + } + object canGrantAccessToCustomViews_ extends MappedBoolean(this) { + override def defaultValue = false + } def id: Long = id_.get def isSystem: Boolean = isSystem_.get @@ -576,6 +582,9 @@ class ViewImpl extends View with LongKeyedMapper[ViewImpl] with ManyToMany with def canCreateCustomView: Boolean = canCreateCustomView_.get def canDeleteCustomView: Boolean = canDeleteCustomView_.get def canUpdateCustomView: Boolean = canUpdateCustomView_.get + + override def canGrantAccessToCustomViews: Boolean = canGrantAccessToCustomViews_.get + override def canRevokeAccessToCustomViews: Boolean = canRevokeAccessToCustomViews_.get } object ViewImpl extends ViewImpl with LongKeyedMetaMapper[ViewImpl]{ diff --git a/obp-api/src/main/scala/code/views/MapperViews.scala b/obp-api/src/main/scala/code/views/MapperViews.scala index 637fba7ded..791683e3ef 100644 --- a/obp-api/src/main/scala/code/views/MapperViews.scala +++ b/obp-api/src/main/scala/code/views/MapperViews.scala @@ -327,7 +327,7 @@ object MapperViews extends Views with MdcLoggable { } def revokeAccountAccessByUser(bankId : BankId, accountId: AccountId, user : User, callContext: Option[CallContext]) : Box[Boolean] = { - canRevokeAccessToViewCommon(bankId, accountId, user, callContext) match { + canRevokeAccessToAllViews(bankId, accountId, user, callContext) match { case true => val permissions = AccountAccess.findAll( By(AccountAccess.user_fk, user.userPrimaryKey.value), @@ -337,7 +337,7 @@ object MapperViews extends Views with MdcLoggable { permissions.foreach(_.delete_!) Full(true) case false => - Failure(CannotRevokeAccountAccess) + Failure(UserLacksPermissionCanRevokeAccessToViewForTargetAccount) } } @@ -799,9 +799,11 @@ object MapperViews extends Views with MdcLoggable { .canUpdateCustomView_(false) .canSeePermissionForOneUser_(false) .canSeePermissionsForAllUsers_(false) + .canRevokeAccessToCustomViews_(false) + .canGrantAccessToCustomViews_(false) viewId match { - case SYSTEM_OWNER_VIEW_ID => + case SYSTEM_OWNER_VIEW_ID | SYSTEM_STANDARD_VIEW_ID => entity .canSeeAvailableViewsForBankAccount_(true) .canSeeTransactionRequests_(true) @@ -812,6 +814,10 @@ object MapperViews extends Views with MdcLoggable { .canUpdateCustomView_(true) .canSeePermissionForOneUser_(true) .canSeePermissionsForAllUsers_(true) + .canRevokeAccessToCustomViews_(true) + .canGrantAccessToCustomViews_(true) + .canGrantAccessToViews_(ALL_SYSTEM_VIEWS_CREATED_FROM_BOOT.mkString(",")) + .canRevokeAccessToViews_(ALL_SYSTEM_VIEWS_CREATED_FROM_BOOT.mkString(",")) case SYSTEM_STAGE_ONE_VIEW_ID => entity .canSeeTransactionDescription_(false) diff --git a/obp-api/src/main/scala/code/views/system/ViewDefinition.scala b/obp-api/src/main/scala/code/views/system/ViewDefinition.scala index 9256c63903..00dc4ac17a 100644 --- a/obp-api/src/main/scala/code/views/system/ViewDefinition.scala +++ b/obp-api/src/main/scala/code/views/system/ViewDefinition.scala @@ -6,7 +6,7 @@ import code.util.{AccountIdString, UUIDString} import com.openbankproject.commons.model._ import net.liftweb.common.Box import net.liftweb.common.Box.tryo -import net.liftweb.mapper._ +import net.liftweb.mapper.{MappedBoolean, _} import scala.collection.immutable.List @@ -57,6 +57,12 @@ class ViewDefinition extends View with LongKeyedMapper[ViewDefinition] with Many object canRevokeAccessToViews_ extends MappedText(this){ override def defaultValue = "" } + object canRevokeAccessToCustomViews_ extends MappedBoolean(this){ + override def defaultValue = false + } + object canGrantAccessToCustomViews_ extends MappedBoolean(this) { + override def defaultValue = false + } object canSeeTransactionThisBankAccount_ extends MappedBoolean(this){ override def defaultValue = false } @@ -340,11 +346,15 @@ class ViewDefinition extends View with LongKeyedMapper[ViewDefinition] with Many isFirehose_(viewData.is_firehose.getOrElse(false)) metadataView_(viewData.metadata_view) - canGrantAccessToViews_(viewData.can_grant_access_to_views.getOrElse(Nil).mkString(",")) - canRevokeAccessToViews_(viewData.can_revoke_access_to_views.getOrElse(Nil).mkString(",")) - val actions = viewData.allowed_actions + if (isSystem) { //The following are admin permissions, only system views are allowed to use them. + canGrantAccessToCustomViews_(actions.exists(_ == "can_grant_access_to_custom_views")) + canRevokeAccessToCustomViews_(actions.exists(_ == "can_revoke_access_to_custom_views")) + canGrantAccessToViews_(viewData.can_grant_access_to_views.getOrElse(Nil).mkString(",")) + canRevokeAccessToViews_(viewData.can_revoke_access_to_views.getOrElse(Nil).mkString(",")) + } + canSeeTransactionThisBankAccount_(actions.exists(_ =="can_see_transaction_this_bank_account")) canSeeTransactionOtherBankAccount_(actions.exists(_ =="can_see_transaction_other_bank_account")) canSeeTransactionMetadata_(actions.exists(_ == "can_see_transaction_metadata")) @@ -456,18 +466,24 @@ class ViewDefinition extends View with LongKeyedMapper[ViewDefinition] with Many def usePublicAliasIfOneExists: Boolean = usePublicAliasIfOneExists_.get def hideOtherAccountMetadataIfAlias: Boolean = hideOtherAccountMetadataIfAlias_.get + //This current view can grant access to other views. override def canGrantAccessToViews : Option[List[String]] = { canGrantAccessToViews_.get == null || canGrantAccessToViews_.get.isEmpty() match { case true => None case _ => Some(canGrantAccessToViews_.get.split(",").toList.map(_.trim)) } } + + def canGrantAccessToCustomViews : Boolean = canGrantAccessToCustomViews_.get + + //the current view can revoke access to other views. override def canRevokeAccessToViews : Option[List[String]] = { canRevokeAccessToViews_.get == null || canRevokeAccessToViews_.get.isEmpty() match { case true => None case _ => Some(canRevokeAccessToViews_.get.split(",").toList.map(_.trim)) } } + override def canRevokeAccessToCustomViews : Boolean = canRevokeAccessToCustomViews_.get //reading access diff --git a/obp-api/src/test/scala/code/api/v1_2_1/API1_2_1Test.scala b/obp-api/src/test/scala/code/api/v1_2_1/API1_2_1Test.scala index 17f23f9d5a..d713f8544d 100644 --- a/obp-api/src/test/scala/code/api/v1_2_1/API1_2_1Test.scala +++ b/obp-api/src/test/scala/code/api/v1_2_1/API1_2_1Test.scala @@ -1865,8 +1865,8 @@ class API1_2_1Test extends ServerSetupWithTestData with DefaultUsers with Privat val bankAccount : AccountJSON = randomPrivateAccount(bankId) When("the request is sent") val reply = grantUserAccessToView(bankId, bankAccount.id, randomString(10), randomCustomViewPermalink(bankId, bankAccount), user1) - Then("we should get a 400 ok code") - reply.code should equal (400) + Then("we should get a 403 ok code") + reply.code should equal (403) And("we should get an error message") reply.body.extract[ErrorMessage].message.nonEmpty should equal (true) } @@ -1879,10 +1879,10 @@ class API1_2_1Test extends ServerSetupWithTestData with DefaultUsers with Privat val viewsBefore = getUserAccountPermission(bankId, bankAccount.id, userId, user1).body.extract[ViewsJSONV121].views.length When("the request is sent") val reply = grantUserAccessToView(bankId, bankAccount.id, userId, randomString(10), user1) - Then("we should get a 404 code") - reply.code should equal (404) + Then("we should get a 403 code") + reply.code should equal (403) And("we should get an error message") - reply.body.extract[ErrorMessage].message.nonEmpty should equal (true) + reply.body.extract[ErrorMessage].message contains(UserLacksPermissionCanGrantAccessToViewForTargetAccount) shouldBe(true) val viewsAfter = getUserAccountPermission(bankId, bankAccount.id, userId, user1).body.extract[ViewsJSONV121].views.length viewsAfter should equal(viewsBefore) } @@ -1895,8 +1895,8 @@ class API1_2_1Test extends ServerSetupWithTestData with DefaultUsers with Privat val viewsBefore = getUserAccountPermission(bankId, bankAccount.id, userId, user1).body.extract[ViewsJSONV121].views.length When("the request is sent") val reply = grantUserAccessToView(bankId, bankAccount.id, userId, randomCustomViewPermalink(bankId, bankAccount), user3) - Then("we should get a 400 ok code") - reply.code should equal (400) + Then("we should get a 403 ok code") + reply.code should equal (403) And("we should get an error message") reply.body.extract[ErrorMessage].message.nonEmpty should equal (true) val viewsAfter = getUserAccountPermission(bankId, bankAccount.id, userId, user1).body.extract[ViewsJSONV121].views.length @@ -1935,8 +1935,8 @@ class API1_2_1Test extends ServerSetupWithTestData with DefaultUsers with Privat val viewsIdsToGrant= randomCustomViewsIdsToGrant(bankId, bankAccount.id) When("the request is sent") val reply = grantUserAccessToViews(bankId, bankAccount.id, userId, viewsIdsToGrant, user1) - Then("we should get a 400 ok code") - reply.code should equal (400) + Then("we should get a 403 ok code") + reply.code should equal (403) And("we should get an error message") reply.body.extract[ErrorMessage].message.nonEmpty should equal (true) } @@ -1949,10 +1949,10 @@ class API1_2_1Test extends ServerSetupWithTestData with DefaultUsers with Privat val viewsIdsToGrant= List(randomString(10),randomString(10)) When("the request is sent") val reply = grantUserAccessToViews(bankId, bankAccount.id, userId, viewsIdsToGrant, user1) - Then("we should get a 404 code") - reply.code should equal (404) + Then("we should get a 403 code") + reply.code should equal (403) And("we should get an error message") - reply.body.extract[ErrorMessage].message.nonEmpty should equal (true) + reply.body.extract[ErrorMessage].message contains(UserLacksPermissionCanGrantAccessToViewForTargetAccount) shouldBe(true) } scenario("we cannot grant a user access to a list of views on an bank account because some views don't exist", API1_2_1, PostPermissions){ @@ -1964,10 +1964,10 @@ class API1_2_1Test extends ServerSetupWithTestData with DefaultUsers with Privat val viewsBefore = getUserAccountPermission(bankId, bankAccount.id, userId, user1).body.extract[ViewsJSONV121].views.length When("the request is sent") val reply = grantUserAccessToViews(bankId, bankAccount.id, userId, viewsIdsToGrant, user1) - Then("we should get a 404 code") - reply.code should equal (404) + Then("we should get a 403 code") + reply.code should equal (403) And("we should get an error message") - reply.body.extract[ErrorMessage].message.nonEmpty should equal (true) + reply.body.extract[ErrorMessage].message contains(UserLacksPermissionCanGrantAccessToViewForTargetAccount) shouldBe(true) val viewsAfter = getUserAccountPermission(bankId, bankAccount.id, userId, user1).body.extract[ViewsJSONV121].views.length viewsAfter should equal(viewsBefore) } @@ -1981,8 +1981,8 @@ class API1_2_1Test extends ServerSetupWithTestData with DefaultUsers with Privat val viewsBefore = getUserAccountPermission(bankId, bankAccount.id, userId, user1).body.extract[ViewsJSONV121].views.length When("the request is sent") val reply = grantUserAccessToViews(bankId, bankAccount.id, userId, viewsIdsToGrant, user3) - Then("we should get a 400 ok code") - reply.code should equal (400) + Then("we should get a 403 ok code") + reply.code should equal (403) And("we should get an error message") reply.body.extract[ErrorMessage].message.nonEmpty should equal (true) val viewsAfter = getUserAccountPermission(bankId, bankAccount.id, userId, user1).body.extract[ViewsJSONV121].views.length @@ -2032,8 +2032,8 @@ class API1_2_1Test extends ServerSetupWithTestData with DefaultUsers with Privat val bankAccount : AccountJSON = randomPrivateAccount(bankId) When("the request is sent") val reply = revokeUserAccessToView(bankId, bankAccount.id, randomString(10), randomCustomViewPermalink(bankId, bankAccount), user1) - Then("we should get a 400 ok code") - reply.code should equal (400) + Then("we should get a 403 ok code") + reply.code should equal (403) } scenario("we can revoke the access of a user to owner view on a bank account if that user is an account holder of that account", API1_2_1, DeletePermission){ @@ -2065,8 +2065,8 @@ class API1_2_1Test extends ServerSetupWithTestData with DefaultUsers with Privat val viewsBefore = getUserAccountPermission(bankId, bankAccount.id, userId, user1).body.extract[ViewsJSONV121].views.length When("the request is sent") val reply = revokeUserAccessToView(bankId, bankAccount.id, userId, randomString(10), user1) - Then("we should get a 400 code") - reply.code should equal (400) + Then("we should get a 403 code") + reply.code should equal (403) val viewsAfter = getUserAccountPermission(bankId, bankAccount.id, userId, user1).body.extract[ViewsJSONV121].views.length viewsAfter should equal(viewsBefore) } @@ -2079,8 +2079,8 @@ class API1_2_1Test extends ServerSetupWithTestData with DefaultUsers with Privat val viewsBefore = getUserAccountPermission(bankId, bankAccount.id, userId, user1).body.extract[ViewsJSONV121].views.length When("the request is sent") val reply = revokeUserAccessToView(bankId, bankAccount.id, userId, randomCustomViewPermalink(bankId, bankAccount), user3) - Then("we should get a 400 ok code") - reply.code should equal (400) + Then("we should get a 403 ok code") + reply.code should equal (403) val viewsAfter = getUserAccountPermission(bankId, bankAccount.id, userId, user1).body.extract[ViewsJSONV121].views.length viewsAfter should equal(viewsBefore) } @@ -2108,8 +2108,8 @@ class API1_2_1Test extends ServerSetupWithTestData with DefaultUsers with Privat val bankAccount : AccountJSON = randomPrivateAccount(bankId) When("the request is sent") val reply = revokeUserAccessToAllViews(bankId, bankAccount.id, randomString(510), user1) - Then("we should get a 400 ok code") - reply.code should equal (400) + Then("we should get a 403 ok code") + reply.code should equal (403) } scenario("we cannot revoke a user access to a view on an bank account because the user does not have owner view access", API1_2_1, DeletePermissions){ @@ -2123,8 +2123,8 @@ class API1_2_1Test extends ServerSetupWithTestData with DefaultUsers with Privat val viewsBefore = getUserAccountPermission(bankId, bankAccount.id, userId, user1).body.extract[ViewsJSONV121].views.length When("the request is sent") val reply = revokeUserAccessToAllViews(bankId, bankAccount.id, userId, user3) - Then("we should get a 400 ok code") - reply.code should equal (400) + Then("we should get a 403 ok code") + reply.code should equal (403) val viewsAfter = getUserAccountPermission(bankId, bankAccount.id, userId, user1).body.extract[ViewsJSONV121].views.length viewsAfter should equal(viewsBefore) } diff --git a/obp-commons/src/main/scala/com/openbankproject/commons/model/ViewModel.scala b/obp-commons/src/main/scala/com/openbankproject/commons/model/ViewModel.scala index f12d74dfab..9000dd9921 100644 --- a/obp-commons/src/main/scala/com/openbankproject/commons/model/ViewModel.scala +++ b/obp-commons/src/main/scala/com/openbankproject/commons/model/ViewModel.scala @@ -250,10 +250,12 @@ trait View { def usePrivateAliasIfOneExists: Boolean def hideOtherAccountMetadataIfAlias: Boolean - - // Introduced in version 5.0.0 + //TODO, in progress, we only make the system view work, the custom views are still in progress.. +// https://gitlab-external.tesobe.com/tesobe/boards/tech-internal/-/issues/314 def canGrantAccessToViews : Option[List[String]] = None + def canGrantAccessToCustomViews : Boolean // if this true, we can grant custom views, if it is false, no one can grant custom views. def canRevokeAccessToViews : Option[List[String]] = None + def canRevokeAccessToCustomViews : Boolean // if this true, we can revoke custom views,if it is false, no one can revoke custom views. //reading access From 596140206bc146a84304db00037db14f5b38c375 Mon Sep 17 00:00:00 2001 From: hongwei Date: Mon, 3 Jul 2023 19:45:38 +0800 Subject: [PATCH 19/41] refactor/code clean, remove some comments --- obp-api/src/main/scala/code/api/v2_1_0/APIMethods210.scala | 1 - obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala | 1 - obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala | 1 - obp-api/src/main/scala/code/model/User.scala | 2 -- 4 files changed, 5 deletions(-) diff --git a/obp-api/src/main/scala/code/api/v2_1_0/APIMethods210.scala b/obp-api/src/main/scala/code/api/v2_1_0/APIMethods210.scala index bda9fb632f..11757f9dd4 100644 --- a/obp-api/src/main/scala/code/api/v2_1_0/APIMethods210.scala +++ b/obp-api/src/main/scala/code/api/v2_1_0/APIMethods210.scala @@ -701,7 +701,6 @@ trait APIMethods210 { BankNotFound, AccountNotFound, UserHasMissingRoles, - UserNoOwnerView, UnknownError ), List(apiTagTransactionRequest, apiTagPsd2)) diff --git a/obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala b/obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala index 6ba6453dfe..065bb495b3 100644 --- a/obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala +++ b/obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala @@ -1073,7 +1073,6 @@ trait APIMethods310 { BankAccountNotFound, UserNoPermissionAccessView, ViewDoesNotPermitAccess, - UserNoOwnerView, GetTransactionRequestsException, UnknownError ), diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index 3be4bbaff6..c246887b56 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -5155,7 +5155,6 @@ trait APIMethods400 { $BankNotFound, $BankAccountNotFound, $UserNoPermissionAccessView, - UserNoOwnerView, GetTransactionRequestsException, UnknownError ), diff --git a/obp-api/src/main/scala/code/model/User.scala b/obp-api/src/main/scala/code/model/User.scala index e0ee47b5e4..10c70b84f4 100644 --- a/obp-api/src/main/scala/code/model/User.scala +++ b/obp-api/src/main/scala/code/model/User.scala @@ -94,8 +94,6 @@ case class UserExtended(val user: User) extends MdcLoggable { } final def checkOwnerViewAccessAndReturnOwnerView(bankIdAccountId: BankIdAccountId, callContext: Option[CallContext]) = { - //Note: now SYSTEM_OWNER_VIEW_ID == SYSTEM_OWNER_VIEW_ID is the same `owner` so we only use one here. - //And in side the checkViewAccessAndReturnView, it will first check the customer view and then will check system view. APIUtil.checkViewAccessAndReturnView(ViewId(SYSTEM_OWNER_VIEW_ID), bankIdAccountId, Some(this.user), callContext) } From 8794ab1937df3bc285405c391f01411c0a3a7721 Mon Sep 17 00:00:00 2001 From: hongwei Date: Mon, 3 Jul 2023 21:05:04 +0800 Subject: [PATCH 20/41] bugfix/fixed the failed jenkins job-Unique index or primary key violation --- .../code/model/dataAccess/AuthUser.scala | 17 +++++++++-------- .../main/scala/code/views/MapperViews.scala | 16 +++++++++------- .../code/views/system/AccountAccess.scala | 19 +++++++++++++------ 3 files changed, 31 insertions(+), 21 deletions(-) diff --git a/obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala b/obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala index 297f20df8b..1797cad9e4 100644 --- a/obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala +++ b/obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala @@ -1436,11 +1436,12 @@ def restoreSomeSessions(): Unit = { _ = logger.debug("refreshViewsAccountAccessAndHolders.csbNewBankAccountIds-------" + csbNewBankAccountIds) view <- Views.views.vend.getOrCreateSystemViewFromCbs(viewId)//TODO, only support system views so far, may add custom views later. _=UserRefreshes.UserRefreshes.vend.createOrUpdateRefreshUser(user.userId) + view <- if (view.isSystem) //if the view is a system view, we will call `grantAccessToSystemView` + Views.views.vend.grantAccessToSystemView(bankId, accountId, view, user) + else //otherwise, we will call `grantAccessToCustomView` + Views.views.vend.grantAccessToCustomView(view.uid, user) } yield { - if (view.isSystem)//if the view is a system view, we will call `grantAccessToSystemView` - Views.views.vend.grantAccessToSystemView(bankId, accountId, view, user) - else //otherwise, we will call `grantAccessToCustomView` - Views.views.vend.grantAccessToCustomView(view.uid, user) + view } //3rd: if the ids are not change, but views are changed, we still need compare the view for each account: @@ -1471,12 +1472,12 @@ def restoreSomeSessions(): Unit = { newViewForAccount <- csbNewViewsForAccount view <- Views.views.vend.getOrCreateSystemViewFromCbs(newViewForAccount)//TODO, only support system views so far, may add custom views later. _ = UserRefreshes.UserRefreshes.vend.createOrUpdateRefreshUser(user.userId) - }yield{ - if (view.isSystem)//if the view is a system view, we will call `grantAccessToSystemView` - Views.views.vend.grantAccessToSystemView(bankAccountId.bankId, bankAccountId.accountId, view, user) + view <- if (view.isSystem) //if the view is a system view, we will call `grantAccessToSystemView` + Views.views.vend.grantAccessToSystemView(bankAccountId.bankId, bankAccountId.accountId, view, user) else //otherwise, we will call `grantAccessToCustomView` Views.views.vend.grantAccessToCustomView(view.uid, user) - + }yield{ + view } } } yield { diff --git a/obp-api/src/main/scala/code/views/MapperViews.scala b/obp-api/src/main/scala/code/views/MapperViews.scala index d9387d0e01..5b5611e2ea 100644 --- a/obp-api/src/main/scala/code/views/MapperViews.scala +++ b/obp-api/src/main/scala/code/views/MapperViews.scala @@ -91,19 +91,21 @@ object MapperViews extends Views with MdcLoggable { } // This is an idempotent function private def getOrGrantAccessToCustomView(user: User, viewDefinition: View, bankId: String, accountId: String): Box[View] = { - if (AccountAccess.count( - By(AccountAccess.user_fk, user.userPrimaryKey.value), - By(AccountAccess.bank_id, bankId), - By(AccountAccess.account_id, accountId), - By(AccountAccess.view_id, viewDefinition.viewId.value)) == 0) { - logger.debug(s"getOrGrantAccessToCustomView AccountAccess.create user(UserId(${user.userId}), ViewId(${viewDefinition.viewId.value}), bankId($bankId), accountId($accountId)") + if (AccountAccess.findByUniqueIndex( + BankId(bankId), + AccountId(accountId), + viewDefinition.viewId, + user.userPrimaryKey, + ALL_CONSUMERS).isEmpty) { + logger.debug(s"getOrGrantAccessToCustomView AccountAccess.create" + + s"user(UserId(${user.userId}), ViewId(${viewDefinition.viewId.value}), bankId($bankId), accountId($accountId), consumerId($ALL_CONSUMERS)") // SQL Insert AccountAccessList val saved = AccountAccess.create. user_fk(user.userPrimaryKey.value). bank_id(bankId). account_id(accountId). view_id(viewDefinition.viewId.value). - view_fk(viewDefinition.id). + consumer_id(ALL_CONSUMERS). save if (saved) { //logger.debug("saved AccountAccessList") diff --git a/obp-api/src/main/scala/code/views/system/AccountAccess.scala b/obp-api/src/main/scala/code/views/system/AccountAccess.scala index 59775b298e..6a7dcc25df 100644 --- a/obp-api/src/main/scala/code/views/system/AccountAccess.scala +++ b/obp-api/src/main/scala/code/views/system/AccountAccess.scala @@ -28,6 +28,16 @@ class AccountAccess extends LongKeyedMapper[AccountAccess] with IdPK with Create } object AccountAccess extends AccountAccess with LongKeyedMetaMapper[AccountAccess] { override def dbIndexes: List[BaseIndex[AccountAccess]] = UniqueIndex(bank_id, account_id, view_id, user_fk, consumer_id) :: super.dbIndexes + + def findByUniqueIndex(bankId: BankId, accountId: AccountId, viewId: ViewId, userPrimaryKey: UserPrimaryKey, consumerId: String) = + AccountAccess.find( + By(AccountAccess.bank_id, bankId.value), + By(AccountAccess.account_id, accountId.value), + By(AccountAccess.view_id, viewId.value), + By(AccountAccess.user_fk, userPrimaryKey.value), + By(AccountAccess.consumer_id, consumerId), + ) + def findAllBySystemViewId(systemViewId:ViewId)= AccountAccess.findAll( By(AccountAccess.view_id, systemViewId.value) ) @@ -38,13 +48,11 @@ object AccountAccess extends AccountAccess with LongKeyedMetaMapper[AccountAcces AccountAccess.findAllByBankIdAccountIdViewId(view.bankId, view.accountId, view.viewId) } def findAllByUserPrimaryKey(userPrimaryKey:UserPrimaryKey)= AccountAccess.findAll( - By(AccountAccess.user_fk, userPrimaryKey.value), - PreCache(AccountAccess.view_fk) + By(AccountAccess.user_fk, userPrimaryKey.value) ) def findAllByBankIdAccountId(bankId:BankId, accountId:AccountId) = AccountAccess.findAll( By(AccountAccess.bank_id, bankId.value), - By(AccountAccess.account_id, accountId.value), - PreCache(AccountAccess.view_fk) + By(AccountAccess.account_id, accountId.value) ) def findAllByBankIdAccountIdViewId(bankId:BankId, accountId:AccountId, viewId:ViewId)= AccountAccess.findAll( By(AccountAccess.bank_id, bankId.value), @@ -55,8 +63,7 @@ object AccountAccess extends AccountAccess with LongKeyedMetaMapper[AccountAcces def findByBankIdAccountIdUserPrimaryKey(bankId: BankId, accountId: AccountId, userPrimaryKey: UserPrimaryKey) = AccountAccess.findAll( By(AccountAccess.bank_id, bankId.value), By(AccountAccess.account_id, accountId.value), - By(AccountAccess.user_fk, userPrimaryKey.value), - PreCache(AccountAccess.view_fk) + By(AccountAccess.user_fk, userPrimaryKey.value) ) def findByBankIdAccountIdViewIdUserPrimaryKey(bankId: BankId, accountId: AccountId, viewId: ViewId, userPrimaryKey: UserPrimaryKey) = AccountAccess.find( From 5a9bcba6dfbaf86a742dc21d3749fc5336356f8d Mon Sep 17 00:00:00 2001 From: hongwei Date: Mon, 3 Jul 2023 23:32:07 +0800 Subject: [PATCH 21/41] refactor/added more logs for refreshViewsAccountAccessAndHolders --- .../main/scala/code/model/dataAccess/AuthUser.scala | 12 +++++++++--- obp-api/src/main/scala/code/views/MapperViews.scala | 9 +++++---- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala b/obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala index 1797cad9e4..c31faa3326 100644 --- a/obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala +++ b/obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala @@ -1414,6 +1414,7 @@ def restoreSomeSessions(): Unit = { //TODO. need to double check if we need to clean accountidmapping table, account meta data (MappedTag) .... for{ cbsRemovedBankAccountId <- cbsRemovedBankAccountIds + _ = logger.debug("refreshViewsAccountAccessAndHolders.cbsRemovedBankAccountIds.cbsRemovedBankAccountId: start-------" + cbsRemovedBankAccountId) bankId = cbsRemovedBankAccountId.bankId accountId = cbsRemovedBankAccountId.accountId _ = Views.views.vend.revokeAccountAccessByUser(bankId, accountId, user, callContext) @@ -1421,25 +1422,28 @@ def restoreSomeSessions(): Unit = { cbsAccount = accountsHeld.find(cbsAccount =>cbsAccount.bankId == bankId.value && cbsAccount.accountId == accountId.value) viewId <- cbsAccount.map(_.viewsToGenerate).getOrElse(List.empty[String]) _=UserRefreshes.UserRefreshes.vend.createOrUpdateRefreshUser(user.userId) + success <- Views.views.vend.removeCustomView(ViewId(viewId), cbsRemovedBankAccountId) + _ = logger.debug("refreshViewsAccountAccessAndHolders.cbsRemovedBankAccountIds.cbsRemovedBankAccountId: finish-------" + cbsRemovedBankAccountId) } yield { - Views.views.vend.removeCustomView(ViewId(viewId), cbsRemovedBankAccountId) + success } //2st: create views/accountAccess/accountHolders for the new coming accounts for { newBankAccountId <- csbNewBankAccountIds + _ = logger.debug("refreshViewsAccountAccessAndHolders.csbNewBankAccountId.newBankAccountId: start-------" + newBankAccountId) _ = AccountHolders.accountHolders.vend.getOrCreateAccountHolder(user,newBankAccountId,Some("UserAuthContext")) bankId = newBankAccountId.bankId accountId = newBankAccountId.accountId newBankAccount = accountsHeld.find(cbsAccount =>cbsAccount.bankId == bankId.value && cbsAccount.accountId == accountId.value) viewId <- newBankAccount.map(_.viewsToGenerate).getOrElse(List.empty[String]) - _ = logger.debug("refreshViewsAccountAccessAndHolders.csbNewBankAccountIds-------" + csbNewBankAccountIds) view <- Views.views.vend.getOrCreateSystemViewFromCbs(viewId)//TODO, only support system views so far, may add custom views later. _=UserRefreshes.UserRefreshes.vend.createOrUpdateRefreshUser(user.userId) view <- if (view.isSystem) //if the view is a system view, we will call `grantAccessToSystemView` Views.views.vend.grantAccessToSystemView(bankId, accountId, view, user) else //otherwise, we will call `grantAccessToCustomView` Views.views.vend.grantAccessToCustomView(view.uid, user) + _ = logger.debug("refreshViewsAccountAccessAndHolders.csbNewBankAccountId.newBankAccountId: finish-------" + newBankAccountId) } yield { view } @@ -1451,9 +1455,9 @@ def restoreSomeSessions(): Unit = { // we can not get the views from the `viewDefinition` table, because we can not delete system views at all. we need to read the view from accountAccess table. //obpViewsForAccount = MapperViews.availableViewsForAccount(bankAccountId).map(_.viewId.value) obpViewsForAccount = Views.views.vend.privateViewsUserCanAccessForAccount(user, bankAccountId).map(_.viewId.value) + _ = logger.debug("refreshViewsAccountAccessAndHolders.obpViewsForAccount-------" + obpViewsForAccount) cbsViewsForAccount = accountsHeld.find(account => account.bankId.equals(bankAccountId.bankId.value) && account.accountId.equals(bankAccountId.accountId.value)).map(_.viewsToGenerate).getOrElse(Nil) - _ = logger.debug("refreshViewsAccountAccessAndHolders.obpViewsForAccount-------" + obpViewsForAccount) _ = logger.debug("refreshViewsAccountAccessAndHolders.cbsViewsForAccount-------" + cbsViewsForAccount) //cbs removed these views, but OBP still contains the data for them, so we need to clean data in OBP side. cbsRemovedViewsForAccount = obpViewsForAccount diff cbsViewsForAccount @@ -1470,12 +1474,14 @@ def restoreSomeSessions(): Unit = { _ = if(csbNewViewsForAccount.nonEmpty){ for{ newViewForAccount <- csbNewViewsForAccount + _ = logger.debug("refreshViewsAccountAccessAndHolders.csbNewViewsForAccount.newViewForAccount start:-------" + newViewForAccount) view <- Views.views.vend.getOrCreateSystemViewFromCbs(newViewForAccount)//TODO, only support system views so far, may add custom views later. _ = UserRefreshes.UserRefreshes.vend.createOrUpdateRefreshUser(user.userId) view <- if (view.isSystem) //if the view is a system view, we will call `grantAccessToSystemView` Views.views.vend.grantAccessToSystemView(bankAccountId.bankId, bankAccountId.accountId, view, user) else //otherwise, we will call `grantAccessToCustomView` Views.views.vend.grantAccessToCustomView(view.uid, user) + _ = logger.debug("refreshViewsAccountAccessAndHolders.csbNewViewsForAccount.newViewForAccount finish:-------" + newViewForAccount) }yield{ view } diff --git a/obp-api/src/main/scala/code/views/MapperViews.scala b/obp-api/src/main/scala/code/views/MapperViews.scala index 5b5611e2ea..1faae5b3f7 100644 --- a/obp-api/src/main/scala/code/views/MapperViews.scala +++ b/obp-api/src/main/scala/code/views/MapperViews.scala @@ -609,7 +609,8 @@ object MapperViews extends Views with MdcLoggable { def getOrCreateSystemViewFromCbs(viewId: String): Box[View] = { - + logger.debug(s"-->getOrCreateSystemViewFromCbs.${viewId} --- start ") + val ownerView = SYSTEM_OWNER_VIEW_ID.equals(viewId.toLowerCase) val accountantsView = SYSTEM_ACCOUNTANT_VIEW_ID.equals(viewId.toLowerCase) val auditorsView = SYSTEM_AUDITOR_VIEW_ID.equals(viewId.toLowerCase) @@ -632,7 +633,7 @@ object MapperViews extends Views with MdcLoggable { Failure(ViewIdNotSupported+ s"Your input viewId is :$viewId") } - logger.debug(s"-->getOrCreateSystemViewFromCbs.${viewId } : ${theView} ") + logger.debug(s"-->getOrCreateSystemViewFromCbs.${viewId } --- finish : ${theView} ") theView } @@ -837,9 +838,9 @@ object MapperViews extends Views with MdcLoggable { } def createAndSaveSystemView(viewId: String) : Box[View] = { - logger.debug(s"-->createAndSaveSystemView.viewId: ${viewId} ") + logger.debug(s"-->createAndSaveSystemView.viewId.start${viewId} ") val res = unsavedSystemView(viewId).saveMe - logger.debug(s"-->createAndSaveSystemView: ${res} ") + logger.debug(s"-->createAndSaveSystemView.finish: ${res} ") Full(res) } From 746cf718eec5dcac32a77fa6071d5436cb3ffd81 Mon Sep 17 00:00:00 2001 From: hongwei Date: Tue, 4 Jul 2023 01:54:37 +0800 Subject: [PATCH 22/41] bugfix/fixed future issue for setAccountHolderAndRefreshUserAccountAccess method --- .../scala/code/api/v2_2_0/APIMethods220.scala | 2 +- .../scala/code/api/v3_1_0/APIMethods310.scala | 7 +++--- .../scala/code/api/v4_0_0/APIMethods400.scala | 4 ++-- .../scala/code/api/v5_0_0/APIMethods500.scala | 2 +- .../code/model/dataAccess/AuthUser.scala | 17 +++++++++---- .../BankAccountCreationDispatcher.scala | 2 +- .../main/scala/code/views/MapperViews.scala | 4 ++-- .../scala/code/api/v2_2_0/AccountTest.scala | 19 --------------- .../scala/code/api/v3_1_0/AccountTest.scala | 24 +------------------ .../code/api/v4_0_0/AccountAccessTest.scala | 3 --- .../scala/code/api/v4_0_0/AccountTest.scala | 14 +---------- .../api/v4_0_0/DeleteAccountCascadeTest.scala | 4 ---- .../api/v4_0_0/DeleteBankCascadeTest.scala | 5 +--- .../api/v4_0_0/SettlementAccountTest.scala | 4 ---- .../code/api/v4_0_0/V400ServerSetup.scala | 4 +--- .../scala/code/api/v5_0_0/AccountTest.scala | 19 --------------- 16 files changed, 27 insertions(+), 107 deletions(-) diff --git a/obp-api/src/main/scala/code/api/v2_2_0/APIMethods220.scala b/obp-api/src/main/scala/code/api/v2_2_0/APIMethods220.scala index 4c7d51483b..441a8246ba 100644 --- a/obp-api/src/main/scala/code/api/v2_2_0/APIMethods220.scala +++ b/obp-api/src/main/scala/code/api/v2_2_0/APIMethods220.scala @@ -832,7 +832,7 @@ trait APIMethods220 { //1 Create or Update the `Owner` for the new account //2 Add permission to the user //3 Set the user as the account holder - _ = BankAccountCreation.setAccountHolderAndRefreshUserAccountAccess(bankId, accountId, postedOrLoggedInUser, callContext) + _ <- BankAccountCreation.setAccountHolderAndRefreshUserAccountAccess(bankId, accountId, postedOrLoggedInUser, callContext) } yield { (JSONFactory220.createAccountJSON(userIdAccountOwner, bankAccount), HttpCode.`200`(callContext)) diff --git a/obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala b/obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala index 111ddf6418..7fad0ea25b 100644 --- a/obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala +++ b/obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala @@ -1890,7 +1890,7 @@ trait APIMethods310 { _ <- NewStyle.function.hasEntitlement("", userId, canRefreshUser, callContext) startTime <- Future{Helpers.now} (user, callContext) <- NewStyle.function.findByUserId(userId, callContext) - _ = AuthUser.refreshUser(user, callContext) + _ <- AuthUser.refreshUser(user, callContext) endTime <- Future{Helpers.now} durationTime = endTime.getTime - startTime.getTime } yield { @@ -2340,8 +2340,9 @@ trait APIMethods310 { "", List.empty, callContext) + success <- BankAccountCreation.setAccountHolderAndRefreshUserAccountAccess(bankId, accountId, u, callContext) }yield { - BankAccountCreation.setAccountHolderAndRefreshUserAccountAccess(bankId, accountId, u, callContext) + success } case _ => Future{""} } @@ -5428,7 +5429,7 @@ trait APIMethods310 { //1 Create or Update the `Owner` for the new account //2 Add permission to the user //3 Set the user as the account holder - _ = BankAccountCreation.setAccountHolderAndRefreshUserAccountAccess(bankId, accountId, postedOrLoggedInUser, callContext) + _ <- BankAccountCreation.setAccountHolderAndRefreshUserAccountAccess(bankId, accountId, postedOrLoggedInUser, callContext) } yield { (JSONFactory310.createAccountJSON(userIdAccountOwner, bankAccount, accountAttributes), HttpCode.`201`(callContext)) } diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index eb13446ab7..b07b088e00 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -536,7 +536,7 @@ trait APIMethods400 { //1 Create or Update the `Owner` for the new account //2 Add permission to the user //3 Set the user as the account holder - _ = BankAccountCreation.setAccountHolderAndRefreshUserAccountAccess(bankId, accountId, postedOrLoggedInUser, callContext) + _ <- BankAccountCreation.setAccountHolderAndRefreshUserAccountAccess(bankId, accountId, postedOrLoggedInUser, callContext) } yield { (JSONFactory400.createSettlementAccountJson(userIdAccountOwner, bankAccount, accountAttributes), HttpCode.`201`(callContext)) } @@ -2631,7 +2631,7 @@ trait APIMethods400 { //1 Create or Update the `Owner` for the new account //2 Add permission to the user //3 Set the user as the account holder - _ = BankAccountCreation.setAccountHolderAndRefreshUserAccountAccess(bankId, accountId, postedOrLoggedInUser, callContext) + _ <- BankAccountCreation.setAccountHolderAndRefreshUserAccountAccess(bankId, accountId, postedOrLoggedInUser, callContext) } yield { (JSONFactory310.createAccountJSON(userIdAccountOwner, bankAccount, accountAttributes), HttpCode.`201`(callContext)) } diff --git a/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala b/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala index c7859a3101..1f038ae5b3 100644 --- a/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala +++ b/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala @@ -391,7 +391,7 @@ trait APIMethods500 { //1 Create or Update the `Owner` for the new account //2 Add permission to the user //3 Set the user as the account holder - _ = BankAccountCreation.setAccountHolderAndRefreshUserAccountAccess(bankId, accountId, postedOrLoggedInUser, callContext) + _ <- BankAccountCreation.setAccountHolderAndRefreshUserAccountAccess(bankId, accountId, postedOrLoggedInUser, callContext) } yield { (JSONFactory310.createAccountJSON(userIdAccountOwner, bankAccount, accountAttributes), HttpCode.`201`(callContext)) } diff --git a/obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala b/obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala index c31faa3326..d16c37a63e 100644 --- a/obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala +++ b/obp-api/src/main/scala/code/model/dataAccess/AuthUser.scala @@ -1376,8 +1376,11 @@ def restoreSomeSessions(): Unit = { connectorEmptyResponse(_, callContext) } _ = logger.debug(s"--> for user($user): AuthUser.refreshUserAccountAccess.accounts : ${accountsHeld}") + + success = refreshViewsAccountAccessAndHolders(user, accountsHeld, callContext) + }yield { - refreshViewsAccountAccessAndHolders(user, accountsHeld, callContext) + success } } @@ -1387,7 +1390,7 @@ def restoreSomeSessions(): Unit = { * This method can only be used by the original user(account holder). * InboundAccount return many fields, but in this method, we only need bankId, accountId and viewId so far. */ - def refreshViewsAccountAccessAndHolders(user: User, accountsHeld: List[InboundAccount], callContext: Option[CallContext]): Unit = { + def refreshViewsAccountAccessAndHolders(user: User, accountsHeld: List[InboundAccount], callContext: Option[CallContext]) = { if(user.isOriginalUser){ //first, we compare the accounts in obp and the accounts in cbs, val (_, privateAccountAccess) = Views.views.vend.privateViewsUserCanAccess(user) @@ -1471,7 +1474,7 @@ def restoreSomeSessions(): Unit = { //cbs has new views which are not in obp yet, we need to create new data for these accounts. csbNewViewsForAccount = cbsViewsForAccount diff obpViewsForAccount _ = logger.debug("refreshViewsAccountAccessAndHolders.csbNewViewsForAccount-------" + csbNewViewsForAccount) - _ = if(csbNewViewsForAccount.nonEmpty){ + success = if(csbNewViewsForAccount.nonEmpty){ for{ newViewForAccount <- csbNewViewsForAccount _ = logger.debug("refreshViewsAccountAccessAndHolders.csbNewViewsForAccount.newViewForAccount start:-------" + newViewForAccount) @@ -1487,10 +1490,14 @@ def restoreSomeSessions(): Unit = { } } } yield { - bankAccountId + success } } - } + true + } + else { + false + } } /** * Find the authUser by author user name(authUser and resourceUser are the same). diff --git a/obp-api/src/main/scala/code/model/dataAccess/BankAccountCreationDispatcher.scala b/obp-api/src/main/scala/code/model/dataAccess/BankAccountCreationDispatcher.scala index f773e7454e..a03dee52eb 100644 --- a/obp-api/src/main/scala/code/model/dataAccess/BankAccountCreationDispatcher.scala +++ b/obp-api/src/main/scala/code/model/dataAccess/BankAccountCreationDispatcher.scala @@ -85,7 +85,7 @@ package code.model.dataAccess { * * @return This is a procedure, no return value. Just use the side effect. */ - def setAccountHolderAndRefreshUserAccountAccess(bankId : BankId, accountId : AccountId, user: User, callContext: Option[CallContext]): Unit = { + def setAccountHolderAndRefreshUserAccountAccess(bankId : BankId, accountId : AccountId, user: User, callContext: Option[CallContext]) = { // Here, we can call `addPermissionToSystemOwnerView` directly, but from now on, we try to simulate the CBS account creation. // 1st-getOrCreateAccountHolder: in this method, we only create the account holder, no view, account access involved here. AccountHolders.accountHolders.vend.getOrCreateAccountHolder(user: User, BankIdAccountId(bankId, accountId)) diff --git a/obp-api/src/main/scala/code/views/MapperViews.scala b/obp-api/src/main/scala/code/views/MapperViews.scala index 1faae5b3f7..4255216a50 100644 --- a/obp-api/src/main/scala/code/views/MapperViews.scala +++ b/obp-api/src/main/scala/code/views/MapperViews.scala @@ -609,7 +609,7 @@ object MapperViews extends Views with MdcLoggable { def getOrCreateSystemViewFromCbs(viewId: String): Box[View] = { - logger.debug(s"-->getOrCreateSystemViewFromCbs.${viewId} --- start ") + logger.debug(s"-->getOrCreateSystemViewFromCbs--- start--${viewId} ") val ownerView = SYSTEM_OWNER_VIEW_ID.equals(viewId.toLowerCase) val accountantsView = SYSTEM_ACCOUNTANT_VIEW_ID.equals(viewId.toLowerCase) @@ -633,7 +633,7 @@ object MapperViews extends Views with MdcLoggable { Failure(ViewIdNotSupported+ s"Your input viewId is :$viewId") } - logger.debug(s"-->getOrCreateSystemViewFromCbs.${viewId } --- finish : ${theView} ") + logger.debug(s"-->getOrCreateSystemViewFromCbs --- finish.${viewId } : ${theView} ") theView } diff --git a/obp-api/src/test/scala/code/api/v2_2_0/AccountTest.scala b/obp-api/src/test/scala/code/api/v2_2_0/AccountTest.scala index 24099686ea..a1a62b8791 100644 --- a/obp-api/src/test/scala/code/api/v2_2_0/AccountTest.scala +++ b/obp-api/src/test/scala/code/api/v2_2_0/AccountTest.scala @@ -15,14 +15,6 @@ import scala.util.Random class AccountTest extends V220ServerSetup with DefaultUsers { - override def beforeAll(): Unit = { - super.beforeAll() - } - - override def afterAll(): Unit = { - super.afterAll() - } - val mockAccountId1 = "NEW_MOCKED_ACCOUNT_ID_01" val mockAccountId2 = "NEW_MOCKED_ACCOUNT_ID_02" @@ -51,9 +43,6 @@ class AccountTest extends V220ServerSetup with DefaultUsers { val responsePut = makePutRequest(requestPut, write(accountPutJSON)) And("We should get a 200") responsePut.code should equal(200) - //for create account endpoint, we need to wait for `setAccountHolderAndRefreshUserAccountAccess` method, - //it is an asynchronous process, need some time to be done. - TimeUnit.SECONDS.sleep(2) When("We make the authenticated access request") val requestGetAll = (v2_2Request / "accounts").GET <@ (user1) @@ -98,10 +87,6 @@ class AccountTest extends V220ServerSetup with DefaultUsers { val requestPut = (v2_2Request / "banks" / testBank.value / "accounts" / mockAccountId1).PUT <@ (user1) val responsePut = makePutRequest(requestPut, write(accountPutJSON)) - //for create account endpoint, we need to wait for `setAccountHolderAndRefreshUserAccountAccess` method, - //it is an asynchronous process, need some time to be done. - TimeUnit.SECONDS.sleep(2) - And("We should get a 200") responsePut.code should equal(200) @@ -165,10 +150,6 @@ class AccountTest extends V220ServerSetup with DefaultUsers { val requestPut = (v2_2Request / "banks" / testBank.value / "accounts" / mockAccountId1).PUT <@ (user1) val responsePut = makePutRequest(requestPut, write(accountPutJSON)) - //for create account endpoint, we need to wait for `setAccountHolderAndRefreshUserAccountAccess` method, - //it is an asynchronous process, need some time to be done. - TimeUnit.SECONDS.sleep(2) - Then("we get the account access for this account") val accountViewsRequest = (v2_2Request / "banks" / testBank.value / "accounts" / mockAccountId1 / "views").GET <@(user1) val accountViewsResponse = makeGetRequest(accountViewsRequest) diff --git a/obp-api/src/test/scala/code/api/v3_1_0/AccountTest.scala b/obp-api/src/test/scala/code/api/v3_1_0/AccountTest.scala index 2526199fb8..af88c2de48 100644 --- a/obp-api/src/test/scala/code/api/v3_1_0/AccountTest.scala +++ b/obp-api/src/test/scala/code/api/v3_1_0/AccountTest.scala @@ -103,10 +103,6 @@ class AccountTest extends V310ServerSetup with DefaultUsers { responsePut1.code should equal(200) responsePut1.body.extract[UpdateAccountResponseJsonV310].account_routings should be (testPutJsonWithIban.account_routings) - //for create account endpoint, we need to wait for `setAccountHolderAndRefreshUserAccountAccess` method, - //it is an asynchronous process, need some time to be done. - TimeUnit.SECONDS.sleep(2) - val responseGet1 = makeGetRequest(requestGet) And("We should get 200 and updated account routings in the getAccount response") responseGet1.code should equal(200) @@ -202,10 +198,6 @@ class AccountTest extends V310ServerSetup with DefaultUsers { val response310 = makePutRequest(request310, write(putCreateAccountJSONV310)) Then("We should get a 201") response310.code should equal(201) - //for create account endpoint, we need to wait for `setAccountHolderAndRefreshUserAccountAccess` method, - //it is an asynchronous process, need some time to be done. - TimeUnit.SECONDS.sleep(2) - val account = response310.body.extract[CreateAccountResponseJsonV310] account.product_code should be (putCreateAccountJSONV310.product_code) @@ -217,10 +209,6 @@ class AccountTest extends V310ServerSetup with DefaultUsers { account.label should be (putCreateAccountJSONV310.label) account.account_routings should be (putCreateAccountJSONV310.account_routings) - - //We need to waite some time for the account creation, because we introduce `AuthUser.refreshUser(user, callContext)` - //It may not finished when we call the get accounts directly. - TimeUnit.SECONDS.sleep(2) Then(s"we call $ApiEndpoint4 to get the account back") val requestApiEndpoint4 = (v3_1_0_Request / "my" / "accounts" ).PUT <@(user1) @@ -278,10 +266,7 @@ class AccountTest extends V310ServerSetup with DefaultUsers { val response310 = makePutRequest(request310, write(putCreateAccountJson)) Then("We should get a 201") response310.code should equal(201) - //for create account endpoint, we need to wait for `setAccountHolderAndRefreshUserAccountAccess` method, - //it is an asynchronous process, need some time to be done. - TimeUnit.SECONDS.sleep(2) - + val account = response310.body.extract[CreateAccountResponseJsonV310] account.product_code should be (putCreateAccountJson.product_code) account.`label` should be (putCreateAccountJson.`label`) @@ -308,10 +293,6 @@ class AccountTest extends V310ServerSetup with DefaultUsers { Then("We should get a 201") responseUser2_310.code should equal(201) - //for create account endpoint, we need to wait for `setAccountHolderAndRefreshUserAccountAccess` method, - //it is an asynchronous process, need some time to be done. - TimeUnit.SECONDS.sleep(2) - Then(s"we call $ApiEndpoint6 to get the account back by user2") val requestApiUser2Endpoint6 = (v3_1_0_Request /"banks" / testBankId.value / "accounts" / userAccountId / Constant.SYSTEM_OWNER_VIEW_ID/ "account" ).GET <@(user2) @@ -328,9 +309,6 @@ class AccountTest extends V310ServerSetup with DefaultUsers { Then("We should get a 201") response310_1.code should equal(201) - //for create account endpoint, we need to wait for `setAccountHolderAndRefreshUserAccountAccess` method, - //it is an asynchronous process, need some time to be done. - TimeUnit.SECONDS.sleep(2) val account = response310_1.body.extract[CreateAccountResponseJsonV310] account.product_code should be (putCreateAccountJSONV310.product_code) account.`label` should be (putCreateAccountJSONV310.`label`) diff --git a/obp-api/src/test/scala/code/api/v4_0_0/AccountAccessTest.scala b/obp-api/src/test/scala/code/api/v4_0_0/AccountAccessTest.scala index 324b7dc2f9..04c96ab466 100644 --- a/obp-api/src/test/scala/code/api/v4_0_0/AccountAccessTest.scala +++ b/obp-api/src/test/scala/code/api/v4_0_0/AccountAccessTest.scala @@ -44,9 +44,6 @@ class AccountAccessTest extends V400ServerSetup { val request400 = (v4_0_0_Request / "banks" / bankId / "accounts" ).POST <@(user1) val response400 = makePostRequest(request400, write(addAccountJson)) Then("We should get a 201") - //for create account endpoint, we need to wait for `setAccountHolderAndRefreshUserAccountAccess` method, - //it is an asynchronous process, need some time to be done. - TimeUnit.SECONDS.sleep(3) response400.code should equal(201) response400.body.extract[CreateAccountResponseJsonV310] diff --git a/obp-api/src/test/scala/code/api/v4_0_0/AccountTest.scala b/obp-api/src/test/scala/code/api/v4_0_0/AccountTest.scala index 7c1e111cb9..0a40d27eb3 100644 --- a/obp-api/src/test/scala/code/api/v4_0_0/AccountTest.scala +++ b/obp-api/src/test/scala/code/api/v4_0_0/AccountTest.scala @@ -106,10 +106,7 @@ class AccountTest extends V400ServerSetup { Then("We should get a 201") response400.code should equal(201) - //for create account endpoint, we need to wait for `setAccountHolderAndRefreshUserAccountAccess` method, - //it is an asynchronous process, need some time to be done. - TimeUnit.SECONDS.sleep(2) - + val account = response400.body.extract[CreateAccountResponseJsonV310] account.account_id should not be empty account.product_code should be (addAccountJson.product_code) @@ -121,11 +118,6 @@ class AccountTest extends V400ServerSetup { account.label should be (addAccountJson.label) account.account_routings should be (addAccountJson.account_routings) - //for create account endpoint, we need to wait for `setAccountHolderAndRefreshUserAccountAccess` method, - //it is an asynchronous process, need some time to be done. - TimeUnit.SECONDS.sleep(3) - - Then(s"We call $ApiEndpoint1 to get the account back") val request = (v4_0_0_Request /"my" / "banks" / testBankId.value/ "accounts" / account.account_id / "account").GET <@ (user1) val response = makeGetRequest(request) @@ -170,10 +162,6 @@ class AccountTest extends V400ServerSetup { Then("We should get a 201") response400_1.code should equal(201) - //for create account endpoint, we need to wait for `setAccountHolderAndRefreshUserAccountAccess` method, - //it is an asynchronous process, need some time to be done. - TimeUnit.SECONDS.sleep(2) - val account = response400_1.body.extract[CreateAccountResponseJsonV310] account.account_id should not be empty account.product_code should be (addAccountJson.product_code) diff --git a/obp-api/src/test/scala/code/api/v4_0_0/DeleteAccountCascadeTest.scala b/obp-api/src/test/scala/code/api/v4_0_0/DeleteAccountCascadeTest.scala index bf77ecf979..78eb5eba9f 100644 --- a/obp-api/src/test/scala/code/api/v4_0_0/DeleteAccountCascadeTest.scala +++ b/obp-api/src/test/scala/code/api/v4_0_0/DeleteAccountCascadeTest.scala @@ -70,10 +70,6 @@ class DeleteAccountCascadeTest extends V400ServerSetup { val account = response400.body.extract[CreateAccountResponseJsonV310] account.account_id should not be empty - //for create account endpoint, we need to wait for `setAccountHolderAndRefreshUserAccountAccess` method, - //it is an asynchronous process, need some time to be done. - TimeUnit.SECONDS.sleep(3) - val postBodyView = createViewJsonV300.copy(name = "_cascade_delete", metadata_view = "_cascade_delete", is_public = false).toCreateViewJson createViewViaEndpoint(bankId, account.account_id, postBodyView, user1) diff --git a/obp-api/src/test/scala/code/api/v4_0_0/DeleteBankCascadeTest.scala b/obp-api/src/test/scala/code/api/v4_0_0/DeleteBankCascadeTest.scala index c79ee5621c..6d65c160fa 100644 --- a/obp-api/src/test/scala/code/api/v4_0_0/DeleteBankCascadeTest.scala +++ b/obp-api/src/test/scala/code/api/v4_0_0/DeleteBankCascadeTest.scala @@ -65,10 +65,7 @@ class DeleteBankCascadeTest extends V400ServerSetup { val request400 = (v4_0_0_Request / "banks" / bankId / "accounts" ).POST <@(user1) val response400 = makePostRequest(request400, write(addAccountJson)) - //for create account endpoint, we need to wait for `setAccountHolderAndRefreshUserAccountAccess` method, - //it is an asynchronous process, need some time to be done. - TimeUnit.SECONDS.sleep(3) - + Then("We should get a 201") response400.code should equal(201) val account = response400.body.extract[CreateAccountResponseJsonV310] diff --git a/obp-api/src/test/scala/code/api/v4_0_0/SettlementAccountTest.scala b/obp-api/src/test/scala/code/api/v4_0_0/SettlementAccountTest.scala index 19b6a80d49..a7033c64ef 100644 --- a/obp-api/src/test/scala/code/api/v4_0_0/SettlementAccountTest.scala +++ b/obp-api/src/test/scala/code/api/v4_0_0/SettlementAccountTest.scala @@ -125,10 +125,6 @@ class SettlementAccountTest extends V400ServerSetup { makePostRequest((v4_0_0_Request / "banks" / testBankId.value / "settlement-accounts" ).POST <@(user1), write(createSettlementAccountJson)) makePostRequest((v4_0_0_Request / "banks" / testBankId.value / "settlement-accounts" ).POST <@(user1), write(createSettlementAccountOtherUser)) - //for create account endpoint, we need to wait for `setAccountHolderAndRefreshUserAccountAccess` method, - //it is an asynchronous process, need some time to be done. - TimeUnit.SECONDS.sleep(4) - When("We send the request") val addedEntitlement: Box[Entitlement] = Entitlement.entitlement.vend.addEntitlement(testBankId.value, resourceUser1.userId, ApiRole.CanGetSettlementAccountAtOneBank.toString) diff --git a/obp-api/src/test/scala/code/api/v4_0_0/V400ServerSetup.scala b/obp-api/src/test/scala/code/api/v4_0_0/V400ServerSetup.scala index 06dfd07671..8b42fb3599 100644 --- a/obp-api/src/test/scala/code/api/v4_0_0/V400ServerSetup.scala +++ b/obp-api/src/test/scala/code/api/v4_0_0/V400ServerSetup.scala @@ -277,9 +277,7 @@ trait V400ServerSetup extends ServerSetupWithTestData with DefaultUsers { And("We make a request v4.0.0") val request400 = (v4_0_0_Request / "banks" / bankId / "accounts" ).POST <@(consumerAndToken) val response400 = makePostRequest(request400, write(json)) - //for create account endpoint, we need to wait for `setAccountHolderAndRefreshUserAccountAccess` method, - //it is an asynchronous process, need some time to be done. - TimeUnit.SECONDS.sleep(3) + Then("We should get a 201") response400.code should equal(201) diff --git a/obp-api/src/test/scala/code/api/v5_0_0/AccountTest.scala b/obp-api/src/test/scala/code/api/v5_0_0/AccountTest.scala index a7fc8df388..c6aae646c2 100644 --- a/obp-api/src/test/scala/code/api/v5_0_0/AccountTest.scala +++ b/obp-api/src/test/scala/code/api/v5_0_0/AccountTest.scala @@ -64,10 +64,6 @@ class AccountTest extends V500ServerSetup with DefaultUsers { val response = makePutRequest(request, write(putCreateAccountJSONV310)) Then("We should get a 201") response.code should equal(201) - //for create account endpoint, we need to wait for `setAccountHolderAndRefreshUserAccountAccess` method, - //it is an asynchronous process, need some time to be done. - TimeUnit.SECONDS.sleep(2) - val account = response.body.extract[CreateAccountResponseJsonV310] account.product_code should be (putCreateAccountJSONV310.product_code) @@ -80,10 +76,6 @@ class AccountTest extends V500ServerSetup with DefaultUsers { account.account_routings should be (putCreateAccountJSONV310.account_routings) - //We need to waite some time for the account creation, because we introduce `AuthUser.refreshUser(user, callContext)` - //It may not finished when we call the get accounts directly. - TimeUnit.SECONDS.sleep(2) - Then(s"we call $ApiEndpoint4 to get the account back") val requestApiEndpoint4 = (v5_0_0_Request / "my" / "accounts" ).PUT <@(user1) val responseApiEndpoint4 = makeGetRequest(requestApiEndpoint4) @@ -141,9 +133,6 @@ class AccountTest extends V500ServerSetup with DefaultUsers { val response500 = makePutRequest(request500, write(putCreateAccountJson)) Then("We should get a 201") response500.code should equal(201) - //for create account endpoint, we need to wait for `setAccountHolderAndRefreshUserAccountAccess` method, - //it is an asynchronous process, need some time to be done. - TimeUnit.SECONDS.sleep(2) val account = response500.body.extract[CreateAccountResponseJsonV310] account.product_code should be (putCreateAccountJson.product_code) @@ -172,11 +161,6 @@ class AccountTest extends V500ServerSetup with DefaultUsers { Then("We should get a 201") responseUser2_500.code should equal(201) - //for create account endpoint, we need to wait for `setAccountHolderAndRefreshUserAccountAccess` method, - //it is an asynchronous process, need some time to be done. - TimeUnit.SECONDS.sleep(2) - - Then(s"we call $ApiEndpoint6 to get the account back by user2") val requestApiUser2Endpoint6 = (v5_0_0_Request /"banks" / testBankId.value / "accounts" / userAccountId / Constant.SYSTEM_OWNER_VIEW_ID/ "account" ).GET <@(user2) val responseApiUser2Endpoint6 = makeGetRequest(requestApiUser2Endpoint6) @@ -193,9 +177,6 @@ class AccountTest extends V500ServerSetup with DefaultUsers { Then("We should get a 201") response310_1.code should equal(201) - //for create account endpoint, we need to wait for `setAccountHolderAndRefreshUserAccountAccess` method, - //it is an asynchronous process, need some time to be done. - TimeUnit.SECONDS.sleep(2) val account = response310_1.body.extract[CreateAccountResponseJsonV310] account.product_code should be (putCreateAccountJSONV310.product_code) account.`label` should be (putCreateAccountJSONV310.`label`) From 691c2be6c24783bd939d57b057d6cf9eacd3b1be Mon Sep 17 00:00:00 2001 From: hongwei Date: Tue, 4 Jul 2023 18:25:32 +0800 Subject: [PATCH 23/41] refactor/remove `hasOwnerViewAccess` replace with specific view permissions -- remove the guard --- .../src/main/scala/code/views/MapperViews.scala | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/obp-api/src/main/scala/code/views/MapperViews.scala b/obp-api/src/main/scala/code/views/MapperViews.scala index 4255216a50..2fed1aa556 100644 --- a/obp-api/src/main/scala/code/views/MapperViews.scala +++ b/obp-api/src/main/scala/code/views/MapperViews.scala @@ -306,22 +306,9 @@ object MapperViews extends Views with MdcLoggable { /** * remove all the accountAccess for one user and linked account. - * If the user has `owner` view accountAccess and also the accountHolder, we can not revoke, just return `false`. - * all the other case, we can revoke all the account access for that user. + * we already has the guard `canRevokeAccessToAllViews` on the top level. */ - def revokeAllAccountAccess(bankId : BankId, accountId: AccountId, user : User) : Box[Boolean] = { - val userIsAccountHolder_? = MapperAccountHolders.getAccountHolders(bankId, accountId).map(h => h.userPrimaryKey).contains(user.userPrimaryKey) - val userHasOwnerViewAccess_? = AccountAccess.find( - By(AccountAccess.bank_id, bankId.value), - By(AccountAccess.account_id, accountId.value), - By(AccountAccess.view_id, SYSTEM_OWNER_VIEW_ID), - By(AccountAccess.user_fk, user.userPrimaryKey.value), - ).isDefined - - if(userIsAccountHolder_? && userHasOwnerViewAccess_?){ - Full(false) - }else{ AccountAccess.find( By(AccountAccess.bank_id, bankId.value), By(AccountAccess.account_id, accountId.value), From d238e9c41e64078babd4ad80d9879cfc8d3e9f99 Mon Sep 17 00:00:00 2001 From: hongwei Date: Tue, 4 Jul 2023 19:02:16 +0800 Subject: [PATCH 24/41] refactor/code clean --- .../dataAccess/BankAccountCreationDispatcher.scala | 12 +----------- obp-api/src/main/scala/code/views/MapperViews.scala | 13 ++++++------- 2 files changed, 7 insertions(+), 18 deletions(-) diff --git a/obp-api/src/main/scala/code/model/dataAccess/BankAccountCreationDispatcher.scala b/obp-api/src/main/scala/code/model/dataAccess/BankAccountCreationDispatcher.scala index a03dee52eb..b1548d5232 100644 --- a/obp-api/src/main/scala/code/model/dataAccess/BankAccountCreationDispatcher.scala +++ b/obp-api/src/main/scala/code/model/dataAccess/BankAccountCreationDispatcher.scala @@ -86,23 +86,13 @@ package code.model.dataAccess { * @return This is a procedure, no return value. Just use the side effect. */ def setAccountHolderAndRefreshUserAccountAccess(bankId : BankId, accountId : AccountId, user: User, callContext: Option[CallContext]) = { - // Here, we can call `addPermissionToSystemOwnerView` directly, but from now on, we try to simulate the CBS account creation. // 1st-getOrCreateAccountHolder: in this method, we only create the account holder, no view, account access involved here. AccountHolders.accountHolders.vend.getOrCreateAccountHolder(user: User, BankIdAccountId(bankId, accountId)) // 2rd-refreshUserAccountAccess: in this method, we will simulate onboarding bank user processes. @refreshUserAccountAccess definition. AuthUser.refreshUser(user, callContext) } - - private def addPermissionToSystemOwnerView(bankId : BankId, accountId : AccountId, user: User): Unit = { - Views.views.vend.getOrCreateSystemView(SYSTEM_OWNER_VIEW_ID) match { - case Full(ownerView) => - Views.views.vend.grantAccessToSystemView(bankId, accountId, ownerView, user) - case _ => - logger.debug(s"Cannot create/get system view: ${SYSTEM_OWNER_VIEW_ID}") - } - } - + } object BankAccountCreationListener extends MdcLoggable { diff --git a/obp-api/src/main/scala/code/views/MapperViews.scala b/obp-api/src/main/scala/code/views/MapperViews.scala index 2fed1aa556..77ddda8f5e 100644 --- a/obp-api/src/main/scala/code/views/MapperViews.scala +++ b/obp-api/src/main/scala/code/views/MapperViews.scala @@ -309,13 +309,12 @@ object MapperViews extends Views with MdcLoggable { * we already has the guard `canRevokeAccessToAllViews` on the top level. */ def revokeAllAccountAccess(bankId : BankId, accountId: AccountId, user : User) : Box[Boolean] = { - AccountAccess.find( - By(AccountAccess.bank_id, bankId.value), - By(AccountAccess.account_id, accountId.value), - By(AccountAccess.user_fk, user.userPrimaryKey.value) - ).foreach(_.delete_!) - Full(true) - } + AccountAccess.find( + By(AccountAccess.bank_id, bankId.value), + By(AccountAccess.account_id, accountId.value), + By(AccountAccess.user_fk, user.userPrimaryKey.value) + ).foreach(_.delete_!) + Full(true) } def revokeAccountAccessByUser(bankId : BankId, accountId: AccountId, user : User, callContext: Option[CallContext]) : Box[Boolean] = { From 961ba601b6d102cc99e89e0566e9e3893dfc1bb6 Mon Sep 17 00:00:00 2001 From: hongwei Date: Tue, 4 Jul 2023 20:00:30 +0800 Subject: [PATCH 25/41] refactor/remove `hasOwnerViewAccess` replace with specific view permissions -- remove the guard - fixed the test --- obp-api/src/test/scala/code/api/v1_2_1/API1_2_1Test.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/obp-api/src/test/scala/code/api/v1_2_1/API1_2_1Test.scala b/obp-api/src/test/scala/code/api/v1_2_1/API1_2_1Test.scala index d713f8544d..df81375fdc 100644 --- a/obp-api/src/test/scala/code/api/v1_2_1/API1_2_1Test.scala +++ b/obp-api/src/test/scala/code/api/v1_2_1/API1_2_1Test.scala @@ -2170,7 +2170,7 @@ class API1_2_1Test extends ServerSetupWithTestData with DefaultUsers with Privat And("The user should not have had his access revoked") val view = Views.views.vend.systemView(ViewId(SYSTEM_OWNER_VIEW_ID)).openOrThrowException(attemptedToOpenAnEmptyBox) - Views.views.vend.getOwners(view).toList should contain (resourceUser3) + Views.views.vend.getOwners(view).toList should not contain (resourceUser3) } } From fef2dd8795ac50acd7cec4a0348a1e8ea4cadad7 Mon Sep 17 00:00:00 2001 From: hongwei Date: Tue, 4 Jul 2023 23:12:47 +0800 Subject: [PATCH 26/41] refactor/remove `hasOwnerViewAccess` replace with specific view permissions -- rename permissions --- .../ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala | 4 ++-- .../MigrationOfViewDefinitionPermissions.scala | 12 ++++++------ .../main/scala/code/api/v1_2_1/APIMethods121.scala | 14 +++++++------- .../main/scala/code/api/v1_4_0/APIMethods140.scala | 2 ++ .../main/scala/code/api/v2_0_0/APIMethods200.scala | 10 +++++----- .../main/scala/code/api/v3_0_0/APIMethods300.scala | 2 +- .../scala/code/model/dataAccess/MappedView.scala | 8 ++++---- .../src/main/scala/code/views/MapperViews.scala | 8 ++++---- .../scala/code/views/system/ViewDefinition.scala | 12 ++++++------ .../openbankproject/commons/model/ViewModel.scala | 4 ++-- 10 files changed, 39 insertions(+), 37 deletions(-) diff --git a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala index f62080743e..d2f7d498bd 100644 --- a/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala +++ b/obp-api/src/main/scala/code/api/ResourceDocs1_4_0/SwaggerDefinitionsJSON.scala @@ -278,8 +278,8 @@ object SwaggerDefinitionsJSON { "can_create_custom_view", "can_delete_custom_view", "can_update_custom_view", - "can_see_permission_for_one_user", - "can_see_permissions_for_all_users", + "can_see_views_with_permissions_for_one_user", + "can_see_views_with_permissions_for_all_users", "can_grant_access_to_custom_views", "can_revoke_access_to_custom_views" ) diff --git a/obp-api/src/main/scala/code/api/util/migration/MigrationOfViewDefinitionPermissions.scala b/obp-api/src/main/scala/code/api/util/migration/MigrationOfViewDefinitionPermissions.scala index aaca7f5136..688de02c3b 100644 --- a/obp-api/src/main/scala/code/api/util/migration/MigrationOfViewDefinitionPermissions.scala +++ b/obp-api/src/main/scala/code/api/util/migration/MigrationOfViewDefinitionPermissions.scala @@ -27,8 +27,8 @@ object MigrationOfViewDefinitionPermissions { .canCreateCustomView_(true) .canDeleteCustomView_(true) .canUpdateCustomView_(true) - .canSeePermissionForOneUser_(true) - .canSeePermissionsForAllUsers_(true) + .canSeeViewsWithPermissionsForOneUser_(true) + .canSeeViewsWithPermissionsForAllUsers_(true) .canGrantAccessToCustomViews_(true) .canRevokeAccessToCustomViews_(true) .canGrantAccessToViews_(ALL_SYSTEM_VIEWS_CREATED_FROM_BOOT.mkString(",")) @@ -50,8 +50,8 @@ object MigrationOfViewDefinitionPermissions { .canCreateCustomView_(true) .canDeleteCustomView_(true) .canUpdateCustomView_(true) - .canSeePermissionForOneUser_(true) - .canSeePermissionsForAllUsers_(true) + .canSeeViewsWithPermissionsForOneUser_(true) + .canSeeViewsWithPermissionsForAllUsers_(true) .canGrantAccessToCustomViews_(true) .canRevokeAccessToCustomViews_(true) .canGrantAccessToViews_(ALL_SYSTEM_VIEWS_CREATED_FROM_BOOT.mkString(",")) @@ -72,8 +72,8 @@ object MigrationOfViewDefinitionPermissions { |${ViewDefinition.canCreateCustomView_.dbColumnName} |${ViewDefinition.canDeleteCustomView_.dbColumnName} |${ViewDefinition.canUpdateCustomView_.dbColumnName} - |${ViewDefinition.canSeePermissionsForAllUsers_.dbColumnName} - |${ViewDefinition.canSeePermissionForOneUser_.dbColumnName} + |${ViewDefinition.canSeeViewsWithPermissionsForAllUsers_.dbColumnName} + |${ViewDefinition.canSeeViewsWithPermissionsForOneUser_.dbColumnName} |${ViewDefinition.canGrantAccessToCustomViews_.dbColumnName} |${ViewDefinition.canRevokeAccessToCustomViews_.dbColumnName} |${ViewDefinition.canGrantAccessToViews_.dbColumnName} diff --git a/obp-api/src/main/scala/code/api/v1_2_1/APIMethods121.scala b/obp-api/src/main/scala/code/api/v1_2_1/APIMethods121.scala index 4a952d3d32..852740e076 100644 --- a/obp-api/src/main/scala/code/api/v1_2_1/APIMethods121.scala +++ b/obp-api/src/main/scala/code/api/v1_2_1/APIMethods121.scala @@ -768,11 +768,11 @@ trait APIMethods121 { for { u <- cc.user ?~ UserNotLoggedIn account <- BankAccountX(bankId, accountId) ?~! BankAccountNotFound - anyViewContainsCanSeePermissionsForAllUsersPermission = Views.views.vend.permission(BankIdAccountId(account.bankId, account.accountId), u) - .map(_.views.map(_.canSeePermissionsForAllUsers).find(_.==(true)).getOrElse(false)).getOrElse(false) + anyViewContainsCanSeeViewsWithPermissionsForAllUsersPermission = Views.views.vend.permission(BankIdAccountId(account.bankId, account.accountId), u) + .map(_.views.map(_.canSeeViewsWithPermissionsForAllUsers).find(_.==(true)).getOrElse(false)).getOrElse(false) _ <- booleanToBox( - anyViewContainsCanSeePermissionsForAllUsersPermission, - s"${ErrorMessages.CreateCustomViewError} You need the `${ViewDefinition.canSeePermissionsForAllUsers_.dbColumnName}` permission on any your views" + anyViewContainsCanSeeViewsWithPermissionsForAllUsersPermission, + s"${ErrorMessages.CreateCustomViewError} You need the `${ViewDefinition.canSeeViewsWithPermissionsForAllUsers_.dbColumnName}` permission on any your views" ) permissions = Views.views.vend.permissions(BankIdAccountId(bankId, accountId)) } yield { @@ -813,11 +813,11 @@ trait APIMethods121 { loggedInUser <- cc.user ?~ UserNotLoggedIn account <- BankAccountX(bankId, accountId) ?~! BankAccountNotFound loggedInUserPermissionBox = Views.views.vend.permission(BankIdAccountId(bankId, accountId), loggedInUser) - anyViewContainsCanSeePermissionForOneUserPermission = loggedInUserPermissionBox.map(_.views.map(_.canSeePermissionForOneUser) + anyViewContainsCanSeeViewsWithPermissionsForOneUserPermission = loggedInUserPermissionBox.map(_.views.map(_.canSeeViewsWithPermissionsForOneUser) .find(_.==(true)).getOrElse(false)).getOrElse(false) _ <- booleanToBox( - anyViewContainsCanSeePermissionForOneUserPermission, - s"${ErrorMessages.CreateCustomViewError} You need the `${ViewDefinition.canSeePermissionForOneUser_.dbColumnName}` permission on any your views" + anyViewContainsCanSeeViewsWithPermissionsForOneUserPermission, + s"${ErrorMessages.CreateCustomViewError} You need the `${ViewDefinition.canSeeViewsWithPermissionsForOneUser_.dbColumnName}` permission on any your views" ) userFromURL <- UserX.findByProviderId(provider, providerId) ?~! UserNotFoundByProviderAndProvideId permission <- Views.views.vend.permission(BankIdAccountId(bankId, accountId), userFromURL) diff --git a/obp-api/src/main/scala/code/api/v1_4_0/APIMethods140.scala b/obp-api/src/main/scala/code/api/v1_4_0/APIMethods140.scala index 651387a85e..c53b0518aa 100644 --- a/obp-api/src/main/scala/code/api/v1_4_0/APIMethods140.scala +++ b/obp-api/src/main/scala/code/api/v1_4_0/APIMethods140.scala @@ -429,6 +429,8 @@ trait APIMethods140 extends MdcLoggable with APIMethods130 with APIMethods121{ ) { view.canSeeTransactionRequestTypes } + // TODO: Consider storing allowed_transaction_request_types (List of String) in View Definition. + // TODO: This would allow us to restrict transaction request types available to the User for an Account transactionRequestTypes <- Future(Connector.connector.vend.getTransactionRequestTypes(u, fromAccount, callContext)) map { connectorEmptyResponse(_, callContext) } diff --git a/obp-api/src/main/scala/code/api/v2_0_0/APIMethods200.scala b/obp-api/src/main/scala/code/api/v2_0_0/APIMethods200.scala index e303a42638..472634188b 100644 --- a/obp-api/src/main/scala/code/api/v2_0_0/APIMethods200.scala +++ b/obp-api/src/main/scala/code/api/v2_0_0/APIMethods200.scala @@ -1011,13 +1011,13 @@ trait APIMethods200 { (Full(u), callContext) <- authenticatedAccess(cc) (_, callContext) <- NewStyle.function.getBank(bankId, callContext) (account, callContext) <- NewStyle.function.getBankAccount(bankId, accountId, callContext) - anyViewContainsCanSeePermissionsForAllUsersPermission = Views.views.vend.permission(BankIdAccountId(account.bankId, account.accountId), u) + anyViewContainsCanSeeViewsWithPermissionsForAllUsersPermission = Views.views.vend.permission(BankIdAccountId(account.bankId, account.accountId), u) .map(_.views.map(_.canUpdateBankAccountLabel).find(_.==(true)).getOrElse(false)).getOrElse(false) _ <- Helper.booleanToFuture( - s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${ViewDefinition.canSeePermissionsForAllUsers_.dbColumnName}` permission on any your views", + s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${ViewDefinition.canSeeViewsWithPermissionsForAllUsers_.dbColumnName}` permission on any your views", cc = callContext ) { - anyViewContainsCanSeePermissionsForAllUsersPermission + anyViewContainsCanSeeViewsWithPermissionsForAllUsersPermission } permissions = Views.views.vend.permissions(BankIdAccountId(bankId, accountId)) } yield { @@ -1054,11 +1054,11 @@ trait APIMethods200 { (bank, callContext) <- BankX(bankId, Some(cc)) ?~! BankNotFound // Check bank exists. account <- BankAccountX(bank.bankId, accountId) ?~! {ErrorMessages.AccountNotFound} // Check Account exists. loggedInUserPermissionBox = Views.views.vend.permission(BankIdAccountId(bankId, accountId), loggedInUser) - anyViewContainsCanSeePermissionForOneUserPermission = loggedInUserPermissionBox.map(_.views.map(_.canSeePermissionForOneUser) + anyViewContainsCanSeePermissionForOneUserPermission = loggedInUserPermissionBox.map(_.views.map(_.canSeeViewsWithPermissionsForOneUser) .find(_.==(true)).getOrElse(false)).getOrElse(false) _ <- booleanToBox( anyViewContainsCanSeePermissionForOneUserPermission, - s"${ErrorMessages.CreateCustomViewError} You need the `${ViewDefinition.canSeePermissionForOneUser_.dbColumnName}` permission on any your views" + s"${ErrorMessages.CreateCustomViewError} You need the `${ViewDefinition.canSeeViewsWithPermissionsForOneUser_.dbColumnName}` permission on any your views" ) userFromURL <- UserX.findByProviderId(provider, providerId) ?~! UserNotFoundByProviderAndProvideId permission <- Views.views.vend.permission(BankIdAccountId(bankId, accountId), userFromURL) diff --git a/obp-api/src/main/scala/code/api/v3_0_0/APIMethods300.scala b/obp-api/src/main/scala/code/api/v3_0_0/APIMethods300.scala index 392caa6687..39380a69cc 100644 --- a/obp-api/src/main/scala/code/api/v3_0_0/APIMethods300.scala +++ b/obp-api/src/main/scala/code/api/v3_0_0/APIMethods300.scala @@ -223,7 +223,7 @@ trait APIMethods300 { anyViewContainsCanSeePermissionForOneUserPermission = Views.views.vend.permission(BankIdAccountId(account.bankId, account.accountId), loggedInUser) .map(_.views.map(_.canUpdateBankAccountLabel).find(_.==(true)).getOrElse(false)).getOrElse(false) _ <- Helper.booleanToFuture( - s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${ViewDefinition.canSeePermissionForOneUser_.dbColumnName}` permission on any your views", + s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${ViewDefinition.canSeeViewsWithPermissionsForOneUser_.dbColumnName}` permission on any your views", cc = callContext ) { anyViewContainsCanSeePermissionForOneUserPermission diff --git a/obp-api/src/main/scala/code/model/dataAccess/MappedView.scala b/obp-api/src/main/scala/code/model/dataAccess/MappedView.scala index fe18582b78..b949ab4cb6 100644 --- a/obp-api/src/main/scala/code/model/dataAccess/MappedView.scala +++ b/obp-api/src/main/scala/code/model/dataAccess/MappedView.scala @@ -304,10 +304,10 @@ class ViewImpl extends View with LongKeyedMapper[ViewImpl] with ManyToMany with object canSeeBankAccountRoutingAddress_ extends MappedBoolean(this){ override def defaultValue = false } - object canSeePermissionForOneUser_ extends MappedBoolean(this){ + object canSeeViewsWithPermissionsForOneUser_ extends MappedBoolean(this){ override def defaultValue = false } - object canSeePermissionsForAllUsers_ extends MappedBoolean(this){ + object canSeeViewsWithPermissionsForAllUsers_ extends MappedBoolean(this){ override def defaultValue = false } object canSeeOtherAccountNationalIdentifier_ extends MappedBoolean(this){ @@ -520,8 +520,8 @@ class ViewImpl extends View with LongKeyedMapper[ViewImpl] with ManyToMany with def canSeeBankRoutingAddress : Boolean = canSeeBankRoutingAddress_.get def canSeeBankAccountRoutingScheme : Boolean = canSeeBankAccountRoutingScheme_.get def canSeeBankAccountRoutingAddress : Boolean = canSeeBankAccountRoutingAddress_.get - def canSeePermissionForOneUser: Boolean = canSeePermissionForOneUser_.get - def canSeePermissionsForAllUsers: Boolean = canSeePermissionsForAllUsers_.get + def canSeeViewsWithPermissionsForOneUser: Boolean = canSeeViewsWithPermissionsForOneUser_.get + def canSeeViewsWithPermissionsForAllUsers: Boolean = canSeeViewsWithPermissionsForAllUsers_.get //other bank account fields def canSeeOtherAccountNationalIdentifier : Boolean = canSeeOtherAccountNationalIdentifier_.get diff --git a/obp-api/src/main/scala/code/views/MapperViews.scala b/obp-api/src/main/scala/code/views/MapperViews.scala index 77ddda8f5e..3529379216 100644 --- a/obp-api/src/main/scala/code/views/MapperViews.scala +++ b/obp-api/src/main/scala/code/views/MapperViews.scala @@ -790,8 +790,8 @@ object MapperViews extends Views with MdcLoggable { .canCreateCustomView_(false) .canDeleteCustomView_(false) .canUpdateCustomView_(false) - .canSeePermissionForOneUser_(false) - .canSeePermissionsForAllUsers_(false) + .canSeeViewsWithPermissionsForOneUser_(false) + .canSeeViewsWithPermissionsForAllUsers_(false) .canRevokeAccessToCustomViews_(false) .canGrantAccessToCustomViews_(false) @@ -805,8 +805,8 @@ object MapperViews extends Views with MdcLoggable { .canCreateCustomView_(true) .canDeleteCustomView_(true) .canUpdateCustomView_(true) - .canSeePermissionForOneUser_(true) - .canSeePermissionsForAllUsers_(true) + .canSeeViewsWithPermissionsForOneUser_(true) + .canSeeViewsWithPermissionsForAllUsers_(true) .canRevokeAccessToCustomViews_(true) .canGrantAccessToCustomViews_(true) .canGrantAccessToViews_(ALL_SYSTEM_VIEWS_CREATED_FROM_BOOT.mkString(",")) diff --git a/obp-api/src/main/scala/code/views/system/ViewDefinition.scala b/obp-api/src/main/scala/code/views/system/ViewDefinition.scala index 6be20ae7c8..e1e53d51e8 100644 --- a/obp-api/src/main/scala/code/views/system/ViewDefinition.scala +++ b/obp-api/src/main/scala/code/views/system/ViewDefinition.scala @@ -320,10 +320,10 @@ class ViewDefinition extends View with LongKeyedMapper[ViewDefinition] with Many object canUpdateCustomView_ extends MappedBoolean(this){ override def defaultValue = false } - object canSeePermissionsForAllUsers_ extends MappedBoolean(this){ + object canSeeViewsWithPermissionsForAllUsers_ extends MappedBoolean(this){ override def defaultValue = false } - object canSeePermissionForOneUser_ extends MappedBoolean(this){ + object canSeeViewsWithPermissionsForOneUser_ extends MappedBoolean(this){ override def defaultValue = false } @@ -439,8 +439,8 @@ class ViewDefinition extends View with LongKeyedMapper[ViewDefinition] with Many canCreateCustomView_(actions.exists(_ == "can_create_custom_view")) canDeleteCustomView_(actions.exists(_ == "can_delete_custom_view")) canUpdateCustomView_(actions.exists(_ == "can_update_custom_view")) - canSeePermissionsForAllUsers_(actions.exists(_ == "can_see_permissions_for_all_users")) - canSeePermissionForOneUser_(actions.exists(_ == "can_see_permission_for_one_user")) + canSeeViewsWithPermissionsForAllUsers_(actions.exists(_ == "can_see_views_with_permissions_for_all_users")) + canSeeViewsWithPermissionsForOneUser_(actions.exists(_ == "can_see_views_with_permissions_for_one_user")) } @@ -526,8 +526,8 @@ class ViewDefinition extends View with LongKeyedMapper[ViewDefinition] with Many def canSeeBankRoutingAddress : Boolean = canSeeBankRoutingAddress_.get def canSeeBankAccountRoutingScheme : Boolean = canSeeBankAccountRoutingScheme_.get def canSeeBankAccountRoutingAddress : Boolean = canSeeBankAccountRoutingAddress_.get - def canSeePermissionForOneUser: Boolean = canSeePermissionForOneUser_.get - def canSeePermissionsForAllUsers : Boolean = canSeePermissionsForAllUsers_.get + def canSeeViewsWithPermissionsForOneUser: Boolean = canSeeViewsWithPermissionsForOneUser_.get + def canSeeViewsWithPermissionsForAllUsers : Boolean = canSeeViewsWithPermissionsForAllUsers_.get //other bank account fields def canSeeOtherAccountNationalIdentifier : Boolean = canSeeOtherAccountNationalIdentifier_.get diff --git a/obp-commons/src/main/scala/com/openbankproject/commons/model/ViewModel.scala b/obp-commons/src/main/scala/com/openbankproject/commons/model/ViewModel.scala index 9000dd9921..6f760e071c 100644 --- a/obp-commons/src/main/scala/com/openbankproject/commons/model/ViewModel.scala +++ b/obp-commons/src/main/scala/com/openbankproject/commons/model/ViewModel.scala @@ -327,9 +327,9 @@ trait View { def canSeeBankAccountRoutingAddress: Boolean - def canSeePermissionForOneUser: Boolean + def canSeeViewsWithPermissionsForOneUser: Boolean - def canSeePermissionsForAllUsers: Boolean + def canSeeViewsWithPermissionsForAllUsers: Boolean //other bank account (counterparty) fields def canSeeOtherAccountNationalIdentifier: Boolean From 6cbdb450496369dbda4f35dbad515c3e08990ed1 Mon Sep 17 00:00:00 2001 From: hongwei Date: Wed, 5 Jul 2023 19:05:43 +0800 Subject: [PATCH 27/41] feature/added the extra error message for i18n --- obp-api/src/main/scala/code/api/OBPRestHelper.scala | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/obp-api/src/main/scala/code/api/OBPRestHelper.scala b/obp-api/src/main/scala/code/api/OBPRestHelper.scala index 45ad8e18d9..6199d42299 100644 --- a/obp-api/src/main/scala/code/api/OBPRestHelper.scala +++ b/obp-api/src/main/scala/code/api/OBPRestHelper.scala @@ -145,8 +145,17 @@ case class APIFailureNewStyle(failMsg: String, locale, if(locale.toString.startsWith("en") || ?!(str, resourceBundleList)==str) //If can not find the value from props or the local is `en`, then return errorBody - else - s": ${?!(str, resourceBundleList)}" + else { + val originalErrorMessageFromScalaCode = ErrorMessages.getValueMatches(_.startsWith(errorCode)).getOrElse("") + // we need to keep the extra message, + // eg: OBP-20006: usuario le faltan uno o más roles': CanGetUserInvitation for BankId(gh.29.uk). + if(failMsg.contains(originalErrorMessageFromScalaCode)){ + s": ${?!(str, resourceBundleList)}"+failMsg.replace(originalErrorMessageFromScalaCode,"") + } else{ + s": ${?!(str, resourceBundleList)}" + } + } + ) val translatedErrorBody = ?(errorCode, locale) From 0d4d00d0c6383065989c77214a504c3ef2fb10eb Mon Sep 17 00:00:00 2001 From: hongwei Date: Thu, 6 Jul 2023 21:16:54 +0800 Subject: [PATCH 28/41] refactor/remove `hasOwnerViewAccess` replace with specific view permissions -- tweaked the customViews --- obp-api/src/main/scala/bootstrap/liftweb/Boot.scala | 2 ++ .../src/main/scala/code/api/constant/constant.scala | 1 + .../MigrationOfViewDefinitionPermissions.scala | 12 ++++++------ .../main/scala/code/api/v1_2_1/APIMethods121.scala | 4 ++-- obp-api/src/main/scala/code/views/MapperViews.scala | 11 ++++++++--- .../openbankproject/commons/model/ViewModel.scala | 1 + 6 files changed, 20 insertions(+), 11 deletions(-) diff --git a/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala b/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala index 488eafe8de..71890a42f1 100644 --- a/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala +++ b/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala @@ -760,6 +760,7 @@ class Boot extends MdcLoggable { val accountant = Views.views.vend.getOrCreateSystemView(SYSTEM_ACCOUNTANT_VIEW_ID).isDefined val standard = Views.views.vend.getOrCreateSystemView(SYSTEM_STANDARD_VIEW_ID).isDefined val stageOne = Views.views.vend.getOrCreateSystemView(SYSTEM_STAGE_ONE_VIEW_ID).isDefined + val enableCustomViews = Views.views.vend.getOrCreateSystemView(SYSTEM_ENABLE_CUSTOM_VIEWS_VIEW_ID).isDefined // Only create Firehose view if they are enabled at instance. val accountFirehose = if (ApiPropsWithAlias.allowAccountFirehose) Views.views.vend.getOrCreateSystemView(SYSTEM_FIREHOSE_VIEW_ID).isDefined @@ -773,6 +774,7 @@ class Boot extends MdcLoggable { |System view ${SYSTEM_FIREHOSE_VIEW_ID} exists/created at the instance: ${accountFirehose} |System view ${SYSTEM_STANDARD_VIEW_ID} exists/created at the instance: ${standard} |System view ${SYSTEM_STAGE_ONE_VIEW_ID} exists/created at the instance: ${stageOne} + |System view ${SYSTEM_ENABLE_CUSTOM_VIEWS_VIEW_ID} exists/created at the instance: ${enableCustomViews} |""".stripMargin logger.info(comment) diff --git a/obp-api/src/main/scala/code/api/constant/constant.scala b/obp-api/src/main/scala/code/api/constant/constant.scala index 45cbfec426..fbe91fcc8a 100644 --- a/obp-api/src/main/scala/code/api/constant/constant.scala +++ b/obp-api/src/main/scala/code/api/constant/constant.scala @@ -29,6 +29,7 @@ object Constant extends MdcLoggable { final val SYSTEM_FIREHOSE_VIEW_ID = "firehose" final val SYSTEM_STANDARD_VIEW_ID = "standard" final val SYSTEM_STAGE_ONE_VIEW_ID = "StageOne" + final val SYSTEM_ENABLE_CUSTOM_VIEWS_VIEW_ID = "EnableCustomViews" final val SYSTEM_READ_ACCOUNTS_BASIC_VIEW_ID = "ReadAccountsBasic" final val SYSTEM_READ_ACCOUNTS_DETAIL_VIEW_ID = "ReadAccountsDetail" final val SYSTEM_READ_BALANCES_VIEW_ID = "ReadBalances" diff --git a/obp-api/src/main/scala/code/api/util/migration/MigrationOfViewDefinitionPermissions.scala b/obp-api/src/main/scala/code/api/util/migration/MigrationOfViewDefinitionPermissions.scala index 688de02c3b..181e7f0a9a 100644 --- a/obp-api/src/main/scala/code/api/util/migration/MigrationOfViewDefinitionPermissions.scala +++ b/obp-api/src/main/scala/code/api/util/migration/MigrationOfViewDefinitionPermissions.scala @@ -24,9 +24,9 @@ object MigrationOfViewDefinitionPermissions { .canSeeTransactionRequests_(true) .canSeeAvailableViewsForBankAccount_(true) .canUpdateBankAccountLabel_(true) - .canCreateCustomView_(true) - .canDeleteCustomView_(true) - .canUpdateCustomView_(true) + .canCreateCustomView_(false) + .canDeleteCustomView_(false) + .canUpdateCustomView_(false) .canSeeViewsWithPermissionsForOneUser_(true) .canSeeViewsWithPermissionsForAllUsers_(true) .canGrantAccessToCustomViews_(true) @@ -47,9 +47,9 @@ object MigrationOfViewDefinitionPermissions { .canSeeTransactionRequests_(true) .canSeeAvailableViewsForBankAccount_(true) .canUpdateBankAccountLabel_(true) - .canCreateCustomView_(true) - .canDeleteCustomView_(true) - .canUpdateCustomView_(true) + .canCreateCustomView_(false) + .canDeleteCustomView_(false) + .canUpdateCustomView_(false) .canSeeViewsWithPermissionsForOneUser_(true) .canSeeViewsWithPermissionsForAllUsers_(true) .canGrantAccessToCustomViews_(true) diff --git a/obp-api/src/main/scala/code/api/v1_2_1/APIMethods121.scala b/obp-api/src/main/scala/code/api/v1_2_1/APIMethods121.scala index 852740e076..ef66248f30 100644 --- a/obp-api/src/main/scala/code/api/v1_2_1/APIMethods121.scala +++ b/obp-api/src/main/scala/code/api/v1_2_1/APIMethods121.scala @@ -683,10 +683,10 @@ trait APIMethods121 { hide_metadata_if_alias_used = updateJsonV121.hide_metadata_if_alias_used, allowed_actions = updateJsonV121.allowed_actions ) - anyViewContainsCancanUpdateCustomViewPermission = Views.views.vend.permission(BankIdAccountId(account.bankId, account.accountId), u) + anyViewContainsCanUpdateCustomViewPermission = Views.views.vend.permission(BankIdAccountId(account.bankId, account.accountId), u) .map(_.views.map(_.canUpdateCustomView).find(_.==(true)).getOrElse(false)).getOrElse(false) _ <- booleanToBox( - anyViewContainsCancanUpdateCustomViewPermission, + anyViewContainsCanUpdateCustomViewPermission, s"${ErrorMessages.CreateCustomViewError} You need the `${ViewDefinition.canUpdateCustomView_.dbColumnName}` permission on any your views" ) updatedView <- Views.views.vend.updateCustomView(BankIdAccountId(bankId, accountId),viewId, updateViewJson) ?~ CreateCustomViewError diff --git a/obp-api/src/main/scala/code/views/MapperViews.scala b/obp-api/src/main/scala/code/views/MapperViews.scala index 3529379216..3e5433b2b0 100644 --- a/obp-api/src/main/scala/code/views/MapperViews.scala +++ b/obp-api/src/main/scala/code/views/MapperViews.scala @@ -794,6 +794,9 @@ object MapperViews extends Views with MdcLoggable { .canSeeViewsWithPermissionsForAllUsers_(false) .canRevokeAccessToCustomViews_(false) .canGrantAccessToCustomViews_(false) + .canCreateCustomView_(false) + .canDeleteCustomView_(false) + .canUpdateCustomView_(false) viewId match { case SYSTEM_OWNER_VIEW_ID | SYSTEM_STANDARD_VIEW_ID => @@ -802,9 +805,6 @@ object MapperViews extends Views with MdcLoggable { .canSeeTransactionRequests_(true) .canSeeTransactionRequestTypes_(true) .canUpdateBankAccountLabel_(true) - .canCreateCustomView_(true) - .canDeleteCustomView_(true) - .canUpdateCustomView_(true) .canSeeViewsWithPermissionsForOneUser_(true) .canSeeViewsWithPermissionsForAllUsers_(true) .canRevokeAccessToCustomViews_(true) @@ -815,6 +815,11 @@ object MapperViews extends Views with MdcLoggable { entity .canSeeTransactionDescription_(false) .canAddTransactionRequestToAnyAccount_(false) + case SYSTEM_ENABLE_CUSTOM_VIEWS_VIEW_ID => + entity + .canCreateCustomView_(true) + .canDeleteCustomView_(true) + .canUpdateCustomView_(true) case SYSTEM_FIREHOSE_VIEW_ID => entity .isFirehose_(true) diff --git a/obp-commons/src/main/scala/com/openbankproject/commons/model/ViewModel.scala b/obp-commons/src/main/scala/com/openbankproject/commons/model/ViewModel.scala index 6f760e071c..ad50663c52 100644 --- a/obp-commons/src/main/scala/com/openbankproject/commons/model/ViewModel.scala +++ b/obp-commons/src/main/scala/com/openbankproject/commons/model/ViewModel.scala @@ -428,6 +428,7 @@ trait View { def canCreateStandingOrder: Boolean + //If any view set these to true, you can create/delete/update the custom view def canCreateCustomView: Boolean def canDeleteCustomView: Boolean def canUpdateCustomView: Boolean From fc7e96200593947e763f007f56a25e690c3c72dd Mon Sep 17 00:00:00 2001 From: hongwei Date: Thu, 6 Jul 2023 23:52:12 +0800 Subject: [PATCH 29/41] refactor/remove `hasOwnerViewAccess` replace with specific view permissions -- tweaked the customViews-fixed tests --- .../main/scala/code/api/constant/constant.scala | 1 + .../src/main/scala/code/api/util/APIUtil.scala | 2 +- .../MigrationOfViewDefinitionPermissions.scala | 16 ++++++++-------- .../src/main/scala/code/views/MapperViews.scala | 4 ++-- .../scala/code/setup/TestConnectorSetup.scala | 4 +++- 5 files changed, 15 insertions(+), 12 deletions(-) diff --git a/obp-api/src/main/scala/code/api/constant/constant.scala b/obp-api/src/main/scala/code/api/constant/constant.scala index fbe91fcc8a..6270315832 100644 --- a/obp-api/src/main/scala/code/api/constant/constant.scala +++ b/obp-api/src/main/scala/code/api/constant/constant.scala @@ -49,6 +49,7 @@ object Constant extends MdcLoggable { SYSTEM_FIREHOSE_VIEW_ID, SYSTEM_STANDARD_VIEW_ID, SYSTEM_STAGE_ONE_VIEW_ID, + SYSTEM_ENABLE_CUSTOM_VIEWS_VIEW_ID, SYSTEM_READ_ACCOUNTS_BASIC_VIEW_ID, SYSTEM_READ_ACCOUNTS_DETAIL_VIEW_ID, SYSTEM_READ_BALANCES_VIEW_ID, diff --git a/obp-api/src/main/scala/code/api/util/APIUtil.scala b/obp-api/src/main/scala/code/api/util/APIUtil.scala index 0f58f45cdc..a5ded1d9e3 100644 --- a/obp-api/src/main/scala/code/api/util/APIUtil.scala +++ b/obp-api/src/main/scala/code/api/util/APIUtil.scala @@ -4123,7 +4123,7 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{ val permissionBox = Views.views.vend.permission(BankIdAccountId(bankId, accountId), user) //check if we can revoke all systemViews Access - val allCanRevokeAccessToViewsPermissions: List[String] = permissionBox.map(_.views.filter(_.canRevokeAccessToCustomViews).map(_.canRevokeAccessToViews.getOrElse(Nil)).flatten).getOrElse(Nil).distinct + val allCanRevokeAccessToViewsPermissions: List[String] = permissionBox.map(_.views.map(_.canRevokeAccessToViews.getOrElse(Nil)).flatten).getOrElse(Nil).distinct val allAccountAccessSystemViews: List[String] = permissionBox.map(_.views.map(_.viewId.value)).getOrElse(Nil).distinct.filter(checkSystemViewIdOrName) val canRevokeAccessToAllSystemViews = allAccountAccessSystemViews.forall(allCanRevokeAccessToViewsPermissions.contains) diff --git a/obp-api/src/main/scala/code/api/util/migration/MigrationOfViewDefinitionPermissions.scala b/obp-api/src/main/scala/code/api/util/migration/MigrationOfViewDefinitionPermissions.scala index 181e7f0a9a..5711385c86 100644 --- a/obp-api/src/main/scala/code/api/util/migration/MigrationOfViewDefinitionPermissions.scala +++ b/obp-api/src/main/scala/code/api/util/migration/MigrationOfViewDefinitionPermissions.scala @@ -24,13 +24,13 @@ object MigrationOfViewDefinitionPermissions { .canSeeTransactionRequests_(true) .canSeeAvailableViewsForBankAccount_(true) .canUpdateBankAccountLabel_(true) + .canSeeViewsWithPermissionsForOneUser_(true) + .canSeeViewsWithPermissionsForAllUsers_(true) .canCreateCustomView_(false) .canDeleteCustomView_(false) .canUpdateCustomView_(false) - .canSeeViewsWithPermissionsForOneUser_(true) - .canSeeViewsWithPermissionsForAllUsers_(true) - .canGrantAccessToCustomViews_(true) - .canRevokeAccessToCustomViews_(true) + .canGrantAccessToCustomViews_(false) + .canRevokeAccessToCustomViews_(false) .canGrantAccessToViews_(ALL_SYSTEM_VIEWS_CREATED_FROM_BOOT.mkString(",")) .canRevokeAccessToViews_(ALL_SYSTEM_VIEWS_CREATED_FROM_BOOT.mkString(",")) .save @@ -47,13 +47,13 @@ object MigrationOfViewDefinitionPermissions { .canSeeTransactionRequests_(true) .canSeeAvailableViewsForBankAccount_(true) .canUpdateBankAccountLabel_(true) + .canSeeViewsWithPermissionsForOneUser_(true) + .canSeeViewsWithPermissionsForAllUsers_(true) .canCreateCustomView_(false) .canDeleteCustomView_(false) .canUpdateCustomView_(false) - .canSeeViewsWithPermissionsForOneUser_(true) - .canSeeViewsWithPermissionsForAllUsers_(true) - .canGrantAccessToCustomViews_(true) - .canRevokeAccessToCustomViews_(true) + .canGrantAccessToCustomViews_(false) + .canRevokeAccessToCustomViews_(false) .canGrantAccessToViews_(ALL_SYSTEM_VIEWS_CREATED_FROM_BOOT.mkString(",")) .canRevokeAccessToViews_(ALL_SYSTEM_VIEWS_CREATED_FROM_BOOT.mkString(",")) .save diff --git a/obp-api/src/main/scala/code/views/MapperViews.scala b/obp-api/src/main/scala/code/views/MapperViews.scala index 3e5433b2b0..7456b7c149 100644 --- a/obp-api/src/main/scala/code/views/MapperViews.scala +++ b/obp-api/src/main/scala/code/views/MapperViews.scala @@ -807,8 +807,6 @@ object MapperViews extends Views with MdcLoggable { .canUpdateBankAccountLabel_(true) .canSeeViewsWithPermissionsForOneUser_(true) .canSeeViewsWithPermissionsForAllUsers_(true) - .canRevokeAccessToCustomViews_(true) - .canGrantAccessToCustomViews_(true) .canGrantAccessToViews_(ALL_SYSTEM_VIEWS_CREATED_FROM_BOOT.mkString(",")) .canRevokeAccessToViews_(ALL_SYSTEM_VIEWS_CREATED_FROM_BOOT.mkString(",")) case SYSTEM_STAGE_ONE_VIEW_ID => @@ -817,6 +815,8 @@ object MapperViews extends Views with MdcLoggable { .canAddTransactionRequestToAnyAccount_(false) case SYSTEM_ENABLE_CUSTOM_VIEWS_VIEW_ID => entity + .canRevokeAccessToCustomViews_(true) + .canGrantAccessToCustomViews_(true) .canCreateCustomView_(true) .canDeleteCustomView_(true) .canUpdateCustomView_(true) diff --git a/obp-api/src/test/scala/code/setup/TestConnectorSetup.scala b/obp-api/src/test/scala/code/setup/TestConnectorSetup.scala index 04d44ca309..c77a048e1e 100644 --- a/obp-api/src/test/scala/code/setup/TestConnectorSetup.scala +++ b/obp-api/src/test/scala/code/setup/TestConnectorSetup.scala @@ -2,7 +2,7 @@ package code.setup import java.util.{Calendar, Date} import code.accountholders.AccountHolders -import code.api.Constant.{SYSTEM_ACCOUNTANT_VIEW_ID, SYSTEM_AUDITOR_VIEW_ID, SYSTEM_FIREHOSE_VIEW_ID, SYSTEM_OWNER_VIEW_ID} +import code.api.Constant.{SYSTEM_ACCOUNTANT_VIEW_ID, SYSTEM_AUDITOR_VIEW_ID, SYSTEM_ENABLE_CUSTOM_VIEWS_VIEW_ID, SYSTEM_FIREHOSE_VIEW_ID, SYSTEM_OWNER_VIEW_ID} import code.api.util.ErrorMessages.attemptedToOpenAnEmptyBox import code.api.util.{APIUtil, OBPLimit, OBPOffset} import code.bankconnectors.{Connector, LocalMappedConnector} @@ -72,12 +72,14 @@ trait TestConnectorSetup { val systemAuditorView = getOrCreateSystemView(SYSTEM_AUDITOR_VIEW_ID) val systemAccountantView = getOrCreateSystemView(SYSTEM_ACCOUNTANT_VIEW_ID) val systemFirehoseView = getOrCreateSystemView(SYSTEM_FIREHOSE_VIEW_ID) + val enableCustomViews = getOrCreateSystemView(SYSTEM_ENABLE_CUSTOM_VIEWS_VIEW_ID) accounts.foreach(account => { Views.views.vend.grantAccessToSystemView(account.bankId, account.accountId, systemOwnerView, user) Views.views.vend.grantAccessToSystemView(account.bankId, account.accountId, systemAuditorView, user) Views.views.vend.grantAccessToSystemView(account.bankId, account.accountId, systemAccountantView, user) Views.views.vend.grantAccessToSystemView(account.bankId, account.accountId, systemFirehoseView, user) + Views.views.vend.grantAccessToSystemView(account.bankId, account.accountId, enableCustomViews, user) val customPublicView = createPublicView(account.bankId, account.accountId) Views.views.vend.grantAccessToCustomView(customPublicView.uid, user) From 053fadcc30b5d0782a81346b747f6901689c8c6d Mon Sep 17 00:00:00 2001 From: hongwei Date: Fri, 7 Jul 2023 23:45:46 +0800 Subject: [PATCH 30/41] refactor/remove `hasOwnerViewAccess` replace with specific view permissions -- tweaked the customViews-fixed tests-step2 --- .../main/scala/code/api/util/APIUtil.scala | 34 ++++++++++++------- .../scala/code/api/util/ErrorMessages.scala | 9 ++++- .../bankconnectors/LocalMappedConnector.scala | 6 ++-- .../main/scala/code/views/MapperViews.scala | 3 ++ .../scala/code/api/v1_2_1/API1_2_1Test.scala | 6 ++-- 5 files changed, 39 insertions(+), 19 deletions(-) diff --git a/obp-api/src/main/scala/code/api/util/APIUtil.scala b/obp-api/src/main/scala/code/api/util/APIUtil.scala index a5ded1d9e3..932b6ab9c2 100644 --- a/obp-api/src/main/scala/code/api/util/APIUtil.scala +++ b/obp-api/src/main/scala/code/api/util/APIUtil.scala @@ -4092,12 +4092,17 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{ val allSystemViewsAccessTobeGranted: List[String] = viewIdsTobeGranted.map(_.value).distinct.filter(checkSystemViewIdOrName) val canGrantAccessToAllSystemViews = allSystemViewsAccessTobeGranted.forall(allCanGrantAccessToViewsPermissions.contains) - //check if we can grant all customViews Access - val allCanGrantAccessToCustomViewsPermissions: List[Boolean] = permissionBox.map(_.views.map(_.canGrantAccessToCustomViews)).getOrElse(Nil) - val canGrantAccessToAllCustomViews = allCanGrantAccessToCustomViewsPermissions.contains(true) - - //we need merge both system and custom access - canGrantAccessToAllSystemViews && canGrantAccessToAllCustomViews + if (allSystemViewsAccessTobeGranted.find(checkCustomViewIdOrName).isDefined){ + //check if we can grant all customViews Access + val allCanGrantAccessToCustomViewsPermissions: List[Boolean] = permissionBox.map(_.views.map(_.canGrantAccessToCustomViews)).getOrElse(Nil) + val canGrantAccessToAllCustomViews = allCanGrantAccessToCustomViewsPermissions.contains(true) + //we need merge both system and custom access + canGrantAccessToAllSystemViews && canGrantAccessToAllCustomViews + } else if (allSystemViewsAccessTobeGranted.find(checkSystemViewIdOrName).isDefined) { + canGrantAccessToAllSystemViews + } else { + false + } } def canRevokeAccessToView(bankId: BankId, accountId: AccountId, viewIdToBeRevoked : ViewId, user: User, callContext: Option[CallContext]): Boolean = { @@ -4127,12 +4132,17 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{ val allAccountAccessSystemViews: List[String] = permissionBox.map(_.views.map(_.viewId.value)).getOrElse(Nil).distinct.filter(checkSystemViewIdOrName) val canRevokeAccessToAllSystemViews = allAccountAccessSystemViews.forall(allCanRevokeAccessToViewsPermissions.contains) - //check if we can revoke all customViews Access - val allCanRevokeAccessToCustomViewsPermissions: List[Boolean] = permissionBox.map(_.views.map(_.canRevokeAccessToCustomViews)).getOrElse(Nil) - val canRevokeAccessToAllCustomViews = allCanRevokeAccessToCustomViewsPermissions.contains(true) - - //we need merge both system and custom access - canRevokeAccessToAllSystemViews && canRevokeAccessToAllCustomViews + if (allAccountAccessSystemViews.find(checkCustomViewIdOrName).isDefined){ + //check if we can revoke all customViews Access + val allCanRevokeAccessToCustomViewsPermissions: List[Boolean] = permissionBox.map(_.views.map(_.canRevokeAccessToCustomViews)).getOrElse(Nil) + val canRevokeAccessToAllCustomViews = allCanRevokeAccessToCustomViewsPermissions.contains(true) + //we need merge both system and custom access + canRevokeAccessToAllSystemViews && canRevokeAccessToAllCustomViews + }else if(allAccountAccessSystemViews.find(checkSystemViewIdOrName).isDefined){ + canRevokeAccessToAllSystemViews + }else{ + false + } } diff --git a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala index c08d95656f..7188203ce2 100644 --- a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala +++ b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala @@ -298,7 +298,14 @@ object ErrorMessages { val CreateCardError = "OBP-30032: Could not insert the Card" val UpdateCardError = "OBP-30033: Could not update the Card" - val ViewIdNotSupported = "OBP-30034: This ViewId is not supported. Only support four now: Owner, Accountant, Auditor, StageOne, Standard, _Public." + val ViewIdNotSupported = s"OBP-30034: This ViewId is not supported. Only support four now: " + + s"$SYSTEM_OWNER_VIEW_ID, " + + s"$SYSTEM_ACCOUNTANT_VIEW_ID, " + + s"$SYSTEM_AUDITOR_VIEW_ID, " + + s"$SYSTEM_STAGE_ONE_VIEW_ID, " + + s"$SYSTEM_STANDARD_VIEW_ID, " + + s"$SYSTEM_ENABLE_CUSTOM_VIEWS_VIEW_ID, " + + s"$CUSTOM_PUBLIC_VIEW_ID." val UserCustomerLinkNotFound = "OBP-30035: User Customer Link not found" diff --git a/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala b/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala index c3e1a1fed7..8e38d213cf 100644 --- a/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala +++ b/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala @@ -10,11 +10,11 @@ import code.accountattribute.AccountAttributeX import code.accountholders.{AccountHolders, MapperAccountHolders} import code.api.BerlinGroup.{AuthenticationType, ScaStatus} import code.api.Constant -import code.api.Constant.{INCOMING_SETTLEMENT_ACCOUNT_ID, OUTGOING_SETTLEMENT_ACCOUNT_ID, SYSTEM_ACCOUNTANT_VIEW_ID, SYSTEM_AUDITOR_VIEW_ID, SYSTEM_OWNER_VIEW_ID, localIdentityProvider} +import code.api.Constant.{INCOMING_SETTLEMENT_ACCOUNT_ID, OUTGOING_SETTLEMENT_ACCOUNT_ID, SYSTEM_ACCOUNTANT_VIEW_ID, SYSTEM_AUDITOR_VIEW_ID, SYSTEM_ENABLE_CUSTOM_VIEWS_VIEW_ID, SYSTEM_OWNER_VIEW_ID, localIdentityProvider} import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON import code.api.attributedefinition.{AttributeDefinition, AttributeDefinitionDI} import code.api.cache.Caching -import code.api.util.APIUtil.{DateWithMsFormat, OBPReturnType, generateUUID, hasEntitlement, isValidCurrencyISOCode, saveConnectorMetric, stringOrNull, unboxFullOrFail} +import code.api.util.APIUtil._ import code.api.util.ApiRole.canCreateAnyTransactionRequest import code.api.util.ErrorMessages.{attemptedToOpenAnEmptyBox, _} import code.api.util._ @@ -555,7 +555,7 @@ object LocalMappedConnector extends Connector with MdcLoggable { */ override def getBankAccountsForUserLegacy(provider: String, username:String, callContext: Option[CallContext]): Box[(List[InboundAccount], Option[CallContext])] = { //1st: get the accounts from userAuthContext - val viewsToGenerate = List("owner") //TODO, so far only set the `owner` view, later need to simulate other views. + val viewsToGenerate = List(SYSTEM_ENABLE_CUSTOM_VIEWS_VIEW_ID,SYSTEM_OWNER_VIEW_ID) //TODO, so far only set the `owner` view, later need to simulate other views. val user = Users.users.vend.getUserByProviderId(provider, username).getOrElse(throw new RuntimeException(s"$RefreshUserError at getBankAccountsForUserLegacy($username, ${callContext})")) val userId = user.userId tryo{net.liftweb.common.Logger(this.getClass).debug(s"getBankAccountsForUser.user says: provider($provider), username($username)")} diff --git a/obp-api/src/main/scala/code/views/MapperViews.scala b/obp-api/src/main/scala/code/views/MapperViews.scala index 7456b7c149..5d5d80c40e 100644 --- a/obp-api/src/main/scala/code/views/MapperViews.scala +++ b/obp-api/src/main/scala/code/views/MapperViews.scala @@ -602,6 +602,7 @@ object MapperViews extends Views with MdcLoggable { val auditorsView = SYSTEM_AUDITOR_VIEW_ID.equals(viewId.toLowerCase) val standardView = SYSTEM_STANDARD_VIEW_ID.equals(viewId.toLowerCase) val stageOneView = SYSTEM_STAGE_ONE_VIEW_ID.toLowerCase.equals(viewId.toLowerCase) + val enableCustomViews = SYSTEM_ENABLE_CUSTOM_VIEWS_VIEW_ID.toLowerCase.equals(viewId.toLowerCase) val theView = if (ownerView) @@ -614,6 +615,8 @@ object MapperViews extends Views with MdcLoggable { getOrCreateSystemView(SYSTEM_STANDARD_VIEW_ID) else if (stageOneView) getOrCreateSystemView(SYSTEM_STAGE_ONE_VIEW_ID) + else if (enableCustomViews) + getOrCreateSystemView(SYSTEM_ENABLE_CUSTOM_VIEWS_VIEW_ID) else { logger.error(ViewIdNotSupported+ s"Your input viewId is :$viewId") Failure(ViewIdNotSupported+ s"Your input viewId is :$viewId") diff --git a/obp-api/src/test/scala/code/api/v1_2_1/API1_2_1Test.scala b/obp-api/src/test/scala/code/api/v1_2_1/API1_2_1Test.scala index df81375fdc..e11ff4bab8 100644 --- a/obp-api/src/test/scala/code/api/v1_2_1/API1_2_1Test.scala +++ b/obp-api/src/test/scala/code/api/v1_2_1/API1_2_1Test.scala @@ -31,6 +31,7 @@ import _root_.net.liftweb.json.Serialization.write import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON import code.api.util.APIUtil import code.api.util.APIUtil.OAuth._ +import code.api.util.APIUtil.checkSystemViewIdOrName import code.bankconnectors.Connector import code.setup.{APIResponse, DefaultUsers, PrivateUser2AccountsAndSetUpWithTestData, ServerSetupWithTestData} import code.views.Views @@ -164,9 +165,7 @@ class API1_2_1Test extends ServerSetupWithTestData with DefaultUsers with Privat val reply = makeGetRequest(request) val possibleViewsPermalinks = reply.body.extract[ViewsJSONV121].views .filterNot(_.is_public==true) - .filterNot(_.id.contains(SYSTEM_OWNER_VIEW_ID)) - .filterNot(_.id.contains(SYSTEM_AUDITOR_VIEW_ID)) - .filterNot(_.id.contains(SYSTEM_ACCOUNTANT_VIEW_ID)) + .filterNot(view=> checkSystemViewIdOrName(view.id)) val randomPosition = nextInt(possibleViewsPermalinks.size) possibleViewsPermalinks(randomPosition).id } @@ -183,6 +182,7 @@ class API1_2_1Test extends ServerSetupWithTestData with DefaultUsers with Privat .filterNot(_.id.contains(SYSTEM_AUDITOR_VIEW_ID)) .filterNot(_.id.contains(SYSTEM_ACCOUNTANT_VIEW_ID)) .filterNot(_.id.contains(SYSTEM_FIREHOSE_VIEW_ID)) + .filterNot(_.id.contains(SYSTEM_ENABLE_CUSTOM_VIEWS_VIEW_ID)) val randomPosition = nextInt(possibleViewsPermalinksWithoutOwner.size) possibleViewsPermalinksWithoutOwner(randomPosition).id } From d941502b8516ff3f65e3700c909620db3de7fa65 Mon Sep 17 00:00:00 2001 From: hongwei Date: Sat, 8 Jul 2023 00:53:56 +0800 Subject: [PATCH 31/41] refactor/remove `hasOwnerViewAccess` replace with specific view permissions -- tweaked the customViews-fixed tests-step3 --- obp-api/src/main/scala/code/api/util/APIUtil.scala | 6 ++---- .../test/scala/code/api/v1_2_1/API1_2_1Test.scala | 12 +++++++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/obp-api/src/main/scala/code/api/util/APIUtil.scala b/obp-api/src/main/scala/code/api/util/APIUtil.scala index 932b6ab9c2..bd648135f5 100644 --- a/obp-api/src/main/scala/code/api/util/APIUtil.scala +++ b/obp-api/src/main/scala/code/api/util/APIUtil.scala @@ -4092,16 +4092,14 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{ val allSystemViewsAccessTobeGranted: List[String] = viewIdsTobeGranted.map(_.value).distinct.filter(checkSystemViewIdOrName) val canGrantAccessToAllSystemViews = allSystemViewsAccessTobeGranted.forall(allCanGrantAccessToViewsPermissions.contains) - if (allSystemViewsAccessTobeGranted.find(checkCustomViewIdOrName).isDefined){ + if (viewIdsTobeGranted.map(_.value).distinct.find(checkCustomViewIdOrName).isDefined){ //check if we can grant all customViews Access val allCanGrantAccessToCustomViewsPermissions: List[Boolean] = permissionBox.map(_.views.map(_.canGrantAccessToCustomViews)).getOrElse(Nil) val canGrantAccessToAllCustomViews = allCanGrantAccessToCustomViewsPermissions.contains(true) //we need merge both system and custom access canGrantAccessToAllSystemViews && canGrantAccessToAllCustomViews - } else if (allSystemViewsAccessTobeGranted.find(checkSystemViewIdOrName).isDefined) { - canGrantAccessToAllSystemViews } else { - false + canGrantAccessToAllSystemViews } } diff --git a/obp-api/src/test/scala/code/api/v1_2_1/API1_2_1Test.scala b/obp-api/src/test/scala/code/api/v1_2_1/API1_2_1Test.scala index e11ff4bab8..fee2c180b0 100644 --- a/obp-api/src/test/scala/code/api/v1_2_1/API1_2_1Test.scala +++ b/obp-api/src/test/scala/code/api/v1_2_1/API1_2_1Test.scala @@ -1995,16 +1995,18 @@ class API1_2_1Test extends ServerSetupWithTestData with DefaultUsers with Privat Given("We will use an access token") val bankId = randomBank val bankAccount : AccountJSON = randomPrivateAccount(bankId) - val userId = resourceUser2.idGivenByProvider + val userId2 = resourceUser2.idGivenByProvider val viewId = getTheRandomView(bankId, bankAccount) val viewsIdsToGrant = viewId :: Nil - grantUserAccessToViews(bankId, bankAccount.id, userId, viewsIdsToGrant, user1) - val viewsBefore = getUserAccountPermission(bankId, bankAccount.id, userId, user1).body.extract[ViewsJSONV121].views.length + val replyGranted = grantUserAccessToViews(bankId, bankAccount.id, userId2, viewsIdsToGrant, user1) + Then("we should get a 201") + replyGranted.code should equal(201) + val viewsBefore = getUserAccountPermission(bankId, bankAccount.id, userId2, user1).body.extract[ViewsJSONV121].views.length When("the request is sent") - val reply = revokeUserAccessToView(bankId, bankAccount.id, userId, viewId, user1) + val reply = revokeUserAccessToView(bankId, bankAccount.id, userId2, viewId, user1) Then("we should get a 204 no content code") reply.code should equal (204) - val viewsAfter = getUserAccountPermission(bankId, bankAccount.id, userId, user1).body.extract[ViewsJSONV121].views.length + val viewsAfter = getUserAccountPermission(bankId, bankAccount.id, userId2, user1).body.extract[ViewsJSONV121].views.length viewsAfter should equal(viewsBefore -1) } From 0bb90f44efba5783afb8ef870ce267090e86982e Mon Sep 17 00:00:00 2001 From: hongwei Date: Tue, 11 Jul 2023 23:32:52 +0800 Subject: [PATCH 32/41] refactor/tweaked error messages --- obp-api/src/main/scala/code/api/util/ErrorMessages.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala index 7188203ce2..2ac07170b9 100644 --- a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala +++ b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala @@ -298,7 +298,7 @@ object ErrorMessages { val CreateCardError = "OBP-30032: Could not insert the Card" val UpdateCardError = "OBP-30033: Could not update the Card" - val ViewIdNotSupported = s"OBP-30034: This ViewId is not supported. Only support four now: " + + val ViewIdNotSupported = s"OBP-30034: This ViewId is not supported. Only the following can be used: " + s"$SYSTEM_OWNER_VIEW_ID, " + s"$SYSTEM_ACCOUNTANT_VIEW_ID, " + s"$SYSTEM_AUDITOR_VIEW_ID, " + From 262582253ce526c296587df83922c4b8adf9b27f Mon Sep 17 00:00:00 2001 From: hongwei Date: Wed, 12 Jul 2023 00:14:10 +0800 Subject: [PATCH 33/41] refactor/tweaked error messages for dbColumnName --- .../main/scala/code/api/util/ErrorMessages.scala | 3 ++- .../scala/code/api/v1_2_1/APIMethods121.scala | 15 ++++++++------- .../scala/code/api/v1_4_0/APIMethods140.scala | 6 +++--- .../scala/code/api/v2_0_0/APIMethods200.scala | 8 ++++---- .../scala/code/api/v2_1_0/APIMethods210.scala | 4 ++-- .../scala/code/api/v2_2_0/APIMethods220.scala | 9 ++++----- .../scala/code/api/v3_0_0/APIMethods300.scala | 7 ++++--- .../scala/code/api/v3_1_0/APIMethods310.scala | 4 ++-- .../scala/code/api/v4_0_0/APIMethods400.scala | 4 ++-- .../scala/code/api/v5_0_0/APIMethods500.scala | 4 ++-- 10 files changed, 33 insertions(+), 31 deletions(-) diff --git a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala index 2ac07170b9..19cfd6088f 100644 --- a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala +++ b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala @@ -7,6 +7,7 @@ import com.openbankproject.commons.model.enums.TransactionRequestStatus._ import code.api.Constant._ import code.api.util.ApiRole.{CanCreateAnyTransactionRequest, canCreateEntitlementAtAnyBank, canCreateEntitlementAtOneBank} import code.views.system.ViewDefinition +import net.liftweb.util.StringHelpers object ErrorMessages { import code.api.util.APIUtil._ @@ -555,7 +556,7 @@ object ErrorMessages { "because the login user doesn't have access to the view of the from account " + "or the consumer doesn't have the access to the view of the from account " + s"or the login user does not have the `${CanCreateAnyTransactionRequest.toString()}` role " + - s"or the view have the permission ${ViewDefinition.canAddTransactionRequestToAnyAccount_.dbColumnName}." + s"or the view have the permission ${StringHelpers.snakify(ViewDefinition.canAddTransactionRequestToAnyAccount_.dbColumnName).dropRight(1)}." val InvalidTransactionRequestCurrency = "OBP-40003: Transaction Request Currency must be the same as From Account Currency." val InvalidTransactionRequestId = "OBP-40004: Transaction Request Id not found." val InsufficientAuthorisationToCreateTransactionType = "OBP-40005: Insufficient authorisation to Create Transaction Type offered by the bank. The Request could not be created because you don't have access to CanCreateTransactionType." diff --git a/obp-api/src/main/scala/code/api/v1_2_1/APIMethods121.scala b/obp-api/src/main/scala/code/api/v1_2_1/APIMethods121.scala index ef66248f30..14aeb7be41 100644 --- a/obp-api/src/main/scala/code/api/v1_2_1/APIMethods121.scala +++ b/obp-api/src/main/scala/code/api/v1_2_1/APIMethods121.scala @@ -37,6 +37,7 @@ import scala.language.postfixOps import scalacache.ScalaCache import scalacache.guava.GuavaCache import com.openbankproject.commons.ExecutionContext.Implicits.global +import net.liftweb.util.StringHelpers import scala.concurrent.Future @@ -497,7 +498,7 @@ trait APIMethods121 { anyViewContainsCanUpdateBankAccountLabelPermission = Views.views.vend.permission(BankIdAccountId(account.bankId, account.accountId), u) .map(_.views.map(_.canUpdateBankAccountLabel).find(_.==(true)).getOrElse(false)).getOrElse(false) _ <- Helper.booleanToFuture( - s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${ViewDefinition.canUpdateBankAccountLabel_.dbColumnName}` permission on any your views", + s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${StringHelpers.snakify(ViewDefinition.canUpdateBankAccountLabel_.dbColumnName).dropRight(1)}` permission on any your views", cc = callContext ) { anyViewContainsCanUpdateBankAccountLabelPermission @@ -561,7 +562,7 @@ trait APIMethods121 { anyViewContainsCanSeeAvailableViewsForBankAccountPermission = permission.views.map(_.canSeeAvailableViewsForBankAccount).find(_.==(true)).getOrElse(false) _ <- Helper.booleanToBox( anyViewContainsCanSeeAvailableViewsForBankAccountPermission, - s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${ViewDefinition.canSeeAvailableViewsForBankAccount_.dbColumnName}` permission on any your views" + s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${StringHelpers.snakify(ViewDefinition.canSeeAvailableViewsForBankAccount_.dbColumnName).dropRight(1)}` permission on any your views" ) views <- Full(Views.views.vend.availableViewsForAccount(BankIdAccountId(bankAccount.bankId, bankAccount.accountId))) } yield { @@ -626,7 +627,7 @@ trait APIMethods121 { .map(_.views.map(_.canCreateCustomView).find(_.==(true)).getOrElse(false)).getOrElse(false) _ <- booleanToBox( anyViewContainsCanCreateCustomViewPermission, - s"${ErrorMessages.CreateCustomViewError} You need the `${ViewDefinition.canCreateCustomView_.dbColumnName}` permission on any your views" + s"${ErrorMessages.CreateCustomViewError} You need the `${StringHelpers.snakify(ViewDefinition.canCreateCustomView_.dbColumnName).dropRight(1)}` permission on any your views" ) view <- Views.views.vend.createCustomView(BankIdAccountId(bankId,accountId), createViewJson)?~ CreateCustomViewError } yield { @@ -687,7 +688,7 @@ trait APIMethods121 { .map(_.views.map(_.canUpdateCustomView).find(_.==(true)).getOrElse(false)).getOrElse(false) _ <- booleanToBox( anyViewContainsCanUpdateCustomViewPermission, - s"${ErrorMessages.CreateCustomViewError} You need the `${ViewDefinition.canUpdateCustomView_.dbColumnName}` permission on any your views" + s"${ErrorMessages.CreateCustomViewError} You need the `${StringHelpers.snakify(ViewDefinition.canUpdateCustomView_.dbColumnName).dropRight(1)}` permission on any your views" ) updatedView <- Views.views.vend.updateCustomView(BankIdAccountId(bankId, accountId),viewId, updateViewJson) ?~ CreateCustomViewError } yield { @@ -732,7 +733,7 @@ trait APIMethods121 { anyViewContainsCanDeleteCustomViewPermission = Views.views.vend.permission(BankIdAccountId(account.bankId, account.accountId), u) .map(_.views.map(_.canDeleteCustomView).find(_.==(true)).getOrElse(false)).getOrElse(false) _ <- Helper.booleanToFuture( - s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${ViewDefinition.canDeleteCustomView_.dbColumnName}` permission on any your views", + s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${StringHelpers.snakify(ViewDefinition.canDeleteCustomView_.dbColumnName).dropRight(1)}` permission on any your views", cc = callContext ) { anyViewContainsCanDeleteCustomViewPermission @@ -772,7 +773,7 @@ trait APIMethods121 { .map(_.views.map(_.canSeeViewsWithPermissionsForAllUsers).find(_.==(true)).getOrElse(false)).getOrElse(false) _ <- booleanToBox( anyViewContainsCanSeeViewsWithPermissionsForAllUsersPermission, - s"${ErrorMessages.CreateCustomViewError} You need the `${ViewDefinition.canSeeViewsWithPermissionsForAllUsers_.dbColumnName}` permission on any your views" + s"${ErrorMessages.CreateCustomViewError} You need the `${StringHelpers.snakify(ViewDefinition.canSeeViewsWithPermissionsForAllUsers_.dbColumnName).dropRight(1)}` permission on any your views" ) permissions = Views.views.vend.permissions(BankIdAccountId(bankId, accountId)) } yield { @@ -817,7 +818,7 @@ trait APIMethods121 { .find(_.==(true)).getOrElse(false)).getOrElse(false) _ <- booleanToBox( anyViewContainsCanSeeViewsWithPermissionsForOneUserPermission, - s"${ErrorMessages.CreateCustomViewError} You need the `${ViewDefinition.canSeeViewsWithPermissionsForOneUser_.dbColumnName}` permission on any your views" + s"${ErrorMessages.CreateCustomViewError} You need the `${StringHelpers.snakify(ViewDefinition.canSeeViewsWithPermissionsForOneUser_.dbColumnName).dropRight(1)}` permission on any your views" ) userFromURL <- UserX.findByProviderId(provider, providerId) ?~! UserNotFoundByProviderAndProvideId permission <- Views.views.vend.permission(BankIdAccountId(bankId, accountId), userFromURL) diff --git a/obp-api/src/main/scala/code/api/v1_4_0/APIMethods140.scala b/obp-api/src/main/scala/code/api/v1_4_0/APIMethods140.scala index c53b0518aa..977dc5bf75 100644 --- a/obp-api/src/main/scala/code/api/v1_4_0/APIMethods140.scala +++ b/obp-api/src/main/scala/code/api/v1_4_0/APIMethods140.scala @@ -22,7 +22,7 @@ import net.liftweb.http.rest.RestHelper import net.liftweb.json.Extraction import net.liftweb.json.JsonAST.JValue import net.liftweb.util.Helpers.tryo -import net.liftweb.util.Props +import net.liftweb.util.{Props, StringHelpers} import scala.collection.immutable.{List, Nil} import scala.concurrent.Future @@ -424,7 +424,7 @@ trait APIMethods140 extends MdcLoggable with APIMethods130 with APIMethods121{ _ <- NewStyle.function.isValidCurrencyISOCode(fromAccount.currency, failMsg, callContext) view <- NewStyle.function.checkViewAccessAndReturnView(viewId, BankIdAccountId(fromAccount.bankId, fromAccount.accountId), Some(u), callContext) _ <- Helper.booleanToFuture( - s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${ViewDefinition.canSeeTransactionRequestTypes_.dbColumnName}` permission on the View(${viewId.value} )", + s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${StringHelpers.snakify(ViewDefinition.canSeeTransactionRequestTypes_.dbColumnName).dropRight(1)}` permission on the View(${viewId.value} )", cc = callContext ) { view.canSeeTransactionRequestTypes @@ -475,7 +475,7 @@ trait APIMethods140 extends MdcLoggable with APIMethods130 with APIMethods121{ view <- APIUtil.checkViewAccessAndReturnView(viewId, BankIdAccountId(bankId, accountId), Some(u), callContext) _ <- Helper.booleanToBox( view.canSeeTransactionRequests, - s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${ViewDefinition.canSeeTransactionRequests_.dbColumnName}` permission on the View(${viewId.value})" + s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${StringHelpers.snakify(ViewDefinition.canSeeTransactionRequests_.dbColumnName).dropRight(1)}` permission on the View(${viewId.value})" ) transactionRequests <- Connector.connector.vend.getTransactionRequests(u, fromAccount, callContext) } diff --git a/obp-api/src/main/scala/code/api/v2_0_0/APIMethods200.scala b/obp-api/src/main/scala/code/api/v2_0_0/APIMethods200.scala index 472634188b..fde75004cd 100644 --- a/obp-api/src/main/scala/code/api/v2_0_0/APIMethods200.scala +++ b/obp-api/src/main/scala/code/api/v2_0_0/APIMethods200.scala @@ -1,7 +1,6 @@ package code.api.v2_0_0 import java.util.{Calendar, Date} - import code.api.Constant._ import code.TransactionTypes.TransactionType import code.api.{APIFailure, APIFailureNewStyle} @@ -43,6 +42,7 @@ import scala.collection.immutable.Nil import scala.collection.mutable.ArrayBuffer import com.openbankproject.commons.ExecutionContext.Implicits.global import com.openbankproject.commons.util.ApiVersion +import net.liftweb.util.StringHelpers import scala.concurrent.Future // Makes JValue assignment to Nil work @@ -1014,7 +1014,7 @@ trait APIMethods200 { anyViewContainsCanSeeViewsWithPermissionsForAllUsersPermission = Views.views.vend.permission(BankIdAccountId(account.bankId, account.accountId), u) .map(_.views.map(_.canUpdateBankAccountLabel).find(_.==(true)).getOrElse(false)).getOrElse(false) _ <- Helper.booleanToFuture( - s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${ViewDefinition.canSeeViewsWithPermissionsForAllUsers_.dbColumnName}` permission on any your views", + s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${StringHelpers.snakify(ViewDefinition.canSeeViewsWithPermissionsForAllUsers_.dbColumnName).dropRight(1)}` permission on any your views", cc = callContext ) { anyViewContainsCanSeeViewsWithPermissionsForAllUsersPermission @@ -1058,7 +1058,7 @@ trait APIMethods200 { .find(_.==(true)).getOrElse(false)).getOrElse(false) _ <- booleanToBox( anyViewContainsCanSeePermissionForOneUserPermission, - s"${ErrorMessages.CreateCustomViewError} You need the `${ViewDefinition.canSeeViewsWithPermissionsForOneUser_.dbColumnName}` permission on any your views" + s"${ErrorMessages.CreateCustomViewError} You need the `${StringHelpers.snakify(ViewDefinition.canSeeViewsWithPermissionsForOneUser_.dbColumnName).dropRight(1)}` permission on any your views" ) userFromURL <- UserX.findByProviderId(provider, providerId) ?~! UserNotFoundByProviderAndProvideId permission <- Views.views.vend.permission(BankIdAccountId(bankId, accountId), userFromURL) @@ -1455,7 +1455,7 @@ trait APIMethods200 { fromAccount <- BankAccountX(bankId, accountId) ?~! AccountNotFound view <-APIUtil.checkViewAccessAndReturnView(viewId, BankIdAccountId(fromAccount.bankId, fromAccount.accountId), Some(u), callContext) _ <- Helper.booleanToBox(view.canSeeTransactionRequests, - s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${ViewDefinition.canSeeTransactionRequests_.dbColumnName}` permission on the View(${viewId.value} )") + s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${StringHelpers.snakify(ViewDefinition.canSeeTransactionRequests_.dbColumnName).dropRight(1)}` permission on the View(${viewId.value} )") transactionRequests <- Connector.connector.vend.getTransactionRequests(u, fromAccount, callContext) } yield { diff --git a/obp-api/src/main/scala/code/api/v2_1_0/APIMethods210.scala b/obp-api/src/main/scala/code/api/v2_1_0/APIMethods210.scala index 11757f9dd4..a85bf277a5 100644 --- a/obp-api/src/main/scala/code/api/v2_1_0/APIMethods210.scala +++ b/obp-api/src/main/scala/code/api/v2_1_0/APIMethods210.scala @@ -33,7 +33,7 @@ import com.openbankproject.commons.model.enums.ChallengeType import com.openbankproject.commons.util.ApiVersion import net.liftweb.json.Extraction import net.liftweb.util.Helpers.tryo -import net.liftweb.util.Props +import net.liftweb.util.{Props, StringHelpers} import scala.collection.immutable.Nil import scala.collection.mutable.ArrayBuffer @@ -715,7 +715,7 @@ trait APIMethods210 { (fromAccount, callContext) <- BankAccountX(bankId, accountId, Some(cc)) ?~! {AccountNotFound} view <- APIUtil.checkViewAccessAndReturnView(viewId, BankIdAccountId(bankId, accountId), Some(u), callContext) _ <- Helper.booleanToBox(view.canSeeTransactionRequests, - s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${ViewDefinition.canSeeTransactionRequests_.dbColumnName}` permission on the View(${viewId.value} )") + s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${StringHelpers.snakify(ViewDefinition.canSeeTransactionRequests_.dbColumnName).dropRight(1)}` permission on the View(${viewId.value} )") (transactionRequests,callContext) <- Connector.connector.vend.getTransactionRequests210(u, fromAccount, callContext) } yield { diff --git a/obp-api/src/main/scala/code/api/v2_2_0/APIMethods220.scala b/obp-api/src/main/scala/code/api/v2_2_0/APIMethods220.scala index 441a8246ba..b39f095e2a 100644 --- a/obp-api/src/main/scala/code/api/v2_2_0/APIMethods220.scala +++ b/obp-api/src/main/scala/code/api/v2_2_0/APIMethods220.scala @@ -1,7 +1,5 @@ package code.api.v2_2_0 -import code.api.Constant.SYSTEM_OWNER_VIEW_ID - import java.util.Date import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON._ import code.api.util.APIUtil._ @@ -35,6 +33,7 @@ import scala.collection.immutable.{List, Nil} import scala.collection.mutable.ArrayBuffer import com.openbankproject.commons.ExecutionContext.Implicits.global import com.openbankproject.commons.util.ApiVersion +import net.liftweb.util.StringHelpers import scala.concurrent.Future @@ -105,7 +104,7 @@ trait APIMethods220 { permission <- NewStyle.function.permission(bankId, accountId, u, callContext) anyViewContainsCanSeeAvailableViewsForBankAccountPermission = permission.views.map(_.canSeeAvailableViewsForBankAccount).find(_.==(true)).getOrElse(false) _ <- Helper.booleanToFuture( - s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${ViewDefinition.canSeeAvailableViewsForBankAccount_.dbColumnName}` permission on any your views", + s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${StringHelpers.snakify(ViewDefinition.canSeeAvailableViewsForBankAccount_.dbColumnName).dropRight(1)}` permission on any your views", cc= callContext ){ anyViewContainsCanSeeAvailableViewsForBankAccountPermission @@ -175,7 +174,7 @@ trait APIMethods220 { .map(_.views.map(_.canCreateCustomView).find(_.==(true)).getOrElse(false)).getOrElse(false) _ <- booleanToBox( anyViewContainsCanCreateCustomViewPermission, - s"${ErrorMessages.CreateCustomViewError} You need the `${ViewDefinition.canCreateCustomView_.dbColumnName}` permission on any your views" + s"${ErrorMessages.CreateCustomViewError} You need the `${StringHelpers.snakify(ViewDefinition.canCreateCustomView_.dbColumnName).dropRight(1)}` permission on any your views" ) view <- Views.views.vend.createCustomView(BankIdAccountId(bankId, accountId), createViewJson) ?~ CreateCustomViewError } yield { @@ -234,7 +233,7 @@ trait APIMethods220 { .map(_.views.map(_.canUpdateCustomView).find(_.==(true)).getOrElse(false)).getOrElse(false) _ <- booleanToBox( anyViewContainsCancanUpdateCustomViewPermission, - s"${ErrorMessages.CreateCustomViewError} You need the `${ViewDefinition.canUpdateCustomView_.dbColumnName}` permission on any your views" + s"${ErrorMessages.CreateCustomViewError} You need the `${StringHelpers.snakify(ViewDefinition.canUpdateCustomView_.dbColumnName).dropRight(1)}` permission on any your views" ) updatedView <- Views.views.vend.updateCustomView(BankIdAccountId(bankId, accountId), viewId, updateViewJson) ?~ CreateCustomViewError } yield { diff --git a/obp-api/src/main/scala/code/api/v3_0_0/APIMethods300.scala b/obp-api/src/main/scala/code/api/v3_0_0/APIMethods300.scala index 39380a69cc..a83f93ab8f 100644 --- a/obp-api/src/main/scala/code/api/v3_0_0/APIMethods300.scala +++ b/obp-api/src/main/scala/code/api/v3_0_0/APIMethods300.scala @@ -49,6 +49,7 @@ import code.model import com.openbankproject.commons.dto.CustomerAndAttribute import com.openbankproject.commons.util.ApiVersion import net.liftweb.json.JsonAST.JField +import net.liftweb.util.StringHelpers trait APIMethods300 { @@ -184,7 +185,7 @@ trait APIMethods300 { .map(_.views.map(_.canCreateCustomView).find(_.==(true)).getOrElse(false)).getOrElse(false) _ <- Helper.booleanToFuture( - s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${ViewDefinition.canCreateCustomView_.dbColumnName}` permission on any your views", + s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${StringHelpers.snakify(ViewDefinition.canCreateCustomView_.dbColumnName).dropRight(1)}` permission on any your views", cc = callContext ) {anyViewContainsCanCreateCustomViewPermission} (view, callContext) <- NewStyle.function.createCustomView(BankIdAccountId(bankId, accountId), createViewJson, callContext) @@ -223,7 +224,7 @@ trait APIMethods300 { anyViewContainsCanSeePermissionForOneUserPermission = Views.views.vend.permission(BankIdAccountId(account.bankId, account.accountId), loggedInUser) .map(_.views.map(_.canUpdateBankAccountLabel).find(_.==(true)).getOrElse(false)).getOrElse(false) _ <- Helper.booleanToFuture( - s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${ViewDefinition.canSeeViewsWithPermissionsForOneUser_.dbColumnName}` permission on any your views", + s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${StringHelpers.snakify(ViewDefinition.canSeeViewsWithPermissionsForOneUser_.dbColumnName).dropRight(1)}` permission on any your views", cc = callContext ) { anyViewContainsCanSeePermissionForOneUserPermission @@ -290,7 +291,7 @@ trait APIMethods300 { .map(_.views.map(_.canUpdateCustomView).find(_.==(true)).getOrElse(false)).getOrElse(false) _ <- Helper.booleanToFuture( - s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${ViewDefinition.canUpdateCustomView_.dbColumnName}` permission on any your views", + s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${StringHelpers.snakify(ViewDefinition.canUpdateCustomView_.dbColumnName).dropRight(1)}` permission on any your views", cc = callContext ) { anyViewContainsCancanUpdateCustomViewPermission diff --git a/obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala b/obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala index 7fad0ea25b..8f96c37f10 100644 --- a/obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala +++ b/obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala @@ -53,7 +53,7 @@ import net.liftweb.http.rest.RestHelper import net.liftweb.json._ import net.liftweb.util.Helpers.tryo import net.liftweb.util.Mailer.{From, PlainMailBodyType, Subject, To} -import net.liftweb.util.{Helpers, Mailer, Props} +import net.liftweb.util.{Helpers, Mailer, Props, StringHelpers} import org.apache.commons.lang3.{StringUtils, Validate} import scala.collection.immutable.{List, Nil} @@ -1088,7 +1088,7 @@ trait APIMethods310 { (fromAccount, callContext) <- NewStyle.function.checkBankAccountExists(bankId, accountId, callContext) view <- NewStyle.function.checkAccountAccessAndGetView(viewId, BankIdAccountId(bankId, accountId), Full(u), callContext) _ <- Helper.booleanToFuture( - s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${ViewDefinition.canSeeTransactionRequests_.dbColumnName}` permission on the View(${viewId.value})", + s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${StringHelpers.snakify(ViewDefinition.canSeeTransactionRequests_.dbColumnName).dropRight(1)}` permission on the View(${viewId.value})", cc=callContext){ view.canSeeTransactionRequests } diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index b07b088e00..e52ada7e60 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -2782,7 +2782,7 @@ trait APIMethods400 { anyViewContainsCanUpdateBankAccountLabelPermission = Views.views.vend.permission(BankIdAccountId(account.bankId, account.accountId), u) .map(_.views.map(_.canUpdateBankAccountLabel).find(_.==(true)).getOrElse(false)).getOrElse(false) _ <- Helper.booleanToFuture( - s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${ViewDefinition.canUpdateBankAccountLabel_.dbColumnName}` permission on any your views", + s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${StringHelpers.snakify(ViewDefinition.canUpdateBankAccountLabel_.dbColumnName).dropRight(1)}` permission on any your views", cc = callContext ) { anyViewContainsCanUpdateBankAccountLabelPermission @@ -5168,7 +5168,7 @@ trait APIMethods400 { _ <- NewStyle.function.isEnabledTransactionRequests(callContext) view <- NewStyle.function.checkAccountAccessAndGetView(viewId, BankIdAccountId(bankId, accountId), Full(u), callContext) _ <- Helper.booleanToFuture( - s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${ViewDefinition.canSeeTransactionRequests_.dbColumnName}` permission on the View(${viewId.value})", + s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${StringHelpers.snakify(ViewDefinition.canSeeTransactionRequests_.dbColumnName).dropRight(1)}` permission on the View(${viewId.value})", cc = callContext) { view.canSeeTransactionRequests } diff --git a/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala b/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala index 1f038ae5b3..d669bae986 100644 --- a/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala +++ b/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala @@ -38,7 +38,7 @@ import net.liftweb.http.rest.RestHelper import net.liftweb.json import net.liftweb.json.{Extraction, compactRender, prettyRender} import net.liftweb.util.Helpers.tryo -import net.liftweb.util.{Helpers, Props} +import net.liftweb.util.{Helpers, Props, StringHelpers} import java.util.concurrent.ThreadLocalRandom import code.accountattribute.AccountAttributeX @@ -1594,7 +1594,7 @@ trait APIMethods500 { permission <- NewStyle.function.permission(bankId, accountId, u, callContext) anyViewContainsCanSeeAvailableViewsForBankAccountPermission = permission.views.map(_.canSeeAvailableViewsForBankAccount).find(_.==(true)).getOrElse(false) _ <- Helper.booleanToFuture( - s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${ViewDefinition.canSeeAvailableViewsForBankAccount_.dbColumnName}` permission on any your views", + s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${StringHelpers.snakify(ViewDefinition.canSeeAvailableViewsForBankAccount_.dbColumnName).dropRight(1)}` permission on any your views", cc = callContext ) { anyViewContainsCanSeeAvailableViewsForBankAccountPermission From caf3507d2b4046916860c269ab209d96e141fd3e Mon Sep 17 00:00:00 2001 From: hongwei Date: Thu, 13 Jul 2023 17:50:18 +0800 Subject: [PATCH 34/41] refactor/tweaked enableCustomViews->manageCustomViews --- obp-api/src/main/scala/bootstrap/liftweb/Boot.scala | 4 ++-- obp-api/src/main/scala/code/api/constant/constant.scala | 4 ++-- obp-api/src/main/scala/code/api/util/ErrorMessages.scala | 2 +- .../scala/code/bankconnectors/LocalMappedConnector.scala | 8 ++++---- obp-api/src/main/scala/code/views/MapperViews.scala | 8 ++++---- obp-api/src/test/scala/code/api/v1_2_1/API1_2_1Test.scala | 2 +- .../src/test/scala/code/setup/TestConnectorSetup.scala | 6 +++--- 7 files changed, 17 insertions(+), 17 deletions(-) diff --git a/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala b/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala index 71890a42f1..941bac83b4 100644 --- a/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala +++ b/obp-api/src/main/scala/bootstrap/liftweb/Boot.scala @@ -760,7 +760,7 @@ class Boot extends MdcLoggable { val accountant = Views.views.vend.getOrCreateSystemView(SYSTEM_ACCOUNTANT_VIEW_ID).isDefined val standard = Views.views.vend.getOrCreateSystemView(SYSTEM_STANDARD_VIEW_ID).isDefined val stageOne = Views.views.vend.getOrCreateSystemView(SYSTEM_STAGE_ONE_VIEW_ID).isDefined - val enableCustomViews = Views.views.vend.getOrCreateSystemView(SYSTEM_ENABLE_CUSTOM_VIEWS_VIEW_ID).isDefined + val manageCustomViews = Views.views.vend.getOrCreateSystemView(SYSTEM_MANAGE_CUSTOM_VIEWS_VIEW_ID).isDefined // Only create Firehose view if they are enabled at instance. val accountFirehose = if (ApiPropsWithAlias.allowAccountFirehose) Views.views.vend.getOrCreateSystemView(SYSTEM_FIREHOSE_VIEW_ID).isDefined @@ -774,7 +774,7 @@ class Boot extends MdcLoggable { |System view ${SYSTEM_FIREHOSE_VIEW_ID} exists/created at the instance: ${accountFirehose} |System view ${SYSTEM_STANDARD_VIEW_ID} exists/created at the instance: ${standard} |System view ${SYSTEM_STAGE_ONE_VIEW_ID} exists/created at the instance: ${stageOne} - |System view ${SYSTEM_ENABLE_CUSTOM_VIEWS_VIEW_ID} exists/created at the instance: ${enableCustomViews} + |System view ${SYSTEM_MANAGE_CUSTOM_VIEWS_VIEW_ID} exists/created at the instance: ${manageCustomViews} |""".stripMargin logger.info(comment) diff --git a/obp-api/src/main/scala/code/api/constant/constant.scala b/obp-api/src/main/scala/code/api/constant/constant.scala index 6270315832..8b70623d67 100644 --- a/obp-api/src/main/scala/code/api/constant/constant.scala +++ b/obp-api/src/main/scala/code/api/constant/constant.scala @@ -29,7 +29,7 @@ object Constant extends MdcLoggable { final val SYSTEM_FIREHOSE_VIEW_ID = "firehose" final val SYSTEM_STANDARD_VIEW_ID = "standard" final val SYSTEM_STAGE_ONE_VIEW_ID = "StageOne" - final val SYSTEM_ENABLE_CUSTOM_VIEWS_VIEW_ID = "EnableCustomViews" + final val SYSTEM_MANAGE_CUSTOM_VIEWS_VIEW_ID = "ManageCustomViews" final val SYSTEM_READ_ACCOUNTS_BASIC_VIEW_ID = "ReadAccountsBasic" final val SYSTEM_READ_ACCOUNTS_DETAIL_VIEW_ID = "ReadAccountsDetail" final val SYSTEM_READ_BALANCES_VIEW_ID = "ReadBalances" @@ -49,7 +49,7 @@ object Constant extends MdcLoggable { SYSTEM_FIREHOSE_VIEW_ID, SYSTEM_STANDARD_VIEW_ID, SYSTEM_STAGE_ONE_VIEW_ID, - SYSTEM_ENABLE_CUSTOM_VIEWS_VIEW_ID, + SYSTEM_MANAGE_CUSTOM_VIEWS_VIEW_ID, SYSTEM_READ_ACCOUNTS_BASIC_VIEW_ID, SYSTEM_READ_ACCOUNTS_DETAIL_VIEW_ID, SYSTEM_READ_BALANCES_VIEW_ID, diff --git a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala index 19cfd6088f..b0ba7d4cd1 100644 --- a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala +++ b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala @@ -305,7 +305,7 @@ object ErrorMessages { s"$SYSTEM_AUDITOR_VIEW_ID, " + s"$SYSTEM_STAGE_ONE_VIEW_ID, " + s"$SYSTEM_STANDARD_VIEW_ID, " + - s"$SYSTEM_ENABLE_CUSTOM_VIEWS_VIEW_ID, " + + s"$SYSTEM_MANAGE_CUSTOM_VIEWS_VIEW_ID, " + s"$CUSTOM_PUBLIC_VIEW_ID." val UserCustomerLinkNotFound = "OBP-30035: User Customer Link not found" diff --git a/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala b/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala index 8e38d213cf..2311603d52 100644 --- a/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala +++ b/obp-api/src/main/scala/code/bankconnectors/LocalMappedConnector.scala @@ -10,13 +10,13 @@ import code.accountattribute.AccountAttributeX import code.accountholders.{AccountHolders, MapperAccountHolders} import code.api.BerlinGroup.{AuthenticationType, ScaStatus} import code.api.Constant -import code.api.Constant.{INCOMING_SETTLEMENT_ACCOUNT_ID, OUTGOING_SETTLEMENT_ACCOUNT_ID, SYSTEM_ACCOUNTANT_VIEW_ID, SYSTEM_AUDITOR_VIEW_ID, SYSTEM_ENABLE_CUSTOM_VIEWS_VIEW_ID, SYSTEM_OWNER_VIEW_ID, localIdentityProvider} +import code.api.Constant.{INCOMING_SETTLEMENT_ACCOUNT_ID, OUTGOING_SETTLEMENT_ACCOUNT_ID, SYSTEM_ACCOUNTANT_VIEW_ID, SYSTEM_AUDITOR_VIEW_ID, SYSTEM_MANAGE_CUSTOM_VIEWS_VIEW_ID, SYSTEM_OWNER_VIEW_ID, localIdentityProvider} import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON import code.api.attributedefinition.{AttributeDefinition, AttributeDefinitionDI} import code.api.cache.Caching import code.api.util.APIUtil._ import code.api.util.ApiRole.canCreateAnyTransactionRequest -import code.api.util.ErrorMessages.{attemptedToOpenAnEmptyBox, _} +import code.api.util.ErrorMessages._ import code.api.util._ import code.api.v1_4_0.JSONFactory1_4_0.TransactionRequestAccountJsonV140 import code.api.v2_1_0._ @@ -72,7 +72,7 @@ import code.transactionrequests.TransactionRequests.TransactionRequestTypes import code.transactionrequests._ import code.users.{UserAttribute, UserAttributeProvider, Users} import code.util.Helper -import code.util.Helper.{MdcLoggable, _} +import code.util.Helper._ import code.views.Views import com.google.common.cache.CacheBuilder import com.openbankproject.commons.ExecutionContext.Implicits.global @@ -555,7 +555,7 @@ object LocalMappedConnector extends Connector with MdcLoggable { */ override def getBankAccountsForUserLegacy(provider: String, username:String, callContext: Option[CallContext]): Box[(List[InboundAccount], Option[CallContext])] = { //1st: get the accounts from userAuthContext - val viewsToGenerate = List(SYSTEM_ENABLE_CUSTOM_VIEWS_VIEW_ID,SYSTEM_OWNER_VIEW_ID) //TODO, so far only set the `owner` view, later need to simulate other views. + val viewsToGenerate = List(SYSTEM_MANAGE_CUSTOM_VIEWS_VIEW_ID,SYSTEM_OWNER_VIEW_ID) //TODO, so far only set the `owner` view, later need to simulate other views. val user = Users.users.vend.getUserByProviderId(provider, username).getOrElse(throw new RuntimeException(s"$RefreshUserError at getBankAccountsForUserLegacy($username, ${callContext})")) val userId = user.userId tryo{net.liftweb.common.Logger(this.getClass).debug(s"getBankAccountsForUser.user says: provider($provider), username($username)")} diff --git a/obp-api/src/main/scala/code/views/MapperViews.scala b/obp-api/src/main/scala/code/views/MapperViews.scala index 5d5d80c40e..9b6c46cc7e 100644 --- a/obp-api/src/main/scala/code/views/MapperViews.scala +++ b/obp-api/src/main/scala/code/views/MapperViews.scala @@ -602,7 +602,7 @@ object MapperViews extends Views with MdcLoggable { val auditorsView = SYSTEM_AUDITOR_VIEW_ID.equals(viewId.toLowerCase) val standardView = SYSTEM_STANDARD_VIEW_ID.equals(viewId.toLowerCase) val stageOneView = SYSTEM_STAGE_ONE_VIEW_ID.toLowerCase.equals(viewId.toLowerCase) - val enableCustomViews = SYSTEM_ENABLE_CUSTOM_VIEWS_VIEW_ID.toLowerCase.equals(viewId.toLowerCase) + val manageCustomViews = SYSTEM_MANAGE_CUSTOM_VIEWS_VIEW_ID.toLowerCase.equals(viewId.toLowerCase) val theView = if (ownerView) @@ -615,8 +615,8 @@ object MapperViews extends Views with MdcLoggable { getOrCreateSystemView(SYSTEM_STANDARD_VIEW_ID) else if (stageOneView) getOrCreateSystemView(SYSTEM_STAGE_ONE_VIEW_ID) - else if (enableCustomViews) - getOrCreateSystemView(SYSTEM_ENABLE_CUSTOM_VIEWS_VIEW_ID) + else if (manageCustomViews) + getOrCreateSystemView(SYSTEM_MANAGE_CUSTOM_VIEWS_VIEW_ID) else { logger.error(ViewIdNotSupported+ s"Your input viewId is :$viewId") Failure(ViewIdNotSupported+ s"Your input viewId is :$viewId") @@ -816,7 +816,7 @@ object MapperViews extends Views with MdcLoggable { entity .canSeeTransactionDescription_(false) .canAddTransactionRequestToAnyAccount_(false) - case SYSTEM_ENABLE_CUSTOM_VIEWS_VIEW_ID => + case SYSTEM_MANAGE_CUSTOM_VIEWS_VIEW_ID => entity .canRevokeAccessToCustomViews_(true) .canGrantAccessToCustomViews_(true) diff --git a/obp-api/src/test/scala/code/api/v1_2_1/API1_2_1Test.scala b/obp-api/src/test/scala/code/api/v1_2_1/API1_2_1Test.scala index fee2c180b0..17359a7d69 100644 --- a/obp-api/src/test/scala/code/api/v1_2_1/API1_2_1Test.scala +++ b/obp-api/src/test/scala/code/api/v1_2_1/API1_2_1Test.scala @@ -182,7 +182,7 @@ class API1_2_1Test extends ServerSetupWithTestData with DefaultUsers with Privat .filterNot(_.id.contains(SYSTEM_AUDITOR_VIEW_ID)) .filterNot(_.id.contains(SYSTEM_ACCOUNTANT_VIEW_ID)) .filterNot(_.id.contains(SYSTEM_FIREHOSE_VIEW_ID)) - .filterNot(_.id.contains(SYSTEM_ENABLE_CUSTOM_VIEWS_VIEW_ID)) + .filterNot(_.id.contains(SYSTEM_MANAGE_CUSTOM_VIEWS_VIEW_ID)) val randomPosition = nextInt(possibleViewsPermalinksWithoutOwner.size) possibleViewsPermalinksWithoutOwner(randomPosition).id } diff --git a/obp-api/src/test/scala/code/setup/TestConnectorSetup.scala b/obp-api/src/test/scala/code/setup/TestConnectorSetup.scala index c77a048e1e..86b6c930e7 100644 --- a/obp-api/src/test/scala/code/setup/TestConnectorSetup.scala +++ b/obp-api/src/test/scala/code/setup/TestConnectorSetup.scala @@ -2,7 +2,7 @@ package code.setup import java.util.{Calendar, Date} import code.accountholders.AccountHolders -import code.api.Constant.{SYSTEM_ACCOUNTANT_VIEW_ID, SYSTEM_AUDITOR_VIEW_ID, SYSTEM_ENABLE_CUSTOM_VIEWS_VIEW_ID, SYSTEM_FIREHOSE_VIEW_ID, SYSTEM_OWNER_VIEW_ID} +import code.api.Constant.{SYSTEM_ACCOUNTANT_VIEW_ID, SYSTEM_AUDITOR_VIEW_ID, SYSTEM_MANAGE_CUSTOM_VIEWS_VIEW_ID, SYSTEM_FIREHOSE_VIEW_ID, SYSTEM_OWNER_VIEW_ID} import code.api.util.ErrorMessages.attemptedToOpenAnEmptyBox import code.api.util.{APIUtil, OBPLimit, OBPOffset} import code.bankconnectors.{Connector, LocalMappedConnector} @@ -72,14 +72,14 @@ trait TestConnectorSetup { val systemAuditorView = getOrCreateSystemView(SYSTEM_AUDITOR_VIEW_ID) val systemAccountantView = getOrCreateSystemView(SYSTEM_ACCOUNTANT_VIEW_ID) val systemFirehoseView = getOrCreateSystemView(SYSTEM_FIREHOSE_VIEW_ID) - val enableCustomViews = getOrCreateSystemView(SYSTEM_ENABLE_CUSTOM_VIEWS_VIEW_ID) + val manageCustomViews = getOrCreateSystemView(SYSTEM_MANAGE_CUSTOM_VIEWS_VIEW_ID) accounts.foreach(account => { Views.views.vend.grantAccessToSystemView(account.bankId, account.accountId, systemOwnerView, user) Views.views.vend.grantAccessToSystemView(account.bankId, account.accountId, systemAuditorView, user) Views.views.vend.grantAccessToSystemView(account.bankId, account.accountId, systemAccountantView, user) Views.views.vend.grantAccessToSystemView(account.bankId, account.accountId, systemFirehoseView, user) - Views.views.vend.grantAccessToSystemView(account.bankId, account.accountId, enableCustomViews, user) + Views.views.vend.grantAccessToSystemView(account.bankId, account.accountId, manageCustomViews, user) val customPublicView = createPublicView(account.bankId, account.accountId) Views.views.vend.grantAccessToCustomView(customPublicView.uid, user) From 7a21fc3d56930969f10a522e744369cd8c2d452b Mon Sep 17 00:00:00 2001 From: hongwei Date: Thu, 13 Jul 2023 17:55:24 +0800 Subject: [PATCH 35/41] refactor/tweaked error message --- obp-api/src/main/scala/code/api/util/ErrorMessages.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala index b0ba7d4cd1..7954296e17 100644 --- a/obp-api/src/main/scala/code/api/util/ErrorMessages.scala +++ b/obp-api/src/main/scala/code/api/util/ErrorMessages.scala @@ -556,7 +556,7 @@ object ErrorMessages { "because the login user doesn't have access to the view of the from account " + "or the consumer doesn't have the access to the view of the from account " + s"or the login user does not have the `${CanCreateAnyTransactionRequest.toString()}` role " + - s"or the view have the permission ${StringHelpers.snakify(ViewDefinition.canAddTransactionRequestToAnyAccount_.dbColumnName).dropRight(1)}." + s"or the view does not have the permission ${StringHelpers.snakify(ViewDefinition.canAddTransactionRequestToAnyAccount_.dbColumnName).dropRight(1)}." val InvalidTransactionRequestCurrency = "OBP-40003: Transaction Request Currency must be the same as From Account Currency." val InvalidTransactionRequestId = "OBP-40004: Transaction Request Id not found." val InsufficientAuthorisationToCreateTransactionType = "OBP-40005: Insufficient authorisation to Create Transaction Type offered by the bank. The Request could not be created because you don't have access to CanCreateTransactionType." From 0e1782eac77ec923b925edc5c64f91e5b3fdd111 Mon Sep 17 00:00:00 2001 From: hongwei Date: Thu, 13 Jul 2023 18:10:17 +0800 Subject: [PATCH 36/41] refactor/change the permission for getPermissionsForBankAccount --- obp-api/src/main/scala/code/api/v2_0_0/APIMethods200.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/obp-api/src/main/scala/code/api/v2_0_0/APIMethods200.scala b/obp-api/src/main/scala/code/api/v2_0_0/APIMethods200.scala index fde75004cd..36efbac22b 100644 --- a/obp-api/src/main/scala/code/api/v2_0_0/APIMethods200.scala +++ b/obp-api/src/main/scala/code/api/v2_0_0/APIMethods200.scala @@ -1012,7 +1012,7 @@ trait APIMethods200 { (_, callContext) <- NewStyle.function.getBank(bankId, callContext) (account, callContext) <- NewStyle.function.getBankAccount(bankId, accountId, callContext) anyViewContainsCanSeeViewsWithPermissionsForAllUsersPermission = Views.views.vend.permission(BankIdAccountId(account.bankId, account.accountId), u) - .map(_.views.map(_.canUpdateBankAccountLabel).find(_.==(true)).getOrElse(false)).getOrElse(false) + .map(_.views.map(_.canSeeViewsWithPermissionsForAllUsers).find(_.==(true)).getOrElse(false)).getOrElse(false) _ <- Helper.booleanToFuture( s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${StringHelpers.snakify(ViewDefinition.canSeeViewsWithPermissionsForAllUsers_.dbColumnName).dropRight(1)}` permission on any your views", cc = callContext From b91140f6b647535a6870e0095d9431b4603c74ea Mon Sep 17 00:00:00 2001 From: hongwei Date: Thu, 13 Jul 2023 18:13:55 +0800 Subject: [PATCH 37/41] refactor/change the permission for getPermissionForUserForBankAccount --- obp-api/src/main/scala/code/api/v3_0_0/APIMethods300.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/obp-api/src/main/scala/code/api/v3_0_0/APIMethods300.scala b/obp-api/src/main/scala/code/api/v3_0_0/APIMethods300.scala index a83f93ab8f..ba4a302bb0 100644 --- a/obp-api/src/main/scala/code/api/v3_0_0/APIMethods300.scala +++ b/obp-api/src/main/scala/code/api/v3_0_0/APIMethods300.scala @@ -222,7 +222,7 @@ trait APIMethods300 { (_, callContext) <- NewStyle.function.getBank(bankId, callContext) (account, callContext) <- NewStyle.function.checkBankAccountExists(bankId, accountId, callContext) anyViewContainsCanSeePermissionForOneUserPermission = Views.views.vend.permission(BankIdAccountId(account.bankId, account.accountId), loggedInUser) - .map(_.views.map(_.canUpdateBankAccountLabel).find(_.==(true)).getOrElse(false)).getOrElse(false) + .map(_.views.map(_.canSeeViewsWithPermissionsForOneUser).find(_.==(true)).getOrElse(false)).getOrElse(false) _ <- Helper.booleanToFuture( s"${ErrorMessages.ViewDoesNotPermitAccess} You need the `${StringHelpers.snakify(ViewDefinition.canSeeViewsWithPermissionsForOneUser_.dbColumnName).dropRight(1)}` permission on any your views", cc = callContext From d578d67de3bf02931eeae1ef7a2f54597bc3abd8 Mon Sep 17 00:00:00 2001 From: hongwei Date: Thu, 13 Jul 2023 18:18:44 +0800 Subject: [PATCH 38/41] docfix/add the custom to some documents --- .../src/main/scala/code/api/v1_2_1/APIMethods121.scala | 4 ++-- .../src/main/scala/code/api/v3_0_0/APIMethods300.scala | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/obp-api/src/main/scala/code/api/v1_2_1/APIMethods121.scala b/obp-api/src/main/scala/code/api/v1_2_1/APIMethods121.scala index 14aeb7be41..9038ada7b0 100644 --- a/obp-api/src/main/scala/code/api/v1_2_1/APIMethods121.scala +++ b/obp-api/src/main/scala/code/api/v1_2_1/APIMethods121.scala @@ -704,8 +704,8 @@ trait APIMethods121 { "deleteViewForBankAccount", "DELETE", "/banks/BANK_ID/accounts/ACCOUNT_ID/views/VIEW_ID", - "Delete View", - "Deletes the view specified by VIEW_ID on the bank account specified by ACCOUNT_ID at bank BANK_ID", + "Delete Custom View", + "Deletes the custom view specified by VIEW_ID on the bank account specified by ACCOUNT_ID at bank BANK_ID", emptyObjectJson, emptyObjectJson, List( diff --git a/obp-api/src/main/scala/code/api/v3_0_0/APIMethods300.scala b/obp-api/src/main/scala/code/api/v3_0_0/APIMethods300.scala index ba4a302bb0..f5d93dc72e 100644 --- a/obp-api/src/main/scala/code/api/v3_0_0/APIMethods300.scala +++ b/obp-api/src/main/scala/code/api/v3_0_0/APIMethods300.scala @@ -138,8 +138,8 @@ trait APIMethods300 { nameOf(createViewForBankAccount), "POST", "/banks/BANK_ID/accounts/ACCOUNT_ID/views", - "Create View", - s"""Create a view on bank account + "Create Custom View", + s"""Create a custom view on bank account | | ${authenticationRequiredMessage(true)} and the user needs to have access to the owner view. | The 'alias' field in the JSON can take one of three values: @@ -245,8 +245,8 @@ trait APIMethods300 { nameOf(updateViewForBankAccount), "PUT", "/banks/BANK_ID/accounts/ACCOUNT_ID/views/VIEW_ID", - "Update View", - s"""Update an existing view on a bank account + "Update Custom View", + s"""Update an existing custom view on a bank account | |${authenticationRequiredMessage(true)} and the user needs to have access to the owner view. | From 5062159ee6750675daec1839c72683d38b4de215 Mon Sep 17 00:00:00 2001 From: hongwei Date: Thu, 13 Jul 2023 18:29:42 +0800 Subject: [PATCH 39/41] refactor/put the CustomView permissions to system views --- .../src/main/scala/code/views/system/ViewDefinition.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/obp-api/src/main/scala/code/views/system/ViewDefinition.scala b/obp-api/src/main/scala/code/views/system/ViewDefinition.scala index e1e53d51e8..ac00941019 100644 --- a/obp-api/src/main/scala/code/views/system/ViewDefinition.scala +++ b/obp-api/src/main/scala/code/views/system/ViewDefinition.scala @@ -353,6 +353,9 @@ class ViewDefinition extends View with LongKeyedMapper[ViewDefinition] with Many canRevokeAccessToCustomViews_(actions.exists(_ == "can_revoke_access_to_custom_views")) canGrantAccessToViews_(viewData.can_grant_access_to_views.getOrElse(Nil).mkString(",")) canRevokeAccessToViews_(viewData.can_revoke_access_to_views.getOrElse(Nil).mkString(",")) + canCreateCustomView_(actions.exists(_ == "can_create_custom_view")) + canDeleteCustomView_(actions.exists(_ == "can_delete_custom_view")) + canUpdateCustomView_(actions.exists(_ == "can_update_custom_view")) } canSeeTransactionThisBankAccount_(actions.exists(_ =="can_see_transaction_this_bank_account")) @@ -436,9 +439,6 @@ class ViewDefinition extends View with LongKeyedMapper[ViewDefinition] with Many canSeeTransactionRequestTypes_(actions.exists(_ == "can_see_transaction_request_types")) canUpdateBankAccountLabel_(actions.exists(_ == "can_update_bank_account_label")) canSeeAvailableViewsForBankAccount_(actions.exists(_ == "can_see_available_views_for_bank_account")) - canCreateCustomView_(actions.exists(_ == "can_create_custom_view")) - canDeleteCustomView_(actions.exists(_ == "can_delete_custom_view")) - canUpdateCustomView_(actions.exists(_ == "can_update_custom_view")) canSeeViewsWithPermissionsForAllUsers_(actions.exists(_ == "can_see_views_with_permissions_for_all_users")) canSeeViewsWithPermissionsForOneUser_(actions.exists(_ == "can_see_views_with_permissions_for_one_user")) } From 392fe30addacaa222a5e5d8edcfe275f67c260e7 Mon Sep 17 00:00:00 2001 From: hongwei Date: Thu, 13 Jul 2023 18:30:39 +0800 Subject: [PATCH 40/41] refactor/added the comments --- .../scala/com/openbankproject/commons/model/ViewModel.scala | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/obp-commons/src/main/scala/com/openbankproject/commons/model/ViewModel.scala b/obp-commons/src/main/scala/com/openbankproject/commons/model/ViewModel.scala index ad50663c52..cb15827286 100644 --- a/obp-commons/src/main/scala/com/openbankproject/commons/model/ViewModel.scala +++ b/obp-commons/src/main/scala/com/openbankproject/commons/model/ViewModel.scala @@ -250,8 +250,7 @@ trait View { def usePrivateAliasIfOneExists: Boolean def hideOtherAccountMetadataIfAlias: Boolean - //TODO, in progress, we only make the system view work, the custom views are still in progress.. -// https://gitlab-external.tesobe.com/tesobe/boards/tech-internal/-/issues/314 + //TODO, in progress, we only make the system view work, the custom views are VIP. def canGrantAccessToViews : Option[List[String]] = None def canGrantAccessToCustomViews : Boolean // if this true, we can grant custom views, if it is false, no one can grant custom views. def canRevokeAccessToViews : Option[List[String]] = None From eeb91e690a81c8e1c61225221c477eb96f698958 Mon Sep 17 00:00:00 2001 From: hongwei Date: Thu, 13 Jul 2023 19:40:52 +0800 Subject: [PATCH 41/41] refactor/removed the unused methods --- .../main/scala/code/api/util/NewStyle.scala | 16 ------------ .../scala/code/api/v4_0_0/APIMethods400.scala | 12 ++++++--- obp-api/src/main/scala/code/util/Helper.scala | 25 ------------------- 3 files changed, 9 insertions(+), 44 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 327c909d99..6d76959291 100644 --- a/obp-api/src/main/scala/code/api/util/NewStyle.scala +++ b/obp-api/src/main/scala/code/api/util/NewStyle.scala @@ -716,22 +716,6 @@ object NewStyle extends MdcLoggable{ } } } - - def canGrantAccessToView(bankId: BankId, accountId: AccountId, viewIdToBeGranted : ViewId, user: User, callContext: Option[CallContext]) : Future[Box[Boolean]] = { - Helper.wrapStatementToFuture(UserLacksPermissionCanGrantAccessToViewForTargetAccount) { - APIUtil.canGrantAccessToView(bankId, accountId, viewIdToBeGranted, user, callContext) - } - } - def canRevokeAccessToView(bankId: BankId, accountId: AccountId, viewIdToBeRevoked : ViewId, user: User, callContext: Option[CallContext]) : Future[Box[Boolean]] = { - Helper.wrapStatementToFuture(UserLacksPermissionCanRevokeAccessToViewForTargetAccount) { - APIUtil.canRevokeAccessToView(bankId, accountId,viewIdToBeRevoked, user, callContext) - } - } - def canRevokeAccessToAllView(bankId: BankId, accountId: AccountId, user: User, callContext: Option[CallContext]) : Future[Box[Boolean]] = { - Helper.wrapStatementToFuture(UserLacksPermissionCanRevokeAccessToViewForTargetAccount) { - APIUtil.canRevokeAccessToAllViews(bankId, accountId, user, callContext) - } - } def createSystemView(view: CreateViewJson, callContext: Option[CallContext]) : Future[View] = { Views.views.vend.createSystemView(view) map { unboxFullOrFail(_, callContext, s"$CreateSystemViewError") diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala index e52ada7e60..13b55d7f7b 100644 --- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala +++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala @@ -4393,7 +4393,9 @@ trait APIMethods400 { postJson <- NewStyle.function.tryons(failMsg, 400, cc.callContext) { json.extract[PostAccountAccessJsonV400] } - _ <- NewStyle.function.canGrantAccessToView(bankId, accountId, ViewId(postJson.view.view_id), u, callContext) + _ <- Helper.booleanToFuture(UserLacksPermissionCanGrantAccessToViewForTargetAccount, cc = cc.callContext) { + APIUtil.canGrantAccessToView(bankId, accountId, ViewId(postJson.view.view_id), u, callContext) + } (user, callContext) <- NewStyle.function.findByUserId(postJson.user_id, callContext) view <- getView(bankId, accountId, postJson.view, callContext) addedView <- grantAccountAccessToUser(bankId, accountId, user, view, callContext) @@ -4504,7 +4506,9 @@ trait APIMethods400 { json.extract[PostAccountAccessJsonV400] } viewId = ViewId(postJson.view.view_id) - _ <- NewStyle.function.canRevokeAccessToView(bankId, accountId, viewId, u, cc.callContext) + _ <- Helper.booleanToFuture(UserLacksPermissionCanGrantAccessToViewForTargetAccount, cc = cc.callContext) { + APIUtil.canRevokeAccessToView(bankId, accountId, viewId, u, callContext) + } (user, callContext) <- NewStyle.function.findByUserId(postJson.user_id, cc.callContext) view <- postJson.view.is_system match { case true => NewStyle.function.systemView(viewId, callContext) @@ -4556,7 +4560,9 @@ trait APIMethods400 { postJson <- NewStyle.function.tryons(failMsg, 400, cc.callContext) { json.extract[PostRevokeGrantAccountAccessJsonV400] } - _ <- NewStyle.function.canRevokeAccessToAllView(bankId, accountId, u, cc.callContext) + _ <- Helper.booleanToFuture(UserLacksPermissionCanGrantAccessToViewForTargetAccount, cc = cc.callContext) { + APIUtil.canRevokeAccessToAllViews(bankId, accountId, u, callContext) + } _ <- Future(Views.views.vend.revokeAccountAccessByUser(bankId, accountId, u, callContext)) map { unboxFullOrFail(_, callContext, s"Cannot revoke") } diff --git a/obp-api/src/main/scala/code/util/Helper.scala b/obp-api/src/main/scala/code/util/Helper.scala index 5a67a57887..4024cee9f2 100644 --- a/obp-api/src/main/scala/code/util/Helper.scala +++ b/obp-api/src/main/scala/code/util/Helper.scala @@ -117,31 +117,6 @@ object Helper{ x => fullBoxOrException(x ~> APIFailureNewStyle(failMsg, failCode, cc.map(_.toLight))) } } - /** - * Helper function which wrap some statement into Future. - * The function is curried i.e. - * use this parameter syntax ---> (failMsg: String)(statement: => Boolean) - * instead of this one ---------> (failMsg: String, statement: => Boolean) - * Below is an example of recommended usage. - * Please note that the second parameter is provided in curly bracket in order to mimics body of a function. - * booleanToFuture(failMsg = UserHasMissingRoles + CanGetAnyUser) { - * hasEntitlement("", u.userId, ApiRole.CanGetAnyUser) - * } - * @param failMsg is used in case that result of call of function booleanToBox returns Empty - * @param statement is call by name parameter. - * @return In case the statement is false the function returns Future[Failure(failMsg)]. - * Otherwise returns Future[Full()]. - */ - def wrapStatementToFuture(failMsg: String, failCode: Int = 400)(statement: => Boolean): Future[Box[Boolean]] = { - Future { - statement match { - case true => Full(statement) - case false => Empty - } - } map { - x => fullBoxOrException(x ~> APIFailureNewStyle(failMsg, failCode)) - } - } val deprecatedJsonGenerationMessage = "json generation handled elsewhere as it changes from api version to api version"