You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Add headless helpers for custom dashboard integrations (#9)
* Start revamping the dashboard
* Add headless helper modules for custom integrations
Introduce three helper modules that make building custom API key UIs
effortless without dictating styling:
- TokenSession: Manages "show token once" pattern for secret keys
- store(session, api_key) - save token after creation
- retrieve_once(session) - get and clear token
- available?(session) - check without clearing
- ExpirationOptions: Handles expiration preset dropdowns
- for_select - returns options for Rails select helper
- parse("30_days") - converts preset to datetime
- default_value - returns "no_expiration"
- ViewHelpers: Data formatting for views (include in ApplicationHelper)
- api_key_status/status_label/status_info
- api_key_environment_label/environment_from_token
- api_key_type_label/publishable?/secret?
These helpers are designed to be framework-agnostic - they return data,
not HTML, so integrators can use Tailwind, Bootstrap, or any styling.
Co-Authored-By: Claude <noreply@anthropic.com>
* Add opt-in form builder extensions for API key forms
Introduce FormBuilderExtensions module that reduces view boilerplate
while letting integrators control all styling. Opt-in via initializer:
Rails.application.config.to_prepare do
ActionView::Helpers::FormBuilder.include(ApiKeys::FormBuilderExtensions)
end
Form helpers included:
- api_key_expiration_select(options, html_options)
One-line expiration dropdown with all presets
<%= form.api_key_expiration_select(class: "my-select") %>
- api_key_scopes_checkboxes(scopes, checked:, &block)
Block-based scope rendering - you provide markup, we handle logic
<%= form.api_key_scopes_checkboxes(@scopes) do |scope, checked| %>
<label><%= check_box_tag ..., checked %><%= scope %></label>
<% end %>
- api_key_token_data
Returns structured hash for building custom token display UIs
{ masked:, full:, viewable:, type:, environment: }
Design principle: helpers yield data and handle logic, integrators
provide all HTML/CSS. Works with any design system.
Co-Authored-By: Claude <noreply@anthropic.com>
* Add model convenience methods and wire up helpers
Model scopes on ApiKey:
- .publishable - keys with key_type: "publishable"
- .secret - keys that are NOT publishable (includes legacy)
Owner instance methods (HasApiKeys):
- available_api_key_scopes - get scopes for forms
- can_create_api_key?(key_type:) - check limits before UI
- create_api_key! now accepts expires_at_preset: param
Auto-cleaning:
- scopes= setter auto-removes blank values (form checkbox fix)
- create_api_key! also cleans scopes array
Wire up in lib/api_keys.rb:
- Require all helper modules
- Create top-level aliases for cleaner API:
- ApiKeys::TokenSession (vs ApiKeys::Helpers::TokenSession)
- ApiKeys::ExpirationOptions
- ApiKeys::ViewHelpers
Co-Authored-By: Claude <noreply@anthropic.com>
* Refactor dashboard views with extracted partials
Extract reusable partials from key row for cleaner code:
- _token_display.html.erb - masked/viewable token with show button
- _key_badges.html.erb - type, environment, expiration badges
- _key_status.html.erb - active/expired/revoked status badge
- _key_actions.html.erb - edit/revoke action buttons
- _empty_state.html.erb - empty state messaging
Update existing partials:
- _key_row.html.erb - now uses extracted partials
- _keys_table.html.erb - simplified table structure
- _publishable_keys.html.erb - improved section layout
- _secret_keys.html.erb - improved section layout
Add minimal JS for show/copy token functionality:
- Event delegation for .btn-show-token and .btn-copy-token
- Vanilla JS, no framework dependencies
- Progressive enhancement (works without JS)
Co-Authored-By: Claude <noreply@anthropic.com>
* Add comprehensive custom integration guide to README
Document all helpers and best practices learned from production
integration into a real SaaS application.
New sections:
- Building Custom Integrations (overview + what you'll need)
- Quick Setup (4-step guide with code)
- Complete Controller Example (90-line production-ready code)
- Model Scopes (.publishable, .secret, .active, etc.)
- Owner Instance Methods (available_api_key_scopes, can_create_api_key?, etc.)
- API Key Instance Methods (full method reference)
- Token Session Helper (store, retrieve_once, available?)
- Expiration Options Helper (for_select, parse, default_value)
- Form Builder Extensions (with ERB examples)
- View Helpers (status, type, environment helpers)
- View Examples (index, form, success page code)
- Best Practices (7 production-learned patterns)
The guide provides copy-paste-ready code for building custom UIs
while using the gem's model layer and business logic.
Co-Authored-By: Claude <noreply@anthropic.com>
* Add tests for headless helper modules
Cover TokenSession, ExpirationOptions, and ViewHelpers to bring
branch coverage above the 60% CI threshold.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Add input validation and edge case protections
Address automated review feedback:
- Add max length check (500 chars) in api_key_environment_from_token
- Add max days limit (3650 / ~10 years) in ExpirationOptions.parse
- Document can_create_api_key? as best-effort check for UI purposes
- Add thorough boundary condition tests for all edge cases
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
<%=button_toapi_keys.revoke_key_path(key),title: "Revoke Key",class: "api-keys-action-revoke",data: {turbo_method: :post,turbo_confirm: "Are you sure you want to revoke this key? It will stop working immediately."}do%>
<%=button_toapi_keys.revoke_key_path(key),title: "Revoke Key",data: {turbo_method: :post,turbo_confirm: "Are you sure you want to revoke this key? It will stop working immediately."}do%>
0 commit comments