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
RevLine 
[253]1using System.Collections.Generic;
[332]2using System.Collections.ObjectModel;
[253]3using System.IO;
4using System.Xml;
5
[325]6namespace AllocsFixes.NetConnections.Servers.Web {
[253]7 public class WebPermissions {
[325]8 private const string PERMISSIONS_FILE = "webpermissions.xml";
9 private static WebPermissions instance;
10 private readonly WebModulePermission defaultModulePermission = new WebModulePermission ("", 0);
[253]11
[325]12 private readonly Dictionary<string, WebModulePermission> knownModules =
[332]13 new CaseInsensitiveStringDictionary<WebModulePermission> ();
[325]14
[326]15 private readonly Dictionary<string, AdminToken> admintokens = new CaseInsensitiveStringDictionary<AdminToken> ();
[325]16 private FileSystemWatcher fileWatcher;
17
[326]18 private readonly Dictionary<string, WebModulePermission> modules = new CaseInsensitiveStringDictionary<WebModulePermission> ();
[325]19
[372]20 private WebPermissions () {
[332]21 allModulesList = new List<WebModulePermission> ();
22 allModulesListRO = new ReadOnlyCollection<WebModulePermission> (allModulesList);
[325]23 Directory.CreateDirectory (GetFilePath ());
24 InitFileWatcher ();
25 Load ();
26 }
27
[253]28 public static WebPermissions Instance {
29 get {
[325]30 lock (typeof (WebPermissions)) {
[372]31 return instance ?? (instance = new WebPermissions ());
[253]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 }
[325]45
46 return null;
[253]47 }
48
49 public WebModulePermission GetModulePermission (string _module) {
[372]50 if (modules.TryGetValue (_module, out WebModulePermission result)) {
[326]51 return result;
[253]52 }
[325]53
[332]54 if (knownModules.TryGetValue (_module, out result)) {
55 return result;
56 }
57
[253]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];
[326]88 admintokens.CopyValuesTo (result);
[253]89 return result;
90 }
91
[325]92
[253]93 // Commands
94 public void AddModulePermission (string _module, int _permissionLevel, bool _save = true) {
[326]95 WebModulePermission p = new WebModulePermission (_module, _permissionLevel);
[253]96 lock (this) {
[332]97 allModulesList.Clear ();
[253]98 modules [_module] = p;
99 if (_save) {
100 Save ();
101 }
102 }
103 }
104
[279]105 public void AddKnownModule (string _module, int _defaultPermission) {
[326]106 if (string.IsNullOrEmpty (_module)) {
107 return;
108 }
[332]109
110 WebModulePermission p = new WebModulePermission (_module, _defaultPermission);
[325]111
[326]112 lock (this) {
[332]113 allModulesList.Clear ();
114 knownModules [_module] = p;
[253]115 }
116 }
117
118 public bool IsKnownModule (string _module) {
[326]119 if (string.IsNullOrEmpty (_module)) {
120 return false;
[253]121 }
[325]122
[326]123 lock (this) {
124 return knownModules.ContainsKey (_module);
125 }
126
[253]127 }
[325]128
[253]129 public void RemoveModulePermission (string _module, bool _save = true) {
130 lock (this) {
[332]131 allModulesList.Clear ();
[326]132 modules.Remove (_module);
[253]133 if (_save) {
134 Save ();
135 }
136 }
137 }
138
[332]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 }
[253]150 }
151 }
152
[332]153 return allModulesListRO;
[253]154 }
155
[325]156
[253]157 //IO Tasks
158
159 private void InitFileWatcher () {
160 fileWatcher = new FileSystemWatcher (GetFilePath (), GetFileName ());
[325]161 fileWatcher.Changed += OnFileChanged;
162 fileWatcher.Created += OnFileChanged;
163 fileWatcher.Deleted += OnFileChanged;
[253]164 fileWatcher.EnableRaisingEvents = true;
165 }
166
[351]167 private void OnFileChanged (object _source, FileSystemEventArgs _e) {
[253]168 Log.Out ("Reloading " + PERMISSIONS_FILE);
169 Load ();
170 }
171
172 private string GetFilePath () {
[420]173 return GamePrefs.GetString (EnumUtils.Parse<EnumGamePrefs> (nameof(EnumGamePrefs.SaveGameFolder)));
[253]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 () {
[326]185 admintokens.Clear ();
186 modules.Clear ();
[253]187
[369]188 if (!File.Exists (GetFullPath ())) {
[372]189 Log.Out ($"Permissions file '{GetFileName ()}' not found, creating.");
[253]190 Save ();
191 return;
192 }
193
[372]194 Log.Out ($"Loading permissions file at '{GetFullPath ()}'");
[253]195
196 XmlDocument xmlDoc = new XmlDocument ();
197
198 try {
199 xmlDoc.Load (GetFullPath ());
200 } catch (XmlException e) {
[326]201 Log.Error ("Failed loading permissions file: " + e.Message);
[253]202 return;
203 }
204
205 XmlNode adminToolsNode = xmlDoc.DocumentElement;
206
[326]207 if (adminToolsNode == null) {
208 Log.Error ("Failed loading permissions file: No DocumentElement found");
209 return;
210 }
211
[253]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 }
[325]218
[253]219 if (subChild.NodeType != XmlNodeType.Element) {
220 Log.Warning ("Unexpected XML node found in 'admintokens' section: " + subChild.OuterXml);
221 continue;
222 }
223
[325]224 XmlElement lineItem = (XmlElement) subChild;
[253]225
226 if (!lineItem.HasAttribute ("name")) {
[325]227 Log.Warning ("Ignoring admintoken-entry because of missing 'name' attribute: " +
228 subChild.OuterXml);
[253]229 continue;
230 }
231
232 if (!lineItem.HasAttribute ("token")) {
[325]233 Log.Warning ("Ignoring admintoken-entry because of missing 'token' attribute: " +
234 subChild.OuterXml);
[253]235 continue;
236 }
237
238 if (!lineItem.HasAttribute ("permission_level")) {
[325]239 Log.Warning ("Ignoring admintoken-entry because of missing 'permission_level' attribute: " +
240 subChild.OuterXml);
[253]241 continue;
242 }
243
244 string name = lineItem.GetAttribute ("name");
245 string token = lineItem.GetAttribute ("token");
[326]246 int permissionLevel;
[253]247 if (!int.TryParse (lineItem.GetAttribute ("permission_level"), out permissionLevel)) {
[325]248 Log.Warning (
249 "Ignoring admintoken-entry because of invalid (non-numeric) value for 'permission_level' attribute: " +
250 subChild.OuterXml);
[253]251 continue;
252 }
253
[325]254 AddAdmin (name, token, permissionLevel, false);
[253]255 }
256 }
257
258 if (childNode.Name == "permissions") {
259 foreach (XmlNode subChild in childNode.ChildNodes) {
260 if (subChild.NodeType == XmlNodeType.Comment) {
261 continue;
262 }
[325]263
[253]264 if (subChild.NodeType != XmlNodeType.Element) {
265 Log.Warning ("Unexpected XML node found in 'permissions' section: " + subChild.OuterXml);
266 continue;
267 }
268
[325]269 XmlElement lineItem = (XmlElement) subChild;
[253]270
271 if (!lineItem.HasAttribute ("module")) {
[325]272 Log.Warning ("Ignoring permission-entry because of missing 'module' attribute: " +
273 subChild.OuterXml);
[253]274 continue;
275 }
[325]276
[253]277 if (!lineItem.HasAttribute ("permission_level")) {
[325]278 Log.Warning ("Ignoring permission-entry because of missing 'permission_level' attribute: " +
279 subChild.OuterXml);
[253]280 continue;
281 }
[325]282
[326]283 int permissionLevel;
[253]284 if (!int.TryParse (lineItem.GetAttribute ("permission_level"), out permissionLevel)) {
[325]285 Log.Warning (
286 "Ignoring permission-entry because of invalid (non-numeric) value for 'permission_level' attribute: " +
287 subChild.OuterXml);
[253]288 continue;
289 }
290
[326]291 AddModulePermission (lineItem.GetAttribute ("module"), permissionLevel, false);
[253]292 }
293 }
294 }
295
296 Log.Out ("Loading permissions file done.");
297 }
298
299 public void Save () {
300 fileWatcher.EnableRaisingEvents = false;
301
[325]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\" /> -->");
[332]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);
[325]312 }
[253]313
[325]314 sw.WriteLine (" </admintokens>");
315 sw.WriteLine ();
316 sw.WriteLine (" <permissions>");
[332]317 foreach (KeyValuePair<string, WebModulePermission> kvp in modules) {
318 sw.WriteLine (" <permission module=\"{0}\" permission_level=\"{1}\" />", kvp.Value.module,
319 kvp.Value.permissionLevel);
[325]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
[253]346 sw.Flush ();
347 sw.Close ();
348 }
349
350 fileWatcher.EnableRaisingEvents = true;
351 }
352
353
354 public class AdminToken {
355 public string name;
[325]356 public int permissionLevel;
[253]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 }
[325]376}
Note: See TracBrowser for help on using the repository browser.