From 98a57ce25659b8c934a2bf36941af931ba5394b0 Mon Sep 17 00:00:00 2001 From: tentenball Date: Fri, 19 Jul 2024 15:13:25 +0900 Subject: [PATCH 01/14] =?UTF-8?q?feat:=20=EC=9C=A0=EC=A0=80=EC=BB=A8?= =?UTF-8?q?=ED=8A=B8=EB=A1=A4=EB=9F=AC=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/gible/domain/user/controller/README.md | 0 .../domain/user/controller/UserController.java | 15 +++++++++++++++ 2 files changed, 15 insertions(+) delete mode 100644 src/main/java/gible/domain/user/controller/README.md create mode 100644 src/main/java/gible/domain/user/controller/UserController.java diff --git a/src/main/java/gible/domain/user/controller/README.md b/src/main/java/gible/domain/user/controller/README.md deleted file mode 100644 index e69de29..0000000 diff --git a/src/main/java/gible/domain/user/controller/UserController.java b/src/main/java/gible/domain/user/controller/UserController.java new file mode 100644 index 0000000..b71372a --- /dev/null +++ b/src/main/java/gible/domain/user/controller/UserController.java @@ -0,0 +1,15 @@ +package gible.domain.user.controller; + +import gible.domain.user.service.UserService; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/user") +public class UserController { + private final UserService userService; + + +} From 83c1a9be7e4063cd6a961582353b52417617db3a Mon Sep 17 00:00:00 2001 From: tentenball Date: Fri, 19 Jul 2024 15:25:37 +0900 Subject: [PATCH 02/14] =?UTF-8?q?feat:=20=EB=A7=88=EC=9D=B4=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=20=EA=B0=80=EC=A0=B8=EC=98=A4=EA=B8=B0=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../gible/domain/user/controller/UserController.java | 12 +++++++++++- src/main/java/gible/domain/user/dto/MyPageRes.java | 11 +++++++++++ .../java/gible/domain/user/service/UserService.java | 7 +++++++ 3 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 src/main/java/gible/domain/user/dto/MyPageRes.java diff --git a/src/main/java/gible/domain/user/controller/UserController.java b/src/main/java/gible/domain/user/controller/UserController.java index b71372a..0f74690 100644 --- a/src/main/java/gible/domain/user/controller/UserController.java +++ b/src/main/java/gible/domain/user/controller/UserController.java @@ -1,7 +1,12 @@ package gible.domain.user.controller; +import gible.domain.security.common.SecurityUserDetails; +import gible.domain.user.dto.MyPageRes; import gible.domain.user.service.UserService; import lombok.RequiredArgsConstructor; +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.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -11,5 +16,10 @@ public class UserController { private final UserService userService; - + @GetMapping("") + public ResponseEntity getMyPage( + @AuthenticationPrincipal SecurityUserDetails userDetails + ){ + return ResponseEntity.ok().body(userService.getMyPage(userDetails.getId())); + } } diff --git a/src/main/java/gible/domain/user/dto/MyPageRes.java b/src/main/java/gible/domain/user/dto/MyPageRes.java new file mode 100644 index 0000000..e774004 --- /dev/null +++ b/src/main/java/gible/domain/user/dto/MyPageRes.java @@ -0,0 +1,11 @@ +package gible.domain.user.dto; + +public record MyPageRes( + String email, + String nickname, + int point +) { + public static MyPageRes of(final String email, final String nickname, final int point) { + return new MyPageRes(email, nickname, point); + } +} diff --git a/src/main/java/gible/domain/user/service/UserService.java b/src/main/java/gible/domain/user/service/UserService.java index 514bc7a..a3e3494 100644 --- a/src/main/java/gible/domain/user/service/UserService.java +++ b/src/main/java/gible/domain/user/service/UserService.java @@ -1,5 +1,6 @@ package gible.domain.user.service; +import gible.domain.user.dto.MyPageRes; import gible.domain.user.entity.User; import gible.domain.user.repository.UserRepository; import gible.exception.CustomException; @@ -21,4 +22,10 @@ public User findById(UUID userId){ public User findByEmail(String email){ return userRepository.findByEmail(email).orElse(null); } + + public MyPageRes getMyPage(UUID userId) { + User user = findById(userId); + return MyPageRes.of(user.getEmail(), user.getNickname(), user.getPoint()); + } + } From ccf30ad57e7eb9a6c4b3fb306da7c782c30d2675 Mon Sep 17 00:00:00 2001 From: tentenball Date: Fri, 19 Jul 2024 15:36:24 +0900 Subject: [PATCH 03/14] =?UTF-8?q?feat:=20=EC=B0=B8=EC=97=AC=EC=9D=B4?= =?UTF-8?q?=EB=B2=A4=ED=8A=B8=20=EC=A1=B0=ED=9A=8C=20=EA=B5=AC=ED=98=84?= =?UTF-8?q?=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../gible/domain/user/controller/UserController.java | 10 ++++++++++ .../java/gible/domain/user/service/UserService.java | 8 +++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/main/java/gible/domain/user/controller/UserController.java b/src/main/java/gible/domain/user/controller/UserController.java index 0f74690..ace6d0b 100644 --- a/src/main/java/gible/domain/user/controller/UserController.java +++ b/src/main/java/gible/domain/user/controller/UserController.java @@ -1,5 +1,6 @@ package gible.domain.user.controller; +import gible.domain.event.dto.EventSummaryRes; import gible.domain.security.common.SecurityUserDetails; import gible.domain.user.dto.MyPageRes; import gible.domain.user.service.UserService; @@ -10,6 +11,8 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import java.util.List; + @RestController @RequiredArgsConstructor @RequestMapping("/user") @@ -22,4 +25,11 @@ public ResponseEntity getMyPage( ){ return ResponseEntity.ok().body(userService.getMyPage(userDetails.getId())); } + + @GetMapping("/participation-event") + public ResponseEntity> getParticipationEvent( + @AuthenticationPrincipal SecurityUserDetails userDetails + ){ + return ResponseEntity.ok().body(userService.getParticipationEvents(userDetails.getId())); + } } diff --git a/src/main/java/gible/domain/user/service/UserService.java b/src/main/java/gible/domain/user/service/UserService.java index a3e3494..301d49f 100644 --- a/src/main/java/gible/domain/user/service/UserService.java +++ b/src/main/java/gible/domain/user/service/UserService.java @@ -1,5 +1,7 @@ package gible.domain.user.service; +import gible.domain.event.dto.EventSummaryRes; +import gible.domain.event.repository.EventRepository; import gible.domain.user.dto.MyPageRes; import gible.domain.user.entity.User; import gible.domain.user.repository.UserRepository; @@ -8,13 +10,14 @@ import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import java.util.List; import java.util.UUID; @Service @RequiredArgsConstructor public class UserService { private final UserRepository userRepository; - + private final EventRepository eventRepository; public User findById(UUID userId){ return userRepository.findById(userId).orElseThrow(()-> new CustomException(ErrorType.USER_NOT_FOUND)); } @@ -28,4 +31,7 @@ public MyPageRes getMyPage(UUID userId) { return MyPageRes.of(user.getEmail(), user.getNickname(), user.getPoint()); } + public List getParticipationEvents(UUID userId) { + + } } From 32c78616e4638a816afd60f14e7d3f0472f745cc Mon Sep 17 00:00:00 2001 From: tentenball Date: Fri, 19 Jul 2024 16:32:17 +0900 Subject: [PATCH 04/14] =?UTF-8?q?feat:=20=EC=9D=B4=EB=B2=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=B0=B8=EC=97=AC=EB=AA=A9=EB=A1=9D=20=EC=A1=B0=ED=9A=8C=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/ParticipateRepository.java | 13 +++++++++++++ .../domain/participate/repository/README.md | 0 .../gible/domain/user/service/UserService.java | 16 ++++++++++------ 3 files changed, 23 insertions(+), 6 deletions(-) create mode 100644 src/main/java/gible/domain/participate/repository/ParticipateRepository.java delete mode 100644 src/main/java/gible/domain/participate/repository/README.md diff --git a/src/main/java/gible/domain/participate/repository/ParticipateRepository.java b/src/main/java/gible/domain/participate/repository/ParticipateRepository.java new file mode 100644 index 0000000..9b3a7d2 --- /dev/null +++ b/src/main/java/gible/domain/participate/repository/ParticipateRepository.java @@ -0,0 +1,13 @@ +package gible.domain.participate.repository; + +import gible.domain.participate.entity.Participate; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.List; +import java.util.UUID; + +@Repository +public interface ParticipateRepository extends JpaRepository { + List findByUser_Id(UUID userId); +} diff --git a/src/main/java/gible/domain/participate/repository/README.md b/src/main/java/gible/domain/participate/repository/README.md deleted file mode 100644 index e69de29..0000000 diff --git a/src/main/java/gible/domain/user/service/UserService.java b/src/main/java/gible/domain/user/service/UserService.java index 301d49f..89c3595 100644 --- a/src/main/java/gible/domain/user/service/UserService.java +++ b/src/main/java/gible/domain/user/service/UserService.java @@ -1,7 +1,8 @@ package gible.domain.user.service; import gible.domain.event.dto.EventSummaryRes; -import gible.domain.event.repository.EventRepository; +import gible.domain.participate.entity.Participate; +import gible.domain.participate.repository.ParticipateRepository; import gible.domain.user.dto.MyPageRes; import gible.domain.user.entity.User; import gible.domain.user.repository.UserRepository; @@ -17,12 +18,13 @@ @RequiredArgsConstructor public class UserService { private final UserRepository userRepository; - private final EventRepository eventRepository; - public User findById(UUID userId){ - return userRepository.findById(userId).orElseThrow(()-> new CustomException(ErrorType.USER_NOT_FOUND)); + private final ParticipateRepository participateRepository; + + public User findById(UUID userId) { + return userRepository.findById(userId).orElseThrow(() -> new CustomException(ErrorType.USER_NOT_FOUND)); } - public User findByEmail(String email){ + public User findByEmail(String email) { return userRepository.findByEmail(email).orElse(null); } @@ -32,6 +34,8 @@ public MyPageRes getMyPage(UUID userId) { } public List getParticipationEvents(UUID userId) { - + return participateRepository.findByUser_Id(userId) + .stream().map(Participate::getEvent).toList() + .stream().map(EventSummaryRes::fromEntity).toList(); } } From 1791262b2dfd8f3e3ebbe022cc806a4f02982d22 Mon Sep 17 00:00:00 2001 From: tentenball Date: Fri, 19 Jul 2024 16:45:58 +0900 Subject: [PATCH 05/14] =?UTF-8?q?refact:=20transactional=20=EC=96=B4?= =?UTF-8?q?=EB=85=B8=ED=85=8C=EC=9D=B4=EC=85=98=20=EC=B6=94=EA=B0=80(?= =?UTF-8?q?=EB=AA=A8=EB=93=A0=20=EB=A9=94=EC=84=9C=EB=93=9C=20readOnly)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/gible/domain/user/service/UserService.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/gible/domain/user/service/UserService.java b/src/main/java/gible/domain/user/service/UserService.java index 89c3595..4457aaa 100644 --- a/src/main/java/gible/domain/user/service/UserService.java +++ b/src/main/java/gible/domain/user/service/UserService.java @@ -10,12 +10,14 @@ import gible.exception.error.ErrorType; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import java.util.List; import java.util.UUID; @Service @RequiredArgsConstructor +@Transactional(readOnly = true) public class UserService { private final UserRepository userRepository; private final ParticipateRepository participateRepository; From e001d8b07c8e0df3aeb4adbc8eafaf46404c7629 Mon Sep 17 00:00:00 2001 From: tentenball Date: Fri, 19 Jul 2024 17:06:49 +0900 Subject: [PATCH 06/14] =?UTF-8?q?feat:=20auth=20=ED=86=A0=ED=81=B0?= =?UTF-8?q?=EC=9E=AC=EB=B0=9C=EA=B8=89=20=EB=A1=9C=EC=A7=81=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/controller/AuthController.java | 6 ++++++ .../gible/domain/auth/dto/RenewTokenReq.java | 9 +++++++++ .../domain/auth/service/AuthService.java | 19 ++++++++++++++++--- 3 files changed, 31 insertions(+), 3 deletions(-) create mode 100644 src/main/java/gible/domain/auth/dto/RenewTokenReq.java diff --git a/src/main/java/gible/domain/auth/controller/AuthController.java b/src/main/java/gible/domain/auth/controller/AuthController.java index c63178f..3a5af20 100644 --- a/src/main/java/gible/domain/auth/controller/AuthController.java +++ b/src/main/java/gible/domain/auth/controller/AuthController.java @@ -1,6 +1,7 @@ package gible.domain.auth.controller; +import gible.domain.auth.dto.RenewTokenReq; import gible.domain.auth.dto.SignInReq; import gible.domain.auth.dto.SignInRes; import gible.domain.auth.service.AuthService; @@ -23,4 +24,9 @@ public ResponseEntity login(@Valid @RequestBody SignInReq signInReq) return ResponseEntity.ok().body(authService.login(signInReq)); } + @PostMapping("/token") + public ResponseEntity renewToken(@Valid @RequestBody RenewTokenReq renewTokenReq) { + return ResponseEntity.ok().body(authService.renewToken(renewTokenReq)); + } + } diff --git a/src/main/java/gible/domain/auth/dto/RenewTokenReq.java b/src/main/java/gible/domain/auth/dto/RenewTokenReq.java new file mode 100644 index 0000000..cddfcf7 --- /dev/null +++ b/src/main/java/gible/domain/auth/dto/RenewTokenReq.java @@ -0,0 +1,9 @@ +package gible.domain.auth.dto; + +import jakarta.validation.constraints.NotBlank; + +public record RenewTokenReq ( + @NotBlank(message = "리프레시 토큰은 필수 작성 항목입니다.") + String RefreshToken +){ +} diff --git a/src/main/java/gible/domain/auth/service/AuthService.java b/src/main/java/gible/domain/auth/service/AuthService.java index 06bf5e4..3576744 100644 --- a/src/main/java/gible/domain/auth/service/AuthService.java +++ b/src/main/java/gible/domain/auth/service/AuthService.java @@ -1,6 +1,7 @@ package gible.domain.auth.service; import gible.domain.auth.dto.KakaoUserInfo; +import gible.domain.auth.dto.RenewTokenReq; import gible.domain.auth.dto.SignInReq; import gible.domain.auth.dto.SignInRes; @@ -12,6 +13,8 @@ import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import java.util.UUID; + @Service @RequiredArgsConstructor public class AuthService { @@ -24,14 +27,24 @@ public SignInRes login(SignInReq signInReq) { if(user == null) { throw new CustomException(ErrorType.NEED_SIGNUP); } - String accessToken = jwtTokenProvider.generateAccessToken(user); - String refreshToken = jwtTokenProvider.generateRefreshToken(user); + return generateSignInRes(user); + } - return SignInRes.of(accessToken, refreshToken); + public SignInRes renewToken(RenewTokenReq renewTokenReq){ + UUID uuid = UUID.randomUUID(); //레디스 로직수정필요 + User user = userService.findById(uuid); //레디스 로직수정필요 + return generateSignInRes(user); } private KakaoUserInfo getUserInfo(SignInReq signInReq) { String accessToken = kakaoService.getAccessToken(signInReq); return kakaoService.getUserInfo(accessToken); } + + private SignInRes generateSignInRes(User user){ + String accessToken = jwtTokenProvider.generateAccessToken(user); + String refreshToken = jwtTokenProvider.generateRefreshToken(user); + + return SignInRes.of(accessToken, refreshToken); + } } From 2939cf2508670e0c290ee214a97fd734f9223edf Mon Sep 17 00:00:00 2001 From: tentenball Date: Fri, 19 Jul 2024 22:03:48 +0900 Subject: [PATCH 07/14] =?UTF-8?q?refact:=20ErrorDto,=20ApiUtil=20=EC=9D=B4?= =?UTF-8?q?=EB=A6=84=20=EB=B3=80=EA=B2=BD(ErrorRes,=20SuccessRes)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../donation/controller/DonationController.java | 4 ++-- .../domain/event/controller/EventController.java | 11 ++++++----- .../gible/domain/post/controller/PostController.java | 8 ++++---- .../java/gible/exception/GlobalExceptionHandler.java | 6 +++--- src/main/java/gible/exception/dto/ErrorDto.java | 11 ----------- src/main/java/gible/exception/dto/ErrorRes.java | 11 +++++++++++ .../global/util/api/{ApiUtil.java => SuccessRes.java} | 8 ++++---- 7 files changed, 30 insertions(+), 29 deletions(-) delete mode 100644 src/main/java/gible/exception/dto/ErrorDto.java create mode 100644 src/main/java/gible/exception/dto/ErrorRes.java rename src/main/java/gible/global/util/api/{ApiUtil.java => SuccessRes.java} (59%) diff --git a/src/main/java/gible/domain/donation/controller/DonationController.java b/src/main/java/gible/domain/donation/controller/DonationController.java index 08262fa..e72fcc2 100644 --- a/src/main/java/gible/domain/donation/controller/DonationController.java +++ b/src/main/java/gible/domain/donation/controller/DonationController.java @@ -4,7 +4,7 @@ import gible.domain.donation.dto.DonationReq; import gible.domain.donation.dto.DonationSenderInfoRes; import gible.domain.donation.service.DonationService; -import gible.global.util.api.ApiUtil; +import gible.global.util.api.SuccessRes; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; @@ -28,7 +28,7 @@ public ResponseEntity donate(@Valid @RequestBody DonationReq donationReq, @AuthenticationPrincipal UserDetails userDetails) { donationService.donate(donationReq, userDetails.getUsername(), postId); - return ResponseEntity.ok(ApiUtil.from("기부 성공.")); + return ResponseEntity.ok(SuccessRes.from("기부 성공.")); } /* 게시글에 대한 기부자 목록 불러오기 */ diff --git a/src/main/java/gible/domain/event/controller/EventController.java b/src/main/java/gible/domain/event/controller/EventController.java index 932ec34..b152e53 100644 --- a/src/main/java/gible/domain/event/controller/EventController.java +++ b/src/main/java/gible/domain/event/controller/EventController.java @@ -4,7 +4,7 @@ import gible.domain.event.dto.EventReq; import gible.domain.event.dto.EventSummaryRes; import gible.domain.event.service.EventService; -import gible.global.util.api.ApiUtil; +import gible.global.util.api.SuccessRes; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; @@ -19,7 +19,8 @@ @RequiredArgsConstructor @RequestMapping("/event") @RestController -public class EventController { +public class +EventController { private final EventService eventService; @@ -28,7 +29,7 @@ public class EventController { public ResponseEntity saveEvent(@Valid @RequestBody EventReq eventReq) { eventService.saveEvent(eventReq); - return ResponseEntity.created(null).body(ApiUtil.from("이벤트 작성 성공.")); + return ResponseEntity.created(null).body(SuccessRes.from("이벤트 작성 성공.")); } /* 이벤트 목록 조회 */ @@ -52,7 +53,7 @@ public ResponseEntity updateEvent(@Valid @RequestBody EventReq updateEventReq @PathVariable UUID eventId) { eventService.updateEvent(updateEventReq, eventId); - return ResponseEntity.ok(ApiUtil.from("이벤트 수정 성공.")); + return ResponseEntity.ok(SuccessRes.from("이벤트 수정 성공.")); } /* 이벤트 삭제 */ @@ -60,6 +61,6 @@ public ResponseEntity updateEvent(@Valid @RequestBody EventReq updateEventReq public ResponseEntity deleteEvent(@PathVariable UUID eventId) { eventService.deleteEvent(eventId); - return ResponseEntity.ok(ApiUtil.from("이벤트 삭제 성공.")); + return ResponseEntity.ok(SuccessRes.from("이벤트 삭제 성공.")); } } diff --git a/src/main/java/gible/domain/post/controller/PostController.java b/src/main/java/gible/domain/post/controller/PostController.java index fb77fdf..10a8a55 100644 --- a/src/main/java/gible/domain/post/controller/PostController.java +++ b/src/main/java/gible/domain/post/controller/PostController.java @@ -4,7 +4,7 @@ import gible.domain.post.dto.PostReq; import gible.domain.post.dto.PostSummaryRes; import gible.domain.post.service.PostService; -import gible.global.util.api.ApiUtil; +import gible.global.util.api.SuccessRes; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; @@ -31,7 +31,7 @@ public ResponseEntity savePost(@Valid @RequestBody PostReq postReq, @AuthenticationPrincipal UserDetails userDetails) { postService.savePost(postReq, userDetails.getUsername()); - return ResponseEntity.created(null).body(ApiUtil.from("게시글 업로드 완료.")); + return ResponseEntity.created(null).body(SuccessRes.from("게시글 업로드 완료.")); } /* 게시글 목록 조회 + 검색 조회 */ @@ -59,7 +59,7 @@ public ResponseEntity updatePost(@Valid @RequestBody PostReq postReq, @PathVariable UUID postId) { postService.updatePost(postReq, postId); - return ResponseEntity.ok(ApiUtil.from("게시글 수정 완료.")); + return ResponseEntity.ok(SuccessRes.from("게시글 수정 완료.")); } /* 게시글 삭제 */ @@ -67,7 +67,7 @@ public ResponseEntity updatePost(@Valid @RequestBody PostReq postReq, public ResponseEntity deletePost(@PathVariable UUID postId) { postService.deletePost(postId); - return ResponseEntity.ok(ApiUtil.from("게시글 삭제 완료.")); + return ResponseEntity.ok(SuccessRes.from("게시글 삭제 완료.")); } } diff --git a/src/main/java/gible/exception/GlobalExceptionHandler.java b/src/main/java/gible/exception/GlobalExceptionHandler.java index 9f70cba..24b3819 100644 --- a/src/main/java/gible/exception/GlobalExceptionHandler.java +++ b/src/main/java/gible/exception/GlobalExceptionHandler.java @@ -1,7 +1,7 @@ package gible.exception; -import gible.exception.dto.ErrorDto; +import gible.exception.dto.ErrorRes; import gible.exception.error.ErrorType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -25,13 +25,13 @@ public class GlobalExceptionHandler { public ResponseEntity handle(CustomException ex){ ErrorType errortype = ex.getErrortype(); log.warn("Error occurred : [errorCode={}, message={}]", errortype.getStatus(), errortype.getMessage()); - return ResponseEntity.status(errortype.getStatus()).body(ErrorDto.of(errortype.getStatus(), errortype.getMessage())); + return ResponseEntity.status(errortype.getStatus()).body(ErrorRes.of(errortype.getStatus(), errortype.getMessage())); } /* 일반 예외 처리 */ @ExceptionHandler protected ResponseEntity customServerException(Exception ex) { - ErrorDto error = new ErrorDto(INTERNAL_SERVER_ERROR.getStatus(), INTERNAL_SERVER_ERROR.getMessage()); + ErrorRes error = new ErrorRes(INTERNAL_SERVER_ERROR.getStatus(), INTERNAL_SERVER_ERROR.getMessage()); log.warn("Error occurred : [errorCode={}, message={}]", error.status(), error.message()); return ResponseEntity.status(error.status()).body(error); } diff --git a/src/main/java/gible/exception/dto/ErrorDto.java b/src/main/java/gible/exception/dto/ErrorDto.java deleted file mode 100644 index b81f3c3..0000000 --- a/src/main/java/gible/exception/dto/ErrorDto.java +++ /dev/null @@ -1,11 +0,0 @@ -package gible.exception.dto; - -public record ErrorDto( - - int status, - String message -) { - public static ErrorDto of(int status, String message) { - return new ErrorDto(status, message); - } -} diff --git a/src/main/java/gible/exception/dto/ErrorRes.java b/src/main/java/gible/exception/dto/ErrorRes.java new file mode 100644 index 0000000..70ab871 --- /dev/null +++ b/src/main/java/gible/exception/dto/ErrorRes.java @@ -0,0 +1,11 @@ +package gible.exception.dto; + +public record ErrorRes( + + int status, + String message +) { + public static ErrorRes of(int status, String message) { + return new ErrorRes(status, message); + } +} diff --git a/src/main/java/gible/global/util/api/ApiUtil.java b/src/main/java/gible/global/util/api/SuccessRes.java similarity index 59% rename from src/main/java/gible/global/util/api/ApiUtil.java rename to src/main/java/gible/global/util/api/SuccessRes.java index df67931..1f1dd94 100644 --- a/src/main/java/gible/global/util/api/ApiUtil.java +++ b/src/main/java/gible/global/util/api/SuccessRes.java @@ -4,17 +4,17 @@ import lombok.Getter; @Getter -public class ApiUtil { +public class SuccessRes { private T response; @Builder - private ApiUtil(T response) { + private SuccessRes(T response) { this.response = response; } - public static ApiUtil from(T response) { - return ApiUtil.builder() + public static SuccessRes from(T response) { + return SuccessRes.builder() .response(response) .build(); } From eb8e312e1450a98862f9048066a392626a15966d Mon Sep 17 00:00:00 2001 From: tentenball Date: Fri, 19 Jul 2024 22:05:11 +0900 Subject: [PATCH 08/14] =?UTF-8?q?feat:=20=EB=A1=9C=EA=B7=B8=EC=95=84?= =?UTF-8?q?=EC=9B=83=20=EB=A1=9C=EC=A7=81=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../gible/domain/auth/controller/AuthController.java | 8 ++++++++ .../java/gible/domain/auth/service/AuthService.java | 6 ++++++ .../java/gible/domain/user/service/UserService.java | 10 +++++++++- 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/main/java/gible/domain/auth/controller/AuthController.java b/src/main/java/gible/domain/auth/controller/AuthController.java index 3a5af20..3ef6611 100644 --- a/src/main/java/gible/domain/auth/controller/AuthController.java +++ b/src/main/java/gible/domain/auth/controller/AuthController.java @@ -5,9 +5,12 @@ import gible.domain.auth.dto.SignInReq; import gible.domain.auth.dto.SignInRes; import gible.domain.auth.service.AuthService; +import gible.domain.security.common.SecurityUserDetails; +import gible.global.util.api.SuccessRes; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; +import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; @@ -24,6 +27,11 @@ public ResponseEntity login(@Valid @RequestBody SignInReq signInReq) return ResponseEntity.ok().body(authService.login(signInReq)); } + @PostMapping("logout") + public ResponseEntity logout(@AuthenticationPrincipal SecurityUserDetails userDetails){ + authService.logout(userDetails.getId()); + return ResponseEntity.ok().body(SuccessRes.from("로그아웃 성공")); + } @PostMapping("/token") public ResponseEntity renewToken(@Valid @RequestBody RenewTokenReq renewTokenReq) { return ResponseEntity.ok().body(authService.renewToken(renewTokenReq)); diff --git a/src/main/java/gible/domain/auth/service/AuthService.java b/src/main/java/gible/domain/auth/service/AuthService.java index 3576744..0bddbd5 100644 --- a/src/main/java/gible/domain/auth/service/AuthService.java +++ b/src/main/java/gible/domain/auth/service/AuthService.java @@ -36,10 +36,15 @@ public SignInRes renewToken(RenewTokenReq renewTokenReq){ return generateSignInRes(user); } + private KakaoUserInfo getUserInfo(SignInReq signInReq) { String accessToken = kakaoService.getAccessToken(signInReq); return kakaoService.getUserInfo(accessToken); } + public void logout(UUID userId) { + userService.deleteById(userId); + //레디스 리프레시토큰 삭제 로직 + } private SignInRes generateSignInRes(User user){ String accessToken = jwtTokenProvider.generateAccessToken(user); @@ -47,4 +52,5 @@ private SignInRes generateSignInRes(User user){ return SignInRes.of(accessToken, refreshToken); } + } diff --git a/src/main/java/gible/domain/user/service/UserService.java b/src/main/java/gible/domain/user/service/UserService.java index 4457aaa..4add7a9 100644 --- a/src/main/java/gible/domain/user/service/UserService.java +++ b/src/main/java/gible/domain/user/service/UserService.java @@ -17,27 +17,35 @@ @Service @RequiredArgsConstructor -@Transactional(readOnly = true) public class UserService { private final UserRepository userRepository; private final ParticipateRepository participateRepository; + @Transactional(readOnly = true) public User findById(UUID userId) { return userRepository.findById(userId).orElseThrow(() -> new CustomException(ErrorType.USER_NOT_FOUND)); } + @Transactional(readOnly = true) public User findByEmail(String email) { return userRepository.findByEmail(email).orElse(null); } + @Transactional(readOnly = true) public MyPageRes getMyPage(UUID userId) { User user = findById(userId); return MyPageRes.of(user.getEmail(), user.getNickname(), user.getPoint()); } + @Transactional(readOnly = true) public List getParticipationEvents(UUID userId) { return participateRepository.findByUser_Id(userId) .stream().map(Participate::getEvent).toList() .stream().map(EventSummaryRes::fromEntity).toList(); } + + @Transactional + public void deleteById(UUID userId) { + userRepository.deleteById(userId); + } } From e2bd75fc42a63556eae71836fbe2f18ab2a58fd2 Mon Sep 17 00:00:00 2001 From: tentenball Date: Fri, 19 Jul 2024 22:12:04 +0900 Subject: [PATCH 09/14] =?UTF-8?q?feat:=20=ED=9A=8C=EC=9B=90=EA=B0=80?= =?UTF-8?q?=EC=9E=85=20=EB=A1=9C=EC=A7=81=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../gible/domain/user/controller/UserController.java | 11 ++++++++--- .../java/gible/domain/user/service/UserService.java | 6 ++++++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/main/java/gible/domain/user/controller/UserController.java b/src/main/java/gible/domain/user/controller/UserController.java index ace6d0b..54693d9 100644 --- a/src/main/java/gible/domain/user/controller/UserController.java +++ b/src/main/java/gible/domain/user/controller/UserController.java @@ -3,13 +3,13 @@ import gible.domain.event.dto.EventSummaryRes; import gible.domain.security.common.SecurityUserDetails; import gible.domain.user.dto.MyPageRes; +import gible.domain.user.dto.SignUpReq; import gible.domain.user.service.UserService; +import gible.global.util.api.SuccessRes; import lombok.RequiredArgsConstructor; 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.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import java.util.List; @@ -19,6 +19,11 @@ public class UserController { private final UserService userService; + @PostMapping("/signUp") + public ResponseEntity SignUp(@RequestBody SignUpReq signUpReq){ + userService.signUp(signUpReq); + return ResponseEntity.ok().body(SuccessRes.from("회원가입 성공")); + } @GetMapping("") public ResponseEntity getMyPage( @AuthenticationPrincipal SecurityUserDetails userDetails diff --git a/src/main/java/gible/domain/user/service/UserService.java b/src/main/java/gible/domain/user/service/UserService.java index 4add7a9..477f958 100644 --- a/src/main/java/gible/domain/user/service/UserService.java +++ b/src/main/java/gible/domain/user/service/UserService.java @@ -4,6 +4,7 @@ import gible.domain.participate.entity.Participate; import gible.domain.participate.repository.ParticipateRepository; import gible.domain.user.dto.MyPageRes; +import gible.domain.user.dto.SignUpReq; import gible.domain.user.entity.User; import gible.domain.user.repository.UserRepository; import gible.exception.CustomException; @@ -48,4 +49,9 @@ public List getParticipationEvents(UUID userId) { public void deleteById(UUID userId) { userRepository.deleteById(userId); } + + @Transactional + public void signUp(SignUpReq signUpReq) { + userRepository.save(SignUpReq.toEntity(signUpReq)); + } } From 05571223c4c7b54d20a453c8ab145701ad404c74 Mon Sep 17 00:00:00 2001 From: tentenball Date: Fri, 19 Jul 2024 22:19:30 +0900 Subject: [PATCH 10/14] =?UTF-8?q?refact:=20=ED=9A=8C=EC=9B=90=EA=B0=80?= =?UTF-8?q?=EC=9E=85=20=EA=B2=80=EC=A6=9D=EB=A1=9C=EC=A7=81=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/gible/domain/user/dto/SignUpReq.java | 8 ++++---- .../java/gible/domain/user/repository/UserRepository.java | 2 ++ src/main/java/gible/domain/user/service/UserService.java | 5 ++++- src/main/java/gible/exception/error/ErrorType.java | 1 + 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/main/java/gible/domain/user/dto/SignUpReq.java b/src/main/java/gible/domain/user/dto/SignUpReq.java index 3e6eb6d..96c5967 100644 --- a/src/main/java/gible/domain/user/dto/SignUpReq.java +++ b/src/main/java/gible/domain/user/dto/SignUpReq.java @@ -5,13 +5,13 @@ import jakarta.validation.constraints.NotBlank; public record SignUpReq( - @NotBlank + @NotBlank(message = "닉네임 입력은 필수입니다.") String nickname, - @NotBlank + @NotBlank(message = "이메일 입력은 필수입니다.") String email, - @NotBlank + @NotBlank(message = "이름 입력은 필수입니다.") String name, - @NotBlank + @NotBlank(message = "전화번호 입력은 필수입니다.") String phoneNumber, String role ) { diff --git a/src/main/java/gible/domain/user/repository/UserRepository.java b/src/main/java/gible/domain/user/repository/UserRepository.java index 6ca42cc..ebb9d73 100644 --- a/src/main/java/gible/domain/user/repository/UserRepository.java +++ b/src/main/java/gible/domain/user/repository/UserRepository.java @@ -8,4 +8,6 @@ public interface UserRepository extends JpaRepository { Optional findByEmail(String email); + + boolean existsByEmail(String email); } diff --git a/src/main/java/gible/domain/user/service/UserService.java b/src/main/java/gible/domain/user/service/UserService.java index 477f958..bf4e399 100644 --- a/src/main/java/gible/domain/user/service/UserService.java +++ b/src/main/java/gible/domain/user/service/UserService.java @@ -9,6 +9,7 @@ import gible.domain.user.repository.UserRepository; import gible.exception.CustomException; import gible.exception.error.ErrorType; +import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -51,7 +52,9 @@ public void deleteById(UUID userId) { } @Transactional - public void signUp(SignUpReq signUpReq) { + public void signUp(@Valid SignUpReq signUpReq) { + if(userRepository.existsByEmail(signUpReq.email())) + throw new CustomException(ErrorType.ALREADY_EXISTS_USER); userRepository.save(SignUpReq.toEntity(signUpReq)); } } diff --git a/src/main/java/gible/exception/error/ErrorType.java b/src/main/java/gible/exception/error/ErrorType.java index d1b81b1..9c9c771 100644 --- a/src/main/java/gible/exception/error/ErrorType.java +++ b/src/main/java/gible/exception/error/ErrorType.java @@ -30,6 +30,7 @@ public enum ErrorType { // 이미 존재하는 값을 보냈을 때. ALREADY_PARTICIPATE_POST(409, "이미 해당 이벤트에 참여하였습니다."), + ALREADY_EXISTS_USER(409, "이미 존재하는 유저입니다."), // 서버 에러 INTERNAL_SERVER_ERROR(500, "서버 에러입니다. 서버 팀에 연락주세요."); From 3de95e08f60e131ffc2ee6a3eaa4aa1d886f89ef Mon Sep 17 00:00:00 2001 From: tentenball Date: Sat, 20 Jul 2024 03:11:45 +0900 Subject: [PATCH 11/14] =?UTF-8?q?feat,=20refact:=20=EB=A6=AC=ED=94=84?= =?UTF-8?q?=EB=A0=88=EC=8B=9C=ED=86=A0=ED=81=B0=EB=B0=9C=EA=B8=89=20?= =?UTF-8?q?=EC=BF=A0=ED=82=A4=20=EC=82=AC=EC=9A=A9,=20=EB=A1=9C=EA=B7=B8?= =?UTF-8?q?=EC=95=84=EC=9B=83=20=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95,?= =?UTF-8?q?=20=ED=9A=8C=EC=9B=90=ED=83=88=ED=87=B4=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/controller/AuthController.java | 25 ++++++++++++++++--- .../domain/auth/service/AuthService.java | 20 +++++++++++---- .../gible/domain/auth/util/CookieUtil.java | 21 ++++++++++++++++ 3 files changed, 57 insertions(+), 9 deletions(-) create mode 100644 src/main/java/gible/domain/auth/util/CookieUtil.java diff --git a/src/main/java/gible/domain/auth/controller/AuthController.java b/src/main/java/gible/domain/auth/controller/AuthController.java index 3ef6611..b7ff7a3 100644 --- a/src/main/java/gible/domain/auth/controller/AuthController.java +++ b/src/main/java/gible/domain/auth/controller/AuthController.java @@ -5,8 +5,10 @@ import gible.domain.auth.dto.SignInReq; import gible.domain.auth.dto.SignInRes; import gible.domain.auth.service.AuthService; +import gible.domain.auth.util.CookieUtil; import gible.domain.security.common.SecurityUserDetails; import gible.global.util.api.SuccessRes; +import jakarta.servlet.http.HttpServletResponse; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; @@ -16,6 +18,9 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import java.util.HashMap; +import java.util.Map; + @RestController @RequiredArgsConstructor @RequestMapping("/auth") @@ -23,18 +28,30 @@ public class AuthController { private final AuthService authService; @PostMapping("/kakaologin") - public ResponseEntity login(@Valid @RequestBody SignInReq signInReq) { - return ResponseEntity.ok().body(authService.login(signInReq)); + public ResponseEntity login(@Valid @RequestBody SignInReq signInReq, HttpServletResponse response) { + SignInRes signInRes = authService.login(signInReq); + CookieUtil.addRtkCookie(response, signInRes.refreshToken()); + + Map responseBody = new HashMap<>(); + responseBody.put("accessToken", signInRes.accessToken()); + + return ResponseEntity.ok(responseBody); } @PostMapping("logout") public ResponseEntity logout(@AuthenticationPrincipal SecurityUserDetails userDetails){ authService.logout(userDetails.getId()); - return ResponseEntity.ok().body(SuccessRes.from("로그아웃 성공")); + return ResponseEntity.ok(SuccessRes.from("로그아웃 성공")); } + @PostMapping("/token") public ResponseEntity renewToken(@Valid @RequestBody RenewTokenReq renewTokenReq) { - return ResponseEntity.ok().body(authService.renewToken(renewTokenReq)); + return ResponseEntity.ok().body(authService.reIssueToken(renewTokenReq)); } + @PostMapping("/withdraw") + public ResponseEntity withdraw(@AuthenticationPrincipal SecurityUserDetails userDetails) { + authService.withdraw(userDetails.getId()); + return ResponseEntity.ok(SuccessRes.from("유저삭제 성공")); + } } diff --git a/src/main/java/gible/domain/auth/service/AuthService.java b/src/main/java/gible/domain/auth/service/AuthService.java index 0bddbd5..0acb247 100644 --- a/src/main/java/gible/domain/auth/service/AuthService.java +++ b/src/main/java/gible/domain/auth/service/AuthService.java @@ -10,8 +10,10 @@ import gible.domain.user.service.UserService; import gible.exception.CustomException; import gible.exception.error.ErrorType; +import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import java.util.UUID; @@ -21,6 +23,8 @@ public class AuthService { private final UserService userService; private final KakaoService kakaoService; private final JwtTokenProvider jwtTokenProvider; + + @Transactional(readOnly = true) public SignInRes login(SignInReq signInReq) { KakaoUserInfo kakaoUserInfo = getUserInfo(signInReq); User user = userService.findByEmail(kakaoUserInfo.email()); @@ -30,21 +34,27 @@ public SignInRes login(SignInReq signInReq) { return generateSignInRes(user); } - public SignInRes renewToken(RenewTokenReq renewTokenReq){ + @Transactional(readOnly = true) + public SignInRes reIssueToken(RenewTokenReq renewTokenReq){ UUID uuid = UUID.randomUUID(); //레디스 로직수정필요 User user = userService.findById(uuid); //레디스 로직수정필요 return generateSignInRes(user); } + public void logout(UUID userId) { + //레디스 리프레시토큰 삭제 로직 + } + + @Transactional + public void withdraw(UUID userId) { + userService.deleteById(userId); + //파이어베이스 연동시 사진 삭제 로직 필요 + } private KakaoUserInfo getUserInfo(SignInReq signInReq) { String accessToken = kakaoService.getAccessToken(signInReq); return kakaoService.getUserInfo(accessToken); } - public void logout(UUID userId) { - userService.deleteById(userId); - //레디스 리프레시토큰 삭제 로직 - } private SignInRes generateSignInRes(User user){ String accessToken = jwtTokenProvider.generateAccessToken(user); diff --git a/src/main/java/gible/domain/auth/util/CookieUtil.java b/src/main/java/gible/domain/auth/util/CookieUtil.java new file mode 100644 index 0000000..56ac170 --- /dev/null +++ b/src/main/java/gible/domain/auth/util/CookieUtil.java @@ -0,0 +1,21 @@ +package gible.domain.auth.util; + + +import gible.domain.security.jwt.JwtTokenProvider; +import gible.domain.user.entity.User; +import jakarta.servlet.http.Cookie; +import jakarta.servlet.http.HttpServletResponse; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public class CookieUtil { + public static void addRtkCookie(HttpServletResponse response, String refreshToken) { + Cookie cookie = new Cookie("refreshToken", refreshToken); + + cookie.setMaxAge(7 * 24 * 60 * 60); + cookie.setSecure(true); + cookie.setHttpOnly(true); + cookie.setPath("/"); + response.addCookie(cookie); + } +} From d99648c50681314eabde56f63fb21514aa7a0451 Mon Sep 17 00:00:00 2001 From: tentenball Date: Sat, 20 Jul 2024 03:19:55 +0900 Subject: [PATCH 12/14] =?UTF-8?q?refact:=20phoneNumber,=20email=20?= =?UTF-8?q?=EA=B2=80=EC=A6=9D=EB=A1=9C=EC=A7=81=20=EA=B5=AC=ED=98=84,=20Va?= =?UTF-8?q?lid=EC=9C=84=EC=B9=98=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../user/controller/UserController.java | 18 ++++++++--------- .../java/gible/domain/user/dto/SignUpReq.java | 4 ++++ .../domain/user/service/UserService.java | 20 +++++++------------ 3 files changed, 19 insertions(+), 23 deletions(-) diff --git a/src/main/java/gible/domain/user/controller/UserController.java b/src/main/java/gible/domain/user/controller/UserController.java index 54693d9..11c1d94 100644 --- a/src/main/java/gible/domain/user/controller/UserController.java +++ b/src/main/java/gible/domain/user/controller/UserController.java @@ -1,18 +1,16 @@ package gible.domain.user.controller; -import gible.domain.event.dto.EventSummaryRes; import gible.domain.security.common.SecurityUserDetails; import gible.domain.user.dto.MyPageRes; import gible.domain.user.dto.SignUpReq; import gible.domain.user.service.UserService; import gible.global.util.api.SuccessRes; +import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.web.bind.annotation.*; -import java.util.List; - @RestController @RequiredArgsConstructor @RequestMapping("/user") @@ -20,7 +18,7 @@ public class UserController { private final UserService userService; @PostMapping("/signUp") - public ResponseEntity SignUp(@RequestBody SignUpReq signUpReq){ + public ResponseEntity SignUp(@Valid @RequestBody SignUpReq signUpReq){ userService.signUp(signUpReq); return ResponseEntity.ok().body(SuccessRes.from("회원가입 성공")); } @@ -31,10 +29,10 @@ public ResponseEntity getMyPage( return ResponseEntity.ok().body(userService.getMyPage(userDetails.getId())); } - @GetMapping("/participation-event") - public ResponseEntity> getParticipationEvent( - @AuthenticationPrincipal SecurityUserDetails userDetails - ){ - return ResponseEntity.ok().body(userService.getParticipationEvents(userDetails.getId())); - } +// @GetMapping("/participation-event") +// public ResponseEntity> getParticipationEvent( +// @AuthenticationPrincipal SecurityUserDetails userDetails +// ){ +// return ResponseEntity.ok().body(userService.getParticipationEvents(userDetails.getId())); +// } } diff --git a/src/main/java/gible/domain/user/dto/SignUpReq.java b/src/main/java/gible/domain/user/dto/SignUpReq.java index 96c5967..bccc906 100644 --- a/src/main/java/gible/domain/user/dto/SignUpReq.java +++ b/src/main/java/gible/domain/user/dto/SignUpReq.java @@ -2,16 +2,20 @@ import gible.domain.user.entity.Role; import gible.domain.user.entity.User; +import jakarta.validation.constraints.Email; import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Pattern; public record SignUpReq( @NotBlank(message = "닉네임 입력은 필수입니다.") String nickname, @NotBlank(message = "이메일 입력은 필수입니다.") + @Email(message = "올바른 이메일 형식이 아닙니다.") String email, @NotBlank(message = "이름 입력은 필수입니다.") String name, @NotBlank(message = "전화번호 입력은 필수입니다.") + @Pattern(regexp = "^010-\\d{4}-\\d{4}$", message = "전화번호 형식은 010-xxxx-xxxx이어야 합니다.") String phoneNumber, String role ) { diff --git a/src/main/java/gible/domain/user/service/UserService.java b/src/main/java/gible/domain/user/service/UserService.java index bf4e399..8bfe489 100644 --- a/src/main/java/gible/domain/user/service/UserService.java +++ b/src/main/java/gible/domain/user/service/UserService.java @@ -1,27 +1,21 @@ package gible.domain.user.service; -import gible.domain.event.dto.EventSummaryRes; -import gible.domain.participate.entity.Participate; -import gible.domain.participate.repository.ParticipateRepository; import gible.domain.user.dto.MyPageRes; import gible.domain.user.dto.SignUpReq; import gible.domain.user.entity.User; import gible.domain.user.repository.UserRepository; import gible.exception.CustomException; import gible.exception.error.ErrorType; -import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.List; import java.util.UUID; @Service @RequiredArgsConstructor public class UserService { private final UserRepository userRepository; - private final ParticipateRepository participateRepository; @Transactional(readOnly = true) public User findById(UUID userId) { @@ -39,12 +33,12 @@ public MyPageRes getMyPage(UUID userId) { return MyPageRes.of(user.getEmail(), user.getNickname(), user.getPoint()); } - @Transactional(readOnly = true) - public List getParticipationEvents(UUID userId) { - return participateRepository.findByUser_Id(userId) - .stream().map(Participate::getEvent).toList() - .stream().map(EventSummaryRes::fromEntity).toList(); - } +// @Transactional(readOnly = true) +// public List getParticipationEvents(UUID userId) { +// return participateRepository.findByUser_Id(userId) +// .stream().map(Participate::getEvent).toList() +// .stream().map(EventSummaryRes::fromEntity).toList(); +// } @Transactional public void deleteById(UUID userId) { @@ -52,7 +46,7 @@ public void deleteById(UUID userId) { } @Transactional - public void signUp(@Valid SignUpReq signUpReq) { + public void signUp(SignUpReq signUpReq) { if(userRepository.existsByEmail(signUpReq.email())) throw new CustomException(ErrorType.ALREADY_EXISTS_USER); userRepository.save(SignUpReq.toEntity(signUpReq)); From c61161f91a3015b88e998e752d3699bfaa8579dc Mon Sep 17 00:00:00 2001 From: tentenball Date: Sun, 21 Jul 2024 21:18:55 +0900 Subject: [PATCH 13/14] =?UTF-8?q?refact:=20cookie=20=EC=82=AC=EC=9A=A9?= =?UTF-8?q?=EB=B2=95=20=EC=88=98=EC=A0=95,=20samesite=EB=AC=B8=EC=A0=9C=20?= =?UTF-8?q?=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/gible/config/SecurityConfig.java | 2 +- .../auth/controller/AuthController.java | 9 ++++-- .../gible/domain/auth/util/CookieUtil.java | 28 +++++++++---------- .../controller/ParticipateController.java | 4 +-- .../domain/security/jwt/JwtTokenProvider.java | 4 +-- .../exception/GlobalExceptionHandler.java | 4 +-- src/main/resources/application.yml | 2 ++ 7 files changed, 29 insertions(+), 24 deletions(-) diff --git a/src/main/java/gible/config/SecurityConfig.java b/src/main/java/gible/config/SecurityConfig.java index 73bc026..a51ad0e 100644 --- a/src/main/java/gible/config/SecurityConfig.java +++ b/src/main/java/gible/config/SecurityConfig.java @@ -21,7 +21,7 @@ protected SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exce httpSecurity.csrf(AbstractHttpConfigurer::disable) .authorizeHttpRequests(authorizeHttpRequests -> authorizeHttpRequests.requestMatchers( - "/auth/kakao", + "/auth/kakaologin", "/auth/token",//라우팅 아직 설정x "/swagger-resources/**", "/swagger-ui/**", diff --git a/src/main/java/gible/domain/auth/controller/AuthController.java b/src/main/java/gible/domain/auth/controller/AuthController.java index b7ff7a3..7d2d480 100644 --- a/src/main/java/gible/domain/auth/controller/AuthController.java +++ b/src/main/java/gible/domain/auth/controller/AuthController.java @@ -11,6 +11,7 @@ import jakarta.servlet.http.HttpServletResponse; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseCookie; import org.springframework.http.ResponseEntity; import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.web.bind.annotation.PostMapping; @@ -26,16 +27,18 @@ @RequestMapping("/auth") public class AuthController { private final AuthService authService; + private final CookieUtil cookieUtil; @PostMapping("/kakaologin") - public ResponseEntity login(@Valid @RequestBody SignInReq signInReq, HttpServletResponse response) { + public ResponseEntity login(@Valid @RequestBody SignInReq signInReq) { SignInRes signInRes = authService.login(signInReq); - CookieUtil.addRtkCookie(response, signInRes.refreshToken()); Map responseBody = new HashMap<>(); responseBody.put("accessToken", signInRes.accessToken()); - return ResponseEntity.ok(responseBody); + return ResponseEntity.ok().header("Set-Cookie", + cookieUtil.addRtkCookie("refreshToken", signInRes.refreshToken()).toString()) + .body(responseBody); } @PostMapping("logout") diff --git a/src/main/java/gible/domain/auth/util/CookieUtil.java b/src/main/java/gible/domain/auth/util/CookieUtil.java index 56ac170..5f6f009 100644 --- a/src/main/java/gible/domain/auth/util/CookieUtil.java +++ b/src/main/java/gible/domain/auth/util/CookieUtil.java @@ -1,21 +1,21 @@ package gible.domain.auth.util; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.ResponseCookie; +import org.springframework.stereotype.Component; -import gible.domain.security.jwt.JwtTokenProvider; -import gible.domain.user.entity.User; -import jakarta.servlet.http.Cookie; -import jakarta.servlet.http.HttpServletResponse; -import lombok.RequiredArgsConstructor; - -@RequiredArgsConstructor +@Component public class CookieUtil { - public static void addRtkCookie(HttpServletResponse response, String refreshToken) { - Cookie cookie = new Cookie("refreshToken", refreshToken); + @Value("${cookie.refresh-expiration}") + private int REFRESH_EXPIRATION; - cookie.setMaxAge(7 * 24 * 60 * 60); - cookie.setSecure(true); - cookie.setHttpOnly(true); - cookie.setPath("/"); - response.addCookie(cookie); + public ResponseCookie addRtkCookie(String key, String value) { + return ResponseCookie.from(key, value) + .maxAge(REFRESH_EXPIRATION) + .secure(true) + .httpOnly(true) + .path("/") + .sameSite("None") + .build(); } } diff --git a/src/main/java/gible/domain/participate/controller/ParticipateController.java b/src/main/java/gible/domain/participate/controller/ParticipateController.java index f1f2590..ce9d2e3 100644 --- a/src/main/java/gible/domain/participate/controller/ParticipateController.java +++ b/src/main/java/gible/domain/participate/controller/ParticipateController.java @@ -3,7 +3,7 @@ import gible.domain.participate.dto.ParticipationEventRes; import gible.domain.participate.service.ParticipateService; import gible.domain.security.common.SecurityUserDetails; -import gible.global.util.api.ApiUtil; +import gible.global.util.api.SuccessRes; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.security.core.annotation.AuthenticationPrincipal; @@ -27,7 +27,7 @@ public ResponseEntity participationEvent(@AuthenticationPrincipal SecurityUse @PathVariable UUID eventId) { participateService.participationEvent(userDetails.getId(), eventId); - return ResponseEntity.ok(ApiUtil.from("참여 완료.")); + return ResponseEntity.ok(SuccessRes.from("참여 완료.")); } /* 사용자가 참여한 이벤트 목록 조회하기 */ diff --git a/src/main/java/gible/domain/security/jwt/JwtTokenProvider.java b/src/main/java/gible/domain/security/jwt/JwtTokenProvider.java index cdb331d..c3d1636 100644 --- a/src/main/java/gible/domain/security/jwt/JwtTokenProvider.java +++ b/src/main/java/gible/domain/security/jwt/JwtTokenProvider.java @@ -54,11 +54,11 @@ public String createToken(String email, Map claims, Long expirat .compact(); } - protected Claims parseClaims(String accessToken){ + public Claims parseClaims(String token){ return Jwts.parser() .verifyWith(jwtConfig.getSecretKey()) .build() - .parseSignedClaims(accessToken) + .parseSignedClaims(token) .getPayload(); } } diff --git a/src/main/java/gible/exception/GlobalExceptionHandler.java b/src/main/java/gible/exception/GlobalExceptionHandler.java index 24b3819..baa6c61 100644 --- a/src/main/java/gible/exception/GlobalExceptionHandler.java +++ b/src/main/java/gible/exception/GlobalExceptionHandler.java @@ -24,7 +24,7 @@ public class GlobalExceptionHandler { @ExceptionHandler(CustomException.class) public ResponseEntity handle(CustomException ex){ ErrorType errortype = ex.getErrortype(); - log.warn("Error occurred : [errorCode={}, message={}]", errortype.getStatus(), errortype.getMessage()); + log.error("Error occurred : [errorCode={}, message={}]", errortype.getStatus(), errortype.getMessage()); return ResponseEntity.status(errortype.getStatus()).body(ErrorRes.of(errortype.getStatus(), errortype.getMessage())); } @@ -32,7 +32,7 @@ public ResponseEntity handle(CustomException ex){ @ExceptionHandler protected ResponseEntity customServerException(Exception ex) { ErrorRes error = new ErrorRes(INTERNAL_SERVER_ERROR.getStatus(), INTERNAL_SERVER_ERROR.getMessage()); - log.warn("Error occurred : [errorCode={}, message={}]", error.status(), error.message()); + log.error("Error occurred : [errorCode={}, message={}]", error.status(), error.message()); return ResponseEntity.status(error.status()).body(error); } diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 28e0bd4..e5fb786 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -20,6 +20,8 @@ jwt: access-expiration: ${JWT_ACCESS_EXPIRATION} refresh-expiration: ${JWT_REFRESH_EXPIRATION} issuer: ${JWT_ISSUER} +cookie: + refresh-expiration: ${COOKIE_REFRESH_EXPIRATION} oauth2: kakao: tokenUri: https://kauth.kakao.com/oauth/token From ae8d62e3aa8fbad14ed2573477208c4e7a1d9c8b Mon Sep 17 00:00:00 2001 From: tentenball Date: Sun, 21 Jul 2024 21:50:46 +0900 Subject: [PATCH 14/14] =?UTF-8?q?refact:=20=ED=86=A0=ED=81=B0=20=EC=9E=AC?= =?UTF-8?q?=EB=B0=9C=EA=B8=89=20=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/controller/AuthController.java | 12 ++----- .../domain/auth/service/AuthService.java | 22 +++++++------ .../domain/security/jwt/JwtTokenProvider.java | 33 ++++++++++--------- .../java/gible/exception/error/ErrorType.java | 4 +-- 4 files changed, 35 insertions(+), 36 deletions(-) diff --git a/src/main/java/gible/domain/auth/controller/AuthController.java b/src/main/java/gible/domain/auth/controller/AuthController.java index 7d2d480..a4b97f6 100644 --- a/src/main/java/gible/domain/auth/controller/AuthController.java +++ b/src/main/java/gible/domain/auth/controller/AuthController.java @@ -1,23 +1,17 @@ package gible.domain.auth.controller; -import gible.domain.auth.dto.RenewTokenReq; import gible.domain.auth.dto.SignInReq; import gible.domain.auth.dto.SignInRes; import gible.domain.auth.service.AuthService; import gible.domain.auth.util.CookieUtil; import gible.domain.security.common.SecurityUserDetails; import gible.global.util.api.SuccessRes; -import jakarta.servlet.http.HttpServletResponse; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; -import org.springframework.http.ResponseCookie; import org.springframework.http.ResponseEntity; import org.springframework.security.core.annotation.AuthenticationPrincipal; -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.RestController; +import org.springframework.web.bind.annotation.*; import java.util.HashMap; import java.util.Map; @@ -48,8 +42,8 @@ public ResponseEntity logout(@AuthenticationPrincipal SecurityUserDetails use } @PostMapping("/token") - public ResponseEntity renewToken(@Valid @RequestBody RenewTokenReq renewTokenReq) { - return ResponseEntity.ok().body(authService.reIssueToken(renewTokenReq)); + public ResponseEntity reissueToken(@CookieValue("refreshToken") String refreshToken){ + return ResponseEntity.ok().body(authService.reissueToken(refreshToken)); } @PostMapping("/withdraw") diff --git a/src/main/java/gible/domain/auth/service/AuthService.java b/src/main/java/gible/domain/auth/service/AuthService.java index 0acb247..6af19f0 100644 --- a/src/main/java/gible/domain/auth/service/AuthService.java +++ b/src/main/java/gible/domain/auth/service/AuthService.java @@ -1,7 +1,6 @@ package gible.domain.auth.service; import gible.domain.auth.dto.KakaoUserInfo; -import gible.domain.auth.dto.RenewTokenReq; import gible.domain.auth.dto.SignInReq; import gible.domain.auth.dto.SignInRes; @@ -10,7 +9,7 @@ import gible.domain.user.service.UserService; import gible.exception.CustomException; import gible.exception.error.ErrorType; -import jakarta.servlet.http.HttpServletRequest; +import io.jsonwebtoken.Claims; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -31,14 +30,17 @@ public SignInRes login(SignInReq signInReq) { if(user == null) { throw new CustomException(ErrorType.NEED_SIGNUP); } - return generateSignInRes(user); + return generateSignInRes(user.getEmail(), user.getId(), user.getRole().toString()); } @Transactional(readOnly = true) - public SignInRes reIssueToken(RenewTokenReq renewTokenReq){ - UUID uuid = UUID.randomUUID(); //레디스 로직수정필요 - User user = userService.findById(uuid); //레디스 로직수정필요 - return generateSignInRes(user); + public SignInRes reissueToken(String refreshToken){ + Claims claims = jwtTokenProvider.parseClaims(refreshToken); + return generateSignInRes( + claims.getSubject(), + UUID.fromString(claims.get("userId", String.class)), + claims.get("role", String.class) + ); } public void logout(UUID userId) { @@ -56,9 +58,9 @@ private KakaoUserInfo getUserInfo(SignInReq signInReq) { return kakaoService.getUserInfo(accessToken); } - private SignInRes generateSignInRes(User user){ - String accessToken = jwtTokenProvider.generateAccessToken(user); - String refreshToken = jwtTokenProvider.generateRefreshToken(user); + private SignInRes generateSignInRes(String email, UUID userId, String role){ + String accessToken = jwtTokenProvider.generateAccessToken(email, userId, role); + String refreshToken = jwtTokenProvider.generateRefreshToken(email, userId, role); return SignInRes.of(accessToken, refreshToken); } diff --git a/src/main/java/gible/domain/security/jwt/JwtTokenProvider.java b/src/main/java/gible/domain/security/jwt/JwtTokenProvider.java index c3d1636..41999fb 100644 --- a/src/main/java/gible/domain/security/jwt/JwtTokenProvider.java +++ b/src/main/java/gible/domain/security/jwt/JwtTokenProvider.java @@ -2,8 +2,6 @@ import gible.config.JwtConfig; -import gible.domain.user.entity.User; -import gible.domain.user.service.UserService; import gible.exception.CustomException; import gible.exception.error.ErrorType; import io.jsonwebtoken.Claims; @@ -19,29 +17,27 @@ @RequiredArgsConstructor public class JwtTokenProvider { private final JwtConfig jwtConfig; - private final UserService userService; public boolean validateToken(String token) { Claims claims = parseClaims(token); - if(userService.findById(claims.get("auth", UUID.class)) == null){ - throw new CustomException(ErrorType.USER_NOT_FOUND); + if(claims == null){ + throw new CustomException(ErrorType.INVALID_TOKEN); + } + if(claims.getExpiration().before(new Date())){ + throw new CustomException(ErrorType.TOKEN_EXPIRED); } return !claims.getExpiration().before(new Date()); } - public String generateAccessToken(User user) { - Map claims = new HashMap<>(); - claims.put("userId", user.getId()); - claims.put("role", user.getRole()); - return createToken(user.getEmail(), claims, jwtConfig.getAccessExpiration()); + public String generateAccessToken(String email, UUID userId, String role) { + Map claims = createClaims(userId, role); + return createToken(email, claims, jwtConfig.getAccessExpiration()); } - public String generateRefreshToken(User user) { - Map claims = new HashMap<>(); - claims.put("userId", user.getId()); - claims.put("role", user.getRole()); - return createToken(user.getEmail(), claims, jwtConfig.getRefreshExpiration()); + public String generateRefreshToken(String email, UUID userId, String role) { + Map claims = createClaims(userId, role); + return createToken(email, claims, jwtConfig.getRefreshExpiration()); } public String createToken(String email, Map claims, Long expiration) { @@ -61,4 +57,11 @@ public Claims parseClaims(String token){ .parseSignedClaims(token) .getPayload(); } + + private static Map createClaims(UUID userId, String role) { + Map claims = new HashMap<>(); + claims.put("userId", userId); + claims.put("role", role); + return claims; + } } diff --git a/src/main/java/gible/exception/error/ErrorType.java b/src/main/java/gible/exception/error/ErrorType.java index 9c9c771..df93e28 100644 --- a/src/main/java/gible/exception/error/ErrorType.java +++ b/src/main/java/gible/exception/error/ErrorType.java @@ -9,8 +9,8 @@ public enum ErrorType { // 인증이 되어 있지 않을 때. UNAUTHORIZED(401, "접근 권한이 없습니다."), - ACCESS_TOKEN_EXPIRED(401, "Access Token이 만료되었습니다."), - INVALID_ACCESS_TOKEN(401, "Access Token이 잘못되었습니다."), + TOKEN_EXPIRED(401, "Token이 만료되었습니다."), + INVALID_TOKEN(401, "Token이 손실되었습니다."), SOCIAL_LOGIN_FAILED(401, "소셜로그인 오류"), NEED_SIGNUP(510, "닉네임 입력이 필요합니다."), // AccessToken 관련 오류