Compare commits

..

No commits in common. "f5dbc4685626324552f2e43b38af9d0fdcee8e3a" and "2e48b0067f0dec2d1f7afbbf2e83596131ba0c7b" have entirely different histories.

10 changed files with 53 additions and 83 deletions

View File

@ -3,9 +3,6 @@ LABEL company="Winsomnia"
LABEL maintainer.name="Wesser" maintainer.email="support@winsomnia.net" LABEL maintainer.name="Wesser" maintainer.email="support@winsomnia.net"
WORKDIR /app WORKDIR /app
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD curl --fail http://localhost:8080/health || exit 1
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src WORKDIR /src
COPY . . COPY . .

View File

@ -5,9 +5,9 @@ namespace Mirea.Api.Endpoint.Configuration.Core.Startup;
public static class ApiVersioningConfiguration public static class ApiVersioningConfiguration
{ {
public static IApiVersioningBuilder AddCustomApiVersioning(this IServiceCollection services) public static void AddCustomApiVersioning(this IServiceCollection services)
{ {
return services.AddApiVersioning(options => services.AddApiVersioning(options =>
{ {
options.DefaultApiVersion = new ApiVersion(1, 0); options.DefaultApiVersion = new ApiVersion(1, 0);
options.AssumeDefaultVersionWhenUnspecified = true; options.AssumeDefaultVersionWhenUnspecified = true;

View File

@ -7,19 +7,17 @@ namespace Mirea.Api.Endpoint.Configuration.Core.Startup;
public static class CacheConfiguration public static class CacheConfiguration
{ {
public static IServiceCollection AddCustomRedis(this IServiceCollection services, IConfiguration configuration, IHealthChecksBuilder? healthChecksBuilder = null) public static IServiceCollection AddCustomRedis(this IServiceCollection services, IConfiguration configuration)
{ {
var cache = configuration.Get<GeneralConfig>()?.CacheSettings; var cache = configuration.Get<GeneralConfig>()?.CacheSettings;
if (cache?.TypeDatabase != CacheSettings.CacheEnum.Redis) if (cache?.TypeDatabase == CacheSettings.CacheEnum.Redis)
return services; {
services.AddStackExchangeRedisCache(options => services.AddStackExchangeRedisCache(options =>
{ {
options.Configuration = cache.ConnectionString; options.Configuration = cache.ConnectionString;
options.InstanceName = "mirea_"; options.InstanceName = "mirea_";
}); });
}
healthChecksBuilder?.AddRedis(cache.ConnectionString!, name: "Redis");
return services; return services;
} }

View File

@ -1,5 +1,4 @@
using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens; using Microsoft.IdentityModel.Tokens;
@ -12,7 +11,7 @@ namespace Mirea.Api.Endpoint.Configuration.Core.Startup;
public static class JwtConfiguration public static class JwtConfiguration
{ {
public static AuthenticationBuilder AddJwtToken(this IServiceCollection services, IConfiguration configuration) public static IServiceCollection AddJwtToken(this IServiceCollection services, IConfiguration configuration)
{ {
var lifeTimeJwt = TimeSpan.FromMinutes(int.Parse(configuration["SECURITY_LIFE_TIME_JWT"]!)); var lifeTimeJwt = TimeSpan.FromMinutes(int.Parse(configuration["SECURITY_LIFE_TIME_JWT"]!));
@ -41,7 +40,7 @@ public static class JwtConfiguration
SigningKey = jwtKey SigningKey = jwtKey
}); });
return services.AddAuthentication(options => services.AddAuthentication(options =>
{ {
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
@ -61,5 +60,7 @@ public static class JwtConfiguration
TokenDecryptionKey = new SymmetricSecurityKey(jwtDecrypt) TokenDecryptionKey = new SymmetricSecurityKey(jwtDecrypt)
}; };
}); });
return services;
} }
} }

View File

@ -15,7 +15,7 @@ public static class LoggerConfiguration
{ {
public static IHostBuilder AddCustomSerilog(this IHostBuilder hostBuilder) public static IHostBuilder AddCustomSerilog(this IHostBuilder hostBuilder)
{ {
return hostBuilder.UseSerilog((context, _, configuration) => hostBuilder.UseSerilog((context, _, configuration) =>
{ {
var generalConfig = context.Configuration.Get<GeneralConfig>()?.LogSettings; var generalConfig = context.Configuration.Get<GeneralConfig>()?.LogSettings;
configuration configuration
@ -51,25 +51,21 @@ public static class LoggerConfiguration
configuration.Filter.ByExcluding(Matching.WithProperty<string>("SourceContext", sc => configuration.Filter.ByExcluding(Matching.WithProperty<string>("SourceContext", sc =>
sc.Contains("Microsoft.EntityFrameworkCore.Database.Command"))); sc.Contains("Microsoft.EntityFrameworkCore.Database.Command")));
}); });
return hostBuilder;
} }
public static IApplicationBuilder UseCustomSerilog(this IApplicationBuilder app) public static IApplicationBuilder UseCustomSerilog(this IApplicationBuilder app)
{ {
return app.UseSerilogRequestLogging(options => app.UseSerilogRequestLogging(options =>
{ {
options.MessageTemplate = "[{RequestMethod}] {RequestPath} [Client {RemoteIPAddress}] [{StatusCode}] in {Elapsed:0.0000} ms"; options.MessageTemplate = "[{RequestMethod}] {RequestPath} [Client {RemoteIPAddress}] [{StatusCode}] in {Elapsed:0.0000} ms";
options.GetLevel = (httpContext, elapsed, ex) => options.GetLevel = (_, elapsed, ex) => elapsed >= 2500 || ex != null
{
if (httpContext.Request.Path.StartsWithSegments("/health"))
return LogEventLevel.Verbose;
return elapsed >= 2500 || ex != null
? LogEventLevel.Warning ? LogEventLevel.Warning
: elapsed >= 1000 : elapsed >= 1000
? LogEventLevel.Information ? LogEventLevel.Information
: LogEventLevel.Debug; : LogEventLevel.Debug;
};
options.EnrichDiagnosticContext = (diagnosticContext, httpContext) => options.EnrichDiagnosticContext = (diagnosticContext, httpContext) =>
{ {
@ -79,5 +75,7 @@ public static class LoggerConfiguration
diagnosticContext.Set("RemoteIPAddress", httpContext.Connection.RemoteIpAddress?.ToString()); diagnosticContext.Set("RemoteIPAddress", httpContext.Connection.RemoteIpAddress?.ToString());
}; };
}); });
return app;
} }
} }

View File

@ -51,13 +51,15 @@ public static class SwaggerConfiguration
options.IncludeXmlComments(Path.Combine(basePath, "ApiDtoDocs.xml")); options.IncludeXmlComments(Path.Combine(basePath, "ApiDtoDocs.xml"));
}); });
return services.AddTransient<IConfigureOptions<SwaggerGenOptions>, ConfigureSwaggerOptions>(); services.AddTransient<IConfigureOptions<SwaggerGenOptions>, ConfigureSwaggerOptions>();
return services;
} }
public static IApplicationBuilder UseCustomSwagger(this IApplicationBuilder app, IServiceProvider services) public static IApplicationBuilder UseCustomSwagger(this IApplicationBuilder app, IServiceProvider services)
{ {
app.UseSwagger(); app.UseSwagger();
return app.UseSwaggerUI(options => app.UseSwaggerUI(options =>
{ {
options.InjectStylesheet($"{UrlHelper.GetSubPath}css/swagger/SwaggerDark.css"); options.InjectStylesheet($"{UrlHelper.GetSubPath}css/swagger/SwaggerDark.css");
var provider = services.GetService<IApiVersionDescriptionProvider>(); var provider = services.GetService<IApiVersionDescriptionProvider>();
@ -70,5 +72,7 @@ public static class SwaggerConfiguration
options.RoutePrefix = UrlHelper.GetSubPathSwagger.Trim('/'); options.RoutePrefix = UrlHelper.GetSubPathSwagger.Trim('/');
} }
}); });
return app;
} }
} }

View File

@ -5,9 +5,9 @@
<ImplicitUsings>disable</ImplicitUsings> <ImplicitUsings>disable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<Company>Winsomnia</Company> <Company>Winsomnia</Company>
<Version>1.0-rc3</Version> <Version>1.0.0-rc2</Version>
<AssemblyVersion>1.0.2.3</AssemblyVersion> <AssemblyVersion>1.0.2.2</AssemblyVersion>
<FileVersion>1.0.2.3</FileVersion> <FileVersion>1.0.2.2</FileVersion>
<AssemblyName>Mirea.Api.Endpoint</AssemblyName> <AssemblyName>Mirea.Api.Endpoint</AssemblyName>
<RootNamespace>$(AssemblyName)</RootNamespace> <RootNamespace>$(AssemblyName)</RootNamespace>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
@ -24,10 +24,8 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Asp.Versioning.Mvc" Version="8.1.0" /> <PackageReference Include="Asp.Versioning.Mvc" Version="8.1.0" />
<PackageReference Include="Asp.Versioning.Mvc.ApiExplorer" Version="8.1.0" /> <PackageReference Include="Asp.Versioning.Mvc.ApiExplorer" Version="8.1.0" />
<PackageReference Include="AspNetCore.HealthChecks.Redis" Version="8.0.1" />
<PackageReference Include="AspNetCore.HealthChecks.System" Version="8.0.1" />
<PackageReference Include="Cronos" Version="0.8.4" /> <PackageReference Include="Cronos" Version="0.8.4" />
<PackageReference Include="EPPlus" Version="7.4.1" /> <PackageReference Include="EPPlus" Version="7.4.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.10" /> <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.10" />
<PackageReference Include="Microsoft.CodeAnalysis.Common" Version="4.11.0" /> <PackageReference Include="Microsoft.CodeAnalysis.Common" Version="4.11.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.11.0" /> <PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.11.0" />
@ -41,22 +39,21 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="Microsoft.IdentityModel.Protocols.OpenIdConnect" Version="8.1.2" /> <PackageReference Include="Microsoft.IdentityModel.Protocols.OpenIdConnect" Version="8.1.2" />
<PackageReference Include="Mirea.Tools.Schedule.WebParser" Version="1.0.4" /> <PackageReference Include="Mirea.Tools.Schedule.WebParser" Version="1.0.3" />
<PackageReference Include="Serilog.AspNetCore" Version="8.0.3" /> <PackageReference Include="Serilog.AspNetCore" Version="8.0.2" />
<PackageReference Include="Serilog.Formatting.Compact" Version="3.0.0" /> <PackageReference Include="Serilog.Formatting.Compact" Version="3.0.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" /> <PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
<PackageReference Include="Serilog.Sinks.Debug" Version="3.0.0" /> <PackageReference Include="Serilog.Sinks.Debug" Version="3.0.0" />
<PackageReference Include="Serilog.Sinks.File" Version="6.0.0" /> <PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="8.0.10" /> <PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="8.0.10" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.9.0" /> <PackageReference Include="Swashbuckle.AspNetCore" Version="6.8.1" />
<PackageReference Include="System.CodeDom" Version="8.0.0" /> <PackageReference Include="System.CodeDom" Version="8.0.0" />
<PackageReference Include="System.Composition" Version="8.0.0" /> <PackageReference Include="System.Composition" Version="8.0.0" />
<PackageReference Include="System.Composition.TypedParts" Version="8.0.0" /> <PackageReference Include="System.Composition.TypedParts" Version="8.0.0" />
<PackageReference Include="System.Drawing.Common" Version="8.0.10" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.1.2" /> <PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.1.2" />
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="6.0.0" /> <PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="6.0.0" />
<PackageReference Include="System.Threading.Channels" Version="8.0.0" /> <PackageReference Include="System.Threading.Channels" Version="8.0.0" />
<PackageReference Include="Z.EntityFramework.Extensions.EFCore" Version="8.103.6" /> <PackageReference Include="Z.EntityFramework.Extensions.EFCore" Version="8.103.5" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -23,7 +23,7 @@ namespace Mirea.Api.Endpoint;
public class Program public class Program
{ {
public static IServiceCollection AddDatabase(IServiceCollection services, IConfiguration configuration, IHealthChecksBuilder? healthCheckBuilder = null) public static IServiceCollection AddDatabase(IServiceCollection services, IConfiguration configuration)
{ {
var dbSettings = configuration.Get<GeneralConfig>()?.DbSettings; var dbSettings = configuration.Get<GeneralConfig>()?.DbSettings;
services.AddApplication(); services.AddApplication();
@ -31,10 +31,6 @@ public class Program
dbSettings?.DatabaseProvider ?? DatabaseProvider.Sqlite, dbSettings?.DatabaseProvider ?? DatabaseProvider.Sqlite,
dbSettings?.ConnectionStringSql ?? string.Empty); dbSettings?.ConnectionStringSql ?? string.Empty);
healthCheckBuilder?.AddDatabaseHealthCheck(
dbSettings?.DatabaseProvider ?? DatabaseProvider.Sqlite,
dbSettings?.ConnectionStringSql ?? string.Empty);
return services; return services;
} }
@ -44,18 +40,13 @@ public class Program
var builder = WebApplication.CreateBuilder(args); var builder = WebApplication.CreateBuilder(args);
builder.Configuration.AddConfiguration(EnvironmentConfiguration.GetEnvironment()); builder.Configuration.AddConfiguration(EnvironmentConfiguration.GetEnvironment());
var healthCheckBuilder = builder.Services.AddHealthChecks();
builder.Configuration.AddJsonFile(GeneralConfig.FilePath, optional: true, reloadOnChange: true); builder.Configuration.AddJsonFile(GeneralConfig.FilePath, optional: true, reloadOnChange: true);
builder.Services.Configure<GeneralConfig>(builder.Configuration); builder.Services.Configure<GeneralConfig>(builder.Configuration);
healthCheckBuilder.AddFile(x => x.AddFile(GeneralConfig.FilePath), name: nameof(GeneralConfig));
builder.Configuration.AddJsonFile(Admin.FilePath, optional: true, reloadOnChange: true); builder.Configuration.AddJsonFile(Admin.FilePath, optional: true, reloadOnChange: true);
builder.Services.Configure<Admin>(builder.Configuration); builder.Services.Configure<Admin>(builder.Configuration);
healthCheckBuilder.AddFile(x => x.AddFile(Admin.FilePath), name: nameof(Admin));
builder.Host.AddCustomSerilog(); builder.Host.AddCustomSerilog();
AddDatabase(builder.Services, builder.Configuration, healthCheckBuilder); AddDatabase(builder.Services, builder.Configuration);
builder.Services.AddControllers(); builder.Services.AddControllers();
@ -64,7 +55,7 @@ public class Program
builder.Services.AddSingleton<ISetupToken, SetupTokenService>(); builder.Services.AddSingleton<ISetupToken, SetupTokenService>();
builder.Services.AddMemoryCache(); builder.Services.AddMemoryCache();
builder.Services.AddCustomRedis(builder.Configuration, healthCheckBuilder); builder.Services.AddCustomRedis(builder.Configuration);
builder.Services.AddCors(options => builder.Services.AddCors(options =>
{ {
@ -117,7 +108,6 @@ public class Program
app.UseStaticFiles(UrlHelper.GetSubPath.TrimEnd('/')); app.UseStaticFiles(UrlHelper.GetSubPath.TrimEnd('/'));
app.UseCors("AllowAll"); app.UseCors("AllowAll");
app.UseCustomSerilog(); app.UseCustomSerilog();
app.MapHealthChecks("/health");
using (var scope = app.Services.CreateScope()) using (var scope = app.Services.CreateScope())
{ {

View File

@ -86,15 +86,4 @@ public static class DependencyInjection
}; };
} }
} }
public static IHealthChecksBuilder AddDatabaseHealthCheck(this IHealthChecksBuilder healthChecksBuilder, DatabaseProvider dbProvider, string connection)
{
return dbProvider switch
{
DatabaseProvider.Mysql => healthChecksBuilder.AddMySql(connection, name: "MySql"),
DatabaseProvider.Sqlite => healthChecksBuilder.AddSqlite(connection, name: "Sqlite"),
DatabaseProvider.Postgresql => healthChecksBuilder.AddNpgSql(connection, name: "PostgreSQL"),
_ => throw new ArgumentException("Unsupported database provider", Enum.GetName(dbProvider))
};
}
} }

View File

@ -5,21 +5,17 @@
<ImplicitUsings>disable</ImplicitUsings> <ImplicitUsings>disable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<Company>Winsomnia</Company> <Company>Winsomnia</Company>
<Version>1.0.1</Version> <Version>1.0.0</Version>
<AssemblyVersion>1.0.3.1</AssemblyVersion> <AssemblyVersion>1.0.3.0</AssemblyVersion>
<FileVersion>1.0.3.1</FileVersion> <FileVersion>1.0.3.0</FileVersion>
<AssemblyName>Mirea.Api.DataAccess.Persistence</AssemblyName> <AssemblyName>Mirea.Api.DataAccess.Persistence</AssemblyName>
<RootNamespace>$(AssemblyName)</RootNamespace> <RootNamespace>$(AssemblyName)</RootNamespace>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="AspNetCore.HealthChecks.MySql" Version="8.0.1" />
<PackageReference Include="AspNetCore.HealthChecks.NpgSql" Version="8.0.2" />
<PackageReference Include="AspNetCore.HealthChecks.Sqlite" Version="8.1.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="8.0.10" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="8.0.10" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.10" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.10" />
<PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks" Version="8.0.10" /> <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.8" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.10" />
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="8.0.2" /> <PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="8.0.2" />
</ItemGroup> </ItemGroup>