AppSetting.cs 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  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 NextcloudTalkSection NextcloudTalk { get; init; } = new();
  15. public sealed class AppSection
  16. {
  17. public string Name { get; init; } = string.Empty;
  18. public string Company { get; init; } = string.Empty;
  19. public string BaseURL { get; init; } = string.Empty;
  20. public string ApiURL { get; init; } = string.Empty;
  21. public string FrontURL { get; init; } = string.Empty;
  22. }
  23. public sealed class ConnectionStringsSection
  24. {
  25. public string DefaultConnection { get; init; } = string.Empty;
  26. public int Timeout { get; init; }
  27. }
  28. public class RedisSection
  29. {
  30. public string DefaultConnection { get; init; } = string.Empty;
  31. public string CachePrefix { get; init; } = string.Empty;
  32. public string AuthTicketPrefix { get; init; } = string.Empty;
  33. public string DataProtectionKey { get; init; } = string.Empty;
  34. public TimeSpan DefaultKeyLifetime { get; init; }
  35. }
  36. public class SmtpSection
  37. {
  38. public string Host { get; init; } = default!;
  39. public int Port { get; init; } = 587;
  40. public string? User { get; init; }
  41. public string? Password { get; init; }
  42. public bool UseStartTls { get; init; } = true;
  43. public string FromEmail { get; init; } = default!;
  44. public string FromName { get; init; } = "no-reply";
  45. }
  46. public class JwtSection
  47. {
  48. public string SecretKey { get; init; } = string.Empty;
  49. public string Issuer { get; init; } = string.Empty;
  50. public string Audience { get; init; } = string.Empty;
  51. public int AccessTokenExpiration { get; init; }
  52. public int RefreshTokenExpiration { get; init; }
  53. }
  54. public class ForwardedHeadersSection
  55. {
  56. public int? ForwardLimit { get; init; } = default;
  57. public List<string> KnownProxies { get; init; } = [];
  58. public List<string> KnownNetworks { get; init; } = [];
  59. }
  60. public class CorsPolicySection
  61. {
  62. public string Name { get; init; } = string.Empty;
  63. public long PreflightMaxAgeSeconds { get; init; } = 0;
  64. public List<string> AllowedOrigins { get; init; } = [];
  65. }
  66. public class YouTubeSection
  67. {
  68. public string HubUrl { get; init; } = "https://pubsubhubbub.appspot.com/subscribe";
  69. public string CallbackUrl { get; init; } = string.Empty;
  70. public string HmacSecret { get; init; } = string.Empty;
  71. public int FeedPollingIntervalMinutes { get; init; } = 3;
  72. }
  73. public class BackgroundJobsSection
  74. {
  75. public bool LiveChat { get; init; } = true;
  76. public bool PubSubRenewal { get; init; } = true;
  77. public bool FeedPolling { get; init; } = true;
  78. public bool LiveViewerPoller { get; init; } = true;
  79. public bool ChannelCacheRefresh { get; init; } = true;
  80. public bool YouTubeDailyAggregator { get; init; } = true;
  81. public bool RankingDailyAggregator { get; init; } = true;
  82. public bool YouTubeStaleDataPurge { get; init; } = true;
  83. public bool ApiPurchaseConfirm { get; init; } = true;
  84. }
  85. /// <summary>
  86. /// Nextcloud Talk 운영 알림 — 봇 계정(Basic auth)으로 OCS Chat API 호출.
  87. /// POST {BaseUrl}/ocs/v2.php/apps/spreed/api/v1/chat/{roomToken}
  88. /// AlertRoomToken = 이상 징후 방 / ActivityRoomToken = API 사용 로그 방.
  89. /// 봇 계정은 두 방의 참가자여야 하며, AppPassword 는 Nextcloud 앱 비밀번호(또는 계정 비밀번호).
  90. /// </summary>
  91. public class NextcloudTalkSection
  92. {
  93. public bool Enabled { get; init; } = false;
  94. /// <summary>메시지 prefix 라벨 (예: Dev/Prod). dev·prod 배포가 둘 다 Production 환경명으로 돌므로 환경명 대신 사용. 비우면 EnvironmentName fallback.</summary>
  95. public string Label { get; init; } = string.Empty;
  96. public string BaseUrl { get; init; } = string.Empty;
  97. public string Username { get; init; } = string.Empty;
  98. public string AppPassword { get; init; } = string.Empty;
  99. public string AlertRoomToken { get; init; } = string.Empty;
  100. public string ActivityRoomToken { get; init; } = string.Empty;
  101. }
  102. /// <summary>
  103. /// 회원 PII(주소/연락처 등) 필드 암호화에 사용하는 AES-GCM 키 묶음.
  104. /// Keys 딕셔너리는 KeyVersion -> Base64(32바이트) 매핑. CurrentKeyVersion 은 신규 암호화에 사용할 버전.
  105. /// 키 회전 시 Keys 에 새 버전 추가 + CurrentKeyVersion 갱신. 복호화는 row 의 KeyVersion 컬럼으로 매핑하여 과거 키 사용.
  106. /// </summary>
  107. public class EncryptionSection
  108. {
  109. public int CurrentKeyVersion { get; init; } = 1;
  110. public Dictionary<string, string> Keys { get; init; } = new();
  111. }
  112. }