mirror of
https://github.com/we-promise/sure.git
synced 2026-08-12 11:10:20 +00:00
e03204bb96bad4e7036ddbc511c849de8b52b3b3
5
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
7f17fbf6da |
security: sanitize exception messages in v1 API responses (FIX-11) (#1521)
* fix(security): sanitize exception messages in API responses (FIX-11)
Replace raw e.message/error.message interpolations in response bodies
with generic error strings, and log class+message server-side. Prevents
leaking internal exception details (stack traces, SQL fragments, record
data) to API clients.
Covers:
- API v1 accounts, categories (index/show), holdings, sync, trades,
transactions (index/show/create/update/destroy), valuations
(show/create/update): replace "Error: #{e.message}" with
"An unexpected error occurred".
- API v1 auth: device-registration rescue paths now log
"[Auth] Device registration failed: ..." and respond with
"Failed to register device".
- WebhooksController#plaid and #plaid_eu: log full error and respond
with "Invalid webhook".
- Settings::ProvidersController: generic user-facing flash alert,
detailed log line with error class + message.
Updates providers_controller_test assertion to match sanitized flash.
* fix(security): address CodeRabbit review
Major — partial-commit on device registration failure:
- Strengthened valid_device_info? to also run MobileDevice's model
validations up-front (device_type inclusion, attribute presence), not
just a flat "are the keys present?" check. A client that sends a bad
device_type ("windows", etc.) is now rejected at the API boundary
BEFORE signup commits any user/family/invite state.
- Wrapped the signup path (user.save + InviteCode.claim + MobileDevice
upsert + token issuance) in ActiveRecord::Base.transaction. A
post-save RecordInvalid from device registration (e.g., racing
uniqueness on device_id) now rolls back the user/invite/family so
clients don't see a partial-account state.
- Rescue branch logs the exception class + message ("#{e.class} - #{e.message}")
for better postmortem debugging, matching the providers controller
pattern.
Nit:
- Tightened providers_controller_test log expectation regex to assert on
both the exception class name AND the message ("StandardError - Database
error"), so a regression that drops either still fails the test.
Tests:
- New: "should reject signup with invalid device_type before committing
any state" — POST /api/v1/auth/signup with device_type="windows"
returns 400 AND asserts no User, MobileDevice, or Doorkeeper::AccessToken
row was created.
Note on SSO path (sso_exchange → issue_mobile_tokens, lines 173/225): the
device_info in those flows comes from Rails.cache (populated by an earlier
request that already passed valid_device_info?), so the pre-validation
covers it indirectly. Wrapping the full SSO account creation (user +
invitation + OidcIdentity + issue_mobile_tokens) in one transaction would
be a meaningful architectural cleanup but is out of scope for this
error-hygiene PR — filed it as a mental note for a follow-up.
|
||
|
|
28d99a2b0d |
Include newer providers in automatic family sync (#934)
* Include newer providers in automatic family sync
Coinbase, CoinStats, Mercury, and SnapTrade all implement Syncable
and have Syncer classes but were not listed in child_syncables,
meaning their data only refreshed on manual sync button clicks.
* refactor(syncer): Open/Closed principle for provider sync
- Adding new providers requires modifying child_syncables (violates O/C)
- plaid_items missing .active scope (bug: syncs deleted items)
- snaptrade_items can exist without user registration → fails on sync
- Scattered knowledge about 'ready to sync' logic
1. **Registry pattern**: SYNCABLE_ITEM_ASSOCIATIONS constant lists all
provider associations that participate in family sync
2. **Encapsulated sync-readiness**: Each item model defines its own
`syncable` scope that knows when it's ready for auto-sync:
- Most providers: `syncable = active` (not scheduled for deletion)
- SnapTrade: `syncable = active + user_registered` (has API creds)
3. **Single loop**: child_syncables iterates the registry, calling
`.syncable` on each association
- Adding a provider = add to registry + define syncable scope
- Each model owns its 'ready to sync' business logic
- Fixes plaid_items bug (now uses .active via .syncable)
- Fixes snaptrade auto-sync failures (filters unregistered items)
- Easy to extend with new conditions per provider
- family/syncer.rb: Registry + dynamic collection
- *_item.rb (7 files): Add `scope :syncable, -> { active }`
- snaptrade_item.rb: Add syncable with user_registered filter
* Fix rubocop bracket spacing in SnaptradeItem syncable scope
|
||
|
|
ba442d5f26 |
Implement Indexa Capital provider with real API integration (#933)
* Add Indexa Capital provider scaffold
Generate Indexa Capital provider scaffolding and align credential fields with the API authentication requirements.
* Fix PR 926 lint and schema CI failures
* Implement Indexa Capital provider with real API integration
- Rewrite all broken view templates (were meta-ERB from code generator)
- Create missing select_accounts.html.erb template
- Implement real API calls: list_accounts via /users/me, get_holdings
via /accounts/{number}/fiscal-results, get_account_balance via
/accounts/{number}/performance
- Add API token auth support (stored token > env token > credentials)
- Add api_token column with encryption support
- Redesign settings panel: API token prominent, credentials collapsible
- Fix account balances display using performance endpoint portfolios
- Fix accounts index empty-state guard missing indexa_capital_items
- Simplify activities fetch job (no activities API endpoint exists)
- Fix i18n interpolation (%%{ -> %{) throughout locale file
* Add tests for Indexa Capital provider integration
- IndexaCapitalItemTest: validations, credentials, scopes, sync status
- IndexaCapitalAccountTest: upsert, holdings, account provider linking
- Provider::IndexaCapitalTest: auth modes, API stubs, error handling
- IndexaCapitalItemsControllerTest: CRUD, setup, linking, authorization
- Fixtures for items (token + credentials) and accounts (mutual + pension)
52 tests, 98 assertions, 0 failures
* Address code review feedback from PR #933
- Fix zero balance bug: use `nil?` instead of `present?` so 0 is stored
- Fix has_indexa_capital_credentials? to check api_token (was ignored)
- Fix build_provider to delegate to Provided concern (was ignoring token)
- Fix IndexaCapital section outside encryption_error guard in settings
- Add account_number sanitization to prevent path traversal in API URLs
- Replace all skipped processor tests with real working tests
- Add zero-balance and path-traversal test coverage
61 tests, 107 assertions, 0 failures
* Address code review round 2: credentials validation, RuboCop, test quality
- Fix RuboCop SpaceInsideArrayLiteralBrackets in credentials check
- Chain where.not calls so all three username/document/password must be present
- Require all three credentials (||) instead of any one (&&) in validate_configuration!
- Move attr_reader to private to avoid exposing credentials publicly
- Parse dates with Date.parse in extract_balance for robustness
- Remove stale TODO and Crypto from supported_account_types
- Order build_provider query deterministically by created_at
- Replace no-op holdings assertion with meaningful assert_difference
* Address code review round 3: JSON parse safety and test precision
- Rescue JSON::ParserError on 2xx responses for clearer error messages
- Fix weak balance assertion: set balance to 0 before processing, assert
expected value (27093.01 = sum of holdings amounts)
* Include Indexa Capital in automatic family sync
Add indexa_capital_items to Family::Syncer#child_syncables so balances
and holdings refresh on daily auto-sync and login sync, not only on
manual sync button clicks.
---------
Signed-off-by: Juan José Mata <juanjo.mata@gmail.com>
Co-authored-by: Juan José Mata <jjmata@jjmata.com>
Co-authored-by: Juan José Mata <juanjo.mata@gmail.com>
|
||
|
|
b08285a10f |
API v1: add amount_cents + signed_amount_cents to transactions (#899)
* feat(api): add amount_cents + signed_amount_cents to transactions * fix: use currency.minor_unit_conversion for amount_cents - Replace hardcoded *100 with currency.minor_unit_conversion - Handles JPY (0 decimals), KWD/BHD (3 decimals), etc. correctly - Add assert_amount_cents_fields helper to validate sign/scale invariants |
||
|
|
3d91e60a8a |
feat: Add subcategory breakdown to Cash Flow Sankey and Reports (#639)
* feat: Add subcategory breakdown to Cash Flow and Reports Implements Discussion #546 - adds hierarchical category/subcategory visualization to both the Sankey chart and Reports breakdown tables. Sankey chart changes: - Income: subcategory → parent category → Cash Flow - Expense: Cash Flow → parent category → subcategory - Extracted process_category_totals helper to DRY up income/expense logic Reports breakdown changes: - Subcategories display nested under parent categories - Smaller dots and indented rows for visual hierarchy - Extracted _breakdown_table partial to eliminate duplication * fix: Dynamic node padding for Sankey chart with many nodes - Add dynamic nodePadding calculation to prevent padding from dominating chart height when there are many subcategory nodes - Extract magic numbers to static constants for configuration - Decompose monolithic #draw() into focused methods - Consolidate duplicate tooltip/currency formatting code - Modernize syntax with spread operators and optional chaining * fix: Hide overlapping Sankey labels, show on hover - Add label overlap detection by grouping nodes by column depth - Hide labels that would overlap with adjacent nodes - Show hidden labels on hover (node rectangle or connected links) - Add hover events to node rectangles (not just text) * fix: Use deterministic fallback colors for categories - Replace Category::COLORS.sample with Category::UNCATEGORIZED_COLOR for income categories in Sankey chart (was producing different colors on each page load) - Add nil color fallback in reports_controller for parent and root categories Addresses CodeRabbit review feedback. * fix: Expand CSS variable map for d3 color manipulation Add hex mappings for commonly used CSS variables so d3 can manipulate opacity for gradients and hover effects: - var(--color-destructive) -> #EC2222 - var(--color-gray-400) -> #9E9E9E - var(--color-gray-500) -> #737373 * test: Add tests for subcategory breakdown in dashboard and reports - Test dashboard renders Sankey chart with parent/subcategory transactions - Test reports groups transactions by parent and subcategories - Test reports handles categories with nil colors - Use EntriesTestHelper#create_transaction for cleaner test setup * Fix lint: use Number.NEGATIVE_INFINITY * Remove obsolete nil color test Category model now validates color presence, so nil color categories cannot exist. The fallback handling in reports_controller is still in place but the scenario is unreachable. * Update reports_controller.rb * FIX trade category --------- Co-authored-by: sokie <sokysrm@gmail.com> |