From e81b12fbea677f31cabde24d6321e7f4d8b537cb Mon Sep 17 00:00:00 2001 From: SEAN Date: Tue, 10 Feb 2026 10:48:57 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EB=82=B4=20=EC=A0=95=EB=B3=B4=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C/=EC=88=98=EC=A0=95=20API=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84=20(#62)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ProfileResponseDto, UpdateProfileRequestDto 생성 - IAuthService에 GetProfileAsync, UpdateProfileAsync 추가 - AuthService에 프로필 조회/수정 로직 구현 - ProfileController 생성 (v1/in/account/profile) --- SPMS.API/Controllers/ProfileController.cs | 59 ++++++++++++++++ .../DTOs/Account/ProfileResponseDto.cs | 24 +++++++ .../DTOs/Account/UpdateProfileRequestDto.cs | 13 ++++ SPMS.Application/Interfaces/IAuthService.cs | 3 + SPMS.Application/Services/AuthService.cs | 70 +++++++++++++++++++ 5 files changed, 169 insertions(+) create mode 100644 SPMS.API/Controllers/ProfileController.cs create mode 100644 SPMS.Application/DTOs/Account/ProfileResponseDto.cs create mode 100644 SPMS.Application/DTOs/Account/UpdateProfileRequestDto.cs diff --git a/SPMS.API/Controllers/ProfileController.cs b/SPMS.API/Controllers/ProfileController.cs new file mode 100644 index 0000000..b5c0795 --- /dev/null +++ b/SPMS.API/Controllers/ProfileController.cs @@ -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))] + [SwaggerResponse(401, "인증되지 않은 요청")] + public async Task GetProfileAsync() + { + var adminIdClaim = User.FindFirst("adminId")?.Value; + if (string.IsNullOrEmpty(adminIdClaim) || !long.TryParse(adminIdClaim, out var adminId)) + { + return Unauthorized(ApiResponse.Fail("101", "인증 정보가 유효하지 않습니다.")); + } + + var result = await _authService.GetProfileAsync(adminId); + return Ok(ApiResponse.Success(result)); + } + + [HttpPost("update")] + [SwaggerOperation( + Summary = "내 정보 수정", + Description = "현재 로그인된 관리자의 프로필 정보(이름, 전화번호)를 수정합니다.")] + [SwaggerResponse(200, "수정 성공", typeof(ApiResponse))] + [SwaggerResponse(400, "변경된 내용 없음")] + [SwaggerResponse(401, "인증되지 않은 요청")] + public async Task UpdateProfileAsync([FromBody] UpdateProfileRequestDto request) + { + var adminIdClaim = User.FindFirst("adminId")?.Value; + if (string.IsNullOrEmpty(adminIdClaim) || !long.TryParse(adminIdClaim, out var adminId)) + { + return Unauthorized(ApiResponse.Fail("101", "인증 정보가 유효하지 않습니다.")); + } + + var result = await _authService.UpdateProfileAsync(adminId, request); + return Ok(ApiResponse.Success(result)); + } +} diff --git a/SPMS.Application/DTOs/Account/ProfileResponseDto.cs b/SPMS.Application/DTOs/Account/ProfileResponseDto.cs new file mode 100644 index 0000000..3077f2f --- /dev/null +++ b/SPMS.Application/DTOs/Account/ProfileResponseDto.cs @@ -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; } +} diff --git a/SPMS.Application/DTOs/Account/UpdateProfileRequestDto.cs b/SPMS.Application/DTOs/Account/UpdateProfileRequestDto.cs new file mode 100644 index 0000000..a7a0992 --- /dev/null +++ b/SPMS.Application/DTOs/Account/UpdateProfileRequestDto.cs @@ -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; } +} diff --git a/SPMS.Application/Interfaces/IAuthService.cs b/SPMS.Application/Interfaces/IAuthService.cs index 6c508dd..f92216f 100644 --- a/SPMS.Application/Interfaces/IAuthService.cs +++ b/SPMS.Application/Interfaces/IAuthService.cs @@ -1,3 +1,4 @@ +using SPMS.Application.DTOs.Account; using SPMS.Application.DTOs.Auth; namespace SPMS.Application.Interfaces; @@ -10,4 +11,6 @@ public interface IAuthService Task LogoutAsync(long adminId); Task ChangePasswordAsync(long adminId, ChangePasswordRequestDto request); Task CheckEmailAsync(EmailCheckRequestDto request); + Task GetProfileAsync(long adminId); + Task UpdateProfileAsync(long adminId, UpdateProfileRequestDto request); } diff --git a/SPMS.Application/Services/AuthService.cs b/SPMS.Application/Services/AuthService.cs index f0995b4..d4ce1ef 100644 --- a/SPMS.Application/Services/AuthService.cs +++ b/SPMS.Application/Services/AuthService.cs @@ -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; @@ -225,4 +226,73 @@ public class AuthService : IAuthService IsAvailable = !exists }; } + + public async Task 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 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 + }; + } }