blob: b5877b6dac40066886dc7b17df09594081496043 [file] [log] [blame]
#nullable enable
using System;
using System.Collections.Generic;
using System.Linq;
using Casbin.Config;
using Casbin.Util;
namespace Casbin.Model;
public class DefaultSections : ISections
{
private static readonly IDictionary<string, string> s_sectionNameMap = new Dictionary<string, string>
{
{ PermConstants.Section.RequestSection, PermConstants.Section.RequestSectionName },
{ PermConstants.Section.PolicySection, PermConstants.Section.PolicySectionName },
{ PermConstants.Section.RoleSection, PermConstants.Section.RoleSectionName },
{ PermConstants.Section.PolicyEffectSection, PermConstants.Section.PolicyEffectSectionName },
{ PermConstants.Section.MatcherSection, PermConstants.Section.MatcherSectionName }
};
private readonly IDictionary<string, IDictionary<string, IReadOnlyAssertion>> _assertionsMap
= new Dictionary<string, IDictionary<string, IReadOnlyAssertion>>();
public bool ContainsSection(string section) => _assertionsMap.ContainsKey(section);
public bool AddSection(string section, string key, string value)
{
if (string.IsNullOrWhiteSpace(value))
{
throw new ArgumentNullException(nameof(value));
}
Assertion assertion = section switch
{
PermConstants.Section.RequestSection => new RequestAssertion { Key = key, Value = value },
PermConstants.Section.PolicySection => new PolicyAssertion { Key = key, Value = value },
PermConstants.Section.RoleSection => new RoleAssertion { Key = key, Value = value },
PermConstants.Section.PolicyEffectSection => new PolicyEffectAssertion { Key = key, Value = value },
PermConstants.Section.MatcherSection => new MatcherAssertion { Key = key, Value = value },
_ => throw new ArgumentOutOfRangeException(nameof(section), section, null)
};
if (section.Equals(PermConstants.Section.RequestSection)
|| section.Equals(PermConstants.Section.PolicySection)
|| section.Equals(PermConstants.Section.RoleSection))
{
string[] tokens = assertion.Value.Split(PermConstants.PolicySeparatorChar)
.Select(t => t.Trim()).ToArray();
if (tokens.Length is not 0)
{
Dictionary<string, int> tokenDic = new();
for (int i = 0; i < tokens.Length; i++)
{
string token = tokens[i].Trim();
if (token is "_")
{
token = i.ToString();
}
tokenDic.Add(token, i);
}
assertion.Tokens = tokenDic;
}
}
else
{
// ReSharper disable once InvokeAsExtensionMethod
assertion.Value = StringUtil.RemoveComments(assertion.Value);
}
if (_assertionsMap.TryGetValue(section, out IDictionary<string, IReadOnlyAssertion>? assertions))
{
// TryAdd is not supported in .NET 4.5
if (assertions.ContainsKey(key))
{
return false;
}
assertions.Add(key, assertion);
return true;
}
Dictionary<string, IReadOnlyAssertion> assertionMap = new() { [key] = assertion };
_assertionsMap.Add(section, assertionMap);
return true;
}
public T GetAssertion<T>(string section, string type)
where T : Assertion
{
if (_assertionsMap.TryGetValue(section, out IDictionary<string, IReadOnlyAssertion>? assertions) is false)
{
throw new ArgumentOutOfRangeException(nameof(section), section, null);
}
if (assertions.TryGetValue(type, out IReadOnlyAssertion? assertion) is false)
{
throw new ArgumentOutOfRangeException(nameof(type), type, null);
}
return (T)assertion;
}
public bool TryGetAssertion<T>(string section, string type, out T? outAssertion)
where T : Assertion
{
if (_assertionsMap.TryGetValue(section, out IDictionary<string, IReadOnlyAssertion>? assertions) is false)
{
outAssertion = default;
return false;
}
if (assertions.TryGetValue(type, out IReadOnlyAssertion? assertion) is false)
{
outAssertion = default;
return false;
}
outAssertion = assertion as T;
return outAssertion is not null;
}
public IDictionary<string, T> GetAssertions<T>(string section)
where T : Assertion
{
if (_assertionsMap.TryGetValue(section, out IDictionary<string, IReadOnlyAssertion>? assertions) is false)
{
throw new ArgumentOutOfRangeException(nameof(section), section, null);
}
return assertions.ToDictionary(kv => kv.Key, kv => (T)kv.Value);
}
public void LoadSection(IConfig config, string section)
{
int i = 1;
while (true)
{
string key = string.Concat(section, GetKeySuffix(i));
if (LoadAssertion(config, section, key) is false)
{
break;
}
i++;
}
}
private bool LoadAssertion(IConfig config, string section, string key)
{
if (s_sectionNameMap.TryGetValue(section, out string? sectionName) is false)
{
return false;
}
string value = config.GetString($"{sectionName}::{key}");
return !string.IsNullOrWhiteSpace(value) && AddSection(section, key, value);
}
private static string GetKeySuffix(int i) => i == 1 ? string.Empty : i.ToString();
}