Index: binary-improvements2/WebServer/src/Permissions/AdminWebModules.cs
===================================================================
--- binary-improvements2/WebServer/src/Permissions/AdminWebModules.cs	(revision 425)
+++ binary-improvements2/WebServer/src/Permissions/AdminWebModules.cs	(revision 426)
@@ -1,4 +1,5 @@
 using System.Collections.Generic;
 using System.Xml;
+using UnityEngine;
 
 namespace Webserver.Permissions {
@@ -40,10 +41,9 @@
 
 
-		public void AddModule (string _module, int _permissionLevel) {
-			WebModule p = new WebModule (_module, _permissionLevel, false);
+		public void AddModule (WebModule _module) {
 			lock (this) {
 				allModulesList.Clear ();
 				
-				modules [_module] = p;
+				modules [_module.Name] = _module;
 				Parent.Save ();
 			}
@@ -80,20 +80,60 @@
 
 #endregion
-
-		public readonly struct WebModule {
-			public readonly string Name;
-			public readonly int PermissionLevel;
-			public readonly bool IsDefault;
-
-			public WebModule (string _name, int _permissionLevel, bool _isDefault) {
+		
+		public struct WebModule {
+			public string Name;
+			public int LevelGlobal;
+			public int[] LevelPerMethod;
+			public bool IsDefault;
+
+			public WebModule (string _name, int _level, bool _isDefault = false) {
+				LevelPerMethod = null;
+				
 				Name = _name;
-				PermissionLevel = _permissionLevel;
+				LevelGlobal = _level;
+				IsDefault = _isDefault;
+			}
+
+			public WebModule (string _name, int _levelGlobal, int[] _levelPerMethod, bool _isDefault = false) {
+				if (_levelPerMethod == null || _levelPerMethod.Length != (int)ERequestMethod.Count) {
+					LevelPerMethod = createDefaultPerMethodArray ();
+
+					for (int i = 0; i < (int)ERequestMethod.Count; i++) {
+						if (_levelPerMethod != null && i < _levelPerMethod.Length) {
+							LevelPerMethod [i] = _levelPerMethod [i];
+						}
+					}
+				} else {
+					LevelPerMethod = _levelPerMethod;
+				}
+
+				Name = _name;
+				LevelGlobal = _levelGlobal;
 				IsDefault = _isDefault;
 			}
 			
 			public void ToXml (XmlElement _parent) {
-				_parent.AddXmlElement ("module")
-						.SetAttrib ("name", Name)
-						.SetAttrib ("permission_level", PermissionLevel.ToString ());
+				bool hasPerMethodLevels = LevelPerMethod != null;
+
+				XmlElement permissionElement = _parent.AddXmlElement ("module")
+					.SetAttrib ("name", Name)
+					.SetAttrib ("permission_level", LevelGlobal.ToString ());
+				
+				if (!hasPerMethodLevels) {
+					return;
+				}
+
+				for (int i = 0; i < LevelPerMethod.Length; i++) {
+					ERequestMethod method = (ERequestMethod)i;
+					int level = LevelPerMethod [i];
+					
+					if (level == MethodLevelNotSupported) {
+						continue;
+					}
+
+					permissionElement.AddXmlElement ("method")
+						.SetAttrib ("name", method.ToStringCached ())
+						.SetAttrib ("permission_level", level.ToString ());
+				}
 			}
 
@@ -117,8 +157,64 @@
 					return false;
 				}
-				
-				_result = new WebModule (name, permissionLevel, false);
+
+				int[] perMethodLevels = null;
+				
+				foreach (XmlNode child in _element.ChildNodes) {
+					if (child.NodeType != XmlNodeType.Element) {
+						continue;
+					}
+
+					XmlElement childElem = (XmlElement)child;
+					if (childElem.Name != "method") {
+						Log.Warning ($"[Web] [Perms] Ignoring module child element, invalid element name: {childElem.OuterXml}");
+						continue;
+					}
+
+					if (!childElem.TryGetAttribute ("name", out string methodName)) {
+						Log.Warning ($"[Web] [Perms] Ignoring module child element, missing 'name' attribute: {childElem.OuterXml}");
+						continue;
+					}
+
+					if (!EnumUtils.TryParse (methodName, out ERequestMethod method, true)) {
+						Log.Warning (
+							$"[Web] [Perms] Ignoring module child element, unknown method name in 'name' attribute: {childElem.OuterXml}");
+						continue;
+					}
+
+					if (method >= ERequestMethod.Count) {
+						Log.Warning (
+							$"[Web] [Perms] Ignoring module child element, invalid method name in 'name' attribute: {childElem.OuterXml}");
+						continue;
+					}
+					
+					if (!childElem.TryGetAttribute ("permission_level", out permissionLevelString)) {
+						Log.Warning ($"[Web] [Perms] Ignoring module child element, missing 'permission_level' attribute: {childElem.OuterXml}");
+						continue;
+					}
+
+					if (!int.TryParse (permissionLevelString, out int methodPermissionLevel)) {
+						Log.Warning (
+							$"[Web] [Perms] Ignoring module child element, invalid (non-numeric) value for 'permission_level' attribute: {childElem.OuterXml}");
+						continue;
+					}
+
+					perMethodLevels ??= createDefaultPerMethodArray ();
+					perMethodLevels [(int)method] = methodPermissionLevel;
+				}
+
+				_result = perMethodLevels != null ? new WebModule (name, permissionLevel, perMethodLevels) : new WebModule (name, permissionLevel);
+
 				return true;
 			}
+
+			private static int[] createDefaultPerMethodArray () {
+				int[] result = new int[(int)ERequestMethod.Count];
+
+				for (int i = 0; i < (int)ERequestMethod.Count; i++) {
+					result [i] = MethodLevelNotSupported;
+				}
+
+				return result;
+			}
 		}
 
@@ -127,4 +223,17 @@
 
 		/// <summary>
+		/// Use global (API based) permission level for the method
+		/// </summary>
+		public const int MethodLevelInheritGlobal = int.MinValue;
+		
+		/// <summary>
+		/// Method not supported
+		/// </summary>
+		public const int MethodLevelNotSupported = int.MinValue + 1;
+
+		public const int PermissionLevelUser = 1000;
+		public const int PermissionLevelGuest = 2000;
+
+		/// <summary>
 		/// Contains all registered modules and their default permission
 		/// </summary>
@@ -136,14 +245,14 @@
 		private readonly List<WebModule> allModulesList = new List<WebModule> ();
 
-		public void AddKnownModule (string _module, int _defaultPermission) {
-			if (string.IsNullOrEmpty (_module)) {
+		public void AddKnownModule (WebModule _module) {
+			if (string.IsNullOrEmpty (_module.Name)) {
 				return;
 			}
 
-			WebModule p = new WebModule (_module, _defaultPermission, true);
-
+			_module.IsDefault = true;
+			
 			lock (this) {
 				allModulesList.Clear ();
-				knownModules [_module] = p;
+				knownModules [_module.Name] = _module;
 			}
 		}
@@ -160,15 +269,10 @@
 
 		public bool ModuleAllowedWithLevel (string _module, int _level) {
-			WebModule permInfo = GetModule (_module)!.Value;
-			return permInfo.PermissionLevel >= _level;
-		}
-
-		public WebModule? GetModule (string _module, bool _returnDefaults = true) {
+			return GetModule (_module).LevelGlobal >= _level;
+		}
+
+		public WebModule GetModule (string _module) {
 			if (modules.TryGetValue (_module, out WebModule result)) {
 				return result;
-			}
-
-			if (!_returnDefaults) {
-				return null;
 			}
 
