merge: develop 머지 충돌 해결 (Profile + EmailVerify 통합)

This commit is contained in:
SEAN 2026-02-10 11:02:47 +09:00
commit 59f5dbf839
5 changed files with 169 additions and 0 deletions

View File

@ -0,0 +1,59 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Swashbuckle.AspNetCore.Annotations;
using SPMS.Application.DTOs.Account;
using SPMS.Application.Interfaces;
using SPMS.Domain.Common;
namespace SPMS.API.Controllers;
[ApiController]
[Route("v1/in/account/profile")]
[ApiExplorerSettings(GroupName = "account")]
[Authorize]
public class ProfileController : ControllerBase
{
private readonly IAuthService _authService;
public ProfileController(IAuthService authService)
{
_authService = authService;
}
[HttpPost("info")]
[SwaggerOperation(
Summary = "내 정보 조회",
Description = "현재 로그인된 관리자의 프로필 정보를 조회합니다.")]
[SwaggerResponse(200, "조회 성공", typeof(ApiResponse<ProfileResponseDto>))]
[SwaggerResponse(401, "인증되지 않은 요청")]
public async Task<IActionResult> GetProfileAsync()
{
var adminIdClaim = User.FindFirst("adminId")?.Value;
if (string.IsNullOrEmpty(adminIdClaim) || !long.TryParse(adminIdClaim, out var adminId))
{
return Unauthorized(ApiResponse<object>.Fail("101", "인증 정보가 유효하지 않습니다."));
}
var result = await _authService.GetProfileAsync(adminId);
return Ok(ApiResponse<ProfileResponseDto>.Success(result));
}
[HttpPost("update")]
[SwaggerOperation(
Summary = "내 정보 수정",
Description = "현재 로그인된 관리자의 프로필 정보(이름, 전화번호)를 수정합니다.")]
[SwaggerResponse(200, "수정 성공", typeof(ApiResponse<ProfileResponseDto>))]
[SwaggerResponse(400, "변경된 내용 없음")]
[SwaggerResponse(401, "인증되지 않은 요청")]
public async Task<IActionResult> UpdateProfileAsync([FromBody] UpdateProfileRequestDto request)
{
var adminIdClaim = User.FindFirst("adminId")?.Value;
if (string.IsNullOrEmpty(adminIdClaim) || !long.TryParse(adminIdClaim, out var adminId))
{
return Unauthorized(ApiResponse<object>.Fail("101", "인증 정보가 유효하지 않습니다."));
}
var result = await _authService.UpdateProfileAsync(adminId, request);
return Ok(ApiResponse<ProfileResponseDto>.Success(result));
}
}

View File

@ -0,0 +1,24 @@
using System.Text.Json.Serialization;
namespace SPMS.Application.DTOs.Account;
public class ProfileResponseDto
{
[JsonPropertyName("admin_code")]
public string AdminCode { get; set; } = string.Empty;
[JsonPropertyName("email")]
public string Email { get; set; } = string.Empty;
[JsonPropertyName("name")]
public string Name { get; set; } = string.Empty;
[JsonPropertyName("phone")]
public string Phone { get; set; } = string.Empty;
[JsonPropertyName("role")]
public int Role { get; set; }
[JsonPropertyName("created_at")]
public DateTime CreatedAt { get; set; }
}

View File

@ -0,0 +1,13 @@
using System.ComponentModel.DataAnnotations;
namespace SPMS.Application.DTOs.Account;
public class UpdateProfileRequestDto
{
[StringLength(50, ErrorMessage = "이름은 50자 이내여야 합니다.")]
public string? Name { get; set; }
[Phone(ErrorMessage = "올바른 전화번호 형식이 아닙니다.")]
[StringLength(20, ErrorMessage = "전화번호는 20자 이내여야 합니다.")]
public string? Phone { get; set; }
}

View File

@ -1,3 +1,4 @@
using SPMS.Application.DTOs.Account;
using SPMS.Application.DTOs.Auth;
namespace SPMS.Application.Interfaces;
@ -11,4 +12,6 @@ public interface IAuthService
Task ChangePasswordAsync(long adminId, ChangePasswordRequestDto request);
Task<EmailCheckResponseDto> CheckEmailAsync(EmailCheckRequestDto request);
Task VerifyEmailAsync(EmailVerifyRequestDto request);
Task<ProfileResponseDto> GetProfileAsync(long adminId);
Task<ProfileResponseDto> UpdateProfileAsync(long adminId, UpdateProfileRequestDto request);
}

View File

@ -1,4 +1,5 @@
using Microsoft.Extensions.Options;
using SPMS.Application.DTOs.Account;
using SPMS.Application.DTOs.Auth;
using SPMS.Application.Interfaces;
using SPMS.Application.Settings;
@ -275,4 +276,73 @@ public class AuthService : IAuthService
await _tokenStore.RemoveAsync($"email_verify:{request.Email}");
}
public async Task<ProfileResponseDto> GetProfileAsync(long adminId)
{
var admin = await _adminRepository.GetByIdAsync(adminId);
if (admin is null)
{
throw new SpmsException(
ErrorCodes.NotFound,
"관리자를 찾을 수 없습니다.",
404);
}
return new ProfileResponseDto
{
AdminCode = admin.AdminCode,
Email = admin.Email,
Name = admin.Name,
Phone = admin.Phone,
Role = (int)admin.Role,
CreatedAt = admin.CreatedAt
};
}
public async Task<ProfileResponseDto> UpdateProfileAsync(long adminId, UpdateProfileRequestDto request)
{
var admin = await _adminRepository.GetByIdAsync(adminId);
if (admin is null)
{
throw new SpmsException(
ErrorCodes.NotFound,
"관리자를 찾을 수 없습니다.",
404);
}
var hasChange = false;
if (request.Name is not null && request.Name != admin.Name)
{
admin.Name = request.Name;
hasChange = true;
}
if (request.Phone is not null && request.Phone != admin.Phone)
{
admin.Phone = request.Phone;
hasChange = true;
}
if (!hasChange)
{
throw new SpmsException(
ErrorCodes.NoChange,
"변경된 내용이 없습니다.",
400);
}
_adminRepository.Update(admin);
await _unitOfWork.SaveChangesAsync();
return new ProfileResponseDto
{
AdminCode = admin.AdminCode,
Email = admin.Email,
Name = admin.Name,
Phone = admin.Phone,
Role = (int)admin.Role,
CreatedAt = admin.CreatedAt
};
}
}