mirror of
https://github.com/tgstation/tgstation-server.git
synced 2026-08-27 07:04:57 +01:00
+5
-1
@@ -16,12 +16,15 @@ configuration:
|
||||
shallow_clone: true
|
||||
artifacts:
|
||||
- path: artifacts/ServerConsole
|
||||
name: Server Console
|
||||
- path: artifacts/ServerService
|
||||
name: Server Service
|
||||
cache:
|
||||
- ~\.nuget\packages -> **\*.csproj
|
||||
- C:\ProgramData\chocolatey\bin -> appveyor.yml
|
||||
- C:\ProgramData\chocolatey\lib -> appveyor.yml
|
||||
install:
|
||||
- choco install fciv doxygen.portable codecov
|
||||
- choco install doxygen.portable codecov
|
||||
- nuget restore tgstation-server.sln
|
||||
build:
|
||||
project: tgstation-server.sln
|
||||
@@ -53,6 +56,7 @@ after_test:
|
||||
- ps: build/UploadCoverage.ps1
|
||||
- ps: build/BuildDox.ps1
|
||||
- dotnet publish src/Tgstation.Server.Host.Console/Tgstation.Server.Host.Console.csproj -o ../../artifacts/ServerConsole -c %CONFIGURATION%
|
||||
- ps: Copy-Item -path "src/Tgstation.Server.Host.Service/bin/$env:CONFIGURATION" -destination ../../artifacts/ServerService -recurse
|
||||
deploy:
|
||||
- provider: GitHub
|
||||
release: "tgstation-server-v$(TGSVersion)"
|
||||
|
||||
@@ -5,14 +5,8 @@ using Tgstation.Server.Api.Rights;
|
||||
namespace Tgstation.Server.Api.Models
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public sealed class Administration : Internal.ServerSettings
|
||||
public sealed class Administration
|
||||
{
|
||||
/// <summary>
|
||||
/// If the <see cref="DreamDaemon"/> instances will not be stopped when the server exits. Resets to <see langword="false"/> when the server restarts
|
||||
/// </summary>
|
||||
[Permissions(ReadRight = AdministrationRights.SoftStop, WriteRight = AdministrationRights.SoftStop)]
|
||||
public bool SoftStop { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The latest available version of the Tgstation.Server.Host assembly from the upstream repository. If <see cref="Version.Minor"/> is higher than <see cref="CurrentVersion"/>'s the update cannot be applied due to API changes
|
||||
/// </summary>
|
||||
|
||||
@@ -9,22 +9,10 @@ namespace Tgstation.Server.Api.Models
|
||||
[Model(RightsType.Byond, RequiresInstance = true)]
|
||||
public sealed class Byond
|
||||
{
|
||||
/// <summary>
|
||||
/// The <see cref="ByondStatus"/> for the <see cref="Byond"/> installation
|
||||
/// </summary>
|
||||
[Permissions(DenyWrite = true, ReadRight = ByondRights.ReadStatus)]
|
||||
public ByondStatus ByondStatus { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="System.Version"/> of the <see cref="Byond"/> installation used for new compiles. Will be <see langword="null"/> if the user does not have permission to view it or there is no BYOND version installed. Only considers the <see cref="Version.Major"/> and <see cref="Version.Minor"/> numbers
|
||||
/// </summary>
|
||||
[Permissions(ReadRight = ByondRights.ReadInstalled, WriteRight = ByondRights.ChangeVersion)]
|
||||
[Permissions(ReadRight = ByondRights.ReadActive, WriteRight = ByondRights.ChangeVersion)]
|
||||
public Version Version { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="System.Version"/> of the <see cref="Byond"/> that's currently running the game servers
|
||||
/// </summary>
|
||||
[Permissions(DenyWrite = true, ReadRight = ByondRights.ReadPrevious)]
|
||||
public Version PreviousVersion { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
namespace Tgstation.Server.Api.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// The status of a <see cref="Byond"/> update job
|
||||
/// </summary>
|
||||
#pragma warning disable CA1717 // Only FlagsAttribute enums should have plural names
|
||||
public enum ByondStatus
|
||||
#pragma warning restore CA1717 // Only FlagsAttribute enums should have plural names
|
||||
{
|
||||
/// <summary>
|
||||
/// No update in progress
|
||||
/// </summary>
|
||||
Idle,
|
||||
/// <summary>
|
||||
/// Preparing to update
|
||||
/// </summary>
|
||||
Starting,
|
||||
/// <summary>
|
||||
/// Revision is downloading
|
||||
/// </summary>
|
||||
Downloading,
|
||||
/// <summary>
|
||||
/// Revision is deflating
|
||||
/// </summary>
|
||||
Staging,
|
||||
/// <summary>
|
||||
/// Revision is ready and waiting for DreamDaemon reboot
|
||||
/// </summary>
|
||||
Staged,
|
||||
/// <summary>
|
||||
/// Revision is being applied
|
||||
/// </summary>
|
||||
Updating,
|
||||
/// <summary>
|
||||
/// User does not have permission to view the <see cref="ByondStatus"/>
|
||||
/// </summary>
|
||||
Hidden,
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
using Tgstation.Server.Api.Rights;
|
||||
|
||||
namespace Tgstation.Server.Api.Models.Internal
|
||||
{
|
||||
/// <summary>
|
||||
/// Metadata about an installation
|
||||
/// </summary>
|
||||
[Model(RightsType.Administration)]
|
||||
public class ServerSettings
|
||||
{
|
||||
/// <summary>
|
||||
/// Automatically send unhandled exception data to a public collection service. This will be limited to system information, path data, and game code compilation information.
|
||||
/// </summary>
|
||||
[Permissions(ReadRight = AdministrationRights.ChangeTelemetry, WriteRight = AdministrationRights.ChangeTelemetry)]
|
||||
public bool EnableTelemetry { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The git repository URL to recieve updates to Tgstation.Server.Host from, must include credentials if necessary. If set to <see langword="null"/> upstream pulls will be disabled entirely. Should be https://github.com/tgstation/tgstation-server or a fork of it
|
||||
/// </summary>
|
||||
[Permissions(ReadRight = AdministrationRights.SetUpstreamRepository, WriteRight = AdministrationRights.SetUpstreamRepository)]
|
||||
public string UpstreamRepository { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -13,24 +13,16 @@ namespace Tgstation.Server.Api.Rights
|
||||
/// </summary>
|
||||
None = 0,
|
||||
/// <summary>
|
||||
/// User can change <see cref="Models.Internal.ServerSettings.UpstreamRepository"/>
|
||||
/// </summary>
|
||||
SetUpstreamRepository = 1,
|
||||
/// <summary>
|
||||
/// User can change <see cref="Models.Internal.ServerSettings.EnableTelemetry"/>
|
||||
/// </summary>
|
||||
ChangeTelemetry = 2,
|
||||
/// <summary>
|
||||
/// User can edit themself and other <see cref="Models.User"/>s
|
||||
/// </summary>
|
||||
EditUsers = 4,
|
||||
EditUsers = 1,
|
||||
/// <summary>
|
||||
/// User can change <see cref="Models.Administration.SoftStop"/>
|
||||
/// User can gracefully restart the host
|
||||
/// </summary>
|
||||
SoftStop = 8,
|
||||
SoftStop = 2,
|
||||
/// <summary>
|
||||
/// User can change <see cref="Models.Administration.CurrentVersion"/>
|
||||
/// </summary>
|
||||
ChangeVersion = 16
|
||||
ChangeVersion = 4
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,24 +13,12 @@ namespace Tgstation.Server.Api.Rights
|
||||
/// </summary>
|
||||
None = 0,
|
||||
/// <summary>
|
||||
/// User may check the installed BYOND version
|
||||
/// User may check the active installed BYOND version
|
||||
/// </summary>
|
||||
ReadInstalled = 1,
|
||||
/// <summary>
|
||||
/// User may check the previous BYOND version
|
||||
/// </summary>
|
||||
ReadPrevious = 2,
|
||||
ReadActive = 1,
|
||||
/// <summary>
|
||||
/// User may change to any BYOND version
|
||||
/// </summary>
|
||||
ChangeVersion = 4,
|
||||
/// <summary>
|
||||
/// User may cancel a pending installation job
|
||||
/// </summary>
|
||||
Cancel = 8,
|
||||
/// <summary>
|
||||
/// User may read the <see cref="Models.ByondStatus"/> of the installation job
|
||||
/// </summary>
|
||||
ReadStatus = 16,
|
||||
ChangeVersion = 4
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,10 +21,9 @@ namespace Tgstation.Server.Client.Components
|
||||
/// <summary>
|
||||
/// Updates the installed BYOND <see cref="Version"/>
|
||||
/// </summary>
|
||||
/// <param name="byond">The <see cref="Byond"/> to update</param>
|
||||
/// <param name="progressCallback">Optional <see cref="Action{T1}"/> taking a <see cref="ByondStatus"/> to run when it changes</param>
|
||||
/// <param name="version">The <see cref="Version"/> to set to active</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation</param>
|
||||
/// <returns>A <see cref="Task"/> representing the running operation</returns>
|
||||
Task Update(Byond byond, Action<ByondStatus> progressCallback, CancellationToken cancellationToken);
|
||||
Task SetActiveVersion(Version version, CancellationToken cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
using System;
|
||||
|
||||
namespace Tgstation.Server.Host.Components
|
||||
{
|
||||
/// <inheritdoc />
|
||||
sealed class ByondExecutableLock : IByondExecutableLock
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public Version Version { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public string DreamDaemonPath { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public string DreamMakerPath { get; set; }
|
||||
|
||||
//at one point in design, byond versions were to delete themselves if they werent the active version
|
||||
//That changed at some point so these functions are intentioanlly left blank
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Dispose() { }
|
||||
|
||||
/// <inheritdoc />
|
||||
public void DoNotDeleteThisSession() { }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Tgstation.Server.Host.IO;
|
||||
|
||||
using MemoryStream = System.IO.MemoryStream;
|
||||
|
||||
namespace Tgstation.Server.Host.Components
|
||||
{
|
||||
/// <inheritdoc />
|
||||
sealed class ByondManager : IByondManager
|
||||
{
|
||||
const string VersionFileName = "Version.txt";
|
||||
const string ActiveVersionFileName = "ActiveVersion.txt";
|
||||
|
||||
const string BinPath = "byond/bin";
|
||||
|
||||
/// <inheritdoc />
|
||||
public Version ActiveVersion { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="IIOManager"/> for the <see cref="ByondManager"/>
|
||||
/// </summary>
|
||||
readonly IIOManager ioManager;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="IByondInstaller"/> for the <see cref="ByondManager"/>
|
||||
/// </summary>
|
||||
readonly IByondInstaller byondInstaller;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="ILogger"/> for the <see cref="ByondManager"/>
|
||||
/// </summary>
|
||||
readonly ILogger<ByondManager> logger;
|
||||
|
||||
/// <summary>
|
||||
/// Map of byond <see cref="Version"/>s to <see cref="Task"/>s that complete when they are installed
|
||||
/// </summary>
|
||||
readonly Dictionary<string, Task> installedVersions;
|
||||
|
||||
/// <summary>
|
||||
/// Construct a <see cref="ByondManager"/>
|
||||
/// </summary>
|
||||
/// <param name="ioManager">The value of <see cref="ioManager"/></param>
|
||||
/// <param name="byondInstaller">The value of <see cref="byondInstaller"/></param>
|
||||
/// <param name="logger">The value of <see cref="logger"/></param>
|
||||
public ByondManager(IIOManager ioManager, IByondInstaller byondInstaller, ILogger<ByondManager> logger)
|
||||
{
|
||||
this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
|
||||
this.byondInstaller = byondInstaller ?? throw new ArgumentNullException(nameof(byondInstaller));
|
||||
this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
|
||||
installedVersions = new Dictionary<string, Task>();
|
||||
}
|
||||
|
||||
static string VersionKey(Version version) => new Version(version.Major, version.Minor).ToString();
|
||||
|
||||
async Task InstallVersion(Version version, CancellationToken cancellationToken)
|
||||
{
|
||||
var ourTcs = new TaskCompletionSource<object>();
|
||||
Task inProgressTask;
|
||||
|
||||
var versionKey = VersionKey(version);
|
||||
bool installed;
|
||||
lock (installedVersions)
|
||||
{
|
||||
installed = installedVersions.TryGetValue(versionKey, out inProgressTask);
|
||||
if (!installed)
|
||||
installedVersions.Add(versionKey, ourTcs.Task);
|
||||
}
|
||||
if(installed)
|
||||
using (cancellationToken.Register(() => ourTcs.SetCanceled()))
|
||||
{
|
||||
await Task.WhenAny(ourTcs.Task, inProgressTask).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
var downloadTask = byondInstaller.DownloadVersion(version, cancellationToken);
|
||||
|
||||
//okay up to us to install it then
|
||||
await ioManager.DeleteDirectory(versionKey, cancellationToken).ConfigureAwait(false);
|
||||
await ioManager.CreateDirectory(versionKey, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
var resolvedPath = ioManager.ResolvePath(versionKey);
|
||||
using (var zipBytes = new MemoryStream(await downloadTask.ConfigureAwait(false)))
|
||||
using (var archive = new ZipArchive(zipBytes))
|
||||
await Task.Factory.StartNew(() => archive.ExtractToDirectory(resolvedPath), cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current).ConfigureAwait(false);
|
||||
|
||||
await byondInstaller.InstallByond(resolvedPath, version, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
//make sure to do this last because this is what tells us we have a valid version
|
||||
await ioManager.WriteAllBytes(ioManager.ConcatPath(versionKey, VersionFileName), Encoding.UTF8.GetBytes(version.ToString()), cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task ChangeVersion(Version version, CancellationToken cancellationToken)
|
||||
{
|
||||
await InstallVersion(version, cancellationToken).ConfigureAwait(false);
|
||||
await ioManager.WriteAllBytes(ActiveVersionFileName, Encoding.UTF8.GetBytes(version.ToString()), cancellationToken).ConfigureAwait(false);
|
||||
ActiveVersion = version;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<IByondExecutableLock> UseExecutables(Version requiredVersion, CancellationToken cancellationToken)
|
||||
{
|
||||
var versionToUse = requiredVersion ?? ActiveVersion;
|
||||
if (versionToUse == null)
|
||||
throw new InvalidOperationException("No BYOND versions installed!");
|
||||
await InstallVersion(requiredVersion, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
var versionKey = VersionKey(versionToUse);
|
||||
|
||||
return new ByondExecutableLock
|
||||
{
|
||||
DreamDaemonPath = ioManager.ResolvePath(ioManager.ConcatPath(versionKey, BinPath, byondInstaller.DreamDaemonName)),
|
||||
DreamMakerPath = ioManager.ResolvePath(ioManager.ConcatPath(versionKey, BinPath, byondInstaller.DreamMakerName)),
|
||||
Version = versionToUse
|
||||
};
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var cacheCleanTask = byondInstaller.CleanCache(cancellationToken);
|
||||
|
||||
var activeVersionBytesTask = ioManager.ReadAllBytes(ActiveVersionFileName, cancellationToken);
|
||||
|
||||
var directories = await ioManager.GetDirectories(".", cancellationToken).ConfigureAwait(false);
|
||||
|
||||
async Task ReadVersion(string path)
|
||||
{
|
||||
var bytes = await ioManager.ReadAllBytes(ioManager.ConcatPath(path, VersionFileName), cancellationToken).ConfigureAwait(false);
|
||||
var text = Encoding.UTF8.GetString(bytes);
|
||||
if (Version.TryParse(text, out var version))
|
||||
{
|
||||
var key = VersionKey(version);
|
||||
lock (installedVersions)
|
||||
if (!installedVersions.ContainsKey(key))
|
||||
{
|
||||
installedVersions.Add(key, Task.CompletedTask);
|
||||
return;
|
||||
}
|
||||
}
|
||||
await ioManager.DeleteDirectory(path, cancellationToken).ConfigureAwait(false);
|
||||
};
|
||||
|
||||
await Task.WhenAll(directories.Select(x => ReadVersion(x))).ConfigureAwait(false);
|
||||
|
||||
var activeVersionString = Encoding.UTF8.GetString(await activeVersionBytesTask.ConfigureAwait(false));
|
||||
if (Version.TryParse(activeVersionString, out var activeVersion))
|
||||
ActiveVersion = activeVersion;
|
||||
else
|
||||
await ioManager.DeleteFile(ActiveVersionFileName, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
await cacheCleanTask.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
@@ -39,9 +39,9 @@ namespace Tgstation.Server.Host.Components
|
||||
public CompilerStatus Status { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="IByond"/> for <see cref="DreamMaker"/>
|
||||
/// The <see cref="IByondManager"/> for <see cref="DreamMaker"/>
|
||||
/// </summary>
|
||||
readonly IByond byond;
|
||||
readonly IByondManager byond;
|
||||
/// <summary>
|
||||
/// The <see cref="IIOManager"/> for <see cref="DreamMaker"/>
|
||||
/// </summary>
|
||||
@@ -82,7 +82,7 @@ namespace Tgstation.Server.Host.Components
|
||||
/// <param name="application">The value of <see cref="application"/></param>
|
||||
/// <param name="eventConsumer">The value of <see cref="eventConsumer"/></param>
|
||||
/// <param name="logger">The value of <see cref="logger"/></param>
|
||||
public DreamMaker(IByond byond, IIOManager ioManager, IConfiguration configuration, ISessionControllerFactory sessionControllerFactory, ICompileJobConsumer compileJobConsumer, IApplication application, IEventConsumer eventConsumer, ILogger<DreamMaker> logger)
|
||||
public DreamMaker(IByondManager byond, IIOManager ioManager, IConfiguration configuration, ISessionControllerFactory sessionControllerFactory, ICompileJobConsumer compileJobConsumer, IApplication application, IEventConsumer eventConsumer, ILogger<DreamMaker> logger)
|
||||
{
|
||||
this.byond = byond;
|
||||
this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
|
||||
@@ -274,7 +274,7 @@ namespace Tgstation.Server.Host.Components
|
||||
|
||||
//run compiler, verify api
|
||||
bool ddVerified;
|
||||
using (var byondLock = byond.UseExecutables(null))
|
||||
using (var byondLock = await byond.UseExecutables(null, cancellationToken).ConfigureAwait(false))
|
||||
{
|
||||
job.ByondVersion = byondLock.Version.ToString();
|
||||
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Tgstation.Server.Host.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// For downloading and installing BYOND extractions for a given system
|
||||
/// </summary>
|
||||
interface IByondInstaller
|
||||
{
|
||||
/// <summary>
|
||||
/// Get the file name of the DreamDaemon executable
|
||||
/// </summary>
|
||||
string DreamDaemonName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Get the file name of the DreamMaker executable
|
||||
/// </summary>
|
||||
string DreamMakerName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Download a given BYOND <paramref name="version"/>
|
||||
/// </summary>
|
||||
/// <param name="version">The <see cref="Version"/> of BYOND to download</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation</param>
|
||||
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="byte"/>s of the zipfile</returns>
|
||||
Task<byte[]> DownloadVersion(Version version, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Does actions necessary to get an extracted BYOND installation working
|
||||
/// </summary>
|
||||
/// <param name="path">The path to the BYOND installation</param>
|
||||
/// <param name="version">The <see cref="Version"/> of BYOND being installed</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation</param>
|
||||
/// <returns></returns>
|
||||
Task InstallByond(string path, Version version, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to cleans the BYOND cache folder for the system
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation</param>
|
||||
/// <returns>A <see cref="Task"/> representing the running operation</returns>
|
||||
Task CleanCache(CancellationToken cancellationToken);
|
||||
}
|
||||
}
|
||||
+11
-17
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@@ -7,33 +8,26 @@ namespace Tgstation.Server.Host.Components
|
||||
/// <summary>
|
||||
/// For managing the BYOND installation
|
||||
/// </summary>
|
||||
public interface IByond
|
||||
public interface IByondManager : IHostedService
|
||||
{
|
||||
/// <summary>
|
||||
/// Change the current BYOND version
|
||||
/// The currently active BYOND version
|
||||
/// </summary>
|
||||
Version ActiveVersion { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Change the active BYOND version
|
||||
/// </summary>
|
||||
/// <param name="version">The new <see cref="Version"/></param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation</param>
|
||||
Task ChangeVersion(Version version, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Get the currently installed BYOND version
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation</param>
|
||||
/// <returns>The current BYOND version</returns>
|
||||
Task<Version> GetVersion(CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Lock the current installation's location and return a <see cref="IByondExecutableLock"/>
|
||||
/// </summary>
|
||||
/// <param name="requiredVersion">The BYOND <see cref="Version"/> required</param>
|
||||
IByondExecutableLock UseExecutables(Version requiredVersion);
|
||||
|
||||
/// <summary>
|
||||
/// Clears the cache folder
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation</param>
|
||||
/// <returns>A <see cref="Task"/> representing the running operation</returns>
|
||||
Task ClearCache(CancellationToken cancellationToken);
|
||||
/// <returns>A <see cref="Task{TResult}"/> resulting in the requested <see cref="IByondExecutableLock"/></returns>
|
||||
Task<IByondExecutableLock> UseExecutables(Version requiredVersion, CancellationToken cancellationToken);
|
||||
}
|
||||
}
|
||||
@@ -16,9 +16,9 @@ namespace Tgstation.Server.Host.Components
|
||||
IRepositoryManager RepositoryManager { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="IByond"/> for the <see cref="IInstance"/>
|
||||
/// The <see cref="IByondManager"/> for the <see cref="IInstance"/>
|
||||
/// </summary>
|
||||
IByond Byond { get; }
|
||||
IByondManager ByondManager { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="IDreamMaker"/> for the <see cref="IInstance"/>
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace Tgstation.Server.Host.Components
|
||||
public IRepositoryManager RepositoryManager { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public IByond Byond { get; }
|
||||
public IByondManager ByondManager { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public IDreamMaker DreamMaker { get; }
|
||||
@@ -59,11 +59,11 @@ namespace Tgstation.Server.Host.Components
|
||||
/// </summary>
|
||||
CancellationTokenSource timerCts;
|
||||
|
||||
public Instance(Api.Models.Instance metadata, IRepositoryManager repositoryManager, IByond byond, IDreamMaker dreamMaker, IWatchdog watchdog, IChat chat, IConfiguration configuration, ICompileJobConsumer compileJobConsumer, IDatabaseContextFactory databaseContextFactory, IDmbFactory dmbFactory)
|
||||
public Instance(Api.Models.Instance metadata, IRepositoryManager repositoryManager, IByondManager byondManager, IDreamMaker dreamMaker, IWatchdog watchdog, IChat chat, IConfiguration configuration, ICompileJobConsumer compileJobConsumer, IDatabaseContextFactory databaseContextFactory, IDmbFactory dmbFactory)
|
||||
{
|
||||
this.metadata = metadata ?? throw new ArgumentNullException(nameof(metadata));
|
||||
RepositoryManager = repositoryManager ?? throw new ArgumentNullException(nameof(repositoryManager));
|
||||
Byond = byond ?? throw new ArgumentNullException(nameof(byond));
|
||||
ByondManager = byondManager ?? throw new ArgumentNullException(nameof(byondManager));
|
||||
DreamMaker = dreamMaker ?? throw new ArgumentNullException(nameof(dreamMaker));
|
||||
watchdog = watchdog ?? throw new ArgumentNullException(nameof(watchdog));
|
||||
Chat = chat ?? throw new ArgumentNullException(nameof(chat));
|
||||
@@ -125,10 +125,10 @@ namespace Tgstation.Server.Host.Components
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task StartAsync(CancellationToken cancellationToken) => Task.WhenAll(SetAutoUpdateInterval(metadata.AutoUpdateInterval), Watchdog.StartAsync(cancellationToken), Chat.StartAsync(cancellationToken), compileJobConsumer.StartAsync(cancellationToken), Watchdog.StartAsync(cancellationToken));
|
||||
public Task StartAsync(CancellationToken cancellationToken) => Task.WhenAll(SetAutoUpdateInterval(metadata.AutoUpdateInterval), ByondManager.StartAsync(cancellationToken), Watchdog.StartAsync(cancellationToken), Chat.StartAsync(cancellationToken), compileJobConsumer.StartAsync(cancellationToken), Watchdog.StartAsync(cancellationToken));
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task StopAsync(CancellationToken cancellationToken) => Task.WhenAll(SetAutoUpdateInterval(null), Watchdog.StopAsync(cancellationToken), Chat.StopAsync(cancellationToken), compileJobConsumer.StopAsync(cancellationToken), Watchdog.StopAsync(cancellationToken));
|
||||
public Task StopAsync(CancellationToken cancellationToken) => Task.WhenAll(SetAutoUpdateInterval(null), ByondManager.StopAsync(cancellationToken), Watchdog.StopAsync(cancellationToken), Chat.StopAsync(cancellationToken), compileJobConsumer.StopAsync(cancellationToken), Watchdog.StopAsync(cancellationToken));
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task SetAutoUpdateInterval(int? newInterval)
|
||||
|
||||
@@ -115,7 +115,7 @@ namespace Tgstation.Server.Host.Components
|
||||
|
||||
var repoManager = new RepositoryManager(metadata.RepositorySettings, repoIoManager);
|
||||
|
||||
IByond byond = null;
|
||||
IByondManager byond = null;
|
||||
var configuration = new Configuration(configurationIoManager, synchronousIOManager, symlinkFactory, loggerFactory.CreateLogger<Configuration>());
|
||||
|
||||
var chat = chatFactory.CreateChat();
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Tgstation.Server.Host.IO;
|
||||
|
||||
namespace Tgstation.Server.Host.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// <see cref="IByondInstaller"/> for Posix systems
|
||||
/// </summary>
|
||||
sealed class PosixByondInstaller : IByondInstaller
|
||||
{
|
||||
/// <summary>
|
||||
/// The URL format string for getting BYOND linux version {0}.{1} zipfile
|
||||
/// </summary>
|
||||
const string ByondRevisionsURL = "https://secure.byond.com/download/build/{0}/{0}.{1}_byond_linux.zip";
|
||||
/// <summary>
|
||||
/// Path to the BYOND cache
|
||||
/// </summary>
|
||||
const string ByondCachePath = "~/.byond"; //TODO: Verify this is correct!!!!!
|
||||
|
||||
/// <inheritdoc />
|
||||
public string DreamDaemonName => "DreamDaemon";
|
||||
|
||||
/// <inheritdoc />
|
||||
public string DreamMakerName => "DreamMaker";
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="IIOManager"/> for the <see cref="PosixByondInstaller"/>
|
||||
/// </summary>
|
||||
readonly IIOManager ioManager;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="ILogger"/> for the <see cref="PosixByondInstaller"/>
|
||||
/// </summary>
|
||||
readonly ILogger<PosixByondInstaller> logger;
|
||||
|
||||
/// <summary>
|
||||
/// Construct a <see cref="WindowsByondInstaller"/>
|
||||
/// </summary>
|
||||
/// <param name="ioManager">The value of <see cref="ioManager"/></param>
|
||||
/// <param name="logger">The value of <see cref="logger"/></param>
|
||||
public PosixByondInstaller(IIOManager ioManager, ILogger<PosixByondInstaller> logger)
|
||||
{
|
||||
this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
|
||||
this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task CleanCache(CancellationToken cancellationToken)
|
||||
{
|
||||
try
|
||||
{
|
||||
await ioManager.DeleteDirectory(ByondCachePath, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
logger.LogWarning("Error deleting BYOND cache! Exception: {0}", e);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<byte[]> DownloadVersion(Version version, CancellationToken cancellationToken)
|
||||
{
|
||||
var ourVersion = version;
|
||||
//lummox is annoying and doesn't like to post linux versions if nothing changed in DreamDaemon/DM
|
||||
//if this for's exit condition ever triggers, i get to say I told you so
|
||||
Exception lastException = null;
|
||||
for (var I = 0; I < 5 && ourVersion.Minor >= 1; ++I, ourVersion = new Version(ourVersion.Major, ourVersion.Minor))
|
||||
{
|
||||
try
|
||||
{
|
||||
var url = String.Format(CultureInfo.InvariantCulture, ByondRevisionsURL, ourVersion.Major, ourVersion.Minor);
|
||||
|
||||
return await ioManager.DownloadFile(new Uri(url), cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
catch (WebException e)
|
||||
{
|
||||
if (!(e.Status == WebExceptionStatus.ProtocolError && e.Response is HttpWebResponse response && response.StatusCode == HttpStatusCode.NotFound))
|
||||
throw;
|
||||
lastException = e;
|
||||
}
|
||||
}
|
||||
throw lastException;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task InstallByond(string path, Version version, CancellationToken cancellationToken) => Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
@@ -24,9 +24,9 @@ namespace Tgstation.Server.Host.Components.Watchdog
|
||||
readonly IExecutor executor;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="IByond"/> for the <see cref="SessionControllerFactory"/>
|
||||
/// The <see cref="IByondManager"/> for the <see cref="SessionControllerFactory"/>
|
||||
/// </summary>
|
||||
readonly IByond byond;
|
||||
readonly IByondManager byond;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="IByondTopicSender"/> for the <see cref="SessionControllerFactory"/>
|
||||
@@ -81,7 +81,7 @@ namespace Tgstation.Server.Host.Components.Watchdog
|
||||
/// <param name="ioManager">The value of <see cref="ioManager"/></param>
|
||||
/// <param name="chat">The value of <see cref="chat"/></param>
|
||||
/// <param name="loggerFactory">The value of <see cref="loggerFactory"/></param>
|
||||
public SessionControllerFactory(IExecutor executor, IByond byond, IByondTopicSender byondTopicSender, IInteropRegistrar interopRegistrar, ICryptographySuite cryptographySuite, IApplication application, IIOManager ioManager, IChat chat, ILoggerFactory loggerFactory, Models.Instance instance)
|
||||
public SessionControllerFactory(IExecutor executor, IByondManager byond, IByondTopicSender byondTopicSender, IInteropRegistrar interopRegistrar, ICryptographySuite cryptographySuite, IApplication application, IIOManager ioManager, IChat chat, ILoggerFactory loggerFactory, Models.Instance instance)
|
||||
{
|
||||
this.executor = executor ?? throw new ArgumentNullException(nameof(executor));
|
||||
this.byond = byond ?? throw new ArgumentNullException(nameof(byond));
|
||||
@@ -142,7 +142,7 @@ namespace Tgstation.Server.Host.Components.Watchdog
|
||||
var chatJsonTrackingContext = await chatJsonTrackingTask.ConfigureAwait(false);
|
||||
try
|
||||
{
|
||||
var byondLock = currentByondLock ?? byond.UseExecutables(Version.Parse(dmbProvider.CompileJob.ByondVersion));
|
||||
var byondLock = currentByondLock ?? await byond.UseExecutables(Version.Parse(dmbProvider.CompileJob.ByondVersion), cancellationToken).ConfigureAwait(false);
|
||||
try
|
||||
{
|
||||
//more sanitization here cause it uses the same scheme
|
||||
@@ -190,7 +190,7 @@ namespace Tgstation.Server.Host.Components.Watchdog
|
||||
var chatJsonTrackingContext = await chat.TrackJsons(basePath, reattachInformation.ChatChannelsJson, reattachInformation.ChatCommandsJson, cancellationToken).ConfigureAwait(false);
|
||||
try
|
||||
{
|
||||
var byondLock = byond.UseExecutables(Version.Parse(reattachInformation.Dmb.CompileJob.ByondVersion));
|
||||
var byondLock = await byond.UseExecutables(Version.Parse(reattachInformation.Dmb.CompileJob.ByondVersion), cancellationToken).ConfigureAwait(false);
|
||||
try
|
||||
{
|
||||
var session = executor.AttachToDreamDaemon(reattachInformation.ProcessId, byondLock);
|
||||
|
||||
@@ -0,0 +1,143 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Tgstation.Server.Host.IO;
|
||||
|
||||
namespace Tgstation.Server.Host.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// <see cref="IByondInstaller"/> for windows systems
|
||||
/// </summary>
|
||||
sealed class WindowsByondInstaller : IByondInstaller
|
||||
{
|
||||
/// <summary>
|
||||
/// The URL format string for getting BYOND windows version {0}.{1} zipfile
|
||||
/// </summary>
|
||||
const string ByondRevisionsURL = "https://secure.byond.com/download/build/{0}/{0}.{1}_byond.zip";
|
||||
/// <summary>
|
||||
/// BYOND's DreamDaemon config file in the cfg modification directory
|
||||
/// </summary>
|
||||
const string ByondDDConfig = "byond/config/daemon.txt";
|
||||
/// <summary>
|
||||
/// Setting to add to <see cref="ByondDDConfig"/> to suppress an invisible user prompt for running a trusted mode .dmb
|
||||
/// </summary>
|
||||
const string ByondNoPromptTrustedMode = "trusted-check 0";
|
||||
/// <summary>
|
||||
/// The directory that contains the BYOND directx redistributable
|
||||
/// </summary>
|
||||
const string ByondDXDir = "byond/directx";
|
||||
|
||||
/// <inheritdoc />
|
||||
public string DreamDaemonName => "dreamdaemon.exe";
|
||||
|
||||
/// <inheritdoc />
|
||||
public string DreamMakerName => "dm.exe";
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="IIOManager"/> for the <see cref="WindowsByondInstaller"/>
|
||||
/// </summary>
|
||||
readonly IIOManager ioManager;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="ILogger"/> for the <see cref="WindowsByondInstaller"/>
|
||||
/// </summary>
|
||||
readonly ILogger<WindowsByondInstaller> logger;
|
||||
|
||||
/// <summary>
|
||||
/// If DirectX was installed
|
||||
/// </summary>
|
||||
bool installedDirectX;
|
||||
|
||||
/// <summary>
|
||||
/// Construct a <see cref="WindowsByondInstaller"/>
|
||||
/// </summary>
|
||||
/// <param name="ioManager">The value of <see cref="ioManager"/></param>
|
||||
/// <param name="logger">The value of <see cref="logger"/></param>
|
||||
public WindowsByondInstaller(IIOManager ioManager, ILogger<WindowsByondInstaller> logger)
|
||||
{
|
||||
this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
|
||||
this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
|
||||
installedDirectX = false;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task CleanCache(CancellationToken cancellationToken)
|
||||
{
|
||||
try
|
||||
{
|
||||
await ioManager.DeleteDirectory(ioManager.ConcatPath(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "byond/cache"), cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
logger.LogWarning("Error deleting BYOND cache! Exception: {0}", e);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<byte[]> DownloadVersion(Version version, CancellationToken cancellationToken)
|
||||
{
|
||||
var url = String.Format(CultureInfo.InvariantCulture, ByondRevisionsURL, version.Major, version.Minor);
|
||||
|
||||
return ioManager.DownloadFile(new Uri(url), cancellationToken);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task InstallByond(string path, Version version, CancellationToken cancellationToken)
|
||||
{
|
||||
var setNoPromptTrustedModeTask = ioManager.WriteAllBytes(ByondDDConfig, Encoding.UTF8.GetBytes(ByondNoPromptTrustedMode), cancellationToken);
|
||||
|
||||
//after this version lummox made DD depend of directx lol
|
||||
if (version.Major >= 512 && version.Minor >= 1427 && Monitor.TryEnter(this))
|
||||
try
|
||||
{
|
||||
if (!installedDirectX)
|
||||
//always install it, it's pretty fast and will do better redundancy checking than us
|
||||
using (var p = new Process())
|
||||
{
|
||||
p.StartInfo.Arguments = "/silent";
|
||||
var rbdx = ioManager.ConcatPath(path, ByondDXDir);
|
||||
p.StartInfo.FileName = rbdx + "/DXSETUP.exe";
|
||||
p.StartInfo.UseShellExecute = false;
|
||||
p.StartInfo.WorkingDirectory = rbdx;
|
||||
p.EnableRaisingEvents = true;
|
||||
var tcs = new TaskCompletionSource<object>();
|
||||
p.Exited += (a, b) => tcs.SetResult(null);
|
||||
try
|
||||
{
|
||||
p.Start();
|
||||
using (cancellationToken.Register(() =>
|
||||
{
|
||||
p.Kill();
|
||||
tcs.SetCanceled();
|
||||
}))
|
||||
await tcs.Task.ConfigureAwait(false);
|
||||
}
|
||||
finally
|
||||
{
|
||||
try
|
||||
{
|
||||
p.Kill();
|
||||
p.WaitForExit();
|
||||
}
|
||||
catch (InvalidOperationException) { }
|
||||
}
|
||||
|
||||
if (p.ExitCode != 0)
|
||||
throw new Exception("Failed to install included DirectX! Exit code: " + p.ExitCode);
|
||||
installedDirectX = true;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
Monitor.Exit(this);
|
||||
}
|
||||
|
||||
await setNoPromptTrustedModeTask.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -154,11 +154,13 @@ namespace Tgstation.Server.Host.Core
|
||||
{
|
||||
services.AddSingleton<ISystemIdentityFactory, WindowsSystemIdentityFactory>();
|
||||
services.AddSingleton<ISymlinkFactory, WindowsSymlinkFactory>();
|
||||
services.AddSingleton<IByondInstaller, WindowsByondInstaller>();
|
||||
}
|
||||
else
|
||||
{
|
||||
services.AddSingleton<ISystemIdentityFactory, PosixSystemIdentityFactory>();
|
||||
services.AddSingleton<ISymlinkFactory, PosixSymlinkFactory>();
|
||||
services.AddSingleton<IByondInstaller, PosixByondInstaller>();
|
||||
}
|
||||
|
||||
services.AddSingleton<IExecutor, Executor>();
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
@@ -243,5 +244,13 @@ namespace Tgstation.Server.Host.IO
|
||||
link = ResolvePath(link);
|
||||
|
||||
}, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<byte[]> DownloadFile(Uri url, CancellationToken cancellationToken)
|
||||
{
|
||||
using (var wc = new WebClient())
|
||||
using (cancellationToken.Register(() => wc.CancelAsync()))
|
||||
return await wc.DownloadDataTaskAsync(url).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@@ -153,5 +154,13 @@ namespace Tgstation.Server.Host.IO
|
||||
/// <param name="cancellationToken">A <see cref="CancellationToken"/> for the operation</param>
|
||||
/// <returns>A <see cref="Task"/> representing the running operation</returns>
|
||||
Task MoveFile(string source, string destination, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Downloads a file from <paramref name="url"/>
|
||||
/// </summary>
|
||||
/// <param name="url">The URL to download</param>
|
||||
/// <param name="cancellationToken">A <see cref="CancellationToken"/> for the operation</param>
|
||||
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="byte"/>s of the downloaded file</returns>
|
||||
Task<byte[]> DownloadFile(Uri url, CancellationToken cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,18 +58,22 @@ namespace Tgstation.Server.Host.IO
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
file.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
file.SetLength(data.Length);
|
||||
if (data != null)
|
||||
{
|
||||
file.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
file.Write(data, 0, data.Length);
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
file.SetLength(data.Length);
|
||||
|
||||
return true;
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
file.Write(data, 0, data.Length);
|
||||
}
|
||||
}
|
||||
if (data == null)
|
||||
File.Delete(path);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,9 +14,6 @@ namespace Tgstation.Server.Host.Models
|
||||
/// <inheritdoc />
|
||||
abstract class DatabaseContext<TParentContext> : DbContext, IDatabaseContext where TParentContext : DbContext
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public DbSet<ServerSettings> ServerSettings { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public DbSet<User> Users { get; set; }
|
||||
|
||||
@@ -126,18 +123,6 @@ namespace Tgstation.Server.Host.Models
|
||||
base.OnConfiguring(optionsBuilder);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<ServerSettings> GetServerSettings(CancellationToken cancellationToken)
|
||||
{
|
||||
var settings = await ServerSettings.FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
|
||||
if (settings == default(ServerSettings))
|
||||
{
|
||||
settings = new ServerSettings();
|
||||
ServerSettings.Add(settings);
|
||||
}
|
||||
return settings;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task Initialize(CancellationToken cancellationToken)
|
||||
{
|
||||
|
||||
@@ -21,11 +21,6 @@ namespace Tgstation.Server.Host.Models
|
||||
/// </summary>
|
||||
const string DefaultAdminPassword = "ISolemlySwearToDeleteTheDataDirectory";
|
||||
|
||||
/// <summary>
|
||||
/// The default git repository to pull server updates from
|
||||
/// </summary>
|
||||
const string DefaultUpstreamRepository = "https://github.com/tgstation/tgstation-server";
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="ICryptographySuite"/> for the <see cref="DatabaseContext{TParentContext}"/>
|
||||
/// </summary>
|
||||
@@ -60,12 +55,6 @@ namespace Tgstation.Server.Host.Models
|
||||
public async Task SeedDatabase(IDatabaseContext databaseContext, CancellationToken cancellationToken)
|
||||
{
|
||||
SeedAdminUser(databaseContext);
|
||||
|
||||
var serverSettings = await databaseContext.GetServerSettings(cancellationToken).ConfigureAwait(false);
|
||||
|
||||
serverSettings.EnableTelemetry = true;
|
||||
serverSettings.UpstreamRepository = DefaultUpstreamRepository;
|
||||
|
||||
await databaseContext.Save(cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
|
||||
@@ -59,13 +59,6 @@ namespace Tgstation.Server.Host.Models
|
||||
/// </summary>
|
||||
DbSet<RepositorySettings> RepositorySettings { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Get the <see cref="ServerSettings"/> in the <see cref="IDatabaseContext"/>
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the operation</param>
|
||||
/// <returns>A <see cref="Task{TResult}"/> resulting in the <see cref="ServerSettings"/> in the <see cref="IDatabaseContext"/></returns>
|
||||
Task<ServerSettings> GetServerSettings(CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Saves changes made to the <see cref="IDatabaseContext"/>
|
||||
/// </summary>
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
namespace Tgstation.Server.Host.Models
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public sealed class ServerSettings : Api.Models.Internal.ServerSettings
|
||||
{
|
||||
/// <summary>
|
||||
/// The row Id
|
||||
/// </summary>
|
||||
public long Id { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -43,7 +43,7 @@ namespace Tgstation.Server.Host.Security.Tests
|
||||
var authContext = new AuthenticationContext(null, user, instanceUser);
|
||||
|
||||
user.AdministrationRights = AdministrationRights.EditUsers;
|
||||
instanceUser.ByondRights = ByondRights.ChangeVersion | ByondRights.ReadInstalled;
|
||||
instanceUser.ByondRights = ByondRights.ChangeVersion | ByondRights.ReadActive;
|
||||
Assert.AreEqual((int)user.AdministrationRights, authContext.GetRight(RightsType.Administration));
|
||||
Assert.AreEqual((int)instanceUser.ByondRights, authContext.GetRight(RightsType.Byond));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user