plutonium 0.33.1 → 0.34.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (143) hide show
  1. checksums.yaml +4 -4
  2. data/# Plutonium: The pre-alpha demo.md +4 -2
  3. data/.claude/skills/assets/SKILL.md +416 -0
  4. data/.claude/skills/connect-resource/SKILL.md +112 -0
  5. data/.claude/skills/controller/SKILL.md +302 -0
  6. data/.claude/skills/create-resource/SKILL.md +240 -0
  7. data/.claude/skills/definition/SKILL.md +218 -0
  8. data/.claude/skills/definition-actions/SKILL.md +386 -0
  9. data/.claude/skills/definition-fields/SKILL.md +474 -0
  10. data/.claude/skills/definition-query/SKILL.md +334 -0
  11. data/.claude/skills/forms/SKILL.md +439 -0
  12. data/.claude/skills/installation/SKILL.md +300 -0
  13. data/.claude/skills/interaction/SKILL.md +382 -0
  14. data/.claude/skills/model/SKILL.md +267 -0
  15. data/.claude/skills/model-features/SKILL.md +286 -0
  16. data/.claude/skills/nested-resources/SKILL.md +274 -0
  17. data/.claude/skills/package/SKILL.md +191 -0
  18. data/.claude/skills/policy/SKILL.md +352 -0
  19. data/.claude/skills/portal/SKILL.md +400 -0
  20. data/.claude/skills/resource/SKILL.md +281 -0
  21. data/.claude/skills/rodauth/SKILL.md +452 -0
  22. data/.claude/skills/views/SKILL.md +563 -0
  23. data/Appraisals +46 -4
  24. data/CHANGELOG.md +38 -1
  25. data/app/assets/plutonium.css +2 -2
  26. data/config/brakeman.ignore +239 -0
  27. data/config/initializers/action_policy.rb +1 -1
  28. data/docs/.vitepress/config.ts +132 -47
  29. data/docs/concepts/architecture.md +226 -0
  30. data/docs/concepts/auto-detection.md +254 -0
  31. data/docs/concepts/index.md +61 -0
  32. data/docs/concepts/packages-portals.md +304 -0
  33. data/docs/concepts/resources.md +224 -0
  34. data/docs/cookbook/blog.md +411 -0
  35. data/docs/cookbook/index.md +289 -0
  36. data/docs/cookbook/saas.md +481 -0
  37. data/docs/getting-started/index.md +57 -0
  38. data/docs/getting-started/installation.md +147 -0
  39. data/docs/getting-started/tutorial/01-setup.md +119 -0
  40. data/docs/getting-started/tutorial/02-first-resource.md +180 -0
  41. data/docs/getting-started/tutorial/03-authentication.md +246 -0
  42. data/docs/getting-started/tutorial/04-authorization.md +170 -0
  43. data/docs/getting-started/tutorial/05-custom-actions.md +202 -0
  44. data/docs/getting-started/tutorial/06-nested-resources.md +147 -0
  45. data/docs/getting-started/tutorial/07-customizing-ui.md +254 -0
  46. data/docs/getting-started/tutorial/index.md +64 -0
  47. data/docs/guides/adding-resources.md +420 -0
  48. data/docs/guides/authentication.md +552 -0
  49. data/docs/guides/authorization.md +468 -0
  50. data/docs/guides/creating-packages.md +380 -0
  51. data/docs/guides/custom-actions.md +523 -0
  52. data/docs/guides/index.md +45 -0
  53. data/docs/guides/multi-tenancy.md +302 -0
  54. data/docs/guides/nested-resources.md +411 -0
  55. data/docs/guides/search-filtering.md +266 -0
  56. data/docs/guides/theming.md +321 -0
  57. data/docs/index.md +68 -26
  58. data/docs/public/CLAUDE.md +64 -21
  59. data/docs/reference/assets/index.md +496 -0
  60. data/docs/reference/controller/index.md +363 -0
  61. data/docs/reference/definition/actions.md +400 -0
  62. data/docs/reference/definition/fields.md +350 -0
  63. data/docs/reference/definition/index.md +252 -0
  64. data/docs/reference/definition/query.md +342 -0
  65. data/docs/reference/generators/index.md +470 -0
  66. data/docs/reference/index.md +49 -0
  67. data/docs/reference/interaction/index.md +445 -0
  68. data/docs/reference/model/features.md +248 -0
  69. data/docs/reference/model/index.md +219 -0
  70. data/docs/reference/policy/index.md +385 -0
  71. data/docs/reference/portal/index.md +382 -0
  72. data/docs/reference/views/forms.md +396 -0
  73. data/docs/reference/views/index.md +479 -0
  74. data/gemfiles/rails_7.gemfile +9 -2
  75. data/gemfiles/rails_7.gemfile.lock +146 -111
  76. data/gemfiles/rails_8.0.gemfile +20 -0
  77. data/gemfiles/rails_8.0.gemfile.lock +417 -0
  78. data/gemfiles/rails_8.1.gemfile +20 -0
  79. data/gemfiles/rails_8.1.gemfile.lock +419 -0
  80. data/lib/generators/pu/gem/dotenv/templates/.env +2 -0
  81. data/lib/generators/pu/gem/dotenv/templates/config/initializers/001_ensure_required_env.rb +3 -1
  82. data/lib/generators/pu/lib/plutonium_generators/model_generator_base.rb +13 -16
  83. data/lib/generators/pu/pkg/portal/USAGE +65 -0
  84. data/lib/generators/pu/pkg/portal/portal_generator.rb +22 -9
  85. data/lib/generators/pu/res/conn/USAGE +71 -0
  86. data/lib/generators/pu/res/model/USAGE +106 -110
  87. data/lib/generators/pu/res/model/templates/model.rb.tt +6 -2
  88. data/lib/generators/pu/res/scaffold/USAGE +85 -0
  89. data/lib/generators/pu/rodauth/install_generator.rb +2 -6
  90. data/lib/generators/pu/rodauth/templates/config/initializers/url_options.rb +17 -0
  91. data/lib/generators/pu/skills/sync/USAGE +14 -0
  92. data/lib/generators/pu/skills/sync/sync_generator.rb +66 -0
  93. data/lib/plutonium/action_policy/sti_policy_lookup.rb +1 -1
  94. data/lib/plutonium/core/controller.rb +2 -2
  95. data/lib/plutonium/interaction/base.rb +1 -0
  96. data/lib/plutonium/package/engine.rb +2 -2
  97. data/lib/plutonium/query/adhoc_block.rb +6 -2
  98. data/lib/plutonium/query/model_scope.rb +1 -1
  99. data/lib/plutonium/railtie.rb +4 -0
  100. data/lib/plutonium/resource/controllers/crud_actions/index_action.rb +1 -1
  101. data/lib/plutonium/resource/query_object.rb +38 -8
  102. data/lib/plutonium/ui/table/components/scopes_bar.rb +39 -34
  103. data/lib/plutonium/version.rb +1 -1
  104. data/lib/tasks/release.rake +26 -4
  105. data/package.json +1 -1
  106. metadata +76 -39
  107. data/brakeman.ignore +0 -28
  108. data/docs/api-examples.md +0 -49
  109. data/docs/guide/claude-code-guide.md +0 -74
  110. data/docs/guide/deep-dive/authorization.md +0 -189
  111. data/docs/guide/deep-dive/multitenancy.md +0 -256
  112. data/docs/guide/deep-dive/resources.md +0 -390
  113. data/docs/guide/getting-started/01-installation.md +0 -165
  114. data/docs/guide/index.md +0 -28
  115. data/docs/guide/introduction/01-what-is-plutonium.md +0 -211
  116. data/docs/guide/introduction/02-core-concepts.md +0 -440
  117. data/docs/guide/tutorial/01-project-setup.md +0 -75
  118. data/docs/guide/tutorial/02-creating-a-feature-package.md +0 -45
  119. data/docs/guide/tutorial/03-defining-resources.md +0 -90
  120. data/docs/guide/tutorial/04-creating-a-portal.md +0 -101
  121. data/docs/guide/tutorial/05-customizing-the-ui.md +0 -128
  122. data/docs/guide/tutorial/06-adding-custom-actions.md +0 -101
  123. data/docs/guide/tutorial/07-implementing-authorization.md +0 -90
  124. data/docs/markdown-examples.md +0 -85
  125. data/docs/modules/action.md +0 -244
  126. data/docs/modules/authentication.md +0 -236
  127. data/docs/modules/configuration.md +0 -599
  128. data/docs/modules/controller.md +0 -443
  129. data/docs/modules/core.md +0 -316
  130. data/docs/modules/definition.md +0 -1308
  131. data/docs/modules/display.md +0 -759
  132. data/docs/modules/form.md +0 -495
  133. data/docs/modules/generator.md +0 -400
  134. data/docs/modules/index.md +0 -167
  135. data/docs/modules/interaction.md +0 -642
  136. data/docs/modules/package.md +0 -151
  137. data/docs/modules/policy.md +0 -176
  138. data/docs/modules/portal.md +0 -710
  139. data/docs/modules/query.md +0 -297
  140. data/docs/modules/resource_record.md +0 -618
  141. data/docs/modules/routing.md +0 -690
  142. data/docs/modules/table.md +0 -301
  143. data/docs/modules/ui.md +0 -631
@@ -0,0 +1,552 @@
1
+ # Authentication
2
+
3
+ This guide covers setting up user authentication with Rodauth.
4
+
5
+ ## Overview
6
+
7
+ Plutonium uses [Rodauth](http://rodauth.jeremyevans.net/) via [rodauth-rails](https://github.com/janko/rodauth-rails) for authentication, providing:
8
+ - User registration and login
9
+ - Password reset
10
+ - Email verification
11
+ - Multi-factor authentication (OTP, WebAuthn, SMS)
12
+ - Session management
13
+ - Account lockout
14
+
15
+ ## Installation
16
+
17
+ ### New Applications
18
+
19
+ The Plutonium template installs Rodauth automatically:
20
+
21
+ ```bash
22
+ rails new myapp -a propshaft -j esbuild -c tailwind \
23
+ -m https://radioactive-labs.github.io/plutonium-core/templates/plutonium.rb
24
+ ```
25
+
26
+ ### Existing Applications
27
+
28
+ ```bash
29
+ rails g pu:rodauth:install
30
+ rails db:migrate
31
+ ```
32
+
33
+ This installs:
34
+ - Required gems (`rodauth-rails`, `bcrypt`, `sequel-activerecord_connection`)
35
+ - `app/rodauth/rodauth_app.rb` - Main Roda app
36
+ - `app/rodauth/rodauth_plugin.rb` - Base plugin
37
+ - `app/controllers/rodauth_controller.rb` - Base controller
38
+ - `config/initializers/rodauth.rb` - Configuration
39
+
40
+ ## Creating Account Types
41
+
42
+ ### Basic User Account
43
+
44
+ ```bash
45
+ rails g pu:rodauth:account user
46
+ rails db:migrate
47
+ ```
48
+
49
+ **Default features** (enabled with `--defaults`, which is on by default):
50
+ - `login`, `logout`, `remember`
51
+ - `create_account`, `verify_account`, `verify_account_grace_period`
52
+ - `reset_password`, `reset_password_notify`
53
+ - `change_login`, `verify_login_change`
54
+ - `change_password`, `change_password_notify`
55
+ - `case_insensitive_login`, `internal_request`
56
+
57
+ ### Admin Account
58
+
59
+ ```bash
60
+ rails g pu:rodauth:admin admin
61
+ rails db:migrate
62
+ ```
63
+
64
+ Includes all base features plus:
65
+ - Multi-phase login (email first, then password)
66
+ - TOTP two-factor authentication (required)
67
+ - Recovery codes
68
+ - Account lockout
69
+ - Active sessions tracking
70
+ - Audit logging
71
+ - **No public signup** - accounts created via rake task
72
+
73
+ ### Customer Account
74
+
75
+ ```bash
76
+ rails g pu:rodauth:customer customer
77
+ rails g pu:rodauth:customer customer --entity=Organization
78
+ rails g pu:rodauth:customer customer --no-allow_signup
79
+ rails db:migrate
80
+ ```
81
+
82
+ Creates a customer account with an associated entity model (for multi-tenancy):
83
+ - Customer account model
84
+ - Entity model (Organization, Company, etc.)
85
+ - Membership join model with has-many-through associations
86
+
87
+ ## Generator Options
88
+
89
+ ### Feature Options
90
+
91
+ ```bash
92
+ # Enable all supported features
93
+ rails g pu:rodauth:account user --kitchen_sink
94
+
95
+ # Disable default features (explicit selection only)
96
+ rails g pu:rodauth:account user --no-defaults
97
+
98
+ # Enable specific features
99
+ rails g pu:rodauth:account user --otp --recovery_codes --lockout
100
+
101
+ # Skip email setup
102
+ rails g pu:rodauth:account user --no-mails
103
+
104
+ # API-only mode (JWT, no sessions)
105
+ rails g pu:rodauth:account user --api_only --jwt --jwt_refresh
106
+
107
+ # Use Argon2 instead of bcrypt
108
+ rails g pu:rodauth:account user --argon2
109
+
110
+ # Mark as primary account (no URL prefix)
111
+ rails g pu:rodauth:account user --primary
112
+ ```
113
+
114
+ ### Available Features
115
+
116
+ | Feature | Description |
117
+ |---------|-------------|
118
+ | `login` | Basic login/logout |
119
+ | `create_account` | User registration |
120
+ | `verify_account` | Email verification |
121
+ | `reset_password` | Password reset via email |
122
+ | `change_password` | Change password when logged in |
123
+ | `change_login` | Change email address |
124
+ | `verify_login_change` | Verify email change |
125
+ | `remember` | "Remember me" functionality |
126
+ | `otp` | TOTP two-factor authentication |
127
+ | `sms_codes` | SMS-based 2FA |
128
+ | `recovery_codes` | Backup codes for 2FA |
129
+ | `webauthn` | WebAuthn/passkey authentication |
130
+ | `lockout` | Lock account after failed attempts |
131
+ | `active_sessions` | Track/manage active sessions |
132
+ | `audit_logging` | Log authentication events |
133
+ | `email_auth` | Passwordless email login |
134
+ | `jwt` | JWT token authentication |
135
+ | `jwt_refresh` | JWT refresh tokens |
136
+ | `close_account` | Allow account deletion |
137
+
138
+ ## Generated Files
139
+
140
+ ```
141
+ app/
142
+ ├── controllers/rodauth/
143
+ │ └── user_controller.rb # Account-specific controller
144
+ ├── mailers/rodauth/
145
+ │ └── user_mailer.rb # Account-specific mailer
146
+ ├── models/
147
+ │ └── user.rb # Account model
148
+ ├── rodauth/
149
+ │ ├── rodauth_app.rb # Main Roda app
150
+ │ ├── rodauth_plugin.rb # Base plugin
151
+ │ └── user_rodauth_plugin.rb # Account-specific config
152
+ ├── policies/
153
+ │ └── user_policy.rb # Account policy
154
+ ├── definitions/
155
+ │ └── user_definition.rb # Account definition
156
+ └── views/rodauth/
157
+ └── user_mailer/ # Email templates
158
+ db/migrate/
159
+ └── xxx_create_users.rb # Account table migration
160
+ ```
161
+
162
+ ## Connecting Auth to Controllers
163
+
164
+ Include the auth module in your controller to require authentication:
165
+
166
+ ```ruby
167
+ # app/controllers/resource_controller.rb
168
+ class ResourceController < PlutoniumController
169
+ include Plutonium::Resource::Controller
170
+ include Plutonium::Auth::Rodauth(:user)
171
+ end
172
+ ```
173
+
174
+ This provides:
175
+
176
+ | Method | Description |
177
+ |--------|-------------|
178
+ | `current_user` | The authenticated account |
179
+ | `logout_url` | URL to logout |
180
+ | `rodauth` | Access to Rodauth instance |
181
+
182
+ ### Portal Configuration
183
+
184
+ For portals, include the auth module in the controller concern:
185
+
186
+ ```ruby
187
+ # packages/admin_portal/app/controllers/admin_portal/concerns/controller.rb
188
+ module AdminPortal
189
+ module Concerns
190
+ module Controller
191
+ extend ActiveSupport::Concern
192
+ include Plutonium::Portal::Controller
193
+ include Plutonium::Auth::Rodauth(:admin)
194
+ end
195
+ end
196
+ end
197
+ ```
198
+
199
+ ## Accessing the Current User
200
+
201
+ ```ruby
202
+ # In controllers
203
+ def index
204
+ @user_posts = current_user.posts
205
+ end
206
+
207
+ # In views (helper method)
208
+ <% if current_user.present? %>
209
+ Welcome, <%= current_user.email %>
210
+ <% end %>
211
+ ```
212
+
213
+ ## Rodauth Plugin Configuration
214
+
215
+ The generated plugin file contains configuration options:
216
+
217
+ ```ruby
218
+ # app/rodauth/user_rodauth_plugin.rb
219
+ class UserRodauthPlugin < RodauthPlugin
220
+ configure do
221
+ # Features enabled for this account
222
+ enable :login, :logout, :remember, :create_account, ...
223
+
224
+ # URL prefix (non-primary accounts)
225
+ prefix "/users"
226
+
227
+ # Store password in column (not separate table)
228
+ account_password_hash_column :password_hash
229
+
230
+ # Controller for views
231
+ rails_controller { Rodauth::UserController }
232
+
233
+ # Model
234
+ rails_account_model { User }
235
+
236
+ # Redirects
237
+ login_redirect "/"
238
+ logout_redirect "/"
239
+
240
+ # Session configuration
241
+ session_key "_user_session"
242
+ remember_cookie_key "_user_remember"
243
+ end
244
+ end
245
+ ```
246
+
247
+ ### Custom Login Redirect
248
+
249
+ ```ruby
250
+ configure do
251
+ login_redirect { "/dashboard" }
252
+
253
+ # Or dynamically
254
+ login_redirect do
255
+ if rails_account.admin?
256
+ "/admin"
257
+ else
258
+ "/dashboard"
259
+ end
260
+ end
261
+ end
262
+ ```
263
+
264
+ ### Password Requirements
265
+
266
+ ```ruby
267
+ configure do
268
+ # Minimum length (default: 8)
269
+ password_minimum_length 12
270
+
271
+ # Custom complexity
272
+ password_meets_requirements? do |password|
273
+ super(password) && password.match?(/\d/) && password.match?(/[^a-zA-Z\d]/)
274
+ end
275
+ end
276
+ ```
277
+
278
+ ### Multi-Phase Login
279
+
280
+ ```ruby
281
+ configure do
282
+ # Ask for email first, then password
283
+ use_multi_phase_login? true
284
+ end
285
+ ```
286
+
287
+ ### Prevent Public Signup
288
+
289
+ ```ruby
290
+ configure do
291
+ before_create_account_route do
292
+ request.halt unless internal_request?
293
+ end
294
+ end
295
+ ```
296
+
297
+ ## Email Configuration
298
+
299
+ Emails are sent via Action Mailer.
300
+
301
+ ### Development
302
+
303
+ ```ruby
304
+ # Gemfile
305
+ gem "letter_opener", group: :development
306
+
307
+ # config/environments/development.rb
308
+ config.action_mailer.delivery_method = :letter_opener
309
+ config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
310
+ ```
311
+
312
+ ### Production
313
+
314
+ ```ruby
315
+ # config/environments/production.rb
316
+ config.action_mailer.delivery_method = :smtp
317
+ config.action_mailer.smtp_settings = {
318
+ address: ENV['SMTP_HOST'],
319
+ port: ENV['SMTP_PORT'],
320
+ user_name: ENV['SMTP_USER'],
321
+ password: ENV['SMTP_PASSWORD']
322
+ }
323
+ ```
324
+
325
+ ### Custom Email Templates
326
+
327
+ Override templates in `app/views/rodauth/user_mailer/`:
328
+
329
+ ```erb
330
+ <%# app/views/rodauth/user_mailer/reset_password.text.erb %>
331
+ Hi <%= @account.email %>,
332
+
333
+ Someone requested a password reset for your account.
334
+
335
+ Reset your password: <%= @reset_password_url %>
336
+
337
+ If you didn't request this, ignore this email.
338
+ ```
339
+
340
+ ## Customizing Views
341
+
342
+ Generate views to customize:
343
+
344
+ ```bash
345
+ # Generate views for specific features
346
+ rails g pu:rodauth:views user --features login create_account reset_password
347
+
348
+ # Generate all views
349
+ rails g pu:rodauth:views user --all
350
+ ```
351
+
352
+ Views are copied to `app/views/rodauth/user/` and can be customized as standard ERB templates.
353
+
354
+ ## Multiple Account Types
355
+
356
+ ### Different Portals, Different Accounts
357
+
358
+ ```ruby
359
+ # packages/admin_portal/app/controllers/admin_portal/concerns/controller.rb
360
+ module AdminPortal
361
+ module Concerns
362
+ module Controller
363
+ extend ActiveSupport::Concern
364
+ include Plutonium::Portal::Controller
365
+ include Plutonium::Auth::Rodauth(:admin)
366
+ end
367
+ end
368
+ end
369
+
370
+ # packages/customer_portal/app/controllers/customer_portal/concerns/controller.rb
371
+ module CustomerPortal
372
+ module Concerns
373
+ module Controller
374
+ extend ActiveSupport::Concern
375
+ include Plutonium::Portal::Controller
376
+ include Plutonium::Auth::Rodauth(:customer)
377
+ end
378
+ end
379
+ end
380
+ ```
381
+
382
+ ### Shared Account Type
383
+
384
+ Multiple portals can share an account type:
385
+
386
+ ```ruby
387
+ # Both portals include the same auth module
388
+ include Plutonium::Auth::Rodauth(:user)
389
+ ```
390
+
391
+ ## Public Portals
392
+
393
+ For portals that don't require authentication, use `Plutonium::Auth::Public`:
394
+
395
+ ```ruby
396
+ # packages/public_portal/app/controllers/public_portal/concerns/controller.rb
397
+ module PublicPortal
398
+ module Concerns
399
+ module Controller
400
+ extend ActiveSupport::Concern
401
+ include Plutonium::Portal::Controller
402
+ include Plutonium::Auth::Public
403
+ end
404
+ end
405
+ end
406
+ ```
407
+
408
+ This provides a `current_user` method that returns `"Guest"`.
409
+
410
+ ## Two-Factor Authentication
411
+
412
+ ### Enable During Generation
413
+
414
+ ```bash
415
+ rails g pu:rodauth:account user --otp --recovery_codes
416
+ ```
417
+
418
+ ### Add to Existing Account
419
+
420
+ ```ruby
421
+ # app/rodauth/user_rodauth_plugin.rb
422
+ configure do
423
+ enable :otp, :recovery_codes
424
+
425
+ # Require 2FA
426
+ two_factor_auth_required? true
427
+ end
428
+ ```
429
+
430
+ Note: The `pu:rodauth:admin` generator automatically enables OTP and recovery codes.
431
+
432
+ ## Creating Accounts
433
+
434
+ ### Admin Accounts
435
+
436
+ Admin accounts are created via rake task (web registration is disabled):
437
+
438
+ ```bash
439
+ # Interactive prompt for email
440
+ rails rodauth:admin
441
+
442
+ # With EMAIL environment variable
443
+ EMAIL=admin@example.com rails rodauth:admin
444
+ ```
445
+
446
+ The task name matches the account name (e.g., `rails rodauth:admin` for an account named `admin`).
447
+
448
+ ### Programmatic Account Creation
449
+
450
+ For accounts with self-registration enabled, use internal requests:
451
+
452
+ ```ruby
453
+ # Create account via internal request
454
+ RodauthApp.rodauth(:user).create_account(
455
+ login: "user@example.com",
456
+ password: "secure_password"
457
+ )
458
+ ```
459
+
460
+ In seeds:
461
+
462
+ ```ruby
463
+ # db/seeds.rb
464
+ RodauthApp.rodauth(:user).create_account(
465
+ login: "user@example.com",
466
+ password: "password123"
467
+ )
468
+ ```
469
+
470
+ ## API Authentication
471
+
472
+ For JSON API authentication:
473
+
474
+ ```bash
475
+ rails g pu:rodauth:account api_user --api_only --jwt --jwt_refresh
476
+ ```
477
+
478
+ This enables:
479
+ - JWT token authentication
480
+ - Refresh tokens
481
+ - No session/cookie handling
482
+
483
+ ### Using JWT
484
+
485
+ ```bash
486
+ # Login
487
+ curl -X POST http://localhost:3000/api_users/login \
488
+ -H "Content-Type: application/json" \
489
+ -d '{"login": "user@example.com", "password": "secret"}'
490
+
491
+ # Response includes tokens
492
+ {"access_token": "...", "refresh_token": "..."}
493
+
494
+ # Authenticated requests
495
+ curl http://localhost:3000/api/posts \
496
+ -H "Authorization: Bearer <access_token>"
497
+ ```
498
+
499
+ ## Troubleshooting
500
+
501
+ ### Routes Not Working
502
+
503
+ Restart the server after installing Rodauth:
504
+
505
+ ```bash
506
+ bin/rails restart
507
+ ```
508
+
509
+ ### Emails Not Sending
510
+
511
+ Check Action Mailer configuration:
512
+
513
+ ```ruby
514
+ # Verify mailer config
515
+ Rails.application.config.action_mailer.delivery_method
516
+ Rails.application.config.action_mailer.default_url_options
517
+ ```
518
+
519
+ Use letter_opener in development to view emails in browser.
520
+
521
+ ### Session Issues
522
+
523
+ Clear session cookies in the browser, or for active_sessions feature:
524
+
525
+ ```ruby
526
+ # In rails runner
527
+ User.find_by(email: "user@example.com").active_session_keys.delete_all
528
+ ```
529
+
530
+ ### Migration Issues
531
+
532
+ Ensure all migrations have run:
533
+
534
+ ```bash
535
+ rails db:migrate:status
536
+ rails db:migrate
537
+ ```
538
+
539
+ ### Account Not Verified
540
+
541
+ For development, you can manually verify accounts:
542
+
543
+ ```ruby
544
+ # In rails runner
545
+ user = User.find_by(email: "user@example.com")
546
+ user.update!(status: 2) # 2 = verified
547
+ ```
548
+
549
+ ## Related
550
+
551
+ - [Authorization](./authorization)
552
+ - [Multi-tenancy](./multi-tenancy)