mirror of
https://github.com/OpenBankProject/OBP-API.git
synced 2026-02-06 19:16:53 +00:00
Merge pull request #2200 from hongwei1/develop
refactor/use viewId instead of view_fk for accountAccess
This commit is contained in:
commit
95cd455ea6
@ -3851,8 +3851,14 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{
|
||||
if(range1.end.before(range2.start) || range1.start.after(range2.end)) false else true
|
||||
}
|
||||
|
||||
def checkCustomViewName(name: String): Boolean = name match {
|
||||
case x if x == "_" + SYSTEM_OWNER_VIEW_ID => false // Reserved name
|
||||
//we need set guard to easily distinguish the system view and custom view,
|
||||
// customer view must start with '_', system can not
|
||||
// viewName and viewId are the same value, just with different format, eg: createViewIdByName(view.name)
|
||||
def checkSystemViewIdOrName(viewId: String): Boolean = !checkCustomViewIdOrName(viewId: String)
|
||||
|
||||
//customer views are started ith `_`,eg _life, _work, and System views startWith letter, eg: owner
|
||||
// viewName and viewId are the same value, just with different format, eg: createViewIdByName(view.name)
|
||||
def checkCustomViewIdOrName(name: String): Boolean = name match {
|
||||
case x if x.startsWith("_") => true // Allowed case
|
||||
case _ => false
|
||||
}
|
||||
|
||||
@ -142,7 +142,8 @@ object ErrorMessages {
|
||||
|
||||
val InvalidInternalRedirectUrl = "OBP-20018: Login failed, invalid internal redirectUrl."
|
||||
val UserNoOwnerView = "OBP-20019: User does not have access to owner view. "
|
||||
val InvalidCustomViewFormat = s"OBP-20020: View name must start with `_`. eg: _work, _life. "
|
||||
val InvalidCustomViewFormat = s"OBP-20020: Custom view name/view_id must start with `_`. eg: _work, _life. "
|
||||
val InvalidSystemViewFormat = s"OBP-20020: System view name/view_id can not start with '_'. eg: owner, standard. "
|
||||
val SystemViewsCanNotBeModified = "OBP-20021: System Views can not be modified. Only the created views can be modified."
|
||||
val ViewDoesNotPermitAccess = "OBP-20022: View does not permit the access."
|
||||
|
||||
|
||||
@ -56,7 +56,7 @@ trait APIMethods121 {
|
||||
.map(JSONFactory.createViewJSON(_))
|
||||
.distinct) ++
|
||||
(privateViewsUserCanAccess
|
||||
.filter(v =>v.accountId.value==null && v.bankId.value == null && v.isSystem && v.isPrivate)//plus the system views.
|
||||
.filter(v =>v.isSystem && v.isPrivate)//plus the system views.
|
||||
.map(JSONFactory.createViewJSON(_))
|
||||
.distinct)
|
||||
JSONFactory.createAccountJSON(account,viewsAvailable)
|
||||
@ -594,7 +594,7 @@ trait APIMethods121 {
|
||||
u <- cc.user ?~ UserNotLoggedIn
|
||||
createViewJsonV121 <- tryo{json.extract[CreateViewJsonV121]} ?~ InvalidJsonFormat
|
||||
//customer views are started ith `_`,eg _life, _work, and System views startWith letter, eg: owner
|
||||
_<- booleanToBox(checkCustomViewName(createViewJsonV121.name), InvalidCustomViewFormat)
|
||||
_<- booleanToBox(checkCustomViewIdOrName(createViewJsonV121.name), InvalidCustomViewFormat+s"Current view_name (${createViewJsonV121.name})")
|
||||
account <- BankAccountX(bankId, accountId) ?~! BankAccountNotFound
|
||||
createViewJson = CreateViewJson(
|
||||
createViewJsonV121.name,
|
||||
@ -605,7 +605,7 @@ trait APIMethods121 {
|
||||
createViewJsonV121.hide_metadata_if_alias_used,
|
||||
createViewJsonV121.allowed_actions
|
||||
)
|
||||
view <- account createView (u, createViewJson)
|
||||
view <- account createCustomView (u, createViewJson)
|
||||
} yield {
|
||||
val viewJSON = JSONFactory.createViewJSON(view)
|
||||
successJsonResponse(Extraction.decompose(viewJSON), 201)
|
||||
@ -649,7 +649,7 @@ trait APIMethods121 {
|
||||
account <- BankAccountX(bankId, accountId) ?~! BankAccountNotFound
|
||||
u <- cc.user ?~ UserNotLoggedIn
|
||||
//customer views are started ith `_`,eg _life, _work, and System views startWith letter, eg: owner
|
||||
_ <- booleanToBox(viewId.value.startsWith("_"), InvalidCustomViewFormat)
|
||||
_ <- booleanToBox(viewId.value.startsWith("_"), InvalidCustomViewFormat +s"Current view_id (${viewId.value})")
|
||||
view <- Views.views.vend.customView(viewId, BankIdAccountId(bankId, accountId)) ?~! ViewNotFound
|
||||
_ <- booleanToBox(!view.isSystem, SystemViewsCanNotBeModified)
|
||||
updateViewJson = UpdateViewJSON(
|
||||
@ -697,7 +697,7 @@ trait APIMethods121 {
|
||||
(_, callContext) <- NewStyle.function.getBank(bankId, callContext)
|
||||
(account, callContext) <- NewStyle.function.getBankAccount(bankId, accountId, callContext)
|
||||
// custom views start with `_` eg _play, _work, and System views start with a letter, eg: owner
|
||||
_ <- Helper.booleanToFuture(InvalidCustomViewFormat, cc=callContext) { viewId.value.startsWith("_") }
|
||||
_ <- 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)
|
||||
} yield {
|
||||
|
||||
@ -151,7 +151,7 @@ trait APIMethods220 {
|
||||
for {
|
||||
createViewJsonV121 <- tryo{json.extract[CreateViewJsonV121]} ?~!InvalidJsonFormat
|
||||
//customer views are started ith `_`,eg _life, _work, and System views startWith letter, eg: owner
|
||||
_<- booleanToBox(checkCustomViewName(createViewJsonV121.name), InvalidCustomViewFormat)
|
||||
_<- booleanToBox(checkCustomViewIdOrName(createViewJsonV121.name), InvalidCustomViewFormat+s"Current view_name (${createViewJsonV121.name})")
|
||||
u <- cc.user ?~!UserNotLoggedIn
|
||||
account <- BankAccountX(bankId, accountId) ?~! BankAccountNotFound
|
||||
createViewJson = CreateViewJson(
|
||||
@ -163,7 +163,7 @@ trait APIMethods220 {
|
||||
createViewJsonV121.hide_metadata_if_alias_used,
|
||||
createViewJsonV121.allowed_actions
|
||||
)
|
||||
view <- account createView (u, createViewJson)
|
||||
view <- account createCustomView (u, createViewJson)
|
||||
} yield {
|
||||
val viewJSON = JSONFactory220.createViewJSON(view)
|
||||
successJsonResponse(Extraction.decompose(viewJSON), 201)
|
||||
@ -203,7 +203,7 @@ trait APIMethods220 {
|
||||
for {
|
||||
updateJsonV121 <- tryo{json.extract[UpdateViewJsonV121]} ?~!InvalidJsonFormat
|
||||
//customer views are started ith `_`,eg _life, _work, and System views startWith letter, eg: owner
|
||||
_ <- booleanToBox(viewId.value.startsWith("_"), InvalidCustomViewFormat)
|
||||
_ <- booleanToBox(viewId.value.startsWith("_"), InvalidCustomViewFormat+s"Current view_name (${viewId.value})")
|
||||
view <- APIUtil.checkViewAccessAndReturnView(viewId, BankIdAccountId(bankId, accountId), cc.user)
|
||||
_ <- booleanToBox(!view.isSystem, SystemViewsCanNotBeModified)
|
||||
u <- cc.user ?~!UserNotLoggedIn
|
||||
|
||||
@ -170,13 +170,13 @@ trait APIMethods300 {
|
||||
x => unboxFullOrFail(x, callContext, msg)
|
||||
}
|
||||
//customer views are started ith `_`,eg _life, _work, and System views startWith letter, eg: owner
|
||||
_ <- Helper.booleanToFuture(failMsg = InvalidCustomViewFormat, cc=callContext) {
|
||||
checkCustomViewName(createViewJson.name)
|
||||
_ <- Helper.booleanToFuture(failMsg = InvalidCustomViewFormat+s"Current view_name (${createViewJson.name})", cc=callContext) {
|
||||
checkCustomViewIdOrName(createViewJson.name)
|
||||
}
|
||||
(account, callContext) <- NewStyle.function.getBankAccount(bankId, accountId, callContext)
|
||||
} yield {
|
||||
for {
|
||||
view <- account createView (u, createViewJson)
|
||||
view <- account createCustomView (u, createViewJson)
|
||||
} yield {
|
||||
(JSONFactory300.createViewJSON(view), callContext.map(_.copy(httpCode = Some(201))))
|
||||
}
|
||||
@ -256,7 +256,7 @@ trait APIMethods300 {
|
||||
x => unboxFullOrFail(x, callContext, msg)
|
||||
}
|
||||
//customer views are started ith `_`,eg _life, _work, and System views startWith letter, eg: owner
|
||||
_ <- Helper.booleanToFuture(failMsg = InvalidCustomViewFormat, cc=callContext) {
|
||||
_ <- Helper.booleanToFuture(failMsg = InvalidCustomViewFormat+s"Current view_name (${viewId.value})", cc=callContext) {
|
||||
updateJson.metadata_view.startsWith("_")
|
||||
}
|
||||
_ <- Views.views.vend.customViewFuture(ViewId(viewId.value), BankIdAccountId(bankId, accountId)) map {
|
||||
|
||||
@ -3921,6 +3921,10 @@ trait APIMethods310 {
|
||||
createViewJson <- NewStyle.function.tryons(failMsg, 400, callContext) {
|
||||
json.extract[CreateViewJsonV300]
|
||||
}
|
||||
//System views can not startwith '_'
|
||||
_ <- Helper.booleanToFuture(failMsg = InvalidSystemViewFormat+s"Current view_name (${createViewJson.name})", cc = callContext) {
|
||||
checkSystemViewIdOrName(createViewJson.name)
|
||||
}
|
||||
_ <- Helper.booleanToFuture(SystemViewCannotBePublicError, failCode=400, cc=callContext) {
|
||||
createViewJson.is_public == false
|
||||
}
|
||||
|
||||
@ -1772,6 +1772,10 @@ trait APIMethods500 {
|
||||
_ <- Helper.booleanToFuture(SystemViewCannotBePublicError, failCode=400, cc=cc.callContext) {
|
||||
createViewJson.is_public == false
|
||||
}
|
||||
// custom views are started with `_`,eg _ life, _ work, and System views can not, eg: owner.
|
||||
_ <- Helper.booleanToFuture(failMsg = InvalidSystemViewFormat +s"Current view_name (${createViewJson.name})", cc = cc.callContext) {
|
||||
checkSystemViewIdOrName(createViewJson.name)
|
||||
}
|
||||
view <- NewStyle.function.createSystemView(createViewJson.toCreateViewJson, cc.callContext)
|
||||
} yield {
|
||||
(createViewJsonV500(view), HttpCode.`201`(cc.callContext))
|
||||
|
||||
@ -4,7 +4,7 @@ import java.util.Date
|
||||
import java.util.UUID.randomUUID
|
||||
import _root_.akka.http.scaladsl.model.HttpMethod
|
||||
import code.accountholders.{AccountHolders, MapperAccountHolders}
|
||||
import code.api.Constant.localIdentityProvider
|
||||
import code.api.Constant.{SYSTEM_ACCOUNTANT_VIEW_ID, SYSTEM_AUDITOR_VIEW_ID, SYSTEM_OWNER_VIEW_ID, localIdentityProvider}
|
||||
import code.api.attributedefinition.AttributeDefinition
|
||||
import code.api.cache.Caching
|
||||
import code.api.util.APIUtil.{OBPReturnType, _}
|
||||
@ -1767,7 +1767,7 @@ trait Connector extends MdcLoggable {
|
||||
|
||||
val ownerView: Box[View] =
|
||||
if(owner_view)
|
||||
Views.views.vend.getOrCreateOwnerView(bankId, accountId, "Owner View")
|
||||
Views.views.vend.getOrCreateSystemView(SYSTEM_OWNER_VIEW_ID)
|
||||
else Empty
|
||||
|
||||
val publicView: Box[View] =
|
||||
@ -1777,12 +1777,12 @@ trait Connector extends MdcLoggable {
|
||||
|
||||
val accountantsView: Box[View] =
|
||||
if(accountants_view)
|
||||
Views.views.vend.getOrCreateAccountantsView(bankId, accountId, "Accountants View")
|
||||
Views.views.vend.getOrCreateSystemView(SYSTEM_ACCOUNTANT_VIEW_ID)
|
||||
else Empty
|
||||
|
||||
val auditorsView: Box[View] =
|
||||
if(auditors_view)
|
||||
Views.views.vend.getOrCreateAuditorsView(bankId, accountId, "Auditors View")
|
||||
Views.views.vend.getOrCreateSystemView(SYSTEM_AUDITOR_VIEW_ID)
|
||||
else Empty
|
||||
|
||||
List(ownerView, publicView, accountantsView, auditorsView).flatten
|
||||
|
||||
@ -10,7 +10,7 @@ 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, localIdentityProvider}
|
||||
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.ResourceDocs1_4_0.SwaggerDefinitionsJSON
|
||||
import code.api.attributedefinition.{AttributeDefinition, AttributeDefinitionDI}
|
||||
import code.api.cache.Caching
|
||||
@ -5550,7 +5550,7 @@ object LocalMappedConnector extends Connector with MdcLoggable {
|
||||
|
||||
val ownerView: Box[View] =
|
||||
if (owner_view)
|
||||
Views.views.vend.getOrCreateOwnerView(bankId, accountId, "Owner View")
|
||||
Views.views.vend.getOrCreateSystemView(SYSTEM_OWNER_VIEW_ID)
|
||||
else Empty
|
||||
|
||||
val publicView: Box[View] =
|
||||
@ -5560,12 +5560,12 @@ object LocalMappedConnector extends Connector with MdcLoggable {
|
||||
|
||||
val accountantsView: Box[View] =
|
||||
if (accountants_view)
|
||||
Views.views.vend.getOrCreateAccountantsView(bankId, accountId, "Accountants View")
|
||||
Views.views.vend.getOrCreateSystemView(SYSTEM_ACCOUNTANT_VIEW_ID)
|
||||
else Empty
|
||||
|
||||
val auditorsView: Box[View] =
|
||||
if (auditors_view)
|
||||
Views.views.vend.getOrCreateAuditorsView(bankId, accountId, "Auditors View")
|
||||
Views.views.vend.getOrCreateSystemView(SYSTEM_AUDITOR_VIEW_ID)
|
||||
else Empty
|
||||
|
||||
List(ownerView, publicView, accountantsView, auditorsView).flatten
|
||||
|
||||
@ -346,11 +346,11 @@ case class BankAccountExtended(val bankAccount: BankAccount) extends MdcLoggable
|
||||
}
|
||||
|
||||
|
||||
final def createView(userDoingTheCreate : User,v: CreateViewJson): Box[View] = {
|
||||
final def createCustomView(userDoingTheCreate : User,v: CreateViewJson): Box[View] = {
|
||||
if(!userDoingTheCreate.hasOwnerViewAccess(BankIdAccountId(bankId,accountId))) {
|
||||
Failure({"user: " + userDoingTheCreate.idGivenByProvider + " at provider " + userDoingTheCreate.provider + " does not have owner access"})
|
||||
} else {
|
||||
val view = Views.views.vend.createView(BankIdAccountId(bankId,accountId), v)
|
||||
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 +
|
||||
|
||||
@ -69,7 +69,7 @@ case class UserExtended(val user: User) extends MdcLoggable {
|
||||
AccountAccess.find(
|
||||
By(AccountAccess.bank_id, bankIdAccountId.bankId.value),
|
||||
By(AccountAccess.account_id, bankIdAccountId.accountId.value),
|
||||
By(AccountAccess.view_fk, viewDefinition.id),
|
||||
By(AccountAccess.view_id, viewDefinition.viewId.value),
|
||||
By(AccountAccess.user_fk, this.userPrimaryKey.value),
|
||||
By(AccountAccess.consumer_id, consumerId.get)).isDefined
|
||||
} else {
|
||||
@ -83,7 +83,7 @@ case class UserExtended(val user: User) extends MdcLoggable {
|
||||
AccountAccess.find(
|
||||
By(AccountAccess.bank_id, bankIdAccountId.bankId.value),
|
||||
By(AccountAccess.account_id, bankIdAccountId.accountId.value),
|
||||
By(AccountAccess.view_fk, viewDefinition.id),
|
||||
By(AccountAccess.view_id, viewDefinition.viewId.value),
|
||||
By(AccountAccess.user_fk, this.userPrimaryKey.value),
|
||||
By(AccountAccess.consumer_id, ALL_CONSUMERS)
|
||||
).isDefined
|
||||
|
||||
@ -73,7 +73,7 @@ object RemotedataViews extends ObpActorInit with Views {
|
||||
(actor ? cc.getSystemViews()).mapTo[List[View]]
|
||||
|
||||
|
||||
def createView(bankAccountId: BankIdAccountId, view: CreateViewJson): Box[View] = getValueFromFuture(
|
||||
def createCustomView(bankAccountId: BankIdAccountId, view: CreateViewJson): Box[View] = getValueFromFuture(
|
||||
(actor ? cc.createView(bankAccountId, view)).mapTo[Box[View]]
|
||||
)
|
||||
def createSystemView(view: CreateViewJson): Future[Box[View]] =
|
||||
@ -136,20 +136,12 @@ object RemotedataViews extends ObpActorInit with Views {
|
||||
(actor ? cc.getOrCreateAccountView(bankAccountUID: BankIdAccountId, viewId: String)).mapTo[Box[View]]
|
||||
)
|
||||
|
||||
def getOrCreateOwnerView(bankId: BankId, accountId: AccountId, description: String) : Box[View] = getValueFromFuture(
|
||||
(actor ? cc.getOrCreateOwnerView(bankId, accountId, description)).mapTo[Box[View]]
|
||||
)
|
||||
|
||||
def getOrCreateSystemView(name: String) : Box[View] = getValueFromFuture(
|
||||
(actor ? cc.getOrCreateSystemView(name)).mapTo[Box[View]]
|
||||
)
|
||||
|
||||
def getOrCreateFirehoseView(bankId: BankId, accountId: AccountId, description: String) : Box[View] = getValueFromFuture(
|
||||
(actor ? cc.getOrCreateFirehoseView(bankId, accountId, description)).mapTo[Box[View]]
|
||||
def getOrCreateSystemView(viewId: String) : Box[View] = getValueFromFuture(
|
||||
(actor ? cc.getOrCreateSystemView(viewId)).mapTo[Box[View]]
|
||||
)
|
||||
|
||||
def getOrCreateCustomPublicView(bankId: BankId, accountId: AccountId, description: String) : Box[View] = getValueFromFuture(
|
||||
(actor ? cc.getOrCreatePublicView(bankId, accountId, description)).mapTo[Box[View]]
|
||||
(actor ? cc.getOrCreatePublicPublicView(bankId, accountId, description)).mapTo[Box[View]]
|
||||
)
|
||||
|
||||
def getOrCreateAccountantsView(bankId: BankId, accountId: AccountId, description: String) : Box[View] = getValueFromFuture(
|
||||
|
||||
@ -83,7 +83,7 @@ class RemotedataViewsActor extends Actor with ObpActorHelper with MdcLoggable {
|
||||
|
||||
case cc.createView(bankAccountId : BankIdAccountId, view: CreateViewJson) =>
|
||||
logger.debug("createView(" + bankAccountId +","+ view +")")
|
||||
sender ! (mapper.createView(bankAccountId, view))
|
||||
sender ! (mapper.createCustomView(bankAccountId, view))
|
||||
|
||||
case cc.createSystemView(view: CreateViewJson) =>
|
||||
logger.debug("createSystemView(" + view +")")
|
||||
@ -140,21 +140,13 @@ class RemotedataViewsActor extends Actor with ObpActorHelper with MdcLoggable {
|
||||
case cc.getOrCreateAccountView(bankAccountUID: BankIdAccountId, viewId: String) =>
|
||||
logger.debug("getOrCreateAccountView(" + BankIdAccountId +", "+ viewId +")")
|
||||
sender ! (mapper.getOrCreateAccountView(bankAccountUID: BankIdAccountId, viewId: String))
|
||||
|
||||
case cc.getOrCreateOwnerView(bankId, accountId, description) =>
|
||||
logger.debug("getOrCreateOwnerView(" + bankId +", "+ accountId +", "+ description +")")
|
||||
sender ! (mapper.getOrCreateOwnerView(bankId, accountId, description))
|
||||
|
||||
case cc.getOrCreateSystemView(name) =>
|
||||
logger.debug("getOrCreateSystemOwnerView(" + name +")")
|
||||
sender ! (mapper.getOrCreateSystemView(name))
|
||||
|
||||
case cc.getOrCreateFirehoseView(bankId, accountId, description) =>
|
||||
logger.debug("getOrCreateFirehoseView(" + bankId +", "+ accountId +", "+ description +")")
|
||||
sender ! (mapper.getOrCreateFirehoseView(bankId, accountId, description))
|
||||
|
||||
case cc.getOrCreatePublicView(bankId, accountId, description) =>
|
||||
logger.debug("getOrCreatePublicView(" + bankId +", "+ accountId +", "+ description +")")
|
||||
case cc.getOrCreatePublicPublicView(bankId, accountId, description) =>
|
||||
logger.debug("getOrCreatePublicPublicView(" + bankId +", "+ accountId +", "+ description +")")
|
||||
sender ! (mapper.getOrCreateCustomPublicView(bankId, accountId, description))
|
||||
|
||||
case cc.getOrCreateAccountantsView(bankId, accountId, description) =>
|
||||
|
||||
@ -30,28 +30,34 @@ object MapperViews extends Views with MdcLoggable {
|
||||
Schemifier.schemify(true, Schemifier.infoF _, ToSchemify.modelsRemotedata: _*)
|
||||
|
||||
private def getViewsForUser(user: User): List[View] = {
|
||||
val privileges = AccountAccess.findAll(
|
||||
val accountAccessList = AccountAccess.findAll(
|
||||
By(AccountAccess.user_fk, user.userPrimaryKey.value),
|
||||
OrderBy(AccountAccess.bank_id, Ascending),
|
||||
OrderBy(AccountAccess.account_id, Ascending)
|
||||
)
|
||||
getViewsCommonPart(privileges)
|
||||
getViewsCommonPart(accountAccessList)
|
||||
}
|
||||
private def getViewsForUserAndAccount(user: User, account : BankIdAccountId): List[View] = {
|
||||
val privileges = AccountAccess.findAll(
|
||||
val accountAccessList = AccountAccess.findAll(
|
||||
By(AccountAccess.user_fk, user.userPrimaryKey.value),
|
||||
By(AccountAccess.bank_id, account.bankId.value),
|
||||
By(AccountAccess.account_id, account.accountId.value)
|
||||
)
|
||||
getViewsCommonPart(privileges)
|
||||
getViewsCommonPart(accountAccessList)
|
||||
}
|
||||
|
||||
private def getViewsCommonPart(privileges: List[AccountAccess]): List[View] = {
|
||||
val views: List[ViewDefinition] = privileges.flatMap(
|
||||
a =>
|
||||
ViewDefinition.find(By(ViewDefinition.id_, a.view_fk.get))
|
||||
.map(v => v.bank_id(a.bank_id.get).account_id(a.account_id.get))
|
||||
).filter(
|
||||
private def getViewFromAccountAccess(accountAccess: AccountAccess) = {
|
||||
if (checkSystemViewIdOrName(accountAccess.view_id.get)) {
|
||||
ViewDefinition.findSystemView(accountAccess.view_id.get)
|
||||
.map(v => v.bank_id(accountAccess.bank_id.get).account_id(accountAccess.account_id.get)) // in case system view do not contains the bankId, and accountId.
|
||||
} else {
|
||||
ViewDefinition.findCustomView(accountAccess.bank_id.get, accountAccess.account_id.get, accountAccess.view_id.get)
|
||||
}
|
||||
}
|
||||
|
||||
private def getViewsCommonPart(accountAccessList: List[AccountAccess]): List[View] = {
|
||||
//we need to get views from accountAccess
|
||||
val views: List[ViewDefinition] = accountAccessList.flatMap(getViewFromAccountAccess).filter(
|
||||
v =>
|
||||
if (allowPublicViews) {
|
||||
true // All views
|
||||
@ -89,9 +95,9 @@ object MapperViews extends Views with MdcLoggable {
|
||||
By(AccountAccess.user_fk, user.userPrimaryKey.value),
|
||||
By(AccountAccess.bank_id, bankId),
|
||||
By(AccountAccess.account_id, accountId),
|
||||
By(AccountAccess.view_fk, viewDefinition.id)) == 0) {
|
||||
//logger.debug(s"saving ViewPrivileges for user ${user.resourceUserId.value} for view ${vImpl.id}")
|
||||
// SQL Insert ViewPrivileges
|
||||
By(AccountAccess.view_id, viewDefinition.viewId.value)) == 0) {
|
||||
//logger.debug(s"saving AccountAccessList for user ${user.resourceUserId.value} for view ${vImpl.id}")
|
||||
// SQL Insert AccountAccessList
|
||||
val saved = AccountAccess.create.
|
||||
user_fk(user.userPrimaryKey.value).
|
||||
bank_id(bankId).
|
||||
@ -100,13 +106,13 @@ object MapperViews extends Views with MdcLoggable {
|
||||
view_fk(viewDefinition.id).
|
||||
save
|
||||
if (saved) {
|
||||
//logger.debug("saved ViewPrivileges")
|
||||
//logger.debug("saved AccountAccessList")
|
||||
Full(viewDefinition)
|
||||
} else {
|
||||
//logger.debug("failed to save ViewPrivileges")
|
||||
//logger.debug("failed to save AccountAccessList")
|
||||
Empty ~> APIFailure("Server error adding permission", 500) //TODO: move message + code logic to api level
|
||||
}
|
||||
} else Full(viewDefinition) //privilege already exists, no need to create one
|
||||
} else Full(viewDefinition) //accountAccess already exists, no need to create one
|
||||
}
|
||||
// This is an idempotent function
|
||||
private def getOrGrantAccessToSystemView(bankId: BankId, accountId: AccountId, user: User, view: View): Box[View] = {
|
||||
@ -123,9 +129,9 @@ object MapperViews extends Views with MdcLoggable {
|
||||
viewDefinition match {
|
||||
case Full(v) => {
|
||||
if(v.isPublic && !allowPublicViews) return Failure(PublicViewsNotAllowedOnThisInstance)
|
||||
// SQL Select Count ViewPrivileges where
|
||||
// SQL Select Count AccountAccessList where
|
||||
// This is idempotent
|
||||
getOrGrantAccessToCustomView(user, v, viewIdBankIdAccountId.bankId.value, viewIdBankIdAccountId.accountId.value) //privilege already exists, no need to create one
|
||||
getOrGrantAccessToCustomView(user, v, viewIdBankIdAccountId.bankId.value, viewIdBankIdAccountId.accountId.value) //accountAccess already exists, no need to create one
|
||||
}
|
||||
case _ => {
|
||||
Empty ~> APIFailure(s"View $viewIdBankIdAccountId. not found", 404) //TODO: move message + code logic to api level
|
||||
@ -187,25 +193,28 @@ object MapperViews extends Views with MdcLoggable {
|
||||
def revokeAccess(viewUID : ViewIdBankIdAccountId, user : User) : Box[Boolean] = {
|
||||
val isRevokedCustomViewAccess =
|
||||
for {
|
||||
viewDefinition <- ViewDefinition.findCustomView(viewUID.bankId.value, viewUID.accountId.value, viewUID.viewId.value)
|
||||
accountAccess <- AccountAccess.find(
|
||||
By(AccountAccess.user_fk, user.userPrimaryKey.value),
|
||||
By(AccountAccess.view_fk, viewDefinition.id)
|
||||
customViewDefinition <- ViewDefinition.findCustomView(viewUID.bankId.value, viewUID.accountId.value, viewUID.viewId.value)
|
||||
accountAccess <- AccountAccess.findByBankIdAccountIdViewIdUserPrimaryKey(
|
||||
viewUID.bankId,
|
||||
viewUID.accountId,
|
||||
viewUID.viewId,
|
||||
user.userPrimaryKey
|
||||
) ?~! CannotFindAccountAccess
|
||||
// Check if we are allowed to remove the View from the User
|
||||
_ <- canRevokeAccessAsBox(viewDefinition, user)
|
||||
} yield {
|
||||
accountAccess.delete_!
|
||||
}
|
||||
|
||||
val isRevokedSystemViewAccess =
|
||||
for {
|
||||
viewDefinition <- ViewDefinition.findSystemView(viewUID.viewId.value)
|
||||
accountAccess <- AccountAccess.find(
|
||||
By(AccountAccess.user_fk, user.userPrimaryKey.value),
|
||||
By(AccountAccess.view_fk, viewDefinition.id)
|
||||
systemViewDefinition <- ViewDefinition.findSystemView(viewUID.viewId.value)
|
||||
accountAccess <- AccountAccess.findByBankIdAccountIdViewIdUserPrimaryKey(
|
||||
viewUID.bankId,
|
||||
viewUID.accountId,
|
||||
viewUID.viewId,
|
||||
user.userPrimaryKey
|
||||
) ?~! CannotFindAccountAccess
|
||||
// Check if we are allowed to remove the View from the User
|
||||
_ <- canRevokeAccessAsBox(viewDefinition, user)
|
||||
_ <- canRevokeOwnerAccessAsBox(viewUID.bankId, viewUID.accountId,systemViewDefinition, user)
|
||||
} yield {
|
||||
accountAccess.delete_!
|
||||
}
|
||||
@ -217,16 +226,17 @@ object MapperViews extends Views with MdcLoggable {
|
||||
def revokeAccessToSystemView(bankId: BankId, accountId: AccountId, view : View, user : User) : Box[Boolean] = {
|
||||
val res =
|
||||
for {
|
||||
viewDefinition <- ViewDefinition.find(By(ViewDefinition.id_, view.id))
|
||||
aa <- AccountAccess.find(
|
||||
By(AccountAccess.user_fk, user.userPrimaryKey.value),
|
||||
By(AccountAccess.bank_id, bankId.value),
|
||||
By(AccountAccess.account_id, accountId.value),
|
||||
By(AccountAccess.view_fk, viewDefinition.id)) ?~! CannotFindAccountAccess
|
||||
systemViewDefinition <- ViewDefinition.find(By(ViewDefinition.id_, view.id))
|
||||
accountAccess <- AccountAccess.findByBankIdAccountIdViewIdUserPrimaryKey(
|
||||
bankId,
|
||||
accountId,
|
||||
view.viewId,
|
||||
user.userPrimaryKey
|
||||
) ?~! CannotFindAccountAccess
|
||||
// Check if we are allowed to remove the View from the User
|
||||
_ <- canRevokeAccessAsBox(viewDefinition, user)
|
||||
_ <- canRevokeOwnerAccessAsBox(bankId: BankId, accountId: AccountId, systemViewDefinition, user)
|
||||
} yield {
|
||||
aa.delete_!
|
||||
accountAccess.delete_!
|
||||
}
|
||||
res
|
||||
}
|
||||
@ -234,12 +244,12 @@ object MapperViews extends Views with MdcLoggable {
|
||||
//Custom View will have bankId and accountId inside the `View`, so no need both in the parameters
|
||||
def revokeAccessToCustomViewForConsumer(view : View, consumerId : String) : Box[Boolean] = {
|
||||
for {
|
||||
viewDefinition <- ViewDefinition.findCustomView(view.bankId.value, view.accountId.value, view.viewId.value)
|
||||
accountAccess <- AccountAccess.find(
|
||||
By(AccountAccess.consumer_id, consumerId),
|
||||
By(AccountAccess.view_fk, viewDefinition.id),
|
||||
By(AccountAccess.bank_id, view.bankId.value),
|
||||
By(AccountAccess.account_id, view.accountId.value)
|
||||
customViewDefinition <- ViewDefinition.findCustomView(view.bankId.value, view.accountId.value, view.viewId.value)
|
||||
accountAccess <- AccountAccess.findByBankIdAccountIdViewIdConsumerId(
|
||||
customViewDefinition.bankId,
|
||||
customViewDefinition.accountId,
|
||||
customViewDefinition.viewId,
|
||||
consumerId
|
||||
) ?~! CannotFindAccountAccess
|
||||
} yield {
|
||||
accountAccess.delete_!
|
||||
@ -249,25 +259,26 @@ object MapperViews extends Views with MdcLoggable {
|
||||
//System View only have the viewId in inside the `View`, both bankId and accountId are empty in the `View`. So we need both in the parameters
|
||||
def revokeAccessToSystemViewForConsumer(bankId: BankId, accountId: AccountId, view : View, consumerId : String) : Box[Boolean] = {
|
||||
for {
|
||||
viewDefinition <- ViewDefinition.find(By(ViewDefinition.id_, view.id))
|
||||
accountAccess <- AccountAccess.find(
|
||||
By(AccountAccess.consumer_id, consumerId),
|
||||
By(AccountAccess.bank_id, bankId.value),
|
||||
By(AccountAccess.account_id, accountId.value),
|
||||
By(AccountAccess.view_fk, viewDefinition.id)) ?~! CannotFindAccountAccess
|
||||
systemViewDefinition <- ViewDefinition.find(By(ViewDefinition.id_, view.id))
|
||||
accountAccess <- AccountAccess.findByBankIdAccountIdViewIdConsumerId(
|
||||
bankId,
|
||||
accountId,
|
||||
systemViewDefinition.viewId,
|
||||
consumerId
|
||||
) ?~! CannotFindAccountAccess
|
||||
} yield {
|
||||
accountAccess.delete_!
|
||||
}
|
||||
}
|
||||
|
||||
//returns Full if deletable, Failure if not
|
||||
def canRevokeAccessAsBox(viewImpl : ViewDefinition, user : User) : Box[Unit] = {
|
||||
if(canRevokeAccess(viewImpl, user)) Full(Unit)
|
||||
def canRevokeOwnerAccessAsBox(bankId: BankId, accountId: AccountId, viewImpl : ViewDefinition, user : User) : Box[Unit] = {
|
||||
if(canRevokeOwnerAccess(bankId: BankId, accountId: AccountId, viewImpl, user)) Full(Unit)
|
||||
else Failure("access cannot be revoked")
|
||||
}
|
||||
|
||||
|
||||
def canRevokeAccess(viewDefinition: ViewDefinition, user : User) : Boolean = {
|
||||
def canRevokeOwnerAccess(bankId: BankId, accountId: AccountId, viewDefinition: ViewDefinition, user : User) : Boolean = {
|
||||
if(viewDefinition.viewId == ViewId(SYSTEM_OWNER_VIEW_ID)) {
|
||||
//if the user is an account holder, we can't revoke access to the owner view
|
||||
val accountHolders = MapperAccountHolders.getAccountHolders(viewDefinition.bankId, viewDefinition.accountId)
|
||||
@ -276,7 +287,11 @@ object MapperViews extends Views with MdcLoggable {
|
||||
} else {
|
||||
// if it's the owner view, we can only revoke access if there would then still be someone else
|
||||
// with access
|
||||
AccountAccess.findAll(By(AccountAccess.view_fk, viewDefinition.id)).length > 1
|
||||
AccountAccess.findAllByBankIdAccountIdViewId(
|
||||
bankId: BankId,
|
||||
accountId: AccountId,
|
||||
viewDefinition.viewId
|
||||
).length > 1
|
||||
}
|
||||
} else {
|
||||
true
|
||||
@ -284,30 +299,31 @@ object MapperViews extends Views with MdcLoggable {
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
This removes the link between a User and a View (Account Access)
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
def revokeAllAccountAccess(bankId : BankId, accountId: AccountId, user : User) : Box[Boolean] = {
|
||||
//TODO: make this more efficient by using one query (with a join)
|
||||
val allUserPrivs = AccountAccess.findAll(By(AccountAccess.user_fk, user.userPrimaryKey.value))
|
||||
|
||||
val relevantAccountPrivs = allUserPrivs.filter(p => p.bank_id == bankId.value && p.account_id == accountId.value)
|
||||
|
||||
val allRelevantPrivsRevokable = relevantAccountPrivs.forall( p => p.view_fk.obj match {
|
||||
case Full(v) => canRevokeAccess(v, user)
|
||||
case _ => false
|
||||
})
|
||||
|
||||
|
||||
if(allRelevantPrivsRevokable) {
|
||||
relevantAccountPrivs.foreach(_.delete_!)
|
||||
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),
|
||||
By(AccountAccess.user_fk, user.userPrimaryKey.value)
|
||||
).foreach(_.delete_!)
|
||||
Full(true)
|
||||
} else {
|
||||
Failure("One of the views this user has access to is the owner view, and there would be no one with access" +
|
||||
" to this owner view if access to the user was revoked. No permissions to any views on the account have been revoked.")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
def revokeAccountAccessByUser(bankId : BankId, accountId: AccountId, user : User) : Box[Boolean] = {
|
||||
@ -355,7 +371,7 @@ object MapperViews extends Views with MdcLoggable {
|
||||
}
|
||||
}
|
||||
|
||||
def getNewViewPermalink(name: String) = {
|
||||
def createViewIdByName(name: String) = {
|
||||
name.replaceAllLiterally(" ", "").toLowerCase
|
||||
}
|
||||
/*
|
||||
@ -364,24 +380,26 @@ object MapperViews extends Views with MdcLoggable {
|
||||
def createSystemView(view: CreateViewJson) : Future[Box[View]] = Future {
|
||||
if(view.is_public) {
|
||||
Failure(SystemViewCannotBePublicError)
|
||||
}else if (!checkSystemViewIdOrName(view.name)) {
|
||||
Failure(InvalidSystemViewFormat+s"Current view_name (${view.name})")
|
||||
} else {
|
||||
view.name.contentEquals("") match {
|
||||
case true =>
|
||||
Failure(EmptyNameOfSystemViewError)
|
||||
case false =>
|
||||
//view-permalink is view.name without spaces and lowerCase. (view.name = my life) <---> (view-permalink = mylife)
|
||||
val newViewPermalink = getNewViewPermalink(view.name)
|
||||
val viewId = createViewIdByName(view.name)
|
||||
val existing = ViewDefinition.count(
|
||||
By(ViewDefinition.view_id, newViewPermalink),
|
||||
By(ViewDefinition.view_id, viewId),
|
||||
NullRef(ViewDefinition.bank_id),
|
||||
NullRef(ViewDefinition.account_id)
|
||||
) == 1
|
||||
|
||||
existing match {
|
||||
case true =>
|
||||
Failure(s"$ExistingSystemViewError $newViewPermalink")
|
||||
Failure(s"$ExistingSystemViewError $viewId")
|
||||
case false =>
|
||||
val createdView = ViewDefinition.create.name_(view.name).view_id(newViewPermalink)
|
||||
val createdView = ViewDefinition.create.name_(view.name).view_id(viewId)
|
||||
createdView.setFromViewData(view)
|
||||
createdView.isSystem_(true)
|
||||
createdView.isPublic_(false)
|
||||
@ -394,8 +412,12 @@ object MapperViews extends Views with MdcLoggable {
|
||||
/*
|
||||
Create View based on the Specification (name, alias behavior, what fields can be seen, actions are allowed etc. )
|
||||
* */
|
||||
def createView(bankAccountId: BankIdAccountId, view: CreateViewJson): Box[View] = {
|
||||
def createCustomView(bankAccountId: BankIdAccountId, view: CreateViewJson): Box[View] = {
|
||||
|
||||
if(!checkCustomViewIdOrName(view.name)) {
|
||||
return Failure(InvalidCustomViewFormat)
|
||||
}
|
||||
|
||||
if(view.is_public && !allowPublicViews) {
|
||||
return Failure(PublicViewsNotAllowedOnThisInstance)
|
||||
}
|
||||
@ -404,19 +426,19 @@ object MapperViews extends Views with MdcLoggable {
|
||||
return Failure("You cannot create a View with an empty Name")
|
||||
}
|
||||
//view-permalink is view.name without spaces and lowerCase. (view.name = my life) <---> (view-permalink = mylife)
|
||||
val newViewPermalink = getNewViewPermalink(view.name)
|
||||
val viewId = createViewIdByName(view.name)
|
||||
|
||||
val existing = ViewDefinition.count(
|
||||
By(ViewDefinition.view_id, newViewPermalink) ::
|
||||
By(ViewDefinition.view_id, viewId) ::
|
||||
ViewDefinition.accountFilter(bankAccountId.bankId, bankAccountId.accountId): _*
|
||||
) == 1
|
||||
|
||||
if (existing)
|
||||
Failure(s"There is already a view with permalink $newViewPermalink on this bank account")
|
||||
Failure(s"There is already a view with permalink $viewId on this bank account")
|
||||
else {
|
||||
val createdView = ViewDefinition.create.
|
||||
name_(view.name).
|
||||
view_id(newViewPermalink).
|
||||
view_id(viewId).
|
||||
bank_id(bankAccountId.bankId.value).
|
||||
account_id(bankAccountId.accountId.value)
|
||||
|
||||
@ -448,19 +470,23 @@ object MapperViews extends Views with MdcLoggable {
|
||||
|
||||
def removeCustomView(viewId: ViewId, bankAccountId: BankIdAccountId): Box[Boolean] = {
|
||||
for {
|
||||
view <- ViewDefinition.findCustomView(bankAccountId.bankId.value, bankAccountId.accountId.value, viewId.value)
|
||||
_ <- AccountAccess.find(By(AccountAccess.view_fk, view.id)).isDefined match {
|
||||
customView <- ViewDefinition.findCustomView(bankAccountId.bankId.value, bankAccountId.accountId.value, viewId.value)
|
||||
_ <- AccountAccess.findAllByBankIdAccountIdViewId(
|
||||
bankAccountId.bankId,
|
||||
bankAccountId.accountId,
|
||||
viewId
|
||||
).length > 0 match {
|
||||
case true => Failure("Account Access record uses this View.") // We want to prevent account access orphans
|
||||
case false => Full()
|
||||
}
|
||||
} yield {
|
||||
view.delete_!
|
||||
customView.delete_!
|
||||
}
|
||||
}
|
||||
def removeSystemView(viewId: ViewId): Future[Box[Boolean]] = Future {
|
||||
for {
|
||||
view <- ViewDefinition.findSystemView(viewId.value)
|
||||
_ <- AccountAccess.find(By(AccountAccess.view_fk, view.id)).isDefined match {
|
||||
_ <- AccountAccess.findAllBySystemViewId(viewId).length > 0 match {
|
||||
case true => Failure("Account Access record uses this View.") // We want to prevent account access orphans
|
||||
case false => Full()
|
||||
}
|
||||
@ -470,11 +496,10 @@ object MapperViews extends Views with MdcLoggable {
|
||||
}
|
||||
|
||||
def assignedViewsForAccount(bankAccountId : BankIdAccountId) : List[View] = {
|
||||
AccountAccess.findAll(
|
||||
By(AccountAccess.bank_id, bankAccountId.bankId.value),
|
||||
By(AccountAccess.account_id, bankAccountId.accountId.value),
|
||||
PreCache(AccountAccess.view_fk)
|
||||
).map(_.view_fk.obj).flatten.distinct
|
||||
AccountAccess.findAllByBankIdAccountId(
|
||||
bankAccountId.bankId,
|
||||
bankAccountId.accountId
|
||||
).map(getViewFromAccountAccess).flatten.distinct
|
||||
}
|
||||
|
||||
//this is more like possible views, it contains the system views+custom views
|
||||
@ -492,10 +517,23 @@ object MapperViews extends Views with MdcLoggable {
|
||||
By(ViewDefinition.isSystem_, true)) // Sandbox specific System views
|
||||
}
|
||||
|
||||
private def getAccountAccessFromPublicViews(publicViews: List[ViewDefinition])={
|
||||
val publicSystemViews = publicViews.filter(_.isSystem)
|
||||
val publicCustomViews = publicViews.filter(!_.isSystem)
|
||||
val publicSystemViewAccountAccess = AccountAccess.findAll(
|
||||
ByList(AccountAccess.view_id, publicSystemViews.map(_.viewId.value)),
|
||||
)
|
||||
val publicCustomViewAccountAccess = AccountAccess.findAll(
|
||||
ByList(AccountAccess.bank_id, publicCustomViews.map(_.bankId.value)),
|
||||
ByList(AccountAccess.account_id, publicCustomViews.map(_.accountId.value)),
|
||||
ByList(AccountAccess.view_id, publicCustomViews.map(_.viewId.value)),
|
||||
)
|
||||
publicCustomViewAccountAccess++publicSystemViewAccountAccess
|
||||
}
|
||||
def publicViews: (List[View], List[AccountAccess]) = {
|
||||
if (APIUtil.allowPublicViews) {
|
||||
val publicViews = ViewDefinition.findAll(By(ViewDefinition.isPublic_, true)) // Custom and System views
|
||||
val publicAccountAccess = AccountAccess.findAll(ByList(AccountAccess.view_fk, publicViews.map(_.id)))
|
||||
val publicViews = ViewDefinition.findAll(By(ViewDefinition.isPublic_, true)) //Both Custom and System views
|
||||
val publicAccountAccess = getAccountAccessFromPublicViews(publicViews)
|
||||
(publicViews, publicAccountAccess)
|
||||
} else {
|
||||
(Nil, Nil)
|
||||
@ -508,7 +546,7 @@ object MapperViews extends Views with MdcLoggable {
|
||||
ViewDefinition.findAll(By(ViewDefinition.isPublic_, true), By(ViewDefinition.bank_id, bankId.value), By(ViewDefinition.isSystem_, false)) ::: // Custom views
|
||||
ViewDefinition.findAll(By(ViewDefinition.isPublic_, true), By(ViewDefinition.isSystem_, true)) ::: // System views
|
||||
ViewDefinition.findAll(By(ViewDefinition.isPublic_, true), By(ViewDefinition.bank_id, bankId.value), By(ViewDefinition.isSystem_, true)) // System views
|
||||
val publicAccountAccess = AccountAccess.findAll(ByList(AccountAccess.view_fk, publicViews.map(_.id)))
|
||||
val publicAccountAccess = getAccountAccessFromPublicViews(publicViews)
|
||||
(publicViews.distinct, publicAccountAccess)
|
||||
} else {
|
||||
(Nil, Nil)
|
||||
@ -516,30 +554,39 @@ object MapperViews extends Views with MdcLoggable {
|
||||
}
|
||||
|
||||
def privateViewsUserCanAccess(user: User): (List[View], List[AccountAccess]) ={
|
||||
val accountAccess = AccountAccess.findAll(
|
||||
By(AccountAccess.user_fk, user.userPrimaryKey.value),
|
||||
PreCache(AccountAccess.view_fk)
|
||||
).filter(r => r.view_fk.obj.isDefined && r.view_fk.obj.map(_.isPrivate).getOrElse(false) == true)
|
||||
val privateViews = accountAccess.map(_.view_fk.obj).flatten.distinct
|
||||
val accountAccess = AccountAccess.findAllByUserPrimaryKey(user.userPrimaryKey)
|
||||
.filter(accountAccess => {
|
||||
val view = getViewFromAccountAccess(accountAccess)
|
||||
view.isDefined && view.map(_.isPrivate)==Full(true)
|
||||
})
|
||||
val privateViews = accountAccess.map(getViewFromAccountAccess).flatten.distinct
|
||||
(privateViews, accountAccess)
|
||||
}
|
||||
def privateViewsUserCanAccess(user: User, viewIds: List[ViewId]): (List[View], List[AccountAccess]) ={
|
||||
val accountAccess = AccountAccess.findAll(
|
||||
By(AccountAccess.user_fk, user.userPrimaryKey.value),
|
||||
ByList(AccountAccess.view_id, viewIds.map(_.value))
|
||||
).filter(r => r.view_fk.obj.isDefined && r.view_fk.obj.map(_.isPrivate).getOrElse(false) == true)
|
||||
).filter(accountAccess => {
|
||||
val view = getViewFromAccountAccess(accountAccess)
|
||||
view.isDefined && view.map(_.isPrivate) == Full(true)
|
||||
})
|
||||
PrivateViewsUserCanAccessCommon(accountAccess)
|
||||
}
|
||||
def privateViewsUserCanAccessAtBank(user: User, bankId: BankId): (List[View], List[AccountAccess]) ={
|
||||
val accountAccess = AccountAccess.findAll(
|
||||
By(AccountAccess.user_fk, user.userPrimaryKey.value),
|
||||
By(AccountAccess.bank_id, bankId.value)
|
||||
).filter(r => r.view_fk.obj.isDefined && r.view_fk.obj.map(_.isPrivate).getOrElse(false) == true)
|
||||
).filter(accountAccess => {
|
||||
val view = getViewFromAccountAccess(accountAccess)
|
||||
view.isDefined && view.map(_.isPrivate) == Full(true)
|
||||
})
|
||||
PrivateViewsUserCanAccessCommon(accountAccess)
|
||||
}
|
||||
|
||||
private def PrivateViewsUserCanAccessCommon(accountAccess: List[AccountAccess]): (List[ViewDefinition], List[AccountAccess]) = {
|
||||
val listOfTuples: List[(AccountAccess, Box[ViewDefinition])] = accountAccess.map(x => (x, x.view_fk.obj))
|
||||
val listOfTuples: List[(AccountAccess, Box[ViewDefinition])] = accountAccess.map(
|
||||
accountAccess => (accountAccess, getViewFromAccountAccess(accountAccess))
|
||||
)
|
||||
val privateViews = listOfTuples.flatMap(
|
||||
tuple => tuple._2.map(v => v.bank_id(tuple._1.bank_id.get).account_id(tuple._1.account_id.get))
|
||||
)
|
||||
@ -547,25 +594,15 @@ object MapperViews extends Views with MdcLoggable {
|
||||
}
|
||||
|
||||
def privateViewsUserCanAccessForAccount(user: User, bankIdAccountId : BankIdAccountId) : List[View] = {
|
||||
val accountAccess = AccountAccess.findAll(
|
||||
By(AccountAccess.user_fk, user.userPrimaryKey.value),
|
||||
By(AccountAccess.bank_id, bankIdAccountId.bankId.value),
|
||||
By(AccountAccess.account_id, bankIdAccountId.accountId.value),
|
||||
PreCache(AccountAccess.view_fk)
|
||||
val accountAccess = AccountAccess.findByBankIdAccountIdUserPrimaryKey(
|
||||
bankIdAccountId.bankId,
|
||||
bankIdAccountId.accountId,
|
||||
user.userPrimaryKey
|
||||
)
|
||||
accountAccess.map(_.view_fk.obj).flatten.filter(view => view.isPrivate == true).distinct
|
||||
accountAccess.map(getViewFromAccountAccess).flatten.filter(view => view.isPrivate == true).distinct
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bankIdAccountId the IncomingAccount from Kafka
|
||||
* @param viewId This field should be selected one from Owner/Public/Accountant/Auditor, only support
|
||||
* these four values.
|
||||
* @return This will insert a View (e.g. the owner view) for an Account (BankAccount), and return the view
|
||||
* Note:
|
||||
* updateUserAccountViews would call createAccountView once per View specified in the IncomingAccount from Kafka.
|
||||
* We should cache this function because the available views on an account will change rarely.
|
||||
*
|
||||
*/
|
||||
|
||||
def getOrCreateAccountView(bankIdAccountId: BankIdAccountId, viewId: String): Box[View] = {
|
||||
|
||||
val bankId = bankIdAccountId.bankId
|
||||
@ -600,43 +637,29 @@ object MapperViews extends Views with MdcLoggable {
|
||||
theView
|
||||
}
|
||||
|
||||
def getOrCreateOwnerView(bankId: BankId, accountId: AccountId, description: String = "Owner View") : Box[View] = {
|
||||
getExistingView(bankId, accountId, SYSTEM_OWNER_VIEW_ID) match {
|
||||
case Empty => createDefaultOwnerView(bankId, accountId, description)
|
||||
case Full(v) => Full(v)
|
||||
case Failure(msg, t, c) => Failure(msg, t, c)
|
||||
case ParamFailure(x,y,z,q) => ParamFailure(x,y,z,q)
|
||||
}
|
||||
}
|
||||
def getOrCreateSystemView(name: String) : Box[View] = {
|
||||
getExistingSystemView(name) match {
|
||||
case Empty => createDefaultSystemView(name)
|
||||
def getOrCreateSystemView(viewId: String) : Box[View] = {
|
||||
getExistingSystemView(viewId) match {
|
||||
case Empty => createDefaultSystemView(viewId)
|
||||
case Full(v) => Full(v)
|
||||
case Failure(msg, t, c) => Failure(msg, t, c)
|
||||
case ParamFailure(x,y,z,q) => ParamFailure(x,y,z,q)
|
||||
}
|
||||
}
|
||||
|
||||
def getOrCreateFirehoseView(bankId: BankId, accountId: AccountId, description: String = "Firehose View") : Box[View] = {
|
||||
getExistingView(bankId, accountId, "firehose") match {
|
||||
case Empty => createDefaultFirehoseView(bankId, accountId, description)
|
||||
case Full(v) => Full(v)
|
||||
case Failure(msg, t, c) => Failure(msg, t, c)
|
||||
case ParamFailure(x,y,z,q) => ParamFailure(x,y,z,q)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* if return the system view owner, it may return all the users, all the user if have its own account, it should have the `owner` view access.
|
||||
* @param view
|
||||
* @return
|
||||
*/
|
||||
def getOwners(view: View) : Set[User] = {
|
||||
val id: Long = ViewDefinition.findCustomView(view.uid.bankId.value, view.uid.accountId.value, view.uid.viewId.value)
|
||||
.or(ViewDefinition.findSystemView(view.viewId.value))
|
||||
.map(_.id).openOr(0)
|
||||
val privileges = AccountAccess.findAll(By(AccountAccess.view_fk, id))
|
||||
val users: List[User] = privileges.flatMap(_.user_fk.obj)
|
||||
val accountAccessList = AccountAccess.findAllByView(view)
|
||||
val users: List[User] = accountAccessList.flatMap(_.user_fk.obj)
|
||||
users.toSet
|
||||
}
|
||||
|
||||
def getOrCreateCustomPublicView(bankId: BankId, accountId: AccountId, description: String = "Public View") : Box[View] = {
|
||||
getExistingView(bankId, accountId, CUSTOM_PUBLIC_VIEW_ID) match {
|
||||
getExistingCustomView(bankId, accountId, CUSTOM_PUBLIC_VIEW_ID) match {
|
||||
case Empty=> createDefaultPublicView(bankId, accountId, description)
|
||||
case Full(v)=> Full(v)
|
||||
case Failure(msg, t, c) => Failure(msg, t, c)
|
||||
@ -645,7 +668,7 @@ object MapperViews extends Views with MdcLoggable {
|
||||
}
|
||||
|
||||
def getOrCreateAccountantsView(bankId: BankId, accountId: AccountId, description: String = "Accountants View") : Box[View] = {
|
||||
getExistingView(bankId, accountId, "accountant") match {
|
||||
getExistingCustomView(bankId, accountId, SYSTEM_ACCOUNTANT_VIEW_ID) match {
|
||||
case Empty => createDefaultAccountantsView(bankId, accountId, description)
|
||||
case Full(v) => Full(v)
|
||||
case Failure(msg, t, c) => Failure(msg, t, c)
|
||||
@ -654,7 +677,7 @@ object MapperViews extends Views with MdcLoggable {
|
||||
}
|
||||
|
||||
def getOrCreateAuditorsView(bankId: BankId, accountId: AccountId, description: String = "Auditors View") : Box[View] = {
|
||||
getExistingView(bankId, accountId, "auditor") match {
|
||||
getExistingCustomView(bankId, accountId, SYSTEM_AUDITOR_VIEW_ID) match {
|
||||
case Empty => createDefaultAuditorsView(bankId, accountId, description)
|
||||
case Full(v) => Full(v)
|
||||
case Failure(msg, t, c) => Failure(msg, t, c)
|
||||
@ -755,11 +778,6 @@ object MapperViews extends Views with MdcLoggable {
|
||||
Full(entity)
|
||||
}
|
||||
|
||||
|
||||
def createDefaultFirehoseView(bankId: BankId, accountId: AccountId, name: String): Box[View] = {
|
||||
createAndSaveFirehoseView(bankId, accountId, "Firehose View")
|
||||
}
|
||||
|
||||
def createDefaultOwnerView(bankId: BankId, accountId: AccountId, name: String): Box[View] = {
|
||||
createAndSaveOwnerView(bankId, accountId, "Owner View")
|
||||
}
|
||||
@ -782,27 +800,22 @@ object MapperViews extends Views with MdcLoggable {
|
||||
createAndSaveDefaultAuditorsView(bankId, accountId, "Auditors View")
|
||||
}
|
||||
|
||||
def getExistingView(bankId: BankId, accountId: AccountId, name: String): Box[View] = {
|
||||
val res = ViewDefinition.findCustomView(bankId.value, accountId.value, name)
|
||||
def getExistingCustomView(bankId: BankId, accountId: AccountId, viewId: String): Box[View] = {
|
||||
val res = ViewDefinition.findCustomView(bankId.value, accountId.value, viewId)
|
||||
if(res.isDefined && res.openOrThrowException(attemptedToOpenAnEmptyBox).isPublic && !allowPublicViews) return Failure(PublicViewsNotAllowedOnThisInstance)
|
||||
res
|
||||
}
|
||||
def getExistingSystemView(name: String): Box[View] = {
|
||||
val res = ViewDefinition.findSystemView(name)
|
||||
def getExistingSystemView(viewId: String): Box[View] = {
|
||||
val res = ViewDefinition.findSystemView(viewId)
|
||||
if(res.isDefined && res.openOrThrowException(attemptedToOpenAnEmptyBox).isPublic && !allowPublicViews) return Failure(PublicViewsNotAllowedOnThisInstance)
|
||||
res
|
||||
}
|
||||
|
||||
def removeAllPermissions(bankId: BankId, accountId: AccountId) : Boolean = {
|
||||
val views = ViewDefinition.findAll(
|
||||
By(ViewDefinition.bank_id, bankId.value),
|
||||
By(ViewDefinition.account_id, accountId.value)
|
||||
AccountAccess.bulkDelete_!!(
|
||||
By(AccountAccess.bank_id, bankId.value),
|
||||
By(AccountAccess.account_id, accountId.value)
|
||||
)
|
||||
var privilegesDeleted = true
|
||||
views.map (x => {
|
||||
privilegesDeleted &&= AccountAccess.bulkDelete_!!(By(AccountAccess.view_fk, x.id_.get))
|
||||
} )
|
||||
privilegesDeleted
|
||||
}
|
||||
|
||||
def removeAllViews(bankId: BankId, accountId: AccountId) : Boolean = {
|
||||
@ -907,15 +920,15 @@ object MapperViews extends Views with MdcLoggable {
|
||||
.canAddTransactionRequestToOwnAccount_(true) //added following two for payments
|
||||
.canAddTransactionRequestToAnyAccount_(true)
|
||||
}
|
||||
def unsavedSystemView(name: String) : ViewDefinition = {
|
||||
def unsavedSystemView(viewId: String) : ViewDefinition = {
|
||||
val entity = create
|
||||
.isSystem_(true)
|
||||
.isFirehose_(false)
|
||||
.bank_id(null)
|
||||
.account_id(null)
|
||||
.name_(StringHelpers.capify(name))
|
||||
.view_id(name)
|
||||
.description_(name)
|
||||
.name_(StringHelpers.capify(viewId))
|
||||
.view_id(viewId)
|
||||
.description_(viewId)
|
||||
.isPublic_(false) //(default is false anyways)
|
||||
.usePrivateAliasIfOneExists_(false) //(default is false anyways)
|
||||
.usePublicAliasIfOneExists_(false) //(default is false anyways)
|
||||
@ -994,7 +1007,7 @@ object MapperViews extends Views with MdcLoggable {
|
||||
.canAddTransactionRequestToOwnAccount_(true) //added following two for payments
|
||||
.canAddTransactionRequestToAnyAccount_(true)
|
||||
|
||||
name match {
|
||||
viewId match {
|
||||
case SYSTEM_STAGE_ONE_VIEW_ID =>
|
||||
entity
|
||||
.canSeeTransactionDescription_(false)
|
||||
|
||||
@ -60,7 +60,7 @@ trait Views {
|
||||
//always return a view id String, not error here.
|
||||
def getMetadataViewId(bankAccountId: BankIdAccountId, viewId : ViewId) = Views.views.vend.customView(viewId, bankAccountId).map(_.metadataView).openOr(viewId.value)
|
||||
|
||||
def createView(bankAccountId: BankIdAccountId, view: CreateViewJson): Box[View]
|
||||
def createCustomView(bankAccountId: BankIdAccountId, view: CreateViewJson): Box[View]
|
||||
def createSystemView(view: CreateViewJson): Future[Box[View]]
|
||||
def removeCustomView(viewId: ViewId, bankAccountId: BankIdAccountId): Box[Boolean]
|
||||
def removeSystemView(viewId: ViewId): Future[Box[Boolean]]
|
||||
@ -97,21 +97,23 @@ trait Views {
|
||||
final def getPrivateBankAccountsFuture(user : User, viewIds: List[ViewId]) : Future[List[BankIdAccountId]] = Future {getPrivateBankAccounts(user, viewIds)}
|
||||
final def getPrivateBankAccounts(user : User, bankId : BankId) : List[BankIdAccountId] = getPrivateBankAccounts(user).filter(_.bankId == bankId).distinct
|
||||
final def getPrivateBankAccountsFuture(user : User, bankId : BankId) : Future[List[BankIdAccountId]] = Future {getPrivateBankAccounts(user, bankId)}
|
||||
|
||||
|
||||
/**
|
||||
* @param bankIdAccountId the IncomingAccount from Kafka
|
||||
* @param viewId This field should be selected one from Owner/Public/Accountant/Auditor, only support
|
||||
* these four values.
|
||||
* @return This will insert a View (e.g. the owner view) for an Account (BankAccount), and return the view
|
||||
* Note:
|
||||
* updateUserAccountViews would call createAccountView once per View specified in the IncomingAccount from Kafka.
|
||||
* We should cache this function because the available views on an account will change rarely.
|
||||
*
|
||||
*/
|
||||
def getOrCreateAccountView(bankAccountUID: BankIdAccountId, viewId: String): Box[View]
|
||||
def getOrCreateFirehoseView(bankId: BankId, accountId: AccountId, description: String) : Box[View]
|
||||
|
||||
def getOrCreateSystemView(name: String) : Box[View]
|
||||
def getOrCreateSystemView(viewId: String) : Box[View]
|
||||
def getOrCreateCustomPublicView(bankId: BankId, accountId: AccountId, description: String) : Box[View]
|
||||
def createCustomRandomView(bankId: BankId, accountId: AccountId) : Box[View]
|
||||
|
||||
@deprecated("There is no custom `Accountant` view, only support system owner view now","2020-01-13")
|
||||
def getOrCreateAccountantsView(bankId: BankId, accountId: AccountId, description: String) : Box[View]
|
||||
@deprecated("There is no custom `Auditor` view, only support system owner view now","2020-01-13")
|
||||
def getOrCreateAuditorsView(bankId: BankId, accountId: AccountId, description: String) : Box[View]
|
||||
@deprecated("There is no custom `owner` view, only support system owner view now","2020-01-13")
|
||||
def getOrCreateOwnerView(bankId: BankId, accountId: AccountId, description: String) : Box[View]
|
||||
|
||||
def getOwners(view: View): Set[User]
|
||||
|
||||
def removeAllPermissions(bankId: BankId, accountId: AccountId) : Boolean
|
||||
@ -158,11 +160,9 @@ class RemotedataViewsCaseClasses {
|
||||
case class getSystemViews()
|
||||
case class customViewFuture(viewId : ViewId, bankAccountId: BankIdAccountId)
|
||||
case class systemViewFuture(viewId : ViewId)
|
||||
case class getOrCreateAccountView(account: BankIdAccountId, viewName: String)
|
||||
case class getOrCreateOwnerView(bankId: BankId, accountId: AccountId, description: String)
|
||||
case class getOrCreateSystemView(name: String)
|
||||
case class getOrCreateFirehoseView(bankId: BankId, accountId: AccountId, description: String)
|
||||
case class getOrCreatePublicView(bankId: BankId, accountId: AccountId, description: String)
|
||||
case class getOrCreateAccountView(account: BankIdAccountId, viewId: String)
|
||||
case class getOrCreateSystemView(viewId: String)
|
||||
case class getOrCreatePublicPublicView(bankId: BankId, accountId: AccountId, description: String)
|
||||
case class getOrCreateAccountantsView(bankId: BankId, accountId: AccountId, description: String)
|
||||
case class getOrCreateAuditorsView(bankId: BankId, accountId: AccountId, description: String)
|
||||
case class createRandomView(bankId: BankId, accountId: AccountId)
|
||||
|
||||
@ -3,6 +3,7 @@ package code.views.system
|
||||
import code.api.Constant.ALL_CONSUMERS
|
||||
import code.model.dataAccess.ResourceUser
|
||||
import code.util.UUIDString
|
||||
import com.openbankproject.commons.model.{AccountId, BankId, UserPrimaryKey, View, ViewId}
|
||||
import net.liftweb.mapper._
|
||||
/*
|
||||
This stores the link between A User and a View
|
||||
@ -12,16 +13,63 @@ class AccountAccess extends LongKeyedMapper[AccountAccess] with IdPK with Create
|
||||
def getSingleton = AccountAccess
|
||||
object user_fk extends MappedLongForeignKey(this, ResourceUser)
|
||||
object bank_id extends MappedString(this, 255)
|
||||
|
||||
//If consumer_id is `ALL-CONSUMERS`, any consumers can use this record
|
||||
//If consumer_id is consumerId (obp UUID), only same consumer can use this record
|
||||
object consumer_id extends MappedString(this, 255){
|
||||
override def defaultValue = ALL_CONSUMERS
|
||||
}
|
||||
object account_id extends MappedString(this, 255)
|
||||
object view_id extends UUIDString(this)
|
||||
|
||||
//If consumer_id is `ALL-CONSUMERS`, any consumers can use this record
|
||||
//If consumer_id is consumerId (obp UUID), only same consumer can use this record
|
||||
object consumer_id extends MappedString(this, 255) {
|
||||
override def defaultValue = ALL_CONSUMERS
|
||||
}
|
||||
|
||||
|
||||
@deprecated("we should use bank_id, account_id and view_id instead of the view_fk","07-03-2023")
|
||||
object view_fk extends MappedLongForeignKey(this, ViewDefinition)
|
||||
}
|
||||
object AccountAccess extends AccountAccess with LongKeyedMetaMapper[AccountAccess] {
|
||||
override def dbIndexes: List[BaseIndex[AccountAccess]] = UniqueIndex(bank_id, account_id, view_fk, user_fk, consumer_id) :: super.dbIndexes
|
||||
def findAllBySystemViewId(systemViewId:ViewId)= AccountAccess.findAll(
|
||||
By(AccountAccess.view_id, systemViewId.value)
|
||||
)
|
||||
def findAllByView(view: View)=
|
||||
if(view.isSystem) {
|
||||
findAllBySystemViewId(view.viewId)
|
||||
}else{
|
||||
AccountAccess.findAllByBankIdAccountIdViewId(view.bankId, view.accountId, view.viewId)
|
||||
}
|
||||
def findAllByUserPrimaryKey(userPrimaryKey:UserPrimaryKey)= AccountAccess.findAll(
|
||||
By(AccountAccess.user_fk, userPrimaryKey.value),
|
||||
PreCache(AccountAccess.view_fk)
|
||||
)
|
||||
def findAllByBankIdAccountId(bankId:BankId, accountId:AccountId) = AccountAccess.findAll(
|
||||
By(AccountAccess.bank_id, bankId.value),
|
||||
By(AccountAccess.account_id, accountId.value),
|
||||
PreCache(AccountAccess.view_fk)
|
||||
)
|
||||
def findAllByBankIdAccountIdViewId(bankId:BankId, accountId:AccountId, viewId:ViewId)= AccountAccess.findAll(
|
||||
By(AccountAccess.bank_id, bankId.value),
|
||||
By(AccountAccess.account_id, accountId.value),
|
||||
By(AccountAccess.view_id, viewId.value)
|
||||
)
|
||||
|
||||
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)
|
||||
)
|
||||
|
||||
def findByBankIdAccountIdViewIdUserPrimaryKey(bankId: BankId, accountId: AccountId, viewId: ViewId, userPrimaryKey: UserPrimaryKey) = 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)
|
||||
)
|
||||
|
||||
def findByBankIdAccountIdViewIdConsumerId(bankId: BankId, accountId: AccountId, viewId: ViewId, consumerId:String ) = AccountAccess.find(
|
||||
By(AccountAccess.bank_id, bankId.value),
|
||||
By(AccountAccess.account_id, accountId.value),
|
||||
By(AccountAccess.view_id, viewId.value),
|
||||
By(AccountAccess.consumer_id, consumerId)
|
||||
)
|
||||
}
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
package code.views.system
|
||||
|
||||
import code.api.util.APIUtil.{checkCustomViewIdOrName, checkSystemViewIdOrName}
|
||||
import code.api.util.ErrorMessages.{InvalidCustomViewFormat, InvalidSystemViewFormat}
|
||||
import code.util.{AccountIdString, UUIDString}
|
||||
import com.openbankproject.commons.model._
|
||||
import net.liftweb.common.Box
|
||||
@ -529,11 +531,19 @@ class ViewDefinition extends View with LongKeyedMapper[ViewDefinition] with Many
|
||||
object ViewDefinition extends ViewDefinition with LongKeyedMetaMapper[ViewDefinition] {
|
||||
override def dbIndexes: List[BaseIndex[ViewDefinition]] = UniqueIndex(composite_unique_key) :: super.dbIndexes
|
||||
override def beforeSave = List(
|
||||
t =>
|
||||
t =>{
|
||||
tryo {
|
||||
val viewId = getUniqueKey(t.bank_id.get, t.account_id.get, t.view_id.get)
|
||||
t.composite_unique_key(viewId)
|
||||
}
|
||||
|
||||
if (t.isSystem && !checkSystemViewIdOrName(t.view_id.get)) {
|
||||
throw new RuntimeException(InvalidSystemViewFormat+s"Current view_id (${t.view_id.get})")
|
||||
}
|
||||
if (!t.isSystem && !checkCustomViewIdOrName(t.view_id.get)) {
|
||||
throw new RuntimeException(InvalidCustomViewFormat+s"Current view_id (${t.view_id.get})")
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
def findSystemView(viewId: String): Box[ViewDefinition] = {
|
||||
|
||||
@ -341,29 +341,29 @@ class API1_2_1Test extends ServerSetupWithTestData with DefaultUsers with Privat
|
||||
makeGetRequest(request)
|
||||
}
|
||||
|
||||
def getUserAccountPermission(bankId : String, accountId : String, userId : String, consumerAndToken: Option[(Consumer, Token)]) : APIResponse = {
|
||||
val request = v1_2_1Request / "banks" / bankId / "accounts" / accountId / "permissions" / defaultProvider / userId <@(consumerAndToken)
|
||||
def getUserAccountPermission(bankId : String, accountId : String, providerId : String, consumerAndToken: Option[(Consumer, Token)]) : APIResponse = {
|
||||
val request = v1_2_1Request / "banks" / bankId / "accounts" / accountId / "permissions" / defaultProvider / providerId <@(consumerAndToken)
|
||||
makeGetRequest(request)
|
||||
}
|
||||
|
||||
def grantUserAccessToView(bankId : String, accountId : String, userId : String, viewId : String, consumerAndToken: Option[(Consumer, Token)]) : APIResponse= {
|
||||
val request = (v1_2_1Request / "banks" / bankId / "accounts" / accountId / "permissions"/ defaultProvider / userId / "views" / viewId).POST <@(consumerAndToken)
|
||||
def grantUserAccessToView(bankId : String, accountId : String, providerId : String, viewId : String, consumerAndToken: Option[(Consumer, Token)]) : APIResponse= {
|
||||
val request = (v1_2_1Request / "banks" / bankId / "accounts" / accountId / "permissions"/ defaultProvider / providerId / "views" / viewId).POST <@(consumerAndToken)
|
||||
makePostRequest(request, "")
|
||||
}
|
||||
|
||||
def grantUserAccessToViews(bankId : String, accountId : String, userId : String, viewIds : List[String], consumerAndToken: Option[(Consumer, Token)]) : APIResponse= {
|
||||
val request = (v1_2_1Request / "banks" / bankId / "accounts" / accountId / "permissions"/ defaultProvider / userId / "views").POST <@(consumerAndToken)
|
||||
def grantUserAccessToViews(bankId : String, accountId : String, providerId : String, viewIds : List[String], consumerAndToken: Option[(Consumer, Token)]) : APIResponse= {
|
||||
val request = (v1_2_1Request / "banks" / bankId / "accounts" / accountId / "permissions"/ defaultProvider / providerId / "views").POST <@(consumerAndToken)
|
||||
val viewsJson = ViewIdsJson(viewIds)
|
||||
makePostRequest(request, write(viewsJson))
|
||||
}
|
||||
|
||||
def revokeUserAccessToView(bankId : String, accountId : String, userId : String, viewId : String, consumerAndToken: Option[(Consumer, Token)]) : APIResponse= {
|
||||
val request = (v1_2_1Request / "banks" / bankId / "accounts" / accountId / "permissions"/ defaultProvider / userId / "views" / viewId).DELETE <@(consumerAndToken)
|
||||
def revokeUserAccessToView(bankId : String, accountId : String, providerId : String, viewId : String, consumerAndToken: Option[(Consumer, Token)]) : APIResponse= {
|
||||
val request = (v1_2_1Request / "banks" / bankId / "accounts" / accountId / "permissions"/ defaultProvider / providerId / "views" / viewId).DELETE <@(consumerAndToken)
|
||||
makeDeleteRequest(request)
|
||||
}
|
||||
|
||||
def revokeUserAccessToAllViews(bankId : String, accountId : String, userId : String, consumerAndToken: Option[(Consumer, Token)]) : APIResponse= {
|
||||
val request = (v1_2_1Request / "banks" / bankId / "accounts" / accountId / "permissions"/ defaultProvider / userId / "views").DELETE <@(consumerAndToken)
|
||||
def revokeUserAccessToAllViews(bankId : String, accountId : String, providerId : String, consumerAndToken: Option[(Consumer, Token)]) : APIResponse= {
|
||||
val request = (v1_2_1Request / "banks" / bankId / "accounts" / accountId / "permissions"/ defaultProvider / providerId / "views").DELETE <@(consumerAndToken)
|
||||
makeDeleteRequest(request)
|
||||
}
|
||||
|
||||
@ -2053,7 +2053,7 @@ class API1_2_1Test extends ServerSetupWithTestData with DefaultUsers with Privat
|
||||
reply.code should equal (204)
|
||||
|
||||
And("The account holder do not have access to the owner view")
|
||||
val view = Views.views.vend.customView(ownerViewId, BankIdAccountId(BankId(bankId), AccountId(bankAccount.id))).openOrThrowException(attemptedToOpenAnEmptyBox)
|
||||
val view = Views.views.vend.systemView(ownerViewId).openOrThrowException(attemptedToOpenAnEmptyBox)
|
||||
Views.views.vend.getOwners(view).toList should not contain (resourceUser3)
|
||||
}
|
||||
|
||||
@ -2135,7 +2135,7 @@ class API1_2_1Test extends ServerSetupWithTestData with DefaultUsers with Privat
|
||||
val bankId = randomBank
|
||||
val bankAccount : AccountJSON = randomPrivateAccount(bankId)
|
||||
val viewId = ViewId(SYSTEM_OWNER_VIEW_ID)
|
||||
val view = Views.views.vend.customView(viewId, BankIdAccountId(BankId(bankId), AccountId(bankAccount.id))).openOrThrowException(attemptedToOpenAnEmptyBox)
|
||||
val view = Views.views.vend.systemView(viewId).openOrThrowException(attemptedToOpenAnEmptyBox)
|
||||
val userId = resourceUser1.idGivenByProvider
|
||||
|
||||
Views.views.vend.getOwners(view).toList.length should equal(1)
|
||||
@ -2143,8 +2143,8 @@ class API1_2_1Test extends ServerSetupWithTestData with DefaultUsers with Privat
|
||||
|
||||
When("the request is sent")
|
||||
val reply = revokeUserAccessToAllViews(bankId, bankAccount.id, userId, user1)
|
||||
Then("we should get a 400 code")
|
||||
reply.code should equal (400)
|
||||
Then("we should get a 204 code")
|
||||
reply.code should equal (204)
|
||||
|
||||
And("The user should not have had his access revoked")
|
||||
Views.views.vend.getOwners(view).toList.length should equal(1)
|
||||
@ -2168,9 +2168,9 @@ class API1_2_1Test extends ServerSetupWithTestData with DefaultUsers with Privat
|
||||
Then("we should get a 204 code")
|
||||
reply.code should equal (204)
|
||||
|
||||
And("The user should have had his access revoked")
|
||||
val view = Views.views.vend.customView(ViewId(SYSTEM_OWNER_VIEW_ID), BankIdAccountId(BankId(bankId), AccountId(bankAccount.id))).openOrThrowException(attemptedToOpenAnEmptyBox)
|
||||
Views.views.vend.getOwners(view).toList should not contain (resourceUser3)
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -78,7 +78,7 @@ class ConsentTest extends V310ServerSetup {
|
||||
response400.code should equal(401)
|
||||
response400.body.extract[ErrorMessage].message should equal(UserNotLoggedIn)
|
||||
}
|
||||
|
||||
|
||||
scenario("We will call the endpoint with user credentials but wrong SCA method", ApiEndpoint1, VersionOfApi) {
|
||||
When("We make a request")
|
||||
val request400 = (v3_1_0_Request / "banks" / bankId / "my" / "consents" / "NOT_EMAIL_NEITHER_SMS" ).POST <@(user1)
|
||||
@ -87,7 +87,7 @@ class ConsentTest extends V310ServerSetup {
|
||||
response400.code should equal(400)
|
||||
response400.body.extract[ErrorMessage].message should equal(ConsentAllowedScaMethods)
|
||||
}
|
||||
|
||||
|
||||
scenario("We will call the endpoint with user credentials", ApiEndpoint1, ApiEndpoint3, VersionOfApi, VersionOfApi2) {
|
||||
wholeFunctionality(RequestHeader.`Consent-JWT`)
|
||||
}
|
||||
|
||||
@ -73,7 +73,7 @@ class SystemViewsTests extends V310ServerSetup {
|
||||
// System view, owner
|
||||
val randomSystemViewId = APIUtil.generateUUID()
|
||||
val postBodySystemViewJson = createSystemViewJsonV300.copy(name=randomSystemViewId).copy(metadata_view = randomSystemViewId).toCreateViewJson
|
||||
val systemViewId = MapperViews.getNewViewPermalink(postBodySystemViewJson.name)
|
||||
val systemViewId = MapperViews.createViewIdByName(postBodySystemViewJson.name)
|
||||
|
||||
def getSystemView(viewId : String, consumerAndToken: Option[(Consumer, Token)]): APIResponse = {
|
||||
val request = v3_1_0_Request / "system-views" / viewId <@(consumerAndToken)
|
||||
|
||||
@ -75,7 +75,7 @@ class SystemViewsTests extends V500ServerSetup {
|
||||
val postBodySystemViewJson = createSystemViewJsonV500
|
||||
.copy(name=randomSystemViewId)
|
||||
.copy(metadata_view = randomSystemViewId).toCreateViewJson
|
||||
val systemViewId = MapperViews.getNewViewPermalink(postBodySystemViewJson.name)
|
||||
val systemViewId = MapperViews.createViewIdByName(postBodySystemViewJson.name)
|
||||
|
||||
def getSystemView(viewId : String, consumerAndToken: Option[(Consumer, Token)]): APIResponse = {
|
||||
val request = v5_0_0_Request / "system-views" / viewId <@(consumerAndToken)
|
||||
|
||||
@ -3,6 +3,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.util.ErrorMessages.attemptedToOpenAnEmptyBox
|
||||
import code.api.util.{APIUtil, OBPLimit, OBPOffset}
|
||||
import code.bankconnectors.{Connector, LocalMappedConnector}
|
||||
import code.model._
|
||||
@ -14,7 +15,6 @@ trait TestConnectorSetup {
|
||||
|
||||
//TODO: implement these right here using Connector.connector.vend and get rid of specific connector setup files
|
||||
protected def createBank(id : String) : Bank
|
||||
@deprecated("Please use `createAccountAndOwnerView` instead, we need owner view for each account! ","2018-02-23")
|
||||
protected def createAccount(bankId: BankId, accountId : AccountId, currency : String) : BankAccount
|
||||
protected def createTransaction(account : BankAccount, startDate : Date, finishDate : Date)
|
||||
protected def createTransactionRequest(account: BankAccount): List[MappedTransactionRequest]
|
||||
@ -25,8 +25,8 @@ trait TestConnectorSetup {
|
||||
/**
|
||||
* This method, will do 4 things:
|
||||
* 1 create account
|
||||
* 2 create the `owner-view`
|
||||
* 3 grant the `owner-view` access to the User.
|
||||
* 2 get or create system the `owner` view
|
||||
* 3 grant the `owner` view access to the User.
|
||||
* 4 create the accountHolder for this account.
|
||||
* @param accountOwner it is just a random user here, the user will have the access to the `owner view`
|
||||
* @param bankId one bankId
|
||||
@ -36,9 +36,9 @@ trait TestConnectorSetup {
|
||||
*/
|
||||
final protected def createAccountRelevantResource(accountOwner: Option[User], bankId: BankId, accountId : AccountId, currency : String) : BankAccount = {
|
||||
val account = createAccount(bankId, accountId, currency)
|
||||
val ownerView = createOwnerView(bankId, accountId)
|
||||
val ownerView = Views.views.vend.getOrCreateSystemView(SYSTEM_OWNER_VIEW_ID).openOrThrowException(attemptedToOpenAnEmptyBox)
|
||||
accountOwner.foreach(AccountHolders.accountHolders.vend.getOrCreateAccountHolder(_, BankIdAccountId(account.bankId, account.accountId)))
|
||||
accountOwner.foreach(Views.views.vend.grantAccessToCustomView(ViewIdBankIdAccountId(ViewId(ownerView.viewId.value), BankId(ownerView.bankId.value), AccountId(ownerView.accountId.value)), _))
|
||||
accountOwner.foreach(Views.views.vend.grantAccessToSystemView(bankId, accountId, ownerView, _))
|
||||
account
|
||||
}
|
||||
|
||||
@ -147,8 +147,6 @@ trait TestConnectorSetup {
|
||||
createBank("payment-test-bank")
|
||||
|
||||
protected def getOrCreateSystemView(name: String): View
|
||||
|
||||
protected def createOwnerView(bankId: BankId, accountId: AccountId) : View
|
||||
protected def createPublicView(bankId: BankId, accountId: AccountId) : View
|
||||
protected def createCustomRandomView(bankId: BankId, accountId: AccountId) : View
|
||||
|
||||
|
||||
@ -2,6 +2,7 @@ package code.setup
|
||||
|
||||
import bootstrap.liftweb.ToSchemify
|
||||
import code.accountholders.AccountHolders
|
||||
import code.api.Constant.{CUSTOM_PUBLIC_VIEW_ID, SYSTEM_OWNER_VIEW_ID}
|
||||
import code.api.util.ErrorMessages._
|
||||
import code.model._
|
||||
import code.model.dataAccess._
|
||||
@ -24,11 +25,11 @@ trait TestConnectorSetupWithStandardPermissions extends TestConnectorSetup {
|
||||
Views.views.vend.getOrCreateSystemView(name).openOrThrowException(attemptedToOpenAnEmptyBox)
|
||||
}
|
||||
protected def createOwnerView(bankId: BankId, accountId: AccountId ) : View = {
|
||||
Views.views.vend.getOrCreateOwnerView(bankId, accountId, randomString(3)).openOrThrowException(attemptedToOpenAnEmptyBox)
|
||||
Views.views.vend.getOrCreateSystemView(SYSTEM_OWNER_VIEW_ID).openOrThrowException(attemptedToOpenAnEmptyBox)
|
||||
}
|
||||
|
||||
protected def createPublicView(bankId: BankId, accountId: AccountId) : View = {
|
||||
Views.views.vend.getOrCreateCustomPublicView(bankId, accountId, randomString(3)).openOrThrowException(attemptedToOpenAnEmptyBox)
|
||||
Views.views.vend.getOrCreateCustomPublicView(bankId: BankId, accountId: AccountId, CUSTOM_PUBLIC_VIEW_ID).openOrThrowException(attemptedToOpenAnEmptyBox)
|
||||
}
|
||||
|
||||
protected def createCustomRandomView(bankId: BankId, accountId: AccountId) : View = {
|
||||
|
||||
@ -57,6 +57,7 @@ trait User {
|
||||
def userPrimaryKey : UserPrimaryKey
|
||||
/** This will be a UUID for Resource User Document */
|
||||
def userId: String
|
||||
//this used same as username now
|
||||
def idGivenByProvider: String
|
||||
def provider : String
|
||||
def emailAddress : String
|
||||
|
||||
Loading…
Reference in New Issue
Block a user