source: binary-improvements2/WebServer/src/Permissions/AdminWebModules.cs@ 420

Last change on this file since 420 was 418, checked in by alloc, 21 months ago

Refactored API authorization to support per-HTTP-method permission levels

File size: 4.9 KB
Line 
1using System.Collections.Generic;
2using System.Xml;
3
4namespace Webserver.Permissions {
5 public class AdminWebModules : AdminSectionAbs {
6 public static AdminWebModules Instance { get; private set; }
7
8 public AdminWebModules (AdminTools _parent) : base (_parent, "webmodules") {
9 Instance = this;
10 }
11
12 private readonly Dictionary<string, WebModule> modules = new CaseInsensitiveStringDictionary<WebModule> ();
13
14
15#region IO
16
17 public override void Clear () {
18 modules.Clear ();
19 }
20
21 protected override void ParseElement (XmlElement _childElement) {
22 if (WebModule.TryParse (_childElement, out WebModule webModule)) {
23 modules [webModule.Name] = webModule;
24 }
25 }
26
27 public override void Save (XmlElement _root) {
28 XmlElement modulesElement = _root.AddXmlElement (SectionTypeName);
29 // modulesElement.AddXmlComment (" <module name=\"adminuser1\" secret=\"supersecrettoken\" permission_level=\"0\" /> ");
30
31 foreach ((string _, WebModule module) in modules) {
32 module.ToXml (modulesElement);
33 }
34 }
35
36#endregion
37
38
39#region Runtime interaction
40
41
42 public void AddModule (string _module, int _permissionLevel) {
43 WebModule p = new WebModule (_module, _permissionLevel, false);
44 lock (this) {
45 allModulesList.Clear ();
46
47 modules [_module] = p;
48 Parent.Save ();
49 }
50 }
51
52 public bool RemoveModule (string _module) {
53 lock (this) {
54 allModulesList.Clear ();
55
56 bool removed = modules.Remove (_module);
57 if (removed) {
58 Parent.Save ();
59 }
60
61 return removed;
62 }
63 }
64
65 public List<WebModule> GetModules () {
66 lock (this) {
67 if (allModulesList.Count != 0) {
68 return allModulesList;
69 }
70
71 foreach ((string moduleName, WebModule moduleDefaultPerm) in knownModules) {
72 allModulesList.Add (modules.TryGetValue (moduleName, out WebModule modulePermission)
73 ? modulePermission
74 : moduleDefaultPerm);
75 }
76
77 return allModulesList;
78 }
79 }
80
81#endregion
82
83 public readonly struct WebModule {
84 public readonly string Name;
85 public readonly int PermissionLevel;
86 public readonly bool IsDefault;
87
88 public WebModule (string _name, int _permissionLevel, bool _isDefault) {
89 Name = _name;
90 PermissionLevel = _permissionLevel;
91 IsDefault = _isDefault;
92 }
93
94 public void ToXml (XmlElement _parent) {
95 _parent.AddXmlElement ("module")
96 .SetAttrib ("name", Name)
97 .SetAttrib ("permission_level", PermissionLevel.ToString ());
98 }
99
100 public static bool TryParse (XmlElement _element, out WebModule _result) {
101 _result = default;
102
103
104 if (!_element.TryGetAttribute ("name", out string name)) {
105 Log.Warning ($"[Web] [Perms] Ignoring module-entry because of missing 'name' attribute: {_element.OuterXml}");
106 return false;
107 }
108
109 if (!_element.TryGetAttribute ("permission_level", out string permissionLevelString)) {
110 Log.Warning ($"[Web] [Perms] Ignoring module-entry because of missing 'permission_level' attribute: {_element.OuterXml}");
111 return false;
112 }
113
114 if (!int.TryParse (permissionLevelString, out int permissionLevel)) {
115 Log.Warning (
116 $"[Web] [Perms] Ignoring module-entry because of invalid (non-numeric) value for 'permission_level' attribute: {_element.OuterXml}");
117 return false;
118 }
119
120 _result = new WebModule (name, permissionLevel, false);
121 return true;
122 }
123 }
124
125
126#region Specials
127
128 /// <summary>
129 /// Contains all registered modules and their default permission
130 /// </summary>
131 private readonly Dictionary<string, WebModule> knownModules = new CaseInsensitiveStringDictionary<WebModule> ();
132
133 /// <summary>
134 /// Public list of all modules, both those with custom permissions as well as those that do not with their default permission
135 /// </summary>
136 private readonly List<WebModule> allModulesList = new List<WebModule> ();
137
138 public void AddKnownModule (string _module, int _defaultPermission) {
139 if (string.IsNullOrEmpty (_module)) {
140 return;
141 }
142
143 WebModule p = new WebModule (_module, _defaultPermission, true);
144
145 lock (this) {
146 allModulesList.Clear ();
147 knownModules [_module] = p;
148 }
149 }
150
151 public bool IsKnownModule (string _module) {
152 if (string.IsNullOrEmpty (_module)) {
153 return false;
154 }
155
156 lock (this) {
157 return knownModules.ContainsKey (_module);
158 }
159 }
160
161 public bool ModuleAllowedWithLevel (string _module, int _level) {
162 WebModule permInfo = GetModule (_module)!.Value;
163 return permInfo.PermissionLevel >= _level;
164 }
165
166 public WebModule? GetModule (string _module, bool _returnDefaults = true) {
167 if (modules.TryGetValue (_module, out WebModule result)) {
168 return result;
169 }
170
171 if (!_returnDefaults) {
172 return null;
173 }
174
175 return knownModules.TryGetValue (_module, out result) ? result : defaultModulePermission;
176 }
177
178 private readonly WebModule defaultModulePermission = new WebModule ("", 0, true);
179
180#endregion
181 }
182}
Note: See TracBrowser for help on using the repository browser.