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
{