blob: 67b9a0a942b4696adf6439acee3346aed1145a9a [file] [log] [blame]
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using Casbin.Model;
using Casbin.UnitTests.Fixtures;
using Casbin.UnitTests.Mock;
using Xunit;
using static Casbin.UnitTests.Util.TestUtil;
namespace Casbin.UnitTests.ModelTests;
[Collection("Model collection")]
public partial class ModelTest
{
private readonly TestModelFixture _testModelFixture;
public ModelTest(TestModelFixture testModelFixture) => _testModelFixture = testModelFixture;
[Fact]
public void TestBasicModel()
{
Enforcer e = new(TestModelFixture.GetBasicTestModel());
Assert.True(e.Enforce("alice", "data1", "read"));
Assert.False(e.Enforce("alice", "data1", "write"));
Assert.False(e.Enforce("alice", "data2", "read"));
Assert.False(e.Enforce("alice", "data2", "write"));
Assert.False(e.Enforce("bob", "data1", "read"));
Assert.False(e.Enforce("bob", "data1", "write"));
Assert.False(e.Enforce("bob", "data2", "read"));
Assert.True(e.Enforce("bob", "data2", "write"));
}
[Fact]
public void TestBasicModelNoPolicy()
{
Enforcer e = new(TestModelFixture.GetNewTestModel(TestModelFixture.BasicModelText));
Assert.False(e.Enforce("alice", "data1", "read"));
Assert.False(e.Enforce("alice", "data1", "write"));
Assert.False(e.Enforce("alice", "data2", "read"));
Assert.False(e.Enforce("alice", "data2", "write"));
Assert.False(e.Enforce("bob", "data1", "read"));
Assert.False(e.Enforce("bob", "data1", "write"));
Assert.False(e.Enforce("bob", "data2", "read"));
Assert.False(e.Enforce("bob", "data2", "write"));
}
[Fact]
public void TestBasicModelWithRoot()
{
Enforcer e = new(TestModelFixture.GetNewTestModel(
TestModelFixture.BasicWithRootModelText,
TestModelFixture.BasicPolicyText));
Assert.True(e.Enforce("alice", "data1", "read"));
Assert.False(e.Enforce("alice", "data1", "write"));
Assert.False(e.Enforce("alice", "data2", "read"));
Assert.False(e.Enforce("alice", "data2", "write"));
Assert.False(e.Enforce("bob", "data1", "read"));
Assert.False(e.Enforce("bob", "data1", "write"));
Assert.False(e.Enforce("bob", "data2", "read"));
Assert.True(e.Enforce("bob", "data2", "write"));
Assert.True(e.Enforce("root", "data1", "read"));
Assert.True(e.Enforce("root", "data1", "write"));
Assert.True(e.Enforce("root", "data2", "read"));
Assert.True(e.Enforce("root", "data2", "write"));
}
[Fact]
public void TestBasicModelWithRootNoPolicy()
{
Enforcer e = new(TestModelFixture.GetNewTestModel(TestModelFixture.BasicWithRootModelText));
Assert.False(e.Enforce("alice", "data1", "read"));
Assert.False(e.Enforce("alice", "data1", "write"));
Assert.False(e.Enforce("alice", "data2", "read"));
Assert.False(e.Enforce("alice", "data2", "write"));
Assert.False(e.Enforce("bob", "data1", "read"));
Assert.False(e.Enforce("bob", "data1", "write"));
Assert.False(e.Enforce("bob", "data2", "read"));
Assert.False(e.Enforce("bob", "data2", "write"));
Assert.True(e.Enforce("root", "data1", "read"));
Assert.True(e.Enforce("root", "data1", "write"));
Assert.True(e.Enforce("root", "data2", "read"));
Assert.True(e.Enforce("root", "data2", "write"));
}
[Fact]
public void TestBasicModelWithoutUsers()
{
Enforcer e = new(TestModelFixture.GetBasicWithoutUserTestModel());
Assert.True(e.Enforce("data1", "read"));
Assert.False(e.Enforce("data1", "write"));
Assert.False(e.Enforce("data2", "read"));
Assert.True(e.Enforce("data2", "write"));
}
[Fact]
public void TestBasicModelWithoutResources()
{
Enforcer e = new(TestModelFixture.GetBasicWithoutResourceTestModel());
Assert.True(e.Enforce("alice", "read"));
Assert.False(e.Enforce("alice", "write"));
Assert.False(e.Enforce("bob", "read"));
Assert.True(e.Enforce("bob", "write"));
}
[Fact]
public void TestRbacModel()
{
Enforcer e = new(TestModelFixture.GetNewRbacTestModel());
e.BuildRoleLinks();
Assert.True(e.Enforce("alice", "data1", "read"));
Assert.False(e.Enforce("alice", "data1", "write"));
Assert.True(e.Enforce("alice", "data2", "read"));
Assert.True(e.Enforce("alice", "data2", "write"));
Assert.False(e.Enforce("bob", "data1", "read"));
Assert.False(e.Enforce("bob", "data1", "write"));
Assert.False(e.Enforce("bob", "data2", "read"));
Assert.True(e.Enforce("bob", "data2", "write"));
}
[Fact]
public void TestRbacModelWithResourceRoles()
{
Enforcer e = new(TestModelFixture.GetNewRbacWithResourceRoleTestModel());
e.BuildRoleLinks();
Assert.True(e.Enforce("alice", "data1", "read"));
Assert.True(e.Enforce("alice", "data1", "write"));
Assert.False(e.Enforce("alice", "data2", "read"));
Assert.True(e.Enforce("alice", "data2", "write"));
Assert.False(e.Enforce("bob", "data1", "read"));
Assert.False(e.Enforce("bob", "data1", "write"));
Assert.False(e.Enforce("bob", "data2", "read"));
Assert.True(e.Enforce("bob", "data2", "write"));
}
[Fact]
public void TestRbacModelWithDomains()
{
Enforcer e = new(TestModelFixture.GetNewRbacWithDomainsTestModel());
e.BuildRoleLinks();
Assert.True(e.Enforce("alice", "domain1", "data1", "read"));
Assert.True(e.Enforce("alice", "domain1", "data1", "write"));
Assert.False(e.Enforce("alice", "domain1", "data2", "read"));
Assert.False(e.Enforce("alice", "domain1", "data2", "write"));
Assert.False(e.Enforce("bob", "domain2", "data1", "read"));
Assert.False(e.Enforce("bob", "domain2", "data1", "write"));
Assert.True(e.Enforce("bob", "domain2", "data2", "read"));
Assert.True(e.Enforce("bob", "domain2", "data2", "write"));
}
[Fact]
public void TestRbacModelWithDomainsAtRuntime()
{
Enforcer e = new(TestModelFixture.GetNewTestModel(TestModelFixture.RbacWithDomainsModelText));
e.BuildRoleLinks();
e.AddPolicy("admin", "domain1", "data1", "read");
e.AddPolicy("admin", "domain1", "data1", "write");
e.AddPolicy("admin", "domain2", "data2", "read");
e.AddPolicy("admin", "domain2", "data2", "write");
e.AddGroupingPolicy("alice", "admin", "domain1");
e.AddGroupingPolicy("bob", "admin", "domain2");
Assert.True(e.Enforce("alice", "domain1", "data1", "read"));
Assert.True(e.Enforce("alice", "domain1", "data1", "write"));
Assert.False(e.Enforce("alice", "domain1", "data2", "read"));
Assert.False(e.Enforce("alice", "domain1", "data2", "write"));
Assert.False(e.Enforce("bob", "domain2", "data1", "read"));
Assert.False(e.Enforce("bob", "domain2", "data1", "write"));
Assert.True(e.Enforce("bob", "domain2", "data2", "read"));
Assert.True(e.Enforce("bob", "domain2", "data2", "write"));
// Remove all policy rules related to domain1 and data1.
e.RemoveFilteredPolicy(1, "domain1", "data1");
Assert.False(e.Enforce("alice", "domain1", "data1", "read"));
Assert.False(e.Enforce("alice", "domain1", "data1", "write"));
Assert.False(e.Enforce("alice", "domain1", "data2", "read"));
Assert.False(e.Enforce("alice", "domain1", "data2", "write"));
Assert.False(e.Enforce("bob", "domain2", "data1", "read"));
Assert.False(e.Enforce("bob", "domain2", "data1", "write"));
Assert.True(e.Enforce("bob", "domain2", "data2", "read"));
Assert.True(e.Enforce("bob", "domain2", "data2", "write"));
// Remove the specified policy rule.
e.RemovePolicy("admin", "domain2", "data2", "read");
Assert.False(e.Enforce("alice", "domain1", "data1", "read"));
Assert.False(e.Enforce("alice", "domain1", "data1", "write"));
Assert.False(e.Enforce("alice", "domain1", "data2", "read"));
Assert.False(e.Enforce("alice", "domain1", "data2", "write"));
Assert.False(e.Enforce("bob", "domain2", "data1", "read"));
Assert.False(e.Enforce("bob", "domain2", "data1", "write"));
Assert.False(e.Enforce("bob", "domain2", "data2", "read"));
Assert.True(e.Enforce("bob", "domain2", "data2", "write"));
}
[Fact]
public async Task TestRbacModelWithDomainsAtRuntimeAsync()
{
Enforcer e = new(TestModelFixture.GetNewTestModel(TestModelFixture.RbacWithDomainsModelText));
e.BuildRoleLinks();
await e.AddPolicyAsync("admin", "domain1", "data1", "read");
await e.AddPolicyAsync("admin", "domain1", "data1", "write");
await e.AddPolicyAsync("admin", "domain2", "data2", "read");
await e.AddPolicyAsync("admin", "domain2", "data2", "write");
await e.AddGroupingPolicyAsync("alice", "admin", "domain1");
await e.AddGroupingPolicyAsync("bob", "admin", "domain2");
Assert.True(await e.EnforceAsync("alice", "domain1", "data1", "read"));
Assert.True(await e.EnforceAsync("alice", "domain1", "data1", "write"));
Assert.False(await e.EnforceAsync("alice", "domain1", "data2", "read"));
Assert.False(await e.EnforceAsync("alice", "domain1", "data2", "write"));
Assert.False(await e.EnforceAsync("bob", "domain2", "data1", "read"));
Assert.False(await e.EnforceAsync("bob", "domain2", "data1", "write"));
Assert.True(await e.EnforceAsync("bob", "domain2", "data2", "read"));
Assert.True(await e.EnforceAsync("bob", "domain2", "data2", "write"));
// Remove all policy rules related to domain1 and data1.
await e.RemoveFilteredPolicyAsync(1, "domain1", "data1");
Assert.False(await e.EnforceAsync("alice", "domain1", "data1", "read"));
Assert.False(await e.EnforceAsync("alice", "domain1", "data1", "write"));
Assert.False(await e.EnforceAsync("alice", "domain1", "data2", "read"));
Assert.False(await e.EnforceAsync("alice", "domain1", "data2", "write"));
Assert.False(await e.EnforceAsync("bob", "domain2", "data1", "read"));
Assert.False(await e.EnforceAsync("bob", "domain2", "data1", "write"));
Assert.True(await e.EnforceAsync("bob", "domain2", "data2", "read"));
Assert.True(await e.EnforceAsync("bob", "domain2", "data2", "write"));
// Remove the specified policy rule.
await e.RemovePolicyAsync("admin", "domain2", "data2", "read");
Assert.False(await e.EnforceAsync("alice", "domain1", "data1", "read"));
Assert.False(await e.EnforceAsync("alice", "domain1", "data1", "write"));
Assert.False(await e.EnforceAsync("alice", "domain1", "data2", "read"));
Assert.False(await e.EnforceAsync("alice", "domain1", "data2", "write"));
Assert.False(await e.EnforceAsync("bob", "domain2", "data1", "read"));
Assert.False(await e.EnforceAsync("bob", "domain2", "data1", "write"));
Assert.False(await e.EnforceAsync("bob", "domain2", "data2", "read"));
Assert.True(await e.EnforceAsync("bob", "domain2", "data2", "write"));
}
[Fact]
public void TestRbacModelWithDeny()
{
Enforcer e = new(TestModelFixture.GetNewRbacWithDenyTestModel());
e.BuildRoleLinks();
Assert.True(e.Enforce("alice", "data1", "read"));
Assert.False(e.Enforce("alice", "data1", "write"));
Assert.True(e.Enforce("alice", "data2", "read"));
Assert.False(e.Enforce("alice", "data2", "write"));
Assert.False(e.Enforce("bob", "data1", "read"));
Assert.False(e.Enforce("bob", "data1", "write"));
Assert.False(e.Enforce("bob", "data2", "read"));
Assert.True(e.Enforce("bob", "data2", "write"));
}
[Fact]
public void TestRbacModelWithOnlyDeny()
{
Enforcer e = new(TestModelFixture.GetNewTestModel(
TestModelFixture.RbacWithNotDenyModelText,
TestModelFixture.RbacWithDenyPolicyText));
e.BuildRoleLinks();
Assert.False(e.Enforce("alice", "data2", "write"));
}
[Fact]
public void TestRbacModelWithCustomData()
{
Enforcer e = new(TestModelFixture.GetNewRbacTestModel());
e.BuildRoleLinks();
// You can add custom data to a grouping policy, Casbin will ignore it. It is only meaningful to the caller.
// This feature can be used to store information like whether "bob" is an end user (so no subject will inherit "bob")
// For Casbin, it is equivalent to: e.addGroupingPolicy("bob", "data2_admin")
e.AddGroupingPolicy("bob", "data2_admin", "custom_data");
Assert.True(e.Enforce("alice", "data1", "read"));
Assert.False(e.Enforce("alice", "data1", "write"));
Assert.True(e.Enforce("alice", "data2", "read"));
Assert.True(e.Enforce("alice", "data2", "write"));
Assert.False(e.Enforce("bob", "data1", "read"));
Assert.False(e.Enforce("bob", "data1", "write"));
Assert.True(e.Enforce("bob", "data2", "read"));
Assert.True(e.Enforce("bob", "data2", "write"));
// You should also take the custom data as a parameter when deleting a grouping policy.
// e.removeGroupingPolicy("bob", "data2_admin") won't work.
// Or you can remove it by using removeFilteredGroupingPolicy().
e.RemoveGroupingPolicy("bob", "data2_admin", "custom_data");
Assert.True(e.Enforce("alice", "data1", "read"));
Assert.False(e.Enforce("alice", "data1", "write"));
Assert.True(e.Enforce("alice", "data2", "read"));
Assert.True(e.Enforce("alice", "data2", "write"));
Assert.False(e.Enforce("bob", "data1", "read"));
Assert.False(e.Enforce("bob", "data1", "write"));
Assert.False(e.Enforce("bob", "data2", "read"));
Assert.True(e.Enforce("bob", "data2", "write"));
}
[Fact]
public async Task TestRbacModelWithCustomDataAsync()
{
Enforcer e = new(TestModelFixture.GetNewRbacTestModel());
e.BuildRoleLinks();
// You can add custom data to a grouping policy, Casbin will ignore it. It is only meaningful to the caller.
// This feature can be used to store information like whether "bob" is an end user (so no subject will inherit "bob")
// For Casbin, it is equivalent to: e.addGroupingPolicy("bob", "data2_admin")
await e.AddGroupingPolicyAsync("bob", "data2_admin", "custom_data");
Assert.True(await e.EnforceAsync("alice", "data1", "read"));
Assert.False(await e.EnforceAsync("alice", "data1", "write"));
Assert.True(await e.EnforceAsync("alice", "data2", "read"));
Assert.True(await e.EnforceAsync("alice", "data2", "write"));
Assert.False(await e.EnforceAsync("bob", "data1", "read"));
Assert.False(await e.EnforceAsync("bob", "data1", "write"));
Assert.True(await e.EnforceAsync("bob", "data2", "read"));
Assert.True(await e.EnforceAsync("bob", "data2", "write"));
// You should also take the custom data as a parameter when deleting a grouping policy.
// e.removeGroupingPolicy("bob", "data2_admin") won't work.
// Or you can remove it by using removeFilteredGroupingPolicy().
await e.RemoveGroupingPolicyAsync("bob", "data2_admin", "custom_data");
Assert.True(await e.EnforceAsync("alice", "data1", "read"));
Assert.False(await e.EnforceAsync("alice", "data1", "write"));
Assert.True(await e.EnforceAsync("alice", "data2", "read"));
Assert.True(await e.EnforceAsync("alice", "data2", "write"));
Assert.False(await e.EnforceAsync("bob", "data1", "read"));
Assert.False(await e.EnforceAsync("bob", "data1", "write"));
Assert.False(await e.EnforceAsync("bob", "data2", "read"));
Assert.True(await e.EnforceAsync("bob", "data2", "write"));
}
[Fact]
public void TestRbacModelWithCustomRoleManager()
{
Enforcer e = new(TestModelFixture.GetNewRbacTestModel());
e.SetRoleManager(new MockCustomRoleManager());
e.BuildRoleLinks();
Assert.True(e.Enforce("alice", "data1", "read"));
Assert.False(e.Enforce("alice", "data1", "write"));
Assert.True(e.Enforce("alice", "data2", "read"));
Assert.True(e.Enforce("alice", "data2", "write"));
Assert.False(e.Enforce("bob", "data1", "read"));
Assert.False(e.Enforce("bob", "data1", "write"));
Assert.False(e.Enforce("bob", "data2", "read"));
Assert.True(e.Enforce("bob", "data2", "write"));
}
[Fact]
public void TestAbacModel()
{
Enforcer e = new(TestModelFixture.GetNewAbacModel());
TestResource data1 = new("data1", "alice");
TestResource data2 = new("data2", "bob");
Assert.True(e.Enforce("alice", data1, "read"));
Assert.True(e.Enforce("alice", data1, "write"));
Assert.False(e.Enforce("alice", data2, "read"));
Assert.False(e.Enforce("alice", data2, "write"));
Assert.False(e.Enforce("bob", data1, "read"));
Assert.False(e.Enforce("bob", data1, "write"));
Assert.True(e.Enforce("bob", data2, "read"));
Assert.True(e.Enforce("bob", data2, "write"));
}
[Fact]
public void TestAbacWithEvalModel()
{
Enforcer e = new(TestModelFixture.GetNewAbacWithEvalModel());
TestSubject subject1 = new("alice", 16);
TestSubject subject2 = new("alice", 20);
TestSubject subject3 = new("alice", 65);
Assert.False(e.Enforce(subject1, "/data1", "read"));
Assert.False(e.Enforce(subject1, "/data2", "read"));
Assert.False(e.Enforce(subject1, "/data1", "write"));
Assert.True(e.Enforce(subject1, "/data2", "write"));
Assert.True(e.Enforce(subject2, "/data1", "read"));
Assert.False(e.Enforce(subject2, "/data2", "read"));
Assert.False(e.Enforce(subject2, "/data1", "write"));
Assert.True(e.Enforce(subject2, "/data2", "write"));
Assert.True(e.Enforce(subject3, "/data1", "read"));
Assert.False(e.Enforce(subject3, "/data2", "read"));
Assert.False(e.Enforce(subject3, "/data1", "write"));
Assert.False(e.Enforce(subject3, "/data2", "write"));
}
[Fact]
public void TestKeyMatchModel()
{
Enforcer e = new(TestModelFixture.GetNewKeyMatchTestModel());
Assert.True(e.Enforce("alice", "/alice_data/resource1", "GET"));
Assert.True(e.Enforce("alice", "/alice_data/resource1", "POST"));
Assert.True(e.Enforce("alice", "/alice_data/resource2", "GET"));
Assert.False(e.Enforce("alice", "/alice_data/resource2", "POST"));
Assert.False(e.Enforce("alice", "/bob_data/resource1", "GET"));
Assert.False(e.Enforce("alice", "/bob_data/resource1", "POST"));
Assert.False(e.Enforce("alice", "/bob_data/resource2", "GET"));
Assert.False(e.Enforce("alice", "/bob_data/resource2", "POST"));
Assert.False(e.Enforce("bob", "/alice_data/resource1", "GET"));
Assert.False(e.Enforce("bob", "/alice_data/resource1", "POST"));
Assert.True(e.Enforce("bob", "/alice_data/resource2", "GET"));
Assert.False(e.Enforce("bob", "/alice_data/resource2", "POST"));
Assert.False(e.Enforce("bob", "/bob_data/resource1", "GET"));
Assert.True(e.Enforce("bob", "/bob_data/resource1", "POST"));
Assert.False(e.Enforce("bob", "/bob_data/resource2", "GET"));
Assert.True(e.Enforce("bob", "/bob_data/resource2", "POST"));
Assert.True(e.Enforce("cathy", "/cathy_data", "GET"));
Assert.True(e.Enforce("cathy", "/cathy_data", "POST"));
Assert.False(e.Enforce("cathy", "/cathy_data", "DELETE"));
}
[Fact]
public void TestPriorityModelIndeterminate()
{
Enforcer e = new(TestModelFixture.GetNewTestModel(
TestModelFixture.PriorityModelText,
TestModelFixture.PriorityIndeterminatePolicyText));
e.BuildRoleLinks();
Assert.False(e.Enforce("alice", "data1", "read"));
}
[Fact]
public void TestPriorityModel()
{
Enforcer e = new(TestModelFixture.GetNewPriorityTestModel());
e.BuildRoleLinks();
Assert.True(e.Enforce("alice", "data1", "read"));
Assert.False(e.Enforce("alice", "data1", "write"));
Assert.False(e.Enforce("alice", "data2", "read"));
Assert.False(e.Enforce("alice", "data2", "write"));
Assert.False(e.Enforce("bob", "data1", "read"));
Assert.False(e.Enforce("bob", "data1", "write"));
Assert.True(e.Enforce("bob", "data2", "read"));
Assert.False(e.Enforce("bob", "data2", "write"));
}
[Fact]
public void TestPriorityExplicitModel()
{
Enforcer e = new(TestModelFixture.GetNewPriorityExplicitTestModel());
e.BuildRoleLinks();
Assert.True(e.Enforce("alice", "data1", "write"));
Assert.True(e.Enforce("alice", "data1", "read"));
Assert.False(e.Enforce("bob", "data2", "read"));
Assert.True(e.Enforce("bob", "data2", "write"));
Assert.False(e.Enforce("data1_deny_group", "data1", "read"));
Assert.False(e.Enforce("data1_deny_group", "data1", "write"));
Assert.True(e.Enforce("data2_allow_group", "data2", "read"));
Assert.True(e.Enforce("data2_allow_group", "data2", "write"));
// add a higher priority policy
e.AddPolicy("1", "bob", "data2", "write", "deny");
Assert.True(e.Enforce("alice", "data1", "write"));
Assert.True(e.Enforce("alice", "data1", "read"));
Assert.False(e.Enforce("bob", "data2", "read"));
Assert.False(e.Enforce("bob", "data2", "write"));
Assert.False(e.Enforce("data1_deny_group", "data1", "read"));
Assert.False(e.Enforce("data1_deny_group", "data1", "write"));
Assert.True(e.Enforce("data2_allow_group", "data2", "read"));
Assert.True(e.Enforce("data2_allow_group", "data2", "write"));
}
[Fact]
public void TestPriorityExplicitDenyOverrideModel()
{
Enforcer e = new(TestModelFixture.GetNewPriorityExplicitDenyOverrideModel());
e.BuildRoleLinks();
Assert.True(e.Enforce("alice", "data2", "write"));
Assert.True(e.Enforce("bob", "data2", "read"));
// adding a new group, simulating behaviour when two different groups are added to the same person.
e.AddPolicy("10", "data2_deny_group_new", "data2", "write", "deny");
e.AddGroupingPolicy("alice", "data2_deny_group_new");
Assert.False(e.Enforce("alice", "data2", "write"));
Assert.True(e.Enforce("bob", "data2", "read"));
// expected enforcement result should be true,
// as there is a policy with a lower rank 10, that produces allow result.
e.AddPolicy("5", "alice", "data2", "write", "allow");
Assert.True(e.Enforce("alice", "data2", "write"));
// adding deny policy for alice for the same obj,
// to ensure that if there is at least one deny, final result will be deny.
e.AddPolicy("5", "alice", "data2", "write", "deny");
Assert.False(e.Enforce("alice", "data2", "write"));
// adding higher fake higher priority policy for alice,
// expected enforcement result should be true (ignore this policy).
e.AddPolicy("2", "alice", "data2", "write", "allow");
Assert.True(e.Enforce("alice", "data2", "write"));
e.AddPolicy("1", "fake-subject", "fake-object", "very-fake-action", "allow");
Assert.True(e.Enforce("alice", "data2", "write"));
// adding higher (less of 0) priority policy for alice,
// to override group policies again.
e.AddPolicy("-1", "alice", "data2", "write", "deny");
Assert.False(e.Enforce("alice", "data2", "write"));
}
[Fact]
public void TestKeyMatch2Model()
{
Enforcer e = new(TestModelFixture.GetNewKeyMatch2TestModel());
Assert.False(e.Enforce("alice", "/alice_data", "GET"));
Assert.True(e.Enforce("alice", "/alice_data/resource1", "GET"));
Assert.False(e.Enforce("alice", "/alice_data2/myid", "GET"));
Assert.True(e.Enforce("alice", "/alice_data2/myid/using/res_id", "GET"));
}
[Fact]
public void TestKeyMatchCustomModel()
{
static bool CustomFunction(string key1, string key2)
{
return (key1 is "/alice_data2/myid/using/res_id" && key2 is "/alice_data/:resource")
|| (key1 is "/alice_data2/myid/using/res_id" && key2 is "/alice_data2/:id/using/:resId");
}
Enforcer e = new(TestModelFixture.GetNewTestModel(
TestModelFixture.KeyMatchCustomModelText,
TestModelFixture.KeyMatch2PolicyText));
e.AddFunction("keyMatchCustom", CustomFunction);
Assert.False(e.Enforce("alice", "/alice_data2/myid", "GET"));
Assert.True(e.Enforce("alice", "/alice_data2/myid/using/res_id", "GET"));
}
[Fact]
public void TestMultipleTypeModel()
{
Enforcer e = new(TestModelFixture.GetNewMultipleTypeTestModel());
e.BuildRoleLinks();
// Use default types
EnforceContext context = e.CreateContext();
Assert.True(e.Enforce(context, "alice", "data1", "read"));
Assert.False(e.Enforce(context, "alice", "data1", "write"));
Assert.True(e.Enforce(context, "bob", "data2", "read"));
Assert.False(e.Enforce(context, "bob", "data2", "write"));
// Use r2 p2 and m2 type
context = e.CreateContext
(
PermConstants.RequestType2,
PermConstants.PolicyType2,
PermConstants.DefaultPolicyEffectType,
PermConstants.MatcherType2
);
Assert.True(e.Enforce(context, "alice", "domain1", "data2", "read"));
Assert.False(e.Enforce(context, "alice", "domain1", "data2", "write"));
Assert.True(e.Enforce(context, "bob", "domain1", "data1", "read"));
Assert.False(e.Enforce(context, "bob", "domain1", "data1", "write"));
// Use r3 p3 and m3 type
context = e.CreateContext
(
PermConstants.RequestType3,
PermConstants.PolicyType3,
PermConstants.DefaultPolicyEffectType,
PermConstants.MatcherType3
);
Assert.True(e.Enforce(context, new { Age = 30 }, "data2", "read"));
Assert.False(e.Enforce(context, new { Age = 70 }, "data2", "read"));
}
[Fact]
public void TestAbacComment()
{
var model = TestModelFixture.GetNewTestModel(TestModelFixture.AbacCommentText);
Assert.Equal(3, model.Sections.GetRequestAssertion("r")?.Tokens.Count);
Assert.Equal(2, model.Sections.GetRequestAssertion("r")?.Tokens["act"]);
Assert.Equal(3, model.Sections.GetPolicyAssertion("p").Tokens.Count);
Assert.Equal("some(where (p.eft == allow))", model.Sections.GetPolicyEffectAssertion("e").Value);
Assert.Equal("r.sub == p.sub && r.obj == p.obj && r.act == p.act",
model.Sections.GetMatcherAssertion("m").Value);
}
[Fact]
public void TestRbacComment()
{
var model = TestModelFixture.GetNewTestModel(TestModelFixture.RbacCommentText);
Assert.Equal(3, model.Sections.GetRequestAssertion("r")?.Tokens.Count);
Assert.Equal(2, model.Sections.GetRequestAssertion("r")?.Tokens["act"]);
Assert.Equal(3, model.Sections.GetPolicyAssertion("p").Tokens.Count);
Assert.Equal("_, _", model.Sections.GetRoleAssertion("g").Value);
Assert.Equal("some(where (p.eft == allow))", model.Sections.GetPolicyEffectAssertion("e").Value);
Assert.Equal("g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act",
model.Sections.GetMatcherAssertion("m").Value);
}
[Fact]
public void TestModelWithCommaAndQuotations()
{
Enforcer e = new Enforcer(TestModelFixture.GetNewCommaAndQuotationsModel());
Assert.True(e.Enforce("alice", "Comma,Test", "Get"));
Assert.False(e.Enforce("alice", "Comma,Test", "Post"));
Assert.False(e.Enforce("alice", "\"Comma,Test\"", "Get"));
Assert.True(e.Enforce("bob", "\"Comma\",\"Quotations\",Test", "Get"));
Assert.False(e.Enforce("bob", "\"Comma\",\"Quotations\",Test", "Post"));
Assert.False(e.Enforce("bob", "\"\"Comma\"\",\"\"Quotations\"\",Test", "Get"));
Assert.False(e.Enforce("bob", "\"\"\"Comma\"\",\"\"Quotations\"\",Test\"", "Get"));
Assert.True(e.Enforce("cindy", "\"Muti Quotations Test", "Get"));
Assert.False(e.Enforce("cindy", "\"Muti Quotations Test", "Post"));
Assert.False(e.Enforce("cindy", "\"\"Muti Quotations Test", "Get"));
Assert.False(e.Enforce("cindy", "\"\"Muti Quotations Test\"", "Get"));
}
[Fact]
public void TestModelWithTabs()
{
Enforcer e = new Enforcer(TestModelFixture.GetNewTabsModel());
e.AddRoleForUserInDomain("/user/john", "admin", "/tenant/1");
Assert.True(e.Enforce("/user/john", "/tenant/1", "/tenant/1/resource", "Write"));
}
[Fact]
public void TestRbacTokensWithSubstringRelation()
{
Enforcer e = new(TestModelFixture.GetNewTestModel(
TestModelFixture.RbacTokensWithSubstringRelationModelText,
TestModelFixture.RbacTokensWithSubstringRelationPolicyText));
e.BuildRoleLinks();
Assert.True(e.Enforce("alice", "tenant1", "data1", "read"));
Assert.True(e.Enforce("alice", "tenant1", "freeread", "read"));
Assert.False(e.Enforce("alice", "tenant2", "data2", "read"));
Assert.False(e.Enforce("alice", "tenant1", "data1", "write"));
Assert.False(e.Enforce("bob", "tenant1", "data1", "read"));
Assert.False(e.Enforce("alice", "tenant3", "freeread", "read"));
Assert.False(e.Enforce("alice", "tenant1", "freeread", "write"));
}
[Fact]
public void TestAbacTokensWithSubstringRelation()
{
Enforcer e = new(TestModelFixture.GetNewTestModel(
TestModelFixture.AbacTokensWithSubstringRelationModelText,
TestModelFixture.AbacTokensWithSubstringRelationPolicyText));
TestResource data1 = new("data1", "alice");
TestResource data2 = new("data2", "bob");
TestSubject subjecta = new("alice", 16);
TestSubject subjectb = new("bob", 65);
TestSubject subjectc = new("candy", 30);
TestSubject subjectd = new("donale", -1);
TestSubject subjecte = new("eleena", 1000000009);
Assert.True(e.Enforce(subjecta, data1, "read"));
Assert.True(e.Enforce(subjectb, data2, "write"));
Assert.True(e.Enforce(subjectc, data1, "read"));
Assert.True(e.Enforce(subjectc, data2, "write"));
Assert.True(e.Enforce(subjecta, data2, "write"));
Assert.True(e.Enforce(subjectb, data1, "read"));
Assert.True(e.Enforce(subjecta, data1, "write"));
Assert.True(e.Enforce(subjectb, data2, "read"));
Assert.False(e.Enforce(subjectc, data1, "write"));
Assert.False(e.Enforce(subjectc, data2, "read"));
Assert.False(e.Enforce(subjectd, data1, "read"));
Assert.False(e.Enforce(subjecte, data2, "write"));
}
[Fact]
public void TestBackslashLineFeed()
{
Enforcer e = new(TestModelFixture.GetNewTestModel(
TestModelFixture.BackslashLineFeedModelText,
TestModelFixture.BackslashLineFeedPolicyText));
Assert.True(e.Enforce("alice", "data1", "read"));
Assert.False(e.Enforce("alice", "data1", "write"));
Assert.False(e.Enforce("alice", "data2", "read"));
Assert.False(e.Enforce("alice", "data2", "write"));
Assert.False(e.Enforce("bob", "data1", "read"));
Assert.False(e.Enforce("bob", "data1", "write"));
Assert.False(e.Enforce("bob", "data2", "read"));
Assert.True(e.Enforce("bob", "data2", "write"));
}
[Fact]
public void TestAccidentalCacheRead()
{
Enforcer e = new(TestModelFixture.GetBasicTestModel());
Assert.True(e.Enforce("alice", "data1", "read"));
Assert.False(e.Enforce("aliced", "ata1", "read"));
Assert.False(e.Enforce("alice", "data", "1read"));
}
[Fact]
public void TestRbacWithIndexMatcher()
{
Enforcer e = new(TestModelFixture.GetNewTestModel(
TestModelFixture.RbacWithIndexMatcherModelText,
TestModelFixture.RbacWithIndexMatcherPolicyText));
e.BuildRoleLinks();
var rule = new Dictionary<string, Dictionary<string, string>>
{
["CompanyData"] = new() { ["CompanyIsActive"] = "True", ["BusinessRole"] = "Role1" }
};
Assert.True(e.Enforce(rule, "WebApp", "/api/transactions/getTransactions", "POST"));
Assert.False(e.Enforce(rule, "Admin", "/api/transactions/getTransactions", "POST"));
rule = new Dictionary<string, Dictionary<string, string>>
{
["CompanyData"] = new() { ["CompanyIsActive"] = "False", ["BusinessRole"] = "Role1" }
};
Assert.False(e.Enforce(rule, "WebApp", "/api/transactions/getTransactions", "POST"));
Assert.True(e.Enforce(rule, "Admin", "/api/transactions/getTransactions", "POST"));
}
[Fact]
public void TestAbacWithDynamicValueType()
{
Enforcer e = new(TestModelFixture.GetNewTestModel(
TestModelFixture.AbacWithDynamicValueTypeModelText,
TestModelFixture.AbacWithDynamicValueTypePolicyText));
var sub = new { Name = "bob" };
var obj1 = new { Object = "/data1", Property1 = "prop-1" };
var obj2 = new { Object = "/data2", Property2 = "prop-2" };
var obj3 = new { Object = "/data2", Property3 = "prop-3" };
Assert.True(e.Enforce(sub, obj1, "read"));
Assert.True(e.Enforce(sub, obj2, "read"));
Assert.False(e.Enforce(sub, obj3, "read"));
// Request again to test the cache hit logic.
Assert.True(e.Enforce(sub, obj1, "read"));
Assert.True(e.Enforce(sub, obj2, "read"));
Assert.False(e.Enforce(sub, obj3, "read"));
}
#if !NET452 && !NET461 && !NET462 && !NETSTANDARD
[Fact]
public void TestAbacJsonRequest()
{
Enforcer e = new(TestModelFixture.GetNewAbacModel());
JsonValue data1Json = new JsonValue("""{ "Name": "data1", "Owner": "alice"}""");
JsonValue data2Json = new JsonValue("""{ "Name": "data2", "Owner": "bob"}""");
Assert.True(e.Enforce("alice", data1Json, "read"));
Assert.True(e.Enforce("alice", data1Json, "write"));
Assert.False(e.Enforce("alice", data2Json, "read"));
Assert.False(e.Enforce("alice", data2Json, "write"));
Assert.False(e.Enforce("bob", data1Json, "read"));
Assert.False(e.Enforce("bob", data1Json, "write"));
Assert.True(e.Enforce("bob", data2Json, "read"));
Assert.True(e.Enforce("bob", data2Json, "write"));
e = new Enforcer(TestModelFixture.GetNewTestModel(
TestModelFixture.AbacNotUsingPolicyModelText,
TestModelFixture.AbacRuleEffectPolicyText));
Assert.True(e.Enforce("alice", data1Json, "read"));
Assert.True(e.Enforce("alice", data1Json, "write"));
Assert.False(e.Enforce("alice", data2Json, "read"));
Assert.False(e.Enforce("alice", data2Json, "write"));
e = new Enforcer(TestModelFixture.GetNewTestModel(
TestModelFixture.AbacRuleModelText,
TestModelFixture.AbacRulePolicyText));
JsonValue sub1Json = new JsonValue("""{ "Name": "alice", "Age": 16}""");
JsonValue sub2Json = new JsonValue("""{ "Name": "alice", "Age": 20}""");
JsonValue sub3Json = new JsonValue("""{ "Name": "alice", "Age": 65}""");
Assert.False(e.Enforce(sub1Json, "/data1", "read"));
Assert.False(e.Enforce(sub1Json, "/data2", "read"));
Assert.False(e.Enforce(sub1Json, "/data1", "write"));
Assert.True(e.Enforce(sub1Json, "/data2", "write"));
Assert.True(e.Enforce(sub2Json, "/data1", "read"));
Assert.False(e.Enforce(sub2Json, "/data2", "read"));
Assert.False(e.Enforce(sub2Json, "/data1", "write"));
Assert.True(e.Enforce(sub2Json, "/data2", "write"));
Assert.True(e.Enforce(sub3Json, "/data1", "read"));
Assert.False(e.Enforce(sub3Json, "/data2", "read"));
Assert.False(e.Enforce(sub3Json, "/data1", "write"));
Assert.False(e.Enforce(sub3Json, "/data2", "write"));
}
#endif
}