plutonium 0.23.4 → 0.23.5
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/app/assets/plutonium.css +2 -2
- data/config/initializers/sqlite_json_alias.rb +1 -1
- data/docs/.vitepress/config.ts +60 -19
- data/docs/guide/cursor-rules.md +75 -0
- data/docs/guide/deep-dive/authorization.md +189 -0
- data/docs/guide/{getting-started → deep-dive}/resources.md +137 -0
- data/docs/guide/getting-started/{installation.md → 01-installation.md} +0 -105
- data/docs/guide/index.md +28 -0
- data/docs/guide/introduction/02-core-concepts.md +440 -0
- data/docs/guide/tutorial/01-project-setup.md +75 -0
- data/docs/guide/tutorial/02-creating-a-feature-package.md +45 -0
- data/docs/guide/tutorial/03-defining-resources.md +90 -0
- data/docs/guide/tutorial/04-creating-a-portal.md +101 -0
- data/docs/guide/tutorial/05-customizing-the-ui.md +128 -0
- data/docs/guide/tutorial/06-adding-custom-actions.md +101 -0
- data/docs/guide/tutorial/07-implementing-authorization.md +90 -0
- data/docs/index.md +24 -31
- data/docs/modules/action.md +190 -0
- data/docs/modules/authentication.md +236 -0
- data/docs/modules/configuration.md +599 -0
- data/docs/modules/controller.md +398 -0
- data/docs/modules/core.md +316 -0
- data/docs/modules/definition.md +876 -0
- data/docs/modules/display.md +759 -0
- data/docs/modules/form.md +605 -0
- data/docs/modules/generator.md +288 -0
- data/docs/modules/index.md +167 -0
- data/docs/modules/interaction.md +470 -0
- data/docs/modules/package.md +151 -0
- data/docs/modules/policy.md +176 -0
- data/docs/modules/portal.md +710 -0
- data/docs/modules/query.md +287 -0
- data/docs/modules/resource_record.md +618 -0
- data/docs/modules/routing.md +641 -0
- data/docs/modules/table.md +293 -0
- data/docs/modules/ui.md +631 -0
- data/docs/public/plutonium.mdc +667 -0
- data/lib/generators/pu/core/assets/assets_generator.rb +0 -5
- data/lib/plutonium/ui/display/resource.rb +7 -2
- data/lib/plutonium/ui/table/resource.rb +8 -3
- data/lib/plutonium/version.rb +1 -1
- metadata +36 -9
- data/docs/guide/getting-started/authorization.md +0 -296
- data/docs/guide/getting-started/core-concepts.md +0 -432
- data/docs/guide/getting-started/index.md +0 -21
- data/docs/guide/tutorial.md +0 -401
- /data/docs/guide/{what-is-plutonium.md → introduction/01-what-is-plutonium.md} +0 -0
@@ -59,9 +59,14 @@ module Plutonium
|
|
59
59
|
column_definition = resource_definition.defined_columns[name] || {}
|
60
60
|
column_options = column_definition[:options] || {}
|
61
61
|
|
62
|
+
# Check for conditional rendering
|
63
|
+
condition = column_options[:condition] || display_options[:condition] || field_options[:condition]
|
64
|
+
conditionally_hidden = condition && !instance_exec(&condition)
|
65
|
+
next if conditionally_hidden
|
66
|
+
|
62
67
|
tag = column_options[:as] || display_definition[:as] || field_options[:as]
|
63
|
-
display_tag_attributes = display_options.except(:wrapper, :as)
|
64
|
-
column_tag_attributes = column_options.except(:wrapper, :as, :align)
|
68
|
+
display_tag_attributes = display_options.except(:wrapper, :as, :condition)
|
69
|
+
column_tag_attributes = column_options.except(:wrapper, :as, :align, :condition)
|
65
70
|
tag_attributes = display_tag_attributes.merge(column_tag_attributes)
|
66
71
|
tag_block = column_definition[:block] || ->(wrapped_object, key) {
|
67
72
|
f = wrapped_object.field(key)
|
@@ -69,7 +74,7 @@ module Plutonium
|
|
69
74
|
f.send(:"#{tag}_tag", **tag_attributes)
|
70
75
|
}
|
71
76
|
|
72
|
-
field_options = field_options.merge(**column_options.slice(:align))
|
77
|
+
field_options = field_options.except(:condition).merge(**column_options.slice(:align))
|
73
78
|
table.column name,
|
74
79
|
**field_options,
|
75
80
|
sort_params: current_query_object.sort_params_for(name),
|
data/lib/plutonium/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: plutonium
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.23.
|
4
|
+
version: 0.23.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stefan Froelich
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-
|
11
|
+
date: 2025-06-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: zeitwerk
|
@@ -493,21 +493,48 @@ files:
|
|
493
493
|
- docs/.vitepress/theme/custom.css
|
494
494
|
- docs/.vitepress/theme/index.ts
|
495
495
|
- docs/api-examples.md
|
496
|
-
- docs/guide/
|
497
|
-
- docs/guide/
|
498
|
-
- docs/guide/
|
499
|
-
- docs/guide/getting-started/installation.md
|
500
|
-
- docs/guide/
|
501
|
-
- docs/guide/
|
502
|
-
- docs/guide/
|
496
|
+
- docs/guide/cursor-rules.md
|
497
|
+
- docs/guide/deep-dive/authorization.md
|
498
|
+
- docs/guide/deep-dive/resources.md
|
499
|
+
- docs/guide/getting-started/01-installation.md
|
500
|
+
- docs/guide/index.md
|
501
|
+
- docs/guide/introduction/01-what-is-plutonium.md
|
502
|
+
- docs/guide/introduction/02-core-concepts.md
|
503
|
+
- docs/guide/tutorial/01-project-setup.md
|
504
|
+
- docs/guide/tutorial/02-creating-a-feature-package.md
|
505
|
+
- docs/guide/tutorial/03-defining-resources.md
|
506
|
+
- docs/guide/tutorial/04-creating-a-portal.md
|
507
|
+
- docs/guide/tutorial/05-customizing-the-ui.md
|
508
|
+
- docs/guide/tutorial/06-adding-custom-actions.md
|
509
|
+
- docs/guide/tutorial/07-implementing-authorization.md
|
503
510
|
- docs/index.md
|
504
511
|
- docs/markdown-examples.md
|
512
|
+
- docs/modules/action.md
|
513
|
+
- docs/modules/authentication.md
|
514
|
+
- docs/modules/configuration.md
|
515
|
+
- docs/modules/controller.md
|
516
|
+
- docs/modules/core.md
|
517
|
+
- docs/modules/definition.md
|
518
|
+
- docs/modules/display.md
|
519
|
+
- docs/modules/form.md
|
520
|
+
- docs/modules/generator.md
|
521
|
+
- docs/modules/index.md
|
522
|
+
- docs/modules/interaction.md
|
523
|
+
- docs/modules/package.md
|
524
|
+
- docs/modules/policy.md
|
525
|
+
- docs/modules/portal.md
|
526
|
+
- docs/modules/query.md
|
527
|
+
- docs/modules/resource_record.md
|
528
|
+
- docs/modules/routing.md
|
529
|
+
- docs/modules/table.md
|
530
|
+
- docs/modules/ui.md
|
505
531
|
- docs/public/android-chrome-192x192.png
|
506
532
|
- docs/public/android-chrome-512x512.png
|
507
533
|
- docs/public/apple-touch-icon.png
|
508
534
|
- docs/public/favicon-16x16.png
|
509
535
|
- docs/public/favicon-32x32.png
|
510
536
|
- docs/public/favicon.ico
|
537
|
+
- docs/public/plutonium.mdc
|
511
538
|
- docs/public/plutonium.png
|
512
539
|
- docs/public/site.webmanifest
|
513
540
|
- docs/public/templates/base.rb
|
@@ -1,296 +0,0 @@
|
|
1
|
-
# Authorization and Access Control
|
2
|
-
|
3
|
-
Plutonium provides a robust authorization system built on top of [Action Policy](https://actionpolicy.evilmartians.io/), offering fine-grained access control, resource scoping, and entity-based authorization.
|
4
|
-
|
5
|
-
## Overview
|
6
|
-
|
7
|
-
Authorization in Plutonium operates at multiple levels:
|
8
|
-
- Resource-level policies
|
9
|
-
- Action-based permissions
|
10
|
-
- Entity-based scoping
|
11
|
-
- Attribute-level access control
|
12
|
-
|
13
|
-
## Basic Policy Definition
|
14
|
-
|
15
|
-
Every resource in Plutonium requires a policy. Here's a basic example:
|
16
|
-
|
17
|
-
```ruby
|
18
|
-
class BlogPolicy < ResourcePolicy
|
19
|
-
# Core CRUD Permissions
|
20
|
-
|
21
|
-
def create?
|
22
|
-
# All authenticated users can create blogs
|
23
|
-
true
|
24
|
-
end
|
25
|
-
|
26
|
-
def read?
|
27
|
-
# Allow anyone to read blogs
|
28
|
-
true
|
29
|
-
end
|
30
|
-
|
31
|
-
def update?
|
32
|
-
# Allow only the blog owner to update
|
33
|
-
owner?
|
34
|
-
end
|
35
|
-
|
36
|
-
def destroy?
|
37
|
-
# Allow only the blog owner or admins to destroy
|
38
|
-
owner? || user.admin?
|
39
|
-
end
|
40
|
-
|
41
|
-
# Attribute Control
|
42
|
-
|
43
|
-
def permitted_attributes_for_create
|
44
|
-
[:title, :content, :category]
|
45
|
-
end
|
46
|
-
|
47
|
-
def permitted_attributes_for_read
|
48
|
-
[:title, :content, :category, :created_at, :updated_at, :user_id]
|
49
|
-
end
|
50
|
-
|
51
|
-
def permitted_attributes_for_update
|
52
|
-
[:title, :content, :category]
|
53
|
-
end
|
54
|
-
|
55
|
-
# Association Access
|
56
|
-
|
57
|
-
def permitted_associations
|
58
|
-
[:comments]
|
59
|
-
end
|
60
|
-
|
61
|
-
private
|
62
|
-
|
63
|
-
def owner?
|
64
|
-
record.user_id == user.id
|
65
|
-
end
|
66
|
-
end
|
67
|
-
```
|
68
|
-
|
69
|
-
## Default Behaviors in Plutonium Policies
|
70
|
-
|
71
|
-
::: info Overview
|
72
|
-
Plutonium's Policy system implements a secure-by-default pattern with clear inheritance chains for both permissions and attribute access.
|
73
|
-
:::
|
74
|
-
|
75
|
-
### Permission Defaults
|
76
|
-
|
77
|
-
Permission methods follow two key patterns: core permissions that default to `false`, and derived permissions that inherit from core ones.
|
78
|
-
|
79
|
-
#### Core Permission Chain
|
80
|
-
|
81
|
-
```mermaid
|
82
|
-
graph TD
|
83
|
-
subgraph Core Permissions
|
84
|
-
A[create? ❌] --> B[update? ❌]
|
85
|
-
A --> C[destroy? ❌]
|
86
|
-
D[read? ❌] --> E[index? ❌]
|
87
|
-
D --> F[show? ❌]
|
88
|
-
end
|
89
|
-
```
|
90
|
-
|
91
|
-
::: warning Security First
|
92
|
-
All core permissions (`create?` and `read?`) default to `false`. You must explicitly override these to grant access.
|
93
|
-
```ruby
|
94
|
-
# Default implementations
|
95
|
-
def create?
|
96
|
-
false
|
97
|
-
end
|
98
|
-
|
99
|
-
def read?
|
100
|
-
false
|
101
|
-
end
|
102
|
-
```
|
103
|
-
:::
|
104
|
-
|
105
|
-
#### Permission Inheritance
|
106
|
-
|
107
|
-
::: code-group
|
108
|
-
```ruby [Action Methods]
|
109
|
-
def update?
|
110
|
-
create? # Inherits from create?
|
111
|
-
end
|
112
|
-
|
113
|
-
def destroy?
|
114
|
-
create? # Inherits from create?
|
115
|
-
end
|
116
|
-
|
117
|
-
def index?
|
118
|
-
read? # Inherits from read?
|
119
|
-
end
|
120
|
-
|
121
|
-
def show?
|
122
|
-
read? # Inherits from read?
|
123
|
-
end
|
124
|
-
```
|
125
|
-
|
126
|
-
```ruby [Helper Methods]
|
127
|
-
def new?
|
128
|
-
create? # Matches create?
|
129
|
-
end
|
130
|
-
|
131
|
-
def edit?
|
132
|
-
update? # Matches update?
|
133
|
-
end
|
134
|
-
|
135
|
-
def search?
|
136
|
-
index? # Matches index?
|
137
|
-
end
|
138
|
-
```
|
139
|
-
:::
|
140
|
-
|
141
|
-
### Attribute Permission Defaults
|
142
|
-
|
143
|
-
Attribute permissions also follow an inheritance pattern, but with auto-detection in development:
|
144
|
-
|
145
|
-
::: details Inheritance Chain
|
146
|
-
```mermaid
|
147
|
-
graph TD
|
148
|
-
subgraph Core Attributes
|
149
|
-
A[permitted_attributes_for_create] --> B[permitted_attributes_for_update]
|
150
|
-
C[permitted_attributes_for_read] --> D[permitted_attributes_for_show]
|
151
|
-
C --> E[permitted_attributes_for_index]
|
152
|
-
end
|
153
|
-
```
|
154
|
-
:::
|
155
|
-
|
156
|
-
#### Core Implementation Details
|
157
|
-
|
158
|
-
::: code-group
|
159
|
-
```ruby [Create Attributes]
|
160
|
-
def permitted_attributes_for_create
|
161
|
-
# Auto-detects fields but excludes system columns
|
162
|
-
autodetect_permitted_fields(:permitted_attributes_for_create) - [
|
163
|
-
resource_class.primary_key.to_sym,
|
164
|
-
:created_at,
|
165
|
-
:updated_at
|
166
|
-
]
|
167
|
-
end
|
168
|
-
```
|
169
|
-
|
170
|
-
```ruby [Read Attributes]
|
171
|
-
def permitted_attributes_for_read
|
172
|
-
# Auto-detects all fields
|
173
|
-
autodetect_permitted_fields(:permitted_attributes_for_read)
|
174
|
-
end
|
175
|
-
```
|
176
|
-
|
177
|
-
```ruby [Update Attributes]
|
178
|
-
def permitted_attributes_for_update
|
179
|
-
# Inherits from create
|
180
|
-
permitted_attributes_for_create
|
181
|
-
end
|
182
|
-
```
|
183
|
-
:::
|
184
|
-
|
185
|
-
::: danger Auto-detection Warning
|
186
|
-
The default attribute detection:
|
187
|
-
- Only works in development
|
188
|
-
- Raises errors in other environments
|
189
|
-
- Shows warning messages
|
190
|
-
- Must be overridden in production
|
191
|
-
:::
|
192
|
-
|
193
|
-
### Association Defaults
|
194
|
-
|
195
|
-
By default, no associations are permitted:
|
196
|
-
|
197
|
-
```ruby
|
198
|
-
def permitted_associations
|
199
|
-
[] # Must be explicitly defined
|
200
|
-
end
|
201
|
-
```
|
202
|
-
|
203
|
-
### Context Object Defaults
|
204
|
-
|
205
|
-
Two built-in authorization contexts:
|
206
|
-
|
207
|
-
::: code-group
|
208
|
-
```ruby [Required Context]
|
209
|
-
# User must be present
|
210
|
-
authorize :user, allow_nil: false
|
211
|
-
```
|
212
|
-
|
213
|
-
```ruby [Optional Context]
|
214
|
-
# Entity scope is optional
|
215
|
-
authorize :entity_scope, allow_nil: true
|
216
|
-
```
|
217
|
-
:::
|
218
|
-
|
219
|
-
#### Default Scoping Behavior
|
220
|
-
|
221
|
-
When an entity scope exists, records are automatically filtered:
|
222
|
-
|
223
|
-
```ruby
|
224
|
-
relation_scope do |relation|
|
225
|
-
next relation unless entity_scope
|
226
|
-
relation.associated_with(entity_scope)
|
227
|
-
end
|
228
|
-
```
|
229
|
-
|
230
|
-
#### Adding Custom Contexts
|
231
|
-
|
232
|
-
You can add additional authorization contexts:
|
233
|
-
|
234
|
-
::: code-group
|
235
|
-
```ruby [Policy]
|
236
|
-
class BlogPolicy < ResourcePolicy
|
237
|
-
authorize :ability, allow_nil: true
|
238
|
-
|
239
|
-
def promote?
|
240
|
-
user.admin? && ability&.can?(:promote, record)
|
241
|
-
end
|
242
|
-
end
|
243
|
-
```
|
244
|
-
|
245
|
-
```ruby [Controller]
|
246
|
-
class BlogsController < ResourceController
|
247
|
-
authorize :ability, through: :current_ability
|
248
|
-
|
249
|
-
private
|
250
|
-
|
251
|
-
def current_ability
|
252
|
-
@current_ability ||= Ability.new(current_user)
|
253
|
-
end
|
254
|
-
end
|
255
|
-
```
|
256
|
-
:::
|
257
|
-
|
258
|
-
## Quick Reference
|
259
|
-
|
260
|
-
| Method Type | Default | Inherits From |
|
261
|
-
|------------|---------|---------------|
|
262
|
-
| create? | false | - |
|
263
|
-
| read? | false | - |
|
264
|
-
| update? | false | create? |
|
265
|
-
| destroy? | false | create? |
|
266
|
-
| index? | false | read? |
|
267
|
-
| show? | false | read? |
|
268
|
-
| attributes_for_create | auto* | - |
|
269
|
-
| attributes_for_read | auto* | - |
|
270
|
-
| attributes_for_update | auto* | create |
|
271
|
-
| associations | [] | - |
|
272
|
-
|
273
|
-
::: warning
|
274
|
-
\*Auto-detection only works in development
|
275
|
-
:::
|
276
|
-
|
277
|
-
## Security Best Practices
|
278
|
-
|
279
|
-
### 1. Never Skip Authorization
|
280
|
-
|
281
|
-
Plutonium controllers automatically verify authorization:
|
282
|
-
|
283
|
-
```ruby
|
284
|
-
class BlogsController < ResourceController
|
285
|
-
def show
|
286
|
-
# This will raise an error if you forget to authorize
|
287
|
-
# authorize! resource_record
|
288
|
-
render :show
|
289
|
-
end
|
290
|
-
end
|
291
|
-
```
|
292
|
-
|
293
|
-
## Related Resources
|
294
|
-
|
295
|
-
- [Action Policy Documentation](https://actionpolicy.evilmartians.io/)
|
296
|
-
- [Rails Security Guide](https://guides.rubyonrails.org/security.html)
|