refactor/remove hasOwnerViewAccess replace with specific view permissions -- added canSeePermissionForOneUser_, canSeePermissionsForAllUsers_

This commit is contained in:
hongwei 2023-06-23 17:38:08 +08:00
parent f65e4bca5d
commit 44f5321e84
12 changed files with 82 additions and 52 deletions

View File

@ -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. "

View File

@ -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(_)

View File

@ -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)

View File

@ -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))

View File

@ -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))

View File

@ -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))
}

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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
}
}

View File

@ -325,6 +325,10 @@ trait View {
def canSeeBankAccountRoutingAddress: Boolean
def canSeePermissionForOneUser: Boolean
def canSeePermissionsForAllUsers: Boolean
//other bank account (counterparty) fields
def canSeeOtherAccountNationalIdentifier: Boolean