improvement: 메시지 저장/검증 계약 통일 (#222) #223
|
|
@ -22,7 +22,7 @@ public class MessageController : ControllerBase
|
|||
}
|
||||
|
||||
[HttpPost("save")]
|
||||
[SwaggerOperation(Summary = "메시지 저장", Description = "메시지 템플릿을 저장합니다. 메시지 코드가 자동 생성됩니다.")]
|
||||
[SwaggerOperation(Summary = "메시지 저장", Description = "메시지 템플릿을 저장합니다. 메시지 코드가 자동 생성됩니다. 필드명은 snake_case(title, body, image_url, link_url, link_type, data)를 사용합니다. 저장 전 validate API로 사전 검증을 권장합니다.")]
|
||||
public async Task<IActionResult> SaveAsync([FromBody] MessageSaveRequestDto request)
|
||||
{
|
||||
var serviceId = GetServiceId();
|
||||
|
|
@ -59,7 +59,7 @@ public class MessageController : ControllerBase
|
|||
}
|
||||
|
||||
[HttpPost("validate")]
|
||||
[SwaggerOperation(Summary = "메시지 유효성 검사", Description = "메시지 내용의 유효성을 검사합니다.")]
|
||||
[SwaggerOperation(Summary = "메시지 유효성 검사", Description = "메시지 내용의 유효성을 검사합니다. save API와 동일한 snake_case 필드명(title, body, image_url, link_url, link_type, data)을 사용합니다. 검증 실패 시 data.errors[]에 field + message 단위로 오류가 반환됩니다.")]
|
||||
public IActionResult ValidateAsync([FromBody] MessageValidateRequestDto request)
|
||||
{
|
||||
var result = _validationService.Validate(request);
|
||||
|
|
|
|||
|
|
@ -1,20 +1,27 @@
|
|||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace SPMS.Application.DTOs.Message;
|
||||
|
||||
public class MessageValidateRequestDto
|
||||
{
|
||||
[Required]
|
||||
[JsonPropertyName("title")]
|
||||
public string Title { get; set; } = string.Empty;
|
||||
|
||||
[Required]
|
||||
[JsonPropertyName("body")]
|
||||
public string Body { get; set; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("image_url")]
|
||||
public string? ImageUrl { get; set; }
|
||||
|
||||
[JsonPropertyName("link_url")]
|
||||
public string? LinkUrl { get; set; }
|
||||
|
||||
[JsonPropertyName("link_type")]
|
||||
public string? LinkType { get; set; }
|
||||
|
||||
public string? Data { get; set; }
|
||||
[JsonPropertyName("data")]
|
||||
public object? Data { get; set; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -82,27 +82,55 @@ public class MessageValidationService : IMessageValidationService
|
|||
errors.Add(new FieldError { Field = "link_type", Message = "link_type은 deeplink, web, none 중 하나여야 합니다." });
|
||||
}
|
||||
|
||||
private static void ValidateData(string? data, List<FieldError> errors)
|
||||
private static void ValidateData(object? data, List<FieldError> errors)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(data))
|
||||
if (data is null)
|
||||
return;
|
||||
|
||||
try
|
||||
// object? → JSON 문자열로 변환
|
||||
string jsonString;
|
||||
if (data is JsonElement jsonElement)
|
||||
{
|
||||
using var doc = JsonDocument.Parse(data);
|
||||
if (doc.RootElement.ValueKind != JsonValueKind.Object)
|
||||
if (jsonElement.ValueKind == JsonValueKind.Null || jsonElement.ValueKind == JsonValueKind.Undefined)
|
||||
return;
|
||||
|
||||
if (jsonElement.ValueKind != JsonValueKind.Object)
|
||||
{
|
||||
errors.Add(new FieldError { Field = "data", Message = "data는 JSON 객체여야 합니다." });
|
||||
return;
|
||||
}
|
||||
|
||||
jsonString = jsonElement.GetRawText();
|
||||
}
|
||||
catch (JsonException)
|
||||
else if (data is string strData)
|
||||
{
|
||||
errors.Add(new FieldError { Field = "data", Message = "유효한 JSON 형식이 아닙니다." });
|
||||
return;
|
||||
if (string.IsNullOrWhiteSpace(strData))
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
using var doc = JsonDocument.Parse(strData);
|
||||
if (doc.RootElement.ValueKind != JsonValueKind.Object)
|
||||
{
|
||||
errors.Add(new FieldError { Field = "data", Message = "data는 JSON 객체여야 합니다." });
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (JsonException)
|
||||
{
|
||||
errors.Add(new FieldError { Field = "data", Message = "유효한 JSON 형식이 아닙니다." });
|
||||
return;
|
||||
}
|
||||
|
||||
jsonString = strData;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 기타 타입은 직렬화하여 검증
|
||||
jsonString = JsonSerializer.Serialize(data);
|
||||
}
|
||||
|
||||
if (System.Text.Encoding.UTF8.GetByteCount(data) > MaxDataSizeBytes)
|
||||
if (System.Text.Encoding.UTF8.GetByteCount(jsonString) > MaxDataSizeBytes)
|
||||
errors.Add(new FieldError { Field = "data", Message = $"data는 {MaxDataSizeBytes / 1024}KB를 초과할 수 없습니다." });
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user