source: binary-improvements/MapRendering/Web/WebPermissions.cs@ 420

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

A21 preparations.
NOT COMPATIBLE WITH A20 ANYMORE!

File size: 11.1 KB
Line 
1using System.Collections.Generic;
2using System.Collections.ObjectModel;
3using System.IO;
4using System.Xml;
5
6namespace AllocsFixes.NetConnections.Servers.Web {
7 public class WebPermissions {
8 private const string PERMISSIONS_FILE = "webpermissions.xml";
9 private static WebPermissions instance;
10 private readonly WebModulePermission defaultModulePermission = new WebModulePermission ("", 0);
11
12 private readonly Dictionary<string, WebModulePermission> knownModules =
13 new CaseInsensitiveStringDictionary<WebModulePermission> ();
14
15 private readonly Dictionary<string, AdminToken> admintokens = new CaseInsensitiveStringDictionary<AdminToken> ();
16 private FileSystemWatcher fileWatcher;
17
18 private readonly Dictionary<string, WebModulePermission> modules = new CaseInsensitiveStringDictionary<WebModulePermission> ();
19
20 private WebPermissions () {
21 allModulesList = new List<WebModulePermission> ();
22 allModulesListRO = new ReadOnlyCollection<WebModulePermission> (allModulesList);
23 Directory.CreateDirectory (GetFilePath ());
24 InitFileWatcher ();
25 Load ();
26 }
27
28 public static WebPermissions Instance {
29 get {
30 lock (typeof (WebPermissions)) {
31 return instance ?? (instance = new WebPermissions ());
32 }
33 }
34 }
35
36 public bool ModuleAllowedWithLevel (string _module, int _level) {
37 WebModulePermission permInfo = GetModulePermission (_module);
38 return permInfo.permissionLevel >= _level;
39 }
40
41 public AdminToken GetWebAdmin (string _name, string _token) {
42 if (IsAdmin (_name) && admintokens [_name].token == _token) {
43 return admintokens [_name];
44 }
45
46 return null;
47 }
48
49 public WebModulePermission GetModulePermission (string _module) {
50 if (modules.TryGetValue (_module, out WebModulePermission result)) {
51 return result;
52 }
53
54 if (knownModules.TryGetValue (_module, out result)) {
55 return result;
56 }
57
58 return defaultModulePermission;
59 }
60
61
62 // Admins
63 public void AddAdmin (string _name, string _token, int _permissionLevel, bool _save = true) {
64 AdminToken c = new AdminToken (_name, _token, _permissionLevel);
65 lock (this) {
66 admintokens [_name] = c;
67 if (_save) {
68 Save ();
69 }
70 }
71 }
72
73 public void RemoveAdmin (string _name, bool _save = true) {
74 lock (this) {
75 admintokens.Remove (_name);
76 if (_save) {
77 Save ();
78 }
79 }
80 }
81
82 public bool IsAdmin (string _name) {
83 return admintokens.ContainsKey (_name);
84 }
85
86 public AdminToken[] GetAdmins () {
87 AdminToken[] result = new AdminToken[admintokens.Count];
88 admintokens.CopyValuesTo (result);
89 return result;
90 }
91
92
93 // Commands
94 public void AddModulePermission (string _module, int _permissionLevel, bool _save = true) {
95 WebModulePermission p = new WebModulePermission (_module, _permissionLevel);
96 lock (this) {
97 allModulesList.Clear ();
98 modules [_module] = p;
99 if (_save) {
100 Save ();
101 }
102 }
103 }
104
105 public void AddKnownModule (string _module, int _defaultPermission) {
106 if (string.IsNullOrEmpty (_module)) {
107 return;
108 }
109
110 WebModulePermission p = new WebModulePermission (_module, _defaultPermission);
111
112 lock (this) {
113 allModulesList.Clear ();
114 knownModules [_module] = p;
115 }
116 }
117
118 public bool IsKnownModule (string _module) {
119 if (string.IsNullOrEmpty (_module)) {
120 return false;
121 }
122
123 lock (this) {
124 return knownModules.ContainsKey (_module);
125 }
126
127 }
128
129 public void RemoveModulePermission (string _module, bool _save = true) {
130 lock (this) {
131 allModulesList.Clear ();
132 modules.Remove (_module);
133 if (_save) {
134 Save ();
135 }
136 }
137 }
138
139 private readonly List<WebModulePermission> allModulesList;
140 private readonly ReadOnlyCollection<WebModulePermission> allModulesListRO;
141
142 public IList<WebModulePermission> GetModules () {
143 if (allModulesList.Count == 0) {
144 foreach (KeyValuePair<string, WebModulePermission> kvp in knownModules) {
145 if (modules.ContainsKey (kvp.Key)) {
146 allModulesList.Add (modules [kvp.Key]);
147 } else {
148 allModulesList.Add (kvp.Value);
149 }
150 }
151 }
152
153 return allModulesListRO;
154 }
155
156
157 //IO Tasks
158
159 private void InitFileWatcher () {
160 fileWatcher = new FileSystemWatcher (GetFilePath (), GetFileName ());
161 fileWatcher.Changed += OnFileChanged;
162 fileWatcher.Created += OnFileChanged;
163 fileWatcher.Deleted += OnFileChanged;
164 fileWatcher.EnableRaisingEvents = true;
165 }
166
167 private void OnFileChanged (object _source, FileSystemEventArgs _e) {
168 Log.Out ("Reloading " + PERMISSIONS_FILE);
169 Load ();
170 }
171
172 private string GetFilePath () {
173 return GamePrefs.GetString (EnumUtils.Parse<EnumGamePrefs> (nameof(EnumGamePrefs.SaveGameFolder)));
174 }
175
176 private string GetFileName () {
177 return PERMISSIONS_FILE;
178 }
179
180 private string GetFullPath () {
181 return GetFilePath () + "/" + GetFileName ();
182 }
183
184 public void Load () {
185 admintokens.Clear ();
186 modules.Clear ();
187
188 if (!File.Exists (GetFullPath ())) {
189 Log.Out ($"Permissions file '{GetFileName ()}' not found, creating.");
190 Save ();
191 return;
192 }
193
194 Log.Out ($"Loading permissions file at '{GetFullPath ()}'");
195
196 XmlDocument xmlDoc = new XmlDocument ();
197
198 try {
199 xmlDoc.Load (GetFullPath ());
200 } catch (XmlException e) {
201 Log.Error ("Failed loading permissions file: " + e.Message);
202 return;
203 }
204
205 XmlNode adminToolsNode = xmlDoc.DocumentElement;
206
207 if (adminToolsNode == null) {
208 Log.Error ("Failed loading permissions file: No DocumentElement found");
209 return;
210 }
211
212 foreach (XmlNode childNode in adminToolsNode.ChildNodes) {
213 if (childNode.Name == "admintokens") {
214 foreach (XmlNode subChild in childNode.ChildNodes) {
215 if (subChild.NodeType == XmlNodeType.Comment) {
216 continue;
217 }
218
219 if (subChild.NodeType != XmlNodeType.Element) {
220 Log.Warning ("Unexpected XML node found in 'admintokens' section: " + subChild.OuterXml);
221 continue;
222 }
223
224 XmlElement lineItem = (XmlElement) subChild;
225
226 if (!lineItem.HasAttribute ("name")) {
227 Log.Warning ("Ignoring admintoken-entry because of missing 'name' attribute: " +
228 subChild.OuterXml);
229 continue;
230 }
231
232 if (!lineItem.HasAttribute ("token")) {
233 Log.Warning ("Ignoring admintoken-entry because of missing 'token' attribute: " +
234 subChild.OuterXml);
235 continue;
236 }
237
238 if (!lineItem.HasAttribute ("permission_level")) {
239 Log.Warning ("Ignoring admintoken-entry because of missing 'permission_level' attribute: " +
240 subChild.OuterXml);
241 continue;
242 }
243
244 string name = lineItem.GetAttribute ("name");
245 string token = lineItem.GetAttribute ("token");
246 int permissionLevel;
247 if (!int.TryParse (lineItem.GetAttribute ("permission_level"), out permissionLevel)) {
248 Log.Warning (
249 "Ignoring admintoken-entry because of invalid (non-numeric) value for 'permission_level' attribute: " +
250 subChild.OuterXml);
251 continue;
252 }
253
254 AddAdmin (name, token, permissionLevel, false);
255 }
256 }
257
258 if (childNode.Name == "permissions") {
259 foreach (XmlNode subChild in childNode.ChildNodes) {
260 if (subChild.NodeType == XmlNodeType.Comment) {
261 continue;
262 }
263
264 if (subChild.NodeType != XmlNodeType.Element) {
265 Log.Warning ("Unexpected XML node found in 'permissions' section: " + subChild.OuterXml);
266 continue;
267 }
268
269 XmlElement lineItem = (XmlElement) subChild;
270
271 if (!lineItem.HasAttribute ("module")) {
272 Log.Warning ("Ignoring permission-entry because of missing 'module' attribute: " +
273 subChild.OuterXml);
274 continue;
275 }
276
277 if (!lineItem.HasAttribute ("permission_level")) {
278 Log.Warning ("Ignoring permission-entry because of missing 'permission_level' attribute: " +
279 subChild.OuterXml);
280 continue;
281 }
282
283 int permissionLevel;
284 if (!int.TryParse (lineItem.GetAttribute ("permission_level"), out permissionLevel)) {
285 Log.Warning (
286 "Ignoring permission-entry because of invalid (non-numeric) value for 'permission_level' attribute: " +
287 subChild.OuterXml);
288 continue;
289 }
290
291 AddModulePermission (lineItem.GetAttribute ("module"), permissionLevel, false);
292 }
293 }
294 }
295
296 Log.Out ("Loading permissions file done.");
297 }
298
299 public void Save () {
300 fileWatcher.EnableRaisingEvents = false;
301
302 using (StreamWriter sw = new StreamWriter (GetFullPath ())) {
303 sw.WriteLine ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
304 sw.WriteLine ("<webpermissions>");
305 sw.WriteLine ();
306 sw.WriteLine (" <admintokens>");
307 sw.WriteLine (
308 " <!-- <token name=\"adminuser1\" token=\"supersecrettoken\" permission_level=\"0\" /> -->");
309 foreach (KeyValuePair<string, AdminToken> kvp in admintokens) {
310 sw.WriteLine (" <token name=\"{0}\" token=\"{1}\" permission_level=\"{2}\" />", kvp.Value.name,
311 kvp.Value.token, kvp.Value.permissionLevel);
312 }
313
314 sw.WriteLine (" </admintokens>");
315 sw.WriteLine ();
316 sw.WriteLine (" <permissions>");
317 foreach (KeyValuePair<string, WebModulePermission> kvp in modules) {
318 sw.WriteLine (" <permission module=\"{0}\" permission_level=\"{1}\" />", kvp.Value.module,
319 kvp.Value.permissionLevel);
320 }
321
322 sw.WriteLine (" <!-- <permission module=\"web.map\" permission_level=\"1000\" /> -->");
323 sw.WriteLine ();
324 sw.WriteLine (" <!-- <permission module=\"webapi.getlog\" permission_level=\"0\" /> -->");
325 sw.WriteLine (
326 " <!-- <permission module=\"webapi.executeconsolecommand\" permission_level=\"0\" /> -->");
327 sw.WriteLine ();
328 sw.WriteLine (" <!-- <permission module=\"webapi.getstats\" permission_level=\"1000\" /> -->");
329 sw.WriteLine (" <!-- <permission module=\"webapi.getplayersonline\" permission_level=\"1000\" /> -->");
330 sw.WriteLine ();
331 sw.WriteLine (
332 " <!-- <permission module=\"webapi.getplayerslocation\" permission_level=\"1000\" /> -->");
333 sw.WriteLine (" <!-- <permission module=\"webapi.viewallplayers\" permission_level=\"1\" /> -->");
334 sw.WriteLine ();
335 sw.WriteLine (" <!-- <permission module=\"webapi.getlandclaims\" permission_level=\"1000\" /> -->");
336 sw.WriteLine (" <!-- <permission module=\"webapi.viewallclaims\" permission_level=\"1\" /> -->");
337 sw.WriteLine ();
338 sw.WriteLine (" <!-- <permission module=\"webapi.getplayerinventory\" permission_level=\"1\" /> -->");
339 sw.WriteLine ();
340 sw.WriteLine (" <!-- <permission module=\"webapi.gethostilelocation\" permission_level=\"1\" /> -->");
341 sw.WriteLine (" <!-- <permission module=\"webapi.getanimalslocation\" permission_level=\"1\" /> -->");
342 sw.WriteLine (" </permissions>");
343 sw.WriteLine ();
344 sw.WriteLine ("</webpermissions>");
345
346 sw.Flush ();
347 sw.Close ();
348 }
349
350 fileWatcher.EnableRaisingEvents = true;
351 }
352
353
354 public class AdminToken {
355 public string name;
356 public int permissionLevel;
357 public string token;
358
359 public AdminToken (string _name, string _token, int _permissionLevel) {
360 name = _name;
361 token = _token;
362 permissionLevel = _permissionLevel;
363 }
364 }
365
366 public struct WebModulePermission {
367 public string module;
368 public int permissionLevel;
369
370 public WebModulePermission (string _module, int _permissionLevel) {
371 module = _module;
372 permissionLevel = _permissionLevel;
373 }
374 }
375 }
376}
Note: See TracBrowser for help on using the repository browser.