Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5508,6 +5508,9 @@ object SwaggerDefinitionsJSON {
val consumerLogoUrlJson = ConsumerLogoUrlJson(
"http://localhost:8888"
)
val consumerNameJson = ConsumerNameJson(
"App name"
)

val consumersJsonV510 = ConsumersJsonV510(
List(consumerJsonV510)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -704,15 +704,6 @@ where the consent was directly managed between ASPSP and PSU e.g. in a re-direct
}



def tweakStatusNames(status: String) = {
val scaStatus = status
.replace(ConsentStatus.INITIATED.toString, "started")
.replace(ConsentStatus.ACCEPTED.toString, "finalised")
.replace(ConsentStatus.REJECTED.toString, "failed")
scaStatus
}

resourceDocs += ResourceDoc(
getConsentScaStatus,
apiVersion,
Expand Down
2 changes: 1 addition & 1 deletion obp-api/src/main/scala/code/api/util/APIUtil.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3783,7 +3783,7 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{
*A Version 1 UUID is a universally unique identifier that is generated using
* a timestamp and the MAC address of the computer on which it was generated.
*/
def checkIfStringIsUUIDVersion1(value: String): Boolean = {
def checkIfStringIsUUID(value: String): Boolean = {
Pattern.compile("^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$")
.matcher(value).matches()
}
Expand Down
2 changes: 2 additions & 0 deletions obp-api/src/main/scala/code/api/util/ApiRole.scala
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,8 @@ object ApiRole extends MdcLoggable{

case class CanUpdateConsumerLogoUrl(requiresBankId: Boolean = false) extends ApiRole
lazy val canUpdateConsumerLogoUrl = CanUpdateConsumerLogoUrl()
case class CanUpdateConsumerName(requiresBankId: Boolean = false) extends ApiRole
lazy val canUpdateConsumerName = CanUpdateConsumerName()

case class CanCreateConsumer (requiresBankId: Boolean = false) extends ApiRole
lazy val canCreateConsumer = CanCreateConsumer()
Expand Down
7 changes: 4 additions & 3 deletions obp-api/src/main/scala/code/api/util/BerlinGroupCheck.scala
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package code.api.util

import code.api.RequestHeader
import code.api.APIFailureNewStyle
import code.api.util.APIUtil.fullBoxOrException
import com.openbankproject.commons.model.User
import net.liftweb.common.{Box, Empty, Failure}
import net.liftweb.common.{Box, Empty}
import net.liftweb.http.provider.HTTPParam

object BerlinGroupCheck {
Expand All @@ -27,7 +28,7 @@ object BerlinGroupCheck {
if (missingHeaders.isEmpty) {
forwardResult // All mandatory headers are present
} else {
(Failure(s"Missing mandatory headers: ${missingHeaders.mkString(", ")}"), forwardResult._2)
(fullBoxOrException(Empty ~> APIFailureNewStyle(s"${ErrorMessages.MissingMandatoryBerlinGroupHeaders}(${missingHeaders.mkString(", ")})", 400, forwardResult._2.map(_.toLight))), forwardResult._2)
}
}

Expand Down
2 changes: 1 addition & 1 deletion obp-api/src/main/scala/code/api/util/ConsentUtil.scala
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,7 @@ object Consent extends MdcLoggable {
}

def getConsentJwtValueByConsentId(consentId: String): Option[MappedConsent] = {
APIUtil.checkIfStringIsUUIDVersion1(consentId) match {
APIUtil.checkIfStringIsUUID(consentId) match {
case true => // String is a UUID
Consents.consentProvider.vend.getConsentByConsentId(consentId) match {
case Full(consent) => Some(consent)
Expand Down
1 change: 1 addition & 0 deletions obp-api/src/main/scala/code/api/util/ErrorMessages.scala
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,7 @@ object ErrorMessages {
val Oauth2ValidateAccessTokenError = "OBP-20215: There was a problem validating the OAuth2 access token. "

val AuthorizationHeaderAmbiguity = "OBP-20250: Request headers used for authorization are ambiguous. "
val MissingMandatoryBerlinGroupHeaders= "OBP-20251: Missing mandatory request headers. "

// X.509
val X509GeneralError = "OBP-20300: PEM Encoded Certificate issue."
Expand Down
44 changes: 40 additions & 4 deletions obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8188,12 +8188,12 @@ trait APIMethods400 extends MdcLoggable {
}
}
staticResourceDocs += ResourceDoc(
getConsentInfos,
getConsentInfosByBank,
implementedInApiVersion,
nameOf(getConsentInfos),
nameOf(getConsentInfosByBank),
"GET",
"/banks/BANK_ID/my/consent-infos",
"Get My Consents Info",
"Get My Consents Info By Bank",
s"""
|
|This endpoint gets the Consents that the current User created.
Expand All @@ -8210,7 +8210,7 @@ trait APIMethods400 extends MdcLoggable {
),
List(apiTagConsent, apiTagPSD2AIS, apiTagPsd2))

lazy val getConsentInfos: OBPEndpoint = {
lazy val getConsentInfosByBank: OBPEndpoint = {
case "banks" :: BankId(bankId) :: "my" :: "consent-infos" :: Nil JsonGet _ => {
cc => implicit val ec = EndpointContext(Some(cc))
for {
Expand All @@ -8224,6 +8224,42 @@ trait APIMethods400 extends MdcLoggable {
}
}

staticResourceDocs += ResourceDoc(
getConsentInfos,
implementedInApiVersion,
nameOf(getConsentInfos),
"GET",
"/my/consent-infos",
"Get My Consents Info",
s"""
|
|This endpoint gets the Consents that the current User created.
|
|${userAuthenticationMessage(true)}
|
""".stripMargin,
EmptyBody,
consentInfosJsonV400,
List(
$UserNotLoggedIn,
$BankNotFound,
UnknownError
),
List(apiTagConsent, apiTagPSD2AIS, apiTagPsd2))

lazy val getConsentInfos: OBPEndpoint = {
case "my" :: "consent-infos" :: Nil JsonGet _ => {
cc => implicit val ec = EndpointContext(Some(cc))
for {
consents <- Future { Consents.consentProvider.vend.getConsentsByUser(cc.userId)
.sortBy(i => (i.creationDateTime, i.apiStandard)).reverse
}
} yield {
(JSONFactory400.createConsentInfosJsonV400(consents), HttpCode.`200`(cc))
}
}
}

staticResourceDocs += ResourceDoc(
getMyPersonalUserAttributes,
implementedInApiVersion,
Expand Down
93 changes: 89 additions & 4 deletions obp-api/src/main/scala/code/api/v5_1_0/APIMethods510.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1518,12 +1518,12 @@ trait APIMethods510 {


staticResourceDocs += ResourceDoc(
getMyConsents,
getMyConsentsByBank,
implementedInApiVersion,
nameOf(getMyConsents),
nameOf(getMyConsentsByBank),
"GET",
"/banks/BANK_ID/my/consents",
"Get My Consents",
"Get My Consents at Bank",
s"""
|
|This endpoint gets the Consents created by a current User.
Expand All @@ -1540,7 +1540,7 @@ trait APIMethods510 {
),
List(apiTagConsent, apiTagPSD2AIS, apiTagPsd2))

lazy val getMyConsents: OBPEndpoint = {
lazy val getMyConsentsByBank: OBPEndpoint = {
case "banks" :: BankId(bankId) :: "my" :: "consents" :: Nil JsonGet _ => {
cc =>
implicit val ec = EndpointContext(Some(cc))
Expand All @@ -1556,6 +1556,44 @@ trait APIMethods510 {
}
}

staticResourceDocs += ResourceDoc(
getMyConsents,
implementedInApiVersion,
nameOf(getMyConsents),
"GET",
"/my/consents",
"Get My Consents",
s"""
|
|This endpoint gets the Consents created by a current User.
|
|${userAuthenticationMessage(true)}
|
""".stripMargin,
EmptyBody,
consentsJsonV400,
List(
$UserNotLoggedIn,
$BankNotFound,
UnknownError
),
List(apiTagConsent, apiTagPSD2AIS, apiTagPsd2))

lazy val getMyConsents: OBPEndpoint = {
case "my" :: "consents" :: Nil JsonGet _ => {
cc =>
implicit val ec = EndpointContext(Some(cc))
for {
consents <- Future {
Consents.consentProvider.vend.getConsentsByUser(cc.userId)
.sortBy(i => (i.creationDateTime, i.apiStandard)).reverse
}
} yield {
(createConsentsInfoJsonV510(consents), HttpCode.`200`(cc))
}
}
}


staticResourceDocs += ResourceDoc(
getConsentsAtBank,
Expand Down Expand Up @@ -3160,6 +3198,53 @@ trait APIMethods510 {
}
}

staticResourceDocs += ResourceDoc(
updateConsumerName,
implementedInApiVersion,
nameOf(updateConsumerName),
"PUT",
"/management/consumers/CONSUMER_ID/consumer/name",
"Update Consumer Name",
s"""Update an existing name for a Consumer specified by CONSUMER_ID.
|
| ${consumerDisabledText()}
|
| CONSUMER_ID can be obtained after you register the application.
|
| Or use the endpoint 'Get Consumers' to get it
|
""".stripMargin,
consumerNameJson,
consumerJsonV510,
List(
$UserNotLoggedIn,
UserHasMissingRoles,
UnknownError
),
List(apiTagConsumer),
Some(List(canUpdateConsumerName))
)

lazy val updateConsumerName: OBPEndpoint = {
case "management" :: "consumers" :: consumerId :: "consumer" :: "name" :: Nil JsonPut json -> _ => {
cc =>
implicit val ec = EndpointContext(Some(cc))
for {
postJson <- NewStyle.function.tryons(InvalidJsonFormat, 400, cc.callContext) {
json.extract[ConsumerNameJson]
}
consumer <- NewStyle.function.getConsumerByConsumerId(consumerId, cc.callContext)
updatedConsumer <- NewStyle.function.updateConsumer(
id = consumer.id.get,
name = Some(postJson.app_name),
callContext = cc.callContext
)
} yield {
(JSONFactory510.createConsumerJSON(updatedConsumer), HttpCode.`200`(cc.callContext))
}
}
}


staticResourceDocs += ResourceDoc(
getConsumer,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -559,6 +559,7 @@ case class APITags(
case class ConsumerLogoUrlJson(
logo_url: String
)
case class ConsumerNameJson(app_name: String)

case class TransactionRequestJsonV510(
transaction_request_id: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -897,10 +897,31 @@ object LocalMappedConnector extends Connector with MdcLoggable {
}
}

def getBankAccountCommon(bankId: BankId, accountId: AccountId, callContext: Option[CallContext]) = {
MappedBankAccount
.find(By(MappedBankAccount.bank, bankId.value), By(MappedBankAccount.theAccountId, accountId.value))
.map(bankAccount => (bankAccount, callContext))
def getBankAccountCommon(bankId: BankId, accountId: AccountId, callContext: Option[CallContext]): Box[(MappedBankAccount, Option[CallContext])] = {

def getByBankAndAccount(): Box[(MappedBankAccount, Option[CallContext])] = {
MappedBankAccount
.find(By(MappedBankAccount.bank, bankId.value), By(MappedBankAccount.theAccountId, accountId.value))
.map(bankAccount => (bankAccount, callContext))
}

if(APIUtil.checkIfStringIsUUID(accountId.value)) {
// Find bank accounts by accountId first
val bankAccounts = MappedBankAccount.findAll(By(MappedBankAccount.theAccountId, accountId.value))

// If exactly one account is found, return it, else filter by bankId
bankAccounts match {
case account :: Nil =>
// If exactly one account is found, return it
Some(account, callContext)
case _ =>
// If multiple or no accounts are found, filter by bankId
getByBankAndAccount()
}
} else {
getByBankAndAccount()
}

}

override def getBankAccounts(bankIdAccountIds: List[BankIdAccountId], callContext: Option[CallContext]): OBPReturnType[Box[List[BankAccount]]] = {
Expand Down
Binary file modified obp-api/src/test/resources/frozen_type_meta_data
Binary file not shown.
28 changes: 24 additions & 4 deletions obp-api/src/test/scala/code/api/v5_1_0/ConsentsTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ class ConsentsTest extends V510ServerSetup with PropsReset{
object ApiEndpoint5 extends Tag(nameOf(Implementations4_0_0.getUsers))
object ApiEndpoint6 extends Tag(nameOf(Implementations5_1_0.revokeConsentAtBank))
object ApiEndpoint7 extends Tag(nameOf(Implementations5_1_0.getConsentByConsentId))
object ApiEndpoint8 extends Tag(nameOf(Implementations5_1_0.getMyConsents))
object ApiEndpoint8 extends Tag(nameOf(Implementations5_1_0.getMyConsentsByBank))
object getMyConsents extends Tag(nameOf(Implementations5_1_0.getMyConsents))
object ApiEndpoint9 extends Tag(nameOf(Implementations5_1_0.getConsentsAtBank))
object GetConsents extends Tag(nameOf(Implementations5_1_0.getConsents))
object UpdateConsentStatusByConsent extends Tag(nameOf(Implementations5_1_0.updateConsentStatusByConsent))
Expand All @@ -92,7 +93,8 @@ class ConsentsTest extends V510ServerSetup with PropsReset{
def getConsentByRequestIdUrl(requestId:String) = (v5_1_0_Request / "consumer"/ "consent-requests"/requestId/"consents").GET<@(user1)
def getConsentByIdUrl(requestId:String) = (v5_1_0_Request / "consumer" / "current" / "consents" / requestId ).GET<@(user1)
def revokeConsentUrl(consentId: String) = (v5_1_0_Request / "banks" / bankId / "consents" / consentId).DELETE
def getMyConsents(consentId: String) = (v5_1_0_Request / "banks" / bankId / "my" / "consents").GET
def getMyConsentAtBank(consentId: String) = (v5_1_0_Request / "banks" / bankId / "my" / "consents").GET
def getMyConsent(consentId: String) = (v5_1_0_Request / "my" / "consents").GET
def getConsentsAtBAnk(consentId: String) = (v5_1_0_Request / "management"/ "consents" / "banks" / bankId).GET
def getConsents(consentId: String) = (v5_1_0_Request / "management"/ "consents").GET
def updateConsentStatusByConsent(consentId: String) = (v5_1_0_Request / "management" / "banks" / bankId / "consents" / consentId).PUT
Expand Down Expand Up @@ -120,7 +122,7 @@ class ConsentsTest extends V510ServerSetup with PropsReset{
feature(s"test $ApiEndpoint8 version $VersionOfApi - Unautenticated access") {
scenario("We will call the endpoint without user credentials", ApiEndpoint8, VersionOfApi) {
When(s"We make a request $ApiEndpoint8")
val response510 = makeGetRequest(getMyConsents("whatever"))
val response510 = makeGetRequest(getMyConsentAtBank("whatever"))
Then("We should get a 401")
response510.code should equal(401)
response510.body.extract[ErrorMessage].message should equal(UserNotLoggedIn)
Expand All @@ -129,7 +131,25 @@ class ConsentsTest extends V510ServerSetup with PropsReset{
feature(s"test $ApiEndpoint8 version $VersionOfApi - Autenticated access") {
scenario("We will call the endpoint with user credentials", ApiEndpoint8, VersionOfApi) {
When(s"We make a request $ApiEndpoint1")
val response510 = makeGetRequest(getMyConsents("whatever")<@(user1))
val response510 = makeGetRequest(getMyConsentAtBank("whatever")<@(user1))
Then("We should get a 200")
response510.code should equal(200)
}
}

feature(s"test $getMyConsents version $VersionOfApi - Unautenticated access") {
scenario("We will call the endpoint without user credentials", getMyConsents, VersionOfApi) {
When(s"We make a request $getMyConsents")
val response510 = makeGetRequest(getMyConsent("whatever"))
Then("We should get a 401")
response510.code should equal(401)
response510.body.extract[ErrorMessage].message should equal(UserNotLoggedIn)
}
}
feature(s"test $getMyConsents version $VersionOfApi - Autenticated access") {
scenario("We will call the endpoint with user credentials", getMyConsents, VersionOfApi) {
When(s"We make a request $ApiEndpoint1")
val response510 = makeGetRequest(getMyConsent("whatever")<@(user1))
Then("We should get a 200")
response510.code should equal(200)
}
Expand Down
Loading
Loading