Ignore:
Timestamp:
Jun 17, 2024, 5:25:43 PM (5 months ago)
Author:
alloc
Message:

1.1.0.1 Release for V 1.0

Location:
TFP-WebServer/WebServer/src
Files:
1 added
20 edited

Legend:

Unmodified
Added
Removed
  • TFP-WebServer/WebServer/src/Commands/EnableOpenIDDebug.cs

    r405 r487  
    55        [UsedImplicitly]
    66        public class EnableOpenIDDebug : ConsoleCmdAbstract {
    7                 protected override string getDescription () {
     7                public override string getDescription () {
    88                        return "enable/disable OpenID debugging";
    99                }
    1010
    11                 protected override string[] getCommands () {
     11                public override string[] getCommands () {
    1212                        return new[] {"openiddebug"};
    1313                }
  • TFP-WebServer/WebServer/src/Commands/WebPermissionsCmd.cs

    r435 r487  
    66        [UsedImplicitly]
    77        public class WebPermissionsCmd : ConsoleCmdAbstract {
    8                 protected override string[] getCommands () {
     8                public override string[] getCommands () {
    99                        return new[] {"webpermission"};
    1010                }
    1111
    12                 protected override string getDescription () {
     12                public override string getDescription () {
    1313                        return "Manage web permission levels";
    1414                }
    1515
    16                 protected override string getHelp () {
     16                public override string getHelp () {
    1717                        return @"
    1818                                |Set/get permission levels required to access a given web functionality. Default
     
    8484                        if (permissionLevelString.EqualsCaseInsensitive (AdminWebModules.MethodLevelInheritKeyword)) {
    8585                                if (isGlobal) {
    86                                         SdtdConsole.Instance.Output ($"Permission level can not use the 'inherit' keyword with the 'global' method keyword.");
     86                                        SdtdConsole.Instance.Output ("Permission level can not use the 'inherit' keyword with the 'global' method keyword.");
    8787                                        return;
    8888                                }
     
    9797                        }
    9898
    99                         module.IsDefault = false;
    10099                        if (isGlobal) {
    101                                 module.LevelGlobal = level;
     100                                module = module.SetLevelGlobal (level);
    102101                        } else {
    103                                 module.LevelPerMethod [(int)method] = level;
     102                                module = module.SetLevelForMethod (method, level);
    104103                        }
    105104                       
  • TFP-WebServer/WebServer/src/Commands/WebTokens.cs

    r405 r487  
    99                private static readonly Regex validNameTokenMatcher = new Regex (@"^\w+$");
    1010
    11                 protected override string[] getCommands () {
     11                public override string[] getCommands () {
    1212                        return new[] {"webtokens"};
    1313                }
    1414
    15                 protected override string getDescription () {
     15                public override string getDescription () {
    1616                        return "Manage web tokens";
    1717                }
    1818
    19                 protected override string getHelp () {
     19                public override string getHelp () {
    2020                        return "Set/get webtoken permission levels. A level of 0 is maximum permission.\n" +
    2121                               "Usage:\n" +
  • TFP-WebServer/WebServer/src/FileCache/InvalidateCachesCmd.cs

    r405 r487  
    55        [UsedImplicitly]
    66        public class InvalidateCachesCmd : ConsoleCmdAbstract {
    7                 protected override string[] getCommands () {
     7                public override string[] getCommands () {
    88                        return new[] {"invalidatecaches"};
    99                }
    1010
    11                 protected override string getDescription () {
     11                public override string getDescription () {
    1212                        return "Invalidate contents of web file caches";
    1313                }
    1414
    15                 protected override string getHelp () {
     15                public override string getHelp () {
    1616                        return "TODO";
    1717                }
  • TFP-WebServer/WebServer/src/FileCache/SimpleCache.cs

    r402 r487  
    1111                        try {
    1212                                lock (fileCache) {
    13                                         if (fileCache.ContainsKey (_filename)) {
    14                                                 return fileCache [_filename];
     13                                        if (fileCache.TryGetValue(_filename, out byte[] content)) {
     14                                                return content;
    1515                                        }
    1616
     
    1919                                        }
    2020
    21                                         fileCache.Add (_filename, File.ReadAllBytes (_filename));
     21                                        byte[] newContent = File.ReadAllBytes (_filename);
     22                                        fileCache.Add (_filename, newContent);
    2223
    23                                         return fileCache [_filename];
     24                                        return newContent;
    2425                                }
    2526                        } catch (Exception e) {
  • TFP-WebServer/WebServer/src/Permissions/AdminApiTokens.cs

    r474 r487  
    1919                }
    2020
    21                 protected override void ParseElement (XmlElement _childElement) {
     21                public override void ParseElement (XmlElement _childElement) {
    2222                        if (ApiToken.TryParse (_childElement, out ApiToken apiToken)) {
    2323                                tokens [apiToken.Name] = apiToken;
  • TFP-WebServer/WebServer/src/Permissions/AdminWebModules.cs

    r474 r487  
     1using System;
    12using System.Collections.Generic;
    23using System.Xml;
     4using JetBrains.Annotations;
     5using UnityEngine;
    36
    47namespace Webserver.Permissions {
     
    1619
    1720                public override void Clear () {
     21                        allModulesList.Clear ();
    1822                        modules.Clear ();
    1923                }
    2024
    21                 protected override void ParseElement (XmlElement _childElement) {
    22                         if (WebModule.TryParse (_childElement, out WebModule webModule)) {
    23                                 modules [webModule.Name] = webModule;
    24                         }
     25                public override void ParseElement (XmlElement _childElement) {
     26                        allModulesList.Clear ();
     27
     28                        if (!WebModule.TryParse (_childElement, out WebModule webModule)) {
     29                                return;
     30                        }
     31
     32                        if (knownModules.TryGetValue (webModule.Name, out WebModule knownModule)) {
     33                                webModule = webModule.FixPermissionLevelsFromKnownModule (knownModule);
     34                        }
     35                       
     36                        modules [webModule.Name] = webModule;
    2537                }
    2638
     
    4355                        lock (Parent) {
    4456                                allModulesList.Clear ();
    45                                
     57                       
    4658                                modules [_module.Name] = _module;
    4759                                Parent.Save ();
     
    8092#endregion
    8193               
    82                 public struct WebModule {
    83                         public string Name;
    84                         public int LevelGlobal;
    85                         public int[] LevelPerMethod;
    86                         public bool IsDefault;
    87 
    88                         public WebModule (string _name, int _level, bool _isDefault = false) {
     94                public readonly struct WebModule {
     95                        public readonly string Name;
     96                        public readonly int LevelGlobal;
     97                        public readonly int[] LevelPerMethod;
     98                        public readonly bool IsDefault;
     99
     100                        public WebModule (string _name, int _level, bool _isDefault) {
    89101                                LevelPerMethod = null;
    90102                               
     
    94106                        }
    95107
    96                         public WebModule (string _name, int _levelGlobal, int[] _levelPerMethod, bool _isDefault = false) {
    97                                 if (_levelPerMethod == null || _levelPerMethod.Length != (int)ERequestMethod.Count) {
     108                        public WebModule (string _name, int _levelGlobal, int[] _levelPerMethod, bool _isDefault) {
     109                                if (_levelPerMethod != null && _levelPerMethod.Length != (int)ERequestMethod.Count) {
    98110                                        LevelPerMethod = createDefaultPerMethodArray ();
    99111
     
    205217                                }
    206218
    207                                 _result = perMethodLevels != null ? new WebModule (name, permissionLevel, perMethodLevels) : new WebModule (name, permissionLevel);
     219                                _result = new WebModule (name, permissionLevel, perMethodLevels, false);
    208220
    209221                                return true;
    210222                        }
    211223
     224                        [MustUseReturnValue]
     225                        public WebModule SetLevelGlobal (int _level) {
     226                                int[] perMethodClone = LevelPerMethod == null ? null : new int[LevelPerMethod.Length];
     227                                if (perMethodClone != null) {
     228                                        Array.Copy (LevelPerMethod, perMethodClone, perMethodClone.Length);
     229                                }
     230
     231                                return new WebModule (Name, _level, perMethodClone, false);
     232                        }
     233
     234                        [MustUseReturnValue]
     235                        public WebModule SetLevelForMethod (ERequestMethod _method, int _level) {
     236                                int[] perMethodClone = createDefaultPerMethodArray ();
     237                                if (LevelPerMethod != null) {
     238                                        Array.Copy (LevelPerMethod, perMethodClone, perMethodClone.Length);
     239                                }
     240
     241                                perMethodClone[(int)_method] = _level;
     242                               
     243                                return new WebModule (Name, LevelGlobal, perMethodClone, false);
     244                        }
     245                       
    212246                        private static int[] createDefaultPerMethodArray () {
    213247                                int[] result = new int[(int)ERequestMethod.Count];
     
    219253                                return result;
    220254                        }
     255
     256                        [MustUseReturnValue]
     257                        public WebModule FixPermissionLevelsFromKnownModule (WebModule _knownModule) {
     258                                if (_knownModule.LevelPerMethod == null) {
     259                                        if (LevelPerMethod != null) {
     260                                                return new WebModule (Name, LevelGlobal, false);
     261                                        }
     262                                        return this;
     263                                }
     264                               
     265                                WebModule result = this;
     266                                for (int i = 0; i < _knownModule.LevelPerMethod.Length; i++) {
     267                                        if (result.LevelPerMethod == null || result.LevelPerMethod[i] == MethodLevelNotSupported) {
     268                                                result = result.SetLevelForMethod ((ERequestMethod)i, _knownModule.LevelPerMethod[i]);
     269                                        }
     270                                }
     271
     272                                return result;
     273                        }
    221274                }
    222275
     
    253306
    254307                public void AddKnownModule (WebModule _module) {
     308                        if (!_module.IsDefault) {
     309                                Log.Warning ($"Call to AddKnownModule with IsDefault==false! From:\n{StackTraceUtility.ExtractStackTrace()}");
     310                        }
     311
    255312                        if (string.IsNullOrEmpty (_module.Name)) {
    256313                                return;
    257314                        }
    258315
    259                         _module.IsDefault = true;
    260                        
    261316                        lock (Parent) {
    262317                                allModulesList.Clear ();
    263318                                knownModules [_module.Name] = _module;
     319                               
     320                                if (modules.TryGetValue (_module.Name, out WebModule overrideModule)) {
     321                                        overrideModule = overrideModule.FixPermissionLevelsFromKnownModule (_module);
     322                                        modules[_module.Name] = overrideModule;
     323                                }
    264324                        }
    265325                }
  • TFP-WebServer/WebServer/src/Permissions/AdminWebUsers.cs

    r485 r487  
    2121                }
    2222
    23                 protected override void ParseElement (XmlElement _childElement) {
     23                public override void ParseElement (XmlElement _childElement) {
    2424                        if (WebUser.TryParse (_childElement, out WebUser webUser)) {
    2525                                users [webUser.Name] = webUser;
  • TFP-WebServer/WebServer/src/SSE/AbsEvent.cs

    r409 r487  
    11using System;
    22using System.Collections.Generic;
    3 using System.IO;
    4 using System.Net.Sockets;
    53using System.Text;
    64using Webserver.UrlHandlers;
    7 using HttpListenerResponse = SpaceWizards.HttpListener.HttpListenerResponse;
    85
    96namespace Webserver.SSE {
    107        public abstract class AbsEvent {
    118                private const int encodingBufferSize = 1024 * 1024;
    12                 private const int keepAliveIntervalSeconds = 10;
    13                 private static readonly byte[] keepAliveData = Encoding.UTF8.GetBytes (": KeepAlive\n\n");
    149
    1510                private readonly SseHandler parent;
     
    1813                private readonly byte[] encodingBuffer;
    1914                private readonly StringBuilder stringBuilder = new StringBuilder ();
    20                 private DateTime lastMessageSent;
    2115
    22                 private readonly List<HttpListenerResponse> openStreams = new List<HttpListenerResponse> ();
     16                private readonly List<SseClient> openClients = new List<SseClient> ();
    2317
    2418                private readonly BlockingQueue<(string _eventName, string _data)> sendQueue =
     
    3731                }
    3832
    39                 public void AddListener (HttpListenerResponse _resp) {
     33                public void AddListener (SseClient _client) {
    4034                        totalOpened++;
    4135                        currentlyOpen++;
    4236
    43                         openStreams.Add (_resp);
     37                        openClients.Add (_client);
    4438                }
    4539
     
    5044
    5145                public void ProcessSendQueue () {
    52                         bool dataSent = false;
    53                        
    5446                        while (sendQueue.HasData ()) {
    5547                                (string eventName, string data) = sendQueue.Dequeue ();
     
    8173                                }
    8274
    83                                 dataSent = true;
    84 
    8575                                sendBufToListeners (buf, bytesToSend);
    86                         }
    87 
    88                         DateTime now = DateTime.Now;
    89                         if (dataSent) {
    90                                 lastMessageSent = now;
    91                         } else if ((now - lastMessageSent).TotalSeconds >= keepAliveIntervalSeconds) {
    92                                 sendBufToListeners (keepAliveData, keepAliveData.Length);
    93                                 lastMessageSent = now;
    9476                        }
    9577                }
    9678
    9779                private void sendBufToListeners (byte[] _bytes, int _bytesToSend) {
    98                         for (int i = openStreams.Count - 1; i >= 0; i--) {
    99                                 HttpListenerResponse resp = openStreams [i];
    100                                 try {
    101                                         if (resp.OutputStream.CanWrite) {
    102                                                 resp.OutputStream.Write (_bytes, 0, _bytesToSend);
    103                                                 resp.OutputStream.Flush ();
    104                                         } else {
    105                                                 currentlyOpen--;
    106                                                 totalClosed++;
     80                        for (int i = openClients.Count - 1; i >= 0; i--) {
     81                                ESseClientWriteResult writeResult = openClients [i].Write (_bytes, _bytesToSend);
     82                                if (writeResult == ESseClientWriteResult.Ok) {
     83                                        continue;
     84                                }
    10785
    108                                                 logError ("Can not write to endpoint, closing", true);
    109                                                 openStreams.RemoveAt (i);
    110                                                 resp.Close ();
    111                                         }
    112                                 } catch (IOException e) {
    113                                         currentlyOpen--;
    114                                         totalClosed++;
     86                                currentlyOpen--;
     87                                totalClosed++;
    11588
    116                                         openStreams.RemoveAt (i);
    117 
    118                                         if (e.InnerException is SocketException se) {
    119                                                 if (se.SocketErrorCode != SocketError.ConnectionAborted && se.SocketErrorCode != SocketError.Shutdown) {
    120                                                         logError ($"SocketError ({se.SocketErrorCode.ToStringCached ()}) while trying to write", true);
    121                                                 }
    122                                         } else {
    123                                                 logError ("IOException while trying to write:", true);
    124                                                 Log.Exception (e);
    125                                         }
    126                                 } catch (Exception e) {
    127                                         currentlyOpen--;
    128                                         totalClosed++;
    129 
    130                                         openStreams.RemoveAt (i);
    131                                         logError ("Exception while trying to write:", true);
    132                                         Log.Exception (e);
    133                                         resp.Close ();
     89                                if (writeResult == ESseClientWriteResult.Error) {
     90                                        logError ("Can not write to endpoint, closing", true);
    13491                                }
    13592                        }
     
    143100
    144101                public virtual int DefaultPermissionLevel () => 0;
     102
     103                public void ClientClosed (SseClient _client) {
     104                        openClients.Remove (_client);
     105                }
    145106        }
    146107}
  • TFP-WebServer/WebServer/src/UrlHandlers/ApiHandler.cs

    r460 r487  
    3030
    3131                private void apiFoundCallback (Type _type) {
    32                         ConstructorInfo ctor = _type.GetConstructor (BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, (Binder)null,
    33                                 apiWithParentCtorTypes, (ParameterModifier[])null);
     32                        ConstructorInfo ctor = _type.GetConstructor (BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null,
     33                                apiWithParentCtorTypes, null);
    3434                        if (ctor != null) {
    3535                                AbsWebAPI apiInstance = (AbsWebAPI)ctor.Invoke (apiWithParentCtorArgs);
     
    3838                        }
    3939
    40                         ctor = _type.GetConstructor (BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, (Binder)null,
    41                                 apiEmptyCtorTypes, (ParameterModifier[])null);
     40                        ctor = _type.GetConstructor (BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null,
     41                                apiEmptyCtorTypes, null);
    4242                        if (ctor != null) {
    4343                                AbsWebAPI apiInstance = (AbsWebAPI)ctor.Invoke (apiEmptyCtorArgs);
  • TFP-WebServer/WebServer/src/UrlHandlers/SessionHandler.cs

    r457 r487  
    2020                private const string userPassLoginUrl = "login";
    2121                public const string userPassLoginName = "User/pass";
    22                 private const string userPassErrorPage = "UserPassLoginFailed";
    2322
    2423                public SessionHandler () : base (null) {
  • TFP-WebServer/WebServer/src/UrlHandlers/SseHandler.cs

    r426 r487  
    2020                private static readonly Type[] ctorTypes = { typeof (SseHandler) };
    2121                private static readonly object[] ctorParams = new object[1];
     22
     23                private readonly List<SseClient> clients = new List<SseClient>();
    2224
    2325                public SseHandler (string _moduleName = null) : base (_moduleName) {
     
    5759
    5860                public override void HandleRequest (RequestContext _context) {
    59                         string eventName = _context.RequestPath.Remove (0, urlBasePath.Length);
    60 
    61                         if (!events.TryGetValue (eventName, out AbsEvent eventInstance)) {
    62                                 Log.Warning ($"[Web] [SSE] In {nameof (SseHandler)}.HandleRequest(): No handler found for event \"{eventName}\"");
    63                                 _context.Response.StatusCode = (int)HttpStatusCode.NotFound;
     61                        string eventNames = _context.QueryParameters ["events"];
     62                        if (string.IsNullOrEmpty (eventNames)) {
     63                                Log.Warning ($"[Web] [SSE] In {nameof (SseHandler)}.HandleRequest(): No 'events' query parameter given");
     64                                _context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
    6465                                return;
    6566                        }
    6667
    67                         if (!IsAuthorizedForEvent (eventName, _context.PermissionLevel)) {
     68                        SseClient client;
     69                        try {
     70                                client = new SseClient(this, _context.Response);
     71                        } catch (Exception e) {
     72                                Log.Error ($"[Web] [SSE] In {nameof (SseHandler)}.HandleRequest(): Could not create client:");
     73                                Log.Exception (e);
     74                                _context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
     75                                return;
     76                        }
     77
     78                        int eventsFound = 0;
     79                        int eventsAuthorized = 0;
     80                        int eventsRegistered = 0;
     81                        foreach (string eventName in eventNames.Split (',', StringSplitOptions.RemoveEmptyEntries)) {
     82                                if (!events.TryGetValue (eventName, out AbsEvent eventInstance)) {
     83                                        Log.Warning ($"[Web] [SSE] In {nameof (SseHandler)}.HandleRequest(): No handler found for event \"{eventName}\"");
     84                                        continue;
     85                                }
     86
     87                                eventsFound++;
     88                               
     89                                if (!IsAuthorizedForEvent (eventName, _context.PermissionLevel)) {
     90                                        continue;
     91                                }
     92
     93                                eventsAuthorized++;
     94
     95                                try
     96                                {
     97                                        eventInstance.AddListener (client);
     98                                } catch (Exception e) {
     99                                        Log.Error ($"[Web] [SSE] In {nameof (SseHandler)}.HandleRequest(): Handler {eventInstance.Name} threw an exception:");
     100                                        Log.Exception (e);
     101                                        _context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
     102                                }
     103
     104                                eventsRegistered++;
     105                        }
     106
     107                        if (eventsFound == 0) {
     108                                _context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
     109                                _context.Response.Close ();
     110                                return;
     111                        }
     112
     113                        if (eventsAuthorized == 0) {
    68114                                _context.Response.StatusCode = (int)HttpStatusCode.Forbidden;
    69115                                if (_context.Connection != null) {
     
    71117                                }
    72118
     119                                _context.Response.Close ();
    73120                                return;
    74121                        }
    75122
    76                         try {
    77                                 eventInstance.AddListener (_context.Response);
    78 
    79                                 // Keep the request open
    80                                 _context.Response.SendChunked = true;
    81 
    82                                 _context.Response.AddHeader ("Content-Type", "text/event-stream");
    83                                 _context.Response.OutputStream.Flush ();
    84                         } catch (Exception e) {
    85                                 Log.Error ($"[Web] [SSE] In {nameof (SseHandler)}.HandleRequest(): Handler {eventInstance.Name} threw an exception:");
    86                                 Log.Exception (e);
    87                                 _context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
    88                         }
     123                        clients.Add (client);
    89124                }
    90125
     
    105140                                        }
    106141                                }
     142
     143                                for (int index = clients.Count - 1; index >= 0; index--) {
     144                                        clients[index].HandleKeepAlive ();
     145                                }
    107146                        }
    108147                }
     
    111150                        evSendRequest.Set ();
    112151                }
     152
     153                public void ClientClosed (SseClient _client) {
     154                        foreach ((string eventName, AbsEvent eventHandler) in events) {
     155                                try {
     156                                        eventHandler.ClientClosed (_client);
     157                                } catch (Exception e) {
     158                                        Log.Error($"[Web] [SSE] '{eventName}': Error closing client");
     159                                        Log.Exception(e);
     160                                }
     161                        }
     162
     163                        clients.Remove (_client);
     164                }
    113165        }
    114166}
  • TFP-WebServer/WebServer/src/Web.cs

    r474 r487  
    172172                }
    173173
     174#if ENABLE_PROFILER
    174175                private readonly UnityEngine.Profiling.CustomSampler getContextSampler = UnityEngine.Profiling.CustomSampler.Create ("GetCtx");
     176#endif
    175177                private readonly UnityEngine.Profiling.CustomSampler authSampler = UnityEngine.Profiling.CustomSampler.Create ("Auth");
    176178                private readonly UnityEngine.Profiling.CustomSampler cookieSampler = UnityEngine.Profiling.CustomSampler.Create ("ConCookie");
     
    191193#else
    192194                        HttpListenerContext ctx = listenerInstance.EndGetContext (_result);
    193                         listenerInstance.BeginGetContext (HandleRequest, listenerInstance);
     195                        listenerInstance.BeginGetContext (handleRequestDelegate, listenerInstance);
    194196#endif
    195197                        try {
  • TFP-WebServer/WebServer/src/WebAPI/APIs/Permissions/CommandPermissions.cs

    r486 r487  
    1010                private const string propertyCommand = "command";
    1111                private const string propertyPermissionLevel = "permissionLevel";
     12                private const string propertyIsDefault = "default";
    1213
    1314                private static readonly byte[] jsonKeyCommand = JsonWriter.GetEncodedPropertyNameWithBeginObject (propertyCommand);
    1415                private static readonly byte[] jsonKeyPermissionLevel = JsonWriter.GetEncodedPropertyNameWithPrefixValueSeparator (propertyPermissionLevel);
     16                private static readonly byte[] jsonKeyIsDefault = JsonWriter.GetEncodedPropertyNameWithPrefixValueSeparator (propertyIsDefault);
    1517
    1618                private static AdminCommands CommandsInstance => GameManager.Instance.adminTools.Commands;
     
    2628                       
    2729                                bool first = true;
    28                                 foreach ((_, AdminCommands.CommandPermission commandPermission) in CommandsInstance.GetCommands ()) {
     30                               
     31                                foreach (IConsoleCommand command in SdtdConsole.Instance.GetCommands ()) {
    2932                                        if (!first) {
    3033                                                writer.WriteValueSeparator ();
     
    3336                                        first = false;
    3437
    35                                         writeCommandJson (ref writer, commandPermission);
     38                                        AdminCommands.CommandPermission commandPermission = CommandsInstance.GetAdminToolsCommandPermission (command.GetCommands());
     39                                        bool isDefault = commandPermission.PermissionLevel == command.DefaultPermissionLevel;
     40                                        if (commandPermission.Command == "") {
     41                                                commandPermission =
     42                                                        new AdminCommands.CommandPermission (command.GetCommands ()[0], commandPermission.PermissionLevel);
     43                                        }
     44
     45                                        writeCommandJson (ref writer, commandPermission, isDefault);
    3646                                }
    37 
     47                               
    3848                                writer.WriteEndArray ();
    3949                               
     
    4656                }
    4757
    48                 private void writeCommandJson (ref JsonWriter _writer, AdminCommands.CommandPermission _commandPermission) {
     58                private void writeCommandJson(ref JsonWriter _writer, AdminCommands.CommandPermission _commandPermission, bool _isDefault) {
    4959                        _writer.WriteRaw (jsonKeyCommand);
    5060                        _writer.WriteString (_commandPermission.Command);
    5161                        _writer.WriteRaw (jsonKeyPermissionLevel);
    5262                        _writer.WriteInt32 (_commandPermission.PermissionLevel);
     63                        _writer.WriteRaw (jsonKeyIsDefault);
     64                        _writer.WriteBoolean (_isDefault);
    5365                        _writer.WriteEndObject ();
    5466                }
  • TFP-WebServer/WebServer/src/WebAPI/APIs/Permissions/CommandPermissions.openapi.yaml

    r486 r487  
    2121          type: integer
    2222          description: Permission level of the command
     23        default:
     24          type: boolean
     25          description: Whether the permission level is the default value for the command
    2326      required:
    2427        - command
    2528        - permissionLevel
     29        - default
    2630
    2731    CommandPermissionList:
  • TFP-WebServer/WebServer/src/WebAPI/APIs/Permissions/WebModules.cs

    r486 r487  
    124124                                }
    125125
    126                                 module.LevelGlobal = permissionLevelGlobal;
     126                                module = module.SetLevelGlobal (permissionLevelGlobal);
    127127                        }
    128128
     
    165165                                        }
    166166
    167                                         module.LevelPerMethod [(int)method] = permissionLevel;
     167                                        module = module.SetLevelForMethod (method, permissionLevel);
    168168                                }
    169169                        }
    170170
    171                         module.IsDefault = false;
    172171                        ModulesInstance.AddModule (module);
    173172
  • TFP-WebServer/WebServer/src/WebAPI/APIs/WorldState/Player.cs

    r463 r487  
    9292                        ClientInfo ci = ConnectionManager.Instance.Clients.ForUserId (_nativeUserId);
    9393                        if (ci == null) {
    94                                 Log.Warning ($"[Web] Player.GET: ClientInfo null");
     94                                Log.Warning ("[Web] Player.GET: ClientInfo null");
    9595                                return;
    9696                        }
     
    100100
    101101                        if (entity == null) {
    102                                 Log.Warning ($"[Web] Player.GET: EntityPlayer null");
     102                                Log.Warning ("[Web] Player.GET: EntityPlayer null");
    103103                                return;
    104104                        }
  • TFP-WebServer/WebServer/src/WebAPI/AbsRestApi.cs

    r486 r487  
    103103                                }
    104104                        } catch (Exception e) {
    105                                 SendEmptyResponse (_context, HttpStatusCode.InternalServerError, jsonInputData, "ERROR_PROCESSING", e);
     105                                try {
     106                                        SendEmptyResponse (_context, HttpStatusCode.InternalServerError, jsonInputData, "ERROR_PROCESSING", e);
     107                                } catch (Exception e2) {
     108                                        Log.Error ($"[Web] In {nameof(AbsRestApi)}.HandleRequest(): Handler {Name} threw an exception while trying to send a previous exception to the client:");
     109                                        Log.Exception (e2);
     110                                }
    106111                        }
    107112                }
  • TFP-WebServer/WebServer/src/WebAPI/OpenApiHelpers.cs

    r466 r487  
    105105                }
    106106
    107                 private static readonly Regex pathMatcher = new Regex ("^\\s{1,2}(/\\S+):.*$", RegexOptions.Compiled | RegexOptions.CultureInvariant);
     107                private static readonly Regex pathMatcher = new Regex (@"^\s{1,2}(/\S+):.*$", RegexOptions.Compiled | RegexOptions.CultureInvariant);
    108108                private Dictionary<string, string> findExportedPaths (string _spec, string _replaceBasePath = null) {
    109109                        Dictionary<string, string> result = new Dictionary<string, string> ();
     
    161161                                                break;
    162162                                        case '\\':
    163                                                 _targetSb.Append ("\\\\");
     163                                                _targetSb.Append (@"\\");
    164164                                                break;
    165165                                        case '\b':
  • TFP-WebServer/WebServer/src/WebCommandResult.cs

    r402 r487  
    1717                private readonly string command;
    1818                private readonly string parameters;
     19                private readonly string sourceName;
    1920
    2021                private readonly RequestContext context;
     
    2627                        parameters = _parameters;
    2728                        responseType = _responseType;
     29                        sourceName = _context.Connection?.Username ?? "Unauth-PermLevel-" + _context.PermissionLevel;
    2830                }
    2931
     
    9395
    9496                public string GetDescription () {
    95                         return $"WebCommandResult_for_{command}";
     97                        return $"WebCommandResult_for_{command}_by_{sourceName}";
    9698                }
    9799        }
Note: See TracChangeset for help on using the changeset viewer.