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

Last change on this file since 333 was 332, checked in by alloc, 6 years ago

*Latest optimizations

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