Skip to content

Commit

Permalink
feat: Add load and save policy to policy manager
Browse files Browse the repository at this point in the history
Signed-off-by: Sagilio <Sagilio@outlook.com>
  • Loading branch information
sagilio committed Feb 19, 2022
1 parent 00ce8a9 commit a7edb11
Show file tree
Hide file tree
Showing 21 changed files with 729 additions and 301 deletions.
4 changes: 2 additions & 2 deletions NetCasbin.UnitTest/ModelTests/EnforcerTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -518,7 +518,7 @@ public async Task TestInitEmptyByInputStreamAsync()
}
#endregion

#region Policy management
#region Store management
[Fact]
public void TestReloadPolicy()
{
Expand Down Expand Up @@ -677,7 +677,7 @@ public void TestEnableAutoSave()
[Fact]
public async Task TestEnableAutoSaveAsync()
{
var e = SyncedEnforcer.Create("examples/basic_model.conf", "examples/basic_policy_for_async_adapter_test.csv");
var e = new Enforcer("examples/basic_model.conf", "examples/basic_policy_for_async_adapter_test.csv");

e.EnableAutoSave(false);
// Because AutoSave is disabled, the policy change only affects the policy in Casbin enforcer,
Expand Down
47 changes: 47 additions & 0 deletions NetCasbin.UnitTest/examples/support_count_model.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
[request_definition]
r = value1
r2 = value1, value2
r3 = value1, value2, value3
r4 = value1, value2, value3, value4
r5 = value1, value2, value3, value4, value5
r6 = value1, value2, value3, value4, value5, value6
r7 = value1, value2, value3, value4, value5, value6, value7
r8 = value1, value2, value3, value4, value5, value6, value7, value8
r9 = value1, value2, value3, value4, value5, value6, value7, value8, value9
r10= value1, value2, value3, value4, value5, value6, value7, value8, value9, value10
r11= value1, value2, value3, value4, value5, value6, value7, value8, value9, value10, value11
r12= value1, value2, value3, value4, value5, value6, value7, value8, value9, value10, value11, value12

[policy_definition]
p = value1
p2 = value1, value2
p3 = value1, value2, value3
p4 = value1, value2, value3, value4
p5 = value1, value2, value3, value4, value5
p6 = value1, value2, value3, value4, value5, value6
p7 = value1, value2, value3, value4, value5, value6, value7
p8 = value1, value2, value3, value4, value5, value6, value7, value8
p9 = value1, value2, value3, value4, value5, value6, value7, value8, value9
p10= value1, value2, value3, value4, value5, value6, value7, value8, value9, value10
p11= value1, value2, value3, value4, value5, value6, value7, value8, value9, value10, value11
p12= value1, value2, value3, value4, value5, value6, value7, value8, value9, value10, value11, value12

[role_definition]
g = _, _

[policy_effect]
e = some(where (p.eft == allow))

[matchers]
m = r.value1 == p.value1
m2 = r2.value1 == p2.value1 && r2.value2 == p2.value2
m3 = r3.value1 == p3.value1 && r3.value2 == p3.value2 && r3.value3 == p3.value3
m4 = r4.value1 == p4.value1 && r4.value2 == p4.value2 && r4.value3 == p4.value3 && r4.value4 == p4.value4
m5 = r5.value1 == p5.value1 && r5.value2 == p5.value2 && r5.value3 == p5.value3 && r5.value4 == p5.value4 && r5.value5 == p5.value5
m6 = r6.value1 == p6.value1 && r6.value2 == p6.value2 && r6.value3 == p6.value3 && r6.value4 == p6.value4 && r6.value5 == p6.value5 && r6.value6 == p6.value6
m7 = r7.value1 == p7.value1 && r7.value2 == p7.value2 && r7.value3 == p7.value3 && r7.value4 == p7.value4 && r7.value5 == p7.value5 && r7.value6 == p7.value6 && r7.value7 == p7.value7
m8 = r8.value1 == p8.value1 && r8.value2 == p8.value2 && r8.value3 == p8.value3 && r8.value4 == p8.value4 && r8.value5 == p8.value5 && r8.value6 == p8.value6 && r8.value7 == p8.value7 && r8.value8 == p8.value8
m9 = r9.value1 == p9.value1 && r9.value2 == p9.value2 && r9.value3 == p9.value3 && r9.value4 == p9.value4 && r9.value5 == p9.value5 && r9.value6 == p9.value6 && r9.value7 == p9.value7 && r9.value8 == p9.value8 && r9.value9 == p9.value9
m10= r10.value1 == p10.value1 && r10.value2 == p10.value2 && r10.value3 == p10.value3 && r10.value4 == p10.value4 && r10.value5 == p10.value5 && r10.value6 == p10.value6 && r10.value7 == p10.value7 && r10.value8 == p10.value8 && r10.value9 == p10.value9 && r10.value10 == p10.value10
m11= r11.value1 == p11.value1 && r11.value2 == p11.value2 && r11.value3 == p11.value3 && r11.value4 == p11.value4 && r11.value5 == p11.value5 && r11.value6 == p11.value6 && r11.value7 == p11.value7 && r11.value8 == p11.value8 && r11.value9 == p11.value9 && r11.value10 == p11.value10 && r11.value11 == p11.value11
m12= r12.value1 == p12.value1 && r12.value2 == p12.value2 && r12.value3 == p12.value3 && r12.value4 == p12.value4 && r12.value5 == p12.value5 && r12.value6 == p12.value6 && r12.value7 == p12.value7 && r12.value8 == p12.value8 && r12.value9 == p12.value9 && r12.value10 == p12.value10 && r12.value11 == p12.value11 && r12.value12 == p12.value12
2 changes: 1 addition & 1 deletion NetCasbin/Abstractions/Model/IModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

namespace Casbin.Model
{
public interface IModel : IPolicy
public interface IModel : IPolicyStore
{
public bool IsSynchronized { get; }

Expand Down
33 changes: 7 additions & 26 deletions NetCasbin/Abstractions/Model/IPolicyManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace Casbin.Model
{
public interface IPolicyManager
public interface IPolicyManager : IPolicyStore
{
public bool IsSynchronized { get; }

Expand All @@ -14,7 +14,7 @@ public interface IPolicyManager

public bool AutoSave { get; set; }

public IPolicy Policy { get; set; }
public IPolicyStore PolicyStore { get; set; }

public void StartRead();

Expand All @@ -28,34 +28,17 @@ public interface IPolicyManager

public void EndWrite();

public IEnumerable<IEnumerable<string>> GetPolicy(string section, string policyType);

public IEnumerable<IEnumerable<string>> GetFilteredPolicy(string section, string policyType, int fieldIndex,
params string[] fieldValues);

public IEnumerable<string> GetValuesForFieldInPolicy(string section, string policyType, int fieldIndex);

public IEnumerable<string> GetValuesForFieldInPolicyAllTypes(string section, int fieldIndex);

public bool LoadPolicy();

public bool SavePolicy();

public bool HasPolicy(string section, string policyType, IEnumerable<string> rule);
public Task<bool> LoadPolicyAsync();

public bool HasPolicies(string section, string policyType, IEnumerable<IEnumerable<string>> rules);
public bool LoadFilteredPolicy(Filter filter);

public bool AddPolicy(string section, string policyType, IEnumerable<string> rule);
public Task<bool> LoadFilteredPolicyAsync(Filter filter);

public bool AddPolicies(string section, string policyType, IEnumerable<IEnumerable<string>> rules);

public bool RemovePolicy(string section, string policyType, IEnumerable<string> rule);

public bool RemovePolicies(string section, string policyType, IEnumerable<IEnumerable<string>> rules);

public IEnumerable<IEnumerable<string>> RemoveFilteredPolicy(string section, string policyType, int fieldIndex, params string[] fieldValues);
public bool SavePolicy();

public bool SavePolicyAsync();
public Task<bool> SavePolicyAsync();

public Task<bool> AddPolicyAsync(string section, string policyType, IEnumerable<string> rule);

Expand All @@ -66,7 +49,5 @@ public IEnumerable<IEnumerable<string>> GetFilteredPolicy(string section, string
public Task<bool> RemovePoliciesAsync(string section, string policyType, IEnumerable<IEnumerable<string>> rules);

public Task<IEnumerable<IEnumerable<string>>> RemoveFilteredPolicyAsync(string section, string policyType, int fieldIndex, params string[] fieldValues);

public void ClearPolicy();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@

namespace Casbin.Model
{
public interface IPolicy
public interface IPolicyStore
{
public Dictionary<string, Dictionary<string, Assertion>> Sections { get; }

public Assertion GetRequiredAssertion(string section, string type);

public bool TryGetAssertion(string section, string policyType, out Assertion returnAssertion);

public IEnumerable<IEnumerable<string>> GetPolicy(string section, string policyType);

public IEnumerable<IEnumerable<string>> GetFilteredPolicy(string section, string policyType, int fieldIndex,
Expand Down
4 changes: 2 additions & 2 deletions NetCasbin/Abstractions/Persist/IEpochAdapter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ namespace Casbin.Persist
{
public interface IEpochAdapter : IReadOnlyAdapter
{
void SavePolicy(IModel model);
void SavePolicy(IPolicyStore model);

Task SavePolicyAsync(IModel model);
Task SavePolicyAsync(IPolicyStore model);
}
}
4 changes: 2 additions & 2 deletions NetCasbin/Abstractions/Persist/IFilteredAdapter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ public interface IFilteredAdapter
{
bool IsFiltered { get; }

void LoadFilteredPolicy(IModel model, Filter filter);
void LoadFilteredPolicy(IPolicyStore store, Filter filter);

Task LoadFilteredPolicyAsync(IModel model, Filter filter);
Task LoadFilteredPolicyAsync(IPolicyStore store, Filter filter);
}
}
4 changes: 2 additions & 2 deletions NetCasbin/Abstractions/Persist/IReadOnlyAdapter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ namespace Casbin.Persist
{
public interface IReadOnlyAdapter
{
void LoadPolicy(IModel model);
void LoadPolicy(IPolicyStore model);

Task LoadPolicyAsync(IModel model);
Task LoadPolicyAsync(IPolicyStore model);
}
}
99 changes: 47 additions & 52 deletions NetCasbin/Adapter/File/FileAdapter.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
Expand All @@ -12,13 +13,13 @@ namespace Casbin.Adapter.File
{
public class FileAdapter : IEpochAdapter
{
protected readonly string _filePath;
protected readonly string FilePath;
private readonly bool _readOnly;
private readonly StreamReader _byteArrayInputStream;

public FileAdapter(string filePath)
{
_filePath = filePath;
FilePath = filePath;
}

public FileAdapter(Stream inputStream)
Expand All @@ -34,128 +35,122 @@ public FileAdapter(Stream inputStream)
}
}

public void LoadPolicy(IModel model)
public void LoadPolicy(IPolicyStore model)
{
if (!string.IsNullOrWhiteSpace(_filePath))
if (string.IsNullOrWhiteSpace(FilePath) is false)
{
using (var sr = new StreamReader(new FileStream(
_filePath, FileMode.Open, FileAccess.Read, FileShare.Read)))
{
LoadPolicyData(model, Helper.LoadPolicyLine, sr);
}
using var sr = new StreamReader(new FileStream(
FilePath, FileMode.Open, FileAccess.Read, FileShare.Read));
LoadPolicyData(model, sr);
}

if (_byteArrayInputStream != null)
if (_byteArrayInputStream is not null)
{
LoadPolicyData(model, Helper.LoadPolicyLine, _byteArrayInputStream);
LoadPolicyData(model, _byteArrayInputStream);
}
}

public async Task LoadPolicyAsync(IModel model)
public async Task LoadPolicyAsync(IPolicyStore store)
{
if (!string.IsNullOrWhiteSpace(_filePath))
if (string.IsNullOrWhiteSpace(FilePath) is false)
{
using (var sr = new StreamReader(new FileStream(
_filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)))
{
await LoadPolicyDataAsync(model, Helper.LoadPolicyLine, sr);
}
using var sr = new StreamReader(new FileStream(
FilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite));
await LoadPolicyDataAsync(store, sr);
Debug.WriteLine("xxx");
}

if (_byteArrayInputStream != null)
if (_byteArrayInputStream is not null)
{
await LoadPolicyDataAsync(model, Helper.LoadPolicyLine, _byteArrayInputStream);
await LoadPolicyDataAsync(store, _byteArrayInputStream);
}
}

public void SavePolicy(IModel model)
public void SavePolicy(IPolicyStore store)
{
if (_byteArrayInputStream != null && _readOnly)
{
throw new Exception("Policy file can not write, because use inputStream is readOnly");
throw new Exception("Store file can not write, because use inputStream is readOnly");
}

if (string.IsNullOrWhiteSpace(_filePath))
if (string.IsNullOrWhiteSpace(FilePath))
{
throw new ArgumentException("Invalid file path, file path cannot be empty");
}

var policy = ConvertToPolicyStrings(model);
var policy = ConvertToPolicyStrings(store);
SavePolicyFile(string.Join("\n", policy));
}

public async Task SavePolicyAsync(IModel model)
public Task SavePolicyAsync(IPolicyStore store)
{
if (_byteArrayInputStream != null && _readOnly)
{
throw new Exception("Policy file can not write, because use inputStream is readOnly");
throw new Exception("Store file can not write, because use inputStream is readOnly");
}

if (string.IsNullOrWhiteSpace(_filePath))
if (string.IsNullOrWhiteSpace(FilePath))
{
throw new ArgumentException("Invalid file path, file path cannot be empty");
}

var policy = ConvertToPolicyStrings(model);
await SavePolicyFileAsync(string.Join("\n", policy));
var policy = ConvertToPolicyStrings(store);
return SavePolicyFileAsync(string.Join("\n", policy));
}

private static IEnumerable<string> GetModelPolicy(IModel model, string ptype)
private static IEnumerable<string> GetModelPolicy(IPolicyStore store, string section)
{
var policy = new List<string>();
foreach (var pair in model.Sections[ptype])
foreach (var kv in store.Sections[section])
{
string key = pair.Key;
Assertion value = pair.Value;
string key = kv.Key;
Assertion value = kv.Value;
policy.AddRange(value.Policy.Select(p => $"{key}, {Utility.RuleToString(p)}"));
}
return policy;
}

private static void LoadPolicyData(IModel model, Helper.LoadPolicyLineHandler<string, IModel> handler, StreamReader inputStream)
private static void LoadPolicyData(IPolicyStore store, StreamReader inputStream)
{
while (!inputStream.EndOfStream)
while (inputStream.EndOfStream is false)
{
string line = inputStream.ReadLine();
handler(line, model);
store.TryLoadPolicyLine(line);
}
}

private async Task LoadPolicyDataAsync(IModel model, Helper.LoadPolicyLineHandler<string, IModel> handler, StreamReader inputStream)
private static async Task LoadPolicyDataAsync(IPolicyStore store, StreamReader inputStream)
{
while (!inputStream.EndOfStream)
while (inputStream.EndOfStream is false)
{
string line = await inputStream.ReadLineAsync();
handler(line, model);
store.TryLoadPolicyLine(line);
}
}

private IEnumerable<string> ConvertToPolicyStrings(IModel model)
private static IEnumerable<string> ConvertToPolicyStrings(IPolicyStore store)
{
var policy = new List<string>();
policy.AddRange(GetModelPolicy(model, PermConstants.DefaultPolicyType));
if (model.Sections.ContainsKey(PermConstants.Section.RoleSection))
policy.AddRange(GetModelPolicy(store, PermConstants.DefaultPolicyType));
if (store.Sections.ContainsKey(PermConstants.Section.RoleSection))
{
policy.AddRange(GetModelPolicy(model, PermConstants.Section.RoleSection));
policy.AddRange(GetModelPolicy(store, PermConstants.Section.RoleSection));
}
return policy;
}

private void SavePolicyFile(string text)
{
System.IO.File.WriteAllText(_filePath, text, Encoding.UTF8);
System.IO.File.WriteAllText(FilePath, text, Encoding.UTF8);
}

private async Task SavePolicyFileAsync(string text)
{
text = text ?? string.Empty;
var content = Encoding.UTF8.GetBytes(text);
using (var fs = new FileStream(
_filePath, FileMode.Create, FileAccess.Write,
FileShare.None, bufferSize: 4096, useAsync: true))
{
await fs.WriteAsync(content, 0, content.Length);
}
byte[] content = Encoding.UTF8.GetBytes(text);
using var fs = new FileStream(
FilePath, FileMode.Create, FileAccess.Write,
FileShare.None, bufferSize: 4096, useAsync: true);
await fs.WriteAsync(content, 0, content.Length);
}
}
}
Loading

0 comments on commit a7edb11

Please sign in to comment.