- Use UTF-8 encoding for all source files
- DO NOT use emojis in source code (scripts, Scala, Java, config files, etc.)
- Emojis are only allowed in Markdown (.md) files - use them if you must.
- Avoid non-ASCII characters in code unless absolutely necessary (e.g., comments in non-English languages)
- Use plain ASCII alternatives in source code:
- Instead of checkmark use [OK] or PASS
- Instead of X mark use [FAIL] or ERROR
- Instead of multiply use x
- Instead of arrow use -> or <- Thank you for your interest in contributing to the Open Bank Project!
If submitting a pull request please read and sign our CLA first.
In the first instance it is sufficient if you create a text file of the CLA with your name and include that in a git commit description.
If you end up making large changes to the source code, we might ask for a paper signed copy of your CLA sent by email to contact@tesobe.com
Please structure git commit messages in a way as shown below:
- bugfix/Something
- feature/Something
- docfix/Something
- refactor/Something
- performance/Something
- test/Something
- enhancement/Something
- security/Something
Please also check if it also needs to be tagged (see below)
- api_change <- if the requests/results of endpoints change or endpoints are added/deleted
Please comment your code ! :-) Imagine an engineer is trying to fix a production issue: she is working on a tiny screen, via a dodgy mobile Internet connection, in a sandstorm - Your code is fresh in your mind. Your comments could help her!
When naming variables use strict camel case e.g. use myUrl not myURL. This is so we can automatically convert from camelCase to snake_case for JSON output.
resourceDocs += ResourceDoc(
getCustomersForUser,
implementedInApiVersion,
nameOf(getCustomersForUser),
"GET",
"/users/current/customers",
"Get Customers for Current User",
s"""Gets all Customers that are linked to a User.
|
|
|${authenticationRequiredMessage(true)}
|
|""",
emptyObjectJson,
customerJsonV300,
List(
UserNotLoggedIn,
UserCustomerLinksNotFoundForUser,
UnknownError
),
Catalogs(notCore, notPSD2, notOBWG),
List(apiTagCustomer, apiTagUser))
// This can be considered a reference new style endpoint.
// This is a partial function. The lazy value should have a meaningful name.
lazy val getCustomersForUser : OBPEndpoint = {
// This defines the URL path and method (GET) for which this partial function will accept the call.
case "users" :: "current" :: "customers" :: Nil JsonGet _ => {
// We have the Call Context (cc) object (provided through the OBPEndpoint type)
// The Call Context contains the authorisation headers etc.
cc => {
for {
// Extract the user from the headers and get an updated callContext
(Full(u), callContext) <- authorizedAccess(cc)
// Now here is the business logic.
// Get The customers related to a user. Process the resonse which might be an Exception
(customers,callContext) <- Connector.connector.vend.getCustomersByUserIdFuture(u.userId, callContext) map {
connectorEmptyResponse(_, callContext)
}
} yield {
// Create the JSON to return. We also return the callContext
(JSONFactory300.createCustomersJson(customers), HttpCode.`200`(callContext))
}
}
}
} lazy val createProduct: OBPEndpoint = {
case "banks" :: BankId(bankId) :: "products" :: ProductCode(productCode) :: Nil JsonPut json -> _ => {
cc =>
for {
// 1. makes sure the user which attempts to use the endpoint is authorized
(Full(u), callContext) <- authorizedAccess(cc)
// 2. makes sure the user which attempts to use the endpoint is allowed to consume it
_ <- NewStyle.function.hasAtLeastOneEntitlement(failMsg = createProductEntitlementsRequiredText)(bankId.value, u.userId, createProductEntitlements, callContext)
// 3. checks the endpoint constraints
(_, callContext) <- NewStyle.function.getBank(bankId, callContext)
failMsg = s"$InvalidJsonFormat The Json body should be the $PostPutProductJsonV310 "
...Please note that that checks at an endpoint should be applied only in case an user is authorized and has privilege to consume the endpoint. Otherwise we can reveal sensitive data to the user. For instace if we reorder the checks in next way:
// 1. makes sure the user which attempts to use the endpoint is authorized
(Full(u), callContext) <- authorizedAccess(cc)
// 3. checks the endpoint constraints
(_, callContext) <- NewStyle.function.getBank(bankId, callContext)
failMsg = s"$InvalidJsonFormat The Json body should be the $PostPutProductJsonV310 "
(Full(u), callContext) <- authorizedAccess(cc)
// 2. makes sure the user which attempts to use the endpoint is allowed to consume it
_ <- NewStyle.function.hasAtLeastOneEntitlement(failMsg = createProductEntitlementsRequiredText)(bankId.value, u.userId, createProductEntitlements, callContext)the user which cannot consume the endpoint still can check does some bank exist or not at that instance. It's not the issue if banks are public data at the instance but it wouldn't be the only business case all the time.
When you write a test for an endpoint please tag it with a version and the endpoint. An example of how to tag tests:
class FundsAvailableTest extends V310ServerSetup {
/**
* Test tags
* Example: To run tests with tag "getPermissions":
* mvn test -D tagsToInclude
*
* This is made possible by the scalatest maven plugin
*/
object VersionOfApi extends Tag(ApiVersion.v3_1_0.toString)
object ApiEndpoint extends Tag(nameOf(Implementations3_1_0.checkFundsAvailable))
feature("Check available funds v3.1.0 - Unauthorized access")
{
scenario("We will check available without user credentials", ApiEndpoint, VersionOfApi) {
val bankId = randomBankId
val bankAccount = randomPrivateAccount(bankId)
val view = randomViewPermalink(bankId, bankAccount)
When("We make a request v3.1.0")
val request310 = (v3_1_0_Request / "banks" / bankId / "accounts" / bankAccount.bank_id / view / "funds-available").GET
val response310 = makeGetRequest(request310)
Then("We should get a 400")
response310.code should equal(400)
And("error should be " + UserNotLoggedIn)
response310.body.extract[ErrorMessage].error should equal (UserNotLoggedIn)
}
}
}If would like to report an issue or suggest any kind of improvement please use Github Issues.
Open Bank Project API, API Explorer and Sofit are dual licenced under the AGPL and commercial licenses. Open Bank Project SDKs are licenced under Apache 2 or MIT style licences.
Please see the NOTICE for each project licence.
See the README for instructions on setup and running the tests :-)
Welcome!