Skip to content

Commit

Permalink
Merge pull request #2302 from hongwei1/develop
Browse files Browse the repository at this point in the history
feature/added obpIdCheck for all post json
  • Loading branch information
simonredfern authored Oct 24, 2023
2 parents 9e8e36a + 12970d8 commit b9fce7e
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 2 deletions.
2 changes: 2 additions & 0 deletions obp-api/src/main/scala/bootstrap/liftweb/CustomDBVendor.scala
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ class CustomDBVendor(driverName: String,
if(maxLifetime.isDefined){
config.setMaxLifetime(maxLifetime.head)
}
//Liftweb DB.scala will set all the new connections to false, so here we set default to false
config.setAutoCommit(false)

(dbUser, dbPassword) match {
case (Full(user), Full(pwd)) =>
Expand Down
48 changes: 48 additions & 0 deletions obp-api/src/main/scala/code/api/util/APIUtil.scala
Original file line number Diff line number Diff line change
Expand Up @@ -995,6 +995,20 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{
}
}


/** only A-Z, a-z, 0-9, -, _, ., and max length <= 36
* OBP APIUtil.generateUUID() length is 36 here.*/
def checkObpId(value:String): String ={
val valueLength = value.length
val regex = """^([A-Za-z0-9\-._]+)$""".r
value match {
case _ if value.isEmpty => SILENCE_IS_GOLDEN
case regex(e) if(valueLength <= 36) => SILENCE_IS_GOLDEN
case regex(e) if(valueLength > 36) => ErrorMessages.InvalidValueLength+" The maximum OBP id length is 36. "
case _ => ErrorMessages.InvalidValueCharacters + " only A-Z, a-z, 0-9, -, _, ., and max length <= 36 "
}
}

/** only A-Z, a-z, 0-9, -, _, ., @, space and max length <= 512 */
def checkUsernameString(value:String): String ={
val valueLength = value.length
Expand Down Expand Up @@ -1819,6 +1833,21 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{
def checkAuth(cc: CallContext): Future[(Box[User], Option[CallContext])] = {
if (isNeedCheckAuth) authenticatedAccessFun(cc) else anonymousAccessFun(cc)
}

def checkObpIds(obpKeyValuePairs: List[(String, String)], callContext: Option[CallContext]): Future[Option[CallContext]] = {
Future{
val allInvalidValueParis = obpKeyValuePairs
.filter(
keyValuePair =>
!checkObpId(keyValuePair._2).equals(SILENCE_IS_GOLDEN)
)
if(allInvalidValueParis.nonEmpty){
throw new RuntimeException(s"$InvalidJsonFormat Here are all invalid values: $allInvalidValueParis")
}else{
callContext
}
}
}

def checkRoles(bankId: Option[BankId], user: Box[User], cc: Option[CallContext]):Future[Box[Unit]] = {
if (isNeedCheckRoles) {
Expand Down Expand Up @@ -1915,6 +1944,11 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{
val originFn: CallContext => Box[JsonResponse] = obpEndpoint.apply(req)

val pathParams = getPathParams(req.path.partPath)

val allObpKeyValuePairs = if(req.request.method =="POST" &&req.json.isDefined)
getAllObpIdKeyValuePairs(req.json.getOrElse(JString("")))
else Nil

val bankId = pathParams.get("BANK_ID").map(BankId(_))
val accountId = pathParams.get("ACCOUNT_ID").map(AccountId(_))
val viewId = pathParams.get("VIEW_ID").map(ViewId(_))
Expand All @@ -1941,6 +1975,8 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{
// if authentication check, do authorizedAccess, else do Rate Limit check
for {
(boxUser, callContext) <- checkAuth(cc)

_ <- checkObpIds(allObpKeyValuePairs, callContext)

// check bankId is valid
(bank, callContext) <- checkBank(bankId, callContext)
Expand Down Expand Up @@ -4813,4 +4849,16 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{
Empty, Empty)
}

def getAllObpIdKeyValuePairs(json: JValue): List[(String, String)] = {
// all the OBP ids:
json
.filterField {
case JField(n, v) =>
(n == "id" || n == "user_id" || n == "bank_id" || n == "account_id" || n == "customer_id"
|| n == "branch_id" || n == "atm_id" || n == "transaction_id" || n == "transaction_request_id"
|| n == "card_id"|| n == "view_id")&&v.isInstanceOf[JString]}
.map(
jField => (jField.name, jField.value.asInstanceOf[JString].s)
)
}
}
2 changes: 1 addition & 1 deletion obp-api/src/main/scala/code/api/util/ExampleValue.scala
Original file line number Diff line number Diff line change
Expand Up @@ -859,7 +859,7 @@ object ExampleValue {
lazy val websiteExample = ConnectorField("www.openbankproject.com",NoDescriptionProvided)
glossaryItems += makeGlossaryItem("website", websiteExample)

lazy val atmIdExample = ConnectorField("atme0352a-9a0f-4bfa-b30b-9003aa467f51","A string that MUST uniquely identify the ATM on this OBP instance.")
lazy val atmIdExample = ConnectorField("atme-9a0f-4bfa-b30b-9003aa467f51","A string that MUST uniquely identify the ATM on this OBP instance.")
glossaryItems += makeGlossaryItem("atm_id", atmIdExample)

lazy val atmAttributeIdExample = ConnectorField("xxaf2a-9a0f-4bfa-b30b-9003aa467f51","A string that MUST uniquely identify the ATM Attribute on this OBP instance.")
Expand Down
4 changes: 3 additions & 1 deletion obp-api/src/test/scala/code/setup/ServerSetup.scala
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,9 @@ trait ServerSetup extends FeatureSpec with SendServerRequests
setPropsValues("transactionRequests_supported_types" -> "SEPA,SANDBOX_TAN,FREE_FORM,COUNTERPARTY,ACCOUNT,ACCOUNT_OTP,SIMPLE,CARD")
setPropsValues("CARD_OTP_INSTRUCTION_TRANSPORT" -> "DUMMY")
setPropsValues("api_instance_id" -> "1_final")

setPropsValues("starConnector_supported_types" -> "mapped,internal")
setPropsValues("connector" -> "star")

val server = TestServer
def baseRequest = host(server.host, server.port)
val secured = APIUtil.getPropsAsBoolValue("external.https", false)
Expand Down
75 changes: 75 additions & 0 deletions obp-api/src/test/scala/code/util/APIUtilTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,11 @@ import code.api.util.APIUtil.{DateWithMsFormat, DefaultToDate, theEpochTime, _}
import code.api.util.ErrorMessages._
import code.api.util._
import code.setup.PropsReset
import code.util.Helper.SILENCE_IS_GOLDEN
import com.openbankproject.commons.model.UserAuthContextCommons
import net.liftweb.common.{Box, Empty, Full}
import net.liftweb.http.provider.HTTPParam
import net.liftweb.json.{JValue, parse}
import org.scalatest.{FeatureSpec, GivenWhenThen, Matchers}

class APIUtilTest extends FeatureSpec with Matchers with GivenWhenThen with PropsReset {
Expand Down Expand Up @@ -748,6 +750,79 @@ class APIUtilTest extends FeatureSpec with Matchers with GivenWhenThen with Prop
val actualValue = APIUtil.getBankIdAccountIdPairsFromUserAuthContexts(userAuthContexts)
actualValue should be(expectedValue)
}

scenario(s"Test the getAllObpIdKeyValuePairs method") {
val json: JValue = parse(
"""{
| "account_id": "1",
| "id": "2",
| "customer_id": "3",
| "age": 1,
| "catchphrase": {
| "one": {
| "atm_id": "4",
| "value": {
| "one": {
| "one": {
| "bank_id": "5",
| "transaction_id": "6"
| },
| "user_id": "7"
| },
| "id":"8"
| }
| },
| "card_id": "9"
| }
|}""".stripMargin)

val actualValue = APIUtil.getAllObpIdKeyValuePairs(json)
val expectedValue= List(
("account_id","1"),
("id","2"),
("customer_id","3"),
("atm_id","4"),
("bank_id","5"),
("transaction_id","6"),
("user_id","7"),
("id","8"),
("card_id","9")
)
actualValue should be(expectedValue)
}


scenario(s"Test the checkObpId method") {
val id1 = "gh.29.uk"
val id2 = "1313_.121"
val id3 = APIUtil.generateUUID()
val id7 = "" //the empty string

// error cases
val id4 = "+123313" //do not support +
val id5 = "@#$" //do not support @#$
val id6 = APIUtil.generateUUID() +"1" //the max length is 36

val actualValue1 = APIUtil.checkObpId(id1)
val actualValue2 = APIUtil.checkObpId(id2)
val actualValue3 = APIUtil.checkObpId(id3)

val actualValue4 = APIUtil.checkObpId(id4)
val actualValue5 = APIUtil.checkObpId(id5)
val actualValue6 = APIUtil.checkObpId(id6)
val actualValue7 = APIUtil.checkObpId(id7)


SILENCE_IS_GOLDEN should be(actualValue1)
SILENCE_IS_GOLDEN should be(actualValue2)
SILENCE_IS_GOLDEN should be(actualValue3)
SILENCE_IS_GOLDEN should be(actualValue7)

actualValue4 contains (InvalidValueCharacters) shouldBe (true)
actualValue5 contains (InvalidValueCharacters) shouldBe (true)
actualValue6 contains (InvalidValueLength) shouldBe (true)

}

}

Expand Down

0 comments on commit b9fce7e

Please sign in to comment.