2024-07-12 13:36:09 -04:00
|
|
|
using System.Collections.ObjectModel;
|
|
|
|
using Serilog;
|
|
|
|
|
|
|
|
namespace TwitchChatTTS.Chat.Groups.Permissions
|
|
|
|
{
|
|
|
|
public class GroupPermissionManager : IGroupPermissionManager
|
|
|
|
{
|
|
|
|
private PermissionNode _root;
|
|
|
|
private ILogger _logger;
|
|
|
|
|
|
|
|
|
|
|
|
public GroupPermissionManager(ILogger logger)
|
|
|
|
{
|
|
|
|
_logger = logger;
|
|
|
|
_root = new PermissionNode(string.Empty, null, null);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public bool? CheckIfAllowed(string path)
|
|
|
|
{
|
2024-08-06 16:32:02 -04:00
|
|
|
var res = Get(path)!.Allow;
|
2024-07-12 13:36:09 -04:00
|
|
|
_logger.Debug($"Permission Node GET {path} = {res?.ToString() ?? "null"}");
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2024-08-06 15:29:29 -04:00
|
|
|
public bool? CheckIfDirectAllowed(string path)
|
|
|
|
{
|
2024-08-06 16:32:02 -04:00
|
|
|
var node = Get(path, nullIfMissing: true);
|
|
|
|
if (node == null)
|
|
|
|
return null;
|
|
|
|
|
|
|
|
var res = node.DirectAllow;
|
2024-08-06 15:29:29 -04:00
|
|
|
_logger.Debug($"Permission Node GET {path} = {res?.ToString() ?? "null"} [direct]");
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2024-08-04 19:46:10 -04:00
|
|
|
public bool? CheckIfAllowed(IEnumerable<string> groups, string path)
|
|
|
|
{
|
2024-08-06 18:50:45 -04:00
|
|
|
bool overall = false;
|
2024-08-04 19:46:10 -04:00
|
|
|
foreach (var group in groups)
|
|
|
|
{
|
2024-07-12 13:36:09 -04:00
|
|
|
var result = CheckIfAllowed($"{group}.{path}");
|
2024-08-06 16:32:02 -04:00
|
|
|
if (result == false)
|
2024-08-06 18:50:45 -04:00
|
|
|
return false;
|
|
|
|
if (result == true)
|
|
|
|
overall = true;
|
2024-07-12 13:36:09 -04:00
|
|
|
}
|
2024-08-06 18:50:45 -04:00
|
|
|
return overall ? true : null;
|
2024-07-12 13:36:09 -04:00
|
|
|
}
|
|
|
|
|
2024-08-06 15:29:29 -04:00
|
|
|
public bool? CheckIfDirectAllowed(IEnumerable<string> groups, string path)
|
|
|
|
{
|
|
|
|
bool overall = false;
|
|
|
|
foreach (var group in groups)
|
|
|
|
{
|
|
|
|
var result = CheckIfDirectAllowed($"{group}.{path}");
|
|
|
|
if (result == false)
|
|
|
|
return false;
|
|
|
|
if (result == true)
|
|
|
|
overall = true;
|
|
|
|
}
|
|
|
|
return overall ? true : null;
|
|
|
|
}
|
|
|
|
|
2024-07-12 13:36:09 -04:00
|
|
|
public void Clear()
|
|
|
|
{
|
2024-07-19 12:56:41 -04:00
|
|
|
_root.Clear();
|
2024-07-12 13:36:09 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
public bool Remove(string path)
|
|
|
|
{
|
|
|
|
var node = Get(path);
|
|
|
|
if (node == null || node.Parent == null)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
var parts = path.Split('.');
|
|
|
|
var last = parts.Last();
|
|
|
|
if (parts.Length > 1 && parts[parts.Length - 1] == node.Parent.Name || parts.Length == 1 && node.Parent.Name == null)
|
|
|
|
{
|
|
|
|
node.Parent.Remove(last);
|
|
|
|
_logger.Debug($"Permission Node REMOVE priv {path}");
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void Set(string path, bool? allow)
|
|
|
|
{
|
|
|
|
var node = Get(path, true);
|
2024-08-06 16:32:02 -04:00
|
|
|
node!.Allow = allow;
|
2024-07-12 13:36:09 -04:00
|
|
|
_logger.Debug($"Permission Node ADD {path} = {allow?.ToString() ?? "null"}");
|
|
|
|
}
|
|
|
|
|
2024-08-06 16:32:02 -04:00
|
|
|
private PermissionNode? Get(string path, bool edit = false, bool nullIfMissing = false)
|
2024-07-12 13:36:09 -04:00
|
|
|
{
|
2024-08-06 16:32:02 -04:00
|
|
|
return Get(_root, path.ToLower(), edit, nullIfMissing);
|
2024-07-12 13:36:09 -04:00
|
|
|
}
|
|
|
|
|
2024-08-06 16:32:02 -04:00
|
|
|
private PermissionNode? Get(PermissionNode node, string path, bool edit, bool nullIfMissing)
|
2024-07-12 13:36:09 -04:00
|
|
|
{
|
|
|
|
if (path.Length == 0)
|
|
|
|
return node;
|
2024-08-04 19:46:10 -04:00
|
|
|
|
2024-07-12 13:36:09 -04:00
|
|
|
var parts = path.Split('.');
|
|
|
|
var name = parts.First();
|
|
|
|
var next = node.Children?.FirstOrDefault(n => n.Name == name);
|
|
|
|
if (next == null)
|
|
|
|
{
|
|
|
|
if (!edit)
|
2024-08-06 16:32:02 -04:00
|
|
|
return nullIfMissing ? null : node;
|
2024-07-12 13:36:09 -04:00
|
|
|
|
|
|
|
next = new PermissionNode(name, node, null);
|
|
|
|
node.Add(next);
|
|
|
|
}
|
2024-08-06 16:32:02 -04:00
|
|
|
return Get(next, string.Join('.', parts.Skip(1)), edit, nullIfMissing);
|
2024-07-12 13:36:09 -04:00
|
|
|
}
|
|
|
|
|
2024-08-04 19:46:10 -04:00
|
|
|
private sealed class PermissionNode
|
2024-07-12 13:36:09 -04:00
|
|
|
{
|
2024-08-04 19:46:10 -04:00
|
|
|
public string Name { get; }
|
|
|
|
public bool? Allow
|
2024-07-12 13:36:09 -04:00
|
|
|
{
|
2024-08-04 19:46:10 -04:00
|
|
|
get
|
|
|
|
{
|
|
|
|
var current = this;
|
|
|
|
while (current._allow == null && current._parent != null)
|
|
|
|
current = current._parent;
|
|
|
|
return current._allow;
|
|
|
|
}
|
|
|
|
set => _allow = value;
|
2024-07-12 13:36:09 -04:00
|
|
|
}
|
2024-08-06 15:29:29 -04:00
|
|
|
public bool? DirectAllow { get => _allow; }
|
2024-07-12 13:36:09 -04:00
|
|
|
|
2024-08-04 19:46:10 -04:00
|
|
|
internal PermissionNode? Parent { get => _parent; }
|
|
|
|
public IList<PermissionNode>? Children { get => _children == null ? null : new ReadOnlyCollection<PermissionNode>(_children); }
|
2024-07-12 13:36:09 -04:00
|
|
|
|
2024-08-04 19:46:10 -04:00
|
|
|
private bool? _allow;
|
|
|
|
private PermissionNode? _parent;
|
|
|
|
private IList<PermissionNode>? _children;
|
2024-07-12 13:36:09 -04:00
|
|
|
|
|
|
|
|
2024-08-04 19:46:10 -04:00
|
|
|
public PermissionNode(string name, PermissionNode? parent, bool? allow)
|
|
|
|
{
|
|
|
|
Name = name;
|
|
|
|
_parent = parent;
|
|
|
|
_allow = allow;
|
|
|
|
}
|
2024-07-12 13:36:09 -04:00
|
|
|
|
2024-08-04 19:46:10 -04:00
|
|
|
internal void Add(PermissionNode child)
|
|
|
|
{
|
|
|
|
if (_children == null)
|
|
|
|
_children = new List<PermissionNode>();
|
|
|
|
_children.Add(child);
|
|
|
|
}
|
2024-07-19 12:56:41 -04:00
|
|
|
|
2024-08-04 19:46:10 -04:00
|
|
|
internal void Clear()
|
|
|
|
{
|
|
|
|
if (_children != null)
|
|
|
|
_children.Clear();
|
|
|
|
}
|
2024-07-12 13:36:09 -04:00
|
|
|
|
2024-08-04 19:46:10 -04:00
|
|
|
public void Remove(string name)
|
2024-07-12 13:36:09 -04:00
|
|
|
{
|
2024-08-04 19:46:10 -04:00
|
|
|
if (_children == null || !_children.Any())
|
|
|
|
return;
|
|
|
|
|
|
|
|
for (var i = 0; i < _children.Count; i++)
|
2024-07-12 13:36:09 -04:00
|
|
|
{
|
2024-08-04 19:46:10 -04:00
|
|
|
if (_children[i].Name == name)
|
|
|
|
{
|
|
|
|
_children.RemoveAt(i);
|
|
|
|
break;
|
|
|
|
}
|
2024-07-12 13:36:09 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|