Account Tags - WIP

This commit is contained in:
Marko Milić 2019-10-11 16:30:24 +02:00
parent ea9aaad170
commit 9309842e02
7 changed files with 148 additions and 6 deletions

View File

@ -1,19 +1,21 @@
package code.api.v4_0_0
import code.api.ChargePolicy
import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON._
import code.api.util.APIUtil._
import code.api.util.ApiRole._
import code.api.util.ApiTag._
import code.api.util.ErrorMessages.{AccountNotFound, AllowedAttemptsUsedUp, BankNotFound, CounterpartyBeneficiaryPermit, InsufficientAuthorisationToCreateTransactionRequest, InvalidAccountIdFormat, InvalidBankIdFormat, InvalidChallengeAnswer, InvalidChallengeType, InvalidChargePolicy, InvalidISOCurrencyCode, InvalidJsonFormat, InvalidNumber, InvalidTransactionRequesChallengeId, InvalidTransactionRequestCurrency, InvalidTransactionRequestType, NotPositiveAmount, TransactionDisabled, TransactionRequestStatusNotInitiated, TransactionRequestTypeHasChanged, UnknownError, UserHasMissingRoles, UserNoPermissionAccessView, UserNotLoggedIn, ViewNotFound}
import code.api.util.ErrorMessages.{AccountNotFound, AllowedAttemptsUsedUp, BankAccountNotFound, BankNotFound, CounterpartyBeneficiaryPermit, InsufficientAuthorisationToCreateTransactionRequest, InvalidAccountIdFormat, InvalidBankIdFormat, InvalidChallengeAnswer, InvalidChallengeType, InvalidChargePolicy, InvalidISOCurrencyCode, InvalidJsonFormat, InvalidNumber, InvalidTransactionRequesChallengeId, InvalidTransactionRequestCurrency, InvalidTransactionRequestType, NoViewPermission, NotPositiveAmount, TransactionDisabled, TransactionRequestStatusNotInitiated, TransactionRequestTypeHasChanged, UnknownError, UserHasMissingRoles, UserNoPermissionAccessView, UserNotLoggedIn, ViewNotFound}
import code.api.util.ExampleValue.{dynamicEntityRequestBodyExample, dynamicEntityResponseBodyExample}
import code.api.util.NewStyle.HttpCode
import code.api.util._
import code.api.v1_2_1.{JSONFactory, PostTransactionTagJSON}
import code.api.v1_4_0.JSONFactory1_4_0.{ChallengeAnswerJSON, TransactionRequestAccountJsonV140}
import code.api.v2_0_0.{EntitlementJSON, EntitlementJSONs, JSONFactory200}
import code.api.v2_1_0._
import code.api.v3_1_0.ListResult
import code.api.{APIFailureNewStyle, ChargePolicy}
import code.dynamicEntity.DynamicEntityCommons
import code.metadata.tags.Tags
import code.model.dataAccess.AuthUser
import code.model.toUserExtended
import code.transactionrequests.TransactionRequests.TransactionChallengeTypes._
@ -28,6 +30,7 @@ import net.liftweb.common.{Box, Full, ParamFailure}
import net.liftweb.http.rest.RestHelper
import net.liftweb.json.Serialization.write
import net.liftweb.json._
import net.liftweb.util.Helpers.now
import net.liftweb.util.StringHelpers
import org.atteo.evo.inflector.English
@ -35,10 +38,6 @@ import scala.collection.immutable.{List, Nil}
import scala.collection.mutable.ArrayBuffer
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
import code.api.v2_0_0.{EntitlementJSON, EntitlementJSONs, JSONFactory200}
import code.api.v3_0_0.JSONFactory300
import code.entitlement.Entitlement
import code.views.Views
trait APIMethods400 {
self: RestHelper =>
@ -1090,6 +1089,98 @@ trait APIMethods400 {
}
}
resourceDocs += ResourceDoc(
addTagForViewOnAccount,
implementedInApiVersion,
"addTagForViewOnAccount",
"POST",
"/banks/BANK_ID/accounts/ACCOUNT_ID/VIEW_ID/metadata/tags",
"Add a tag.",
s"""Posts a tag about an account ACCOUNT_ID on a [view](#1_2_1-getViewsForBankAccount) VIEW_ID.
|
|${authenticationRequiredMessage(true)}
|
|Authentication is required as the tag is linked with the user.""",
postTransactionTagJSON,
transactionTagJSON,
List(
UserNotLoggedIn,
BankAccountNotFound,
InvalidJsonFormat,
NoViewPermission,
ViewNotFound,
UnknownError),
Catalogs(notCore, notPSD2, notOBWG),
List(apiTagAccount))
lazy val addTagForViewOnAccount : OBPEndpoint = {
//add a tag
case "banks" :: BankId(bankId) :: "accounts" :: AccountId(accountId) :: ViewId(viewId) :: "metadata" :: "tags" :: Nil JsonPost json -> _ => {
cc =>
for {
(Full(u), callContext) <- authorizedAccess(cc)
(_, callContext) <- NewStyle.function.getBank(bankId, callContext)
(_, callContext) <- NewStyle.function.checkBankAccountExists(bankId, accountId, callContext)
view <- NewStyle.function.view(viewId, BankIdAccountId(bankId, accountId), callContext)
_ <- NewStyle.function.hasViewAccess(view, u)
_ <- Helper.booleanToFuture(failMsg = s"$NoViewPermission can_add_tag. Current ViewId($viewId)") {
view.canAddTag
}
tagJson <- NewStyle.function.tryons(s"$InvalidJsonFormat The Json body should be the $PostTransactionTagJSON ", 400, callContext) {
json.extract[PostTransactionTagJSON]
}
(postedTag, callContext) <- Future(Tags.tags.vend.addTagOnAccount(bankId, accountId)(u.userPrimaryKey, viewId, tagJson.value, now)) map {
i => (connectorEmptyResponse(i, callContext), callContext)
}
} yield {
(JSONFactory.createTransactionTagJSON(postedTag), HttpCode.`201`(callContext))
}
}
}
resourceDocs += ResourceDoc(
deleteTagForViewOnAccount,
implementedInApiVersion,
"deleteTagForViewOnAccount",
"DELETE",
"/banks/BANK_ID/accounts/ACCOUNT_ID/VIEW_ID/metadata/tags/TAG_ID",
"Delete a tag.",
"""Deletes the tag TAG_ID about the account ACCOUNT_ID made on [view](#1_2_1-getViewsForBankAccount).
|Authentication via OAuth is required. The user must either have owner privileges for this account,
|or must be the user that posted the tag.
|""".stripMargin,
emptyObjectJson,
emptyObjectJson,
List(NoViewPermission,
ViewNotFound,
UnknownError),
Catalogs(notCore, notPSD2, notOBWG),
List(apiTagAccount))
lazy val deleteTagForViewOnAccount : OBPEndpoint = {
//delete a tag
case "banks" :: BankId(bankId) :: "accounts" :: AccountId(accountId) :: ViewId(viewId) :: "metadata" :: "tags" :: tagId :: Nil JsonDelete _ => {
cc =>
for {
(Full(u), callContext) <- authorizedAccess(cc)
(_, callContext) <- NewStyle.function.getBank(bankId, callContext)
(_, callContext) <- NewStyle.function.checkBankAccountExists(bankId, accountId, callContext)
view <- NewStyle.function.view(viewId, BankIdAccountId(bankId, accountId), callContext)
_ <- NewStyle.function.hasViewAccess(view, u)
_ <- Helper.booleanToFuture(failMsg = s"$NoViewPermission can_delete_tag. Current ViewId($viewId)") {
view.canDeleteTag
}
deleted <- Future(Tags.tags.vend.deleteTagOnAccount(bankId, accountId)(tagId)) map {
i => (connectorEmptyResponse(i, callContext), callContext)
}
} yield {
(Full(deleted), HttpCode.`200`(callContext))
}
}
}
}
}

View File

@ -395,6 +395,8 @@ object OBPAPI4_0_0 extends OBPRestHelper with APIMethods130 with APIMethods140 w
Implementations4_0_0.root ::
Implementations4_0_0.getCallContext ::
Implementations4_0_0.getEntitlements ::
Implementations4_0_0.addTagForViewOnAccount ::
Implementations4_0_0.deleteTagForViewOnAccount ::
Nil
def allResourceDocs = MockerConnector.doc ++

View File

@ -32,11 +32,30 @@ object MappedTags extends Tags {
.date(datePosted).saveMe
}
}
override def addTagOnAccount(bankId: BankId, accountId: AccountId)
(userId: UserPrimaryKey, viewId: ViewId, tagText: String, datePosted: Date): Box[TransactionTag] = {
val metadateViewId = Views.views.vend.getMetadataViewId(BankIdAccountId(bankId, accountId), viewId)
tryo{
MappedTag.create
.bank(bankId.value)
.account(accountId.value)
.transaction(null)
.view(metadateViewId)
.user(userId.value)
.tag(tagText)
.date(datePosted).saveMe
}
}
override def deleteTag(bankId: BankId, accountId: AccountId, transactionId: TransactionId)(tagId: String): Box[Boolean] = {
//tagId is always unique so we actually don't need to use bankId, accountId, or transactionId
MappedTag.find(By(MappedTag.tagId, tagId)).map(_.delete_!)
}
override def deleteTagOnAccount(bankId: BankId, accountId: AccountId)(tagId: String): Box[Boolean] = {
//tagId is always unique so we actually don't need to use bankId, accountId, or transactionId
MappedTag.find(By(MappedTag.tagId, tagId), By(MappedTag.bank, bankId.value), By(MappedTag.account, accountId.value)).map(_.delete_!)
}
override def bulkDeleteTags(bankId: BankId, accountId: AccountId): Boolean = {
val tagsDeleted = MappedTag.bulkDelete_!!(

View File

@ -27,6 +27,15 @@ private object MongoTransactionTags extends Tags {
tag(tagText).
date(datePosted).saveTheRecord()
}
def addTagOnAccount(bankId : BankId, accountId : AccountId)(userId: UserPrimaryKey, viewId : ViewId, tagText : String, datePosted : Date) : Box[TransactionTag] = {
OBPTag.createRecord.
bankId(bankId.value).
accountId(accountId.value).
userId(userId.value).
forView(viewId.value).
tag(tagText).
date(datePosted).saveTheRecord()
}
def deleteTag(bankId : BankId, accountId : AccountId, transactionId: TransactionId)(tagId : String) : Box[Boolean] = {
//use delete with find query to avoid concurrency issues
OBPTag.delete(OBPTag.getFindQuery(bankId, accountId, transactionId, tagId))
@ -34,6 +43,9 @@ private object MongoTransactionTags extends Tags {
//we don't have any useful information here so just assume it worked
Full(true)
}
def deleteTagOnAccount(bankId : BankId, accountId : AccountId)(tagId : String) : Box[Boolean] = {
deleteTag(bankId, accountId, TransactionId(""))(tagId)
}
def bulkDeleteTags(bankId: BankId, accountId: AccountId): Boolean = ???

View File

@ -25,8 +25,10 @@ trait Tags {
def getTags(bankId : BankId, accountId : AccountId, transactionId: TransactionId)(viewId : ViewId) : List[TransactionTag]
def addTag(bankId : BankId, accountId : AccountId, transactionId: TransactionId)(userId: UserPrimaryKey, viewId : ViewId, tagText : String, datePosted : Date) : Box[TransactionTag]
def addTagOnAccount(bankId : BankId, accountId : AccountId)(userId: UserPrimaryKey, viewId : ViewId, tagText : String, datePosted : Date) : Box[TransactionTag]
//TODO: viewId? should tagId always be unique -> in that case bankId, accountId, and transactionId would not be required
def deleteTag(bankId : BankId, accountId : AccountId, transactionId: TransactionId)(tagId : String) : Box[Boolean]
def deleteTagOnAccount(bankId : BankId, accountId : AccountId)(tagId : String) : Box[Boolean]
def bulkDeleteTags(bankId: BankId, accountId: AccountId) : Boolean
}
@ -34,7 +36,9 @@ trait Tags {
class RemotedataTagsCaseClasses{
case class getTags(bankId : BankId, accountId : AccountId, transactionId: TransactionId, viewId : ViewId)
case class addTag(bankId : BankId, accountId : AccountId, transactionId: TransactionId, userId: UserPrimaryKey, viewId : ViewId, tagText : String, datePosted : Date)
case class addTagOnAccount(bankId : BankId, accountId : AccountId, userId: UserPrimaryKey, viewId : ViewId, tagText : String, datePosted : Date)
case class deleteTag(bankId : BankId, accountId : AccountId, transactionId: TransactionId, tagId : String)
case class deleteTagOnAccount(bankId : BankId, accountId : AccountId, tagId : String)
case class bulkDeleteTags(bankId: BankId, accountId: AccountId)
}

View File

@ -23,10 +23,16 @@ object RemotedataTags extends ObpActorInit with Tags {
def addTag(bankId : BankId, accountId : AccountId, transactionId: TransactionId)(userId: UserPrimaryKey, viewId : ViewId, tagText : String, datePosted : Date) : Box[TransactionTag] = getValueFromFuture(
(actor ? cc.addTag(bankId, accountId, transactionId, userId, viewId, tagText, datePosted)).mapTo[Box[TransactionTag]]
)
def addTagOnAccount(bankId : BankId, accountId : AccountId)(userId: UserPrimaryKey, viewId : ViewId, tagText : String, datePosted : Date) : Box[TransactionTag] = getValueFromFuture(
(actor ? cc.addTagOnAccount(bankId, accountId, userId, viewId, tagText, datePosted)).mapTo[Box[TransactionTag]]
)
def deleteTag(bankId : BankId, accountId : AccountId, transactionId: TransactionId)(tagId : String) : Box[Boolean] = getValueFromFuture(
(actor ? cc.deleteTag(bankId, accountId, transactionId, tagId)).mapTo[Box[Boolean]]
)
def deleteTagOnAccount(bankId : BankId, accountId : AccountId)(tagId : String) : Box[Boolean] = getValueFromFuture(
(actor ? cc.deleteTagOnAccount(bankId, accountId, tagId)).mapTo[Box[Boolean]]
)
def bulkDeleteTags(bankId: BankId, accountId: AccountId): Boolean = getValueFromFuture(
(actor ? cc.bulkDeleteTags(bankId, accountId)).mapTo[Boolean]

View File

@ -21,11 +21,19 @@ class RemotedataTagsActor extends Actor with ObpActorHelper with MdcLoggable {
case cc.addTag(bankId, accountId, transactionId, userId, viewId, text, datePosted) =>
logger.debug("addTag(" + bankId +", "+ accountId +", "+ transactionId +", "+ text +", "+ text +", "+ datePosted +")")
sender ! (mapper.addTag(bankId, accountId, transactionId)(userId, viewId, text, datePosted))
case cc.addTagOnAccount(bankId, accountId, userId, viewId, text, datePosted) =>
logger.debug("addTag(" + bankId +", "+ accountId +", " + text +", "+ text +", "+ datePosted +")")
sender ! (mapper.addTagOnAccount(bankId, accountId)(userId, viewId, text, datePosted))
case cc.deleteTag(bankId : BankId, accountId : AccountId, transactionId: TransactionId, tagId : String) =>
logger.debug("deleteTag(" + bankId +", "+ accountId +", "+ transactionId + tagId +")")
sender ! (mapper.deleteTag(bankId, accountId, transactionId)(tagId))
case cc.deleteTagOnAccount(bankId : BankId, accountId : AccountId, tagId : String) =>
logger.debug("deleteTag(" + bankId +", "+ accountId +", "+ tagId +")")
sender ! (mapper.deleteTagOnAccount(bankId, accountId)(tagId))
case cc.bulkDeleteTags(bankId: BankId, accountId: AccountId) =>
logger.debug("bulkDeleteTags(" + bankId +", "+ accountId + ")")
sender ! (mapper.bulkDeleteTags(bankId, accountId))