General code cleanup pass

This commit is contained in:
Cyberboss
2020-01-12 17:29:49 -05:00
parent 9f27402195
commit cd53ca9db4
12 changed files with 143 additions and 25 deletions
@@ -4,7 +4,6 @@ using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using Tgstation.Server.Api;
+13 -4
View File
@@ -23,7 +23,6 @@ using System;
using System.Globalization;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Tgstation.Server.Api;
using Tgstation.Server.Host.Components;
@@ -57,6 +56,11 @@ namespace Tgstation.Server.Host.Core
/// </summary>
readonly IConfiguration configuration;
/// <summary>
/// The <see cref="IAssemblyInformationProvider"/> for the <see cref="Application"/>.
/// </summary>
readonly IAssemblyInformationProvider assemblyInformationProvider;
/// <summary>
/// The <see cref="Microsoft.AspNetCore.Hosting.IHostingEnvironment"/> for the <see cref="Application"/>
/// </summary>
@@ -76,15 +80,20 @@ namespace Tgstation.Server.Host.Core
/// Construct an <see cref="Application"/>
/// </summary>
/// <param name="configuration">The value of <see cref="configuration"/></param>
/// <param name="assemblyInformationProvider">The <see cref="IAssemblyInformationProvider"/> for the <see cref="Application"/>.</param>
/// <param name="hostingEnvironment">The value of <see cref="hostingEnvironment"/></param>
public Application(IConfiguration configuration, Microsoft.AspNetCore.Hosting.IHostingEnvironment hostingEnvironment)
public Application(
IConfiguration configuration,
IAssemblyInformationProvider assemblyInformationProvider,
Microsoft.AspNetCore.Hosting.IHostingEnvironment hostingEnvironment)
{
this.configuration = configuration ?? throw new ArgumentNullException(nameof(configuration));
this.assemblyInformationProvider = assemblyInformationProvider ?? throw new ArgumentNullException(nameof(assemblyInformationProvider));
this.hostingEnvironment = hostingEnvironment ?? throw new ArgumentNullException(nameof(hostingEnvironment));
startupTcs = new TaskCompletionSource<object>();
Version = Assembly.GetExecutingAssembly().GetName().Version;
Version = assemblyInformationProvider.Name.Version;
VersionString = String.Format(CultureInfo.InvariantCulture, "{0} v{1}", VersionPrefix, Version);
}
@@ -258,7 +267,7 @@ namespace Tgstation.Server.Host.Core
// Important to do this before applying our own filters
// Otherwise we'll get NullReferenceExceptions on parameters to be setup in our document filter
var assemblyLocation = Assembly.GetExecutingAssembly().Location;
var assemblyLocation = assemblyInformationProvider.Path;
var filePath = ioManager.ConcatPath(ioManager.GetDirectoryName(assemblyLocation), String.Concat(ioManager.GetFileNameWithoutExtension(assemblyLocation), ".xml"));
c.IncludeXmlComments(filePath);
@@ -0,0 +1,24 @@
using System.Reflection;
namespace Tgstation.Server.Host.Core
{
/// <inheritdoc />
sealed class AssemblyInformationProvider : IAssemblyInformationProvider
{
/// <inheritdoc />
public string Path { get; }
/// <inheritdoc />
public AssemblyName Name { get; }
/// <summary>
/// Initializes a new instance of the <see cref="AssemblyInformationProvider"/> <see langword="class"/>.
/// </summary>
public AssemblyInformationProvider()
{
Assembly assembly = Assembly.GetExecutingAssembly();
Path = assembly.Location;
Name = assembly.GetName();
}
}
}
@@ -0,0 +1,20 @@
using System.Reflection;
namespace Tgstation.Server.Host.Core
{
/// <summary>
/// For retrieving the <see cref="Assembly"/>'s location.
/// </summary>
interface IAssemblyInformationProvider
{
/// <summary>
/// Gets the path to the executing assembly.
/// </summary>
string Path { get; }
/// <summary>
/// Gets the <see cref="AssemblyName"/>.
/// </summary>
AssemblyName Name { get; }
}
}
@@ -1,8 +1,8 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Options;
using System.IO;
using System.Reflection;
using Tgstation.Server.Host.Configuration;
using Tgstation.Server.Host.Core;
using Tgstation.Server.Host.IO;
namespace Tgstation.Server.Host.Models.Migrations
{
@@ -28,7 +28,9 @@ namespace Tgstation.Server.Host.Models.Migrations
public static IOptions<DatabaseConfiguration> GetDbContextOptions()
{
var builder = new ConfigurationBuilder();
builder.SetBasePath(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location));
var assemblyInfoProvider = new AssemblyInformationProvider();
var ioManager = new DefaultIOManager();
builder.SetBasePath(ioManager.GetDirectoryName(assemblyInfoProvider.Path));
builder.AddJsonFile(RootJson);
builder.AddJsonFile(DevJson);
var configuration = builder.Build();
+1 -1
View File
@@ -16,7 +16,7 @@ namespace Tgstation.Server.Host
/// The <see cref="IServerFactory"/> to use
/// </summary>
#pragma warning disable SA1401 // Fields must be private
internal static IServerFactory ServerFactory = new ServerFactory();
internal static IServerFactory ServerFactory = Host.ServerFactory.CreateDefault();
#pragma warning restore SA1401 // Fields must be private
/// <summary>
@@ -2,7 +2,6 @@
using System;
using System.Globalization;
using System.IdentityModel.Tokens.Jwt;
using System.Reflection;
using System.Security.Claims;
using System.Threading;
using System.Threading.Tasks;
@@ -42,7 +41,11 @@ namespace Tgstation.Server.Host.Security
/// </summary>
/// <param name="asyncDelayer">The value of <see cref="asyncDelayer"/></param>
/// <param name="cryptographySuite">The <see cref="ICryptographySuite"/> used for generating the <see cref="ValidationParameters"/></param>
public TokenFactory(IAsyncDelayer asyncDelayer, ICryptographySuite cryptographySuite)
/// <param name="assemblyInformationProvider">The <see cref="IAssemblyInformationProvider"/> used to generate the issuer name.</param>
public TokenFactory(
IAsyncDelayer asyncDelayer,
ICryptographySuite cryptographySuite,
IAssemblyInformationProvider assemblyInformationProvider)
{
ValidationParameters = new TokenValidationParameters
{
@@ -50,7 +53,7 @@ namespace Tgstation.Server.Host.Security
IssuerSigningKey = new SymmetricSecurityKey(cryptographySuite.GetSecureBytes(TokenSigningKeyByteAmount)),
ValidateIssuer = true,
ValidIssuer = Assembly.GetExecutingAssembly().GetName().Name,
ValidIssuer = assemblyInformationProvider.Name.Name,
ValidateLifetime = true,
ValidateAudience = true,
+8 -1
View File
@@ -30,6 +30,11 @@ namespace Tgstation.Server.Host
/// </summary>
readonly IWebHostBuilder webHostBuilder;
/// <summary>
/// The <see cref="IIOManager"/> for the <see cref="Server"/>.
/// </summary>
readonly IIOManager ioManager;
/// <summary>
/// The <see cref="IRestartHandler"/>s to run when the <see cref="Server"/> restarts
/// </summary>
@@ -69,10 +74,12 @@ namespace Tgstation.Server.Host
/// Construct a <see cref="Server"/>
/// </summary>
/// <param name="webHostBuilder">The value of <see cref="webHostBuilder"/></param>
/// <param name="ioManager">The value of <see cref="ioManager"/>.</param>
/// <param name="updatePath">The value of <see cref="updatePath"/></param>
public Server(IWebHostBuilder webHostBuilder, string updatePath)
public Server(IWebHostBuilder webHostBuilder, IIOManager ioManager, string updatePath)
{
this.webHostBuilder = webHostBuilder ?? throw new ArgumentNullException(nameof(webHostBuilder));
this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
this.updatePath = updatePath;
webHostBuilder.ConfigureServices(serviceCollection => serviceCollection.AddSingleton<IServerControl>(this));
+39 -3
View File
@@ -1,29 +1,65 @@
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.IO;
using System.Reflection;
using Tgstation.Server.Host.Core;
using Tgstation.Server.Host.IO;
namespace Tgstation.Server.Host
{
/// <inheritdoc />
public sealed class ServerFactory : IServerFactory
{
/// <summary>
/// The <see cref="IAssemblyInformationProvider"/> for the <see cref="ServerFactory"/>.
/// </summary>
readonly IAssemblyInformationProvider assemblyInformationProvider;
/// <summary>
/// The <see cref="IIOManager"/> for the <see cref="ServerFactory"/>.
/// </summary>
readonly IIOManager ioManager;
/// <summary>
/// Create the default <see cref="IServerFactory"/>.
/// </summary>
/// <returns>A new <see cref="IServerFactory"/> with the default settings.</returns>
public static IServerFactory CreateDefault()
=> new ServerFactory(
new AssemblyInformationProvider(),
new DefaultIOManager());
/// <summary>
/// Initializes a new instance of the <see cref="ServerFactory"/>.
/// </summary>
/// <param name="assemblyInformationProvider">The value of <see cref="assemblyInformationProvider"/>.</param>
/// <param name="ioManager">The value of <see cref="ioManager"/>.</param>
internal ServerFactory(IAssemblyInformationProvider assemblyInformationProvider, IIOManager ioManager)
{
this.assemblyInformationProvider = assemblyInformationProvider ?? throw new ArgumentNullException(nameof(assemblyInformationProvider));
this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
}
/// <inheritdoc />
public IServer CreateServer(string[] args, string updatePath)
{
var webHost = WebHost.CreateDefaultBuilder(args ?? throw new ArgumentNullException(nameof(args)))
.ConfigureAppConfiguration((context, configurationBuilder) => configurationBuilder.SetBasePath(Directory.GetCurrentDirectory()))
.ConfigureServices(serviceCollection =>
{
serviceCollection.AddSingleton(ioManager);
serviceCollection.AddSingleton(assemblyInformationProvider);
})
.UseStartup<Application>()
.SuppressStatusMessages(true)
.UseShutdownTimeout(TimeSpan.FromMinutes(1));
if(updatePath != null)
webHost.UseContentRoot(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location));
webHost.UseContentRoot(Path.GetDirectoryName(assemblyInformationProvider.Path));
return new Server(webHost, updatePath);
return new Server(webHost, ioManager, updatePath);
}
}
}
@@ -23,13 +23,18 @@ namespace Tgstation.Server.Host.Core.Tests
[TestMethod]
public void TestMethodThrows()
{
Assert.ThrowsException<ArgumentNullException>(() => new Application(null, null));
Assert.ThrowsException<ArgumentNullException>(() => new Application(null, null, null));
var mockConfiguration = new Mock<IConfiguration>();
Assert.ThrowsException<ArgumentNullException>(() => new Application(mockConfiguration.Object, null));
Assert.ThrowsException<ArgumentNullException>(() => new Application(mockConfiguration.Object, null, null));
var mockAssemblyInfo = new Mock<IAssemblyInformationProvider>();
mockAssemblyInfo.SetupGet(x => x.Name).Returns(typeof(Application).Assembly.GetName());
Assert.ThrowsException<ArgumentNullException>(() => new Application(mockConfiguration.Object, mockAssemblyInfo.Object, null));
var mockHostingEnvironment = new Mock<IHostingEnvironment>();
var app = new Application(mockConfiguration.Object, mockHostingEnvironment.Object);
var app = new Application(mockConfiguration.Object, mockAssemblyInfo.Object, mockHostingEnvironment.Object);
Assert.ThrowsException<ArgumentNullException>(() => app.ConfigureServices(null));
Assert.ThrowsException<ArgumentNullException>(() => app.Configure(null, null, null, null, null));
@@ -69,11 +74,11 @@ namespace Tgstation.Server.Host.Core.Tests
public void TestConfigureServicesThrowsWhenSetupWizardConfigurationDemands()
{
var mockConfiguration = new Mock<IConfiguration>();
Assert.ThrowsException<ArgumentNullException>(() => new Application(mockConfiguration.Object, null));
var mockAssemblyInfo = new Mock<IAssemblyInformationProvider>();
mockAssemblyInfo.SetupGet(x => x.Name).Returns(typeof(Application).Assembly.GetName());
var mockHostingEnvironment = new Mock<IHostingEnvironment>();
var app = new Application(mockConfiguration.Object, mockHostingEnvironment.Object);
var app = new Application(mockConfiguration.Object, mockAssemblyInfo.Object, mockHostingEnvironment.Object);
var mockOptions = new Mock<IOptions<GeneralConfiguration>>();
mockOptions.SetupGet(x => x.Value).Returns(new GeneralConfiguration
@@ -1,5 +1,8 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using System;
using Tgstation.Server.Host.Core;
using Tgstation.Server.Host.IO;
namespace Tgstation.Server.Host.Tests
{
@@ -9,10 +12,20 @@ namespace Tgstation.Server.Host.Tests
[TestClass]
public sealed class TestServerFactory
{
[TestMethod]
public void TestContructor()
{
Assert.ThrowsException<ArgumentNullException>(() => new ServerFactory(null, null));
IAssemblyInformationProvider assemblyInformationProvider = Mock.Of<IAssemblyInformationProvider>();
Assert.ThrowsException<ArgumentNullException>(() => new ServerFactory(assemblyInformationProvider, null));
IIOManager ioManager = Mock.Of<IIOManager>();
new ServerFactory(assemblyInformationProvider, ioManager);
}
[TestMethod]
public void TestWorksWithoutUpdatePath()
{
var factory = new ServerFactory();
var factory = ServerFactory.CreateDefault();
Assert.ThrowsException<ArgumentNullException>(() => factory.CreateServer(null, null));
factory.CreateServer(Array.Empty<string>(), null);
@@ -21,7 +34,7 @@ namespace Tgstation.Server.Host.Tests
[TestMethod]
public void TestWorksWithUpdatePath()
{
var factory = new ServerFactory();
var factory = ServerFactory.CreateDefault();
const string Path = "/test";
Assert.ThrowsException<ArgumentNullException>(() => factory.CreateServer(null, null));
@@ -68,7 +68,7 @@ namespace Tgstation.Server.Tests
if (dumpOpenAPISpecpath)
Environment.SetEnvironmentVariable("ASPNETCORE_ENVIRONMENT", "Development");
realServer = new ServerFactory().CreateServer(args.ToArray(), updatePath);
realServer = ServerFactory.CreateDefault().CreateServer(args.ToArray(), updatePath);
}
public void Dispose()