From 4d6caed779f4b881f2b169eed74b0516ad496d70 Mon Sep 17 00:00:00 2001 From: Dion Date: Thu, 25 Jan 2024 08:07:43 +0100 Subject: [PATCH 01/10] Swagger autogen is broken --- .../Helpers/SetupDatebaseTypes.cs | 20 ++++++++++++++++--- .../BufferingFileSystemWatcher.cs | 19 ++++++++++++++++-- starsky/starsky.sln.DotSettings | 1 + starsky/starsky/Startup.cs | 6 +++--- .../BufferingFileSystemWatcherTest.cs | 15 ++++++++++++++ 5 files changed, 53 insertions(+), 8 deletions(-) diff --git a/starsky/starsky.foundation.database/Helpers/SetupDatebaseTypes.cs b/starsky/starsky.foundation.database/Helpers/SetupDatebaseTypes.cs index 8b9cb0a152..3e39b2d9f5 100644 --- a/starsky/starsky.foundation.database/Helpers/SetupDatebaseTypes.cs +++ b/starsky/starsky.foundation.database/Helpers/SetupDatebaseTypes.cs @@ -1,4 +1,3 @@ -#nullable enable using System; using Microsoft.ApplicationInsights; using Microsoft.EntityFrameworkCore; @@ -36,7 +35,7 @@ public ApplicationDbContext BuilderDbFactory() return new ApplicationDbContext(BuilderDbFactorySwitch()); } - internal ServerVersion GetServerVersionMySql() + private ServerVersion GetServerVersionMySql() { try { @@ -50,6 +49,12 @@ internal ServerVersion GetServerVersionMySql() return new MariaDbServerVersion("10.2"); } + /// + /// Setup database connection + /// + /// Assembly name, used for running migrations + /// + /// Missing arguments internal DbContextOptions BuilderDbFactorySwitch(string? foundationDatabaseName = "") { switch ( _appSettings.DatabaseType ) @@ -110,6 +115,15 @@ internal bool EnableDatabaseTracking( DbContextOptionsBuilder + /// Setup database connection + /// use boot parameters to run with EF Migrations and a direct connection + /// ENABLE_DEFAULT_DATABASE: SQLite + /// ENABLE_MYSQL_DATABASE: MySql + /// In runtime those parameters are not needed and not useful. + /// + /// Assembly name, used for migrations + /// services is null public void BuilderDb(string? foundationDatabaseName = "") { if ( _services == null ) throw new AggregateException("services is missing"); @@ -145,7 +159,7 @@ public void BuilderDb(string? foundationDatabaseName = "") })); #endif - _services.AddScoped(provider => new ApplicationDbContext(BuilderDbFactorySwitch(foundationDatabaseName))); + _services.AddScoped(_ => new ApplicationDbContext(BuilderDbFactorySwitch(foundationDatabaseName))); } } diff --git a/starsky/starsky.foundation.sync/WatcherServices/BufferingFileSystemWatcher.cs b/starsky/starsky.foundation.sync/WatcherServices/BufferingFileSystemWatcher.cs index 73fcdb0392..6e5e113f21 100644 --- a/starsky/starsky.foundation.sync/WatcherServices/BufferingFileSystemWatcher.cs +++ b/starsky/starsky.foundation.sync/WatcherServices/BufferingFileSystemWatcher.cs @@ -409,6 +409,7 @@ orderby fi.LastWriteTime ascending eventHandler(this, e); return false; } + internal bool? InvokeHandler(ErrorEventHandler? eventHandler, ErrorEventArgs e) { if ( eventHandler == null ) @@ -428,12 +429,26 @@ orderby fi.LastWriteTime ascending } // end InvokeHandlers + /// + /// Status if is Disposed + /// + internal bool IsDisposed { get; set; } = false; + + /// + /// Dispose and unsubscribe all events + /// + /// is disposing protected override void Dispose(bool disposing) { if (disposing) { - _cancellationTokenSource.Cancel(); - _cancellationTokenSource.Dispose(); + IsDisposed = true; + if ( !_cancellationTokenSource.IsCancellationRequested ) + { + _cancellationTokenSource.Cancel(); + } + + _cancellationTokenSource.Dispose(); _containedFsw.Dispose(); } base.Dispose(disposing); diff --git a/starsky/starsky.sln.DotSettings b/starsky/starsky.sln.DotSettings index 10a81da966..82d6a16c73 100644 --- a/starsky/starsky.sln.DotSettings +++ b/starsky/starsky.sln.DotSettings @@ -3,6 +3,7 @@ True True True + True True True True diff --git a/starsky/starsky/Startup.cs b/starsky/starsky/Startup.cs index 08792910ce..377899ca2c 100644 --- a/starsky/starsky/Startup.cs +++ b/starsky/starsky/Startup.cs @@ -1,4 +1,3 @@ -#nullable enable using System; using System.Globalization; using System.IO; @@ -56,7 +55,7 @@ public Startup(string[]? args = null) { if ( !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("app__appsettingspath")) ) { - Console.WriteLine("app__appsettingspath: " + Environment.GetEnvironmentVariable("app__appsettingspath")); + Console.WriteLine("app__appSettingsPath: " + Environment.GetEnvironmentVariable("app__appsettingspath")); } _configuration = SetupAppSettings.AppSettingsToBuilder(args).ConfigureAwait(false).GetAwaiter().GetResult(); } @@ -82,7 +81,8 @@ public void ConfigureServices(IServiceCollection services) // LoggerFactory services.AddTelemetryLogging(_appSettings); - var foundationDatabaseName = typeof(ApplicationDbContext).Assembly.FullName?.Split(",").FirstOrDefault(); + var foundationDatabaseName = typeof(ApplicationDbContext) + .Assembly.FullName?.Split(",").FirstOrDefault(); new SetupDatabaseTypes(_appSettings,services).BuilderDb(foundationDatabaseName); new SetupHealthCheck(_appSettings,services).BuilderHealth(); EfCoreMigrationsOnProject(services).ConfigureAwait(false); diff --git a/starsky/starskytest/starsky.foundation.sync/WatcherServices/BufferingFileSystemWatcherTest.cs b/starsky/starskytest/starsky.foundation.sync/WatcherServices/BufferingFileSystemWatcherTest.cs index 2e5e688f12..4acd4c653c 100644 --- a/starsky/starskytest/starsky.foundation.sync/WatcherServices/BufferingFileSystemWatcherTest.cs +++ b/starsky/starskytest/starsky.foundation.sync/WatcherServices/BufferingFileSystemWatcherTest.cs @@ -674,5 +674,20 @@ public void InvokeHandler_ErrorEventHandler() wrapper.Dispose(); watcher.Dispose(); } + + [TestMethod] + [SuppressMessage("Usage", "S3966:Objects should not be disposed more than once")] + public void DisposeDouble() + { + var watcher = new FileSystemWatcher(_tempFolder); + var wrapper = new BufferingFileSystemWatcher(watcher); + + wrapper.Dispose(); + Assert.IsTrue(wrapper.IsDisposed); + + wrapper.Dispose(); + + Assert.IsTrue(wrapper.IsDisposed); + } } } From 5269339786a26143a8ce2ac25b3719ea4c3e94e9 Mon Sep 17 00:00:00 2001 From: Dion van Velde Date: Thu, 25 Jan 2024 08:10:57 +0100 Subject: [PATCH 02/10] rename .Net core into .NET --- .github/workflows/auto-update-swagger-dotnet.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/auto-update-swagger-dotnet.yml b/.github/workflows/auto-update-swagger-dotnet.yml index ff1966b4fb..603a071b8f 100644 --- a/.github/workflows/auto-update-swagger-dotnet.yml +++ b/.github/workflows/auto-update-swagger-dotnet.yml @@ -1,4 +1,4 @@ -name: Auto Update Swagger +name: 'Update Swagger definitions' on: workflow_dispatch: @@ -26,7 +26,7 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Setup .NET Core + - name: Setup .NET SDK uses: actions/setup-dotnet@v4 with: dotnet-version: 8.0.101 From 9de47cfdb3e263d58dcff86982b453a813c66b7d Mon Sep 17 00:00:00 2001 From: Dion Date: Thu, 25 Jan 2024 08:26:46 +0100 Subject: [PATCH 03/10] add comments --- starsky/starsky/Controllers/AccountController.cs | 10 +++++----- starsky/starsky/Startup.cs | 10 ++++++++-- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/starsky/starsky/Controllers/AccountController.cs b/starsky/starsky/Controllers/AccountController.cs index 194600984e..1035a6b0e8 100644 --- a/starsky/starsky/Controllers/AccountController.cs +++ b/starsky/starsky/Controllers/AccountController.cs @@ -34,12 +34,12 @@ public AccountController(IUserManager userManager, AppSettings appSettings, IAnt /// /// Check the account status of the current logged in user /// - /// logged in - /// when not logged in + /// Logged in + /// When not logged in /// There are no accounts, you must create an account first - /// Current User does not exist in database - /// database connection error - /// account name, id, and create date + /// The Current User does not exist in database + /// Database Connection Error + /// account name, id, and create date as json [HttpGet("/api/account/status")] [ProducesResponseType(typeof(UserIdentifierStatusModel), 200)] [ProducesResponseType(typeof(string), 401)] diff --git a/starsky/starsky/Startup.cs b/starsky/starsky/Startup.cs index 377899ca2c..44b919fb43 100644 --- a/starsky/starsky/Startup.cs +++ b/starsky/starsky/Startup.cs @@ -45,6 +45,9 @@ public sealed class Startup private readonly IConfigurationRoot _configuration; private AppSettings? _appSettings; + /// + /// application/xhtml+xml image/svg+xml + /// private static readonly string[] CompressionMimeTypes = [ "application/xhtml+xml", @@ -273,10 +276,13 @@ void PrepareResponse(StaticFileResponseContext ctx) } // Allow Current Directory and wwwroot in Base Directory - app.UseStaticFiles(new StaticFileOptions + if ( _appSettings?.AddSwaggerExportExitAfter != true ) + { + app.UseStaticFiles(new StaticFileOptions { OnPrepareResponse = PrepareResponse - }); + }); + } // Use in wwwroot in build directory; the default option assumes Current Directory if ( _appSettings != null && Directory.Exists(Path.Combine(_appSettings.BaseDirectoryProject, "wwwroot")) ) From 76f21be0463707e61c61bd773ee5292d9020a77e Mon Sep 17 00:00:00 2001 From: SwaggerUpdateBot Date: Thu, 25 Jan 2024 07:30:39 +0000 Subject: [PATCH 04/10] [Swagger] Auto commited swagger/openapi list --- documentation/static/openapi/openapi.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/documentation/static/openapi/openapi.json b/documentation/static/openapi/openapi.json index eee0591a90..5c17c88216 100644 --- a/documentation/static/openapi/openapi.json +++ b/documentation/static/openapi/openapi.json @@ -26,7 +26,7 @@ "parameters": [], "responses": { "200": { - "description": "logged in", + "description": "Logged in", "headers": {}, "content": { "application/json": { @@ -63,7 +63,7 @@ "unresolvedReference": false }, "401": { - "description": "when not logged in", + "description": "When not logged in", "headers": {}, "content": { "application/json": { @@ -123,7 +123,7 @@ "unresolvedReference": false }, "503": { - "description": "database connection error", + "description": "Database Connection Error", "headers": {}, "content": { "application/json": { @@ -153,7 +153,7 @@ "unresolvedReference": false }, "409": { - "description": "Current User does not exist in database", + "description": "The Current User does not exist in database", "headers": {}, "content": {}, "links": {}, From 1fa52fac5802782f2b7ff20340cb10b7d1c2ec7d Mon Sep 17 00:00:00 2001 From: Dion Date: Thu, 25 Jan 2024 08:33:54 +0100 Subject: [PATCH 05/10] Update XML comments Account controller --- .../starsky/Controllers/AccountController.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/starsky/starsky/Controllers/AccountController.cs b/starsky/starsky/Controllers/AccountController.cs index 1035a6b0e8..87f894add9 100644 --- a/starsky/starsky/Controllers/AccountController.cs +++ b/starsky/starsky/Controllers/AccountController.cs @@ -121,11 +121,11 @@ public IActionResult LoginGet(string? returnUrl = null, bool? fromLogout = null) /// /// Email, password and remember me bool /// Login status - /// successful login - /// login failed - /// ValidateAntiForgeryToken - /// login failed due lock - /// login failed due signIn errors + /// Successful login + /// Login failed + /// ValidateAntiForgeryToken error + /// Login failed due lock + /// Login failed due signIn errors [HttpPost("/api/account/login")] [ProducesResponseType(typeof(string),200)] [ProducesResponseType(typeof(string),401)] @@ -162,8 +162,8 @@ public async Task LoginPost(LoginViewModel model) /// /// Logout the current HttpContext out /// - /// - /// successful logout + /// Login Status + /// Successful logout [HttpPost("/api/account/logout")] [ProducesResponseType(200)] [AllowAnonymous] @@ -178,7 +178,7 @@ public IActionResult LogoutJson() /// /// insert url to redirect /// redirect to return url - /// + /// Redirect to login page [HttpGet("/account/logout")] [ProducesResponseType(200)] [AllowAnonymous] @@ -193,7 +193,7 @@ public IActionResult Logout(string? returnUrl = null) /// Update password for current user /// /// Password, ChangedPassword and ChangedConfirmPassword - /// Login status + /// Change secret status /// successful login /// Model is not correct /// please login first or your current password is not correct From c629829cb1b01dcddb05dd23e206b5085fbbb342 Mon Sep 17 00:00:00 2001 From: Dion Date: Thu, 25 Jan 2024 16:19:37 +0100 Subject: [PATCH 06/10] add test --- .../Helpers/SetupAppSettings.cs | 1 - starsky/starsky/Startup.cs | 105 +++++++++------ starsky/starskytest/root/StartupTest.cs | 124 ++++++++++++++++++ 3 files changed, 190 insertions(+), 40 deletions(-) diff --git a/starsky/starsky.foundation.platform/Helpers/SetupAppSettings.cs b/starsky/starsky.foundation.platform/Helpers/SetupAppSettings.cs index 802f8a2b18..786dd79dda 100644 --- a/starsky/starsky.foundation.platform/Helpers/SetupAppSettings.cs +++ b/starsky/starsky.foundation.platform/Helpers/SetupAppSettings.cs @@ -1,4 +1,3 @@ -#nullable enable using System; using System.Collections.Generic; using System.IO; diff --git a/starsky/starsky/Startup.cs b/starsky/starsky/Startup.cs index 44b919fb43..a5d045baff 100644 --- a/starsky/starsky/Startup.cs +++ b/starsky/starsky/Startup.cs @@ -266,46 +266,8 @@ public void Configure(IApplicationBuilder app, IHostEnvironment env, IHostApplic new SwaggerSetupHelper(_appSettings!).Add02AppUseSwaggerAndUi(app); app.UseContentSecurityPolicy(); - - void PrepareResponse(StaticFileResponseContext ctx) - { - // Cache static files for 356 days - ctx.Context.Response.Headers.Append("Expires", DateTime.UtcNow.AddDays(365) - .ToString("R", CultureInfo.InvariantCulture)); - ctx.Context.Response.Headers.Append("Cache-Control", "public, max-age=31536000"); - } - - // Allow Current Directory and wwwroot in Base Directory - if ( _appSettings?.AddSwaggerExportExitAfter != true ) - { - app.UseStaticFiles(new StaticFileOptions - { - OnPrepareResponse = PrepareResponse - }); - } - - // Use in wwwroot in build directory; the default option assumes Current Directory - if ( _appSettings != null && Directory.Exists(Path.Combine(_appSettings.BaseDirectoryProject, "wwwroot")) ) - { - app.UseStaticFiles(new StaticFileOptions - { - OnPrepareResponse = PrepareResponse, - FileProvider = new PhysicalFileProvider( - Path.Combine(_appSettings.BaseDirectoryProject, "wwwroot")) - }); - } - if ( _appSettings != null && Directory.Exists(Path.Combine(_appSettings.BaseDirectoryProject, "clientapp", "build", "assets")) ) - { - app.UseStaticFiles(new StaticFileOptions - { - OnPrepareResponse = PrepareResponse, - FileProvider = new PhysicalFileProvider( - Path.Combine(_appSettings.BaseDirectoryProject, "clientapp", "build", "assets")), - RequestPath = $"/assets", - } - ); - } + SetupStaticFiles(app); app.UseAuthentication(); app.UseBasicAuthentication(); @@ -341,6 +303,71 @@ void PrepareResponse(StaticFileResponseContext ctx) applicationLifetime.ApplicationStopping.Register(onStoppedSync.Flush); } } + + /// + /// Add Static Files to the application + /// + /// Application builder + /// 1. bool = local dir 2. wwwroot in assembly 3. clientapp + internal (bool,bool,bool) SetupStaticFiles(IApplicationBuilder app) + { + var result = ( false, false, false ); + + // Allow Current Directory and wwwroot in Base Directory + // AppSettings can be null when running tests + if ( _appSettings?.AddSwaggerExportExitAfter != true ) + { + app.UseStaticFiles(new StaticFileOptions + { + OnPrepareResponse = PrepareResponse + }); + result.Item1 = true; + } + + if ( _appSettings == null ) + { + return result; + } + + // Use in wwwroot in build directory; the default option assumes Current Directory + if ( Directory.Exists(Path.Combine(_appSettings.BaseDirectoryProject, "wwwroot")) ) + { + app.UseStaticFiles(new StaticFileOptions + { + OnPrepareResponse = PrepareResponse, + FileProvider = new PhysicalFileProvider( + Path.Combine(_appSettings.BaseDirectoryProject, "wwwroot")) + }); + result.Item2 = true; + } + + // Check if clientapp is build and use the assets folder + if ( !Directory.Exists(Path.Combine( + _appSettings.BaseDirectoryProject, "clientapp", "build", + "assets")) ) + { + return result; + } + + app.UseStaticFiles(new StaticFileOptions + { + OnPrepareResponse = PrepareResponse, + FileProvider = new PhysicalFileProvider( + Path.Combine(_appSettings.BaseDirectoryProject, "clientapp", "build", "assets")), + RequestPath = $"/assets", + } + ); + result.Item3 = true; + return result; + } + + void PrepareResponse(StaticFileResponseContext ctx) + { + // Cache static files for 356 days + ctx.Context.Response.Headers.Append("Expires", DateTime.UtcNow.AddDays(365) + .ToString("R", CultureInfo.InvariantCulture)); + ctx.Context.Response.Headers.Append("Cache-Control", "public, max-age=31536000"); + } /// /// Run the latest migration on the database. diff --git a/starsky/starskytest/root/StartupTest.cs b/starsky/starskytest/root/StartupTest.cs index 7d67120cc5..5c2e377b5b 100644 --- a/starsky/starskytest/root/StartupTest.cs +++ b/starsky/starskytest/root/StartupTest.cs @@ -1,15 +1,21 @@ using System; using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; using Microsoft.ApplicationInsights.Extensibility; using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting.Internal; +using Microsoft.Extensions.Options; using Microsoft.VisualStudio.TestTools.UnitTesting; using starsky; using starsky.foundation.platform.Models; using starsky.foundation.realtime.Interfaces; +using starsky.foundation.storage.Storage; using starskytest.FakeMocks; namespace starskytest.root @@ -64,5 +70,123 @@ public void Startup_ConfigureServicesConfigure1() Assert.IsNotNull(applicationBuilder); Assert.IsNotNull(env); } + + private static IEnumerable? GetMiddlewareInstance(IApplicationBuilder app) + { + const string middlewareTypeName = "Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware"; + var appBuilderType = typeof(ApplicationBuilder); + var middlewareField = appBuilderType.GetField("_components", BindingFlags.Instance | BindingFlags.NonPublic); + var components = middlewareField?.GetValue(app); + + if (components != null) + { + var element = components as List>; + + var middlewares = element?.Where(p => + p.Target?.ToString() == middlewareTypeName); + if ( middlewares == null ) + { + return null; + } + + var status = new List(); + foreach ( var middleware in middlewares ) + { + + var type = middleware.Target?.GetType(); + var privatePropertyInfo = type?.GetField("_args", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public); + var privateFieldValue = + privatePropertyInfo?.GetValue(middleware.Target) as object[]; + + status.Add(privateFieldValue); + } + return status; + } + + return null; + } + + [TestMethod] + public void BasicFlow_Default() + { + var startup = new Startup(); + var serviceCollection = new ServiceCollection(); + var serviceProvider = serviceCollection.BuildServiceProvider(); + var serviceProviderInterface = serviceProvider.GetRequiredService(); + + var applicationBuilder = new ApplicationBuilder(serviceProviderInterface); + var result = startup.SetupStaticFiles(applicationBuilder); + + Assert.IsNotNull(result); + Assert.IsTrue(result.Item1); + Assert.IsFalse(result.Item2); + Assert.IsFalse(result.Item3); + + var middlewareInstance = GetMiddlewareInstance(applicationBuilder)?.FirstOrDefault() as object?[]; + var value = middlewareInstance?.FirstOrDefault() as OptionsWrapper; + + Assert.IsFalse(value?.Value.RequestPath.HasValue); + Assert.AreEqual(string.Empty, value?.Value.RequestPath.Value); + } + + [TestMethod] + public void BasicFlow_Assets() + { + var startup = new Startup(); + var serviceCollection = new ServiceCollection(); + serviceCollection.AddSingleton(); + var serviceProvider = serviceCollection.BuildServiceProvider(); + var serviceProviderInterface = serviceProvider.GetRequiredService(); + + var storage = new StorageHostFullPathFilesystem(); + storage.CreateDirectory(Path.Combine(new AppSettings().BaseDirectoryProject, "wwwroot")); + storage.CreateDirectory(Path.Combine(new AppSettings().BaseDirectoryProject, "clientapp", "build")); + + var applicationBuilder = new ApplicationBuilder(serviceProviderInterface); + startup.ConfigureServices(serviceCollection); + var result = startup.SetupStaticFiles(applicationBuilder); + + Assert.IsNotNull(result); + + Assert.IsTrue(result.Item1); + Assert.IsTrue(result.Item2); + Assert.IsTrue(result.Item3); + + var middlewareInstance = GetMiddlewareInstance(applicationBuilder)?.ToList()[1] as object?[]; + var value = middlewareInstance?.FirstOrDefault() as OptionsWrapper; + + Assert.IsFalse(value?.Value.RequestPath.HasValue); + Assert.AreEqual(string.Empty, value?.Value.RequestPath.Value); + } + + [TestMethod] + public void BasicFlow_Assets2() + { + var startup = new Startup(); + var serviceCollection = new ServiceCollection(); + serviceCollection.AddSingleton(); + var serviceProvider = serviceCollection.BuildServiceProvider(); + var serviceProviderInterface = serviceProvider.GetRequiredService(); + + var applicationBuilder = new ApplicationBuilder(serviceProviderInterface); + startup.ConfigureServices(serviceCollection); + + var storage = new StorageHostFullPathFilesystem(); + storage.CreateDirectory(Path.Combine(new AppSettings().BaseDirectoryProject, "wwwroot")); + storage.CreateDirectory(Path.Combine(new AppSettings().BaseDirectoryProject, "clientapp", "build")); + + var result = startup.SetupStaticFiles(applicationBuilder); + Assert.IsNotNull(result); + + Assert.IsTrue(result.Item1); + Assert.IsTrue(result.Item2); + Assert.IsTrue(result.Item3); + + var middlewareInstance = GetMiddlewareInstance(applicationBuilder)?.ToList()[2] as object?[]; + var value = middlewareInstance?.FirstOrDefault() as OptionsWrapper; + + Assert.IsTrue(value?.Value.RequestPath.HasValue); + Assert.AreEqual("/assets", value?.Value.RequestPath.Value); + } } } From 90052387482a0e913de83c7bb357b63ec77c5d81 Mon Sep 17 00:00:00 2001 From: Dion Date: Thu, 25 Jan 2024 16:25:08 +0100 Subject: [PATCH 07/10] add logging --- starsky/starskytest/root/StartupTest.cs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/starsky/starskytest/root/StartupTest.cs b/starsky/starskytest/root/StartupTest.cs index 5c2e377b5b..e7f2e98ac5 100644 --- a/starsky/starskytest/root/StartupTest.cs +++ b/starsky/starskytest/root/StartupTest.cs @@ -132,21 +132,24 @@ public void BasicFlow_Default() [TestMethod] public void BasicFlow_Assets() { + var storage = new StorageHostFullPathFilesystem(); + storage.CreateDirectory(Path.Combine(new AppSettings().BaseDirectoryProject, "wwwroot")); + storage.CreateDirectory(Path.Combine(new AppSettings().BaseDirectoryProject, "clientapp", "build")); + var startup = new Startup(); var serviceCollection = new ServiceCollection(); serviceCollection.AddSingleton(); var serviceProvider = serviceCollection.BuildServiceProvider(); var serviceProviderInterface = serviceProvider.GetRequiredService(); - - var storage = new StorageHostFullPathFilesystem(); - storage.CreateDirectory(Path.Combine(new AppSettings().BaseDirectoryProject, "wwwroot")); - storage.CreateDirectory(Path.Combine(new AppSettings().BaseDirectoryProject, "clientapp", "build")); var applicationBuilder = new ApplicationBuilder(serviceProviderInterface); startup.ConfigureServices(serviceCollection); var result = startup.SetupStaticFiles(applicationBuilder); Assert.IsNotNull(result); + + Console.WriteLine("result:"); + Console.WriteLine("1: " +result.Item1 + " 2: " + result.Item2 + " 3: " + result.Item3); Assert.IsTrue(result.Item1); Assert.IsTrue(result.Item2); @@ -178,6 +181,9 @@ public void BasicFlow_Assets2() var result = startup.SetupStaticFiles(applicationBuilder); Assert.IsNotNull(result); + Console.WriteLine("result:"); + Console.WriteLine("1: " +result.Item1 + " 2: " + result.Item2 + " 3: " + result.Item3); + Assert.IsTrue(result.Item1); Assert.IsTrue(result.Item2); Assert.IsTrue(result.Item3); From a6c62ac1357c2ebbd9acf59c484dbc0cef0514e5 Mon Sep 17 00:00:00 2001 From: Dion Date: Thu, 25 Jan 2024 16:27:17 +0100 Subject: [PATCH 08/10] add assets --- starsky/starsky/Startup.cs | 3 +-- starsky/starskytest/root/StartupTest.cs | 8 +++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/starsky/starsky/Startup.cs b/starsky/starsky/Startup.cs index a5d045baff..d37ad404ee 100644 --- a/starsky/starsky/Startup.cs +++ b/starsky/starsky/Startup.cs @@ -343,8 +343,7 @@ public void Configure(IApplicationBuilder app, IHostEnvironment env, IHostApplic // Check if clientapp is build and use the assets folder if ( !Directory.Exists(Path.Combine( - _appSettings.BaseDirectoryProject, "clientapp", "build", - "assets")) ) + _appSettings.BaseDirectoryProject, "clientapp", "build", "assets")) ) { return result; } diff --git a/starsky/starskytest/root/StartupTest.cs b/starsky/starskytest/root/StartupTest.cs index e7f2e98ac5..238ee1fc7b 100644 --- a/starsky/starskytest/root/StartupTest.cs +++ b/starsky/starskytest/root/StartupTest.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Reflection; @@ -71,7 +72,8 @@ public void Startup_ConfigureServicesConfigure1() Assert.IsNotNull(env); } - private static IEnumerable? GetMiddlewareInstance(IApplicationBuilder app) + [SuppressMessage("ReSharper", "ReturnTypeCanBeEnumerable.Local")] + private static List? GetMiddlewareInstance(IApplicationBuilder app) { const string middlewareTypeName = "Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware"; var appBuilderType = typeof(ApplicationBuilder); @@ -134,7 +136,7 @@ public void BasicFlow_Assets() { var storage = new StorageHostFullPathFilesystem(); storage.CreateDirectory(Path.Combine(new AppSettings().BaseDirectoryProject, "wwwroot")); - storage.CreateDirectory(Path.Combine(new AppSettings().BaseDirectoryProject, "clientapp", "build")); + storage.CreateDirectory(Path.Combine(new AppSettings().BaseDirectoryProject, "clientapp", "build", "assets")); var startup = new Startup(); var serviceCollection = new ServiceCollection(); @@ -176,7 +178,7 @@ public void BasicFlow_Assets2() var storage = new StorageHostFullPathFilesystem(); storage.CreateDirectory(Path.Combine(new AppSettings().BaseDirectoryProject, "wwwroot")); - storage.CreateDirectory(Path.Combine(new AppSettings().BaseDirectoryProject, "clientapp", "build")); + storage.CreateDirectory(Path.Combine(new AppSettings().BaseDirectoryProject, "clientapp", "build", "assets")); var result = startup.SetupStaticFiles(applicationBuilder); Assert.IsNotNull(result); From 66c14080518f13907fb7d1ff7411a60660731b3c Mon Sep 17 00:00:00 2001 From: Dion Date: Thu, 25 Jan 2024 16:37:53 +0100 Subject: [PATCH 09/10] add check --- starsky/starsky/Startup.cs | 7 ++++--- starsky/starskytest/root/StartupTest.cs | 26 +++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/starsky/starsky/Startup.cs b/starsky/starsky/Startup.cs index d37ad404ee..804f8194d5 100644 --- a/starsky/starsky/Startup.cs +++ b/starsky/starsky/Startup.cs @@ -308,8 +308,9 @@ public void Configure(IApplicationBuilder app, IHostEnvironment env, IHostApplic /// Add Static Files to the application /// /// Application builder + /// assetsName /// 1. bool = local dir 2. wwwroot in assembly 3. clientapp - internal (bool,bool,bool) SetupStaticFiles(IApplicationBuilder app) + internal (bool,bool,bool) SetupStaticFiles(IApplicationBuilder app, string assetsName = "assets") { var result = ( false, false, false ); @@ -343,7 +344,7 @@ public void Configure(IApplicationBuilder app, IHostEnvironment env, IHostApplic // Check if clientapp is build and use the assets folder if ( !Directory.Exists(Path.Combine( - _appSettings.BaseDirectoryProject, "clientapp", "build", "assets")) ) + _appSettings.BaseDirectoryProject, "clientapp", "build", assetsName)) ) { return result; } @@ -352,7 +353,7 @@ public void Configure(IApplicationBuilder app, IHostEnvironment env, IHostApplic { OnPrepareResponse = PrepareResponse, FileProvider = new PhysicalFileProvider( - Path.Combine(_appSettings.BaseDirectoryProject, "clientapp", "build", "assets")), + Path.Combine(_appSettings.BaseDirectoryProject, "clientapp", "build", assetsName)), RequestPath = $"/assets", } ); diff --git a/starsky/starskytest/root/StartupTest.cs b/starsky/starskytest/root/StartupTest.cs index 238ee1fc7b..16f2df0ba3 100644 --- a/starsky/starskytest/root/StartupTest.cs +++ b/starsky/starskytest/root/StartupTest.cs @@ -196,5 +196,31 @@ public void BasicFlow_Assets2() Assert.IsTrue(value?.Value.RequestPath.HasValue); Assert.AreEqual("/assets", value?.Value.RequestPath.Value); } + + [TestMethod] + public void BasicFlow_Assets_NotFound() + { + var startup = new Startup(); + var serviceCollection = new ServiceCollection(); + serviceCollection.AddSingleton(); + var serviceProvider = serviceCollection.BuildServiceProvider(); + var serviceProviderInterface = serviceProvider.GetRequiredService(); + + var applicationBuilder = new ApplicationBuilder(serviceProviderInterface); + startup.ConfigureServices(serviceCollection); + + var storage = new StorageHostFullPathFilesystem(); + storage.CreateDirectory(Path.Combine(new AppSettings().BaseDirectoryProject, "wwwroot")); + + var result = startup.SetupStaticFiles(applicationBuilder,"not-found-folder-name"); + Assert.IsNotNull(result); + + Console.WriteLine("result:"); + Console.WriteLine("1: " +result.Item1 + " 2: " + result.Item2 + " 3: " + result.Item3); + + Assert.IsTrue(result.Item1); + Assert.IsTrue(result.Item2); + Assert.IsFalse(result.Item3); + } } } From e6d8bbd85f4cf7bec2b3abee551f01f88d043a40 Mon Sep 17 00:00:00 2001 From: Dion Date: Thu, 25 Jan 2024 16:43:38 +0100 Subject: [PATCH 10/10] add test --- starsky/starsky/Startup.cs | 2 +- starsky/starskytest/root/StartupTest.cs | 26 ++++++++++++++++++++++--- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/starsky/starsky/Startup.cs b/starsky/starsky/Startup.cs index 804f8194d5..b02a1cb0cd 100644 --- a/starsky/starsky/Startup.cs +++ b/starsky/starsky/Startup.cs @@ -361,7 +361,7 @@ public void Configure(IApplicationBuilder app, IHostEnvironment env, IHostApplic return result; } - void PrepareResponse(StaticFileResponseContext ctx) + internal static void PrepareResponse(StaticFileResponseContext ctx) { // Cache static files for 356 days ctx.Context.Response.Headers.Append("Expires", DateTime.UtcNow.AddDays(365) diff --git a/starsky/starskytest/root/StartupTest.cs b/starsky/starskytest/root/StartupTest.cs index 16f2df0ba3..c3c09f5ff8 100644 --- a/starsky/starskytest/root/StartupTest.cs +++ b/starsky/starskytest/root/StartupTest.cs @@ -7,8 +7,10 @@ using Microsoft.ApplicationInsights.Extensibility; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.StaticFiles; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.FileProviders; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting.Internal; using Microsoft.Extensions.Options; @@ -77,7 +79,9 @@ public void Startup_ConfigureServicesConfigure1() { const string middlewareTypeName = "Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware"; var appBuilderType = typeof(ApplicationBuilder); - var middlewareField = appBuilderType.GetField("_components", BindingFlags.Instance | BindingFlags.NonPublic); + const BindingFlags bindingTypes1 = BindingFlags.Instance | + BindingFlags.NonPublic; + var middlewareField = appBuilderType.GetField("_components", bindingTypes1); var components = middlewareField?.GetValue(app); if (components != null) @@ -94,9 +98,11 @@ public void Startup_ConfigureServicesConfigure1() var status = new List(); foreach ( var middleware in middlewares ) { - var type = middleware.Target?.GetType(); - var privatePropertyInfo = type?.GetField("_args", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public); + const BindingFlags bindingTypes = BindingFlags.Instance | + BindingFlags.NonPublic | + BindingFlags.Public; + var privatePropertyInfo = type?.GetField("_args", bindingTypes); var privateFieldValue = privatePropertyInfo?.GetValue(middleware.Target) as object[]; @@ -222,5 +228,19 @@ public void BasicFlow_Assets_NotFound() Assert.IsTrue(result.Item2); Assert.IsFalse(result.Item3); } + + [TestMethod] + public void PrepareResponse_CheckValues() + { + var httpContext = new DefaultHttpContext(); + var context = new StaticFileResponseContext(httpContext, + new NotFoundFileInfo("test")); + // Act + Startup.PrepareResponse(context); + // Assert + Assert.IsNotNull(context.Context.Response.Headers.Expires); + Assert.AreEqual("public, max-age=31536000", + context.Context.Response.Headers.CacheControl.ToString()); + } } }