Centralize admin validation rules
TaxBaik CI/CD / build-and-deploy (push) Successful in 3m4s

This commit is contained in:
2026-07-07 16:22:03 +09:00
parent cd7892e858
commit 4c2a13712b
4 changed files with 59 additions and 36 deletions
@@ -5,23 +5,23 @@ using System.ComponentModel.DataAnnotations;
public class SubmitInquiryDto public class SubmitInquiryDto
{ {
[Required(ErrorMessage = "이름을 입력하세요.")] [Required(ErrorMessage = "이름을 입력하세요.")]
[StringLength(100, ErrorMessage = "이름은 최대 100자까지 입력 가능합니다.")] [StringLength(ValidationRules.NameMaxLength, ErrorMessage = "이름은 최대 100자까지 입력 가능합니다.")]
public string Name { get; set; } = string.Empty; public string Name { get; set; } = string.Empty;
[Required(ErrorMessage = "전화번호를 입력하세요.")] [Required(ErrorMessage = "전화번호를 입력하세요.")]
[RegularExpression( [RegularExpression(
@"^(0(?:2|3[1-3]|4[1-4]|5[1-5]|6[1-4]|70|50[5-9]|[7-9](?:\d{1,2})?)\d{7,8}|0\d{9,10})$", ValidationRules.KoreanPhonePattern,
ErrorMessage = "올바른 전화번호 형식이 아닙니다.")] ErrorMessage = "올바른 전화번호 형식이 아닙니다.")]
public string Phone { get; set; } = string.Empty; public string Phone { get; set; } = string.Empty;
[EmailAddress(ErrorMessage = "올바른 이메일 형식이 아닙니다.")] [EmailAddress(ErrorMessage = "올바른 이메일 형식이 아닙니다.")]
public string? Email { get; set; } public string? Email { get; set; }
[StringLength(50, ErrorMessage = "상담분야는 최대 50자까지 입력 가능합니다.")] [StringLength(ValidationRules.ServiceTypeMaxLength, ErrorMessage = "상담분야는 최대 50자까지 입력 가능합니다.")]
public string ServiceType { get; set; } = string.Empty; public string ServiceType { get; set; } = string.Empty;
[Required(ErrorMessage = "문의 내용을 입력하세요.")] [Required(ErrorMessage = "문의 내용을 입력하세요.")]
[StringLength(5000, MinimumLength = 10, ErrorMessage = "문의 내용은 최소 10자, 최대 5000자까지 입력 가능합니다.")] [StringLength(ValidationRules.MessageMaxLength, MinimumLength = ValidationRules.MessageMinLength, ErrorMessage = "문의 내용은 최소 10자, 최대 5000자까지 입력 가능합니다.")]
public string Message { get; set; } = string.Empty; public string Message { get; set; } = string.Empty;
public bool SuppressNotification { get; set; } public bool SuppressNotification { get; set; }
@@ -5,28 +5,28 @@ using System.ComponentModel.DataAnnotations;
public class UpdateInquiryDto public class UpdateInquiryDto
{ {
[Required(ErrorMessage = "이름을 입력하세요.")] [Required(ErrorMessage = "이름을 입력하세요.")]
[StringLength(100, ErrorMessage = "이름은 최대 100자까지 입력 가능합니다.")] [StringLength(ValidationRules.NameMaxLength, ErrorMessage = "이름은 최대 100자까지 입력 가능합니다.")]
public string Name { get; set; } = string.Empty; public string Name { get; set; } = string.Empty;
[Required(ErrorMessage = "전화번호를 입력하세요.")] [Required(ErrorMessage = "전화번호를 입력하세요.")]
[RegularExpression( [RegularExpression(
@"^(0(?:2|3[1-3]|4[1-4]|5[1-5]|6[1-4]|70|50[5-9]|[7-9](?:\d{1,2})?)\d{7,8}|0\d{9,10})$", ValidationRules.KoreanPhonePattern,
ErrorMessage = "올바른 전화번호 형식이 아닙니다.")] ErrorMessage = "올바른 전화번호 형식이 아닙니다.")]
public string Phone { get; set; } = string.Empty; public string Phone { get; set; } = string.Empty;
[EmailAddress(ErrorMessage = "올바른 이메일 형식이 아닙니다.")] [EmailAddress(ErrorMessage = "올바른 이메일 형식이 아닙니다.")]
public string? Email { get; set; } public string? Email { get; set; }
[StringLength(50, ErrorMessage = "상담분야는 최대 50자까지 입력 가능합니다.")] [StringLength(ValidationRules.ServiceTypeMaxLength, ErrorMessage = "상담분야는 최대 50자까지 입력 가능합니다.")]
public string ServiceType { get; set; } = string.Empty; public string ServiceType { get; set; } = string.Empty;
[Required(ErrorMessage = "문의 내용을 입력하세요.")] [Required(ErrorMessage = "문의 내용을 입력하세요.")]
[StringLength(5000, MinimumLength = 10, ErrorMessage = "문의 내용은 최소 10자, 최대 5000자까지 입력 가능합니다.")] [StringLength(ValidationRules.MessageMaxLength, MinimumLength = ValidationRules.MessageMinLength, ErrorMessage = "문의 내용은 최소 10자, 최대 5000자까지 입력 가능합니다.")]
public string Message { get; set; } = string.Empty; public string Message { get; set; } = string.Empty;
[Required(ErrorMessage = "상태를 선택하세요.")] [Required(ErrorMessage = "상태를 선택하세요.")]
public string Status { get; set; } = string.Empty; public string Status { get; set; } = string.Empty;
[StringLength(1000, ErrorMessage = "관리 메모는 최대 1000자까지 입력 가능합니다.")] [StringLength(ValidationRules.MemoMaxLength, ErrorMessage = "관리 메모는 최대 1000자까지 입력 가능합니다.")]
public string? AdminMemo { get; set; } public string? AdminMemo { get; set; }
} }
@@ -0,0 +1,22 @@
namespace TaxBaik.Application.DTOs;
public static class ValidationRules
{
public const int NameMaxLength = 100;
public const int PhoneMaxLength = 20;
public const int ServiceTypeMaxLength = 50;
public const int MessageMaxLength = 5000;
public const int MessageMinLength = 10;
public const int MemoMaxLength = 1000;
public const int TitleMaxLength = 100;
public const int QuestionMaxLength = 300;
public const int ContentMaxLength = 30000;
public const int TagsMaxLength = 500;
public const int SeoTitleMaxLength = 120;
public const int SeoDescriptionMaxLength = 300;
public const int ContractNumberMaxLength = 50;
public const int RiskLevelMaxLength = 20;
public const string KoreanPhonePattern =
@"^(0(?:2|3[1-3]|4[1-4]|5[1-5]|6[1-4]|70|50[5-9]|[7-9](?:\d{1,2})?)\d{7,8}|0\d{9,10})$";
}
@@ -1,6 +1,7 @@
namespace TaxBaik.WasmClient.Components.Admin.Forms; namespace TaxBaik.WasmClient.Components.Admin.Forms;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using TaxBaik.Application.DTOs;
public sealed class CompanyFormModel public sealed class CompanyFormModel
{ {
@@ -30,51 +31,51 @@ public sealed class CompanyFormModel
public sealed class InquiryFormModel public sealed class InquiryFormModel
{ {
[Required(ErrorMessage = "이름을 입력하세요.")] [Required(ErrorMessage = "이름을 입력하세요.")]
[StringLength(100, ErrorMessage = "이름은 최대 100자까지 입력 가능합니다.")] [StringLength(ValidationRules.NameMaxLength, ErrorMessage = "이름은 최대 100자까지 입력 가능합니다.")]
public string Name { get; set; } = ""; public string Name { get; set; } = "";
[Required(ErrorMessage = "전화번호를 입력하세요.")] [Required(ErrorMessage = "전화번호를 입력하세요.")]
[RegularExpression( [RegularExpression(
@"^(0(?:2|3[1-3]|4[1-4]|5[1-5]|6[1-4]|70|50[5-9]|[7-9](?:\d{1,2})?)\d{7,8}|0\d{9,10})$", ValidationRules.KoreanPhonePattern,
ErrorMessage = "올바른 전화번호 형식이 아닙니다.")] ErrorMessage = "올바른 전화번호 형식이 아닙니다.")]
public string Phone { get; set; } = ""; public string Phone { get; set; } = "";
[EmailAddress(ErrorMessage = "올바른 이메일 형식이 아닙니다.")] [EmailAddress(ErrorMessage = "올바른 이메일 형식이 아닙니다.")]
public string? Email { get; set; } public string? Email { get; set; }
[StringLength(50, ErrorMessage = "상담분야는 최대 50자까지 입력 가능합니다.")] [StringLength(ValidationRules.ServiceTypeMaxLength, ErrorMessage = "상담분야는 최대 50자까지 입력 가능합니다.")]
public string ServiceType { get; set; } = "기타"; public string ServiceType { get; set; } = "기타";
[Required(ErrorMessage = "문의 내용을 입력하세요.")] [Required(ErrorMessage = "문의 내용을 입력하세요.")]
[StringLength(5000, MinimumLength = 10, ErrorMessage = "문의 내용은 최소 10자, 최대 5000자까지 입력 가능합니다.")] [StringLength(ValidationRules.MessageMaxLength, MinimumLength = ValidationRules.MessageMinLength, ErrorMessage = "문의 내용은 최소 10자, 최대 5000자까지 입력 가능합니다.")]
public string Message { get; set; } = ""; public string Message { get; set; } = "";
[Required(ErrorMessage = "상태를 선택하세요.")] [Required(ErrorMessage = "상태를 선택하세요.")]
public string Status { get; set; } = "new"; public string Status { get; set; } = "new";
[StringLength(1000, ErrorMessage = "관리 메모는 최대 1000자까지 입력 가능합니다.")] [StringLength(ValidationRules.MemoMaxLength, ErrorMessage = "관리 메모는 최대 1000자까지 입력 가능합니다.")]
public string? AdminMemo { get; set; } public string? AdminMemo { get; set; }
} }
public sealed class BlogFormModel public sealed class BlogFormModel
{ {
[Required(ErrorMessage = "제목을 입력하세요.")] [Required(ErrorMessage = "제목을 입력하세요.")]
[StringLength(100, ErrorMessage = "제목은 최대 100자까지 입력 가능합니다.")] [StringLength(ValidationRules.TitleMaxLength, ErrorMessage = "제목은 최대 100자까지 입력 가능합니다.")]
public string Title { get; set; } = ""; public string Title { get; set; } = "";
[Required(ErrorMessage = "본문 내용을 입력하세요.")] [Required(ErrorMessage = "본문 내용을 입력하세요.")]
[StringLength(30000, MinimumLength = 10, ErrorMessage = "본문은 최소 10자 이상이어야 합니다.")] [StringLength(ValidationRules.ContentMaxLength, MinimumLength = ValidationRules.MessageMinLength, ErrorMessage = "본문은 최소 10자 이상이어야 합니다.")]
public string Content { get; set; } = ""; public string Content { get; set; } = "";
public int? CategoryId { get; set; } public int? CategoryId { get; set; }
[StringLength(500, ErrorMessage = "태그는 최대 500자까지 입력 가능합니다.")] [StringLength(ValidationRules.TagsMaxLength, ErrorMessage = "태그는 최대 500자까지 입력 가능합니다.")]
public string? Tags { get; set; } public string? Tags { get; set; }
[StringLength(120, ErrorMessage = "SEO 제목은 최대 120자까지 입력 가능합니다.")] [StringLength(ValidationRules.SeoTitleMaxLength, ErrorMessage = "SEO 제목은 최대 120자까지 입력 가능합니다.")]
public string? SeoTitle { get; set; } public string? SeoTitle { get; set; }
[StringLength(300, ErrorMessage = "SEO 설명은 최대 300자까지 입력 가능합니다.")] [StringLength(ValidationRules.SeoDescriptionMaxLength, ErrorMessage = "SEO 설명은 최대 300자까지 입력 가능합니다.")]
public string? SeoDescription { get; set; } public string? SeoDescription { get; set; }
public bool IsPublished { get; set; } public bool IsPublished { get; set; }
@@ -83,14 +84,14 @@ public sealed class BlogFormModel
public sealed class FaqFormModel public sealed class FaqFormModel
{ {
[Required(ErrorMessage = "질문을 입력하세요.")] [Required(ErrorMessage = "질문을 입력하세요.")]
[StringLength(300, ErrorMessage = "질문은 최대 300자까지 입력 가능합니다.")] [StringLength(ValidationRules.QuestionMaxLength, ErrorMessage = "질문은 최대 300자까지 입력 가능합니다.")]
public string Question { get; set; } = ""; public string Question { get; set; } = "";
[Required(ErrorMessage = "답변을 입력하세요.")] [Required(ErrorMessage = "답변을 입력하세요.")]
[StringLength(5000, MinimumLength = 10, ErrorMessage = "답변은 최소 10자, 최대 5000자까지 입력 가능합니다.")] [StringLength(ValidationRules.MessageMaxLength, MinimumLength = ValidationRules.MessageMinLength, ErrorMessage = "답변은 최소 10자, 최대 5000자까지 입력 가능합니다.")]
public string Answer { get; set; } = ""; public string Answer { get; set; } = "";
[StringLength(50, ErrorMessage = "카테고리는 최대 50자까지 입력 가능합니다.")] [StringLength(ValidationRules.ServiceTypeMaxLength, ErrorMessage = "카테고리는 최대 50자까지 입력 가능합니다.")]
public string? Category { get; set; } public string? Category { get; set; }
[Range(0, 9999, ErrorMessage = "정렬 순서는 0 이상 9999 이하이어야 합니다.")] [Range(0, 9999, ErrorMessage = "정렬 순서는 0 이상 9999 이하이어야 합니다.")]
@@ -102,31 +103,31 @@ public sealed class FaqFormModel
public sealed class ClientFormModel public sealed class ClientFormModel
{ {
[Required(ErrorMessage = "고객명을 입력하세요.")] [Required(ErrorMessage = "고객명을 입력하세요.")]
[StringLength(100, ErrorMessage = "고객명은 최대 100자까지 입력 가능합니다.")] [StringLength(ValidationRules.NameMaxLength, ErrorMessage = "고객명은 최대 100자까지 입력 가능합니다.")]
public string Name { get; set; } = ""; public string Name { get; set; } = "";
[StringLength(100, ErrorMessage = "회사명은 최대 100자까지 입력 가능합니다.")] [StringLength(ValidationRules.NameMaxLength, ErrorMessage = "회사명은 최대 100자까지 입력 가능합니다.")]
public string? CompanyName { get; set; } public string? CompanyName { get; set; }
[StringLength(20, ErrorMessage = "전화번호는 최대 20자까지 입력 가능합니다.")] [StringLength(ValidationRules.PhoneMaxLength, ErrorMessage = "전화번호는 최대 20자까지 입력 가능합니다.")]
public string? Phone { get; set; } public string? Phone { get; set; }
[EmailAddress(ErrorMessage = "올바른 이메일 형식이 아닙니다.")] [EmailAddress(ErrorMessage = "올바른 이메일 형식이 아닙니다.")]
public string? Email { get; set; } public string? Email { get; set; }
[StringLength(50, ErrorMessage = "서비스 유형은 최대 50자까지 입력 가능합니다.")] [StringLength(ValidationRules.ServiceTypeMaxLength, ErrorMessage = "서비스 유형은 최대 50자까지 입력 가능합니다.")]
public string? ServiceType { get; set; } public string? ServiceType { get; set; }
[StringLength(50, ErrorMessage = "세금 유형은 최대 50자까지 입력 가능합니다.")] [StringLength(ValidationRules.ServiceTypeMaxLength, ErrorMessage = "세금 유형은 최대 50자까지 입력 가능합니다.")]
public string? TaxType { get; set; } public string? TaxType { get; set; }
[Required(ErrorMessage = "상태를 선택하세요.")] [Required(ErrorMessage = "상태를 선택하세요.")]
public string Status { get; set; } = "active"; public string Status { get; set; } = "active";
[StringLength(50, ErrorMessage = "유입 경로는 최대 50자까지 입력 가능합니다.")] [StringLength(ValidationRules.ServiceTypeMaxLength, ErrorMessage = "유입 경로는 최대 50자까지 입력 가능합니다.")]
public string? Source { get; set; } public string? Source { get; set; }
[StringLength(1000, ErrorMessage = "메모는 최대 1000자까지 입력 가능합니다.")] [StringLength(ValidationRules.MemoMaxLength, ErrorMessage = "메모는 최대 1000자까지 입력 가능합니다.")]
public string? Memo { get; set; } public string? Memo { get; set; }
} }
@@ -136,11 +137,11 @@ public sealed class ContractFormModel
public int? ClientId { get; set; } public int? ClientId { get; set; }
[Required(ErrorMessage = "계약번호를 입력하세요.")] [Required(ErrorMessage = "계약번호를 입력하세요.")]
[StringLength(50, ErrorMessage = "계약번호는 최대 50자까지 입력 가능합니다.")] [StringLength(ValidationRules.ContractNumberMaxLength, ErrorMessage = "계약번호는 최대 50자까지 입력 가능합니다.")]
public string ContractNumber { get; set; } = ""; public string ContractNumber { get; set; } = "";
[Required(ErrorMessage = "서비스 유형을 선택하세요.")] [Required(ErrorMessage = "서비스 유형을 선택하세요.")]
[StringLength(50, ErrorMessage = "서비스 유형은 최대 50자까지 입력 가능합니다.")] [StringLength(ValidationRules.ServiceTypeMaxLength, ErrorMessage = "서비스 유형은 최대 50자까지 입력 가능합니다.")]
public string ServiceType { get; set; } = ""; public string ServiceType { get; set; } = "";
[Required(ErrorMessage = "계약 시작일을 입력하세요.")] [Required(ErrorMessage = "계약 시작일을 입력하세요.")]
@@ -156,7 +157,7 @@ public sealed class TaxFilingScheduleFormModel
public int? ClientId { get; set; } public int? ClientId { get; set; }
[Required(ErrorMessage = "신고 유형을 선택하세요.")] [Required(ErrorMessage = "신고 유형을 선택하세요.")]
[StringLength(50, ErrorMessage = "신고 유형은 최대 50자까지 입력 가능합니다.")] [StringLength(ValidationRules.ServiceTypeMaxLength, ErrorMessage = "신고 유형은 최대 50자까지 입력 가능합니다.")]
public string FilingType { get; set; } = ""; public string FilingType { get; set; } = "";
[Required(ErrorMessage = "마감일을 입력하세요.")] [Required(ErrorMessage = "마감일을 입력하세요.")]
@@ -172,23 +173,23 @@ public sealed class TaxProfileFormModel
public int? ClientId { get; set; } public int? ClientId { get; set; }
[Required(ErrorMessage = "사업 유형을 선택하세요.")] [Required(ErrorMessage = "사업 유형을 선택하세요.")]
[StringLength(50, ErrorMessage = "사업 유형은 최대 50자까지 입력 가능합니다.")] [StringLength(ValidationRules.ServiceTypeMaxLength, ErrorMessage = "사업 유형은 최대 50자까지 입력 가능합니다.")]
public string BusinessType { get; set; } = ""; public string BusinessType { get; set; } = "";
[Required(ErrorMessage = "위험도를 선택하세요.")] [Required(ErrorMessage = "위험도를 선택하세요.")]
[StringLength(20, ErrorMessage = "위험도는 최대 20자까지 입력 가능합니다.")] [StringLength(ValidationRules.RiskLevelMaxLength, ErrorMessage = "위험도는 최대 20자까지 입력 가능합니다.")]
public string TaxRiskLevel { get; set; } = "normal"; public string TaxRiskLevel { get; set; } = "normal";
public DateTime? NextFilingDueDate { get; set; } public DateTime? NextFilingDueDate { get; set; }
[StringLength(1000, ErrorMessage = "특수 사항은 최대 1000자까지 입력 가능합니다.")] [StringLength(ValidationRules.MemoMaxLength, ErrorMessage = "특수 사항은 최대 1000자까지 입력 가능합니다.")]
public string? SpecialNotes { get; set; } public string? SpecialNotes { get; set; }
} }
public sealed class SiteSettingsFormModel public sealed class SiteSettingsFormModel
{ {
[Required(ErrorMessage = "전화번호를 입력하세요.")] [Required(ErrorMessage = "전화번호를 입력하세요.")]
[StringLength(20, ErrorMessage = "전화번호는 최대 20자까지 입력 가능합니다.")] [StringLength(ValidationRules.PhoneMaxLength, ErrorMessage = "전화번호는 최대 20자까지 입력 가능합니다.")]
public string Phone { get; set; } = ""; public string Phone { get; set; } = "";
[Required(ErrorMessage = "이메일을 입력하세요.")] [Required(ErrorMessage = "이메일을 입력하세요.")]