Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Swagger autogen is broken after .NET 8 upgrade #1348

Merged
merged 11 commits into from
Jan 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/auto-update-swagger-dotnet.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Auto Update Swagger
name: 'Update Swagger definitions'

on:
workflow_dispatch:
Expand Down Expand Up @@ -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
Expand Down
8 changes: 4 additions & 4 deletions documentation/static/openapi/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
"parameters": [],
"responses": {
"200": {
"description": "logged in",
"description": "Logged in",
"headers": {},
"content": {
"application/json": {
Expand Down Expand Up @@ -63,7 +63,7 @@
"unresolvedReference": false
},
"401": {
"description": "when not logged in",
"description": "When not logged in",
"headers": {},
"content": {
"application/json": {
Expand Down Expand Up @@ -123,7 +123,7 @@
"unresolvedReference": false
},
"503": {
"description": "database connection error",
"description": "Database Connection Error",
"headers": {},
"content": {
"application/json": {
Expand Down Expand Up @@ -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": {},
Expand Down
20 changes: 17 additions & 3 deletions starsky/starsky.foundation.database/Helpers/SetupDatebaseTypes.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#nullable enable
using System;
using Microsoft.ApplicationInsights;
using Microsoft.EntityFrameworkCore;
Expand Down Expand Up @@ -36,7 +35,7 @@ public ApplicationDbContext BuilderDbFactory()
return new ApplicationDbContext(BuilderDbFactorySwitch());
}

internal ServerVersion GetServerVersionMySql()
private ServerVersion GetServerVersionMySql()
{
try
{
Expand All @@ -50,6 +49,12 @@ internal ServerVersion GetServerVersionMySql()
return new MariaDbServerVersion("10.2");
}

/// <summary>
/// Setup database connection
/// </summary>
/// <param name="foundationDatabaseName">Assembly name, used for running migrations</param>
/// <returns></returns>
/// <exception cref="AggregateException">Missing arguments</exception>
internal DbContextOptions<ApplicationDbContext> BuilderDbFactorySwitch(string? foundationDatabaseName = "")
{
switch ( _appSettings.DatabaseType )
Expand Down Expand Up @@ -110,6 +115,15 @@ internal bool EnableDatabaseTracking( DbContextOptionsBuilder<ApplicationDbConte
return true;
}

/// <summary>
/// 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.
/// </summary>
/// <param name="foundationDatabaseName">Assembly name, used for migrations</param>
/// <exception cref="AggregateException">services is null</exception>
public void BuilderDb(string? foundationDatabaseName = "")
{
if ( _services == null ) throw new AggregateException("services is missing");
Expand Down Expand Up @@ -145,7 +159,7 @@ public void BuilderDb(string? foundationDatabaseName = "")
}));
#endif

_services.AddScoped(provider => new ApplicationDbContext(BuilderDbFactorySwitch(foundationDatabaseName)));
_services.AddScoped(_ => new ApplicationDbContext(BuilderDbFactorySwitch(foundationDatabaseName)));
}

}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#nullable enable
using System;
using System.Collections.Generic;
using System.IO;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,7 @@ orderby fi.LastWriteTime ascending
eventHandler(this, e);
return false;
}

internal bool? InvokeHandler(ErrorEventHandler? eventHandler, ErrorEventArgs e)
{
if ( eventHandler == null )
Expand All @@ -428,12 +429,26 @@ orderby fi.LastWriteTime ascending
}
// end InvokeHandlers

/// <summary>
/// Status if is Disposed
/// </summary>
internal bool IsDisposed { get; set; } = false;

/// <summary>
/// Dispose and unsubscribe all events
/// </summary>
/// <param name="disposing">is disposing</param>
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);
Expand Down
1 change: 1 addition & 0 deletions starsky/starsky.sln.DotSettings
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
<s:Boolean x:Key="/Default/CodeEditing/ContextActionTable/DisabledContextActions/=JetBrains_002EReSharper_002EIntentions_002ECSharp_002EContextActions_002EComments_002EDeleteCommentAction/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeEditing/ContextActionTable/DisabledContextActions/=JetBrains_002EReSharper_002EIntentions_002ERazor_002EContextActions_002EComments_002EDeleteCommentAction/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=accountmanagement/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=clientapp/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=databasetelemetry/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=exiftool/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=filenamebase/@EntryIndexedValue">True</s:Boolean>
Expand Down
28 changes: 14 additions & 14 deletions starsky/starsky/Controllers/AccountController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,12 @@ public AccountController(IUserManager userManager, AppSettings appSettings, IAnt
/// <summary>
/// Check the account status of the current logged in user
/// </summary>
/// <response code="200">logged in</response>
/// <response code="401">when not logged in</response>
/// <response code="200">Logged in</response>
/// <response code="401">When not logged in</response>
/// <response code="406">There are no accounts, you must create an account first</response>
/// <response code="409">Current User does not exist in database</response>
/// <response code="503">database connection error</response>
/// <returns>account name, id, and create date</returns>
/// <response code="409">The Current User does not exist in database</response>
/// <response code="503">Database Connection Error</response>
/// <returns>account name, id, and create date as json</returns>
[HttpGet("/api/account/status")]
[ProducesResponseType(typeof(UserIdentifierStatusModel), 200)]
[ProducesResponseType(typeof(string), 401)]
Expand Down Expand Up @@ -121,11 +121,11 @@ public IActionResult LoginGet(string? returnUrl = null, bool? fromLogout = null)
/// </summary>
/// <param name="model">Email, password and remember me bool</param>
/// <returns>Login status</returns>
/// <response code="200">successful login</response>
/// <response code="401">login failed</response>
/// <response code="405">ValidateAntiForgeryToken</response>
/// <response code="423">login failed due lock</response>
/// <response code="500">login failed due signIn errors</response>
/// <response code="200">Successful login</response>
/// <response code="401">Login failed</response>
/// <response code="405">ValidateAntiForgeryToken error</response>
/// <response code="423">Login failed due lock</response>
/// <response code="500">Login failed due signIn errors</response>
[HttpPost("/api/account/login")]
[ProducesResponseType(typeof(string),200)]
[ProducesResponseType(typeof(string),401)]
Expand Down Expand Up @@ -162,8 +162,8 @@ public async Task<IActionResult> LoginPost(LoginViewModel model)
/// <summary>
/// Logout the current HttpContext out
/// </summary>
/// <returns></returns>
/// <response code="200">successful logout</response>
/// <returns>Login Status</returns>
/// <response code="200">Successful logout</response>
[HttpPost("/api/account/logout")]
[ProducesResponseType(200)]
[AllowAnonymous]
Expand All @@ -178,7 +178,7 @@ public IActionResult LogoutJson()
/// </summary>
/// <param name="returnUrl">insert url to redirect</param>
/// <response code="302">redirect to return url</response>
/// <returns></returns>
/// <returns>Redirect to login page</returns>
[HttpGet("/account/logout")]
[ProducesResponseType(200)]
[AllowAnonymous]
Expand All @@ -193,7 +193,7 @@ public IActionResult Logout(string? returnUrl = null)
/// Update password for current user
/// </summary>
/// <param name="model">Password, ChangedPassword and ChangedConfirmPassword</param>
/// <returns>Login status</returns>
/// <returns>Change secret status</returns>
/// <response code="200">successful login</response>
/// <response code="400">Model is not correct</response>
/// <response code="401"> please login first or your current password is not correct</response>
Expand Down
111 changes: 72 additions & 39 deletions starsky/starsky/Startup.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#nullable enable
using System;
using System.Globalization;
using System.IO;
Expand Down Expand Up @@ -46,6 +45,9 @@
private readonly IConfigurationRoot _configuration;
private AppSettings? _appSettings;

/// <summary>
/// application/xhtml+xml image/svg+xml
/// </summary>
private static readonly string[] CompressionMimeTypes =
[
"application/xhtml+xml",
Expand All @@ -56,7 +58,7 @@
{
if ( !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("app__appsettingspath")) )
{
Console.WriteLine("app__appsettingspath: " + Environment.GetEnvironmentVariable("app__appsettingspath"));
Console.WriteLine("app__appSettingsPath: " + Environment.GetEnvironmentVariable("app__appsettingspath"));

Check warning on line 61 in starsky/starsky/Startup.cs

View check run for this annotation

Codecov / codecov/patch

starsky/starsky/Startup.cs#L61

Added line #L61 was not covered by tests
}
_configuration = SetupAppSettings.AppSettingsToBuilder(args).ConfigureAwait(false).GetAwaiter().GetResult();
}
Expand All @@ -82,7 +84,8 @@
// 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);
Expand Down Expand Up @@ -263,43 +266,8 @@
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
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();
Expand Down Expand Up @@ -335,6 +303,71 @@
applicationLifetime.ApplicationStopping.Register(onStoppedSync.Flush);
}
}

/// <summary>
/// Add Static Files to the application
/// </summary>
/// <param name="app">Application builder</param>
/// <param name="assetsName">assetsName</param>
/// <returns>1. bool = local dir 2. wwwroot in assembly 3. clientapp</returns>
internal (bool,bool,bool) SetupStaticFiles(IApplicationBuilder app, string assetsName = "assets")
{
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", assetsName)) )
{
return result;
}

app.UseStaticFiles(new StaticFileOptions
{
OnPrepareResponse = PrepareResponse,
FileProvider = new PhysicalFileProvider(
Path.Combine(_appSettings.BaseDirectoryProject, "clientapp", "build", assetsName)),
RequestPath = $"/assets",
}
);
result.Item3 = true;
return result;
}

internal static 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");
}

/// <summary>
/// Run the latest migration on the database.
Expand Down
Loading
Loading