diff --git a/src/main/java/com/blog/domain/auth/controller/OAuth2Controller.java b/src/main/java/com/blog/domain/auth/controller/OAuth2Controller.java index e50e794..271fa99 100644 --- a/src/main/java/com/blog/domain/auth/controller/OAuth2Controller.java +++ b/src/main/java/com/blog/domain/auth/controller/OAuth2Controller.java @@ -1,7 +1,10 @@ package com.blog.domain.auth.controller; import com.blog.domain.auth.dto.ResponseMessage; +import com.blog.domain.auth.dto.requests.OAuthRegisterRequest; import com.blog.domain.auth.dto.responses.LoginPostResponse; +import com.blog.domain.auth.dto.responses.OAuthLoginResponse; +import com.blog.domain.auth.dto.responses.RegisterPostResponse; import com.blog.domain.auth.entity.enums.OAuthProvider; import com.blog.domain.auth.service.OAuth2Service; import com.blog.global.common.dto.ResponseDto; @@ -10,11 +13,14 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; import java.io.IOException; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @@ -31,36 +37,46 @@ public class OAuth2Controller { // utils private final OAuth2AuthExecutor oAuth2AuthExecutor; - @GetMapping("/{provider}") - @Operation(summary = "OAuth2 로그인을 위한 redirect URL을 반환합니다. provider에는 'kakao'가 들어갑니다.") + @GetMapping("/kakao") + @Operation(summary = "OAuth2 로그인을 위한 redirect URL을 반환합니다.") public void getOAuthLogin( - @PathVariable("provider") String provider, HttpServletResponse httpServletResponse ) throws IOException { - OAuthProvider oAuthProviders = OAuthProvider.valueOf(provider.toUpperCase()); + OAuthProvider oAuthProviders = OAuthProvider.valueOf("KAKAO"); String authorizationUrl = this.oAuth2AuthExecutor.getAuthorizationUrl( oAuthProviders.getOauthUrlBuilderClass()); httpServletResponse.sendRedirect(authorizationUrl); } - @GetMapping("/{provider}/redirect") - @Operation(summary = "AuthCode를 받아 OAuth2 로그인을 진행합니다. provider에는 'kakao'가 들어갑니다.") - public ResponseDto getOAuthLoginRedirect( - @PathVariable("provider") String provider, + @GetMapping("/kakao/redirect") + @Operation(summary = "AuthCode를 받아 OAuth2 로그인을 진행합니다.") + public ResponseDto getOAuthLoginRedirect( @RequestParam("code") String code) { - OAuthProvider oAuthProviders = OAuthProvider.valueOf(provider.toUpperCase()); + OAuthProvider oAuthProviders = OAuthProvider.valueOf("KAKAO"); MemberInfoFromProviders memberInfoFromProviders = this.oAuth2AuthExecutor.getMemberInfoFrom( oAuthProviders.getOauth2ProviderClientClass(), code ); - LoginPostResponse loginInfo = this.oAuth2Service.oauth2Login(memberInfoFromProviders); + OAuthLoginResponse loginInfo = this.oAuth2Service.oauth2Login(memberInfoFromProviders); return ResponseDto.of( HttpStatus.OK.value(), - ResponseMessage.LOGIN_SUCCESS.getMessage(), + loginInfo.getResponseMessage(), loginInfo ); } + + @PostMapping("/register-oauth") + @Operation(summary = "OAuth2 회원가입을 진행합니다.") + public ResponseDto postOAuthRegister( + @RequestBody @Valid OAuthRegisterRequest oAuthRegisterRequest + ) { + return ResponseDto.of( + HttpStatus.CREATED.value(), + ResponseMessage.REGISTER_SUCCESS.getMessage(), + this.oAuth2Service.oauth2Register(oAuthRegisterRequest) + ); + } } diff --git a/src/main/java/com/blog/domain/auth/dto/ResponseMessage.java b/src/main/java/com/blog/domain/auth/dto/ResponseMessage.java index 8911a82..961b71e 100644 --- a/src/main/java/com/blog/domain/auth/dto/ResponseMessage.java +++ b/src/main/java/com/blog/domain/auth/dto/ResponseMessage.java @@ -15,7 +15,8 @@ public enum ResponseMessage { NOT_FOUND_ACCESS_TOKEN("Access Token을 찾을 수 없습니다."), NOT_FOUND_REFRESH_TOKEN("Refresh Token을 찾을 수 없습니다."), REISSUE_ACCESS_TOKEN_SUCCESS("액세스 토큰 재발급에 성공했습니다."), - OAUTH2_REGISTER_FAILURE("OAuth2 회원가입에 실패했습니다."); + OAUTH2_REGISTER_FAILURE("OAuth2 회원가입에 실패했습니다."), + OAUTH2_REGISTER_REQUIRED("OAuth2 회원가입이 필요합니다."); private final String message; } diff --git a/src/main/java/com/blog/domain/auth/dto/requests/OAuthRegisterRequest.java b/src/main/java/com/blog/domain/auth/dto/requests/OAuthRegisterRequest.java new file mode 100644 index 0000000..e948fe9 --- /dev/null +++ b/src/main/java/com/blog/domain/auth/dto/requests/OAuthRegisterRequest.java @@ -0,0 +1,41 @@ +package com.blog.domain.auth.dto.requests; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Pattern; +import jakarta.validation.constraints.Size; + +public record OAuthRegisterRequest( + @Schema(description = "사용자 이메일", example = "user@example.com") + @NotEmpty(message = "이메일은 필수 입력 사항입니다.") + @Email(regexp = "^\\w+([.-]?\\w+)*@\\w+([.-]?\\w+)*(\\.\\w{2,3})+$", message = "이메일 형식이 올바르지 않습니다.") + String email, + + @Schema(description = "사용자 닉네임 (영문, 숫자만 가능)", example = "john123") + @NotEmpty(message = "닉네임은 공백이 아니어야 합니다.") + @Size(min = 3, max = 20, message = "닉네임은 최소 3자 이상, 최대 20자 이하여야 합니다.") + @Pattern(regexp = "^[a-zA-Z0-9]+$", message = "닉네임은 영문, 숫자만 가능합니다.") + String nickname, + + @Schema(description = "프로필 사진 URL", example = "https://example.com/profile.jpg") + @Size(max = 1000, message = "프로필 사진의 길이가, 허용량을 초과했습니다.") + String profilePicture, + + @Schema(description = "생년월일 (YYYY-MM-DD)", example = "2000-01-01") + @NotNull(message = "생년월일은 필수 입력 사항입니다.") + String birthDate, + + @Schema(description = "사용자 이름", example = "김주영") + @Size(max = 20, message = "이름은 최대 20자 이하여야 합니다.") + @Pattern(regexp = "^[가-힣]*$", message = "이름은 한글만 가능합니다.") + @NotEmpty(message = "이름은 공백이 아니어야 합니다.") + String name, + + @Schema(description = "사용자 소개", example = "안녕하세요!") + @Size(max = 30, message = "소개는 최대 30자 이하여야 합니다.") + String introduction +) { + +} diff --git a/src/main/java/com/blog/domain/auth/dto/requests/RegisterPostRequest.java b/src/main/java/com/blog/domain/auth/dto/requests/RegisterPostRequest.java index d0b7694..b01a6ad 100644 --- a/src/main/java/com/blog/domain/auth/dto/requests/RegisterPostRequest.java +++ b/src/main/java/com/blog/domain/auth/dto/requests/RegisterPostRequest.java @@ -31,13 +31,20 @@ public record RegisterPostRequest( @Schema(description = "프로필 사진 URL", example = "https://example.com/profile.jpg") @Size(max = 1000, message = "프로필 사진의 길이가, 허용량을 초과했습니다.") - String profilePicture -) { + String profilePicture, + + @Schema(description = "생년월일 (YYYY-MM-DD)", example = "2000-01-01") + @NotNull(message = "생년월일은 필수 입력 사항입니다.") + String birthDate, - public static RegisterPostRequest createOauthRegister(String email, String nickname, String password, String profilePicture) { - if (email == null) { - email = UUID.randomUUID().toString().replace("-", "") + "@leets.land"; - } - return new RegisterPostRequest(email, nickname, password, profilePicture); - } + @Schema(description = "사용자 이름", example = "김주영") + @Size(max = 20, message = "이름은 최대 20자 이하여야 합니다.") + @Pattern(regexp = "^[가-힣]*$", message = "이름은 한글만 가능합니다.") + @NotEmpty(message = "이름은 공백이 아니어야 합니다.") + String name, + + @Schema(description = "사용자 소개", example = "안녕하세요!") + @Size(max = 30, message = "소개는 최대 30자 이하여야 합니다.") + String introduction +) { } diff --git a/src/main/java/com/blog/domain/auth/dto/responses/LoginPostResponse.java b/src/main/java/com/blog/domain/auth/dto/responses/LoginPostResponse.java index 0fcbc8c..f4cc69b 100644 --- a/src/main/java/com/blog/domain/auth/dto/responses/LoginPostResponse.java +++ b/src/main/java/com/blog/domain/auth/dto/responses/LoginPostResponse.java @@ -1,5 +1,6 @@ package com.blog.domain.auth.dto.responses; +import com.blog.domain.auth.dto.ResponseMessage; import io.swagger.v3.oas.annotations.media.Schema; @Schema(description = "로그인 응답 DTO") @@ -15,5 +16,10 @@ public record LoginPostResponse( @Schema(description = "프로필 사진 URL", example = "https://example.com/profile.jpg") String profilePicture -) { +) implements OAuthLoginResponse{ + + @Override + public String getResponseMessage() { + return ResponseMessage.LOGIN_SUCCESS.getMessage(); + } } \ No newline at end of file diff --git a/src/main/java/com/blog/domain/auth/dto/responses/OAuthLoginResponse.java b/src/main/java/com/blog/domain/auth/dto/responses/OAuthLoginResponse.java new file mode 100644 index 0000000..dec2588 --- /dev/null +++ b/src/main/java/com/blog/domain/auth/dto/responses/OAuthLoginResponse.java @@ -0,0 +1,6 @@ +package com.blog.domain.auth.dto.responses; + +public interface OAuthLoginResponse { + + String getResponseMessage(); +} diff --git a/src/main/java/com/blog/domain/auth/dto/responses/OAuthRegisterRequiredResponse.java b/src/main/java/com/blog/domain/auth/dto/responses/OAuthRegisterRequiredResponse.java new file mode 100644 index 0000000..0e45ba8 --- /dev/null +++ b/src/main/java/com/blog/domain/auth/dto/responses/OAuthRegisterRequiredResponse.java @@ -0,0 +1,22 @@ +package com.blog.domain.auth.dto.responses; + +import com.blog.domain.auth.dto.ResponseMessage; +import com.blog.global.common.oauth.MemberInfoFromProviders; + +public record OAuthRegisterRequiredResponse( + String nickname, + String picture +) implements OAuthLoginResponse{ + + @Override + public String getResponseMessage() { + return ResponseMessage.OAUTH2_REGISTER_REQUIRED.getMessage(); + } + + public static OAuthRegisterRequiredResponse from(MemberInfoFromProviders memberInfoFromProviders) { + return new OAuthRegisterRequiredResponse( + memberInfoFromProviders.nickname(), + memberInfoFromProviders.picture() + ); + } +} diff --git a/src/main/java/com/blog/domain/auth/dto/responses/RegisterPostResponse.java b/src/main/java/com/blog/domain/auth/dto/responses/RegisterPostResponse.java index 32f70fc..51e6b68 100644 --- a/src/main/java/com/blog/domain/auth/dto/responses/RegisterPostResponse.java +++ b/src/main/java/com/blog/domain/auth/dto/responses/RegisterPostResponse.java @@ -1,5 +1,6 @@ package com.blog.domain.auth.dto.responses; +import com.blog.domain.user.domain.entity.User; import io.swagger.v3.oas.annotations.media.Schema; @Schema(description = "회원가입 응답 DTO") @@ -13,4 +14,12 @@ public record RegisterPostResponse( @Schema(description = "등록된 프로필 사진 URL", example = "https://example.com/profile.jpg") String profilePicture ) { + + public static RegisterPostResponse of(User user) { + return new RegisterPostResponse( + user.getEmail(), + user.getNickname(), + user.getProfilePicture() + ); + } } diff --git a/src/main/java/com/blog/domain/auth/service/AuthService.java b/src/main/java/com/blog/domain/auth/service/AuthService.java index 0859df3..e067919 100644 --- a/src/main/java/com/blog/domain/auth/service/AuthService.java +++ b/src/main/java/com/blog/domain/auth/service/AuthService.java @@ -10,6 +10,7 @@ import com.blog.domain.user.domain.entity.User; import com.blog.domain.user.domain.service.UserService; import com.blog.domain.user.exception.EmailDuplicateException; +import com.blog.domain.user.exception.NicknameDuplicateException; import com.blog.global.common.utils.jwt.JwtAuthenticator; import com.blog.global.common.utils.jwt.JwtExtractor; import com.blog.global.common.utils.jwt.JwtProvider; @@ -74,6 +75,11 @@ public RegisterPostResponse register(RegisterPostRequest registerPostRequest) { throw new EmailDuplicateException(); } + boolean isNicknameDuplicate = this.userService.checkNicknameDuplicate(registerPostRequest.nickname()); + if (isNicknameDuplicate) { + throw new NicknameDuplicateException(); + } + String hashedPassword = this.userService.hashPassword(registerPostRequest.password()); User user = User.create(registerPostRequest, hashedPassword); diff --git a/src/main/java/com/blog/domain/auth/service/OAuth2Service.java b/src/main/java/com/blog/domain/auth/service/OAuth2Service.java index a927908..57398ae 100644 --- a/src/main/java/com/blog/domain/auth/service/OAuth2Service.java +++ b/src/main/java/com/blog/domain/auth/service/OAuth2Service.java @@ -1,12 +1,14 @@ package com.blog.domain.auth.service; import com.blog.domain.auth.dto.requests.LoginPostRequest; -import com.blog.domain.auth.dto.requests.RegisterPostRequest; -import com.blog.domain.auth.dto.responses.LoginPostResponse; +import com.blog.domain.auth.dto.requests.OAuthRegisterRequest; +import com.blog.domain.auth.dto.responses.OAuthLoginResponse; +import com.blog.domain.auth.dto.responses.OAuthRegisterRequiredResponse; import com.blog.domain.auth.dto.responses.RegisterPostResponse; -import com.blog.domain.auth.exception.OAuth2RegisterFailureException; import com.blog.domain.user.domain.entity.User; import com.blog.domain.user.domain.service.UserService; +import com.blog.domain.user.exception.EmailDuplicateException; +import com.blog.domain.user.exception.NicknameDuplicateException; import com.blog.global.common.oauth.MemberInfoFromProviders; import com.blog.global.config.properties.AppConfigProperties; import jakarta.transaction.Transactional; @@ -25,28 +27,36 @@ public class OAuth2Service { private final AppConfigProperties appConfigProperties; @Transactional - public LoginPostResponse oauth2Login(MemberInfoFromProviders memberInfoFromProviders) { + public OAuthLoginResponse oauth2Login(MemberInfoFromProviders memberInfoFromProviders) { Optional getLoginAvailableResponse = this.userService.checkLoginAvailableByNickname(memberInfoFromProviders.nickname(), this.appConfigProperties.getOauthDummyPassword()); if (getLoginAvailableResponse.isEmpty()) { - RegisterPostRequest oauthRegister = - RegisterPostRequest.createOauthRegister( - memberInfoFromProviders.email(), - memberInfoFromProviders.nickname(), - this.appConfigProperties.getOauthDummyPassword(), - memberInfoFromProviders.picture() - ); - this.authService.register(oauthRegister); - - this.userService.checkLoginAvailable(oauthRegister.email(), - this.appConfigProperties.getOauthDummyPassword()) - .orElseThrow(OAuth2RegisterFailureException::new); + return OAuthRegisterRequiredResponse.from(memberInfoFromProviders); } LoginPostRequest loginPostRequest = LoginPostRequest.createOAuthLogin( memberInfoFromProviders.nickname(), this.appConfigProperties.getOauthDummyPassword()); return this.authService.login(loginPostRequest, true); } + + @Transactional + public RegisterPostResponse oauth2Register(OAuthRegisterRequest oAuthRegisterRequest) { + boolean isEmailDuplicate = this.userService.checkEmailDuplicate(oAuthRegisterRequest.email()); + if (isEmailDuplicate) { + throw new EmailDuplicateException(); + } + + boolean isNicknameDuplicate = this.userService.checkNicknameDuplicate(oAuthRegisterRequest.nickname()); + if (isNicknameDuplicate) { + throw new NicknameDuplicateException(); + } + + User user = User.create(oAuthRegisterRequest, + this.userService.hashPassword(this.appConfigProperties.getOauthDummyPassword()) + ); + + return RegisterPostResponse.of(this.userService.save(user)); + } } diff --git a/src/main/java/com/blog/domain/user/application/dto/request/UserPatchRequest.java b/src/main/java/com/blog/domain/user/application/dto/request/UserPatchRequest.java new file mode 100644 index 0000000..5463f28 --- /dev/null +++ b/src/main/java/com/blog/domain/user/application/dto/request/UserPatchRequest.java @@ -0,0 +1,48 @@ +package com.blog.domain.user.application.dto.request; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Pattern; +import jakarta.validation.constraints.Size; + +public record UserPatchRequest( + @Schema(description = "사용자 이메일", example = "user@example.com") + @NotEmpty(message = "이메일은 필수 입력 사항입니다.") + @Email(regexp = "^\\w+([.-]?\\w+)*@\\w+([.-]?\\w+)*(\\.\\w{2,3})+$", message = "이메일 형식이 올바르지 않습니다.") + String email, + + @Schema(description = "사용자 닉네임 (영문, 숫자만 가능)", example = "john123") + @NotEmpty(message = "닉네임은 공백이 아니어야 합니다.") + @Size(min = 3, max = 20, message = "닉네임은 최소 3자 이상, 최대 20자 이하여야 합니다.") + @Pattern(regexp = "^[a-zA-Z0-9]+$", message = "닉네임은 영문, 숫자만 가능합니다.") + String nickname, + + @Schema(description = "비밀번호 (8~64자, 영문, 숫자, 특수문자 필수)", example = "Password123!") + @NotEmpty(message = "비밀번호는 공백이 아니어야 합니다.") + @Size(min = 8, max = 64, message = "비밀번호는 최소 8자 이상, 최대 64자 이하여야 합니다.") + @Pattern(regexp = "^(?=.*[a-zA-Z])(?=.*\\d)(?=.*[@$!%*?&])[A-Za-z\\d@$!%*?&]{8,64}$", + message = "비밀번호 8~64자, 영문, 숫자, 특수문자가 필수입니다.") + String password, + + @Schema(description = "프로필 사진 URL", example = "https://example.com/profile.jpg") + @Size(max = 1000, message = "프로필 사진의 길이가, 허용량을 초과했습니다.") + String profilePicture, + + @Schema(description = "생년월일 (YYYY-MM-DD)", example = "2000-01-01") + @NotNull(message = "생년월일은 필수 입력 사항입니다.") + String birthDate, + + @Schema(description = "사용자 이름", example = "김주영") + @Size(max = 20, message = "이름은 최대 20자 이하여야 합니다.") + @Pattern(regexp = "^[가-힣]*$", message = "이름은 한글만 가능합니다.") + @NotEmpty(message = "이름은 공백이 아니어야 합니다.") + String name, + + @Schema(description = "사용자 소개", example = "안녕하세요!") + @Size(max = 30, message = "소개는 최대 30자 이하여야 합니다.") + String introduction +) { + +} diff --git a/src/main/java/com/blog/domain/user/domain/entity/User.java b/src/main/java/com/blog/domain/user/domain/entity/User.java index d523607..cfa3849 100644 --- a/src/main/java/com/blog/domain/user/domain/entity/User.java +++ b/src/main/java/com/blog/domain/user/domain/entity/User.java @@ -1,6 +1,8 @@ package com.blog.domain.user.domain.entity; +import com.blog.domain.auth.dto.requests.OAuthRegisterRequest; import com.blog.domain.auth.dto.requests.RegisterPostRequest; +import com.blog.domain.user.application.dto.request.UserPatchRequest; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; @@ -30,6 +32,9 @@ public class User { @Setter private String nickname; + @Column(length = 20) + private String name; + @Column(name = "profile_picture", length = 255) @Setter private String profilePicture; @@ -41,12 +46,43 @@ public class User { @Setter private String password; + @Column(nullable = false) + private LocalDate birthDate; + + @Column(length = 30) + private String introduction; + public static User create(RegisterPostRequest request, String encodedPassword) { return User.builder() .nickname(request.nickname()) .profilePicture(request.profilePicture()) .email(request.email()) .password(encodedPassword) + .birthDate(LocalDate.parse(request.birthDate())) + .name(request.name()) + .introduction(request.introduction()) .build(); } + + public static User create(OAuthRegisterRequest request, String encodedDummyPassword) { + return User.builder() + .nickname(request.nickname()) + .profilePicture(request.profilePicture()) + .email(request.email()) + .password(encodedDummyPassword) + .birthDate(LocalDate.parse(request.birthDate())) + .name(request.name()) + .introduction(request.introduction()) + .build(); + } + + public void updateUserInfoFrom(UserPatchRequest userPatchRequest, String encodedPassword) { + this.nickname = userPatchRequest.nickname(); + this.profilePicture = userPatchRequest.profilePicture(); + this.name = userPatchRequest.name(); + this.introduction = userPatchRequest.introduction(); + this.email = userPatchRequest.email(); + this.birthDate = LocalDate.parse(userPatchRequest.birthDate()); + this.password = encodedPassword; + } } \ No newline at end of file diff --git a/src/main/java/com/blog/domain/user/domain/service/UserService.java b/src/main/java/com/blog/domain/user/domain/service/UserService.java index 0a7a180..3961660 100644 --- a/src/main/java/com/blog/domain/user/domain/service/UserService.java +++ b/src/main/java/com/blog/domain/user/domain/service/UserService.java @@ -1,8 +1,11 @@ package com.blog.domain.user.domain.service; +import com.blog.domain.user.application.dto.request.UserPatchRequest; import com.blog.domain.user.application.dto.response.UserGetResponse; import com.blog.domain.user.domain.entity.User; import com.blog.domain.user.domain.repository.UserRepository; +import com.blog.domain.user.exception.EmailDuplicateException; +import com.blog.domain.user.exception.NicknameDuplicateException; import com.blog.domain.user.exception.UserNotFoundException; import com.blog.global.common.auth.MemberContext; import com.blog.global.common.auth.TokenMemberInfo; @@ -50,6 +53,10 @@ public boolean checkEmailDuplicate(String email) { return this.userRepository.findByEmail(email).isPresent(); } + public boolean checkNicknameDuplicate(String nickname) { + return this.userRepository.findByNickname(nickname).isPresent(); + } + public String hashPassword(String password) { return this.bCryptPasswordEncoder.encode(password); } @@ -88,4 +95,26 @@ public UserGetResponse getMyInfo() { return UserGetResponse.from(this.findById(member.id())); } + + @Transactional + public void updateUser(UserPatchRequest userPatchRequest) { + boolean isEmailDuplicate = this.checkEmailDuplicate(userPatchRequest.email()); + if (isEmailDuplicate) { + throw new EmailDuplicateException(); + } + + boolean isNicknameDuplicate = this.checkNicknameDuplicate(userPatchRequest.nickname()); + if (isNicknameDuplicate) { + throw new NicknameDuplicateException(); + } + + TokenMemberInfo member = MemberContext.getMember(); + User user = this.findById(member.id()); + + String hashedPassword = this.hashPassword(userPatchRequest.password()); + + user.updateUserInfoFrom(userPatchRequest, hashedPassword); + + this.save(user); + } } diff --git a/src/main/java/com/blog/domain/user/exception/NicknameDuplicateException.java b/src/main/java/com/blog/domain/user/exception/NicknameDuplicateException.java new file mode 100644 index 0000000..2709aa5 --- /dev/null +++ b/src/main/java/com/blog/domain/user/exception/NicknameDuplicateException.java @@ -0,0 +1,10 @@ +package com.blog.domain.user.exception; + +import com.blog.global.common.exception.ApplicationException; + +public class NicknameDuplicateException extends ApplicationException { + + public NicknameDuplicateException() { + super(409, "이미 사용중인 닉네임입니다."); + } +} diff --git a/src/main/java/com/blog/domain/user/presentation/UserController.java b/src/main/java/com/blog/domain/user/presentation/UserController.java index 1cbd50e..d338e9c 100644 --- a/src/main/java/com/blog/domain/user/presentation/UserController.java +++ b/src/main/java/com/blog/domain/user/presentation/UserController.java @@ -3,6 +3,7 @@ import com.blog.domain.user.application.dto.request.NicknamePatchRequest; import com.blog.domain.user.application.dto.request.PasswordPatchRequest; import com.blog.domain.user.application.dto.request.ProfilePicturePatchRequest; +import com.blog.domain.user.application.dto.request.UserPatchRequest; import com.blog.domain.user.application.dto.response.UserGetResponse; import com.blog.domain.user.domain.service.UserGetService; import com.blog.domain.user.domain.service.UserService; @@ -29,6 +30,17 @@ public class UserController { private final UserService userService; + @PatchMapping + @UseGuards({MemberGuard.class}) + @Operation(summary = "유저 정보를 수정하는 API입니다.") + public ResponseDto updateUser( + @RequestBody @Valid UserPatchRequest userPatchRequest + ) { + this.userService.updateUser(userPatchRequest); + + return ResponseDto.of(HttpStatus.OK.value(), ResponseMessage.USER_UPDATED.getMessage()); + } + @PatchMapping("/picture") @UseGuards({MemberGuard.class}) @Operation(summary = "프로필 사진을 수정하는 API입니다.") diff --git a/src/main/java/com/blog/domain/user/presentation/constant/ResponseMessage.java b/src/main/java/com/blog/domain/user/presentation/constant/ResponseMessage.java index b9be124..22179e4 100644 --- a/src/main/java/com/blog/domain/user/presentation/constant/ResponseMessage.java +++ b/src/main/java/com/blog/domain/user/presentation/constant/ResponseMessage.java @@ -11,7 +11,8 @@ public enum ResponseMessage { PROFILE_PICTURE_UPDATED("프로필 사진이 업데이트 되었습니다"), NICKNAME_UPDATED("닉네임이 업데이트 되었습니다"), PASSWORD_UPDATED("비밀번호가 업데이트 되었습니다"), - FOUND_MY_INFO_SUCCESS("내 정보 조회에 성공했습니다"); + FOUND_MY_INFO_SUCCESS("내 정보 조회에 성공했습니다"), + USER_UPDATED("유저 정보가 업데이트 되었습니다"); private final String message;