using Microsoft.AspNetCore.Http; using System.ComponentModel; namespace Application.Features.Config.Get; public sealed class Response { public int ID { get; init; } public BasicConfigDto Basic { get; init; } = new(); public ImagesConfigDto Images { get; init; } = new(); public MetaConfigDto Meta { get; init; } = new(); public CompanyConfigDto Company { get; init; } = new(); public AccountConfigDto Account { get; init; } = new(); public EmailTemplateConfigDto EmailTemplate { get; init; } = new(); public ExternalApiConfigDto External { get; init; } = new(); public TossConfigDto Toss { get; init; } = new(); public AttendanceConfigDto Attendance { get; init; } = new(); public SignupRewardConfigDto SignupReward { get; init; } = new(); public RewardConfigDto Reward { get; init; } = new(); public PaperConfigDto Paper { get; init; } = new(); public DataCollectionConfigDto DataCollection { get; init; } = new(); public sealed class BasicConfigDto { [DisplayName("사이트 이름")] public string? SiteName { get; init; } [DisplayName("사이트 주소")] public string? SiteURL { get; init; } [DisplayName("최고 관리자 ID")] public string? RootID { get; init; } [DisplayName("송수신 이메일")] public string? FromEmail { get; init; } [DisplayName("송수신자 이름")] public string? FromName { get; init; } [DisplayName("SMTP Server")] public string? SmtpServer { get; init; } [DisplayName("SMTP Port")] public int? SmtpPort { get; set; } [DisplayName("SMTP Enable SSL")] public bool SmtpEnableSSL { get; init; } = false; [DisplayName("SMTP Username")] public string? SmtpUsername { get; init; } [DisplayName("SMTP Password")] public string? SmtpPassword { get; init; } [DisplayName("관리자단 접근 가능 IP")] public string? AdminWhiteIPList { get; init; } [DisplayName("사용자단 접근 가능 IP")] public string? FrontWhiteIPList { get; init; } [DisplayName("차단 시 안내문 제목")] public string? BlockAlertTitle { get; init; } [DisplayName("차단 시 안내문 내용")] public string? BlockAlertContent { get; init; } [DisplayName("점검 여부")] public bool IsMaintenance { get; init; } = false; [DisplayName("점검 내용")] public string? MaintenanceContent { get; init; } [DisplayName("쪽지 일일 발송 제한")] public int NoteDailySendLimit { get; init; } = 3; } public sealed class ImagesConfigDto { // ====== DB의 저장/표시용 경로(문자열) ====== [DisplayName("Favicon")] public string? FaviconPath { get; init; } [DisplayName("Logo-square")] public string? LogoSquarePath { get; init; } [DisplayName("Logo-horizontal")] public string? LogoHorizontalPath { get; init; } [DisplayName("og-default")] public string? OgDefaultPath { get; init; } [DisplayName("Twitter-image")] public string? TwitterImagePath { get; init; } [DisplayName("Apple-touch-icon")] public string? AppleTouchIconPath { get; init; } [DisplayName("App-icon-192")] public string? AppIcon192Path { get; init; } [DisplayName("App-icon-512")] public string? AppIcon512Path { get; init; } // ====== 파일업로드 입력(새 업로드용) ====== [DisplayName("Favicon 업로드")] public IFormFile? FaviconFile { get; init; } [DisplayName("Logo-square 업로드")] public IFormFile? LogoSquareFile { get; init; } [DisplayName("Logo-horizontal 업로드")] public IFormFile? LogoHorizontalFile { get; init; } [DisplayName("og-default 업로드")] public IFormFile? OgDefaultFile { get; init; } [DisplayName("Twitter-image 업로드")] public IFormFile? TwitterImageFile { get; init; } [DisplayName("Apple-touch-icon 업로드")] public IFormFile? AppleTouchIconFile { get; init; } [DisplayName("App-icon-192 업로드")] public IFormFile? AppIcon192File { get; init; } [DisplayName("App-icon-512 업로드")] public IFormFile? AppIcon512File { get; init; } } public sealed class MetaConfigDto { [DisplayName("Meta Keywords")] public string? Keywords { get; init; } [DisplayName("Meta Description")] public string? Description { get; init; } [DisplayName("Meta Author")] public string? Author { get; init; } [DisplayName("Meta Viewport")] public string? Viewport { get; init; } [DisplayName("Meta ApplicationName")] public string? ApplicationName { get; init; } [DisplayName("Meta Generator")] public string? Generator { get; init; } [DisplayName("Meta Robots")] public string? Robots { get; init; } [DisplayName("Meta Adds")] public string? Adds { get; init; } } public sealed class CompanyConfigDto { [DisplayName("상호 명")] public string? Name { get; init; } [DisplayName("사업자 등록 번호")] public string? RegNo { get; init; } [DisplayName("사업장 소재지")] public string? Address { get; init; } [DisplayName("우편번호")] public string? ZipCode { get; init; } [DisplayName("대표자 명")] public string? Owner { get; init; } [DisplayName("대표 전화번호")] public string? Tel { get; init; } [DisplayName("FAX")] public string? Fax { get; init; } [DisplayName("통신판매업 신고번호")] public string? RetailSaleNo { get; init; } [DisplayName("부가통신 사업자번호")] public string? AddedSaleNo { get; init; } [DisplayName("호스팅 서비스")] public string? Hosting { get; init; } [DisplayName("정보관리책임자")] public string? AdminName { get; init; } [DisplayName("정보관리책임자 이메일")] public string? AdminEmail { get; init; } [DisplayName("사이트 주소")] public string? SiteUrl { get; init; } [DisplayName("입금계좌 - 은행")] public string? BankCode { get; init; } [DisplayName("입금계좌 - 예금주")] public string? BankOwner { get; init; } [DisplayName("입금계좌 - 계좌번호")] public string? BankNumber { get; init; } } public sealed class AccountConfigDto { [DisplayName("회원가입 시 - 차단 여부")] public bool IsRegisterBlock { get; init; } [DisplayName("회원가입 시 - 이메일 인증 여부")] public bool IsRegisterEmailAuth { get; init; } [DisplayName("회원가입 시 - 비밀번호 최소 길이")] public ushort? PasswordMinLength { get; init; } [DisplayName("회원가입 시 - 비밀번호 대문자 최소 수")] public ushort? PasswordUppercaseLength { get; init; } [DisplayName("회원가입 시 - 비밀번호 숫자 최소 수")] public ushort? PasswordNumbersLength { get; init; } [DisplayName("회원가입 시 - 비밀번호 특수문자 최소 수")] public ushort? PasswordSpecialcharsLength { get; init; } [DisplayName("회원가입 시 - 금지 이메일")] public string? DeniedEmailList { get; init; } [DisplayName("회원가입 시 - 금지 별명")] public string? DeniedNameList { get; init; } [DisplayName("회원가입 시 - 이메일 변경 주기")] public ushort? ChangeEmailDay { get; init; } [DisplayName("회원가입 시 - 별명 변경 주기")] public ushort? ChangeNameDay { get; init; } [DisplayName("회원가입 시 - 한마디 변경 주기")] public ushort? ChangeSummaryDay { get; init; } [DisplayName("회원가입 시 - 자기소개 변경 주기")] public ushort? ChangeIntroDay { get; init; } [DisplayName("회원가입 시 - 프로필 이미지 변경 주기")] public ushort? ChangeThumbDay { get; init; } [DisplayName("회원가입 시 - 비밀번호 변경 주기")] public ushort? ChangePasswordDay { get; init; } [DisplayName("로그인 시 - 이메일 인증 필요")] public bool IsLoginEmailVerifiedOnly { get; init; } [DisplayName("로그인 시 - 로그인 시도(회)")] public ushort? MaxLoginTryCount { get; init; } [DisplayName("로그인 시 - 로그인 제한(초)")] public ushort? MaxLoginTryLimitSecond { get; init; } } public sealed class EmailTemplateConfigDto { [DisplayName("회원가입 시 - 제목")] public string? RegisterEmailFormTitle { get; init; } [DisplayName("회원가입 시 - 내용")] public string? RegisterEmailFormContent { get; init; } [DisplayName("회원가입 완료 - 제목")] public string? RegistrationEmailFormTitle { get; init; } [DisplayName("회원가입 완료 - 내용")] public string? RegistrationEmailFormContent { get; init; } [DisplayName("비밀번호 재설정 - 제목")] public string? ResetPasswordEmailFormTitle { get; init; } [DisplayName("비밀번호 재설정 - 내용")] public string? ResetPasswordEmailFormContent { get; init; } [DisplayName("비밀번호 변경 완료 - 제목")] public string? ChangedPasswordEmailFormTitle { get; init; } [DisplayName("비밀번호 변경 완료 - 내용")] public string? ChangedPasswordEmailFormContent { get; init; } [DisplayName("회원탈퇴 시 - 제목")] public string? WithdrawEmailFormTitle { get; init; } [DisplayName("회원탈퇴 시 - 내용")] public string? WithdrawEmailFormContent { get; init; } [DisplayName("회원탈퇴 인증 - 제목")] public string? WithdrawVerifyEmailFormTitle { get; init; } [DisplayName("회원탈퇴 인증 - 내용")] public string? WithdrawVerifyEmailFormContent { get; init; } [DisplayName("이메일 변경 시 - 제목")] public string? EmailVerifyFormTitle { get; init; } [DisplayName("이메일 변경 시 - 내용")] public string? EmailVerifyFormContent { get; init; } [DisplayName("이메일 변경 완료 - 제목")] public string? ChangedEmailFormTitle { get; init; } [DisplayName("이메일 변경 완료 - 내용")] public string? ChangedEmailFormContent { get; init; } } public sealed class ExternalApiConfigDto { [DisplayName("YouTube - API Name")] public string? YouTubeApiKeyEnc { get; init; } [DisplayName("YouTube - API Key")] public string? YouTubeApiName { get; init; } [DisplayName("Google - Client ID")] public string? GoogleClientId { get; init; } [DisplayName("Google - Client Secret")] public string? GoogleClientSecretEnc { get; init; } [DisplayName("Google - App ID")] public string? GoogleAppId { get; init; } // OAuth — 관리자 확인용으로 키/시크릿 원문(복호화)까지 노출 (사용자 승인 — /api/config 익명 공개 포함) [DisplayName("네이버 - Client ID")] public string? NaverClientId { get; init; } [DisplayName("네이버 - Client Secret")] public string? NaverClientSecret { get; init; } [DisplayName("카카오 - REST API 키")] public string? KakaoRestApiKey { get; init; } [DisplayName("카카오 - JavaScript 키")] public string? KakaoJavascriptKey { get; init; } [DisplayName("카카오 - Admin 키")] public string? KakaoAdminKey { get; init; } [DisplayName("네이버검색 - Client ID")] public string? NaverSearchClientId { get; init; } [DisplayName("네이버검색 - Client Secret")] public string? NaverSearchClientSecret { get; init; } } // 데이터 수집 — 공개(/api/config)에는 암호문(enc) 그대로 노출 — 복호화 평문은 Admin 화면에서만 public sealed class DataCollectionConfigDto { public string? DataGoKrServiceKey { get; init; } public string? KrxApiKey { get; init; } public string? OpenDartApiKey { get; init; } public string? KoreaEximExchangeKey { get; init; } public string? KoreaEximLoanRateKey { get; init; } public string? KoreaEximIntlRateKey { get; init; } public string? SeibroApiKey { get; init; } public string? KosisApiKey { get; init; } public bool StockDataMasterSync { get; init; } public bool StockDataDailyPriceSync { get; init; } public bool KrxIndexSync { get; init; } public bool KrxBondIndexSync { get; init; } public bool KrxStockSync { get; init; } public bool KrxEtpSync { get; init; } public bool KrxWarrantSync { get; init; } public bool KrxBondSync { get; init; } public bool KrxDerivativeSync { get; init; } public bool KrxCommoditySync { get; init; } public bool KrxEsgSync { get; init; } public bool OpenDartDisclosureSync { get; init; } public bool KoreaEximMacroSync { get; init; } public bool KosisSync { get; init; } public bool WorldIndexEnabled { get; init; } public bool MarketQuoteEnabled { get; init; } public bool SeibroIssuerSync { get; init; } public bool SeibroDividendSync { get; init; } public bool SeibroSupplySync { get; init; } public bool SeibroCorpActionSync { get; init; } public bool SeibroBondSync { get; init; } public bool SeibroDerivSync { get; init; } public bool SeibroForeignSync { get; init; } } // 토스페이먼츠 결제 설정 — 키 원문/암호문은 응답에 싣지 않는다 (설정 여부만 노출) public sealed class TossConfigDto { [DisplayName("토스 - 결제 환경")] public string? TossPayMode { get; init; } [DisplayName("토스 - Test Client Key 설정 여부")] public bool HasTestClientKey { get; init; } [DisplayName("토스 - Test Secret Key 설정 여부")] public bool HasTestSecretKey { get; init; } [DisplayName("토스 - Live Client Key 설정 여부")] public bool HasLiveClientKey { get; init; } [DisplayName("토스 - Live Secret Key 설정 여부")] public bool HasLiveSecretKey { get; init; } } public sealed class AttendanceConfigDto { [DisplayName("출석 기능 활성화")] public bool IsEnabled { get; init; } = false; [DisplayName("기본 경험치")] public int BaseExp { get; init; } = 0; [DisplayName("기본 코인")] public int BasePoint { get; init; } = 0; [DisplayName("연속 출석 가중치 사용")] public bool UseStreakBonus { get; init; } = false; [DisplayName("1일당 추가 경험치")] public int StreakBonusPerDay { get; init; } = 0; [DisplayName("1일당 추가 코인")] public int StreakBonusPointPerDay { get; init; } = 0; [DisplayName("가중치 최대 적용 일수")] public int StreakBonusMaxDays { get; init; } = 0; [DisplayName("순위 보상 사용")] public bool UseRankBonus { get; init; } = false; [DisplayName("순위별 보상 설정 (JSON)")] public string? RankBonusConfig { get; init; } } public sealed class SignupRewardConfigDto { [DisplayName("가입 축하 보상 활성화")] public bool Enabled { get; init; } = false; [DisplayName("지급 코인")] public int CoinAmount { get; init; } = 0; [DisplayName("지급 캐시")] public int CashAmount { get; init; } = 0; [DisplayName("지급 경험치")] public int ExpAmount { get; init; } = 0; } public sealed class RewardConfigDto { [DisplayName("게시글 경험치")] public int PostExp { get; init; } = 0; [DisplayName("게시글 토큰")] public int PostPoint { get; init; } = 0; [DisplayName("댓글 경험치")] public int CommentExp { get; init; } = 0; [DisplayName("댓글 토큰")] public int CommentPoint { get; init; } = 0; [DisplayName("추천(누른 쪽) 경험치")] public int LikeGivenExp { get; init; } = 0; [DisplayName("추천(받은 쪽) 토큰")] public int LikeReceivedPoint { get; init; } = 0; [DisplayName("최소 게시글 길이")] public int MinPostLength { get; init; } = 0; [DisplayName("최소 댓글 길이")] public int MinCommentLength { get; init; } = 0; [DisplayName("신규 회원 보상 유예(일)")] public int NewMemberHoldDays { get; init; } = 0; [DisplayName("게시글 일일 횟수 상한")] public int PostDailyCount { get; init; } = 0; [DisplayName("게시글 일일 경험치 상한")] public int PostDailyExp { get; init; } = 0; [DisplayName("게시글 일일 토큰 상한")] public int PostDailyPoint { get; init; } = 0; [DisplayName("댓글 일일 횟수 상한")] public int CommentDailyCount { get; init; } = 0; [DisplayName("댓글 일일 경험치 상한")] public int CommentDailyExp { get; init; } = 0; [DisplayName("댓글 일일 토큰 상한")] public int CommentDailyPoint { get; init; } = 0; [DisplayName("추천(누른 쪽) 일일 횟수 상한")] public int LikeGivenDailyCount { get; init; } = 0; [DisplayName("추천(누른 쪽) 일일 경험치 상한")] public int LikeGivenDailyExp { get; init; } = 0; [DisplayName("추천(받은 쪽) 일일 횟수 상한")] public int LikeReceivedDailyCount { get; init; } = 0; [DisplayName("추천(받은 쪽) 일일 토큰 상한")] public int LikeReceivedDailyPoint { get; init; } = 0; [DisplayName("채팅 일일 횟수 상한")] public int ChatDailyCount { get; init; } = 0; [DisplayName("채팅 일일 경험치 상한")] public int ChatDailyExp { get; init; } = 0; [DisplayName("응원 수수료율(%)")] public int CheerFeePercent { get; init; } = 20; [DisplayName("응원 최소 금액")] public int CheerMinAmount { get; init; } = 100; [DisplayName("응원 일일 발신 총액 상한(0=무제한)")] public int CheerDailyMax { get; init; } = 0; } public sealed class PaperConfigDto { [DisplayName("모의투자 활성화")] public bool Enabled { get; init; } = true; [DisplayName("매매 수수료(Bp)")] public int FeeRateBp { get; init; } = 15; [DisplayName("거래세(Bp)")] public int TaxRateBp { get; init; } = 18; [DisplayName("최소 입금 토큰")] public int MinDeposit { get; init; } = 10000; [DisplayName("최대 보유 토큰(0=무제한)")] public int MaxHolding { get; init; } = 0; [DisplayName("출금 수익 소각(Bp, 0=사용안함)")] public int WithdrawProfitBurnBp { get; init; } = 0; [DisplayName("1주문 상한(Bp, 3000=30%)")] public int OrderMaxPctBp { get; init; } = 3000; [DisplayName("리더보드 등재 최소 체결수")] public int MinFillsForRank { get; init; } = 3; } }