Skip to content

Commit e8ba47c

Browse files
authored
fix: respect AutoSave flag for grouping policy operations (#395)
1 parent 67dd0a4 commit e8ba47c

File tree

3 files changed

+129
-0
lines changed

3 files changed

+129
-0
lines changed
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
using System.Collections.Generic;
2+
using System.Threading.Tasks;
3+
using Casbin.Model;
4+
using Casbin.Persist;
5+
using Casbin.Persist.Adapter.File;
6+
7+
namespace Casbin.UnitTests.Mock;
8+
9+
public class MockSingleAdapter : FileAdapter, ISingleAdapter
10+
{
11+
public List<string> SavedPolicies { get; } = new();
12+
13+
public MockSingleAdapter(string filePath) : base(filePath)
14+
{
15+
}
16+
17+
public void AddPolicy(string section, string policyType, IPolicyValues rule)
18+
{
19+
SavedPolicies.Add($"AddPolicy: {section}.{policyType} {rule.ToText()}");
20+
}
21+
22+
public Task AddPolicyAsync(string section, string policyType, IPolicyValues rule)
23+
{
24+
SavedPolicies.Add($"AddPolicyAsync: {section}.{policyType} {rule.ToText()}");
25+
#if NET452
26+
return Task.FromResult(0);
27+
#else
28+
return Task.CompletedTask;
29+
#endif
30+
}
31+
32+
public void UpdatePolicy(string section, string policyType, IPolicyValues oldRule, IPolicyValues newRule)
33+
{
34+
SavedPolicies.Add($"UpdatePolicy: {section}.{policyType} {oldRule.ToText()} -> {newRule.ToText()}");
35+
}
36+
37+
public Task UpdatePolicyAsync(string section, string policyType, IPolicyValues oldRules, IPolicyValues newRules)
38+
{
39+
SavedPolicies.Add($"UpdatePolicyAsync: {section}.{policyType} {oldRules.ToText()} -> {newRules.ToText()}");
40+
#if NET452
41+
return Task.FromResult(0);
42+
#else
43+
return Task.CompletedTask;
44+
#endif
45+
}
46+
47+
public void RemovePolicy(string section, string policyType, IPolicyValues rule)
48+
{
49+
SavedPolicies.Add($"RemovePolicy: {section}.{policyType} {rule.ToText()}");
50+
}
51+
52+
public Task RemovePolicyAsync(string section, string policyType, IPolicyValues rule)
53+
{
54+
SavedPolicies.Add($"RemovePolicyAsync: {section}.{policyType} {rule.ToText()}");
55+
#if NET452
56+
return Task.FromResult(0);
57+
#else
58+
return Task.CompletedTask;
59+
#endif
60+
}
61+
62+
public void ClearSavedPolicies()
63+
{
64+
SavedPolicies.Clear();
65+
}
66+
}

Casbin.UnitTests/ModelTests/EnforcerTest.cs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -939,6 +939,59 @@ public async Task TestEnableAutoSaveAsync()
939939
Assert.True(await e.EnforceAsync("bob", "data2", "write"));
940940
}
941941

942+
[Fact]
943+
public void TestAutoSaveGroupingPolicy()
944+
{
945+
// This test verifies that AddGroupingPolicy() respects the AutoSave flag.
946+
// When AutoSave is disabled, grouping policy changes should not be saved to the adapter.
947+
948+
MockSingleAdapter adapter = new("Examples/rbac_policy.csv");
949+
Enforcer e = new("Examples/rbac_model.conf", adapter);
950+
951+
// Verify initial state: alice has data2_admin role
952+
Assert.True(e.HasGroupingPolicy("alice", "data2_admin"));
953+
Assert.False(e.HasGroupingPolicy("bob", "data2_admin"));
954+
955+
adapter.ClearSavedPolicies();
956+
e.EnableAutoSave(false);
957+
958+
// Because AutoSave is disabled, the grouping policy change should only affect
959+
// the policy in Casbin enforcer, it should NOT call the adapter.
960+
e.AddGroupingPolicy("bob", "data2_admin");
961+
962+
// Verify the change is in memory
963+
Assert.True(e.HasGroupingPolicy("bob", "data2_admin"));
964+
965+
// Verify the adapter was NOT called because AutoSave is disabled
966+
Assert.Empty(adapter.SavedPolicies);
967+
}
968+
969+
[Fact]
970+
public async Task TestAutoSaveGroupingPolicyAsync()
971+
{
972+
// This test verifies that AddGroupingPolicyAsync() respects the AutoSave flag.
973+
// When AutoSave is disabled, grouping policy changes should not be saved to the adapter.
974+
975+
MockSingleAdapter adapter = new("Examples/rbac_policy.csv");
976+
Enforcer e = new("Examples/rbac_model.conf", adapter);
977+
978+
// Verify initial state
979+
Assert.True(e.HasGroupingPolicy("alice", "data2_admin"));
980+
Assert.False(e.HasGroupingPolicy("bob", "data2_admin"));
981+
982+
adapter.ClearSavedPolicies();
983+
e.EnableAutoSave(false);
984+
985+
// Add grouping policy with AutoSave disabled
986+
await e.AddGroupingPolicyAsync("bob", "data2_admin");
987+
988+
// Verify the change is in memory
989+
Assert.True(e.HasGroupingPolicy("bob", "data2_admin"));
990+
991+
// Verify the adapter was NOT called because AutoSave is disabled
992+
Assert.Empty(adapter.SavedPolicies);
993+
}
994+
942995
[Fact]
943996
public void TestInitWithAdapter()
944997
{

Casbin/Extensions/Model/ModelExtension.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,10 +228,20 @@ public static async Task<bool> SavePolicyAsync(this IModel model)
228228

229229
public static void SetAutoSave(this IModel model, bool autoSave)
230230
{
231+
// Set AutoSave for policy assertions (section "p")
231232
foreach (KeyValuePair<string, PolicyAssertion> pair in model.Sections.GetPolicyAssertions())
232233
{
233234
pair.Value.PolicyManager.AutoSave = autoSave;
234235
}
236+
237+
// Set AutoSave for role/grouping assertions (section "g") if they exist
238+
if (model.Sections.ContainsSection(PermConstants.Section.RoleSection))
239+
{
240+
foreach (KeyValuePair<string, RoleAssertion> pair in model.Sections.GetRoleAssertions())
241+
{
242+
pair.Value.PolicyManager.AutoSave = autoSave;
243+
}
244+
}
235245
}
236246

237247
public static IPolicyManager GetPolicyManager(this IModel model, string section,

0 commit comments

Comments
 (0)