2025-05-09 08:52:18 -05:00
|
|
|
<%
|
|
|
|
nav_sections = [
|
|
|
|
{
|
2025-05-15 10:19:56 -04:00
|
|
|
header: t(".general_section_title"),
|
2025-05-09 08:52:18 -05:00
|
|
|
items: [
|
2025-05-15 10:19:56 -04:00
|
|
|
{ label: t(".profile_label"), path: settings_profile_path, icon: "circle-user" },
|
|
|
|
{ label: t(".preferences_label"), path: settings_preferences_path, icon: "bolt" },
|
|
|
|
{ label: t(".security_label"), path: settings_security_path, icon: "shield-check" },
|
Add comprehensive API v1 with OAuth and API key authentication (#2389)
* OAuth
* Add API test routes and update Doorkeeper token handling for test environment
- Introduced API namespace with test routes for controller testing in the test environment.
- Updated Doorkeeper configuration to allow fallback to plain tokens in the test environment for easier testing.
- Modified schema to change resource_owner_id type from bigint to string.
* Implement API key authentication and enhance access control
- Replaced Doorkeeper OAuth authentication with a custom method supporting both OAuth and API keys in the BaseController.
- Added methods for API key authentication, including validation and logging.
- Introduced scope-based authorization for API keys in the TestController.
- Updated routes to include API key management endpoints.
- Enhanced logging for API access to include authentication method details.
- Added tests for API key functionality, including validation, scope checks, and access control enforcement.
* Add API key rate limiting and usage tracking
- Implemented rate limiting for API key authentication in BaseController.
- Added methods to check rate limits, render appropriate responses, and include rate limit headers in responses.
- Updated routes to include a new usage resource for tracking API usage.
- Enhanced tests to verify rate limit functionality, including exceeding limits and per-key tracking.
- Cleaned up Redis data in tests to ensure isolation between test cases.
* Add Jbuilder for JSON rendering and refactor AccountsController
- Added Jbuilder gem for improved JSON response handling.
- Refactored index action in AccountsController to utilize Jbuilder for rendering JSON.
- Removed manual serialization of accounts and streamlined response structure.
- Implemented a before_action in BaseController to enforce JSON format for all API requests.
* Add transactions resource to API routes
- Added routes for transactions, allowing index, show, create, update, and destroy actions.
- This enhancement supports comprehensive transaction management within the API.
* Enhance API authentication and onboarding handling
- Updated BaseController to skip onboarding requirements for API endpoints and added manual token verification for OAuth authentication.
- Improved error handling and logging for invalid access tokens.
- Introduced a method to set up the current context for API requests, ensuring compatibility with session-like behavior.
- Excluded API paths from onboarding redirects in the Onboardable concern.
- Updated database schema to change resource_owner_id type from bigint to string for OAuth access grants.
* Fix rubocop offenses
- Fix indentation and spacing issues
- Convert single quotes to double quotes
- Add spaces inside array brackets
- Fix comment alignment
- Add missing trailing newlines
- Correct else/end alignment
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Fix API test failures and improve test reliability
- Fix ApiRateLimiterTest by removing mock users method and using fixtures
- Fix UsageControllerTest by removing mock users method and using fixtures
- Fix BaseControllerTest by using different users for multiple API keys
- Use unique display_key values with SecureRandom to avoid conflicts
- Fix double render issue in UsageController by returning after authorize_scope\!
- Specify controller name in routes for usage resource
- Remove trailing whitespace and empty lines per Rubocop
All tests now pass and linting is clean.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Add API transactions controller warning to brakeman ignore
The account_id parameter in the API transactions controller is properly
validated on line 79: family.accounts.find(transaction_params[:account_id])
This ensures users can only create transactions in accounts belonging to
their family, making this a false positive.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Signed-off-by: Josh Pigford <josh@joshpigford.com>
Co-authored-by: Claude <noreply@anthropic.com>
2025-06-17 15:57:05 -05:00
|
|
|
{ label: "API Key", path: settings_api_key_path, icon: "key" },
|
2025-05-15 10:19:56 -04:00
|
|
|
{ label: t(".self_hosting_label"), path: settings_hosting_path, icon: "database", if: self_hosted? },
|
|
|
|
{ label: t(".billing_label"), path: settings_billing_path, icon: "circle-dollar-sign", if: !self_hosted? },
|
|
|
|
{ label: t(".accounts_label"), path: accounts_path, icon: "layers" },
|
|
|
|
{ label: t(".imports_label"), path: imports_path, icon: "download" }
|
2025-05-09 08:52:18 -05:00
|
|
|
]
|
|
|
|
},
|
|
|
|
{
|
2025-05-15 10:19:56 -04:00
|
|
|
header: t(".transactions_section_title"),
|
2025-05-09 08:52:18 -05:00
|
|
|
items: [
|
2025-05-15 10:19:56 -04:00
|
|
|
{ label: t(".tags_label"), path: tags_path, icon: "tags" },
|
|
|
|
{ label: t(".categories_label"), path: categories_path, icon: "shapes" },
|
|
|
|
{ label: t(".rules_label"), path: rules_path, icon: "git-branch" },
|
|
|
|
{ label: t(".merchants_label"), path: family_merchants_path, icon: "store" }
|
2025-05-09 08:52:18 -05:00
|
|
|
]
|
|
|
|
},
|
|
|
|
{
|
2025-05-15 10:19:56 -04:00
|
|
|
header: t(".other_section_title"),
|
2025-05-09 08:52:18 -05:00
|
|
|
items: [
|
2025-05-15 10:19:56 -04:00
|
|
|
{ label: t(".whats_new_label"), path: changelog_path, icon: "box" },
|
|
|
|
{ label: t(".feedback_label"), path: feedback_path, icon: "megaphone" }
|
2025-05-09 08:52:18 -05:00
|
|
|
]
|
|
|
|
}
|
|
|
|
]
|
|
|
|
%>
|
|
|
|
|
2025-04-30 22:24:13 -04:00
|
|
|
<div class="space-y-4">
|
2025-04-30 22:29:06 -04:00
|
|
|
<div class="hidden lg:flex items-center gap-2 p-1.5">
|
2025-07-18 08:30:00 -04:00
|
|
|
<%= render DS::Link.new(
|
2025-04-30 18:14:22 -04:00
|
|
|
text: "Back",
|
|
|
|
icon: "chevron-left",
|
|
|
|
href: previous_path,
|
|
|
|
variant: "ghost",
|
|
|
|
) %>
|
2025-04-23 10:42:30 -03:00
|
|
|
<%= link_to previous_path, class: "hidden md:block uppercase bg-surface-inset-hover rounded-sm px-1 py-0.5 text-xs text-secondary shadow-sm ml-1 pointer-events-none", data: { controller: "hotkey", hotkey: "Escape" } do %>
|
2025-04-30 18:14:22 -04:00
|
|
|
<kbd>esc</kbd>
|
2024-10-01 02:58:15 +05:30
|
|
|
<% end %>
|
2024-09-20 15:56:21 -04:00
|
|
|
</div>
|
2025-04-18 18:53:10 +05:30
|
|
|
<nav class="space-y-4 hidden md:block">
|
2025-05-09 08:52:18 -05:00
|
|
|
<% nav_sections.each do |section| %>
|
|
|
|
<section class="space-y-2">
|
|
|
|
<div class="flex items-center gap-2 px-3">
|
|
|
|
<h3 class="uppercase text-secondary font-medium text-xs"><%= section[:header] %></h3>
|
2025-05-20 14:13:18 -05:00
|
|
|
<%= render "shared/ruler", classes: "w-full" %>
|
2025-05-09 08:52:18 -05:00
|
|
|
</div>
|
|
|
|
<ul class="space-y-1">
|
|
|
|
<% section[:items].each do |item| %>
|
|
|
|
<% next if item[:if] == false %>
|
|
|
|
<li>
|
|
|
|
<%= render "settings/settings_nav_item", name: item[:label], path: item[:path], icon: item[:icon] %>
|
|
|
|
</li>
|
|
|
|
<% end %>
|
|
|
|
</ul>
|
|
|
|
</section>
|
|
|
|
<% end %>
|
2024-09-20 15:56:21 -04:00
|
|
|
<section>
|
2025-04-30 18:14:22 -04:00
|
|
|
<%= button_to session_path(Current.session), method: :delete, class: "flex items-center gap-2 px-3 py-2 rounded-lg text-sm text-destructive hover:bg-surface-hover w-full" do %>
|
|
|
|
<%= icon("log-out", color: "current") %>
|
2024-09-20 15:56:21 -04:00
|
|
|
<span><%= t(".logout") %></span>
|
2024-04-25 16:31:12 -04:00
|
|
|
<% end %>
|
2024-09-20 15:56:21 -04:00
|
|
|
</section>
|
|
|
|
</nav>
|
2025-05-22 12:46:57 -03:00
|
|
|
<nav class="space-y-4 overflow-y-auto md:hidden" id="mobile-settings-nav" data-controller="preserve-scroll scroll-on-connect">
|
2025-04-18 11:39:58 -04:00
|
|
|
<ul class="flex space-y-1">
|
2025-04-30 22:29:06 -04:00
|
|
|
<li>
|
2025-07-18 08:30:00 -04:00
|
|
|
<%= render DS::Link.new(
|
2025-04-30 22:29:06 -04:00
|
|
|
text: "Back",
|
|
|
|
icon: "chevron-left",
|
|
|
|
href: previous_path,
|
|
|
|
variant: "ghost",
|
|
|
|
) %>
|
|
|
|
</li>
|
2025-05-09 08:52:18 -05:00
|
|
|
<% nav_sections.each do |section| %>
|
|
|
|
<% section[:items].each do |item| %>
|
|
|
|
<% next if item[:if] == false %>
|
|
|
|
<li>
|
|
|
|
<%= render "settings/settings_nav_item", name: item[:label], path: item[:path], icon: item[:icon] %>
|
|
|
|
</li>
|
|
|
|
<% end %>
|
2025-04-18 11:39:58 -04:00
|
|
|
<% end %>
|
2025-04-30 18:14:22 -04:00
|
|
|
<%= button_to session_path(Current.session), method: :delete, class: "flex items-center gap-2 px-3 py-2 rounded-lg text-sm text-destructive hover:bg-surface-hover w-full" do %>
|
2025-04-30 22:24:13 -04:00
|
|
|
<%= icon("log-out", color: "current") %>
|
2025-04-18 18:53:10 +05:30
|
|
|
<span><%= t(".logout") %></span>
|
|
|
|
<% end %>
|
2025-04-18 11:39:58 -04:00
|
|
|
</ul>
|
2025-04-18 18:53:10 +05:30
|
|
|
</nav>
|
2024-09-20 15:56:21 -04:00
|
|
|
</div>
|