using Pomelo.EntityFrameworkCore; using System.Text; using Microsoft.EntityFrameworkCore; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.IdentityModel.Tokens; using Microsoft.AspNetCore.SignalR; using Microsoft.Extensions.FileProviders; using Microsoft.Extensions.DependencyInjection; using System.Net.Http; using System.Security.Cryptography.X509Certificates; using System.Text.Json; using Back; using Back.Program.Common.Auth; using Back.Program.Common.Auth.Interface; using Back.Program.Common.Chat; using Back.Program.Common.Data; using Back.Program.Common.Middleware; using Back.Program.Common.Model; using Back.Program.Models.Entities; using Back.Program.Repositories.V1; using Back.Program.Repositories.V1.Interfaces; using Back.Program.Services.V1; using Back.Program.Services.V1.Interfaces; Boolean isLocal = false; // 로컬 테스트 할 때는 이거 키고 아니면 끄기 // isLocal = true; var builder = WebApplication.CreateBuilder(args); // DB 설정부 시작 builder.Configuration.AddJsonFile("private/dbSetting.json", optional: true, reloadOnChange: true); builder.Services.AddHttpContextAccessor(); builder.Services.AddDbContext(optionsAction: (serviceProvider, options) => { var httpContextAccessor = serviceProvider.GetRequiredService(); var dbName = httpContextAccessor.HttpContext?.Request.Query["aca_code"].ToString(); var baseConnectionString = builder.Configuration.GetConnectionString("MariaDbConnection"); if (!string.IsNullOrEmpty(dbName)) { baseConnectionString = baseConnectionString.Replace("database=AcaMate", $"database={dbName}"); } options.UseMySql(baseConnectionString, ServerVersion.AutoDetect(baseConnectionString)); }); // DB 설정부 끝 var dbString = builder.Configuration.GetConnectionString("MariaDbConnection"); var userString = builder.Configuration.GetConnectionString("DBAccount"); // JWT 설정부 시작 if (builder.Environment.IsDevelopment()) { builder.Configuration.AddJsonFile("private/jwtSetting.Development.json", optional: true, reloadOnChange: true); } else { builder.Configuration.AddJsonFile("private/jwtSetting.json", optional: true, reloadOnChange: true); } builder.Services.Configure(builder.Configuration.GetSection("JwtSettings")); builder.Services.AddAuthentication(options => { options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }) .AddJwtBearer(options => { var jwtSettings = builder.Configuration.GetSection("JwtSettings").Get(); options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidateAudience = true, ValidateLifetime = true, ValidateIssuerSigningKey = true, ValidIssuer = jwtSettings.Issuer, ValidAudience = jwtSettings.Audience, IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSettings.SecretKey)), ClockSkew = TimeSpan.FromMinutes(jwtSettings.ClockSkewMinutes) }; }); // JWT 설정부 끝 // PUSH 설정부 // 설정 바인딩 (appsettings.json의 "ApnsPushService" 섹션) builder.Services.Configure(builder.Configuration.GetSection("PushFileSetting")); // HttpClientFactory를 이용한 ApnsPushService 등록 (핸들러에 인증서 추가) builder.Services.AddHttpClient(client => { var settings = builder.Configuration.GetSection("PushFileSetting").Get(); client.BaseAddress = new Uri(settings.uri); client.Timeout = TimeSpan.FromSeconds(60); }) .ConfigurePrimaryHttpMessageHandler(() => { var config = builder.Configuration.GetSection("PushFileSetting").Get(); var handler = new HttpClientHandler(); // p12PWPath 파일에서 비밀번호 읽어오기 (예시: JSON {"Password": "비밀번호"}) var json = File.ReadAllText(config.p12PWPath); var keys = JsonSerializer.Deserialize>(json); var certificate = new X509Certificate2(config.p12Path, keys["Password"]); handler.ClientCertificates.Add(certificate); handler.SslProtocols = System.Security.Authentication.SslProtocols.Tls12; return handler; }); // InMemoryPushQueue와 백그라운드 서비스 등록 builder.Services.AddSingleton(); builder.Services.AddHostedService(); // PUSH 설정부 끝 builder.Services.AddControllers(); // 세션 설정 // IN-MEMORY 캐시 builder.Services.AddDistributedMemoryCache(); builder.Services.AddSession(); // ==== SCOPED 으로 등록 할 서비스 ==== // // 여기다가 API 있는 컨트롤러들 AddScoped 하면 되는건가? builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); // builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); // builder.Services.AddScoped(); // // builder.Services.AddScoped(); builder.Services.AddEndpointsApiExplorer(); // 스웨거 설정 추가 부분 // builder.Services.AddSwaggerGen(); builder.Services.AddCustomSwagger(); // SignalR 설정 추가 부분 builder.Services.AddSignalR(); builder.Services.AddCors(option => { option.AddPolicy("CorsPolicy", builder => { builder .WithOrigins("https://devacamate.ipstein.myds.me", "https://acamate.ipstein.myds.me") // 특정 도메인만 허용 .AllowAnyMethod() .AllowAnyHeader() .AllowCredentials(); }); }); // 로그 설정 부분 builder.Logging.ClearProviders(); builder.Logging.AddConsole(); builder.Logging.SetMinimumLevel(builder.Environment.IsDevelopment() ? LogLevel.Trace : LogLevel.Warning); if (isLocal) { builder.WebHost.UseUrls("http://0.0.0.0:5144"); } else { builder.WebHost.UseUrls(builder.Environment.IsDevelopment()? "http://0.0.0.0:7004":"http://0.0.0.0:7003"); } ///// ===== builder 설정 부 ===== ///// var app = builder.Build(); string staticRoot; if (isLocal) { staticRoot = app.Environment.IsDevelopment() ? //"/publish/debug/wwwroot" : "/publish/release/wwwroot" ; Path.Combine(Directory.GetCurrentDirectory(), "publish", "debug", "wwwroot") : Path.Combine(Directory.GetCurrentDirectory(), "publish", "release", "wwwroot") ; } else { staticRoot = app.Environment.IsDevelopment() ? "/src/publish/debug/wwwroot" : "/src/publish/release/wwwroot" ; } if (app.Environment.IsDevelopment()) { app.UseCustomSwaggerUI(); app.UseDeveloperExceptionPage(); // 좀더 자세한 예외 정보 제공 } else { app.UseExceptionHandler("/error"); app.UseHsts(); } // 로컬 테스트 위한 부분 (올릴떄는 켜두기) // app.UseHttpsRedirection(); app.UseStaticFiles(new StaticFileOptions { FileProvider = new PhysicalFileProvider(staticRoot), RequestPath = "" }); app.UseRouting(); app.UseSession(); app.UseCors("CorsPolicy"); app.UseAuthentication(); app.UseAuthorization(); // 헤더 미들웨어 부분 app.UseMiddleware ((object)new string[] { "iOS_AM_Connect_Key", "And_AM_Connect_Key", "Web-AM-Connect-Key" }); app.UseWebSockets(); Console.WriteLine($"[정적 파일 경로] {staticRoot}"); app.UseEndpoints(end => { ControllerEndpointRouteBuilderExtensions.MapControllers(end); end.MapHub("/chatHub"); end.MapFallback(context => { return context.Response.SendFileAsync(Path.Combine(staticRoot, "index.html")); }); }); //예외처리 미들웨어 부분 app.UseMiddleware(); app.Run();