plutonium 0.14.1 → 0.15.0.pre.rc2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (182) hide show
  1. checksums.yaml +4 -4
  2. data/README copy.md +1 -1
  3. data/README.md +1 -1
  4. data/app/assets/plutonium.css +1 -1
  5. data/app/views/{application → plutonium}/_resource_header.html copy.erb +1 -1
  6. data/app/views/{application → plutonium}/_resource_header.html.erb +1 -1
  7. data/app/views/{application → plutonium}/_resource_sidebar.html.erb +2 -0
  8. data/app/views/resource/_resource_details.html.erb +1 -36
  9. data/app/views/resource/_resource_form.html.erb +1 -5
  10. data/app/views/resource/_resource_table.html.erb +315 -85
  11. data/app/views/resource/edit.html.erb +1 -5
  12. data/app/views/resource/index.html.erb +1 -5
  13. data/app/views/resource/new.html.erb +1 -5
  14. data/app/views/resource/show.html.erb +1 -5
  15. data/config/initializers/pagy.rb +1 -0
  16. data/config/initializers/rabl.rb +27 -20
  17. data/gemfiles/rails_7.gemfile.lock +5 -1
  18. data/lib/generators/pu/core/install/templates/app/controllers/plutonium_controller.rb.tt +2 -0
  19. data/lib/generators/pu/core/install/templates/app/controllers/resource_controller.rb.tt +21 -1
  20. data/lib/generators/pu/core/install/templates/app/definitions/resource_definition.rb.tt +2 -0
  21. data/lib/generators/pu/core/install/templates/app/models/resource_record.rb.tt +0 -2
  22. data/lib/generators/pu/core/install/templates/config/initializers/plutonium.rb +1 -8
  23. data/lib/generators/pu/eject/shell/shell_generator.rb +2 -2
  24. data/lib/generators/pu/lib/plutonium_generators/concerns/actions.rb +1 -1
  25. data/lib/generators/pu/lib/plutonium_generators/concerns/logger.rb +1 -1
  26. data/lib/generators/pu/lib/plutonium_generators/generator.rb +5 -3
  27. data/lib/generators/pu/lib/plutonium_generators/model_generator_base.rb +26 -2
  28. data/lib/generators/pu/pkg/{feature/feature_generator.rb → package/package_generator.rb} +4 -4
  29. data/lib/generators/pu/pkg/{feature → package}/templates/app/controllers/resource_controller.rb.tt +0 -2
  30. data/lib/generators/pu/pkg/package/templates/app/definitions/resource_definition.rb.tt +4 -0
  31. data/lib/generators/pu/pkg/package/templates/app/query_objects/resource_query_object.rb.tt +4 -0
  32. data/lib/generators/pu/pkg/{app/app_generator.rb → portal/portal_generator.rb} +10 -8
  33. data/lib/generators/pu/pkg/{app → portal}/templates/app/controllers/concerns/controller.rb.tt +3 -7
  34. data/lib/generators/pu/pkg/{app → portal}/templates/app/controllers/dashboard_controller.rb.tt +1 -1
  35. data/lib/generators/pu/pkg/portal/templates/app/controllers/plutonium_controller.rb.tt +5 -0
  36. data/lib/generators/pu/pkg/{app/templates/app/controllers/controller.rb.tt → portal/templates/app/controllers/resource_controller.rb.tt} +1 -1
  37. data/lib/generators/pu/pkg/portal/templates/app/definitions/resource_definition.rb.tt +4 -0
  38. data/lib/generators/pu/pkg/{app → portal}/templates/app/views/package/dashboard/index.html.erb +2 -1
  39. data/lib/generators/pu/res/conn/conn_generator.rb +78 -3
  40. data/lib/generators/pu/res/conn/templates/app/controllers/resource_controller.rb.tt +1 -1
  41. data/lib/generators/pu/res/conn/templates/app/definitions/resource_definition.rb.tt +3 -0
  42. data/lib/generators/pu/res/conn/templates/app/policies/resource_policy.rb.tt +29 -1
  43. data/lib/generators/pu/res/conn/templates/app/presenters/resource_presenter.rb.tt +1 -1
  44. data/lib/generators/pu/res/conn/templates/app/query_objects/resource_query_object.rb.tt +1 -1
  45. data/lib/generators/pu/res/model/model_generator.rb +0 -7
  46. data/lib/generators/pu/res/model/templates/model.rb.tt +4 -1
  47. data/lib/generators/pu/res/scaffold/scaffold_generator.rb +22 -4
  48. data/lib/generators/pu/res/scaffold/templates/controller.rb.tt +0 -1
  49. data/lib/generators/pu/res/scaffold/templates/definition.rb.tt +4 -0
  50. data/lib/generators/pu/res/scaffold/templates/policy.rb.tt +2 -2
  51. data/lib/generators/pu/rodauth/templates/app/controllers/rodauth_controller.rb.tt +1 -1
  52. data/lib/generators/pu/rodauth/templates/app/rodauth/account_rodauth_plugin.rb.tt +270 -0
  53. data/lib/plutonium/action/README.md +0 -0
  54. data/lib/plutonium/action/base.rb +103 -0
  55. data/lib/plutonium/action/interactive.rb +117 -0
  56. data/lib/plutonium/action/route_options.rb +65 -0
  57. data/lib/plutonium/action/simple.rb +8 -0
  58. data/lib/plutonium/auth.rb +1 -1
  59. data/lib/plutonium/configuration.rb +0 -8
  60. data/lib/plutonium/core/actions/collection.rb +1 -1
  61. data/lib/plutonium/core/associations/renderers/factory.rb +3 -1
  62. data/lib/plutonium/core/controller.rb +110 -0
  63. data/lib/plutonium/core/controllers/authorizable.rb +12 -35
  64. data/lib/plutonium/core/controllers/bootable.rb +38 -7
  65. data/lib/plutonium/core/controllers/entity_scoping.rb +6 -2
  66. data/lib/plutonium/core/fields/renderers/association_renderer.rb +1 -1
  67. data/lib/plutonium/core/ui/collection.rb +1 -1
  68. data/lib/plutonium/core/ui/detail.rb +1 -1
  69. data/lib/plutonium/core/ui/form.rb +1 -1
  70. data/lib/plutonium/definition/actions.rb +50 -0
  71. data/lib/plutonium/definition/base.rb +92 -0
  72. data/lib/plutonium/definition/config_attr.rb +30 -0
  73. data/lib/plutonium/definition/defineable_props.rb +96 -0
  74. data/lib/plutonium/definition/search.rb +21 -0
  75. data/lib/plutonium/engine/validator.rb +30 -0
  76. data/lib/plutonium/engine.rb +25 -0
  77. data/lib/plutonium/helpers/form_helper.rb +1 -3
  78. data/lib/plutonium/interaction/README.md +369 -0
  79. data/lib/plutonium/interaction/base.rb +75 -0
  80. data/lib/plutonium/interaction/concerns/presentable.rb +61 -0
  81. data/lib/plutonium/interaction/concerns/workflow_dsl.rb +82 -0
  82. data/lib/plutonium/interaction/outcome.rb +129 -0
  83. data/lib/plutonium/interaction/response/base.rb +63 -0
  84. data/lib/plutonium/interaction/response/null.rb +33 -0
  85. data/lib/plutonium/interaction/response/redirect.rb +30 -0
  86. data/lib/plutonium/interaction/response/render.rb +28 -0
  87. data/lib/plutonium/lib/bit_flags.rb +70 -9
  88. data/lib/plutonium/{config → lib}/overlayed_hash.rb +1 -1
  89. data/lib/plutonium/lib/smart_cache.rb +171 -0
  90. data/lib/plutonium/models/has_cents.rb +170 -0
  91. data/lib/plutonium/{pkg/base.rb → package/engine.rb} +10 -2
  92. data/lib/plutonium/{application → portal}/controller.rb +3 -11
  93. data/lib/plutonium/{application → portal}/dynamic_controllers.rb +4 -4
  94. data/lib/plutonium/portal/engine.rb +15 -0
  95. data/lib/plutonium/railtie.rb +33 -1
  96. data/lib/plutonium/reloader.rb +5 -5
  97. data/lib/plutonium/resource/controller.rb +51 -34
  98. data/lib/plutonium/resource/controllers/authorizable.rb +128 -0
  99. data/lib/plutonium/{core → resource}/controllers/crud_actions.rb +23 -22
  100. data/lib/plutonium/resource/controllers/defineable.rb +26 -0
  101. data/lib/plutonium/{core → resource}/controllers/interactive_actions.rb +12 -12
  102. data/lib/plutonium/resource/controllers/presentable.rb +41 -0
  103. data/lib/plutonium/resource/controllers/queryable.rb +44 -0
  104. data/lib/plutonium/resource/definition.rb +6 -0
  105. data/lib/plutonium/resource/policy.rb +25 -13
  106. data/lib/plutonium/resource/query_object.rb +50 -51
  107. data/lib/plutonium/resource/record.rb +6 -89
  108. data/lib/plutonium/resource/register.rb +82 -0
  109. data/lib/plutonium/routing/mapper_extensions.rb +1 -1
  110. data/lib/plutonium/routing/resource_registration.rb +1 -1
  111. data/lib/plutonium/routing/route_set_extensions.rb +6 -18
  112. data/lib/plutonium/ui/action_button.rb +125 -0
  113. data/lib/plutonium/ui/breadcrumbs.rb +163 -0
  114. data/lib/plutonium/ui/component/base.rb +13 -0
  115. data/lib/plutonium/ui/component/behaviour.rb +38 -0
  116. data/lib/plutonium/ui/component/kit.rb +31 -0
  117. data/lib/plutonium/ui/component/methods.rb +54 -0
  118. data/lib/plutonium/ui/display/base.rb +25 -0
  119. data/lib/plutonium/ui/display/component/association.rb +26 -0
  120. data/lib/plutonium/ui/display/resource.rb +77 -0
  121. data/lib/plutonium/ui/display/theme.rb +27 -0
  122. data/lib/plutonium/ui/dyna_frame/content.rb +20 -0
  123. data/lib/plutonium/ui/empty_card.rb +20 -0
  124. data/lib/plutonium/ui/form/base.rb +37 -0
  125. data/lib/plutonium/ui/form/resource.rb +75 -0
  126. data/lib/plutonium/ui/form/theme.rb +42 -0
  127. data/lib/plutonium/ui/page/base.rb +112 -0
  128. data/lib/plutonium/ui/page/edit.rb +23 -0
  129. data/lib/plutonium/ui/page/index.rb +27 -0
  130. data/lib/plutonium/ui/page/new.rb +23 -0
  131. data/lib/plutonium/ui/page/show.rb +27 -0
  132. data/lib/plutonium/ui/page_header.rb +49 -0
  133. data/lib/plutonium/ui/table/base.rb +13 -0
  134. data/lib/plutonium/ui/table/components/pagy_info.rb +70 -0
  135. data/lib/plutonium/ui/table/components/pagy_page_info.rb +70 -0
  136. data/lib/plutonium/ui/table/components/pagy_pagination.rb +105 -0
  137. data/lib/plutonium/ui/table/components/scopes_bar.rb +136 -0
  138. data/lib/plutonium/ui/table/components/search_bar.rb +158 -0
  139. data/lib/plutonium/ui/table/display_theme.rb +21 -0
  140. data/lib/plutonium/ui/table/resource.rb +98 -0
  141. data/lib/plutonium/ui/table/theme.rb +35 -0
  142. data/lib/plutonium/ui.rb +9 -0
  143. data/lib/plutonium/version.rb +5 -1
  144. data/lib/plutonium.rb +14 -1
  145. data/package-lock.json +19 -22
  146. data/package.json +4 -4
  147. data/src/css/plutonium.css +15 -0
  148. data/tailwind.options.js +11 -3
  149. metadata +218 -81
  150. data/lib/generators/pu/core/install/templates/app/presenters/resource_presenter.rb.tt +0 -2
  151. data/lib/generators/pu/core/install/templates/app/query_objects/resource_query_object.rb.tt +0 -2
  152. data/lib/generators/pu/pkg/feature/templates/app/query_objects/resource_query_object.rb.tt +0 -4
  153. data/lib/plutonium/concerns/resource_validatable.rb +0 -34
  154. data/lib/plutonium/config.rb +0 -9
  155. data/lib/plutonium/core/controllers/base.rb +0 -101
  156. data/lib/plutonium/core/controllers/presentable.rb +0 -65
  157. data/lib/plutonium/core/controllers/queryable.rb +0 -28
  158. data/lib/plutonium/pkg/app.rb +0 -35
  159. data/lib/plutonium/pkg/concerns/resource_validatable.rb +0 -36
  160. data/lib/plutonium/pkg/feature.rb +0 -18
  161. data/lib/plutonium/policy/initializer.rb +0 -22
  162. data/lib/plutonium/policy/scope.rb +0 -19
  163. data/lib/plutonium/pundit/context.rb +0 -18
  164. data/lib/plutonium/pundit/policy_finder.rb +0 -25
  165. data/lib/plutonium/resource/policy_context.rb +0 -5
  166. data/lib/plutonium/resource_register.rb +0 -83
  167. data/lib/plutonium/smart_cache.rb +0 -151
  168. /data/app/views/{application → plutonium}/_flash.html.erb +0 -0
  169. /data/app/views/{application → plutonium}/_flash_alerts.html.erb +0 -0
  170. /data/app/views/{application → plutonium}/_flash_toasts.html.erb +0 -0
  171. /data/lib/generators/pu/pkg/{app/templates/app/views/package → package/templates}/.keep +0 -0
  172. /data/lib/generators/pu/pkg/{feature → package}/templates/app/interactions/resource_interaction.rb.tt +0 -0
  173. /data/lib/generators/pu/pkg/{feature → package}/templates/app/models/resource_record.rb.tt +0 -0
  174. /data/lib/generators/pu/pkg/{feature → package}/templates/app/policies/resource_policy.rb.tt +0 -0
  175. /data/lib/generators/pu/pkg/{feature → package}/templates/app/presenters/resource_presenter.rb.tt +0 -0
  176. /data/lib/generators/pu/pkg/{feature → package}/templates/lib/engine.rb.tt +0 -0
  177. /data/lib/generators/pu/pkg/{app → portal}/templates/app/policies/resource_policy.rb.tt +0 -0
  178. /data/lib/generators/pu/pkg/{app → portal}/templates/app/presenters/resource_presenter.rb.tt +0 -0
  179. /data/lib/generators/pu/pkg/{app → portal}/templates/app/query_objects/resource_query_object.rb.tt +0 -0
  180. /data/lib/generators/pu/pkg/{feature/templates → portal/templates/app/views/package}/.keep +0 -0
  181. /data/lib/generators/pu/pkg/{app → portal}/templates/config/routes.rb.tt +0 -0
  182. /data/lib/generators/pu/pkg/{app → portal}/templates/lib/engine.rb.tt +0 -0
@@ -1,5 +1,5 @@
1
1
  module Plutonium
2
- module Core
2
+ module Resource
3
3
  module Controllers
4
4
  module CrudActions
5
5
  extend ActiveSupport::Concern
@@ -10,44 +10,40 @@ module Plutonium
10
10
 
11
11
  # GET /resources(.{format})
12
12
  def index
13
- authorize resource_class
13
+ authorize_current! resource_class
14
14
  set_page_title resource_class.model_name.human.pluralize.titleize
15
15
 
16
16
  @search_object = current_query_object
17
- base_query = policy_scope(resource_class)
17
+ base_query = current_authorized_scope
18
18
  base_query = @search_object.apply(base_query)
19
- base_query = base_query.public_send(params[:scope].to_sym) if params[:scope].present?
19
+ # base_query = base_query.public_send(params[:scope].to_sym) if params[:scope].present?
20
20
  @pagy, @resource_records = pagy base_query
21
- @collection = build_collection
22
21
 
23
22
  render :index
24
23
  end
25
24
 
26
25
  # GET /resources/1(.{format})
27
26
  def show
28
- authorize resource_record
27
+ authorize_current! resource_record
29
28
  set_page_title resource_record.to_label.titleize
30
29
 
31
- @detail = build_detail
32
-
33
30
  render :show
34
31
  end
35
32
 
36
33
  # GET /resources/new
37
34
  def new
38
- authorize resource_class
35
+ authorize_current! resource_class
39
36
  set_page_title "Create #{resource_class.model_name.human.titleize}"
40
37
 
41
38
  @resource_record = resource_class.new
42
39
  maybe_apply_submitted_resource_params!
43
- @form = build_form
44
40
 
45
41
  render :new
46
42
  end
47
43
 
48
44
  # POST /resources(.{format})
49
45
  def create
50
- authorize resource_class
46
+ authorize_current! resource_class
51
47
  set_page_title "Create #{resource_class.model_name.human.titleize}"
52
48
 
53
49
  @resource_record = resource_class.new resource_params
@@ -61,7 +57,6 @@ module Plutonium
61
57
  format.any { render :show, status: :created, location: redirect_url_after_submit }
62
58
  else
63
59
  format.html do
64
- @form = build_form
65
60
  render :new, status: :unprocessable_entity
66
61
  end
67
62
  format.any do
@@ -74,18 +69,17 @@ module Plutonium
74
69
 
75
70
  # GET /resources/1/edit
76
71
  def edit
77
- authorize resource_record
72
+ authorize_current! resource_record
78
73
  set_page_title "Update #{resource_record.to_label.titleize}"
79
74
 
80
75
  maybe_apply_submitted_resource_params!
81
- @form = build_form
82
76
 
83
77
  render :edit
84
78
  end
85
79
 
86
80
  # PATCH/PUT /resources/1(.{format})
87
81
  def update
88
- authorize resource_record
82
+ authorize_current! resource_record
89
83
  set_page_title "Update #{resource_record.to_label.titleize}"
90
84
 
91
85
  respond_to do |format|
@@ -97,7 +91,6 @@ module Plutonium
97
91
  format.any { render :show, status: :ok, location: redirect_url_after_submit }
98
92
  else
99
93
  format.html do
100
- @form = build_form
101
94
  render :edit, status: :unprocessable_entity
102
95
  end
103
96
  format.any do
@@ -110,13 +103,13 @@ module Plutonium
110
103
 
111
104
  # DELETE /resources/1(.{format})
112
105
  def destroy
113
- authorize resource_record
106
+ authorize_current! resource_record
114
107
 
115
108
  respond_to do |format|
116
109
  resource_record.destroy
117
110
 
118
111
  format.html do
119
- redirect_to resource_url_for(resource_class),
112
+ redirect_to redirect_url_after_destroy,
120
113
  notice: "#{resource_class.model_name.human} was successfully deleted."
121
114
  end
122
115
  format.json { head :no_content }
@@ -143,13 +136,13 @@ module Plutonium
143
136
 
144
137
  url = case preferred_action_after_submit
145
138
  when "show"
146
- resource_url_for(resource_record) if current_policy.show?
139
+ resource_url_for(resource_record) if current_policy.allowed_to? :show?
147
140
  when "edit"
148
- resource_url_for(resource_record, action: :edit) if current_policy.edit?
141
+ resource_url_for(resource_record, action: :edit) if current_policy.allowed_to? :edit?
149
142
  when "new"
150
- resource_url_for(resource_class, action: :new) if current_policy.new?
143
+ resource_url_for(resource_class, action: :new) if current_policy.allowed_to? :new?
151
144
  when "index"
152
- resource_url_for(resource_class) if current_policy.index?
145
+ resource_url_for(resource_class) if current_policy.allowed_to? :index?
153
146
  else
154
147
  # ensure we have a valid value
155
148
  session[:action_after_submit_preference] = "show"
@@ -157,6 +150,14 @@ module Plutonium
157
150
  url || resource_url_for(resource_record)
158
151
  end
159
152
 
153
+ def redirect_url_after_destroy
154
+ if (return_to = url_from(params[:return_to]))
155
+ return return_to
156
+ end
157
+
158
+ resource_url_for(resource_class)
159
+ end
160
+
160
161
  def preferred_action_after_submit
161
162
  @preferred_action_after_submit = begin
162
163
  if %w[new edit show index].include? params[:commit]
@@ -0,0 +1,26 @@
1
+ using Plutonium::Refinements::ParameterRefinements
2
+
3
+ module Plutonium
4
+ module Resource
5
+ module Controllers
6
+ module Defineable
7
+ extend ActiveSupport::Concern
8
+
9
+ included do
10
+ helper_method :current_definition, :resource_definition
11
+ end
12
+
13
+ private
14
+
15
+ def resource_definition(resource_class)
16
+ definition_class = "#{resource_class}Definition".constantize
17
+ definition_class.new
18
+ end
19
+
20
+ def current_definition
21
+ @current_definition ||= resource_definition resource_class
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -1,5 +1,5 @@
1
1
  module Plutonium
2
- module Core
2
+ module Resource
3
3
  module Controllers
4
4
  module InteractiveActions
5
5
  extend ActiveSupport::Concern
@@ -7,17 +7,17 @@ module Plutonium
7
7
  included do
8
8
  helper_method :current_interactive_action
9
9
 
10
- before_action :validate_interactive_resource_action, only: %i[
10
+ before_action :validate_interactive_resource_action!, only: %i[
11
11
  begin_interactive_resource_record_action commit_interactive_resource_record_action
12
12
  begin_interactive_resource_collection_action commit_interactive_resource_collection_action
13
13
  begin_interactive_resource_recordless_action commit_interactive_resource_recordless_action
14
14
  ]
15
15
 
16
- before_action :authorize_interactive_resource_record_action, only: %i[
16
+ before_action :authorize_interactive_resource_record_action!, only: %i[
17
17
  begin_interactive_resource_record_action commit_interactive_resource_record_action
18
18
  ]
19
19
 
20
- before_action :authorize_interactive_resource_action, only: %i[
20
+ before_action :authorize_interactive_resource_action!, only: %i[
21
21
  begin_interactive_resource_collection_action commit_interactive_resource_collection_action
22
22
  begin_interactive_resource_recordless_action commit_interactive_resource_recordless_action
23
23
  ]
@@ -123,7 +123,7 @@ module Plutonium
123
123
 
124
124
  # GET /resources/actions/:interactive_action
125
125
  def begin_interactive_resource_recordless_action
126
- skip_policy_scope
126
+ # skip_policy_scope
127
127
 
128
128
  @interaction = current_interactive_action.interaction.new interaction_params
129
129
 
@@ -136,7 +136,7 @@ module Plutonium
136
136
 
137
137
  # POST /resources/actions/:interactive_action
138
138
  def commit_interactive_resource_recordless_action
139
- skip_policy_scope
139
+ # skip_policy_scope
140
140
 
141
141
  respond_to do |format|
142
142
  inputs = interaction_params
@@ -182,25 +182,25 @@ module Plutonium
182
182
  @interactive_resource_actions ||= current_presenter.actions.except :new, :show, :edit, :destroy
183
183
  end
184
184
 
185
- def validate_interactive_resource_action
185
+ def validate_interactive_resource_action!
186
186
  interactive_resource_action = params[:interactive_action]&.to_sym
187
187
  unless interactive_resource_actions.key?(interactive_resource_action)
188
188
  raise ::AbstractController::ActionNotFound, "Unknown action '#{interactive_resource_action}'"
189
189
  end
190
190
  end
191
191
 
192
- def authorize_interactive_resource_record_action
192
+ def authorize_interactive_resource_record_action!
193
193
  interactive_resource_action = params[:interactive_action]&.to_sym
194
- authorize resource_record, :"#{interactive_resource_action}?"
194
+ authorize_current! resource_record, to: :"#{interactive_resource_action}?"
195
195
  end
196
196
 
197
- def authorize_interactive_resource_action
197
+ def authorize_interactive_resource_action!
198
198
  interactive_resource_action = params[:interactive_action]&.to_sym
199
- authorize resource_class, :"#{interactive_resource_action}?"
199
+ authorize_current! resource_class, to: :"#{interactive_resource_action}?"
200
200
  end
201
201
 
202
202
  def interactive_resource_collection
203
- @interactive_resource_collection ||= policy_scope(resource_class).from_path_param(params.require(:ids)).all
203
+ @interactive_resource_collection ||= current_authorized_scope.from_path_param(params.require(:ids))
204
204
  end
205
205
 
206
206
  def interaction_params
@@ -0,0 +1,41 @@
1
+ module Plutonium
2
+ module Resource
3
+ module Controllers
4
+ module Presentable
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ helper_method :presentable_attributes, :present_associations?
9
+ helper_method :build_form, :build_detail, :build_collection
10
+ end
11
+
12
+ private
13
+
14
+ def presentable_attributes
15
+ @presentable_attributes ||= begin
16
+ presentable_attributes = permitted_attributes
17
+ presentable_attributes -= [scoped_entity_param_key, :"#{scoped_entity_param_key}_id"] if scoped_to_entity?
18
+ presentable_attributes -= [parent_input_param, :"#{parent_input_param}_id"] if current_parent.present?
19
+ presentable_attributes
20
+ end
21
+ end
22
+
23
+ def build_collection
24
+ current_definition.collection_class.new(@resource_records, resource_fields: presentable_attributes, resource_definition: current_definition)
25
+ end
26
+
27
+ def build_detail
28
+ current_definition.detail_class.new(resource_record, resource_fields: presentable_attributes, resource_associations: permitted_associations, resource_definition: current_definition)
29
+ end
30
+
31
+ def build_form(record = resource_record)
32
+ current_definition.form_class.new(record, resource_fields: presentable_attributes, resource_definition: current_definition)
33
+ end
34
+
35
+ def present_associations?
36
+ current_parent.nil?
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,44 @@
1
+ using Plutonium::Refinements::ParameterRefinements
2
+
3
+ module Plutonium
4
+ module Resource
5
+ module Controllers
6
+ module Queryable
7
+ extend ActiveSupport::Concern
8
+
9
+ included do
10
+ helper_method :resource_query_params, :current_query_object
11
+ end
12
+
13
+ def resource_query_object(resource_class, params)
14
+ query_object_class = "#{resource_class}QueryObject".constantize
15
+ query_object_class.new resource_context, params
16
+ end
17
+
18
+ def current_query_object
19
+ @current_query_object ||= Plutonium::Resource::QueryObject.new(resource_context, resource_query_params) do |query_object|
20
+ if current_definition.search_definition
21
+ query_object.define_search proc { |scope, search:|
22
+ current_definition.search_definition.call(scope, search)
23
+ }
24
+ end
25
+
26
+ current_definition.defined_scopes.each do |key, value|
27
+ query_object.define_scope key, value[:block]
28
+ end
29
+
30
+ current_definition.defined_sorts.each do |key, value|
31
+ query_object.define_sorter key, value[:block]
32
+ end
33
+
34
+ query_object
35
+ end
36
+ end
37
+
38
+ def resource_query_params
39
+ (params[:q]&.nilify&.to_unsafe_h || {}).with_indifferent_access
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,6 @@
1
+ module Plutonium
2
+ module Resource
3
+ class Definition < Plutonium::Definition::Base
4
+ end
5
+ end
6
+ end
@@ -1,13 +1,19 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Plutonium
2
4
  module Resource
3
5
  # Policy class to define permissions and attributes for a resource.
4
6
  # This class provides methods to check permissions for various actions
5
7
  # and to retrieve permitted attributes for these actions.
6
- class Policy
7
- include Plutonium::Policy::Initializer
8
+ class Policy < ActionPolicy::Base
9
+ authorize :user, allow_nil: false
10
+ authorize :scope, allow_nil: true
8
11
 
9
- # Scope class to define the scope of the policy.
10
- class Scope < Plutonium::Policy::Scope
12
+ relation_scope do |relation|
13
+ if scope.present?
14
+ relation = relation.associated_with(scope)
15
+ end
16
+ relation
11
17
  end
12
18
 
13
19
  # Sends a method and raises an error if the method is not implemented.
@@ -95,7 +101,7 @@ module Plutonium
95
101
  # @return [Array<Symbol>] The permitted attributes.
96
102
  def permitted_attributes_for_create
97
103
  autodetect_permitted_fields(:permitted_attributes_for_create) - [
98
- context.resource_context.resource_class.primary_key.to_sym, # primary_key
104
+ resource_class.primary_key.to_sym, # primary_key
99
105
  :created_at, :updated_at # timestamps
100
106
  ]
101
107
  end
@@ -153,13 +159,17 @@ module Plutonium
153
159
 
154
160
  private
155
161
 
162
+ def resource_class
163
+ record.instance_of?(Class) ? record : record.class
164
+ end
165
+
156
166
  # Autodetects the permitted fields for a given method.
157
167
  #
158
168
  # @param method_name [Symbol] The name of the method.
159
169
  # @return [Array<Symbol>] The auto-detected permitted fields.
160
170
  def autodetect_permitted_fields(method_name)
161
171
  warn_about_autodetect_usage(method_name)
162
- context.resource_context.resource_class.resource_field_names
172
+ resource_class.resource_field_names
163
173
  end
164
174
 
165
175
  # Warns about the usage of auto-detection of fields.
@@ -171,16 +181,18 @@ module Plutonium
171
181
  raise "Resource field auto-detection: #{self.class}##{method} outside development"
172
182
  end
173
183
 
174
- Plutonium.logger.warn %(
175
- 🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
184
+ Plutonium.logger.warn {
185
+ %(
186
+ 🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
176
187
 
177
- Resource field auto-detection: #{self.class}##{method}
188
+ Resource field auto-detection: #{self.class}##{method}
178
189
 
179
- Auto-detected resource fields result in security holes and will fail outside of development.
180
- Override #{context.resource_context.resource_class}Policy or #{self.class} with your own ##{method} method.
190
+ Auto-detected resource fields result in security holes and will fail outside of development.
191
+ Override #{resource_class}Policy or #{self.class} with your own ##{method} method.
181
192
 
182
- 🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
183
- )
193
+ 🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
194
+ )
195
+ }
184
196
  end
185
197
  end
186
198
  end
@@ -102,7 +102,7 @@ module Plutonium
102
102
  #
103
103
  # @param context [Object] The context in which the query object is used.
104
104
  # @param params [Hash] The parameters for initialization.
105
- def initialize(context, params)
105
+ def initialize(context, params, &)
106
106
  @context = context
107
107
 
108
108
  define_standard_queries
@@ -110,10 +110,54 @@ module Plutonium
110
110
  define_filters
111
111
  define_sorters
112
112
 
113
+ yield self if block_given?
114
+
113
115
  extract_filter_params(params)
114
116
  extract_sort_params(params)
115
117
  end
116
118
 
119
+ # Defines a filter with the given name and body.
120
+ #
121
+ # @param name [Symbol] The name of the filter.
122
+ # @param body [Proc, nil] The body of the filter.
123
+ def define_filter(name, body = nil, &)
124
+ body ||= name
125
+ filter_definitions[name] = build_query(body, &)
126
+ end
127
+
128
+ # Defines a scope with the given name and body.
129
+ #
130
+ # @param name [Symbol] The name of the scope.
131
+ # @param body [Proc, nil] The body of the scope.
132
+ def define_scope(name, body = nil)
133
+ body ||= name
134
+ scope_definitions[name] = build_query(body)
135
+ end
136
+
137
+ # Defines a sort with the given name and body.
138
+ #
139
+ # @param name [Symbol] The name of the sort.
140
+ # @param body [Proc, nil] The body of the sort.
141
+ def define_sorter(name, body = nil)
142
+ if body.nil?
143
+ sort_field = determine_sort_field(name)
144
+ body = ->(scope, direction:) { scope.order(sort_field => direction) }
145
+ end
146
+
147
+ sort_definitions[name] = build_query(body) do |query|
148
+ query.define_field_input :direction
149
+ end
150
+ end
151
+
152
+ # Defines a search filter with the given body.
153
+ #
154
+ # @param body [Proc, Symbol] The body of the search filter.
155
+ def define_search(body)
156
+ @search_filter = build_query(body) do |query|
157
+ query.define_field_input :search
158
+ end
159
+ end
160
+
117
161
  # Builds a URL with the given options for search and sorting.
118
162
  #
119
163
  # @param options [Hash] The options for building the URL.
@@ -186,48 +230,6 @@ module Plutonium
186
230
  define_search(:search) if resource_class.respond_to?(:search)
187
231
  end
188
232
 
189
- # Defines a filter with the given name and body.
190
- #
191
- # @param name [Symbol] The name of the filter.
192
- # @param body [Proc, nil] The body of the filter.
193
- def define_filter(name, body = nil, &)
194
- body ||= name
195
- filter_definitions[name] = build_query(body, &)
196
- end
197
-
198
- # Defines a scope with the given name and body.
199
- #
200
- # @param name [Symbol] The name of the scope.
201
- # @param body [Proc, nil] The body of the scope.
202
- def define_scope(name, body = nil)
203
- body ||= name
204
- scope_definitions[name] = build_query(body)
205
- end
206
-
207
- # Defines a sort with the given name and body.
208
- #
209
- # @param name [Symbol] The name of the sort.
210
- # @param body [Proc, nil] The body of the sort.
211
- def define_sorter(name, body = nil)
212
- if body.nil?
213
- sort_field = determine_sort_field(name)
214
- body = ->(scope, direction:) { scope.order(sort_field => direction) }
215
- end
216
-
217
- sort_definitions[name] = build_query(body) do |query|
218
- query.define_field_input :direction
219
- end
220
- end
221
-
222
- # Defines a search filter with the given body.
223
- #
224
- # @param body [Proc, Symbol] The body of the search filter.
225
- def define_search(body)
226
- @search_filter = build_query(body) do |query|
227
- query.define_field_input :search
228
- end
229
- end
230
-
231
233
  # Extracts filter parameters from the given params.
232
234
  #
233
235
  # @param params [Hash] The parameters to extract.
@@ -308,14 +310,11 @@ module Plutonium
308
310
  query_params[:sort_fields] << sort.to_s unless query_params[:sort_fields].include?(sort.to_s)
309
311
 
310
312
  sort_direction = selected_sort_directions[sort]
311
- if sort_direction.nil?
312
- query_params[:sort_directions][sort] = "ASC"
313
- elsif sort_direction == "ASC"
314
- query_params[:sort_directions][sort] = "DESC"
315
- else
316
- query_params[:sort_fields].delete_if { |e| e == sort.to_s }
317
- query_params[:sort_directions].delete(sort)
318
- end
313
+ query_params[:sort_directions][sort] = (sort_direction == "ASC") ? "DESC" : "ASC"
314
+ # else
315
+ # query_params[:sort_fields].delete_if { |e| e == sort.to_s }
316
+ # query_params[:sort_directions].delete(sort)
317
+ # end
319
318
  end
320
319
  end
321
320