plutonium 0.33.1 → 0.34.0

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