modules/backend/Write-InfrastructureLayer.ps1
|
param( [string]$ProjectName, [string]$OrmMode, [string]$OutputPath, [bool]$Observability = $false ) . (Join-Path (Split-Path $MyInvocation.MyCommand.Path) "..\core\Utils.ps1") $base = Join-Path $OutputPath "src\$ProjectName.Infrastructure" function Write-File($rel, $con) { Write-CoreFile (Join-Path $base $rel) $con } function T($t) { $t.Replace("{P}", $ProjectName) } # ===== TokenService ===== Write-File "Services\TokenService.cs" (T @' using System.IdentityModel.Tokens.Jwt; using System.Security.Claims; using System.Text; using Microsoft.Extensions.Configuration; using Microsoft.IdentityModel.Tokens; using {P}.Application.Interfaces; namespace {P}.Infrastructure.Services; public class TokenService : ITokenService { private readonly IConfiguration _config; public TokenService(IConfiguration config) => _config = config; public string GenerateToken(int userId, string username, string role = "User") { var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:Key"]!)); var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); var expires = DateTime.UtcNow.AddHours(8); var claims = new[] { new Claim(ClaimTypes.NameIdentifier, userId.ToString()), new Claim(ClaimTypes.Name, username), new Claim(ClaimTypes.Role, role) }; var token = new JwtSecurityToken( issuer: _config["Jwt:Issuer"], audience: _config["Jwt:Audience"], claims: claims, expires: expires, signingCredentials: creds); return new JwtSecurityTokenHandler().WriteToken(token); } } '@) # ===== BcryptPasswordHasher ===== Write-File "Services\BcryptPasswordHasher.cs" (T @' using {P}.Application.Interfaces; namespace {P}.Infrastructure.Services; public class BcryptPasswordHasher : IPasswordHasher { public string Hash(string password) => BCrypt.Net.BCrypt.HashPassword(password, workFactor: 11); public bool Verify(string password, string hash) => BCrypt.Net.BCrypt.Verify(password, hash); } '@) if ($Observability) { # ===== SerilogConfiguration ===== Write-File "Configurations\SerilogConfiguration.cs" (T @' using Microsoft.AspNetCore.Builder; using Serilog; namespace {P}.Infrastructure.Configurations; public static class SerilogConfiguration { public static void AddSerilogConfiguration(this ConfigureHostBuilder host) { host.UseSerilog((ctx, lc) => lc .WriteTo.Console() .ReadFrom.Configuration(ctx.Configuration)); } } '@) } # ===== ServiceRegistration ===== $obsUsing = if ($Observability) { "using {P}.Infrastructure.Configurations;" } else { "" } Write-File "ServiceRegistration\InfrastructureServiceRegistration.cs" (T @" using System.Text; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.IdentityModel.Tokens; using {P}.Application.Interfaces; using {P}.Infrastructure.Services; $obsUsing namespace {P}.Infrastructure.ServiceRegistration; public static class InfrastructureServiceRegistration { public static IServiceCollection AddInfrastructureServices( this IServiceCollection services, IConfiguration configuration) { services.AddScoped<ITokenService, TokenService>(); services.AddScoped<IPasswordHasher, BcryptPasswordHasher>(); services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(opt => { opt.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidateAudience = true, ValidateLifetime = true, ValidateIssuerSigningKey = true, ValidIssuer = configuration["Jwt:Issuer"], ValidAudience = configuration["Jwt:Audience"], IssuerSigningKey = new SymmetricSecurityKey( Encoding.UTF8.GetBytes(configuration["Jwt:Key"]!)) }; }); return services; } } "@) |