@@ -186,23 +186,145 @@ def permit!(privilege, options = {})
186186 attr_validator = AttributeValidator . new ( self , user , options [ :object ] , privilege , options [ :context ] )
187187 rules = matching_auth_rules ( roles , privileges , options [ :context ] )
188188
189- # Test each rule in turn to see whether any one of them is satisfied.
189+ # _____ _ ____ ____
190+ # / ___| (_) | _ \| _ \
191+ # \ `--. _ __ _ ___ ___| | | | |_) |
192+ # `--. \ '_ \| |/ __/ _ \ | | | _ <
193+ # /\__/ / |_) | | (_| __/ |_| | |_) |
194+ # \____/| .__/|_|\___\___|____/|____/
195+ # | |
196+ # |_|
197+ use_spicedb_auth = false
198+
190199 rules . each do |rule |
191- return true if rule . validate? ( attr_validator , options [ :skip_attribute_test ] )
200+ unless rule . role . to_s . start_with? ( "leases__" , "lease_renewals__" )
201+ # Existing behavior for non-lease-related rules
202+ return true if rule . validate? ( attr_validator , options [ :skip_attribute_test ] )
203+ next
204+ end
205+
206+ use_spicedb_auth = true
207+
208+ auth_service_class = Rails . application . config . try ( :spicedb_authorization_service )
209+ @auth_service = auth_service_class . new
210+
211+ vhost_id = Core ::Company . guid if defined? ( Core ::Company )
212+ raise StandardError , "Vhost ID not found" if vhost_id . nil?
213+
214+ puts "\n ==== Processing new rule ===="
215+ puts "Rule: #{ rule . inspect } "
216+ puts "Role: #{ rule . role } "
217+
218+ permission_to_check = rule . role . to_s . gsub ( "__" , "_" ) + "_permission"
219+ puts "Permission to check: #{ permission_to_check } "
220+
221+ if rule . attributes . empty?
222+ puts "Rule has no attributes, checking spicedb directly"
223+
224+ authorized = @auth_service . check_permission (
225+ resource : { type : "vhost" , id : vhost_id } ,
226+ permission : permission_to_check
227+ )
228+ puts "Authorized? #{ authorized } "
229+
230+ return true if authorized
231+ else
232+ puts "Rule has #{ rule . attributes . count } attributes, examining them:"
233+
234+ rule . attributes . each_with_index do |attribute , index |
235+ puts "\n -- Attribute ##{ index + 1 } : #{ attribute . inspect } "
236+
237+ if attribute . instance_variable_defined? ( '@conditions_hash' )
238+ conditions = attribute . instance_variable_get ( '@conditions_hash' )
239+ puts " Conditions hash: #{ conditions . inspect } "
240+ else
241+ puts " !! No conditions_hash instance variable found, skipping"
242+ next
243+ end
244+
245+ next unless conditions . is_a? ( Hash )
246+
247+ puts " Checking conditions against current values:"
248+ condition_matched = false
249+
250+ if conditions . key? ( :granular_permissions )
251+ rule_requires = conditions [ :granular_permissions ] [ 1 ]
252+ should_consider = options [ :object ] &.respond_to? ( :granular_permissions ) && options [ :object ] &.granular_permissions != nil
253+ actual_value = should_consider ? options [ :object ] &.granular_permissions : nil
254+
255+ puts " Granular permissions - Rule requires: #{ rule_requires } , Actual: #{ actual_value } "
256+ if rule_requires == actual_value
257+ condition_matched = true
258+ puts " ✓ Granular permissions condition matched!"
259+ else
260+ puts " ✗ Granular permissions condition did not match"
261+ end
262+ else
263+ puts " (No granular_permissions condition to check)"
264+ end
265+
266+ if conditions . key? ( :is_renewal )
267+ rule_requires = conditions [ :is_renewal ] [ 1 ]
268+ should_consider = options [ :object ] &.respond_to? ( :is_renewal ) && options [ :object ] &.is_renewal != nil
269+ # Check if the lease document is a renewal
270+ response = @auth_service . lookup_subjects (
271+ resource_type : "lease_document" ,
272+ resource_id : options [ :object ] &.lease_uuid ,
273+ permission : "renewal" ,
274+ subject_type : "lease_document" ,
275+ )
276+ actual_value = response [ :subject_ids ] . any?
277+
278+ puts " Is renewal - Rule requires: #{ rule_requires } , Actual: #{ actual_value } "
279+ if rule_requires == actual_value
280+ condition_matched = true
281+ puts " ✓ Is_renewal condition matched!"
282+ else
283+ puts " ✗ Is_renewal condition did not match"
284+ end
285+ else
286+ puts " (No is_renewal condition to check)"
287+ end
288+
289+ if condition_matched
290+ puts " At least one matching condition found, checking spicedb"
291+
292+ authorized = @auth_service . check_permission (
293+ resource : { type : "vhost" , id : vhost_id } ,
294+ permission : permission_to_check
295+ )
296+ puts " Authorized? #{ authorized } "
297+
298+ return true if authorized
299+ else
300+ puts " No matching conditions, skipping spicedb check for this attribute"
301+ end
302+ end
303+ end
192304 end
193305
306+ source_prefix = use_spicedb_auth ? "SpiceDB authorization failed. " : ""
307+
194308 if options [ :bang ]
195309 if rules . empty?
196310 raise NotAuthorized , "No matching rules found for #{ privilege } for User with id #{ user . try ( :id ) } " +
197311 "(roles #{ roles . inspect } , privileges #{ privileges . inspect } , " +
198312 "context #{ options [ :context ] . inspect } )."
199313 else
200- raise AttributeAuthorizationError , "#{ privilege } not allowed for User with id #{ user . try ( :id ) } on #{ ( options [ :object ] || options [ :context ] ) . inspect } ."
314+ raise AttributeAuthorizationError , "#{ source_prefix } #{ privilege } not allowed for User with id #{ user . try ( :id ) } " +
315+ "on #{ ( options [ :object ] || options [ :context ] ) . inspect } ."
201316 end
202317 else
203318 false
204319 end
205- end
320+ end
321+ # _____ _ _ _____
322+ # | ___| | \ | | | _ |
323+ # | |__ | \| | | | | |
324+ # | __| | . ` | | | | |
325+ # | |___ | |\ | \ \_/ /
326+ # \____/ \_| \_/ \___/
327+
206328
207329 # Calls permit! but doesn't raise authorization errors. If no exception is
208330 # raised, permit? returns true and yields to the optional block.
0 commit comments