diff --git a/src/main/java/com/seeat/server/domain/review/domain/repository/ReviewRepository.java b/src/main/java/com/seeat/server/domain/review/domain/repository/ReviewRepository.java index 49c2f1dd..5591559a 100644 --- a/src/main/java/com/seeat/server/domain/review/domain/repository/ReviewRepository.java +++ b/src/main/java/com/seeat/server/domain/review/domain/repository/ReviewRepository.java @@ -285,11 +285,9 @@ ORDER BY COUNT(rl.user.id) DESC, r.createdAt DESC * @return ReviewLikeCountResponse 응답 */ @Query(""" - SELECT COUNT(DISTINCT r.id) AS reviewCount, - COUNT(rl.id) AS likeCount - FROM Review r - LEFT JOIN ReviewLike rl ON rl.review.id = r.id - WHERE r.user.id = :userId + SELECT + (SELECT COUNT(r) FROM Review r WHERE r.user.id = :userId) AS reviewCount, + (SELECT COUNT(rl) FROM ReviewLike rl WHERE rl.user.id = :userId) AS likeCount """) Optional findReviewAndLikeCountByUserId(@Param("userId") Long userId); diff --git a/src/main/java/com/seeat/server/domain/user/application/service/UserService.java b/src/main/java/com/seeat/server/domain/user/application/service/UserService.java index 7d115e1d..363dc3d5 100644 --- a/src/main/java/com/seeat/server/domain/user/application/service/UserService.java +++ b/src/main/java/com/seeat/server/domain/user/application/service/UserService.java @@ -96,7 +96,7 @@ public Optional getUserBySocialAndSocialId(UserSocial social, String socia * @param request 회원가입을 위한 추가 정보 */ @Override - public void createUser(TempUserInfo tempUserInfo, UserSignUpRequest request) throws IOException { + public User createUser(TempUserInfo tempUserInfo, UserSignUpRequest request) throws IOException { String thumbnailImage = "thumbnail"; @@ -123,6 +123,8 @@ public void createUser(TempUserInfo tempUserInfo, UserSignUpRequest request) thr userAuditoriumRepository.save(userAuditorium); } } + + return user; } /** diff --git a/src/main/java/com/seeat/server/domain/user/application/usecase/UserUseCase.java b/src/main/java/com/seeat/server/domain/user/application/usecase/UserUseCase.java index 6643b4e3..217dd228 100644 --- a/src/main/java/com/seeat/server/domain/user/application/usecase/UserUseCase.java +++ b/src/main/java/com/seeat/server/domain/user/application/usecase/UserUseCase.java @@ -23,7 +23,7 @@ public interface UserUseCase { Optional getUserBySocialAndSocialId(UserSocial social, String socialId); // 사용자 생성 - void createUser(TempUserInfo tempUserInfo, UserSignUpRequest request) throws IOException; + User createUser(TempUserInfo tempUserInfo, UserSignUpRequest request) throws IOException; // redis, cookie - refreshToken 삭제 (로그아웃) void logout(HttpServletRequest request, HttpServletResponse response); diff --git a/src/main/java/com/seeat/server/domain/user/domain/repository/UserAuditoriumRepository.java b/src/main/java/com/seeat/server/domain/user/domain/repository/UserAuditoriumRepository.java index acb9d2a8..d9d577cc 100644 --- a/src/main/java/com/seeat/server/domain/user/domain/repository/UserAuditoriumRepository.java +++ b/src/main/java/com/seeat/server/domain/user/domain/repository/UserAuditoriumRepository.java @@ -1,6 +1,7 @@ package com.seeat.server.domain.user.domain.repository; import com.seeat.server.domain.theater.domain.entity.Auditorium; +import com.seeat.server.domain.user.domain.entity.User; import com.seeat.server.domain.user.domain.entity.UserAuditorium; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; @@ -19,4 +20,6 @@ public interface UserAuditoriumRepository extends JpaRepository findAuditoriumsByUserId(@Param("userId") Long userId); void deleteByUserId(Long userId); + + boolean existsByUserAndAuditorium(User user, Auditorium auditorium); } diff --git a/src/main/java/com/seeat/server/domain/user/presentation/UserController.java b/src/main/java/com/seeat/server/domain/user/presentation/UserController.java index 7e15af42..963a4de8 100644 --- a/src/main/java/com/seeat/server/domain/user/presentation/UserController.java +++ b/src/main/java/com/seeat/server/domain/user/presentation/UserController.java @@ -4,6 +4,7 @@ import com.seeat.server.domain.user.application.dto.response.UserNicknameResponse; import com.seeat.server.domain.user.application.usecase.UserUseCase; import com.seeat.server.domain.user.application.dto.request.UserSignUpRequest; +import com.seeat.server.domain.user.domain.entity.User; import com.seeat.server.domain.user.domain.entity.UserRole; import com.seeat.server.domain.user.presentation.swagger.UserControllerSpec; import com.seeat.server.global.response.ApiResponse; @@ -39,6 +40,7 @@ public class UserController implements UserControllerSpec { */ @PostMapping() public ApiResponse userSignUp( + HttpServletResponse response, @RequestBody @Valid UserSignUpRequest request, @RequestHeader("Temp-User-Key") String tempUserKey) throws IOException { @@ -48,7 +50,12 @@ public ApiResponse userSignUp( throw new CustomException(ErrorCode.NOT_TEMP_USER, null); } - userService.createUser(tempUserInfo, request); + User user = userService.createUser(tempUserInfo, request); + + // 토큰 발급 + tokenService.generateTokensAndSetHeaders(response, user); + + // 임시유저 정보 삭제 redisService.deleteValues(tempUserKey); return ApiResponse.created(); diff --git a/src/main/java/com/seeat/server/domain/user/presentation/swagger/UserControllerSpec.java b/src/main/java/com/seeat/server/domain/user/presentation/swagger/UserControllerSpec.java index 2d46fd33..06b6ff57 100644 --- a/src/main/java/com/seeat/server/domain/user/presentation/swagger/UserControllerSpec.java +++ b/src/main/java/com/seeat/server/domain/user/presentation/swagger/UserControllerSpec.java @@ -4,6 +4,7 @@ import com.seeat.server.domain.user.application.dto.response.UserNicknameResponse; import com.seeat.server.global.response.ApiResponse; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; @@ -18,6 +19,7 @@ public interface UserControllerSpec { /** * 회원가입 API * + * @param response 토큰을 헤더 및 쿠키에 설정하기 위한 HTTP 응답 객체 * @param request 추가 정보 요청값 * @param tempUserKey 임시유저정보 * @return 회원가입 완료 응답 @@ -28,6 +30,7 @@ public interface UserControllerSpec { description = "최초 로그인 추가 회원가입입니다." ) ApiResponse userSignUp( + @Parameter(hidden = true) HttpServletResponse response, @RequestBody @Valid UserSignUpRequest request, @RequestHeader String tempUserKey ) throws IOException; diff --git a/src/main/java/com/seeat/server/security/jwt/JwtProvider.java b/src/main/java/com/seeat/server/security/jwt/JwtProvider.java index a9931b37..2f7c193a 100644 --- a/src/main/java/com/seeat/server/security/jwt/JwtProvider.java +++ b/src/main/java/com/seeat/server/security/jwt/JwtProvider.java @@ -113,23 +113,30 @@ public String generateToken(User user, long tokenValidTime) { public String generateDevTokenWithMockUser(Long userId, String username, UserRole role) { /// 개발용 유저 실제 DB에 저장 + // 개발용 유저 SocialId 구성 String cleanedId = ("dev-" + userId).trim(); User user = userRepository.findBySocialAndSocialId(KAKAO, cleanedId) .orElseGet(() -> userRepository.save(createMockUser(userId, username, role))); - // 상영관 저장 - Auditorium auditorium = auditoriumRepository.findById("1001") + // 상영관 ID로 조회 + Auditorium auditorium = auditoriumRepository.findById("13018") .orElseThrow(() -> new NoSuchElementException(ErrorCode.NOT_AUDITORIUM.getMessage())); - UserAuditorium userAuditorium = UserAuditorium.of(user, auditorium); - userAuditoriumRepository.save(userAuditorium); + // 유저-상영관 매핑이 존재하지 않을 때만 저장 + boolean alreadyMapped = userAuditoriumRepository.existsByUserAndAuditorium(user, auditorium); + if (!alreadyMapped) { + UserAuditorium userAuditorium = UserAuditorium.of(user, auditorium); + userAuditoriumRepository.save(userAuditorium); + } + + // 권한 설정 Collection authorities = Collections.singletonList( new SimpleGrantedAuthority(role.getRole()) ); + // 인증 객체 설정 Authentication mockAuthentication = new UsernamePasswordAuthenticationToken( user, null, authorities); - SecurityContextHolder.getContext().setAuthentication(mockAuthentication); return generateToken(mockAuthentication, devTokenExpiration); diff --git a/src/test/java/com/seeat/server/domain/user/application/service/UserProfileServiceTest.java b/src/test/java/com/seeat/server/domain/user/application/service/UserProfileServiceTest.java index 4d919a36..d4a8a8f3 100644 --- a/src/test/java/com/seeat/server/domain/user/application/service/UserProfileServiceTest.java +++ b/src/test/java/com/seeat/server/domain/user/application/service/UserProfileServiceTest.java @@ -96,6 +96,7 @@ public class UserProfileServiceTest { private User user2; private User user3; private User user4; + private User user5; private HashTag hashTag1; private HashTag hashTag2; private HashTag hashTag3; @@ -111,6 +112,7 @@ void setUp() throws IOException { user2 = repository.save(UserFixtures.createUser("user2@test.com")); user3 = repository.save(UserFixtures.createUser("user3@test.com")); user4 = repository.save(UserFixtures.createUser("user4@test.com")); + user5 = repository.save(UserFixtures.createUser("user5@test.com")); hashTag1 = hashTagRepository.save(HashTagFixtures.createHashTag(HashTagType.SOUND, "해시태그 1")); hashTag2 = hashTagRepository.save(HashTagFixtures.createHashTag(HashTagType.COMPANION, "해시태그 2")); hashTag3 = hashTagRepository.save(HashTagFixtures.createHashTag(HashTagType.ENVIRONMENT, "해시태그 3")); @@ -126,16 +128,20 @@ void getUserInfo_Success() throws IOException { // given userAuditoriumRepository.save(UserAuditorium.of(user1, auditorium)); - Review review1 = reviewService.createReview(getReviewRequest(List.of(seat1, seat2), 5, "test-1"), user1.getId()); - Review review2 = reviewService.createReview(getReviewRequest(List.of(seat1, seat2), 5, "test-1"), user1.getId()); + Review review1 = reviewService.createReview(getReviewRequest(List.of(seat1, seat2), 1, "test-1"), user1.getId()); + Review review2 = reviewService.createReview(getReviewRequest(List.of(seat1, seat2), 2, "test-2"), user2.getId()); + Review review3 = reviewService.createReview(getReviewRequest(List.of(seat1, seat2), 3, "test-3"), user3.getId()); + Review review4 = reviewService.createReview(getReviewRequest(List.of(seat1, seat2), 4, "test-4"), user4.getId()); + Review review5 = reviewService.createReview(getReviewRequest(List.of(seat1, seat2), 5, "test-5"), user5.getId()); + Review review6 = reviewService.createReview(getReviewRequest(List.of(seat1, seat2), 5, "test-1"), user1.getId()); /// 좋아요 reviewLikeRepository.saveAll(List.of( - ReviewLikeFixtures.stub(user2, review1), - ReviewLikeFixtures.stub(user3, review1), - ReviewLikeFixtures.stub(user2, review1), - ReviewLikeFixtures.stub(user3, review2), - ReviewLikeFixtures.stub(user4, review2) + ReviewLikeFixtures.stub(user1, review1), + ReviewLikeFixtures.stub(user1, review2), + ReviewLikeFixtures.stub(user1, review3), + ReviewLikeFixtures.stub(user1, review4), + ReviewLikeFixtures.stub(user1, review5) ));