hot-glue 0.5.19.2 → 0.5.20

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 016741b47374d4b624bb04c96757bf92ca48bef198ca39ff642d94b571024949
4
- data.tar.gz: 91ac3ecd1745958f7df484cb1ad009b63e02891e8f9021e7c7cd062aff7baaf6
3
+ metadata.gz: 48857d455006404276d88ee9481b21664a413e14403f8432a26cb13fc4351f4a
4
+ data.tar.gz: d15f7a0d742a7164e0f58c4bd25a620198efed8106c7e36bfeea1a34251d4889
5
5
  SHA512:
6
- metadata.gz: 32b258df9e7f7d989d7827aa5ed420019bc6283447822f254a01ebfc4dd705dcb2428d73f9685a65ed2e6157b114a38a8395144f351a16144f03b61ecc4c26c7
7
- data.tar.gz: e66eea5d26d987815a0583c80e49401a55fefaa59e5a2db503cc7fe488c403103a5699895966e73415dd2ca0de21452022cd1b68445859e8338330376c7aacf0
6
+ metadata.gz: 916d29b5b2f60c273bf9d0094511d95b39b54f8d57c3b41c251d17dc9b7f918914a6ca529f4eca000461fa7c2b4e2b36f954fb3ee59f0fda8a8ed53038c773e0
7
+ data.tar.gz: cbddef65679e3dd42d18143d964f3a9ad9ccb25490bfc054d8fd73f23c24d0a74751a8e07c96fc5404792bb6fe553b2d70a6f6fc168ceaf4a39247d96a4d360e
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- hot-glue (0.5.19.1)
4
+ hot-glue (0.5.19.2)
5
5
  ffaker (~> 2.16)
6
6
  kaminari (~> 1.2)
7
7
  rails (> 5.1)
data/README.md CHANGED
@@ -75,15 +75,11 @@ For Hot Glue, you will need:
75
75
 
76
76
  Section #1 is to create a new Rails app. (Or you can do that yourself.)
77
77
 
78
- Section #2 is to setup Rspec, FactoryBot, and Faker.
78
+ Section #2 is to setup Rspec, FactoryBot, and Faker — choose 2B for Rspec0
79
79
 
80
- Section #4 is optional but highly recommended.
80
+ Skip #3 and #4 is optional. #5 is optional but recommended.
81
81
 
82
- Section #5 is where you will pick a CSS Framework (Bootstrap, Tailwind, or none)
83
-
84
- Section #6 is for two support gems (Kaminari) for Hot Glue
85
-
86
- Section #7 is for Hot Glue itself
82
+ Sectoin #6 is for Hot Glue itself, and Section #7 is for Kaminari
87
83
 
88
84
  You will also need section #8 to setup Devise if you want authentication.
89
85
 
@@ -645,15 +641,6 @@ This is what would happen if 9 fields, specified in the order A,B,C,D,E,F,G,H,I,
645
641
 
646
642
 
647
643
 
648
- ### `--show-only=`
649
- (separate field names by COMMA)
650
-
651
- Any fields only the 'show-only' list will appear as non-editable on the generated form for both new & edit actions. (visible only)
652
-
653
- IMPORTANT: By default, all fields that begin with an underscore (`_`) are automatically show-only.
654
-
655
- This is for fields you want globally non-editable by users in your app. For example, a counter cache or other field set only by a backend mechanism.
656
-
657
644
  ### `--modify=field1{...},field2{...}`
658
645
 
659
646
 
@@ -685,12 +672,92 @@ The available modifiers are:
685
672
  | truthy label\|falsy label | specify a binary switch with a pipe (\|) character if the value is truthy, it will display as "truthy label" if the value is falsy, it will display as "falsy label" | boolean, datetime, date, time | | |
686
673
  | | | | | |
687
674
 
675
+ ### `--pundit`
676
+ If you enable Pundit, your controllers will look for a Policy that matches the name of the thing being built.
677
+
678
+ **Realtime Field-level Access**
679
+ Hot Glue gives you automatic field level access control if you create `*_able?` methods for each field you'd like to control on your Pundit policy.
680
+
681
+ (Although this is not what Pundit recommends for field level access control, it has been implemented this way to provide field-by-field user feedback to the user shown in red just like Rails validation errors are currently shown. This is is only hypothetical, because the interface correctly shows the field as viewable or editable anyway, making bad entry only something that could be achieved through a mistake or hacking. Nevertheless, rest assured that if there was a input mistake-- like a user having a field editable when it shouldn't be, the backend policy would guard against the disallowed input and show an error message.)
682
+
683
+ The `*_able?` method should return true or false depending on whether or not the field can be edited. (No distinction is made between the different contexts. You may check if the record is new using `new_record?`.
684
+
685
+ The `*_able?` method is used by Hot Glue only on the new and edit actions, but you should incorporate it into the policy's `update?` method as in the example, which will extend other operations since Hot Glue will use the policy to authorize the action
686
+ Add one `*_able?` method to the policy for each field you want to allow field-level access control.
687
+
688
+ Replace `*` with the name of the field you want under access control. Remember to include `_id` for foreign keys. You do not need it for any field you don't want under access control.
689
+
690
+ When the method returns true, the field will be displayed to the user (and allowed) for editing.
691
+ When the method returns false, the field will be displayed as read-only (viewable) to the user.
692
+
693
+ Important: These special fields determine *only* display behavior (new and edit), not create and update.
694
+
695
+ For create & update field-level access control, you must also implement the `update?` method on the Policy. Notice how in the example policy below, the `update?` method uses the `name_able?` method when it is checking if the name field can be updated, tying the feature together.
696
+
697
+ You can set Pundit to be enabled globally on the whole project for every build in `config/hot_glue.yml` (then you can leave off the `--pundit` flag from the scaffold command)
698
+ `:pundit_default:` (all builds in that project will use Pundit)
699
+
700
+
701
+ Here's an example `ThingPolicy` that would allow **editing the name field** only if:
702
+ • the current user is an admin
703
+ • the sent_at date is nil (meaning it has not been sent yet)
704
+
705
+ For your policies, copy the `initialize` method of both the outer class (`ThingPolicy`) and the inner class (`Scope`) exactly as shown below.
706
+
707
+
708
+ ```
709
+ class ThingPolicy < ApplicationPolicy
710
+ def initialize(user, record)
711
+ @user = user
712
+ @record = record
713
+ end
714
+
715
+ def name_able?
716
+ @record.sent_at.nil?
717
+ end
718
+
719
+ def update?
720
+ if !@user.is_admin?
721
+ return false
722
+ elsif record.name_changed? && !name_able?
723
+ record.errors.add(:name, "cannot be changed.")
724
+ return false
725
+ else
726
+ return true
727
+ end
728
+ end
729
+
730
+ class Scope < Scope
731
+ attr_reader :user, :scope
732
+ def initialize(user, scope)
733
+ @user = user
734
+ @scope = scope
735
+ end
736
+ end
737
+ end
738
+ ```
739
+
740
+
741
+ Because Hot Glue detects the `*_able?` methods at build time, if you add them to your policy, you will have to rebuild your scaffold.
742
+
743
+
744
+ ### `--show-only=`
745
+ (separate field names by COMMA)
746
+
747
+ • Make this field appear as viewable only all actions. (visible only)
748
+ • When set on this list, it will override any Pundit policy even when Pundit would otherwise allow the access.
749
+
750
+ IMPORTANT: By default, all fields that begin with an underscore (`_`) are automatically show-only.
751
+
752
+ This is for fields you want globally non-editable by users in your app. For example, a counter cache or other field set only by a backend mechanism.
688
753
 
689
754
 
690
755
  ### `--update-show-only`
691
756
  (separate field names by COMMA)
692
757
 
693
- Fields on the `update show only` (and not on the `show only` list) will appear as non-editible only for the **edit** action, but will still allow entry for the **create** action.
758
+ Make this field appear as viewable only for the edit action (and not allowed in the update action).
759
+ • When set on this list, it will override any Pundit policy for edit/update actions even when Pundit would otherwise allow the access.
760
+
694
761
 
695
762
  Note that Hot Glue still generates a singular partial (`_form`) for both actions, but your form will now contain statements like:
696
763
 
@@ -705,6 +772,35 @@ Note that Hot Glue still generates a singular partial (`_form`) for both actions
705
772
  This works for both regular fields, association fields, and alt lookup fields.
706
773
 
707
774
 
775
+ When mixing the show only, update show only, and Pundit features, notice that the show only + update show only will act to override whatever the policy might say.
776
+
777
+ Remember, the show only list is specified using `--show-only` and the update show only list is specified using `--update-show-only`.
778
+
779
+ 'Viewable' means it displays as view-only (not editable) even on the form. In this context, 'viewable' means 'read-only'. It does not mean 'visible'.
780
+
781
+ That's because when the field is **not viewable**, then it is editable or inputable. This may seem counter-intuitive for a standard interpretation of the word 'viewable,' but consider that Hot Glue has been carefully designed this way. If you do not want the field to appear at all, then you simply remove it using the exclude list or don't specify it in your include list. If the field is being built at all, Hot Glue assumes your users want to see or edit it. Other special cases are beyond the scope of Hot Glue but can easily be added using direct customization of the code.
782
+
783
+ Without Pundit:
784
+ | | on new screen | on edit screen |
785
+ |------------------------------------------|---------------|----------------|
786
+ | for a field on the show only list | viewable | viewable |
787
+ | for a field on the update show only list | inputable | viewable |
788
+ | for all other fields | inputable | inputable |
789
+
790
+
791
+ With Pundit:
792
+ | | on new screen | on edit screen |
793
+ |------------------------------------------|---------------|----------------|
794
+ | for a field on the show only list | viewable | viewable |
795
+ | for a field on the update show only list | check policy | viewable |
796
+ | for all other fields | check policy | check policy |
797
+ | | | |
798
+
799
+ Remember, if there's a corresponding `*_able?` method on the policy, it will be used to determine if the field is **editable** or not in the cases where 'check policy' is above.
800
+ (where `*` is the name of your field)
801
+
802
+ As shown in the method `name_able?` of the example ThingPolicy above, if this field on your policy returns true, the field will be editable. If it returns false, the field will be viewable (read-only).
803
+
708
804
 
709
805
  ### `--ujs_syntax=true` (Default is set automatically based on whether you have turbo-rails installed)
710
806
 
@@ -1300,6 +1396,12 @@ end
1300
1396
 
1301
1397
  # VERSION HISTORY
1302
1398
 
1399
+ #### 2023-09-08 - v0.5.20
1400
+ `--pundit` authorization
1401
+ • Will look for a `XyzPolicy` class and method on your class named `*_able?` matching the fields on your object. See Pundit section for details.
1402
+ • Field-level access control (can determine which fields are editble or viewable based on the record or current user or combination factors)
1403
+ • The field-level access control doesn't show the fields as editable to the user if they can't be edited by the user (it shows them as view-only).
1404
+
1303
1405
  #### 2023-09-02 - v0.5.19
1304
1406
 
1305
1407
  Given a table generated with this schema:
@@ -116,7 +116,7 @@ class AssociationField < Field
116
116
 
117
117
  def form_show_only_output
118
118
  assoc_name = name.to_s.gsub("_id","")
119
- assoc = eval("#{singular_class}.reflect_on_association(:#{assoc_name})")
119
+ assoc = eval("#{class_name}.reflect_on_association(:#{assoc_name})")
120
120
  if assoc.nil?
121
121
  exit_message = "*** Oops. on the #{singular_class} object, there doesn't seem to be an association called '#{assoc_name}'"
122
122
  exit
@@ -37,7 +37,7 @@ class DateTimeField < Field
37
37
  "<%= datetime_field_localized(f, :#{name}, #{singular}.#{name}, '#{ name.to_s.humanize }') %>"
38
38
  end
39
39
 
40
- def line_field_output
40
+ def viewable_output
41
41
  if modify_binary?
42
42
  modified_display_output
43
43
  else
@@ -115,7 +115,7 @@ class Field
115
115
  end
116
116
 
117
117
  def modified_display_output
118
- if modify[:cast] && modify[:cast] == "$"
118
+ if modify[:cast] && modify[:cast] == "$"
119
119
  "<%= number_to_currency(#{singular}.#{name}) %>"
120
120
  elsif modify[:binary]
121
121
  "<%= #{singular}.#{name} ? '#{modify[:binary][:truthy]}' : '#{modify[:binary][:falsy]}' %>"
@@ -8,7 +8,7 @@ module HotGlue
8
8
  :inline_list_labels, :layout_object,
9
9
  :columns, :col_identifier, :singular,
10
10
  :form_placeholder_labels, :hawk_keys, :update_show_only,
11
- :alt_lookups, :attachments, :show_only, :columns_map
11
+ :alt_lookups, :attachments, :show_only, :columns_map, :pundit
12
12
 
13
13
 
14
14
  def initialize(singular:, singular_class: ,
@@ -17,7 +17,7 @@ module HotGlue
17
17
  ownership_field: , form_labels_position: ,
18
18
  inline_list_labels: ,
19
19
  form_placeholder_labels:, hawk_keys: ,
20
- update_show_only:, alt_lookups: , attachments: , columns_map: )
20
+ update_show_only:, alt_lookups: , attachments: , columns_map:, pundit: )
21
21
 
22
22
  @singular = singular
23
23
  @singular_class = singular_class
@@ -28,6 +28,7 @@ module HotGlue
28
28
  @small_buttons = small_buttons
29
29
  @layout_strategy = layout_strategy
30
30
  @show_only = show_only
31
+ @pundit = pundit
31
32
  @ownership_field = ownership_field
32
33
 
33
34
  @form_labels_position = form_labels_position
@@ -81,30 +82,34 @@ module HotGlue
81
82
  result = columns.map{ |column|
82
83
  " <div class='#{column_classes} cell--#{singular}--#{column.join("-")}' >" +
83
84
  column.map { |col|
84
- field_result = show_only.include?(col.to_sym) ?
85
- columns_map[col].form_show_only_output :
86
- columns_map[col].form_field_output
87
85
 
88
86
  field_error_name = columns_map[col].field_error_name
89
87
 
90
-
91
88
  label_class = columns_map[col].label_class
92
89
  label_for = columns_map[col].label_for
93
90
 
94
91
  the_label = "\n<label class='#{label_class}' for='#{label_for}'>#{col.to_s.humanize}</label>"
95
- show_only_open = ""
96
- show_only_close = ""
97
92
 
98
- if update_show_only.include?(col)
99
- show_only_open = "<% if action_name == 'edit' %>" +
100
- show_only_result(type: type, col: col, singular: singular) + "<% else %>"
101
- show_only_close = "<% end %>"
102
- end
93
+
94
+ field_result =
95
+ if show_only.include?(col)
96
+ columns_map[col].form_show_only_output
97
+ elsif update_show_only.include?(col) && !@pundit
98
+ "<% if action_name == 'edit' %>" + columns_map[col].form_show_only_output + "<% else %>" + columns_map[col].form_field_output + "<% end %>"
99
+ elsif update_show_only.include?(col) && @pundit && eval("defined? #{singular_class}Policy") && eval("#{singular_class}Policy").instance_methods.include?("#{col}_able?".to_sym)
100
+ "<% if action_name == 'create' && policy(@#{singular}).#{col}_able? %>" + columns_map[col].form_show_only_output + "<% else %>" + columns_map[col].form_field_output + "<% end %>"
101
+
102
+ # show only on the update action overrides any pundit policy
103
+ elsif @pundit && eval("defined? #{singular_class}Policy") && eval("#{singular_class}Policy").instance_methods.include?("#{col}_able?".to_sym)
104
+ "<% if policy(@#{singular}).#{col}_able? %>" + columns_map[col].form_field_output + "<% else %>" + columns_map[col].form_show_only_output + "<% end %>"
105
+ else
106
+ columns_map[col].form_field_output
107
+ end
103
108
 
104
109
  add_spaces_each_line( "\n <span class='<%= \"alert-danger\" if #{singular}.errors.details.keys.include?(:#{field_error_name}) %>' #{'style="display: inherit;"'} >\n" +
105
110
  add_spaces_each_line( (form_labels_position == 'before' ? the_label : "") +
106
- show_only_open + field_result + show_only_close +
107
- (form_labels_position == 'after' ? the_label : "") , 4) +
111
+ + field_result +
112
+ (form_labels_position == 'after' ? the_label : "") , 4) +
108
113
  "\n </span>\n <br />", 2)
109
114
 
110
115
  }.join("") + "\n </div>"
@@ -21,7 +21,7 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
21
21
  :display_as, :downnest_children, :downnest_object, :hawk_keys, :layout_object, :modify,
22
22
  :nest_with, :path, :plural, :sample_file_path, :show_only_data, :singular,
23
23
  :singular_class, :smart_layout, :stacked_downnesting, :update_show_only, :ownership_field,
24
- :layout_strategy, :form_placeholder_labels, :form_labels_position
24
+ :layout_strategy, :form_placeholder_labels, :form_labels_position, :pundit
25
25
 
26
26
  class_option :singular, type: :string, default: nil
27
27
  class_option :plural, type: :string, default: nil
@@ -81,6 +81,7 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
81
81
  class_option :button_icons, default: nil
82
82
  class_option :modify, default: {}
83
83
  class_option :display_as, default: {}
84
+ class_option :pundit, default: nil
84
85
 
85
86
  def initialize(*meta_args)
86
87
  super
@@ -295,6 +296,12 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
295
296
  @display_list_after_update = options['display_list_after_update'] || false
296
297
  @smart_layout = options['smart_layout']
297
298
 
299
+ @pundit = options['pundit']
300
+ if @pundit.nil?
301
+ @pundit = get_default_from_config(key: :pundit_default)
302
+ end
303
+
304
+
298
305
  if options['include'].include?(":") && @smart_layout
299
306
  raise HotGlue::Error, "You specified both --smart-layout and also specified grouping mode (there is a : character in your field include list); you must remove the colon(s) from your --include tag or remove the --smart-layout option"
300
307
  end
@@ -443,7 +450,8 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
443
450
  form_placeholder_labels: @form_placeholder_labels,
444
451
  alt_lookups: @alt_lookups,
445
452
  attachments: @attachments,
446
- columns_map: @columns_map
453
+ columns_map: @columns_map,
454
+ pundit: @pundit,
447
455
  )
448
456
  elsif @markup == "slim"
449
457
  raise(HotGlue::Error, "SLIM IS NOT IMPLEMENTED")
@@ -806,7 +814,8 @@ class HotGlue::ScaffoldGenerator < Erb::Generators::ScaffoldGenerator
806
814
  show_only_list = which_partial == :create ? @show_only : (@update_show_only + @show_only)
807
815
 
808
816
  if show_only_list.include?(col)
809
- " page.should have_no_selector(:css, \"[name='#{testing_name}[#{ col.to_s }]'\")"
817
+ # TODO: decide if this should get re-implemeneted
818
+ # " page.should have_no_selector(:css, \"[name='#{testing_name}[#{ col.to_s }]'\")"
810
819
  else
811
820
  col_obj.spec_setup_and_change_act(which_partial)
812
821
  end
@@ -65,21 +65,29 @@ class <%= controller_class_name %> < <%= controller_descends_from %>
65
65
  @<%= singular_name %> = (<%= auth_object.gsub("@",'') %><%= " if params.include?(:#{@nested_set[0][:singular]}_id)" if @nested_set.any? && @nested_set[0][:optional] %>)<% if @nested_set.any? && @nested_set[0][:optional] %> || <%= class_name %>.find(params[:id])<% end %>
66
66
  end<% end %>
67
67
 
68
- def load_all_<%= plural %><% if !@self_auth %>
68
+ def load_all_<%= plural %><% if @pundit %>
69
+ @<%= plural_name %> = policy_scope(<%= class_name %>).page(params[:page])<%= n_plus_one_includes %>
70
+ authorize @<%= plural_name %>.all<% else %> <% if !@self_auth %>
69
71
  @<%= plural_name %> = <%= object_scope.gsub("@",'') %>.page(params[:page])<%= n_plus_one_includes %><%= " if params.include?(:#{ @nested_set.last[:singular]}_id)" if @nested_set.any? && @nested_set[0] && @nested_set[0][:optional] %><% if @nested_set[0] && @nested_set[0][:optional] %>
70
72
  @<%= plural_name %> = <%= class_name %>.all<% end %><% else %>
71
73
  @<%= plural_name %> = <%= class_name %>.where(id: <%= auth_object.gsub("@",'') %>.id)<%= n_plus_one_includes %> # returns iterable even though this <%= singular_name %> is only allowed access to themselves<% end %>
74
+ <% end %>
72
75
  end
73
76
 
74
77
  def index
75
- load_all_<%= plural %>
78
+ load_all_<%= plural %><% if @pundit %>
79
+ rescue Pundit::NotAuthorizedError
80
+ flash[:alert] = "You are not authorized to perform this action."<% end %>
76
81
  end
77
82
 
78
83
  <% if create_action %> def new<% if @object_owner_sym %>
79
- @<%= singular_name %> = <%= class_name %>.new(<% if eval("#{class_name}.reflect_on_association(:#{@object_owner_sym})").class == ActiveRecord::Reflection::BelongsToReflection %><%= @object_owner_sym %>: <%= @object_owner_eval %><% end %>)<% elsif @object_owner_optional && any_nested? %>
80
- @<%= singular_name %> = <%= class_name %>.new({}.merge(<%= @nested_set.last[:singular] %> ? {<%= @object_owner_sym %>: <%= @object_owner_eval %>} : {}))<% else %>
81
- @<%= singular_name %> = <%= class_name %>.new(<% if any_nested? %><%= @object_owner_sym %>: <%= @object_owner_eval %><% end %>)
82
- <% end %>
84
+ @<%= singular_name %> = <% if @pundit %>policy_scope(<% end %><%= class_name %><% if @pundit %>)<% end %>.new(<% if eval("#{class_name}.reflect_on_association(:#{@object_owner_sym})").class == ActiveRecord::Reflection::BelongsToReflection %><%= @object_owner_sym %>: <%= @object_owner_eval %><% end %>)<% elsif @object_owner_optional && any_nested? %>
85
+ @<%= singular_name %> = <% if @pundit %>policy_scope(<% end %><%= class_name %><% if @pundit %>)<% end %>.new({}.merge(<%= @nested_set.last[:singular] %> ? {<%= @object_owner_sym %>: <%= @object_owner_eval %>} : {}))<% else %>
86
+ @<%= singular_name %> = <% if @pundit %>policy_scope(<% end %><%= class_name %><% if @pundit %>)<% end %>.new(<% if any_nested? %><%= @object_owner_sym %>: <%= @object_owner_eval %><% end %>)<% end %>
87
+ <% if @pundit %>authorize @<%= singular_name %><% end %><% if @pundit %>
88
+ rescue Pundit::NotAuthorizedError
89
+ flash[:alert] = "You are not authorized to perform this action."
90
+ render :index<% end %>
83
91
  end
84
92
 
85
93
  def create
@@ -106,12 +114,18 @@ class <%= controller_class_name %> < <%= controller_descends_from %>
106
114
  else
107
115
  flash[:alert] = "Oops, your <%= singular_name %> could not be created. #{@hawk_alarm}"
108
116
  render :create, status: :unprocessable_entity
109
- end
117
+ end<% if @pundit %>
118
+ rescue Pundit::NotAuthorizedError
119
+ flash[:alert] = "Creating <%= singular %> not authorized. #{@<%= singular %>.errors.collect{|k| "#{k.attribute} #{k.message}"}.join(" ")} #{flash[:notice]} "
120
+ render :index <% end %>
110
121
  end
111
122
 
112
123
  <% end %>
113
124
  <% unless @no_edit %> def edit
114
- render :edit
125
+ render :edit<% if @pundit %>
126
+ rescue Pundit::NotAuthorizedError
127
+ flash[:alert] = "Editing #{@<%= singular %>.<%= display_class %>} not authorized."
128
+ render :index <% end %>
115
129
  end
116
130
 
117
131
  <% end %><% if @build_update_action %> def update
@@ -120,7 +134,7 @@ class <%= controller_class_name %> < <%= controller_descends_from %>
120
134
  }.join("\n") %><% end %> <% merge_lookups = @alt_lookups.filter{|key,d| ! @update_show_only.include?(key.to_sym) }.collect{|key, data| "#{key.gsub("_id", "")}: #{key.gsub("_id", "")}" }.join(",") %>
121
135
  <% @magic_buttons.each { |button| %>@<%= singular_name %>.<%= button %>! if <%= singular_name %>_params[:__<%= button %>]
122
136
  <% } %>
123
- modified_params = modify_date_inputs_on_params(<%= singular_name %>_params.dup<%= controller_update_params_tap_away_alt_lookups %>, <%= current_user_object %>, <%= datetime_fields_list %>) <% if @object_owner_sym && eval("#{class_name}.reflect_on_association(:#{@object_owner_sym})").class == ActiveRecord::Reflection::BelongsToReflection %>
137
+ modified_params = modify_date_inputs_on_params(<% if @update_show_only %>update_<% end %><%= singular_name %>_params.dup<%= controller_update_params_tap_away_alt_lookups %>, <%= current_user_object %>, <%= datetime_fields_list %>) <% if @object_owner_sym && eval("#{class_name}.reflect_on_association(:#{@object_owner_sym})").class == ActiveRecord::Reflection::BelongsToReflection %>
124
138
  modified_params = modified_params.merge(<%= @object_owner_sym %>: <%= @object_owner_eval %>) <% elsif @object_owner_optional && any_nested? %>
125
139
  modified_params = modified_params.merge(<%= @object_owner_name %> ? {<%= @object_owner_sym %>: <%= @object_owner_eval %>} : {}) <% elsif !@object_owner_eval.empty? %>
126
140
  modified_params = modified_params.merge(<%= @object_owner_eval %>) <% end %><% if !merge_lookups.empty? %>
@@ -136,7 +150,13 @@ class <%= controller_class_name %> < <%= controller_descends_from %>
136
150
  <%= @update_alt_lookups.collect{|key, data|
137
151
  " @#{ singular_name }.#{key.gsub("_id", "")} = #{key.gsub("_id", "")}"
138
152
  }.join("/n") %><% end %><%= controller_attachment_orig_filename_pickup_syntax %>
153
+ <% if @pundit %>
154
+ if @<%= singular_name %>.attributes = modified_params
155
+ authorize @<%= singular_name %>
156
+ @<%= singular_name %>.save
157
+ <% else %>
139
158
  if @<%= singular_name %>.update(modified_params)
159
+ <% end %>
140
160
  <% if @display_list_after_update %> load_all_<%= plural %><% end %>
141
161
  flash[:notice] = "#{flash[:notice]} Saved #{@<%= singular %>.<%= display_class %>}"
142
162
  flash[:alert] = @hawk_alarm if @hawk_alarm
@@ -144,22 +164,33 @@ class <%= controller_class_name %> < <%= controller_descends_from %>
144
164
  else
145
165
  flash[:alert] = "#{flash[:notice]} <%= singular_name.titlecase %> could not be saved. #{@hawk_alarm}"
146
166
  render :update, status: :unprocessable_entity
147
- end
167
+ end<% if @pundit %>
168
+ rescue Pundit::NotAuthorizedError
169
+ flash[:alert] = "Updating #{@<%= singular_name %>.<%= display_class %>} not authorized. "
170
+ render :update<% end %>
148
171
  end
149
172
 
150
173
  <% end %><% if destroy_action %> def destroy
174
+ <% if @pundit %>authorize @<%= singular_name %><% end %>
151
175
  begin
152
176
  @<%=singular_name%>.destroy
153
177
  flash[:notice] = '<%= singular_name.titlecase %> successfully deleted'
154
178
  rescue StandardError => e
155
179
  flash[:alert] = '<%= singular_name.titlecase %> could not be deleted'
156
180
  end <%= post_action_parental_updates %>
157
- load_all_<%= plural %>
181
+ load_all_<%= plural %><% if @pundit %>
182
+ rescue Pundit::NotAuthorizedError
183
+ flash[:alert] = "Deleting #{@<%= singular_name %>.<%= display_class %>} not authorized. "
184
+ render :update<% end %>
158
185
  end<% end %>
159
186
 
160
187
  def <%=singular_name%>_params
161
- params.require(:<%= testing_name %>).permit(<%= (fields_filtered_for_email_lookups - @show_only) + @magic_buttons.collect{|x| "__#{x}".to_sym }%>)
162
- end
188
+ params.require(:<%= testing_name %>).permit(<%= (fields_filtered_for_email_lookups - @show_only ) + @magic_buttons.collect{|x| "__#{x}".to_sym }%>)
189
+ end<% if @update_show_only %>
190
+
191
+ def update_<%=singular_name%>_params
192
+ params.require(:<%= testing_name %>).permit(<%= (fields_filtered_for_email_lookups - @update_show_only) + @magic_buttons.collect{|x| "__#{x}".to_sym }%>)
193
+ end<% end %>
163
194
 
164
195
  def namespace
165
196
  <% if @namespace %>'<%= @namespace %>/'<% else %><% end %>
@@ -1,5 +1,5 @@
1
1
  module HotGlue
2
2
  class Version
3
- CURRENT = '0.5.19.2'
3
+ CURRENT = '0.5.20'
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hot-glue
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.19.2
4
+ version: 0.5.20
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jason Fleetwood-Boldt
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-09-04 00:00:00.000000000 Z
11
+ date: 2023-09-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails