using System.Collections.Generic; using System.Xml; namespace Webserver.Permissions { public class AdminWebModules : AdminSectionAbs { public static AdminWebModules Instance { get; private set; } public AdminWebModules (AdminTools _parent) : base (_parent, "webmodules") { Instance = this; } private readonly Dictionary modules = new CaseInsensitiveStringDictionary (); #region IO public override void Clear () { modules.Clear (); } protected override void ParseElement (XmlElement _childElement) { if (WebModule.TryParse (_childElement, out WebModule webModule)) { modules [webModule.Name] = webModule; } } public override void Save (XmlElement _root) { XmlElement modulesElement = _root.AddXmlElement (SectionTypeName); // modulesElement.AddXmlComment (" "); foreach ((string _, WebModule module) in modules) { module.ToXml (modulesElement); } } #endregion #region Runtime interaction public void AddModule (string _module, int _permissionLevel) { WebModule p = new WebModule (_module, _permissionLevel, false); lock (this) { allModulesList.Clear (); modules [_module] = p; Parent.Save (); } } public bool RemoveModule (string _module) { lock (this) { allModulesList.Clear (); bool removed = modules.Remove (_module); if (removed) { Parent.Save (); } return removed; } } public List GetModules () { lock (this) { if (allModulesList.Count != 0) { return allModulesList; } foreach ((string moduleName, WebModule moduleDefaultPerm) in knownModules) { allModulesList.Add (modules.TryGetValue (moduleName, out WebModule modulePermission) ? modulePermission : moduleDefaultPerm); } return allModulesList; } } #endregion public readonly struct WebModule { public readonly string Name; public readonly int PermissionLevel; public readonly bool IsDefault; public WebModule (string _name, int _permissionLevel, bool _isDefault) { Name = _name; PermissionLevel = _permissionLevel; IsDefault = _isDefault; } public void ToXml (XmlElement _parent) { _parent.AddXmlElement ("module") .SetAttrib ("name", Name) .SetAttrib ("permission_level", PermissionLevel.ToString ()); } public static bool TryParse (XmlElement _element, out WebModule _result) { _result = default; if (!_element.TryGetAttribute ("name", out string name)) { Log.Warning ($"[Web] [Perms] Ignoring module-entry because of missing 'name' attribute: {_element.OuterXml}"); return false; } if (!_element.TryGetAttribute ("permission_level", out string permissionLevelString)) { Log.Warning ($"[Web] [Perms] Ignoring module-entry because of missing 'permission_level' attribute: {_element.OuterXml}"); return false; } if (!int.TryParse (permissionLevelString, out int permissionLevel)) { Log.Warning ( $"[Web] [Perms] Ignoring module-entry because of invalid (non-numeric) value for 'permission_level' attribute: {_element.OuterXml}"); return false; } _result = new WebModule (name, permissionLevel, false); return true; } } #region Specials /// /// Contains all registered modules and their default permission /// private readonly Dictionary knownModules = new CaseInsensitiveStringDictionary (); /// /// Public list of all modules, both those with custom permissions as well as those that do not with their default permission /// private readonly List allModulesList = new List (); public void AddKnownModule (string _module, int _defaultPermission) { if (string.IsNullOrEmpty (_module)) { return; } WebModule p = new WebModule (_module, _defaultPermission, true); lock (this) { allModulesList.Clear (); knownModules [_module] = p; } } public bool IsKnownModule (string _module) { if (string.IsNullOrEmpty (_module)) { return false; } lock (this) { return knownModules.ContainsKey (_module); } } public bool ModuleAllowedWithLevel (string _module, int _level) { WebModule permInfo = GetModule (_module)!.Value; return permInfo.PermissionLevel >= _level; } public WebModule? GetModule (string _module, bool _returnDefaults = true) { if (modules.TryGetValue (_module, out WebModule result)) { return result; } if (!_returnDefaults) { return null; } return knownModules.TryGetValue (_module, out result) ? result : defaultModulePermission; } private readonly WebModule defaultModulePermission = new WebModule ("", 0, true); #endregion } }