Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
99 commits
Select commit Hold shift + click to select a range
9d17eab
feat: delete account holders in the account and bank cascades
hongwei1 Nov 3, 2026
4e3d8a9
feat: delete consent challenges once they can no longer be used
hongwei1 Nov 3, 2026
2eead28
feat(props): add allow_cascade_delete, default false
hongwei1 Nov 3, 2026
b6de837
feat(v4.0.0): register cascade-delete endpoints only when allow_casca…
hongwei1 Nov 3, 2026
6a44492
feat(deletion): cascade account deletion to the challenges of consent…
hongwei1 Nov 3, 2026
7263721
test: name the repeated cascade step once in DeleteAccountCascadeTest
hongwei1 Nov 3, 2026
5affdc1
test: give the new cascade holder steps their own descriptions
hongwei1 Nov 3, 2026
351ae70
Merge branch 'feature/remove-spent-consent-challenges' into develop
hongwei1 Nov 3, 2026
fe72dd1
Merge branch 'feature/cascade-delete-account-holders' into develop
hongwei1 Nov 3, 2026
3630852
fix(deletion): find the consent challenges to cascade through the cha…
hongwei1 Nov 3, 2026
32b4756
Merge branch 'feature/cascade-delete-consent-challenges' into develop
hongwei1 Nov 3, 2026
17eca47
test: enable allow_cascade_delete for tests and run the disabled case…
hongwei1 Nov 3, 2026
5492a72
test: cover cascade-delete endpoints with allow_cascade_delete on and…
hongwei1 Nov 3, 2026
fcb54d7
docs: note allow_cascade_delete in the glossary and release notes
hongwei1 Nov 3, 2026
dab43ef
refactor: limit allow_cascade_delete to the /management/cascading end…
hongwei1 Nov 3, 2026
3992ccc
feat(consent): let the PSU refuse a consent it has not authorised wit…
hongwei1 Nov 3, 2026
0664ffa
Merge branch 'feature/reject-consent-without-sca' into develop
hongwei1 Nov 3, 2026
323d0be
chore(resource-docs): allowlist the refusal sentence in updateConsent…
hongwei1 Nov 3, 2026
79c2c86
Merge remote-tracking branch 'Hongwei/feature/reject-consent-without-…
hongwei1 Nov 3, 2026
d1e7230
test: check the cascade-delete route chain and every version prefix
hongwei1 Nov 3, 2026
de6a1b6
refactor(v4.0.0): gate cascade-delete docs and routes from one route set
hongwei1 Nov 3, 2026
3035bae
docs(props): note the Resource Docs cache next to allow_cascade_delete
hongwei1 Nov 3, 2026
0e1ea92
test: check whether the cascade-delete roles are offered
hongwei1 Nov 3, 2026
884a0b6
feat: stop offering the cascade-delete roles while allow_cascade_dele…
hongwei1 Nov 3, 2026
139b026
Merge pull request #108 from hongwei1/feature/allow-cascade-delete-prop
hongwei1 Nov 3, 2026
1fb881f
fix(deps): update http4s to 0.23.35 and BouncyCastle to 1.85
hongwei1 Nov 3, 2026
32f6c6a
test: cover the Berlin Group payment initiation view and scaRedirect …
hongwei1 Nov 3, 2026
4b75a47
fix: grant InitiatePaymentsBerlinGroup to account holders and build s…
hongwei1 Nov 3, 2026
ae9d210
fix: treat a blank scaRedirect URL as unset and document the view and…
hongwei1 Nov 3, 2026
9227aa7
test: cover deleting card attributes with the card, the account casca…
hongwei1 Nov 3, 2026
62655bc
fix: delete a card's attributes with the card and add Delete Card Att…
hongwei1 Nov 3, 2026
91acf88
fix: delete card attributes by bank and answer 404 for an unknown att…
hongwei1 Nov 3, 2026
699e90c
test: cover where the passcode of an EMAIL or SMS challenge goes
hongwei1 Nov 3, 2026
3724208
test: cover the bank cascade deleting the bank's dynamic entities and…
hongwei1 Nov 3, 2026
41d80b0
fix: send challenge passcodes to the user when no customer is linked,…
hongwei1 Nov 3, 2026
bfe7bb6
fix: delete a bank's dynamic entities, records and access rows with t…
hongwei1 Nov 3, 2026
c46a12b
fix: send an EMAIL passcode before saving its challenge and cover the…
hongwei1 Nov 3, 2026
a59da90
test: cover a rate limit's to_date and the scope fields that are not …
hongwei1 Nov 3, 2026
e2d9fc3
fix: require an id when the bank cascade deletes dynamic entities and…
hongwei1 Nov 3, 2026
b4d3dc4
fix: hold a rate limit to its exact dates and refuse the scope fields…
hongwei1 Nov 3, 2026
d73d01b
chore: review the rate limit ResourceDoc differences in the parity al…
hongwei1 Nov 3, 2026
28b46f9
test: give the tests that start an SCA a method the user can be reach…
hongwei1 Nov 4, 2026
b825eba
Merge pull request #111 from hongwei1/fix/bg-payment-view-and-redirect
hongwei1 Nov 4, 2026
8136ae8
Merge pull request #113 from hongwei1/fix/card-attribute-delete
hongwei1 Nov 4, 2026
c77ed11
Merge pull request #109 from hongwei1/fix/http4s-bouncycastle-cves
hongwei1 Nov 4, 2026
54d062e
test: cover a failed passcode send, an unconfirmed own address and th…
hongwei1 Nov 4, 2026
b99da00
fix: save a passcode challenge only once it has been sent, and fail t…
hongwei1 Nov 4, 2026
d58c8aa
test: accept the documented rate limit example and empty scope fields…
hongwei1 Nov 4, 2026
3e39c03
fix: accept the documented rate limit example and treat an empty scop…
hongwei1 Nov 4, 2026
d346309
test: cover the bank cascade deleting records whose definition is alr…
hongwei1 Nov 4, 2026
d22c383
fix: delete the bank's records that have no definition left, and say …
hongwei1 Nov 4, 2026
c055ab2
test: cover several signers of whom one cannot be reached, a shared a…
hongwei1 Nov 4, 2026
0b111e2
fix: keep the challenges of the signers who can be reached and requir…
hongwei1 Nov 4, 2026
a3b4acb
test: keep a subscription's bank_id across an update, and read the re…
hongwei1 Nov 4, 2026
f0a0257
test: keep the system space when the bank cascade deletes a bank whos…
hongwei1 Nov 4, 2026
a45c318
fix: keep a subscription's bank_id when its rate limit is updated, an…
hongwei1 Nov 4, 2026
49ca7bb
refactor: move the boot reconciliation of the opt-in system views int…
hongwei1 Nov 4, 2026
07417b9
test: cover the payment initiation view on held accounts and the opt-…
hongwei1 Nov 4, 2026
32764d7
test: cover Delete Card Attribute across banks and through the routed…
hongwei1 Nov 4, 2026
b800faa
fix: leave the system space alone when the cascaded bank's id is its …
hongwei1 Nov 4, 2026
07764da
test: tell too few users who may answer apart from a missing address
hongwei1 Nov 4, 2026
8525c53
fix: grant the payment initiation view on held accounts also when acc…
hongwei1 Nov 4, 2026
11c32cc
fix: delete a card attribute through the connector
hongwei1 Nov 4, 2026
c55e161
fix: answer OBP-35060 when fewer users may answer than the account re…
hongwei1 Nov 4, 2026
0b67997
test: say which hour the assume keeps to_date in
hongwei1 Nov 4, 2026
a80442a
test: check the SYS bank itself is deleted
hongwei1 Nov 4, 2026
6d2d84b
test: keep a holder's other views when an account is opened, and hono…
hongwei1 Nov 4, 2026
a0d901f
fix: only add views on held accounts when accounts change, and respec…
hongwei1 Nov 4, 2026
fd99d40
fix: report a connector that cannot delete a card attribute as the ot…
hongwei1 Nov 4, 2026
e384f6e
docs: say which refresh still takes away the views the connector does…
hongwei1 Nov 4, 2026
6d1209d
Merge remote-tracking branch 'Hongwei/develop' into fix/challenge-rec…
hongwei1 Nov 4, 2026
5eedcd6
test: cover cascading deletes that fail part way
hongwei1 Nov 4, 2026
c6f60e9
fix: roll a cascading delete back to a savepoint when it fails
hongwei1 Nov 4, 2026
4fabc1b
refactor: run the cascade savepoint through DeletionUtil.withSavepoint
hongwei1 Nov 4, 2026
3069747
test: cover the cascade savepoint on its own and through the request …
hongwei1 Nov 4, 2026
38748d4
fix: do not fail a cascade on a database that cannot release a savepoint
hongwei1 Nov 4, 2026
f33dfcd
test: say which databases the foreign key scenario tells apart
hongwei1 Nov 4, 2026
898a473
test: check the savepoint itself reaches the real connection, and a s…
hongwei1 Nov 4, 2026
f638fa4
test: cover the v3.1.0 and v4.0.0 Set Rate Limits next to v6.0.0 rate…
hongwei1 Nov 4, 2026
ae6d33b
fix: refuse the legacy Set Rate Limits for a consumer with several ra…
hongwei1 Nov 4, 2026
13c8c9e
test: change a legacy rate limit stored with empty scope fields
hongwei1 Nov 4, 2026
1e69c82
fix: recognise a legacy rate limit stored with empty scope fields
hongwei1 Nov 4, 2026
aa514c0
test: cancel the per-second scenarios when the first call is too slow…
hongwei1 Nov 4, 2026
8aa64db
fix(cards): declare CanDeleteCardsForBank on the delete card resource…
hongwei1 Nov 4, 2026
c7dca73
test: set the v3.1.0 call limits from another consumer through one he…
hongwei1 Nov 4, 2026
2675f1a
Merge pull request #119 from hongwei1/fix/rate-limit-to-date-and-scope
hongwei1 Nov 4, 2026
4c69758
Merge pull request #117 from hongwei1/fix/bank-cascade-dynamic-entities
hongwei1 Nov 4, 2026
0e7c41f
Merge pull request #122 from hongwei1/fix/cascade-delete-atomic
hongwei1 Nov 4, 2026
0a33db3
fix(abac): answer rejected rule code with the error validate reports
hongwei1 Nov 4, 2026
90c1c41
test: run the v3.1.0 call limit scenarios for the longer periods from…
hongwei1 Nov 4, 2026
7c712fa
Merge remote-tracking branch 'Hongwei/develop' into fix/legacy-call-l…
hongwei1 Nov 4, 2026
01eb24c
Merge pull request #116 from hongwei1/fix/challenge-recipient-fallback
hongwei1 Nov 4, 2026
a239684
Merge pull request #120 from hongwei1/fix/card-attribute-delete-conne…
hongwei1 Nov 4, 2026
bc8a254
Merge pull request #121 from hongwei1/fix/bg-payment-view-refresh
hongwei1 Nov 4, 2026
502552b
Merge pull request #124 from hongwei1/fix/delete-card-doc-role
hongwei1 Nov 4, 2026
e3fba37
Merge pull request #125 from hongwei1/fix/legacy-call-limits-put
hongwei1 Nov 4, 2026
bbfa120
test: assert the error each invalid ABAC rule code is classified as
hongwei1 Nov 4, 2026
b0ce6da
Merge pull request #127 from hongwei1/fix/abac-rule-error-codes
hongwei1 Nov 4, 2026
dc4fc6a
Merge remote-tracking branch 'origin/develop' into develop
hongwei1 Nov 6, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion .github/workflows/build_container.yml
Original file line number Diff line number Diff line change
Expand Up @@ -240,17 +240,20 @@ jobs:
test_filter: >-
code.api.v4_0_0.Dynamic
- shard: 10
name: "PropGatedPublicEndpoint (read_*_requires_role=true)"
name: "PropGatedPublicEndpoint (read_*_requires_role=true, allow_cascade_delete=false)"
# JsonSchemaValidationPublicPropTrueTest / AuthenticationTypeValidationPublicPropTrueTest
# need read_json_schema_validation_requires_role /
# read_authentication_type_validation_requires_role forced true, which is baked into
# Http4s400's ResourceDoc error list at object-init time -- a value only one JVM can
# observe. Every other shard boots with these props unset (false, the default) and
# the pom.xml default tagsToExclude skips this tag there. This shard is the only place
# the true branch is exercised; see the "Run tests" step's shard-10 special case below.
# CascadeDeleteDisabledTest is here for the opposite reason: every other shard has
# allow_cascade_delete=true, and only this JVM starts with it false.
test_filter: >-
code.api.v4_0_0.JsonSchemaValidationPublicPropTrueTest
code.api.v4_0_0.AuthenticationTypeValidationPublicPropTrueTest
code.api.v4_0_0.CascadeDeleteDisabledTest

services:
redis:
Expand Down Expand Up @@ -341,6 +344,7 @@ jobs:
echo allow_sandbox_data_import=true >> obp-api/src/main/resources/props/test.default.props
echo sandbox_data_import_secret=change_me >> obp-api/src/main/resources/props/test.default.props
echo allow_account_deletion=true >> obp-api/src/main/resources/props/test.default.props
echo allow_cascade_delete=true >> obp-api/src/main/resources/props/test.default.props
echo allowed_internal_redirect_urls = /,/oauth/authorize >> obp-api/src/main/resources/props/test.default.props
echo transactionRequests_enabled=true >> obp-api/src/main/resources/props/test.default.props
echo transactionRequests_supported_types=SEPA,SANDBOX_TAN,FREE_FORM,COUNTERPARTY,ACCOUNT,SIMPLE >> obp-api/src/main/resources/props/test.default.props
Expand Down Expand Up @@ -449,6 +453,8 @@ jobs:
if [ "${{ matrix.shard }}" = "10" ]; then
export OBP_READ_JSON_SCHEMA_VALIDATION_REQUIRES_ROLE="true"
export OBP_READ_AUTHENTICATION_TYPE_VALIDATION_REQUIRES_ROLE="true"
# The cascade-delete routes are fixed when the API objects initialise; off here only.
export OBP_ALLOW_CASCADE_DELETE="false"
EXTRA_MVN_ARGS="-DtagsToInclude=PropGatedPublicEndpoint -Dtest.tagsToExclude="
fi

Expand Down
8 changes: 7 additions & 1 deletion .github/workflows/build_pull_request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -234,17 +234,20 @@ jobs:
test_filter: >-
code.api.v4_0_0.Dynamic
- shard: 10
name: "PropGatedPublicEndpoint (read_*_requires_role=true)"
name: "PropGatedPublicEndpoint (read_*_requires_role=true, allow_cascade_delete=false)"
# JsonSchemaValidationPublicPropTrueTest / AuthenticationTypeValidationPublicPropTrueTest
# need read_json_schema_validation_requires_role /
# read_authentication_type_validation_requires_role forced true, which is baked into
# Http4s400's ResourceDoc error list at object-init time -- a value only one JVM can
# observe. Every other shard boots with these props unset (false, the default) and
# the pom.xml default tagsToExclude skips this tag there. This shard is the only place
# the true branch is exercised; see the "Run tests" step's shard-10 special case below.
# CascadeDeleteDisabledTest is here for the opposite reason: every other shard has
# allow_cascade_delete=true, and only this JVM starts with it false.
test_filter: >-
code.api.v4_0_0.JsonSchemaValidationPublicPropTrueTest
code.api.v4_0_0.AuthenticationTypeValidationPublicPropTrueTest
code.api.v4_0_0.CascadeDeleteDisabledTest

services:
redis:
Expand Down Expand Up @@ -335,6 +338,7 @@ jobs:
echo allow_sandbox_data_import=true >> obp-api/src/main/resources/props/test.default.props
echo sandbox_data_import_secret=change_me >> obp-api/src/main/resources/props/test.default.props
echo allow_account_deletion=true >> obp-api/src/main/resources/props/test.default.props
echo allow_cascade_delete=true >> obp-api/src/main/resources/props/test.default.props
echo allowed_internal_redirect_urls = /,/oauth/authorize >> obp-api/src/main/resources/props/test.default.props
echo transactionRequests_enabled=true >> obp-api/src/main/resources/props/test.default.props
echo transactionRequests_supported_types=SEPA,SANDBOX_TAN,FREE_FORM,COUNTERPARTY,ACCOUNT,SIMPLE >> obp-api/src/main/resources/props/test.default.props
Expand Down Expand Up @@ -453,6 +457,8 @@ jobs:
if [ "${{ matrix.shard }}" = "10" ]; then
export OBP_READ_JSON_SCHEMA_VALIDATION_REQUIRES_ROLE="true"
export OBP_READ_AUTHENTICATION_TYPE_VALIDATION_REQUIRES_ROLE="true"
# The cascade-delete routes are fixed when the API objects initialise; off here only.
export OBP_ALLOW_CASCADE_DELETE="false"
EXTRA_MVN_ARGS="-DtagsToInclude=PropGatedPublicEndpoint -Dtest.tagsToExclude="
fi

Expand Down
4 changes: 2 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -295,9 +295,9 @@ Shards are defined per-matrix-entry in `.github/workflows/build_pull_request.yml
| `code.connector`, `code.util`, `code.api.Authentication*`, `code.api.dauthTest`, `code.api.DirectLoginTest`, `code.api.gateWayloginTest`, `code.api.OBPRestHelperTest`, `code.entitlement`, `code.bankaccountcreation`, `code.bankconnectors`, `code.container`, `code.management`, `code.metrics`, `code.concurrency` | 8 |
| anything else | **8** (catch-all) |
| `code.api.v4_0_0.Dynamic*` | 9 |
| `code.api.v4_0_0.JsonSchemaValidationPublicPropTrueTest`, `code.api.v4_0_0.AuthenticationTypeValidationPublicPropTrueTest` (tagged `PropGatedPublicEndpoint`) | 10 |
| `code.api.v4_0_0.JsonSchemaValidationPublicPropTrueTest`, `code.api.v4_0_0.AuthenticationTypeValidationPublicPropTrueTest`, `code.api.v4_0_0.CascadeDeleteDisabledTest` (tagged `PropGatedPublicEndpoint`) | 10 |

Shard 10 is a special case: it's the only shard that overrides pom.xml's default `tagsToExclude` (which otherwise skips `PropGatedPublicEndpoint` everywhere) and sets `OBP_READ_JSON_SCHEMA_VALIDATION_REQUIRES_ROLE`/`OBP_READ_AUTHENTICATION_TYPE_VALIDATION_REQUIRES_ROLE=true`, because those two props are baked into `Http4s400`'s `ResourceDoc` error lists at object-init time — a single JVM can only ever observe one value of each, so the `true` branch needs its own shard while every other shard (which boots with the props unset, i.e. `false`) exercises the default branch. `run_tests_parallel.sh` (local runner) mirrors this with a dedicated sequential step after its 4 main shards — see that script's own comment near `PropGatedPublicEndpoint`.
Shard 10 is a special case: it's the only shard that overrides pom.xml's default `tagsToExclude` (which otherwise skips `PropGatedPublicEndpoint` everywhere) and sets `OBP_READ_JSON_SCHEMA_VALIDATION_REQUIRES_ROLE`/`OBP_READ_AUTHENTICATION_TYPE_VALIDATION_REQUIRES_ROLE=true`, because those two props are baked into `Http4s400`'s `ResourceDoc` error lists at object-init time — a single JVM can only ever observe one value of each, so the `true` branch needs its own shard while every other shard (which boots with the props unset, i.e. `false`) exercises the default branch. Shard 10 also sets `OBP_ALLOW_CASCADE_DELETE=false` for `CascadeDeleteDisabledTest`: every other shard runs with `allow_cascade_delete=true`, and the cascade-delete routes are likewise fixed at object-init time. `run_tests_parallel.sh` (local runner) mirrors this with a dedicated sequential step after its 4 main shards — see that script's own comment near `PropGatedPublicEndpoint`.

To explicitly move a package to a different shard, add it to that shard's `test_filter` block — it will be excluded from the catch-all automatically. `run_tests_parallel.sh` (local runner) uses a coarser 4-shard layout that folds all 9 CI shards' coverage into 4 wildcardSuites groups — see its own header comment for the mapping.

Expand Down
8 changes: 5 additions & 3 deletions obp-api/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpg-jdk18on</artifactId>
<version>1.84</version>
<version>1.85</version>
</dependency>
<dependency>
<groupId>org.http4s</groupId>
Expand All @@ -75,7 +75,7 @@
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk18on</artifactId>
<version>1.84</version>
<version>1.85</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
<dependency>
Expand Down Expand Up @@ -633,7 +633,9 @@
observe. Excluded here by default (every ordinary shard/local/IDE run boots with
the props unset, i.e. false) and run separately with -Dtest.tagsToExclude=
-DtagsToInclude=PropGatedPublicEndpoint plus the two OBP_READ_*_REQUIRES_ROLE
env vars set true (see run_tests_parallel.sh and the CI job that runs them);
env vars set true (see run_tests_parallel.sh and the CI job that runs them).
CascadeDeleteDisabledTest shares the tag and runs there with
OBP_ALLOW_CASCADE_DELETE=false;
see the ${test.tagsToExclude} property declared above for why this is not a
plain literal. -->
<tagsToExclude>${test.tagsToExclude}</tagsToExclude>
Expand Down
15 changes: 15 additions & 0 deletions obp-api/src/main/resources/props/sample.props.template
Original file line number Diff line number Diff line change
Expand Up @@ -639,6 +639,20 @@ messageQueue.createBankAccounts=true
## Set this to true if you want to allow users to delete accounts (local ones like HBCI connected)
allow_account_deletion=true

## Cascade-delete endpoints: each deletes a bank object together with everything stored under it.
## DELETE /obp/v4.0.0/management/cascading/banks/BANK_ID
## DELETE /obp/v4.0.0/management/cascading/banks/BANK_ID/accounts/ACCOUNT_ID
## DELETE /obp/v4.0.0/management/cascading/banks/BANK_ID/accounts/ACCOUNT_ID/transactions/TRANSACTION_ID
## DELETE /obp/v4.0.0/management/cascading/banks/BANK_ID/products/PRODUCT_CODE
## DELETE /obp/v4.0.0/management/cascading/banks/BANK_ID/customers/CUSTOMER_ID
## When false (the default) they are not routed and not listed in the Resource Docs of any version,
## so a request gets 404. Set to true to make them available. Read at startup. The Dynamic Entity
## cascade deletes (.../dynamic-entities/cascade/DYNAMIC_ENTITY_ID) are not affected.
## The Resource Docs responses are cached in Redis (staticResourceDocsObp.cache.ttl.seconds), so after a
## change and restart they can list the old set of endpoints until that TTL passes, or until the rd_static
## and rd_all cache namespaces are invalidated (POST /obp/v6.0.0/management/cache/namespaces/invalidate).
allow_cascade_delete=false

## Secret key that allows access to api calls to get info about oauth tokens. You should change this
## to your own secret key
BankMockKey=change_me
Expand Down Expand Up @@ -1237,6 +1251,7 @@ display_internal_errors=false
# Please note that in case that redirect_url_value contains special word PLACEHOLDER it will be replaced with actual ID
# http://127.0.0.1:8080/confirm-bg-consent-request?PAYMENT_ID=PLACEHOLDER
# psu_make_payment_sca_redirect_url = redirect_url_value
# When it is not set (or blank), the response to a payment initiation has no scaRedirect link.
# -------------------------------------------------------------- Authentication methods --

## This property is used for documenting at Resource Doc. It may include the port also (but not /obp)
Expand Down
3 changes: 3 additions & 0 deletions obp-api/src/main/resources/props/test.default.props.template
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,9 @@ sandbox_data_import_secret=change_me

#set this to true if you want to allow users to delete accounts
allow_account_deletion=true
# The cascade-delete endpoints are off by default; Delete*CascadeTest and DeleteCascadeCounterpartiesTest
# need them. CascadeDeleteDisabledTest runs with them off.
allow_cascade_delete=true

# This needs to be a list all the types of transaction_requests that we have tests for. Else those tests will fail
transactionRequests_supported_types=SANDBOX_TAN,COUNTERPARTY,SEPA,ACCOUNT_OTP,ACCOUNT,SIMPLE,AGENT_CASH_WITHDRAWAL,CARD
Expand Down
24 changes: 6 additions & 18 deletions obp-api/src/main/scala/bootstrap/liftweb/Boot.scala
Original file line number Diff line number Diff line change
Expand Up @@ -384,24 +384,12 @@ class Boot extends MdcLoggable {
}

// The remaining two stay opt-in: nothing in the code requires them to exist, so whether an
// instance has them is still the operator's call. Their permission sets ARE code-defined
// though, so where they do exist they are kept current the same way -- the prop decides
// existence, not whether the code is authoritative about what a view grants.
APIUtil.getPropsValue("additional_system_views") match {
case Full(value) =>
val additionalSystemViewsFromProps = value.split(",").map(_.trim).toList
val additionalSystemViews = List(
SYSTEM_READ_TRANSACTIONS_BERLIN_GROUP_VIEW_ID,
SYSTEM_INITIATE_PAYMENTS_BERLIN_GROUP_VIEW_ID
)
for {
systemView <- additionalSystemViewsFromProps
if additionalSystemViews.exists(_ == systemView)
} {
Views.views.vend.ensureSystemViewUpToDate(systemView)
}
case _ => // Do nothing
}
// instance has them is still the operator's call. (The mapped connector is the exception: it lists
// both in viewsToGenerate, so a refresh creates them and grants them to the holders of their accounts
// whether or not they are listed here.) Their permission sets ARE code-defined though, so wherever they
// exist, listed or not, they are kept current the same way, unless reconcile_permissions_at_boot is false --
// the prop decides existence, not whether the code is authoritative about what a view grants.
Views.views.vend.ensureOptInSystemViewsUpToDate(APIUtil.getPropsValue("additional_system_views"))

}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4310,8 +4310,8 @@ object SwaggerDefinitionsJSON {
lazy val callLimitPostJsonV600 = CallLimitPostJsonV600(
from_date = DateWithDayExampleObject,
to_date = DateWithDayExampleObject,
api_version = Some(ApiVersion.v6_0_0.toString),
api_name = Some("getConsumerCallLimits"),
api_version = None,
api_name = None,
bank_id = None,
per_second_call_limit = "100",
per_minute_call_limit = "1000",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ object JSONFactory_BERLIN_GROUP_1_3 extends CustomJsonFormats with MdcLoggable{
)

case class InitiatePaymentResponseLinks(
scaRedirect: LinkHrefJson,
scaRedirect: Option[LinkHrefJson],
self: LinkHrefJson,
status: LinkHrefJson,
scaStatus: LinkHrefJson
Expand Down Expand Up @@ -801,18 +801,18 @@ object JSONFactory_BERLIN_GROUP_1_3 extends CustomJsonFormats with MdcLoggable{
// Remark: This code may be
//map OBP transactionRequestId to BerlinGroup PaymentId
val paymentId = transactionRequest.id.value
val scaRedirectUrlPattern = getPropsValue("psu_make_payment_sca_redirect_url")
.openOr(MissingPropsValueAtThisInstance + "psu_make_payment_sca_redirect_url")
val scaRedirectUrl =
if (scaRedirectUrlPattern.contains("PLACEHOLDER"))
scaRedirectUrlPattern.replace("PLACEHOLDER", paymentId)
// Without psu_make_payment_sca_redirect_url there is no page to send the PSU to, so the link is left out.
val scaRedirectUrl = getPropsValue("psu_make_payment_sca_redirect_url").toOption.filter(_.trim.nonEmpty).map { pattern =>
if (pattern.contains("PLACEHOLDER"))
pattern.replace("PLACEHOLDER", paymentId)
else
s"$scaRedirectUrlPattern/${paymentId}"
s"$pattern/$paymentId"
}
InitiatePaymentResponseJson(
transactionStatus = mapTransactionStatus(transactionRequest.status),
paymentId = paymentId,
_links = InitiatePaymentResponseLinks(
scaRedirect = LinkHrefJson(s"$scaRedirectUrl/$paymentId"),
scaRedirect = scaRedirectUrl.map(LinkHrefJson(_)),
self = LinkHrefJson(s"/${ConstantsBG.berlinGroupVersion1.apiShortVersion}/payments/sepa-credit-transfers/$paymentId"),
status = LinkHrefJson(s"/${ConstantsBG.berlinGroupVersion1.apiShortVersion}/payments/$paymentId/status"),
scaStatus = LinkHrefJson(s"/${ConstantsBG.berlinGroupVersion1.apiShortVersion}/payments/$paymentId/authorisations/${paymentId}")
Expand Down
7 changes: 7 additions & 0 deletions obp-api/src/main/scala/code/api/util/APIUtil.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2655,6 +2655,13 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{

def getDisabledEndpointOperationIds() : List[String] = APIUtil.getPropsValue("api_disabled_endpoints").getOrElse("").replace("[", "").replace("]", "").split(",").toList.filter(_.nonEmpty)

/**
* allow_cascade_delete (default false). The v4.0.0 /management/cascading/... endpoints are
* routed and documented only when this is true. It is read when the API version objects are
* initialised, so a change takes effect on restart. The Dynamic Entity cascade deletes, which
* back up to a ZZ_BAK_ entity first, are not affected.
*/
def cascadeDeleteEnabled: Boolean = getPropsAsBoolValue("allow_cascade_delete", false)


def getEnabledVersions() : List[String] = APIUtil.getPropsValue("api_enabled_versions").getOrElse("").replace("[", "").replace("]", "").split(",").toList.filter(_.nonEmpty).map(_.trim)
Expand Down
14 changes: 13 additions & 1 deletion obp-api/src/main/scala/code/api/util/ApiRole.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1690,10 +1690,22 @@ object ApiRole extends MdcLoggable{
}
}

// Checked only by the /management/cascading endpoints, so not offered while allow_cascade_delete=false
// leaves those endpoints out. valueOf still resolves them, for entitlements granted earlier.
private lazy val cascadeDeleteRoleNames: Set[String] = Set[ApiRole](
canDeleteTransactionCascade,
canDeleteAccountCascade,
canDeleteBankCascade,
canDeleteProductCascade,
canDeleteCustomerCascade
).map(_.toString)
private lazy val offeredRoleNames: List[String] =
roles.map(_.toString).filter(name => APIUtil.cascadeDeleteEnabled || !cascadeDeleteRoleNames.contains(name))

def availableRoles: List[String] = {
import scala.jdk.CollectionConverters._
val dynamicRoles = dynamicApiRoles.keys().asScala.toList
dynamicRoles ::: roles.map(_.toString)
dynamicRoles ::: offeredRoleNames
}

}
Expand Down
29 changes: 29 additions & 0 deletions obp-api/src/main/scala/code/api/util/ConsentUtil.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1057,6 +1057,35 @@ object Consent extends MdcLoggable {
consentJwtBox.foreach(releaseVrpMandateArtefacts(consent, _))
}

/**
* The consent statuses after which an SCA challenge raised for the consent can no longer be used:
* a REVOKED consent is re-authenticated with a fresh challenge, and REJECTED and EXPIRED are terminal.
*/
val consentChallengeEndingStatuses: Set[ConsentStatus] =
Set(ConsentStatus.REVOKED, ConsentStatus.REJECTED, ConsentStatus.EXPIRED)

/**
* Delete the OBP_CONSENT_CHALLENGE rows of a consent once none of them can be used any more: when
* one has been answered correctly, or when the consent reaches one of consentChallengeEndingStatuses.
*
* Nothing reads these rows after the answer -- the attempt counter only matters while a challenge
* is still open -- so the row is not an audit trail, it is a hashed one-time password waiting to
* be swept. Berlin Group consent challenges are left alone (their authorisation endpoints keep
* listing them), and so are transaction request challenges.
*
* Never fails the caller: by the time this runs the answer or the status change has happened, and
* a row left behind is logged rather than turned into an error for something that succeeded.
*/
def removeConsentChallenges(consentId: String): Unit =
code.transactionChallenge.Challenges.ChallengeProvider.vend
.deleteChallengesByConsentId(consentId, com.openbankproject.commons.model.enums.ChallengeType.OBP_CONSENT_CHALLENGE.toString) match {
case Failure(msg, ex, _) =>
logger.error(
s"removeConsentChallenges: the challenges of consent $consentId could not be deleted: $msg" +
ex.map(e => s" (${e.getClass.getSimpleName}: ${e.getMessage})").getOrElse(""))
case _ =>
}

/**
* Release the artefacts a VRP mandate created, when the consent that owns them is revoked.
*
Expand Down
Loading
Loading