Skip to content

Commit ff3942a

Browse files
committed
Handle id_in_scope attribute checks
1 parent 4dac361 commit ff3942a

File tree

3 files changed

+56
-17
lines changed

3 files changed

+56
-17
lines changed

lib/.DS_Store

6 KB
Binary file not shown.
6 KB
Binary file not shown.

lib/declarative_authorization/authorization.rb

Lines changed: 56 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@ def permit!(privilege, options = {})
214214
puts "\n==== Processing new rule ===="
215215
puts "Rule: #{rule.inspect}"
216216
puts "Role: #{rule.role}"
217+
puts "Join Operator: #{rule.join_operator}" if rule.respond_to?(:join_operator)
217218

218219
permission_to_check = rule.role.to_s.gsub("__", "_") + "_permission"
219220
puts "Permission to check: #{permission_to_check}"
@@ -230,6 +231,9 @@ def permit!(privilege, options = {})
230231
return true if authorized
231232
else
232233
puts "Rule has #{rule.attributes.count} attributes, examining them:"
234+
235+
all_attributes_matched = true
236+
any_attribute_matched = false
233237

234238
rule.attributes.each_with_index do |attribute, index|
235239
puts "\n -- Attribute ##{index + 1}: #{attribute.inspect}"
@@ -245,24 +249,22 @@ def permit!(privilege, options = {})
245249
next unless conditions.is_a?(Hash)
246250

247251
puts " Checking conditions against current values:"
248-
condition_matched = false
252+
current_attribute_matched = true
249253

250254
if conditions.key?(:granular_permissions)
251255
rule_requires = conditions[:granular_permissions][1]
252256
actual_value = options[:object]&.granular_permissions if options[:object].respond_to?(:granular_permissions)
253257

254258
puts " Granular permissions - Rule requires: #{rule_requires}, Actual: #{actual_value}"
255259
if rule_requires == actual_value
256-
condition_matched = true
257260
puts " ✓ Granular permissions condition matched!"
258261
else
259262
puts " ✗ Granular permissions condition did not match"
263+
current_attribute_matched = false
260264
end
261-
else
262-
puts " (No granular_permissions condition to check)"
263265
end
264266

265-
if conditions.key?(:is_renewal)
267+
if conditions.key?(:is_renewal) && current_attribute_matched
266268
rule_requires = conditions[:is_renewal][1]
267269
# If options[:object] has is_renewal, we'll use that value instead of obtaining it from SpiceDB.
268270
# This allows for Blue Moon leases and others to be checked without having to make a SpiceDB call for the value of is_renewal.
@@ -276,36 +278,73 @@ def permit!(privilege, options = {})
276278
resource_type: "lease_document",
277279
resource_id: options[:object]&.lease_document_uuid.to_s,
278280
permission: "renewal",
279-
subject_type: "lease_document",
281+
subject_type: "lease_document"
280282
)
281-
actual_value = response[:subject_ids].any?
283+
actual_value = response.any?
282284
end
283285

284286
puts " Is renewal - Rule requires: #{rule_requires}, Actual: #{actual_value}"
285287
if rule_requires == actual_value
286-
condition_matched = true
287288
puts " ✓ Is_renewal condition matched!"
288289
else
289290
puts " ✗ Is_renewal condition did not match"
291+
current_attribute_matched = false
292+
end
293+
end
294+
295+
if conditions.key?(:id) && current_attribute_matched
296+
condition_type = conditions[:id][0]
297+
condition_proc = conditions[:id][1]
298+
299+
if condition_type == :id_in_scope && condition_proc.is_a?(Proc)
300+
puts " Checking Occupancy ID in scope condition"
301+
user_has_access_to_occupancy = attribute.validate?(attr_validator)
302+
puts " User has access to occupancy? #{user_has_access_to_occupancy}"
303+
if user_has_access_to_occupancy
304+
puts " ✓ This attribute matched conditions"
305+
else
306+
puts " ✗ This attribute did not match conditions"
307+
current_attribute_matched = false
308+
end
290309
end
310+
end
311+
312+
if current_attribute_matched
313+
any_attribute_matched = true
314+
puts " ✓ All conditions matched for this attribute"
291315
else
292-
puts " (No is_renewal condition to check)"
316+
all_attributes_matched = false
317+
puts " ✗ Not all conditions matched for this attribute"
293318
end
294-
295-
if condition_matched
296-
# For now, we will assume each rule's conditions are OR'd together. This is not the case
297-
# for all rules, but it's the most common case and a good starting point.
298-
puts " At least one matching condition found, checking spicedb"
299-
319+
end
320+
321+
puts " Finished checking attributes, checking if rule is authorized"
322+
323+
if rule.respond_to?(:join_operator) && rule.join_operator == :and
324+
puts " Rule uses AND operator, checking if all attributes matched: #{all_attributes_matched}"
325+
if all_attributes_matched
326+
puts " All attributes matched, checking SpiceDB permission"
327+
authorized = @auth_service.check_permission(
328+
resource: { type: "vhost", id: vhost_id },
329+
permission: permission_to_check
330+
)
331+
puts " Authorized? #{authorized}"
332+
return true if authorized
333+
else
334+
puts " Not all attributes matched, authorization denied for this rule"
335+
end
336+
else
337+
puts " Rule uses OR operator (default), checking if any attribute matched: #{any_attribute_matched}"
338+
if any_attribute_matched
339+
puts " At least one attribute matched, checking SpiceDB permission"
300340
authorized = @auth_service.check_permission(
301341
resource: { type: "vhost", id: vhost_id },
302342
permission: permission_to_check
303343
)
304344
puts " Authorized? #{authorized}"
305-
306345
return true if authorized
307346
else
308-
puts " No matching conditions, skipping spicedb check for this attribute"
347+
puts " No attributes matched, authorization denied for this rule"
309348
end
310349
end
311350
end

0 commit comments

Comments
 (0)