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 27f1f147b..982b1067b 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 96a932679..e1e2a3452 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 2b05a20b9..3b2768d77 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 7e2f60d4d..31ee40bd4 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 8b73b1594..0cc0a8597 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 0fd327cc2..392caa668 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 0e06e38a0..cdb2347d3 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 8a1d427d2..9a0d1144d 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 44a40a3f0..637fba7de 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 1cf88b3d8..9256c6390 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 a25c145db..03f96341a 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 21e1bf2c1..f12d74dfa 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