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.
- checksums.yaml +4 -4
- data/# Plutonium: The pre-alpha demo.md +4 -2
- data/.claude/skills/assets/SKILL.md +416 -0
- data/.claude/skills/connect-resource/SKILL.md +112 -0
- data/.claude/skills/controller/SKILL.md +302 -0
- data/.claude/skills/create-resource/SKILL.md +240 -0
- data/.claude/skills/definition/SKILL.md +218 -0
- data/.claude/skills/definition-actions/SKILL.md +386 -0
- data/.claude/skills/definition-fields/SKILL.md +474 -0
- data/.claude/skills/definition-query/SKILL.md +334 -0
- data/.claude/skills/forms/SKILL.md +439 -0
- data/.claude/skills/installation/SKILL.md +300 -0
- data/.claude/skills/interaction/SKILL.md +382 -0
- data/.claude/skills/model/SKILL.md +267 -0
- data/.claude/skills/model-features/SKILL.md +286 -0
- data/.claude/skills/nested-resources/SKILL.md +274 -0
- data/.claude/skills/package/SKILL.md +191 -0
- data/.claude/skills/policy/SKILL.md +352 -0
- data/.claude/skills/portal/SKILL.md +400 -0
- data/.claude/skills/resource/SKILL.md +281 -0
- data/.claude/skills/rodauth/SKILL.md +452 -0
- data/.claude/skills/views/SKILL.md +563 -0
- data/Appraisals +46 -4
- data/CHANGELOG.md +32 -1
- data/app/assets/plutonium.css +2 -2
- data/config/brakeman.ignore +239 -0
- data/config/initializers/action_policy.rb +1 -1
- data/docs/.vitepress/config.ts +132 -47
- data/docs/concepts/architecture.md +226 -0
- data/docs/concepts/auto-detection.md +254 -0
- data/docs/concepts/index.md +61 -0
- data/docs/concepts/packages-portals.md +304 -0
- data/docs/concepts/resources.md +224 -0
- data/docs/cookbook/blog.md +412 -0
- data/docs/cookbook/index.md +289 -0
- data/docs/cookbook/saas.md +481 -0
- data/docs/getting-started/index.md +56 -0
- data/docs/getting-started/installation.md +146 -0
- data/docs/getting-started/tutorial/01-setup.md +118 -0
- data/docs/getting-started/tutorial/02-first-resource.md +180 -0
- data/docs/getting-started/tutorial/03-authentication.md +246 -0
- data/docs/getting-started/tutorial/04-authorization.md +170 -0
- data/docs/getting-started/tutorial/05-custom-actions.md +202 -0
- data/docs/getting-started/tutorial/06-nested-resources.md +147 -0
- data/docs/getting-started/tutorial/07-customizing-ui.md +254 -0
- data/docs/getting-started/tutorial/index.md +64 -0
- data/docs/guides/adding-resources.md +420 -0
- data/docs/guides/authentication.md +551 -0
- data/docs/guides/authorization.md +468 -0
- data/docs/guides/creating-packages.md +380 -0
- data/docs/guides/custom-actions.md +523 -0
- data/docs/guides/index.md +45 -0
- data/docs/guides/multi-tenancy.md +302 -0
- data/docs/guides/nested-resources.md +411 -0
- data/docs/guides/search-filtering.md +266 -0
- data/docs/guides/theming.md +321 -0
- data/docs/index.md +67 -26
- data/docs/public/CLAUDE.md +64 -21
- data/docs/reference/assets/index.md +496 -0
- data/docs/reference/controller/index.md +363 -0
- data/docs/reference/definition/actions.md +400 -0
- data/docs/reference/definition/fields.md +350 -0
- data/docs/reference/definition/index.md +252 -0
- data/docs/reference/definition/query.md +342 -0
- data/docs/reference/generators/index.md +469 -0
- data/docs/reference/index.md +49 -0
- data/docs/reference/interaction/index.md +445 -0
- data/docs/reference/model/features.md +248 -0
- data/docs/reference/model/index.md +219 -0
- data/docs/reference/policy/index.md +385 -0
- data/docs/reference/portal/index.md +382 -0
- data/docs/reference/views/forms.md +396 -0
- data/docs/reference/views/index.md +479 -0
- data/gemfiles/rails_7.gemfile +9 -2
- data/gemfiles/rails_7.gemfile.lock +146 -111
- data/gemfiles/rails_8.0.gemfile +20 -0
- data/gemfiles/rails_8.0.gemfile.lock +417 -0
- data/gemfiles/rails_8.1.gemfile +20 -0
- data/gemfiles/rails_8.1.gemfile.lock +419 -0
- data/lib/generators/pu/gem/dotenv/templates/.env +2 -0
- data/lib/generators/pu/gem/dotenv/templates/config/initializers/001_ensure_required_env.rb +3 -1
- data/lib/generators/pu/lib/plutonium_generators/model_generator_base.rb +13 -16
- data/lib/generators/pu/pkg/portal/USAGE +65 -0
- data/lib/generators/pu/pkg/portal/portal_generator.rb +22 -9
- data/lib/generators/pu/res/conn/USAGE +71 -0
- data/lib/generators/pu/res/model/USAGE +106 -110
- data/lib/generators/pu/res/model/templates/model.rb.tt +6 -2
- data/lib/generators/pu/res/scaffold/USAGE +85 -0
- data/lib/generators/pu/rodauth/install_generator.rb +2 -6
- data/lib/generators/pu/rodauth/templates/config/initializers/url_options.rb +17 -0
- data/lib/generators/pu/skills/sync/USAGE +14 -0
- data/lib/generators/pu/skills/sync/sync_generator.rb +66 -0
- data/lib/plutonium/action_policy/sti_policy_lookup.rb +1 -1
- data/lib/plutonium/core/controller.rb +2 -2
- data/lib/plutonium/interaction/base.rb +1 -0
- data/lib/plutonium/package/engine.rb +2 -2
- data/lib/plutonium/query/adhoc_block.rb +6 -2
- data/lib/plutonium/query/model_scope.rb +1 -1
- data/lib/plutonium/railtie.rb +4 -0
- data/lib/plutonium/resource/controllers/crud_actions/index_action.rb +1 -1
- data/lib/plutonium/resource/query_object.rb +38 -8
- data/lib/plutonium/ui/table/components/scopes_bar.rb +39 -34
- data/lib/plutonium/version.rb +1 -1
- data/lib/tasks/release.rake +19 -4
- data/package.json +1 -1
- metadata +76 -39
- data/brakeman.ignore +0 -28
- data/docs/api-examples.md +0 -49
- data/docs/guide/claude-code-guide.md +0 -74
- data/docs/guide/deep-dive/authorization.md +0 -189
- data/docs/guide/deep-dive/multitenancy.md +0 -256
- data/docs/guide/deep-dive/resources.md +0 -390
- data/docs/guide/getting-started/01-installation.md +0 -165
- data/docs/guide/index.md +0 -28
- data/docs/guide/introduction/01-what-is-plutonium.md +0 -211
- data/docs/guide/introduction/02-core-concepts.md +0 -440
- data/docs/guide/tutorial/01-project-setup.md +0 -75
- data/docs/guide/tutorial/02-creating-a-feature-package.md +0 -45
- data/docs/guide/tutorial/03-defining-resources.md +0 -90
- data/docs/guide/tutorial/04-creating-a-portal.md +0 -101
- data/docs/guide/tutorial/05-customizing-the-ui.md +0 -128
- data/docs/guide/tutorial/06-adding-custom-actions.md +0 -101
- data/docs/guide/tutorial/07-implementing-authorization.md +0 -90
- data/docs/markdown-examples.md +0 -85
- data/docs/modules/action.md +0 -244
- data/docs/modules/authentication.md +0 -236
- data/docs/modules/configuration.md +0 -599
- data/docs/modules/controller.md +0 -443
- data/docs/modules/core.md +0 -316
- data/docs/modules/definition.md +0 -1308
- data/docs/modules/display.md +0 -759
- data/docs/modules/form.md +0 -495
- data/docs/modules/generator.md +0 -400
- data/docs/modules/index.md +0 -167
- data/docs/modules/interaction.md +0 -642
- data/docs/modules/package.md +0 -151
- data/docs/modules/policy.md +0 -176
- data/docs/modules/portal.md +0 -710
- data/docs/modules/query.md +0 -297
- data/docs/modules/resource_record.md +0 -618
- data/docs/modules/routing.md +0 -690
- data/docs/modules/table.md +0 -301
- 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)
|