Merge pull request #2141 from constantine2nd/develop

A few features
This commit is contained in:
Simon Redfern 2022-10-27 12:21:43 +02:00 committed by GitHub
commit 4aaf5e6a2f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
40 changed files with 1866 additions and 136 deletions

View File

@ -122,7 +122,7 @@ import code.transactionattribute.MappedTransactionAttribute
import code.transactionrequests.{MappedTransactionRequest, MappedTransactionRequestTypeCharge, TransactionRequestReasons}
import code.usercustomerlinks.MappedUserCustomerLink
import code.userlocks.UserLocks
import code.users.{UserAgreement, UserAttribute, UserInitAction, UserInvitation}
import code.users.{UserAgreement, UserAttribute, UserInitAction, UserInvitation, Users}
import code.util.Helper.MdcLoggable
import code.util.{Helper, HydraUtil}
import code.validation.JsonSchemaValidation
@ -130,7 +130,7 @@ import code.views.Views
import code.views.system.{AccountAccess, ViewDefinition}
import code.webhook.{BankAccountNotificationWebhook, MappedAccountWebhook, SystemAccountNotificationWebhook, WebhookHelperActors}
import code.webuiprops.WebUiProps
import com.openbankproject.commons.model.ErrorMessage
import com.openbankproject.commons.model.{ErrorMessage, User}
import com.openbankproject.commons.util.Functions.Implicits._
import com.openbankproject.commons.util.{ApiVersion, Functions}
import javax.mail.{Authenticator, PasswordAuthentication}
@ -611,7 +611,11 @@ class Boot extends MdcLoggable {
// In case it's true we use that value to set up a new cookie value
S.param("locale") match {
case Full(requestedLocale) if requestedLocale != null => {
val computedLocale = I18NUtil.computeLocale(requestedLocale)
val computedLocale: Locale = I18NUtil.computeLocale(requestedLocale)
val id: Long = AuthUser.getCurrentUser.map(_.user.userPrimaryKey.value).getOrElse(0)
Users.users.vend.getResourceUserByResourceUserId(id).map {
u => u.LastUsedLocale(computedLocale.toString).save
}
S.addCookie(HTTPCookie(localeCookieName, requestedLocale))
computedLocale
}

View File

@ -95,7 +95,7 @@ object SwaggerDefinitionsJSON {
accountRoutings = List(accountRouting)
)
val createViewJson = CreateViewJson(
val createViewJsonV300 = CreateViewJsonV300(
name = "_test",
description = "This view is for family",
metadata_view ="_test",
@ -186,9 +186,103 @@ object SwaggerDefinitionsJSON {
)
)
val createSystemViewJson = createViewJson.copy(name = "test", metadata_view = "test", is_public = false)
val createSystemViewJsonV300 = createViewJsonV300.copy(name = "test", metadata_view = "test", is_public = false)
val updateViewJSON = UpdateViewJSON(
val createSystemViewJsonV500 = CreateViewJsonV500(
name = "_test",
description = "This view is for family",
metadata_view ="_test",
is_public = false,
which_alias_to_use = "family",
hide_metadata_if_alias_used = false,
allowed_actions = List(
"can_see_transaction_this_bank_account",
"can_see_transaction_other_bank_account",
"can_see_transaction_metadata",
"can_see_transaction_label",
"can_see_transaction_amount",
"can_see_transaction_type",
"can_see_transaction_currency",
"can_see_transaction_start_date",
"can_see_transaction_finish_date",
"can_see_transaction_balance",
"can_see_comments",
"can_see_narrative",
"can_see_tags",
"can_see_images",
"can_see_bank_account_owners",
"can_see_bank_account_type",
"can_see_bank_account_balance",
"can_see_bank_account_currency",
"can_see_bank_account_label",
"can_see_bank_account_national_identifier",
"can_see_bank_account_swift_bic",
"can_see_bank_account_iban",
"can_see_bank_account_number",
"can_see_bank_account_bank_name",
"can_see_other_account_national_identifier",
"can_see_other_account_swift_bic",
"can_see_other_account_iban",
"can_see_other_account_bank_name",
"can_see_other_account_number",
"can_see_other_account_metadata",
"can_see_other_account_kind",
"can_see_more_info",
"can_see_url",
"can_see_image_url",
"can_see_open_corporates_url",
"can_see_corporate_location",
"can_see_physical_location",
"can_see_public_alias",
"can_see_private_alias",
"can_add_more_info",
"can_add_url",
"can_add_image_url",
"can_add_open_corporates_url",
"can_add_corporate_location",
"can_add_physical_location",
"can_add_public_alias",
"can_add_private_alias",
"can_delete_corporate_location",
"can_delete_physical_location",
"can_edit_narrative",
"can_add_comment",
"can_delete_comment",
"can_add_tag",
"can_delete_tag",
"can_add_image",
"can_delete_image",
"can_add_where_tag",
"can_see_where_tag",
"can_delete_where_tag",
"can_create_counterparty",
//V300 New
"can_see_bank_routing_scheme",
"can_see_bank_routing_address",
"can_see_bank_account_routing_scheme",
"can_see_bank_account_routing_address",
"can_see_other_bank_routing_scheme",
"can_see_other_bank_routing_address",
"can_see_other_account_routing_scheme",
"can_see_other_account_routing_address",
//v310
"can_query_available_funds",
"can_add_transaction_request_to_own_account",
"can_add_transaction_request_to_any_account",
"can_see_bank_account_credit_limit",
//v400
"can_create_direct_debit",
"can_create_standing_order",
//payments
"can_add_transaction_request_to_any_account"
),
// Version 5.0.0
can_grant_access_to_views = Some(List("owner")),
can_revoke_access_to_views = Some(List("owner"))
)
val updateViewJsonV300 = UpdateViewJsonV300(
description = "this is for family",
is_public = true,
metadata_view = SYSTEM_OWNER_VIEW_ID,
@ -267,8 +361,91 @@ object SwaggerDefinitionsJSON {
"can_query_available_funds"
)
)
lazy val updateSystemViewJson310 = updateViewJsonV300.copy(is_public = false, is_firehose = Some(false))
lazy val updateSystemViewJson310 = updateViewJSON.copy(is_public = false, is_firehose = Some(false))
val updateViewJsonV500 = UpdateViewJsonV500(
description = "this is for family",
is_public = true,
metadata_view = SYSTEM_OWNER_VIEW_ID,
which_alias_to_use = "family",
hide_metadata_if_alias_used = true,
allowed_actions = List(
"can_see_transaction_this_bank_account",
"can_see_transaction_other_bank_account",
"can_see_transaction_metadata",
"can_see_transaction_label",
"can_see_transaction_amount",
"can_see_transaction_type",
"can_see_transaction_currency",
"can_see_transaction_start_date",
"can_see_transaction_finish_date",
"can_see_transaction_balance",
"can_see_comments",
"can_see_narrative", "can_see_tags",
"can_see_images",
"can_see_bank_account_owners",
"can_see_bank_account_type",
"can_see_bank_account_balance",
"can_see_bank_account_currency",
"can_see_bank_account_label",
"can_see_bank_account_national_identifier",
"can_see_bank_account_swift_bic",
"can_see_bank_account_iban",
"can_see_bank_account_number",
"can_see_bank_account_bank_name",
"can_see_other_account_national_identifier",
"can_see_other_account_swift_bic",
"can_see_other_account_iban",
"can_see_other_account_bank_name",
"can_see_other_account_number",
"can_see_other_account_metadata",
"can_see_other_account_kind",
"can_see_more_info",
"can_see_url",
"can_see_image_url",
"can_see_open_corporates_url",
"can_see_corporate_location",
"can_see_physical_location",
"can_see_public_alias",
"can_see_private_alias",
"can_add_more_info",
"can_add_url",
"can_add_image_url",
"can_add_open_corporates_url",
"can_add_corporate_location",
"can_add_physical_location",
"can_add_public_alias",
"can_add_private_alias",
"can_delete_corporate_location",
"can_delete_physical_location",
"can_edit_narrative",
"can_add_comment",
"can_delete_comment",
"can_add_tag",
"can_delete_tag",
"can_add_image",
"can_delete_image",
"can_add_where_tag",
"can_see_where_tag",
"can_delete_where_tag",
"can_create_counterparty",
//V300 New
"can_see_bank_routing_scheme",
"can_see_bank_routing_address",
"can_see_bank_account_routing_scheme",
"can_see_bank_account_routing_address",
"can_see_other_bank_routing_scheme",
"can_see_other_bank_routing_address",
"can_see_other_account_routing_scheme",
"can_see_other_account_routing_address",
//v310
"can_query_available_funds"
),
// Version 5.0.0
can_grant_access_to_views = Some(List("owner")),
can_revoke_access_to_views = Some(List("owner"))
)
lazy val updateSystemViewJson500 = updateViewJsonV500.copy(is_public = false, is_firehose = Some(false))
val transactionTypeIdSwagger = TransactionTypeId(value = "123")
@ -834,8 +1011,8 @@ object SwaggerDefinitionsJSON {
)
val bankRoutingJsonV121 = BankRoutingJsonV121(
scheme = "Bank_ID",
address = "gh.29.uk"
scheme = schemeExample.value,
address = addressExample.value
)
val bankJSON = BankJSON(
@ -859,6 +1036,14 @@ object SwaggerDefinitionsJSON {
list = List(bankAttributeBankResponseJsonV400)
)
val postBankJson400 = PostBankJson400(
id = "gh.29.uk",
short_name = "short_name ",
full_name = "full_name",
logo = "logo",
website = "www.openbankproject.com",
bank_routings = List(bankRoutingJsonV121)
)
val bankJson400 = BankJson400(
id = "gh.29.uk",
short_name = "short_name ",
@ -869,23 +1054,22 @@ object SwaggerDefinitionsJSON {
attributes = Some(List(bankAttributeBankResponseJsonV400))
)
val bankJson500 = BankJson500(
id = "gh.29.uk",
bank_code = "bank_code ",
full_name = "full_name",
logo = "logo",
website = "www.openbankproject.com",
id = bankIdExample.value,
bank_code = bankCodeExample.value,
full_name = bankFullNameExample.value,
logo = bankLogoUrlExample.value,
website = bankLogoUrlExample.value,
bank_routings = List(bankRoutingJsonV121),
attributes = Some(List(bankAttributeBankResponseJsonV400))
)
val postBankJson500 = PostBankJson500(
id = Some("gh.29.uk"),
bank_code = "bank_code",
full_name = Some("full_name"),
logo = Some("logo"),
website = Some("www.openbankproject.com"),
bank_routings = Some(List(bankRoutingJsonV121)),
attributes = Some(List(bankAttributeBankResponseJsonV400))
id = Some(idExample.value),
bank_code = bankCodeExample.value,
full_name = Some(fullNameExample.value),
logo = Some(logoExample.value),
website = Some(websiteExample.value),
bank_routings = Some(List(bankRoutingJsonV121))
)
val banksJSON400 = BanksJson400(
@ -1281,7 +1465,7 @@ object SwaggerDefinitionsJSON {
face_image = customerFaceImageJson,
date_of_birth = DateWithDayExampleObject,
relationship_status = ExampleValue.relationshipStatusExample.value,
dependants = ExampleValue.dependentsExample.value.toInt,
dependants = ExampleValue.dependantsExample.value.toInt,
dob_of_dependants = List(DateWithDayExampleObject),
highest_education_attained = ExampleValue.highestEducationAttainedExample.value,
employment_status = ExampleValue.employmentStatusExample.value,
@ -1298,7 +1482,7 @@ object SwaggerDefinitionsJSON {
face_image = customerFaceImageJson,
date_of_birth = DateWithDayExampleObject,
relationship_status = ExampleValue.relationshipStatusExample.value,
dependants = ExampleValue.dependentsExample.value.toInt,
dependants = ExampleValue.dependantsExample.value.toInt,
dob_of_dependants = List(DateWithDayExampleObject),
highest_education_attained = ExampleValue.highestEducationAttainedExample.value,
employment_status = ExampleValue.employmentStatusExample.value,
@ -2002,7 +2186,7 @@ object SwaggerDefinitionsJSON {
face_image = customerFaceImageJson,
date_of_birth = DateWithDayExampleObject,
relationship_status = ExampleValue.relationshipStatusExample.value,
dependants = ExampleValue.dependentsExample.value.toInt,
dependants = ExampleValue.dependantsExample.value.toInt,
dob_of_dependants = List(DateWithDayExampleObject),
highest_education_attained = ExampleValue.highestEducationAttainedExample.value,
employment_status = ExampleValue.employmentStatusExample.value,
@ -2136,7 +2320,7 @@ object SwaggerDefinitionsJSON {
face_image = customerFaceImageJson,
date_of_birth = DateWithDayExampleObject,
relationship_status = ExampleValue.relationshipStatusExample.value,
dependants = ExampleValue.dependentsExample.value.toInt,
dependants = ExampleValue.dependantsExample.value.toInt,
dob_of_dependants = List(DateWithDayExampleObject),
credit_rating = Option(customerCreditRatingJSON),
credit_limit = Option(amountOfMoneyJsonV121),
@ -2172,7 +2356,7 @@ object SwaggerDefinitionsJSON {
face_image = customerFaceImageJson,
date_of_birth = DateWithDayExampleObject,
relationship_status = ExampleValue.relationshipStatusExample.value,
dependants = ExampleValue.dependentsExample.value.toInt,
dependants = ExampleValue.dependantsExample.value.toInt,
dob_of_dependants = List(DateWithDayExampleObject),
credit_rating = customerCreditRatingJSON,
credit_limit = amountOfMoneyJsonV121,
@ -2192,7 +2376,7 @@ object SwaggerDefinitionsJSON {
face_image = customerFaceImageJson,
date_of_birth = "19900101",
relationship_status = ExampleValue.relationshipStatusExample.value,
dependants = ExampleValue.dependentsExample.value.toInt,
dependants = ExampleValue.dependantsExample.value.toInt,
dob_of_dependants = List("19900101"),
credit_rating = Option(customerCreditRatingJSON),
credit_limit = Option(amountOfMoneyJsonV121),
@ -2221,7 +2405,7 @@ object SwaggerDefinitionsJSON {
face_image = customerFaceImageJson,
date_of_birth = DateWithDayExampleObject,
relationship_status = ExampleValue.relationshipStatusExample.value,
dependants = ExampleValue.dependentsExample.value.toInt,
dependants = ExampleValue.dependantsExample.value.toInt,
dob_of_dependants = List(DateWithDayExampleObject),
credit_rating = customerCreditRatingJSON,
credit_limit = amountOfMoneyJsonV121,
@ -2236,12 +2420,13 @@ object SwaggerDefinitionsJSON {
val postCustomerJsonV500 =
PostCustomerJsonV500(
legal_name = ExampleValue.legalNameExample.value,
mobile_phone_number = ExampleValue.mobileNumberExample.value,
customer_number = Some(ExampleValue.customerNumberExample.value),
mobile_phone_number = ExampleValue.mobilePhoneNumberExample.value,
email = Some(ExampleValue.emailExample.value),
face_image = Some(customerFaceImageJson),
date_of_birth = Some(DateWithDayExampleObject),
relationship_status = Some(ExampleValue.relationshipStatusExample.value),
dependants = Some(ExampleValue.dependentsExample.value.toInt),
dependants = Some(ExampleValue.dependantsExample.value.toInt),
dob_of_dependants = Some(List(DateWithDayExampleObject)),
credit_rating = Some(customerCreditRatingJSON),
credit_limit = Some(amountOfMoneyJsonV121),
@ -2264,7 +2449,7 @@ object SwaggerDefinitionsJSON {
face_image = customerFaceImageJson,
date_of_birth = DateWithDayExampleObject,
relationship_status = ExampleValue.relationshipStatusExample.value,
dependants = ExampleValue.dependentsExample.value.toInt,
dependants = ExampleValue.dependantsExample.value.toInt,
dob_of_dependants = List(DateWithDayExampleObject),
credit_rating = Option(customerCreditRatingJSON),
credit_limit = Option(amountOfMoneyJsonV121),
@ -2341,7 +2526,7 @@ object SwaggerDefinitionsJSON {
face_image = customerFaceImageJson,
date_of_birth = DateWithDayExampleObject,
relationship_status = ExampleValue.relationshipStatusExample.value,
dependants = ExampleValue.dependentsExample.value.toInt,
dependants = ExampleValue.dependantsExample.value.toInt,
dob_of_dependants = List(DateWithDayExampleObject),
credit_rating = Option(customerCreditRatingJSON),
credit_limit = Option(amountOfMoneyJsonV121),
@ -2366,7 +2551,7 @@ object SwaggerDefinitionsJSON {
face_image = customerFaceImageJson,
date_of_birth = DateWithDayExampleObject,
relationship_status = ExampleValue.relationshipStatusExample.value,
dependants = ExampleValue.dependentsExample.value.toInt,
dependants = ExampleValue.dependantsExample.value.toInt,
dob_of_dependants = List(DateWithDayExampleObject),
credit_rating = Option(customerCreditRatingJSON),
credit_limit = Option(amountOfMoneyJsonV121),
@ -2390,7 +2575,7 @@ object SwaggerDefinitionsJSON {
face_image = customerFaceImageJson,
date_of_birth = "19900101",
relationship_status = ExampleValue.relationshipStatusExample.value,
dependants = ExampleValue.dependentsExample.value.toInt,
dependants = ExampleValue.dependantsExample.value.toInt,
dob_of_dependants = List("19900101"),
credit_rating = Option(customerCreditRatingJSON),
credit_limit = Option(amountOfMoneyJsonV121),
@ -2409,7 +2594,7 @@ object SwaggerDefinitionsJSON {
val putUpdateCustomerDataJsonV310 = PutUpdateCustomerDataJsonV310(
face_image = customerFaceImageJson,
relationship_status = ExampleValue.relationshipStatusExample.value,
dependants = ExampleValue.dependentsExample.value.toInt,
dependants = ExampleValue.dependantsExample.value.toInt,
highest_education_attained = ExampleValue.highestEducationAttainedExample.value,
employment_status = ExampleValue.employmentStatusExample.value
)
@ -2735,6 +2920,104 @@ object SwaggerDefinitionsJSON {
views = List(viewJSONV220)
)
val viewJsonV500 = ViewJsonV500(
id = "1234",
short_name = "short_name",
description = "description",
metadata_view = SYSTEM_OWNER_VIEW_ID,
is_public = true,
is_system = true,
alias = "No",
hide_metadata_if_alias_used = true,
can_add_comment = true,
can_add_corporate_location = true,
can_add_image = true,
can_add_image_url = true,
can_add_more_info = true,
can_add_open_corporates_url = true,
can_add_physical_location = true,
can_add_private_alias = true,
can_add_public_alias = true,
can_add_tag = true,
can_add_url = true,
can_add_where_tag = true,
can_delete_comment = true,
can_add_counterparty = true,
can_delete_corporate_location = true,
can_delete_image = true,
can_delete_physical_location = true,
can_delete_tag = true,
can_delete_where_tag = true,
can_edit_owner_comment = true,
can_see_bank_account_balance = true,
can_query_available_funds = true,
can_see_bank_account_bank_name = true,
can_see_bank_account_currency = true,
can_see_bank_account_iban = true,
can_see_bank_account_label = true,
can_see_bank_account_national_identifier = true,
can_see_bank_account_number = true,
can_see_bank_account_owners = true,
can_see_bank_account_swift_bic = true,
can_see_bank_account_type = true,
can_see_comments = true,
can_see_corporate_location = true,
can_see_image_url = true,
can_see_images = true,
can_see_more_info = true,
can_see_open_corporates_url = true,
can_see_other_account_bank_name = true,
can_see_other_account_iban = true,
can_see_other_account_kind = true,
can_see_other_account_metadata = true,
can_see_other_account_national_identifier = true,
can_see_other_account_number = true,
can_see_other_account_swift_bic = true,
can_see_owner_comment = true,
can_see_physical_location = true,
can_see_private_alias = true,
can_see_public_alias = true,
can_see_tags = true,
can_see_transaction_amount = true,
can_see_transaction_balance = true,
can_see_transaction_currency = true,
can_see_transaction_description = true,
can_see_transaction_finish_date = true,
can_see_transaction_metadata = true,
can_see_transaction_other_bank_account = true,
can_see_transaction_start_date = true,
can_see_transaction_this_bank_account = true,
can_see_transaction_type = true,
can_see_url = true,
can_see_where_tag = true,
//V300 new
can_see_bank_routing_scheme = true,
can_see_bank_routing_address = true,
can_see_bank_account_routing_scheme = true,
can_see_bank_account_routing_address = true,
can_see_other_bank_routing_scheme = true,
can_see_other_bank_routing_address = true,
can_see_other_account_routing_scheme = true,
can_see_other_account_routing_address = true,
can_add_transaction_request_to_own_account = true, //added following two for payments
can_add_transaction_request_to_any_account = true,
can_see_bank_account_credit_limit = true,
can_create_direct_debit = true,
can_create_standing_order = true,
can_grant_access_to_views = List("Owner"),
can_revoke_access_to_views = List("Owner")
)
val viewsJsonV500 = ViewsJsonV500(
views = List(viewJsonV500)
)
val viewIdJsonV500 = ViewIdJsonV500(id = "owner")
val viewIdsJsonV500 = ViewsIdsJsonV500(
views = List(viewIdJsonV500)
)
val fXRateJSON = FXRateJsonV220(
bank_id = bankIdExample.value,
from_currency_code = "EUR",
@ -3334,12 +3617,12 @@ object SwaggerDefinitionsJSON {
bank_id = bankIdExample.value,
label = labelExample.value,
number = numberExample.value,
owners = "user_id:b27327a2-a822-41e5-a909-0150da688939,provider:https://finx22openplatform.fintech-galaxy.com,user_name:synth_user_1_54891",
owners = List(FastFirehoseOwners(user_id="b27327a2-a822-41e5-a909-0150da688939",provider="https://finx22openplatform.fintech-galaxy.com,user_name:synth_user_1_54891", user_name="")),
product_code = productCodeExample.value,
balance = amountOfMoneyJsonV121,
account_routings = "bank_id:bisb.com,account_id:c590e38e-847c-466f-9a62-f2ad67daf106",
account_attributes= "type:INTEGER,code:Loan1,value:0," +
"type:STRING,code:Loan1,value:4421.783"
account_routings = List(FastFirehoseRoutings(bank_id="bisb.com",account_id="c590e38e-847c-466f-9a62-f2ad67daf106")),
account_attributes= List(FastFirehoseAttributes(`type`="INTEGER",code="Loan1",value="0"),
FastFirehoseAttributes(`type`="STRING",code="Loan1",value="4421.783"))
)

View File

@ -806,6 +806,12 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{
null
else
text
def nullToString(text : String) =
if(text == null)
null
else
text
def stringOptionOrNull(text : Option[String]) =
text match {

View File

@ -351,6 +351,9 @@ object ApiRole {
case class CanReadMetrics (requiresBankId: Boolean = false) extends ApiRole
lazy val canReadMetrics = CanReadMetrics()
case class CanGetMetricsAtOneBank(requiresBankId: Boolean = true) extends ApiRole
lazy val canGetMetricsAtOneBank = CanGetMetricsAtOneBank()
case class CanGetConfig(requiresBankId: Boolean = false) extends ApiRole
lazy val canGetConfig = CanGetConfig()

View File

@ -499,7 +499,7 @@ object ErrorMessages {
val ConsentUserCannotBeAdded = "OBP-35026: The Consent's User cannot be added."
val ConsentUserAuthContextCannotBeAdded = "OBP-35027: The Consent's User Auth Context cannot be added."
val ConsentRequestNotFound = "OBP-35028: Consent Request not found by CONSENT_REQUEST_ID. "
val ConsentRequestAlreadyUsed = "OBP-35029: The CONSENT_REQUEST_ID is used to create Consent. "
val ConsentRequestIsInvalid = "OBP-35029: The CONSENT_REQUEST_ID is invalid. "
//Authorisations
val AuthorisationNotFound = "OBP-36001: Authorisation not found. Please specify valid values for PAYMENT_ID and AUTHORISATION_ID. "

View File

@ -1,7 +1,7 @@
package code.api.util
import code.api.util.APIUtil.{DateWithMs, DateWithMsExampleString, parseDate}
import code.api.util.APIUtil.{DateWithMs, DateWithMsExampleString, oneYearAgoDate, formatDate, oneYearAgo, parseDate}
import code.api.util.ErrorMessages.{InvalidJsonFormat, UnknownError, UserHasMissingRoles, UserNotLoggedIn}
import net.liftweb.json.JsonDSL._
import code.api.util.Glossary.{glossaryItems, makeGlossaryItem}
@ -23,13 +23,14 @@ case class ConnectorField(value: String, description: String) {
object ExampleValue {
val NoDescriptionProvided = "no-description-provided"
val NoExampleProvided = "no-example-provided"
val NoExampleProvided = ""
val booleanTrue = "true"
lazy val bankIdGlossary = glossaryItems.find(_.title == "Bank.bank_id").map(_.textDescription)
lazy val bankIdExample = ConnectorField("gh.29.uk", s"A string that MUST uniquely identify the bank on this OBP instance. It COULD be a UUID but is generally a short string that easily identifies the bank / brand it represents.")
lazy val bank_idExample = bankIdExample
glossaryItems += makeGlossaryItem("Bank.bank_id", bankIdExample)
lazy val accountIdExample = ConnectorField("8ca8a7e4-6d02-40e3-a129-0b2bf89de9f0", s"A string that, in combination with the bankId MUST uniquely identify the account on this OBP instance. SHOULD be a UUID. MUST NOT be able to guess accountNumber from accountId. OBP-API or Adapter keeps a mapping between accountId and accountNumber. AccountId is a non reversible hash of the human readable account number.")
lazy val account_idExample = accountIdExample
@ -96,7 +97,10 @@ object ExampleValue {
lazy val relationshipStatusExample = ConnectorField("single", s"relationship status")
glossaryItems += makeGlossaryItem("Customer.relationshipStatus", relationshipStatusExample)
lazy val dependentsExample = ConnectorField("1", s"the number of dependents")
lazy val dependantsExample = ConnectorField("1", s"the number of dependants")
glossaryItems += makeGlossaryItem("Customer.dependants", dependantsExample)
lazy val dependentsExample = ConnectorField("2", s"the number of dependents") // Dominant form in American English
glossaryItems += makeGlossaryItem("Customer.dependents", dependentsExample)
lazy val kycStatusExample = ConnectorField(booleanTrue, s"This is boolean to indicate if the cusomter's KYC has been checked.")
@ -785,7 +789,7 @@ object ExampleValue {
lazy val customerUserIdExample = ConnectorField(NoExampleProvided,NoDescriptionProvided)
glossaryItems += makeGlossaryItem("customer_user_id", customerUserIdExample)
lazy val bankCodeExample = ConnectorField(NoExampleProvided,NoDescriptionProvided)
lazy val bankCodeExample = ConnectorField("CGHZ",NoDescriptionProvided)
glossaryItems += makeGlossaryItem("bank_code", bankCodeExample)
lazy val averageResponseTimeExample = ConnectorField(NoExampleProvided,NoDescriptionProvided)
@ -848,7 +852,7 @@ object ExampleValue {
lazy val canAddTransactionRequestToAnyAccountExample = ConnectorField(NoExampleProvided,NoDescriptionProvided)
glossaryItems += makeGlossaryItem("can_add_transaction_request_to_any_account", canAddTransactionRequestToAnyAccountExample)
lazy val websiteExample = ConnectorField(NoExampleProvided,NoDescriptionProvided)
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.")
@ -962,7 +966,7 @@ object ExampleValue {
lazy val accountExample = ConnectorField(NoExampleProvided,NoDescriptionProvided)
glossaryItems += makeGlossaryItem("account", accountExample)
lazy val idExample = ConnectorField(NoExampleProvided,NoDescriptionProvided)
lazy val idExample = ConnectorField("d8839721-ad8f-45dd-9f78-2080414b93f9",NoDescriptionProvided)
glossaryItems += makeGlossaryItem("id", idExample)
lazy val canAddCorporateLocationExample = ConnectorField(NoExampleProvided,NoDescriptionProvided)
@ -1031,7 +1035,7 @@ object ExampleValue {
lazy val toDateExample = ConnectorField(NoExampleProvided,NoDescriptionProvided)
glossaryItems += makeGlossaryItem("to_date", toDateExample)
lazy val bankRoutingsExample = ConnectorField(NoExampleProvided,NoDescriptionProvided)
lazy val bankRoutingsExample = ConnectorField("bank routing in form of (scheme, address)",NoDescriptionProvided)
glossaryItems += makeGlossaryItem("bank_routings", bankRoutingsExample)
lazy val canSeeOpenCorporatesUrlExample = ConnectorField(NoExampleProvided,NoDescriptionProvided)
@ -1085,9 +1089,6 @@ object ExampleValue {
lazy val temporaryCreditDocumentationExample = ConnectorField(NoExampleProvided,NoDescriptionProvided)
glossaryItems += makeGlossaryItem("temporary_credit_documentation", temporaryCreditDocumentationExample)
lazy val dependantsExample = ConnectorField(NoExampleProvided,NoDescriptionProvided)
glossaryItems += makeGlossaryItem("dependants", dependantsExample)
lazy val locationExample = ConnectorField(NoExampleProvided,NoDescriptionProvided)
glossaryItems += makeGlossaryItem("location", locationExample)
@ -1275,7 +1276,7 @@ object ExampleValue {
lazy val wednesdayExample = ConnectorField(NoExampleProvided,NoDescriptionProvided)
glossaryItems += makeGlossaryItem("wednesday", wednesdayExample)
lazy val lastOkDateExample = ConnectorField(NoExampleProvided,NoDescriptionProvided)
lazy val lastOkDateExample = ConnectorField(formatDate(oneYearAgoDate),NoDescriptionProvided)
glossaryItems += makeGlossaryItem("last_ok_date", lastOkDateExample)
lazy val transactionTypesExample = ConnectorField(NoExampleProvided,NoDescriptionProvided)
@ -1591,7 +1592,7 @@ object ExampleValue {
lazy val dateInsertedExample = ConnectorField(NoExampleProvided,NoDescriptionProvided)
glossaryItems += makeGlossaryItem("date_inserted", dateInsertedExample)
lazy val schemeExample = ConnectorField(NoExampleProvided,NoDescriptionProvided)
lazy val schemeExample = ConnectorField("scheme value",NoDescriptionProvided)
glossaryItems += makeGlossaryItem("scheme", schemeExample)
lazy val customerAddressIdExample = ConnectorField(NoExampleProvided,NoDescriptionProvided)
@ -1762,7 +1763,7 @@ object ExampleValue {
lazy val branchTypeExample = ConnectorField(NoExampleProvided,NoDescriptionProvided)
glossaryItems += makeGlossaryItem("branch_type", branchTypeExample)
lazy val fullNameExample = ConnectorField(NoExampleProvided,NoDescriptionProvided)
lazy val fullNameExample = ConnectorField("full name string",NoDescriptionProvided)
glossaryItems += makeGlossaryItem("full_name", fullNameExample)
lazy val canCreateDirectDebitExample = ConnectorField(booleanTrue,NoDescriptionProvided)
@ -1861,7 +1862,7 @@ object ExampleValue {
lazy val postedExample = ConnectorField("2020-01-27",NoDescriptionProvided)
glossaryItems += makeGlossaryItem("posted", postedExample)
lazy val logoExample = ConnectorField(NoExampleProvided,NoDescriptionProvided)
lazy val logoExample = ConnectorField("logo url",NoDescriptionProvided)
glossaryItems += makeGlossaryItem("logo", logoExample)
lazy val topApisExample = ConnectorField(NoExampleProvided,NoDescriptionProvided)
@ -1987,7 +1988,7 @@ object ExampleValue {
lazy val toCurrencyCodeExample = ConnectorField("EUR",NoDescriptionProvided)
glossaryItems += makeGlossaryItem("to_currency_code", toCurrencyCodeExample)
lazy val dobOfDependantsExample = ConnectorField(NoExampleProvided,NoDescriptionProvided)
lazy val dobOfDependantsExample = ConnectorField("[2019-09-08, 2017-07-12]",NoDescriptionProvided)
glossaryItems += makeGlossaryItem("dob_of_dependants", dobOfDependantsExample)
lazy val settlementAccountsExample = ConnectorField(NoExampleProvided,NoDescriptionProvided)
@ -2059,7 +2060,7 @@ object ExampleValue {
lazy val createdByUserIdExample = ConnectorField(NoExampleProvided,NoDescriptionProvided)
glossaryItems += makeGlossaryItem("created_by_user_id", createdByUserIdExample)
lazy val attributesExample = ConnectorField(NoExampleProvided,NoDescriptionProvided)
lazy val attributesExample = ConnectorField("attribute value in form of (name, value)",NoDescriptionProvided)
glossaryItems += makeGlossaryItem("attributes", attributesExample)
lazy val revokedExample = ConnectorField(NoExampleProvided,NoDescriptionProvided)
@ -2071,7 +2072,7 @@ object ExampleValue {
lazy val currentCreditDocumentationExample = ConnectorField(NoExampleProvided,NoDescriptionProvided)
glossaryItems += makeGlossaryItem("current_credit_documentation", currentCreditDocumentationExample)
lazy val mobilePhoneNumberExample = ConnectorField(NoExampleProvided,NoDescriptionProvided)
lazy val mobilePhoneNumberExample = ConnectorField("+49 30 901820",NoDescriptionProvided)
glossaryItems += makeGlossaryItem("mobile_phone_number", mobilePhoneNumberExample)
lazy val saturdayExample = ConnectorField(NoExampleProvided,NoDescriptionProvided)

View File

@ -654,6 +654,9 @@ object NewStyle extends MdcLoggable{
Views.views.vend.systemViewFuture(viewId) map {
unboxFullOrFail(_, callContext, s"$SystemViewNotFound. Current ViewId is $viewId")
}
}
def systemViews(): Future[List[View]] = {
Views.views.vend.getSystemViews()
}
def grantAccessToCustomView(view : View, user: User, callContext: Option[CallContext]) : Future[View] = {
view.isSystem match {
@ -2522,6 +2525,53 @@ object NewStyle extends MdcLoggable{
) map {
i => (unboxFullOrFail(i._1, callContext, CreateCustomerError), i._2)
}
def createCustomerC2(
bankId: BankId,
legalName: String,
customerNumber: String,
mobileNumber: String,
email: String,
faceImage:
CustomerFaceImageTrait,
dateOfBirth: Date,
relationshipStatus: String,
dependents: Int,
dobOfDependents: List[Date],
highestEducationAttained: String,
employmentStatus: String,
kycStatus: Boolean,
lastOkDate: Date,
creditRating: Option[CreditRatingTrait],
creditLimit: Option[AmountOfMoneyTrait],
title: String,
branchId: String,
nameSuffix: String,
callContext: Option[CallContext]): OBPReturnType[Customer] =
Connector.connector.vend.createCustomerC2(
bankId: BankId,
legalName: String,
customerNumber: String,
mobileNumber: String,
email: String,
faceImage:
CustomerFaceImageTrait,
dateOfBirth: Date,
relationshipStatus: String,
dependents: Int,
dobOfDependents: List[Date],
highestEducationAttained: String,
employmentStatus: String,
kycStatus: Boolean,
lastOkDate: Date,
creditRating: Option[CreditRatingTrait],
creditLimit: Option[AmountOfMoneyTrait],
title: String,
branchId: String,
nameSuffix: String,
callContext: Option[CallContext]
) map {
i => (unboxFullOrFail(i._1, callContext, CreateCustomerError), i._2)
}
def updateCustomerScaData(customerId: String,
mobileNumber: Option[String],

View File

@ -366,7 +366,31 @@ object JSONFactory1_4_0 extends MdcLoggable{
* @return Bank.bank_id
*/
def getGlossaryItemTitle(parameter: String): String = {
glossaryItems.find(_.title.toLowerCase.contains(s"${parameter.toLowerCase}")).map(_.title).getOrElse("").replaceAll(" ","-")
def isUrlParameter(): Boolean = {
List(
"BANK_ID",
"ACCOUNT_ID",
"CUSTOMER_ID",
"TRANSACTION_ID",
"ATTRIBUTE_ID",
"VIEW_ID",
"USER_ID",
"PRODUCT_CODE",
"PRODUCT_ID",
"OPERATION_ID",
"ENDPOINT_TAG_ID",
).exists(_ == parameter)
}
parameter match {
case _ if isUrlParameter() =>
glossaryItems
.find(_.title.toLowerCase.contains(s"${parameter.toLowerCase}"))
.map(_.title).getOrElse("").replaceAll(" ","-")
case _ =>
glossaryItems
.find(_.title.toLowerCase.equals(s"${parameter.toLowerCase}"))
.map(_.title).getOrElse("").replaceAll(" ","-")
}
}
/**
@ -420,31 +444,31 @@ object JSONFactory1_4_0 extends MdcLoggable{
* @param parameter BANK_ID
* @return [BANK_ID](/glossary#Bank.bank_id):gh.29.uk
*/
def prepareDescription(parameter: String, types: List[(String, Boolean)]): String = {
def prepareDescription(parameter: String, optionalTypeFields: List[(String, Boolean)]): String = {
val glossaryItemTitle = getGlossaryItemTitle(parameter)
val exampleFieldValue = getExampleFieldValue(parameter)
def boldIfMandatory() = {
types.exists(i => i._1 == parameter && i._2 == false) match {
optionalTypeFields.exists(i => i._1 == parameter && i._2 == false) match {
case true =>
s"**$parameter**"
s"***$parameter**"
case false =>
s"$parameter"
}
}
if(exampleFieldValue.contains(ExampleValue.NoExampleProvided)){
if(glossaryItemTitle.contains("jsonstring")){
""
} else {
s"""
|
|* [${boldIfMandatory()}](/glossary#$glossaryItemTitle): $exampleFieldValue
|
|""".stripMargin
}
s"""
|
|* [${boldIfMandatory()}](/glossary#$glossaryItemTitle): $exampleFieldValue
|
|""".stripMargin
}
}
def prepareJsonFieldDescription(jsonBody: scala.Product, jsonType: String): String = {
jsonBody.productIterator
val (jsonBodyJValue: json.JValue, types) = jsonBody match {
val (jsonBodyJValue: json.JValue, optionalTypeFields) = jsonBody match {
case JvalueCaseClass(jValue) =>
val types = Nil
(jValue, types)
@ -455,9 +479,14 @@ object JSONFactory1_4_0 extends MdcLoggable{
(decompose(jsonBody), types)
}
val jsonBodyFields =JsonUtils.collectFieldNames(jsonBodyJValue).keySet.toList.sorted
// Group by is mandatory criteria and sort those 2 groups by name of the field
val jsonBodyFieldsOptional = JsonUtils.collectFieldNames(jsonBodyJValue).keySet.toList
.filter(x => optionalTypeFields.exists(i => i._1 == x && i._2 == true)).sorted
val jsonBodyFieldsMandatory = JsonUtils.collectFieldNames(jsonBodyJValue).keySet.toList
.filter(x => optionalTypeFields.exists(i => i._1 == x && i._2 == false)).sorted
val jsonBodyFields = jsonBodyFieldsMandatory ::: jsonBodyFieldsOptional
val jsonFieldsDescription = jsonBodyFields.map(i => prepareDescription(i, types))
val jsonFieldsDescription = jsonBodyFields.map(i => prepareDescription(i, optionalTypeFields))
val jsonTitleType = if (jsonType.contains("request")) "\n\n\n**JSON request body fields:**\n\n" else "\n\n\n**JSON response body fields:**\n\n"

View File

@ -148,7 +148,7 @@ trait APIMethods300 {
|
| You MUST use a leading _ (underscore) in the view name because other view names are reserved for OBP [system views](/index#group-View-System).
| """,
SwaggerDefinitionsJSON.createViewJson,
SwaggerDefinitionsJSON.createViewJsonV300,
viewJsonV300,
List(
UserNotLoggedIn,
@ -233,7 +233,7 @@ trait APIMethods300 {
|
|The json sent is the same as during view creation (above), with one difference: the 'name' field
|of a view is not editable (it is only set when a view is created)""",
updateViewJSON,
updateViewJsonV300,
viewJsonV300,
List(
InvalidJsonFormat,
@ -251,7 +251,7 @@ trait APIMethods300 {
val res =
for {
(Full(u), callContext) <- authenticatedAccess(cc)
updateJson <- Future { tryo{json.extract[UpdateViewJSON]} } map {
updateJson <- Future { tryo{json.extract[UpdateViewJsonV300]} } map {
val msg = s"$InvalidJsonFormat The Json body should be the $UpdateViewJSON "
x => unboxFullOrFail(x, callContext, msg)
}
@ -270,7 +270,7 @@ trait APIMethods300 {
(account, callContext) <- NewStyle.function.getBankAccount(bankId, accountId, callContext)
} yield {
for {
updatedView <- account.updateView(u, viewId, updateJson)
updatedView <- account.updateView(u, viewId, updateJson.toUpdateViewJson)
} yield {
(JSONFactory300.createViewJSON(updatedView), HttpCode.`200`(callContext))
}

View File

@ -71,7 +71,44 @@ import scala.util.Try
//started - view relevant case classes
case class CreateViewJsonV300(
name: String,
description: String,
metadata_view: String,
is_public: Boolean,
which_alias_to_use: String,
hide_metadata_if_alias_used: Boolean,
allowed_actions : List[String]
) {
def toCreateViewJson = CreateViewJson(
name = this.name,
description = this.description,
metadata_view = this.metadata_view,
is_public = this.is_public,
which_alias_to_use = this.which_alias_to_use,
hide_metadata_if_alias_used = this.hide_metadata_if_alias_used,
allowed_actions = this.allowed_actions
)
}
case class UpdateViewJsonV300(
description: String,
metadata_view: String,
is_public: Boolean,
is_firehose: Option[Boolean] = None,
which_alias_to_use: String,
hide_metadata_if_alias_used: Boolean,
allowed_actions: List[String]
) {
def toUpdateViewJson = UpdateViewJSON(
description = this.description,
metadata_view = this.metadata_view,
is_public = this.is_public,
is_firehose = this.is_firehose,
which_alias_to_use = this.which_alias_to_use,
hide_metadata_if_alias_used = this.hide_metadata_if_alias_used,
allowed_actions = this.allowed_actions
)
}
case class ViewsJsonV300(
views : List[ViewJsonV300]
)

View File

@ -3,6 +3,7 @@ package code.api.v3_1_0
import java.text.SimpleDateFormat
import java.util.UUID
import java.util.regex.Pattern
import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON._
import code.api.ResourceDocs1_4_0.{MessageDocsSwaggerDefinitions, ResourceDocsAPIMethodsUtil, SwaggerDefinitionsJSON, SwaggerJSONFactory}
import code.api.util.APIUtil.{getWebUIPropsPairs, _}
@ -16,7 +17,7 @@ import code.api.v1_2_1.{JSONFactory, RateLimiting}
import code.api.v2_0_0.CreateMeetingJson
import code.api.v2_1_0._
import code.api.v2_2_0.{CreateAccountJSONV220, JSONFactory220}
import code.api.v3_0_0.JSONFactory300
import code.api.v3_0_0.{CreateViewJsonV300, JSONFactory300}
import code.api.v3_0_0.JSONFactory300.createAdapterInfoJson
import code.api.v3_1_0.JSONFactory310._
import code.bankconnectors.rest.RestConnector_vMar2019
@ -3880,7 +3881,7 @@ trait APIMethods310 {
|
| Please note that system views cannot be public. In case you try to set it you will get the error $SystemViewCannotBePublicError
| """,
SwaggerDefinitionsJSON.createSystemViewJson,
SwaggerDefinitionsJSON.createSystemViewJsonV300,
viewJsonV300,
List(
UserNotLoggedIn,
@ -3900,12 +3901,12 @@ trait APIMethods310 {
_ <- NewStyle.function.hasEntitlement("", user.userId, canCreateSystemView, callContext)
failMsg = s"$InvalidJsonFormat The Json body should be the $CreateViewJson "
createViewJson <- NewStyle.function.tryons(failMsg, 400, callContext) {
json.extract[CreateViewJson]
json.extract[CreateViewJsonV300]
}
_ <- Helper.booleanToFuture(SystemViewCannotBePublicError, failCode=400, cc=callContext) {
createViewJson.is_public == false
}
view <- NewStyle.function.createSystemView(createViewJson, callContext)
view <- NewStyle.function.createSystemView(createViewJson.toCreateViewJson, callContext)
} yield {
(JSONFactory310.createViewJSON(view), HttpCode.`201`(callContext))
}
@ -3929,7 +3930,7 @@ trait APIMethods310 {
"user does not have owner access"
),
List(apiTagSystemView, apiTagNewStyle),
Some(List(canCreateSystemView))
Some(List(canDeleteSystemView))
)
lazy val deleteSystemView: OBPEndpoint = {

View File

@ -3969,7 +3969,7 @@ trait APIMethods400 {
| - Outgoing account (name: Default outgoing settlement account, Account ID: OBP_DEFAULT_OUTGOING_ACCOUNT_ID, currency: EUR)
|
|""",
bankJson400,
postBankJson400,
bankJson400,
List(
InvalidJsonFormat,

View File

@ -106,6 +106,14 @@ case class BankJson400(
bank_routings: List[BankRoutingJsonV121],
attributes: Option[List[BankAttributeBankResponseJsonV400]]
)
case class PostBankJson400(
id: String,
short_name: String,
full_name: String,
logo: String,
website: String,
bank_routings: List[BankRoutingJsonV121]
)
case class BanksJson400(banks: List[BankJson400])
@ -236,11 +244,11 @@ case class FastFirehoseAccountJsonV400(
bank_id: String,
label: String,
number: String,
owners: String,
owners: List[FastFirehoseOwners],
product_code: String,
balance: AmountOfMoneyJsonV121,
account_routings: String ,
account_attributes: String
account_routings: List[FastFirehoseRoutings] ,
account_attributes: List[FastFirehoseAttributes]
)
case class FastFirehoseAccountsJsonV400(

View File

@ -1,6 +1,9 @@
package code.api.v5_0_0
import java.util.Date
import java.util.concurrent.ThreadLocalRandom
import code.accountattribute.AccountAttributeX
import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON
import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON._
import code.api.util.APIUtil._
import code.api.util.ApiRole._
@ -14,20 +17,23 @@ import code.api.v3_0_0.JSONFactory300
import code.api.v3_1_0._
import code.api.v4_0_0.JSONFactory400.createCustomersMinimalJson
import code.api.v4_0_0.{JSONFactory400, PutProductJsonV400}
import code.api.v5_0_0.JSONFactory500.createPhysicalCardJson
import code.api.v5_0_0.JSONFactory500.{createPhysicalCardJson, createViewJsonV500, createViewsJsonV500, createViewsIdsJsonV500}
import code.bankconnectors.Connector
import code.consent.{ConsentRequests, Consents}
import code.entitlement.Entitlement
import code.metrics.APIMetrics
import code.model._
import code.model.dataAccess.BankAccountCreation
import code.transactionrequests.TransactionRequests.TransactionRequestTypes.{apply => _}
import code.util.Helper
import code.util.Helper.booleanToFuture
import code.views.Views
import com.github.dwickern.macros.NameOf.nameOf
import com.openbankproject.commons.ExecutionContext.Implicits.global
import com.openbankproject.commons.model.enums.StrongCustomerAuthentication
import com.openbankproject.commons.model.{AccountAttribute, AccountId, AccountRouting, BankAccount, BankId, BankIdAccountId, CardAction, CardAttributeCommons, CardCollectionInfo, CardPostedInfo, CardReplacementInfo, CardReplacementReason, CreditLimit, CreditRating, CustomerFaceImage, CustomerId, PinResetInfo, PinResetReason, ProductCode, TransactionRequestType, UserAuthContextUpdateStatus, View, ViewId}
import com.openbankproject.commons.model._
import com.openbankproject.commons.util.ApiVersion
import net.liftweb.common.{Box, Empty, Full}
import net.liftweb.common.{Empty, Full}
import net.liftweb.http.Req
import net.liftweb.http.rest.RestHelper
import net.liftweb.json
@ -41,7 +47,6 @@ import code.util.Helper.booleanToFuture
import scala.collection.immutable.{List, Nil}
import scala.collection.mutable.ArrayBuffer
import scala.concurrent
import scala.concurrent.Future
import scala.util.Random
@ -763,6 +768,7 @@ trait APIMethods500 {
UserNotLoggedIn,
$BankNotFound,
InvalidJsonFormat,
ConsentRequestIsInvalid,
ConsentAllowedScaMethods,
RolesAllowedInConsent,
ViewsAllowedInConsent,
@ -788,7 +794,7 @@ trait APIMethods500 {
)) map {
i => unboxFullOrFail(i,callContext, ConsentRequestNotFound)
}
_ <- Helper.booleanToFuture(ConsentRequestAlreadyUsed, cc=callContext){
_ <- Helper.booleanToFuture(ConsentRequestIsInvalid, cc=callContext){
Consents.consentProvider.vend.getConsentByConsentRequestId(consentRequestId).isEmpty
}
_ <- Helper.booleanToFuture(ConsentAllowedScaMethods, cc=callContext){
@ -988,9 +994,12 @@ trait APIMethods500 {
_ <- Helper.booleanToFuture(failMsg = InvalidJsonContent + s" The field dependants(${postedData.dependants.getOrElse(0)}) not equal the length(${postedData.dob_of_dependants.getOrElse(Nil).length }) of dob_of_dependants array", 400, cc.callContext) {
postedData.dependants.getOrElse(0) == postedData.dob_of_dependants.getOrElse(Nil).length
}
(customer, callContext) <- NewStyle.function.createCustomer(
customerNumber = postedData.customer_number.getOrElse(Random.nextInt(Integer.MAX_VALUE).toString)
(_, callContext) <- NewStyle.function.checkCustomerNumberAvailable(bankId, customerNumber, cc.callContext)
(customer, callContext) <- NewStyle.function.createCustomerC2(
bankId,
postedData.legal_name,
customerNumber,
postedData.mobile_phone_number,
postedData.email.getOrElse(""),
CustomerFaceImage(
@ -1010,7 +1019,7 @@ trait APIMethods500 {
postedData.title.getOrElse(""),
postedData.branch_id.getOrElse(""),
postedData.name_suffix.getOrElse(""),
cc.callContext,
callContext,
)
} yield {
(JSONFactory310.createCustomerJson(customer), HttpCode.`201`(callContext))
@ -1443,6 +1452,354 @@ trait APIMethods500 {
}
}
staticResourceDocs += ResourceDoc(
getViewsForBankAccount,
implementedInApiVersion,
nameOf(getViewsForBankAccount),
"GET",
"/banks/BANK_ID/accounts/ACCOUNT_ID/views",
"Get Views for Account",
s"""#Views
|
|
|Views in Open Bank Project provide a mechanism for fine grained access control and delegation to Accounts and Transactions. Account holders use the 'owner' view by default. Delegated access is made through other views for example 'accountants', 'share-holders' or 'tagging-application'. Views can be created via the API and each view has a list of entitlements.
|
|Views on accounts and transactions filter the underlying data to redact certain fields for certain users. For instance the balance on an account may be hidden from the public. The way to know what is possible on a view is determined in the following JSON.
|
|**Data:** When a view moderates a set of data, some fields my contain the value `null` rather than the original value. This indicates either that the user is not allowed to see the original data or the field is empty.
|
|There is currently one exception to this rule; the 'holder' field in the JSON contains always a value which is either an alias or the real name - indicated by the 'is_alias' field.
|
|**Action:** When a user performs an action like trying to post a comment (with POST API call), if he is not allowed, the body response will contain an error message.
|
|**Metadata:**
|Transaction metadata (like images, tags, comments, etc.) will appears *ONLY* on the view where they have been created e.g. comments posted to the public view only appear on the public view.
|
|The other account metadata fields (like image_URL, more_info, etc.) are unique through all the views. Example, if a user edits the 'more_info' field in the 'team' view, then the view 'authorities' will show the new value (if it is allowed to do it).
|
|# All
|*Optional*
|
|Returns the list of the views created for account ACCOUNT_ID at BANK_ID.
|
|${authenticationRequiredMessage(true)} and the user needs to have access to the owner view.""",
emptyObjectJson,
viewsJsonV500,
List(
$UserNotLoggedIn,
$BankAccountNotFound,
UnknownError
),
List(apiTagView, apiTagAccount, apiTagNewStyle))
lazy val getViewsForBankAccount : OBPEndpoint = {
//get the available views on an bank account
case "banks" :: BankId(bankId) :: "accounts" :: AccountId(accountId) :: "views" :: Nil JsonGet req => {
cc =>
val res =
for {
_ <- Helper.booleanToFuture(failMsg = UserNoOwnerView +"userId : " + cc.userId + ". account : " + accountId, cc=cc.callContext){
cc.loggedInUser.hasOwnerViewAccess(BankIdAccountId(bankId, accountId))
}
} yield {
for {
views <- Full(Views.views.vend.availableViewsForAccount(BankIdAccountId(bankId, accountId)))
} yield {
(createViewsJsonV500(views), HttpCode.`200`(cc.callContext))
}
}
res map { fullBoxOrException(_) } map { unboxFull(_) }
}
}
staticResourceDocs += ResourceDoc(
deleteSystemView,
implementedInApiVersion,
"deleteSystemView",
"DELETE",
"/system-views/VIEW_ID",
"Delete System View",
"Deletes the system view specified by VIEW_ID",
emptyObjectJson,
emptyObjectJson,
List(
UserNotLoggedIn,
BankAccountNotFound,
UnknownError,
"user does not have owner access"
),
List(apiTagSystemView, apiTagNewStyle),
Some(List(canDeleteSystemView))
)
lazy val deleteSystemView: OBPEndpoint = {
case "system-views" :: viewId :: Nil JsonDelete req => {
cc =>
for {
_ <- NewStyle.function.systemView(ViewId(viewId), cc.callContext)
view <- NewStyle.function.deleteSystemView(ViewId(viewId), cc.callContext)
} yield {
(Full(view), HttpCode.`200`(cc.callContext))
}
}
}
staticResourceDocs += ResourceDoc(
getMetricsAtBank,
implementedInApiVersion,
nameOf(getMetricsAtBank),
"GET",
"/management/metrics/banks/BANK_ID",
"Get Metrics at Bank",
s"""Get the all metrics at the Bank specified by BANK_ID
|
|require CanReadMetrics role
|
|Filters Part 1.*filtering* (no wilde cards etc.) parameters to GET /management/metrics
|
|Should be able to filter on the following metrics fields
|
|eg: /management/metrics?from_date=$DateWithMsExampleString&to_date=$DateWithMsExampleString&limit=50&offset=2
|
|1 from_date (defaults to one week before current date): eg:from_date=$DateWithMsExampleString
|
|2 to_date (defaults to current date) eg:to_date=$DateWithMsExampleString
|
|3 limit (for pagination: defaults to 50) eg:limit=200
|
|4 offset (for pagination: zero index, defaults to 0) eg: offset=10
|
|5 sort_by (defaults to date field) eg: sort_by=date
| possible values:
| "url",
| "date",
| "user_name",
| "app_name",
| "developer_email",
| "implemented_by_partial_function",
| "implemented_in_version",
| "consumer_id",
| "verb"
|
|6 direction (defaults to date desc) eg: direction=desc
|
|eg: /management/metrics?from_date=$DateWithMsExampleString&to_date=$DateWithMsExampleString&limit=10000&offset=0&anon=false&app_name=TeatApp&implemented_in_version=v2.1.0&verb=POST&user_id=c7b6cb47-cb96-4441-8801-35b57456753a&user_name=susan.uk.29@example.com&consumer_id=78
|
|Other filters:
|
|7 consumer_id (if null ignore)
|
|8 user_id (if null ignore)
|
|9 anon (if null ignore) only support two value : true (return where user_id is null.) or false (return where user_id is not null.)
|
|10 url (if null ignore), note: can not contain '&'.
|
|11 app_name (if null ignore)
|
|12 implemented_by_partial_function (if null ignore),
|
|13 implemented_in_version (if null ignore)
|
|14 verb (if null ignore)
|
|15 correlation_id (if null ignore)
|
|16 duration (if null ignore) non digit chars will be silently omitted
|
""".stripMargin,
emptyObjectJson,
metricsJson,
List(
$UserNotLoggedIn,
UserHasMissingRoles,
UnknownError
),
List(apiTagMetric, apiTagApi, apiTagNewStyle),
Some(List(canGetMetricsAtOneBank)))
lazy val getMetricsAtBank : OBPEndpoint = {
case "management" :: "metrics" :: "banks" :: bankId :: Nil JsonGet _ => {
cc => {
for {
httpParams <- NewStyle.function.extractHttpParamsFromUrl(cc.url)
(obpQueryParams, callContext) <- createQueriesByHttpParamsFuture(httpParams, cc.callContext)
metrics <- Future(APIMetrics.apiMetrics.vend.getAllMetrics(obpQueryParams ::: List(OBPBankId(bankId))))
} yield {
(JSONFactory210.createMetricsJson(metrics), HttpCode.`200`(callContext))
}
}
}
}
staticResourceDocs += ResourceDoc(
getSystemView,
implementedInApiVersion,
"getSystemView",
"GET",
"/system-views/VIEW_ID",
"Get System View",
s"""Get System View
|
|${authenticationRequiredMessage(true)}
|
""".stripMargin,
emptyObjectJson,
viewJsonV500,
List(
$UserNotLoggedIn,
$BankNotFound,
UnknownError
),
List(apiTagSystemView, apiTagNewStyle),
Some(List(canGetSystemView))
)
lazy val getSystemView: OBPEndpoint = {
case "system-views" :: viewId :: Nil JsonGet _ => {
cc =>
for {
view <- NewStyle.function.systemView(ViewId(viewId), cc.callContext)
} yield {
(createViewJsonV500(view), HttpCode.`200`(cc.callContext))
}
}
}
staticResourceDocs += ResourceDoc(
getSystemViewsIds,
implementedInApiVersion,
nameOf(getSystemViewsIds),
"GET",
"/system-views-ids",
"Get Ids of System Views",
s"""Get Ids of System Views
|
|${authenticationRequiredMessage(true)}
|
""".stripMargin,
emptyObjectJson,
viewIdsJsonV500,
List(
$UserNotLoggedIn,
$BankNotFound,
UnknownError
),
List(apiTagSystemView, apiTagNewStyle),
Some(List(canGetSystemView))
)
lazy val getSystemViewsIds: OBPEndpoint = {
case "system-views-ids" :: Nil JsonGet _ => {
cc =>
for {
views <- NewStyle.function.systemViews()
} yield {
(createViewsIdsJsonV500(views), HttpCode.`200`(cc.callContext))
}
}
}
staticResourceDocs += ResourceDoc(
createSystemView,
implementedInApiVersion,
nameOf(createSystemView),
"POST",
"/system-views",
"Create System View",
s"""Create a system view
|
| ${authenticationRequiredMessage(true)} and the user needs to have access to the $canCreateSystemView entitlement.
| The 'alias' field in the JSON can take one of two values:
|
| * _public_: to use the public alias if there is one specified for the other account.
| * _private_: to use the public alias if there is one specified for the other account.
|
| * _''(empty string)_: to use no alias; the view shows the real name of the other account.
|
| The 'hide_metadata_if_alias_used' field in the JSON can take boolean values. If it is set to `true` and there is an alias on the other account then the other accounts' metadata (like more_info, url, image_url, open_corporates_url, etc.) will be hidden. Otherwise the metadata will be shown.
|
| The 'allowed_actions' field is a list containing the name of the actions allowed on this view, all the actions contained will be set to `true` on the view creation, the rest will be set to `false`.
|
| Please note that system views cannot be public. In case you try to set it you will get the error $SystemViewCannotBePublicError
| """,
createSystemViewJsonV500,
viewJsonV500,
List(
$UserNotLoggedIn,
InvalidJsonFormat,
UnknownError
),
List(apiTagSystemView, apiTagNewStyle),
Some(List(canCreateSystemView))
)
lazy val createSystemView : OBPEndpoint = {
//creates a system view
case "system-views" :: Nil JsonPost json -> _ => {
cc =>
for {
createViewJson <- NewStyle.function.tryons(failMsg = s"$InvalidJsonFormat The Json body should be the $CreateViewJson ", 400, cc.callContext) {
json.extract[CreateViewJsonV500]
}
_ <- Helper.booleanToFuture(SystemViewCannotBePublicError, failCode=400, cc=cc.callContext) {
createViewJson.is_public == false
}
view <- NewStyle.function.createSystemView(createViewJson.toCreateViewJson, cc.callContext)
} yield {
(createViewJsonV500(view), HttpCode.`201`(cc.callContext))
}
}
}
staticResourceDocs += ResourceDoc(
updateSystemView,
implementedInApiVersion,
nameOf(updateSystemView),
"PUT",
"/system-views/VIEW_ID",
"Update System View",
s"""Update an existing view on a bank account
|
|${authenticationRequiredMessage(true)} and the user needs to have access to the owner view.
|
|The json sent is the same as during view creation (above), with one difference: the 'name' field
|of a view is not editable (it is only set when a view is created)""",
updateSystemViewJson500,
viewJsonV500,
List(
InvalidJsonFormat,
$UserNotLoggedIn,
BankAccountNotFound,
UnknownError
),
List(apiTagSystemView, apiTagNewStyle),
Some(List(canUpdateSystemView))
)
lazy val updateSystemView : OBPEndpoint = {
//updates a view on a bank account
case "system-views" :: viewId :: Nil JsonPut json -> _ => {
cc =>
for {
updateJson <- Future { tryo{json.extract[UpdateViewJsonV500]} } map {
val msg = s"$InvalidJsonFormat The Json body should be the $UpdateViewJSON "
x => unboxFullOrFail(x, cc.callContext, msg)
}
_ <- Helper.booleanToFuture(SystemViewCannotBePublicError, failCode=400, cc=cc.callContext) {
updateJson.is_public == false
}
_ <- NewStyle.function.systemView(ViewId(viewId), cc.callContext)
updatedView <- NewStyle.function.updateSystemView(ViewId(viewId), updateJson.toUpdateViewJson, cc.callContext)
} yield {
(JSONFactory310.createViewJSON(updatedView), HttpCode.`200`(cc.callContext))
}
}
}
staticResourceDocs += ResourceDoc(
createCustomerAccountLink,
implementedInApiVersion,

View File

@ -28,23 +28,22 @@ package code.api.v5_0_0
import java.lang
import java.util.Date
import code.api.util.APIUtil.{stringOptionOrNull, stringOrNull}
import code.api.util.APIUtil.{nullToString, stringOptionOrNull, stringOrNull}
import code.api.v1_2_1.BankRoutingJsonV121
import code.api.v1_4_0.JSONFactory1_4_0.{CustomerFaceImageJson, MetaJsonV140}
import code.api.v1_3_0.JSONFactory1_3_0.{cardActionsToString, createAccountJson, createPinResetJson, createReplacementJson}
import code.api.v1_3_0.{PinResetJSON, ReplacementJSON}
import code.api.v1_4_0.JSONFactory1_4_0.CustomerFaceImageJson
import code.api.v1_4_0.JSONFactory1_4_0.{CustomerFaceImageJson, MetaJsonV140}
import code.api.v2_1_0.CustomerCreditRatingJSON
import code.api.v3_0_0.{AdapterInfoJsonV300, CustomerAttributeResponseJsonV300, JSONFactory300}
import code.api.v3_1_0.{AccountAttributeResponseJson, AccountBasicV310, CustomerWithAttributesJsonV310, PhysicalCardWithAttributesJsonV310, PostConsentEntitlementJsonV310}
import code.api.v4_0_0.BankAttributeBankResponseJsonV400
import code.bankattribute.BankAttribute
import code.customeraccountlinks.CustomerAccountLinkTrait
import com.openbankproject.commons.model.{AccountAttribute, AccountRouting, AccountRoutingJsonV121, AmountOfMoneyJsonV121, Bank, BankAccount, CardAttribute, Customer, CustomerAttribute, InboundAdapterInfoInternal, InboundStatusMessage, PhysicalCardTrait, User, UserAuthContext, UserAuthContextUpdate, View, ViewBasic}
import com.openbankproject.commons.model.{AccountAttribute, AccountRouting, AccountRoutingJsonV121, AmountOfMoneyJsonV121, Bank, BankAccount, CardAttribute, CreateViewJson, Customer, CustomerAttribute, InboundAdapterInfoInternal, InboundStatusMessage, PhysicalCardTrait, UpdateViewJSON, User, UserAuthContext, UserAuthContextUpdate, View, ViewBasic}
import net.liftweb.json.JsonAST.JValue
import net.liftweb.util.Helpers
import scala.collection.immutable
import scala.collection.immutable.List
case class PostBankJson500(
@ -53,8 +52,7 @@ case class PostBankJson500(
full_name: Option[String],
logo: Option[String],
website: Option[String],
bank_routings: Option[List[BankRoutingJsonV121]],
attributes: Option[List[BankAttributeBankResponseJsonV400]]
bank_routings: Option[List[BankRoutingJsonV121]]
)
case class BankJson500(
@ -78,6 +76,7 @@ case class CreateAccountRequestJsonV500(
case class PostCustomerJsonV500(
legal_name: String,
customer_number: Option[String] = None,
mobile_phone_number: String,
email: Option[String] = None,
face_image: Option[CustomerFaceImageJson] = None,
@ -381,6 +380,147 @@ case class AdapterInfoJsonV500(
)
case class CreateViewJsonV500(
name: String,
description: String,
metadata_view: String,
is_public: Boolean,
which_alias_to_use: String,
hide_metadata_if_alias_used: Boolean,
allowed_actions : List[String],
can_grant_access_to_views : Option[List[String]] = None,
can_revoke_access_to_views : Option[List[String]] = None
) {
def toCreateViewJson = CreateViewJson(
name = this.name,
description = this.description,
metadata_view = this.metadata_view,
is_public = this.is_public,
which_alias_to_use = this.which_alias_to_use,
hide_metadata_if_alias_used = this.hide_metadata_if_alias_used,
allowed_actions = this.allowed_actions,
can_grant_access_to_views = this.can_grant_access_to_views,
can_revoke_access_to_views = this.can_revoke_access_to_views
)
}
case class UpdateViewJsonV500(
description: String,
metadata_view: String,
is_public: Boolean,
is_firehose: Option[Boolean] = None,
which_alias_to_use: String,
hide_metadata_if_alias_used: Boolean,
allowed_actions: List[String],
can_grant_access_to_views : Option[List[String]] = None,
can_revoke_access_to_views : Option[List[String]] = None
) {
def toUpdateViewJson = UpdateViewJSON(
description = this.description,
metadata_view = this.metadata_view,
is_public = this.is_public,
is_firehose = this.is_firehose,
which_alias_to_use = this.which_alias_to_use,
hide_metadata_if_alias_used = this.hide_metadata_if_alias_used,
allowed_actions = this.allowed_actions,
can_grant_access_to_views = this.can_grant_access_to_views,
can_revoke_access_to_views = this.can_revoke_access_to_views
)
}
case class ViewsJsonV500(views : List[ViewJsonV500])
case class ViewIdJsonV500(id: String)
case class ViewsIdsJsonV500(views : List[ViewIdJsonV500])
case class ViewJsonV500(
val id: String,
val short_name: String,
val description: String,
val metadata_view: String,
val is_public: Boolean,
val is_system: Boolean,
val is_firehose: Option[Boolean] = None,
val alias: String,
val hide_metadata_if_alias_used: Boolean,
val can_grant_access_to_views : List[String],
val can_revoke_access_to_views : List[String],
val can_add_comment : Boolean,
val can_add_corporate_location : Boolean,
val can_add_image : Boolean,
val can_add_image_url: Boolean,
val can_add_more_info: Boolean,
val can_add_open_corporates_url : Boolean,
val can_add_physical_location : Boolean,
val can_add_private_alias : Boolean,
val can_add_public_alias : Boolean,
val can_add_tag : Boolean,
val can_add_url: Boolean,
val can_add_where_tag : Boolean,
val can_delete_comment: Boolean,
val can_add_counterparty : Boolean,
val can_delete_corporate_location : Boolean,
val can_delete_image : Boolean,
val can_delete_physical_location : Boolean,
val can_delete_tag : Boolean,
val can_delete_where_tag : Boolean,
val can_edit_owner_comment: Boolean,
val can_see_bank_account_balance: Boolean,
val can_query_available_funds: Boolean,
val can_see_bank_account_bank_name: Boolean,
val can_see_bank_account_currency: Boolean,
val can_see_bank_account_iban: Boolean,
val can_see_bank_account_label: Boolean,
val can_see_bank_account_national_identifier: Boolean,
val can_see_bank_account_number: Boolean,
val can_see_bank_account_owners: Boolean,
val can_see_bank_account_swift_bic: Boolean,
val can_see_bank_account_type: Boolean,
val can_see_comments: Boolean,
val can_see_corporate_location: Boolean,
val can_see_image_url: Boolean,
val can_see_images: Boolean,
val can_see_more_info: Boolean,
val can_see_open_corporates_url: Boolean,
val can_see_other_account_bank_name: Boolean,
val can_see_other_account_iban: Boolean,
val can_see_other_account_kind: Boolean,
val can_see_other_account_metadata: Boolean,
val can_see_other_account_national_identifier: Boolean,
val can_see_other_account_number: Boolean,
val can_see_other_account_swift_bic: Boolean,
val can_see_owner_comment: Boolean,
val can_see_physical_location: Boolean,
val can_see_private_alias: Boolean,
val can_see_public_alias: Boolean,
val can_see_tags: Boolean,
val can_see_transaction_amount: Boolean,
val can_see_transaction_balance: Boolean,
val can_see_transaction_currency: Boolean,
val can_see_transaction_description: Boolean,
val can_see_transaction_finish_date: Boolean,
val can_see_transaction_metadata: Boolean,
val can_see_transaction_other_bank_account: Boolean,
val can_see_transaction_start_date: Boolean,
val can_see_transaction_this_bank_account: Boolean,
val can_see_transaction_type: Boolean,
val can_see_url: Boolean,
val can_see_where_tag: Boolean,
//V300 new
val can_see_bank_routing_scheme: Boolean,
val can_see_bank_routing_address: Boolean,
val can_see_bank_account_routing_scheme: Boolean,
val can_see_bank_account_routing_address: Boolean,
val can_see_other_bank_routing_scheme: Boolean,
val can_see_other_bank_routing_address: Boolean,
val can_see_other_account_routing_scheme: Boolean,
val can_see_other_account_routing_address: Boolean,
val can_add_transaction_request_to_own_account: Boolean, //added following two for payments
val can_add_transaction_request_to_any_account: Boolean,
val can_see_bank_account_credit_limit: Boolean,
val can_create_direct_debit: Boolean,
val can_create_standing_order: Boolean
)
object JSONFactory500 {
def createUserAuthContextJson(userAuthContext: UserAuthContext): UserAuthContextJsonV500 = {
@ -579,7 +719,7 @@ object JSONFactory500 {
enabled = card.enabled,
cancelled = card.cancelled,
on_hot_list = card.onHotList,
technology = stringOrNull(card.technology),
technology = nullToString(card.technology),
networks = card.networks,
allows = card.allows.map(cardActionsToString).toList,
account = createAccountJson(card.account, user),
@ -604,7 +744,116 @@ object JSONFactory500 {
def createCustomerAccountLinksJon(customerAccountLinks: List[CustomerAccountLinkTrait]): CustomerAccountLinksJson = {
CustomerAccountLinksJson(customerAccountLinks.map(createCustomerAccountLinkJson))
}
}
def createViewJsonV500(view : View) : ViewJsonV500 = {
val alias =
if(view.usePublicAliasIfOneExists)
"public"
else if(view.usePrivateAliasIfOneExists)
"private"
else
""
ViewJsonV500(
id = view.viewId.value,
short_name = stringOrNull(view.name),
description = stringOrNull(view.description),
metadata_view= view.metadataView,
is_public = view.isPublic,
is_system = view.isSystem,
alias = alias,
hide_metadata_if_alias_used = view.hideOtherAccountMetadataIfAlias,
can_add_comment = view.canAddComment,
can_add_corporate_location = view.canAddCorporateLocation,
can_add_image = view.canAddImage,
can_add_image_url = view.canAddImageURL,
can_add_more_info = view.canAddMoreInfo,
can_add_open_corporates_url = view.canAddOpenCorporatesUrl,
can_add_physical_location = view.canAddPhysicalLocation,
can_add_private_alias = view.canAddPrivateAlias,
can_add_public_alias = view.canAddPublicAlias,
can_add_tag = view.canAddTag,
can_add_url = view.canAddURL,
can_add_where_tag = view.canAddWhereTag,
can_delete_comment = view.canDeleteComment,
can_add_counterparty = view.canAddCounterparty,
can_delete_corporate_location = view.canDeleteCorporateLocation,
can_delete_image = view.canDeleteImage,
can_delete_physical_location = view.canDeletePhysicalLocation,
can_delete_tag = view.canDeleteTag,
can_delete_where_tag = view.canDeleteWhereTag,
can_edit_owner_comment = view.canEditOwnerComment,
can_see_bank_account_balance = view.canSeeBankAccountBalance,
can_query_available_funds = view.canQueryAvailableFunds,
can_see_bank_account_bank_name = view.canSeeBankAccountBankName,
can_see_bank_account_currency = view.canSeeBankAccountCurrency,
can_see_bank_account_iban = view.canSeeBankAccountIban,
can_see_bank_account_label = view.canSeeBankAccountLabel,
can_see_bank_account_national_identifier = view.canSeeBankAccountNationalIdentifier,
can_see_bank_account_number = view.canSeeBankAccountNumber,
can_see_bank_account_owners = view.canSeeBankAccountOwners,
can_see_bank_account_swift_bic = view.canSeeBankAccountSwift_bic,
can_see_bank_account_type = view.canSeeBankAccountType,
can_see_comments = view.canSeeComments,
can_see_corporate_location = view.canSeeCorporateLocation,
can_see_image_url = view.canSeeImageUrl,
can_see_images = view.canSeeImages,
can_see_more_info = view.canSeeMoreInfo,
can_see_open_corporates_url = view.canSeeOpenCorporatesUrl,
can_see_other_account_bank_name = view.canSeeOtherAccountBankName,
can_see_other_account_iban = view.canSeeOtherAccountIBAN,
can_see_other_account_kind = view.canSeeOtherAccountKind,
can_see_other_account_metadata = view.canSeeOtherAccountMetadata,
can_see_other_account_national_identifier = view.canSeeOtherAccountNationalIdentifier,
can_see_other_account_number = view.canSeeOtherAccountNumber,
can_see_other_account_swift_bic = view.canSeeOtherAccountSWIFT_BIC,
can_see_owner_comment = view.canSeeOwnerComment,
can_see_physical_location = view.canSeePhysicalLocation,
can_see_private_alias = view.canSeePrivateAlias,
can_see_public_alias = view.canSeePublicAlias,
can_see_tags = view.canSeeTags,
can_see_transaction_amount = view.canSeeTransactionAmount,
can_see_transaction_balance = view.canSeeTransactionBalance,
can_see_transaction_currency = view.canSeeTransactionCurrency,
can_see_transaction_description = view.canSeeTransactionDescription,
can_see_transaction_finish_date = view.canSeeTransactionFinishDate,
can_see_transaction_metadata = view.canSeeTransactionMetadata,
can_see_transaction_other_bank_account = view.canSeeTransactionOtherBankAccount,
can_see_transaction_start_date = view.canSeeTransactionStartDate,
can_see_transaction_this_bank_account = view.canSeeTransactionThisBankAccount,
can_see_transaction_type = view.canSeeTransactionType,
can_see_url = view.canSeeUrl,
can_see_where_tag = view.canSeeWhereTag,
//V300 new
can_see_bank_routing_scheme = view.canSeeBankRoutingScheme,
can_see_bank_routing_address = view.canSeeBankRoutingAddress,
can_see_bank_account_routing_scheme = view.canSeeBankAccountRoutingScheme,
can_see_bank_account_routing_address = view.canSeeBankAccountRoutingAddress,
can_see_other_bank_routing_scheme = view.canSeeOtherBankRoutingScheme,
can_see_other_bank_routing_address = view.canSeeOtherBankRoutingAddress,
can_see_other_account_routing_scheme = view.canSeeOtherAccountRoutingScheme,
can_see_other_account_routing_address= view.canSeeOtherAccountRoutingAddress,
can_add_transaction_request_to_own_account = view.canAddTransactionRequestToOwnAccount, //added following two for payments
can_add_transaction_request_to_any_account = view.canAddTransactionRequestToAnyAccount,
can_see_bank_account_credit_limit = view.canSeeBankAccountCreditLimit,
can_create_direct_debit = view.canCreateDirectDebit,
can_create_standing_order = view.canCreateStandingOrder,
// Version 5.0.0
can_grant_access_to_views = view.canGrantAccessToViews.getOrElse(Nil),
can_revoke_access_to_views = view.canRevokeAccessToViews.getOrElse(Nil),
)
}
def createViewsJsonV500(views : List[View]) : ViewsJsonV500 = {
ViewsJsonV500(views.map(createViewJsonV500))
}
def createViewsIdsJsonV500(views : List[View]) : ViewsIdsJsonV500 = {
ViewsIdsJsonV500(views.map(i => ViewIdJsonV500(i.viewId.value)))
}
def createAdapterInfoJson(inboundAdapterInfoInternal: InboundAdapterInfoInternal, startTime: Long): AdapterInfoJsonV500 = {
AdapterInfoJsonV500(

View File

@ -1945,7 +1945,31 @@ trait Connector extends MdcLoggable {
nameSuffix: String,
callContext: Option[CallContext],
): OBPReturnType[Box[Customer]] = Future{(Failure(setUnimplementedError), callContext)}
def createCustomerC2(
bankId: BankId,
legalName: String,
customerNumber: String,
mobileNumber: String,
email: String,
faceImage:
CustomerFaceImageTrait,
dateOfBirth: Date,
relationshipStatus: String,
dependents: Int,
dobOfDependents: List[Date],
highestEducationAttained: String,
employmentStatus: String,
kycStatus: Boolean,
lastOkDate: Date,
creditRating: Option[CreditRatingTrait],
creditLimit: Option[AmountOfMoneyTrait],
title: String,
branchId: String,
nameSuffix: String,
callContext: Option[CallContext],
): OBPReturnType[Box[Customer]] = Future{(Failure(setUnimplementedError), callContext)}
def updateCustomerScaData(customerId: String,
mobileNumber: Option[String],
email: Option[String],

View File

@ -873,6 +873,60 @@ object LocalMappedConnector extends Connector with MdcLoggable {
}
private def findFirehoseAccounts(bankId: BankId, ordering: SQLSyntax, limit: Int, offset: Int)(implicit session: DBSession = AutoSession) = {
def parseOwners(owners: String): List[FastFirehoseOwners] = {
if(!owners.isEmpty) {
transformString(owners).map {
i =>
FastFirehoseOwners(
user_id = i("user_id").mkString(""),
provider = i("provider").mkString(""),
user_name = i("user_name").mkString("")
)
}
} else {
List()
}
}
def parseRoutings(owners: String): List[FastFirehoseRoutings] = {
if(!owners.isEmpty) {
transformString(owners).map {
i =>
FastFirehoseRoutings(
bank_id = i("bank_id").mkString(""),
account_id = i("account_id").mkString("")
)
}
} else {
List()
}
}
def parseAttributes(owners: String): List[FastFirehoseAttributes] = {
if(!owners.isEmpty) {
transformString(owners).map {
i =>
FastFirehoseAttributes(
`type` = i("type").mkString(""),
code = i("code").mkString(""),
value = i("value").mkString("")
)
}
} else {
List()
}
}
def transformString(owners: String): List[Map[String, List[String]]] = {
val splitToRows: List[String] = owners.split("::").toList
val keyValuePairs: List[List[(String, String)]] = splitToRows.map { i=>
i.split(",").toList.map {
x =>
val keyValue: Array[String] = x.split(":")
if(keyValue.size == 2) (keyValue(0), keyValue(1)) else (keyValue(0), "")
}
}
val maps: List[Map[String, List[String]]] = keyValuePairs.map(_.groupBy(_._1).map { case (k,v) => (k,v.map(_._2))})
maps
}
val sqlResult = sql"""
|select
| mappedbankaccount.theaccountid as account_id,
@ -887,7 +941,7 @@ object LocalMappedConnector extends Connector with MdcLoggable {
| ||resourceuser.provider_
| ||',user_name:'
| ||resourceuser.name_,
| ',') as owners
| '::') as owners
| from resourceuser
| where
| resourceuser.id = mapperaccountholders.user_c
@ -901,7 +955,7 @@ object LocalMappedConnector extends Connector with MdcLoggable {
| ||bankaccountrouting.bankid
| ||',account_id:'
| ||bankaccountrouting.accountid,
| ','
| '::'
| ) as account_routings
| from bankaccountrouting
| where
@ -915,7 +969,7 @@ object LocalMappedConnector extends Connector with MdcLoggable {
| ||mappedaccountattribute.mcode
| ||',value:'
| ||mappedaccountattribute.mvalue,
| ',') as account_attributes
| '::') as account_attributes
| from mappedaccountattribute
| where
| mappedaccountattribute.maccountid = mappedbankaccount.theaccountid
@ -930,28 +984,31 @@ object LocalMappedConnector extends Connector with MdcLoggable {
|
|
|""".stripMargin
.map(
.map {
rs => // Map result to case class
val owners = parseOwners(rs.stringOpt(5).map(_.toString).getOrElse(""))
val routings = parseRoutings(rs.stringOpt(9).map(_.toString).getOrElse(""))
val attributes = parseAttributes(rs.stringOpt(10).map(_.toString).getOrElse(""))
FastFirehoseAccount(
id = rs.stringOpt(1).map(_.toString).getOrElse(null),
bankId= rs.stringOpt(2).map(_.toString).getOrElse(null),
label= rs.stringOpt(3).map(_.toString).getOrElse(null),
bankId = rs.stringOpt(2).map(_.toString).getOrElse(null),
label = rs.stringOpt(3).map(_.toString).getOrElse(null),
number = rs.stringOpt(4).map(_.toString).getOrElse(null),
owners = rs.stringOpt(5).map(_.toString).getOrElse(null),
productCode = rs.stringOpt(6).map(_.toString).getOrElse(null),
owners = owners,
productCode = rs.stringOpt(6).map(_.toString).getOrElse(null),
balance = AmountOfMoney(
currency = rs.stringOpt(7).map(_.toString).getOrElse(null),
amount = rs.bigIntOpt(8).map( a =>
amount = rs.bigIntOpt(8).map(a =>
Helper.smallestCurrencyUnitToBigDecimal(
a.longValue(),
rs.stringOpt(7).getOrElse("EUR")
).toString()
).getOrElse(null)
),
accountRoutings = rs.stringOpt(9).map(_.toString).getOrElse(null),
accountAttributes = rs.stringOpt(10).map(_.toString).getOrElse(null)
accountRoutings = routings,
accountAttributes = attributes
)
).list().apply()
}.list().apply()
sqlResult
}
@ -3434,6 +3491,52 @@ object LocalMappedConnector extends Connector with MdcLoggable {
), callContext)
}
override def createCustomerC2(
bankId: BankId,
legalName: String,
customerNumber: String,
mobileNumber: String,
email: String,
faceImage:
CustomerFaceImageTrait,
dateOfBirth: Date,
relationshipStatus: String,
dependents: Int,
dobOfDependents: List[Date],
highestEducationAttained: String,
employmentStatus: String,
kycStatus: Boolean,
lastOkDate: Date,
creditRating: Option[CreditRatingTrait],
creditLimit: Option[AmountOfMoneyTrait],
title: String,
branchId: String,
nameSuffix: String,
callContext: Option[CallContext]
): OBPReturnType[Box[Customer]] = Future {
(CustomerX.customerProvider.vend.addCustomer(
bankId,
customerNumber,
legalName,
mobileNumber,
email,
faceImage,
dateOfBirth,
relationshipStatus,
dependents,
dobOfDependents,
highestEducationAttained,
employmentStatus,
kycStatus,
lastOkDate,
creditRating,
creditLimit,
title,
branchId,
nameSuffix
), callContext)
}
override def updateCustomerScaData(customerId: String,
mobileNumber: Option[String],
email: Option[String],

View File

@ -125,6 +125,7 @@ object MappedMetrics extends APIMetrics with MdcLoggable{
.flatMap(consumerIdToPrimaryKey)
.map(By(MappedMetric.consumerId, _) )
val bankId = queryParams.collect { case OBPBankId(value) => Like(MappedMetric.url, s"%banks/$value%") }.headOption
val userId = queryParams.collect { case OBPUserId(value) => By(MappedMetric.userId, value) }.headOption
val url = queryParams.collect { case OBPUrl(value) => By(MappedMetric.url, value) }.headOption
val appName = queryParams.collect { case OBPAppName(value) => By(MappedMetric.appName, value) }.headOption
@ -149,6 +150,7 @@ object MappedMetrics extends APIMetrics with MdcLoggable{
ordering,
consumerId.toSeq,
userId.toSeq,
bankId.toSeq,
url.toSeq,
appName.toSeq,
implementedInVersion.toSeq,

View File

@ -85,6 +85,9 @@ class ResourceUser extends LongKeyedMapper[ResourceUser] with User with ManyToMa
override def defaultValue = false
}
object LastMarketingAgreementSignedDate extends MappedDate(this)
object LastUsedLocale extends MappedString(this, 10) {
override def defaultValue = null
}
def emailAddress = {
val e = email.get
@ -114,6 +117,7 @@ class ResourceUser extends LongKeyedMapper[ResourceUser] with User with ManyToMa
override def createdByUserInvitationId = if(CreatedByUserInvitationId.get == null) None else if (CreatedByUserInvitationId.get.isEmpty) None else Some(CreatedByUserInvitationId.get) //null --> None
override def isDeleted: Option[Boolean] = if(IsDeleted.jdbcFriendly(IsDeleted.calcFieldName) == null) None else Some(IsDeleted.get) // null --> None
override def lastMarketingAgreementSignedDate: Option[Date] = if(IsDeleted.jdbcFriendly(LastMarketingAgreementSignedDate.calcFieldName) == null) None else Some(LastMarketingAgreementSignedDate.get) // null --> None
override def lastUsedLocale: Option[String] = if(LastUsedLocale.get == null) None else Some(LastUsedLocale.get) // null --> None
}
object ResourceUser extends ResourceUser with LongKeyedMetaMapper[ResourceUser]{

View File

@ -69,6 +69,10 @@ object RemotedataViews extends ObpActorInit with Views {
def systemViewFuture(viewId : ViewId) : Future[Box[View]] =
(actor ? cc.systemViewFuture(viewId)).mapTo[Box[View]]
def getSystemViews() : Future[List[View]] =
(actor ? cc.getSystemViews()).mapTo[List[View]]
def createView(bankAccountId: BankIdAccountId, view: CreateViewJson): Box[View] = getValueFromFuture(
(actor ? cc.createView(bankAccountId, view)).mapTo[Box[View]]
)

View File

@ -64,6 +64,10 @@ class RemotedataViewsActor extends Actor with ObpActorHelper with MdcLoggable {
case cc.systemView(viewId: ViewId) =>
logger.debug("view(" + viewId + ")")
sender ! (mapper.systemView(viewId))
case cc.getSystemViews() =>
logger.debug("getSystemViews()")
sender ! (mapper.getSystemViews())
case cc.customViewFuture(viewId: ViewId, bankAccountId: BankIdAccountId) =>
logger.debug("customViewFuture(" + viewId +", "+ bankAccountId + ")")

View File

@ -340,6 +340,15 @@ object MapperViews extends Views with MdcLoggable {
def systemView(viewId : ViewId) : Box[View] = {
ViewDefinition.findSystemView(viewId.value)
}
def getSystemViews() : Future[List[View]] = {
Future {
ViewDefinition.findAll(
NullRef(ViewDefinition.bank_id),
NullRef(ViewDefinition.account_id),
By(ViewDefinition.isSystem_, true)
)
}
}
def systemViewFuture(viewId : ViewId) : Future[Box[View]] = {
Future {
systemView(viewId)

View File

@ -55,6 +55,7 @@ trait Views {
def systemView(viewId : ViewId) : Box[View]
def customViewFuture(viewId : ViewId, bankAccountId: BankIdAccountId) : Future[Box[View]]
def systemViewFuture(viewId : ViewId) : Future[Box[View]]
def getSystemViews(): Future[List[View]]
//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)
@ -154,6 +155,7 @@ class RemotedataViewsCaseClasses {
def apply(viewId: ViewId, bankAccountId: BankIdAccountId): Box[View] = this (viewId, bankAccountId)
}
case class systemView(viewId : ViewId)
case class getSystemViews()
case class customViewFuture(viewId : ViewId, bankAccountId: BankIdAccountId)
case class systemViewFuture(viewId : ViewId)
case class getOrCreateAccountView(account: BankIdAccountId, viewName: String)

View File

@ -49,6 +49,12 @@ class ViewDefinition extends View with LongKeyedMapper[ViewDefinition] with Many
object hideOtherAccountMetadataIfAlias_ extends MappedBoolean(this){
override def defaultValue = false
}
object canGrantAccessToViews_ extends MappedText(this){
override def defaultValue = ""
}
object canRevokeAccessToViews_ extends MappedText(this){
override def defaultValue = ""
}
object canSeeTransactionThisBankAccount_ extends MappedBoolean(this){
override def defaultValue = false
}
@ -303,6 +309,9 @@ class ViewDefinition extends View with LongKeyedMapper[ViewDefinition] with Many
isPublic_(viewData.is_public)
isFirehose_(viewData.is_firehose.getOrElse(false))
metadataView_(viewData.metadata_view)
canGrantAccessToViews_(viewData.can_grant_access_to_views.getOrElse(Nil).mkString(","))
canRevokeAccessToViews_(viewData.can_revoke_access_to_views.getOrElse(Nil).mkString(","))
val actions = viewData.allowed_actions
@ -408,6 +417,19 @@ class ViewDefinition extends View with LongKeyedMapper[ViewDefinition] with Many
def usePublicAliasIfOneExists: Boolean = usePublicAliasIfOneExists_.get
def hideOtherAccountMetadataIfAlias: Boolean = hideOtherAccountMetadataIfAlias_.get
override def canGrantAccessToViews : Option[List[String]] = {
canGrantAccessToViews_.get == null || canGrantAccessToViews_.get.isEmpty() match {
case true => None
case _ => Some(canGrantAccessToViews_.get.split(",").toList.map(_.trim))
}
}
override def canRevokeAccessToViews : Option[List[String]] = {
canRevokeAccessToViews_.get == null || canRevokeAccessToViews_.get.isEmpty() match {
case true => None
case _ => Some(canRevokeAccessToViews_.get.split(",").toList.map(_.trim))
}
}
//reading access
//transaction fields

View File

@ -23,7 +23,7 @@ object MappedWebUiPropsProvider extends WebUiPropsProvider {
override def createOrUpdate(webUiProps: WebUiPropsT): Box[WebUiPropsT] = {
WebUiProps.find(By(WebUiProps.Name, webUiProps.name))
.or(Full(WebUiProps.create))
.map(_.Name(webUiProps.name).Value(webUiProps.value).saveMe())
.map(_.Name(webUiProps.name.trim()).Value(webUiProps.value).saveMe())
}
override def delete(webUiPropsId: String):Box[Boolean] = WebUiProps.find(By(WebUiProps.WebUiPropsId, webUiPropsId)) match {
@ -81,6 +81,6 @@ class WebUiProps extends WebUiPropsT with LongKeyedMapper[WebUiProps] with IdPK
}
object WebUiProps extends WebUiProps with LongKeyedMetaMapper[WebUiProps] {
override def dbIndexes = UniqueIndex(WebUiPropsId) :: super.dbIndexes
override def dbIndexes = UniqueIndex(WebUiPropsId) :: UniqueIndex(Name) :: super.dbIndexes
}

View File

@ -29,7 +29,7 @@ package code.api.v2_2_0
import code.api.Constant._
import _root_.net.liftweb.json.Serialization.write
import com.openbankproject.commons.model.ErrorMessage
import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON.createViewJson
import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON.createViewJsonV300
import code.api.util.APIUtil.OAuth._
import code.api.v1_2._
import code.api.v1_2_1.UpdateViewJsonV121
@ -67,7 +67,7 @@ class API2_2_0Test extends V220ServerSetup with DefaultUsers {
/********************* API test methods ********************/
//System view, owner
val postBodySystemViewJson = createViewJson.copy(name=SYSTEM_OWNER_VIEW_ID)
val postBodySystemViewJson = createViewJsonV300.copy(name=SYSTEM_OWNER_VIEW_ID).toCreateViewJson
def randomBank : String = {
val banksJson = getBanksInfo.body.extract[BanksJSON]
@ -90,7 +90,7 @@ class API2_2_0Test extends V220ServerSetup with DefaultUsers {
viewsIdsToGrant
}
def randomView(isPublic: Boolean, alias: String) = createViewJson
def randomView(isPublic: Boolean, alias: String) = createViewJsonV300.toCreateViewJson
def getBanksInfo : APIResponse = {

View File

@ -53,9 +53,9 @@ class ViewsTests extends V300ServerSetup {
//Custom view, name starts from `_`
val postBodyViewJson = createViewJson
val postBodyViewJson = createViewJsonV300.toCreateViewJson
//System view, owner
val postBodySystemViewJson = createViewJson.copy(name=SYSTEM_OWNER_VIEW_ID).copy(metadata_view = SYSTEM_OWNER_VIEW_ID)
val postBodySystemViewJson = createViewJsonV300.copy(name=SYSTEM_OWNER_VIEW_ID).copy(metadata_view = SYSTEM_OWNER_VIEW_ID).toCreateViewJson
def getAccountViews(bankId : String, accountId : String, consumerAndToken: Option[(Consumer, Token)]): APIResponse = {
val request = v3_0Request / "banks" / bankId / "accounts" / accountId / "views" <@(consumerAndToken)

View File

@ -72,7 +72,7 @@ class SystemViewsTests extends V310ServerSetup {
// Custom view, name starts from `_`
// System view, owner
val randomSystemViewId = APIUtil.generateUUID()
val postBodySystemViewJson = createSystemViewJson.copy(name=randomSystemViewId).copy(metadata_view = randomSystemViewId)
val postBodySystemViewJson = createSystemViewJsonV300.copy(name=randomSystemViewId).copy(metadata_view = randomSystemViewId).toCreateViewJson
val systemViewId = MapperViews.getNewViewPermalink(postBodySystemViewJson.name)
def getSystemView(viewId : String, consumerAndToken: Option[(Consumer, Token)]): APIResponse = {

View File

@ -2,7 +2,7 @@ package code.api.v4_0_0
import com.openbankproject.commons.model.ErrorMessage
import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON
import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON.createViewJson
import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON.createViewJsonV300
import code.api.util.APIUtil.OAuth._
import code.api.util.ApiRole
import com.openbankproject.commons.util.ApiVersion
@ -37,7 +37,7 @@ class AccountAccessTest extends V400ServerSetup {
lazy val bankAccount = randomPrivateAccountViaEndpoint(bankId)
lazy val ownerView = randomOwnerViewPermalinkViaEndpoint(bankId, bankAccount)
lazy val postAccountAccessJson = PostAccountAccessJsonV400(resourceUser2.userId, PostViewJsonV400("_test_view", false))
lazy val postBodyViewJson = createViewJson
lazy val postBodyViewJson = createViewJsonV300.toCreateViewJson
def createAnAccount(bankId: String, user: Option[(Consumer,Token)]): CreateAccountResponseJsonV310 = {
val addAccountJson = SwaggerDefinitionsJSON.createAccountRequestJsonV310.copy(user_id = resourceUser1.userId, balance = AmountOfMoneyJsonV121("EUR","0"))

View File

@ -1,7 +1,7 @@
package code.api.v4_0_0
import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON
import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON.createViewJson
import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON.createViewJsonV300
import code.api.util.APIUtil.OAuth._
import code.api.util.ApiRole
import code.api.util.ApiRole.CanDeleteAccountCascade
@ -74,7 +74,7 @@ class DeleteAccountCascadeTest extends V400ServerSetup {
//it is an asynchronous process, need some time to be done.
TimeUnit.SECONDS.sleep(3)
val postBodyView = createViewJson.copy(name = "_cascade_delete", metadata_view = "_cascade_delete", is_public = false)
val postBodyView = createViewJsonV300.copy(name = "_cascade_delete", metadata_view = "_cascade_delete", is_public = false).toCreateViewJson
createViewViaEndpoint(bankId, account.account_id, postBodyView, user1)
createAccountAttributeViaEndpoint(

View File

@ -1,7 +1,7 @@
package code.api.v4_0_0
import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON
import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON.createViewJson
import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON.createViewJsonV300
import code.api.util.APIUtil.OAuth._
import code.api.util.{APIUtil, ApiRole}
import code.api.util.ApiRole.{CanDeleteAccountCascade, CanDeleteBankCascade}
@ -76,7 +76,7 @@ class DeleteBankCascadeTest extends V400ServerSetup {
val account = response400.body.extract[CreateAccountResponseJsonV310]
account.account_id should not be empty
val postBodyView = createViewJson.copy(name = "_cascade_delete", metadata_view = "_cascade_delete", is_public = false)
val postBodyView = createViewJsonV300.copy(name = "_cascade_delete", metadata_view = "_cascade_delete", is_public = false).toCreateViewJson
createViewViaEndpoint(bankId, account.account_id, postBodyView, user1)
createAccountAttributeViaEndpoint(

View File

@ -4,7 +4,7 @@ import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
import code.api.Constant._
import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON
import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON.createViewJson
import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON.createViewJsonV300
import code.api.util.APIUtil.OAuth.{Consumer, Token, _}
import code.api.util.ApiRole.{CanCreateAccountAttributeAtOneBank, CanCreateCustomer, CanCreateProduct, _}
import code.api.util.{APIUtil, ApiRole}
@ -359,7 +359,7 @@ trait V400ServerSetup extends ServerSetupWithTestData with DefaultUsers {
// Create to account
val toAccount = createAccountViaEndpoint(bank.bankId.value, addAccountJson2, user1)
// Create a custom view
val customViewJson = createViewJson.copy(name = "_cascade_delete", metadata_view = "_cascade_delete", is_public = false)
val customViewJson = createViewJsonV300.copy(name = "_cascade_delete", metadata_view = "_cascade_delete", is_public = false).toCreateViewJson
val customView = createViewViaEndpoint(bank.bankId.value, fromAccount.account_id, customViewJson, user1)
// Grant access to the view
grantUserAccessToViewViaEndpoint(

View File

@ -0,0 +1,96 @@
/**
Open Bank Project - API
Copyright (C) 2011-2019, TESOBE GmbH.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Email: contact@tesobe.com
TESOBE GmbH.
Osloer Strasse 16/17
Berlin 13359, Germany
This product includes software developed at
TESOBE (http://www.tesobe.com/)
*/
package code.api.v5_0_0
import code.api.util.APIUtil.OAuth._
import code.api.util.ApiRole.CanGetMetricsAtOneBank
import code.api.util.ErrorMessages.{UserHasMissingRoles, UserNotLoggedIn}
import code.api.v2_1_0.MetricsJson
import code.api.v5_0_0.APIMethods500.Implementations5_0_0
import code.entitlement.Entitlement
import code.setup.APIResponse
import com.github.dwickern.macros.NameOf.nameOf
import com.openbankproject.commons.model.ErrorMessage
import com.openbankproject.commons.util.ApiVersion
import org.scalatest.Tag
class MetricsTest extends V500ServerSetup {
override def beforeAll(): Unit = {
super.beforeAll()
}
override def afterAll(): Unit = {
super.afterAll()
}
/**
* 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.v5_0_0.toString)
object ApiEndpoint1 extends Tag(nameOf(Implementations5_0_0.getMetricsAtBank))
lazy val bankId = testBankId1.value
def getMetrics(consumerAndToken: Option[(Consumer, Token)], bankId: String): APIResponse = {
val request = v5_0_0_Request / "management" / "metrics" / "banks" / bankId <@(consumerAndToken)
makeGetRequest(request)
}
feature(s"test $ApiEndpoint1 version $VersionOfApi - Unauthorized access") {
scenario("We will call the endpoint without user credentials", ApiEndpoint1, VersionOfApi) {
When(s"We make a request $ApiEndpoint1")
val response400 = getMetrics(None, bankId)
Then("We should get a 401")
response400.code should equal(401)
response400.body.extract[ErrorMessage].message should equal(UserNotLoggedIn)
}
}
feature(s"test $ApiEndpoint1 version $VersionOfApi - Authorized access") {
scenario("We will call the endpoint without user credentials", ApiEndpoint1, VersionOfApi) {
When(s"We make a request $ApiEndpoint1")
val response400 = getMetrics(user1, bankId)
Then("We should get a 403")
response400.code should equal(403)
response400.body.extract[ErrorMessage].message contains (UserHasMissingRoles + CanGetMetricsAtOneBank) should be (true)
}
}
feature(s"test $ApiEndpoint1 version $VersionOfApi - Authorized access with proper Role") {
scenario("We will call the endpoint without user credentials", ApiEndpoint1, VersionOfApi) {
When(s"We make a request $ApiEndpoint1")
Entitlement.entitlement.vend.addEntitlement(bankId, resourceUser1.userId, CanGetMetricsAtOneBank.toString)
val response400 = getMetrics(user1, bankId)
Then("We should get a 200")
response400.code should equal(200)
response400.body.extract[MetricsJson]
}
}
}

View File

@ -0,0 +1,314 @@
/**
Open Bank Project - API
Copyright (C) 2011-2019, TESOBE GmbH.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Email: contact@tesobe.com
TESOBE GmbH.
Osloer Strasse 16/17
Berlin 13359, Germany
This product includes software developed at
TESOBE (http://www.tesobe.com/)
*/
package code.api.v5_0_0
import _root_.net.liftweb.json.Serialization.write
import code.api.Constant._
import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON._
import code.api.util.APIUtil
import code.api.util.APIUtil.OAuth._
import code.api.util.ApiRole.{CanCreateSystemView, CanDeleteSystemView, CanGetSystemView, CanUpdateSystemView}
import code.api.util.ErrorMessages.{UserHasMissingRoles, UserNotLoggedIn}
import code.api.v5_0_0.APIMethods500.Implementations5_0_0
import code.entitlement.Entitlement
import code.setup.APIResponse
import code.views.MapperViews
import code.views.system.AccountAccess
import com.github.dwickern.macros.NameOf.nameOf
import com.openbankproject.commons.model.{CreateViewJson, ErrorMessage, UpdateViewJSON}
import com.openbankproject.commons.util.ApiVersion
import net.liftweb.mapper.By
import org.scalatest.Tag
import scala.collection.immutable.List
class SystemViewsTests extends V500ServerSetup {
override def beforeAll(): Unit = {
super.beforeAll()
}
override def afterAll(): Unit = {
super.afterAll()
}
/**
* 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.v5_0_0.toString)
object ApiEndpoint1 extends Tag(nameOf(Implementations5_0_0.getSystemView))
object ApiEndpoint2 extends Tag(nameOf(Implementations5_0_0.createSystemView))
object ApiEndpoint3 extends Tag(nameOf(Implementations5_0_0.updateSystemView))
object ApiEndpoint4 extends Tag(nameOf(Implementations5_0_0.deleteSystemView))
object ApiEndpoint5 extends Tag(nameOf(Implementations5_0_0.getSystemViewsIds))
// Custom view, name starts from `_`
// System view, owner
val randomSystemViewId = APIUtil.generateUUID()
val postBodySystemViewJson = createSystemViewJsonV500
.copy(name=randomSystemViewId)
.copy(metadata_view = randomSystemViewId).toCreateViewJson
val systemViewId = MapperViews.getNewViewPermalink(postBodySystemViewJson.name)
def getSystemView(viewId : String, consumerAndToken: Option[(Consumer, Token)]): APIResponse = {
val request = v5_0_0_Request / "system-views" / viewId <@(consumerAndToken)
makeGetRequest(request)
}
def getSystemViewsIds(consumerAndToken: Option[(Consumer, Token)]): APIResponse = {
val request = v5_0_0_Request / "system-views-ids" <@(consumerAndToken)
makeGetRequest(request)
}
def postSystemView(view: CreateViewJson, consumerAndToken: Option[(Consumer, Token)]): APIResponse = {
val request = (v5_0_0_Request / "system-views").POST <@(consumerAndToken)
makePostRequest(request, write(view))
}
def putSystemView(viewId : String, view: UpdateViewJSON, consumerAndToken: Option[(Consumer, Token)]): APIResponse = {
val request = (v5_0_0_Request / "system-views" / viewId).PUT <@(consumerAndToken)
makePutRequest(request, write(view))
}
def deleteSystemView(viewId : String, consumerAndToken: Option[(Consumer, Token)]): APIResponse = {
val request = (v5_0_0_Request / "system-views" / viewId).DELETE <@(consumerAndToken)
makeDeleteRequest(request)
}
def createSystemView(viewId: String): Boolean = {
Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, CanCreateSystemView.toString)
val postBody = postBodySystemViewJson.copy(name=viewId).copy(metadata_view = viewId)
val response400 = postSystemView(postBody, user1)
response400.code == 201
}
feature(s"test $ApiEndpoint2 version $VersionOfApi - Unauthorized access") {
scenario("We will call the endpoint without user credentials", ApiEndpoint1, VersionOfApi) {
When(s"We make a request $ApiEndpoint2")
val response400 = postSystemView(postBodySystemViewJson, None)
Then("We should get a 401")
response400.code should equal(401)
response400.body.extract[ErrorMessage].message should equal(UserNotLoggedIn)
}
}
feature(s"test $ApiEndpoint2 version $VersionOfApi - Authorized access") {
scenario("We will call the endpoint without user credentials", ApiEndpoint1, VersionOfApi) {
When(s"We make a request $ApiEndpoint2")
val response400 = postSystemView(postBodySystemViewJson, user1)
Then("We should get a 403")
response400.code should equal(403)
response400.body.extract[ErrorMessage].message should equal(UserHasMissingRoles + CanCreateSystemView)
}
}
feature(s"test $ApiEndpoint2 version $VersionOfApi - Authorized access with proper Role") {
scenario("We will call the endpoint without user credentials", ApiEndpoint1, VersionOfApi) {
When(s"We make a request $ApiEndpoint2")
Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, CanCreateSystemView.toString)
val response400 = postSystemView(postBodySystemViewJson, user1)
Then("We should get a 201")
response400.code should equal(201)
response400.body.extract[ViewJsonV500]
}
}
feature(s"test $ApiEndpoint1 version $VersionOfApi - Unauthorized access") {
scenario("We will call the endpoint without user credentials", ApiEndpoint1, VersionOfApi) {
When(s"We make a request $ApiEndpoint1")
val response400 = getSystemView("", None)
Then("We should get a 401")
response400.code should equal(401)
response400.body.extract[ErrorMessage].message should equal(UserNotLoggedIn)
}
}
feature(s"test $ApiEndpoint1 version $VersionOfApi - Authorized access") {
scenario("We will call the endpoint without user credentials", ApiEndpoint1, VersionOfApi) {
When(s"We make a request $ApiEndpoint1")
val response400 = getSystemView("", user1)
Then("We should get a 403")
response400.code should equal(403)
response400.body.extract[ErrorMessage].message should equal(UserHasMissingRoles + CanGetSystemView)
}
}
feature(s"test $ApiEndpoint1 version $VersionOfApi - Authorized access with proper Role") {
scenario("We will call the endpoint without user credentials", ApiEndpoint1, VersionOfApi) {
val viewId = APIUtil.generateUUID()
createSystemView(viewId)
When(s"We make a request $ApiEndpoint1")
Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, CanGetSystemView.toString)
val response400 = getSystemView(viewId, user1)
Then("We should get a 200")
response400.code should equal(200)
response400.body.extract[ViewJsonV500]
}
}
feature(s"test $ApiEndpoint3 version $VersionOfApi - Unauthorized access") {
scenario("We will call the endpoint without user credentials", ApiEndpoint3, VersionOfApi) {
When(s"We make a request $ApiEndpoint3")
val response400 = getSystemView("", None)
Then("We should get a 401")
response400.code should equal(401)
response400.body.extract[ErrorMessage].message should equal(UserNotLoggedIn)
}
}
feature(s"test $ApiEndpoint3 version $VersionOfApi - Authorized access") {
scenario("We will call the endpoint without user credentials", ApiEndpoint3, VersionOfApi) {
When(s"We make a request $ApiEndpoint3")
val response400 = getSystemView("", user1)
Then("We should get a 403")
response400.code should equal(403)
response400.body.extract[ErrorMessage].message should equal(UserHasMissingRoles + CanGetSystemView)
}
}
feature(s"test $ApiEndpoint3 version $VersionOfApi - Authorized access with proper Role") {
scenario("we will update a view on a bank account", ApiEndpoint3, VersionOfApi) {
val updatedViewDescription = "aloha"
val updatedAliasToUse = "public"
val allowedActions = List("can_see_images", "can_delete_comment")
def viewUpdateJson(originalView : ViewJsonV500) = {
//it's not perfect, assumes too much about originalView (i.e. randomView(true, ""))
UpdateViewJSON(
description = updatedViewDescription,
metadata_view = originalView.metadata_view,
is_public = originalView.is_public,
is_firehose = Some(true),
which_alias_to_use = updatedAliasToUse,
hide_metadata_if_alias_used = !originalView.hide_metadata_if_alias_used,
allowed_actions = allowedActions,
can_grant_access_to_views = Some(originalView.can_grant_access_to_views),
can_revoke_access_to_views = Some(originalView.can_revoke_access_to_views)
)
}
Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, CanCreateSystemView.toString)
Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, CanUpdateSystemView.toString)
Given("A view exists")
val creationReply = postSystemView(postBodySystemViewJson, user1)
creationReply.code should equal (201)
val createdView : ViewJsonV500 = creationReply.body.extract[ViewJsonV500]
createdView.id should not startWith("_")
createdView.can_see_images should equal(true)
createdView.can_delete_comment should equal(true)
createdView.can_delete_physical_location should equal(true)
createdView.can_edit_owner_comment should equal(true)
createdView.description should not equal(updatedViewDescription)
createdView.hide_metadata_if_alias_used should equal(false)
When("We use a valid access token and valid put json")
val reply = putSystemView(createdView.id, viewUpdateJson(createdView), user1)
Then("We should get back the updated view")
reply.code should equal (200)
val updatedView = reply.body.extract[ViewJsonV500]
updatedView.can_see_images should equal(true)
updatedView.can_delete_comment should equal(true)
updatedView.can_delete_physical_location should equal(false)
updatedView.can_edit_owner_comment should equal(false)
updatedView.description should equal(updatedViewDescription)
updatedView.hide_metadata_if_alias_used should equal(true)
updatedView.is_firehose should equal(Some(true))
}
}
feature(s"test $ApiEndpoint4 version $VersionOfApi - Unauthorized access") {
scenario("We will call the endpoint without user credentials", ApiEndpoint4, VersionOfApi) {
When(s"We make a request $ApiEndpoint4")
val response400 = deleteSystemView("", None)
Then("We should get a 401")
response400.code should equal(401)
response400.body.extract[ErrorMessage].message should equal(UserNotLoggedIn)
}
}
feature(s"test $ApiEndpoint4 version $VersionOfApi - Authorized access") {
scenario("We will call the endpoint without user credentials", ApiEndpoint4, VersionOfApi) {
When(s"We make a request $ApiEndpoint4")
val response400 = deleteSystemView("", user1)
Then("We should get a 403")
response400.code should equal(403)
response400.body.extract[ErrorMessage].message should equal(UserHasMissingRoles + CanDeleteSystemView)
}
}
feature(s"test $ApiEndpoint4 version $VersionOfApi - Authorized access with proper Role") {
scenario("We will call the endpoint without user credentials", ApiEndpoint4, VersionOfApi) {
val viewId = APIUtil.generateUUID()
createSystemView(viewId)
Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, CanDeleteSystemView.toString)
When(s"We make a request $ApiEndpoint4")
val response400 = deleteSystemView(viewId, user1)
Then("We should get a 200")
response400.code should equal(200)
}
}
feature(s"test $ApiEndpoint4 version $VersionOfApi - Authorized access with proper Role in order to delete owner view") {
scenario("We will call the endpoint without user credentials", ApiEndpoint4, VersionOfApi) {
Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, CanDeleteSystemView.toString)
When(s"We make a request $ApiEndpoint4")
AccountAccess.findAll(
By(AccountAccess.view_id, SYSTEM_OWNER_VIEW_ID),
By(AccountAccess.user_fk, resourceUser1.id.get)
).forall(_.delete_!) // Remove all rows assigned to the system owner view in order to delete it
val response400 = deleteSystemView(SYSTEM_OWNER_VIEW_ID, user1)
Then("We should get a 200")
response400.code should equal(200)
}
}
feature(s"test $ApiEndpoint5 version $VersionOfApi - Unauthorized access") {
scenario("We will call the endpoint without user credentials", ApiEndpoint1, VersionOfApi) {
When(s"We make a request $ApiEndpoint5")
val response400 = getSystemViewsIds(None)
Then("We should get a 401")
response400.code should equal(401)
response400.body.extract[ErrorMessage].message should equal(UserNotLoggedIn)
}
}
feature(s"test $ApiEndpoint5 version $VersionOfApi - Authorized access") {
scenario("We will call the endpoint without user credentials", ApiEndpoint1, VersionOfApi) {
When(s"We make a request $ApiEndpoint2")
val response400 = getSystemViewsIds(user1)
Then("We should get a 403")
response400.code should equal(403)
response400.body.extract[ErrorMessage].message should equal(UserHasMissingRoles + CanGetSystemView)
}
}
feature(s"test $ApiEndpoint5 version $VersionOfApi - Authorized access with proper Role") {
scenario("We will call the endpoint without user credentials", ApiEndpoint1, VersionOfApi) {
When(s"We make a request $ApiEndpoint2")
Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, CanGetSystemView.toString)
val response400 = getSystemViewsIds(user1)
Then("We should get a 200")
response400.code should equal(200)
response400.body.extract[ViewsIdsJsonV500]
}
}
}

View File

@ -12,6 +12,7 @@ import code.setup.{APIResponse, DefaultUsers, ServerSetupWithTestData}
import com.openbankproject.commons.util.ApiShortVersions
import dispatch.Req
import code.api.util.APIUtil.OAuth._
import code.api.v2_0_0.BasicAccountsJSON
import net.liftweb.json.Serialization.write
import scala.util.Random.nextInt
@ -33,6 +34,16 @@ trait V500ServerSetup extends ServerSetupWithTestData with DefaultUsers {
bank.id
}
def getPrivateAccounts(bankId : String, consumerAndToken: Option[(Consumer, Token)]) : APIResponse = {
val request = v5_0_0_Request / "banks" / bankId / "accounts" / "private" <@(consumerAndToken) //TODO, how can we know which endpoint it called? Although it is V300, but this endpoint called V200-privateAccountsAtOneBank
makeGetRequest(request)
}
def randomPrivateAccountId(bankId : String) : String = {
val accountsJson = getPrivateAccounts(bankId, user1).body.extract[BasicAccountsJSON].accounts //TODO, how to make this map automatically.
val randomPosition = nextInt(accountsJson.size)
accountsJson(randomPosition).id
}
// This will call create customer ,then return the customerId
def createAndGetCustomerIdViaEndpoint(bankId:String, consumerAndToken: Option[(Consumer, Token)]) = {
val postCustomerJson = SwaggerDefinitionsJSON.postCustomerJsonV310

View File

@ -0,0 +1,93 @@
/**
Open Bank Project - API
Copyright (C) 2011-2019, TESOBE GmbH.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Email: contact@tesobe.com
TESOBE GmbH.
Osloer Strasse 16/17
Berlin 13359, Germany
This product includes software developed at
TESOBE (http://www.tesobe.com/)
*/
package code.api.v5_0_0
import code.api.Constant._
import code.api.ResourceDocs1_4_0.SwaggerDefinitionsJSON._
import code.api.util.APIUtil.OAuth._
import code.api.v1_2_1.{PermissionJSON, PermissionsJSON}
import code.api.v3_0_0.OBPAPI3_0_0.Implementations3_0_0
import code.setup.APIResponse
import com.github.dwickern.macros.NameOf.nameOf
import com.openbankproject.commons.util.ApiVersion
import org.scalatest.Tag
import scala.util.Random.nextInt
class ViewsTests extends V500ServerSetup {
object VersionOfApi extends Tag(ApiVersion.v5_0_0.toString)
object ApiEndpoint1 extends Tag(nameOf(Implementations3_0_0.getPermissionForUserForBankAccount))
//Custom view, name starts from `_`
val postBodyViewJson = createViewJsonV300
//System view, owner
val postBodySystemViewJson = createViewJsonV300.copy(name=SYSTEM_OWNER_VIEW_ID).copy(metadata_view = SYSTEM_OWNER_VIEW_ID)
def getAccountAccessForUser(bankId: String, accountId: String, provider : String, providerId : String, consumerAndToken: Option[(Consumer, Token)]): APIResponse = {
val request = (v5_0_0_Request / "banks" / bankId / "accounts" / accountId / "permissions" / provider / providerId).GET <@(consumerAndToken)
makeGetRequest(request)
}
//This will call v1_2_1Request and we need it here to prepare the data for further tests
//BK need to check this endpoint....
def getAccountPermissions(bankId : String, accountId : String, consumerAndToken: Option[(Consumer, Token)]): APIResponse = {
val request = v5_0_0_Request / "banks" / bankId / "accounts" / accountId / "permissions" <@(consumerAndToken)
makeGetRequest(request)
}
//This is a helper method, used to prepare the test parameters
def randomAccountPermission(bankId : String, accountId : String) : PermissionJSON = {
val persmissionsInfo = getAccountPermissions(bankId, accountId, user1).body.extract[PermissionsJSON]
val randomPermission = nextInt(persmissionsInfo.permissions.size)
persmissionsInfo.permissions(randomPermission)
}
feature(s"$ApiEndpoint1 - Get Account access for User. - $VersionOfApi") {
scenario("we will Get Account access for User.") {
Given("Prepare all the parameters:")
val bankId = randomBankId
val bankAccountId = randomPrivateAccountId(bankId)
val provider = defaultProvider
val permission = randomAccountPermission(bankId, bankAccountId)
val providerId = permission.user.id
When("We use a valid access token and valid put json")
val reply = getAccountAccessForUser(bankId, bankAccountId, provider, providerId, user1)
Then("We should get back the updated view")
reply.code should equal(200)
val response = reply.body.extract[ViewsJsonV500]
response.views.length should not equal (0)
//Note: as to new system view stuff, now the default account should both have some system view accesses and custom view accesses.
response.views.filter(_.is_system).length > 0 should be (true)
response.views.filter(!_.is_system).length > 0 should be (true)
}
}
}

View File

@ -393,16 +393,19 @@ case class FirehoseAccountUser(
displayName : String
)
case class FastFirehoseOwners(user_id: String, provider: String, user_name: String)
case class FastFirehoseRoutings(bank_id: String, account_id: String)
case class FastFirehoseAttributes(`type`: String, code: String, value: String)
case class FastFirehoseAccount(
id: String,
bankId: String,
label: String,
number: String,
owners: String,
owners: List[FastFirehoseOwners],
productCode: String,
balance: AmountOfMoney,
accountRoutings: String,
accountAttributes: String
accountRoutings: List[FastFirehoseRoutings],
accountAttributes: List[FastFirehoseAttributes],
)
case class FastFirehoseAccounts(

View File

@ -69,6 +69,7 @@ trait User {
def isConsentUser = createdByConsentId.nonEmpty
def isDeleted: Option[Boolean]
def lastMarketingAgreementSignedDate: Option[Date]
def lastUsedLocale: Option[String] = None
}
case class UserPrimaryKey(val value : Long) {

View File

@ -52,6 +52,8 @@ trait ViewSpecification {
def which_alias_to_use: String
def hide_metadata_if_alias_used: Boolean
def allowed_actions : List[String]
def can_grant_access_to_views : Option[List[String]] = None
def can_revoke_access_to_views : Option[List[String]] = None
}
/*
@ -64,7 +66,9 @@ case class CreateViewJson(
is_public: Boolean,
which_alias_to_use: String,
hide_metadata_if_alias_used: Boolean,
allowed_actions : List[String]
allowed_actions : List[String],
override val can_grant_access_to_views : Option[List[String]] = None,
override val can_revoke_access_to_views : Option[List[String]] = None
) extends ViewSpecification
@ -78,7 +82,9 @@ case class UpdateViewJSON(
override val is_firehose: Option[Boolean] = None,
which_alias_to_use: String,
hide_metadata_if_alias_used: Boolean,
allowed_actions: List[String]) extends ViewSpecification
allowed_actions: List[String],
override val can_grant_access_to_views : Option[List[String]] = None,
override val can_revoke_access_to_views : Option[List[String]] = None) extends ViewSpecification
@ -245,6 +251,10 @@ trait View {
def hideOtherAccountMetadataIfAlias: Boolean
// Introduced in version 5.0.0
def canGrantAccessToViews : Option[List[String]] = None
def canRevokeAccessToViews : Option[List[String]] = None
//reading access
//transaction fields