Commit Graph

12 Commits

Author SHA1 Message Date
Juan José Mata
b3f70c8951 feat:Add SnapTrade OAuth device flow (#2523)
* Add SnapTrade OAuth connection flow

* Restore SnapTrade brokerage portal links

* Guard SnapTrade OAuth setup completion

* Move SnapTrade OAuth start to POST

* Use one SnapTrade item in provider panel

* Fix SnapTrade OAuth controller tests

* Fix SnapTrade OAuth drawer completion redirect

* Update SnapTrade limits message.

* Restrict SnapTrade OAuth scopes
2026-06-29 00:30:03 +02:00
Juan José Mata
b416618558 Add SnapTrade OAuth device flow (#2494)
* Add SnapTrade OAuth device flow

* Add SnapTrade OAuth device flow

### Motivation
- Integrate SnapTrade device-code OAuth so administrators can start a device authorization flow and poll for tokens using SnapTrade's well-known OAuth metadata endpoint.
- Persist and encrypt device-flow token material on `SnaptradeItem` to support long-lived API calls and future refresh handling.

### Description
- Add OAuth discovery and device-code support to the SnapTrade provider with `oauth_authorization_server_metadata`, `start_device_authorization`, and `poll_device_token` helper methods and shared `oauth_connection` / `parse_oauth_response` helpers.
- Persist OAuth device-flow tokens on `snaptrade_items` via a migration that adds `oauth_access_token`, `oauth_refresh_token`, `oauth_token_type`, `oauth_scope`, and `oauth_token_expires_at`, and update `db/schema.rb` accordingly.
- Extend `SnaptradeItem` to encrypt stored `oauth_access_token` and `oauth_refresh_token` when ActiveRecord encryption is configured and add `oauth_token_active?` to check token validity.
- Add high-level `start_oauth_device_flow` and `complete_oauth_device_flow!` helpers to the `SnaptradeItem::Provided` concern to start authorization and persist token responses.
- Expose admin-only member routes and JSON controller actions `start_oauth_device_flow` and `complete_oauth_device_flow` on `SnaptradeItemsController` to drive the device flow from the UI.
- Add focused Minitest coverage: `test/models/provider/snaptrade_oauth_test.rb` for provider requests and error handling and `test/models/snaptrade_item_oauth_test.rb` for token persistence.

### Testing
- Ran the targeted test suite: `bin/rails test test/models/provider/snaptrade_oauth_test.rb test/models/snaptrade_item_oauth_test.rb test/controllers/snaptrade_items_controller_test.rb`, and all tests passed.
- Ran `bin/rubocop` against modified files and no offenses were reported.

* Add SnapTrade OAuth device flow

### Motivation
- Integrate SnapTrade device-code OAuth so administrators can start a device authorization flow and poll for tokens using SnapTrade's well-known OAuth metadata endpoint.
- Persist and encrypt device-flow token material on `SnaptradeItem` to support long-lived API calls and future refresh handling.

### Description
- Add OAuth discovery and device-code support to the SnapTrade provider with `oauth_authorization_server_metadata`, `start_device_authorization`, and `poll_device_token` helper methods and shared `oauth_connection` / `parse_oauth_response` helpers.
- Persist OAuth device-flow tokens on `snaptrade_items` via a migration that adds `oauth_access_token`, `oauth_refresh_token`, `oauth_token_type`, `oauth_scope`, and `oauth_token_expires_at`, and update `db/schema.rb` accordingly.
- Extend `SnaptradeItem` to encrypt stored `oauth_access_token` and `oauth_refresh_token` when ActiveRecord encryption is configured and add `oauth_token_active?` to check token validity.
- Add high-level `start_oauth_device_flow` and `complete_oauth_device_flow!` helpers to the `SnaptradeItem::Provided` concern to start authorization and persist token responses.
- Expose admin-only member routes and JSON controller actions `start_oauth_device_flow` and `complete_oauth_device_flow` on `SnaptradeItemsController` to drive the device flow from the UI.
- Add focused Minitest coverage: `test/models/provider/snaptrade_oauth_test.rb` for provider requests and error handling and `test/models/snaptrade_item_oauth_test.rb` for token persistence.

### Testing
- Ran the targeted test suite: `bin/rails test test/models/provider/snaptrade_oauth_test.rb test/models/snaptrade_item_oauth_test.rb test/controllers/snaptrade_items_controller_test.rb`, and all tests passed.
- Ran `bin/rubocop` against modified files and no offenses were reported.

* Add SnapTrade OAuth device flow

### Motivation
- Integrate SnapTrade device-code OAuth so administrators can start a device authorization flow and poll for tokens using SnapTrade's well-known OAuth metadata endpoint.
- Persist and encrypt device-flow token material on `SnaptradeItem` to support long-lived API calls and future refresh handling.

### Description
- Add OAuth discovery and device-code support to the SnapTrade provider with `oauth_authorization_server_metadata`, `start_device_authorization`, and `poll_device_token` helper methods and shared `oauth_connection` / `parse_oauth_response` helpers.
- Persist OAuth device-flow tokens on `snaptrade_items` via a migration that adds `oauth_access_token`, `oauth_refresh_token`, `oauth_token_type`, `oauth_scope`, and `oauth_token_expires_at`, and update `db/schema.rb` accordingly.
- Extend `SnaptradeItem` to encrypt stored `oauth_access_token` and `oauth_refresh_token` when ActiveRecord encryption is configured and add `oauth_token_active?` to check token validity.
- Add high-level `start_oauth_device_flow` and `complete_oauth_device_flow!` helpers to the `SnaptradeItem::Provided` concern to start authorization and persist token responses.
- Expose admin-only member routes and JSON controller actions `start_oauth_device_flow` and `complete_oauth_device_flow` on `SnaptradeItemsController` to drive the device flow from the UI.
- Add focused Minitest coverage: `test/models/provider/snaptrade_oauth_test.rb` for provider requests and error handling and `test/models/snaptrade_item_oauth_test.rb` for token persistence.

### Testing
- Ran the targeted test suite: `bin/rails test test/models/provider/snaptrade_oauth_test.rb test/models/snaptrade_item_oauth_test.rb test/controllers/snaptrade_items_controller_test.rb`, and all tests passed.
- Ran `bin/rubocop` against modified files and no offenses were reported.

* Add SnapTrade OAuth device flow

### Motivation
- Integrate SnapTrade device-code OAuth so administrators can start a device authorization flow and poll for tokens using SnapTrade's well-known OAuth metadata endpoint.
- Persist and encrypt device-flow token material on `SnaptradeItem` to support long-lived API calls and future refresh handling.

### Description
- Add OAuth discovery and device-code support to the SnapTrade provider with `oauth_authorization_server_metadata`, `start_device_authorization`, and `poll_device_token` helper methods and shared `oauth_connection` / `parse_oauth_response` helpers.
- Persist OAuth device-flow tokens on `snaptrade_items` via a migration that adds `oauth_access_token`, `oauth_refresh_token`, `oauth_token_type`, `oauth_scope`, and `oauth_token_expires_at`, and update `db/schema.rb` accordingly.
- Extend `SnaptradeItem` to encrypt stored `oauth_access_token` and `oauth_refresh_token` when ActiveRecord encryption is configured and add `oauth_token_active?` to check token validity.
- Add high-level `start_oauth_device_flow` and `complete_oauth_device_flow!` helpers to the `SnaptradeItem::Provided` concern to start authorization and persist token responses.
- Expose admin-only member routes and JSON controller actions `start_oauth_device_flow` and `complete_oauth_device_flow` on `SnaptradeItemsController` to drive the device flow from the UI.
- Add focused Minitest coverage: `test/models/provider/snaptrade_oauth_test.rb` for provider requests and error handling and `test/models/snaptrade_item_oauth_test.rb` for token persistence.

### Testing
- Ran the targeted test suite: `bin/rails test test/models/provider/snaptrade_oauth_test.rb test/models/snaptrade_item_oauth_test.rb test/controllers/snaptrade_items_controller_test.rb`, and all tests passed.
- Ran `bin/rubocop` against modified files and no offenses were reported.

* Add SnapTrade OAuth device flow (provider, model, controller, routes, migration, tests)

### Motivation

- Add support for SnapTrade OAuth 2.0 device authorization flow so users can authorize SnapTrade via device codes in addition to the existing portal flow.
- Persist OAuth token metadata on `SnaptradeItem` for subsequent polling and usage by the provider and UI.

### Description

- Implemented OAuth device flow in the provider with `oauth_authorization_server_metadata`, `start_device_authorization`, and `poll_device_token`, plus HTTP helper methods `oauth_connection`, `oauth_client_id`, and `parse_oauth_response` in `Provider::Snaptrade`.
- Added controller endpoints `start_oauth_device_flow` and `complete_oauth_device_flow` in `SnaptradeItemsController` with robust error handling and helpers `oauth_error_payload` and `parse_oauth_error_body` to surface OAuth error fields.
- Extended `SnaptradeItem` with encrypted columns for `oauth_access_token`, `oauth_refresh_token`, token metadata, `oauth_token_active?`, and model methods `start_oauth_device_flow` and `complete_oauth_device_flow!` to store token metadata.
- Added migration `AddOauthDeviceFlowToSnaptradeItems` and updated `db/schema.rb` to include the new columns, registered a new initializer `config/initializers/snaptrade.rb` to read `SNAPTRADE_OAUTH_CLIENT_ID`, and updated `.env*.example` files to document `SNAPTRADE_OAUTH_CLIENT_ID`.
- Exposed new routes `start_oauth_device_flow` and `complete_oauth_device_flow` for `snaptrade_items`.

### Testing

- Added unit tests for provider OAuth behavior in `test/models/provider/snaptrade_oauth_test.rb`, model token persistence in `test/models/snaptrade_item_oauth_test.rb`, and controller error propagation in `test/controllers/snaptrade_items_controller_test.rb`.
- Ran the test suite with `bin/rails test` and the full test run (including the new SnapTrade OAuth tests) passed.

* Add SnapTrade OAuth device flow (start/poll), store tokens, and tests

### Motivation
- Add support for SnapTrade OAuth Device Authorization flow so administrators can start device authorization and poll for tokens without exposing provider internals.
- Persist OAuth token metadata on `SnaptradeItem` so the app can reuse and surface token state for SnapTrade integrations.
- Improve error handling and sanitization for OAuth API errors returned by SnapTrade to avoid leaking upstream internals.

### Description
- Introduces new environment examples and initializer: adds `SNAPTRADE_OAUTH_CLIENT_ID` to `.env.local.example`/`.env.test.example` and configures `Rails.configuration.x.snaptrade.oauth_client_id` in `config/initializers/snaptrade.rb`.
- Extends `Provider::Snaptrade` with OAuth device flow support, adding discovery URL, device grant constant, Faraday `oauth_connection`, and methods `oauth_authorization_server_metadata`, `start_device_authorization`, `poll_device_token`, `oauth_client_id`, and `parse_oauth_response`, plus improved retry and API error wrapping.
- Adds DB migration and schema changes to store OAuth fields on `snaptrade_items` (`oauth_access_token`, `oauth_refresh_token`, `oauth_token_type`, `oauth_scope`, `oauth_token_expires_at`) and marks those attributes encrypted when ActiveRecord encryption is enabled.
- Adds `SnaptradeItem` helpers `start_oauth_device_flow`, `complete_oauth_device_flow!`, and `oauth_token_active?` to start/poll and persist token metadata.
- Adds controller actions `start_oauth_device_flow` and `complete_oauth_device_flow` with sanitized error responses and helper methods `oauth_error_payload` and `parse_oauth_error_body`, and wires new member routes in `config/routes.rb`.
- Updates `SnaptradeItemsController` before_action lists to include the new actions and adds user-facing error message helper `start_oauth_device_flow_error_message`.

### Testing
- Added unit tests `test/models/provider/snaptrade_oauth_test.rb` to validate discovery, device authorization request, token polling, missing client ID handling, and OAuth error propagation, and all assertions passed.
- Added `test/models/snaptrade_item_oauth_test.rb` to assert `complete_oauth_device_flow!` stores tokens and expiry and that `oauth_token_active?` reports correctly, and the test passed.
- Extended `test/controllers/snaptrade_items_controller_test.rb` with controller-level tests confirming sanitized OAuth error payloads and behavior for start/complete endpoints, and these controller tests passed.

* Add SnapTrade OAuth device flow support and token storage

### Motivation

- Add support for the OAuth 2.0 device authorization flow for SnapTrade so users can link brokerages via a device-code flow without traditional browser-based client redirects.
- Persist OAuth token metadata on the SnaptradeItem so tokens can be reused and expiration tracked.
- Surface and sanitize provider error payloads to callers while avoiding leakage of internal configuration details.

### Description

- Added new DB columns and a migration (`oauth_access_token`, `oauth_refresh_token`, `oauth_token_type`, `oauth_scope`, `oauth_token_expires_at`) and updated `db/schema.rb` to reflect the change.
- Encrypted the new token fields on `SnaptradeItem` and added `oauth_token_active?`, `start_oauth_device_flow`, and `complete_oauth_device_flow!` helpers to the model.
- Implemented OAuth logic in `Provider::Snaptrade` including discovery (`OAUTH_DISCOVERY_URL`), `start_device_authorization`, `poll_device_token`, request parsing, retry handling, and a small Faraday connection wrapper; added configuration accessors for `oauth_client_id` via `config.x.snaptrade`.
- Added controller endpoints `start_oauth_device_flow` and `complete_oauth_device_flow` with safe error handling and helpers to format OAuth error payloads, and registered new member routes for `snaptrade_items`.
- Added an initializer to load `SNAPTRADE_OAUTH_CLIENT_ID` into `Rails.configuration.x.snaptrade`, and updated `.env.local.example` and `.env.test.example` to include the new env var.
- Added unit tests for provider OAuth behavior (`test/models/provider/snaptrade_oauth_test.rb`), SnaptradeItem token persistence (`test/models/snaptrade_item_oauth_test.rb`), and controller error handling (`test/controllers/snaptrade_items_controller_test.rb`), and updated controller tests accordingly.

### Testing

- Ran provider-level tests in `Provider::SnaptradeOauthTest` to validate discovery, device authorization, token polling, and error handling, which passed.
- Ran model tests in `SnaptradeItemOauthTest` to verify token metadata is stored and `oauth_token_active?` works, which passed.
- Ran controller tests in `SnaptradeItemsControllerTest` that exercise the start/complete endpoints and error sanitization, which passed.

* Add SnapTrade OAuth device-flow support and token storage

### Motivation

- Add support for SnapTrade OAuth device authorization so users can perform device-code based OAuth without embedding secrets in the browser.
- Persist OAuth token metadata on `SnaptradeItem` and expose programmatic start/complete endpoints while avoiding leaking provider internals on errors.
- Make OAuth client ID configurable via environment or credentials for Sure deployments.

### Description

- Introduce `SNAPTRADE_OAUTH_CLIENT_ID` to `.env` examples and add `config.x.snaptrade.oauth_client_id` initializer for configuration.
- Add migration `AddOauthDeviceFlowToSnaptradeItems` and update `schema.rb` to add `oauth_access_token`, `oauth_refresh_token`, `oauth_token_type`, `oauth_scope`, and `oauth_token_expires_at` to `snaptrade_items`.
- Persist and encrypt new token fields in `SnaptradeItem` and add helper methods `oauth_token_active?`, `start_oauth_device_flow`, and `complete_oauth_device_flow!`.
- Extend `Provider::Snaptrade` with OAuth discovery, device authorization (`start_device_authorization`), token polling (`poll_device_token`), Faraday-based `oauth_connection`, parsing and error-wrapping logic, and retry handling.
- Add controller actions `start_oauth_device_flow` and `complete_oauth_device_flow` to `SnaptradeItemsController`, plus helper methods to format OAuth error payloads and user-facing error messages.
- Wire up new routes (`post :start_oauth_device_flow`, `post :complete_oauth_device_flow`) and add `config/initializers/snaptrade.rb`.
- Add comprehensive tests for the OAuth flow and controller error handling and update a system test stub to avoid provider leakage during UI tests.

### Testing

- Added `Provider::SnaptradeOauthTest` which stubs discovery, device authorization and token endpoints and asserts request payloads and responses; tests passed.
- Added `SnaptradeItemOauthTest` which verifies token metadata persistence and `oauth_token_active?`; test passed.
- Extended `SnaptradeItemsControllerTest` with scenarios for successful and failing device-flow completion and start flow error handling; tests passed.
- Ran the affected system test changes in `TradesTest` (provider stubbing and modal behavior); the updated tests passed.
2026-06-27 06:43:12 +02:00
Brendon Scheiber
0c126b1674 feat(i18n): extract hardcoded English strings to locale files (#1806)
* Extract hardcoded strings to i18n

Replace numerous hardcoded English strings with I18n lookups (t / I18n.t) across controllers, views, helpers, and components, and convert model validation error messages to symbol keys. Added multiple locale files under config/locales for models and views. This centralizes user-facing notices/alerts, UI text, import/validation messages, and prepares the app for localization and easier translation maintenance.

* Update en.yml

* Update preview-cleanup.yml

* Revert "Update preview-cleanup.yml"

This reverts commit 1ba6d3c34c.

* test: align i18n assertions with translated messages

* Standardize balance error key and tweak locales

Replace SophtronAccount's :requires_balance error key with :no_balance and update related locale strings for sophtron, plaid, and simplefin accounts to use the new key and clearer copy. Also switch the QIF upload redirect notice to use a relative translation key (t('.qif_uploaded')), remove an unused SSO providers help line, and fix a trailing-newline/whitespace issue in the subscriptions locale. These changes standardize validation keys and improve translation consistency and messaging.

---------

Co-authored-by: KiloClaw <kiloclaw@openclaw.ai>
2026-05-17 09:52:49 +02:00
Sure Admin (bot)
e677d382c2 fix: send first-time SnapTrade users to connect flow (#1613)
* fix: route unregistered SnapTrade users to connect flow

* test: fix snaptrade controller sign-out helper

* fix: prefer active registered snaptrade items

* test: avoid Current.family outside request cycle

* fix: preserve snaptrade resume flow

* fix: read snaptrade resume session with indifferent keys

---------

Co-authored-by: SureBot <sure-bot@we-promise.com>
2026-05-03 10:28:31 +02:00
UberDudePL
cebdf1d4f7 Polish localization: complete translations, pluralization fixes, and reusable locale audit tooling (#1356)
* Add production-ready Polish localization and reusable locale audit tooling

- add and update Polish locale files across models, views, mailers, and shared translations
- add runtime rails-i18n dependency and Polish locale support in language helper
- add regression coverage for Polish pluralization and locale-aware money formatting
- introduce reusable locale audit script for any locale plus backward-compatible PL wrapper
- add localization audit docs and generated PL readiness/pluralization reports
- resolve one/few/many/other pluralization consistency for Polish locales

* Fix Polish locale review feedback

* Fix locale compatibility regressions

* Polish locale typo pass and wrapper cleanup

* Final language improvements and test isolation for Polish locales

- Improved partial_success wording in SnapTrade with proper noun inflection
- Fixed typos: Pomin → Pomiń in Mercury and LunchFlow items
- Isolated I18n backend state in polish_pluralization_test to prevent test coupling

* Fix code review comments in locale audit scripts

- Use RbConfig.ruby instead of 'ruby' to ensure consistent interpreter
- Remove Symbol from permitted_classes and explicitly allow CLDR plural symbols (one, few, many, other) in YAML loading

* Simplify i18n flow and align locale interpolation keys

* Remove locale audit scripts and localization docs
2026-04-07 11:55:58 +02:00
soky srm
9410e5b38d Providers sharing (#1273)
* third party provider scoping

* Simplify logic and allow only admins to mange providers

* Broadcast fixes

* FIX tests and build

* Fixes

* Reviews

* Scope merchants

* DRY fixes
2026-03-25 17:47:04 +01:00
Anas Limouri
998ea6f7c5 fix: Resolve infinite sync loop on SnapTrade setup accounts page (#1256)
* Fix infinite sync loop on SnapTrade setup accounts page

* Address PR feedback: behavior assertions & stale sync recovery

- Uses `latest_sync.completed?` so we don't drop dropped/failed syncs
- Replaces `assigns` checks with `assert_select` DOM checks
- Adds required IDs/classes to the html template for assertions
2026-03-23 14:22:37 +01:00
LPW
24981ffd52 Add "Link to existing" option in SnapTrade Setup Accounts modal (#935)
* Add account linking functionality for SnapTrade items

- Introduced UI to link existing accounts when setting up SnapTrade items, preventing duplicate account creation.
- Updated controller to fetch linkable accounts.
- Added tests to verify proper filtering of accounts and linking behavior.

* Add `snaptrade_item_id` to account linking flow for SnapTrade items

- Updated controller to allow specifying `snaptrade_item_id` when linking accounts.
- Adjusted form and views to include `snaptrade_item_id` as a hidden field.
- Enhanced tests to validate behavior with the new parameter.
2026-02-08 10:30:46 +01:00
LPW
01c2209492 Add tests for SnapTrade error handling and refine unlink behavior (#931)
- Introduced new tests to cover SnapTrade decryption and connection errors in `SnaptradeItemsControllerTest`.
- Updated error messages for improved user clarity.
- Modified `unlink` functionality to preserve `SnaptradeAccount` records while ensuring proper detachment of associated holdings.
2026-02-07 23:15:18 +01:00
LPW
e6d8112278 Add SnapTrade connection management UI for freeing up connection slots (#747)
* Add SnapTrade connection management with lazy-loading and deletion functionality.

* Refactor lazy-load controller to simplify event handling and enhance loading state management; improve SnapTrade deletion logic with additional safeguards and logging.

* Improve SnapTrade connection error handling and centralize unknown brokerage message using i18n.

* Centralize SnapTrade connection default name and missing authorization ID messages using i18n.

* Enhance SnapTrade connection deletion logic with improved error handling, i18n support for API deletion failures, and consistent Turbo Stream responses.

---------

Co-authored-by: luckyPipewrench <luckypipewrench@proton.me>
2026-01-23 08:55:34 +01:00
LPW
9858b36dc7 Centralize sdk_object_to_hash logic in DataHelpers module and update all references for improved reusability and consistency. Add error handling for partial and failed SnapTrade account linking. (#741)
Co-authored-by: luckyPipewrench <luckypipewrench@proton.me>
2026-01-22 22:19:44 +01:00
LPW
a83f70425f Add SnapTrade brokerage integration with full trade history support (#737)
* Introduce SnapTrade integration with models, migrations, views, and activity processing logic.

* Refactor SnapTrade activities processing: improve activity fetching flow, handle pending states, and update UI elements for enhanced user feedback.

* Update Brakeman ignore file to include intentional redirect for SnapTrade OAuth portal.

* Refactor SnapTrade models, views, and processing logic: add currency extraction helper, improve pending state handling, optimize migration checks, and enhance user feedback in UI.

* Remove encryption for SnapTrade `snaptrade_user_id`, as it is an identifier, not a secret.

* Introduce `SnaptradeConnectionCleanupJob` to asynchronously handle SnapTrade connection cleanup and improve i18n for SnapTrade item status messages.

* Update SnapTrade encryption: make `snaptrade_user_secret` non-deterministic to enhance security.

---------

Signed-off-by: Juan José Mata <juanjo.mata@gmail.com>
Co-authored-by: luckyPipewrench <luckypipewrench@proton.me>
Co-authored-by: Juan José Mata <juanjo.mata@gmail.com>
2026-01-22 20:52:49 +01:00