mirror of
https://github.com/tgstation/tgstation-server.git
synced 2026-08-30 00:22:40 +01:00
Abstract HttpClient and FileDownloader
- Set all requests to use assemblyInformationProvider UserAgent by default. - Removed DefaultIOManager's dependency on IAssemblyInformationProvider. - Fixed bad Dispose scope for requests under construction in SwarmService.
This commit is contained in:
+1
-1
@@ -7,7 +7,7 @@
|
||||
<TgsConfigVersion>4.5.0</TgsConfigVersion>
|
||||
<TgsApiVersion>9.9.0</TgsApiVersion>
|
||||
<TgsApiLibraryVersion>10.3.0</TgsApiLibraryVersion>
|
||||
<TgsClientVersion>11.3.0</TgsClientVersion>
|
||||
<TgsClientVersion>11.3.1</TgsClientVersion>
|
||||
<TgsDmapiVersion>6.4.2</TgsDmapiVersion>
|
||||
<TgsInteropVersion>5.6.0</TgsInteropVersion>
|
||||
<TgsHostWatchdogVersion>1.2.2</TgsHostWatchdogVersion>
|
||||
|
||||
@@ -20,6 +20,7 @@ using Newtonsoft.Json.Serialization;
|
||||
using Tgstation.Server.Api;
|
||||
using Tgstation.Server.Api.Models;
|
||||
using Tgstation.Server.Api.Models.Response;
|
||||
using Tgstation.Server.Common;
|
||||
|
||||
namespace Tgstation.Server.Client
|
||||
{
|
||||
@@ -50,7 +51,7 @@ namespace Tgstation.Server.Client
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="HttpClientImplementation"/> for the <see cref="ApiClient"/>.
|
||||
/// The <see cref="IHttpClient"/> for the <see cref="ApiClient"/>.
|
||||
/// </summary>
|
||||
readonly IHttpClient httpClient;
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
|
||||
using Tgstation.Server.Api;
|
||||
using Tgstation.Server.Common;
|
||||
|
||||
namespace Tgstation.Server.Client
|
||||
{
|
||||
@@ -13,7 +14,7 @@ namespace Tgstation.Server.Client
|
||||
ApiHeaders apiHeaders,
|
||||
ApiHeaders? tokenRefreshHeaders,
|
||||
bool authless) => new ApiClient(
|
||||
new HttpClientImplementation(),
|
||||
new HttpClient(),
|
||||
url,
|
||||
apiHeaders,
|
||||
tokenRefreshHeaders,
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Tgstation.Server.Client
|
||||
{
|
||||
/// <inheritdoc />
|
||||
sealed class HttpClientImplementation : IHttpClient
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public TimeSpan Timeout
|
||||
{
|
||||
get => httpClient.Timeout;
|
||||
set => httpClient.Timeout = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The real <see cref="HttpClient"/>.
|
||||
/// </summary>
|
||||
readonly HttpClient httpClient;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="HttpClientImplementation"/> class.
|
||||
/// </summary>
|
||||
public HttpClientImplementation()
|
||||
{
|
||||
httpClient = new HttpClient();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Dispose() => httpClient.Dispose();
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) => httpClient.SendAsync(request, cancellationToken);
|
||||
}
|
||||
}
|
||||
@@ -41,6 +41,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Tgstation.Server.Api\Tgstation.Server.Api.csproj" />
|
||||
<ProjectReference Include="..\Tgstation.Server.Common\Tgstation.Server.Common.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Tgstation.Server.Common
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public sealed class HttpClient : IHttpClient
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public TimeSpan Timeout
|
||||
{
|
||||
get => httpClient.Timeout;
|
||||
set => httpClient.Timeout = value;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public HttpRequestHeaders DefaultRequestHeaders => httpClient.DefaultRequestHeaders;
|
||||
|
||||
/// <summary>
|
||||
/// The real <see cref="System.Net.Http.HttpClient"/>.
|
||||
/// </summary>
|
||||
readonly System.Net.Http.HttpClient httpClient;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="HttpClient"/> class.
|
||||
/// </summary>
|
||||
/// <param name="implementation">The <see cref="System.Net.Http.HttpClient"/> to wrap.</param>
|
||||
public HttpClient(System.Net.Http.HttpClient implementation)
|
||||
{
|
||||
httpClient = implementation ?? throw new ArgumentNullException(nameof(implementation));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="HttpClient"/> class.
|
||||
/// </summary>
|
||||
public HttpClient()
|
||||
: this(new System.Net.Http.HttpClient())
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Dispose() => httpClient.Dispose();
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) => httpClient.SendAsync(request, cancellationToken);
|
||||
}
|
||||
}
|
||||
+8
-2
@@ -1,20 +1,26 @@
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Tgstation.Server.Client
|
||||
namespace Tgstation.Server.Common
|
||||
{
|
||||
/// <summary>
|
||||
/// For sending HTTP requests.
|
||||
/// </summary>
|
||||
interface IHttpClient : IDisposable
|
||||
public interface IHttpClient : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// The request timeout.
|
||||
/// </summary>
|
||||
TimeSpan Timeout { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="HttpRequestHeaders"/> used on every request.
|
||||
/// </summary>
|
||||
HttpRequestHeaders DefaultRequestHeaders { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Send an HTTP request.
|
||||
/// </summary>
|
||||
@@ -0,0 +1,31 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="../../build/Version.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<DebugType>Full</DebugType>
|
||||
<Version>$(TgsCoreVersion)</Version>
|
||||
<CodeAnalysisRuleSet>../../build/analyzers.ruleset</CodeAnalysisRuleSet>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<DocumentationFile>bin\$(Configuration)\netstandard2.0\Tgstation.Server.Client.xml</DocumentationFile>
|
||||
<EnableNETAnalyzers>true</EnableNETAnalyzers>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Release'">
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<WarningsAsErrors />
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<!-- Usage: Linting -->
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<AdditionalFiles Include="../../build/stylecop.json" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -39,14 +39,21 @@ namespace Tgstation.Server.Host.Components.Byond
|
||||
/// </summary>
|
||||
protected ILogger<ByondInstallerBase> Logger { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="IFileDownloader"/> for the <see cref="ByondInstallerBase"/>.
|
||||
/// </summary>
|
||||
readonly IFileDownloader fileDownloader;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ByondInstallerBase"/> class.
|
||||
/// </summary>
|
||||
/// <param name="ioManager">The value of <see cref="IOManager"/>.</param>
|
||||
/// <param name="fileDownloader">The value of <see cref="fileDownloader"/>.</param>
|
||||
/// <param name="logger">The value of <see cref="Logger"/>.</param>
|
||||
protected ByondInstallerBase(IIOManager ioManager, ILogger<ByondInstallerBase> logger)
|
||||
protected ByondInstallerBase(IIOManager ioManager, IFileDownloader fileDownloader, ILogger<ByondInstallerBase> logger)
|
||||
{
|
||||
IOManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
|
||||
this.fileDownloader = fileDownloader ?? throw new ArgumentNullException(nameof(fileDownloader));
|
||||
Logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
}
|
||||
|
||||
@@ -88,11 +95,9 @@ namespace Tgstation.Server.Host.Components.Byond
|
||||
if (version == null)
|
||||
throw new ArgumentNullException(nameof(version));
|
||||
|
||||
Logger.LogTrace("Downloading BYOND version {major}.{minor}...", version.Major, version.Minor);
|
||||
var url = String.Format(CultureInfo.InvariantCulture, ByondRevisionsUrlTemplate, version.Major, version.Minor);
|
||||
|
||||
Logger.LogTrace("Downloading from: {0}", url);
|
||||
|
||||
return IOManager.DownloadFile(new Uri(url), cancellationToken);
|
||||
return fileDownloader.DownloadFile(new Uri(url), cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,9 +49,14 @@ namespace Tgstation.Server.Host.Components.Byond
|
||||
/// </summary>
|
||||
/// <param name="postWriteHandler">The value of <see cref="postWriteHandler"/>.</param>
|
||||
/// <param name="ioManager">The <see cref="IIOManager"/> for the <see cref="ByondInstallerBase"/>.</param>
|
||||
/// <param name="fileDownloader">The <see cref="IFileDownloader"/> for the <see cref="ByondInstallerBase"/>.</param>
|
||||
/// <param name="logger">The <see cref="ILogger"/> for the <see cref="ByondInstallerBase"/>.</param>
|
||||
public PosixByondInstaller(IPostWriteHandler postWriteHandler, IIOManager ioManager, ILogger<PosixByondInstaller> logger)
|
||||
: base(ioManager, logger)
|
||||
public PosixByondInstaller(
|
||||
IPostWriteHandler postWriteHandler,
|
||||
IIOManager ioManager,
|
||||
IFileDownloader fileDownloader,
|
||||
ILogger<PosixByondInstaller> logger)
|
||||
: base(ioManager, fileDownloader, logger)
|
||||
{
|
||||
this.postWriteHandler = postWriteHandler ?? throw new ArgumentNullException(nameof(postWriteHandler));
|
||||
|
||||
@@ -89,7 +94,7 @@ namespace Tgstation.Server.Host.Components.Byond
|
||||
|
||||
async Task WriteAndMakeExecutable(string pathToScript, string script)
|
||||
{
|
||||
Logger.LogTrace("Writing script {0}:{1}{2}", pathToScript, Environment.NewLine, script);
|
||||
Logger.LogTrace("Writing script {path}:{newLine}{scriptContents}", pathToScript, Environment.NewLine, script);
|
||||
await IOManager.WriteAllBytes(pathToScript, Encoding.ASCII.GetBytes(script), cancellationToken);
|
||||
postWriteHandler.HandleWrite(IOManager.ResolvePath(pathToScript));
|
||||
}
|
||||
|
||||
@@ -81,9 +81,15 @@ namespace Tgstation.Server.Host.Components.Byond
|
||||
/// <param name="processExecutor">The value of <see cref="processExecutor"/>.</param>
|
||||
/// <param name="generalConfigurationOptions">The <see cref="IOptions{TOptions}"/> containing the value of <see cref="generalConfiguration"/>.</param>
|
||||
/// <param name="ioManager">The <see cref="IIOManager"/> for the <see cref="ByondInstallerBase"/>.</param>
|
||||
/// <param name="fileDownloader">The <see cref="IFileDownloader"/> for the <see cref="ByondInstallerBase"/>.</param>
|
||||
/// <param name="logger">The <see cref="ILogger"/> for the <see cref="ByondInstallerBase"/>.</param>
|
||||
public WindowsByondInstaller(IProcessExecutor processExecutor, IIOManager ioManager, IOptions<GeneralConfiguration> generalConfigurationOptions, ILogger<WindowsByondInstaller> logger)
|
||||
: base(ioManager, logger)
|
||||
public WindowsByondInstaller(
|
||||
IProcessExecutor processExecutor,
|
||||
IIOManager ioManager,
|
||||
IFileDownloader fileDownloader,
|
||||
IOptions<GeneralConfiguration> generalConfigurationOptions,
|
||||
ILogger<WindowsByondInstaller> logger)
|
||||
: base(ioManager, fileDownloader, logger)
|
||||
{
|
||||
this.processExecutor = processExecutor ?? throw new ArgumentNullException(nameof(processExecutor));
|
||||
generalConfiguration = generalConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(generalConfigurationOptions));
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
using Tgstation.Server.Common;
|
||||
using Tgstation.Server.Host.System;
|
||||
|
||||
namespace Tgstation.Server.Host.Core
|
||||
{
|
||||
/// <inheritdoc />
|
||||
sealed class AbstractHttpClientFactory : IAbstractHttpClientFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// The real <see cref="IHttpClientFactory"/>.
|
||||
/// </summary>
|
||||
readonly IHttpClientFactory httpClientFactory;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="IAssemblyInformationProvider"/> for the <see cref="AbstractHttpClientFactory"/>.
|
||||
/// </summary>
|
||||
readonly IAssemblyInformationProvider assemblyInformationProvider;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="ILogger"/> for the <see cref="AbstractHttpClientFactory"/>.
|
||||
/// </summary>
|
||||
readonly ILogger<AbstractHttpClientFactory> logger;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AbstractHttpClientFactory"/> class.
|
||||
/// </summary>
|
||||
/// <param name="httpClientFactory">The value of <see cref="httpClientFactory"/>.</param>
|
||||
/// <param name="assemblyInformationProvider">The value of <see cref="assemblyInformationProvider"/>.</param>
|
||||
/// <param name="logger">The value of <see cref="logger"/>.</param>
|
||||
public AbstractHttpClientFactory(
|
||||
IHttpClientFactory httpClientFactory,
|
||||
IAssemblyInformationProvider assemblyInformationProvider,
|
||||
ILogger<AbstractHttpClientFactory> logger)
|
||||
{
|
||||
this.httpClientFactory = httpClientFactory ?? throw new ArgumentNullException(nameof(httpClientFactory));
|
||||
this.assemblyInformationProvider = assemblyInformationProvider ?? throw new ArgumentNullException(nameof(assemblyInformationProvider));
|
||||
this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IHttpClient CreateClient()
|
||||
{
|
||||
logger.LogTrace("Creating client...");
|
||||
var innerClient = httpClientFactory.CreateClient();
|
||||
try
|
||||
{
|
||||
var client = new Tgstation.Server.Common.HttpClient(innerClient);
|
||||
client.DefaultRequestHeaders.UserAgent.Add(assemblyInformationProvider.ProductInfoHeaderValue);
|
||||
return client;
|
||||
}
|
||||
catch
|
||||
{
|
||||
innerClient.Dispose();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -73,7 +73,7 @@ namespace Tgstation.Server.Host.Core
|
||||
public static IServerFactory CreateDefaultServerFactory()
|
||||
{
|
||||
var assemblyInformationProvider = new AssemblyInformationProvider();
|
||||
var ioManager = new DefaultIOManager(assemblyInformationProvider);
|
||||
var ioManager = new DefaultIOManager();
|
||||
return new ServerFactory(
|
||||
assemblyInformationProvider,
|
||||
ioManager);
|
||||
@@ -253,6 +253,7 @@ namespace Tgstation.Server.Host.Core
|
||||
|
||||
// Enable managed HTTP clients
|
||||
services.AddHttpClient();
|
||||
services.AddSingleton<IAbstractHttpClientFactory, AbstractHttpClientFactory>();
|
||||
|
||||
void AddTypedContext<TContext>() where TContext : DatabaseContext
|
||||
{
|
||||
@@ -350,6 +351,7 @@ namespace Tgstation.Server.Host.Core
|
||||
services.AddSingleton<IProviderFactory, ProviderFactory>();
|
||||
services.AddSingleton<IChatManagerFactory, ChatManagerFactory>();
|
||||
services.AddSingleton<ISynchronousIOManager, SynchronousIOManager>();
|
||||
services.AddSingleton<IFileDownloader, FileDownloader>();
|
||||
services.AddSingleton<FileTransferService>();
|
||||
services.AddSingleton<IFileTransferStreamHandler>(x => x.GetRequiredService<FileTransferService>());
|
||||
services.AddSingleton<IFileTransferTicketProvider>(x => x.GetRequiredService<FileTransferService>());
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
using Tgstation.Server.Common;
|
||||
|
||||
namespace Tgstation.Server.Host.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates <see cref="IHttpClient"/>s.
|
||||
/// </summary>
|
||||
public interface IAbstractHttpClientFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// Create a <see cref="IHttpClient"/>.
|
||||
/// </summary>
|
||||
/// <returns>A new <see cref="IHttpClient"/>.</returns>
|
||||
IHttpClient CreateClient();
|
||||
}
|
||||
}
|
||||
@@ -30,6 +30,11 @@ namespace Tgstation.Server.Host.Core
|
||||
/// </summary>
|
||||
readonly IIOManager ioManager;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="IFileDownloader"/> for the <see cref="ServerUpdater"/>.
|
||||
/// </summary>
|
||||
readonly IFileDownloader fileDownloader;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="IServerControl"/> for the <see cref="ServerUpdater"/>.
|
||||
/// </summary>
|
||||
@@ -55,18 +60,21 @@ namespace Tgstation.Server.Host.Core
|
||||
/// </summary>
|
||||
/// <param name="gitHubClientFactory">The value of <see cref="gitHubClientFactory"/>.</param>
|
||||
/// <param name="ioManager">The value of <see cref="ioManager"/>.</param>
|
||||
/// <param name="fileDownloader">The value of <see cref="fileDownloader"/>.</param>
|
||||
/// <param name="serverControl">The value of <see cref="serverControl"/>.</param>
|
||||
/// <param name="logger">The value of <see cref="logger"/>.</param>
|
||||
/// <param name="updatesConfigurationOptions">The <see cref="IOptions{TOptions}"/> containing the value of <see cref="updatesConfiguration"/>.</param>
|
||||
public ServerUpdater(
|
||||
IGitHubClientFactory gitHubClientFactory,
|
||||
IIOManager ioManager,
|
||||
IFileDownloader fileDownloader,
|
||||
IServerControl serverControl,
|
||||
ILogger<ServerUpdater> logger,
|
||||
IOptions<UpdatesConfiguration> updatesConfigurationOptions)
|
||||
{
|
||||
this.gitHubClientFactory = gitHubClientFactory ?? throw new ArgumentNullException(nameof(gitHubClientFactory));
|
||||
this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
|
||||
this.fileDownloader = fileDownloader ?? throw new ArgumentNullException(nameof(fileDownloader));
|
||||
this.serverControl = serverControl ?? throw new ArgumentNullException(nameof(serverControl));
|
||||
this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
updatesConfiguration = updatesConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(updatesConfigurationOptions));
|
||||
@@ -154,7 +162,7 @@ namespace Tgstation.Server.Host.Core
|
||||
try
|
||||
{
|
||||
logger.LogTrace("Downloading zip package...");
|
||||
updateZipData = await ioManager.DownloadFile(serverUpdateOperation.UpdateZipUrl, cancellationToken);
|
||||
updateZipData = await fileDownloader.DownloadFile(serverUpdateOperation.UpdateZipUrl, cancellationToken);
|
||||
}
|
||||
catch (Exception e1)
|
||||
{
|
||||
|
||||
@@ -3,12 +3,10 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Tgstation.Server.Host.Core;
|
||||
using Tgstation.Server.Host.System;
|
||||
|
||||
namespace Tgstation.Server.Host.IO
|
||||
{
|
||||
@@ -32,11 +30,6 @@ namespace Tgstation.Server.Host.IO
|
||||
/// </summary>
|
||||
public const TaskCreationOptions BlockingTaskCreationOptions = TaskCreationOptions.None;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="IAssemblyInformationProvider"/> for the <see cref="DefaultIOManager"/>.
|
||||
/// </summary>
|
||||
readonly IAssemblyInformationProvider assemblyInformationProvider;
|
||||
|
||||
/// <summary>
|
||||
/// Recursively empty a directory.
|
||||
/// </summary>
|
||||
@@ -67,22 +60,6 @@ namespace Tgstation.Server.Host.IO
|
||||
dir.Delete(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DefaultIOManager"/> class.
|
||||
/// </summary>
|
||||
/// <param name="assemblyInformationProvider">The value of <see cref="assemblyInformationProvider"/>.</param>
|
||||
public DefaultIOManager(IAssemblyInformationProvider assemblyInformationProvider)
|
||||
{
|
||||
this.assemblyInformationProvider = assemblyInformationProvider ?? throw new ArgumentNullException(nameof(assemblyInformationProvider));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DefaultIOManager"/> class.
|
||||
/// </summary>
|
||||
protected DefaultIOManager()
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task CopyDirectory(
|
||||
string src,
|
||||
@@ -296,29 +273,6 @@ namespace Tgstation.Server.Host.IO
|
||||
BlockingTaskCreationOptions,
|
||||
TaskScheduler.Current);
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<MemoryStream> DownloadFile(Uri url, CancellationToken cancellationToken)
|
||||
{
|
||||
using var httpClient = new HttpClient();
|
||||
httpClient.DefaultRequestHeaders.UserAgent.Add(assemblyInformationProvider.ProductInfoHeaderValue);
|
||||
var webRequestTask = httpClient.GetAsync(url, cancellationToken);
|
||||
using var response = await webRequestTask;
|
||||
response.EnsureSuccessStatusCode();
|
||||
using var responseStream = await response.Content.ReadAsStreamAsync(cancellationToken);
|
||||
var memoryStream = new MemoryStream();
|
||||
try
|
||||
{
|
||||
await responseStream.CopyToAsync(memoryStream, cancellationToken);
|
||||
memoryStream.Seek(0, SeekOrigin.Begin);
|
||||
return memoryStream;
|
||||
}
|
||||
catch
|
||||
{
|
||||
memoryStream.Dispose();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task ZipToDirectory(string path, Stream zipFile, CancellationToken cancellationToken) => Task.Factory.StartNew(
|
||||
() =>
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
using Tgstation.Server.Host.Core;
|
||||
|
||||
namespace Tgstation.Server.Host.IO
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public sealed class FileDownloader : IFileDownloader
|
||||
{
|
||||
/// <summary>
|
||||
/// The <see cref="IAbstractHttpClientFactory"/> for the <see cref="FileDownloader"/>.
|
||||
/// </summary>
|
||||
readonly IAbstractHttpClientFactory httpClientFactory;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="ILogger"/> for the <see cref="FileDownloader"/>.
|
||||
/// </summary>
|
||||
readonly ILogger<FileDownloader> logger;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="FileDownloader"/> class.
|
||||
/// </summary>
|
||||
/// <param name="httpClientFactory">The value of <see cref="httpClientFactory"/>.</param>
|
||||
/// <param name="logger">The value of <see cref="logger"/>.</param>
|
||||
public FileDownloader(IAbstractHttpClientFactory httpClientFactory, ILogger<FileDownloader> logger)
|
||||
{
|
||||
this.httpClientFactory = httpClientFactory ?? throw new ArgumentNullException(nameof(httpClientFactory));
|
||||
this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<MemoryStream> DownloadFile(Uri url, CancellationToken cancellationToken)
|
||||
{
|
||||
logger.LogDebug("Starting download of {url}...", url);
|
||||
using var httpClient = httpClientFactory.CreateClient();
|
||||
using var request = new HttpRequestMessage(
|
||||
HttpMethod.Get,
|
||||
url);
|
||||
|
||||
var webRequestTask = httpClient.SendAsync(request, cancellationToken);
|
||||
using var response = await webRequestTask;
|
||||
response.EnsureSuccessStatusCode();
|
||||
using var responseStream = await response.Content.ReadAsStreamAsync(cancellationToken);
|
||||
var memoryStream = new MemoryStream();
|
||||
try
|
||||
{
|
||||
await responseStream.CopyToAsync(memoryStream, cancellationToken);
|
||||
memoryStream.Seek(0, SeekOrigin.Begin);
|
||||
return memoryStream;
|
||||
}
|
||||
catch
|
||||
{
|
||||
memoryStream.Dispose();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Tgstation.Server.Host.IO
|
||||
{
|
||||
/// <summary>
|
||||
/// Downloads files.
|
||||
/// </summary>
|
||||
interface IFileDownloader
|
||||
{
|
||||
/// <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 a <see cref="MemoryStream"/> of the downloaded file.</returns>
|
||||
Task<MemoryStream> DownloadFile(Uri url, CancellationToken cancellationToken);
|
||||
}
|
||||
}
|
||||
@@ -192,14 +192,6 @@ namespace Tgstation.Server.Host.IO
|
||||
/// <returns>A <see cref="Task"/> representing the running operation.</returns>
|
||||
Task MoveDirectory(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 a <see cref="MemoryStream"/> of the downloaded file.</returns>
|
||||
Task<MemoryStream> DownloadFile(Uri url, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Extract a set of <paramref name="zipFile"/> to a given <paramref name="path"/>.
|
||||
/// </summary>
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
using Tgstation.Server.Api.Models;
|
||||
using Tgstation.Server.Host.Configuration;
|
||||
using Tgstation.Server.Host.System;
|
||||
using Tgstation.Server.Host.Core;
|
||||
|
||||
namespace Tgstation.Server.Host.Security.OAuth
|
||||
{
|
||||
@@ -18,29 +17,27 @@ namespace Tgstation.Server.Host.Security.OAuth
|
||||
public override OAuthProvider Provider => OAuthProvider.Discord;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Uri TokenUrl => new Uri("https://discord.com/api/oauth2/token");
|
||||
protected override Uri TokenUrl => new ("https://discord.com/api/oauth2/token");
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Uri UserInformationUrl => new Uri("https://discord.com/api/users/@me");
|
||||
protected override Uri UserInformationUrl => new ("https://discord.com/api/users/@me");
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DiscordOAuthValidator"/> class.
|
||||
/// </summary>
|
||||
/// <param name="httpClientFactory">The <see cref="IHttpClientFactory"/> for the <see cref="GenericOAuthValidator"/>.</param>
|
||||
/// <param name="assemblyInformationProvider">The <see cref="IAssemblyInformationProvider"/> for the <see cref="GenericOAuthValidator"/>.</param>
|
||||
/// <param name="httpClientFactory">The <see cref="IAbstractHttpClientFactory"/> for the <see cref="GenericOAuthValidator"/>.</param>
|
||||
/// <param name="logger">The <see cref="ILogger"/> for the <see cref="GenericOAuthValidator"/>.</param>
|
||||
/// <param name="oAuthConfiguration">The <see cref="OAuthConfiguration"/> for the <see cref="GenericOAuthValidator"/>.</param>
|
||||
public DiscordOAuthValidator(
|
||||
IHttpClientFactory httpClientFactory,
|
||||
IAssemblyInformationProvider assemblyInformationProvider,
|
||||
IAbstractHttpClientFactory httpClientFactory,
|
||||
ILogger<DiscordOAuthValidator> logger,
|
||||
OAuthConfiguration oAuthConfiguration)
|
||||
: base(httpClientFactory, assemblyInformationProvider, logger, oAuthConfiguration)
|
||||
: base(httpClientFactory, logger, oAuthConfiguration)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override OAuthTokenRequest CreateTokenRequest(string code) => new OAuthTokenRequest(OAuthConfiguration, code, "identify");
|
||||
protected override OAuthTokenRequest CreateTokenRequest(string code) => new (OAuthConfiguration, code, "identify");
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override string DecodeTokenPayload(dynamic responseJson) => responseJson.access_token;
|
||||
|
||||
@@ -13,8 +13,9 @@ using Newtonsoft.Json.Serialization;
|
||||
|
||||
using Tgstation.Server.Api;
|
||||
using Tgstation.Server.Api.Models;
|
||||
using Tgstation.Server.Common;
|
||||
using Tgstation.Server.Host.Configuration;
|
||||
using Tgstation.Server.Host.System;
|
||||
using Tgstation.Server.Host.Core;
|
||||
|
||||
namespace Tgstation.Server.Host.Security.OAuth
|
||||
{
|
||||
@@ -49,18 +50,13 @@ namespace Tgstation.Server.Host.Security.OAuth
|
||||
/// <summary>
|
||||
/// The <see cref="IHttpClientFactory"/> for the <see cref="GenericOAuthValidator"/>.
|
||||
/// </summary>
|
||||
readonly IHttpClientFactory httpClientFactory;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="IAssemblyInformationProvider"/> for the <see cref="GenericOAuthValidator"/>.
|
||||
/// </summary>
|
||||
readonly IAssemblyInformationProvider assemblyInformationProvider;
|
||||
readonly IAbstractHttpClientFactory httpClientFactory;
|
||||
|
||||
/// <summary>
|
||||
/// Gets <see cref="JsonSerializerSettings"/> that should be used.
|
||||
/// </summary>
|
||||
/// <returns>A new <see cref="JsonSerializerSettings"/> <see cref="object"/>.</returns>
|
||||
protected static JsonSerializerSettings SerializerSettings() => new JsonSerializerSettings
|
||||
protected static JsonSerializerSettings SerializerSettings() => new ()
|
||||
{
|
||||
ContractResolver = new DefaultContractResolver
|
||||
{
|
||||
@@ -72,17 +68,14 @@ namespace Tgstation.Server.Host.Security.OAuth
|
||||
/// Initializes a new instance of the <see cref="GenericOAuthValidator"/> class.
|
||||
/// </summary>
|
||||
/// <param name="httpClientFactory">The value of <see cref="httpClientFactory"/>.</param>
|
||||
/// <param name="assemblyInformationProvider">The value of <see cref="assemblyInformationProvider"/>.</param>
|
||||
/// <param name="logger">The value of <see cref="Logger"/>.</param>
|
||||
/// <param name="oAuthConfiguration">The value of <see cref="OAuthConfiguration"/>.</param>
|
||||
public GenericOAuthValidator(
|
||||
IHttpClientFactory httpClientFactory,
|
||||
IAssemblyInformationProvider assemblyInformationProvider,
|
||||
IAbstractHttpClientFactory httpClientFactory,
|
||||
ILogger<GenericOAuthValidator> logger,
|
||||
OAuthConfiguration oAuthConfiguration)
|
||||
{
|
||||
this.httpClientFactory = httpClientFactory ?? throw new ArgumentNullException(nameof(httpClientFactory));
|
||||
this.assemblyInformationProvider = assemblyInformationProvider ?? throw new ArgumentNullException(nameof(assemblyInformationProvider));
|
||||
Logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
OAuthConfiguration = oAuthConfiguration ?? throw new ArgumentNullException(nameof(oAuthConfiguration));
|
||||
}
|
||||
@@ -109,7 +102,7 @@ namespace Tgstation.Server.Host.Security.OAuth
|
||||
tokenRequest.Content = new FormUrlEncodedContent(tokenRequestDictionary);
|
||||
|
||||
var tokenResponse = await httpClient.SendAsync(tokenRequest, cancellationToken);
|
||||
tokenResponsePayload = await tokenResponse.Content.ReadAsStringAsync();
|
||||
tokenResponsePayload = await tokenResponse.Content.ReadAsStringAsync(cancellationToken);
|
||||
tokenResponse.EnsureSuccessStatusCode();
|
||||
var tokenResponseJson = JObject.Parse(tokenResponsePayload);
|
||||
|
||||
@@ -129,7 +122,7 @@ namespace Tgstation.Server.Host.Security.OAuth
|
||||
accessToken);
|
||||
|
||||
var userInformationResponse = await httpClient.SendAsync(userInformationRequest, cancellationToken);
|
||||
userInformationPayload = await userInformationResponse.Content.ReadAsStringAsync();
|
||||
userInformationPayload = await userInformationResponse.Content.ReadAsStringAsync(cancellationToken);
|
||||
userInformationResponse.EnsureSuccessStatusCode();
|
||||
|
||||
var userInformationJson = JObject.Parse(userInformationPayload);
|
||||
@@ -178,16 +171,15 @@ namespace Tgstation.Server.Host.Security.OAuth
|
||||
protected abstract OAuthTokenRequest CreateTokenRequest(string code);
|
||||
|
||||
/// <summary>
|
||||
/// Create a new configured <see cref="HttpClient"/>.
|
||||
/// Create a new configured <see cref="IHttpClient"/>.
|
||||
/// </summary>
|
||||
/// <returns>A new configured <see cref="HttpClient"/>.</returns>
|
||||
HttpClient CreateHttpClient()
|
||||
/// <returns>A new configured <see cref="IHttpClient"/>.</returns>
|
||||
IHttpClient CreateHttpClient()
|
||||
{
|
||||
var httpClient = httpClientFactory.CreateClient();
|
||||
try
|
||||
{
|
||||
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(MediaTypeNames.Application.Json));
|
||||
httpClient.DefaultRequestHeaders.UserAgent.Add(assemblyInformationProvider.ProductInfoHeaderValue);
|
||||
return httpClient;
|
||||
}
|
||||
catch
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
using Tgstation.Server.Api.Models;
|
||||
using Tgstation.Server.Host.Configuration;
|
||||
using Tgstation.Server.Host.System;
|
||||
using Tgstation.Server.Host.Core;
|
||||
|
||||
namespace Tgstation.Server.Host.Security.OAuth
|
||||
{
|
||||
@@ -18,29 +17,27 @@ namespace Tgstation.Server.Host.Security.OAuth
|
||||
public override OAuthProvider Provider => OAuthProvider.InvisionCommunity;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Uri TokenUrl => new Uri($"{OAuthConfiguration.ServerUrl}/oauth/token/"); // This needs the trailing slash or it doesnt get the token. Do not remove.
|
||||
protected override Uri TokenUrl => new ($"{OAuthConfiguration.ServerUrl}/oauth/token/"); // This needs the trailing slash or it doesnt get the token. Do not remove.
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Uri UserInformationUrl => new Uri($"{OAuthConfiguration.ServerUrl}/api/core/me");
|
||||
protected override Uri UserInformationUrl => new ($"{OAuthConfiguration.ServerUrl}/api/core/me");
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="InvisionCommunityOAuthValidator"/> class.
|
||||
/// </summary>
|
||||
/// <param name="httpClientFactory">The <see cref="IHttpClientFactory"/> for the <see cref="GenericOAuthValidator"/>.</param>
|
||||
/// <param name="assemblyInformationProvider">The <see cref="IAssemblyInformationProvider"/> for the <see cref="GenericOAuthValidator"/>.</param>
|
||||
/// <param name="httpClientFactory">The <see cref="IAbstractHttpClientFactory"/> for the <see cref="GenericOAuthValidator"/>.</param>
|
||||
/// <param name="logger">The <see cref="ILogger"/> for the <see cref="GenericOAuthValidator"/>.</param>
|
||||
/// <param name="oAuthConfiguration">The <see cref="OAuthConfiguration"/> for the <see cref="GenericOAuthValidator"/>.</param>
|
||||
public InvisionCommunityOAuthValidator(
|
||||
IHttpClientFactory httpClientFactory,
|
||||
IAssemblyInformationProvider assemblyInformationProvider,
|
||||
IAbstractHttpClientFactory httpClientFactory,
|
||||
ILogger<InvisionCommunityOAuthValidator> logger,
|
||||
OAuthConfiguration oAuthConfiguration)
|
||||
: base(httpClientFactory, assemblyInformationProvider, logger, oAuthConfiguration)
|
||||
: base(httpClientFactory, logger, oAuthConfiguration)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override OAuthTokenRequest CreateTokenRequest(string code) => new OAuthTokenRequest(OAuthConfiguration, code, "profile");
|
||||
protected override OAuthTokenRequest CreateTokenRequest(string code) => new (OAuthConfiguration, code, "profile");
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override string DecodeTokenPayload(dynamic responseJson) => responseJson.access_token;
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
using Tgstation.Server.Api.Models;
|
||||
using Tgstation.Server.Host.Configuration;
|
||||
using Tgstation.Server.Host.System;
|
||||
using Tgstation.Server.Host.Core;
|
||||
|
||||
namespace Tgstation.Server.Host.Security.OAuth
|
||||
{
|
||||
@@ -18,10 +17,10 @@ namespace Tgstation.Server.Host.Security.OAuth
|
||||
public override OAuthProvider Provider => OAuthProvider.Keycloak;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Uri TokenUrl => new Uri($"{BaseProtocolPath}/token");
|
||||
protected override Uri TokenUrl => new ($"{BaseProtocolPath}/token");
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Uri UserInformationUrl => new Uri($"{BaseProtocolPath}/userinfo");
|
||||
protected override Uri UserInformationUrl => new ($"{BaseProtocolPath}/userinfo");
|
||||
|
||||
/// <summary>
|
||||
/// Base path to the server's OAuth endpoint.
|
||||
@@ -31,21 +30,19 @@ namespace Tgstation.Server.Host.Security.OAuth
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="KeycloakOAuthValidator"/> class.
|
||||
/// </summary>
|
||||
/// <param name="httpClientFactory">The <see cref="IHttpClientFactory"/> for the <see cref="GenericOAuthValidator"/>.</param>
|
||||
/// <param name="assemblyInformationProvider">The <see cref="IAssemblyInformationProvider"/> for the <see cref="GenericOAuthValidator"/>.</param>
|
||||
/// <param name="httpClientFactory">The <see cref="IAbstractHttpClientFactory"/> for the <see cref="GenericOAuthValidator"/>.</param>
|
||||
/// <param name="logger">The <see cref="ILogger"/> for the <see cref="GenericOAuthValidator"/>.</param>
|
||||
/// <param name="oAuthConfiguration">The <see cref="OAuthConfiguration"/> for the <see cref="GenericOAuthValidator"/>.</param>
|
||||
public KeycloakOAuthValidator(
|
||||
IHttpClientFactory httpClientFactory,
|
||||
IAssemblyInformationProvider assemblyInformationProvider,
|
||||
IAbstractHttpClientFactory httpClientFactory,
|
||||
ILogger<KeycloakOAuthValidator> logger,
|
||||
OAuthConfiguration oAuthConfiguration)
|
||||
: base(httpClientFactory, assemblyInformationProvider, logger, oAuthConfiguration)
|
||||
: base(httpClientFactory, logger, oAuthConfiguration)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override OAuthTokenRequest CreateTokenRequest(string code) => new OAuthTokenRequest(OAuthConfiguration, code, "openid");
|
||||
protected override OAuthTokenRequest CreateTokenRequest(string code) => new (OAuthConfiguration, code, "openid");
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override string DecodeTokenPayload(dynamic responseJson) => responseJson.access_token;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@@ -11,7 +10,6 @@ using Microsoft.Extensions.Options;
|
||||
using Tgstation.Server.Api.Models;
|
||||
using Tgstation.Server.Host.Configuration;
|
||||
using Tgstation.Server.Host.Core;
|
||||
using Tgstation.Server.Host.System;
|
||||
|
||||
namespace Tgstation.Server.Host.Security.OAuth
|
||||
{
|
||||
@@ -27,14 +25,12 @@ namespace Tgstation.Server.Host.Security.OAuth
|
||||
/// Initializes a new instance of the <see cref="OAuthProviders"/> class.
|
||||
/// </summary>
|
||||
/// <param name="gitHubClientFactory">The <see cref="IGitHubClientFactory"/> to use.</param>
|
||||
/// <param name="httpClientFactory">The <see cref="IHttpClientFactory"/> to use.</param>
|
||||
/// <param name="assemblyInformationProvider">The <see cref="IAssemblyInformationProvider"/> to use.</param>
|
||||
/// <param name="httpClientFactory">The <see cref="IAbstractHttpClientFactory"/> to use.</param>
|
||||
/// <param name="loggerFactory">The <see cref="ILoggerFactory"/> to use.</param>
|
||||
/// <param name="securityConfigurationOptions">The <see cref="IOptions{TOptions}"/> containing the <see cref="SecurityConfiguration"/> to use.</param>
|
||||
public OAuthProviders(
|
||||
IGitHubClientFactory gitHubClientFactory,
|
||||
IHttpClientFactory httpClientFactory,
|
||||
IAssemblyInformationProvider assemblyInformationProvider,
|
||||
IAbstractHttpClientFactory httpClientFactory,
|
||||
ILoggerFactory loggerFactory,
|
||||
IOptions<SecurityConfiguration> securityConfigurationOptions)
|
||||
{
|
||||
@@ -60,7 +56,6 @@ namespace Tgstation.Server.Host.Security.OAuth
|
||||
validatorsBuilder.Add(
|
||||
new DiscordOAuthValidator(
|
||||
httpClientFactory,
|
||||
assemblyInformationProvider,
|
||||
loggerFactory.CreateLogger<DiscordOAuthValidator>(),
|
||||
discordConfig));
|
||||
|
||||
@@ -68,7 +63,6 @@ namespace Tgstation.Server.Host.Security.OAuth
|
||||
validatorsBuilder.Add(
|
||||
new TGForumsOAuthValidator(
|
||||
httpClientFactory,
|
||||
assemblyInformationProvider,
|
||||
loggerFactory.CreateLogger<TGForumsOAuthValidator>(),
|
||||
tgConfig));
|
||||
|
||||
@@ -76,7 +70,6 @@ namespace Tgstation.Server.Host.Security.OAuth
|
||||
validatorsBuilder.Add(
|
||||
new KeycloakOAuthValidator(
|
||||
httpClientFactory,
|
||||
assemblyInformationProvider,
|
||||
loggerFactory.CreateLogger<KeycloakOAuthValidator>(),
|
||||
keyCloakConfig));
|
||||
|
||||
@@ -84,7 +77,6 @@ namespace Tgstation.Server.Host.Security.OAuth
|
||||
validatorsBuilder.Add(
|
||||
new InvisionCommunityOAuthValidator(
|
||||
httpClientFactory,
|
||||
assemblyInformationProvider,
|
||||
loggerFactory.CreateLogger<InvisionCommunityOAuthValidator>(),
|
||||
invisionConfig));
|
||||
}
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
using Tgstation.Server.Api.Models;
|
||||
using Tgstation.Server.Host.Configuration;
|
||||
using Tgstation.Server.Host.System;
|
||||
using Tgstation.Server.Host.Core;
|
||||
|
||||
namespace Tgstation.Server.Host.Security.OAuth
|
||||
{
|
||||
@@ -26,18 +25,15 @@ namespace Tgstation.Server.Host.Security.OAuth
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TGForumsOAuthValidator"/> class.
|
||||
/// </summary>
|
||||
/// <param name="httpClientFactory">The <see cref="IHttpClientFactory"/> for the <see cref="GenericOAuthValidator"/>.</param>
|
||||
/// <param name="assemblyInformationProvider">The <see cref="IAssemblyInformationProvider"/> for the <see cref="GenericOAuthValidator"/>.</param>
|
||||
/// <param name="httpClientFactory">The <see cref="IAbstractHttpClientFactory"/> for the <see cref="GenericOAuthValidator"/>.</param>
|
||||
/// <param name="logger">The <see cref="ILogger"/> for the <see cref="GenericOAuthValidator"/>.</param>
|
||||
/// <param name="oAuthConfiguration">The <see cref="OAuthConfiguration"/> for the <see cref="GenericOAuthValidator"/>.</param>
|
||||
public TGForumsOAuthValidator(
|
||||
IHttpClientFactory httpClientFactory,
|
||||
IAssemblyInformationProvider assemblyInformationProvider,
|
||||
IAbstractHttpClientFactory httpClientFactory,
|
||||
ILogger<TGForumsOAuthValidator> logger,
|
||||
OAuthConfiguration oAuthConfiguration)
|
||||
: base(
|
||||
httpClientFactory,
|
||||
assemblyInformationProvider,
|
||||
logger,
|
||||
oAuthConfiguration)
|
||||
{
|
||||
|
||||
@@ -71,11 +71,6 @@ namespace Tgstation.Server.Host.Swarm
|
||||
/// </summary>
|
||||
bool SwarmMode => swarmConfiguration.PrivateKey != null;
|
||||
|
||||
/// <summary>
|
||||
/// Lazily constructed <see cref="IRestartRegistration"/>.
|
||||
/// </summary>
|
||||
readonly Lazy<IRestartRegistration> lazyRestartRegistration;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="IDatabaseContextFactory"/> for the <see cref="SwarmService"/>.
|
||||
/// </summary>
|
||||
@@ -92,9 +87,9 @@ namespace Tgstation.Server.Host.Swarm
|
||||
readonly IAssemblyInformationProvider assemblyInformationProvider;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="IHttpClientFactory"/> for the <see cref="SwarmService"/>.
|
||||
/// The <see cref="IAbstractHttpClientFactory"/> for the <see cref="SwarmService"/>.
|
||||
/// </summary>
|
||||
readonly IHttpClientFactory httpClientFactory;
|
||||
readonly IAbstractHttpClientFactory httpClientFactory;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="IAsyncDelayer"/> for the <see cref="SwarmService"/>.
|
||||
@@ -106,6 +101,11 @@ namespace Tgstation.Server.Host.Swarm
|
||||
/// </summary>
|
||||
readonly IServerUpdater serverUpdater;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="IRestartRegistration"/> for the <see cref="SwarmService"/>.
|
||||
/// </summary>
|
||||
readonly IRestartRegistration restartRegistration;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="ILogger"/> for the <see cref="SwarmService"/>.
|
||||
/// </summary>
|
||||
@@ -202,7 +202,7 @@ namespace Tgstation.Server.Host.Swarm
|
||||
IDatabaseContextFactory databaseContextFactory,
|
||||
IDatabaseSeeder databaseSeeder,
|
||||
IAssemblyInformationProvider assemblyInformationProvider,
|
||||
IHttpClientFactory httpClientFactory,
|
||||
IAbstractHttpClientFactory httpClientFactory,
|
||||
IServerControl serverControl,
|
||||
IServerUpdater serverUpdater,
|
||||
IAsyncDelayer asyncDelayer,
|
||||
@@ -215,6 +215,7 @@ namespace Tgstation.Server.Host.Swarm
|
||||
this.httpClientFactory = httpClientFactory ?? throw new ArgumentNullException(nameof(httpClientFactory));
|
||||
if (serverControl == null)
|
||||
throw new ArgumentNullException(nameof(serverControl));
|
||||
restartRegistration = serverControl.RegisterForRestart(this);
|
||||
|
||||
this.serverUpdater = serverUpdater ?? throw new ArgumentNullException(nameof(serverUpdater));
|
||||
this.asyncDelayer = asyncDelayer ?? throw new ArgumentNullException(nameof(asyncDelayer));
|
||||
@@ -249,12 +250,14 @@ namespace Tgstation.Server.Host.Swarm
|
||||
|
||||
updateSynchronizationLock = new object();
|
||||
}
|
||||
|
||||
lazyRestartRegistration = new Lazy<IRestartRegistration>(() => serverControl.RegisterForRestart(this));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Dispose() => serverHealthCheckCancellationTokenSource?.Dispose();
|
||||
public void Dispose()
|
||||
{
|
||||
restartRegistration.Dispose();
|
||||
serverHealthCheckCancellationTokenSource?.Dispose();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task RemoteAbortUpdate(CancellationToken cancellationToken)
|
||||
@@ -379,7 +382,7 @@ namespace Tgstation.Server.Host.Swarm
|
||||
if (!commitGoAhead)
|
||||
{
|
||||
logger.LogDebug(
|
||||
"Update commit failed!{0}",
|
||||
"Update commit failed!{maybeTimeout}",
|
||||
timeoutTask.IsCompleted
|
||||
? " Timed out!"
|
||||
: String.Empty);
|
||||
@@ -465,8 +468,6 @@ namespace Tgstation.Server.Host.Swarm
|
||||
else
|
||||
logger.LogTrace("Swarm mode disabled");
|
||||
|
||||
_ = lazyRestartRegistration.Value;
|
||||
|
||||
SwarmRegistrationResult result;
|
||||
if (swarmController)
|
||||
{
|
||||
@@ -1164,25 +1165,22 @@ namespace Tgstation.Server.Host.Swarm
|
||||
var request = new HttpRequestMessage(
|
||||
httpMethod,
|
||||
swarmServer.Address + subroute[1..]);
|
||||
|
||||
request.Headers.Add(SwarmConstants.ApiKeyHeader, swarmConfiguration.PrivateKey);
|
||||
request.Headers.UserAgent.Clear();
|
||||
request.Headers.UserAgent.Add(assemblyInformationProvider.ProductInfoHeaderValue);
|
||||
request.Headers.Accept.Clear();
|
||||
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(MediaTypeNames.Application.Json));
|
||||
if (registrationIdOverride.HasValue)
|
||||
request.Headers.Add(SwarmConstants.RegistrationIdHeader, registrationIdOverride.Value.ToString());
|
||||
else if (swarmController)
|
||||
{
|
||||
lock (swarmServers)
|
||||
if (registrationIds.TryGetValue(swarmServer.Identifier, out var registrationId))
|
||||
request.Headers.Add(SwarmConstants.RegistrationIdHeader, registrationId.ToString());
|
||||
}
|
||||
else if (controllerRegistration.HasValue)
|
||||
request.Headers.Add(SwarmConstants.RegistrationIdHeader, controllerRegistration.Value.ToString());
|
||||
|
||||
try
|
||||
{
|
||||
request.Headers.Add(SwarmConstants.ApiKeyHeader, swarmConfiguration.PrivateKey);
|
||||
request.Headers.Accept.Clear();
|
||||
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(MediaTypeNames.Application.Json));
|
||||
if (registrationIdOverride.HasValue)
|
||||
request.Headers.Add(SwarmConstants.RegistrationIdHeader, registrationIdOverride.Value.ToString());
|
||||
else if (swarmController)
|
||||
{
|
||||
lock (swarmServers)
|
||||
if (registrationIds.TryGetValue(swarmServer.Identifier, out var registrationId))
|
||||
request.Headers.Add(SwarmConstants.RegistrationIdHeader, registrationId.ToString());
|
||||
}
|
||||
else if (controllerRegistration.HasValue)
|
||||
request.Headers.Add(SwarmConstants.RegistrationIdHeader, controllerRegistration.Value.ToString());
|
||||
|
||||
if (body != null)
|
||||
request.Content = new StringContent(
|
||||
JsonConvert.SerializeObject(body, SerializerSettings),
|
||||
|
||||
@@ -139,6 +139,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Tgstation.Server.Api\Tgstation.Server.Api.csproj" />
|
||||
<ProjectReference Include="..\Tgstation.Server.Common\Tgstation.Server.Common.csproj" />
|
||||
<ProjectReference Include="..\Tgstation.Server.Host.Common\Tgstation.Server.Host.Common.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -11,8 +11,8 @@ using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Tgstation.Server.Api;
|
||||
using Tgstation.Server.Api.Models;
|
||||
using Tgstation.Server.Api.Models.Response;
|
||||
using Tgstation.Server.Common;
|
||||
|
||||
namespace Tgstation.Server.Client.Tests
|
||||
{
|
||||
|
||||
@@ -15,14 +15,16 @@ namespace Tgstation.Server.Host.Components.Byond.Tests
|
||||
[TestMethod]
|
||||
public void TestConstruction()
|
||||
{
|
||||
Assert.ThrowsException<ArgumentNullException>(() => new PosixByondInstaller(null, null, null));
|
||||
Assert.ThrowsException<ArgumentNullException>(() => new PosixByondInstaller(null, null, null, null));
|
||||
var mockPostWriteHandler = new Mock<IPostWriteHandler>();
|
||||
Assert.ThrowsException<ArgumentNullException>(() => new PosixByondInstaller(mockPostWriteHandler.Object, null, null));
|
||||
Assert.ThrowsException<ArgumentNullException>(() => new PosixByondInstaller(mockPostWriteHandler.Object, null, null, null));
|
||||
var mockIOManager = new Mock<IIOManager>();
|
||||
Assert.ThrowsException<ArgumentNullException>(() => new PosixByondInstaller(mockPostWriteHandler.Object, mockIOManager.Object, null));
|
||||
Assert.ThrowsException<ArgumentNullException>(() => new PosixByondInstaller(mockPostWriteHandler.Object, mockIOManager.Object, null, null));
|
||||
var mockFileDownloader = Mock.Of<IFileDownloader>();
|
||||
Assert.ThrowsException<ArgumentNullException>(() => new PosixByondInstaller(mockPostWriteHandler.Object, mockIOManager.Object, mockFileDownloader, null));
|
||||
|
||||
var mockLogger = new Mock<ILogger<PosixByondInstaller>>();
|
||||
_ = new PosixByondInstaller(mockPostWriteHandler.Object, mockIOManager.Object, mockLogger.Object);
|
||||
_ = new PosixByondInstaller(mockPostWriteHandler.Object, mockIOManager.Object, mockFileDownloader, mockLogger.Object);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
@@ -31,7 +33,8 @@ namespace Tgstation.Server.Host.Components.Byond.Tests
|
||||
var mockPostWriteHandler = new Mock<IPostWriteHandler>();
|
||||
var mockIOManager = new Mock<IIOManager>();
|
||||
var mockLogger = new Mock<ILogger<PosixByondInstaller>>();
|
||||
var installer = new PosixByondInstaller(mockPostWriteHandler.Object, mockIOManager.Object, mockLogger.Object);
|
||||
var mockFileDownloader = Mock.Of<IFileDownloader>();
|
||||
var installer = new PosixByondInstaller(mockPostWriteHandler.Object, mockIOManager.Object, mockFileDownloader, mockLogger.Object);
|
||||
await installer.CleanCache(default);
|
||||
}
|
||||
|
||||
@@ -42,12 +45,13 @@ namespace Tgstation.Server.Host.Components.Byond.Tests
|
||||
var mockIOManager = new Mock<IIOManager>();
|
||||
var mockPostWriteHandler = new Mock<IPostWriteHandler>();
|
||||
var mockLogger = new Mock<ILogger<PosixByondInstaller>>();
|
||||
var installer = new PosixByondInstaller(mockPostWriteHandler.Object, mockIOManager.Object, mockLogger.Object);
|
||||
var mockFileDownloader = new Mock<IFileDownloader>();
|
||||
var installer = new PosixByondInstaller(mockPostWriteHandler.Object, mockIOManager.Object, mockFileDownloader.Object, mockLogger.Object);
|
||||
|
||||
await Assert.ThrowsExceptionAsync<ArgumentNullException>(() => installer.DownloadVersion(null, default));
|
||||
|
||||
var ourArray = Array.Empty<byte>();
|
||||
mockIOManager.Setup(x => x.DownloadFile(It.Is<Uri>(uri => uri == new Uri("https://secure.byond.com/download/build/511/511.1385_byond_linux.zip")), default)).Returns(Task.FromResult(new MemoryStream(ourArray))).Verifiable();
|
||||
mockFileDownloader.Setup(x => x.DownloadFile(It.Is<Uri>(uri => uri == new Uri("https://secure.byond.com/download/build/511/511.1385_byond_linux.zip")), default)).Returns(Task.FromResult(new MemoryStream(ourArray))).Verifiable();
|
||||
|
||||
var result = await installer.DownloadVersion(new Version(511, 1385), default);
|
||||
|
||||
@@ -61,7 +65,8 @@ namespace Tgstation.Server.Host.Components.Byond.Tests
|
||||
var mockIOManager = new Mock<IIOManager>();
|
||||
var mockPostWriteHandler = new Mock<IPostWriteHandler>();
|
||||
var mockLogger = new Mock<ILogger<PosixByondInstaller>>();
|
||||
var installer = new PosixByondInstaller(mockPostWriteHandler.Object, mockIOManager.Object, mockLogger.Object);
|
||||
var mockFileDownloader = Mock.Of<IFileDownloader>();
|
||||
var installer = new PosixByondInstaller(mockPostWriteHandler.Object, mockIOManager.Object, mockFileDownloader, mockLogger.Object);
|
||||
|
||||
const string FakePath = "fake";
|
||||
await Assert.ThrowsExceptionAsync<ArgumentNullException>(() => installer.InstallByond(null, null, default));
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace Tgstation.Server.Host.IO.Tests
|
||||
[TestClass]
|
||||
public sealed class TestIOManager
|
||||
{
|
||||
readonly IIOManager ioManager = new DefaultIOManager(new AssemblyInformationProvider());
|
||||
readonly IIOManager ioManager = new DefaultIOManager();
|
||||
|
||||
[TestMethod]
|
||||
public async Task TestDeleteDirectory()
|
||||
|
||||
@@ -57,7 +57,7 @@ namespace Tgstation.Server.Host.System.Tests
|
||||
processExecutor = new ProcessExecutor(
|
||||
new PosixProcessFeatures(
|
||||
new Lazy<IProcessExecutor>(() => processExecutor),
|
||||
new DefaultIOManager(new AssemblyInformationProvider()),
|
||||
new DefaultIOManager(),
|
||||
loggerFactory.CreateLogger<PosixProcessFeatures>()),
|
||||
Mock.Of<IIOManager>(),
|
||||
loggerFactory.CreateLogger<ProcessExecutor>(),
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace Tgstation.Server.Host.System.Tests
|
||||
{
|
||||
features = RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
|
||||
? (IProcessFeatures)new WindowsProcessFeatures(Mock.Of<ILogger<WindowsProcessFeatures>>())
|
||||
: new PosixProcessFeatures(new Lazy<IProcessExecutor>(() => null), new DefaultIOManager(new AssemblyInformationProvider()), Mock.Of<ILogger<PosixProcessFeatures>>());
|
||||
: new PosixProcessFeatures(new Lazy<IProcessExecutor>(() => null), new DefaultIOManager(), Mock.Of<ILogger<PosixProcessFeatures>>());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
|
||||
@@ -84,7 +84,7 @@ namespace Tgstation.Server.Host.Tests
|
||||
mockServer.Setup(x => x.Run(It.IsAny<CancellationToken>())).Throws(exception);
|
||||
mockServer.SetupGet(x => x.RestartRequested).Returns(true);
|
||||
var mockServerFactory = new Mock<IServerFactory>();
|
||||
mockServerFactory.SetupGet(x => x.IOManager).Returns(new DefaultIOManager(new AssemblyInformationProvider()));
|
||||
mockServerFactory.SetupGet(x => x.IOManager).Returns(new DefaultIOManager());
|
||||
mockServerFactory.Setup(x => x.CreateServer(It.IsNotNull<string[]>(), It.IsAny<string>(), It.IsAny<CancellationToken>())).ReturnsAsync(mockServer.Object);
|
||||
var program = new Program
|
||||
{
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
using Tgstation.Server.Common;
|
||||
using Tgstation.Server.Host.Core;
|
||||
|
||||
namespace Tgstation.Server.Tests
|
||||
{
|
||||
sealed class ConcreteHttpClientFactory : IAbstractHttpClientFactory
|
||||
{
|
||||
public IHttpClient CreateClient() => new HttpClient();
|
||||
}
|
||||
}
|
||||
@@ -105,12 +105,18 @@ namespace Tgstation.Server.Tests.Instance
|
||||
var byondInstaller = new PlatformIdentifier().IsWindows
|
||||
? (IByondInstaller)new WindowsByondInstaller(
|
||||
Mock.Of<IProcessExecutor>(),
|
||||
new DefaultIOManager(new AssemblyInformationProvider()),
|
||||
Mock.Of<IIOManager>(),
|
||||
new FileDownloader(
|
||||
new ConcreteHttpClientFactory(),
|
||||
Mock.Of<ILogger<FileDownloader>>()),
|
||||
generalConfigOptionsMock.Object,
|
||||
Mock.Of<ILogger<WindowsByondInstaller>>())
|
||||
: new PosixByondInstaller(
|
||||
Mock.Of<IPostWriteHandler>(),
|
||||
new DefaultIOManager(new AssemblyInformationProvider()),
|
||||
Mock.Of<IIOManager>(),
|
||||
new FileDownloader(
|
||||
new ConcreteHttpClientFactory(),
|
||||
Mock.Of<ILogger<FileDownloader>>()),
|
||||
Mock.Of<ILogger<PosixByondInstaller>>());
|
||||
|
||||
using var windowsByondInstaller = byondInstaller as WindowsByondInstaller;
|
||||
|
||||
@@ -103,7 +103,7 @@ namespace Tgstation.Server.Tests.Instance
|
||||
Task SetupDMApiTests(CancellationToken cancellationToken)
|
||||
{
|
||||
// just use an I/O manager here
|
||||
var ioManager = new DefaultIOManager(new AssemblyInformationProvider());
|
||||
var ioManager = new DefaultIOManager();
|
||||
return Task.WhenAll(
|
||||
ioManager.CopyDirectory(
|
||||
"../../../../DMAPI",
|
||||
|
||||
@@ -193,6 +193,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tgstation.Server.Migrator.C
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tgstation.Server.Host.Common", "src\Tgstation.Server.Host.Common\Tgstation.Server.Host.Common.csproj", "{CF3968A0-EA81-4464-B2D4-C7D40F6B5BCB}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tgstation.Server.Common", "src\Tgstation.Server.Common\Tgstation.Server.Common.csproj", "{70CD9A98-D31A-44A4-81D1-D02764CEEEFD}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -341,6 +343,14 @@ Global
|
||||
{CF3968A0-EA81-4464-B2D4-C7D40F6B5BCB}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{CF3968A0-EA81-4464-B2D4-C7D40F6B5BCB}.ReleaseNoService|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{CF3968A0-EA81-4464-B2D4-C7D40F6B5BCB}.ReleaseNoService|Any CPU.Build.0 = Release|Any CPU
|
||||
{70CD9A98-D31A-44A4-81D1-D02764CEEEFD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{70CD9A98-D31A-44A4-81D1-D02764CEEEFD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{70CD9A98-D31A-44A4-81D1-D02764CEEEFD}.DebugNoService|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{70CD9A98-D31A-44A4-81D1-D02764CEEEFD}.DebugNoService|Any CPU.Build.0 = Debug|Any CPU
|
||||
{70CD9A98-D31A-44A4-81D1-D02764CEEEFD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{70CD9A98-D31A-44A4-81D1-D02764CEEEFD}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{70CD9A98-D31A-44A4-81D1-D02764CEEEFD}.ReleaseNoService|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{70CD9A98-D31A-44A4-81D1-D02764CEEEFD}.ReleaseNoService|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
using Tgstation.Server.Common;
|
||||
using Tgstation.Server.Host.Core;
|
||||
|
||||
namespace Tgstation.Server.Migrator
|
||||
{
|
||||
sealed class ConcreteHttpClientFactory : IAbstractHttpClientFactory
|
||||
{
|
||||
public IHttpClient CreateClient() => new HttpClient();
|
||||
}
|
||||
}
|
||||
@@ -15,11 +15,15 @@ using System.ServiceProcess;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
using Octokit;
|
||||
|
||||
using Tgstation.Server.Api;
|
||||
using Tgstation.Server.Client;
|
||||
using Tgstation.Server.Host.IO;
|
||||
using Tgstation.Server.Host.Setup;
|
||||
using Tgstation.Server.Migrator;
|
||||
|
||||
using FileMode = System.IO.FileMode;
|
||||
|
||||
@@ -377,10 +381,14 @@ try
|
||||
|
||||
// TGS5 DOWNLOAD AND UNZIP
|
||||
Console.WriteLine("Downloading TGS5...");
|
||||
using (var tgsFiveZipMemoryStream = await SetupApplication.IOManager.DownloadFile(new Uri(serverServiceAsset.BrowserDownloadUrl), default))
|
||||
|
||||
var httpClientFactory = new ConcreteHttpClientFactory();
|
||||
using (var loggerFactory = LoggerFactory.Create(builder => { }))
|
||||
{
|
||||
var fileDownloader = new FileDownloader(httpClientFactory, loggerFactory.CreateLogger<FileDownloader>());
|
||||
using var tgsFiveZipMemoryStream = await fileDownloader.DownloadFile(new Uri(serverServiceAsset.BrowserDownloadUrl), default);
|
||||
Console.WriteLine("Unzipping TGS5...");
|
||||
await SetupApplication.IOManager.ZipToDirectory(tgsInstallPath, tgsFiveZipMemoryStream, default);
|
||||
await serverFactory.IOManager.ZipToDirectory(tgsInstallPath, tgsFiveZipMemoryStream, default);
|
||||
}
|
||||
|
||||
// TGS5 CONFIG SETUP
|
||||
|
||||
Reference in New Issue
Block a user