ae_declarative_authorization 1.7.0 → 2.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 56ec4f643afa582330c80d6383b776bc99d459eec3ecc89369c5fcdbc11287a3
4
- data.tar.gz: 76a94f61774f7b1e2c92b92f84bce2e924ef26f84135eb4e53109f29395322d0
3
+ metadata.gz: 3ef6198e116e9ca661b4799db0fb643b3ac2edfed4afecf87b44fd2f2dade3d8
4
+ data.tar.gz: 6231b714160be944286cb181b6c4f68dd49b8048688b38943bf078f84d666f02
5
5
  SHA512:
6
- metadata.gz: 21bb39616062054dd32243a8511be52c61dac5d30aada8fd451874251c98f3600b1c3e7f35092525798dee652eda100c5a8251482769c759310b009cf68d98e8
7
- data.tar.gz: 0b13eb2582830386ccc5544554415ea15c385ff6155523e889af55c7a5036c39964f6a0ba558b0b71203c535aa64dbd485b8510899ff74726634ca5ed564fc73
6
+ metadata.gz: e5e1396443afc071a0818ceb4ee65adbd65e518aa47d451d44d200a8f927cd29a8e47223f22581d6e746bae66f2a092ce6de371ebed7e504b1605bd0407c041f
7
+ data.tar.gz: ac878748b8c0d6bff2696e8e6a47e59be771da115b378a1a28d2aa0f9056dd41301434ef2325471a9255c2416b2e892ddef7ddbeafce491aad5c0bb77443ffb3
@@ -23,6 +23,8 @@ module DeclarativeAuthorization
23
23
  end
24
24
 
25
25
  def allowed(options)
26
+ return unless @test_class.run_assertion?(options)
27
+
26
28
  role, privileges, actions, params_name = extract_options(options)
27
29
 
28
30
  actions.each do |action|
@@ -38,6 +40,8 @@ module DeclarativeAuthorization
38
40
  end
39
41
 
40
42
  def denied(options)
43
+ return unless @test_class.run_assertion?(options)
44
+
41
45
  role, privileges, actions, params_name = extract_options(options)
42
46
 
43
47
  actions.each do |action|
@@ -89,6 +93,8 @@ module DeclarativeAuthorization
89
93
  end
90
94
 
91
95
  def allowed(options)
96
+ return unless @test_class.run_assertion?(options)
97
+
92
98
  if options[:when]
93
99
  privilege(options[:when]) { allowed(options) }
94
100
  else
@@ -97,6 +103,8 @@ module DeclarativeAuthorization
97
103
  end
98
104
 
99
105
  def denied(options)
106
+ return unless @test_class.run_assertion?(options)
107
+
100
108
  if options[:when]
101
109
  privilege(options[:when]) { denied(options) }
102
110
  else
@@ -119,21 +127,54 @@ module DeclarativeAuthorization
119
127
 
120
128
  def role(role, &block)
121
129
  raise "Role cannot be blank!" if role.blank?
122
- Blockenspiel.invoke(block, RoleTestGenerator.new(@test_class, role))
130
+
131
+ Blockenspiel.invoke(block, RoleTestGenerator.new(@test_class, role)) if @test_class.run_role_test?(role)
132
+ end
133
+ end
134
+
135
+ class AccessTestParser
136
+ include Blockenspiel::DSL
137
+
138
+ def initialize(test_class)
139
+ @test_class = test_class
140
+ end
141
+
142
+ def params(_name, &_block);end
143
+
144
+ def role(role, &block)
145
+ Blockenspiel.invoke(block, self) if @test_class.run_role_test?(role)
123
146
  end
124
147
 
148
+ def privilege(_privilege, &block)
149
+ Blockenspiel.invoke(block, self)
150
+ end
151
+
152
+ def allowed(options)
153
+ if options[:only]
154
+ @test_class.run_all_assertions = false
155
+ end
156
+ end
157
+
158
+ def denied(options)
159
+ if options[:only]
160
+ @test_class.run_all_assertions = false
161
+ end
162
+ end
125
163
  end
126
164
 
127
165
  module ClassMethods
128
- attr_reader :access_tests_defined
166
+ attr_reader :access_tests_defined, :only_run_roles
167
+ attr_accessor :run_all_assertions
129
168
 
130
169
  def skip_access_tests_for_actions(*actions)
131
170
  @skipped_access_test_actions ||= []
132
171
  @skipped_access_test_actions += actions.map(&:to_sym)
133
172
  end
134
173
 
135
- def access_tests(&block)
174
+ def access_tests(only_run_roles: nil, &block)
136
175
  @access_tests_defined = true
176
+ @run_all_assertions = true
177
+ @only_run_roles = only_run_roles
137
178
  file_output ||= [ Dir.tmpdir + '/test/profiles/access_checking', ENV['TEST_ENV_NUMBER'] ].compact.join('.')
138
179
  unless File.exist?(file_output)
139
180
  FileUtils.mkdir_p(File.dirname(file_output))
@@ -142,6 +183,7 @@ module DeclarativeAuthorization
142
183
  file.puts self.controller_class.name
143
184
  end
144
185
 
186
+ Blockenspiel.invoke(block, AccessTestParser.new(self))
145
187
  Blockenspiel.invoke(block, AccessTestGenerator.new(self))
146
188
  end
147
189
 
@@ -192,6 +234,14 @@ module DeclarativeAuthorization
192
234
  define_method("access_test_params_for_#{name}", &block)
193
235
  end
194
236
 
237
+ def run_role_test?(role)
238
+ @only_run_roles.nil? || @only_run_roles.include?(role)
239
+ end
240
+
241
+ def run_assertion?(assertion_options)
242
+ @run_all_assertions || assertion_options[:only]
243
+ end
244
+
195
245
  end
196
246
 
197
247
  protected
@@ -248,15 +298,27 @@ module DeclarativeAuthorization
248
298
  errors_to_reraise << Mocha::ExpectationError if defined?(Mocha::ExpectationError)
249
299
 
250
300
  begin
301
+ if options[:debug]
302
+ puts "Debug: Sending request - role: #{role}, action: #{action}, privilege: #{privilege}, params: #{params.inspect}, http_method: #{http_method}, xhr: #{xhr}"
303
+ end
251
304
  send *send_args, **send_kwargs
305
+ if options[:debug]
306
+ puts "Debug: Response status: #{response.status}" if response.status
307
+ puts "Debug: flash[:error]: #{flash[:error]}" if flash[:error]
308
+ puts "Debug: flash[:alert]: #{flash[:alert]}" if flash[:alert]
309
+ end
252
310
  return response_forbidden?
253
311
  rescue *errors_to_reraise => e
254
312
  raise e
255
313
  rescue => e
256
- if options[:print_error]
257
- puts "\n#{e.class.name} raised in action '#{action}':"
258
- puts e.message
259
- puts e.backtrace.join("\n")
314
+ # Exceptions are expected from controllers as complete requests are not always made in access tests
315
+ if options[:debug]
316
+ puts "Debug: Exception raised from controller, not considered as an error for access tests as response is not coming from the declarative authorization framework."
317
+ puts "Debug: Response status: #{response.status}" if response.status
318
+ puts "Debug: flash[:error]: #{flash[:error]}" if flash[:error]
319
+ puts "Debug: flash[:alert]: #{flash[:alert]}" if flash[:alert]
320
+ puts "Debug: Exception: #{e.class} - #{e.message}"
321
+ puts e.backtrace.join("\n") if e.backtrace
260
322
  end
261
323
  return false
262
324
  end
@@ -1,3 +1,3 @@
1
1
  module DeclarativeAuthorization
2
- VERSION = '1.7.0'.freeze
2
+ VERSION = '2.0.0'.freeze
3
3
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ae_declarative_authorization
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.7.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - AppFolio
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-06-18 00:00:00.000000000 Z
10
+ date: 2025-08-18 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: blockenspiel
@@ -77,7 +77,6 @@ files:
77
77
  - lib/generators/authorization/install/install_generator.rb
78
78
  - lib/generators/authorization/rules/rules_generator.rb
79
79
  - lib/generators/authorization/rules/templates/authorization_rules.rb
80
- - lib/rubocop/cop/decl_auth/before_actions_precede_access_filter.rb
81
80
  - lib/tasks/authorization_tasks.rake
82
81
  - rubocop-decl-auth.yml
83
82
  homepage: https://github.com/appfolio/ae_declarative_authorization
@@ -1,44 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RuboCop
4
- module Cop
5
- module DeclAuth
6
- # Enforces placing all `before_action` statements prior to the first `filter_access_to` statement.
7
- # This ensures that any data required by the access filters is available before the filter is applied.
8
- # See the documentation above the `filter_access_to` method in Authorization::Controller::DSL for more information
9
- #
10
- # @example
11
- # # bad
12
- # before_action: :do_something
13
- # filter_access_to :all
14
- # before_action :find_object
15
- #
16
- # # good
17
- # before_action: :do_something
18
- # before_action :find_object
19
- #
20
- # filter_access_to :all
21
- #
22
- class BeforeActionsPrecedeAccessFilter < RuboCop::Cop::Base
23
- def_node_search :before_actions, '(send nil? :before_action ...)'
24
- def_node_search :access_filters, '(send nil? :filter_access_to ...)'
25
-
26
- MSG = '`:filter_access_to` statements should be placed after all other `:before_action` statements.'
27
-
28
- def on_class(node)
29
- before_actions = before_actions(node)
30
- access_filters = access_filters(node)
31
-
32
- return if before_actions.count.zero? || access_filters.count.zero?
33
-
34
- last_before_action = before_actions.to_a.last
35
- first_access_filter = access_filters.to_a.first
36
-
37
- return if last_before_action.sibling_index < first_access_filter.sibling_index
38
-
39
- add_offense(access_filters.first, message: MSG)
40
- end
41
- end
42
- end
43
- end
44
- end