diff --git a/src/Tgstation.Server.Host/Components/Interop/CommCommand.cs b/src/Tgstation.Server.Host/Components/Interop/CommCommand.cs index cc9ab8571a..7145d35aae 100644 --- a/src/Tgstation.Server.Host/Components/Interop/CommCommand.cs +++ b/src/Tgstation.Server.Host/Components/Interop/CommCommand.cs @@ -8,8 +8,13 @@ namespace Tgstation.Server.Host.Components.Interop sealed class CommCommand { /// - /// The raw JSON decond of the + /// The dictionary of the /// public IReadOnlyDictionary Parameters { get; set; } + + /// + /// The raw JSON of the + /// + public string RawJson { get; set; } } } \ No newline at end of file diff --git a/src/Tgstation.Server.Host/Components/Interop/CommContext.cs b/src/Tgstation.Server.Host/Components/Interop/CommContext.cs index 839086a3bb..f9c5208d88 100644 --- a/src/Tgstation.Server.Host/Components/Interop/CommContext.cs +++ b/src/Tgstation.Server.Host/Components/Interop/CommContext.cs @@ -109,10 +109,11 @@ namespace Tgstation.Server.Host.Components.Interop { command = new CommCommand { - Parameters = JsonConvert.DeserializeObject>(file) + Parameters = JsonConvert.DeserializeObject>(file), + RawJson = file }; } - catch (JsonSerializationException ex) + catch (JsonException ex) { //file not fully written yet logger.LogDebug("Suppressing json convert exception for command file write: {0}", ex); diff --git a/src/Tgstation.Server.Host/Components/Watchdog/SessionController.cs b/src/Tgstation.Server.Host/Components/Watchdog/SessionController.cs index dd5d2b7ebb..8cd90b5b72 100644 --- a/src/Tgstation.Server.Host/Components/Watchdog/SessionController.cs +++ b/src/Tgstation.Server.Host/Components/Watchdog/SessionController.cs @@ -1,6 +1,7 @@ using Byond.TopicSender; using Microsoft.Extensions.Logging; using Newtonsoft.Json; +using Newtonsoft.Json.Serialization; using System; using System.Collections.Generic; using System.Globalization; @@ -286,6 +287,25 @@ namespace Tgstation.Server.Host.Components.Watchdog content = new object(); switch (method) { + case Constants.DMCommandChat: + try + { + var message = JsonConvert.DeserializeObject(command.RawJson, new JsonSerializerSettings + { + ContractResolver = new CamelCasePropertyNamesContractResolver() + }); + if (message.ChannelIds == null) + throw new InvalidOperationException("Missing ChannelIds field!"); + if (message.Message == null) + throw new InvalidOperationException("Missing Message field!"); + await chat.SendMessage(message.Message, message.ChannelIds, cancellationToken).ConfigureAwait(false); + } + catch (Exception e) + { + logger.LogDebug("Exception while decoding chat message! Exception: {0}", e); + goto default; + } + break; case Constants.DMCommandServerPrimed: //currently unused, maybe in the future break; diff --git a/src/Tgstation.Server.Host/Controllers/InstanceController.cs b/src/Tgstation.Server.Host/Controllers/InstanceController.cs index 5db9cd5897..e220a74e39 100644 --- a/src/Tgstation.Server.Host/Controllers/InstanceController.cs +++ b/src/Tgstation.Server.Host/Controllers/InstanceController.cs @@ -9,7 +9,6 @@ using System.Linq; using System.Linq.Expressions; using System.Net; using System.Reflection; -using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; using Tgstation.Server.Api; @@ -121,6 +120,17 @@ namespace Tgstation.Server.Host.Controllers return BadRequest(new ErrorMessage { Message = "path must not be empty!" }); NormalizeModelPath(model, out var rawPath); + + var localPath = ioManager.ResolvePath("."); + NormalizeModelPath(new Api.Models.Instance + { + Path = localPath + }, out var normalizedLocalPath); + + if (rawPath.StartsWith(normalizedLocalPath, StringComparison.Ordinal)) + return Conflict("Instances cannot be created in the installation directory!"); + + var dirExistsTask = ioManager.DirectoryExists(model.Path, cancellationToken); bool attached = false; if (await ioManager.FileExists(model.Path, cancellationToken).ConfigureAwait(false) || await dirExistsTask.ConfigureAwait(false)) diff --git a/tests/Tgstation.Server.Tests/InstanceManagerTest.cs b/tests/Tgstation.Server.Tests/InstanceManagerTest.cs index 0c9efe68b9..6a09d73d63 100644 --- a/tests/Tgstation.Server.Tests/InstanceManagerTest.cs +++ b/tests/Tgstation.Server.Tests/InstanceManagerTest.cs @@ -51,6 +51,13 @@ namespace Tgstation.Server.Tests }, cancellationToken)).ConfigureAwait(false); await Assert.ThrowsExceptionAsync(() => instanceManagerClient.CreateOrAttach(firstTest, cancellationToken)).ConfigureAwait(false); + //can't create instances in installation directory + await Assert.ThrowsExceptionAsync(() => instanceManagerClient.CreateOrAttach(new Api.Models.Instance + { + Path = "./A/Local/Path", + Name = "NoInstallDirTest" + }, cancellationToken)).ConfigureAwait(false); + //can't move to existent directories await Assert.ThrowsExceptionAsync(() => instanceManagerClient.Update(new Api.Models.Instance {