2024-05-29 06:30:01 +03:00
using Microsoft.AspNetCore.Authentication.JwtBearer ;
2023-12-29 04:19:18 +03:00
using Microsoft.AspNetCore.Builder ;
2024-01-26 19:34:42 +03:00
using Microsoft.AspNetCore.Mvc ;
using Microsoft.AspNetCore.Mvc.ApiExplorer ;
using Microsoft.AspNetCore.Mvc.Versioning ;
using Microsoft.Extensions.Configuration ;
2023-12-29 04:19:18 +03:00
using Microsoft.Extensions.DependencyInjection ;
using Microsoft.Extensions.Hosting ;
2024-01-26 19:34:42 +03:00
using Microsoft.Extensions.Options ;
2024-05-29 06:30:01 +03:00
using Microsoft.IdentityModel.Tokens ;
2024-01-26 19:34:42 +03:00
using Mirea.Api.DataAccess.Application ;
using Mirea.Api.DataAccess.Persistence ;
2024-05-30 23:58:24 +03:00
using Mirea.Api.DataAccess.Persistence.Common ;
2024-05-28 06:56:25 +03:00
using Mirea.Api.Endpoint.Common.Interfaces ;
2024-05-28 06:49:40 +03:00
using Mirea.Api.Endpoint.Common.Services ;
2024-05-29 06:30:01 +03:00
using Mirea.Api.Endpoint.Common.Services.Security ;
2024-01-28 06:29:47 +03:00
using Mirea.Api.Endpoint.Configuration ;
2024-05-28 06:53:52 +03:00
using Mirea.Api.Endpoint.Configuration.General ;
2024-05-30 23:30:11 +03:00
using Mirea.Api.Endpoint.Configuration.General.Settings ;
2024-05-28 07:12:58 +03:00
using Mirea.Api.Endpoint.Configuration.General.Validators ;
2024-05-28 06:30:42 +03:00
using Mirea.Api.Endpoint.Configuration.Swagger ;
2024-05-28 07:04:07 +03:00
using Mirea.Api.Endpoint.Middleware ;
2024-05-29 06:30:01 +03:00
using Mirea.Api.Security.Common.Interfaces ;
2024-01-26 19:34:42 +03:00
using Swashbuckle.AspNetCore.SwaggerGen ;
using System ;
using System.Collections ;
using System.IO ;
using System.Linq ;
2024-05-29 06:30:01 +03:00
using System.Text ;
2023-12-29 04:19:18 +03:00
namespace Mirea.Api.Endpoint ;
public class Program
{
2024-01-26 19:30:41 +03:00
private static IConfigurationRoot ConfigureEnvironment ( )
{
EnvironmentManager . LoadEnvironment ( ".env" ) ;
var environmentVariables = Environment . GetEnvironmentVariables ( )
. OfType < DictionaryEntry > ( )
. ToDictionary (
entry = > entry . Key . ToString ( ) ? ? string . Empty ,
entry = > entry . Value ? . ToString ( ) ? ? string . Empty
) ;
var result = new ConfigurationBuilder ( ) . AddInMemoryCollection ( environmentVariables ! ) ;
return result . Build ( ) ;
}
2024-05-29 06:30:01 +03:00
private static IServiceCollection ConfigureJwtToken ( IServiceCollection services , IConfiguration configuration )
{
var lifeTimeJwt = TimeSpan . FromMinutes ( int . Parse ( configuration [ "SECURITY_LIFE_TIME_JWT" ] ! ) ) ;
var jwtDecrypt = Encoding . UTF8 . GetBytes ( configuration [ "SECURITY_ENCRYPTION_TOKEN" ] ? ? string . Empty ) ;
if ( jwtDecrypt . Length ! = 32 )
throw new InvalidOperationException ( "The secret token \"SECURITY_ENCRYPTION_TOKEN\" cannot be less than 32 characters long. Now the size is equal is " + jwtDecrypt . Length ) ;
var jwtKey = Encoding . UTF8 . GetBytes ( configuration [ "SECURITY_SIGNING_TOKEN" ] ? ? string . Empty ) ;
if ( jwtKey . Length ! = 64 )
throw new InvalidOperationException ( "The signature token \"SECURITY_SIGNING_TOKEN\" cannot be less than 64 characters. Now the size is " + jwtKey . Length ) ;
var jwtIssuer = configuration [ "SECURITY_JWT_ISSUER" ] ;
var jwtAudience = configuration [ "SECURITY_JWT_AUDIENCE" ] ;
if ( string . IsNullOrEmpty ( jwtAudience ) | | string . IsNullOrEmpty ( jwtIssuer ) )
throw new InvalidOperationException ( "The \"SECURITY_JWT_ISSUER\" and \"SECURITY_JWT_AUDIENCE\" are not specified" ) ;
services . AddSingleton < IAccessToken , JwtTokenService > ( _ = > new JwtTokenService
{
Audience = jwtAudience ,
Issuer = jwtIssuer ,
Lifetime = lifeTimeJwt ,
EncryptionKey = jwtDecrypt ,
SigningKey = jwtKey
} ) ;
services . AddAuthentication ( options = >
{
options . DefaultAuthenticateScheme = JwtBearerDefaults . AuthenticationScheme ;
options . DefaultChallengeScheme = JwtBearerDefaults . AuthenticationScheme ;
} ) . AddJwtBearer ( options = >
{
options . TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true ,
ValidIssuer = jwtIssuer ,
ValidateAudience = true ,
ValidAudience = jwtAudience ,
ValidateLifetime = true ,
ValidateIssuerSigningKey = true ,
IssuerSigningKey = new SymmetricSecurityKey ( jwtKey ) ,
TokenDecryptionKey = new SymmetricSecurityKey ( jwtDecrypt )
} ;
} ) ;
return services ;
}
2024-05-29 06:42:14 +03:00
private static IServiceCollection ConfigureSecurity ( IServiceCollection services )
{
services . AddSingleton < IAccessToken , JwtTokenService > ( ) ;
services . AddSingleton < IRevokedToken , MemoryRevokedTokenService > ( ) ;
return services ;
}
2023-12-29 04:19:18 +03:00
public static void Main ( string [ ] args )
{
2024-01-26 19:31:28 +03:00
Directory . SetCurrentDirectory ( AppDomain . CurrentDomain . BaseDirectory ) ;
2023-12-29 04:19:18 +03:00
var builder = WebApplication . CreateBuilder ( args ) ;
2024-01-26 19:30:41 +03:00
builder . Configuration . AddConfiguration ( ConfigureEnvironment ( ) ) ;
2024-05-28 06:49:40 +03:00
builder . Configuration . AddJsonFile ( PathBuilder . Combine ( GeneralConfig . FilePath ) , optional : true , reloadOnChange : true ) ;
builder . Services . Configure < GeneralConfig > ( builder . Configuration ) ;
2023-12-29 04:19:18 +03:00
2024-05-30 23:30:11 +03:00
var generalConfig = builder . Configuration . Get < GeneralConfig > ( ) ;
2024-01-26 19:36:18 +03:00
builder . Services . AddApplication ( ) ;
2024-05-30 20:26:42 +03:00
builder . Services . AddPersistence ( generalConfig ? . DbSettings ? . DatabaseProvider ? ? DatabaseProvider . Sqlite , generalConfig ? . DbSettings ? . ConnectionStringSql ? ? string . Empty ) ;
2023-12-29 04:19:18 +03:00
builder . Services . AddControllers ( ) ;
2024-01-26 19:32:10 +03:00
2024-05-28 07:01:23 +03:00
builder . Services . AddSingleton < IMaintenanceModeNotConfigureService , MaintenanceModeNotConfigureService > ( ) ;
builder . Services . AddSingleton < IMaintenanceModeService , MaintenanceModeService > ( ) ;
2024-05-28 06:56:25 +03:00
builder . Services . AddSingleton < ISetupToken , SetupTokenService > ( ) ;
2024-01-26 19:32:10 +03:00
builder . Services . AddCors ( options = >
{
options . AddPolicy ( "AllowAll" , policy = >
{
policy . AllowAnyHeader ( ) ;
policy . AllowAnyMethod ( ) ;
policy . AllowAnyOrigin ( ) ;
} ) ;
} ) ;
2024-01-26 19:33:25 +03:00
builder . Services . AddApiVersioning ( options = >
{
options . DefaultApiVersion = new ApiVersion ( 1 , 0 ) ;
options . AssumeDefaultVersionWhenUnspecified = true ;
options . ReportApiVersions = true ;
options . ApiVersionReader = new UrlSegmentApiVersionReader ( ) ;
} ) ;
builder . Services . AddVersionedApiExplorer ( options = >
{
options . GroupNameFormat = "'v'VVV" ;
options . SubstituteApiVersionInUrl = true ;
} ) ;
2023-12-29 04:19:18 +03:00
builder . Services . AddEndpointsApiExplorer ( ) ;
2024-01-26 19:33:25 +03:00
builder . Services . AddSwaggerGen ( options = >
{
options . OperationFilter < SwaggerDefaultValues > ( ) ;
var basePath = Path . Combine ( AppDomain . CurrentDomain . BaseDirectory ) ;
var xmlPath = Path . Combine ( basePath , "docs.xml" ) ;
options . IncludeXmlComments ( xmlPath ) ;
} ) ;
builder . Services . AddTransient < IConfigureOptions < SwaggerGenOptions > , ConfigureSwaggerOptions > ( ) ;
2023-12-29 04:19:18 +03:00
var app = builder . Build ( ) ;
2024-01-26 19:35:45 +03:00
#if DEBUG
// Write configurations
foreach ( var item in app . Configuration . AsEnumerable ( ) )
Console . WriteLine ( $"{item.Key}:{item.Value}" ) ;
#endif
2024-01-26 19:36:18 +03:00
2024-05-28 07:12:58 +03:00
using ( var scope = app . Services . CreateScope ( ) )
{
var serviceProvider = scope . ServiceProvider ;
var optionsSnapshot = serviceProvider . GetRequiredService < IOptionsSnapshot < GeneralConfig > > ( ) ;
var settingsValidator = new SettingsRequiredValidator ( optionsSnapshot ) ;
var isDoneConfig = settingsValidator . AreSettingsValid ( ) ;
if ( isDoneConfig )
{
var uberDbContext = serviceProvider . GetRequiredService < UberDbContext > ( ) ;
var maintenanceModeService = serviceProvider . GetRequiredService < IMaintenanceModeNotConfigureService > ( ) ;
maintenanceModeService . DisableMaintenanceMode ( ) ;
DbInitializer . Initialize ( uberDbContext ) ;
// todo: if admin not found
}
}
2024-01-26 19:36:18 +03:00
2023-12-29 04:19:18 +03:00
// Configure the HTTP request pipeline.
if ( app . Environment . IsDevelopment ( ) )
{
app . UseSwagger ( ) ;
2024-01-26 19:33:25 +03:00
app . UseSwaggerUI ( options = >
{
var provider = app . Services . GetService < IApiVersionDescriptionProvider > ( ) ;
2024-01-26 20:38:49 +03:00
foreach ( var description in provider ! . ApiVersionDescriptions )
2024-01-26 19:33:25 +03:00
{
var url = $"/swagger/{description.GroupName}/swagger.json" ;
var name = description . GroupName . ToUpperInvariant ( ) ;
options . SwaggerEndpoint ( url , name ) ;
}
} ) ;
2023-12-29 04:19:18 +03:00
}
2024-05-28 07:04:07 +03:00
app . UseMiddleware < MaintenanceModeMiddleware > ( ) ;
2024-05-28 07:16:15 +03:00
app . UseMiddleware < CustomExceptionHandlerMiddleware > ( ) ;
2023-12-29 04:19:18 +03:00
app . UseHttpsRedirection ( ) ;
app . UseAuthorization ( ) ;
app . MapControllers ( ) ;
app . Run ( ) ;
}
}