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

Last change on this file since 371 was 369, checked in by alloc, 3 years ago

Preparations for A20 release
Changes usage of "SteamID" to "UserID" in console commands
Also changes a bunch of the WebAPI stuff to show / use UserIDs

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