refactor: distribute configurations by classes
This commit is contained in:
		@@ -0,0 +1,27 @@
 | 
			
		||||
using Microsoft.AspNetCore.Mvc;
 | 
			
		||||
using Microsoft.AspNetCore.Mvc.Versioning;
 | 
			
		||||
using Microsoft.Extensions.DependencyInjection;
 | 
			
		||||
 | 
			
		||||
namespace Mirea.Api.Endpoint.Configuration.AppConfig;
 | 
			
		||||
 | 
			
		||||
public static class ApiVersioningConfiguration
 | 
			
		||||
{
 | 
			
		||||
    public static void AddCustomApiVersioning(this IServiceCollection services)
 | 
			
		||||
    {
 | 
			
		||||
        services.AddApiVersioning(options =>
 | 
			
		||||
        {
 | 
			
		||||
            options.DefaultApiVersion = new ApiVersion(1, 0);
 | 
			
		||||
            options.AssumeDefaultVersionWhenUnspecified = true;
 | 
			
		||||
            options.ReportApiVersions = true;
 | 
			
		||||
            options.ApiVersionReader = new UrlSegmentApiVersionReader();
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        services.AddVersionedApiExplorer(options =>
 | 
			
		||||
        {
 | 
			
		||||
            options.GroupNameFormat = "'v'VVV";
 | 
			
		||||
            options.SubstituteApiVersionInUrl = true;
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        services.AddEndpointsApiExplorer();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										68
									
								
								Endpoint/Configuration/AppConfig/EnvironmentConfiguration.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								Endpoint/Configuration/AppConfig/EnvironmentConfiguration.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,68 @@
 | 
			
		||||
using Microsoft.Extensions.Configuration;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.IO;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
 | 
			
		||||
namespace Mirea.Api.Endpoint.Configuration.AppConfig;
 | 
			
		||||
 | 
			
		||||
public static class EnvironmentConfiguration
 | 
			
		||||
{
 | 
			
		||||
    private static IDictionary<string, string> LoadEnvironment(string envFile)
 | 
			
		||||
    {
 | 
			
		||||
        Dictionary<string, string> environment = new();
 | 
			
		||||
 | 
			
		||||
        if (!File.Exists(envFile)) return environment;
 | 
			
		||||
 | 
			
		||||
        foreach (var line in File.ReadAllLines(envFile))
 | 
			
		||||
        {
 | 
			
		||||
            if (string.IsNullOrEmpty(line)) continue;
 | 
			
		||||
 | 
			
		||||
            var commentIndex = line.IndexOf('#', StringComparison.Ordinal);
 | 
			
		||||
 | 
			
		||||
            string arg = line;
 | 
			
		||||
 | 
			
		||||
            if (commentIndex != -1)
 | 
			
		||||
                arg = arg.Remove(commentIndex, arg.Length - commentIndex);
 | 
			
		||||
 | 
			
		||||
            var parts = arg.Split(
 | 
			
		||||
                '=',
 | 
			
		||||
                StringSplitOptions.RemoveEmptyEntries);
 | 
			
		||||
 | 
			
		||||
            if (parts.Length > 2)
 | 
			
		||||
                parts = [parts[0], string.Join("=", parts[1..])];
 | 
			
		||||
 | 
			
		||||
            if (parts.Length != 2)
 | 
			
		||||
                continue;
 | 
			
		||||
 | 
			
		||||
            environment.Add(parts[0].Trim(), parts[1].Trim());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return environment;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static IConfigurationRoot GetEnvironment()
 | 
			
		||||
    {
 | 
			
		||||
        var variablesFromFile = 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!)
 | 
			
		||||
            .AddInMemoryCollection(variablesFromFile!);
 | 
			
		||||
 | 
			
		||||
#if DEBUG
 | 
			
		||||
        result.AddInMemoryCollection(LoadEnvironment(".env.develop")!);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
        Environment.SetEnvironmentVariable("PATH_TO_SAVE", variablesFromFile["PATH_TO_SAVE"]);
 | 
			
		||||
 | 
			
		||||
        return result.Build();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										66
									
								
								Endpoint/Configuration/AppConfig/JwtConfiguration.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								Endpoint/Configuration/AppConfig/JwtConfiguration.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,66 @@
 | 
			
		||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
 | 
			
		||||
using Microsoft.Extensions.Configuration;
 | 
			
		||||
using Microsoft.Extensions.DependencyInjection;
 | 
			
		||||
using Microsoft.IdentityModel.Tokens;
 | 
			
		||||
using Mirea.Api.Endpoint.Common.Services.Security;
 | 
			
		||||
using Mirea.Api.Security.Common.Interfaces;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Text;
 | 
			
		||||
 | 
			
		||||
namespace Mirea.Api.Endpoint.Configuration.AppConfig;
 | 
			
		||||
 | 
			
		||||
public static class JwtConfiguration
 | 
			
		||||
{
 | 
			
		||||
    public static IServiceCollection AddJwtToken(this 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;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										26
									
								
								Endpoint/Configuration/AppConfig/SecureConfiguration.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								Endpoint/Configuration/AppConfig/SecureConfiguration.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
			
		||||
using Microsoft.Extensions.Configuration;
 | 
			
		||||
using Microsoft.Extensions.DependencyInjection;
 | 
			
		||||
using Mirea.Api.Endpoint.Common.Services.Security;
 | 
			
		||||
using Mirea.Api.Endpoint.Configuration.General.Settings;
 | 
			
		||||
using Mirea.Api.Security;
 | 
			
		||||
using Mirea.Api.Security.Common.Interfaces;
 | 
			
		||||
 | 
			
		||||
namespace Mirea.Api.Endpoint.Configuration.AppConfig;
 | 
			
		||||
 | 
			
		||||
public static class SecureConfiguration
 | 
			
		||||
{
 | 
			
		||||
    public static IServiceCollection AddSecurity(this IServiceCollection services, IConfiguration configuration)
 | 
			
		||||
    {
 | 
			
		||||
        services.AddSecurityServices(configuration);
 | 
			
		||||
 | 
			
		||||
        services.AddSingleton<IAccessToken, JwtTokenService>();
 | 
			
		||||
        services.AddSingleton<IRevokedToken, MemoryRevokedTokenService>();
 | 
			
		||||
 | 
			
		||||
        if (configuration.Get<CacheSettings>()?.TypeDatabase == CacheSettings.CacheEnum.Redis)
 | 
			
		||||
            services.AddSingleton<ICacheService, DistributedCacheService>();
 | 
			
		||||
        else
 | 
			
		||||
            services.AddSingleton<ICacheService, MemoryCacheService>();
 | 
			
		||||
 | 
			
		||||
        return services;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										48
									
								
								Endpoint/Configuration/AppConfig/SwaggerConfiguration.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								Endpoint/Configuration/AppConfig/SwaggerConfiguration.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,48 @@
 | 
			
		||||
using Microsoft.AspNetCore.Builder;
 | 
			
		||||
using Microsoft.AspNetCore.Mvc.ApiExplorer;
 | 
			
		||||
using Microsoft.Extensions.DependencyInjection;
 | 
			
		||||
using Microsoft.Extensions.Options;
 | 
			
		||||
using Mirea.Api.Endpoint.Configuration.Swagger;
 | 
			
		||||
using Swashbuckle.AspNetCore.SwaggerGen;
 | 
			
		||||
using System;
 | 
			
		||||
using System.IO;
 | 
			
		||||
 | 
			
		||||
namespace Mirea.Api.Endpoint.Configuration.AppConfig;
 | 
			
		||||
 | 
			
		||||
public static class SwaggerConfiguration
 | 
			
		||||
{
 | 
			
		||||
    public static IServiceCollection AddCustomSwagger(this IServiceCollection services)
 | 
			
		||||
    {
 | 
			
		||||
        services.AddSwaggerGen(options =>
 | 
			
		||||
        {
 | 
			
		||||
            options.SchemaFilter<SwaggerExampleFilter>();
 | 
			
		||||
            options.OperationFilter<SwaggerDefaultValues>();
 | 
			
		||||
            var basePath = AppDomain.CurrentDomain.BaseDirectory;
 | 
			
		||||
 | 
			
		||||
            options.IncludeXmlComments(Path.Combine(basePath, "docs.xml"));
 | 
			
		||||
            options.IncludeXmlComments(Path.Combine(basePath, "ApiDtoDocs.xml"));
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        services.AddTransient<IConfigureOptions<SwaggerGenOptions>, ConfigureSwaggerOptions>();
 | 
			
		||||
 | 
			
		||||
        return services;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static IApplicationBuilder UseCustomSwagger(this IApplicationBuilder app, IServiceProvider services)
 | 
			
		||||
    {
 | 
			
		||||
        app.UseSwagger();
 | 
			
		||||
        app.UseSwaggerUI(options =>
 | 
			
		||||
        {
 | 
			
		||||
            var provider = services.GetService<IApiVersionDescriptionProvider>();
 | 
			
		||||
 | 
			
		||||
            foreach (var description in provider!.ApiVersionDescriptions)
 | 
			
		||||
            {
 | 
			
		||||
                var url = $"/swagger/{description.GroupName}/swagger.json";
 | 
			
		||||
                var name = description.GroupName.ToUpperInvariant();
 | 
			
		||||
                options.SwaggerEndpoint(url, name);
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        return app;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user