AcaMate_API/Program.cs
2025-05-19 17:00:19 +09:00

239 lines
8.0 KiB
C#

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;
var builder = WebApplication.CreateBuilder(args);
// DB 설정부 시작
builder.Configuration.AddJsonFile("private/dbSetting.json", optional: true, reloadOnChange: true);
builder.Services.AddHttpContextAccessor();
// var connectionString = builder.Configuration.GetConnectionString("MariaDbConnection");
// builder.Services.AddDbContext<AppDbContext>(options => options.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString)));
builder.Services.AddDbContext<AppDbContext>(optionsAction: (serviceProvider, options) =>
{
var httpContextAccessor = serviceProvider.GetRequiredService<IHttpContextAccessor>();
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<JwtSettings>(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<JwtSettings>();
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<PushFileSetting>(builder.Configuration.GetSection("PushFileSetting"));
// HttpClientFactory를 이용한 ApnsPushService 등록 (핸들러에 인증서 추가)
builder.Services.AddHttpClient<IPushService, PushService>(client =>
{
var settings = builder.Configuration.GetSection("PushFileSetting").Get<PushFileSetting>();
client.BaseAddress = new Uri(settings.uri);
client.Timeout = TimeSpan.FromSeconds(60);
})
.ConfigurePrimaryHttpMessageHandler(() =>
{
var config = builder.Configuration.GetSection("PushFileSetting").Get<PushFileSetting>();
var handler = new HttpClientHandler();
// using var reader = new StreamReader(config.p12PWPath, new UTF8Encoding(false));
// var json = reader.ReadToEndAsync();
// p12PWPath 파일에서 비밀번호 읽어오기 (예시: JSON {"Password": "비밀번호"})
var json = File.ReadAllText(config.p12PWPath);
var keys = JsonSerializer.Deserialize<Dictionary<string, string>>(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<IPushQueue, InMemoryPushQueue>();
builder.Services.AddHostedService<PushBackgroundService>();
// PUSH 설정부 끝
builder.Services.AddControllers();
// 여기다가 API 있는 컨트롤러들 AddScoped 하면 되는건가?
builder.Services.AddScoped<JwtTokenService>();
builder.Services.AddScoped<ILogRepository, LogRepository>();
builder.Services.AddScoped<IRepositoryService, RepositoryService>();
builder.Services.AddScoped<IHeaderConfig, HeaderConfigRepository>();
builder.Services.AddScoped<IUserService, UserService>();
builder.Services.AddScoped<IUserRepository, UserRepository>();
builder.Services.AddScoped<IAppService, AppService>();
builder.Services.AddScoped<IAppRepository, AppRepository>();
// builder.Services.AddScoped<IPushService, PushService>();
builder.Services.AddScoped<IPushRepository, PushRepository>();
// builder.Services.AddScoped<UserService>(); //
// builder.Services.AddScoped<UserController>();
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();
if (builder.Environment.IsDevelopment()) {
builder.Logging.SetMinimumLevel(LogLevel.Trace);
}
else
{
builder.Logging.SetMinimumLevel(LogLevel.Warning);
}
builder.WebHost.UseUrls("http://0.0.0.0:7004");
// 로컬 테스트 위한 부분 (올릴때는 꺼두기)
// builder.WebHost.UseUrls("http://0.0.0.0:5144");
///// ===== builder 설정 부 ===== /////
var app = builder.Build();
string staticRoot;
if (app.Environment.IsDevelopment())
{
// app.UseSwagger();
// app.UseSwaggerUI();
app.UseCustomSwaggerUI();
app.UseDeveloperExceptionPage(); // 좀더 자세한 예외 정보 제공
staticRoot = Path.Combine(Directory.GetCurrentDirectory(), "publish", "debug", "wwwroot");
}
else
{
app.UseExceptionHandler("/error");
app.UseHsts();
staticRoot = Path.Combine(Directory.GetCurrentDirectory(), "publish", "release", "wwwroot");
}
// 로컬 테스트 위한 부분 (올릴떄는 켜두기)
app.UseHttpsRedirection();
//예외처리 미들웨어 부분
app.UseMiddleware<ExceptionMiddleware>();
// 헤더 미들웨어 부분
app.UseMiddleware<APIHeaderMiddleware>(
(object)new string[] { "iOS_AM_Connect_Key", "And_AM_Connect_Key", "Web_AM_Connect_Key" }
);
// app.UseBlazorFrameworkFiles();
// app.UseStaticFiles();
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = new PhysicalFileProvider(staticRoot),
RequestPath = ""
});
app.UseRouting();
app.UseCors("CorsPolicy");
app.UseAuthorization();
app.UseWebSockets();
app.UseEndpoints(end =>
{
ControllerEndpointRouteBuilderExtensions.MapControllers(end);
// 프론트 테스트 위한 부분
end.MapFallbackToFile("index.html");
end.MapHub<ChatHub>("/chatHub");
});
app.Run();