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
|
@@ -14,39 +14,9 @@ module Plutonium
|
|
|
14
14
|
"flex flex-wrap justify-between items-center gap-4 mb-4"
|
|
15
15
|
) do
|
|
16
16
|
div(class: "flex flex-wrap items-center gap-2") do
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
id: "#{name}-scope",
|
|
21
|
-
href: current_query_object.build_url(scope: nil),
|
|
22
|
-
class:
|
|
23
|
-
"px-4 py-2 text-sm font-medium text-white bg-primary-700 border border-primary-700 rounded-lg hover:bg-primary-800 focus:z-10 focus:ring-2 focus:ring-primary-700 focus:text-white dark:bg-primary-600 dark:border-primary-600 dark:hover:bg-primary-700 dark:focus:ring-primary-800"
|
|
24
|
-
) { name.humanize }
|
|
25
|
-
else
|
|
26
|
-
a(
|
|
27
|
-
id: "#{name}-scope",
|
|
28
|
-
href: current_query_object.build_url(scope: nil),
|
|
29
|
-
class:
|
|
30
|
-
"px-4 py-2 text-sm font-medium text-gray-500 bg-white border border-gray-300 rounded-lg hover:bg-gray-100 hover:text-gray-700 focus:z-10 focus:ring-2 focus:ring-gray-300 focus:text-gray-700 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700 dark:focus:ring-gray-700 dark:focus:text-white"
|
|
31
|
-
) { name.humanize }
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
current_query_object.scope_definitions.each do |name, definition|
|
|
35
|
-
if name == current_scope
|
|
36
|
-
a(
|
|
37
|
-
id: "#{name}-scope",
|
|
38
|
-
href: current_query_object.build_url(scope: name),
|
|
39
|
-
class:
|
|
40
|
-
"px-4 py-2 text-sm font-medium text-white bg-primary-700 border border-primary-700 rounded-lg hover:bg-primary-800 focus:z-10 focus:ring-2 focus:ring-primary-700 focus:text-white dark:bg-primary-600 dark:border-primary-600 dark:hover:bg-primary-700 dark:focus:ring-primary-800"
|
|
41
|
-
) { name.humanize }
|
|
42
|
-
else
|
|
43
|
-
a(
|
|
44
|
-
id: "#{name}-scope",
|
|
45
|
-
href: current_query_object.build_url(scope: name),
|
|
46
|
-
class:
|
|
47
|
-
"px-4 py-2 text-sm font-medium text-gray-500 bg-white border border-gray-300 rounded-lg hover:bg-gray-100 hover:text-gray-700 focus:z-10 focus:ring-2 focus:ring-gray-300 focus:text-gray-700 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700 dark:focus:ring-gray-700 dark:focus:text-white"
|
|
48
|
-
) { name.humanize }
|
|
49
|
-
end
|
|
17
|
+
render_all_scope_button
|
|
18
|
+
current_query_object.scope_definitions.each_key do |name|
|
|
19
|
+
render_scope_button(name)
|
|
50
20
|
end
|
|
51
21
|
end
|
|
52
22
|
|
|
@@ -124,7 +94,42 @@ module Plutonium
|
|
|
124
94
|
|
|
125
95
|
private
|
|
126
96
|
|
|
127
|
-
def
|
|
97
|
+
def render_all_scope_button
|
|
98
|
+
active = all_scope_active?
|
|
99
|
+
a(
|
|
100
|
+
id: "all-scope",
|
|
101
|
+
href: current_query_object.build_url(scope: nil),
|
|
102
|
+
class: active ? active_scope_class : inactive_scope_class
|
|
103
|
+
) { "All" }
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def render_scope_button(name)
|
|
107
|
+
active = name.to_s == current_scope
|
|
108
|
+
a(
|
|
109
|
+
id: "#{name}-scope",
|
|
110
|
+
href: current_query_object.build_url(scope: name),
|
|
111
|
+
class: active ? active_scope_class : inactive_scope_class
|
|
112
|
+
) { name.to_s.humanize }
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def current_scope
|
|
116
|
+
# Use the effective scope (includes default when no selection)
|
|
117
|
+
current_query_object.selected_scope
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def all_scope_active?
|
|
121
|
+
# Active if user explicitly selected "All" OR no scope param and no default
|
|
122
|
+
current_query_object.all_scope_selected? ||
|
|
123
|
+
(!raw_resource_query_params.key?(:scope) && current_query_object.default_scope_name.blank?)
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def active_scope_class
|
|
127
|
+
"px-4 py-2 text-sm font-medium text-white bg-primary-700 border border-primary-700 rounded-lg hover:bg-primary-800 focus:z-10 focus:ring-2 focus:ring-primary-700 focus:text-white dark:bg-primary-600 dark:border-primary-600 dark:hover:bg-primary-700 dark:focus:ring-primary-800"
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def inactive_scope_class
|
|
131
|
+
"px-4 py-2 text-sm font-medium text-gray-500 bg-white border border-gray-300 rounded-lg hover:bg-gray-100 hover:text-gray-700 focus:z-10 focus:ring-2 focus:ring-gray-300 focus:text-gray-700 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700 dark:focus:ring-gray-700 dark:focus:text-white"
|
|
132
|
+
end
|
|
128
133
|
|
|
129
134
|
def render?
|
|
130
135
|
current_query_object.scope_definitions.present?
|
data/lib/plutonium/version.rb
CHANGED
data/lib/tasks/release.rake
CHANGED
|
@@ -6,10 +6,25 @@ namespace :release do
|
|
|
6
6
|
current_version = Plutonium::VERSION
|
|
7
7
|
puts "Current version: #{current_version}"
|
|
8
8
|
|
|
9
|
+
# Find the tag to compare against
|
|
10
|
+
version_tag = "v#{current_version}"
|
|
11
|
+
tag_exists = system("git rev-parse #{version_tag} >/dev/null 2>&1")
|
|
12
|
+
|
|
13
|
+
unless tag_exists
|
|
14
|
+
# Fall back to most recent tag
|
|
15
|
+
version_tag = `git describe --tags --abbrev=0 2>/dev/null`.strip
|
|
16
|
+
if version_tag.empty?
|
|
17
|
+
puts "No tags found, comparing against initial commit"
|
|
18
|
+
version_tag = `git rev-list --max-parents=0 HEAD`.strip
|
|
19
|
+
else
|
|
20
|
+
puts "Tag v#{current_version} not found, comparing against #{version_tag}"
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
9
24
|
# Check for breaking changes, features, or fixes since last tag
|
|
10
|
-
breaking = `git log
|
|
11
|
-
features = `git log
|
|
12
|
-
fixes = `git log
|
|
25
|
+
breaking = `git log #{version_tag}..HEAD --oneline | grep -i "BREAKING CHANGE"`.strip
|
|
26
|
+
features = `git log #{version_tag}..HEAD --oneline | grep "^[a-f0-9]* feat"`.strip
|
|
27
|
+
fixes = `git log #{version_tag}..HEAD --oneline | grep "^[a-f0-9]* fix"`.strip
|
|
13
28
|
|
|
14
29
|
major, minor, patch = current_version.split(".").map(&:to_i)
|
|
15
30
|
|
|
@@ -54,7 +69,7 @@ namespace :release do
|
|
|
54
69
|
package_json_file = "package.json"
|
|
55
70
|
if File.exist?(package_json_file)
|
|
56
71
|
package_content = File.read(package_json_file)
|
|
57
|
-
updated_package = package_content.gsub(/"version":\s*"[\d.]+"/, %
|
|
72
|
+
updated_package = package_content.gsub(/"version":\s*"[\d.]+"/, %("version": "#{version}"))
|
|
58
73
|
File.write(package_json_file, updated_package)
|
|
59
74
|
puts "✓ Updated #{package_json_file}"
|
|
60
75
|
end
|
data/package.json
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.
|
|
4
|
+
version: 0.34.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Stefan Froelich
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-01-
|
|
11
|
+
date: 2026-01-18 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: zeitwerk
|
|
@@ -399,6 +399,26 @@ extensions: []
|
|
|
399
399
|
extra_rdoc_files: []
|
|
400
400
|
files:
|
|
401
401
|
- "# Plutonium: The pre-alpha demo.md"
|
|
402
|
+
- ".claude/skills/assets/SKILL.md"
|
|
403
|
+
- ".claude/skills/connect-resource/SKILL.md"
|
|
404
|
+
- ".claude/skills/controller/SKILL.md"
|
|
405
|
+
- ".claude/skills/create-resource/SKILL.md"
|
|
406
|
+
- ".claude/skills/definition-actions/SKILL.md"
|
|
407
|
+
- ".claude/skills/definition-fields/SKILL.md"
|
|
408
|
+
- ".claude/skills/definition-query/SKILL.md"
|
|
409
|
+
- ".claude/skills/definition/SKILL.md"
|
|
410
|
+
- ".claude/skills/forms/SKILL.md"
|
|
411
|
+
- ".claude/skills/installation/SKILL.md"
|
|
412
|
+
- ".claude/skills/interaction/SKILL.md"
|
|
413
|
+
- ".claude/skills/model-features/SKILL.md"
|
|
414
|
+
- ".claude/skills/model/SKILL.md"
|
|
415
|
+
- ".claude/skills/nested-resources/SKILL.md"
|
|
416
|
+
- ".claude/skills/package/SKILL.md"
|
|
417
|
+
- ".claude/skills/policy/SKILL.md"
|
|
418
|
+
- ".claude/skills/portal/SKILL.md"
|
|
419
|
+
- ".claude/skills/resource/SKILL.md"
|
|
420
|
+
- ".claude/skills/rodauth/SKILL.md"
|
|
421
|
+
- ".claude/skills/views/SKILL.md"
|
|
402
422
|
- ".cliff.toml"
|
|
403
423
|
- ".node-version"
|
|
404
424
|
- ".rspec"
|
|
@@ -486,8 +506,8 @@ files:
|
|
|
486
506
|
- app/views/rodauth/webauthn_autofill.html.erb
|
|
487
507
|
- app/views/rodauth/webauthn_remove.html.erb
|
|
488
508
|
- app/views/rodauth/webauthn_setup.html.erb
|
|
489
|
-
- brakeman.ignore
|
|
490
509
|
- config.ru
|
|
510
|
+
- config/brakeman.ignore
|
|
491
511
|
- config/initializers/action_policy.rb
|
|
492
512
|
- config/initializers/hotwire_turbo_monkey_patches.rb
|
|
493
513
|
- config/initializers/pagy.rb
|
|
@@ -496,43 +516,35 @@ files:
|
|
|
496
516
|
- docs/.vitepress/config.ts
|
|
497
517
|
- docs/.vitepress/theme/custom.css
|
|
498
518
|
- docs/.vitepress/theme/index.ts
|
|
499
|
-
- docs/
|
|
500
|
-
- docs/
|
|
501
|
-
- docs/
|
|
502
|
-
- docs/
|
|
503
|
-
- docs/
|
|
504
|
-
- docs/
|
|
505
|
-
- docs/
|
|
506
|
-
- docs/
|
|
507
|
-
- docs/
|
|
508
|
-
- docs/
|
|
509
|
-
- docs/
|
|
510
|
-
- docs/
|
|
511
|
-
- docs/
|
|
512
|
-
- docs/
|
|
513
|
-
- docs/
|
|
514
|
-
- docs/
|
|
519
|
+
- docs/concepts/architecture.md
|
|
520
|
+
- docs/concepts/auto-detection.md
|
|
521
|
+
- docs/concepts/index.md
|
|
522
|
+
- docs/concepts/packages-portals.md
|
|
523
|
+
- docs/concepts/resources.md
|
|
524
|
+
- docs/cookbook/blog.md
|
|
525
|
+
- docs/cookbook/index.md
|
|
526
|
+
- docs/cookbook/saas.md
|
|
527
|
+
- docs/getting-started/index.md
|
|
528
|
+
- docs/getting-started/installation.md
|
|
529
|
+
- docs/getting-started/tutorial/01-setup.md
|
|
530
|
+
- docs/getting-started/tutorial/02-first-resource.md
|
|
531
|
+
- docs/getting-started/tutorial/03-authentication.md
|
|
532
|
+
- docs/getting-started/tutorial/04-authorization.md
|
|
533
|
+
- docs/getting-started/tutorial/05-custom-actions.md
|
|
534
|
+
- docs/getting-started/tutorial/06-nested-resources.md
|
|
535
|
+
- docs/getting-started/tutorial/07-customizing-ui.md
|
|
536
|
+
- docs/getting-started/tutorial/index.md
|
|
537
|
+
- docs/guides/adding-resources.md
|
|
538
|
+
- docs/guides/authentication.md
|
|
539
|
+
- docs/guides/authorization.md
|
|
540
|
+
- docs/guides/creating-packages.md
|
|
541
|
+
- docs/guides/custom-actions.md
|
|
542
|
+
- docs/guides/index.md
|
|
543
|
+
- docs/guides/multi-tenancy.md
|
|
544
|
+
- docs/guides/nested-resources.md
|
|
545
|
+
- docs/guides/search-filtering.md
|
|
546
|
+
- docs/guides/theming.md
|
|
515
547
|
- docs/index.md
|
|
516
|
-
- docs/markdown-examples.md
|
|
517
|
-
- docs/modules/action.md
|
|
518
|
-
- docs/modules/authentication.md
|
|
519
|
-
- docs/modules/configuration.md
|
|
520
|
-
- docs/modules/controller.md
|
|
521
|
-
- docs/modules/core.md
|
|
522
|
-
- docs/modules/definition.md
|
|
523
|
-
- docs/modules/display.md
|
|
524
|
-
- docs/modules/form.md
|
|
525
|
-
- docs/modules/generator.md
|
|
526
|
-
- docs/modules/index.md
|
|
527
|
-
- docs/modules/interaction.md
|
|
528
|
-
- docs/modules/package.md
|
|
529
|
-
- docs/modules/policy.md
|
|
530
|
-
- docs/modules/portal.md
|
|
531
|
-
- docs/modules/query.md
|
|
532
|
-
- docs/modules/resource_record.md
|
|
533
|
-
- docs/modules/routing.md
|
|
534
|
-
- docs/modules/table.md
|
|
535
|
-
- docs/modules/ui.md
|
|
536
548
|
- docs/public/CLAUDE.md
|
|
537
549
|
- docs/public/android-chrome-192x192.png
|
|
538
550
|
- docs/public/android-chrome-512x512.png
|
|
@@ -554,10 +566,29 @@ files:
|
|
|
554
566
|
- docs/public/tutorial/plutonium-posts-detail-customized.png
|
|
555
567
|
- docs/public/tutorial/plutonium-posts-detail.png
|
|
556
568
|
- docs/public/tutorial/plutonium-publish-post.png
|
|
569
|
+
- docs/reference/assets/index.md
|
|
570
|
+
- docs/reference/controller/index.md
|
|
571
|
+
- docs/reference/definition/actions.md
|
|
572
|
+
- docs/reference/definition/fields.md
|
|
573
|
+
- docs/reference/definition/index.md
|
|
574
|
+
- docs/reference/definition/query.md
|
|
575
|
+
- docs/reference/generators/index.md
|
|
576
|
+
- docs/reference/index.md
|
|
577
|
+
- docs/reference/interaction/index.md
|
|
578
|
+
- docs/reference/model/features.md
|
|
579
|
+
- docs/reference/model/index.md
|
|
580
|
+
- docs/reference/policy/index.md
|
|
581
|
+
- docs/reference/portal/index.md
|
|
582
|
+
- docs/reference/views/forms.md
|
|
583
|
+
- docs/reference/views/index.md
|
|
557
584
|
- esbuild.config.js
|
|
558
585
|
- exe/pug
|
|
559
586
|
- gemfiles/rails_7.gemfile
|
|
560
587
|
- gemfiles/rails_7.gemfile.lock
|
|
588
|
+
- gemfiles/rails_8.0.gemfile
|
|
589
|
+
- gemfiles/rails_8.0.gemfile.lock
|
|
590
|
+
- gemfiles/rails_8.1.gemfile
|
|
591
|
+
- gemfiles/rails_8.1.gemfile.lock
|
|
561
592
|
- lib/active_model/validations/array_validator.rb
|
|
562
593
|
- lib/active_model/validations/attached_validator.rb
|
|
563
594
|
- lib/active_model/validations/url_validator.rb
|
|
@@ -633,6 +664,7 @@ files:
|
|
|
633
664
|
- lib/generators/pu/pkg/package/templates/app/presenters/resource_presenter.rb.tt
|
|
634
665
|
- lib/generators/pu/pkg/package/templates/app/query_objects/resource_query_object.rb.tt
|
|
635
666
|
- lib/generators/pu/pkg/package/templates/lib/engine.rb.tt
|
|
667
|
+
- lib/generators/pu/pkg/portal/USAGE
|
|
636
668
|
- lib/generators/pu/pkg/portal/portal_generator.rb
|
|
637
669
|
- lib/generators/pu/pkg/portal/templates/app/controllers/concerns/controller.rb.tt
|
|
638
670
|
- lib/generators/pu/pkg/portal/templates/app/controllers/dashboard_controller.rb.tt
|
|
@@ -646,6 +678,7 @@ files:
|
|
|
646
678
|
- lib/generators/pu/pkg/portal/templates/app/views/package/dashboard/index.html.erb
|
|
647
679
|
- lib/generators/pu/pkg/portal/templates/config/routes.rb.tt
|
|
648
680
|
- lib/generators/pu/pkg/portal/templates/lib/engine.rb.tt
|
|
681
|
+
- lib/generators/pu/res/conn/USAGE
|
|
649
682
|
- lib/generators/pu/res/conn/conn_generator.rb
|
|
650
683
|
- lib/generators/pu/res/conn/templates/.keep
|
|
651
684
|
- lib/generators/pu/res/conn/templates/app/controllers/resource_controller.rb.tt
|
|
@@ -659,6 +692,7 @@ files:
|
|
|
659
692
|
- lib/generators/pu/res/model/templates/create_table_migration.rb.tt
|
|
660
693
|
- lib/generators/pu/res/model/templates/model.rb.tt
|
|
661
694
|
- lib/generators/pu/res/model/templates/module.rb.tt
|
|
695
|
+
- lib/generators/pu/res/scaffold/USAGE
|
|
662
696
|
- lib/generators/pu/res/scaffold/scaffold_generator.rb
|
|
663
697
|
- lib/generators/pu/res/scaffold/templates/.keep
|
|
664
698
|
- lib/generators/pu/res/scaffold/templates/controller.rb.tt
|
|
@@ -719,6 +753,7 @@ files:
|
|
|
719
753
|
- lib/generators/pu/rodauth/templates/app/views/rodauth_mailer/webauthn_authenticator_added.text.erb
|
|
720
754
|
- lib/generators/pu/rodauth/templates/app/views/rodauth_mailer/webauthn_authenticator_removed.text.erb
|
|
721
755
|
- lib/generators/pu/rodauth/templates/config/initializers/rodauth.rb.tt
|
|
756
|
+
- lib/generators/pu/rodauth/templates/config/initializers/url_options.rb
|
|
722
757
|
- lib/generators/pu/rodauth/templates/db/migrate/create_rodauth.rb.tt
|
|
723
758
|
- lib/generators/pu/rodauth/templates/db/migrate/install_rodauth.rb.tt
|
|
724
759
|
- lib/generators/pu/rodauth/templates/lib/tasks/rodauth_admin.rake.tt
|
|
@@ -732,6 +767,8 @@ files:
|
|
|
732
767
|
- lib/generators/pu/service/sidekiq/templates/app/sidekiq/sidekiq_job.rb
|
|
733
768
|
- lib/generators/pu/service/sidekiq/templates/config/initializers/sidekiq.rb
|
|
734
769
|
- lib/generators/pu/service/sidekiq/templates/config/sidekiq.yml
|
|
770
|
+
- lib/generators/pu/skills/sync/USAGE
|
|
771
|
+
- lib/generators/pu/skills/sync/sync_generator.rb
|
|
735
772
|
- lib/plutonium.rb
|
|
736
773
|
- lib/plutonium/action/README.md
|
|
737
774
|
- lib/plutonium/action/base.rb
|
data/brakeman.ignore
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"ignored_warnings": [
|
|
3
|
-
{
|
|
4
|
-
"warning_type": "Cross-Site Request Forgery",
|
|
5
|
-
"warning_code": 7,
|
|
6
|
-
"fingerprint": "1cb8570b8c91f38317cdf909e01e7016359846174f427e86011633c344d30fc3",
|
|
7
|
-
"check_name": "ForgerySetting",
|
|
8
|
-
"message": "`protect_from_forgery` should be called in `Plutonium::Resource::Controller`",
|
|
9
|
-
"file": "lib/plutonium/resource/controller.rb",
|
|
10
|
-
"line": 10,
|
|
11
|
-
"link": "https://brakemanscanner.org/docs/warning_types/cross-site_request_forgery/",
|
|
12
|
-
"code": null,
|
|
13
|
-
"render_path": null,
|
|
14
|
-
"location": {
|
|
15
|
-
"type": "controller",
|
|
16
|
-
"controller": "Plutonium::Resource::Controller"
|
|
17
|
-
},
|
|
18
|
-
"user_input": null,
|
|
19
|
-
"confidence": "High",
|
|
20
|
-
"cwe_id": [
|
|
21
|
-
352
|
|
22
|
-
],
|
|
23
|
-
"note": "Tests confirm csrf tokens are being verified. False flag."
|
|
24
|
-
}
|
|
25
|
-
],
|
|
26
|
-
"updated": "2024-02-24 17:32:51 +0000",
|
|
27
|
-
"brakeman_version": "6.1.2"
|
|
28
|
-
}
|
data/docs/api-examples.md
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
outline: deep
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
# Runtime API Examples
|
|
6
|
-
|
|
7
|
-
This page demonstrates usage of some of the runtime APIs provided by VitePress.
|
|
8
|
-
|
|
9
|
-
The main `useData()` API can be used to access site, theme, and page data for the current page. It works in both `.md` and `.vue` files:
|
|
10
|
-
|
|
11
|
-
```md
|
|
12
|
-
<script setup>
|
|
13
|
-
import { useData } from 'vitepress'
|
|
14
|
-
|
|
15
|
-
const { theme, page, frontmatter } = useData()
|
|
16
|
-
</script>
|
|
17
|
-
|
|
18
|
-
## Results
|
|
19
|
-
|
|
20
|
-
### Theme Data
|
|
21
|
-
<pre>{{ theme }}</pre>
|
|
22
|
-
|
|
23
|
-
### Page Data
|
|
24
|
-
<pre>{{ page }}</pre>
|
|
25
|
-
|
|
26
|
-
### Page Frontmatter
|
|
27
|
-
<pre>{{ frontmatter }}</pre>
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
<script setup>
|
|
31
|
-
import { useData } from 'vitepress'
|
|
32
|
-
|
|
33
|
-
const { site, theme, page, frontmatter } = useData()
|
|
34
|
-
</script>
|
|
35
|
-
|
|
36
|
-
## Results
|
|
37
|
-
|
|
38
|
-
### Theme Data
|
|
39
|
-
<pre>{{ theme }}</pre>
|
|
40
|
-
|
|
41
|
-
### Page Data
|
|
42
|
-
<pre>{{ page }}</pre>
|
|
43
|
-
|
|
44
|
-
### Page Frontmatter
|
|
45
|
-
<pre>{{ frontmatter }}</pre>
|
|
46
|
-
|
|
47
|
-
## More
|
|
48
|
-
|
|
49
|
-
Check out the documentation for the [full list of runtime APIs](https://vitepress.dev/reference/runtime-api#usedata).
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: Claude Code Guide for Plutonium Development
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
<script setup>
|
|
6
|
-
import { withBase } from 'vitepress'
|
|
7
|
-
</script>
|
|
8
|
-
|
|
9
|
-
# Claude Code Guide for Plutonium Development
|
|
10
|
-
|
|
11
|
-
This page provides comprehensive development guidance for building Plutonium applications effectively. This guide is designed to help AI assistants and developers understand the framework's patterns and best practices.
|
|
12
|
-
|
|
13
|
-
## Quick Start
|
|
14
|
-
|
|
15
|
-
**Download the CLAUDE.md File**: <a :href="withBase('/CLAUDE.md')" target="_blank">📄 CLAUDE.md</a>
|
|
16
|
-
|
|
17
|
-
**Or download directly from your terminal**:
|
|
18
|
-
|
|
19
|
-
::: code-group
|
|
20
|
-
|
|
21
|
-
```bash [Unix/Linux/macOS/WSL]
|
|
22
|
-
curl -o CLAUDE.md https://radioactive-labs.github.io/plutonium-core/CLAUDE.md
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
```cmd [Windows]
|
|
26
|
-
curl -o CLAUDE.md https://radioactive-labs.github.io/plutonium-core/CLAUDE.md
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
:::
|
|
30
|
-
|
|
31
|
-
## Using This Guide
|
|
32
|
-
|
|
33
|
-
Claude Code uses CLAUDE.md files for project-specific context:
|
|
34
|
-
|
|
35
|
-
1. **Download the guide**: Right-click the link above and "Save As" to download the `CLAUDE.md` file
|
|
36
|
-
2. **Place in your project root** as `CLAUDE.md`
|
|
37
|
-
3. **Claude Code automatically loads** this file for project context
|
|
38
|
-
4. **Enhance with your own instructions** by adding project-specific details
|
|
39
|
-
|
|
40
|
-
The guide provides comprehensive patterns and examples for building Plutonium applications with AI assistance.
|
|
41
|
-
|
|
42
|
-
## What's Included
|
|
43
|
-
|
|
44
|
-
The CLAUDE.md guide contains comprehensive guidelines for:
|
|
45
|
-
|
|
46
|
-
### 🏗️ **Framework Architecture**
|
|
47
|
-
- Resource-oriented development patterns
|
|
48
|
-
- Package architecture (Feature & Portal packages)
|
|
49
|
-
- Component-based UI with Phlex
|
|
50
|
-
- Business logic through Interactions
|
|
51
|
-
|
|
52
|
-
### 📝 **Resource Development**
|
|
53
|
-
- **Auto-detection philosophy** - Field types are automatically detected from models
|
|
54
|
-
- **Definition patterns** - Only override when needed
|
|
55
|
-
- **Policy-based authorization** - Fine-grained permissions
|
|
56
|
-
- **Interaction-driven business logic** - Encapsulated operations
|
|
57
|
-
|
|
58
|
-
### 🔧 **Development Patterns**
|
|
59
|
-
- **Generator commands** for scaffolding
|
|
60
|
-
- **Authentication setup** with Rodauth
|
|
61
|
-
- **Multi-tenancy** with entity scoping
|
|
62
|
-
- **Query objects** for filtering and search
|
|
63
|
-
|
|
64
|
-
### 🎨 **UI Customization**
|
|
65
|
-
- **Component architecture** with Phlex
|
|
66
|
-
- **Custom display blocks** with `phlexi_tag`
|
|
67
|
-
- **Conditional rendering** with context awareness
|
|
68
|
-
- **Layout customization** patterns
|
|
69
|
-
|
|
70
|
-
### ⚡ **Best Practices**
|
|
71
|
-
- **Performance optimization** techniques
|
|
72
|
-
- **Security guidelines** and defaults
|
|
73
|
-
- **Code organization** principles
|
|
74
|
-
- **Development workflow** recommendations
|
|
@@ -1,189 +0,0 @@
|
|
|
1
|
-
# Deep Dive: Authorization
|
|
2
|
-
|
|
3
|
-
Plutonium provides a robust authorization system built on top of [Action Policy](https://actionpolicy.evilmartians.io/). It's designed to be secure by default while offering fine-grained control over every aspect of your application's access control.
|
|
4
|
-
|
|
5
|
-
## Core Principles
|
|
6
|
-
|
|
7
|
-
Authorization in Plutonium is handled by **Policy** classes. Every resource should have a corresponding policy that inherits from `Plutonium::Resource::Policy`.
|
|
8
|
-
|
|
9
|
-
A policy's primary job is to answer the question: "Can the current `user` perform this `action` on this `record`?"
|
|
10
|
-
|
|
11
|
-
```ruby
|
|
12
|
-
class PostPolicy < Plutonium::Resource::Policy
|
|
13
|
-
# Can the user see a list of posts?
|
|
14
|
-
def index?
|
|
15
|
-
true # Everyone can see the list
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
# Can the user update this specific post?
|
|
19
|
-
def update?
|
|
20
|
-
# `record` is the post instance.
|
|
21
|
-
# `user` is the current authenticated user.
|
|
22
|
-
record.author == user || user.admin?
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
# ... other permissions
|
|
26
|
-
end
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
## Secure by Default: The Permission Chain
|
|
30
|
-
|
|
31
|
-
Plutonium policies are secure by default. If a permission is not explicitly granted, it's denied. This is achieved through a clear inheritance chain.
|
|
32
|
-
|
|
33
|
-
::: code-group
|
|
34
|
-
```ruby [Core Permissions]
|
|
35
|
-
# These are the base permissions.
|
|
36
|
-
# They both default to `false`. You MUST override them.
|
|
37
|
-
def create?
|
|
38
|
-
false
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
def read?
|
|
42
|
-
false
|
|
43
|
-
end
|
|
44
|
-
```
|
|
45
|
-
```ruby [Derived Permissions]
|
|
46
|
-
# These permissions inherit from the core ones.
|
|
47
|
-
# You can override them for more granular control.
|
|
48
|
-
def update?
|
|
49
|
-
create?
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
def destroy?
|
|
53
|
-
create?
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
def index?
|
|
57
|
-
read?
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
def show?
|
|
61
|
-
read?
|
|
62
|
-
end
|
|
63
|
-
```
|
|
64
|
-
:::
|
|
65
|
-
|
|
66
|
-
::: danger Always Define Core Permissions
|
|
67
|
-
Because `create?` and `read?` default to `false`, you must define them in your policy to grant any access. If `create?` is `false`, then `update?` and `destroy?` will also be `false` unless you explicitly override them.
|
|
68
|
-
:::
|
|
69
|
-
|
|
70
|
-
## Attribute & Association Permissions
|
|
71
|
-
|
|
72
|
-
Beyond actions, policies also control access to a resource's data at a granular level.
|
|
73
|
-
|
|
74
|
-
### Attribute Permissions
|
|
75
|
-
|
|
76
|
-
Attribute permissions control which fields a user can see or submit in a form. They follow a similar inheritance chain.
|
|
77
|
-
|
|
78
|
-
::: code-group
|
|
79
|
-
```ruby [Read Attributes]
|
|
80
|
-
# Controls which fields are returned for `index` and `show` actions.
|
|
81
|
-
def permitted_attributes_for_read
|
|
82
|
-
# By default, auto-detects all columns in development,
|
|
83
|
-
# but MUST be overridden for production.
|
|
84
|
-
end
|
|
85
|
-
```
|
|
86
|
-
```ruby [Create/Update Attributes]
|
|
87
|
-
# Controls which fields are allowed in `create` and `update` actions.
|
|
88
|
-
def permitted_attributes_for_create
|
|
89
|
-
# By default, auto-detects columns (minus some system ones)
|
|
90
|
-
# in development, but MUST be overridden for production.
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
def permitted_attributes_for_update
|
|
94
|
-
# Inherits from `permitted_attributes_for_create` by default.
|
|
95
|
-
permitted_attributes_for_create
|
|
96
|
-
end
|
|
97
|
-
```
|
|
98
|
-
:::
|
|
99
|
-
|
|
100
|
-
::: warning Override in Production
|
|
101
|
-
The default auto-detection for attributes only works in development to speed up initial scaffolding. You **must** override `permitted_attributes_for_create` and `permitted_attributes_for_read` in your policies for them to work in production.
|
|
102
|
-
:::
|
|
103
|
-
|
|
104
|
-
### Association Permissions
|
|
105
|
-
|
|
106
|
-
By default, no associations are permitted. You must explicitly list which related resources can be included.
|
|
107
|
-
|
|
108
|
-
```ruby
|
|
109
|
-
class PostPolicy < Plutonium::Resource::Policy
|
|
110
|
-
def permitted_associations
|
|
111
|
-
[:comments, :author]
|
|
112
|
-
end
|
|
113
|
-
end
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
## Scoping: Filtering Collections
|
|
117
|
-
|
|
118
|
-
A policy's `relation_scope` is used to filter down a collection of records to only what the current user should see. This is applied automatically on `index` pages.
|
|
119
|
-
|
|
120
|
-
::: code-group
|
|
121
|
-
```ruby [Simple Scope]
|
|
122
|
-
class PostPolicy < Plutonium::Resource::Policy
|
|
123
|
-
relation_scope do |relation|
|
|
124
|
-
if user.admin?
|
|
125
|
-
relation # Admins see all posts
|
|
126
|
-
else
|
|
127
|
-
# Others only see their own posts or published posts
|
|
128
|
-
relation.where(author: user).or(relation.where(published: true))
|
|
129
|
-
end
|
|
130
|
-
end
|
|
131
|
-
end
|
|
132
|
-
```
|
|
133
|
-
```ruby [Multi-Tenant Scope]
|
|
134
|
-
class PostPolicy < Plutonium::Resource::Policy
|
|
135
|
-
relation_scope do |relation|
|
|
136
|
-
# `super` applies the portal's entity scoping first
|
|
137
|
-
# e.g., `relation.associated_with(current_organization)`
|
|
138
|
-
relation = super(relation)
|
|
139
|
-
|
|
140
|
-
# Then, apply additional logic
|
|
141
|
-
if user.admin?
|
|
142
|
-
relation
|
|
143
|
-
else
|
|
144
|
-
relation.where(published: true)
|
|
145
|
-
end
|
|
146
|
-
end
|
|
147
|
-
end
|
|
148
|
-
```
|
|
149
|
-
:::
|
|
150
|
-
|
|
151
|
-
## Authorization Context
|
|
152
|
-
|
|
153
|
-
Policies have access to a `context` object. By default, Plutonium provides two:
|
|
154
|
-
|
|
155
|
-
- **`user`**: The current authenticated user. This is **required**.
|
|
156
|
-
- **`entity_scope`**: The current portal's multi-tenancy record (e.g., the current `Organization`). This is optional.
|
|
157
|
-
|
|
158
|
-
You can add your own custom context objects for more complex scenarios.
|
|
159
|
-
|
|
160
|
-
::: details Adding Custom Context
|
|
161
|
-
Imagine you have a separate `Ability` system that you also want to check.
|
|
162
|
-
|
|
163
|
-
**1. Define the context in the Policy:**
|
|
164
|
-
```ruby
|
|
165
|
-
class PostPolicy < ResourcePolicy
|
|
166
|
-
authorize :ability, allow_nil: true
|
|
167
|
-
|
|
168
|
-
def promote?
|
|
169
|
-
# You can now use `ability` in your permission checks
|
|
170
|
-
user.admin? && ability&.can?(:promote, record)
|
|
171
|
-
end
|
|
172
|
-
end
|
|
173
|
-
```
|
|
174
|
-
|
|
175
|
-
**2. Provide the context from the Controller:**
|
|
176
|
-
```ruby
|
|
177
|
-
class PostsController < ResourceController
|
|
178
|
-
# This tells the policy how to find the `ability` object.
|
|
179
|
-
authorize :ability, through: :current_ability
|
|
180
|
-
|
|
181
|
-
private
|
|
182
|
-
|
|
183
|
-
def current_ability
|
|
184
|
-
# Your custom logic to find the ability object
|
|
185
|
-
Ability.new(user)
|
|
186
|
-
end
|
|
187
|
-
end
|
|
188
|
-
```
|
|
189
|
-
:::
|