Skip to content

feat(condo): DOMA-13345 card binding handlers - #7905

Open
vovaaxeapolla wants to merge 7 commits into
mainfrom
feat/condo/DOMA-13345/card-binding-handlers
Open

feat(condo): DOMA-13345 card binding handlers#7905
vovaaxeapolla wants to merge 7 commits into
mainfrom
feat/condo/DOMA-13345/card-binding-handlers

Conversation

@vovaaxeapolla

@vovaaxeapolla vovaaxeapolla commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • New Features

    • View a user’s saved payment cards across supported acquiring integrations.
    • Delete saved payment cards.
    • Configure card retrieval and deletion endpoints for acquiring integrations.
    • Card results are deduplicated and enriched with integration information.
  • Access Control

    • Restricted card operations to authenticated and authorized requests.
  • Bug Fixes

    • Improved resilience when individual integrations fail during card retrieval or deletion.
  • Tests

    • Added coverage for successful, unauthorized, duplicate, empty, and partial-failure scenarios.

@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 721e0c07-bcba-41d8-9cbe-a0d81ee8eafa

📥 Commits

Reviewing files that changed from the base of the PR and between 361c8d3 and 36cbba4.

📒 Files selected for processing (2)
  • apps/eps
  • apps/rb
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/rb

📝 Walkthrough

Walkthrough

The acquiring domain adds GraphQL operations to retrieve and delete saved card bindings. It adds provider requests, deduplication, authorization, integration endpoint fields, database migration changes, server utilities, test helpers, generated schema types, and coverage.

Changes

Card Binding Operations

Layer / File(s) Summary
Integration endpoint contracts
apps/condo/domains/acquiring/schema/AcquiringIntegration.js, apps/condo/migrations/..., apps/condo/domains/acquiring/gql.js, apps/condo/schema.graphql, apps/condo/schema.ts
Adds optional card retrieval and deletion URLs, database columns, analytics view fields, GraphQL operations, and generated schema types.
Provider requests and card aggregation
apps/condo/domains/acquiring/utils/serverSchema/cardsOnlineInteraction.js, apps/condo/domains/acquiring/utils/serverSchema/allCardBindings/*, apps/condo/domains/acquiring/utils/serverSchema/deleteCardBinding/*
Fetches and deletes cards across eligible integrations. Deduplicates cards and preserves integration metadata.
Server orchestration and GraphQL services
apps/condo/domains/acquiring/utils/serverSchema/index.js, apps/condo/domains/acquiring/access/*, apps/condo/domains/acquiring/schema/*Service.js, apps/condo/domains/acquiring/schema/index.js
Adds validated server helpers, access rules, the allCardBindings query, and the deleteCardBinding mutation.
Execution coverage and test clients
apps/condo/domains/acquiring/schema/*.test.js, apps/condo/domains/acquiring/schema/*.spec.js, apps/condo/domains/acquiring/utils/serverSchema/allCardBindings/utils.spec.js, apps/condo/domains/acquiring/utils/testSchema/index.js
Adds coverage for authorization, aggregation, metadata completion, partial failures, deletion, and test-client helpers.

Subproject References

Layer / File(s) Summary
Application subproject pointers
apps/eps, apps/rb
Updates the EPS and RB subproject commit references.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related PRs

Suggested labels: 🐘 BIG

Suggested reviewers: abshnko, dkoviazin

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant AllCardBindingsService
    participant AcquiringIntegrations
    participant CardProvider
    participant DeleteCardBindingService

    Client->>AllCardBindingsService: Request card bindings
    AllCardBindingsService->>AcquiringIntegrations: Find eligible integrations
    AcquiringIntegrations-->>AllCardBindingsService: Integration endpoints
    AllCardBindingsService->>CardProvider: Fetch cards concurrently
    CardProvider-->>AllCardBindingsService: Card tokens
    AllCardBindingsService-->>Client: Deduplicated card tokens

    Client->>DeleteCardBindingService: Delete card binding
    DeleteCardBindingService->>CardProvider: Delete card across integrations
    CardProvider-->>DeleteCardBindingService: Deletion results
    DeleteCardBindingService-->>Client: Status "ok"
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the main change: adding card binding handlers in the condo application.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/condo/DOMA-13345/card-binding-handlers

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@vovaaxeapolla vovaaxeapolla added 🔬 WIP Not intended to be merged right now, it is a work in progress 🚨 Migrations We have a database migrations here! labels Aug 5, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0f4f2afdfc

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

if (user.deletedAt) return false
if (user.isAdmin) return true

return !!userId

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Restrict card binding reads to the authenticated user

For non-admins this access check only verifies that the request contains some user.id, so any signed-in user who knows or can obtain another user's id can call allCardBindings for that id and receive that user's saved card tokens from every acquiring integration. This should compare the requested id with authentication.item.id (or otherwise enforce an explicit permission) before allowing the query.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, we think that it is impossible to guess another user's id. The second reason is that old flow will use service user and auth userId will not be equal to userId from request

if (user.deletedAt) return false
if (user.isAdmin) return true

return !!(userId && cardId)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Restrict card binding deletes to the authenticated user

For non-admins this only checks that user.id and cardId are present, so any authenticated user can submit another user's id and delete that user's saved card binding across acquiring integrations. The mutation should ensure the requested user is the authenticated user (or require a dedicated permission) before allowing deletion.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above

Comment on lines +28 to +30
for (const result of results) {
if (result.status === 'fulfilled') {
continue

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Propagate failed card deletion attempts

When an acquiring endpoint returns a non-2xx response or times out, deleteUserCard catches the error and resolves false, so Promise.allSettled marks the attempt as fulfilled and this loop treats it as success. In that scenario the GraphQL mutation still returns { status: 'ok' } even though the card remains bound in at least one integration, leaving callers with a false success signal.

Useful? React with 👍 / 👎.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (4)
apps/condo/domains/acquiring/utils/testSchema/index.js (1)

81-82: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use one single-quoted import for this module.

Combine these imports from @condo/domains/acquiring/gql and use single quotes.

Proposed fix
-const { DELETE_CARD_BINDING_MUTATION } = require('`@condo/domains/acquiring/gql`')
-const { ALL_CARD_BINDINGS_QUERY } = require("`@condo/domains/acquiring/gql`");
+const {
+    ALL_CARD_BINDINGS_QUERY,
+    DELETE_CARD_BINDING_MUTATION,
+} = require('`@condo/domains/acquiring/gql`')
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/condo/domains/acquiring/utils/testSchema/index.js` around lines 81 - 82,
Combine the DELETE_CARD_BINDING_MUTATION and ALL_CARD_BINDINGS_QUERY imports
from `@condo/domains/acquiring/gql` into one require statement, using single
quotes consistently.

Source: Coding guidelines

apps/condo/domains/acquiring/schema/DeleteCardBindingService.spec.js (1)

1-38: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

Keep this unit spec independent of Keystone schema utilities.

This *.spec.js file creates Keystone clients and initializes schema test state. Keep schema integration coverage in DeleteCardBindingService.test.js. Make this spec exercise isolated behavior with mocked dependencies.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/condo/domains/acquiring/schema/DeleteCardBindingService.spec.js` around
lines 1 - 38, Remove Keystone client creation and schema test-state
initialization from the DeleteCardBindingService spec, including
makeLoggedInAdminClient, makeClientWithNewRegisteredAndLoggedInUser, TestUtils,
AcquiringTestMixin, setFakeClientMode, and the beforeAll setup. Keep schema
integration coverage in DeleteCardBindingService.test.js and leave this spec
focused on isolated behavior with mocked dependencies.

Source: Coding guidelines

apps/condo/domains/acquiring/schema/AllCardBindingsService.spec.js (2)

1-15: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Order imports by the configured groups.

@app/condo/index is an internal import. It must not precede external and @open-condo imports. Place external imports first, then @open-condo, then internal imports with the required blank lines.

As per coding guidelines, import groups must follow builtin → external → @open-condo → internal, with blank lines between groups.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/condo/domains/acquiring/schema/AllCardBindingsService.spec.js` around
lines 1 - 15, Reorder the imports in the test file according to the configured
groups: place the external `@faker-js/faker` import first, followed by
`@open-condo/keystone/test.utils`, then the internal `@app/condo/index` and
remaining `@condo` imports. Preserve blank lines between each group.

Source: Coding guidelines


41-230: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Move these schema integration scenarios to a .test.js file.

These tests initialize Keystone test infrastructure, create integrations, and execute GraphQL requests. Keep this behavior in AllCardBindingsService.test.js, or replace the infrastructure with isolated dependency mocks before retaining the .spec.js suffix.

As per coding guidelines, *.spec.js tests must mock dependencies rather than rely on Keystone schema test utilities.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/condo/domains/acquiring/schema/AllCardBindingsService.spec.js` around
lines 41 - 230, Move the integration scenarios from the AllCardBindingsService
spec suite into AllCardBindingsService.test.js, preserving the existing Keystone
setup, integration creation, and GraphQL request behavior. Keep the current
tests unchanged in coverage and assertions while reserving the .spec.js suffix
for tests using isolated dependency mocks.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/condo/domains/acquiring/access/AllCardBindingsService.js`:
- Around line 6-11: Update canAllCardBindings so non-admin authenticated users
are authorized only when userId matches user.id, while preserving the existing
authentication, deleted-user, and admin checks. Add coverage verifying a
non-admin request with a different user ID is rejected.

In `@apps/condo/domains/acquiring/schema/DeleteCardBindingService.test.js`:
- Around line 28-39: Update canDeleteCardBinding and the delete flow to ignore
or reject a caller-supplied user.id for non-admin users, deriving the target
user ID from the authenticated context instead. Preserve admin behavior for
authorized cross-user deletion, and extend the user: execute test to verify
another user’s ID is rejected.

In `@apps/condo/domains/acquiring/utils/serverSchema/allCardBindings/utils.js`:
- Around line 10-14: Update the acquiringIntegrations query in fetchCardTokens
to filter only on getUserCardsUrl_not when retrieving cards, removing the
deleteUserCardUrl_not requirement. Keep the deletion-endpoint condition
restricted to the delete flow.

In `@apps/condo/domains/acquiring/utils/serverSchema/cardsOnlineInteraction.js`:
- Around line 45-56: Update the card-deletion POST in the fetch call to disable
retries by setting maxRetries to 0, unless a provider-supported stable
idempotency key is added to the request. Keep the existing request method,
payload, and timeout behavior unchanged.

In `@apps/condo/domains/acquiring/utils/serverSchema/deleteCardBinding/utils.js`:
- Around line 28-37: Update deleteCardBinding to propagate rejected provider
deletions instead of only logging them and resolving successfully. After
processing results, return a non-success result or rethrow an error that
includes the failed integrations; ensure DeleteCardBindingService does not
return { status: 'ok' } when any deleteUserCard call fails.

---

Nitpick comments:
In `@apps/condo/domains/acquiring/schema/AllCardBindingsService.spec.js`:
- Around line 1-15: Reorder the imports in the test file according to the
configured groups: place the external `@faker-js/faker` import first, followed by
`@open-condo/keystone/test.utils`, then the internal `@app/condo/index` and
remaining `@condo` imports. Preserve blank lines between each group.
- Around line 41-230: Move the integration scenarios from the
AllCardBindingsService spec suite into AllCardBindingsService.test.js,
preserving the existing Keystone setup, integration creation, and GraphQL
request behavior. Keep the current tests unchanged in coverage and assertions
while reserving the .spec.js suffix for tests using isolated dependency mocks.

In `@apps/condo/domains/acquiring/schema/DeleteCardBindingService.spec.js`:
- Around line 1-38: Remove Keystone client creation and schema test-state
initialization from the DeleteCardBindingService spec, including
makeLoggedInAdminClient, makeClientWithNewRegisteredAndLoggedInUser, TestUtils,
AcquiringTestMixin, setFakeClientMode, and the beforeAll setup. Keep schema
integration coverage in DeleteCardBindingService.test.js and leave this spec
focused on isolated behavior with mocked dependencies.

In `@apps/condo/domains/acquiring/utils/testSchema/index.js`:
- Around line 81-82: Combine the DELETE_CARD_BINDING_MUTATION and
ALL_CARD_BINDINGS_QUERY imports from `@condo/domains/acquiring/gql` into one
require statement, using single quotes consistently.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: cc5663f8-9ee6-46e5-a0ef-2bf3d7b33379

📥 Commits

Reviewing files that changed from the base of the PR and between d6c617a and 0f4f2af.

📒 Files selected for processing (20)
  • apps/condo/domains/acquiring/access/AllCardBindingsService.js
  • apps/condo/domains/acquiring/access/DeleteCardBindingService.js
  • apps/condo/domains/acquiring/gql.js
  • apps/condo/domains/acquiring/schema/AcquiringIntegration.js
  • apps/condo/domains/acquiring/schema/AllCardBindingsService.js
  • apps/condo/domains/acquiring/schema/AllCardBindingsService.spec.js
  • apps/condo/domains/acquiring/schema/AllCardBindingsService.test.js
  • apps/condo/domains/acquiring/schema/DeleteCardBindingService.js
  • apps/condo/domains/acquiring/schema/DeleteCardBindingService.spec.js
  • apps/condo/domains/acquiring/schema/DeleteCardBindingService.test.js
  • apps/condo/domains/acquiring/schema/index.js
  • apps/condo/domains/acquiring/utils/serverSchema/allCardBindings/utils.js
  • apps/condo/domains/acquiring/utils/serverSchema/allCardBindings/utils.spec.js
  • apps/condo/domains/acquiring/utils/serverSchema/cardsOnlineInteraction.js
  • apps/condo/domains/acquiring/utils/serverSchema/deleteCardBinding/utils.js
  • apps/condo/domains/acquiring/utils/serverSchema/index.js
  • apps/condo/domains/acquiring/utils/testSchema/index.js
  • apps/condo/migrations/20260804174816-0545_acquiringintegration_deleteusercardurl_and_more.js
  • apps/eps
  • apps/rb

Comment on lines +6 to +11
async function canAllCardBindings ({ args: { data: { user: { id: userId } } }, authentication: { item: user } }) {
if (!user) return throwAuthenticationError()
if (user.deletedAt) return false
if (user.isAdmin) return true

return !!userId

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

fd -a 'AllCardBindingsService' . | sed 's#^\./##'
echo '--- outline/service ---'
ast-grep outline apps/condo/domains/acquiring/access/AllCardBindingsService.js || true
echo '--- service ---'
cat -n apps/condo/domains/acquiring/access/AllCardBindingsService.js
echo '--- tests ---'
ast-grep outline apps/condo/domains/acquiring/access/AllCardBindingsService.test.js || true
cat -n apps/condo/domains/acquiring/access/AllCardBindingsService.test.js
echo '--- usages ---'
rg -n "canAllCardBindings|AllCardBindingsService|data\.user\.id|allCardBindings|user:\s*\{" apps/condo/domains/acquiring -S

Repository: open-condo-software/condo

Length of output: 1747


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- acquired access/schem tests ---'
for f in apps/condo/domains/acquiring/schema/AllCardBindingsService.test.js apps/condo/domains/acquiring/schema/AllCardBindingsService.spec.js; do
  if [ -f "$f" ]; then
    echo "### $f"
    cat -n "$f"
  fi
done

echo '--- schema service files outline ---'
ast-grep outline apps/condo/domains/acquiring/schema/AllCardBindingsService.js || true
echo '--- schema service file ---'
cat -n apps/condo/domains/acquiring/schema/AllCardBindingsService.js

echo '--- usages ---'
rg -n "canAllCardBindings|AllCardBindingsService|allCardBindings|data\.user\.id|user:\s*\{" apps/condo/domains/acquiring -S

Repository: open-condo-software/condo

Length of output: 27844


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- allCardBindings implementation ---'
cat -n apps/condo/domains/acquiring/utils/serverSchema/index.js | sed -n '130,185p'
echo '--- fetchCardTokens helpers ---'
cat -n apps/condo/domains/acquiring/utils/serverSchema/allCardBindings/utils.js | sed -n '1,220p'
echo '--- getUserCards usages ---'
rg -n "getUserCards|fetchCardTokens|deduplicateCardTokens|allCardBindings" apps/condo/domains/acquiring/utils/serverSchema apps/condo/domains/acquiring -S

echo '--- delete card binding access test for comparison ---'
rg -n "canDeleteCardBinding|DeleteCardBindingService" apps/condo/domains/acquiring -S
cat -n apps/condo/domains/acquiring/access/DeleteCardBindingService.js
cat -n apps/condo/domains/acquiring/utils/serverSchema/DeleteCardBindingService.js

Repository: open-condo-software/condo

Length of output: 16092


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- getUserCards implementation ---'
cat -n apps/condo/domains/acquiring/utils/serverSchema/cardsOnlineInteraction.js | sed -n '1,90p'

echo '--- exact service files access pattern diff context ---'
wc -l apps/condo/domains/acquiring/schema/DeleteCardBindingService.spec.js apps/condo/domains/acquiring/schema/DeleteCardBindingService.test.js apps/condo/domains/acquiring/access/DeleteCardBindingService.js apps/condo/domains/acquiring/schema/DeleteCardBindingService.js
cat -n apps/condo/domains/acquiring/schema/DeleteCardBindingService.spec.js | sed -n '1,90p'
cat -n apps/condo/domains/acquiring/schema/DeleteCardBindingService.test.js | sed -n '1,90p'

Repository: open-condo-software/condo

Length of output: 7322


🌐 Web query:

open condo Deleting of card binding service tests user execute should reject unauthorized user id

💡 Result:

In the Open Condo (condo) platform, testing unauthorized access for sensitive services—such as card binding, payment registration, or other administrative actions—follows a standardized pattern within the project's testing framework [1][2][3]. Tests for rejecting unauthorized users are typically implemented as integration tests using the project's Keystone-based testing utilities [3]. To verify that a service correctly rejects an unauthorized user ID, developers follow these practices: 1. Setup Isolated Clients: Developers use helpers such as makeClientWithServiceUser or similar authentication fixtures to create distinct client contexts [1][2]. 2. Define Access Rights: The test cases define both authorized and unauthorized states. For example, a test may configure a service user with an access-right set that explicitly has a permission flag (e.g., canExecuteRegisterExternalPayments) set to false [1]. 3. Assert Rejection: The test attempts to execute the service method with the unauthorized client context and asserts that the operation fails with an access-denied error (often mapping to a 403 Forbidden status or a specific GraphQL/API access-denied response) [1][2][4]. Because Open Condo utilizes role-based access control (RBAC) scoped to organizations [5], these tests verify that the system correctly validates the user's permissions within the specific organizational context of the request, ensuring that a user ID without the necessary privileges cannot trigger the deletion or registration of bound cards or other restricted entities [1][5][2]. Internal security enforcement is validated by ensuring that the access-control middleware is triggered before the service logic executes [5][6].

Citations:


IDOR (CWE-639): Authorization Bypass Through User-Controlled Key (IDOR)

Reachability: External

Restrict non-admin reads to the authenticated user.

canAllCardBindings() returns true for any truthy data.user.id. The resolver uses that ID to fetch card bindings, so an authenticated non-admin can request another user’s saved card metadata. Require userId === user.id for non-admin users, and add a test that rejects a different user ID.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/condo/domains/acquiring/access/AllCardBindingsService.js` around lines 6
- 11, Update canAllCardBindings so non-admin authenticated users are authorized
only when userId matches user.id, while preserving the existing authentication,
deleted-user, and admin checks. Add coverage verifying a non-admin request with
a different user ID is rejected.

Comment on lines +28 to +39
test('user: execute', async () => {
const client = await makeClientWithNewRegisteredAndLoggedInUser()

const [result] = await deleteCardBindingByTestClient(client, {
user: {
id: faker.datatype.uuid(),
},
cardId: faker.datatype.uuid(),
})

expect(result.status).toBe('ok')
})

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== locate files =="
fd -a 'DeleteCardBindingService|DeleteCardBinding|cardBinding|acquiring' . | sed 's#^\./##' | head -200

echo "== git diff stat =="
git diff --stat || true

echo "== relevant search =="
rg -n "deleteCardBinding|DeleteCardBindingService|cardBinding|DeleteCardBinding" apps/condo/domains/acquiring -S || true

Repository: open-condo-software/condo

Length of output: 6073


🏁 Script executed:

#!/bin/bash
set -euo pipefail

for f in \
  apps/condo/domains/acquiring/schema/DeleteCardBindingService.js \
  apps/condo/domains/acquiring/access/DeleteCardBindingService.js \
  apps/condo/domains/acquiring/utils/serverSchema/deleteCardBinding/utils.js \
  apps/condo/domains/acquiring/utils/serverSchema/index.js \
  apps/condo/domains/acquiring/schema/DeleteCardBindingService.test.js \
  apps/condo/domains/acquiring/schema/DeleteCardBindingService.spec.js \
  apps/condo/domains/acquiring/gql.js
do
  echo "== $f =="
  cat -n "$f"
done

echo "== structural/context usages near delete operations =="
python3 - <<'PY'
from pathlib import Path
paths = [
 'apps/condo/domains/acquiring/schema/DeleteCardBindingService.js',
 'apps/condo/domains/acquiring/access/DeleteCardBindingService.js',
 'apps/condo/domains/acquiring/utils/serverSchema/deleteCardBinding/utils.py'
]
for path in ['apps/condo/domains/acquiring/utils/serverSchema/deleteCardBinding/utils.js','apps/condo/domains/acquiring/utils/serverSchema/index.js']:
    p=Path(path)
    if p.exists():
        txt=p.read_text()
        print(f'--- {p} contains id fields ---')
        for i,line in enumerate(txt.splitlines(),1):
            if 'id' in line and ('user' in line or 'context' in line or 'deleteCardBinding' in line or 'authentication' in line or 'requireContext' in line):
                print(f'{i}: {line}')
PY

Repository: open-condo-software/condo

Length of output: 28631


IDOR (CWE-639): Authorization Bypass Through User-Controlled Key (IDOR)

Reachability: External

Reject deletion requests for another user.

canDeleteCardBinding does not prevent non-admin callers from passing an arbitrary user.id; the delete flow then forwards that value. Derive the user ID from the authenticated context for non-admin requests and add coverage that another user’s ID is rejected.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/condo/domains/acquiring/schema/DeleteCardBindingService.test.js` around
lines 28 - 39, Update canDeleteCardBinding and the delete flow to ignore or
reject a caller-supplied user.id for non-admin users, deriving the target user
ID from the authenticated context instead. Preserve admin behavior for
authorized cross-user deletion, and extend the user: execute test to verify
another user’s ID is rejected.

Comment on lines +45 to +56
const response = await fetch(url, {
maxRetries: 5,
timeoutBetweenRequests: 1000,
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
userId,
cardId,
}),
})

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n -C 4 'deleteUserCard|deleteUserCardUrl|maxRetries|idempot' apps packages -g '*.js'

Repository: open-condo-software/condo

Length of output: 34002


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the delete call path and retry implementation without executing repo code.
sed -n '35,75p' apps/condo/domains/acquiring/utils/serverSchema/cardsOnlineInteraction.js
sed -n '160,210p' packages/keystone/fetch.js
rg -n -C 3 'acquiringCard.*delete|CardBinding|deleteCardBinding' apps/condo/domains/acquiring -g '*.js'

Repository: open-condo-software/condo

Length of output: 36211


Do not retry the card-deletion POST without idempotency.

fetchWithRetriesAndLogger retries after a failed response or exception, and this call sets maxRetries: 5 with only userId and cardId in the body. If the acquiring endpoint deletes the card but the response is lost, a later retry can repeat the deletion. Set maxRetries = 0 for this mutation, or add a provider-supported stable idempotency key.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/condo/domains/acquiring/utils/serverSchema/cardsOnlineInteraction.js`
around lines 45 - 56, Update the card-deletion POST in the fetch call to disable
retries by setting maxRetries to 0, unless a provider-supported stable
idempotency key is added to the request. Keep the existing request method,
payload, and timeout behavior unchanged.

Comment on lines +28 to +37
for (const result of results) {
if (result.status === 'fulfilled') {
continue
}

logger.error({
msg: 'failed to delete card binding',
err: result.reason,
})
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Files matching relevant paths:"
fd -a 'utils\.js$|DeleteCardBindingService\.js$|deleteCardBinding' . | sed 's#^\./##' | head -100

echo
echo "target utils outline:"
ast-grep outline apps/condo/domains/acquiring/utils/serverSchema/deleteCardBinding/utils.js || true

echo
echo "target utils content:"
cat -n apps/condo/domains/acquiring/utils/serverSchema/deleteCardBinding/utils.js

echo
echo "service overview:"
cat -n apps/condo/domains/acquiring/schema/DeleteCardBindingService.js | sed -n '1,220p'

Repository: open-condo-software/condo

Length of output: 7396


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Search for deleteCardBinding usages and return handling:"
rg -n "deleteCardBinding|DeleteCardBinding|cardBinding|card binding" apps/condo/domains/acquiring -g '*.js' -g '*.ts' | head -250

echo
echo "Relevant schema/service files list:"
git ls-files 'apps/condo/domains/acquiring/**' | rg 'DeleteCardBinding|deleteCardBinding|schema|utils' | sort

Repository: open-condo-software/condo

Length of output: 11425


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "deleteUserCard implementation:"
cat -n apps/condo/domains/acquiring/utils/serverSchema/cardsOnlineInteraction.js | sed -n '1,130p'

echo
echo "DeleteCardBindingService tests/specs relevant sections:"
cat -n apps/condo/domains/acquiring/schema/DeleteCardBindingService.test.js | sed -n '1,140p'
echo
cat -n apps/condo/domains/acquiring/schema/DeleteCardBindingService.spec.js | sed -n '1,120p'

echo
echo "testSchema delete helper and serverSchema delete wrapper:"
cat -n apps/condo/domains/acquiring/utils/testSchema/index.js | sed -n '648,710p'
echo
cat -n apps/condo/domains/acquiring/utils/serverSchema/index.js | sed -n '145,185p'

echo
echo "Programmatic model equivalent:"
node - <<'JS'
async function promiseAllSettledAndResolve() {
  const results = await Promise.allSettled([
    Promise.resolve({}),
    Promise.reject(new Error('provider failed')),
    Promise.resolve({}),
  ])
  for (const result of results) {
    if (result.status === 'fulfilled') continue
    console.log('logged rejected result')
  }
  return undefined
}
promiseAllSettledAndResolve().then(result => {
  console.log('function resolved to:', result)
  const serviceOutput = { status: 'ok' }
  console.log('service output:', serviceOutput)
})
JS

Repository: open-condo-software/condo

Length of output: 11893


Propagate failed provider deletions.

deleteUserCard logs and returns false when a provider call fails, and deleteCardBinding still resolves. DeleteCardBindingService then returns { status: 'ok' } after that resolve. If any provider deletion fails, return a non-success result containing the failed integrations or rethrow after collecting rejected results.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/condo/domains/acquiring/utils/serverSchema/deleteCardBinding/utils.js`
around lines 28 - 37, Update deleteCardBinding to propagate rejected provider
deletions instead of only logging them and resolving successfully. After
processing results, return a non-success result or rethrow an error that
includes the failed integrations; ensure DeleteCardBindingService does not
return { status: 'ok' } when any deleteUserCard call fails.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
apps/condo/schema.ts (1)

66-74: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use four-space indentation in the changed TypeScript declarations.

If this file is generated, update its generator or formatter and regenerate the file.

  • apps/condo/schema.ts#L66-L74: Indent the added fields with four spaces.
  • apps/condo/schema.ts#L1166-L1170: Indent the added input fields with four spaces.
  • apps/condo/schema.ts#L1202-L1206: Indent the added history fields with four spaces.
  • apps/condo/schema.ts#L1232-L1236: Indent the added history input fields with four spaces.
  • apps/condo/schema.ts#L1267-L1271: Indent the added update input fields with four spaces.
  • apps/condo/schema.ts#L1326-L1343: Indent the filter fields with four spaces.
  • apps/condo/schema.ts#L1364-L1381: Indent the filter fields with four spaces.
  • apps/condo/schema.ts#L1589-L1593: Indent the added input fields with four spaces.
  • apps/condo/schema.ts#L1635-L1652: Indent the filter fields with four spaces.
  • apps/condo/schema.ts#L1673-L1690: Indent the filter fields with four spaces.
  • apps/condo/schema.ts#L2062-L2069: Indent type members with four spaces.
  • apps/condo/schema.ts#L24978-L24988: Indent type members with four spaces.
  • apps/condo/schema.ts#L28830-L28838: Indent type members with four spaces.
  • apps/condo/schema.ts#L48740-L48740: Indent the mutation member with four spaces.
  • apps/condo/schema.ts#L58280-L58282: Indent the argument member with four spaces.
  • apps/condo/schema.ts#L79683-L79683: Indent the query member with four spaces.
  • apps/condo/schema.ts#L85988-L85990: Indent the argument member with four spaces.
  • apps/condo/schema.ts#L92841-L92848: Indent enum members with four spaces.
  • apps/condo/schema.ts#L92890-L92897: Indent enum members with four spaces.

As per coding guidelines, **/*.{js,jsx,ts,tsx} files must use four-space indentation.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/condo/schema.ts` around lines 66 - 74, Update the generated TypeScript
declarations in apps/condo/schema.ts so all changed members use four-space
indentation: lines 66-74, 1166-1170, 1202-1206, 1232-1236, 1267-1271, 1326-1343,
1364-1381, 1589-1593, 1635-1652, 1673-1690, 2062-2069, 24978-24988, 28830-28838,
48740, 58280-58282, 79683, 85988-85990, 92841-92848, and 92890-92897. If
schema.ts is generated, update its generator or formatter and regenerate it
rather than applying only manual edits.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@apps/condo/schema.ts`:
- Around line 66-74: Update the generated TypeScript declarations in
apps/condo/schema.ts so all changed members use four-space indentation: lines
66-74, 1166-1170, 1202-1206, 1232-1236, 1267-1271, 1326-1343, 1364-1381,
1589-1593, 1635-1652, 1673-1690, 2062-2069, 24978-24988, 28830-28838, 48740,
58280-58282, 79683, 85988-85990, 92841-92848, and 92890-92897. If schema.ts is
generated, update its generator or formatter and regenerate it rather than
applying only manual edits.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 9f643fd8-f14d-4a87-b410-fe329def0cdc

📥 Commits

Reviewing files that changed from the base of the PR and between 0f4f2af and 361c8d3.

📒 Files selected for processing (4)
  • apps/condo/domains/acquiring/schema/index.js
  • apps/condo/schema.graphql
  • apps/condo/schema.ts
  • apps/eps
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/condo/domains/acquiring/schema/index.js

@sonarqubecloud

sonarqubecloud Bot commented Aug 6, 2026

Copy link
Copy Markdown

@vovaaxeapolla vovaaxeapolla added ✋🙂 Review please Comments are resolved, take a look, please and removed 🔬 WIP Not intended to be merged right now, it is a work in progress labels Aug 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🚨 Migrations We have a database migrations here! ✋🙂 Review please Comments are resolved, take a look, please

Development

Successfully merging this pull request may close these issues.

1 participant