avo 2.17.1.pre.3 → 2.17.1.pre.4.issue.1342

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of avo might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e373d0b7b292a05ed70462e7a20e78a2f7c559a94f7aca774cd68165e18d2c70
4
- data.tar.gz: 545d0fb57feac7577871bceeb107eec82a22d3f8ea0fe50370e93083b4fa4667
3
+ metadata.gz: 0cb67ed800f6808830e072dfeaf5acb53a9c8960d7ca1b1fc01a5ac27ab478b4
4
+ data.tar.gz: 861965614539773f8c6242e211bb7e3449b8393ad2306cf3aa1bcbb030a36212
5
5
  SHA512:
6
- metadata.gz: 7854ba8a53232541ed1ae751099ccf40a339bc25ab85f6cd2e3fa28b7d958f7e480e4d53acea0110acd7167e710e3fdfef91104d567a796b832360c2ce699a46
7
- data.tar.gz: d00ec57468d98d63e4e594d93e1eb3bce3bc4734eb65951805124511d2e45eabab646b4b9f16e6d0f458c76732e7cf64d00bfa828154ea92173483bcad174afe
6
+ metadata.gz: 5a2d565a8a5839e25f23cd4bdac2308c07a5b89dacadd090b8ddcaf5180b58fa4d7f844ebafbd02c167d60d9f0f5193c6b7cd2790c61f538fc8aadfa50e6f32b
7
+ data.tar.gz: e1a6e356003227ff73440bd51a8aecdce3f4522be2c4cb0829fbd35a88d9916ffcb860638428f19296d66e054396f8683f759852282c22559b6f76fd415a8d81
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- avo (2.17.1.pre.3)
4
+ avo (2.17.1.pre.4.issue.1342)
5
5
  active_link_to
6
6
  addressable
7
7
  breadcrumbs_on_rails
@@ -8,6 +8,7 @@
8
8
  date_field_disable_mobile_value: @field.disable_mobile,
9
9
  date_field_time24_hr_value: @field.time_24hr,
10
10
  date_field_timezone_value: @field.timezone,
11
+ date_field_relative_value: @field.relative,
11
12
  date_field_field_type_value: "dateTime",
12
13
  date_field_picker_options_value: @field.picker_options,
13
14
  } do %>
@@ -5,6 +5,7 @@
5
5
  date_field_enable_time_value: true,
6
6
  date_field_format_value: @field.format,
7
7
  date_field_timezone_value: @field.timezone,
8
+ date_field_relative_value: @field.relative,
8
9
  date_field_picker_format_value: @field.picker_format,
9
10
  date_field_field_type_value: "dateTime",
10
11
  } do %>
@@ -5,6 +5,7 @@
5
5
  date_field_enable_time_value: true,
6
6
  date_field_format_value: @field.format,
7
7
  date_field_timezone_value: @field.timezone,
8
+ date_field_relative_value: @field.relative,
8
9
  date_field_picker_format_value: @field.picker_format,
9
10
  date_field_field_type_value: "dateTime",
10
11
  } do %>
@@ -25,7 +25,7 @@
25
25
  <% end %>
26
26
  <% if body? %>
27
27
  <div class="flex flex-col sm:flex-row space-y-4 sm:space-y-0 sm:gap-4 w-full">
28
- <div class="relative flex-1 overflow-auto <%= white_panel_classes %> <%= @body_classes %> <% if sidebar? %> w-2/3 <% end %>">
28
+ <div class="relative flex-1 <%= white_panel_classes %> <%= @body_classes %> <% if sidebar? %> w-2/3 overflow-auto <% else %> w-full <% end %>">
29
29
  <%= body %>
30
30
  </div>
31
31
  <% if sidebar? %>
@@ -46,10 +46,8 @@
46
46
  </div>
47
47
  <% if view_type.to_sym == :table %>
48
48
  <% if @resources.present? %>
49
- <div class="w-full overflow-auto flex flex-col mt-0 mac-styled-scrollbar">
50
- <div class="relative flex-1 flex">
51
- <%= render(Avo::Index::ResourceTableComponent.new(resources: @resources, resource: @resource, reflection: @reflection, parent_model: @parent_model, parent_resource: @parent_resource, pagy: @pagy, query: @query)) %>
52
- </div>
49
+ <div class="w-full relative flex-1 flex mac-styled-scrollbar overflow-auto mt-0">
50
+ <%= render(Avo::Index::ResourceTableComponent.new(resources: @resources, resource: @resource, reflection: @reflection, parent_model: @parent_model, parent_resource: @parent_resource, pagy: @pagy, query: @query)) %>
53
51
  </div>
54
52
  <% else %>
55
53
  <%= helpers.empty_state resource_name: @resource.name.downcase.pluralize, related_name: params[:related_name], view_type: view_type, add_background: true %>
@@ -1,11 +1,5 @@
1
1
  module Avo
2
2
  class ApplicationController < ::ActionController::Base
3
- if defined?(Pundit::Authorization)
4
- include Pundit::Authorization
5
- else
6
- include Pundit
7
- end
8
-
9
3
  include Pagy::Backend
10
4
  include Avo::ApplicationHelper
11
5
  include Avo::UrlHelpers
@@ -24,7 +18,7 @@ module Avo
24
18
  before_action :set_view
25
19
  before_action :set_sidebar_open
26
20
 
27
- rescue_from Pundit::NotAuthorizedError, with: :render_unauthorized
21
+ rescue_from Avo::NotAuthorizedError, with: :render_unauthorized
28
22
  rescue_from ActiveRecord::RecordInvalid, with: :exception_logger
29
23
 
30
24
  helper_method :_current_user, :resources_path, :resource_path, :new_resource_path, :edit_resource_path, :resource_attach_path, :resource_detach_path, :related_resources_path, :turbo_frame_request?, :resource_view_path
@@ -257,18 +251,16 @@ module Avo
257
251
  instance_eval(&Avo.configuration.authenticate)
258
252
  end
259
253
 
260
- def render_unauthorized(exception)
261
- if !exception.is_a? Pundit::NotDefinedError
262
- flash.now[:notice] = t "avo.not_authorized"
263
-
264
- redirect_url = if request.referrer.blank? || (request.referrer == request.url)
265
- root_url
266
- else
267
- request.referrer
268
- end
254
+ def render_unauthorized(_exception)
255
+ flash.now[:notice] = t "avo.not_authorized"
269
256
 
270
- redirect_to(redirect_url)
257
+ redirect_url = if request.referrer.blank? || (request.referrer == request.url)
258
+ root_url
259
+ else
260
+ request.referrer
271
261
  end
262
+
263
+ redirect_to(redirect_url)
272
264
  end
273
265
 
274
266
  def set_authorization
@@ -157,7 +157,7 @@ module Avo
157
157
  private
158
158
 
159
159
  def set_related_authorization
160
- @authorization = if related_resource
160
+ @related_authorization = if related_resource
161
161
  related_resource.authorization(user: _current_user)
162
162
  else
163
163
  Services::AuthorizationService.new _current_user
@@ -60,6 +60,18 @@ export default class extends Controller {
60
60
  return this.viewValue === 'show'
61
61
  }
62
62
 
63
+ get fieldIsDate() {
64
+ return this.fieldTypeValue === 'date'
65
+ }
66
+
67
+ get fieldIsDateTime() {
68
+ return this.fieldTypeValue === 'dateTime'
69
+ }
70
+
71
+ get fieldIsTime() {
72
+ return this.fieldTypeValue === 'time'
73
+ }
74
+
63
75
  // Parse the time as if it were UTC
64
76
  get parsedValue() {
65
77
  return DateTime.fromISO(this.initialValue, { zone: 'UTC' })
@@ -10,6 +10,8 @@ module Avo
10
10
  class_attribute :tabs_tabs_holder
11
11
  class_attribute :raw_tabs
12
12
  class_attribute :tools_holder
13
+
14
+ class_attribute :backup_items_holder
13
15
  end
14
16
 
15
17
  class_methods do
@@ -103,6 +105,25 @@ module Avo
103
105
  end
104
106
  end
105
107
 
108
+ def with_temporary_items(&block)
109
+ # back-up the previous items
110
+ self.backup_items_holder = items_holder
111
+
112
+ self.items_holder = Avo::ItemsHolder.new
113
+
114
+ instance_eval(&block)
115
+ end
116
+
117
+ def restore_items_from_backup
118
+ self.items_holder = backup_items_holder if backup_items_holder.present?
119
+ end
120
+
121
+ def with_new_items(&block)
122
+ self.items_holder = Avo::ItemsHolder.new
123
+
124
+ instance_eval(&block)
125
+ end
126
+
106
127
  private
107
128
 
108
129
  def extract_fields_from_items(thing)
@@ -311,6 +332,10 @@ module Avo
311
332
  [main_panel, *panelfull_items]
312
333
  end
313
334
 
335
+ def with_new_items(&block)
336
+ self.class.with_new_items(&block)
337
+ end
338
+
314
339
  private
315
340
 
316
341
  def check_license
@@ -37,6 +37,7 @@ module Avo
37
37
  attr_accessor :model_resource_mapping
38
38
  attr_accessor :tabs_style
39
39
  attr_accessor :resource_default_view
40
+ attr_accessor :authorization_client
40
41
  attr_writer :branding
41
42
 
42
43
  def initialize
@@ -85,6 +86,7 @@ module Avo
85
86
  @model_resource_mapping = {}
86
87
  @tabs_style = :tabs
87
88
  @resource_default_view = :show
89
+ @authorization_client = nil
88
90
  end
89
91
 
90
92
  def current_user_method(&block)
@@ -5,6 +5,7 @@ module Avo
5
5
  attr_reader :picker_format
6
6
  attr_reader :time_24hr
7
7
  attr_reader :timezone
8
+ attr_reader :relative
8
9
 
9
10
  def initialize(id, **args, &block)
10
11
  super(id, **args, &block)
@@ -13,6 +14,7 @@ module Avo
13
14
  add_string_prop args, :picker_format, "Y-m-d H:i:S"
14
15
  add_string_prop args, :format, "yyyy-LL-dd TT"
15
16
  add_string_prop args, :timezone
17
+ add_boolean_prop args, :relative, true
16
18
  end
17
19
 
18
20
  def formatted_value
@@ -1,20 +1,14 @@
1
1
  module Avo
2
2
  module Fields
3
- class TimeField < DateField
3
+ class TimeField < DateTimeField
4
4
  attr_reader :format
5
5
  attr_reader :picker_format
6
- attr_reader :time_24hr
7
- attr_reader :timezone
8
- attr_reader :relative
9
6
 
10
7
  def initialize(id, **args, &block)
11
8
  super(id, **args, &block)
12
9
 
13
- add_boolean_prop args, :time_24hr
14
10
  add_string_prop args, :picker_format, "H:i:S"
15
11
  add_string_prop args, :format, "TT"
16
- add_string_prop args, :timezone
17
- add_boolean_prop args, :relative, true
18
12
  end
19
13
 
20
14
  def formatted_value
@@ -0,0 +1,51 @@
1
+ module Avo
2
+ module Services
3
+ module AuthorizationClients
4
+ class PunditClient
5
+ def authorize(user, record, action, policy_class: nil)
6
+ Pundit.authorize(user, record, action, policy_class: policy_class)
7
+ rescue Pundit::NotDefinedError
8
+ raise NoPolicyError
9
+ rescue Pundit::NotAuthorizedError
10
+ raise NotAuthorizedError
11
+ end
12
+
13
+ def policy(user, record)
14
+ Pundit.policy(user, record)
15
+ end
16
+
17
+ def policy!(user, record)
18
+ Pundit.policy!(user, record)
19
+ rescue Pundit::NotDefinedError
20
+ raise NoPolicyError
21
+ end
22
+
23
+ def apply_policy(user, model, policy_class: nil)
24
+ # Try and figure out the scope from a given policy or auto-detected one
25
+ scope_from_policy_class = scope_for_policy_class(policy_class)
26
+
27
+ # If we discover one use it.
28
+ # Else fallback to pundit.
29
+ if scope_from_policy_class.present?
30
+ scope_from_policy_class.new(user, model).resolve
31
+ else
32
+ Pundit.policy_scope!(user, model)
33
+ end
34
+ rescue Pundit::NotDefinedError => error
35
+ raise NoPolicyError
36
+ end
37
+
38
+ private
39
+
40
+ # Fetches the scope for a given policy
41
+ def scope_for_policy_class(policy_class = nil)
42
+ return if policy_class.blank?
43
+
44
+ if policy_class.present? && defined?(policy_class::Scope)
45
+ policy_class::Scope
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -3,29 +3,30 @@ module Avo
3
3
  class AuthorizationService
4
4
  attr_accessor :user
5
5
  attr_accessor :record
6
+ attr_accessor :policy_class
6
7
 
7
8
  class << self
9
+ def client
10
+ (configuration_client || default_client).new
11
+ end
12
+
8
13
  def authorize(user, record, action, policy_class: nil, **args)
9
14
  return true if skip_authorization
10
15
  return true if user.nil?
11
16
 
12
- policy_class ||= Pundit.policy(user, record)&.class
13
- begin
14
- if policy_class&.new(user, record)
15
- Pundit.authorize user, record, action, policy_class: policy_class
16
- end
17
-
18
- true
19
- rescue Pundit::NotDefinedError => e
20
- return false unless Avo.configuration.raise_error_on_missing_policy
21
-
22
- raise e
23
- rescue => error
24
- if args[:raise_exception] == false
25
- false
26
- else
27
- raise error
28
- end
17
+ client.authorize user, record, action, policy_class: policy_class
18
+
19
+ true
20
+ rescue NoPolicyError => error
21
+ # By default, Avo allows anything if you don't have a policy present.
22
+ return true unless Avo.configuration.raise_error_on_missing_policy
23
+
24
+ raise error
25
+ rescue => error
26
+ if args[:raise_exception] == false
27
+ false
28
+ else
29
+ raise error
29
30
  end
30
31
  end
31
32
 
@@ -35,7 +36,7 @@ module Avo
35
36
  # If no action passed we should raise error if the user wants that.
36
37
  # If not, just allow it.
37
38
  if action.nil?
38
- raise Pundit::NotDefinedError.new "Policy method is missing" if Avo.configuration.raise_error_on_missing_policy
39
+ raise NoPolicyError.new "Policy method is missing" if Avo.configuration.raise_error_on_missing_policy
39
40
 
40
41
  return true
41
42
  end
@@ -48,44 +49,27 @@ module Avo
48
49
  def apply_policy(user, model, policy_class: nil)
49
50
  return model if skip_authorization || user.nil?
50
51
 
51
- begin
52
- # Try and figure out the scope from a given policy or auto-detected one
53
- scope_from_policy_class = scope_for_policy_class(policy_class)
54
-
55
- # If we discover one use it.
56
- # Else fallback to pundit.
57
- if scope_from_policy_class.present?
58
- scope_from_policy_class.new(user, model).resolve
59
- else
60
- Pundit.policy_scope!(user, model)
61
- end
62
- rescue Pundit::NotDefinedError => e
63
- return model unless Avo.configuration.raise_error_on_missing_policy
64
-
65
- raise e
66
- end
52
+ client.apply_policy(user, model, policy_class: policy_class)
53
+ rescue NoPolicyError => error
54
+ return model unless Avo.configuration.raise_error_on_missing_policy
55
+
56
+ raise error
67
57
  end
68
58
 
69
59
  def skip_authorization
70
60
  Avo::App.license.lacks_with_trial :authorization
71
61
  end
72
62
 
73
- def authorized_methods(user, record)
74
- [:new, :edit, :update, :show, :destroy].map do |method|
75
- [method, authorize(user, record, Avo.configuration.authorization_methods[method])]
76
- end.to_h
77
- end
78
-
79
63
  def defined_methods(user, record, policy_class: nil, **args)
80
- return Pundit.policy!(user, record).methods if policy_class.nil?
64
+ return client.policy!(user, record).methods if policy_class.nil?
81
65
 
82
66
  # I'm aware this will not raise a Pundit error.
83
67
  # Should the policy not exist, it will however raise an uninitialized constant error, which is probably what we want when specifying a custom policy
84
68
  policy_class.new(user, record).methods
85
- rescue Pundit::NotDefinedError => e
69
+ rescue NoPolicyError => error
86
70
  return [] unless Avo.configuration.raise_error_on_missing_policy
87
71
 
88
- raise e
72
+ raise error
89
73
  rescue => error
90
74
  if args[:raise_exception] == false
91
75
  []
@@ -94,24 +78,27 @@ module Avo
94
78
  end
95
79
  end
96
80
 
97
- # Fetches the scope for a given policy
98
- def scope_for_policy_class(policy_class = nil)
99
- return if policy_class.blank?
81
+ def configuration_client
82
+ client = Avo.configuration.authorization_client
100
83
 
101
- if policy_class.present? && defined?(policy_class::Scope)
102
- policy_class::Scope
84
+ return if client.blank?
85
+
86
+ if client.is_a?(String)
87
+ client.safe_constantize
88
+ else
89
+ client
103
90
  end
104
91
  end
92
+
93
+ def default_client
94
+ Avo::Services::AuthorizationClients::PunditClient
95
+ end
105
96
  end
106
97
 
107
98
  def initialize(user = nil, record = nil, policy_class: nil)
108
99
  @user = user
109
100
  @record = record
110
- @policy_class = policy_class || Pundit.policy(user, record)&.class
111
- end
112
-
113
- def authorize(action, **args)
114
- self.class.authorize(user, record, action, policy_class: @policy_class, **args)
101
+ @policy_class = policy_class || self.class.client.policy(user, record)&.class
115
102
  end
116
103
 
117
104
  def set_record(record)
@@ -120,22 +107,16 @@ module Avo
120
107
  self
121
108
  end
122
109
 
123
- def set_user(user)
124
- @user = user
125
-
126
- self
127
- end
128
-
129
110
  def authorize_action(action, **args)
130
- self.class.authorize_action(user, record, action, policy_class: @policy_class, **args)
111
+ self.class.authorize_action(user, record, action, policy_class: policy_class, **args)
131
112
  end
132
113
 
133
114
  def apply_policy(model)
134
- self.class.apply_policy(user, model, policy_class: @policy_class)
115
+ self.class.apply_policy(user, model, policy_class: policy_class)
135
116
  end
136
117
 
137
118
  def defined_methods(model, **args)
138
- self.class.defined_methods(user, model, policy_class: @policy_class, **args)
119
+ self.class.defined_methods(user, model, policy_class: policy_class, **args)
139
120
  end
140
121
 
141
122
  def has_method?(method, **args)
data/lib/avo/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Avo
2
- VERSION = "2.17.1.pre.3" unless const_defined?(:VERSION)
2
+ VERSION = "2.17.1.pre.4.issue.1342" unless const_defined?(:VERSION)
3
3
  end
data/lib/avo.rb CHANGED
@@ -44,6 +44,10 @@ module Avo
44
44
  class LicenseVerificationTemperedError < StandardError; end
45
45
 
46
46
  class LicenseInvalidError < StandardError; end
47
+
48
+ class NotAuthorizedError < StandardError; end
49
+
50
+ class NoPolicyError < StandardError; end
47
51
  end
48
52
 
49
53
  loader.eager_load
@@ -30,6 +30,7 @@ Avo.configure do |config|
30
30
  # destroy: 'destroy?',
31
31
  # }
32
32
  # config.raise_error_on_missing_policy = false
33
+ # config.authorization_client = false
33
34
 
34
35
  ## == Localization ==
35
36
  # config.locale = 'en-US'