Skip to content

Commit dbd28b7

Browse files
committed
feat: fix enforce_ex() API returning empty explanations for allow rules in deny models (#412)
1 parent 785e306 commit dbd28b7

File tree

2 files changed

+13
-1
lines changed

2 files changed

+13
-1
lines changed

casbin/core_enforcer.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -481,8 +481,11 @@ def enforce_ex(self, *rvals):
481481
else:
482482
policy_effects.add(Effector.ALLOW)
483483

484+
# Update explain_index for any matching policy before checking early break condition
485+
# to ensure explanations are captured for allow rules in deny models
486+
explain_index = i
487+
484488
if self.eft.intermediate_effect(policy_effects) != Effector.INDETERMINATE:
485-
explain_index = i
486489
break
487490

488491
else:

tests/test_enforcer.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,15 @@ def test_enforce_rbac_with_deny(self):
285285
self.assertTrue(e.enforce("alice", "data2", "read"))
286286
self.assertFalse(e.enforce("alice", "data2", "write"))
287287

288+
def test_enforce_ex_rbac_with_deny(self):
289+
e = self.get_enforcer(
290+
get_examples("rbac_with_deny_model.conf"),
291+
get_examples("rbac_with_deny_policy.csv"),
292+
)
293+
# Test that enforce_ex returns explanations for both allow and deny cases
294+
self.assertTupleEqual(e.enforce_ex("alice", "data2", "read"), (True, ["data2_admin", "data2", "read", "allow"]))
295+
self.assertTupleEqual(e.enforce_ex("alice", "data2", "write"), (False, ["alice", "data2", "write", "deny"]))
296+
288297
def test_enforce_rbac_with_domains(self):
289298
e = self.get_enforcer(
290299
get_examples("rbac_with_domains_model.conf"),

0 commit comments

Comments
 (0)