diff --git a/backend/src/main/java/com/funeat/auth/dto/LoginRequest.java b/backend/src/main/java/com/funeat/auth/dto/LoginInfo.java similarity index 67% rename from backend/src/main/java/com/funeat/auth/dto/LoginRequest.java rename to backend/src/main/java/com/funeat/auth/dto/LoginInfo.java index 0479c3932..2987c111a 100644 --- a/backend/src/main/java/com/funeat/auth/dto/LoginRequest.java +++ b/backend/src/main/java/com/funeat/auth/dto/LoginInfo.java @@ -1,10 +1,10 @@ package com.funeat.auth.dto; -public class LoginRequest { +public class LoginInfo { private final Long id; - public LoginRequest(final Long id) { + public LoginInfo(final Long id) { this.id = id; } diff --git a/backend/src/main/java/com/funeat/auth/presentation/AuthApiController.java b/backend/src/main/java/com/funeat/auth/presentation/AuthApiController.java index a1d7a9c2a..4abaf9555 100644 --- a/backend/src/main/java/com/funeat/auth/presentation/AuthApiController.java +++ b/backend/src/main/java/com/funeat/auth/presentation/AuthApiController.java @@ -1,7 +1,7 @@ package com.funeat.auth.presentation; import com.funeat.auth.application.AuthService; -import com.funeat.auth.dto.LoginRequest; +import com.funeat.auth.dto.LoginInfo; import com.funeat.auth.dto.SignUserDto; import com.funeat.auth.util.AuthenticationPrincipal; import java.net.URI; @@ -47,7 +47,7 @@ public ResponseEntity loginAuthorizeUser(@RequestParam("code") final Strin } @GetMapping("/api/logout") - public ResponseEntity logout(@AuthenticationPrincipal final LoginRequest loginRequest, + public ResponseEntity logout(@AuthenticationPrincipal final LoginInfo loginInfo, final HttpServletRequest request) { request.getSession().removeAttribute("member"); diff --git a/backend/src/main/java/com/funeat/auth/presentation/AuthController.java b/backend/src/main/java/com/funeat/auth/presentation/AuthController.java index 3141f110d..eb65e8be4 100644 --- a/backend/src/main/java/com/funeat/auth/presentation/AuthController.java +++ b/backend/src/main/java/com/funeat/auth/presentation/AuthController.java @@ -1,6 +1,6 @@ package com.funeat.auth.presentation; -import com.funeat.auth.dto.LoginRequest; +import com.funeat.auth.dto.LoginInfo; import com.funeat.auth.util.AuthenticationPrincipal; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.responses.ApiResponse; @@ -35,5 +35,5 @@ public interface AuthController { description = "로그아웃 성공." ) @GetMapping - ResponseEntity logout(@AuthenticationPrincipal LoginRequest loginRequest, HttpServletRequest request); + ResponseEntity logout(@AuthenticationPrincipal LoginInfo loginInfo, HttpServletRequest request); } diff --git a/backend/src/main/java/com/funeat/auth/util/AuthArgumentResolver.java b/backend/src/main/java/com/funeat/auth/util/AuthArgumentResolver.java index fe7ed3628..3c32afd6e 100644 --- a/backend/src/main/java/com/funeat/auth/util/AuthArgumentResolver.java +++ b/backend/src/main/java/com/funeat/auth/util/AuthArgumentResolver.java @@ -1,6 +1,6 @@ package com.funeat.auth.util; -import com.funeat.auth.dto.LoginRequest; +import com.funeat.auth.dto.LoginInfo; import java.util.Objects; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; @@ -26,6 +26,6 @@ public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer m final HttpSession session = Objects.requireNonNull(request).getSession(); final String id = String.valueOf(session.getAttribute("member")); - return new LoginRequest(Long.valueOf(id)); + return new LoginInfo(Long.valueOf(id)); } } diff --git a/backend/src/main/java/com/funeat/auth/util/MemberHandlerInterceptor.java b/backend/src/main/java/com/funeat/auth/util/MemberHandlerInterceptor.java new file mode 100644 index 000000000..894ddc80a --- /dev/null +++ b/backend/src/main/java/com/funeat/auth/util/MemberHandlerInterceptor.java @@ -0,0 +1,20 @@ +package com.funeat.auth.util; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.HandlerInterceptor; + +@Component +public class MemberHandlerInterceptor implements HandlerInterceptor { + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { + final HttpSession session = request.getSession(); + if (session.getAttribute("member") == null) { + throw new IllegalArgumentException("login error"); + } + return true; + } +} diff --git a/backend/src/main/java/com/funeat/common/WebConfig.java b/backend/src/main/java/com/funeat/common/WebConfig.java index 31af5acbb..7a5939dd6 100644 --- a/backend/src/main/java/com/funeat/common/WebConfig.java +++ b/backend/src/main/java/com/funeat/common/WebConfig.java @@ -2,6 +2,7 @@ import com.funeat.auth.util.AuthArgumentResolver; import com.funeat.auth.util.AuthHandlerInterceptor; +import com.funeat.auth.util.MemberHandlerInterceptor; import java.util.List; import org.springframework.context.annotation.Configuration; import org.springframework.format.FormatterRegistry; @@ -16,19 +17,24 @@ public class WebConfig implements WebMvcConfigurer { private final CustomPageableHandlerMethodArgumentResolver customPageableHandlerMethodArgumentResolver; private final AuthArgumentResolver authArgumentResolver; private final AuthHandlerInterceptor authHandlerInterceptor; + private final MemberHandlerInterceptor memberHandlerInterceptor; public WebConfig(final CustomPageableHandlerMethodArgumentResolver customPageableHandlerMethodArgumentResolver, final AuthArgumentResolver authArgumentResolver, - final AuthHandlerInterceptor authHandlerInterceptor) { + final AuthHandlerInterceptor authHandlerInterceptor, + final MemberHandlerInterceptor memberHandlerInterceptor) { this.customPageableHandlerMethodArgumentResolver = customPageableHandlerMethodArgumentResolver; this.authArgumentResolver = authArgumentResolver; this.authHandlerInterceptor = authHandlerInterceptor; + this.memberHandlerInterceptor = memberHandlerInterceptor; } @Override public void addInterceptors(final InterceptorRegistry registry) { registry.addInterceptor(authHandlerInterceptor) .addPathPatterns("/api/products/*/reviews/*"); + registry.addInterceptor(memberHandlerInterceptor) + .addPathPatterns("/api/members/*"); } @Override @@ -47,6 +53,7 @@ public void addCorsMappings(final CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("*") .allowedMethods("*") - .allowedHeaders("*"); + .allowedHeaders("*") + .exposedHeaders("Location", "Set-Cookie"); } } diff --git a/backend/src/main/java/com/funeat/member/presentation/MemberApiController.java b/backend/src/main/java/com/funeat/member/presentation/MemberApiController.java index 06f80e746..546c5665d 100644 --- a/backend/src/main/java/com/funeat/member/presentation/MemberApiController.java +++ b/backend/src/main/java/com/funeat/member/presentation/MemberApiController.java @@ -1,11 +1,12 @@ package com.funeat.member.presentation; +import com.funeat.auth.dto.LoginInfo; +import com.funeat.auth.util.AuthenticationPrincipal; import com.funeat.member.application.MemberService; import com.funeat.member.dto.MemberProfileResponse; import com.funeat.member.dto.MemberRequest; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; @@ -19,16 +20,21 @@ public MemberApiController(final MemberService memberService) { this.memberService = memberService; } - @GetMapping("/api/members/{memberId}") - public ResponseEntity getMemberProfile(@PathVariable final Long memberId) { + @GetMapping("/api/members") + public ResponseEntity getMemberProfile( + @AuthenticationPrincipal final LoginInfo loginInfo) { + final Long memberId = loginInfo.getId(); + final MemberProfileResponse response = memberService.getMemberProfile(memberId); return ResponseEntity.ok(response); } - @PutMapping("/api/members/{memberId}") - public ResponseEntity putMemberProfile(@PathVariable final Long memberId, + @PutMapping("/api/members") + public ResponseEntity putMemberProfile(@AuthenticationPrincipal final LoginInfo loginInfo, @RequestBody final MemberRequest request) { + final Long memberId = loginInfo.getId(); + memberService.modify(memberId, request); return ResponseEntity.ok().build(); diff --git a/backend/src/main/java/com/funeat/member/presentation/MemberController.java b/backend/src/main/java/com/funeat/member/presentation/MemberController.java index 0ac2807ad..dee16f3b2 100644 --- a/backend/src/main/java/com/funeat/member/presentation/MemberController.java +++ b/backend/src/main/java/com/funeat/member/presentation/MemberController.java @@ -1,5 +1,7 @@ package com.funeat.member.presentation; +import com.funeat.auth.dto.LoginInfo; +import com.funeat.auth.util.AuthenticationPrincipal; import com.funeat.member.dto.MemberProfileResponse; import com.funeat.member.dto.MemberRequest; import io.swagger.v3.oas.annotations.Operation; @@ -7,7 +9,6 @@ import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; @@ -20,7 +21,7 @@ public interface MemberController { description = "사용자 정보 조회 성공." ) @GetMapping - ResponseEntity getMemberProfile(@PathVariable Long memberId); + ResponseEntity getMemberProfile(@AuthenticationPrincipal LoginInfo loginInfo); @Operation(summary = "사용자 정보 수정", description = "사용자 닉네임과 프로필 사진을 수정한다.") @ApiResponse( @@ -28,5 +29,6 @@ public interface MemberController { description = "사용자 정보 수정 성공." ) @PutMapping - ResponseEntity putMemberProfile(@PathVariable Long memberId, @RequestBody MemberRequest request); + ResponseEntity putMemberProfile(@AuthenticationPrincipal LoginInfo loginInfo, + @RequestBody MemberRequest request); } diff --git a/backend/src/main/java/com/funeat/review/presentation/ReviewApiController.java b/backend/src/main/java/com/funeat/review/presentation/ReviewApiController.java index cd3b1eac2..728a2a3f0 100644 --- a/backend/src/main/java/com/funeat/review/presentation/ReviewApiController.java +++ b/backend/src/main/java/com/funeat/review/presentation/ReviewApiController.java @@ -1,6 +1,6 @@ package com.funeat.review.presentation; -import com.funeat.auth.dto.LoginRequest; +import com.funeat.auth.dto.LoginInfo; import com.funeat.auth.util.AuthenticationPrincipal; import com.funeat.review.application.ReviewService; import com.funeat.review.presentation.dto.RankingReviewsResponse; @@ -33,7 +33,7 @@ public ReviewApiController(final ReviewService reviewService) { @PostMapping(value = "/api/products/{productId}/reviews", consumes = {MediaType.MULTIPART_FORM_DATA_VALUE, MediaType.APPLICATION_JSON_VALUE}) public ResponseEntity writeReview(@PathVariable final Long productId, - @AuthenticationPrincipal final LoginRequest loginInfo, + @AuthenticationPrincipal final LoginInfo loginInfo, @RequestPart(required = false) final MultipartFile image, @RequestPart final ReviewCreateRequest reviewRequest) { reviewService.create(productId, loginInfo.getId(), image, reviewRequest); @@ -43,7 +43,7 @@ public ResponseEntity writeReview(@PathVariable final Long productId, @PatchMapping("/api/products/{productId}/reviews/{reviewId}") public ResponseEntity toggleLikeReview(@PathVariable Long reviewId, - @AuthenticationPrincipal LoginRequest loginInfo, + @AuthenticationPrincipal LoginInfo loginInfo, @RequestBody ReviewFavoriteRequest request) { reviewService.likeReview(reviewId, loginInfo.getId(), request); diff --git a/backend/src/main/java/com/funeat/review/presentation/ReviewController.java b/backend/src/main/java/com/funeat/review/presentation/ReviewController.java index 527085aec..e751c519d 100644 --- a/backend/src/main/java/com/funeat/review/presentation/ReviewController.java +++ b/backend/src/main/java/com/funeat/review/presentation/ReviewController.java @@ -1,6 +1,6 @@ package com.funeat.review.presentation; -import com.funeat.auth.dto.LoginRequest; +import com.funeat.auth.dto.LoginInfo; import com.funeat.auth.util.AuthenticationPrincipal; import com.funeat.review.presentation.dto.RankingReviewsResponse; import com.funeat.review.presentation.dto.ReviewCreateRequest; @@ -29,7 +29,7 @@ public interface ReviewController { description = "리뷰 작성 성공." ) @PostMapping - ResponseEntity writeReview(@PathVariable Long productId, @AuthenticationPrincipal LoginRequest loginInfo, + ResponseEntity writeReview(@PathVariable Long productId, @AuthenticationPrincipal LoginInfo loginInfo, @RequestPart MultipartFile image, @RequestPart ReviewCreateRequest reviewRequest); @Operation(summary = "리뷰 좋아요", description = "리뷰에 좋아요 또는 취소를 한다.") @@ -38,7 +38,7 @@ ResponseEntity writeReview(@PathVariable Long productId, @AuthenticationPr description = "리뷰 좋아요(취소) 성공." ) @PatchMapping - ResponseEntity toggleLikeReview(@PathVariable Long reviewId, @AuthenticationPrincipal LoginRequest loginInfo, + ResponseEntity toggleLikeReview(@PathVariable Long reviewId, @AuthenticationPrincipal LoginInfo loginInfo, @RequestBody ReviewFavoriteRequest request); @Operation(summary = "리뷰를 정렬후 조회", description = "리뷰를 정렬후 조회한다.") diff --git a/backend/src/test/java/com/funeat/acceptance/member/MemberAcceptanceTest.java b/backend/src/test/java/com/funeat/acceptance/member/MemberAcceptanceTest.java index 25a4fc397..a3b725d09 100644 --- a/backend/src/test/java/com/funeat/acceptance/member/MemberAcceptanceTest.java +++ b/backend/src/test/java/com/funeat/acceptance/member/MemberAcceptanceTest.java @@ -2,6 +2,7 @@ import static com.funeat.acceptance.common.CommonSteps.STATUS_CODE를_검증한다; import static com.funeat.acceptance.common.CommonSteps.정상_처리; +import static com.funeat.acceptance.common.LoginSteps.로그인_쿠키를_얻는다; import static com.funeat.acceptance.member.MemberSteps.사용자_정보_수정_요청; import static com.funeat.acceptance.member.MemberSteps.사용자_정보_조회_요청; import static org.assertj.core.api.SoftAssertions.assertSoftly; @@ -21,10 +22,11 @@ public class MemberAcceptanceTest extends AcceptanceTest { void 사용자_정보를_확인하다() { // given final var member = new Member("test", "http://www.test.com", "1"); - final var memberId = 멤버_추가_요청(member); + 멤버_추가_요청(member); + final var loginCookie = 로그인_쿠키를_얻는다(); // when - final var response = 사용자_정보_조회_요청(memberId); + final var response = 사용자_정보_조회_요청(loginCookie); // then STATUS_CODE를_검증한다(response, 정상_처리); @@ -35,12 +37,13 @@ public class MemberAcceptanceTest extends AcceptanceTest { void 사용자_정보를_수정하다() { // given final var member = new Member("before", "http://www.before.com", "1"); - final var memberId = 멤버_추가_요청(member); + 멤버_추가_요청(member); + final var loginCookie = 로그인_쿠키를_얻는다(); final var request = new MemberRequest("after", "http://www.after.com"); // when - final var response = 사용자_정보_수정_요청(memberId, request); + final var response = 사용자_정보_수정_요청(loginCookie, request); // then STATUS_CODE를_검증한다(response, 정상_처리); diff --git a/backend/src/test/java/com/funeat/acceptance/member/MemberSteps.java b/backend/src/test/java/com/funeat/acceptance/member/MemberSteps.java index ca7812e1d..0a4f81636 100644 --- a/backend/src/test/java/com/funeat/acceptance/member/MemberSteps.java +++ b/backend/src/test/java/com/funeat/acceptance/member/MemberSteps.java @@ -8,20 +8,22 @@ public class MemberSteps { - public static ExtractableResponse 사용자_정보_수정_요청(final Long memberId, final MemberRequest request) { + public static ExtractableResponse 사용자_정보_수정_요청(final String loginCookie, final MemberRequest request) { return given() + .cookie("JSESSIONID", loginCookie) .contentType("application/json") .body(request) .when() - .put("/api/members/{memberId}", memberId) + .put("/api/members") .then() .extract(); } - public static ExtractableResponse 사용자_정보_조회_요청(final Long memberId) { + public static ExtractableResponse 사용자_정보_조회_요청(final String loginCookie) { return given() + .cookie("JSESSIONID", loginCookie) .when() - .get("/api/members/{memberId}", memberId) + .get("/api/members") .then() .extract(); }