From cd53ca9db44d6863cbada5e12b2381838bd6d300 Mon Sep 17 00:00:00 2001 From: Cyberboss Date: Sun, 12 Jan 2020 17:29:49 -0500 Subject: [PATCH] General code cleanup pass --- .../Controllers/TgsOpenApiFilters.cs | 1 - src/Tgstation.Server.Host/Core/Application.cs | 17 ++++++-- .../Core/AssemblyInformationProvider.cs | 24 +++++++++++ .../Core/IAssemblyInformationProvider.cs | 20 +++++++++ .../DesignTimeDbContextFactoryHelpers.cs | 8 ++-- src/Tgstation.Server.Host/Program.cs | 2 +- .../Security/TokenFactory.cs | 9 ++-- src/Tgstation.Server.Host/Server.cs | 9 +++- src/Tgstation.Server.Host/ServerFactory.cs | 42 +++++++++++++++++-- .../Core/TestApplication.cs | 17 +++++--- .../TestServerFactory.cs | 17 +++++++- tests/Tgstation.Server.Tests/TestingServer.cs | 2 +- 12 files changed, 143 insertions(+), 25 deletions(-) create mode 100644 src/Tgstation.Server.Host/Core/AssemblyInformationProvider.cs create mode 100644 src/Tgstation.Server.Host/Core/IAssemblyInformationProvider.cs diff --git a/src/Tgstation.Server.Host/Controllers/TgsOpenApiFilters.cs b/src/Tgstation.Server.Host/Controllers/TgsOpenApiFilters.cs index f158398efe..b9c0e0f8d9 100644 --- a/src/Tgstation.Server.Host/Controllers/TgsOpenApiFilters.cs +++ b/src/Tgstation.Server.Host/Controllers/TgsOpenApiFilters.cs @@ -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; diff --git a/src/Tgstation.Server.Host/Core/Application.cs b/src/Tgstation.Server.Host/Core/Application.cs index 9939ea6778..796d929743 100644 --- a/src/Tgstation.Server.Host/Core/Application.cs +++ b/src/Tgstation.Server.Host/Core/Application.cs @@ -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 /// readonly IConfiguration configuration; + /// + /// The for the . + /// + readonly IAssemblyInformationProvider assemblyInformationProvider; + /// /// The for the /// @@ -76,15 +80,20 @@ namespace Tgstation.Server.Host.Core /// Construct an /// /// The value of + /// The for the . /// The value of - 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(); - 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); diff --git a/src/Tgstation.Server.Host/Core/AssemblyInformationProvider.cs b/src/Tgstation.Server.Host/Core/AssemblyInformationProvider.cs new file mode 100644 index 0000000000..41fe7919ca --- /dev/null +++ b/src/Tgstation.Server.Host/Core/AssemblyInformationProvider.cs @@ -0,0 +1,24 @@ +using System.Reflection; + +namespace Tgstation.Server.Host.Core +{ + /// + sealed class AssemblyInformationProvider : IAssemblyInformationProvider + { + /// + public string Path { get; } + + /// + public AssemblyName Name { get; } + + /// + /// Initializes a new instance of the . + /// + public AssemblyInformationProvider() + { + Assembly assembly = Assembly.GetExecutingAssembly(); + Path = assembly.Location; + Name = assembly.GetName(); + } + } +} diff --git a/src/Tgstation.Server.Host/Core/IAssemblyInformationProvider.cs b/src/Tgstation.Server.Host/Core/IAssemblyInformationProvider.cs new file mode 100644 index 0000000000..8112deb276 --- /dev/null +++ b/src/Tgstation.Server.Host/Core/IAssemblyInformationProvider.cs @@ -0,0 +1,20 @@ +using System.Reflection; + +namespace Tgstation.Server.Host.Core +{ + /// + /// For retrieving the 's location. + /// + interface IAssemblyInformationProvider + { + /// + /// Gets the path to the executing assembly. + /// + string Path { get; } + + /// + /// Gets the . + /// + AssemblyName Name { get; } + } +} diff --git a/src/Tgstation.Server.Host/Models/Migrations/DesignTimeDbContextFactoryHelpers.cs b/src/Tgstation.Server.Host/Models/Migrations/DesignTimeDbContextFactoryHelpers.cs index cb4e730d1e..2de82a18bf 100644 --- a/src/Tgstation.Server.Host/Models/Migrations/DesignTimeDbContextFactoryHelpers.cs +++ b/src/Tgstation.Server.Host/Models/Migrations/DesignTimeDbContextFactoryHelpers.cs @@ -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 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(); diff --git a/src/Tgstation.Server.Host/Program.cs b/src/Tgstation.Server.Host/Program.cs index 83895df62b..0e81f1d1f9 100644 --- a/src/Tgstation.Server.Host/Program.cs +++ b/src/Tgstation.Server.Host/Program.cs @@ -16,7 +16,7 @@ namespace Tgstation.Server.Host /// The to use /// #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 /// diff --git a/src/Tgstation.Server.Host/Security/TokenFactory.cs b/src/Tgstation.Server.Host/Security/TokenFactory.cs index 2974f6d3b1..3023189b84 100644 --- a/src/Tgstation.Server.Host/Security/TokenFactory.cs +++ b/src/Tgstation.Server.Host/Security/TokenFactory.cs @@ -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 /// /// The value of /// The used for generating the - public TokenFactory(IAsyncDelayer asyncDelayer, ICryptographySuite cryptographySuite) + /// The used to generate the issuer name. + 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, diff --git a/src/Tgstation.Server.Host/Server.cs b/src/Tgstation.Server.Host/Server.cs index 45a683a91e..7dcf93d719 100644 --- a/src/Tgstation.Server.Host/Server.cs +++ b/src/Tgstation.Server.Host/Server.cs @@ -30,6 +30,11 @@ namespace Tgstation.Server.Host /// readonly IWebHostBuilder webHostBuilder; + /// + /// The for the . + /// + readonly IIOManager ioManager; + /// /// The s to run when the restarts /// @@ -69,10 +74,12 @@ namespace Tgstation.Server.Host /// Construct a /// /// The value of + /// The value of . /// The value of - 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(this)); diff --git a/src/Tgstation.Server.Host/ServerFactory.cs b/src/Tgstation.Server.Host/ServerFactory.cs index d06f20fa93..57c46c1ae2 100644 --- a/src/Tgstation.Server.Host/ServerFactory.cs +++ b/src/Tgstation.Server.Host/ServerFactory.cs @@ -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 { /// public sealed class ServerFactory : IServerFactory { + /// + /// The for the . + /// + readonly IAssemblyInformationProvider assemblyInformationProvider; + + /// + /// The for the . + /// + readonly IIOManager ioManager; + + /// + /// Create the default . + /// + /// A new with the default settings. + public static IServerFactory CreateDefault() + => new ServerFactory( + new AssemblyInformationProvider(), + new DefaultIOManager()); + + /// + /// Initializes a new instance of the . + /// + /// The value of . + /// The value of . + internal ServerFactory(IAssemblyInformationProvider assemblyInformationProvider, IIOManager ioManager) + { + this.assemblyInformationProvider = assemblyInformationProvider ?? throw new ArgumentNullException(nameof(assemblyInformationProvider)); + this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager)); + } + /// 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() .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); } } } diff --git a/tests/Tgstation.Server.Host.Tests/Core/TestApplication.cs b/tests/Tgstation.Server.Host.Tests/Core/TestApplication.cs index 94eba126e5..d19f8c3aa8 100644 --- a/tests/Tgstation.Server.Host.Tests/Core/TestApplication.cs +++ b/tests/Tgstation.Server.Host.Tests/Core/TestApplication.cs @@ -23,13 +23,18 @@ namespace Tgstation.Server.Host.Core.Tests [TestMethod] public void TestMethodThrows() { - Assert.ThrowsException(() => new Application(null, null)); + Assert.ThrowsException(() => new Application(null, null, null)); var mockConfiguration = new Mock(); - Assert.ThrowsException(() => new Application(mockConfiguration.Object, null)); + Assert.ThrowsException(() => new Application(mockConfiguration.Object, null, null)); + + var mockAssemblyInfo = new Mock(); + mockAssemblyInfo.SetupGet(x => x.Name).Returns(typeof(Application).Assembly.GetName()); + + Assert.ThrowsException(() => new Application(mockConfiguration.Object, mockAssemblyInfo.Object, null)); var mockHostingEnvironment = new Mock(); - var app = new Application(mockConfiguration.Object, mockHostingEnvironment.Object); + var app = new Application(mockConfiguration.Object, mockAssemblyInfo.Object, mockHostingEnvironment.Object); Assert.ThrowsException(() => app.ConfigureServices(null)); Assert.ThrowsException(() => app.Configure(null, null, null, null, null)); @@ -69,11 +74,11 @@ namespace Tgstation.Server.Host.Core.Tests public void TestConfigureServicesThrowsWhenSetupWizardConfigurationDemands() { var mockConfiguration = new Mock(); - Assert.ThrowsException(() => new Application(mockConfiguration.Object, null)); - + var mockAssemblyInfo = new Mock(); + mockAssemblyInfo.SetupGet(x => x.Name).Returns(typeof(Application).Assembly.GetName()); var mockHostingEnvironment = new Mock(); - var app = new Application(mockConfiguration.Object, mockHostingEnvironment.Object); + var app = new Application(mockConfiguration.Object, mockAssemblyInfo.Object, mockHostingEnvironment.Object); var mockOptions = new Mock>(); mockOptions.SetupGet(x => x.Value).Returns(new GeneralConfiguration diff --git a/tests/Tgstation.Server.Host.Tests/TestServerFactory.cs b/tests/Tgstation.Server.Host.Tests/TestServerFactory.cs index 1334ae87c9..eede3ff41c 100644 --- a/tests/Tgstation.Server.Host.Tests/TestServerFactory.cs +++ b/tests/Tgstation.Server.Host.Tests/TestServerFactory.cs @@ -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(() => new ServerFactory(null, null)); + IAssemblyInformationProvider assemblyInformationProvider = Mock.Of(); + Assert.ThrowsException(() => new ServerFactory(assemblyInformationProvider, null)); + IIOManager ioManager = Mock.Of(); + new ServerFactory(assemblyInformationProvider, ioManager); + } + [TestMethod] public void TestWorksWithoutUpdatePath() { - var factory = new ServerFactory(); + var factory = ServerFactory.CreateDefault(); Assert.ThrowsException(() => factory.CreateServer(null, null)); factory.CreateServer(Array.Empty(), 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(() => factory.CreateServer(null, null)); diff --git a/tests/Tgstation.Server.Tests/TestingServer.cs b/tests/Tgstation.Server.Tests/TestingServer.cs index 17f8ba84b7..29ece7cbca 100644 --- a/tests/Tgstation.Server.Tests/TestingServer.cs +++ b/tests/Tgstation.Server.Tests/TestingServer.cs @@ -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()