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
data/docs/modules/controller.md
DELETED
|
@@ -1,443 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: Controller Module
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
# Controller Module
|
|
6
|
-
|
|
7
|
-
The Controller module is your gateway to handling HTTP requests in Plutonium applications. It combines Rails' ActionController with Plutonium-specific enhancements to create a powerful, convention-over-configuration approach that eliminates boilerplate while providing enterprise-grade features like authorization and multi-tenancy.
|
|
8
|
-
|
|
9
|
-
::: tip Module Organization
|
|
10
|
-
Controller functionality is distributed across multiple focused modules:
|
|
11
|
-
- `lib/plutonium/core/controller.rb` - Foundation and core utilities
|
|
12
|
-
- `lib/plutonium/resource/controller.rb` - Complete CRUD operations
|
|
13
|
-
- `lib/plutonium/portal/controller.rb` - Portal-specific features and multi-tenancy
|
|
14
|
-
:::
|
|
15
|
-
|
|
16
|
-
## Core Philosophy
|
|
17
|
-
|
|
18
|
-
Plutonium's controller system is built on three fundamental principles:
|
|
19
|
-
|
|
20
|
-
- **Convention over Configuration**: Intelligent defaults that work out of the box with minimal setup
|
|
21
|
-
- **Modular Architecture**: Mix and match functionality based on your needs
|
|
22
|
-
- **Enterprise Readiness**: Built-in authentication, authorization and multi-tenancy
|
|
23
|
-
|
|
24
|
-
## Understanding Resource Registration
|
|
25
|
-
|
|
26
|
-
Before diving into controllers, it's crucial to understand how Plutonium connects your resources to the web through registration and routing.
|
|
27
|
-
|
|
28
|
-
### Registering Resources
|
|
29
|
-
|
|
30
|
-
Resources must be registered with each portal to become accessible through the web interface:
|
|
31
|
-
|
|
32
|
-
```ruby
|
|
33
|
-
# packages/admin_portal/config/routes.rb
|
|
34
|
-
AdminPortal::Engine.routes.draw do
|
|
35
|
-
root to: "dashboard#index"
|
|
36
|
-
|
|
37
|
-
# Basic resource registration
|
|
38
|
-
register_resource User
|
|
39
|
-
register_resource Post
|
|
40
|
-
register_resource Comment
|
|
41
|
-
|
|
42
|
-
# Advanced registration with options
|
|
43
|
-
register_resource Profile, singular: true # Creates singular routes
|
|
44
|
-
register_resource Report do
|
|
45
|
-
# Add custom routes alongside the standard ones
|
|
46
|
-
member do
|
|
47
|
-
get :download
|
|
48
|
-
post :regenerate
|
|
49
|
-
end
|
|
50
|
-
end
|
|
51
|
-
end
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
### What Registration Gives You
|
|
55
|
-
|
|
56
|
-
When you register a resource, Plutonium automatically creates:
|
|
57
|
-
|
|
58
|
-
1. **Complete CRUD routes**: All standard RESTful endpoints
|
|
59
|
-
2. **Nested association routes**: Based on your model's `has_many` relationships
|
|
60
|
-
3. **Interactive action routes**: For custom business operations
|
|
61
|
-
4. **Entity-scoped routes**: If your portal uses multi-tenancy
|
|
62
|
-
|
|
63
|
-
```ruby
|
|
64
|
-
# This simple registration:
|
|
65
|
-
register_resource Post
|
|
66
|
-
|
|
67
|
-
# Automatically generates:
|
|
68
|
-
# GET /posts # index - list all posts
|
|
69
|
-
# GET /posts/new # new - form for creating posts
|
|
70
|
-
# POST /posts # create - handle post creation
|
|
71
|
-
# GET /posts/:id # show - display a specific post
|
|
72
|
-
# GET /posts/:id/edit # edit - form for editing posts
|
|
73
|
-
# PATCH /posts/:id # update - handle post updates
|
|
74
|
-
# DELETE /posts/:id # destroy - delete posts
|
|
75
|
-
|
|
76
|
-
# Plus interactive action routes:
|
|
77
|
-
# GET /posts/resource_actions/:interactive_action # Resource-level actions
|
|
78
|
-
# POST /posts/resource_actions/:interactive_action
|
|
79
|
-
# GET /posts/:id/record_actions/:interactive_action # Individual record actions
|
|
80
|
-
# POST /posts/:id/record_actions/:interactive_action
|
|
81
|
-
|
|
82
|
-
# Plus nested routes for associations (if Post has_many :comments):
|
|
83
|
-
# GET /posts/:post_id/nested_comments
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
### Entity Scoping in Routes
|
|
87
|
-
|
|
88
|
-
If your portal is scoped to an entity (like Organization), all routes are automatically nested:
|
|
89
|
-
|
|
90
|
-
```ruby
|
|
91
|
-
# Engine configuration
|
|
92
|
-
class AdminPortal::Engine < Rails::Engine
|
|
93
|
-
include Plutonium::Portal::Engine
|
|
94
|
-
scope_to_entity Organization, strategy: :path
|
|
95
|
-
end
|
|
96
|
-
|
|
97
|
-
# Your routes become:
|
|
98
|
-
# GET /:organization_id/posts
|
|
99
|
-
# GET /:organization_id/posts/:id
|
|
100
|
-
# All data is automatically scoped to the organization
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
## Controller Components
|
|
104
|
-
|
|
105
|
-
### Base Controller: The Foundation
|
|
106
|
-
|
|
107
|
-
Every Plutonium controller starts with `Plutonium::Core::Controller`, which provides essential framework integration:
|
|
108
|
-
|
|
109
|
-
```ruby
|
|
110
|
-
# app/controllers/application_controller.rb
|
|
111
|
-
class ApplicationController < ActionController::Base
|
|
112
|
-
include Plutonium::Core::Controller
|
|
113
|
-
|
|
114
|
-
# You now have access to all Plutonium controller features
|
|
115
|
-
end
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
**Key Capabilities:**
|
|
119
|
-
- **Smart URL Generation**: Automatic resource URL creation with proper routing
|
|
120
|
-
- **Enhanced Flash Messages**: Extended message types (`:success`, `:warning`, `:error`)
|
|
121
|
-
- **View Integration**: Automatic view path resolution and layout management
|
|
122
|
-
- **Resource Management**: Access to registered resources and metadata
|
|
123
|
-
- **CSRF Protection**: Automatic CSRF protection with smart handling for API requests
|
|
124
|
-
|
|
125
|
-
**Essential Methods:**
|
|
126
|
-
```ruby
|
|
127
|
-
# URL generation that understands your resource structure
|
|
128
|
-
resource_url_for(@user) # => "/users/1"
|
|
129
|
-
resource_url_for(@user, action: :edit) # => "/users/1/edit"
|
|
130
|
-
resource_url_for(User) # => "/users"
|
|
131
|
-
|
|
132
|
-
# Build complex URL arguments for nested resources
|
|
133
|
-
resource_url_args_for(@user, Post) # => {controller: "/users/posts", user_id: 1}
|
|
134
|
-
|
|
135
|
-
# Access application metadata
|
|
136
|
-
registered_resources # => [User, Post, Comment, ...]
|
|
137
|
-
|
|
138
|
-
# Page title management
|
|
139
|
-
set_page_title("User Profile")
|
|
140
|
-
make_page_title("Dashboard") # => "Dashboard | MyApp"
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
### Resource Controller: Complete CRUD Operations
|
|
144
|
-
|
|
145
|
-
The Resource Controller provides full CRUD functionality with zero configuration:
|
|
146
|
-
|
|
147
|
-
```ruby
|
|
148
|
-
class PostsController < ApplicationController
|
|
149
|
-
include Plutonium::Resource::Controller
|
|
150
|
-
|
|
151
|
-
# That's it! All CRUD actions are automatically available:
|
|
152
|
-
# index, show, new, create, edit, update, destroy
|
|
153
|
-
end
|
|
154
|
-
```
|
|
155
|
-
|
|
156
|
-
**What You Get Automatically:**
|
|
157
|
-
- **Complete CRUD Operations**: All RESTful actions implemented
|
|
158
|
-
- **Smart Parameter Handling**: Automatic parameter processing and validation
|
|
159
|
-
- **Authorization Integration**: Policy checks on every action
|
|
160
|
-
- **Query Integration**: Automatic filtering, searching, and sorting
|
|
161
|
-
- **Interaction Support**: Business logic through interaction classes
|
|
162
|
-
- **Nested Resource Support**: Handles parent-child relationships automatically
|
|
163
|
-
- **Pagination**: Built-in pagination with sensible defaults
|
|
164
|
-
|
|
165
|
-
**Key Methods Available:**
|
|
166
|
-
```ruby
|
|
167
|
-
# Resource management
|
|
168
|
-
resource_class # => Post
|
|
169
|
-
resource_record! # => @post (raises if not found)
|
|
170
|
-
resource_record? # => @post or nil
|
|
171
|
-
current_parent # => parent record for nested routes
|
|
172
|
-
|
|
173
|
-
# Parameter handling with automatic authorization
|
|
174
|
-
resource_params # => processed params with proper scoping
|
|
175
|
-
submitted_resource_params # => raw submitted parameters
|
|
176
|
-
|
|
177
|
-
# View builders for consistent UI
|
|
178
|
-
build_form # => form builder for the resource
|
|
179
|
-
build_detail # => detail view builder
|
|
180
|
-
build_collection # => collection view builder
|
|
181
|
-
|
|
182
|
-
# Query objects for data access
|
|
183
|
-
current_query_object # => handles filtering, searching, sorting
|
|
184
|
-
```
|
|
185
|
-
|
|
186
|
-
### Portal Controller: Multi-Tenancy and Segmentation
|
|
187
|
-
|
|
188
|
-
Portal Controllers provide specialized functionality for multi-tenant applications and user segmentation:
|
|
189
|
-
|
|
190
|
-
```ruby
|
|
191
|
-
module AdminPortal
|
|
192
|
-
class PostsController < ResourceController
|
|
193
|
-
include AdminPortal::Concerns::Controller
|
|
194
|
-
|
|
195
|
-
# Automatically inherits from ::PostsController
|
|
196
|
-
# Includes portal-specific concerns and scoping
|
|
197
|
-
end
|
|
198
|
-
end
|
|
199
|
-
```
|
|
200
|
-
|
|
201
|
-
## Controller Concerns: Modular Functionality
|
|
202
|
-
|
|
203
|
-
Plutonium's controller system uses several modular concerns that provide specific capabilities:
|
|
204
|
-
|
|
205
|
-
### Bootable: Initialization and Setup
|
|
206
|
-
|
|
207
|
-
Handles the foundational setup that makes everything work smoothly:
|
|
208
|
-
|
|
209
|
-
```ruby
|
|
210
|
-
# Automatically included - provides:
|
|
211
|
-
# ✓ Package detection and engine resolution
|
|
212
|
-
# ✓ View path configuration for proper template loading
|
|
213
|
-
# ✓ Flash message type registration
|
|
214
|
-
|
|
215
|
-
# Available methods:
|
|
216
|
-
current_package # => current package module (e.g., AdminPortal)
|
|
217
|
-
current_engine # => current Rails engine instance
|
|
218
|
-
```
|
|
219
|
-
|
|
220
|
-
### Entity Scoping: Multi-Tenancy Made Simple
|
|
221
|
-
|
|
222
|
-
Provides powerful multi-tenancy capabilities with automatic data scoping:
|
|
223
|
-
|
|
224
|
-
```ruby
|
|
225
|
-
# Check if the controller is scoped to an entity
|
|
226
|
-
scoped_to_entity? # => true/false
|
|
227
|
-
|
|
228
|
-
# Get the current scoped entity
|
|
229
|
-
current_scoped_entity # => current organization/tenant
|
|
230
|
-
|
|
231
|
-
# Access scoping configuration
|
|
232
|
-
scoped_entity_strategy # => :path, :subdomain, :custom_method
|
|
233
|
-
scoped_entity_param_key # => :organization_id
|
|
234
|
-
scoped_entity_class # => Organization
|
|
235
|
-
```
|
|
236
|
-
|
|
237
|
-
#### Setting Up Entity Scoping
|
|
238
|
-
|
|
239
|
-
Configure scoping at the engine level and implement custom strategies as needed:
|
|
240
|
-
|
|
241
|
-
```ruby
|
|
242
|
-
# 1. Configure in your engine
|
|
243
|
-
class AdminPortal::Engine < Rails::Engine
|
|
244
|
-
include Plutonium::Portal::Engine
|
|
245
|
-
|
|
246
|
-
# Path-based scoping (URLs like /organizations/123/posts)
|
|
247
|
-
scope_to_entity Organization, strategy: :path
|
|
248
|
-
|
|
249
|
-
# Or custom strategy for more control
|
|
250
|
-
scope_to_entity Organization, strategy: :current_organization
|
|
251
|
-
end
|
|
252
|
-
|
|
253
|
-
# 2. For custom strategies, implement the method in your controller concern
|
|
254
|
-
module AdminPortal::Concerns::Controller
|
|
255
|
-
private
|
|
256
|
-
|
|
257
|
-
# Method name MUST match the strategy name exactly
|
|
258
|
-
def current_organization
|
|
259
|
-
# Custom logic - could be subdomain, session, JWT, etc.
|
|
260
|
-
@current_organization ||= begin
|
|
261
|
-
# Primary: subdomain lookup
|
|
262
|
-
Organization.find_by(subdomain: request.subdomain) ||
|
|
263
|
-
# Fallback: session-based lookup
|
|
264
|
-
current_user.organizations.find(session[:org_id])
|
|
265
|
-
end
|
|
266
|
-
end
|
|
267
|
-
end
|
|
268
|
-
```
|
|
269
|
-
|
|
270
|
-
### Authorizable: Comprehensive Security
|
|
271
|
-
|
|
272
|
-
Integrates with ActionPolicy to provide robust authorization throughout your application:
|
|
273
|
-
|
|
274
|
-
```ruby
|
|
275
|
-
# Authorization methods that work automatically
|
|
276
|
-
authorize_current!(resource_record!) # Check permissions for current resource
|
|
277
|
-
authorize_current!(resource_class) # Check permissions for resource class
|
|
278
|
-
authorize_current!(record, to: :interactive_action?) # Check specific action permission
|
|
279
|
-
|
|
280
|
-
# Policy access and queries
|
|
281
|
-
current_policy # Get policy for current resource
|
|
282
|
-
current_policy.allowed_to?(:show?) # Check if action is allowed
|
|
283
|
-
policy_for(@user) # Get policy for specific resource
|
|
284
|
-
authorized_resource_scope(User) # Get authorized scope for resource class
|
|
285
|
-
|
|
286
|
-
# Permission helpers
|
|
287
|
-
permitted_attributes # Get allowed attributes for current action
|
|
288
|
-
permitted_associations # Get allowed associations
|
|
289
|
-
```
|
|
290
|
-
|
|
291
|
-
**Authorization Examples:**
|
|
292
|
-
```ruby
|
|
293
|
-
class PostsController < ApplicationController
|
|
294
|
-
include Plutonium::Resource::Controller
|
|
295
|
-
|
|
296
|
-
def index
|
|
297
|
-
# Authorization is automatically checked against PostPolicy#index?
|
|
298
|
-
# No additional code needed
|
|
299
|
-
end
|
|
300
|
-
|
|
301
|
-
def custom_publish
|
|
302
|
-
# Check custom permissions
|
|
303
|
-
authorize_current!(resource_record!, to: :publish?)
|
|
304
|
-
|
|
305
|
-
# Your business logic here
|
|
306
|
-
PublishPostInteraction.call(post: resource_record!)
|
|
307
|
-
|
|
308
|
-
redirect_to resource_url_for(resource_record!), success: "Post published!"
|
|
309
|
-
end
|
|
310
|
-
|
|
311
|
-
def conditional_action
|
|
312
|
-
# Check permissions before taking action
|
|
313
|
-
if current_policy.allowed_to?(:edit?)
|
|
314
|
-
redirect_to resource_url_for(resource_record!, action: :edit)
|
|
315
|
-
else
|
|
316
|
-
redirect_to resource_url_for(resource_record!),
|
|
317
|
-
warning: "You don't have permission to edit this post"
|
|
318
|
-
end
|
|
319
|
-
end
|
|
320
|
-
|
|
321
|
-
private
|
|
322
|
-
|
|
323
|
-
def resource_params
|
|
324
|
-
# Only permit attributes that the policy allows
|
|
325
|
-
params.require(:post).permit(*permitted_attributes)
|
|
326
|
-
end
|
|
327
|
-
end
|
|
328
|
-
```
|
|
329
|
-
|
|
330
|
-
## Advanced Usage Patterns
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
### Nested Resources: Automatic Relationship Handling
|
|
334
|
-
|
|
335
|
-
Plutonium automatically handles nested resources based on your ActiveRecord associations:
|
|
336
|
-
|
|
337
|
-
```ruby
|
|
338
|
-
# Your models define the relationships
|
|
339
|
-
class User < ResourceRecord
|
|
340
|
-
has_many :posts
|
|
341
|
-
has_many :comments
|
|
342
|
-
end
|
|
343
|
-
|
|
344
|
-
class Post < ResourceRecord
|
|
345
|
-
belongs_to :user
|
|
346
|
-
has_many :comments
|
|
347
|
-
end
|
|
348
|
-
|
|
349
|
-
# Register resources normally
|
|
350
|
-
AdminPortal::Engine.routes.draw do
|
|
351
|
-
register_resource User
|
|
352
|
-
register_resource Post
|
|
353
|
-
register_resource Comment
|
|
354
|
-
end
|
|
355
|
-
|
|
356
|
-
# Plutonium automatically creates nested routes:
|
|
357
|
-
# /users/:user_id/nested_posts
|
|
358
|
-
# /users/:user_id/nested_comments
|
|
359
|
-
# /posts/:post_id/nested_comments
|
|
360
|
-
```
|
|
361
|
-
|
|
362
|
-
**Automatic Parent Resolution:**
|
|
363
|
-
```ruby
|
|
364
|
-
# In a nested route like /users/123/nested_posts/456
|
|
365
|
-
current_parent # => User.find(123) - automatically resolved
|
|
366
|
-
parent_route_param # => :user_id
|
|
367
|
-
parent_input_param # => :user (the belongs_to association name)
|
|
368
|
-
|
|
369
|
-
# Parameters are automatically merged
|
|
370
|
-
resource_params # => includes user: current_parent
|
|
371
|
-
```
|
|
372
|
-
|
|
373
|
-
**Smart URL Generation:**
|
|
374
|
-
```ruby
|
|
375
|
-
# From within a nested controller context
|
|
376
|
-
resource_url_for(Post) # => "/users/123/nested_posts"
|
|
377
|
-
resource_url_for(@post) # => "/users/123/nested_posts/456"
|
|
378
|
-
resource_url_for(@post, action: :edit) # => "/users/123/nested_posts/456/edit"
|
|
379
|
-
|
|
380
|
-
# Explicit parent specification
|
|
381
|
-
resource_url_for(Post, parent: @user) # => "/users/123/nested_posts"
|
|
382
|
-
```
|
|
383
|
-
|
|
384
|
-
### Multi-Format Response Handling
|
|
385
|
-
|
|
386
|
-
Plutonium automatically handles different response formats for you.
|
|
387
|
-
It currently supports HTML, JSON, and Turbo Streams.
|
|
388
|
-
|
|
389
|
-
### CSRF Protection
|
|
390
|
-
|
|
391
|
-
Plutonium provides intelligent CSRF (Cross-Site Request Forgery) protection that automatically adapts to different request types:
|
|
392
|
-
|
|
393
|
-
```ruby
|
|
394
|
-
# Automatically configured in Plutonium::Core::Controller
|
|
395
|
-
protect_from_forgery with: :null_session, if: -> { request.headers['Authorization'].present? }
|
|
396
|
-
```
|
|
397
|
-
|
|
398
|
-
**How It Works:**
|
|
399
|
-
- **Session-based requests** (typical web forms, SPA AJAX calls): Full CSRF protection is enforced
|
|
400
|
-
- **Token-based requests** (API calls with Authorization headers): CSRF protection is skipped using `:null_session`
|
|
401
|
-
|
|
402
|
-
**Security Benefits:**
|
|
403
|
-
- SPAs using session cookies remain protected against CSRF attacks
|
|
404
|
-
- API clients using Bearer tokens, Basic auth, or other Authorization headers bypass CSRF (as intended)
|
|
405
|
-
- No configuration needed - works automatically based on request characteristics
|
|
406
|
-
|
|
407
|
-
**Authorization Header Examples:**
|
|
408
|
-
```http
|
|
409
|
-
# These requests will skip CSRF protection:
|
|
410
|
-
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9...
|
|
411
|
-
Authorization: Basic dXNlcjpwYXNzd29yZA==
|
|
412
|
-
Authorization: ApiKey abc123
|
|
413
|
-
```
|
|
414
|
-
|
|
415
|
-
**For SPA Development:**
|
|
416
|
-
If your SPA uses session-based authentication, include CSRF tokens in your AJAX requests:
|
|
417
|
-
|
|
418
|
-
```javascript
|
|
419
|
-
// Include CSRF token in meta tags
|
|
420
|
-
<%= csrf_meta_tags %>
|
|
421
|
-
|
|
422
|
-
// Send token in AJAX requests
|
|
423
|
-
fetch('/api/posts', {
|
|
424
|
-
method: 'POST',
|
|
425
|
-
headers: {
|
|
426
|
-
'Content-Type': 'application/json',
|
|
427
|
-
'X-CSRF-Token': document.querySelector('[name="csrf-token"]').content
|
|
428
|
-
},
|
|
429
|
-
body: JSON.stringify(data)
|
|
430
|
-
})
|
|
431
|
-
```
|
|
432
|
-
|
|
433
|
-
## Related Modules
|
|
434
|
-
|
|
435
|
-
The Controller module works seamlessly with other Plutonium components:
|
|
436
|
-
|
|
437
|
-
- **[Core](./core.md)**: Foundation and essential utilities
|
|
438
|
-
- **[Resource Record](./resource_record.md)**: CRUD operations and resource management
|
|
439
|
-
- **[Portal](./portal.md)**: Multi-tenant portal functionality
|
|
440
|
-
- **[Authentication](./authentication.md)**: User authentication and session management
|
|
441
|
-
- **[Policy](./policy.md)**: Authorization and access control
|
|
442
|
-
- **[Interaction](./interaction.md)**: Business logic encapsulation
|
|
443
|
-
- **[Routing](./routing.md)**: Resource registration and route generation
|