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

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

*Latest optimizations

File size: 11.2 KB
Line 
1using System.Collections.Generic;
2using System.Collections.ObjectModel;
3using System.IO;
4using System.Xml;
5using UniLinq;
6
7namespace AllocsFixes.NetConnections.Servers.Web {
8        public class WebPermissions {
9                private const string PERMISSIONS_FILE = "webpermissions.xml";
10                private static WebPermissions instance;
11                private readonly WebModulePermission defaultModulePermission = new WebModulePermission ("", 0);
12
13                private readonly Dictionary<string, WebModulePermission> knownModules =
14                        new CaseInsensitiveStringDictionary<WebModulePermission> ();
15
16                private readonly Dictionary<string, AdminToken> admintokens = new CaseInsensitiveStringDictionary<AdminToken> ();
17                private FileSystemWatcher fileWatcher;
18
19                private readonly Dictionary<string, WebModulePermission> modules = new CaseInsensitiveStringDictionary<WebModulePermission> ();
20
21                public WebPermissions () {
22                        allModulesList = new List<WebModulePermission> ();
23                        allModulesListRO = new ReadOnlyCollection<WebModulePermission> (allModulesList);
24                        Directory.CreateDirectory (GetFilePath ());
25                        InitFileWatcher ();
26                        Load ();
27                }
28
29                public static WebPermissions Instance {
30                        get {
31                                lock (typeof (WebPermissions)) {
32                                        if (instance == null) {
33                                                instance = new WebPermissions ();
34                                        }
35
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                        }
50
51                        return null;
52                }
53
54                public WebModulePermission GetModulePermission (string _module) {
55                        WebModulePermission result;
56                        if (modules.TryGetValue (_module, out result)) {
57                                return result;
58                        }
59
60                        if (knownModules.TryGetValue (_module, out result)) {
61                                return result;
62                        }
63
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];
94                        admintokens.CopyValuesTo (result);
95                        return result;
96                }
97
98
99                // Commands
100                public void AddModulePermission (string _module, int _permissionLevel, bool _save = true) {
101                        WebModulePermission p = new WebModulePermission (_module, _permissionLevel);
102                        lock (this) {
103                                allModulesList.Clear ();
104                                modules [_module] = p;
105                                if (_save) {
106                                        Save ();
107                                }
108                        }
109                }
110
111                public void AddKnownModule (string _module, int _defaultPermission) {
112                        if (string.IsNullOrEmpty (_module)) {
113                                return;
114                        }
115                       
116                        WebModulePermission p = new WebModulePermission (_module, _defaultPermission);
117
118                        lock (this) {
119                                allModulesList.Clear ();
120                                knownModules [_module] = p;
121                        }
122                }
123
124                public bool IsKnownModule (string _module) {
125                        if (string.IsNullOrEmpty (_module)) {
126                                return false;
127                        }
128
129                        lock (this) {
130                                return knownModules.ContainsKey (_module);
131                        }
132
133                }
134
135                public void RemoveModulePermission (string _module, bool _save = true) {
136                        lock (this) {
137                                allModulesList.Clear ();
138                                modules.Remove (_module);
139                                if (_save) {
140                                        Save ();
141                                }
142                        }
143                }
144
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                                        }
156                                }
157                        }
158
159                        return allModulesListRO;
160                }
161
162
163                //IO Tasks
164
165                private void InitFileWatcher () {
166                        fileWatcher = new FileSystemWatcher (GetFilePath (), GetFileName ());
167                        fileWatcher.Changed += OnFileChanged;
168                        fileWatcher.Created += OnFileChanged;
169                        fileWatcher.Deleted += OnFileChanged;
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 () {
191                        admintokens.Clear ();
192                        modules.Clear ();
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) {
207                                Log.Error ("Failed loading permissions file: " + e.Message);
208                                return;
209                        }
210
211                        XmlNode adminToolsNode = xmlDoc.DocumentElement;
212
213                        if (adminToolsNode == null) {
214                                Log.Error ("Failed loading permissions file: No DocumentElement found");
215                                return;
216                        }
217                       
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                                                }
224
225                                                if (subChild.NodeType != XmlNodeType.Element) {
226                                                        Log.Warning ("Unexpected XML node found in 'admintokens' section: " + subChild.OuterXml);
227                                                        continue;
228                                                }
229
230                                                XmlElement lineItem = (XmlElement) subChild;
231
232                                                if (!lineItem.HasAttribute ("name")) {
233                                                        Log.Warning ("Ignoring admintoken-entry because of missing 'name' attribute: " +
234                                                                     subChild.OuterXml);
235                                                        continue;
236                                                }
237
238                                                if (!lineItem.HasAttribute ("token")) {
239                                                        Log.Warning ("Ignoring admintoken-entry because of missing 'token' attribute: " +
240                                                                     subChild.OuterXml);
241                                                        continue;
242                                                }
243
244                                                if (!lineItem.HasAttribute ("permission_level")) {
245                                                        Log.Warning ("Ignoring admintoken-entry because of missing 'permission_level' attribute: " +
246                                                                     subChild.OuterXml);
247                                                        continue;
248                                                }
249
250                                                string name = lineItem.GetAttribute ("name");
251                                                string token = lineItem.GetAttribute ("token");
252                                                int permissionLevel;
253                                                if (!int.TryParse (lineItem.GetAttribute ("permission_level"), out permissionLevel)) {
254                                                        Log.Warning (
255                                                                "Ignoring admintoken-entry because of invalid (non-numeric) value for 'permission_level' attribute: " +
256                                                                subChild.OuterXml);
257                                                        continue;
258                                                }
259
260                                                AddAdmin (name, token, permissionLevel, false);
261                                        }
262                                }
263
264                                if (childNode.Name == "permissions") {
265                                        foreach (XmlNode subChild in childNode.ChildNodes) {
266                                                if (subChild.NodeType == XmlNodeType.Comment) {
267                                                        continue;
268                                                }
269
270                                                if (subChild.NodeType != XmlNodeType.Element) {
271                                                        Log.Warning ("Unexpected XML node found in 'permissions' section: " + subChild.OuterXml);
272                                                        continue;
273                                                }
274
275                                                XmlElement lineItem = (XmlElement) subChild;
276
277                                                if (!lineItem.HasAttribute ("module")) {
278                                                        Log.Warning ("Ignoring permission-entry because of missing 'module' attribute: " +
279                                                                     subChild.OuterXml);
280                                                        continue;
281                                                }
282
283                                                if (!lineItem.HasAttribute ("permission_level")) {
284                                                        Log.Warning ("Ignoring permission-entry because of missing 'permission_level' attribute: " +
285                                                                     subChild.OuterXml);
286                                                        continue;
287                                                }
288
289                                                int permissionLevel;
290                                                if (!int.TryParse (lineItem.GetAttribute ("permission_level"), out permissionLevel)) {
291                                                        Log.Warning (
292                                                                "Ignoring permission-entry because of invalid (non-numeric) value for 'permission_level' attribute: " +
293                                                                subChild.OuterXml);
294                                                        continue;
295                                                }
296
297                                                AddModulePermission (lineItem.GetAttribute ("module"), permissionLevel, false);
298                                        }
299                                }
300                        }
301
302                        Log.Out ("Loading permissions file done.");
303                }
304
305                public void Save () {
306                        fileWatcher.EnableRaisingEvents = false;
307
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\" /> -->");
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);
318                                }
319
320                                sw.WriteLine (" </admintokens>");
321                                sw.WriteLine ();
322                                sw.WriteLine (" <permissions>");
323                                foreach (KeyValuePair<string, WebModulePermission> kvp in modules) {
324                                        sw.WriteLine ("         <permission module=\"{0}\" permission_level=\"{1}\" />", kvp.Value.module,
325                                                kvp.Value.permissionLevel);
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
352                                sw.Flush ();
353                                sw.Close ();
354                        }
355
356                        fileWatcher.EnableRaisingEvents = true;
357                }
358
359
360                public class AdminToken {
361                        public string name;
362                        public int permissionLevel;
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        }
382}
Note: See TracBrowser for help on using the repository browser.