diff --git a/src/main/java/Gotcha/common/jwt/auth/SecurityUserDetails.java b/src/main/java/Gotcha/common/jwt/auth/SecurityUserDetails.java index 85ff32ee..53ed0ffb 100644 --- a/src/main/java/Gotcha/common/jwt/auth/SecurityUserDetails.java +++ b/src/main/java/Gotcha/common/jwt/auth/SecurityUserDetails.java @@ -1,6 +1,7 @@ package Gotcha.common.jwt.auth; import Gotcha.common.security.CustomGrantedAuthority; +import Gotcha.domain.user.entity.Role; import Gotcha.domain.user.entity.User; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import lombok.Getter; @@ -46,6 +47,10 @@ public Long getId(){ return user.getId(); } + public Role getRole() { + return user.getRole(); + } + @Override public boolean isAccountNonExpired() { return true; diff --git a/src/main/java/Gotcha/domain/user/api/UserApi.java b/src/main/java/Gotcha/domain/user/api/UserApi.java index 8bc5c7ac..771bd621 100644 --- a/src/main/java/Gotcha/domain/user/api/UserApi.java +++ b/src/main/java/Gotcha/domain/user/api/UserApi.java @@ -1,5 +1,6 @@ package Gotcha.domain.user.api; +import Gotcha.common.jwt.auth.SecurityUserDetails; import Gotcha.domain.user.dto.NicknameReq; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; @@ -9,6 +10,7 @@ import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; import org.springframework.http.ResponseEntity; +import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.web.bind.annotation.RequestBody; @Tag(name = "[사용자 API]", description = "사용자 관련 API") @@ -49,4 +51,42 @@ public interface UserApi { })) }) ResponseEntity checkNickname(@Valid @RequestBody NicknameReq nicknameReq); + + @Operation(summary = "사용자 정보 조회", description = "사용자 정보 조회 API") + @ApiResponses({ + @ApiResponse(responseCode = "200", description = "사용자 정보 조회 성공", + content = @Content(mediaType = "application/json", examples = { + @ExampleObject(name = "게스트 조회", value = """ + { + "nickname": "웃긴너구리", + "email": null, + "role": "GUEST" + } + """), + @ExampleObject(name = "사용자 조회", value = """ + { + "nickname": "테스트", + "email": "test@gmail.com", + "role": "USER" + } + """), + @ExampleObject(name = "관리자 조회", value = """ + { + "nickname": "관리자", + "email": "admin@gmail.com", + "role": "ADMIN" + } + """) + })), + @ApiResponse(responseCode = "404", description = "존재하지 않는 사용자", + content = @Content(mediaType = "application/json", examples = { + @ExampleObject(value = """ + { + "status": "NOT_FOUND", + "message": "존재하지 않는 사용자입니다." + } + """) + })), + }) + ResponseEntity getUserInfo(@AuthenticationPrincipal SecurityUserDetails userDetails); } diff --git a/src/main/java/Gotcha/domain/user/controller/UserController.java b/src/main/java/Gotcha/domain/user/controller/UserController.java index 0a0b043c..2d552f96 100644 --- a/src/main/java/Gotcha/domain/user/controller/UserController.java +++ b/src/main/java/Gotcha/domain/user/controller/UserController.java @@ -1,12 +1,17 @@ package Gotcha.domain.user.controller; import Gotcha.common.api.SuccessRes; +import Gotcha.common.jwt.auth.SecurityUserDetails; import Gotcha.domain.user.api.UserApi; import Gotcha.domain.user.dto.NicknameReq; +import Gotcha.domain.user.dto.UserInfoRes; import Gotcha.domain.user.service.UserService; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; @@ -25,4 +30,11 @@ public ResponseEntity checkNickname(@Valid @RequestBody NicknameReq nicknameR return ResponseEntity.ok(SuccessRes.from("사용 가능한 닉네임입니다.")); } + + @GetMapping("/me/main-info") + public ResponseEntity getUserInfo(@AuthenticationPrincipal SecurityUserDetails userDetails){ + UserInfoRes userInfoRes = userService.getUserInfo(userDetails.getId(), userDetails.getRole()); + + return ResponseEntity.status(HttpStatus.OK).body(userInfoRes); + } } diff --git a/src/main/java/Gotcha/domain/user/dto/UserInfoRes.java b/src/main/java/Gotcha/domain/user/dto/UserInfoRes.java new file mode 100644 index 00000000..97792237 --- /dev/null +++ b/src/main/java/Gotcha/domain/user/dto/UserInfoRes.java @@ -0,0 +1,18 @@ +package Gotcha.domain.user.dto; + +import Gotcha.domain.user.entity.Role; +import Gotcha.domain.user.entity.User; + +public record UserInfoRes( + String nickname, + String email, + Role role +) { + public static UserInfoRes fromEntity(User user){ + return new UserInfoRes( + user.getNickname(), + user.getEmail(), + user.getRole() + ); + } +} diff --git a/src/main/java/Gotcha/domain/user/exceptionCode/UserExceptionCode.java b/src/main/java/Gotcha/domain/user/exceptionCode/UserExceptionCode.java index 739921b4..c1682d0d 100644 --- a/src/main/java/Gotcha/domain/user/exceptionCode/UserExceptionCode.java +++ b/src/main/java/Gotcha/domain/user/exceptionCode/UserExceptionCode.java @@ -9,7 +9,8 @@ @ToString public enum UserExceptionCode implements ExceptionCode { NICKNAME_EXIST(HttpStatus.CONFLICT, "이미 존재하는 닉네임입니다."), - EMAIL_EXIST(HttpStatus.CONFLICT, "이미 가입된 이메일입니다."); + EMAIL_EXIST(HttpStatus.CONFLICT, "이미 가입된 이메일입니다."), + INVALID_USERID(HttpStatus.NOT_FOUND, "존재하지 않는 사용자입니다."); private final HttpStatus status; private final String message; diff --git a/src/main/java/Gotcha/domain/user/service/UserService.java b/src/main/java/Gotcha/domain/user/service/UserService.java index d4d981cb..76324364 100644 --- a/src/main/java/Gotcha/domain/user/service/UserService.java +++ b/src/main/java/Gotcha/domain/user/service/UserService.java @@ -2,12 +2,19 @@ import Gotcha.common.exception.CustomException; import Gotcha.common.util.RedisUtil; +import Gotcha.domain.user.dto.UserInfoRes; +import Gotcha.domain.user.entity.Role; +import Gotcha.domain.user.entity.User; import Gotcha.domain.user.exceptionCode.UserExceptionCode; import Gotcha.domain.user.repository.UserRepository; import lombok.RequiredArgsConstructor; +import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.Optional; + +import static Gotcha.common.redis.RedisProperties.GUEST_KEY_PREFIX; import static Gotcha.common.redis.RedisProperties.NICKNAME_VERIFY_KEY_PREFIX; @Service @@ -35,4 +42,24 @@ public void checkEmail(String email) { throw new CustomException(UserExceptionCode.EMAIL_EXIST); } } + + @Transactional(readOnly = true) + public UserInfoRes getUserInfo(Long userId, Role role){ + User user = switch (role){ + case GUEST -> findGuestByGuestId(userId); + case USER,ADMIN -> findUserByUserId(userId); + default -> throw new CustomException(UserExceptionCode.INVALID_USERID); + }; + return UserInfoRes.fromEntity(user); + } + + private User findUserByUserId(Long userId){ + return userRepository.findById(userId) + .orElseThrow(()->new CustomException(UserExceptionCode.INVALID_USERID)); + } + + private User findGuestByGuestId(Long guestId){ + return Optional.ofNullable((User) redisUtil.getData(GUEST_KEY_PREFIX + guestId)) + .orElseThrow(()-> new CustomException(UserExceptionCode.INVALID_USERID)); + } }