diff --git a/build/Version.props b/build/Version.props
index b65405fdb7..d72259794c 100644
--- a/build/Version.props
+++ b/build/Version.props
@@ -4,7 +4,7 @@
4.5.0
2.0.0
- 7.2.0
+ 7.3.0
8.2.0
5.2.3
0.4.0
diff --git a/src/Tgstation.Server.Api/Models/ErrorCode.cs b/src/Tgstation.Server.Api/Models/ErrorCode.cs
index 174de92a6f..6c9772d582 100644
--- a/src/Tgstation.Server.Api/Models/ErrorCode.cs
+++ b/src/Tgstation.Server.Api/Models/ErrorCode.cs
@@ -563,6 +563,12 @@ namespace Tgstation.Server.Api.Models
/// An attempt to connect a chat bot failed.
///
[Description("Failed to connect chat bot!")]
- ChatCannotConnectProvider
+ ChatCannotConnectProvider,
+
+ ///
+ /// Attempt to add DreamDaemon to the list of firewall exempt processes failed.
+ ///
+ [Description("Failed to allow DreamDaemon through the Windows firewall!")]
+ ByondDreamDaemonFirewallFail,
}
}
diff --git a/src/Tgstation.Server.Api/Models/LogFile.cs b/src/Tgstation.Server.Api/Models/LogFile.cs
index cdb99832c0..3f67f93d11 100644
--- a/src/Tgstation.Server.Api/Models/LogFile.cs
+++ b/src/Tgstation.Server.Api/Models/LogFile.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using Tgstation.Server.Api.Models.Internal;
namespace Tgstation.Server.Api.Models
@@ -11,7 +11,7 @@ namespace Tgstation.Server.Api.Models
///
/// The name of the log file.
///
- public string? Name { get; set; }
+ public string Name { get; set; } = String.Empty;
///
/// The of when the log file was modified.
diff --git a/src/Tgstation.Server.Host/.config/dotnet-tools.json b/src/Tgstation.Server.Host/.config/dotnet-tools.json
index 4947a30bdf..79d13146a3 100644
--- a/src/Tgstation.Server.Host/.config/dotnet-tools.json
+++ b/src/Tgstation.Server.Host/.config/dotnet-tools.json
@@ -3,10 +3,10 @@
"isRoot": true,
"tools": {
"dotnet-ef": {
- "version": "3.1.6",
+ "version": "3.1.7",
"commands": [
"dotnet-ef"
]
}
}
-}
\ No newline at end of file
+}
diff --git a/src/Tgstation.Server.Host/Components/Byond/WindowsByondInstaller.cs b/src/Tgstation.Server.Host/Components/Byond/WindowsByondInstaller.cs
index eb249c99c7..12782bbb8b 100644
--- a/src/Tgstation.Server.Host/Components/Byond/WindowsByondInstaller.cs
+++ b/src/Tgstation.Server.Host/Components/Byond/WindowsByondInstaller.cs
@@ -1,4 +1,4 @@
-using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Logging;
using System;
using System.Text;
using System.Threading;
@@ -84,65 +84,99 @@ namespace Tgstation.Server.Host.Components.Byond
public void Dispose() => semaphore.Dispose();
///
- public override async Task InstallByond(string path, Version version, CancellationToken cancellationToken)
- {
- async Task SetNoPromptTrusted()
- {
- var configPath = IOManager.ConcatPath(path, ByondConfigDir);
- await IOManager.CreateDirectory(configPath, cancellationToken).ConfigureAwait(false);
+ public override Task InstallByond(string path, Version version, CancellationToken cancellationToken)
+ => Task.WhenAll(
+ SetNoPromptTrusted(path, cancellationToken),
+ InstallDirectX(path, cancellationToken),
+ AddDreamDaemonToFirewall(path, cancellationToken));
- var configFilePath = IOManager.ConcatPath(configPath, ByondDDConfig);
- Logger.LogTrace("Disabling trusted prompts in {0}...", configFilePath);
- await IOManager.WriteAllBytes(
- configFilePath,
- Encoding.UTF8.GetBytes(ByondNoPromptTrustedMode),
- cancellationToken)
- .ConfigureAwait(false);
+ async Task SetNoPromptTrusted(string path, CancellationToken cancellationToken)
+ {
+ var configPath = IOManager.ConcatPath(path, ByondConfigDir);
+ await IOManager.CreateDirectory(configPath, cancellationToken).ConfigureAwait(false);
+
+ var configFilePath = IOManager.ConcatPath(configPath, ByondDDConfig);
+ Logger.LogTrace("Disabling trusted prompts in {0}...", configFilePath);
+ await IOManager.WriteAllBytes(
+ configFilePath,
+ Encoding.UTF8.GetBytes(ByondNoPromptTrustedMode),
+ cancellationToken)
+ .ConfigureAwait(false);
+ }
+
+ async Task InstallDirectX(string path, CancellationToken cancellationToken)
+ {
+ using var lockContext = await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false);
+ if (installedDirectX)
+ {
+ Logger.LogTrace("DirectX already installed.");
+ return;
}
- var setNoPromptTrustedModeTask = SetNoPromptTrusted();
+ Logger.LogTrace("Installing DirectX redistributable...");
- // after this version lummox made DD depend of directx lol
- // but then he became amazing and not only fixed it but also gave us 30s compiles \[T]/
- // then he readded it again so -_-
- if (!installedDirectX)
- using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false))
- if (!installedDirectX)
- {
- // ^check again because race conditions
- Logger.LogTrace("Installing DirectX redistributable...");
+ // always install it, it's pretty fast and will do better redundancy checking than us
+ var rbdx = IOManager.ConcatPath(path, ByondDXDir);
- // always install it, it's pretty fast and will do better redundancy checking than us
- var rbdx = IOManager.ConcatPath(path, ByondDXDir);
+ try
+ {
+ // noShellExecute because we aren't doing runas shennanigans
+ using var directXInstaller = processExecutor.LaunchProcess(
+ IOManager.ConcatPath(rbdx, "DXSETUP.exe"),
+ rbdx,
+ "/silent",
+ noShellExecute: true);
- // noShellExecute because we aren't doing runas shennanigans
- IProcess directXInstaller;
- try
- {
- directXInstaller = processExecutor.LaunchProcess(
- IOManager.ConcatPath(rbdx, "DXSETUP.exe"),
- rbdx, "/silent",
- noShellExecute: true);
- }
- catch (Exception e)
- {
- throw new JobException(ErrorCode.ByondDirectXInstallFail, e);
- }
+ int exitCode;
+ using (cancellationToken.Register(() => directXInstaller.Terminate()))
+ exitCode = await directXInstaller.Lifetime.ConfigureAwait(false);
+ cancellationToken.ThrowIfCancellationRequested();
- using (directXInstaller)
- {
- int exitCode;
- using (cancellationToken.Register(() => directXInstaller.Terminate()))
- exitCode = await directXInstaller.Lifetime.ConfigureAwait(false);
- cancellationToken.ThrowIfCancellationRequested();
+ if (exitCode != 0)
+ throw new JobException(ErrorCode.ByondDirectXInstallFail, new JobException($"Invalid exit code: {exitCode}"));
+ installedDirectX = true;
+ }
+ catch (Exception e)
+ {
+ throw new JobException(ErrorCode.ByondDirectXInstallFail, e);
+ }
+ }
- if (exitCode != 0)
- throw new JobException(ErrorCode.ByondDirectXInstallFail, new JobException($"Invalid exit code: {exitCode}"));
- installedDirectX = true;
- }
- }
+ async Task AddDreamDaemonToFirewall(string path, CancellationToken cancellationToken)
+ {
+ var dreamDaemonPath = IOManager.ResolvePath(
+ IOManager.ConcatPath(
+ path,
+ ByondManager.BinPath,
+ DreamDaemonName));
- await setNoPromptTrustedModeTask.ConfigureAwait(false);
+ try
+ {
+ using var netshProcess = processExecutor.LaunchProcess(
+ "netsh.exe",
+ IOManager.ResolvePath(),
+ $"advfirewall firewall add rule name=\"TGS DreamDaemon\" program=\"{dreamDaemonPath}\" protocol=tcp dir=in enable=yes action=allow",
+ true,
+ true,
+ true);
+
+ int exitCode;
+ using (cancellationToken.Register(() => netshProcess.Terminate()))
+ exitCode = await netshProcess.Lifetime.ConfigureAwait(false);
+ cancellationToken.ThrowIfCancellationRequested();
+
+ Logger.LogDebug(
+ "netsh.exe output:{0}{1}",
+ Environment.NewLine,
+ await netshProcess.GetCombinedOutput(cancellationToken).ConfigureAwait(false));
+
+ if (exitCode != 0)
+ throw new JobException(ErrorCode.ByondDreamDaemonFirewallFail, new JobException($"Invalid exit code: {exitCode}"));
+ }
+ catch (Exception ex)
+ {
+ throw new JobException(ErrorCode.ByondDreamDaemonFirewallFail, ex);
+ }
}
}
}
diff --git a/src/Tgstation.Server.Host/Components/Chat/Providers/DiscordProvider.cs b/src/Tgstation.Server.Host/Components/Chat/Providers/DiscordProvider.cs
index a660d927d7..e4b6aef02f 100644
--- a/src/Tgstation.Server.Host/Components/Chat/Providers/DiscordProvider.cs
+++ b/src/Tgstation.Server.Host/Components/Chat/Providers/DiscordProvider.cs
@@ -57,7 +57,7 @@ namespace Tgstation.Server.Host.Components.Chat.Providers
///
/// The mention provided by the Discord library
/// The normalized mention
- static string NormalizeMentions(string fromDiscord) => fromDiscord.Replace(" fromDiscord.Replace("<@!", "<@", StringComparison.Ordinal);
///
/// Construct a
@@ -96,6 +96,16 @@ namespace Tgstation.Server.Host.Components.Chat.Providers
if (e.Author.Id == client.CurrentUser.Id)
return;
+ if (e.Content.Equals("Based on what?", StringComparison.OrdinalIgnoreCase))
+ {
+ // DCT: None available
+ await SendMessage(
+ e.Channel.Id,
+ "https://youtu.be/LrNu-SuFF_o",
+ default)
+ .ConfigureAwait(false);
+ }
+
var pm = e.Channel is IPrivateChannel;
if (!pm && !mappedChannels.Contains(e.Channel.Id))
diff --git a/src/Tgstation.Server.Host/Controllers/AdministrationController.cs b/src/Tgstation.Server.Host/Controllers/AdministrationController.cs
index d689416fa9..bb68d12467 100644
--- a/src/Tgstation.Server.Host/Controllers/AdministrationController.cs
+++ b/src/Tgstation.Server.Host/Controllers/AdministrationController.cs
@@ -374,7 +374,7 @@ namespace Tgstation.Server.Host.Controllers
/// An IO error occurred while downloading.
[HttpGet(Routes.Logs + "/{*path}")]
[TgsAuthorize(AdministrationRights.DownloadLogs)]
- [ProducesResponseType(typeof(List), 200)]
+ [ProducesResponseType(typeof(LogFile), 200)]
[ProducesResponseType(typeof(ErrorMessage), 409)]
public async Task GetLog(string path, CancellationToken cancellationToken)
{
diff --git a/src/Tgstation.Server.Host/Controllers/ConfigurationController.cs b/src/Tgstation.Server.Host/Controllers/ConfigurationController.cs
index cecd5f2c93..3a76b8bc5b 100644
--- a/src/Tgstation.Server.Host/Controllers/ConfigurationController.cs
+++ b/src/Tgstation.Server.Host/Controllers/ConfigurationController.cs
@@ -1,4 +1,4 @@
-using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
@@ -291,6 +291,9 @@ namespace Tgstation.Server.Host.Controllers
if (directory == null)
throw new ArgumentNullException(nameof(directory));
+ if (directory.Path == null)
+ return BadRequest(new ErrorMessage(ErrorCode.ModelValidationFailure));
+
if (ForbidDueToModeConflicts(directory.Path, out var systemIdentity))
return Forbid();
diff --git a/src/Tgstation.Server.Host/Core/SwaggerConfiguration.cs b/src/Tgstation.Server.Host/Core/SwaggerConfiguration.cs
index 674ba28987..2266298ef6 100644
--- a/src/Tgstation.Server.Host/Core/SwaggerConfiguration.cs
+++ b/src/Tgstation.Server.Host/Core/SwaggerConfiguration.cs
@@ -128,7 +128,18 @@ namespace Tgstation.Server.Host.Core
new OpenApiInfo
{
Title = "TGS API",
- Version = ApiHeaders.Version.Semver().ToString()
+ Version = ApiHeaders.Version.Semver().ToString(),
+ License = new OpenApiLicense
+ {
+ Name = "AGPL-3.0",
+ Url = new Uri("https://github.com/tgstation/tgstation-server/blob/dev/LICENSE")
+ },
+ Contact = new OpenApiContact
+ {
+ Name = "/tg/station 13",
+ Url = new Uri("https://github.com/tgstation")
+ },
+ Description = "A production scale tool for BYOND server management"
});
// Important to do this before applying our own filters
@@ -136,6 +147,9 @@ namespace Tgstation.Server.Host.Core
swaggerGenOptions.IncludeXmlComments(assemblyDocumentationPath);
swaggerGenOptions.IncludeXmlComments(apiDocumentationPath);
+ // nullable stuff
+ swaggerGenOptions.UseAllOfToExtendReferenceSchemas();
+
swaggerGenOptions.OperationFilter();
swaggerGenOptions.DocumentFilter();
swaggerGenOptions.SchemaFilter();
@@ -337,15 +351,18 @@ namespace Tgstation.Server.Host.Core
// Nothing is required
schema.Required.Clear();
- if (!schema.Enum?.Any() ?? false)
- return;
-
// Could be nullable type, make sure to get the right one
- Type enumType = context.Type.IsConstructedGenericType
+ Type nonNullableType = context.Type.IsConstructedGenericType
? context.Type.GenericTypeArguments.First()
: context.Type;
- OpenApiEnumVarNamesExtension.Apply(schema, enumType);
+ if (nonNullableType != context.Type)
+ schema.Nullable = true;
+
+ if (!schema.Enum?.Any() ?? false)
+ return;
+
+ OpenApiEnumVarNamesExtension.Apply(schema, nonNullableType);
}
}
}
diff --git a/src/Tgstation.Server.Host/Tgstation.Server.Host.csproj b/src/Tgstation.Server.Host/Tgstation.Server.Host.csproj
index ba065d5aa6..cad2b4d249 100644
--- a/src/Tgstation.Server.Host/Tgstation.Server.Host.csproj
+++ b/src/Tgstation.Server.Host/Tgstation.Server.Host.csproj
@@ -48,20 +48,20 @@
-
-
-
+
+
+
all
runtime; build; native; contentfiles; analyzers
-
-
+
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
-
-
+
+
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
@@ -81,12 +81,12 @@
-
+
-
+