AppSetting.cs 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. namespace SharedKernel;
  2. public sealed class AppSettings
  3. {
  4. public AppSection App { get; init; } = new();
  5. public ConnectionStringsSection ConnectionStrings { get; init; } = new();
  6. public RedisSection Redis { get; init; } = new();
  7. public SmtpSection SMTP { get; init; } = new();
  8. public JwtSection JWT { get; init; } = new();
  9. public ForwardedHeadersSection ForwardedHeaders { get; init; } = new();
  10. public CorsPolicySection CorsPolicy { get; init; } = new();
  11. public YouTubeSection YouTube { get; init; } = new();
  12. public BackgroundJobsSection BackgroundJobs { get; init; } = new();
  13. public EncryptionSection Encryption { get; init; } = new();
  14. public FeaturesSection Features { get; init; } = new();
  15. public StockDataSection StockData { get; init; } = new();
  16. public sealed class AppSection
  17. {
  18. public string Name { get; init; } = string.Empty;
  19. public string Company { get; init; } = string.Empty;
  20. public string BaseURL { get; init; } = string.Empty;
  21. public string ApiURL { get; init; } = string.Empty;
  22. public string FrontURL { get; init; } = string.Empty;
  23. }
  24. public sealed class ConnectionStringsSection
  25. {
  26. public string DefaultConnection { get; init; } = string.Empty;
  27. public int Timeout { get; init; }
  28. }
  29. public class RedisSection
  30. {
  31. public string DefaultConnection { get; init; } = string.Empty;
  32. public string CachePrefix { get; init; } = string.Empty;
  33. public string AuthTicketPrefix { get; init; } = string.Empty;
  34. public string DataProtectionKey { get; init; } = string.Empty;
  35. public TimeSpan DefaultKeyLifetime { get; init; }
  36. }
  37. public class SmtpSection
  38. {
  39. public string Host { get; init; } = default!;
  40. public int Port { get; init; } = 587;
  41. public string? User { get; init; }
  42. public string? Password { get; init; }
  43. public bool UseStartTls { get; init; } = true;
  44. public string FromEmail { get; init; } = default!;
  45. public string FromName { get; init; } = "no-reply";
  46. }
  47. public class JwtSection
  48. {
  49. public string SecretKey { get; init; } = string.Empty;
  50. public string Issuer { get; init; } = string.Empty;
  51. public string Audience { get; init; } = string.Empty;
  52. public int AccessTokenExpiration { get; init; }
  53. public int RefreshTokenExpiration { get; init; }
  54. }
  55. public class ForwardedHeadersSection
  56. {
  57. public int? ForwardLimit { get; init; } = default;
  58. public List<string> KnownProxies { get; init; } = [];
  59. public List<string> KnownNetworks { get; init; } = [];
  60. }
  61. public class CorsPolicySection
  62. {
  63. public string Name { get; init; } = string.Empty;
  64. public long PreflightMaxAgeSeconds { get; init; } = 0;
  65. public List<string> AllowedOrigins { get; init; } = [];
  66. }
  67. public class YouTubeSection
  68. {
  69. public string HubUrl { get; init; } = "https://pubsubhubbub.appspot.com/subscribe";
  70. public string CallbackUrl { get; init; } = string.Empty;
  71. public string HmacSecret { get; init; } = string.Empty;
  72. public int FeedPollingIntervalMinutes { get; init; } = 3;
  73. }
  74. public class BackgroundJobsSection
  75. {
  76. public bool LiveChat { get; init; } = true;
  77. public bool PubSubRenewal { get; init; } = true;
  78. public bool FeedPolling { get; init; } = true;
  79. public bool LiveViewerPoller { get; init; } = true;
  80. public bool ChannelCacheRefresh { get; init; } = true;
  81. public bool YouTubeDailyAggregator { get; init; } = true;
  82. public bool YouTubeStaleDataPurge { get; init; } = true;
  83. }
  84. /// <summary>
  85. /// 기능 단위 활성화 플래그. 코드/스키마는 보존하고 노출만 차단하는 soft-off 스위치.
  86. /// Channel=false 시 채널/스튜디오/YouTube 관련 API 와 백그라운드 서비스 전체 비활성 (기본 false).
  87. /// </summary>
  88. public class FeaturesSection
  89. {
  90. public bool Channel { get; init; } = false;
  91. }
  92. /// <summary>
  93. /// 회원 PII(주소/연락처 등) 필드 암호화에 사용하는 AES-GCM 키 묶음.
  94. /// Keys 딕셔너리는 KeyVersion -> Base64(32바이트) 매핑. CurrentKeyVersion 은 신규 암호화에 사용할 버전.
  95. /// 키 회전 시 Keys 에 새 버전 추가 + CurrentKeyVersion 갱신. 복호화는 row 의 KeyVersion 컬럼으로 매핑하여 과거 키 사용.
  96. /// </summary>
  97. public class EncryptionSection
  98. {
  99. public int CurrentKeyVersion { get; init; } = 1;
  100. public Dictionary<string, string> Keys { get; init; } = new();
  101. }
  102. /// <summary>
  103. /// 주식 데이터 수집 배치 설정 (개미투자 D1). 플래그 기본 false — API 키 발급/운영 결정 후 활성화.
  104. /// Features:Channel 게이트와 무관하게 별도 등록 (AddStockDataServices).
  105. /// </summary>
  106. public class StockDataSection
  107. {
  108. /// <summary>종목 마스터 동기화 배치 (StockMasterSyncService) 활성화</summary>
  109. public bool MasterSync { get; init; } = false;
  110. /// <summary>T+1 일별 시세 수집 배치 (DailyPriceSyncService) 활성화</summary>
  111. public bool DailyPriceSync { get; init; } = false;
  112. /// <summary>마스터 동기화 실행 시각 (KST, "HH:mm")</summary>
  113. public string MasterSyncTime { get; init; } = "07:30";
  114. /// <summary>일별 시세 수집 실행 시각 (KST, "HH:mm") — 금융위 API 는 영업일+1 13시 이후 반영</summary>
  115. public string DailyPriceSyncTime { get; init; } = "13:10";
  116. public DataGoKrSection DataGoKr { get; init; } = new();
  117. /// <summary>공공데이터포털 (data.go.kr) 금융위 API</summary>
  118. public class DataGoKrSection
  119. {
  120. /// <summary>서비스 키 (Decoding 원본 키 — 요청 시 URL 인코딩). 비어 있으면 배치는 로그만 남기고 skip.</summary>
  121. public string ServiceKey { get; init; } = string.Empty;
  122. public string BaseUrl { get; init; } = "https://apis.data.go.kr";
  123. /// <summary>페이지당 행 수 (numOfRows)</summary>
  124. public int PageSize { get; init; } = 1000;
  125. }
  126. }
  127. }