mirror of
https://github.com/tgstation/tgstation-server.git
synced 2026-08-23 13:07:07 +01:00
Merge pull request #824 from tgstation/4.0.1.4 [TGSDeploy]
Version 4.0.1.4
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||
<DebugType>Full</DebugType>
|
||||
<Version>4.0.1.3</Version>
|
||||
<Version>4.0.1.4</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||
|
||||
@@ -7,5 +7,5 @@ using System.Runtime.InteropServices;
|
||||
[assembly: Guid("29927416-3b78-49a7-a560-5ccaa638b6b4")]
|
||||
[assembly: InternalsVisibleTo("Tgstation.Server.Host.Service.Tests")]
|
||||
|
||||
[assembly: AssemblyVersion("4.0.1.3")]
|
||||
[assembly: AssemblyFileVersion("4.0.1.3")]
|
||||
[assembly: AssemblyVersion("4.0.1.4")]
|
||||
[assembly: AssemblyFileVersion("4.0.1.4")]
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<DebugType>Full</DebugType>
|
||||
<AddSyntheticProjectReferencesForSolutionDependencies>false</AddSyntheticProjectReferencesForSolutionDependencies>
|
||||
<Version>4.0.1.3</Version>
|
||||
<Version>4.0.1.4</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||
|
||||
@@ -38,12 +38,12 @@ namespace Tgstation.Server.Host.Components.Chat
|
||||
/// <summary>
|
||||
/// If this is considered a channel for admin commands
|
||||
/// </summary>
|
||||
public bool IsAdmin { get; set; }
|
||||
public bool IsAdminChannel { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If this is a 1-to-1 chat channel
|
||||
/// </summary>
|
||||
public bool IsPrivate { get; set; }
|
||||
public bool IsPrivateChannel { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// For user use
|
||||
|
||||
@@ -195,7 +195,7 @@ namespace Tgstation.Server.Host.Components.Chat
|
||||
{
|
||||
var providerId = providers.Where(x => x.Value == provider).Select(x => x.Key).First();
|
||||
var enumerable = mappedChannels.Where(x => x.Value.ProviderId == providerId && x.Value.ProviderChannelId == message.User.Channel.RealId);
|
||||
if (message.User.Channel.IsPrivate)
|
||||
if (message.User.Channel.IsPrivateChannel)
|
||||
lock (mappedChannels)
|
||||
{
|
||||
if (!provider.Connected)
|
||||
@@ -223,7 +223,7 @@ namespace Tgstation.Server.Host.Components.Chat
|
||||
var mapping = enumerable.First().Value;
|
||||
message.User.Channel.Id = mapping.Channel.Id;
|
||||
message.User.Channel.Tag = mapping.Channel.Tag;
|
||||
message.User.Channel.IsAdmin = mapping.Channel.IsAdmin;
|
||||
message.User.Channel.IsAdminChannel = mapping.Channel.IsAdminChannel;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -236,7 +236,7 @@ namespace Tgstation.Server.Host.Components.Chat
|
||||
|
||||
var addressed = address == CommonMention.ToUpperInvariant() || address == provider.BotMention.ToUpperInvariant();
|
||||
|
||||
if (!addressed && !message.User.Channel.IsPrivate)
|
||||
if (!addressed && !message.User.Channel.IsPrivateChannel)
|
||||
//no mention
|
||||
return;
|
||||
|
||||
@@ -302,7 +302,7 @@ namespace Tgstation.Server.Host.Components.Chat
|
||||
return;
|
||||
}
|
||||
|
||||
if (commandHandler.AdminOnly && !message.User.Channel.IsAdmin)
|
||||
if (commandHandler.AdminOnly && !message.User.Channel.IsAdminChannel)
|
||||
{
|
||||
await SendMessage("Use this command in an admin channel!", new List<ulong> { message.User.Channel.RealId }, cancellationToken).ConfigureAwait(false);
|
||||
return;
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace Tgstation.Server.Host.Components.Chat.Commands
|
||||
string HelpText { get; }
|
||||
|
||||
/// <summary>
|
||||
/// If the command should only be available to <see cref="User"/>s who's <see cref="User.Channel"/> has <see cref="Channel.IsAdmin"/> set
|
||||
/// If the command should only be available to <see cref="User"/>s who's <see cref="User.Channel"/> has <see cref="Channel.IsAdminChannel"/> set
|
||||
/// </summary>
|
||||
bool AdminOnly { get; }
|
||||
|
||||
|
||||
@@ -97,7 +97,7 @@ namespace Tgstation.Server.Host.Components.Chat.Providers
|
||||
Channel = new Channel
|
||||
{
|
||||
RealId = e.Channel.Id,
|
||||
IsPrivate = pm,
|
||||
IsPrivateChannel = pm,
|
||||
ConnectionName = pm ? e.Author.Username : (e.Channel as ITextChannel)?.Guild.Name ?? "UNKNOWN",
|
||||
FriendlyName = e.Channel.Name
|
||||
//isAdmin and Tag populated by manager
|
||||
@@ -188,10 +188,10 @@ namespace Tgstation.Server.Host.Components.Chat.Providers
|
||||
return new Channel
|
||||
{
|
||||
RealId = discordChannel.Id,
|
||||
IsAdmin = channel.IsAdminChannel == true,
|
||||
IsAdminChannel = channel.IsAdminChannel == true,
|
||||
ConnectionName = discordChannel.Guild.Name,
|
||||
FriendlyName = discordChannel.Name,
|
||||
IsPrivate = false,
|
||||
IsPrivateChannel = false,
|
||||
Tag = channel.Tag
|
||||
};
|
||||
};
|
||||
|
||||
@@ -204,7 +204,7 @@ namespace Tgstation.Server.Host.Components.Chat.Providers
|
||||
ConnectionName = address,
|
||||
FriendlyName = isPrivate ? String.Format(CultureInfo.InvariantCulture, "PM: {0}", channelName) : channelName,
|
||||
RealId = channelId,
|
||||
IsPrivate = isPrivate
|
||||
IsPrivateChannel = isPrivate
|
||||
//isAdmin and Tag populated by manager
|
||||
},
|
||||
FriendlyName = username,
|
||||
@@ -393,10 +393,10 @@ namespace Tgstation.Server.Host.Components.Chat.Providers
|
||||
return new Channel
|
||||
{
|
||||
RealId = id.Value,
|
||||
IsAdmin = x.IsAdminChannel == true,
|
||||
IsAdminChannel = x.IsAdminChannel == true,
|
||||
ConnectionName = address,
|
||||
FriendlyName = channelIdMap[id.Value],
|
||||
IsPrivate = false,
|
||||
IsPrivateChannel = false,
|
||||
Tag = x.Tag
|
||||
};
|
||||
}).ToList();
|
||||
|
||||
@@ -12,7 +12,7 @@ using Tgstation.Server.Host.IO;
|
||||
namespace Tgstation.Server.Host.Components
|
||||
{
|
||||
/// <inheritdoc />
|
||||
sealed class InstanceManager : IInstanceManager, IHostedService, IDisposable
|
||||
sealed class InstanceManager : IInstanceManager, IRestartHandler, IHostedService, IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// The <see cref="IInstanceFactory"/> for the <see cref="InstanceManager"/>
|
||||
@@ -49,6 +49,11 @@ namespace Tgstation.Server.Host.Components
|
||||
/// </summary>
|
||||
readonly Dictionary<long, IInstance> instances;
|
||||
|
||||
/// <summary>
|
||||
/// Used in <see cref="StopAsync(CancellationToken)"/> to determine if database downgrades must be made
|
||||
/// </summary>
|
||||
Version downgradeVersion;
|
||||
|
||||
/// <summary>
|
||||
/// If the <see cref="InstanceManager"/> has been <see cref="Dispose"/>d
|
||||
/// </summary>
|
||||
@@ -62,16 +67,21 @@ namespace Tgstation.Server.Host.Components
|
||||
/// <param name="databaseContextFactory">The value of <paramref name="databaseContextFactory"/></param>
|
||||
/// <param name="application">The value of <see cref="application"/></param>
|
||||
/// <param name="jobManager">The value of <see cref="jobManager"/></param>
|
||||
/// <param name="serverControl">The <see cref="IServerControl"/> used to register the <see cref="InstanceManager"/> as a <see cref="IRestartHandler"/></param>
|
||||
/// <param name="logger">The value of <see cref="logger"/></param>
|
||||
public InstanceManager(IInstanceFactory instanceFactory, IIOManager ioManager, IDatabaseContextFactory databaseContextFactory, IApplication application, IJobManager jobManager, ILogger<InstanceManager> logger)
|
||||
public InstanceManager(IInstanceFactory instanceFactory, IIOManager ioManager, IDatabaseContextFactory databaseContextFactory, IApplication application, IJobManager jobManager, IServerControl serverControl, ILogger<InstanceManager> logger)
|
||||
{
|
||||
this.instanceFactory = instanceFactory ?? throw new ArgumentNullException(nameof(instanceFactory));
|
||||
this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
|
||||
this.databaseContextFactory = databaseContextFactory ?? throw new ArgumentNullException(nameof(databaseContextFactory));
|
||||
this.application = application ?? throw new ArgumentNullException(nameof(application));
|
||||
this.jobManager = jobManager ?? throw new ArgumentNullException(nameof(jobManager));
|
||||
if (serverControl == null)
|
||||
throw new ArgumentNullException(nameof(serverControl));
|
||||
this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
|
||||
serverControl.RegisterForRestart(this);
|
||||
|
||||
instances = new Dictionary<long, IInstance>();
|
||||
}
|
||||
|
||||
@@ -225,6 +235,17 @@ namespace Tgstation.Server.Host.Components
|
||||
await jobManager.StopAsync(cancellationToken).ConfigureAwait(false);
|
||||
await Task.WhenAll(instances.Select(x => x.Value.StopAsync(cancellationToken))).ConfigureAwait(false);
|
||||
await instanceFactory.StopAsync(cancellationToken).ConfigureAwait(false);
|
||||
|
||||
//downgrade the db if necessary
|
||||
if (downgradeVersion != null)
|
||||
await databaseContextFactory.UseContext(db => db.SchemaDowngradeForServerVersion(downgradeVersion, cancellationToken)).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task HandleRestart(Version updateVersion, CancellationToken cancellationToken)
|
||||
{
|
||||
downgradeVersion = updateVersion != null && updateVersion < application.Version ? updateVersion : null;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace Tgstation.Server.Host.Components.Interop
|
||||
sealed class ChatCommand
|
||||
{
|
||||
public string Command { get; set; }
|
||||
public string Parameters { get; set; }
|
||||
public string Params { get; set; }
|
||||
public User User { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace Tgstation.Server.Host.Components.Interop
|
||||
/// <summary>
|
||||
/// The dictionary of the <see cref="CommCommand"/>
|
||||
/// </summary>
|
||||
public IReadOnlyDictionary<string, string> Parameters { get; set; }
|
||||
public IReadOnlyDictionary<string, object> Parameters { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The raw JSON of the <see cref="CommCommand"/>
|
||||
|
||||
@@ -109,7 +109,7 @@ namespace Tgstation.Server.Host.Components.Interop
|
||||
{
|
||||
command = new CommCommand
|
||||
{
|
||||
Parameters = JsonConvert.DeserializeObject<IReadOnlyDictionary<string, string>>(file),
|
||||
Parameters = JsonConvert.DeserializeObject<IReadOnlyDictionary<string, object>>(file),
|
||||
RawJson = file
|
||||
};
|
||||
}
|
||||
|
||||
@@ -221,6 +221,8 @@ namespace Tgstation.Server.Host.Components.Watchdog
|
||||
return result;
|
||||
};
|
||||
LaunchResult = GetLaunchResult();
|
||||
|
||||
logger.LogDebug("Created session controller. Primary: {0}, CommsKey: {1}, Port: {2}", IsPrimary, reattachInformation.AccessIdentifier, Port);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -316,7 +318,7 @@ namespace Tgstation.Server.Host.Components.Watchdog
|
||||
case Constants.DMCommandNewPort:
|
||||
lock (this)
|
||||
{
|
||||
if (!query.TryGetValue(Constants.DMParameterData, out var stringPort) || !UInt16.TryParse(stringPort, out var currentPort))
|
||||
if (!query.TryGetValue(Constants.DMParameterData, out var stringPortObject) || !UInt16.TryParse(stringPortObject as string, out var currentPort))
|
||||
{
|
||||
/////UHHHH
|
||||
logger.LogWarning("DreamDaemon sent new port command without providing it's own!");
|
||||
@@ -354,7 +356,7 @@ namespace Tgstation.Server.Host.Components.Watchdog
|
||||
content = new ErrorMessage { Message = "Invalid API validation request!" };
|
||||
break;
|
||||
}
|
||||
if (!query.TryGetValue(Constants.DMParameterData, out var stringMinimumSecurityLevel) || !Enum.TryParse<DreamDaemonSecurity>(stringMinimumSecurityLevel, out var minimumSecurityLevel))
|
||||
if (!query.TryGetValue(Constants.DMParameterData, out var stringMinimumSecurityLevelObject) || !Enum.TryParse<DreamDaemonSecurity>(stringMinimumSecurityLevelObject as string, out var minimumSecurityLevel))
|
||||
apiValidationStatus = ApiValidationStatus.BadValidationRequest;
|
||||
else
|
||||
switch (minimumSecurityLevel)
|
||||
@@ -479,6 +481,7 @@ namespace Tgstation.Server.Host.Components.Watchdog
|
||||
return false;
|
||||
}
|
||||
|
||||
reattachInformation.Port = port;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -453,20 +453,13 @@ namespace Tgstation.Server.Host.Components.Watchdog
|
||||
|
||||
//servers now swapped
|
||||
|
||||
//enable this now
|
||||
monitorState.ActiveServer.ClosePortOnReboot = true;
|
||||
//enable this now if inactive server is not still valid
|
||||
monitorState.ActiveServer.ClosePortOnReboot = restartOnceSwapped;
|
||||
|
||||
if (!restartOnceSwapped)
|
||||
{
|
||||
//inactive server still valid
|
||||
|
||||
//disable this
|
||||
monitorState.InactiveServer.ClosePortOnReboot = false;
|
||||
|
||||
//now try to reopen it on the private port
|
||||
//failing that, just reboot it
|
||||
restartOnceSwapped = !await monitorState.InactiveServer.SetPort(ActiveLaunchParameters.SecondaryPort.Value, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
//break either way because any issues past this point would be solved by the reboot
|
||||
if (restartOnceSwapped)
|
||||
@@ -1059,7 +1052,7 @@ namespace Tgstation.Server.Host.Components.Watchdog
|
||||
var commandObject = new ChatCommand
|
||||
{
|
||||
Command = commandName,
|
||||
Parameters = arguments,
|
||||
Params = arguments,
|
||||
User = sender
|
||||
};
|
||||
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
@@ -169,5 +173,51 @@ namespace Tgstation.Server.Host.Models
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task Save(CancellationToken cancellationToken) => SaveChangesAsync(cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// If the MY_ class of migrations should be used instead of the MS_ class
|
||||
/// </summary>
|
||||
/// <returns><see langword="true"/> if the MY_ class of migrations should be used instead of the MS_ class, <see langword="false"/> otherwise</returns>
|
||||
protected abstract bool UseMySQLMigrations();
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task SchemaDowngradeForServerVersion(Version version, CancellationToken cancellationToken)
|
||||
{
|
||||
if (version == null)
|
||||
throw new ArgumentNullException(nameof(version));
|
||||
if (version < new Version(4, 0))
|
||||
throw new ArgumentOutOfRangeException(nameof(version), version, "Not a valid V4 version!");
|
||||
|
||||
string targetMigration = null;
|
||||
|
||||
//Update this with new migrations as they are made
|
||||
//Always use the MS class
|
||||
|
||||
//TODO: Uncomment once #816 is merged
|
||||
/*
|
||||
if (version < new Version(4, 0, 2))
|
||||
targetMigration = nameof(MSReattachCompileJobRequired);
|
||||
*/
|
||||
|
||||
if (targetMigration == null)
|
||||
return;
|
||||
|
||||
if (UseMySQLMigrations())
|
||||
targetMigration = String.Format(CultureInfo.InvariantCulture, "MY" + targetMigration.Substring(2));
|
||||
|
||||
//even though it clearly implements it in the DatabaseFacade definition this won't work without casting (╯ಠ益ಠ)╯︵ ┻━┻
|
||||
var dbServiceProvider = ((IInfrastructure<IServiceProvider>)Database).Instance;
|
||||
var migrator = dbServiceProvider.GetRequiredService<IMigrator>();
|
||||
|
||||
Logger.LogInformation("Migrating down to version {0}. Target: {1}", version, targetMigration);
|
||||
try
|
||||
{
|
||||
await migrator.MigrateAsync(targetMigration, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.LogCritical("Failed to migrate! Exception: {0}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@@ -87,5 +88,13 @@ namespace Tgstation.Server.Host.Models
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation</param>
|
||||
/// <returns>A <see cref="Task"/> representing the running operation</returns>
|
||||
Task Initialize(CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Attempt to downgrade the schema to the migration used for a given server <paramref name="version"/>
|
||||
/// </summary>
|
||||
/// <param name="version">The tgstation-server <see cref="Version"/> that the schema should downgrade for</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation</param>
|
||||
/// <returns>A <see cref="Task"/> representing the running operation</returns>
|
||||
Task SchemaDowngradeForServerVersion(Version version, CancellationToken cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,5 +38,8 @@ namespace Tgstation.Server.Host.Models
|
||||
else
|
||||
options.UseMySql(DatabaseConfiguration.ConnectionString);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override bool UseMySQLMigrations() => true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,5 +26,8 @@ namespace Tgstation.Server.Host.Models
|
||||
base.OnConfiguring(options);
|
||||
options.UseSqlServer(DatabaseConfiguration.ConnectionString);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override bool UseMySQLMigrations() => false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||
<DebugType>Full</DebugType>
|
||||
<Version>4.0.1.3</Version>
|
||||
<Version>4.0.1.4</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||
|
||||
Reference in New Issue
Block a user