diff --git a/src/main/java/com/example/solidconnection/application/controller/ApplicationController.java b/src/main/java/com/example/solidconnection/application/controller/ApplicationController.java index dce62235f..6d8c45fbf 100644 --- a/src/main/java/com/example/solidconnection/application/controller/ApplicationController.java +++ b/src/main/java/com/example/solidconnection/application/controller/ApplicationController.java @@ -5,6 +5,8 @@ import com.example.solidconnection.application.dto.ApplyRequest; import com.example.solidconnection.application.service.ApplicationQueryService; import com.example.solidconnection.application.service.ApplicationSubmissionService; +import com.example.solidconnection.custom.resolver.AuthorizedUser; +import com.example.solidconnection.siteuser.domain.SiteUser; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; @@ -16,8 +18,6 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; -import java.security.Principal; - @RequiredArgsConstructor @RequestMapping("/application") @RestController @@ -29,9 +29,10 @@ public class ApplicationController { // 지원서 제출하기 api @PostMapping() public ResponseEntity apply( - Principal principal, - @Valid @RequestBody ApplyRequest applyRequest) { - boolean result = applicationSubmissionService.apply(principal.getName(), applyRequest); + @AuthorizedUser SiteUser siteUser, + @Valid @RequestBody ApplyRequest applyRequest + ) { + boolean result = applicationSubmissionService.apply(siteUser, applyRequest); return ResponseEntity .status(HttpStatus.OK) .body(new ApplicationSubmissionResponse(result)); @@ -39,20 +40,22 @@ public ResponseEntity apply( @GetMapping public ResponseEntity getApplicants( - Principal principal, + @AuthorizedUser SiteUser siteUser, @RequestParam(required = false, defaultValue = "") String region, - @RequestParam(required = false, defaultValue = "") String keyword) { - applicationQueryService.validateSiteUserCanViewApplicants(principal.getName()); - ApplicationsResponse result = applicationQueryService.getApplicants(principal.getName(), region, keyword); + @RequestParam(required = false, defaultValue = "") String keyword + ) { + applicationQueryService.validateSiteUserCanViewApplicants(siteUser); + ApplicationsResponse result = applicationQueryService.getApplicants(siteUser, region, keyword); return ResponseEntity .ok(result); } @GetMapping("/competitors") public ResponseEntity getApplicantsForUserCompetitors( - Principal principal) { - applicationQueryService.validateSiteUserCanViewApplicants(principal.getName()); - ApplicationsResponse result = applicationQueryService.getApplicantsByUserApplications(principal.getName()); + @AuthorizedUser SiteUser siteUser + ) { + applicationQueryService.validateSiteUserCanViewApplicants(siteUser); + ApplicationsResponse result = applicationQueryService.getApplicantsByUserApplications(siteUser); return ResponseEntity .ok(result); } diff --git a/src/main/java/com/example/solidconnection/application/service/ApplicationQueryService.java b/src/main/java/com/example/solidconnection/application/service/ApplicationQueryService.java index 68cf9c0aa..170d7cf13 100644 --- a/src/main/java/com/example/solidconnection/application/service/ApplicationQueryService.java +++ b/src/main/java/com/example/solidconnection/application/service/ApplicationQueryService.java @@ -8,7 +8,6 @@ import com.example.solidconnection.cache.annotation.ThunderingHerdCaching; import com.example.solidconnection.custom.exception.CustomException; import com.example.solidconnection.siteuser.domain.SiteUser; -import com.example.solidconnection.siteuser.repository.SiteUserRepository; import com.example.solidconnection.type.VerifyStatus; import com.example.solidconnection.university.domain.University; import com.example.solidconnection.university.domain.UniversityInfoForApply; @@ -34,7 +33,6 @@ public class ApplicationQueryService { private final ApplicationRepository applicationRepository; private final UniversityInfoForApplyRepository universityInfoForApplyRepository; - private final SiteUserRepository siteUserRepository; private final UniversityFilterRepositoryImpl universityFilterRepository; @Value("${university.term}") @@ -49,9 +47,7 @@ public class ApplicationQueryService { * */ @Transactional(readOnly = true) @ThunderingHerdCaching(key = "application:query:{1}:{2}", cacheManager = "customCacheManager", ttlSec = 86400) - public ApplicationsResponse getApplicants(String email, String regionCode, String keyword) { - SiteUser siteUser = siteUserRepository.getByEmail(email); - + public ApplicationsResponse getApplicants(SiteUser siteUser, String regionCode, String keyword) { // 국가와 키워드와 지역을 통해 대학을 필터링한다. List universities = universityFilterRepository.findByRegionCodeAndKeywords(regionCode, List.of(keyword)); @@ -64,9 +60,7 @@ public ApplicationsResponse getApplicants(String email, String regionCode, Strin } @Transactional(readOnly = true) - public ApplicationsResponse getApplicantsByUserApplications(String email) { - SiteUser siteUser = siteUserRepository.getByEmail(email); - + public ApplicationsResponse getApplicantsByUserApplications(SiteUser siteUser) { Application userLatestApplication = applicationRepository.getApplicationBySiteUserAndTerm(siteUser, term); List userAppliedUniversities = Arrays.asList( Optional.ofNullable(userLatestApplication.getFirstChoiceUniversity()) @@ -91,8 +85,7 @@ public ApplicationsResponse getApplicantsByUserApplications(String email) { // 학기별로 상태가 관리된다. // 금학기에 지원이력이 있는 사용자만 지원정보를 확인할 수 있도록 한다. @Transactional(readOnly = true) - public void validateSiteUserCanViewApplicants(String email) { - SiteUser siteUser = siteUserRepository.getByEmail(email); + public void validateSiteUserCanViewApplicants(SiteUser siteUser) { VerifyStatus verifyStatus = applicationRepository.getApplicationBySiteUserAndTerm(siteUser, term).getVerifyStatus(); if (verifyStatus != VerifyStatus.APPROVED) { throw new CustomException(APPLICATION_NOT_APPROVED); diff --git a/src/main/java/com/example/solidconnection/application/service/ApplicationSubmissionService.java b/src/main/java/com/example/solidconnection/application/service/ApplicationSubmissionService.java index f82e9ad76..beb2f0cb0 100644 --- a/src/main/java/com/example/solidconnection/application/service/ApplicationSubmissionService.java +++ b/src/main/java/com/example/solidconnection/application/service/ApplicationSubmissionService.java @@ -38,7 +38,6 @@ public class ApplicationSubmissionService { private final ApplicationRepository applicationRepository; private final UniversityInfoForApplyRepository universityInfoForApplyRepository; - private final SiteUserRepository siteUserRepository; private final GpaScoreRepository gpaScoreRepository; private final LanguageTestScoreRepository languageTestScoreRepository; @@ -48,8 +47,7 @@ public class ApplicationSubmissionService { // 학점 및 어학성적이 모두 유효한 경우에만 지원서 등록이 가능하다. // 기존에 있던 status field 우선 APRROVED로 입력시킨다. @Transactional - public boolean apply(String email, ApplyRequest applyRequest) { - SiteUser siteUser = siteUserRepository.getByEmail(email); + public boolean apply(SiteUser siteUser, ApplyRequest applyRequest) { UniversityChoiceRequest universityChoiceRequest = applyRequest.universityChoiceRequest(); validateUniversityChoices(universityChoiceRequest); diff --git a/src/main/java/com/example/solidconnection/auth/controller/AuthController.java b/src/main/java/com/example/solidconnection/auth/controller/AuthController.java index 5f48124dc..1f6415157 100644 --- a/src/main/java/com/example/solidconnection/auth/controller/AuthController.java +++ b/src/main/java/com/example/solidconnection/auth/controller/AuthController.java @@ -8,6 +8,10 @@ import com.example.solidconnection.auth.service.AuthService; import com.example.solidconnection.auth.service.SignInService; import com.example.solidconnection.auth.service.SignUpService; +import com.example.solidconnection.custom.resolver.AuthorizedUser; +import com.example.solidconnection.custom.resolver.ExpiredToken; +import com.example.solidconnection.custom.security.authentication.ExpiredTokenAuthentication; +import com.example.solidconnection.siteuser.domain.SiteUser; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; @@ -17,8 +21,6 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -import java.security.Principal; - @RequiredArgsConstructor @RequestMapping("/auth") @RestController @@ -29,32 +31,42 @@ public class AuthController { private final SignInService signInService; @PostMapping("/kakao") - public ResponseEntity processKakaoOauth(@RequestBody KakaoCodeRequest kakaoCodeRequest) { + public ResponseEntity processKakaoOauth( + @RequestBody KakaoCodeRequest kakaoCodeRequest + ) { KakaoOauthResponse kakaoOauthResponse = signInService.signIn(kakaoCodeRequest); return ResponseEntity.ok(kakaoOauthResponse); } @PostMapping("/sign-up") - public ResponseEntity signUp(@Valid @RequestBody SignUpRequest signUpRequest) { + public ResponseEntity signUp( + @Valid @RequestBody SignUpRequest signUpRequest + ) { SignUpResponse signUpResponseDto = signUpService.signUp(signUpRequest); return ResponseEntity.ok(signUpResponseDto); } @PostMapping("/sign-out") - public ResponseEntity signOut(Principal principal) { - authService.signOut(principal.getName()); + public ResponseEntity signOut( + @ExpiredToken ExpiredTokenAuthentication expiredToken + ) { + authService.signOut(expiredToken.getToken()); return ResponseEntity.ok().build(); } @PatchMapping("/quit") - public ResponseEntity quit(Principal principal) { - authService.quit(principal.getName()); + public ResponseEntity quit( + @AuthorizedUser SiteUser siteUser + ) { + authService.quit(siteUser); return ResponseEntity.ok().build(); } @PostMapping("/reissue") - public ResponseEntity reissueToken(Principal principal) { - ReissueResponse reissueResponse = authService.reissue(principal.getName()); + public ResponseEntity reissueToken( + @ExpiredToken ExpiredTokenAuthentication expiredToken + ) { + ReissueResponse reissueResponse = authService.reissue(expiredToken.getSubject()); return ResponseEntity.ok(reissueResponse); } } diff --git a/src/main/java/com/example/solidconnection/auth/service/AuthService.java b/src/main/java/com/example/solidconnection/auth/service/AuthService.java index e16044e97..aed6f922f 100644 --- a/src/main/java/com/example/solidconnection/auth/service/AuthService.java +++ b/src/main/java/com/example/solidconnection/auth/service/AuthService.java @@ -4,7 +4,6 @@ import com.example.solidconnection.auth.dto.ReissueResponse; import com.example.solidconnection.custom.exception.CustomException; import com.example.solidconnection.siteuser.domain.SiteUser; -import com.example.solidconnection.siteuser.repository.SiteUserRepository; import lombok.RequiredArgsConstructor; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; @@ -23,11 +22,8 @@ @Service public class AuthService { - public static final String SIGN_OUT_VALUE = "signOut"; - private final RedisTemplate redisTemplate; private final TokenProvider tokenProvider; - private final SiteUserRepository siteUserRepository; /* * 로그아웃 한다. @@ -48,8 +44,7 @@ public void signOut(String accessToken) { * - e.g. 2024-01-01 18:00 탈퇴 시, 2024-01-02 00:00 가 탈퇴일이 된다. * */ @Transactional - public void quit(String email) { - SiteUser siteUser = siteUserRepository.getByEmail(email); + public void quit(SiteUser siteUser) { LocalDate tomorrow = LocalDate.now().plusDays(1); siteUser.setQuitedAt(tomorrow); } diff --git a/src/main/java/com/example/solidconnection/auth/service/SignInService.java b/src/main/java/com/example/solidconnection/auth/service/SignInService.java index 2cd356d73..ae4947596 100644 --- a/src/main/java/com/example/solidconnection/auth/service/SignInService.java +++ b/src/main/java/com/example/solidconnection/auth/service/SignInService.java @@ -7,12 +7,15 @@ import com.example.solidconnection.auth.dto.kakao.KakaoOauthResponse; import com.example.solidconnection.auth.dto.kakao.KakaoUserInfoDto; import com.example.solidconnection.auth.domain.TokenType; +import com.example.solidconnection.siteuser.domain.AuthType; import com.example.solidconnection.siteuser.domain.SiteUser; import com.example.solidconnection.siteuser.repository.SiteUserRepository; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.Optional; + @RequiredArgsConstructor @Service public class SignInService { @@ -35,11 +38,12 @@ public class SignInService { public KakaoOauthResponse signIn(KakaoCodeRequest kakaoCodeRequest) { KakaoUserInfoDto kakaoUserInfoDto = kakaoOAuthClient.processOauth(kakaoCodeRequest.code()); String email = kakaoUserInfoDto.kakaoAccountDto().email(); - boolean isAlreadyRegistered = siteUserRepository.existsByEmail(email); + Optional optionalSiteUser = siteUserRepository.findByEmailAndAuthType(email, AuthType.KAKAO); - if (isAlreadyRegistered) { - resetQuitedAt(email); - return getSignInInfo(email); + if (optionalSiteUser.isPresent()) { + SiteUser siteUser = optionalSiteUser.get(); + resetQuitedAt(siteUser); + return getSignInInfo(siteUser); } return getFirstAccessInfo(kakaoUserInfoDto); @@ -47,8 +51,7 @@ public KakaoOauthResponse signIn(KakaoCodeRequest kakaoCodeRequest) { // 계적 복구 기한이 지난 회원은 자정마다 삭제된다. (UserRemovalScheduler 참고) // 따라서 DB 에서 조회되었다면 아직 기한이 지나지 않았다는 뜻이므로, 탈퇴 날짜를 초기화한다. - private void resetQuitedAt(String email) { - SiteUser siteUser = siteUserRepository.getByEmail(email); + private void resetQuitedAt(SiteUser siteUser) { if (siteUser.getQuitedAt() == null) { return; } @@ -56,9 +59,9 @@ private void resetQuitedAt(String email) { siteUser.setQuitedAt(null); } - private SignInResponse getSignInInfo(String email) { - String accessToken = tokenProvider.generateToken(email, TokenType.ACCESS); - String refreshToken = tokenProvider.generateToken(email, TokenType.REFRESH); + private SignInResponse getSignInInfo(SiteUser siteUser) { + String accessToken = tokenProvider.generateToken(siteUser, TokenType.ACCESS); + String refreshToken = tokenProvider.generateToken(siteUser, TokenType.REFRESH); tokenProvider.saveToken(refreshToken, TokenType.REFRESH); return new SignInResponse(true, accessToken, refreshToken); } diff --git a/src/main/java/com/example/solidconnection/auth/service/SignUpService.java b/src/main/java/com/example/solidconnection/auth/service/SignUpService.java index 5cbd781eb..697cdbdc0 100644 --- a/src/main/java/com/example/solidconnection/auth/service/SignUpService.java +++ b/src/main/java/com/example/solidconnection/auth/service/SignUpService.java @@ -10,6 +10,7 @@ import com.example.solidconnection.repositories.InterestedCountyRepository; import com.example.solidconnection.repositories.InterestedRegionRepository; import com.example.solidconnection.repositories.RegionRepository; +import com.example.solidconnection.siteuser.domain.AuthType; import com.example.solidconnection.siteuser.domain.SiteUser; import com.example.solidconnection.siteuser.repository.SiteUserRepository; import com.example.solidconnection.type.Role; @@ -45,6 +46,7 @@ public class SignUpService { * - 관심 국가와 지역은 site_user_id를 참조하므로, 사용자 저장 후 저장한다. * - 바로 로그인하도록 액세스 토큰과 리프레시 토큰을 발급한다. * */ + // todo: 여러가지 가입 방법 적용해야 함 @Transactional public SignUpResponse signUp(SignUpRequest signUpRequest) { // 검증 @@ -62,14 +64,14 @@ public SignUpResponse signUp(SignUpRequest signUpRequest) { saveInterestedCountry(signUpRequest, savedSiteUser); // 토큰 발급 - String accessToken = tokenProvider.generateToken(email, TokenType.ACCESS); - String refreshToken = tokenProvider.generateToken(email, TokenType.REFRESH); + String accessToken = tokenProvider.generateToken(siteUser, TokenType.ACCESS); + String refreshToken = tokenProvider.generateToken(siteUser, TokenType.REFRESH); tokenProvider.saveToken(refreshToken, TokenType.REFRESH); return new SignUpResponse(accessToken, refreshToken); } private void validateUserNotDuplicated(String email) { - if (siteUserRepository.existsByEmail(email)) { + if (siteUserRepository.existsByEmailAndAuthType(email, AuthType.KAKAO)) { throw new CustomException(USER_ALREADY_EXISTED); } } diff --git a/src/main/java/com/example/solidconnection/auth/service/TokenProvider.java b/src/main/java/com/example/solidconnection/auth/service/TokenProvider.java index 9cba77c36..2dbf288ad 100644 --- a/src/main/java/com/example/solidconnection/auth/service/TokenProvider.java +++ b/src/main/java/com/example/solidconnection/auth/service/TokenProvider.java @@ -2,6 +2,7 @@ import com.example.solidconnection.auth.domain.TokenType; import com.example.solidconnection.config.security.JwtProperties; +import com.example.solidconnection.siteuser.domain.SiteUser; import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; @@ -12,8 +13,8 @@ import java.util.Date; import java.util.concurrent.TimeUnit; -import static com.example.solidconnection.util.JwtUtils.parseSubjectIgnoringExpiration; import static com.example.solidconnection.util.JwtUtils.parseSubject; +import static com.example.solidconnection.util.JwtUtils.parseSubjectIgnoringExpiration; @RequiredArgsConstructor @Component @@ -22,8 +23,13 @@ public class TokenProvider { private final RedisTemplate redisTemplate; private final JwtProperties jwtProperties; - public String generateToken(String email, TokenType tokenType) { - Claims claims = Jwts.claims().setSubject(email); + public String generateToken(SiteUser siteUser, TokenType tokenType) { + String subject = siteUser.getId().toString(); + return generateToken(subject, tokenType); + } + + public String generateToken(String string, TokenType tokenType) { + Claims claims = Jwts.claims().setSubject(string); Date now = new Date(); Date expiredDate = new Date(now.getTime() + tokenType.getExpireTime()); return Jwts.builder() diff --git a/src/main/java/com/example/solidconnection/comment/controller/CommentController.java b/src/main/java/com/example/solidconnection/comment/controller/CommentController.java index a7eaab252..fda360b4a 100644 --- a/src/main/java/com/example/solidconnection/comment/controller/CommentController.java +++ b/src/main/java/com/example/solidconnection/comment/controller/CommentController.java @@ -6,6 +6,8 @@ import com.example.solidconnection.comment.dto.CommentUpdateRequest; import com.example.solidconnection.comment.dto.CommentUpdateResponse; import com.example.solidconnection.comment.service.CommentService; +import com.example.solidconnection.custom.resolver.AuthorizedUser; +import com.example.solidconnection.siteuser.domain.SiteUser; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; @@ -17,8 +19,6 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -import java.security.Principal; - @RestController @RequiredArgsConstructor @RequestMapping("/posts") @@ -28,35 +28,32 @@ public class CommentController { @PostMapping("/{post_id}/comments") public ResponseEntity createComment( - Principal principal, + @AuthorizedUser SiteUser siteUser, @PathVariable("post_id") Long postId, @Valid @RequestBody CommentCreateRequest commentCreateRequest ) { - CommentCreateResponse commentCreateResponse = commentService.createComment( - principal.getName(), postId, commentCreateRequest); - return ResponseEntity.ok().body(commentCreateResponse); + CommentCreateResponse response = commentService.createComment(siteUser, postId, commentCreateRequest); + return ResponseEntity.ok().body(response); } @PatchMapping("/{post_id}/comments/{comment_id}") public ResponseEntity updateComment( - Principal principal, + @AuthorizedUser SiteUser siteUser, @PathVariable("post_id") Long postId, @PathVariable("comment_id") Long commentId, @Valid @RequestBody CommentUpdateRequest commentUpdateRequest ) { - CommentUpdateResponse commentUpdateResponse = commentService.updateComment( - principal.getName(), postId, commentId, commentUpdateRequest - ); - return ResponseEntity.ok().body(commentUpdateResponse); + CommentUpdateResponse response = commentService.updateComment(siteUser, postId, commentId, commentUpdateRequest); + return ResponseEntity.ok().body(response); } @DeleteMapping("/{post_id}/comments/{comment_id}") public ResponseEntity deleteCommentById( - Principal principal, + @AuthorizedUser SiteUser siteUser, @PathVariable("post_id") Long postId, @PathVariable("comment_id") Long commentId ) { - CommentDeleteResponse commentDeleteResponse = commentService.deleteCommentById(principal.getName(), postId, commentId); - return ResponseEntity.ok().body(commentDeleteResponse); + CommentDeleteResponse response = commentService.deleteCommentById(siteUser, postId, commentId); + return ResponseEntity.ok().body(response); } } diff --git a/src/main/java/com/example/solidconnection/comment/service/CommentService.java b/src/main/java/com/example/solidconnection/comment/service/CommentService.java index 7d25ee5f6..b7c1c6068 100644 --- a/src/main/java/com/example/solidconnection/comment/service/CommentService.java +++ b/src/main/java/com/example/solidconnection/comment/service/CommentService.java @@ -12,7 +12,6 @@ import com.example.solidconnection.post.domain.Post; import com.example.solidconnection.post.repository.PostRepository; import com.example.solidconnection.siteuser.domain.SiteUser; -import com.example.solidconnection.siteuser.repository.SiteUserRepository; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -29,25 +28,22 @@ public class CommentService { private final CommentRepository commentRepository; - private final SiteUserRepository siteUserRepository; private final PostRepository postRepository; @Transactional(readOnly = true) - public List findCommentsByPostId(String email, Long postId) { + public List findCommentsByPostId(SiteUser siteUser, Long postId) { return commentRepository.findCommentTreeByPostId(postId) .stream() - .map(comment -> PostFindCommentResponse.from(isOwner(comment, email), comment)) + .map(comment -> PostFindCommentResponse.from(isOwner(comment, siteUser), comment)) .collect(Collectors.toList()); } - private Boolean isOwner(Comment comment, String email) { - return comment.getSiteUser().getEmail().equals(email); + private Boolean isOwner(Comment comment, SiteUser siteUser) { + return comment.getSiteUser().getId().equals(siteUser.getId()); } @Transactional - public CommentCreateResponse createComment(String email, Long postId, CommentCreateRequest commentCreateRequest) { - - SiteUser siteUser = siteUserRepository.getByEmail(email); + public CommentCreateResponse createComment(SiteUser siteUser, Long postId, CommentCreateRequest commentCreateRequest) { Post post = postRepository.getById(postId); Comment parentComment = null; @@ -68,13 +64,11 @@ private void validateCommentDepth(Comment parentComment) { } @Transactional - public CommentUpdateResponse updateComment(String email, Long postId, Long commentId, CommentUpdateRequest commentUpdateRequest) { - - SiteUser siteUser = siteUserRepository.getByEmail(email); + public CommentUpdateResponse updateComment(SiteUser siteUser, Long postId, Long commentId, CommentUpdateRequest commentUpdateRequest) { Post post = postRepository.getById(postId); Comment comment = commentRepository.getById(commentId); validateDeprecated(comment); - validateOwnership(comment, email); + validateOwnership(comment, siteUser); comment.updateContent(commentUpdateRequest.content()); @@ -88,11 +82,10 @@ private void validateDeprecated(Comment comment) { } @Transactional - public CommentDeleteResponse deleteCommentById(String email, Long postId, Long commentId) { - SiteUser siteUser = siteUserRepository.getByEmail(email); + public CommentDeleteResponse deleteCommentById(SiteUser siteUser, Long postId, Long commentId) { Post post = postRepository.getById(postId); Comment comment = commentRepository.getById(commentId); - validateOwnership(comment, email); + validateOwnership(comment, siteUser); if (comment.getParentComment() != null) { // 대댓글인 경우 @@ -119,8 +112,8 @@ public CommentDeleteResponse deleteCommentById(String email, Long postId, Long c return new CommentDeleteResponse(commentId); } - private void validateOwnership(Comment comment, String email) { - if (!comment.getSiteUser().getEmail().equals(email)) { + private void validateOwnership(Comment comment, SiteUser siteUser) { + if (!comment.getSiteUser().getId().equals(siteUser.getId())) { throw new CustomException(INVALID_POST_ACCESS); } } diff --git a/src/main/java/com/example/solidconnection/config/security/AuthenticationManagerConfig.java b/src/main/java/com/example/solidconnection/config/security/AuthenticationManagerConfig.java new file mode 100644 index 000000000..785283d7d --- /dev/null +++ b/src/main/java/com/example/solidconnection/config/security/AuthenticationManagerConfig.java @@ -0,0 +1,25 @@ +package com.example.solidconnection.config.security; + +import com.example.solidconnection.custom.security.provider.ExpiredTokenAuthenticationProvider; +import com.example.solidconnection.custom.security.provider.SiteUserAuthenticationProvider; +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.ProviderManager; + +@RequiredArgsConstructor +@Configuration +public class AuthenticationManagerConfig { + + private final SiteUserAuthenticationProvider siteUserAuthenticationProvider; + private final ExpiredTokenAuthenticationProvider expiredTokenAuthenticationProvider; + + @Bean + public AuthenticationManager authenticationManager() { + return new ProviderManager( + siteUserAuthenticationProvider, + expiredTokenAuthenticationProvider + ); + } +} diff --git a/src/main/java/com/example/solidconnection/config/security/JwtAuthentication.java b/src/main/java/com/example/solidconnection/config/security/JwtAuthentication.java deleted file mode 100644 index 84692709a..000000000 --- a/src/main/java/com/example/solidconnection/config/security/JwtAuthentication.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.example.solidconnection.config.security; - -import org.springframework.security.authentication.AbstractAuthenticationToken; -import org.springframework.security.core.GrantedAuthority; - -import java.util.Collection; - -public class JwtAuthentication extends AbstractAuthenticationToken { - - private final String token; - private final Object principal; - - public JwtAuthentication(Object principal, String token, Collection authorities) { - super(authorities); - this.token = token; - this.principal = principal; - setAuthenticated(true); - } - - @Override - public Object getCredentials() { - return this.token; - } - - @Override - public Object getPrincipal() { - return this.principal; - } -} diff --git a/src/main/java/com/example/solidconnection/config/security/JwtAuthenticationFilter.java b/src/main/java/com/example/solidconnection/config/security/JwtAuthenticationFilter.java deleted file mode 100644 index 5c7ab9f97..000000000 --- a/src/main/java/com/example/solidconnection/config/security/JwtAuthenticationFilter.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.example.solidconnection.config.security; - -import jakarta.servlet.FilterChain; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.stereotype.Component; -import org.springframework.web.filter.OncePerRequestFilter; - -import java.io.IOException; - -import static com.example.solidconnection.util.JwtUtils.parseSubject; -import static com.example.solidconnection.util.JwtUtils.parseTokenFromRequest; - -@Component -@RequiredArgsConstructor -public class JwtAuthenticationFilter extends OncePerRequestFilter { - - private static final String REISSUE_URI = "/auth/reissue"; - private static final String REISSUE_METHOD = "post"; - - private final JwtProperties jwtProperties; - - @Override - protected void doFilterInternal(@NonNull HttpServletRequest request, - @NonNull HttpServletResponse response, - @NonNull FilterChain filterChain) throws ServletException, IOException { - String token = parseTokenFromRequest(request); - if (token == null || isReissueRequest(request)) { - filterChain.doFilter(request, response); - return; - } - - String subject = parseSubject(token, jwtProperties.secret()); - UserDetails userDetails = new JwtUserDetails(subject); - Authentication auth = new JwtAuthentication(userDetails, token, userDetails.getAuthorities()); - SecurityContextHolder.getContext().setAuthentication(auth); - filterChain.doFilter(request, response); - } - - private boolean isReissueRequest(HttpServletRequest request) { - return REISSUE_URI.equals(request.getRequestURI()) && REISSUE_METHOD.equals(request.getMethod()); - } -} diff --git a/src/main/java/com/example/solidconnection/config/security/SecurityConfiguration.java b/src/main/java/com/example/solidconnection/config/security/SecurityConfiguration.java index 3f6307f8f..6851b3e8c 100644 --- a/src/main/java/com/example/solidconnection/config/security/SecurityConfiguration.java +++ b/src/main/java/com/example/solidconnection/config/security/SecurityConfiguration.java @@ -1,5 +1,8 @@ package com.example.solidconnection.config.security; +import com.example.solidconnection.custom.security.filter.ExceptionHandlerFilter; +import com.example.solidconnection.custom.security.filter.JwtAuthenticationFilter; +import com.example.solidconnection.custom.security.filter.SignOutCheckFilter; import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; diff --git a/src/main/java/com/example/solidconnection/config/web/WebMvcConfig.java b/src/main/java/com/example/solidconnection/config/web/WebMvcConfig.java new file mode 100644 index 000000000..10e468f56 --- /dev/null +++ b/src/main/java/com/example/solidconnection/config/web/WebMvcConfig.java @@ -0,0 +1,27 @@ +package com.example.solidconnection.config.web; + + +import com.example.solidconnection.custom.resolver.AuthorizedUserResolver; +import com.example.solidconnection.custom.resolver.ExpiredTokenResolver; +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.method.support.HandlerMethodArgumentResolver; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +import java.util.List; + +@Configuration +@RequiredArgsConstructor +public class WebMvcConfig implements WebMvcConfigurer { + + private final AuthorizedUserResolver authorizedUserResolver; + private final ExpiredTokenResolver expiredTokenResolver; + + @Override + public void addArgumentResolvers(List resolvers) { + resolvers.addAll(List.of( + authorizedUserResolver, + expiredTokenResolver + )); + } +} diff --git a/src/main/java/com/example/solidconnection/custom/resolver/AuthorizedUser.java b/src/main/java/com/example/solidconnection/custom/resolver/AuthorizedUser.java new file mode 100644 index 000000000..b14d80994 --- /dev/null +++ b/src/main/java/com/example/solidconnection/custom/resolver/AuthorizedUser.java @@ -0,0 +1,11 @@ +package com.example.solidconnection.custom.resolver; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +public @interface AuthorizedUser { +} diff --git a/src/main/java/com/example/solidconnection/custom/resolver/AuthorizedUserResolver.java b/src/main/java/com/example/solidconnection/custom/resolver/AuthorizedUserResolver.java new file mode 100644 index 000000000..93707b007 --- /dev/null +++ b/src/main/java/com/example/solidconnection/custom/resolver/AuthorizedUserResolver.java @@ -0,0 +1,38 @@ +package com.example.solidconnection.custom.resolver; + +import com.example.solidconnection.custom.security.userdetails.SiteUserDetails; +import com.example.solidconnection.siteuser.domain.SiteUser; +import lombok.RequiredArgsConstructor; +import org.springframework.core.MethodParameter; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Component; +import org.springframework.web.bind.support.WebDataBinderFactory; +import org.springframework.web.context.request.NativeWebRequest; +import org.springframework.web.method.support.HandlerMethodArgumentResolver; +import org.springframework.web.method.support.ModelAndViewContainer; + +@Component +@RequiredArgsConstructor +public class AuthorizedUserResolver implements HandlerMethodArgumentResolver { + + @Override + public boolean supportsParameter(MethodParameter parameter) { + return parameter.hasParameterAnnotation(AuthorizedUser.class) + && parameter.getParameterType().equals(SiteUser.class); + } + + @Override + public Object resolveArgument(MethodParameter parameter, + ModelAndViewContainer mavContainer, + NativeWebRequest webRequest, + WebDataBinderFactory binderFactory) throws Exception { + try { + SiteUserDetails principal = (SiteUserDetails) SecurityContextHolder.getContext() + .getAuthentication() + .getPrincipal(); + return principal.getSiteUser(); + } catch (Exception e) { + return null; + } + } +} diff --git a/src/main/java/com/example/solidconnection/custom/resolver/ExpiredToken.java b/src/main/java/com/example/solidconnection/custom/resolver/ExpiredToken.java new file mode 100644 index 000000000..61abff98c --- /dev/null +++ b/src/main/java/com/example/solidconnection/custom/resolver/ExpiredToken.java @@ -0,0 +1,11 @@ +package com.example.solidconnection.custom.resolver; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +public @interface ExpiredToken { +} diff --git a/src/main/java/com/example/solidconnection/custom/resolver/ExpiredTokenResolver.java b/src/main/java/com/example/solidconnection/custom/resolver/ExpiredTokenResolver.java new file mode 100644 index 000000000..691136438 --- /dev/null +++ b/src/main/java/com/example/solidconnection/custom/resolver/ExpiredTokenResolver.java @@ -0,0 +1,34 @@ +package com.example.solidconnection.custom.resolver; + +import com.example.solidconnection.custom.security.authentication.ExpiredTokenAuthentication; +import lombok.RequiredArgsConstructor; +import org.springframework.core.MethodParameter; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Component; +import org.springframework.web.bind.support.WebDataBinderFactory; +import org.springframework.web.context.request.NativeWebRequest; +import org.springframework.web.method.support.HandlerMethodArgumentResolver; +import org.springframework.web.method.support.ModelAndViewContainer; + +@Component +@RequiredArgsConstructor +public class ExpiredTokenResolver implements HandlerMethodArgumentResolver { + + @Override + public boolean supportsParameter(MethodParameter parameter) { + return parameter.hasParameterAnnotation(ExpiredToken.class) + && parameter.getParameterType().equals(ExpiredTokenAuthentication.class); + } + + @Override + public Object resolveArgument(MethodParameter parameter, + ModelAndViewContainer mavContainer, + NativeWebRequest webRequest, + WebDataBinderFactory binderFactory) throws Exception { + try { + return SecurityContextHolder.getContext().getAuthentication(); + } catch (Exception e) { + return null; + } + } +} diff --git a/src/main/java/com/example/solidconnection/custom/security/authentication/ExpiredTokenAuthentication.java b/src/main/java/com/example/solidconnection/custom/security/authentication/ExpiredTokenAuthentication.java new file mode 100644 index 000000000..811ea6a1b --- /dev/null +++ b/src/main/java/com/example/solidconnection/custom/security/authentication/ExpiredTokenAuthentication.java @@ -0,0 +1,18 @@ +package com.example.solidconnection.custom.security.authentication; + +public class ExpiredTokenAuthentication extends JwtAuthentication { + + public ExpiredTokenAuthentication(String token) { + super(token, null); + setAuthenticated(false); + } + + public ExpiredTokenAuthentication(String token, String subject) { + super(token, subject); + setAuthenticated(false); + } + + public String getSubject() { + return (String) getPrincipal(); + } +} diff --git a/src/main/java/com/example/solidconnection/custom/security/authentication/JwtAuthentication.java b/src/main/java/com/example/solidconnection/custom/security/authentication/JwtAuthentication.java new file mode 100644 index 000000000..ba195caff --- /dev/null +++ b/src/main/java/com/example/solidconnection/custom/security/authentication/JwtAuthentication.java @@ -0,0 +1,30 @@ +package com.example.solidconnection.custom.security.authentication; + +import org.springframework.security.authentication.AbstractAuthenticationToken; + +public abstract class JwtAuthentication extends AbstractAuthenticationToken { + + private final String credentials; + + private final Object principal; + + public JwtAuthentication(String token, Object principal) { + super(null); + this.credentials = token; + this.principal = principal; + } + + @Override + public Object getCredentials() { + return this.credentials; + } + + @Override + public Object getPrincipal() { + return this.principal; + } + + public final String getToken() { + return (String) getCredentials(); + } +} diff --git a/src/main/java/com/example/solidconnection/custom/security/authentication/SiteUserAuthentication.java b/src/main/java/com/example/solidconnection/custom/security/authentication/SiteUserAuthentication.java new file mode 100644 index 000000000..3387cee55 --- /dev/null +++ b/src/main/java/com/example/solidconnection/custom/security/authentication/SiteUserAuthentication.java @@ -0,0 +1,16 @@ +package com.example.solidconnection.custom.security.authentication; + +import com.example.solidconnection.custom.security.userdetails.SiteUserDetails; + +public class SiteUserAuthentication extends JwtAuthentication { + + public SiteUserAuthentication(String token) { + super(token, null); + setAuthenticated(false); + } + + public SiteUserAuthentication(String token, SiteUserDetails principal) { + super(token, principal); + setAuthenticated(true); + } +} diff --git a/src/main/java/com/example/solidconnection/config/security/ExceptionHandlerFilter.java b/src/main/java/com/example/solidconnection/custom/security/filter/ExceptionHandlerFilter.java similarity index 97% rename from src/main/java/com/example/solidconnection/config/security/ExceptionHandlerFilter.java rename to src/main/java/com/example/solidconnection/custom/security/filter/ExceptionHandlerFilter.java index 59022c198..8d09bfada 100644 --- a/src/main/java/com/example/solidconnection/config/security/ExceptionHandlerFilter.java +++ b/src/main/java/com/example/solidconnection/custom/security/filter/ExceptionHandlerFilter.java @@ -1,4 +1,4 @@ -package com.example.solidconnection.config.security; +package com.example.solidconnection.custom.security.filter; import com.example.solidconnection.custom.exception.CustomException; import com.example.solidconnection.custom.response.ErrorResponse; diff --git a/src/main/java/com/example/solidconnection/custom/security/filter/JwtAuthenticationFilter.java b/src/main/java/com/example/solidconnection/custom/security/filter/JwtAuthenticationFilter.java new file mode 100644 index 000000000..3f5bce556 --- /dev/null +++ b/src/main/java/com/example/solidconnection/custom/security/filter/JwtAuthenticationFilter.java @@ -0,0 +1,55 @@ +package com.example.solidconnection.custom.security.filter; + +import com.example.solidconnection.config.security.JwtProperties; +import com.example.solidconnection.custom.security.authentication.ExpiredTokenAuthentication; +import com.example.solidconnection.custom.security.authentication.JwtAuthentication; +import com.example.solidconnection.custom.security.authentication.SiteUserAuthentication; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Component; +import org.springframework.web.filter.OncePerRequestFilter; + +import java.io.IOException; + +import static com.example.solidconnection.util.JwtUtils.isExpired; +import static com.example.solidconnection.util.JwtUtils.parseTokenFromRequest; + + +@Component +@RequiredArgsConstructor +public class JwtAuthenticationFilter extends OncePerRequestFilter { + + private final JwtProperties jwtProperties; + private final AuthenticationManager authenticationManager; + + @Override + public void doFilterInternal(@NonNull HttpServletRequest request, + @NonNull HttpServletResponse response, + @NonNull FilterChain filterChain) throws ServletException, IOException { + String token = parseTokenFromRequest(request); + if (token == null) { + filterChain.doFilter(request, response); + return; + } + + JwtAuthentication authToken = createAuthentication(token); + Authentication auth = authenticationManager.authenticate(authToken); + SecurityContextHolder.getContext().setAuthentication(auth); + + filterChain.doFilter(request, response); + } + + private JwtAuthentication createAuthentication(String token) { + if (isExpired(token, jwtProperties.secret())) { + return new ExpiredTokenAuthentication(token); + } + return new SiteUserAuthentication(token); + } +} diff --git a/src/main/java/com/example/solidconnection/config/security/SignOutCheckFilter.java b/src/main/java/com/example/solidconnection/custom/security/filter/SignOutCheckFilter.java similarity index 92% rename from src/main/java/com/example/solidconnection/config/security/SignOutCheckFilter.java rename to src/main/java/com/example/solidconnection/custom/security/filter/SignOutCheckFilter.java index c71252f1f..90fb6866e 100644 --- a/src/main/java/com/example/solidconnection/config/security/SignOutCheckFilter.java +++ b/src/main/java/com/example/solidconnection/custom/security/filter/SignOutCheckFilter.java @@ -1,5 +1,6 @@ -package com.example.solidconnection.config.security; +package com.example.solidconnection.custom.security.filter; +import com.example.solidconnection.config.security.JwtProperties; import com.example.solidconnection.custom.exception.CustomException; import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; diff --git a/src/main/java/com/example/solidconnection/custom/security/provider/ExpiredTokenAuthenticationProvider.java b/src/main/java/com/example/solidconnection/custom/security/provider/ExpiredTokenAuthenticationProvider.java new file mode 100644 index 000000000..d7461a0e6 --- /dev/null +++ b/src/main/java/com/example/solidconnection/custom/security/provider/ExpiredTokenAuthenticationProvider.java @@ -0,0 +1,34 @@ +package com.example.solidconnection.custom.security.provider; + + +import com.example.solidconnection.config.security.JwtProperties; +import com.example.solidconnection.custom.security.authentication.ExpiredTokenAuthentication; +import com.example.solidconnection.custom.security.authentication.JwtAuthentication; +import lombok.RequiredArgsConstructor; +import org.springframework.security.authentication.AuthenticationProvider; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.stereotype.Component; + +import static com.example.solidconnection.util.JwtUtils.parseSubjectIgnoringExpiration; + +@Component +@RequiredArgsConstructor +public class ExpiredTokenAuthenticationProvider implements AuthenticationProvider { + + private final JwtProperties jwtProperties; + + @Override + public Authentication authenticate(Authentication auth) throws AuthenticationException { + JwtAuthentication jwtAuth = (JwtAuthentication) auth; + String token = jwtAuth.getToken(); + String subject = parseSubjectIgnoringExpiration(token, jwtProperties.secret()); + + return new ExpiredTokenAuthentication(token, subject); + } + + @Override + public boolean supports(Class authentication) { + return ExpiredTokenAuthentication.class.isAssignableFrom(authentication); + } +} diff --git a/src/main/java/com/example/solidconnection/custom/security/provider/SiteUserAuthenticationProvider.java b/src/main/java/com/example/solidconnection/custom/security/provider/SiteUserAuthenticationProvider.java new file mode 100644 index 000000000..25f211710 --- /dev/null +++ b/src/main/java/com/example/solidconnection/custom/security/provider/SiteUserAuthenticationProvider.java @@ -0,0 +1,37 @@ +package com.example.solidconnection.custom.security.provider; + +import com.example.solidconnection.config.security.JwtProperties; +import com.example.solidconnection.custom.security.userdetails.SiteUserDetails; +import com.example.solidconnection.custom.security.userdetails.SiteUserDetailsService; +import com.example.solidconnection.custom.security.authentication.JwtAuthentication; +import com.example.solidconnection.custom.security.authentication.SiteUserAuthentication; +import lombok.RequiredArgsConstructor; +import org.springframework.security.authentication.AuthenticationProvider; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.stereotype.Component; + +import static com.example.solidconnection.util.JwtUtils.parseSubject; + +@Component +@RequiredArgsConstructor +public class SiteUserAuthenticationProvider implements AuthenticationProvider { + + private final JwtProperties jwtProperties; + private final SiteUserDetailsService siteUserDetailsService; + + @Override + public Authentication authenticate(Authentication auth) throws AuthenticationException { + JwtAuthentication jwtAuth = (JwtAuthentication) auth; + String token = jwtAuth.getToken(); + + String username = parseSubject(token, jwtProperties.secret()); + SiteUserDetails userDetails = (SiteUserDetails) siteUserDetailsService.loadUserByUsername(username); + return new SiteUserAuthentication(token, userDetails); + } + + @Override + public boolean supports(Class authentication) { + return SiteUserAuthentication.class.isAssignableFrom(authentication); + } +} diff --git a/src/main/java/com/example/solidconnection/config/security/JwtUserDetails.java b/src/main/java/com/example/solidconnection/custom/security/userdetails/SiteUserDetails.java similarity index 63% rename from src/main/java/com/example/solidconnection/config/security/JwtUserDetails.java rename to src/main/java/com/example/solidconnection/custom/security/userdetails/SiteUserDetails.java index b3bbda5fa..36a0b815a 100644 --- a/src/main/java/com/example/solidconnection/config/security/JwtUserDetails.java +++ b/src/main/java/com/example/solidconnection/custom/security/userdetails/SiteUserDetails.java @@ -1,16 +1,23 @@ -package com.example.solidconnection.config.security; +package com.example.solidconnection.custom.security.userdetails; +import com.example.solidconnection.siteuser.domain.SiteUser; +import lombok.Getter; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import java.util.Collection; -public class JwtUserDetails implements UserDetails { +public class SiteUserDetails implements UserDetails { + // userDetails 에서 userName 은 사용자 식별자를 의미함 private final String userName; - public JwtUserDetails(String userName) { - this.userName = userName; + @Getter + private final SiteUser siteUser; + + public SiteUserDetails(SiteUser siteUser) { + this.siteUser = siteUser; + this.userName = String.valueOf(siteUser.getId()); } @Override diff --git a/src/main/java/com/example/solidconnection/custom/security/userdetails/SiteUserDetailsService.java b/src/main/java/com/example/solidconnection/custom/security/userdetails/SiteUserDetailsService.java new file mode 100644 index 000000000..fd23fa899 --- /dev/null +++ b/src/main/java/com/example/solidconnection/custom/security/userdetails/SiteUserDetailsService.java @@ -0,0 +1,48 @@ +package com.example.solidconnection.custom.security.userdetails; + +import com.example.solidconnection.custom.exception.CustomException; +import com.example.solidconnection.siteuser.domain.SiteUser; +import com.example.solidconnection.siteuser.repository.SiteUserRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Service; + +import static com.example.solidconnection.custom.exception.ErrorCode.AUTHENTICATION_FAILED; +import static com.example.solidconnection.custom.exception.ErrorCode.INVALID_TOKEN; + +@Service +@RequiredArgsConstructor +public class SiteUserDetailsService implements UserDetailsService { + + private final SiteUserRepository siteUserRepository; + + @Override + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { + long siteUserId = getSiteUserId(username); + SiteUser siteUser = getSiteUser(siteUserId); + validateNotQuit(siteUser); + + return new SiteUserDetails(siteUser); + } + + private long getSiteUserId(String username) { + try { + return Long.parseLong(username); + } catch (NumberFormatException e) { + throw new CustomException(INVALID_TOKEN, "인증 정보가 지정된 형식과 일치하지 않습니다."); + } + } + + private SiteUser getSiteUser(long siteUserId) { + return siteUserRepository.findById(siteUserId) + .orElseThrow(() -> new CustomException(AUTHENTICATION_FAILED, "인증 정보에 해당하는 사용자를 찾을 수 없습니다.")); + } + + private void validateNotQuit(SiteUser siteUser) { + if (siteUser.getQuitedAt() != null) { + throw new CustomException(AUTHENTICATION_FAILED, "탈퇴한 사용자입니다."); + } + } +} diff --git a/src/main/java/com/example/solidconnection/post/controller/PostController.java b/src/main/java/com/example/solidconnection/post/controller/PostController.java index c3ff3ce3a..bc3f9d123 100644 --- a/src/main/java/com/example/solidconnection/post/controller/PostController.java +++ b/src/main/java/com/example/solidconnection/post/controller/PostController.java @@ -1,5 +1,6 @@ package com.example.solidconnection.post.controller; +import com.example.solidconnection.custom.resolver.AuthorizedUser; import com.example.solidconnection.post.dto.PostCreateRequest; import com.example.solidconnection.post.dto.PostCreateResponse; import com.example.solidconnection.post.dto.PostDeleteResponse; @@ -11,6 +12,7 @@ import com.example.solidconnection.post.service.PostCommandService; import com.example.solidconnection.post.service.PostLikeService; import com.example.solidconnection.post.service.PostQueryService; +import com.example.solidconnection.siteuser.domain.SiteUser; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; @@ -25,7 +27,6 @@ import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; -import java.security.Principal; import java.util.Collections; import java.util.List; @@ -40,75 +41,72 @@ public class PostController { @PostMapping(value = "/{code}/posts") public ResponseEntity createPost( - Principal principal, + @AuthorizedUser SiteUser siteUser, @PathVariable("code") String code, @Valid @RequestPart("postCreateRequest") PostCreateRequest postCreateRequest, - @RequestParam(value = "file", required = false) List imageFile) { - + @RequestParam(value = "file", required = false) List imageFile + ) { if (imageFile == null) { imageFile = Collections.emptyList(); } - PostCreateResponse post = postCommandService - .createPost(principal.getName(), code, postCreateRequest, imageFile); + PostCreateResponse post = postCommandService.createPost(siteUser, code, postCreateRequest, imageFile); return ResponseEntity.ok().body(post); } @PatchMapping(value = "/{code}/posts/{post_id}") public ResponseEntity updatePost( - Principal principal, + @AuthorizedUser SiteUser siteUser, @PathVariable("code") String code, @PathVariable("post_id") Long postId, @Valid @RequestPart("postUpdateRequest") PostUpdateRequest postUpdateRequest, - @RequestParam(value = "file", required = false) List imageFile) { - + @RequestParam(value = "file", required = false) List imageFile + ) { if (imageFile == null) { imageFile = Collections.emptyList(); } - PostUpdateResponse postUpdateResponse = postCommandService - .updatePost(principal.getName(), code, postId, postUpdateRequest, imageFile); + PostUpdateResponse postUpdateResponse = postCommandService.updatePost( + siteUser, code, postId, postUpdateRequest, imageFile + ); return ResponseEntity.ok().body(postUpdateResponse); } @GetMapping("/{code}/posts/{post_id}") public ResponseEntity findPostById( - Principal principal, + @AuthorizedUser SiteUser siteUser, @PathVariable("code") String code, - @PathVariable("post_id") Long postId) { - - PostFindResponse postFindResponse = postQueryService - .findPostById(principal.getName(), code, postId); + @PathVariable("post_id") Long postId + ) { + PostFindResponse postFindResponse = postQueryService.findPostById(siteUser, code, postId); return ResponseEntity.ok().body(postFindResponse); } @DeleteMapping(value = "/{code}/posts/{post_id}") public ResponseEntity deletePostById( - Principal principal, + @AuthorizedUser SiteUser siteUser, @PathVariable("code") String code, - @PathVariable("post_id") Long postId) { - - PostDeleteResponse postDeleteResponse = postCommandService.deletePostById(principal.getName(), code, postId); + @PathVariable("post_id") Long postId + ) { + PostDeleteResponse postDeleteResponse = postCommandService.deletePostById(siteUser, code, postId); return ResponseEntity.ok().body(postDeleteResponse); } @PostMapping(value = "/{code}/posts/{post_id}/like") public ResponseEntity likePost( - Principal principal, + @AuthorizedUser SiteUser siteUser, @PathVariable("code") String code, @PathVariable("post_id") Long postId ) { - - PostLikeResponse postLikeResponse = postLikeService.likePost(principal.getName(), code, postId); + PostLikeResponse postLikeResponse = postLikeService.likePost(siteUser, code, postId); return ResponseEntity.ok().body(postLikeResponse); } @DeleteMapping(value = "/{code}/posts/{post_id}/like") public ResponseEntity dislikePost( - Principal principal, + @AuthorizedUser SiteUser siteUser, @PathVariable("code") String code, @PathVariable("post_id") Long postId ) { - - PostDislikeResponse postDislikeResponse = postLikeService.dislikePost(principal.getName(), code, postId); + PostDislikeResponse postDislikeResponse = postLikeService.dislikePost(siteUser, code, postId); return ResponseEntity.ok().body(postDislikeResponse); } } diff --git a/src/main/java/com/example/solidconnection/post/service/PostCommandService.java b/src/main/java/com/example/solidconnection/post/service/PostCommandService.java index 7b0c4f937..74eb86310 100644 --- a/src/main/java/com/example/solidconnection/post/service/PostCommandService.java +++ b/src/main/java/com/example/solidconnection/post/service/PostCommandService.java @@ -15,7 +15,6 @@ import com.example.solidconnection.s3.UploadedFileUrlResponse; import com.example.solidconnection.service.RedisService; import com.example.solidconnection.siteuser.domain.SiteUser; -import com.example.solidconnection.siteuser.repository.SiteUserRepository; import com.example.solidconnection.type.BoardCode; import com.example.solidconnection.type.ImgType; import com.example.solidconnection.type.PostCategory; @@ -39,14 +38,13 @@ public class PostCommandService { private final PostRepository postRepository; - private final SiteUserRepository siteUserRepository; private final BoardRepository boardRepository; private final S3Service s3Service; private final RedisService redisService; private final RedisUtils redisUtils; @Transactional - public PostCreateResponse createPost(String email, String code, PostCreateRequest postCreateRequest, + public PostCreateResponse createPost(SiteUser siteUser, String code, PostCreateRequest postCreateRequest, List imageFile) { // 유효성 검증 String boardCode = validateCode(code); @@ -54,7 +52,6 @@ public PostCreateResponse createPost(String email, String code, PostCreateReques validateFileSize(imageFile); // 객체 생성 - SiteUser siteUser = siteUserRepository.getByEmail(email); Board board = boardRepository.getByCode(boardCode); Post post = postCreateRequest.toEntity(siteUser, board); // 이미지 처리 @@ -65,12 +62,12 @@ public PostCreateResponse createPost(String email, String code, PostCreateReques } @Transactional - public PostUpdateResponse updatePost(String email, String code, Long postId, PostUpdateRequest postUpdateRequest, + public PostUpdateResponse updatePost(SiteUser siteUser, String code, Long postId, PostUpdateRequest postUpdateRequest, List imageFile) { // 유효성 검증 String boardCode = validateCode(code); Post post = postRepository.getById(postId); - validateOwnership(post, email); + validateOwnership(post, siteUser); validateQuestion(post); validateFileSize(imageFile); @@ -96,10 +93,10 @@ private void savePostImages(List imageFile, Post post) { } @Transactional - public PostDeleteResponse deletePostById(String email, String code, Long postId) { + public PostDeleteResponse deletePostById(SiteUser siteUser, String code, Long postId) { String boardCode = validateCode(code); Post post = postRepository.getById(postId); - validateOwnership(post, email); + validateOwnership(post, siteUser); validateQuestion(post); removePostImages(post); @@ -119,8 +116,8 @@ private String validateCode(String code) { } } - private void validateOwnership(Post post, String email) { - if (!post.getSiteUser().getEmail().equals(email)) { + private void validateOwnership(Post post, SiteUser siteUser) { + if (!post.getSiteUser().getId().equals(siteUser.getId())) { throw new CustomException(INVALID_POST_ACCESS); } } diff --git a/src/main/java/com/example/solidconnection/post/service/PostLikeService.java b/src/main/java/com/example/solidconnection/post/service/PostLikeService.java index 8a72d5f9f..5aaf994c7 100644 --- a/src/main/java/com/example/solidconnection/post/service/PostLikeService.java +++ b/src/main/java/com/example/solidconnection/post/service/PostLikeService.java @@ -8,7 +8,6 @@ import com.example.solidconnection.post.repository.PostLikeRepository; import com.example.solidconnection.post.repository.PostRepository; import com.example.solidconnection.siteuser.domain.SiteUser; -import com.example.solidconnection.siteuser.repository.SiteUserRepository; import com.example.solidconnection.type.BoardCode; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -23,14 +22,12 @@ public class PostLikeService { private final PostRepository postRepository; - private final SiteUserRepository siteUserRepository; private final PostLikeRepository postLikeRepository; @Transactional(isolation = Isolation.READ_COMMITTED) - public PostLikeResponse likePost(String email, String code, Long postId) { + public PostLikeResponse likePost(SiteUser siteUser, String code, Long postId) { String boardCode = validateCode(code); Post post = postRepository.getById(postId); - SiteUser siteUser = siteUserRepository.getByEmail(email); validateDuplicatePostLike(post, siteUser); PostLike postLike = new PostLike(); @@ -42,10 +39,9 @@ public PostLikeResponse likePost(String email, String code, Long postId) { } @Transactional(isolation = Isolation.READ_COMMITTED) - public PostDislikeResponse dislikePost(String email, String code, Long postId) { + public PostDislikeResponse dislikePost(SiteUser siteUser, String code, Long postId) { String boardCode = validateCode(code); Post post = postRepository.getById(postId); - SiteUser siteUser = siteUserRepository.getByEmail(email); PostLike postLike = postLikeRepository.getByPostAndSiteUser(post, siteUser); postLike.resetPostAndSiteUser(); diff --git a/src/main/java/com/example/solidconnection/post/service/PostQueryService.java b/src/main/java/com/example/solidconnection/post/service/PostQueryService.java index d53470124..a45ca3968 100644 --- a/src/main/java/com/example/solidconnection/post/service/PostQueryService.java +++ b/src/main/java/com/example/solidconnection/post/service/PostQueryService.java @@ -12,7 +12,6 @@ import com.example.solidconnection.service.RedisService; import com.example.solidconnection.siteuser.domain.SiteUser; import com.example.solidconnection.siteuser.dto.PostFindSiteUserResponse; -import com.example.solidconnection.siteuser.repository.SiteUserRepository; import com.example.solidconnection.type.BoardCode; import com.example.solidconnection.util.RedisUtils; import lombok.RequiredArgsConstructor; @@ -28,28 +27,26 @@ public class PostQueryService { private final PostRepository postRepository; - private final SiteUserRepository siteUserRepository; private final CommentService commentService; private final RedisService redisService; private final RedisUtils redisUtils; private final PostLikeRepository postLikeRepository; @Transactional(readOnly = true) - public PostFindResponse findPostById(String email, String code, Long postId) { + public PostFindResponse findPostById(SiteUser siteUser, String code, Long postId) { String boardCode = validateCode(code); Post post = postRepository.getByIdUsingEntityGraph(postId); - SiteUser siteUser = siteUserRepository.getByEmail(email); - Boolean isOwner = getIsOwner(post, email); + Boolean isOwner = getIsOwner(post, siteUser); Boolean isLiked = getIsLiked(post, siteUser); PostFindBoardResponse boardPostFindResultDTO = PostFindBoardResponse.from(post.getBoard()); PostFindSiteUserResponse siteUserPostFindResultDTO = PostFindSiteUserResponse.from(post.getSiteUser()); List postImageFindResultDTOList = PostFindPostImageResponse.from(post.getPostImageList()); - List commentFindResultDTOList = commentService.findCommentsByPostId(email, postId); + List commentFindResultDTOList = commentService.findCommentsByPostId(siteUser, postId); // caching && 어뷰징 방지 - if (redisService.isPresent(redisUtils.getValidatePostViewCountRedisKey(email, postId))) { + if (redisService.isPresent(redisUtils.getValidatePostViewCountRedisKey(siteUser.getId(), postId))) { redisService.increaseViewCount(redisUtils.getPostViewCountRedisKey(postId)); } @@ -65,8 +62,8 @@ private String validateCode(String code) { } } - private Boolean getIsOwner(Post post, String email) { - return post.getSiteUser().getEmail().equals(email); + private Boolean getIsOwner(Post post, SiteUser siteUser) { + return post.getSiteUser().getId().equals(siteUser.getId()); } private Boolean getIsLiked(Post post, SiteUser siteUser) { diff --git a/src/main/java/com/example/solidconnection/s3/S3Controller.java b/src/main/java/com/example/solidconnection/s3/S3Controller.java index 0f32a4ab6..26f9160c0 100644 --- a/src/main/java/com/example/solidconnection/s3/S3Controller.java +++ b/src/main/java/com/example/solidconnection/s3/S3Controller.java @@ -1,5 +1,7 @@ package com.example.solidconnection.s3; +import com.example.solidconnection.custom.resolver.AuthorizedUser; +import com.example.solidconnection.siteuser.domain.SiteUser; import com.example.solidconnection.type.ImgType; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Value; @@ -11,8 +13,6 @@ import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; -import java.security.Principal; - @RequiredArgsConstructor @RequestMapping("/file") @RestController @@ -34,29 +34,34 @@ public class S3Controller { @PostMapping("/profile/pre") public ResponseEntity uploadPreProfileImage( - @RequestParam("file") MultipartFile imageFile) { + @RequestParam("file") MultipartFile imageFile + ) { UploadedFileUrlResponse profileImageUrl = s3Service.uploadFile(imageFile, ImgType.PROFILE); return ResponseEntity.ok(profileImageUrl); } @PostMapping("/profile/post") public ResponseEntity uploadPostProfileImage( - @RequestParam("file") MultipartFile imageFile, Principal principal) { + @AuthorizedUser SiteUser siteUser, + @RequestParam("file") MultipartFile imageFile + ) { UploadedFileUrlResponse profileImageUrl = s3Service.uploadFile(imageFile, ImgType.PROFILE); - s3Service.deleteExProfile(principal.getName()); + s3Service.deleteExProfile(siteUser); return ResponseEntity.ok(profileImageUrl); } @PostMapping("/gpa") public ResponseEntity uploadGpaImage( - @RequestParam("file") MultipartFile imageFile) { + @RequestParam("file") MultipartFile imageFile + ) { UploadedFileUrlResponse profileImageUrl = s3Service.uploadFile(imageFile, ImgType.GPA); return ResponseEntity.ok(profileImageUrl); } @PostMapping("/language-test") public ResponseEntity uploadLanguageImage( - @RequestParam("file") MultipartFile imageFile) { + @RequestParam("file") MultipartFile imageFile + ) { UploadedFileUrlResponse profileImageUrl = s3Service.uploadFile(imageFile, ImgType.LANGUAGE_TEST); return ResponseEntity.ok(profileImageUrl); } diff --git a/src/main/java/com/example/solidconnection/s3/S3Service.java b/src/main/java/com/example/solidconnection/s3/S3Service.java index 049be9fa3..2f3c633dd 100644 --- a/src/main/java/com/example/solidconnection/s3/S3Service.java +++ b/src/main/java/com/example/solidconnection/s3/S3Service.java @@ -109,8 +109,8 @@ private String getFileExtension(String fileName) { * - 기존 파일의 key(S3파일명)를 찾는다. * - S3에서 파일을 삭제한다. * */ - public void deleteExProfile(String email) { - String key = getExProfileImageUrl(email); + public void deleteExProfile(SiteUser siteUser) { + String key = siteUser.getProfileImageUrl(); deleteFile(key); } @@ -129,9 +129,4 @@ private void deleteFile(String fileName) { throw new CustomException(S3_CLIENT_EXCEPTION); } } - - private String getExProfileImageUrl(String email) { - SiteUser siteUser = siteUserRepository.getByEmail(email); - return siteUser.getProfileImageUrl(); - } } diff --git a/src/main/java/com/example/solidconnection/score/controller/ScoreController.java b/src/main/java/com/example/solidconnection/score/controller/ScoreController.java index 42ee7b009..6c54ab5fe 100644 --- a/src/main/java/com/example/solidconnection/score/controller/ScoreController.java +++ b/src/main/java/com/example/solidconnection/score/controller/ScoreController.java @@ -1,10 +1,12 @@ package com.example.solidconnection.score.controller; +import com.example.solidconnection.custom.resolver.AuthorizedUser; import com.example.solidconnection.score.dto.GpaScoreRequest; import com.example.solidconnection.score.dto.GpaScoreStatusResponse; import com.example.solidconnection.score.dto.LanguageTestScoreRequest; import com.example.solidconnection.score.dto.LanguageTestScoreStatusResponse; import com.example.solidconnection.score.service.ScoreService; +import com.example.solidconnection.siteuser.domain.SiteUser; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; @@ -14,8 +16,6 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -import java.security.Principal; - @RestController @RequestMapping("/score") @RequiredArgsConstructor @@ -26,32 +26,38 @@ public class ScoreController { // 학점을 등록하는 api @PostMapping("/gpa") public ResponseEntity submitGpaScore( - Principal principal, - @Valid @RequestBody GpaScoreRequest gpaScoreRequest) { - Long id = scoreService.submitGpaScore(principal.getName(), gpaScoreRequest); + @AuthorizedUser SiteUser siteUser, + @Valid @RequestBody GpaScoreRequest gpaScoreRequest + ) { + Long id = scoreService.submitGpaScore(siteUser, gpaScoreRequest); return ResponseEntity.ok(id); } // 어학성적을 등록하는 api @PostMapping("/languageTest") public ResponseEntity submitLanguageTestScore( - Principal principal, - @Valid @RequestBody LanguageTestScoreRequest languageTestScoreRequest) { - Long id = scoreService.submitLanguageTestScore(principal.getName(), languageTestScoreRequest); + @AuthorizedUser SiteUser siteUser, + @Valid @RequestBody LanguageTestScoreRequest languageTestScoreRequest + ) { + Long id = scoreService.submitLanguageTestScore(siteUser, languageTestScoreRequest); return ResponseEntity.ok(id); } // 학점 상태를 확인하는 api @GetMapping("/gpa") - public ResponseEntity getGpaScoreStatus(Principal principal) { - GpaScoreStatusResponse gpaScoreStatus = scoreService.getGpaScoreStatus(principal.getName()); + public ResponseEntity getGpaScoreStatus( + @AuthorizedUser SiteUser siteUser + ) { + GpaScoreStatusResponse gpaScoreStatus = scoreService.getGpaScoreStatus(siteUser); return ResponseEntity.ok(gpaScoreStatus); } // 어학 성적 상태를 확인하는 api @GetMapping("/languageTest") - public ResponseEntity getLanguageTestScoreStatus(Principal principal) { - LanguageTestScoreStatusResponse languageTestScoreStatus = scoreService.getLanguageTestScoreStatus(principal.getName()); + public ResponseEntity getLanguageTestScoreStatus( + @AuthorizedUser SiteUser siteUser + ) { + LanguageTestScoreStatusResponse languageTestScoreStatus = scoreService.getLanguageTestScoreStatus(siteUser); return ResponseEntity.ok(languageTestScoreStatus); } } diff --git a/src/main/java/com/example/solidconnection/score/service/ScoreService.java b/src/main/java/com/example/solidconnection/score/service/ScoreService.java index d09038fa5..e6c9d5c6e 100644 --- a/src/main/java/com/example/solidconnection/score/service/ScoreService.java +++ b/src/main/java/com/example/solidconnection/score/service/ScoreService.java @@ -12,7 +12,6 @@ import com.example.solidconnection.score.repository.GpaScoreRepository; import com.example.solidconnection.score.repository.LanguageTestScoreRepository; import com.example.solidconnection.siteuser.domain.SiteUser; -import com.example.solidconnection.siteuser.repository.SiteUserRepository; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -28,12 +27,9 @@ public class ScoreService { private final GpaScoreRepository gpaScoreRepository; private final LanguageTestScoreRepository languageTestScoreRepository; - private final SiteUserRepository siteUserRepository; @Transactional - public Long submitGpaScore(String email, GpaScoreRequest gpaScoreRequest) { - SiteUser siteUser = siteUserRepository.getByEmail(email); - + public Long submitGpaScore(SiteUser siteUser, GpaScoreRequest gpaScoreRequest) { GpaScore newGpaScore = new GpaScore(gpaScoreRequest.toGpa(), siteUser, gpaScoreRequest.issueDate()); newGpaScore.setSiteUser(siteUser); GpaScore savedNewGpaScore = gpaScoreRepository.save(newGpaScore); // 저장 후 반환된 객체 @@ -41,8 +37,7 @@ public Long submitGpaScore(String email, GpaScoreRequest gpaScoreRequest) { } @Transactional - public Long submitLanguageTestScore(String email, LanguageTestScoreRequest languageTestScoreRequest) { - SiteUser siteUser = siteUserRepository.getByEmail(email); + public Long submitLanguageTestScore(SiteUser siteUser, LanguageTestScoreRequest languageTestScoreRequest) { LanguageTest languageTest = languageTestScoreRequest.toLanguageTest(); LanguageTestScore newScore = new LanguageTestScore( @@ -53,8 +48,7 @@ public Long submitLanguageTestScore(String email, LanguageTestScoreRequest langu } @Transactional(readOnly = true) - public GpaScoreStatusResponse getGpaScoreStatus(String email) { - SiteUser siteUser = siteUserRepository.getByEmail(email); + public GpaScoreStatusResponse getGpaScoreStatus(SiteUser siteUser) { List gpaScoreStatusList = Optional.ofNullable(siteUser.getGpaScoreList()) .map(scores -> scores.stream() @@ -65,8 +59,7 @@ public GpaScoreStatusResponse getGpaScoreStatus(String email) { } @Transactional(readOnly = true) - public LanguageTestScoreStatusResponse getLanguageTestScoreStatus(String email) { - SiteUser siteUser = siteUserRepository.getByEmail(email); + public LanguageTestScoreStatusResponse getLanguageTestScoreStatus(SiteUser siteUser) { List languageTestScoreStatusList = Optional.ofNullable(siteUser.getLanguageTestScoreList()) .map(scores -> scores.stream() diff --git a/src/main/java/com/example/solidconnection/siteuser/controller/SiteUserController.java b/src/main/java/com/example/solidconnection/siteuser/controller/SiteUserController.java index c0d58356f..11c154243 100644 --- a/src/main/java/com/example/solidconnection/siteuser/controller/SiteUserController.java +++ b/src/main/java/com/example/solidconnection/siteuser/controller/SiteUserController.java @@ -1,5 +1,7 @@ package com.example.solidconnection.siteuser.controller; +import com.example.solidconnection.custom.resolver.AuthorizedUser; +import com.example.solidconnection.siteuser.domain.SiteUser; import com.example.solidconnection.siteuser.dto.MyPageResponse; import com.example.solidconnection.siteuser.dto.MyPageUpdateResponse; import com.example.solidconnection.siteuser.dto.NicknameUpdateRequest; @@ -17,8 +19,6 @@ import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; -import java.security.Principal; - @RequiredArgsConstructor @RequestMapping("/my-page") @RestController @@ -27,32 +27,36 @@ class SiteUserController { private final SiteUserService siteUserService; @GetMapping - public ResponseEntity getMyPageInfo(Principal principal) { - MyPageResponse myPageResponse = siteUserService.getMyPageInfo(principal.getName()); - return ResponseEntity - .ok(myPageResponse); + public ResponseEntity getMyPageInfo( + @AuthorizedUser SiteUser siteUser + ) { + MyPageResponse myPageResponse = siteUserService.getMyPageInfo(siteUser); + return ResponseEntity.ok(myPageResponse); } @GetMapping("/update") - public ResponseEntity getMyPageInfoToUpdate(Principal principal) { - MyPageUpdateResponse myPageUpdateDto = siteUserService.getMyPageInfoToUpdate(principal.getName()); - return ResponseEntity - .ok(myPageUpdateDto); + public ResponseEntity getMyPageInfoToUpdate( + @AuthorizedUser SiteUser siteUser + ) { + MyPageUpdateResponse myPageUpdateDto = siteUserService.getMyPageInfoToUpdate(siteUser); + return ResponseEntity.ok(myPageUpdateDto); } @PatchMapping("/update/profileImage") public ResponseEntity updateProfileImage( - Principal principal, - @RequestParam(value = "file", required = false) MultipartFile imageFile) { - ProfileImageUpdateResponse profileImageUpdateResponse = siteUserService.updateProfileImage(principal.getName(), imageFile); + @AuthorizedUser SiteUser siteUser, + @RequestParam(value = "file", required = false) MultipartFile imageFile + ) { + ProfileImageUpdateResponse profileImageUpdateResponse = siteUserService.updateProfileImage(siteUser, imageFile); return ResponseEntity.ok().body(profileImageUpdateResponse); } @PatchMapping("/update/nickname") public ResponseEntity updateNickname( - Principal principal, - @Valid @RequestBody NicknameUpdateRequest nicknameUpdateRequest) { - NicknameUpdateResponse nicknameUpdateResponse = siteUserService.updateNickname(principal.getName(), nicknameUpdateRequest); + @AuthorizedUser SiteUser siteUser, + @Valid @RequestBody NicknameUpdateRequest nicknameUpdateRequest + ) { + NicknameUpdateResponse nicknameUpdateResponse = siteUserService.updateNickname(siteUser, nicknameUpdateRequest); return ResponseEntity.ok().body(nicknameUpdateResponse); } } diff --git a/src/main/java/com/example/solidconnection/siteuser/repository/LikedUniversityRepository.java b/src/main/java/com/example/solidconnection/siteuser/repository/LikedUniversityRepository.java index c3793eb06..d15949723 100644 --- a/src/main/java/com/example/solidconnection/siteuser/repository/LikedUniversityRepository.java +++ b/src/main/java/com/example/solidconnection/siteuser/repository/LikedUniversityRepository.java @@ -10,9 +10,9 @@ public interface LikedUniversityRepository extends JpaRepository { - List findAllBySiteUser_Email(String email); + List findAllBySiteUser_Id(long siteUserId); - int countBySiteUser_Email(String email); + int countBySiteUser_Id(long siteUserId); Optional findBySiteUserAndUniversityInfoForApply(SiteUser siteUser, UniversityInfoForApply universityInfoForApply); } diff --git a/src/main/java/com/example/solidconnection/siteuser/repository/SiteUserRepository.java b/src/main/java/com/example/solidconnection/siteuser/repository/SiteUserRepository.java index 6b77252c5..e0617f046 100644 --- a/src/main/java/com/example/solidconnection/siteuser/repository/SiteUserRepository.java +++ b/src/main/java/com/example/solidconnection/siteuser/repository/SiteUserRepository.java @@ -1,6 +1,6 @@ package com.example.solidconnection.siteuser.repository; -import com.example.solidconnection.custom.exception.CustomException; +import com.example.solidconnection.siteuser.domain.AuthType; import com.example.solidconnection.siteuser.domain.SiteUser; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; @@ -11,22 +11,15 @@ import java.util.List; import java.util.Optional; -import static com.example.solidconnection.custom.exception.ErrorCode.USER_NOT_FOUND; - @Repository public interface SiteUserRepository extends JpaRepository { - Optional findByEmail(String email); + Optional findByEmailAndAuthType(String email, AuthType authType); - boolean existsByEmail(String email); + boolean existsByEmailAndAuthType(String email, AuthType authType); boolean existsByNickname(String nickname); @Query("SELECT u FROM SiteUser u WHERE u.quitedAt <= :cutoffDate") List findUsersToBeRemoved(@Param("cutoffDate") LocalDate cutoffDate); - - default SiteUser getByEmail(String email) { - return findByEmail(email) - .orElseThrow(() -> new CustomException(USER_NOT_FOUND)); - } } diff --git a/src/main/java/com/example/solidconnection/siteuser/service/SiteUserService.java b/src/main/java/com/example/solidconnection/siteuser/service/SiteUserService.java index a7a2e5d71..c181c2809 100644 --- a/src/main/java/com/example/solidconnection/siteuser/service/SiteUserService.java +++ b/src/main/java/com/example/solidconnection/siteuser/service/SiteUserService.java @@ -42,9 +42,8 @@ public class SiteUserService { * 마이페이지 정보를 조회한다. * */ @Transactional(readOnly = true) - public MyPageResponse getMyPageInfo(String email) { - SiteUser siteUser = siteUserRepository.getByEmail(email); - int likedUniversityCount = likedUniversityRepository.countBySiteUser_Email(email); + public MyPageResponse getMyPageInfo(SiteUser siteUser) { + int likedUniversityCount = likedUniversityRepository.countBySiteUser_Id(siteUser.getId()); return MyPageResponse.of(siteUser, likedUniversityCount); } @@ -52,8 +51,7 @@ public MyPageResponse getMyPageInfo(String email) { * 내 정보를 수정하기 위한 마이페이지 정보를 조회한다. (닉네임, 프로필 사진) * */ @Transactional(readOnly = true) - public MyPageUpdateResponse getMyPageInfoToUpdate(String email) { - SiteUser siteUser = siteUserRepository.getByEmail(email); + public MyPageUpdateResponse getMyPageInfoToUpdate(SiteUser siteUser) { return MyPageUpdateResponse.from(siteUser); } @@ -61,9 +59,8 @@ public MyPageUpdateResponse getMyPageInfoToUpdate(String email) { * 관심 대학교 목록을 조회한다. * */ @Transactional(readOnly = true) - public List getWishUniversity(String email) { - SiteUser siteUser = siteUserRepository.getByEmail(email); - List likedUniversities = likedUniversityRepository.findAllBySiteUser_Email(siteUser.getEmail()); + public List getWishUniversity(SiteUser siteUser) { + List likedUniversities = likedUniversityRepository.findAllBySiteUser_Id(siteUser.getId()); return likedUniversities.stream() .map(likedUniversity -> UniversityInfoForApplyPreviewResponse.from(likedUniversity.getUniversityInfoForApply())) .toList(); @@ -73,13 +70,12 @@ public List getWishUniversity(String emai * 프로필 이미지를 수정한다. * */ @Transactional - public ProfileImageUpdateResponse updateProfileImage(String email, MultipartFile imageFile) { - SiteUser siteUser = siteUserRepository.getByEmail(email); + public ProfileImageUpdateResponse updateProfileImage(SiteUser siteUser, MultipartFile imageFile) { validateProfileImage(imageFile); // 프로필 이미지를 처음 수정하는 경우에는 deleteExProfile 수행하지 않음 if (!isDefaultProfileImage(siteUser.getProfileImageUrl())) { - s3Service.deleteExProfile(email); + s3Service.deleteExProfile(siteUser); } UploadedFileUrlResponse uploadedFileUrlResponse = s3Service.uploadFile(imageFile, ImgType.PROFILE); siteUser.setProfileImageUrl(uploadedFileUrlResponse.fileUrl()); @@ -102,9 +98,7 @@ private boolean isDefaultProfileImage(String profileImageUrl) { * 닉네임을 수정한다. * */ @Transactional - public NicknameUpdateResponse updateNickname(String email, NicknameUpdateRequest nicknameUpdateRequest) { - SiteUser siteUser = siteUserRepository.getByEmail(email); - + public NicknameUpdateResponse updateNickname(SiteUser siteUser, NicknameUpdateRequest nicknameUpdateRequest) { validateNicknameDuplicated(nicknameUpdateRequest.nickname()); validateNicknameNotChangedRecently(siteUser.getNicknameModifiedAt()); diff --git a/src/main/java/com/example/solidconnection/university/controller/UniversityController.java b/src/main/java/com/example/solidconnection/university/controller/UniversityController.java index 1acfcb931..505bfe072 100644 --- a/src/main/java/com/example/solidconnection/university/controller/UniversityController.java +++ b/src/main/java/com/example/solidconnection/university/controller/UniversityController.java @@ -1,5 +1,7 @@ package com.example.solidconnection.university.controller; +import com.example.solidconnection.custom.resolver.AuthorizedUser; +import com.example.solidconnection.siteuser.domain.SiteUser; import com.example.solidconnection.siteuser.service.SiteUserService; import com.example.solidconnection.type.LanguageTestType; import com.example.solidconnection.university.dto.IsLikeResponse; @@ -19,7 +21,6 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; -import java.security.Principal; import java.util.List; @RequiredArgsConstructor @@ -34,42 +35,45 @@ public class UniversityController { @GetMapping("/recommends") public ResponseEntity getUniversityRecommends( - Principal principal) { - if (principal == null) { + @AuthorizedUser SiteUser siteUser + ) { + if (siteUser == null) { return ResponseEntity.ok(universityRecommendService.getGeneralRecommends()); } else { - return ResponseEntity.ok(universityRecommendService.getPersonalRecommends(principal.getName())); + return ResponseEntity.ok(universityRecommendService.getPersonalRecommends(siteUser)); } } @GetMapping("/like") - public ResponseEntity> getMyWishUniversity(Principal principal) { - List wishUniversities - = siteUserService.getWishUniversity(principal.getName()); - return ResponseEntity - .ok(wishUniversities); + public ResponseEntity> getMyWishUniversity( + @AuthorizedUser SiteUser siteUser + ) { + List wishUniversities = siteUserService.getWishUniversity(siteUser); + return ResponseEntity.ok(wishUniversities); } @GetMapping("/{universityInfoForApplyId}/like") public ResponseEntity getIsLiked( - Principal principal, - @PathVariable Long universityInfoForApplyId) { - IsLikeResponse isLiked = universityLikeService.getIsLiked(principal.getName(), universityInfoForApplyId); + @AuthorizedUser SiteUser siteUser, + @PathVariable Long universityInfoForApplyId + ) { + IsLikeResponse isLiked = universityLikeService.getIsLiked(siteUser, universityInfoForApplyId); return ResponseEntity.ok(isLiked); } @PostMapping("/{universityInfoForApplyId}/like") public ResponseEntity addWishUniversity( - Principal principal, - @PathVariable Long universityInfoForApplyId) { - LikeResultResponse likeResultResponse = universityLikeService.likeUniversity(principal.getName(), universityInfoForApplyId); - return ResponseEntity - .ok(likeResultResponse); + @AuthorizedUser SiteUser siteUser, + @PathVariable Long universityInfoForApplyId + ) { + LikeResultResponse likeResultResponse = universityLikeService.likeUniversity(siteUser, universityInfoForApplyId); + return ResponseEntity.ok(likeResultResponse); } @GetMapping("/detail/{universityInfoForApplyId}") public ResponseEntity getUniversityDetails( - @PathVariable Long universityInfoForApplyId) { + @PathVariable Long universityInfoForApplyId + ) { UniversityDetailResponse universityDetailResponse = universityQueryService.getUniversityDetail(universityInfoForApplyId); return ResponseEntity.ok(universityDetailResponse); } @@ -80,7 +84,8 @@ public ResponseEntity> searchUnivers @RequestParam(required = false, defaultValue = "") String region, @RequestParam(required = false, defaultValue = "") List keyword, @RequestParam(required = false, defaultValue = "") LanguageTestType testType, - @RequestParam(required = false, defaultValue = "") String testScore) { + @RequestParam(required = false, defaultValue = "") String testScore + ) { List universityInfoForApplyPreviewResponse = universityQueryService.searchUniversity(region, keyword, testType, testScore).universityInfoForApplyPreviewResponses(); return ResponseEntity.ok(universityInfoForApplyPreviewResponse); diff --git a/src/main/java/com/example/solidconnection/university/service/UniversityLikeService.java b/src/main/java/com/example/solidconnection/university/service/UniversityLikeService.java index 4b15e5b8d..d926bc516 100644 --- a/src/main/java/com/example/solidconnection/university/service/UniversityLikeService.java +++ b/src/main/java/com/example/solidconnection/university/service/UniversityLikeService.java @@ -2,7 +2,6 @@ import com.example.solidconnection.siteuser.domain.SiteUser; import com.example.solidconnection.siteuser.repository.LikedUniversityRepository; -import com.example.solidconnection.siteuser.repository.SiteUserRepository; import com.example.solidconnection.university.domain.LikedUniversity; import com.example.solidconnection.university.domain.UniversityInfoForApply; import com.example.solidconnection.university.dto.IsLikeResponse; @@ -24,7 +23,6 @@ public class UniversityLikeService { private final UniversityInfoForApplyRepository universityInfoForApplyRepository; private final LikedUniversityRepository likedUniversityRepository; - private final SiteUserRepository siteUserRepository; @Value("${university.term}") public String term; @@ -34,8 +32,7 @@ public class UniversityLikeService { * - 이미 좋아요가 눌러져있다면, 좋아요를 취소한다. * */ @Transactional - public LikeResultResponse likeUniversity(String email, Long universityInfoForApplyId) { - SiteUser siteUser = siteUserRepository.getByEmail(email); + public LikeResultResponse likeUniversity(SiteUser siteUser, Long universityInfoForApplyId) { UniversityInfoForApply universityInfoForApply = universityInfoForApplyRepository.getUniversityInfoForApplyById(universityInfoForApplyId); Optional alreadyLikedUniversity = likedUniversityRepository.findBySiteUserAndUniversityInfoForApply(siteUser, universityInfoForApply); @@ -56,8 +53,7 @@ public LikeResultResponse likeUniversity(String email, Long universityInfoForApp * '좋아요'한 대학교인지 확인한다. * */ @Transactional(readOnly = true) - public IsLikeResponse getIsLiked(String email, Long universityInfoForApplyId) { - SiteUser siteUser = siteUserRepository.getByEmail(email); + public IsLikeResponse getIsLiked(SiteUser siteUser, Long universityInfoForApplyId) { UniversityInfoForApply universityInfoForApply = universityInfoForApplyRepository.getUniversityInfoForApplyById(universityInfoForApplyId); boolean isLike = likedUniversityRepository.findBySiteUserAndUniversityInfoForApply(siteUser, universityInfoForApply).isPresent(); return new IsLikeResponse(isLike); diff --git a/src/main/java/com/example/solidconnection/university/service/UniversityRecommendService.java b/src/main/java/com/example/solidconnection/university/service/UniversityRecommendService.java index 654b08390..4d9ab6242 100644 --- a/src/main/java/com/example/solidconnection/university/service/UniversityRecommendService.java +++ b/src/main/java/com/example/solidconnection/university/service/UniversityRecommendService.java @@ -2,7 +2,6 @@ import com.example.solidconnection.cache.annotation.ThunderingHerdCaching; import com.example.solidconnection.siteuser.domain.SiteUser; -import com.example.solidconnection.siteuser.repository.SiteUserRepository; import com.example.solidconnection.university.domain.UniversityInfoForApply; import com.example.solidconnection.university.dto.UniversityInfoForApplyPreviewResponse; import com.example.solidconnection.university.dto.UniversityRecommendsResponse; @@ -24,7 +23,6 @@ public class UniversityRecommendService { private final UniversityInfoForApplyRepository universityInfoForApplyRepository; private final GeneralUniversityRecommendService generalUniversityRecommendService; - private final SiteUserRepository siteUserRepository; @Value("${university.term}") private String term; @@ -36,8 +34,7 @@ public class UniversityRecommendService { * - 맞춤 추천 대학교의 수가 6개보다 적다면, 공통 추천 대학교 후보에서 이번 term 에 열리는 학교들을 부족한 수 만큼 불러온다. * */ @Transactional(readOnly = true) - public UniversityRecommendsResponse getPersonalRecommends(String email) { - SiteUser siteUser = siteUserRepository.getByEmail(email); + public UniversityRecommendsResponse getPersonalRecommends(SiteUser siteUser) { // 맞춤 추천 대학교를 불러온다. List personalRecommends = universityInfoForApplyRepository .findUniversityInfoForAppliesBySiteUsersInterestedCountryOrRegionAndTerm(siteUser, term); diff --git a/src/main/java/com/example/solidconnection/util/RedisUtils.java b/src/main/java/com/example/solidconnection/util/RedisUtils.java index 6c56fa73f..ed67acac0 100644 --- a/src/main/java/com/example/solidconnection/util/RedisUtils.java +++ b/src/main/java/com/example/solidconnection/util/RedisUtils.java @@ -44,8 +44,8 @@ public String getPostViewCountRedisKey(Long postId) { return VIEW_COUNT_KEY_PREFIX.getValue() + postId; } - public String getValidatePostViewCountRedisKey(String email, Long postId) { - return VALIDATE_VIEW_COUNT_KEY_PREFIX.getValue() + postId + ":" + email; + public String getValidatePostViewCountRedisKey(long siteUserId, Long postId) { + return VALIDATE_VIEW_COUNT_KEY_PREFIX.getValue() + postId + ":" + siteUserId; } public Long getPostIdFromPostViewCountRedisKey(String key) { diff --git a/src/test/java/com/example/solidconnection/application/service/ApplicationQueryServiceTest.java b/src/test/java/com/example/solidconnection/application/service/ApplicationQueryServiceTest.java index b8f5cd283..f06116ebb 100644 --- a/src/test/java/com/example/solidconnection/application/service/ApplicationQueryServiceTest.java +++ b/src/test/java/com/example/solidconnection/application/service/ApplicationQueryServiceTest.java @@ -26,7 +26,7 @@ class 지원자_목록_조회_테스트 { void 이번_학기_전체_지원자를_조회한다() { // when ApplicationsResponse response = applicationQueryService.getApplicants( - 테스트유저_2.getEmail(), + 테스트유저_2, "", "" ); @@ -72,7 +72,7 @@ class 지원자_목록_조회_테스트 { void 이번_학기_특정_지역_지원자를_조회한다() { // when ApplicationsResponse response = applicationQueryService.getApplicants( - 테스트유저_2.getEmail(), + 테스트유저_2, 영미권.getCode(), "" ); @@ -99,7 +99,7 @@ class 지원자_목록_조회_테스트 { void 이번_학기_지원자를_대학_국문_이름으로_필터링해서_조회한다() { // when ApplicationsResponse response = applicationQueryService.getApplicants( - 테스트유저_2.getEmail(), + 테스트유저_2, null, "일본" ); @@ -124,7 +124,7 @@ class 지원자_목록_조회_테스트 { void 이전_학기_지원자는_조회되지_않는다() { // when ApplicationsResponse response = applicationQueryService.getApplicants( - 테스트유저_1.getEmail(), + 테스트유저_1, "", "" ); @@ -152,7 +152,7 @@ class 경쟁자_목록_조회_테스트 { void 이번_학기_지원한_대학의_경쟁자_목록을_조회한다() { // when ApplicationsResponse response = applicationQueryService.getApplicantsByUserApplications( - 테스트유저_2.getEmail() + 테스트유저_2 ); // then @@ -180,7 +180,7 @@ class 경쟁자_목록_조회_테스트 { void 이번_학기_지원한_대학_중_미선택이_있을_때_경쟁자_목록을_조회한다() { // when ApplicationsResponse response = applicationQueryService.getApplicantsByUserApplications( - 테스트유저_7.getEmail() + 테스트유저_7 ); // then @@ -202,7 +202,7 @@ class 경쟁자_목록_조회_테스트 { void 이번_학기_지원한_대학이_모두_미선택일_때_경쟁자_목록을_조회한다() { //when ApplicationsResponse response = applicationQueryService.getApplicantsByUserApplications( - 테스트유저_6.getEmail() + 테스트유저_6 ); // then diff --git a/src/test/java/com/example/solidconnection/application/service/ApplicationSubmissionServiceTest.java b/src/test/java/com/example/solidconnection/application/service/ApplicationSubmissionServiceTest.java index 84f130d54..911172bfd 100644 --- a/src/test/java/com/example/solidconnection/application/service/ApplicationSubmissionServiceTest.java +++ b/src/test/java/com/example/solidconnection/application/service/ApplicationSubmissionServiceTest.java @@ -58,7 +58,7 @@ class ApplicationSubmissionServiceTest extends BaseIntegrationTest { ApplyRequest request = new ApplyRequest(gpaScore.getId(), languageTestScore.getId(), universityChoiceRequest); // when - boolean result = applicationSubmissionService.apply(테스트유저_1.getEmail(), request); + boolean result = applicationSubmissionService.apply(테스트유저_1, request); // then Application savedApplication = applicationRepository.findBySiteUserAndTerm(테스트유저_1, term).orElseThrow(); @@ -92,7 +92,7 @@ class ApplicationSubmissionServiceTest extends BaseIntegrationTest { // when & then assertThatCode(() -> - applicationSubmissionService.apply(테스트유저_1.getEmail(), request) + applicationSubmissionService.apply(테스트유저_1, request) ) .isInstanceOf(CustomException.class) .hasMessage(INVALID_GPA_SCORE_STATUS.getMessage()); @@ -112,7 +112,7 @@ class ApplicationSubmissionServiceTest extends BaseIntegrationTest { // when & then assertThatCode(() -> - applicationSubmissionService.apply(테스트유저_1.getEmail(), request) + applicationSubmissionService.apply(테스트유저_1, request) ) .isInstanceOf(CustomException.class) .hasMessage(INVALID_LANGUAGE_TEST_SCORE_STATUS.getMessage()); @@ -132,7 +132,7 @@ class ApplicationSubmissionServiceTest extends BaseIntegrationTest { // when & then assertThatCode(() -> - applicationSubmissionService.apply(테스트유저_1.getEmail(), request) + applicationSubmissionService.apply(테스트유저_1, request) ) .isInstanceOf(CustomException.class) .hasMessage(CANT_APPLY_FOR_SAME_UNIVERSITY.getMessage()); @@ -151,12 +151,12 @@ class ApplicationSubmissionServiceTest extends BaseIntegrationTest { ApplyRequest request = new ApplyRequest(gpaScore.getId(), languageTestScore.getId(), universityChoiceRequest); for (int i = 0; i < APPLICATION_UPDATE_COUNT_LIMIT + 1; i++) { - applicationSubmissionService.apply(테스트유저_1.getEmail(), request); + applicationSubmissionService.apply(테스트유저_1, request); } // when & then assertThatCode(() -> - applicationSubmissionService.apply(테스트유저_1.getEmail(), request) + applicationSubmissionService.apply(테스트유저_1, request) ) .isInstanceOf(CustomException.class) .hasMessage(APPLY_UPDATE_LIMIT_EXCEED.getMessage()); diff --git a/src/test/java/com/example/solidconnection/comment/service/CommentServiceTest.java b/src/test/java/com/example/solidconnection/comment/service/CommentServiceTest.java index 418a04d8c..d38463dcb 100644 --- a/src/test/java/com/example/solidconnection/comment/service/CommentServiceTest.java +++ b/src/test/java/com/example/solidconnection/comment/service/CommentServiceTest.java @@ -56,7 +56,7 @@ class 댓글_조회_테스트 { // when List responses = commentService.findCommentsByPostId( - 테스트유저_1.getEmail(), + 테스트유저_1, testPost.getId() ); @@ -114,7 +114,7 @@ class 댓글_생성_테스트 { // when CommentCreateResponse response = commentService.createComment( - 테스트유저_1.getEmail(), + 테스트유저_1, testPost.getId(), request ); @@ -139,7 +139,7 @@ class 댓글_생성_테스트 { // when CommentCreateResponse response = commentService.createComment( - 테스트유저_2.getEmail(), + 테스트유저_2, testPost.getId(), request ); @@ -166,7 +166,7 @@ class 댓글_생성_테스트 { // when & then assertThatThrownBy(() -> commentService.createComment( - 테스트유저_1.getEmail(), + 테스트유저_1, testPost.getId(), request )) @@ -184,7 +184,7 @@ class 댓글_생성_테스트 { // when & then assertThatThrownBy(() -> commentService.createComment( - 테스트유저_1.getEmail(), + 테스트유저_1, testPost.getId(), request )) @@ -205,7 +205,7 @@ class 댓글_수정_테스트 { // when CommentUpdateResponse response = commentService.updateComment( - 테스트유저_1.getEmail(), + 테스트유저_1, testPost.getId(), comment.getId(), request @@ -232,7 +232,7 @@ class 댓글_수정_테스트 { // when & then assertThatThrownBy(() -> commentService.updateComment( - 테스트유저_2.getEmail(), + 테스트유저_2, testPost.getId(), comment.getId(), request @@ -251,7 +251,7 @@ class 댓글_수정_테스트 { // when & then assertThatThrownBy(() -> commentService.updateComment( - 테스트유저_1.getEmail(), + 테스트유저_1, testPost.getId(), comment.getId(), request @@ -275,7 +275,7 @@ class 댓글_삭제_테스트 { // when CommentDeleteResponse response = commentService.deleteCommentById( - 테스트유저_1.getEmail(), + 테스트유저_1, testPost.getId(), comment.getId() ); @@ -300,7 +300,7 @@ class 댓글_삭제_테스트 { // when CommentDeleteResponse response = commentService.deleteCommentById( - 테스트유저_1.getEmail(), + 테스트유저_1, testPost.getId(), parentComment.getId() ); @@ -330,7 +330,7 @@ class 댓글_삭제_테스트 { // when CommentDeleteResponse response = commentService.deleteCommentById( - 테스트유저_2.getEmail(), + 테스트유저_2, testPost.getId(), childComment1.getId() ); @@ -361,7 +361,7 @@ class 댓글_삭제_테스트 { // when CommentDeleteResponse response = commentService.deleteCommentById( - 테스트유저_2.getEmail(), + 테스트유저_2, testPost.getId(), childComment.getId() ); @@ -383,7 +383,7 @@ class 댓글_삭제_테스트 { // when & then assertThatThrownBy(() -> commentService.deleteCommentById( - 테스트유저_2.getEmail(), + 테스트유저_2, testPost.getId(), comment.getId() )) diff --git a/src/test/java/com/example/solidconnection/concurrency/PostLikeCountConcurrencyTest.java b/src/test/java/com/example/solidconnection/concurrency/PostLikeCountConcurrencyTest.java index 36bd91819..544b31b4c 100644 --- a/src/test/java/com/example/solidconnection/concurrency/PostLikeCountConcurrencyTest.java +++ b/src/test/java/com/example/solidconnection/concurrency/PostLikeCountConcurrencyTest.java @@ -4,7 +4,6 @@ import com.example.solidconnection.board.repository.BoardRepository; import com.example.solidconnection.post.domain.Post; import com.example.solidconnection.post.repository.PostRepository; -import com.example.solidconnection.post.service.PostCommandService; import com.example.solidconnection.post.service.PostLikeService; import com.example.solidconnection.siteuser.domain.SiteUser; import com.example.solidconnection.siteuser.repository.SiteUserRepository; @@ -24,6 +23,7 @@ import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; +import static com.example.solidconnection.e2e.DynamicFixture.createSiteUserByEmail; import static org.junit.jupiter.api.Assertions.assertEquals; @TestContainerSpringBootTest @@ -57,7 +57,6 @@ void setUp() { siteUserRepository.save(siteUser); post = createPost(board, siteUser); postRepository.save(post); - createSiteUsers(); } private SiteUser createSiteUser() { @@ -72,22 +71,6 @@ private SiteUser createSiteUser() { ); } - private void createSiteUsers() { - for (int i = 0; i < 1000; i++) { - - SiteUser siteUser = new SiteUser( - "email" + i, - "nickname", - "profileImageUrl", - "1999-01-01", - PreparationStatus.CONSIDERING, - Role.MENTEE, - Gender.MALE - ); - siteUserRepository.save(siteUser); - } - } - private Board createBoard() { return new Board( "FREE", "자유게시판"); @@ -117,10 +100,11 @@ private Post createPost(Board board, SiteUser siteUser) { for (int i = 0; i < THREAD_NUMS; i++) { String email = "email" + i; + SiteUser tmpSiteUser = siteUserRepository.save(createSiteUserByEmail(email)); executorService.submit(() -> { try { - postLikeService.likePost(email, board.getCode(), post.getId()); - postLikeService.dislikePost(email, board.getCode(), post.getId()); + postLikeService.likePost(tmpSiteUser, board.getCode(), post.getId()); + postLikeService.dislikePost(tmpSiteUser, board.getCode(), post.getId()); } finally { doneSignal.countDown(); } diff --git a/src/test/java/com/example/solidconnection/concurrency/PostViewCountConcurrencyTest.java b/src/test/java/com/example/solidconnection/concurrency/PostViewCountConcurrencyTest.java index dcd423168..678e2b084 100644 --- a/src/test/java/com/example/solidconnection/concurrency/PostViewCountConcurrencyTest.java +++ b/src/test/java/com/example/solidconnection/concurrency/PostViewCountConcurrencyTest.java @@ -96,7 +96,7 @@ private Post createPost(Board board, SiteUser siteUser) { @Test public void 게시글을_조회할_때_조회수_동시성_문제를_해결한다() throws InterruptedException { - redisService.deleteKey(redisUtils.getValidatePostViewCountRedisKey(siteUser.getEmail(), post.getId())); + redisService.deleteKey(redisUtils.getValidatePostViewCountRedisKey(siteUser.getId(), post.getId())); ExecutorService executorService = Executors.newFixedThreadPool(THREAD_POOL_SIZE); CountDownLatch doneSignal = new CountDownLatch(THREAD_NUMS); @@ -126,7 +126,7 @@ private Post createPost(Board board, SiteUser siteUser) { @Test public void 게시글을_조회할_때_조회수_조작_문제를_해결한다() throws InterruptedException { - redisService.deleteKey(redisUtils.getValidatePostViewCountRedisKey(siteUser.getEmail(), post.getId())); + redisService.deleteKey(redisUtils.getValidatePostViewCountRedisKey(siteUser.getId(), post.getId())); ExecutorService executorService = Executors.newFixedThreadPool(THREAD_POOL_SIZE); CountDownLatch doneSignal = new CountDownLatch(THREAD_NUMS); @@ -134,7 +134,7 @@ private Post createPost(Board board, SiteUser siteUser) { for (int i = 0; i < THREAD_NUMS; i++) { executorService.submit(() -> { try { - boolean isFirstTime = redisService.isPresent(redisUtils.getValidatePostViewCountRedisKey(siteUser.getEmail(), post.getId())); + boolean isFirstTime = redisService.isPresent(redisUtils.getValidatePostViewCountRedisKey(siteUser.getId(), post.getId())); if (isFirstTime) { redisService.increaseViewCount(redisUtils.getPostViewCountRedisKey(post.getId())); } @@ -147,7 +147,7 @@ private Post createPost(Board board, SiteUser siteUser) { for (int i = 0; i < THREAD_NUMS; i++) { executorService.submit(() -> { try { - boolean isFirstTime = redisService.isPresent(redisUtils.getValidatePostViewCountRedisKey(siteUser.getEmail(), post.getId())); + boolean isFirstTime = redisService.isPresent(redisUtils.getValidatePostViewCountRedisKey(siteUser.getId(), post.getId())); if (isFirstTime) { redisService.increaseViewCount(redisUtils.getPostViewCountRedisKey(post.getId())); } diff --git a/src/test/java/com/example/solidconnection/concurrency/ThunderingHerdTest.java b/src/test/java/com/example/solidconnection/concurrency/ThunderingHerdTest.java index dce720610..35ab993f5 100644 --- a/src/test/java/com/example/solidconnection/concurrency/ThunderingHerdTest.java +++ b/src/test/java/com/example/solidconnection/concurrency/ThunderingHerdTest.java @@ -66,9 +66,9 @@ private SiteUser createSiteUser() { executorService.submit(() -> { try { List tasks = Arrays.asList( - () -> applicationQueryService.getApplicants(siteUser.getEmail(), "", ""), - () -> applicationQueryService.getApplicants(siteUser.getEmail(), "ASIA", ""), - () -> applicationQueryService.getApplicants(siteUser.getEmail(), "", "추오") + () -> applicationQueryService.getApplicants(siteUser, "", ""), + () -> applicationQueryService.getApplicants(siteUser, "ASIA", ""), + () -> applicationQueryService.getApplicants(siteUser, "", "추오") ); Collections.shuffle(tasks); tasks.forEach(Runnable::run); diff --git a/src/test/java/com/example/solidconnection/config/security/JwtAuthenticationFilterTest.java b/src/test/java/com/example/solidconnection/config/security/JwtAuthenticationFilterTest.java deleted file mode 100644 index 16e3639f1..000000000 --- a/src/test/java/com/example/solidconnection/config/security/JwtAuthenticationFilterTest.java +++ /dev/null @@ -1,126 +0,0 @@ -package com.example.solidconnection.config.security; - -import com.example.solidconnection.custom.exception.CustomException; -import com.example.solidconnection.support.TestContainerSpringBootTest; -import io.jsonwebtoken.Jwts; -import io.jsonwebtoken.SignatureAlgorithm; -import jakarta.servlet.FilterChain; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.mock.web.MockHttpServletRequest; -import org.springframework.mock.web.MockHttpServletResponse; -import org.springframework.security.core.context.SecurityContextHolder; - -import java.util.Date; - -import static com.example.solidconnection.custom.exception.ErrorCode.INVALID_TOKEN; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatCode; -import static org.mockito.BDDMockito.then; -import static org.mockito.Mockito.spy; - -@TestContainerSpringBootTest -@DisplayName("토큰 인증 필터 테스트") -class JwtAuthenticationFilterTest { - - @Autowired - private JwtAuthenticationFilter jwtAuthenticationFilter; - - @Autowired - private JwtProperties jwtProperties; - - private HttpServletRequest request; - private HttpServletResponse response; - private FilterChain filterChain; - - @BeforeEach - void setUp() { - response = new MockHttpServletResponse(); - filterChain = spy(FilterChain.class); - SecurityContextHolder.clearContext(); - } - - @Test - public void 유효한_토큰에_대한_인증_정보를_저장한다() throws Exception { - // given - String token = Jwts.builder() - .setSubject("subject") - .setIssuedAt(new Date()) - .setExpiration(new Date(System.currentTimeMillis() + 1000)) - .signWith(SignatureAlgorithm.HS256, jwtProperties.secret()) - .compact(); - request = createRequestWithToken(token); - - // when - jwtAuthenticationFilter.doFilterInternal(request, response, filterChain); - - // then - assertThat(SecurityContextHolder.getContext().getAuthentication()) - .isExactlyInstanceOf(JwtAuthentication.class); - then(filterChain).should().doFilter(request, response); - } - - @Test - public void 토큰이_없으면_다음_필터로_진행한다() throws Exception { - // given - request = new MockHttpServletRequest(); - - // when - jwtAuthenticationFilter.doFilterInternal(request, response, filterChain); - - // then - assertThat(SecurityContextHolder.getContext().getAuthentication()).isNull(); - then(filterChain).should().doFilter(request, response); - } - - @Nested - class 유효하지_않은_토큰으로_인증하면_예외를_응답한다 { - - @Test - public void 만료된_토큰으로_인증하면_예외를_응답한다() throws Exception { - // given - String token = Jwts.builder() - .setSubject("subject") - .setIssuedAt(new Date()) - .setExpiration(new Date(System.currentTimeMillis() - 1000)) - .signWith(SignatureAlgorithm.HS256, jwtProperties.secret()) - .compact(); - request = createRequestWithToken(token); - - // when & then - assertThatCode(() -> jwtAuthenticationFilter.doFilterInternal(request, response, filterChain)) - .isInstanceOf(CustomException.class) - .hasMessage(INVALID_TOKEN.getMessage()); - then(filterChain).shouldHaveNoMoreInteractions(); - } - - @Test - public void 서명하지_않은_토큰으로_인증하면_예외를_응답한다() throws Exception { - // given - String token = Jwts.builder() - .setSubject("subject") - .setIssuedAt(new Date()) - .setExpiration(new Date(System.currentTimeMillis() - 1000)) - .signWith(SignatureAlgorithm.HS256, "wrongSecretKey") - .compact(); - request = createRequestWithToken(token); - - // when & then - assertThatCode(() -> jwtAuthenticationFilter.doFilterInternal(request, response, filterChain)) - .isInstanceOf(CustomException.class) - .hasMessage(INVALID_TOKEN.getMessage()); - then(filterChain).shouldHaveNoMoreInteractions(); - } - } - - private HttpServletRequest createRequestWithToken(String token) { - MockHttpServletRequest request = new MockHttpServletRequest(); - request.addHeader("Authorization", "Bearer " + token); - return request; - } -} diff --git a/src/test/java/com/example/solidconnection/custom/resolver/AuthorizedUserResolverTest.java b/src/test/java/com/example/solidconnection/custom/resolver/AuthorizedUserResolverTest.java new file mode 100644 index 000000000..763fdf101 --- /dev/null +++ b/src/test/java/com/example/solidconnection/custom/resolver/AuthorizedUserResolverTest.java @@ -0,0 +1,67 @@ +package com.example.solidconnection.custom.resolver; + + +import com.example.solidconnection.custom.security.authentication.SiteUserAuthentication; +import com.example.solidconnection.custom.security.userdetails.SiteUserDetails; +import com.example.solidconnection.siteuser.domain.SiteUser; +import com.example.solidconnection.siteuser.repository.SiteUserRepository; +import com.example.solidconnection.support.TestContainerSpringBootTest; +import com.example.solidconnection.type.Gender; +import com.example.solidconnection.type.PreparationStatus; +import com.example.solidconnection.type.Role; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.context.SecurityContextHolder; + +import static org.assertj.core.api.Assertions.assertThat; + +@TestContainerSpringBootTest +@DisplayName("인증된 사용자 argument resolver 테스트") +class AuthorizedUserResolverTest { + + @Autowired + private AuthorizedUserResolver authorizedUserResolver; + + @Autowired + private SiteUserRepository siteUserRepository; + + @BeforeEach + void setUp() { + SecurityContextHolder.clearContext(); + } + + @Test + void security_context_에_저장된_인증된_사용자를_반환한다() throws Exception { + // given + SiteUser siteUser = siteUserRepository.save(createSiteUser()); + SiteUserDetails userDetails = new SiteUserDetails(siteUser); + SiteUserAuthentication authentication = new SiteUserAuthentication("token", userDetails); + SecurityContextHolder.getContext().setAuthentication(authentication); + + // when + SiteUser resolveSiteUser = (SiteUser) authorizedUserResolver.resolveArgument(null, null, null, null); + + // then + assertThat(resolveSiteUser).isEqualTo(siteUser); + } + + @Test + void security_context_에_저장된_사용자가_없으면_null_을_반환한다() throws Exception { + // when, then + assertThat(authorizedUserResolver.resolveArgument(null, null, null, null)).isNull(); + } + + private SiteUser createSiteUser() { + return new SiteUser( + "test@example.com", + "nickname", + "profileImageUrl", + "1999-01-01", + PreparationStatus.CONSIDERING, + Role.MENTEE, + Gender.MALE + ); + } +} diff --git a/src/test/java/com/example/solidconnection/custom/resolver/ExpiredTokenResolverTest.java b/src/test/java/com/example/solidconnection/custom/resolver/ExpiredTokenResolverTest.java new file mode 100644 index 000000000..a0393dbc7 --- /dev/null +++ b/src/test/java/com/example/solidconnection/custom/resolver/ExpiredTokenResolverTest.java @@ -0,0 +1,43 @@ +package com.example.solidconnection.custom.resolver; + +import com.example.solidconnection.custom.security.authentication.ExpiredTokenAuthentication; +import com.example.solidconnection.support.TestContainerSpringBootTest; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.context.SecurityContextHolder; + +import static org.assertj.core.api.Assertions.assertThat; + +@TestContainerSpringBootTest +@DisplayName("만료된 토큰 argument resolver 테스트") +class ExpiredTokenResolverTest { + + @BeforeEach + void setUp() { + SecurityContextHolder.clearContext(); + } + + @Autowired + private ExpiredTokenResolver expiredTokenResolver; + + @Test + void security_context_에_저장된_만료시간을_검증하지_않는_토큰을_반환한다() throws Exception { + // given + ExpiredTokenAuthentication authentication = new ExpiredTokenAuthentication("token"); + SecurityContextHolder.getContext().setAuthentication(authentication); + + // when + ExpiredTokenAuthentication expiredTokenAuthentication = (ExpiredTokenAuthentication) expiredTokenResolver.resolveArgument(null, null, null, null); + + // then + assertThat(expiredTokenAuthentication.getToken()).isEqualTo("token"); + } + + @Test + void security_context_에_저장된_만료시간을_검증하지_않는_토큰이_없으면_null_을_반환한다() throws Exception { + // when, then + assertThat(expiredTokenResolver.resolveArgument(null, null, null, null)).isNull(); + } +} diff --git a/src/test/java/com/example/solidconnection/custom/security/authentication/ExpiredTokenAuthenticationTest.java b/src/test/java/com/example/solidconnection/custom/security/authentication/ExpiredTokenAuthenticationTest.java new file mode 100644 index 000000000..9ef78d0c7 --- /dev/null +++ b/src/test/java/com/example/solidconnection/custom/security/authentication/ExpiredTokenAuthenticationTest.java @@ -0,0 +1,64 @@ +package com.example.solidconnection.custom.security.authentication; + +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.Date; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertAll; + +@DisplayName("만료된 토큰 인증 정보 테스트") +class ExpiredTokenAuthenticationTest { + + @Test + void 인증_정보에_저장된_토큰을_반환한다() { + // given + String token = "token123"; + ExpiredTokenAuthentication auth = new ExpiredTokenAuthentication(token); + + // when + String result = auth.getToken(); + + // then + assertThat(result).isEqualTo(token); + } + + @Test + void 인증_정보에_저장된_토큰의_subject_를_반환한다() { + // given + String subject = "subject321"; + String token = createToken(subject); + ExpiredTokenAuthentication auth = new ExpiredTokenAuthentication(token, subject); + + // when + String result = auth.getSubject(); + + // then + assertThat(result).isEqualTo(subject); + } + + @Test + void 항상_isAuthenticated_는_false_를_반환한다() { + // given + ExpiredTokenAuthentication auth1 = new ExpiredTokenAuthentication("token"); + ExpiredTokenAuthentication auth2 = new ExpiredTokenAuthentication("token", "subject"); + + // when & then + assertAll( + () -> assertThat(auth1.isAuthenticated()).isFalse(), + () -> assertThat(auth2.isAuthenticated()).isFalse() + ); + } + + private String createToken(String subject) { + return Jwts.builder() + .setSubject(subject) + .setIssuedAt(new Date()) + .setExpiration(new Date(System.currentTimeMillis() + 1000)) + .signWith(SignatureAlgorithm.HS256, "secret") + .compact(); + } +} diff --git a/src/test/java/com/example/solidconnection/custom/security/authentication/SiteUserAuthenticationTest.java b/src/test/java/com/example/solidconnection/custom/security/authentication/SiteUserAuthenticationTest.java new file mode 100644 index 000000000..6932fcd28 --- /dev/null +++ b/src/test/java/com/example/solidconnection/custom/security/authentication/SiteUserAuthenticationTest.java @@ -0,0 +1,73 @@ +package com.example.solidconnection.custom.security.authentication; + +import com.example.solidconnection.custom.security.userdetails.SiteUserDetails; +import com.example.solidconnection.siteuser.domain.SiteUser; +import com.example.solidconnection.type.Gender; +import com.example.solidconnection.type.PreparationStatus; +import com.example.solidconnection.type.Role; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class SiteUserAuthenticationTest { + + @Test + void 인증_정보에_저장된_토큰을_반환한다() { + // given + String token = "token"; + SiteUserAuthentication authentication = new SiteUserAuthentication(token); + + // when + String result = authentication.getToken(); + + // then + assertThat(result).isEqualTo(token); + } + + @Test + void 인증_정보에_저장된_사용자를_반환한다() { + // given + SiteUserDetails userDetails = new SiteUserDetails(createSiteUser()); + SiteUserAuthentication authentication = new SiteUserAuthentication("token", userDetails); + + // when & then + SiteUserDetails actual = (SiteUserDetails) authentication.getPrincipal(); + + // then + assertThat(actual) + .extracting("siteUser") + .extracting("id") + .isEqualTo(userDetails.getSiteUser().getId()); + } + + @Test + void 인증_전에_생성되면_isAuthenticated_는_false_를_반환한다() { + // given + SiteUserAuthentication authentication = new SiteUserAuthentication("token"); + + // when & then + assertThat(authentication.isAuthenticated()).isFalse(); + } + + @Test + void 인증_후에_생성되면_isAuthenticated_는_true_를_반환한다() { + // given + SiteUserDetails userDetails = new SiteUserDetails(createSiteUser()); + SiteUserAuthentication authentication = new SiteUserAuthentication("token", userDetails); + + // when & then + assertThat(authentication.isAuthenticated()).isTrue(); + } + + private SiteUser createSiteUser() { + return new SiteUser( + "test@example.com", + "nickname", + "profileImageUrl", + "1999-01-01", + PreparationStatus.CONSIDERING, + Role.MENTEE, + Gender.MALE + ); + } +} diff --git a/src/test/java/com/example/solidconnection/config/security/ExceptionHandlerFilterTest.java b/src/test/java/com/example/solidconnection/custom/security/filter/ExceptionHandlerFilterTest.java similarity index 98% rename from src/test/java/com/example/solidconnection/config/security/ExceptionHandlerFilterTest.java rename to src/test/java/com/example/solidconnection/custom/security/filter/ExceptionHandlerFilterTest.java index f4e8dc666..091a75eb8 100644 --- a/src/test/java/com/example/solidconnection/config/security/ExceptionHandlerFilterTest.java +++ b/src/test/java/com/example/solidconnection/custom/security/filter/ExceptionHandlerFilterTest.java @@ -1,4 +1,4 @@ -package com.example.solidconnection.config.security; +package com.example.solidconnection.custom.security.filter; import com.example.solidconnection.custom.exception.CustomException; import com.example.solidconnection.custom.exception.ErrorCode; diff --git a/src/test/java/com/example/solidconnection/custom/security/filter/JwtAuthenticationFilterTest.java b/src/test/java/com/example/solidconnection/custom/security/filter/JwtAuthenticationFilterTest.java new file mode 100644 index 000000000..cbca9c5f2 --- /dev/null +++ b/src/test/java/com/example/solidconnection/custom/security/filter/JwtAuthenticationFilterTest.java @@ -0,0 +1,116 @@ +package com.example.solidconnection.custom.security.filter; + +import com.example.solidconnection.config.security.JwtProperties; +import com.example.solidconnection.custom.security.authentication.ExpiredTokenAuthentication; +import com.example.solidconnection.custom.security.authentication.SiteUserAuthentication; +import com.example.solidconnection.custom.security.userdetails.SiteUserDetailsService; +import com.example.solidconnection.support.TestContainerSpringBootTest; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; +import jakarta.servlet.FilterChain; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; +import org.springframework.security.core.context.SecurityContextHolder; + +import java.util.Date; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.BDDMockito.then; +import static org.mockito.Mockito.spy; + +@TestContainerSpringBootTest +@DisplayName("토큰 인증 필터 테스트") +class JwtAuthenticationFilterTest { + + @Autowired + private JwtAuthenticationFilter jwtAuthenticationFilter; + + @Autowired + private JwtProperties jwtProperties; + + @MockBean + private SiteUserDetailsService siteUserDetailsService; + + private HttpServletRequest request; + private HttpServletResponse response; + private FilterChain filterChain; + + @BeforeEach() + void setUp() { + response = new MockHttpServletResponse(); + filterChain = spy(FilterChain.class); + SecurityContextHolder.clearContext(); + } + + @Test + public void 토큰이_없으면_다음_필터로_진행한다() throws Exception { + // given + request = new MockHttpServletRequest(); + + // when + jwtAuthenticationFilter.doFilterInternal(request, response, filterChain); + + // then + assertThat(SecurityContextHolder.getContext().getAuthentication()).isNull(); + then(filterChain).should().doFilter(request, response); + } + + @Nested + class 토큰이_있으면_컨텍스트에_저장한다 { + + @Test + void 유효한_토큰을_컨텍스트에_저장한다() throws Exception { + // given + Date validExpiration = new Date(System.currentTimeMillis() + 1000); + String token = createTokenWithExpiration(validExpiration); + request = createRequestWithToken(token); + + // when + jwtAuthenticationFilter.doFilterInternal(request, response, filterChain); + + // then + assertThat(SecurityContextHolder.getContext().getAuthentication()) + .isExactlyInstanceOf(SiteUserAuthentication.class); + then(filterChain).should().doFilter(request, response); + } + + @Test + void 만료된_토큰을_컨텍스트에_저장한다() throws Exception { + // given + Date invalidExpiration = new Date(System.currentTimeMillis() - 1000); + String token = createTokenWithExpiration(invalidExpiration); + request = createRequestWithToken(token); + + // when + jwtAuthenticationFilter.doFilterInternal(request, response, filterChain); + + // then + assertThat(SecurityContextHolder.getContext().getAuthentication()) + .isExactlyInstanceOf(ExpiredTokenAuthentication.class); + then(filterChain).should().doFilter(request, response); + } + } + + private String createTokenWithExpiration(Date expiration) { + return Jwts.builder() + .setSubject("1") + .setIssuedAt(new Date()) + .setExpiration(expiration) + .signWith(SignatureAlgorithm.HS256, jwtProperties.secret()) + .compact(); + } + + private HttpServletRequest createRequestWithToken(String token) { + MockHttpServletRequest request = new MockHttpServletRequest(); + request.addHeader("Authorization", "Bearer " + token); + return request; + } +} diff --git a/src/test/java/com/example/solidconnection/config/security/SignOutCheckFilterTest.java b/src/test/java/com/example/solidconnection/custom/security/filter/SignOutCheckFilterTest.java similarity index 96% rename from src/test/java/com/example/solidconnection/config/security/SignOutCheckFilterTest.java rename to src/test/java/com/example/solidconnection/custom/security/filter/SignOutCheckFilterTest.java index a067bf9d9..7eac22c71 100644 --- a/src/test/java/com/example/solidconnection/config/security/SignOutCheckFilterTest.java +++ b/src/test/java/com/example/solidconnection/custom/security/filter/SignOutCheckFilterTest.java @@ -1,5 +1,6 @@ -package com.example.solidconnection.config.security; +package com.example.solidconnection.custom.security.filter; +import com.example.solidconnection.config.security.JwtProperties; import com.example.solidconnection.custom.exception.CustomException; import com.example.solidconnection.support.TestContainerSpringBootTest; import io.jsonwebtoken.Jwts; diff --git a/src/test/java/com/example/solidconnection/custom/security/provider/ExpiredTokenAuthenticationProviderTest.java b/src/test/java/com/example/solidconnection/custom/security/provider/ExpiredTokenAuthenticationProviderTest.java new file mode 100644 index 000000000..ad6053359 --- /dev/null +++ b/src/test/java/com/example/solidconnection/custom/security/provider/ExpiredTokenAuthenticationProviderTest.java @@ -0,0 +1,80 @@ +package com.example.solidconnection.custom.security.provider; + +import com.example.solidconnection.config.security.JwtProperties; +import com.example.solidconnection.custom.exception.CustomException; +import com.example.solidconnection.custom.security.authentication.ExpiredTokenAuthentication; +import com.example.solidconnection.support.TestContainerSpringBootTest; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.Authentication; + +import java.net.PasswordAuthentication; +import java.util.Date; + +import static com.example.solidconnection.custom.exception.ErrorCode.INVALID_TOKEN; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.junit.jupiter.api.Assertions.*; + +@TestContainerSpringBootTest +@DisplayName("만료된 토큰 provider 테스트") +class ExpiredTokenAuthenticationProviderTest { + + @Autowired + private ExpiredTokenAuthenticationProvider expiredTokenAuthenticationProvider; + + @Autowired + private JwtProperties jwtProperties; + + @Test + void 처리할_수_있는_타입인지를_반환한다() { + // given + Class supportedType = ExpiredTokenAuthentication.class; + Class notSupportedType = PasswordAuthentication.class; + + // when & then + assertAll( + () -> assertTrue(expiredTokenAuthenticationProvider.supports(supportedType)), + () -> assertFalse(expiredTokenAuthenticationProvider.supports(notSupportedType)) + ); + } + + @Test + void 만료된_토큰의_인증_정보를_반환한다() { + // given + String expiredToken = createExpiredToken(); + ExpiredTokenAuthentication ExpiredTokenAuthentication = new ExpiredTokenAuthentication(expiredToken); + + // when + Authentication result = expiredTokenAuthenticationProvider.authenticate(ExpiredTokenAuthentication); + + // then + assertAll( + () -> assertThat(result).isInstanceOf(ExpiredTokenAuthentication.class), + () -> assertThat(result.isAuthenticated()).isFalse() + ); + } + + @Test + void 유효하지_않은_토큰이면_예외_응답을_반환한다() { + // given + ExpiredTokenAuthentication ExpiredTokenAuthentication = new ExpiredTokenAuthentication("invalid token"); + + // when & then + assertThatCode(() -> expiredTokenAuthenticationProvider.authenticate(ExpiredTokenAuthentication)) + .isInstanceOf(CustomException.class) + .hasMessageContaining(INVALID_TOKEN.getMessage()); + } + + private String createExpiredToken() { + return Jwts.builder() + .setSubject("1") + .setIssuedAt(new Date()) + .setExpiration(new Date(System.currentTimeMillis() - 1000)) + .signWith(SignatureAlgorithm.HS256, jwtProperties.secret()) + .compact(); + } +} diff --git a/src/test/java/com/example/solidconnection/custom/security/provider/SiteUserAuthenticationProviderTest.java b/src/test/java/com/example/solidconnection/custom/security/provider/SiteUserAuthenticationProviderTest.java new file mode 100644 index 000000000..46d7498a2 --- /dev/null +++ b/src/test/java/com/example/solidconnection/custom/security/provider/SiteUserAuthenticationProviderTest.java @@ -0,0 +1,159 @@ +package com.example.solidconnection.custom.security.provider; + +import com.example.solidconnection.config.security.JwtProperties; +import com.example.solidconnection.custom.exception.CustomException; +import com.example.solidconnection.custom.security.authentication.SiteUserAuthentication; +import com.example.solidconnection.custom.security.userdetails.SiteUserDetails; +import com.example.solidconnection.siteuser.domain.SiteUser; +import com.example.solidconnection.siteuser.repository.SiteUserRepository; +import com.example.solidconnection.support.TestContainerSpringBootTest; +import com.example.solidconnection.type.Gender; +import com.example.solidconnection.type.PreparationStatus; +import com.example.solidconnection.type.Role; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.Authentication; + +import java.net.PasswordAuthentication; +import java.util.Date; + +import static com.example.solidconnection.custom.exception.ErrorCode.AUTHENTICATION_FAILED; +import static com.example.solidconnection.custom.exception.ErrorCode.INVALID_TOKEN; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.junit.jupiter.api.Assertions.assertAll; + +@TestContainerSpringBootTest +@DisplayName("사용자 인증정보 provider 테스트") +class SiteUserAuthenticationProviderTest { + + @Autowired + private SiteUserAuthenticationProvider siteUserAuthenticationProvider; + + @Autowired + private JwtProperties jwtProperties; + + @Autowired + private SiteUserRepository siteUserRepository; + + private SiteUser siteUser; + + @BeforeEach + void setUp() { + siteUser = createSiteUser(); + siteUserRepository.save(siteUser); + } + + @Test + void 처리할_수_있는_타입인지를_반환한다() { + // given + Class supportedType = SiteUserAuthentication.class; + Class notSupportedType = PasswordAuthentication.class; + + // when & then + assertAll( + () -> assertThat(siteUserAuthenticationProvider.supports(supportedType)).isTrue(), + () -> assertThat(siteUserAuthenticationProvider.supports(notSupportedType)).isFalse() + ); + } + + @Test + void 유효한_토큰이면_정상적으로_인증_정보를_반환한다() { + // given + String token = createValidToken(siteUser.getId()); + SiteUserAuthentication auth = new SiteUserAuthentication(token); + + // when + Authentication result = siteUserAuthenticationProvider.authenticate(auth); + + // then + assertThat(result).isNotNull(); + assertAll( + () -> assertThat(result.getCredentials()).isEqualTo(token), + () -> assertThat(result.getPrincipal().getClass()).isEqualTo(SiteUserDetails.class) + ); + } + + @Nested + class 예외_응답을_반환하다 { + + @Test + void 유효하지_않은_토큰이면_예외_응답을_반환한다() { + // given + SiteUserAuthentication expiredAuth = new SiteUserAuthentication(createExpiredToken()); + + // when & then + assertThatCode(() -> siteUserAuthenticationProvider.authenticate(expiredAuth)) + .isInstanceOf(CustomException.class) + .hasMessageContaining(INVALID_TOKEN.getMessage()); + } + + @Test + void 사용자_정보의_형식이_다르면_예외_응답을_반환한다() { + // given + SiteUserAuthentication wrongSubjectTypeAuth = new SiteUserAuthentication(createWrongSubjectTypeToken()); + + // when & then + assertThatCode(() -> siteUserAuthenticationProvider.authenticate(wrongSubjectTypeAuth)) + .isInstanceOf(CustomException.class) + .hasMessageContaining(INVALID_TOKEN.getMessage()); + } + + @Test + void 유효한_토큰이지만_해당되는_사용자가_없으면_예외_응답을_반환한다() { + // given + long notExistingUserId = siteUser.getId() + 100; + String token = createValidToken(notExistingUserId); + SiteUserAuthentication auth = new SiteUserAuthentication(token); + + // when & then + assertThatCode(() -> siteUserAuthenticationProvider.authenticate(auth)) + .isInstanceOf(CustomException.class) + .hasMessageContaining(AUTHENTICATION_FAILED.getMessage()); + } + } + + private String createValidToken(long id) { + return Jwts.builder() + .setSubject(String.valueOf(id)) + .setIssuedAt(new Date()) + .setExpiration(new Date(System.currentTimeMillis() + 1000)) + .signWith(SignatureAlgorithm.HS256, jwtProperties.secret()) + .compact(); + } + + private String createExpiredToken() { + return Jwts.builder() + .setSubject(String.valueOf(siteUser.getId())) + .setIssuedAt(new Date()) + .setExpiration(new Date(System.currentTimeMillis() - 1000)) + .signWith(SignatureAlgorithm.HS256, jwtProperties.secret()) + .compact(); + } + + private String createWrongSubjectTypeToken() { + return Jwts.builder() + .setSubject("subject") + .setIssuedAt(new Date()) + .setExpiration(new Date(System.currentTimeMillis() + 1000)) + .signWith(SignatureAlgorithm.HS256, jwtProperties.secret()) + .compact(); + } + + private SiteUser createSiteUser() { + return new SiteUser( + "test@example.com", + "nickname", + "profileImageUrl", + "1999-01-01", + PreparationStatus.CONSIDERING, + Role.MENTEE, + Gender.MALE + ); + } +} diff --git a/src/test/java/com/example/solidconnection/custom/security/userdetails/SiteUserDetailsServiceTest.java b/src/test/java/com/example/solidconnection/custom/security/userdetails/SiteUserDetailsServiceTest.java new file mode 100644 index 000000000..731f840f3 --- /dev/null +++ b/src/test/java/com/example/solidconnection/custom/security/userdetails/SiteUserDetailsServiceTest.java @@ -0,0 +1,104 @@ +package com.example.solidconnection.custom.security.userdetails; + +import com.example.solidconnection.custom.exception.CustomException; +import com.example.solidconnection.siteuser.domain.SiteUser; +import com.example.solidconnection.siteuser.repository.SiteUserRepository; +import com.example.solidconnection.support.TestContainerSpringBootTest; +import com.example.solidconnection.type.Gender; +import com.example.solidconnection.type.PreparationStatus; +import com.example.solidconnection.type.Role; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import java.time.LocalDate; + +import static com.example.solidconnection.custom.exception.ErrorCode.AUTHENTICATION_FAILED; +import static com.example.solidconnection.custom.exception.ErrorCode.INVALID_TOKEN; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.junit.jupiter.api.Assertions.*; + +@DisplayName("사용자 인증 정보 서비스 테스트") +@TestContainerSpringBootTest +class SiteUserDetailsServiceTest { + + @Autowired + private SiteUserDetailsService userDetailsService; + + @Autowired + private SiteUserRepository siteUserRepository; + + @Test + void 사용자_인증_정보를_반환한다() { + // given + SiteUser siteUser = siteUserRepository.save(createSiteUser()); + String username = getUserName(siteUser); + + // when + SiteUserDetails userDetails = (SiteUserDetails) userDetailsService.loadUserByUsername(username); + + // then + assertAll( + () -> assertThat(userDetails.getUsername()).isEqualTo(username), + () -> assertThat(userDetails.getSiteUser()).extracting("id").isEqualTo(siteUser.getId()) + ); + } + + @Nested + class 예외_응답을_반환한다 { + + @Test + void 지정되지_않은_형식의_식별자가_주어지면_예외_응답을_반환한다() { + // given + String username = "notNumber"; + + // when & then + assertThatCode(() -> userDetailsService.loadUserByUsername(username)) + .isInstanceOf(CustomException.class) + .hasMessageContaining(INVALID_TOKEN.getMessage()); + } + + @Test + void 식별자에_해당하는_사용자가_없으면_예외_응답을_반환한다() { + // given + String username = "1234"; + + // when & then + assertThatCode(() -> userDetailsService.loadUserByUsername(username)) + .isInstanceOf(CustomException.class) + .hasMessageContaining(AUTHENTICATION_FAILED.getMessage()); + } + + @Test + void 탈퇴한_사용자이면_예외_응답을_반환한다() { + // given + SiteUser siteUser = createSiteUser(); + siteUser.setQuitedAt(LocalDate.now()); + siteUserRepository.save(siteUser); + String username = getUserName(siteUser); + + // when & then + assertThatCode(() -> userDetailsService.loadUserByUsername(username)) + .isInstanceOf(CustomException.class) + .hasMessageContaining(AUTHENTICATION_FAILED.getMessage()); + } + } + + private SiteUser createSiteUser() { + return new SiteUser( + "test@example.com", + "nickname", + "profileImageUrl", + "1999-01-01", + PreparationStatus.CONSIDERING, + Role.MENTEE, + Gender.MALE + ); + } + + private String getUserName(SiteUser siteUser) { + return siteUser.getId().toString(); + } +} diff --git a/src/test/java/com/example/solidconnection/e2e/ApplicantsQueryTest.java b/src/test/java/com/example/solidconnection/e2e/ApplicantsQueryTest.java index 6b739248b..40f39e646 100644 --- a/src/test/java/com/example/solidconnection/e2e/ApplicantsQueryTest.java +++ b/src/test/java/com/example/solidconnection/e2e/ApplicantsQueryTest.java @@ -7,8 +7,8 @@ import com.example.solidconnection.application.dto.ApplicationsResponse; import com.example.solidconnection.application.dto.UniversityApplicantsResponse; import com.example.solidconnection.application.repository.ApplicationRepository; -import com.example.solidconnection.auth.service.TokenProvider; import com.example.solidconnection.auth.domain.TokenType; +import com.example.solidconnection.auth.service.TokenProvider; import com.example.solidconnection.siteuser.domain.SiteUser; import com.example.solidconnection.siteuser.repository.SiteUserRepository; import com.example.solidconnection.type.VerifyStatus; @@ -30,13 +30,13 @@ class ApplicantsQueryTest extends UniversityDataSetUpEndToEndTest { @Autowired - SiteUserRepository siteUserRepository; + private SiteUserRepository siteUserRepository; @Autowired - ApplicationRepository applicationRepository; + private ApplicationRepository applicationRepository; @Autowired - TokenProvider tokenProvider; + private TokenProvider tokenProvider; private String accessToken; private String adminAccessToken; @@ -55,24 +55,8 @@ class ApplicantsQueryTest extends UniversityDataSetUpEndToEndTest { @BeforeEach public void setUpUserAndToken() { - // setUp - 회원 정보 저장 - String email = "email@email.com"; - SiteUser siteUser = siteUserRepository.save(createSiteUserByEmail(email)); - - // setUp - 엑세스 토큰 생성과 리프레시 토큰 생성 및 저장 - accessToken = tokenProvider.generateToken(email, TokenType.ACCESS); - String refreshToken = tokenProvider.generateToken(email, TokenType.REFRESH); - tokenProvider.saveToken(refreshToken, TokenType.REFRESH); - - adminAccessToken = tokenProvider.generateToken("email5", TokenType.ACCESS); - String adminRefreshToken = tokenProvider.generateToken("email5", TokenType.REFRESH); - tokenProvider.saveToken(adminRefreshToken, TokenType.REFRESH); - - user6AccessToken = tokenProvider.generateToken("email6", TokenType.ACCESS); - String user6RefreshToken = tokenProvider.generateToken("email6", TokenType.REFRESH); - tokenProvider.saveToken(user6RefreshToken, TokenType.REFRESH); - // setUp - 사용자 정보 저장 + SiteUser 나 = siteUserRepository.save(createSiteUserByEmail("my-email")); SiteUser 사용자1 = siteUserRepository.save(createSiteUserByEmail("email1")); SiteUser 사용자2 = siteUserRepository.save(createSiteUserByEmail("email2")); SiteUser 사용자3 = siteUserRepository.save(createSiteUserByEmail("email3")); @@ -80,16 +64,30 @@ public void setUpUserAndToken() { SiteUser 사용자5_관리자 = siteUserRepository.save(createSiteUserByEmail("email5")); SiteUser 사용자6 = siteUserRepository.save(createSiteUserByEmail("email6")); + // setUp - 엑세스 토큰 생성과 리프레시 토큰 생성 및 저장 + accessToken = tokenProvider.generateToken(나, TokenType.ACCESS); + String refreshToken = tokenProvider.generateToken(나, TokenType.REFRESH); + tokenProvider.saveToken(refreshToken, TokenType.REFRESH); + + adminAccessToken = tokenProvider.generateToken(사용자5_관리자, TokenType.ACCESS); + String adminRefreshToken = tokenProvider.generateToken(사용자5_관리자, TokenType.REFRESH); + tokenProvider.saveToken(adminRefreshToken, TokenType.REFRESH); + + user6AccessToken = tokenProvider.generateToken(사용자6, TokenType.ACCESS); + String user6RefreshToken = tokenProvider.generateToken(사용자6, TokenType.REFRESH); + tokenProvider.saveToken(user6RefreshToken, TokenType.REFRESH); + // setUp - 지원 정보 저장 Gpa gpa = createDummyGpa(); LanguageTest languageTest = createDummyLanguageTest(); - 나의_지원정보 = new Application(siteUser, gpa, languageTest, term); + 나의_지원정보 = new Application(나, gpa, languageTest, term); 사용자1_지원정보 = new Application(사용자1, gpa, languageTest, term); 사용자2_지원정보 = new Application(사용자2, gpa, languageTest, term); 사용자3_지원정보 = new Application(사용자3, gpa, languageTest, term); 사용자4_이전학기_지원정보 = new Application(사용자4_이전학기_지원자, gpa, languageTest, beforeTerm); 사용자5_관리자_지원정보 = new Application(사용자5_관리자, gpa, languageTest, term); 사용자6_지원정보 = new Application(사용자6, gpa, languageTest, term); + 나의_지원정보.updateUniversityChoice(괌대학_B_지원_정보, 괌대학_A_지원_정보, 린츠_카톨릭대학_지원_정보, "0"); 사용자1_지원정보.updateUniversityChoice(괌대학_A_지원_정보, 괌대학_B_지원_정보, 그라츠공과대학_지원_정보, "1"); 사용자2_지원정보.updateUniversityChoice(메이지대학_지원_정보, 그라츠대학_지원_정보, 서던덴마크대학교_지원_정보, "2"); @@ -337,5 +335,4 @@ public void setUpUserAndToken() { assertThat(secondChoiceApplicants.size()).isEqualTo(choicedUniversityCount); assertThat(thirdChoiceApplicants.size()).isEqualTo(choicedUniversityCount); } - } diff --git a/src/test/java/com/example/solidconnection/e2e/MyPageTest.java b/src/test/java/com/example/solidconnection/e2e/MyPageTest.java index fb42216c9..567b1016d 100644 --- a/src/test/java/com/example/solidconnection/e2e/MyPageTest.java +++ b/src/test/java/com/example/solidconnection/e2e/MyPageTest.java @@ -19,21 +19,24 @@ @DisplayName("마이페이지 테스트") class MyPageTest extends BaseEndToEndTest { - private final String email = "email@email.com"; + private SiteUser siteUser; + @Autowired private SiteUserRepository siteUserRepository; + @Autowired private TokenProvider tokenProvider; + private String accessToken; @BeforeEach public void setUpUserAndToken() { // setUp - 회원 정보 저장 - siteUserRepository.save(createSiteUserByEmail(email)); + siteUser = siteUserRepository.save(createSiteUserByEmail("email")); // setUp - 엑세스 토큰 생성과 리프레시 토큰 생성 및 저장 - accessToken = tokenProvider.generateToken(email, TokenType.ACCESS); - String refreshToken = tokenProvider.generateToken(email, TokenType.REFRESH); + accessToken = tokenProvider.generateToken(siteUser, TokenType.ACCESS); + String refreshToken = tokenProvider.generateToken(siteUser, TokenType.REFRESH); tokenProvider.saveToken(refreshToken, TokenType.REFRESH); } @@ -48,11 +51,10 @@ public void setUpUserAndToken() { .statusCode(HttpStatus.OK.value()) .extract().as(MyPageResponse.class); - SiteUser savedSiteUser = siteUserRepository.getByEmail(email); assertAll("불러온 마이 페이지 정보가 DB의 정보와 일치한다.", - () -> assertThat(myPageResponse.nickname()).isEqualTo(savedSiteUser.getNickname()), - () -> assertThat(myPageResponse.birth()).isEqualTo(savedSiteUser.getBirth()), - () -> assertThat(myPageResponse.profileImageUrl()).isEqualTo(savedSiteUser.getProfileImageUrl()), - () -> assertThat(myPageResponse.email()).isEqualTo(savedSiteUser.getEmail())); + () -> assertThat(myPageResponse.nickname()).isEqualTo(siteUser.getNickname()), + () -> assertThat(myPageResponse.birth()).isEqualTo(siteUser.getBirth()), + () -> assertThat(myPageResponse.profileImageUrl()).isEqualTo(siteUser.getProfileImageUrl()), + () -> assertThat(myPageResponse.email()).isEqualTo(siteUser.getEmail())); } } diff --git a/src/test/java/com/example/solidconnection/e2e/MyPageUpdateTest.java b/src/test/java/com/example/solidconnection/e2e/MyPageUpdateTest.java index 6d7f52032..025ddb7d7 100644 --- a/src/test/java/com/example/solidconnection/e2e/MyPageUpdateTest.java +++ b/src/test/java/com/example/solidconnection/e2e/MyPageUpdateTest.java @@ -37,17 +37,15 @@ class MyPageUpdateTest extends BaseEndToEndTest { private SiteUser siteUser; - private final String email = "email@email.com"; - @BeforeEach public void setUpUserAndToken() { // setUp - 회원 정보 저장 - siteUser = createSiteUserByEmail(email); + siteUser = createSiteUserByEmail("email"); siteUserRepository.save(siteUser); // setUp - 엑세스 토큰 생성과 리프레시 토큰 생성 및 저장 - accessToken = tokenProvider.generateToken(email, TokenType.ACCESS); - String refreshToken = tokenProvider.generateToken(email, TokenType.REFRESH); + accessToken = tokenProvider.generateToken(siteUser, TokenType.ACCESS); + String refreshToken = tokenProvider.generateToken(siteUser, TokenType.REFRESH); tokenProvider.saveToken(refreshToken, TokenType.REFRESH); } @@ -62,10 +60,9 @@ public void setUpUserAndToken() { .statusCode(HttpStatus.OK.value()) .extract().as(MyPageUpdateResponse.class); - SiteUser savedSiteUser = siteUserRepository.getByEmail(email); assertAll("불러온 마이 페이지 정보가 DB의 정보와 일치한다.", - () -> assertThat(myPageUpdateResponse.nickname()).isEqualTo(savedSiteUser.getNickname()), - () -> assertThat(myPageUpdateResponse.profileImageUrl()).isEqualTo(savedSiteUser.getProfileImageUrl())); + () -> assertThat(myPageUpdateResponse.nickname()).isEqualTo(siteUser.getNickname()), + () -> assertThat(myPageUpdateResponse.profileImageUrl()).isEqualTo(siteUser.getProfileImageUrl())); } @Test @@ -82,9 +79,9 @@ public void setUpUserAndToken() { .statusCode(HttpStatus.OK.value()) .extract().as(NicknameUpdateResponse.class); - SiteUser savedSiteUser = siteUserRepository.getByEmail(email); + SiteUser updatedSiteUser = siteUserRepository.findById(siteUser.getId()).get(); assertAll("마이 페이지 정보가 수정된다.", - () -> assertThat(nicknameUpdateResponse.nickname()).isEqualTo(savedSiteUser.getNickname())); + () -> assertThat(nicknameUpdateResponse.nickname()).isEqualTo(updatedSiteUser.getNickname())); } @Test diff --git a/src/test/java/com/example/solidconnection/e2e/SignInTest.java b/src/test/java/com/example/solidconnection/e2e/SignInTest.java index efd5ad1d7..26eba657a 100644 --- a/src/test/java/com/example/solidconnection/e2e/SignInTest.java +++ b/src/test/java/com/example/solidconnection/e2e/SignInTest.java @@ -79,7 +79,7 @@ class SignInTest extends BaseEndToEndTest { .willReturn(createKakaoUserInfoDtoByEmail(email)); // setUp - 사용자 정보 저장 - siteUserRepository.save(createSiteUserByEmail(email)); + SiteUser siteUser = siteUserRepository.save(createSiteUserByEmail(email)); // request - body 생성 및 요청 KakaoCodeRequest kakaoCodeRequest = new KakaoCodeRequest(kakaoCode); @@ -95,7 +95,7 @@ class SignInTest extends BaseEndToEndTest { () -> assertThat(response.isRegistered()).isTrue(), () -> assertThat(response.accessToken()).isNotNull(), () -> assertThat(response.refreshToken()).isNotNull()); - assertThat(redisTemplate.opsForValue().get(REFRESH.addPrefixToSubject(email))) + assertThat(redisTemplate.opsForValue().get(REFRESH.addPrefixToSubject(siteUser.getId().toString()))) .as("리프레시 토큰을 저장한다.") .isEqualTo(response.refreshToken()); } @@ -112,7 +112,7 @@ class SignInTest extends BaseEndToEndTest { SiteUser siteUserFixture = createSiteUserByEmail(email); LocalDate justBeforeRemoval = LocalDate.now().minusDays(ACCOUNT_RECOVER_DURATION - 1); siteUserFixture.setQuitedAt(justBeforeRemoval); - siteUserRepository.save(siteUserFixture); + SiteUser siteUser = siteUserRepository.save(siteUserFixture); // request - body 생성 및 요청 KakaoCodeRequest kakaoCodeRequest = new KakaoCodeRequest(kakaoCode); @@ -124,12 +124,13 @@ class SignInTest extends BaseEndToEndTest { .statusCode(HttpStatus.OK.value()) .extract().as(SignInResponse.class); + SiteUser updatedSiteUser = siteUserRepository.findById(siteUser.getId()).get(); assertAll("리프레스 토큰과 엑세스 토큰을 응답하고, 탈퇴 날짜를 초기화한다.", () -> assertThat(response.isRegistered()).isTrue(), () -> assertThat(response.accessToken()).isNotNull(), () -> assertThat(response.refreshToken()).isNotNull(), - () -> assertThat(siteUserRepository.getByEmail(email).getQuitedAt()).isNull()); - assertThat(redisTemplate.opsForValue().get(REFRESH.addPrefixToSubject(email))) + () -> assertThat(updatedSiteUser.getQuitedAt()).isNull()); + assertThat(redisTemplate.opsForValue().get(REFRESH.addPrefixToSubject(siteUser.getId().toString()))) .as("리프레시 토큰을 저장한다.") .isEqualTo(response.refreshToken()); } diff --git a/src/test/java/com/example/solidconnection/e2e/SignUpTest.java b/src/test/java/com/example/solidconnection/e2e/SignUpTest.java index 07dafb539..1eb152387 100644 --- a/src/test/java/com/example/solidconnection/e2e/SignUpTest.java +++ b/src/test/java/com/example/solidconnection/e2e/SignUpTest.java @@ -12,6 +12,7 @@ import com.example.solidconnection.repositories.InterestedCountyRepository; import com.example.solidconnection.repositories.InterestedRegionRepository; import com.example.solidconnection.repositories.RegionRepository; +import com.example.solidconnection.siteuser.domain.AuthType; import com.example.solidconnection.siteuser.domain.SiteUser; import com.example.solidconnection.siteuser.repository.SiteUserRepository; import com.example.solidconnection.type.Gender; @@ -86,7 +87,7 @@ class SignUpTest extends BaseEndToEndTest { .statusCode(HttpStatus.OK.value()) .extract().as(SignUpResponse.class); - SiteUser savedSiteUser = siteUserRepository.getByEmail(email); + SiteUser savedSiteUser = siteUserRepository.findByEmailAndAuthType(email, AuthType.KAKAO).get(); assertAll( "회원 정보를 저장한다.", () -> assertThat(savedSiteUser.getId()).isNotNull(), @@ -109,7 +110,7 @@ class SignUpTest extends BaseEndToEndTest { () -> assertThat(interestedCountries).containsExactlyInAnyOrderElementsOf(countries) ); - assertThat(redisTemplate.opsForValue().get(REFRESH.addPrefixToSubject(email))) + assertThat(redisTemplate.opsForValue().get(REFRESH.addPrefixToSubject(savedSiteUser.getId().toString()))) .as("리프레시 토큰을 저장한다.") .isEqualTo(response.refreshToken()); } diff --git a/src/test/java/com/example/solidconnection/e2e/UniversityDetailTest.java b/src/test/java/com/example/solidconnection/e2e/UniversityDetailTest.java index 947f44fd0..b7e112d00 100644 --- a/src/test/java/com/example/solidconnection/e2e/UniversityDetailTest.java +++ b/src/test/java/com/example/solidconnection/e2e/UniversityDetailTest.java @@ -36,8 +36,8 @@ public void setUpUserAndToken() { siteUserRepository.save(siteUser); // setUp - 엑세스 토큰 생성과 리프레시 토큰 생성 및 저장 - accessToken = tokenProvider.generateToken(email, TokenType.ACCESS); - String refreshToken = tokenProvider.generateToken(email, TokenType.REFRESH); + accessToken = tokenProvider.generateToken(siteUser, TokenType.ACCESS); + String refreshToken = tokenProvider.generateToken(siteUser, TokenType.REFRESH); tokenProvider.saveToken(refreshToken, TokenType.REFRESH); } diff --git a/src/test/java/com/example/solidconnection/e2e/UniversityLikeTest.java b/src/test/java/com/example/solidconnection/e2e/UniversityLikeTest.java index dccd1092f..301b373c4 100644 --- a/src/test/java/com/example/solidconnection/e2e/UniversityLikeTest.java +++ b/src/test/java/com/example/solidconnection/e2e/UniversityLikeTest.java @@ -33,8 +33,6 @@ @DisplayName("대학교 좋아요 테스트") class UniversityLikeTest extends UniversityDataSetUpEndToEndTest { - private final String email = "email@email.com"; - @Autowired private SiteUserRepository siteUserRepository; @@ -53,12 +51,12 @@ class UniversityLikeTest extends UniversityDataSetUpEndToEndTest { @BeforeEach public void setUpUserAndToken() { // setUp - 회원 정보 저장 - siteUser = createSiteUserByEmail(email); + siteUser = createSiteUserByEmail("email@email.com"); siteUserRepository.save(siteUser); // setUp - 엑세스 토큰 생성과 리프레시 토큰 생성 및 저장 - accessToken = tokenProvider.generateToken(email, TokenType.ACCESS); - String refreshToken = tokenProvider.generateToken(email, TokenType.REFRESH); + accessToken = tokenProvider.generateToken(siteUser, TokenType.ACCESS); + String refreshToken = tokenProvider.generateToken(siteUser, TokenType.REFRESH); tokenProvider.saveToken(refreshToken, TokenType.REFRESH); } @@ -102,7 +100,7 @@ public void setUpUserAndToken() { .extract().as(LikeResultResponse.class); Optional likedUniversity - = likedUniversityRepository.findAllBySiteUser_Email(email).stream().findFirst(); + = likedUniversityRepository.findAllBySiteUser_Id(siteUser.getId()).stream().findFirst(); assertAll("좋아요 누른 대학교를 저장하고 좋아요 성공 응답을 반환한다.", () -> assertThat(likedUniversity).isPresent(), () -> assertThat(likedUniversity.get().getId()).isEqualTo(괌대학_A_지원_정보.getId()), @@ -125,7 +123,7 @@ public void setUpUserAndToken() { .extract().as(LikeResultResponse.class); Optional likedUniversity - = likedUniversityRepository.findAllBySiteUser_Email(email).stream().findFirst(); + = likedUniversityRepository.findAllBySiteUser_Id(siteUser.getId()).stream().findFirst(); assertAll("좋아요 누른 대학교를 삭제하고, 좋아요 취소 응답을 반환한다.", () -> assertThat(likedUniversity).isEmpty(), () -> assertThat(response.result()).isEqualTo(LIKE_CANCELED_MESSAGE) diff --git a/src/test/java/com/example/solidconnection/e2e/UniversityRecommendTest.java b/src/test/java/com/example/solidconnection/e2e/UniversityRecommendTest.java index 4f3bd3042..358f779cd 100644 --- a/src/test/java/com/example/solidconnection/e2e/UniversityRecommendTest.java +++ b/src/test/java/com/example/solidconnection/e2e/UniversityRecommendTest.java @@ -54,8 +54,8 @@ void setUp() { generalUniversityRecommendService.init(); // setUp - 엑세스 토큰 생성과 리프레시 토큰 생성 및 저장 - accessToken = tokenProvider.generateToken(email, TokenType.ACCESS); - String refreshToken = tokenProvider.generateToken(email, TokenType.REFRESH); + accessToken = tokenProvider.generateToken(siteUser, TokenType.ACCESS); + String refreshToken = tokenProvider.generateToken(siteUser, TokenType.REFRESH); tokenProvider.saveToken(refreshToken, TokenType.REFRESH); } diff --git a/src/test/java/com/example/solidconnection/e2e/UniversitySearchTest.java b/src/test/java/com/example/solidconnection/e2e/UniversitySearchTest.java index 4859f9fe2..22abbfb53 100644 --- a/src/test/java/com/example/solidconnection/e2e/UniversitySearchTest.java +++ b/src/test/java/com/example/solidconnection/e2e/UniversitySearchTest.java @@ -1,12 +1,10 @@ package com.example.solidconnection.e2e; -import com.example.solidconnection.auth.service.TokenProvider; import com.example.solidconnection.auth.domain.TokenType; +import com.example.solidconnection.auth.service.TokenProvider; import com.example.solidconnection.siteuser.domain.SiteUser; -import com.example.solidconnection.siteuser.repository.LikedUniversityRepository; import com.example.solidconnection.siteuser.repository.SiteUserRepository; import com.example.solidconnection.university.dto.UniversityInfoForApplyPreviewResponse; -import com.example.solidconnection.university.repository.UniversityInfoForApplyRepository; import io.restassured.RestAssured; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; @@ -21,17 +19,9 @@ @DisplayName("대학교 검색 테스트") class UniversitySearchTest extends UniversityDataSetUpEndToEndTest { - private final String email = "email@email.com"; - @Autowired private SiteUserRepository siteUserRepository; - @Autowired - private UniversityInfoForApplyRepository universityInfoForApplyRepository; - - @Autowired - private LikedUniversityRepository likedUniversityRepository; - @Autowired private TokenProvider tokenProvider; @@ -41,12 +31,12 @@ class UniversitySearchTest extends UniversityDataSetUpEndToEndTest { @BeforeEach public void setUpUserAndToken() { // setUp - 회원 정보 저장 - siteUser = createSiteUserByEmail(email); + siteUser = createSiteUserByEmail("email@email.com"); siteUserRepository.save(siteUser); // setUp - 엑세스 토큰 생성과 리프레시 토큰 생성 및 저장 - accessToken = tokenProvider.generateToken(email, TokenType.ACCESS); - String refreshToken = tokenProvider.generateToken(email, TokenType.REFRESH); + accessToken = tokenProvider.generateToken(siteUser, TokenType.ACCESS); + String refreshToken = tokenProvider.generateToken(siteUser, TokenType.REFRESH); tokenProvider.saveToken(refreshToken, TokenType.REFRESH); } diff --git a/src/test/java/com/example/solidconnection/post/service/PostCommandServiceTest.java b/src/test/java/com/example/solidconnection/post/service/PostCommandServiceTest.java index eb1b2b652..3cdc5a40c 100644 --- a/src/test/java/com/example/solidconnection/post/service/PostCommandServiceTest.java +++ b/src/test/java/com/example/solidconnection/post/service/PostCommandServiceTest.java @@ -78,7 +78,7 @@ class 게시글_생성_테스트 { // when PostCreateResponse response = postCommandService.createPost( - 테스트유저_1.getEmail(), + 테스트유저_1, 자유게시판.getCode(), request, imageFiles @@ -108,7 +108,7 @@ class 게시글_생성_테스트 { // when & then assertThatThrownBy(() -> - postCommandService.createPost(테스트유저_1.getEmail(), 자유게시판.getCode(), request, imageFiles)) + postCommandService.createPost(테스트유저_1, 자유게시판.getCode(), request, imageFiles)) .isInstanceOf(CustomException.class) .hasMessage(INVALID_POST_CATEGORY.getMessage()); } @@ -121,7 +121,7 @@ class 게시글_생성_테스트 { // when & then assertThatThrownBy(() -> - postCommandService.createPost(테스트유저_1.getEmail(), 자유게시판.getCode(), request, imageFiles)) + postCommandService.createPost(테스트유저_1, 자유게시판.getCode(), request, imageFiles)) .isInstanceOf(CustomException.class) .hasMessage(INVALID_POST_CATEGORY.getMessage()); } @@ -134,7 +134,7 @@ class 게시글_생성_테스트 { // when & then assertThatThrownBy(() -> - postCommandService.createPost(테스트유저_1.getEmail(), 자유게시판.getCode(), request, imageFiles)) + postCommandService.createPost(테스트유저_1, 자유게시판.getCode(), request, imageFiles)) .isInstanceOf(CustomException.class) .hasMessage(CAN_NOT_UPLOAD_MORE_THAN_FIVE_IMAGES.getMessage()); } @@ -158,7 +158,7 @@ class 게시글_수정_테스트 { // when PostUpdateResponse response = postCommandService.updatePost( - 테스트유저_1.getEmail(), + 테스트유저_1, 자유게시판.getCode(), testPost.getId(), request, @@ -189,7 +189,7 @@ class 게시글_수정_테스트 { // when & then assertThatThrownBy(() -> postCommandService.updatePost( - 테스트유저_2.getEmail(), + 테스트유저_2, 자유게시판.getCode(), testPost.getId(), request, @@ -209,7 +209,7 @@ class 게시글_수정_테스트 { // when & then assertThatThrownBy(() -> postCommandService.updatePost( - 테스트유저_1.getEmail(), + 테스트유저_1, 자유게시판.getCode(), testPost.getId(), request, @@ -229,7 +229,7 @@ class 게시글_수정_테스트 { // when & then assertThatThrownBy(() -> postCommandService.updatePost( - 테스트유저_1.getEmail(), + 테스트유저_1, 자유게시판.getCode(), testPost.getId(), request, @@ -253,7 +253,7 @@ class 게시글_삭제_테스트 { // when PostDeleteResponse response = postCommandService.deletePostById( - 테스트유저_1.getEmail(), + 테스트유저_1, 자유게시판.getCode(), testPost.getId() ); @@ -275,7 +275,7 @@ class 게시글_삭제_테스트 { // when & then assertThatThrownBy(() -> postCommandService.deletePostById( - 테스트유저_2.getEmail(), + 테스트유저_2, 자유게시판.getCode(), testPost.getId() )) @@ -291,7 +291,7 @@ class 게시글_삭제_테스트 { // when & then assertThatThrownBy(() -> postCommandService.deletePostById( - 테스트유저_1.getEmail(), + 테스트유저_1, 자유게시판.getCode(), testPost.getId() )) diff --git a/src/test/java/com/example/solidconnection/post/service/PostLikeServiceTest.java b/src/test/java/com/example/solidconnection/post/service/PostLikeServiceTest.java index 9fe6a2704..460b9a15b 100644 --- a/src/test/java/com/example/solidconnection/post/service/PostLikeServiceTest.java +++ b/src/test/java/com/example/solidconnection/post/service/PostLikeServiceTest.java @@ -44,7 +44,7 @@ class 게시글_좋아요_테스트 { // when PostLikeResponse response = postLikeService.likePost( - 테스트유저_1.getEmail(), + 테스트유저_1, 자유게시판.getCode(), testPost.getId() ); @@ -63,12 +63,12 @@ class 게시글_좋아요_테스트 { void 이미_좋아요한_게시글을_다시_좋아요하면_예외_응답을_반환한다() { // given Post testPost = createPost(자유게시판, 테스트유저_1); - postLikeService.likePost(테스트유저_1.getEmail(), 자유게시판.getCode(), testPost.getId()); + postLikeService.likePost(테스트유저_1, 자유게시판.getCode(), testPost.getId()); // when & then assertThatThrownBy(() -> postLikeService.likePost( - 테스트유저_1.getEmail(), + 테스트유저_1, 자유게시판.getCode(), testPost.getId() )) @@ -84,12 +84,12 @@ class 게시글_좋아요_취소_테스트 { void 게시글_좋아요를_성공적으로_취소한다() { // given Post testPost = createPost(자유게시판, 테스트유저_1); - PostLikeResponse beforeResponse = postLikeService.likePost(테스트유저_1.getEmail(), 자유게시판.getCode(), testPost.getId()); + PostLikeResponse beforeResponse = postLikeService.likePost(테스트유저_1, 자유게시판.getCode(), testPost.getId()); long beforeLikeCount = beforeResponse.likeCount(); // when PostDislikeResponse response = postLikeService.dislikePost( - 테스트유저_1.getEmail(), + 테스트유저_1, 자유게시판.getCode(), testPost.getId() ); @@ -112,7 +112,7 @@ class 게시글_좋아요_취소_테스트 { // when & then assertThatThrownBy(() -> postLikeService.dislikePost( - 테스트유저_1.getEmail(), + 테스트유저_1, 자유게시판.getCode(), testPost.getId() )) diff --git a/src/test/java/com/example/solidconnection/post/service/PostQueryServiceTest.java b/src/test/java/com/example/solidconnection/post/service/PostQueryServiceTest.java index 7ec36b0df..d9acf5845 100644 --- a/src/test/java/com/example/solidconnection/post/service/PostQueryServiceTest.java +++ b/src/test/java/com/example/solidconnection/post/service/PostQueryServiceTest.java @@ -53,12 +53,12 @@ class PostQueryServiceTest extends BaseIntegrationTest { Post testPost = createPost(자유게시판, 테스트유저_1, expectedImageUrl); List comments = createComments(testPost, 테스트유저_1, List.of("첫번째 댓글", "두번째 댓글")); - String validateKey = redisUtils.getValidatePostViewCountRedisKey(테스트유저_1.getEmail(), testPost.getId()); + String validateKey = redisUtils.getValidatePostViewCountRedisKey(테스트유저_1.getId(), testPost.getId()); String viewCountKey = redisUtils.getPostViewCountRedisKey(testPost.getId()); // when PostFindResponse response = postQueryService.findPostById( - 테스트유저_1.getEmail(), + 테스트유저_1, 자유게시판.getCode(), testPost.getId() ); diff --git a/src/test/java/com/example/solidconnection/score/service/ScoreServiceTest.java b/src/test/java/com/example/solidconnection/score/service/ScoreServiceTest.java index 4a511d867..681b708a2 100644 --- a/src/test/java/com/example/solidconnection/score/service/ScoreServiceTest.java +++ b/src/test/java/com/example/solidconnection/score/service/ScoreServiceTest.java @@ -55,7 +55,7 @@ class ScoreServiceTest extends BaseIntegrationTest { ); // when - GpaScoreStatusResponse response = scoreService.getGpaScoreStatus(testUser.getEmail()); + GpaScoreStatusResponse response = scoreService.getGpaScoreStatus(testUser); // then assertThat(response.gpaScoreStatusList()) @@ -73,7 +73,7 @@ class ScoreServiceTest extends BaseIntegrationTest { SiteUser testUser = createSiteUser(); // when - GpaScoreStatusResponse response = scoreService.getGpaScoreStatus(testUser.getEmail()); + GpaScoreStatusResponse response = scoreService.getGpaScoreStatus(testUser); // then assertThat(response.gpaScoreStatusList()).isEmpty(); @@ -87,9 +87,10 @@ class ScoreServiceTest extends BaseIntegrationTest { createLanguageTestScore(testUser, LanguageTestType.TOEIC, "100"), createLanguageTestScore(testUser, LanguageTestType.TOEFL_IBT, "7.5") ); + siteUserRepository.save(testUser); // when - LanguageTestScoreStatusResponse response = scoreService.getLanguageTestScoreStatus(testUser.getEmail()); + LanguageTestScoreStatusResponse response = scoreService.getLanguageTestScoreStatus(testUser); // then assertThat(response.languageTestScoreStatusList()) @@ -107,7 +108,7 @@ class ScoreServiceTest extends BaseIntegrationTest { SiteUser testUser = createSiteUser(); // when - LanguageTestScoreStatusResponse response = scoreService.getLanguageTestScoreStatus(testUser.getEmail()); + LanguageTestScoreStatusResponse response = scoreService.getLanguageTestScoreStatus(testUser); // then assertThat(response.languageTestScoreStatusList()).isEmpty(); @@ -120,7 +121,7 @@ class ScoreServiceTest extends BaseIntegrationTest { GpaScoreRequest request = createGpaScoreRequest(); // when - long scoreId = scoreService.submitGpaScore(testUser.getEmail(), request); + long scoreId = scoreService.submitGpaScore(testUser, request); GpaScore savedScore = gpaScoreRepository.findById(scoreId).orElseThrow(); // then @@ -140,7 +141,7 @@ class ScoreServiceTest extends BaseIntegrationTest { LanguageTestScoreRequest request = createLanguageTestScoreRequest(); // when - long scoreId = scoreService.submitLanguageTestScore(testUser.getEmail(), request); + long scoreId = scoreService.submitLanguageTestScore(testUser, request); LanguageTestScore savedScore = languageTestScoreRepository.findById(scoreId).orElseThrow(); // then @@ -172,6 +173,7 @@ private GpaScore createGpaScore(SiteUser siteUser, double gpa, double gpaCriteri siteUser, LocalDate.now() ); + gpaScore.setSiteUser(siteUser); return gpaScoreRepository.save(gpaScore); } @@ -181,6 +183,7 @@ private LanguageTestScore createLanguageTestScore(SiteUser siteUser, LanguageTes LocalDate.now(), siteUser ); + languageTestScore.setSiteUser(siteUser); return languageTestScoreRepository.save(languageTestScore); } diff --git a/src/test/java/com/example/solidconnection/siteuser/service/SiteUserServiceTest.java b/src/test/java/com/example/solidconnection/siteuser/service/SiteUserServiceTest.java index 8fdae031e..9fc6410d8 100644 --- a/src/test/java/com/example/solidconnection/siteuser/service/SiteUserServiceTest.java +++ b/src/test/java/com/example/solidconnection/siteuser/service/SiteUserServiceTest.java @@ -64,7 +64,7 @@ class SiteUserServiceTest extends BaseIntegrationTest { int likedUniversityCount = createLikedUniversities(testUser); // when - MyPageResponse response = siteUserService.getMyPageInfo(testUser.getEmail()); + MyPageResponse response = siteUserService.getMyPageInfo(testUser); // then Assertions.assertAll( @@ -84,7 +84,7 @@ class SiteUserServiceTest extends BaseIntegrationTest { SiteUser testUser = createSiteUser(); // when - MyPageUpdateResponse response = siteUserService.getMyPageInfoToUpdate(testUser.getEmail()); + MyPageUpdateResponse response = siteUserService.getMyPageInfoToUpdate(testUser); // then Assertions.assertAll( @@ -100,7 +100,7 @@ class SiteUserServiceTest extends BaseIntegrationTest { int likedUniversityCount = createLikedUniversities(testUser); // when - List response = siteUserService.getWishUniversity(testUser.getEmail()); + List response = siteUserService.getWishUniversity(testUser); // then assertThat(response) @@ -127,7 +127,7 @@ class 프로필_이미지_수정_테스트 { // when ProfileImageUpdateResponse response = siteUserService.updateProfileImage( - testUser.getEmail(), + testUser, imageFile ); @@ -144,7 +144,7 @@ class 프로필_이미지_수정_테스트 { .willReturn(new UploadedFileUrlResponse("newProfileImageUrl")); // when - siteUserService.updateProfileImage(testUser.getEmail(), imageFile); + siteUserService.updateProfileImage(testUser, imageFile); // then then(s3Service).should(never()).deleteExProfile(any()); @@ -159,10 +159,10 @@ class 프로필_이미지_수정_테스트 { .willReturn(new UploadedFileUrlResponse("newProfileImageUrl")); // when - siteUserService.updateProfileImage(testUser.getEmail(), imageFile); + siteUserService.updateProfileImage(testUser, imageFile); // then - then(s3Service).should().deleteExProfile(testUser.getEmail()); + then(s3Service).should().deleteExProfile(testUser); } @Test @@ -172,7 +172,7 @@ class 프로필_이미지_수정_테스트 { MockMultipartFile emptyFile = createEmptyImageFile(); // when & then - assertThatCode(() -> siteUserService.updateProfileImage(testUser.getEmail(), emptyFile)) + assertThatCode(() -> siteUserService.updateProfileImage(testUser, emptyFile)) .isInstanceOf(CustomException.class) .hasMessage(PROFILE_IMAGE_NEEDED.getMessage()); } @@ -190,12 +190,12 @@ class 닉네임_수정_테스트 { // when NicknameUpdateResponse response = siteUserService.updateNickname( - testUser.getEmail(), + testUser, request ); // then - SiteUser updatedUser = siteUserRepository.getByEmail(testUser.getEmail()); + SiteUser updatedUser = siteUserRepository.findById(testUser.getId()).get(); assertThat(updatedUser.getNicknameModifiedAt()).isNotNull(); assertThat(response.nickname()).isEqualTo(newNickname); } @@ -208,7 +208,7 @@ class 닉네임_수정_테스트 { NicknameUpdateRequest request = new NicknameUpdateRequest("duplicatedNickname"); // when & then - assertThatCode(() -> siteUserService.updateNickname(testUser.getEmail(), request)) + assertThatCode(() -> siteUserService.updateNickname(testUser, request)) .isInstanceOf(CustomException.class) .hasMessage(NICKNAME_ALREADY_EXISTED.getMessage()); } @@ -225,7 +225,7 @@ class 닉네임_수정_테스트 { // when & then assertThatCode(() -> - siteUserService.updateNickname(testUser.getEmail(), request)) + siteUserService.updateNickname(testUser, request)) .isInstanceOf(CustomException.class) .hasMessage(createExpectedErrorMessage(modifiedAt)); } @@ -278,7 +278,7 @@ private int createLikedUniversities(SiteUser testUser) { likedUniversityRepository.save(likedUniversity1); likedUniversityRepository.save(likedUniversity2); likedUniversityRepository.save(likedUniversity3); - return likedUniversityRepository.countBySiteUser_Email(testUser.getEmail()); + return likedUniversityRepository.countBySiteUser_Id(testUser.getId()); } private MockMultipartFile createValidImageFile() { diff --git a/src/test/java/com/example/solidconnection/university/service/UniversityLikeServiceTest.java b/src/test/java/com/example/solidconnection/university/service/UniversityLikeServiceTest.java index 14371486c..51958ed5d 100644 --- a/src/test/java/com/example/solidconnection/university/service/UniversityLikeServiceTest.java +++ b/src/test/java/com/example/solidconnection/university/service/UniversityLikeServiceTest.java @@ -40,8 +40,7 @@ class UniversityLikeServiceTest extends BaseIntegrationTest { SiteUser testUser = createSiteUser(); // when - LikeResultResponse response = universityLikeService.likeUniversity( - testUser.getEmail(), 괌대학_A_지원_정보.getId()); + LikeResultResponse response = universityLikeService.likeUniversity(testUser, 괌대학_A_지원_정보.getId()); // then assertThat(response.result()).isEqualTo(LIKE_SUCCESS_MESSAGE); @@ -56,8 +55,7 @@ class UniversityLikeServiceTest extends BaseIntegrationTest { saveLikedUniversity(testUser, 괌대학_A_지원_정보); // when - LikeResultResponse response = universityLikeService.likeUniversity( - testUser.getEmail(), 괌대학_A_지원_정보.getId()); + LikeResultResponse response = universityLikeService.likeUniversity(testUser, 괌대학_A_지원_정보.getId()); // then assertThat(response.result()).isEqualTo(LIKE_CANCELED_MESSAGE); @@ -72,7 +70,7 @@ class UniversityLikeServiceTest extends BaseIntegrationTest { Long invalidUniversityId = 9999L; // when & then - assertThatCode(() -> universityLikeService.likeUniversity(testUser.getEmail(), invalidUniversityId)) + assertThatCode(() -> universityLikeService.likeUniversity(testUser, invalidUniversityId)) .isInstanceOf(CustomException.class) .hasMessage(UNIVERSITY_INFO_FOR_APPLY_NOT_FOUND.getMessage()); } @@ -84,7 +82,7 @@ class UniversityLikeServiceTest extends BaseIntegrationTest { saveLikedUniversity(testUser, 괌대학_A_지원_정보); // when - IsLikeResponse response = universityLikeService.getIsLiked(testUser.getEmail(), 괌대학_A_지원_정보.getId()); + IsLikeResponse response = universityLikeService.getIsLiked(testUser, 괌대학_A_지원_정보.getId()); // then assertThat(response.isLike()).isTrue(); @@ -96,7 +94,7 @@ class UniversityLikeServiceTest extends BaseIntegrationTest { SiteUser testUser = createSiteUser(); // when - IsLikeResponse response = universityLikeService.getIsLiked(testUser.getEmail(), 괌대학_A_지원_정보.getId()); + IsLikeResponse response = universityLikeService.getIsLiked(testUser, 괌대학_A_지원_정보.getId()); // then assertThat(response.isLike()).isFalse(); @@ -109,7 +107,7 @@ class UniversityLikeServiceTest extends BaseIntegrationTest { Long invalidUniversityId = 9999L; // when & then - assertThatCode(() -> universityLikeService.getIsLiked(testUser.getEmail(), invalidUniversityId)) + assertThatCode(() -> universityLikeService.getIsLiked(testUser, invalidUniversityId)) .isInstanceOf(CustomException.class) .hasMessage(UNIVERSITY_INFO_FOR_APPLY_NOT_FOUND.getMessage()); } diff --git a/src/test/java/com/example/solidconnection/university/service/UniversityRecommendServiceTest.java b/src/test/java/com/example/solidconnection/university/service/UniversityRecommendServiceTest.java index 17d951614..102eb6dd6 100644 --- a/src/test/java/com/example/solidconnection/university/service/UniversityRecommendServiceTest.java +++ b/src/test/java/com/example/solidconnection/university/service/UniversityRecommendServiceTest.java @@ -52,7 +52,7 @@ void setUp() { interestedRegionRepository.save(new InterestedRegion(testUser, 영미권)); // when - UniversityRecommendsResponse response = universityRecommendService.getPersonalRecommends(testUser.getEmail()); + UniversityRecommendsResponse response = universityRecommendService.getPersonalRecommends(testUser); // then assertThat(response.recommendedUniversities()) @@ -72,7 +72,7 @@ void setUp() { interestedCountyRepository.save(new InterestedCountry(testUser, 덴마크)); // when - UniversityRecommendsResponse response = universityRecommendService.getPersonalRecommends(testUser.getEmail()); + UniversityRecommendsResponse response = universityRecommendService.getPersonalRecommends(testUser); // then assertThat(response.recommendedUniversities()) @@ -91,7 +91,7 @@ void setUp() { interestedCountyRepository.save(new InterestedCountry(testUser, 덴마크)); // when - UniversityRecommendsResponse response = universityRecommendService.getPersonalRecommends(testUser.getEmail()); + UniversityRecommendsResponse response = universityRecommendService.getPersonalRecommends(testUser); // then assertThat(response.recommendedUniversities()) @@ -112,7 +112,7 @@ void setUp() { SiteUser testUser = createSiteUser(); // when - UniversityRecommendsResponse response = universityRecommendService.getPersonalRecommends(testUser.getEmail()); + UniversityRecommendsResponse response = universityRecommendService.getPersonalRecommends(testUser); // then assertThat(response.recommendedUniversities())