From 47926a7abd3caaf24aef363ecd056d4e7f14d7b8 Mon Sep 17 00:00:00 2001 From: Minseok Song <99078115+skytin1004@users.noreply.github.com> Date: Tue, 30 Jan 2024 08:45:45 +0900 Subject: [PATCH] =?UTF-8?q?[refactor/Inhabas#222]=EA=B5=AC=EA=B8=80=20?= =?UTF-8?q?=EC=8A=A4=ED=83=80=EC=9D=BC=20=EC=BB=A8=EB=B2=A4=EC=85=98=20?= =?UTF-8?q?=EB=A6=AC=ED=8E=99=ED=86=A0=EB=A7=81=20(#227)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: whitem4rk --- build.gradle | 4 +- .../com/inhabas/api/auth/AuthBeansConfig.java | 130 +-- .../com/inhabas/api/auth/AuthProperties.java | 79 +- .../inhabas/api/auth/AuthSecurityConfig.java | 131 +-- .../java/com/inhabas/api/auth/CorsConfig.java | 15 +- .../api/auth/domain/error/ErrorCode.java | 108 ++- .../api/auth/domain/error/ErrorResponse.java | 29 +- .../authException/AuthExceptionCodes.java | 77 +- .../authException/CustomAuthException.java | 28 +- .../InvalidAuthorityException.java | 7 +- .../InvalidOAuth2InfoException.java | 6 +- .../UnauthorizedRedirectUrlException.java | 8 +- .../UnsupportedOAuth2ProviderException.java | 6 +- .../businessException/BusinessException.java | 24 +- .../InternalServerException.java | 9 +- .../InvalidInputException.java | 8 +- .../businessException/NotFoundException.java | 9 +- .../auth/domain/oauth2/CustomOAuth2User.java | 44 +- .../oauth2/CustomOAuth2UserService.java | 75 +- .../auth/domain/oauth2/OAuth2Provider.java | 36 +- .../domain/oauth2/cookie/CookieUtils.java | 157 ++-- ...eOAuth2AuthorizationRequestRepository.java | 113 +-- .../Oauth2AuthenticationFailureHandler.java | 70 +- .../Oauth2AuthenticationSuccessHandler.java | 128 +-- .../oauth2/majorInfo/domain/MajorInfo.java | 52 +- .../majorInfo/domain/valueObject/College.java | 44 +- .../majorInfo/domain/valueObject/Major.java | 44 +- .../oauth2/majorInfo/dto/MajorInfoDto.java | 16 +- .../majorInfo/dto/MajorInfoSaveDto.java | 23 +- .../repository/MajorInfoRepository.java | 6 +- .../majorInfo/usecase/MajorInfoService.java | 10 +- .../usecase/MajorInfoServiceImpl.java | 40 +- .../oauth2/member/domain/entity/Member.java | 366 ++++---- .../domain/entity/UpdateNameRequest.java | 77 +- .../exception/MemberNotFoundException.java | 7 +- .../member/domain/valueObject/Email.java | 49 +- .../member/domain/valueObject/Generation.java | 41 +- .../member/domain/valueObject/Grade.java | 37 +- .../domain/valueObject/IbasInformation.java | 93 +- .../member/domain/valueObject/Introduce.java | 55 +- .../member/domain/valueObject/MemberType.java | 20 +- .../member/domain/valueObject/Name.java | 44 +- .../member/domain/valueObject/Phone.java | 40 +- .../domain/valueObject/RequestStatus.java | 22 +- .../member/domain/valueObject/Role.java | 25 +- .../domain/valueObject/SchoolInformation.java | 140 ++- .../member/domain/valueObject/StudentId.java | 46 +- .../dto/ApprovedMemberManagementDto.java | 50 +- .../domain/oauth2/member/dto/ContactDto.java | 23 +- .../dto/MemberDuplicationQueryCondition.java | 75 +- .../oauth2/member/dto/MyProfileDto.java | 78 +- .../dto/NotApprovedMemberManagementDto.java | 40 +- .../oauth2/member/dto/ProfileDetailDto.java | 18 +- .../oauth2/member/dto/ProfileIntroDto.java | 14 +- .../oauth2/member/dto/ProfileNameDto.java | 15 +- .../oauth2/member/dto/UpdateRequestDto.java | 12 +- .../member/dto/UpdateRoleRequestDto.java | 10 +- .../member/repository/MemberRepository.java | 23 +- .../repository/MemberRepositoryCustom.java | 19 +- .../repository/MemberRepositoryImpl.java | 186 ++-- .../UpdateNameRequestRepository.java | 6 +- .../member/security/DefaultRoleHierarchy.java | 81 +- .../oauth2/member/security/Hierarchical.java | 7 +- .../security/MemberAuthorityProvider.java | 95 +- .../security/MemberPrincipalService.java | 108 +-- .../security/masking/CustomObjectMapper.java | 25 +- .../member/security/masking/Masked.java | 9 +- .../member/security/masking/Masking.java | 91 +- .../member/security/masking/MaskingType.java | 6 +- .../masking/StringPropertyMasker.java | 52 +- .../service/MemberDuplicationChecker.java | 4 +- .../service/MemberDuplicationCheckerImpl.java | 24 +- .../oauth2/member/service/MemberService.java | 46 +- .../member/service/MemberServiceImpl.java | 374 ++++---- .../domain/entity/MemberSocialAccount.java | 86 +- .../NoSuchSocialAccountException.java | 6 +- .../socialAccount/domain/valueObject/UID.java | 44 +- .../MemberSocialAccountRepository.java | 14 +- .../MemberSocialAccountRepositoryCustom.java | 6 +- .../MemberSocialAccountRepositoryImpl.java | 36 +- .../DefaultUserAuthorityProvider.java | 14 +- .../UserAuthorityProvider.java | 16 +- .../oauth2/userInfo/GoogleOAuth2UserInfo.java | 70 +- .../oauth2/userInfo/KakaoOAuth2UserInfo.java | 69 +- .../oauth2/userInfo/NaverOAuth2UserInfo.java | 74 +- .../oauth2/userInfo/OAuth2UserInfo.java | 63 +- .../OAuth2UserInfoAuthentication.java | 81 +- .../userInfo/OAuth2UserInfoFactory.java | 54 +- .../domain/token/CustomRequestMatcher.java | 33 +- .../domain/token/JwtAccessDeniedHandler.java | 47 +- .../auth/domain/token/RefreshRequestDto.java | 3 +- .../token/TokenAuthenticationResult.java | 38 +- .../api/auth/domain/token/TokenDto.java | 23 +- .../api/auth/domain/token/TokenReIssuer.java | 5 +- .../api/auth/domain/token/TokenResolver.java | 12 +- .../api/auth/domain/token/TokenUtil.java | 40 +- .../token/controller/JwtTokenController.java | 36 +- .../exception/ExpiredTokenException.java | 8 +- .../exception/InvalidTokenException.java | 8 +- .../exception/TokenMissingException.java | 9 +- .../jwtUtils/JwtAuthenticationProvider.java | 23 +- .../jwtUtils/JwtAuthenticationResult.java | 21 +- .../jwtUtils/JwtAuthenticationToken.java | 33 +- .../token/jwtUtils/JwtTokenReIssuer.java | 27 +- .../token/jwtUtils/JwtTokenResolver.java | 24 +- .../domain/token/jwtUtils/JwtTokenUtil.java | 305 ++++--- .../jwtUtils/refreshToken/RefreshToken.java | 23 +- .../RefreshTokenNotFoundException.java | 14 +- .../refreshToken/RefreshTokenRepository.java | 3 +- .../DefaultUserPrincipalService.java | 8 +- .../InvalidJwtTokenHandler.java | 25 +- .../JwtAuthenticationEntryPoint.java | 46 +- .../JwtAuthenticationFilter.java | 130 +-- .../SocialNotFoundException.java | 8 +- .../TokenAuthenticationFailureHandler.java | 5 +- .../securityFilter/UserPrincipalService.java | 10 +- .../com/inhabas/api/auth/TestApplication.java | 7 +- .../domain/oauth2/OAuth2ProviderTest.java | 38 +- .../domain/oauth2/cookie/CookieUtilsTest.java | 268 +++--- ...th2AuthorizationRequestRepositoryTest.java | 355 ++++---- ...auth2AuthenticationFailureHandlerTest.java | 122 +-- ...auth2AuthenticationSuccessHandlerTest.java | 185 ++-- .../domain/valueObject/CollegeTest.java | 66 +- .../domain/valueObject/MajorTest.java | 60 +- .../usecase/MajorInfoServiceTest.java | 155 ++-- .../member/domain/entity/MemberTest.java | 144 ++-- .../member/domain/valueObject/EmailTest.java | 104 ++- .../domain/valueObject/GenerationTest.java | 41 +- .../member/domain/valueObject/GradeTest.java | 42 +- .../domain/valueObject/IntroduceTest.java | 70 +- .../domain/valueObject/MemberTypeTest.java | 41 +- .../member/domain/valueObject/NameTest.java | 74 +- .../member/domain/valueObject/PhoneTest.java | 93 +- .../domain/valueObject/StudentIdTest.java | 68 +- .../repository/MemberRepositoryTest.java | 369 ++++---- .../UpdateNameRequestRepositoryTest.java | 52 +- .../security/MemberAuthorityProviderTest.java | 99 +-- .../security/MemberPrincipalServiceTest.java | 68 +- .../service/MemberDuplicationCheckerTest.java | 128 +-- .../member/service/MemberServiceTest.java | 377 ++++---- .../domain/valueObject/UidTest.java | 84 +- .../MemberSocialAccountRepositoryTest.java | 82 +- .../auth/domain/token/JwtControllerTest.java | 68 +- .../domain/token/JwtTokenReIssueTest.java | 95 +- .../domain/token/JwtTokenResolverTest.java | 105 ++- .../auth/domain/token/JwtTokenUtilTest.java | 293 +++---- .../token/RefreshTokenRepositoryTest.java | 44 +- ...kenAuthenticationProcessingFilterTest.java | 115 +-- .../testAnnotation/DefaultDataJpaTest.java | 14 +- .../java/com/inhabas/api/config/S3Config.java | 41 +- .../api/domain/file/usecase/S3Service.java | 10 +- .../domain/file/usecase/S3ServiceImpl.java | 154 ++-- .../main/java/com/inhabas/api/JpaConfig.java | 18 +- .../api/sshTunneling/SshDataSourceConfig.java | 34 +- .../sshTunneling/SshTunnelingInitializer.java | 98 +-- .../java/com/inhabas/api/ApiApplication.java | 12 +- .../com/inhabas/api/config/CloudConfig.java | 3 +- .../com/inhabas/api/config/SwaggerConfig.java | 187 ++-- .../com/inhabas/api/config/WebConfig.java | 14 +- .../inhabas/api/config/WebSecurityConfig.java | 314 +++---- .../com/inhabas/api/domain/BaseEntity.java | 30 +- .../api/domain/board/domain/AlbumBoard.java | 70 +- .../api/domain/board/domain/BaseBoard.java | 108 +-- .../api/domain/board/domain/NormalBoard.java | 97 +-- .../board/domain/valueObject/Content.java | 45 +- .../board/domain/valueObject/Title.java | 44 +- .../api/domain/board/dto/BoardDto.java | 26 +- .../api/domain/board/dto/SaveBoardDto.java | 27 +- .../api/domain/board/dto/UpdateBoardDto.java | 35 +- .../OnlyWriterModifiableException.java | 13 +- .../exception/OnlyWriterUpdateException.java | 7 +- .../exception/S3UploadFailedException.java | 7 +- .../WriterUnmodifiableException.java | 9 +- .../board/repository/BaseBoardRepository.java | 6 +- .../repository/NormalBoardRepository.java | 7 +- .../NormalBoardRepositoryCustom.java | 8 +- .../repository/NormalBoardRepositoryImpl.java | 122 +-- .../board/usecase/BoardSecurityChecker.java | 163 ++-- .../domain/board/usecase/BoardService.java | 16 +- .../board/usecase/BoardServiceImpl.java | 88 +- .../ApplicationCannotModifiableException.java | 12 +- .../budget/ApplicationNotFoundException.java | 12 +- .../BudgetHistoryNotFoundException.java | 12 +- .../HistoryCannotModifiableException.java | 12 +- .../domain/budget/domain/BudgetHistory.java | 165 ++-- .../domain/BudgetSupportApplication.java | 237 ++--- .../domain/converter/StatusConverter.java | 26 +- .../budget/domain/valueObject/Account.java | 70 +- .../domain/valueObject/ApplicantAccount.java | 42 +- .../domain/valueObject/ApplicationStatus.java | 25 +- .../budget/domain/valueObject/Details.java | 42 +- .../budget/domain/valueObject/Price.java | 33 +- .../domain/valueObject/RejectReason.java | 44 +- .../budget/domain/valueObject/Title.java | 42 +- .../dto/BudgetApplicationDetailDto.java | 37 +- .../budget/dto/BudgetApplicationListDto.java | 21 +- .../dto/BudgetApplicationRegisterForm.java | 82 +- .../BudgetApplicationStatusChangeRequest.java | 18 +- .../dto/BudgetApplicationUpdateForm.java | 28 +- .../budget/dto/BudgetHistoryCreateForm.java | 93 +- .../budget/dto/BudgetHistoryDetailDto.java | 30 +- .../budget/dto/BudgetHistoryListResponse.java | 14 +- .../budget/dto/BudgetHistoryModifyForm.java | 22 +- .../BudgetApplicationRepository.java | 6 +- .../BudgetApplicationRepositoryCustom.java | 13 +- .../BudgetApplicationRepositoryImpl.java | 174 ++-- .../repository/BudgetHistoryRepository.java | 10 +- .../BudgetHistoryRepositoryCustom.java | 13 +- .../BudgetHistoryRepositoryImpl.java | 174 ++-- .../usecase/BudgetApplicationProcessor.java | 5 +- .../BudgetApplicationProcessorImpl.java | 77 +- .../usecase/BudgetApplicationService.java | 17 +- .../usecase/BudgetApplicationServiceImpl.java | 90 +- .../budget/usecase/BudgetHistoryService.java | 21 +- .../usecase/BudgetHistoryServiceImpl.java | 110 +-- .../api/domain/club/domain/ClubHistory.java | 67 +- .../club/dto/ClubActivityDetailDto.java | 94 +- .../api/domain/club/dto/ClubActivityDto.java | 82 +- .../api/domain/club/dto/ClubHistoryDto.java | 79 +- .../domain/club/dto/SaveClubActivityDto.java | 31 +- .../domain/club/dto/SaveClubHistoryDto.java | 35 +- .../repository/ClubActivityRepository.java | 6 +- .../repository/ClubHistoryRepository.java | 6 +- .../club/usecase/ClubActivityService.java | 15 +- .../club/usecase/ClubActivityServiceImpl.java | 274 +++--- .../club/usecase/ClubHistoryService.java | 16 +- .../club/usecase/ClubHistoryServiceImpl.java | 111 ++- .../api/domain/comment/domain/Comment.java | 272 +++--- .../comment/domain/valueObject/Content.java | 44 +- .../domain/comment/dto/CommentDetailDto.java | 79 +- .../domain/comment/dto/CommentSaveDto.java | 33 +- .../domain/comment/dto/CommentUpdateDto.java | 20 +- .../api/domain/comment/dto/WriterInfo.java | 33 +- .../comment/repository/CommentRepository.java | 7 +- .../repository/CommentRepositoryImpl.java | 79 +- .../repository/CustomCommentRepository.java | 7 +- .../comment/usecase/CommentService.java | 13 +- .../comment/usecase/CommentServiceImpl.java | 77 +- .../domain/contest/domain/ContestBoard.java | 93 +- .../domain/valueObject/Association.java | 56 +- .../contest/domain/valueObject/Topic.java | 42 +- .../contest/dto/DetailContestBoardDto.java | 41 +- .../contest/dto/ListContestBoardDto.java | 19 +- .../contest/dto/SaveContestBoardDto.java | 44 +- .../contest/dto/UpdateContestBoardDto.java | 47 +- .../repository/ContestBoardRepository.java | 7 +- .../ContestBoardRepositoryCustom.java | 14 +- .../ContestBoardRepositoryImpl.java | 164 ++-- .../contest/usecase/ContestBoardService.java | 27 +- .../usecase/ContestBoardServiceImpl.java | 122 +-- .../api/domain/file/domain/BaseFile.java | 85 +- .../api/domain/file/domain/BoardFile.java | 70 +- .../file/domain/valueObject/FileName.java | 50 +- .../file/domain/valueObject/FileUrl.java | 45 +- .../api/domain/file/dto/FileDownloadDto.java | 21 +- .../api/domain/file/dto/FileUploadDto.java | 20 +- .../file/repository/BoardFileRepository.java | 6 +- .../LectureCannotModifiableException.java | 12 +- .../api/domain/lecture/domain/Lecture.java | 263 +++--- .../api/domain/lecture/domain/Student.java | 85 +- .../converter/LectureStatusConverter.java | 28 +- .../converter/StudentStatusConverter.java | 26 +- .../domain/valueObject/LectureStatus.java | 25 +- .../domain/valueObject/StudentStatus.java | 22 +- .../domain/lecture/dto/LectureDetailDto.java | 128 +-- .../domain/lecture/dto/LectureListDto.java | 60 +- .../lecture/dto/LectureRegisterForm.java | 111 +-- .../dto/LectureStatusUpdateRequest.java | 16 +- .../domain/lecture/dto/LectureUpdateForm.java | 8 +- .../domain/lecture/dto/StudentListDto.java | 49 +- .../lecture/repository/LectureRepository.java | 7 +- .../repository/LectureRepositoryCustom.java | 11 +- .../repository/LectureRepositoryImpl.java | 134 +-- .../lecture/repository/StudentRepository.java | 20 +- .../repository/StudentRepositoryCustom.java | 5 +- .../repository/StudentRepositoryImpl.java | 87 +- .../usecase/LectureSecurityChecker.java | 25 +- .../lecture/usecase/LectureService.java | 17 +- .../lecture/usecase/LectureServiceImpl.java | 103 +-- .../usecase/LectureStudentService.java | 30 +- .../usecase/LectureStudentServiceImpl.java | 111 +-- .../inhabas/api/domain/menu/domain/Menu.java | 85 +- .../api/domain/menu/domain/MenuGroup.java | 27 +- .../menu/domain/valueObject/Description.java | 44 +- .../domain/valueObject/MenuGroupName.java | 42 +- .../menu/domain/valueObject/MenuId.java | 59 +- .../menu/domain/valueObject/MenuName.java | 42 +- .../menu/domain/valueObject/MenuType.java | 111 +-- .../inhabas/api/domain/menu/dto/MenuDto.java | 72 +- .../api/domain/menu/dto/MenuGroupDto.java | 22 +- .../menu/repository/MenuGroupRepository.java | 6 +- .../menu/repository/MenuRepository.java | 8 +- .../menu/repository/MenuRepositoryCustom.java | 9 +- .../menu/repository/MenuRepositoryImpl.java | 71 +- .../api/domain/menu/usecase/MenuService.java | 8 +- .../domain/menu/usecase/MenuServiceImpl.java | 40 +- .../api/domain/policy/domain/PolicyTerm.java | 41 +- .../api/domain/policy/domain/PolicyType.java | 22 +- .../api/domain/policy/dto/PolicyTermDto.java | 21 +- .../domain/policy/dto/SavePolicyTernDto.java | 16 +- .../respository/PolicyTermRepository.java | 6 +- .../policy/usecase/PolicyTermService.java | 5 +- .../policy/usecase/PolicyTermServiceImpl.java | 47 +- .../questionnaire/domain/Questionnaire.java | 24 +- .../questionnaire/dto/QuestionnaireDto.java | 5 +- .../repository/QuestionnaireRepository.java | 8 +- .../usecase/QuestionnaireService.java | 6 +- .../usecase/QuestionnaireServiceImpl.java | 24 +- .../domain/signUp/domain/entity/Answer.java | 70 +- .../api/domain/signUp/dto/AnswerDto.java | 13 +- .../api/domain/signUp/dto/SignUpDto.java | 95 +- .../exception/NotWriteAnswersException.java | 9 +- .../exception/NotWriteProfileException.java | 9 +- .../signUp/repository/AnswerRepository.java | 8 +- .../domain/signUp/usecase/AnswerService.java | 9 +- .../signUp/usecase/AnswerServiceImpl.java | 168 ++-- .../domain/signUp/usecase/SignUpService.java | 23 +- .../signUp/usecase/SignUpServiceImpl.java | 243 +++--- .../domain/entity/SignUpSchedule.java | 153 ++-- .../signUpSchedule/dto/SignUpScheduleDto.java | 91 +- .../exception/InvalidDateException.java | 7 +- .../SignUpNotAvailableException.java | 7 +- .../repository/SignUpScheduleRepository.java | 6 +- .../usecase/SignUpAvailabilityChecker.java | 2 +- .../SignUpAvailabilityCheckerImpl.java | 17 +- .../usecase/SignUpScheduler.java | 5 +- .../usecase/SignUpSchedulerStrict.java | 136 +-- .../inhabas/api/global/dto/PageInfoDto.java | 24 +- .../global/dto/PagedMemberResponseDto.java | 25 +- .../com/inhabas/api/global/util/FileUtil.java | 95 +- .../com/inhabas/api/global/util/PageUtil.java | 22 +- .../inhabas/api/global/util/StringUtil.java | 8 +- .../com/inhabas/api/web/BoardController.java | 144 ++-- .../api/web/BudgetApplicationController.java | 199 +++-- .../api/web/BudgetHistoryController.java | 188 ++-- .../api/web/ClubActivityController.java | 343 ++++---- .../api/web/ClubHistoryController.java | 272 +++--- .../inhabas/api/web/CommentController.java | 293 ++++--- .../api/web/ContestBoardController.java | 154 ++-- .../inhabas/api/web/ExceptionController.java | 191 ++-- .../inhabas/api/web/LectureController.java | 362 ++++---- .../com/inhabas/api/web/MemberController.java | 299 ++++--- .../com/inhabas/api/web/MenuController.java | 114 +-- .../inhabas/api/web/MyProfileController.java | 185 ++-- .../inhabas/api/web/PolicyTermController.java | 127 +-- .../com/inhabas/api/web/SignUpController.java | 425 ++++----- .../api/web/SignUpScheduleController.java | 88 +- .../ArgumentResolverConfig.java | 14 +- .../web/argumentResolver/Authenticated.java | 7 +- .../LoginMemberArgumentResolver.java | 57 +- .../api/web/converter/MenuIdConverter.java | 28 +- .../web/interceptor/InterceptorConfig.java | 33 +- .../SignUpControllerInterceptor.java | 28 +- .../com/inhabas/api/ApiApplicationTests.java | 9 +- .../inhabas/api/domain/BaseEntityTest.java | 102 ++- .../domain/board/domain/AlbumBoardTest.java | 103 ++- .../domain/board/domain/BaseBoardTest.java | 156 ++-- .../domain/board/domain/NormalBoardTest.java | 29 +- .../domain/valueObject/AlbumExampleTest.java | 39 +- .../domain/valueObject/BoardContentTest.java | 79 +- .../board/domain/valueObject/TitleTest.java | 81 +- .../domain/board/dto/SaveBoardDtoTest.java | 122 +-- .../domain/board/dto/UpdateBoardDtoTest.java | 82 +- .../repository/NormalBoardRepositoryTest.java | 365 ++++---- .../board/usecase/BoardServiceTest.java | 297 +++---- .../StatusAttributeConverterTest.java | 196 ++--- .../BudgetApplicationRepositoryTest.java | 188 ++-- .../BudgetHistoryRepositoryTest.java | 368 ++++---- .../BudgetApplicationProcessorTest.java | 293 ++++--- .../usecase/BudgetApplicationServiceTest.java | 468 +++++----- .../usecase/BudgetHistoryServiceTest.java | 485 ++++++----- .../budget/valueObject/AccountTest.java | 76 +- .../valueObject/ApplicantAccountTest.java | 78 +- .../domain/budget/valueObject/DetailTest.java | 78 +- .../domain/budget/valueObject/PriceTest.java | 76 +- .../budget/valueObject/RejectReasonTest.java | 78 +- .../domain/budget/valueObject/TitleTest.java | 78 +- .../club/domain/entity/ClubHistoryTest.java | 67 +- .../club/dto/ClubActivityDetailDtoTest.java | 92 +- .../domain/club/dto/ClubActivityDtoTest.java | 87 +- .../domain/club/dto/ClubHistoryDtoTest.java | 124 +-- .../club/dto/SaveClubActivityDtoTest.java | 81 +- .../club/dto/SaveClubHistoryDtoTest.java | 79 +- .../usecase/ClubActivityServiceImplTest.java | 330 ++++--- .../usecase/ClubHistoryServiceImplTest.java | 352 ++++---- .../domain/comment/domain/CommentTest.java | 162 ++-- .../valueObject/CommentContentTest.java | 107 ++- .../repository/CommentRepositoryTest.java | 292 +++---- .../comment/usecase/CommentServiceTest.java | 275 +++--- .../domain/contestBoard/ContestBoardTest.java | 64 +- .../dto/SaveContestBoardDtoTest.java | 236 ++--- .../dto/UpdateContestBoardDtoTest.java | 173 ++-- .../ContestBoardRepositoryTest.java | 177 ++-- .../usecase/ContestBoardServiceTest.java | 329 ++++--- .../api/domain/file/domain/BoardFileTest.java | 41 +- .../file/domain/valueObject/FileNameTest.java | 100 ++- .../file/domain/valueObject/FileUrlTest.java | 110 ++- .../domain/file/dto/FileDownloadDtoTest.java | 73 +- .../domain/file/dto/FileUploadDtoTest.java | 5 +- .../repository/LectureRepositoryTest.java | 159 ++-- .../repository/StudentRepositoryTest.java | 114 ++- .../usecase/LectureSecurityCheckerTest.java | 142 ++- .../usecase/LectureServiceImplTest.java | 698 +++++++-------- .../usecase/LectureStudentServiceDBTest.java | 134 ++- .../LectureStudentServiceMockTest.java | 250 +++--- .../member/domain/entity/MemberTest.java | 238 ++--- .../domain/menu/domain/MenuExampleTest.java | 13 +- .../MenuCategoryDescriptionTest.java | 63 +- .../valueObject/MenuGroupExampleTest.java | 13 +- .../domain/valueObject/MenuGroupNameTest.java | 80 +- .../menu/domain/valueObject/MenuNameTest.java | 73 +- .../menu/repository/MenuRepositoryTest.java | 311 +++---- .../domain/menu/usecase/MenuServiceTest.java | 85 +- .../domain/policy/domain/PolicyTermTest.java | 59 +- .../domain/policy/domain/PolicyTypeTest.java | 60 +- .../domain/policy/dto/PolicyTermDtoTest.java | 73 +- .../policy/dto/SavePolicyTernDtoTest.java | 72 +- .../policy/usecase/PolicyTermServiceTest.java | 167 ++-- .../QuestionnaireRepositoryTest.java | 57 +- .../usecase/QuestionnaireServiceTest.java | 67 +- .../domain/signUp/SignUpIntegrationTest.java | 655 +++++++------- .../signUp/domain/entity/AnswerTest.java | 41 +- .../repository/AnswerRepositoryTest.java | 60 +- .../signUp/usecase/AnswerServiceTest.java | 184 ++-- .../signUp/usecase/SignUpServiceTest.java | 525 ++++++----- .../domain/entity/SignUpScheduleTest.java | 200 +++-- .../usecase/StrictSignUpSchedulerTest.java | 238 ++--- .../api/securityConfig/RoleHierarchyTest.java | 171 ++-- .../inhabas/api/web/BoardControllerTest.java | 341 ++++---- .../web/BudgetApplicationControllerTest.java | 180 ++-- .../api/web/BudgetHistoryControllerTest.java | 287 +++--- .../api/web/ClubActivityControllerTest.java | 575 ++++++------- .../api/web/ClubHistoryControllerTest.java | 588 ++++++------- .../api/web/CommentControllerTest.java | 363 ++++---- .../api/web/ContestBoardControllerTest.java | 315 ++++--- .../api/web/LectureControllerTest.java | 814 +++++++++--------- .../inhabas/api/web/MemberControllerTest.java | 338 ++++---- .../inhabas/api/web/MenuControllerTest.java | 75 +- .../api/web/MyProfileControllerTest.java | 302 ++++--- .../api/web/PolicyTermControllerTest.java | 304 ++++--- .../inhabas/api/web/SignUpControllerTest.java | 573 ++++++------ .../api/web/SignUpScheduleControllerTest.java | 165 ++-- .../ArgumentResolverTest.java | 96 +-- .../api/web/configTest/WebConfigTest.java | 29 +- .../testAnnotataion/CustomSpringBootTest.java | 17 +- .../testAnnotataion/DefaultDataJpaTest.java | 29 +- .../testAnnotataion/DefaultWebMvcTest.java | 29 +- .../testAnnotataion/NoSecureWebMvcTest.java | 23 +- .../WithMockCustomOAuth2Account.java | 23 +- ...omOAuth2AccountSecurityContextFactory.java | 73 +- .../WithMockJwtAuthenticationToken.java | 16 +- ...enticationTokenSecurityContextFactory.java | 30 +- .../testConfig/InterceptorConfigMockBean.java | 6 +- .../TestConfigurationForSecurity.java | 69 +- .../testConfig/TestEmptyController.java | 4 +- 455 files changed, 20556 insertions(+), 20152 deletions(-) diff --git a/build.gradle b/build.gradle index 593fb683..20f9c5ce 100644 --- a/build.gradle +++ b/build.gradle @@ -11,8 +11,8 @@ spotless { target("**/*.java") // google 자바 포맷 적용 googleJavaFormat() - // 불필요한 임포트 제거 - removeUnusedImports() + // 불필요한 임포트 제거 - 현재 미구현된 부분 있어서 기능 제거 추후 미구현 부분은 import에 '//'처리 필요함. + // removeUnusedImports() // 마지막줄 New Line 처리 endWithNewline() // 공백 제거 diff --git a/module-auth/src/main/java/com/inhabas/api/auth/AuthBeansConfig.java b/module-auth/src/main/java/com/inhabas/api/auth/AuthBeansConfig.java index d45a62be..15a24349 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/AuthBeansConfig.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/AuthBeansConfig.java @@ -1,84 +1,86 @@ package com.inhabas.api.auth; +import javax.sql.DataSource; + +import lombok.RequiredArgsConstructor; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.security.oauth2.client.JdbcOAuth2AuthorizedClientService; +import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService; +import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; + import com.inhabas.api.auth.domain.oauth2.cookie.HttpCookieOAuth2AuthorizationRequestRepository; import com.inhabas.api.auth.domain.oauth2.handler.Oauth2AuthenticationFailureHandler; import com.inhabas.api.auth.domain.oauth2.handler.Oauth2AuthenticationSuccessHandler; import com.inhabas.api.auth.domain.oauth2.userAuthorityProvider.DefaultUserAuthorityProvider; import com.inhabas.api.auth.domain.oauth2.userAuthorityProvider.UserAuthorityProvider; -import com.inhabas.api.auth.domain.token.TokenUtil; import com.inhabas.api.auth.domain.token.TokenReIssuer; import com.inhabas.api.auth.domain.token.TokenResolver; -import com.inhabas.api.auth.domain.token.jwtUtils.JwtTokenUtil; +import com.inhabas.api.auth.domain.token.TokenUtil; import com.inhabas.api.auth.domain.token.jwtUtils.JwtTokenReIssuer; import com.inhabas.api.auth.domain.token.jwtUtils.JwtTokenResolver; +import com.inhabas.api.auth.domain.token.jwtUtils.JwtTokenUtil; import com.inhabas.api.auth.domain.token.jwtUtils.refreshToken.RefreshTokenRepository; import com.inhabas.api.auth.domain.token.securityFilter.DefaultUserPrincipalService; import com.inhabas.api.auth.domain.token.securityFilter.UserPrincipalService; -import io.jsonwebtoken.Jwt; -import lombok.RequiredArgsConstructor; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.security.oauth2.client.JdbcOAuth2AuthorizedClientService; -import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService; -import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; - -import javax.sql.DataSource; @Configuration @RequiredArgsConstructor public class AuthBeansConfig { - private final JwtTokenUtil jwtTokenUtil; - private final AuthProperties authProperties; - private final RefreshTokenRepository refreshTokenRepository; - - @Bean - public HttpCookieOAuth2AuthorizationRequestRepository httpCookieOAuth2AuthorizationRequestRepository() { - return new HttpCookieOAuth2AuthorizationRequestRepository(); - } - - - @Bean - public Oauth2AuthenticationSuccessHandler oauth2AuthenticationSuccessHandler(RefreshTokenRepository refreshTokenRepository) { - return new Oauth2AuthenticationSuccessHandler( - jwtTokenUtil, this.authProperties, this.httpCookieOAuth2AuthorizationRequestRepository()); - } - - @Bean - public Oauth2AuthenticationFailureHandler oauth2AuthenticationFailureHandler() { - return new Oauth2AuthenticationFailureHandler( - this.authProperties, this.httpCookieOAuth2AuthorizationRequestRepository()); - } - - @ConditionalOnMissingBean - public UserAuthorityProvider userAuthorityService() { - return new DefaultUserAuthorityProvider(); - } - - @Bean - public OAuth2AuthorizedClientService authorizedClientService( - DataSource dataSource, ClientRegistrationRepository clientRegistrationRepository) { - return new JdbcOAuth2AuthorizedClientService(new JdbcTemplate(dataSource), clientRegistrationRepository); - } - - @ConditionalOnMissingBean - public UserPrincipalService userPrincipalService() { - return new DefaultUserPrincipalService(); - } - - - @Bean - public TokenResolver tokenResolver() { - return new JwtTokenResolver(); - } - - - @Bean - public TokenReIssuer tokenReIssuer(TokenUtil tokenUtil, TokenResolver tokenResolver, - RefreshTokenRepository refreshTokenRepository) { - return new JwtTokenReIssuer(tokenUtil, tokenResolver, refreshTokenRepository); - } - + private final JwtTokenUtil jwtTokenUtil; + private final AuthProperties authProperties; + private final RefreshTokenRepository refreshTokenRepository; + + @Bean + public HttpCookieOAuth2AuthorizationRequestRepository + httpCookieOAuth2AuthorizationRequestRepository() { + return new HttpCookieOAuth2AuthorizationRequestRepository(); + } + + @Bean + public Oauth2AuthenticationSuccessHandler oauth2AuthenticationSuccessHandler( + RefreshTokenRepository refreshTokenRepository) { + return new Oauth2AuthenticationSuccessHandler( + jwtTokenUtil, this.authProperties, this.httpCookieOAuth2AuthorizationRequestRepository()); + } + + @Bean + public Oauth2AuthenticationFailureHandler oauth2AuthenticationFailureHandler() { + return new Oauth2AuthenticationFailureHandler( + this.authProperties, this.httpCookieOAuth2AuthorizationRequestRepository()); + } + + @ConditionalOnMissingBean + public UserAuthorityProvider userAuthorityService() { + return new DefaultUserAuthorityProvider(); + } + + @Bean + public OAuth2AuthorizedClientService authorizedClientService( + DataSource dataSource, ClientRegistrationRepository clientRegistrationRepository) { + return new JdbcOAuth2AuthorizedClientService( + new JdbcTemplate(dataSource), clientRegistrationRepository); + } + + @ConditionalOnMissingBean + public UserPrincipalService userPrincipalService() { + return new DefaultUserPrincipalService(); + } + + @Bean + public TokenResolver tokenResolver() { + return new JwtTokenResolver(); + } + + @Bean + public TokenReIssuer tokenReIssuer( + TokenUtil tokenUtil, + TokenResolver tokenResolver, + RefreshTokenRepository refreshTokenRepository) { + return new JwtTokenReIssuer(tokenUtil, tokenResolver, refreshTokenRepository); + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/AuthProperties.java b/module-auth/src/main/java/com/inhabas/api/auth/AuthProperties.java index a63222be..f70697b9 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/AuthProperties.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/AuthProperties.java @@ -1,60 +1,57 @@ package com.inhabas.api.auth; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.cloud.context.config.annotation.RefreshScope; - import java.net.URI; import java.util.ArrayList; import java.util.List; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.cloud.context.config.annotation.RefreshScope; + @RefreshScope @ConfigurationProperties(prefix = "auth") public class AuthProperties { - private final OAuth2 oauth2 = new OAuth2(); - + private final OAuth2 oauth2 = new OAuth2(); + public static final class OAuth2 { - public static final class OAuth2 { + private String defaultRedirectUri; - private String defaultRedirectUri; + private final List authorizedRedirectUris = new ArrayList<>(); - private final List authorizedRedirectUris = new ArrayList<>(); - - public String getDefaultRedirectUri() { - return defaultRedirectUri; - } - - public void setDefaultRedirectUri(String defaultRedirectUri) { - this.defaultRedirectUri = defaultRedirectUri; - } - - public List getAuthorizedRedirectUris() { - return authorizedRedirectUris; - } + public String getDefaultRedirectUri() { + return defaultRedirectUri; + } + public void setDefaultRedirectUri(String defaultRedirectUri) { + this.defaultRedirectUri = defaultRedirectUri; + } - /** - * OAuth2 인증 요청 시 redirect_uri 를 변조하려는 불법적인 시도를 막기 위한 보안적인 조치 - * @param uri 프론트에서 입력한 redirect_uri - * @return api 에 등록되어 있는 uri 이면 true. - */ - public boolean isAuthorizedRedirectUri(String uri) { - URI clientRedirectUri = URI.create(uri); - return this.authorizedRedirectUris - .stream() - .anyMatch(authorizedRedirectUri -> { - // scheme, host, port 가 동일해야 함. - URI authorizedURI = URI.create(authorizedRedirectUri); - return authorizedURI.getHost().equalsIgnoreCase(clientRedirectUri.getHost()) - && authorizedURI.getPort() == clientRedirectUri.getPort() - && authorizedURI.getScheme().equalsIgnoreCase(clientRedirectUri.getScheme()); - }); - } + public List getAuthorizedRedirectUris() { + return authorizedRedirectUris; } - public OAuth2 getOauth2() { - return oauth2; + /** + * OAuth2 인증 요청 시 redirect_uri 를 변조하려는 불법적인 시도를 막기 위한 보안적인 조치 + * + * @param uri 프론트에서 입력한 redirect_uri + * @return api 에 등록되어 있는 uri 이면 true. + */ + public boolean isAuthorizedRedirectUri(String uri) { + URI clientRedirectUri = URI.create(uri); + return this.authorizedRedirectUris.stream() + .anyMatch( + authorizedRedirectUri -> { + // scheme, host, port 가 동일해야 함. + URI authorizedURI = URI.create(authorizedRedirectUri); + return authorizedURI.getHost().equalsIgnoreCase(clientRedirectUri.getHost()) + && authorizedURI.getPort() == clientRedirectUri.getPort() + && authorizedURI.getScheme().equalsIgnoreCase(clientRedirectUri.getScheme()); + }); } -} \ No newline at end of file + } + + public OAuth2 getOauth2() { + return oauth2; + } +} diff --git a/module-auth/src/main/java/com/inhabas/api/auth/AuthSecurityConfig.java b/module-auth/src/main/java/com/inhabas/api/auth/AuthSecurityConfig.java index 7adf59f5..bc83b374 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/AuthSecurityConfig.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/AuthSecurityConfig.java @@ -1,10 +1,7 @@ package com.inhabas.api.auth; -import com.inhabas.api.auth.domain.oauth2.CustomOAuth2UserService; -import com.inhabas.api.auth.domain.oauth2.cookie.HttpCookieOAuth2AuthorizationRequestRepository; -import com.inhabas.api.auth.domain.oauth2.handler.Oauth2AuthenticationFailureHandler; -import com.inhabas.api.auth.domain.oauth2.handler.Oauth2AuthenticationSuccessHandler; import lombok.RequiredArgsConstructor; + import org.springframework.context.annotation.Profile; import org.springframework.core.annotation.Order; import org.springframework.security.config.annotation.web.builders.HttpSecurity; @@ -14,74 +11,80 @@ import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService; import org.springframework.web.cors.CorsUtils; +import com.inhabas.api.auth.domain.oauth2.CustomOAuth2UserService; +import com.inhabas.api.auth.domain.oauth2.cookie.HttpCookieOAuth2AuthorizationRequestRepository; +import com.inhabas.api.auth.domain.oauth2.handler.Oauth2AuthenticationFailureHandler; +import com.inhabas.api.auth.domain.oauth2.handler.Oauth2AuthenticationSuccessHandler; + @Order(0) // 인증 관련 security filter chain 은 우선순위가 가장 높아야 함. @EnableWebSecurity @RequiredArgsConstructor @Profile({"dev", "local", "production"}) // 테스트에는 포함시키지 않음. public class AuthSecurityConfig extends WebSecurityConfigurerAdapter { - private final CustomOAuth2UserService customOAuth2UserService; - private final OAuth2AuthorizedClientService authorizedClientService; - private final Oauth2AuthenticationSuccessHandler oauth2AuthenticationSuccessHandler; - private final Oauth2AuthenticationFailureHandler oauth2AuthenticationFailureHandler; - private final HttpCookieOAuth2AuthorizationRequestRepository httpCookieOAuth2AuthorizationRequestRepository; - - /** 소셜 로그인 api

- * - * 진행과정은 아래와 같다.
- *
    - *
  1. 사용자가 소셜로그인 시작. (프론트에서 redirect_url 보내줘야함.)
  2. - *
  3. OAuth2 인증 진행 -> 기존 회원인지 검사
  4. - *
      - *
    1. 성공 -> OAuth2AuthenticationSuccessHandler
    2. - *
        - *
      1. 프론트에서 보내준 redirect_url 검증 (-> 실패하면 failure handler 에서 처리)
      2. - *
      3. jwt 토큰 발급 및 로그인 처리
      4. - *
      5. 리다이렉트
      6. - *
      - * - *
    3. 실패 -> OAuth2AuthenticationFailureHandler
    4. - *
    - * - *
- * - * 회원가입이나, jwt 토큰 발급을 위한 url 로 함부로 접근할 수 없게 하기 위해 - * jwt 토근이 발급되기 이전까지는 OAuth2 인증 결과를 세션을 통해서 유지함. - * 따라서 critical 한 url 에 대해서 OAuth2 인증이 완료된 세션에 한해서만 허용. - */ - @Override - protected void configure(HttpSecurity http) throws Exception { - - http - .requestMatchers().antMatchers("/login/**") - .and() - // 세션 생성 금지 - .sessionManagement() - .sessionCreationPolicy(SessionCreationPolicy.STATELESS) - .and() - .cors() - .and() - .authorizeRequests() - .requestMatchers(CorsUtils::isPreFlightRequest).permitAll() - .anyRequest().permitAll() - .and() - .csrf().disable() + private final CustomOAuth2UserService customOAuth2UserService; + private final OAuth2AuthorizedClientService authorizedClientService; + private final Oauth2AuthenticationSuccessHandler oauth2AuthenticationSuccessHandler; + private final Oauth2AuthenticationFailureHandler oauth2AuthenticationFailureHandler; + private final HttpCookieOAuth2AuthorizationRequestRepository + httpCookieOAuth2AuthorizationRequestRepository; - // Oauth 로그인 설정 - .oauth2Login() - .authorizedClientService(authorizedClientService) - .authorizationEndpoint() - .baseUri("/login/oauth2/authorization") - .authorizationRequestRepository(httpCookieOAuth2AuthorizationRequestRepository) - .and() + /** + * 소셜 로그인 api
+ *
+ * 진행과정은 아래와 같다.
+ * + *
    + *
  1. 사용자가 소셜로그인 시작. (프론트에서 redirect_url 보내줘야함.) + *
  2. OAuth2 인증 진행 -> 기존 회원인지 검사 + *
      + *
    1. 성공 -> OAuth2AuthenticationSuccessHandler + *
        + *
      1. 프론트에서 보내준 redirect_url 검증 (-> 실패하면 failure handler 에서 처리) + *
      2. jwt 토큰 발급 및 로그인 처리 + *
      3. 리다이렉트 + *
      + *
    2. 실패 -> OAuth2AuthenticationFailureHandler + *
    + *
+ * + * 회원가입이나, jwt 토큰 발급을 위한 url 로 함부로 접근할 수 없게 하기 위해 jwt 토근이 발급되기 이전까지는 OAuth2 인증 결과를 세션을 통해서 유지함. + * 따라서 critical 한 url 에 대해서 OAuth2 인증이 완료된 세션에 한해서만 허용. + */ + @Override + protected void configure(HttpSecurity http) throws Exception { - // 사용자 정보를 가져오는 엔드포인트에 대한 설정 - .userInfoEndpoint() - .userService(customOAuth2UserService) - .and() - .failureHandler(oauth2AuthenticationFailureHandler) - .successHandler(oauth2AuthenticationSuccessHandler); + http.requestMatchers() + .antMatchers("/login/**") + .and() + // 세션 생성 금지 + .sessionManagement() + .sessionCreationPolicy(SessionCreationPolicy.STATELESS) + .and() + .cors() + .and() + .authorizeRequests() + .requestMatchers(CorsUtils::isPreFlightRequest) + .permitAll() + .anyRequest() + .permitAll() + .and() + .csrf() + .disable() - } + // Oauth 로그인 설정 + .oauth2Login() + .authorizedClientService(authorizedClientService) + .authorizationEndpoint() + .baseUri("/login/oauth2/authorization") + .authorizationRequestRepository(httpCookieOAuth2AuthorizationRequestRepository) + .and() + // 사용자 정보를 가져오는 엔드포인트에 대한 설정 + .userInfoEndpoint() + .userService(customOAuth2UserService) + .and() + .failureHandler(oauth2AuthenticationFailureHandler) + .successHandler(oauth2AuthenticationSuccessHandler); + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/CorsConfig.java b/module-auth/src/main/java/com/inhabas/api/auth/CorsConfig.java index af3e731c..4edb2ec1 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/CorsConfig.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/CorsConfig.java @@ -5,18 +5,13 @@ import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; -/** - * 개발 서버에 한해서만 cors 를 적용함. 대신 개발 전용 api 에 대해 높은 수준의 access control 이 보장되어야 함. - */ +/** 개발 서버에 한해서만 cors 를 적용함. 대신 개발 전용 api 에 대해 높은 수준의 access control 이 보장되어야 함. */ @Configuration @Profile("dev") public class CorsConfig implements WebMvcConfigurer { - @Override - public void addCorsMappings(CorsRegistry registry) { - registry.addMapping("/**") - .allowedOrigins("*") - .allowedMethods("*") - .allowedHeaders("*"); - } + @Override + public void addCorsMappings(CorsRegistry registry) { + registry.addMapping("/**").allowedOrigins("*").allowedMethods("*").allowedHeaders("*"); + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/error/ErrorCode.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/error/ErrorCode.java index b3271228..f2fd51ea 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/error/ErrorCode.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/error/ErrorCode.java @@ -7,64 +7,52 @@ @AllArgsConstructor public enum ErrorCode { - // Global - INTERNAL_SERVER_ERROR(500, "G001", "내부 서버 오류입니다."), - METHOD_NOT_ALLOWED(405, "G002", "허용되지 않은 HTTP method입니다."), - INVALID_INPUT_VALUE(400, "G003", "입력값이 없거나, 타입이 유효하지 않습니다."), - NOT_FOUND(404, "G004", "데이터가 존재하지 않습니다."), - UNSUPPORTED_MEDIA_TYPE(415, "G005", "지원되지 않는 형식입니다."), - - // Basic - - - // Member - MEMBER_NOT_FOUND(400, "M001", "존재 하지 않는 유저입니다."), - AUTHORITY_INVALID(403, "M002", "권한이 없습니다."), - - // Auth (ExceptionHandler 불필요) - /** - * The value of one or more redirection URIs is - * unauthorized. - */ - UNAUTHORIZED_REDIRECT_URI(401, "A001", "유효하지 않은 redirect_uri 입니다."), - /** - * 지원하지 않는 소셜로그인 - */ - UNSUPPORTED_OAUTH2_PROVIDER(401, "A002", "지원하지 않는 소셜로그인입니다."), - /** - * 인증에 필수적인 정보가 OAuth provider 로부터 전달되지 않았음. - * 사용자가 개인정보 제공에 비동의했거나, 제대로 계정 정보를 설정하지 않은 경우 발생 - */ - INVALID_OAUTH2_INFO(401, "A003", "잘못된 OAuth 정보입니다."), - /** - * request 에 담긴 토큰정보를 사용해 기존 사용자 정보를 조회하였으나, 존재하지 않는 경우 발생. - * 또는 최초 소셜로그인 시도하였으나 가입한 회원이 아니라면 해당 오류 발생 - * @see com.inhabas.api.auth.domain.token.securityFilter; - */ - SOCIAL_NOT_FOUND(401, "A004", "기존 회원이 아니거나 회원가입 되지 않은 회원입니다."), - JWT_INVALID(401, "A005", "유효하지 않은 토큰입니다."), - JWT_EXPIRED(401, "A006", "만료된 토큰입니다."), - JWT_MISSING(401, "A007", "토큰이 존재하지 않습니다."), - EXPIRED_REFRESH_TOKEN(401, "A008", "만료된 REFRESH 토큰입니다. 재로그인 해주십시오."), - - - // SignUp - SIGNUP_NOT_AVAILABLE(403, "S001", "회원가입 기간이 아닙니다."), - INVALID_SIGNUP_DATE(400, "S002", "등록 마감일이 시작일보다 앞설 수 없습니다."), - INVALID_INTERVIEW_DATE(400, "S003", "면접 마감일이 시작일보다 앞설 수 없습니다."), - INVALID_ANNOUNCE_DATE(400, "S004", "결과 발표일이 면접 마감일보다 앞설 수 없습니다."), - NOT_WRITE_PROFILE(400, "S005", "아직 회원 프로필을 생성하지 않아서 회원가입을 마무리 할 수 없습니다."), - NOT_WRITE_ANSWERS(400, "S006", "아직 면접 질문을 작성하지 않아서 회원가입을 마무리 할 수 없습니다."), - - - // Board - WRITER_UNMODIFIABLE(403, "B001", "글 작성자를 변경 할 수 없습니다."), - ONLY_WRITER_UPDATE(403, "B002", "글 작성자만 수정 가능합니다."), - S3_UPLOAD_FAILED(500, "B003", "파일 업로드를 실패했습니다.") - ; - - private final int status; - private final String code; - private final String message; - + // Global + INTERNAL_SERVER_ERROR(500, "G001", "내부 서버 오류입니다."), + METHOD_NOT_ALLOWED(405, "G002", "허용되지 않은 HTTP method입니다."), + INVALID_INPUT_VALUE(400, "G003", "입력값이 없거나, 타입이 유효하지 않습니다."), + NOT_FOUND(404, "G004", "데이터가 존재하지 않습니다."), + UNSUPPORTED_MEDIA_TYPE(415, "G005", "지원되지 않는 형식입니다."), + + // Basic + + // Member + MEMBER_NOT_FOUND(400, "M001", "존재 하지 않는 유저입니다."), + AUTHORITY_INVALID(403, "M002", "권한이 없습니다."), + + // Auth (ExceptionHandler 불필요) + /** The value of one or more redirection URIs is unauthorized. */ + UNAUTHORIZED_REDIRECT_URI(401, "A001", "유효하지 않은 redirect_uri 입니다."), + /** 지원하지 않는 소셜로그인 */ + UNSUPPORTED_OAUTH2_PROVIDER(401, "A002", "지원하지 않는 소셜로그인입니다."), + /** 인증에 필수적인 정보가 OAuth provider 로부터 전달되지 않았음. 사용자가 개인정보 제공에 비동의했거나, 제대로 계정 정보를 설정하지 않은 경우 발생 */ + INVALID_OAUTH2_INFO(401, "A003", "잘못된 OAuth 정보입니다."), + /** + * request 에 담긴 토큰정보를 사용해 기존 사용자 정보를 조회하였으나, 존재하지 않는 경우 발생. 또는 최초 소셜로그인 시도하였으나 가입한 회원이 아니라면 해당 오류 + * 발생 + * + * @see com.inhabas.api.auth.domain.token.securityFilter; + */ + SOCIAL_NOT_FOUND(401, "A004", "기존 회원이 아니거나 회원가입 되지 않은 회원입니다."), + JWT_INVALID(401, "A005", "유효하지 않은 토큰입니다."), + JWT_EXPIRED(401, "A006", "만료된 토큰입니다."), + JWT_MISSING(401, "A007", "토큰이 존재하지 않습니다."), + EXPIRED_REFRESH_TOKEN(401, "A008", "만료된 REFRESH 토큰입니다. 재로그인 해주십시오."), + + // SignUp + SIGNUP_NOT_AVAILABLE(403, "S001", "회원가입 기간이 아닙니다."), + INVALID_SIGNUP_DATE(400, "S002", "등록 마감일이 시작일보다 앞설 수 없습니다."), + INVALID_INTERVIEW_DATE(400, "S003", "면접 마감일이 시작일보다 앞설 수 없습니다."), + INVALID_ANNOUNCE_DATE(400, "S004", "결과 발표일이 면접 마감일보다 앞설 수 없습니다."), + NOT_WRITE_PROFILE(400, "S005", "아직 회원 프로필을 생성하지 않아서 회원가입을 마무리 할 수 없습니다."), + NOT_WRITE_ANSWERS(400, "S006", "아직 면접 질문을 작성하지 않아서 회원가입을 마무리 할 수 없습니다."), + + // Board + WRITER_UNMODIFIABLE(403, "B001", "글 작성자를 변경 할 수 없습니다."), + ONLY_WRITER_UPDATE(403, "B002", "글 작성자만 수정 가능합니다."), + S3_UPLOAD_FAILED(500, "B003", "파일 업로드를 실패했습니다."); + + private final int status; + private final String code; + private final String message; } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/error/ErrorResponse.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/error/ErrorResponse.java index 5ee2bf7b..66e4c8b2 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/error/ErrorResponse.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/error/ErrorResponse.java @@ -8,20 +8,17 @@ @NoArgsConstructor(access = AccessLevel.PROTECTED) public class ErrorResponse { - private int status; - private String code; - private String message; - - - private ErrorResponse(final ErrorCode code) { - this.message = code.getMessage(); - this.status = code.getStatus(); - this.code = code.getCode(); - } - - public static ErrorResponse of(final ErrorCode code) { - return new ErrorResponse(code); - } - + private int status; + private String code; + private String message; + + private ErrorResponse(final ErrorCode code) { + this.message = code.getMessage(); + this.status = code.getStatus(); + this.code = code.getCode(); + } + + public static ErrorResponse of(final ErrorCode code) { + return new ErrorResponse(code); + } } - diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/error/authException/AuthExceptionCodes.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/error/authException/AuthExceptionCodes.java index 0bd1874f..ee3916d1 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/error/authException/AuthExceptionCodes.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/error/authException/AuthExceptionCodes.java @@ -2,46 +2,39 @@ public interface AuthExceptionCodes { - - /** - * {@code invalid_request} - The request is missing a required parameter, includes an - * invalid parameter value, includes a parameter more than once, or is otherwise - * malformed. - */ - String INVALID_REQUEST = "invalid_request"; - - /** - * {@code access_denied} - The resource owner or authorization server denied the - * request. - */ - String ACCESS_DENIED = "access_denied"; - - /** - * {@code invalid_token} - The access token provided is expired, revoked, malformed, - * or invalid for other reasons. The resource SHOULD respond with the HTTP 401 - * (Unauthorized) status code. The client MAY request a new access token and retry the - * protected resource request. - * - * @see RFC-6750 - Section - * 3.1 - Error Codes - */ - String INVALID_TOKEN = "invalid_token"; - - /** - * {@code temporarily_unavailable} - The authorization server is currently unable to - * handle the request due to a temporary overloading or maintenance of the server. - * (This error code is needed because a 503 Service Unavailable HTTP status code - * cannot be returned to the client via an HTTP redirect.) - */ - String TEMPORARILY_UNAVAILABLE = "temporarily_unavailable"; - - /** - * {@code unsupported_token_type} - The authorization server does not support the - * revocation of the presented token type. - * - * @see RFC-7009 - Section - * 2.2.1 - Error Response - */ - String UNSUPPORTED_TOKEN_TYPE = "unsupported_token_type"; - + /** + * {@code invalid_request} - The request is missing a required parameter, includes an invalid + * parameter value, includes a parameter more than once, or is otherwise malformed. + */ + String INVALID_REQUEST = "invalid_request"; + + /** {@code access_denied} - The resource owner or authorization server denied the request. */ + String ACCESS_DENIED = "access_denied"; + + /** + * {@code invalid_token} - The access token provided is expired, revoked, malformed, or invalid + * for other reasons. The resource SHOULD respond with the HTTP 401 (Unauthorized) status code. + * The client MAY request a new access token and retry the protected resource request. + * + * @see RFC-6750 - Section 3.1 - Error + * Codes + */ + String INVALID_TOKEN = "invalid_token"; + + /** + * {@code temporarily_unavailable} - The authorization server is currently unable to handle the + * request due to a temporary overloading or maintenance of the server. (This error code is needed + * because a 503 Service Unavailable HTTP status code cannot be returned to the client via an HTTP + * redirect.) + */ + String TEMPORARILY_UNAVAILABLE = "temporarily_unavailable"; + + /** + * {@code unsupported_token_type} - The authorization server does not support the revocation of + * the presented token type. + * + * @see RFC-7009 - Section 2.2.1 - + * Error Response + */ + String UNSUPPORTED_TOKEN_TYPE = "unsupported_token_type"; } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/error/authException/CustomAuthException.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/error/authException/CustomAuthException.java index 05998520..aec7e3c1 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/error/authException/CustomAuthException.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/error/authException/CustomAuthException.java @@ -1,27 +1,27 @@ package com.inhabas.api.auth.domain.error.authException; -import com.inhabas.api.auth.domain.error.ErrorCode; import lombok.Getter; + import org.springframework.security.core.AuthenticationException; +import com.inhabas.api.auth.domain.error.ErrorCode; + /** - * {@code auth-module} 에서 발생하는 오류들은 {@code CustomAuthException} 을 상속받아서 구현해야함. - * 특히 spring security filter에서 발생하는 오류들을 처리하기 위해서는 필수적으로 {@code AuthenticationException} 을 상속받아야함. + * {@code auth-module} 에서 발생하는 오류들은 {@code CustomAuthException} 을 상속받아서 구현해야함. 특히 spring security + * filter에서 발생하는 오류들을 처리하기 위해서는 필수적으로 {@code AuthenticationException} 을 상속받아야함. */ @Getter public abstract class CustomAuthException extends AuthenticationException { - private final ErrorCode errorCode; - - - public CustomAuthException(String message, ErrorCode errorCode) { - super(message); - this.errorCode = errorCode; - } + private final ErrorCode errorCode; - public CustomAuthException(ErrorCode errorCode) { - super(errorCode.getMessage()); - this.errorCode = errorCode; - } + public CustomAuthException(String message, ErrorCode errorCode) { + super(message); + this.errorCode = errorCode; + } + public CustomAuthException(ErrorCode errorCode) { + super(errorCode.getMessage()); + this.errorCode = errorCode; + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/error/authException/InvalidAuthorityException.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/error/authException/InvalidAuthorityException.java index 47499730..842585ae 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/error/authException/InvalidAuthorityException.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/error/authException/InvalidAuthorityException.java @@ -4,8 +4,7 @@ public class InvalidAuthorityException extends CustomAuthException { - public InvalidAuthorityException() { - super(ErrorCode.AUTHORITY_INVALID); - } - + public InvalidAuthorityException() { + super(ErrorCode.AUTHORITY_INVALID); + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/error/authException/InvalidOAuth2InfoException.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/error/authException/InvalidOAuth2InfoException.java index b1896497..b666e4f0 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/error/authException/InvalidOAuth2InfoException.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/error/authException/InvalidOAuth2InfoException.java @@ -4,7 +4,7 @@ public class InvalidOAuth2InfoException extends CustomAuthException { - public InvalidOAuth2InfoException() { - super(ErrorCode.INVALID_OAUTH2_INFO); - } + public InvalidOAuth2InfoException() { + super(ErrorCode.INVALID_OAUTH2_INFO); + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/error/authException/UnauthorizedRedirectUrlException.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/error/authException/UnauthorizedRedirectUrlException.java index f4974ff0..897760ca 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/error/authException/UnauthorizedRedirectUrlException.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/error/authException/UnauthorizedRedirectUrlException.java @@ -2,9 +2,9 @@ import com.inhabas.api.auth.domain.error.ErrorCode; -public class UnauthorizedRedirectUrlException extends CustomAuthException{ +public class UnauthorizedRedirectUrlException extends CustomAuthException { - public UnauthorizedRedirectUrlException() { - super(ErrorCode.UNAUTHORIZED_REDIRECT_URI); - } + public UnauthorizedRedirectUrlException() { + super(ErrorCode.UNAUTHORIZED_REDIRECT_URI); + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/error/authException/UnsupportedOAuth2ProviderException.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/error/authException/UnsupportedOAuth2ProviderException.java index 1549b22e..77b67cea 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/error/authException/UnsupportedOAuth2ProviderException.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/error/authException/UnsupportedOAuth2ProviderException.java @@ -4,7 +4,7 @@ public class UnsupportedOAuth2ProviderException extends CustomAuthException { - public UnsupportedOAuth2ProviderException() { - super(ErrorCode.UNSUPPORTED_OAUTH2_PROVIDER); - } + public UnsupportedOAuth2ProviderException() { + super(ErrorCode.UNSUPPORTED_OAUTH2_PROVIDER); + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/error/businessException/BusinessException.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/error/businessException/BusinessException.java index 02faa024..ce4d34d9 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/error/businessException/BusinessException.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/error/businessException/BusinessException.java @@ -1,21 +1,21 @@ package com.inhabas.api.auth.domain.error.businessException; -import com.inhabas.api.auth.domain.error.ErrorCode; import lombok.Getter; +import com.inhabas.api.auth.domain.error.ErrorCode; + @Getter public class BusinessException extends RuntimeException { - private final ErrorCode errorCode; - - public BusinessException(String message, ErrorCode errorCode) { - super(message); - this.errorCode = errorCode; - } + private final ErrorCode errorCode; - public BusinessException(ErrorCode errorCode) { - super(errorCode.getMessage()); - this.errorCode = errorCode; - } + public BusinessException(String message, ErrorCode errorCode) { + super(message); + this.errorCode = errorCode; + } -} \ No newline at end of file + public BusinessException(ErrorCode errorCode) { + super(errorCode.getMessage()); + this.errorCode = errorCode; + } +} diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/error/businessException/InternalServerException.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/error/businessException/InternalServerException.java index 700b983c..21b0384a 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/error/businessException/InternalServerException.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/error/businessException/InternalServerException.java @@ -4,10 +4,7 @@ public class InternalServerException extends BusinessException { - public InternalServerException() { - super(ErrorCode.INTERNAL_SERVER_ERROR); - } - + public InternalServerException() { + super(ErrorCode.INTERNAL_SERVER_ERROR); + } } - - diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/error/businessException/InvalidInputException.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/error/businessException/InvalidInputException.java index d1e4050f..ef7354d0 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/error/businessException/InvalidInputException.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/error/businessException/InvalidInputException.java @@ -4,9 +4,7 @@ public class InvalidInputException extends BusinessException { - public InvalidInputException() { - super(ErrorCode.INVALID_INPUT_VALUE); - } - + public InvalidInputException() { + super(ErrorCode.INVALID_INPUT_VALUE); + } } - diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/error/businessException/NotFoundException.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/error/businessException/NotFoundException.java index 9c0a2aba..95c192a5 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/error/businessException/NotFoundException.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/error/businessException/NotFoundException.java @@ -4,10 +4,7 @@ public class NotFoundException extends BusinessException { - public NotFoundException() { - super(ErrorCode.NOT_FOUND); - } - + public NotFoundException() { + super(ErrorCode.NOT_FOUND); + } } - - diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/CustomOAuth2User.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/CustomOAuth2User.java index baba4e37..63ed1d92 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/CustomOAuth2User.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/CustomOAuth2User.java @@ -1,29 +1,29 @@ package com.inhabas.api.auth.domain.oauth2; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.oauth2.core.user.DefaultOAuth2User; - import java.util.Collection; import java.util.Map; -public class CustomOAuth2User extends DefaultOAuth2User { - - private Long memberId; - - public CustomOAuth2User(Collection authorities, - Map attributes, - String nameAttributeKey, - Long memberId) { - super(authorities, attributes, nameAttributeKey); - this.memberId = memberId; - } - - public Long getMemberId() { - return memberId; - } +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.oauth2.core.user.DefaultOAuth2User; - public void setMemberId(Long memberId) { - this.memberId = memberId; - } +public class CustomOAuth2User extends DefaultOAuth2User { -} \ No newline at end of file + private Long memberId; + + public CustomOAuth2User( + Collection authorities, + Map attributes, + String nameAttributeKey, + Long memberId) { + super(authorities, attributes, nameAttributeKey); + this.memberId = memberId; + } + + public Long getMemberId() { + return memberId; + } + + public void setMemberId(Long memberId) { + this.memberId = memberId; + } +} diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/CustomOAuth2UserService.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/CustomOAuth2UserService.java index 3665ba20..fbdf03dd 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/CustomOAuth2UserService.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/CustomOAuth2UserService.java @@ -1,14 +1,9 @@ package com.inhabas.api.auth.domain.oauth2; -import com.inhabas.api.auth.domain.error.authException.InvalidOAuth2InfoException; -import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; -import com.inhabas.api.auth.domain.oauth2.socialAccount.domain.valueObject.UID; -import com.inhabas.api.auth.domain.oauth2.userAuthorityProvider.UserAuthorityProvider; -import com.inhabas.api.auth.domain.oauth2.userInfo.OAuth2UserInfo; -import com.inhabas.api.auth.domain.oauth2.userInfo.OAuth2UserInfoFactory; -import com.inhabas.api.auth.domain.oauth2.member.service.MemberService; -import com.inhabas.api.auth.domain.oauth2.member.repository.MemberRepository; +import java.util.Collection; + import lombok.RequiredArgsConstructor; + import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService; import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest; @@ -17,39 +12,53 @@ import org.springframework.security.oauth2.core.user.OAuth2User; import org.springframework.stereotype.Component; -import java.util.Collection; +import com.inhabas.api.auth.domain.error.authException.InvalidOAuth2InfoException; +import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; +import com.inhabas.api.auth.domain.oauth2.member.repository.MemberRepository; +import com.inhabas.api.auth.domain.oauth2.member.service.MemberService; +import com.inhabas.api.auth.domain.oauth2.socialAccount.domain.valueObject.UID; +import com.inhabas.api.auth.domain.oauth2.userAuthorityProvider.UserAuthorityProvider; +import com.inhabas.api.auth.domain.oauth2.userInfo.OAuth2UserInfo; +import com.inhabas.api.auth.domain.oauth2.userInfo.OAuth2UserInfoFactory; @Component @RequiredArgsConstructor public class CustomOAuth2UserService extends DefaultOAuth2UserService { - private final UserAuthorityProvider userAuthorityProvider; - private final MemberService memberService; - private final MemberRepository memberRepository; - - @Override - public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException { + private final UserAuthorityProvider userAuthorityProvider; + private final MemberService memberService; + private final MemberRepository memberRepository; - DefaultOAuth2User oAuth2User = (DefaultOAuth2User) super.loadUser(userRequest); + @Override + public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException { - OAuth2UserInfo oAuth2UserInfo = OAuth2UserInfoFactory.getOAuth2UserInfo( - userRequest.getClientRegistration().getRegistrationId(), oAuth2User.getAttributes()); - // 필수값 받아왔는지 확인 - if(!oAuth2UserInfo.validateNecessaryFields()) { - throw new InvalidOAuth2InfoException(); - } - // db 에 소셜 계정 정보 update - memberService.updateSocialAccountInfo(oAuth2UserInfo); - Member member = memberRepository.findByProviderAndUid( - oAuth2UserInfo.getProvider(), new UID(oAuth2UserInfo.getId())) - .orElseThrow(() -> new InvalidOAuth2InfoException()); + DefaultOAuth2User oAuth2User = (DefaultOAuth2User) super.loadUser(userRequest); + OAuth2UserInfo oAuth2UserInfo = + OAuth2UserInfoFactory.getOAuth2UserInfo( + userRequest.getClientRegistration().getRegistrationId(), oAuth2User.getAttributes()); + // 필수값 받아왔는지 확인 + if (!oAuth2UserInfo.validateNecessaryFields()) { + throw new InvalidOAuth2InfoException(); + } + // db 에 소셜 계정 정보 update + memberService.updateSocialAccountInfo(oAuth2UserInfo); + Member member = + memberRepository + .findByProviderAndUid(oAuth2UserInfo.getProvider(), new UID(oAuth2UserInfo.getId())) + .orElseThrow(() -> new InvalidOAuth2InfoException()); - // 현재 로그인하려는 유저에 맞는 권한을 들고옴. - Collection authorities = userAuthorityProvider.determineAuthorities(oAuth2UserInfo); + // 현재 로그인하려는 유저에 맞는 권한을 들고옴. + Collection authorities = + userAuthorityProvider.determineAuthorities(oAuth2UserInfo); - String nameAttributeKey = userRequest.getClientRegistration().getProviderDetails().getUserInfoEndpoint() - .getUserNameAttributeName(); - return new CustomOAuth2User(authorities, oAuth2UserInfo.getAttributes(), nameAttributeKey, member.getId()); - } + String nameAttributeKey = + userRequest + .getClientRegistration() + .getProviderDetails() + .getUserInfoEndpoint() + .getUserNameAttributeName(); + return new CustomOAuth2User( + authorities, oAuth2UserInfo.getAttributes(), nameAttributeKey, member.getId()); + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/OAuth2Provider.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/OAuth2Provider.java index 1e1dc720..e1bb4af8 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/OAuth2Provider.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/OAuth2Provider.java @@ -1,25 +1,25 @@ package com.inhabas.api.auth.domain.oauth2; -import com.inhabas.api.auth.domain.error.authException.UnsupportedOAuth2ProviderException; - import java.util.Arrays; -public enum OAuth2Provider { - GOOGLE, - NAVER, - KAKAO; +import com.inhabas.api.auth.domain.error.authException.UnsupportedOAuth2ProviderException; - /** - * 대소문자 구분하지 않고 OAuth2Provider 타입으로 변환. +public enum OAuth2Provider { + GOOGLE, + NAVER, + KAKAO; - * @param registrationId oauth2 provider - * @return OAuth2Provider - * @exception UnsupportedOAuth2ProviderException 지원하지 않는 OAuth2 Provider 입니다. - */ - public static OAuth2Provider convert(String registrationId) { - return Arrays.stream(OAuth2Provider.values()) - .filter(provider -> provider.toString().equals(registrationId.toUpperCase())) - .findAny() - .orElseThrow(UnsupportedOAuth2ProviderException::new); - } + /** + * 대소문자 구분하지 않고 OAuth2Provider 타입으로 변환. + * + * @param registrationId oauth2 provider + * @return OAuth2Provider + * @exception UnsupportedOAuth2ProviderException 지원하지 않는 OAuth2 Provider 입니다. + */ + public static OAuth2Provider convert(String registrationId) { + return Arrays.stream(OAuth2Provider.values()) + .filter(provider -> provider.toString().equals(registrationId.toUpperCase())) + .findAny() + .orElseThrow(UnsupportedOAuth2ProviderException::new); + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/cookie/CookieUtils.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/cookie/CookieUtils.java index 2c97c088..521c4095 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/cookie/CookieUtils.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/cookie/CookieUtils.java @@ -1,98 +1,93 @@ package com.inhabas.api.auth.domain.oauth2.cookie; -import io.micrometer.core.instrument.util.StringUtils; -import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest; -import org.springframework.util.SerializationUtils; - -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; import java.util.Base64; import java.util.Objects; import java.util.Optional; -public interface CookieUtils { +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; - /** - * request 에 담겨 있는 쿠키를 꺼낸다. - */ - static Optional resolveCookie(HttpServletRequest request, String cookieName) { +import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest; +import org.springframework.util.SerializationUtils; - Cookie[] cookies = request.getCookies(); +import io.micrometer.core.instrument.util.StringUtils; - if (cookies != null && cookies.length > 0) { - for (Cookie cookie : cookies) { - if (cookie.getName().equals(cookieName)) { - return Optional.of(cookie); - } - } - } +public interface CookieUtils { - return Optional.empty(); - } + /** request 에 담겨 있는 쿠키를 꺼낸다. */ + static Optional resolveCookie(HttpServletRequest request, String cookieName) { + Cookie[] cookies = request.getCookies(); - /** - * 쿠키를 지우는 작업은 없고, maxAge 를 0으로 설정해서 브라우저가 파기하도록 한다. - */ - static void deleteCookie(HttpServletRequest request, HttpServletResponse response, String cookieName) { - - Cookie[] cookies = request.getCookies(); - if (cookies != null && cookies.length > 0) { - for (Cookie cookie: cookies) { - if (cookie.getName().equals(cookieName)) { - cookie.setValue(""); - cookie.setPath("/"); - cookie.setMaxAge(0); - response.addCookie(cookie); - break; - } - } + if (cookies != null && cookies.length > 0) { + for (Cookie cookie : cookies) { + if (cookie.getName().equals(cookieName)) { + return Optional.of(cookie); } + } } - /** - * @param response 응답에 쿠키를 적어서 보내줌 - * @param cookieName key - * @param cookieContents value - * @param maxAge 초 단위 - */ - static void setCookie(HttpServletResponse response, String cookieName, String cookieContents, int maxAge) { - - Cookie cookie = new Cookie(cookieName, cookieContents); - cookie.setPath("/"); - cookie.setHttpOnly(true); - cookie.setMaxAge(maxAge); - response.addCookie(cookie); - } - - - /** - * @param request OAuth2AuthorizationRequest - * @return 브라우저 쿠키에 담기 위해 OAuth2AuthorizationRequest 를 string 으로 변환. - */ - static String serialize(OAuth2AuthorizationRequest request) { - - return Base64.getUrlEncoder() - .encodeToString(SerializationUtils.serialize(request)); - } - - - /** - * @param cookie HttpServletRequest 로부터 resolve 한 쿠키 - * @param clz 반환 타입 - * @return string 으로 쿠키의 값을 clz 타입으로 반환 - */ - static T deserialize(Cookie cookie, Class clz) { - - if (isDeleted(cookie)) - return null; - else - return clz.cast(SerializationUtils.deserialize( - Base64.getUrlDecoder().decode(cookie.getValue()))); - } - - private static boolean isDeleted(Cookie cookie) { - return StringUtils.isBlank(cookie.getValue()) || Objects.isNull(cookie.getValue()); + return Optional.empty(); + } + + /** 쿠키를 지우는 작업은 없고, maxAge 를 0으로 설정해서 브라우저가 파기하도록 한다. */ + static void deleteCookie( + HttpServletRequest request, HttpServletResponse response, String cookieName) { + + Cookie[] cookies = request.getCookies(); + if (cookies != null && cookies.length > 0) { + for (Cookie cookie : cookies) { + if (cookie.getName().equals(cookieName)) { + cookie.setValue(""); + cookie.setPath("/"); + cookie.setMaxAge(0); + response.addCookie(cookie); + break; + } + } } + } + + /** + * @param response 응답에 쿠키를 적어서 보내줌 + * @param cookieName key + * @param cookieContents value + * @param maxAge 초 단위 + */ + static void setCookie( + HttpServletResponse response, String cookieName, String cookieContents, int maxAge) { + + Cookie cookie = new Cookie(cookieName, cookieContents); + cookie.setPath("/"); + cookie.setHttpOnly(true); + cookie.setMaxAge(maxAge); + response.addCookie(cookie); + } + + /** + * @param request OAuth2AuthorizationRequest + * @return 브라우저 쿠키에 담기 위해 OAuth2AuthorizationRequest 를 string 으로 변환. + */ + static String serialize(OAuth2AuthorizationRequest request) { + + return Base64.getUrlEncoder().encodeToString(SerializationUtils.serialize(request)); + } + + /** + * @param cookie HttpServletRequest 로부터 resolve 한 쿠키 + * @param clz 반환 타입 + * @return string 으로 쿠키의 값을 clz 타입으로 반환 + */ + static T deserialize(Cookie cookie, Class clz) { + + if (isDeleted(cookie)) return null; + else + return clz.cast( + SerializationUtils.deserialize(Base64.getUrlDecoder().decode(cookie.getValue()))); + } + + private static boolean isDeleted(Cookie cookie) { + return StringUtils.isBlank(cookie.getValue()) || Objects.isNull(cookie.getValue()); + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/cookie/HttpCookieOAuth2AuthorizationRequestRepository.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/cookie/HttpCookieOAuth2AuthorizationRequestRepository.java index d02c165a..9173941e 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/cookie/HttpCookieOAuth2AuthorizationRequestRepository.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/cookie/HttpCookieOAuth2AuthorizationRequestRepository.java @@ -1,72 +1,81 @@ package com.inhabas.api.auth.domain.oauth2.cookie; -import org.apache.commons.lang3.StringUtils; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + import org.springframework.security.oauth2.client.web.AuthorizationRequestRepository; import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import org.apache.commons.lang3.StringUtils; /** - * IBAS 로그인 과정 종료 후에 프론트로 리다이렉션 시켜줘야하는데, 프론트에서 최초 요청 파라미터(redirect_uri)로 콜백 주소를 지정하게 해주기 위함. - * OAuth2 Authorization Code Grant 과정에서 리다이렉션이 일어나므로 요청 파라미터를 브라우저 쿠키에 저장해야함. - * 따라서 Oauth2AuthorizationRequest 를 쿠키에 저장. + * IBAS 로그인 과정 종료 후에 프론트로 리다이렉션 시켜줘야하는데, 프론트에서 최초 요청 파라미터(redirect_uri)로 콜백 주소를 지정하게 해주기 위함. OAuth2 + * Authorization Code Grant 과정에서 리다이렉션이 일어나므로 요청 파라미터를 브라우저 쿠키에 저장해야함. 따라서 + * Oauth2AuthorizationRequest 를 쿠키에 저장. + * * @see org.springframework.security.oauth2.client.web.AuthorizationRequestRepository */ -public class HttpCookieOAuth2AuthorizationRequestRepository implements AuthorizationRequestRepository { - - public static final String OAUTH2_AUTHORIZATION_REQUEST_COOKIE_NAME = "oauth2_auth_request"; - public static final String REDIRECT_URL_PARAM_COOKIE_NAME = "redirect_url"; - private static final int cookieExpireSeconds = 180; +public class HttpCookieOAuth2AuthorizationRequestRepository + implements AuthorizationRequestRepository { + public static final String OAUTH2_AUTHORIZATION_REQUEST_COOKIE_NAME = "oauth2_auth_request"; + public static final String REDIRECT_URL_PARAM_COOKIE_NAME = "redirect_url"; + private static final int cookieExpireSeconds = 180; - @Override - public OAuth2AuthorizationRequest loadAuthorizationRequest(HttpServletRequest request) { - return CookieUtils.resolveCookie(request, OAUTH2_AUTHORIZATION_REQUEST_COOKIE_NAME) - .map(cookie -> CookieUtils.deserialize(cookie, OAuth2AuthorizationRequest.class)) - .orElse(null); - } + @Override + public OAuth2AuthorizationRequest loadAuthorizationRequest(HttpServletRequest request) { + return CookieUtils.resolveCookie(request, OAUTH2_AUTHORIZATION_REQUEST_COOKIE_NAME) + .map(cookie -> CookieUtils.deserialize(cookie, OAuth2AuthorizationRequest.class)) + .orElse(null); + } - @Override - public void saveAuthorizationRequest(OAuth2AuthorizationRequest authorizationRequest, HttpServletRequest request, HttpServletResponse response) { - if (authorizationRequest == null) { - CookieUtils.deleteCookie(request, response, OAUTH2_AUTHORIZATION_REQUEST_COOKIE_NAME); - CookieUtils.deleteCookie(request, response, REDIRECT_URL_PARAM_COOKIE_NAME); - return; - } - CookieUtils.setCookie(response, OAUTH2_AUTHORIZATION_REQUEST_COOKIE_NAME, CookieUtils.serialize(authorizationRequest), cookieExpireSeconds); - String redirectUrlAfterLogin = request.getParameter(REDIRECT_URL_PARAM_COOKIE_NAME); - if (StringUtils.isNotBlank(redirectUrlAfterLogin)) { - CookieUtils.setCookie(response, REDIRECT_URL_PARAM_COOKIE_NAME, redirectUrlAfterLogin, cookieExpireSeconds); - } + @Override + public void saveAuthorizationRequest( + OAuth2AuthorizationRequest authorizationRequest, + HttpServletRequest request, + HttpServletResponse response) { + if (authorizationRequest == null) { + CookieUtils.deleteCookie(request, response, OAUTH2_AUTHORIZATION_REQUEST_COOKIE_NAME); + CookieUtils.deleteCookie(request, response, REDIRECT_URL_PARAM_COOKIE_NAME); + return; } - - @Deprecated - @Override - public OAuth2AuthorizationRequest removeAuthorizationRequest(HttpServletRequest request) { - return null; + CookieUtils.setCookie( + response, + OAUTH2_AUTHORIZATION_REQUEST_COOKIE_NAME, + CookieUtils.serialize(authorizationRequest), + cookieExpireSeconds); + String redirectUrlAfterLogin = request.getParameter(REDIRECT_URL_PARAM_COOKIE_NAME); + if (StringUtils.isNotBlank(redirectUrlAfterLogin)) { + CookieUtils.setCookie( + response, REDIRECT_URL_PARAM_COOKIE_NAME, redirectUrlAfterLogin, cookieExpireSeconds); } + } - /** - * OAuth2AuthorizationRequest 를 쿠키에서 제거함. - * @return OAuth2AuthorizationRequest - */ - @Override - public OAuth2AuthorizationRequest removeAuthorizationRequest(HttpServletRequest request, HttpServletResponse response) { + @Deprecated + @Override + public OAuth2AuthorizationRequest removeAuthorizationRequest(HttpServletRequest request) { + return null; + } - // 쿠키 삭제하기 전에 쿠키 문자열을 객체로 변환 - OAuth2AuthorizationRequest authorizationRequest = this.loadAuthorizationRequest(request); - CookieUtils.deleteCookie(request, response, OAUTH2_AUTHORIZATION_REQUEST_COOKIE_NAME); + /** + * OAuth2AuthorizationRequest 를 쿠키에서 제거함. + * + * @return OAuth2AuthorizationRequest + */ + @Override + public OAuth2AuthorizationRequest removeAuthorizationRequest( + HttpServletRequest request, HttpServletResponse response) { - return authorizationRequest; - } + // 쿠키 삭제하기 전에 쿠키 문자열을 객체로 변환 + OAuth2AuthorizationRequest authorizationRequest = this.loadAuthorizationRequest(request); + CookieUtils.deleteCookie(request, response, OAUTH2_AUTHORIZATION_REQUEST_COOKIE_NAME); + return authorizationRequest; + } - /** - * redirect_url이 담긴 쿠키는 인증이 완전히 완료된 후에 제거되어야함. - */ - public void clearCookies(HttpServletRequest request, HttpServletResponse response) { - CookieUtils.deleteCookie(request, response, OAUTH2_AUTHORIZATION_REQUEST_COOKIE_NAME); - CookieUtils.deleteCookie(request, response, REDIRECT_URL_PARAM_COOKIE_NAME); - } + /** redirect_url이 담긴 쿠키는 인증이 완전히 완료된 후에 제거되어야함. */ + public void clearCookies(HttpServletRequest request, HttpServletResponse response) { + CookieUtils.deleteCookie(request, response, OAUTH2_AUTHORIZATION_REQUEST_COOKIE_NAME); + CookieUtils.deleteCookie(request, response, REDIRECT_URL_PARAM_COOKIE_NAME); + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/handler/Oauth2AuthenticationFailureHandler.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/handler/Oauth2AuthenticationFailureHandler.java index 4f337a59..7a56fc88 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/handler/Oauth2AuthenticationFailureHandler.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/handler/Oauth2AuthenticationFailureHandler.java @@ -1,56 +1,58 @@ package com.inhabas.api.auth.domain.oauth2.handler; -import com.inhabas.api.auth.AuthProperties; -import com.inhabas.api.auth.domain.oauth2.cookie.HttpCookieOAuth2AuthorizationRequestRepository; -import lombok.RequiredArgsConstructor; -import org.springframework.security.core.AuthenticationException; -import org.springframework.security.oauth2.core.OAuth2AuthenticationException; -import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; -@RequiredArgsConstructor -public class Oauth2AuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler { +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; - private final AuthProperties authProperties; - private final HttpCookieOAuth2AuthorizationRequestRepository httpCookieOAuth2AuthorizationRequestRepository; - private static final String ERROR_PARAM = "?error="; +import lombok.RequiredArgsConstructor; - @Override - public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException { +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.oauth2.core.OAuth2AuthenticationException; +import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler; - String targetUrl = getAuthorizedTargetUrl(exception); +import com.inhabas.api.auth.AuthProperties; +import com.inhabas.api.auth.domain.oauth2.cookie.HttpCookieOAuth2AuthorizationRequestRepository; - httpCookieOAuth2AuthorizationRequestRepository.clearCookies(request, response); - getRedirectStrategy().sendRedirect(request, response, targetUrl); +@RequiredArgsConstructor +public class Oauth2AuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler { - } + private final AuthProperties authProperties; + private final HttpCookieOAuth2AuthorizationRequestRepository + httpCookieOAuth2AuthorizationRequestRepository; + private static final String ERROR_PARAM = "?error="; + @Override + public void onAuthenticationFailure( + HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) + throws IOException { - private String getAuthorizedTargetUrl(AuthenticationException exception) { + String targetUrl = getAuthorizedTargetUrl(exception); - StringBuilder targetUrl = new StringBuilder(); - targetUrl.append(authProperties.getOauth2().getDefaultRedirectUri()); + httpCookieOAuth2AuthorizationRequestRepository.clearCookies(request, response); + getRedirectStrategy().sendRedirect(request, response, targetUrl); + } - String encodedErrorMessage = URLEncoder.encode(getExceptionMessage(exception), StandardCharsets.UTF_8); - targetUrl.append(ERROR_PARAM).append(encodedErrorMessage); + private String getAuthorizedTargetUrl(AuthenticationException exception) { - return targetUrl.toString(); + StringBuilder targetUrl = new StringBuilder(); + targetUrl.append(authProperties.getOauth2().getDefaultRedirectUri()); - } + String encodedErrorMessage = + URLEncoder.encode(getExceptionMessage(exception), StandardCharsets.UTF_8); + targetUrl.append(ERROR_PARAM).append(encodedErrorMessage); + return targetUrl.toString(); + } - private String getExceptionMessage(AuthenticationException exception) { + private String getExceptionMessage(AuthenticationException exception) { - if (exception instanceof OAuth2AuthenticationException) { - return ((OAuth2AuthenticationException) exception).getError().getErrorCode(); - } else { - return exception.getLocalizedMessage(); - } + if (exception instanceof OAuth2AuthenticationException) { + return ((OAuth2AuthenticationException) exception).getError().getErrorCode(); + } else { + return exception.getLocalizedMessage(); } - + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/handler/Oauth2AuthenticationSuccessHandler.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/handler/Oauth2AuthenticationSuccessHandler.java index 1547bb94..77432981 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/handler/Oauth2AuthenticationSuccessHandler.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/handler/Oauth2AuthenticationSuccessHandler.java @@ -1,82 +1,90 @@ package com.inhabas.api.auth.domain.oauth2.handler; -import com.inhabas.api.auth.AuthProperties; -import com.inhabas.api.auth.domain.error.authException.UnauthorizedRedirectUrlException; -import com.inhabas.api.auth.domain.oauth2.cookie.CookieUtils; -import com.inhabas.api.auth.domain.oauth2.cookie.HttpCookieOAuth2AuthorizationRequestRepository; -import com.inhabas.api.auth.domain.oauth2.userInfo.OAuth2UserInfoFactory; -import com.inhabas.api.auth.domain.token.TokenUtil; +import static com.inhabas.api.auth.domain.oauth2.cookie.HttpCookieOAuth2AuthorizationRequestRepository.REDIRECT_URL_PARAM_COOKIE_NAME; + +import java.io.IOException; + +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; + import org.springframework.security.core.Authentication; import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken; import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler; import org.springframework.web.util.UriComponentsBuilder; -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; - -import static com.inhabas.api.auth.domain.oauth2.cookie.HttpCookieOAuth2AuthorizationRequestRepository.REDIRECT_URL_PARAM_COOKIE_NAME; - +import com.inhabas.api.auth.AuthProperties; +import com.inhabas.api.auth.domain.error.authException.UnauthorizedRedirectUrlException; +import com.inhabas.api.auth.domain.oauth2.cookie.CookieUtils; +import com.inhabas.api.auth.domain.oauth2.cookie.HttpCookieOAuth2AuthorizationRequestRepository; +import com.inhabas.api.auth.domain.oauth2.userInfo.OAuth2UserInfoFactory; +import com.inhabas.api.auth.domain.token.TokenUtil; @RequiredArgsConstructor @Slf4j public class Oauth2AuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler { - private final TokenUtil tokenUtil; - private final AuthProperties authProperties; - private final HttpCookieOAuth2AuthorizationRequestRepository httpCookieOAuth2AuthorizationRequestRepository; + private final TokenUtil tokenUtil; + private final AuthProperties authProperties; + private final HttpCookieOAuth2AuthorizationRequestRepository + httpCookieOAuth2AuthorizationRequestRepository; + + @Override + public void onAuthenticationSuccess( + HttpServletRequest request, HttpServletResponse response, Authentication authentication) + throws IOException { + String targetUrl = this.determineTargetUrl(request, response, authentication); + if (response.isCommitted()) { + log.debug("Response has already been committed. Unable to redirect to " + targetUrl); + return; + } - @Override - public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException { - String targetUrl = this.determineTargetUrl(request, response, authentication); + this.clearAuthenticationAttributes(request); + this.httpCookieOAuth2AuthorizationRequestRepository.clearCookies(request, response); + this.getRedirectStrategy().sendRedirect(request, response, targetUrl); + } - if (response.isCommitted()) { - log.debug("Response has already been committed. Unable to redirect to " + targetUrl); - return; - } + /** + * @param authentication 인증 완료된 결과 + * @return 인증 결과를 사용해서 access 토큰을 발급하고, 쿠키에 저장되어 있던 redirect_uri(프론트에서 적어준 것)와 합쳐서 반환. 명시되지 않으면 + * 설정파일({@link AuthProperties})에 명시된 default redirect url 값 적용 + */ + @Override + protected String determineTargetUrl( + HttpServletRequest request, HttpServletResponse response, Authentication authentication) { - this.clearAuthenticationAttributes(request); - this.httpCookieOAuth2AuthorizationRequestRepository.clearCookies(request, response); - this.getRedirectStrategy().sendRedirect(request, response, targetUrl); + String targetUrl = + CookieUtils.resolveCookie(request, REDIRECT_URL_PARAM_COOKIE_NAME) + .map(Cookie::getValue) + .orElse(authProperties.getOauth2().getDefaultRedirectUri()); + if (notAuthorized(targetUrl)) { + /* 여기서 AuthenticationException 이 발생하면 예외는 AbstractAuthenticationProcessingFilter.doFilter 에서 처리된다. + * - AbstractAuthenticationProcessingFilter.doFilter 안에서 try~ catch~ 에서 잡힘. + * - -> AbstractAuthenticationProcessingFilter.unsuccessfulAuthentication() + * - -> Oauth2AuthenticationFailureHandler().onAuthenticationFailure() + * */ + throw new UnauthorizedRedirectUrlException(); } - /** - * @param authentication 인증 완료된 결과 - * @return 인증 결과를 사용해서 access 토큰을 발급하고, 쿠키에 저장되어 있던 redirect_uri(프론트에서 적어준 것)와 합쳐서 반환. - * 명시되지 않으면 설정파일({@link AuthProperties})에 명시된 default redirect url 값 적용 - */ - @Override - protected String determineTargetUrl(HttpServletRequest request, HttpServletResponse response, Authentication authentication) { - - String targetUrl = CookieUtils.resolveCookie(request, REDIRECT_URL_PARAM_COOKIE_NAME) - .map(Cookie::getValue) - .orElse(authProperties.getOauth2().getDefaultRedirectUri()); - if (notAuthorized(targetUrl)) { - /* 여기서 AuthenticationException 이 발생하면 예외는 AbstractAuthenticationProcessingFilter.doFilter 에서 처리된다. - * - AbstractAuthenticationProcessingFilter.doFilter 안에서 try~ catch~ 에서 잡힘. - * - -> AbstractAuthenticationProcessingFilter.unsuccessfulAuthentication() - * - -> Oauth2AuthenticationFailureHandler().onAuthenticationFailure() - * */ - throw new UnauthorizedRedirectUrlException(); - } - - String imageUrl = OAuth2UserInfoFactory.getOAuth2UserInfo((OAuth2AuthenticationToken) authentication) - .getImageUrl(); - - return UriComponentsBuilder.fromUriString(targetUrl) - .queryParam("accessToken", tokenUtil.createAccessToken(authentication)) - .queryParam("refreshToken", tokenUtil.createRefreshToken(authentication)) - .queryParam("expiresIn", tokenUtil.getExpiration()) - .queryParam("imageUrl", imageUrl) - .build().toUriString(); - } + String imageUrl = + OAuth2UserInfoFactory.getOAuth2UserInfo((OAuth2AuthenticationToken) authentication) + .getImageUrl(); - private boolean notAuthorized(String redirectUrl) { - return !redirectUrl.isBlank() && - !authProperties.getOauth2().isAuthorizedRedirectUri(redirectUrl); - } + return UriComponentsBuilder.fromUriString(targetUrl) + .queryParam("accessToken", tokenUtil.createAccessToken(authentication)) + .queryParam("refreshToken", tokenUtil.createRefreshToken(authentication)) + .queryParam("expiresIn", tokenUtil.getExpiration()) + .queryParam("imageUrl", imageUrl) + .build() + .toUriString(); + } + + private boolean notAuthorized(String redirectUrl) { + return !redirectUrl.isBlank() + && !authProperties.getOauth2().isAuthorizedRedirectUri(redirectUrl); + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/majorInfo/domain/MajorInfo.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/majorInfo/domain/MajorInfo.java index 9741f235..fe539ed2 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/majorInfo/domain/MajorInfo.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/majorInfo/domain/MajorInfo.java @@ -1,18 +1,18 @@ package com.inhabas.api.auth.domain.oauth2.majorInfo.domain; -import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; -import com.inhabas.api.auth.domain.oauth2.majorInfo.domain.valueObject.College; -import com.inhabas.api.auth.domain.oauth2.majorInfo.domain.valueObject.Major; +import javax.persistence.*; + import lombok.AccessLevel; import lombok.NoArgsConstructor; -import javax.persistence.*; +import com.inhabas.api.auth.domain.oauth2.majorInfo.domain.valueObject.College; +import com.inhabas.api.auth.domain.oauth2.majorInfo.domain.valueObject.Major; +import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; /** - * 전공 정보는 학교 운영 방침에 따라 변함. - * 항상 전공 목록을 최신으로 유지하기는 하지만, - * 과거 변경되기 이전의 전공을 갖는 학생 정보가 남아있어야 한다.
+ * 전공 정보는 학교 운영 방침에 따라 변함. 항상 전공 목록을 최신으로 유지하기는 하지만, 과거 변경되기 이전의 전공을 갖는 학생 정보가 남아있어야 한다.
* 따라서 회원 정보에 전공을 저장한 때는 fk 로 저장하지 않고 단순 문자열로만 저장한다. + * * @see Member */ @Entity @@ -20,30 +20,28 @@ @NoArgsConstructor(access = AccessLevel.PROTECTED) public class MajorInfo { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Integer id; + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer id; - @Embedded - private College college; + @Embedded private College college; - @Embedded - private Major major; + @Embedded private Major major; - public MajorInfo(String college, String major) { - this.college = new College(college); - this.major = new Major(major); - } + public MajorInfo(String college, String major) { + this.college = new College(college); + this.major = new Major(major); + } - public Integer getId() { - return id; - } + public Integer getId() { + return id; + } - public String getCollege() { - return college.getValue(); - } + public String getCollege() { + return college.getValue(); + } - public String getMajor() { - return major.getValue(); - } + public String getMajor() { + return major.getValue(); + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/majorInfo/domain/valueObject/College.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/majorInfo/domain/valueObject/College.java index 2282e03d..33aff651 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/majorInfo/domain/valueObject/College.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/majorInfo/domain/valueObject/College.java @@ -1,40 +1,38 @@ package com.inhabas.api.auth.domain.oauth2.majorInfo.domain.valueObject; -import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; +import java.util.Objects; import javax.persistence.Column; import javax.persistence.Embeddable; import javax.persistence.Transient; -import java.util.Objects; + +import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; @Embeddable public class College { - @Column(name = "COLLEGE", length = 20, nullable = false) - private String value; + @Column(name = "COLLEGE", length = 20, nullable = false) + private String value; - @Transient - private final int MAX_LENGTH = 20; + @Transient private final int MAX_LENGTH = 20; - public College() {} + public College() {} - public College(String value) { - if (validate(value)) - this.value = value; - else - throw new InvalidInputException(); - } + public College(String value) { + if (validate(value)) this.value = value; + else throw new InvalidInputException(); + } - private boolean validate(Object value) { - if (Objects.isNull(value)) return false; - if (!(value instanceof String)) return false; + private boolean validate(Object value) { + if (Objects.isNull(value)) return false; + if (!(value instanceof String)) return false; - String o = (String) value; - if (o.isBlank()) return false; - return o.length() < MAX_LENGTH; - } + String o = (String) value; + if (o.isBlank()) return false; + return o.length() < MAX_LENGTH; + } - public String getValue() { - return value; - } + public String getValue() { + return value; + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/majorInfo/domain/valueObject/Major.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/majorInfo/domain/valueObject/Major.java index 2354369a..8bc1428f 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/majorInfo/domain/valueObject/Major.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/majorInfo/domain/valueObject/Major.java @@ -1,40 +1,38 @@ package com.inhabas.api.auth.domain.oauth2.majorInfo.domain.valueObject; -import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; +import java.util.Objects; import javax.persistence.Column; import javax.persistence.Embeddable; import javax.persistence.Transient; -import java.util.Objects; + +import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; @Embeddable public class Major { - @Column(name = "MAJOR", length = 50) - private String value; + @Column(name = "MAJOR", length = 50) + private String value; - @Transient - private static final int MAX_LENGTH = 50; + @Transient private static final int MAX_LENGTH = 50; - public Major() {} + public Major() {} - public Major(String value) { - if (validate(value)) - this.value = value; - else - throw new InvalidInputException(); - } + public Major(String value) { + if (validate(value)) this.value = value; + else throw new InvalidInputException(); + } - private boolean validate(Object value) { - if (Objects.isNull(value)) return false; - if (!(value instanceof String)) return false; + private boolean validate(Object value) { + if (Objects.isNull(value)) return false; + if (!(value instanceof String)) return false; - String o = (String) value; - if (o.isBlank()) return false; - return o.length() < MAX_LENGTH; - } + String o = (String) value; + if (o.isBlank()) return false; + return o.length() < MAX_LENGTH; + } - public String getValue() { - return value; - } + public String getValue() { + return value; + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/majorInfo/dto/MajorInfoDto.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/majorInfo/dto/MajorInfoDto.java index f68258e8..f12ed2f2 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/majorInfo/dto/MajorInfoDto.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/majorInfo/dto/MajorInfoDto.java @@ -7,15 +7,15 @@ @NoArgsConstructor public class MajorInfoDto { - private Integer id; + private Integer id; - private String college; + private String college; - private String major; + private String major; - public MajorInfoDto(Integer id, String college, String major) { - this.id = id; - this.college = college; - this.major = major; - } + public MajorInfoDto(Integer id, String college, String major) { + this.id = id; + this.college = college; + this.major = major; + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/majorInfo/dto/MajorInfoSaveDto.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/majorInfo/dto/MajorInfoSaveDto.java index f5a817ff..ae19f093 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/majorInfo/dto/MajorInfoSaveDto.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/majorInfo/dto/MajorInfoSaveDto.java @@ -1,23 +1,26 @@ package com.inhabas.api.auth.domain.oauth2.majorInfo.dto; +import javax.validation.constraints.NotBlank; + import lombok.Data; import lombok.NoArgsConstructor; -import org.hibernate.validator.constraints.Length; -import javax.validation.constraints.NotBlank; +import org.hibernate.validator.constraints.Length; @Data @NoArgsConstructor public class MajorInfoSaveDto { - @NotBlank @Length(max = 20) - private String college; + @NotBlank + @Length(max = 20) + private String college; - @NotBlank @Length(max = 50) - private String major; + @NotBlank + @Length(max = 50) + private String major; - public MajorInfoSaveDto(String college, String major) { - this.college = college; - this.major = major; - } + public MajorInfoSaveDto(String college, String major) { + this.college = college; + this.major = major; + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/majorInfo/repository/MajorInfoRepository.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/majorInfo/repository/MajorInfoRepository.java index def35e33..be4b2133 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/majorInfo/repository/MajorInfoRepository.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/majorInfo/repository/MajorInfoRepository.java @@ -1,7 +1,7 @@ package com.inhabas.api.auth.domain.oauth2.majorInfo.repository; -import com.inhabas.api.auth.domain.oauth2.majorInfo.domain.MajorInfo; import org.springframework.data.jpa.repository.JpaRepository; -public interface MajorInfoRepository extends JpaRepository { -} +import com.inhabas.api.auth.domain.oauth2.majorInfo.domain.MajorInfo; + +public interface MajorInfoRepository extends JpaRepository {} diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/majorInfo/usecase/MajorInfoService.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/majorInfo/usecase/MajorInfoService.java index 4ea21cef..80047c02 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/majorInfo/usecase/MajorInfoService.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/majorInfo/usecase/MajorInfoService.java @@ -1,15 +1,15 @@ package com.inhabas.api.auth.domain.oauth2.majorInfo.usecase; +import java.util.List; + import com.inhabas.api.auth.domain.oauth2.majorInfo.dto.MajorInfoDto; import com.inhabas.api.auth.domain.oauth2.majorInfo.dto.MajorInfoSaveDto; -import java.util.List; - public interface MajorInfoService { - List getAllMajorInfo(); + List getAllMajorInfo(); - void saveMajorInfo(MajorInfoSaveDto majorInfoSaveDto); + void saveMajorInfo(MajorInfoSaveDto majorInfoSaveDto); - void deleteMajorInfo(Integer majorId); + void deleteMajorInfo(Integer majorId); } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/majorInfo/usecase/MajorInfoServiceImpl.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/majorInfo/usecase/MajorInfoServiceImpl.java index 23ee6d7d..fc3b5bc4 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/majorInfo/usecase/MajorInfoServiceImpl.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/majorInfo/usecase/MajorInfoServiceImpl.java @@ -1,33 +1,37 @@ package com.inhabas.api.auth.domain.oauth2.majorInfo.usecase; -import com.inhabas.api.auth.domain.oauth2.majorInfo.domain.MajorInfo; -import com.inhabas.api.auth.domain.oauth2.majorInfo.repository.MajorInfoRepository; -import com.inhabas.api.auth.domain.oauth2.majorInfo.dto.MajorInfoDto; -import com.inhabas.api.auth.domain.oauth2.majorInfo.dto.MajorInfoSaveDto; import java.util.List; import java.util.stream.Collectors; + import lombok.RequiredArgsConstructor; + import org.springframework.stereotype.Service; +import com.inhabas.api.auth.domain.oauth2.majorInfo.domain.MajorInfo; +import com.inhabas.api.auth.domain.oauth2.majorInfo.dto.MajorInfoDto; +import com.inhabas.api.auth.domain.oauth2.majorInfo.dto.MajorInfoSaveDto; +import com.inhabas.api.auth.domain.oauth2.majorInfo.repository.MajorInfoRepository; + @Service @RequiredArgsConstructor public class MajorInfoServiceImpl implements MajorInfoService { - private final MajorInfoRepository majorInfoRepository; + private final MajorInfoRepository majorInfoRepository; - public List getAllMajorInfo() { - return majorInfoRepository.findAll().stream() - .map(majorInfo -> new MajorInfoDto(majorInfo.getId(), majorInfo.getCollege(), majorInfo.getMajor())) - .collect(Collectors.toList()); - } + public List getAllMajorInfo() { + return majorInfoRepository.findAll().stream() + .map( + majorInfo -> + new MajorInfoDto(majorInfo.getId(), majorInfo.getCollege(), majorInfo.getMajor())) + .collect(Collectors.toList()); + } - public void saveMajorInfo(MajorInfoSaveDto majorInfoSaveDto) { - majorInfoRepository.save( - new MajorInfo(majorInfoSaveDto.getCollege(), majorInfoSaveDto.getMajor()) - ); - } + public void saveMajorInfo(MajorInfoSaveDto majorInfoSaveDto) { + majorInfoRepository.save( + new MajorInfo(majorInfoSaveDto.getCollege(), majorInfoSaveDto.getMajor())); + } - public void deleteMajorInfo(Integer majorId) { - majorInfoRepository.deleteById(majorId); - } + public void deleteMajorInfo(Integer majorId) { + majorInfoRepository.deleteById(majorId); + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/entity/Member.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/entity/Member.java index 123e2fee..8956c9c1 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/entity/Member.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/entity/Member.java @@ -1,196 +1,210 @@ package com.inhabas.api.auth.domain.oauth2.member.domain.entity; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.inhabas.api.auth.domain.oauth2.OAuth2Provider; -import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.*; -import com.inhabas.api.auth.domain.oauth2.socialAccount.domain.valueObject.UID; -import com.inhabas.api.auth.domain.oauth2.userInfo.OAuth2UserInfo; +import static com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.Role.*; + +import java.time.LocalDateTime; + +import javax.persistence.*; + import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; -import org.springframework.data.jpa.domain.support.AuditingEntityListener; -import javax.persistence.*; -import java.time.LocalDateTime; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; -import static com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.Role.*; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.inhabas.api.auth.domain.oauth2.OAuth2Provider; +import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.*; +import com.inhabas.api.auth.domain.oauth2.socialAccount.domain.valueObject.UID; +import com.inhabas.api.auth.domain.oauth2.userInfo.OAuth2UserInfo; @Entity -@Table(name = "user", uniqueConstraints = {@UniqueConstraint(name = "UNIQUE_PROVIDER_UID", columnNames = {"provider", "uid"})}) +@Table( + name = "user", + uniqueConstraints = { + @UniqueConstraint( + name = "UNIQUE_PROVIDER_UID", + columnNames = {"provider", "uid"}) + }) @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) @EntityListeners(AuditingEntityListener.class) public class Member { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @Embedded - private StudentId studentId; - - @Embedded - private Name name; - - @Embedded - private Phone phone; - - @Embedded - private Email email; - - @Column(name = "PICTURE", length = 1000) - private String picture; - - @Embedded - private SchoolInformation schoolInformation; - - @Embedded - private IbasInformation ibasInformation; + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Embedded private StudentId studentId; - @Enumerated(value = EnumType.STRING) - private OAuth2Provider provider; + @Embedded private Name name; + + @Embedded private Phone phone; - @Embedded - private UID uid; + @Embedded private Email email; + + @Column(name = "PICTURE", length = 1000) + private String picture; + + @Embedded private SchoolInformation schoolInformation; - @Column(name = "LAST_LOGIN", nullable = false) - private LocalDateTime lastLogin; - - @Lob - @Column(name = "EXTRA_DATA", nullable = false) - private String extraData; - - @Column(name = "IS_DELETED") - private boolean isDeleted = false; - - @Builder - public Member(StudentId studentId, String name, String phone, String email, String picture, SchoolInformation schoolInformation, IbasInformation ibasInformation) { - this.studentId = studentId; - this.name = new Name(name); - this.phone = new Phone(phone); - this.email = new Email(email); - this.picture = picture; - this.schoolInformation = schoolInformation; - this.ibasInformation = ibasInformation; - } - - @Builder - public Member(OAuth2UserInfo userInfo) { - this.provider = userInfo.getProvider(); - this.uid = new UID(userInfo.getId()); - this.lastLogin = LocalDateTime.now(); - this.picture = userInfo.getImageUrl(); - this.email = new Email(userInfo.getEmail()); - this.ibasInformation = new IbasInformation(ANONYMOUS); - try { - this.extraData = new ObjectMapper().writeValueAsString(userInfo.getExtraData()); - } catch (JsonProcessingException ignored) {} - } - - @Builder - public Member(String name, String email, Role role) { - this.name = new Name(name); - this.email = new Email(email); - this.ibasInformation = new IbasInformation(role); - } - - public String getStudentId() { - return this.studentId != null ? this.studentId.getValue() : null; - } + @Embedded private IbasInformation ibasInformation; + + @Enumerated(value = EnumType.STRING) + private OAuth2Provider provider; - public String getName() { - return this.name != null ? this.name.getValue() : null; - } - - public String getPhone() { - return this.phone != null ? this.phone.getValue() : null; - } - public SchoolInformation getSchoolInformation() { - return this.schoolInformation != null ? this.schoolInformation : null; - } - - public String getEmail() { - return this.email.getValue(); - } - - public Role getRole() { - return this.ibasInformation.getRole(); - } - - - public boolean isDeleted() { - return this.isDeleted; - } - - public void setName(String name) { - this.name = new Name(name); - } - - public void setStudentId(String studentId) { - this.studentId = new StudentId(studentId); - } - public void setPhone(String phone) { - this.phone = new Phone(phone); - } - - public void setEmail(String email) { - this.email = new Email(email); - } - - public void setSchoolInformation(SchoolInformation schoolInformation) { - this.schoolInformation = schoolInformation; - } - - public void setRole(Role role) { - this.ibasInformation.setRole(role); - } - - public Member setLastLoginTime(LocalDateTime time) { - this.lastLogin = time; - return this; - } - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(Member.class.isAssignableFrom(o.getClass()))) return false; - Member member = (Member) o; - return getId().equals(member.getId()) - && getName().equals(member.getName()) - && getPhone().equals(member.getPhone()) - && getPicture().equals(member.getPicture()) - && getSchoolInformation().equals(member.getSchoolInformation()) - && getIbasInformation().equals(member.getIbasInformation()); - } - - public boolean isSameMember(Long id) { - return this.id.equals(id); - } - - public boolean isUnderGraduate() { - return this.schoolInformation.getMemberType() == MemberType.UNDERGRADUATE; - } - public boolean isGraduated() { - return this.schoolInformation.getMemberType() == MemberType.GRADUATED; - } - public boolean isProfessor() { - return this.schoolInformation.getMemberType() == MemberType.PROFESSOR; - } - public boolean isOther() { - return this.schoolInformation.getMemberType() == MemberType.OTHER; - } - public boolean isBachelor() { - return this.schoolInformation.getMemberType() == MemberType.BACHELOR; - } - - public boolean isCompleteToSignUp() { - return this.ibasInformation.isCompleteToSignUp(); - } - - public void finishSignUp() { - this.ibasInformation.finishSignUp(); - } + @Embedded private UID uid; + + @Column(name = "LAST_LOGIN", nullable = false) + private LocalDateTime lastLogin; + + @Lob + @Column(name = "EXTRA_DATA", nullable = false) + private String extraData; + + @Column(name = "IS_DELETED") + private boolean isDeleted = false; + + @Builder + public Member( + StudentId studentId, + String name, + String phone, + String email, + String picture, + SchoolInformation schoolInformation, + IbasInformation ibasInformation) { + this.studentId = studentId; + this.name = new Name(name); + this.phone = new Phone(phone); + this.email = new Email(email); + this.picture = picture; + this.schoolInformation = schoolInformation; + this.ibasInformation = ibasInformation; + } + + @Builder + public Member(OAuth2UserInfo userInfo) { + this.provider = userInfo.getProvider(); + this.uid = new UID(userInfo.getId()); + this.lastLogin = LocalDateTime.now(); + this.picture = userInfo.getImageUrl(); + this.email = new Email(userInfo.getEmail()); + this.ibasInformation = new IbasInformation(ANONYMOUS); + try { + this.extraData = new ObjectMapper().writeValueAsString(userInfo.getExtraData()); + } catch (JsonProcessingException ignored) { + } + } + + @Builder + public Member(String name, String email, Role role) { + this.name = new Name(name); + this.email = new Email(email); + this.ibasInformation = new IbasInformation(role); + } + + public String getStudentId() { + return this.studentId != null ? this.studentId.getValue() : null; + } + + public String getName() { + return this.name != null ? this.name.getValue() : null; + } + + public String getPhone() { + return this.phone != null ? this.phone.getValue() : null; + } + + public SchoolInformation getSchoolInformation() { + return this.schoolInformation != null ? this.schoolInformation : null; + } + + public String getEmail() { + return this.email.getValue(); + } + + public Role getRole() { + return this.ibasInformation.getRole(); + } + + public boolean isDeleted() { + return this.isDeleted; + } + + public void setName(String name) { + this.name = new Name(name); + } + + public void setStudentId(String studentId) { + this.studentId = new StudentId(studentId); + } + + public void setPhone(String phone) { + this.phone = new Phone(phone); + } + + public void setEmail(String email) { + this.email = new Email(email); + } + + public void setSchoolInformation(SchoolInformation schoolInformation) { + this.schoolInformation = schoolInformation; + } + + public void setRole(Role role) { + this.ibasInformation.setRole(role); + } + + public Member setLastLoginTime(LocalDateTime time) { + this.lastLogin = time; + return this; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(Member.class.isAssignableFrom(o.getClass()))) return false; + Member member = (Member) o; + return getId().equals(member.getId()) + && getName().equals(member.getName()) + && getPhone().equals(member.getPhone()) + && getPicture().equals(member.getPicture()) + && getSchoolInformation().equals(member.getSchoolInformation()) + && getIbasInformation().equals(member.getIbasInformation()); + } + + public boolean isSameMember(Long id) { + return this.id.equals(id); + } + + public boolean isUnderGraduate() { + return this.schoolInformation.getMemberType() == MemberType.UNDERGRADUATE; + } + + public boolean isGraduated() { + return this.schoolInformation.getMemberType() == MemberType.GRADUATED; + } + + public boolean isProfessor() { + return this.schoolInformation.getMemberType() == MemberType.PROFESSOR; + } + + public boolean isOther() { + return this.schoolInformation.getMemberType() == MemberType.OTHER; + } + + public boolean isBachelor() { + return this.schoolInformation.getMemberType() == MemberType.BACHELOR; + } + + public boolean isCompleteToSignUp() { + return this.ibasInformation.isCompleteToSignUp(); + } + + public void finishSignUp() { + this.ibasInformation.finishSignUp(); + } } - - diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/entity/UpdateNameRequest.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/entity/UpdateNameRequest.java index 4e8a637d..184ed3f3 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/entity/UpdateNameRequest.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/entity/UpdateNameRequest.java @@ -1,18 +1,21 @@ package com.inhabas.api.auth.domain.oauth2.member.domain.entity; -import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.Name; -import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.RequestStatus; +import static com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.RequestStatus.PENDING; + +import java.time.LocalDateTime; + +import javax.persistence.*; + import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; + import org.springframework.data.annotation.CreatedDate; import org.springframework.data.jpa.domain.support.AuditingEntityListener; -import javax.persistence.*; -import java.time.LocalDateTime; - -import static com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.RequestStatus.PENDING; +import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.Name; +import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.RequestStatus; @Entity @Table(name = "UPDATE_NAME_REQUEST") @@ -21,32 +24,38 @@ @EntityListeners(AuditingEntityListener.class) public class UpdateNameRequest { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @ManyToOne(fetch = FetchType.LAZY, optional = false) - @JoinColumn(name = "USER_ID") - private Member member; - - @Embedded - private Name name; - - @CreatedDate - @Column(name = "DATE_REQUESTED", nullable = false, updatable = false, columnDefinition = "DATETIME(0) DEFAULT CURRENT_TIMESTAMP") - private LocalDateTime dateRequested; - - @Column(name = "REQUEST_STATUS", nullable = false, columnDefinition = "VARCHAR(20) DEFAULT 'PENDING'") - private RequestStatus requestStatus; - - @Column(name = "REJECT_REASON", length = 255) - private String rejectReason; - - @Builder - public UpdateNameRequest(Member member, String name) { - this.member = member; - this.name = new Name(name); - this.dateRequested = LocalDateTime.now(); - this.requestStatus = PENDING; - } + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY, optional = false) + @JoinColumn(name = "USER_ID") + private Member member; + + @Embedded private Name name; + + @CreatedDate + @Column( + name = "DATE_REQUESTED", + nullable = false, + updatable = false, + columnDefinition = "DATETIME(0) DEFAULT CURRENT_TIMESTAMP") + private LocalDateTime dateRequested; + + @Column( + name = "REQUEST_STATUS", + nullable = false, + columnDefinition = "VARCHAR(20) DEFAULT 'PENDING'") + private RequestStatus requestStatus; + + @Column(name = "REJECT_REASON", length = 255) + private String rejectReason; + + @Builder + public UpdateNameRequest(Member member, String name) { + this.member = member; + this.name = new Name(name); + this.dateRequested = LocalDateTime.now(); + this.requestStatus = PENDING; + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/exception/MemberNotFoundException.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/exception/MemberNotFoundException.java index ccce26e5..d2dc08fa 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/exception/MemberNotFoundException.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/exception/MemberNotFoundException.java @@ -5,8 +5,7 @@ public class MemberNotFoundException extends BusinessException { - public MemberNotFoundException() { - super(ErrorCode.MEMBER_NOT_FOUND); - } - + public MemberNotFoundException() { + super(ErrorCode.MEMBER_NOT_FOUND); + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/Email.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/Email.java index 4b7ce431..732c7e05 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/Email.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/Email.java @@ -1,41 +1,42 @@ package com.inhabas.api.auth.domain.oauth2.member.domain.valueObject; -import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; +import java.util.Objects; +import java.util.regex.Pattern; import javax.persistence.Column; import javax.persistence.Embeddable; -import java.util.Objects; -import java.util.regex.Pattern; + +import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; @Embeddable public class Email { - @Column(name = "EMAIL", length = 150, nullable = false) - private String value; + @Column(name = "EMAIL", length = 150, nullable = false) + private String value; - private static final int MAX_LENGTH = 150; + private static final int MAX_LENGTH = 150; - private static final Pattern EMAIL_PATTERN = Pattern.compile("^[\\w!#$%&'*+/=?`{|}~^-]+(?:\\.[\\w!#$%&'*+/=?`{|}~^-]+)*@(?:[a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,6}$"); + private static final Pattern EMAIL_PATTERN = + Pattern.compile( + "^[\\w!#$%&'*+/=?`{|}~^-]+(?:\\.[\\w!#$%&'*+/=?`{|}~^-]+)*@(?:[a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,6}$"); - public Email() {} + public Email() {} - public Email(String value) { - if (validate(value)) - this.value = value; - else - throw new InvalidInputException(); - } + public Email(String value) { + if (validate(value)) this.value = value; + else throw new InvalidInputException(); + } - private boolean validate(Object value) { - if (Objects.isNull(value)) return false; - if (!(value instanceof String)) return false; + private boolean validate(Object value) { + if (Objects.isNull(value)) return false; + if (!(value instanceof String)) return false; - String o = (String) value; - if (o.isBlank()) return false; - return o.length() < MAX_LENGTH && EMAIL_PATTERN.matcher(o).matches(); - } + String o = (String) value; + if (o.isBlank()) return false; + return o.length() < MAX_LENGTH && EMAIL_PATTERN.matcher(o).matches(); + } - public String getValue() { - return value; - } + public String getValue() { + return value; + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/Generation.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/Generation.java index 5aa835b2..339f99c6 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/Generation.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/Generation.java @@ -1,36 +1,33 @@ package com.inhabas.api.auth.domain.oauth2.member.domain.valueObject; -import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; -import lombok.Getter; +import java.util.Objects; import javax.persistence.Column; import javax.persistence.Embeddable; -import java.util.Objects; -/** - * 회원의 재학중인 학기가 아니라, 동아리 운영 상의 기수를 의미함. - * 2020-2학기부터 1기, 2021-1학기가 2기,, - */ +import lombok.Getter; + +import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; + +/** 회원의 재학중인 학기가 아니라, 동아리 운영 상의 기수를 의미함. 2020-2학기부터 1기, 2021-1학기가 2기,, */ @Embeddable @Getter public class Generation { - @Column(name = "GENERATION") - private int value; + @Column(name = "GENERATION") + private int value; - public Generation() {} + public Generation() {} - public Generation(int value) { - if (validate(value)) - this.value = value; - else - throw new InvalidInputException(); - } + public Generation(int value) { + if (validate(value)) this.value = value; + else throw new InvalidInputException(); + } - private boolean validate(Object value) { - if (Objects.isNull(value)) return false; - if (!(value instanceof Integer)) return false; - int o = (Integer) value; - return o > 0; - } + private boolean validate(Object value) { + if (Objects.isNull(value)) return false; + if (!(value instanceof Integer)) return false; + int o = (Integer) value; + return o > 0; + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/Grade.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/Grade.java index 3e2169c1..a650a227 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/Grade.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/Grade.java @@ -1,33 +1,32 @@ package com.inhabas.api.auth.domain.oauth2.member.domain.valueObject; -import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; -import lombok.Getter; +import java.util.Objects; import javax.persistence.Column; import javax.persistence.Embeddable; -import java.util.Objects; + +import lombok.Getter; + +import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; @Getter @Embeddable public class Grade { - @Column(name = "GRADE") - private Integer value = 0; - - public Grade() {} + @Column(name = "GRADE") + private Integer value = 0; - public Grade(Integer value) { - if (validate(value)) - this.value = value; - else - throw new InvalidInputException(); - } + public Grade() {} - boolean validate(Object value) { - if (Objects.isNull(value)) return true; - if (!(value instanceof Integer)) return false; - int o = (Integer) value; - return 0 <= o && o <= 5; // 1학년부터 5학년(초과학기)까지 가능, 0학년은 학생이 아닐때 - } + public Grade(Integer value) { + if (validate(value)) this.value = value; + else throw new InvalidInputException(); + } + boolean validate(Object value) { + if (Objects.isNull(value)) return true; + if (!(value instanceof Integer)) return false; + int o = (Integer) value; + return 0 <= o && o <= 5; // 1학년부터 5학년(초과학기)까지 가능, 0학년은 학생이 아닐때 + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/IbasInformation.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/IbasInformation.java index 0c829348..3a76f7e8 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/IbasInformation.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/IbasInformation.java @@ -1,68 +1,67 @@ package com.inhabas.api.auth.domain.oauth2.member.domain.valueObject; +import java.time.LocalDateTime; +import java.util.Objects; + +import javax.persistence.*; + import lombok.AccessLevel; import lombok.Getter; import lombok.NoArgsConstructor; -import javax.persistence.*; -import java.time.LocalDateTime; -import java.util.Objects; - @Embeddable @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) public class IbasInformation { - @Enumerated(EnumType.STRING) - private Role role; - + @Enumerated(EnumType.STRING) + private Role role; - @Column(name = "DATE_JOINED") - private LocalDateTime dateJoined; + @Column(name = "DATE_JOINED") + private LocalDateTime dateJoined; - @Embedded - private Introduce introduce; + @Embedded private Introduce introduce; - @Column(name = "IS_HOF") - private Boolean isHOF = false; + @Column(name = "IS_HOF") + private Boolean isHOF = false; - public IbasInformation(Role role) { - this.role = role; - this.introduce = new Introduce(); - this.isHOF = false; - } + public IbasInformation(Role role) { + this.role = role; + this.introduce = new Introduce(); + this.isHOF = false; + } - public String getIntroduce() { - return introduce.getValue(); - } + public String getIntroduce() { + return introduce.getValue(); + } - public void setRole(Role role) { - this.role = role; - } + public void setRole(Role role) { + this.role = role; + } - public void setIsHOF(Boolean isHOF) { - this.isHOF = isHOF; - } + public void setIsHOF(Boolean isHOF) { + this.isHOF = isHOF; + } - public void setIntroduce(String introduce) { - this.introduce = new Introduce(introduce); - } + public void setIntroduce(String introduce) { + this.introduce = new Introduce(introduce); + } - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof IbasInformation)) return false; - IbasInformation that = (IbasInformation) o; - return getRole() == that.getRole() - && getDateJoined().equals(that.getDateJoined()) - && getIntroduce().equals(that.getIntroduce()) - && getIsHOF() == (that.getIsHOF()); - } + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof IbasInformation)) return false; + IbasInformation that = (IbasInformation) o; + return getRole() == that.getRole() + && getDateJoined().equals(that.getDateJoined()) + && getIntroduce().equals(that.getIntroduce()) + && getIsHOF() == (that.getIsHOF()); + } - public boolean isCompleteToSignUp() { - return Objects.nonNull(this.dateJoined); - } + public boolean isCompleteToSignUp() { + return Objects.nonNull(this.dateJoined); + } - public void finishSignUp() { - this.dateJoined = LocalDateTime.now(); - } -} \ No newline at end of file + public void finishSignUp() { + this.dateJoined = LocalDateTime.now(); + } +} diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/Introduce.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/Introduce.java index 7b51f205..9cc85840 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/Introduce.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/Introduce.java @@ -1,40 +1,37 @@ package com.inhabas.api.auth.domain.oauth2.member.domain.valueObject; -import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; +import java.util.Objects; import javax.persistence.Column; import javax.persistence.Embeddable; import javax.persistence.Transient; -import java.util.Objects; + +import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; @Embeddable public class Introduce { - @Column(name = "INTRO") - private String value = ""; - - @Transient - private static final int MAX_LENGTH = 300; - - public Introduce() {} - - public Introduce(String value) { - if (Objects.isNull(value)) - this.value = ""; - else if (validate(value)) - this.value = value; - else - throw new InvalidInputException(); - } - - private boolean validate(Object value) { - if (Objects.isNull(value)) return false; - if (!(value instanceof String)) return false; - String o = (String) value; - return o.length() < MAX_LENGTH; - } - - public String getValue() { - return value; - } + @Column(name = "INTRO") + private String value = ""; + + @Transient private static final int MAX_LENGTH = 300; + + public Introduce() {} + + public Introduce(String value) { + if (Objects.isNull(value)) this.value = ""; + else if (validate(value)) this.value = value; + else throw new InvalidInputException(); + } + + private boolean validate(Object value) { + if (Objects.isNull(value)) return false; + if (!(value instanceof String)) return false; + String o = (String) value; + return o.length() < MAX_LENGTH; + } + + public String getValue() { + return value; + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/MemberType.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/MemberType.java index a24a8cce..894ca54b 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/MemberType.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/MemberType.java @@ -1,17 +1,15 @@ package com.inhabas.api.auth.domain.oauth2.member.domain.valueObject; public enum MemberType { + UNDERGRADUATE("학부생"), + BACHELOR("학사"), + GRADUATED("대학원생"), + PROFESSOR("교수"), + OTHER("기타"); - UNDERGRADUATE("학부생"), - BACHELOR("학사"), - GRADUATED("대학원생"), - PROFESSOR("교수"), - OTHER("기타"); + private final String value; - private final String value; - - MemberType(String value) { - this.value = value; - } + MemberType(String value) { + this.value = value; + } } - diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/Name.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/Name.java index b4448df3..f5503b0c 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/Name.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/Name.java @@ -1,40 +1,38 @@ package com.inhabas.api.auth.domain.oauth2.member.domain.valueObject; -import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; +import java.util.Objects; import javax.persistence.Column; import javax.persistence.Embeddable; import javax.persistence.Transient; -import java.util.Objects; + +import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; @Embeddable public class Name { - @Column(name = "NAME", length = 50) - private String value; + @Column(name = "NAME", length = 50) + private String value; - @Transient - private static final int MAX_LENGTH = 50; + @Transient private static final int MAX_LENGTH = 50; - public Name() {} + public Name() {} - public Name(String value) { - if (validate(value)) - this.value = value; - else - throw new InvalidInputException(); - } + public Name(String value) { + if (validate(value)) this.value = value; + else throw new InvalidInputException(); + } - private boolean validate(Object value) { - if (Objects.isNull(value)) return false; - if (!(value instanceof String)) return false; + private boolean validate(Object value) { + if (Objects.isNull(value)) return false; + if (!(value instanceof String)) return false; - String o = (String) value; - if (o.isBlank()) return false; - return o.length() < MAX_LENGTH; - } + String o = (String) value; + if (o.isBlank()) return false; + return o.length() < MAX_LENGTH; + } - public String getValue() { - return value; - } + public String getValue() { + return value; + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/Phone.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/Phone.java index efae36cc..266853ff 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/Phone.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/Phone.java @@ -1,35 +1,35 @@ package com.inhabas.api.auth.domain.oauth2.member.domain.valueObject; -import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; -import lombok.Getter; +import java.util.Objects; +import java.util.regex.Pattern; import javax.persistence.Column; import javax.persistence.Embeddable; -import java.util.Objects; -import java.util.regex.Pattern; + +import lombok.Getter; + +import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; @Embeddable @Getter public class Phone { - @Column(name = "PHONE", length = 15) - private String value; + @Column(name = "PHONE", length = 15) + private String value; - private static final Pattern PHONE_PATTERN = Pattern.compile("^(010)-\\d{4}-\\d{4}$"); + private static final Pattern PHONE_PATTERN = Pattern.compile("^(010)-\\d{4}-\\d{4}$"); - public Phone() {} + public Phone() {} - public Phone(String value) { - if (this.validate(value)) - this.value = value; - else - throw new InvalidInputException(); - } + public Phone(String value) { + if (this.validate(value)) this.value = value; + else throw new InvalidInputException(); + } - private boolean validate(Object value) { - if (Objects.isNull(value)) return false; - if (!(value instanceof String)) return false; - String o = (String) value; - return PHONE_PATTERN.matcher(o).matches(); // only 010-****-**** - } + private boolean validate(Object value) { + if (Objects.isNull(value)) return false; + if (!(value instanceof String)) return false; + String o = (String) value; + return PHONE_PATTERN.matcher(o).matches(); // only 010-****-**** + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/RequestStatus.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/RequestStatus.java index c3afb263..af35409c 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/RequestStatus.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/RequestStatus.java @@ -1,18 +1,18 @@ package com.inhabas.api.auth.domain.oauth2.member.domain.valueObject; public enum RequestStatus { - PENDING("승인대기"), - APPROVED("승인완료"), - REJECTED("승인거절"), - COMPLETED("처리완료"); + PENDING("승인대기"), + APPROVED("승인완료"), + REJECTED("승인거절"), + COMPLETED("처리완료"); - private final String value; + private final String value; - RequestStatus(String value) { - this.value = value; - } + RequestStatus(String value) { + this.value = value; + } - public String getValue() { - return value; - } + public String getValue() { + return value; + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/Role.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/Role.java index 7cd6aa3e..d3292ce2 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/Role.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/Role.java @@ -1,19 +1,18 @@ package com.inhabas.api.auth.domain.oauth2.member.domain.valueObject; /** - * 모든 회원은 교수와 학생으로 나뉨. 교수와 학생 간 권한차이는 없음.
수직적 권한 계층은 Role 에 의해서 결정됨. + * 모든 회원은 교수와 학생으로 나뉨. 교수와 학생 간 권한차이는 없음.
+ * 수직적 권한 계층은 Role 에 의해서 결정됨. */ public enum Role { - ADMIN, // 사이트 관리자 - CHIEF, // 회장 - VICE_CHIEF, // 회장 - EXECUTIVES, // 회장단 - SECRETARY, // 총무 - BASIC, // 활동 일반회원 (교수 포함) - DEACTIVATED, // 비활동회원 (졸업생 포험) - NOT_APPROVED, // 가입 후 아직 승인되지 않은 회원 - SIGNING_UP, // Oauth 인증 후 회원가입을 완료하기 전 회원 - ANONYMOUS; // 익명. 유일하게 회원가입을 시도할 수 있는 권한. 즉 상위의 권한으로 회원가입 시도 불가 ; - + ADMIN, // 사이트 관리자 + CHIEF, // 회장 + VICE_CHIEF, // 회장 + EXECUTIVES, // 회장단 + SECRETARY, // 총무 + BASIC, // 활동 일반회원 (교수 포함) + DEACTIVATED, // 비활동회원 (졸업생 포험) + NOT_APPROVED, // 가입 후 아직 승인되지 않은 회원 + SIGNING_UP, // Oauth 인증 후 회원가입을 완료하기 전 회원 + ANONYMOUS; // 익명. 유일하게 회원가입을 시도할 수 있는 권한. 즉 상위의 권한으로 회원가입 시도 불가 ; } - diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/SchoolInformation.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/SchoolInformation.java index a9417dc0..91e56f16 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/SchoolInformation.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/SchoolInformation.java @@ -1,83 +1,79 @@ package com.inhabas.api.auth.domain.oauth2.member.domain.valueObject; -import com.inhabas.api.auth.domain.oauth2.majorInfo.domain.valueObject.Major; +import java.util.Objects; + +import javax.persistence.*; + import lombok.AccessLevel; import lombok.NoArgsConstructor; -import javax.persistence.*; -import java.util.Objects; +import com.inhabas.api.auth.domain.oauth2.majorInfo.domain.valueObject.Major; @Embeddable @NoArgsConstructor(access = AccessLevel.PROTECTED) public class SchoolInformation { - @Embedded - private Major major; - - @Embedded - private Grade grade; - - @Embedded - private Generation generation; - - @Column(name = "TYPE") - @Enumerated(EnumType.STRING) - private MemberType memberType; - - private static final int DEFAULT_GRADE = 0; // 학생이 아닌 경우 0학년 - - public SchoolInformation(String major, Integer grade, Integer generation, MemberType memberType) { - this.major = new Major(major); - this.grade = new Grade(grade); - this.generation = new Generation(generation); - this.memberType = memberType; - } - - public SchoolInformation(String major, Integer generation, MemberType memberType) { - this.major = new Major(major); - this.generation = new Generation(generation); - this.memberType = memberType; - this.grade = new Grade(DEFAULT_GRADE); - } - - - /* factory methods */ - public static SchoolInformation ofUnderGraduate(String major, Integer generation) { - return new SchoolInformation(major, generation, MemberType.UNDERGRADUATE); - } - - public String getMajor() { - return this.major.getValue(); - } - - public Integer getGrade() { - return this.grade.getValue(); - } - - public Integer getGeneration() { - return this.generation.getValue(); - } - - public MemberType getMemberType() { - return this.memberType; - } - - public void setMajor(String major) { - this.major = new Major(major); - } - - public void setGrade(Integer grade) { - this.grade = new Grade(grade); - } - - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof SchoolInformation)) return false; - SchoolInformation that = (SchoolInformation) o; - return Objects.equals(getMajor(), that.getMajor()) - && getGeneration().equals(that.getGeneration()); - } - + @Embedded private Major major; + + @Embedded private Grade grade; + + @Embedded private Generation generation; + + @Column(name = "TYPE") + @Enumerated(EnumType.STRING) + private MemberType memberType; + + private static final int DEFAULT_GRADE = 0; // 학생이 아닌 경우 0학년 + + public SchoolInformation(String major, Integer grade, Integer generation, MemberType memberType) { + this.major = new Major(major); + this.grade = new Grade(grade); + this.generation = new Generation(generation); + this.memberType = memberType; + } + + public SchoolInformation(String major, Integer generation, MemberType memberType) { + this.major = new Major(major); + this.generation = new Generation(generation); + this.memberType = memberType; + this.grade = new Grade(DEFAULT_GRADE); + } + + /* factory methods */ + public static SchoolInformation ofUnderGraduate(String major, Integer generation) { + return new SchoolInformation(major, generation, MemberType.UNDERGRADUATE); + } + + public String getMajor() { + return this.major.getValue(); + } + + public Integer getGrade() { + return this.grade.getValue(); + } + + public Integer getGeneration() { + return this.generation.getValue(); + } + + public MemberType getMemberType() { + return this.memberType; + } + + public void setMajor(String major) { + this.major = new Major(major); + } + + public void setGrade(Integer grade) { + this.grade = new Grade(grade); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof SchoolInformation)) return false; + SchoolInformation that = (SchoolInformation) o; + return Objects.equals(getMajor(), that.getMajor()) + && getGeneration().equals(that.getGeneration()); + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/StudentId.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/StudentId.java index c1349972..3cdd5eb9 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/StudentId.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/StudentId.java @@ -1,40 +1,38 @@ package com.inhabas.api.auth.domain.oauth2.member.domain.valueObject; -import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; -import lombok.AccessLevel; -import lombok.NoArgsConstructor; +import java.util.Objects; import javax.persistence.Column; import javax.persistence.Embeddable; import javax.persistence.Transient; -import java.util.Objects; + +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; @Embeddable @NoArgsConstructor(access = AccessLevel.PROTECTED) public class StudentId { + @Column(name = "STUDENT_ID", length = 30) + private String id; - @Column(name = "STUDENT_ID", length = 30) - private String id; - - @Transient - private static final int MAX_LENGTH = 30; + @Transient private static final int MAX_LENGTH = 30; - public StudentId(String id) { - if (validate(id)) - this.id = id; - else - throw new InvalidInputException(); - } + public StudentId(String id) { + if (validate(id)) this.id = id; + else throw new InvalidInputException(); + } - private boolean validate(Object value) { - if (Objects.isNull(value)) return false; - if (!(value instanceof String)) return false; - String o = (String) value; - return o.length() < MAX_LENGTH; - } + private boolean validate(Object value) { + if (Objects.isNull(value)) return false; + if (!(value instanceof String)) return false; + String o = (String) value; + return o.length() < MAX_LENGTH; + } - public String getValue() { - return id; - } + public String getValue() { + return id; + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/ApprovedMemberManagementDto.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/ApprovedMemberManagementDto.java index b0cf93e6..c8e5d35e 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/ApprovedMemberManagementDto.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/ApprovedMemberManagementDto.java @@ -1,46 +1,40 @@ package com.inhabas.api.auth.domain.oauth2.member.dto; -import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.Role; -import com.inhabas.api.auth.domain.oauth2.member.security.masking.Masked; -import com.inhabas.api.auth.domain.oauth2.member.security.masking.MaskingType; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; -import org.hibernate.validator.constraints.Length; - import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; import javax.validation.constraints.Pattern; import javax.validation.constraints.Positive; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.Role; +import com.inhabas.api.auth.domain.oauth2.member.security.masking.Masked; +import com.inhabas.api.auth.domain.oauth2.member.security.masking.MaskingType; +import org.hibernate.validator.constraints.Length; + @Data @NoArgsConstructor @AllArgsConstructor public class ApprovedMemberManagementDto { - @NotBlank - @Length(max = 50) - private String name; - - @NotNull - @Positive - private Long memberId; - - @NotNull - private String studentId; + @NotBlank + @Length(max = 50) + private String name; - @Pattern(regexp = "^(010)-\\d{4}-\\d{4}$") - @Masked(type = MaskingType.PHONE) - private String phoneNumber; + @NotNull @Positive private Long memberId; - @NotBlank - private Role role; + @NotNull private String studentId; - @NotNull - private Integer generation; + @Pattern(regexp = "^(010)-\\d{4}-\\d{4}$") + @Masked(type = MaskingType.PHONE) + private String phoneNumber; - @NotBlank - @Length(max = 50) - private String major; + @NotBlank private Role role; + @NotNull private Integer generation; + @NotBlank + @Length(max = 50) + private String major; } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/ContactDto.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/ContactDto.java index 251dadf9..9a502ee6 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/ContactDto.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/ContactDto.java @@ -1,26 +1,23 @@ package com.inhabas.api.auth.domain.oauth2.member.dto; +import javax.validation.constraints.NotBlank; + import lombok.Data; import lombok.NoArgsConstructor; -import javax.validation.constraints.NotBlank; - @Data @NoArgsConstructor public class ContactDto { - @NotBlank - private String name; + @NotBlank private String name; - @NotBlank - private String phoneNumber; + @NotBlank private String phoneNumber; - @NotBlank - private String email; + @NotBlank private String email; - public ContactDto(String name, String phoneNumber, String email) { - this.name = name; - this.phoneNumber = phoneNumber; - this.email = email; - } + public ContactDto(String name, String phoneNumber, String email) { + this.name = name; + this.phoneNumber = phoneNumber; + this.email = email; + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/MemberDuplicationQueryCondition.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/MemberDuplicationQueryCondition.java index 587e24db..336a3b4e 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/MemberDuplicationQueryCondition.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/MemberDuplicationQueryCondition.java @@ -1,53 +1,54 @@ package com.inhabas.api.auth.domain.oauth2.member.dto; +import java.util.Objects; + +import lombok.NoArgsConstructor; + import com.fasterxml.jackson.annotation.JsonInclude; import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; import com.inhabas.api.auth.domain.oauth2.OAuth2Provider; import com.inhabas.api.auth.domain.oauth2.socialAccount.domain.valueObject.UID; -import lombok.NoArgsConstructor; - -import java.util.Objects; @NoArgsConstructor @JsonInclude(JsonInclude.Include.NON_NULL) public class MemberDuplicationQueryCondition { - private OAuth2Provider provider; + private OAuth2Provider provider; - private UID uid; + private UID uid; - public MemberDuplicationQueryCondition(OAuth2Provider provider, String uid) { - this.provider = provider; - setUid(uid); - } - - public void verifyTwoParameters() { - if (Objects.isNull(provider) || Objects.isNull(uid)) { - throw new InvalidInputException(); - } - } - - public OAuth2Provider getProvider() { - return provider; - } - - /** - * do not delete this method. this getter's return type is used for get parameter of SignUpController - */ - - public String getUidNumber() { - return uid.getValue(); - } - - public void setProvider(OAuth2Provider provider) { - this.provider = provider; - } - - public void setUid(String uid) { - this.uid = new UID(uid); - } + public MemberDuplicationQueryCondition(OAuth2Provider provider, String uid) { + this.provider = provider; + setUid(uid); + } - public UID getUid() { - return uid; + public void verifyTwoParameters() { + if (Objects.isNull(provider) || Objects.isNull(uid)) { + throw new InvalidInputException(); } + } + + public OAuth2Provider getProvider() { + return provider; + } + + /** + * do not delete this method. this getter's return type is used for get parameter of + * SignUpController + */ + public String getUidNumber() { + return uid.getValue(); + } + + public void setProvider(OAuth2Provider provider) { + this.provider = provider; + } + + public void setUid(String uid) { + this.uid = new UID(uid); + } + + public UID getUid() { + return uid; + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/MyProfileDto.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/MyProfileDto.java index 566c3824..63a447df 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/MyProfileDto.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/MyProfileDto.java @@ -1,59 +1,61 @@ package com.inhabas.api.auth.domain.oauth2.member.dto; +import javax.validation.constraints.*; + +import lombok.*; + import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.MemberType; import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.Role; -import lombok.*; import org.hibernate.validator.constraints.Length; -import javax.validation.constraints.*; - @Getter @Setter public class MyProfileDto { - @NotBlank - @Length(max = 50) - private String name; + @NotBlank + @Length(max = 50) + private String name; - @NotNull - private String studentId; + @NotNull private String studentId; - @NotNull - private String major; + @NotNull private String major; - @NotNull - @Positive - private Integer grade; + @NotNull @Positive private Integer grade; - @Email - private String email; + @Email private String email; - @Pattern(regexp = "^(010)-\\d{4}-\\d{4}$") - private String phoneNumber; + @Pattern(regexp = "^(010)-\\d{4}-\\d{4}$") + private String phoneNumber; - @NotNull - private String picture; + @NotNull private String picture; - @NotNull - private Role role; + @NotNull private Role role; - @NotNull - private MemberType type; + @NotNull private MemberType type; - private String introduce; + private String introduce; - @Builder - public MyProfileDto(String name, String studentId, String major, Integer grade, String email, - String phoneNumber, String picture, Role role, MemberType type, String introduce) { - this.name = name; - this.studentId = studentId; - this.major = major; - this.grade = grade; - this.email = email; - this.phoneNumber = phoneNumber; - this.picture = picture; - this.role = role; - this.type = type; - this.introduce = introduce; - } + @Builder + public MyProfileDto( + String name, + String studentId, + String major, + Integer grade, + String email, + String phoneNumber, + String picture, + Role role, + MemberType type, + String introduce) { + this.name = name; + this.studentId = studentId; + this.major = major; + this.grade = grade; + this.email = email; + this.phoneNumber = phoneNumber; + this.picture = picture; + this.role = role; + this.type = type; + this.introduce = introduce; + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/NotApprovedMemberManagementDto.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/NotApprovedMemberManagementDto.java index 55e60d10..63360d16 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/NotApprovedMemberManagementDto.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/NotApprovedMemberManagementDto.java @@ -1,41 +1,35 @@ package com.inhabas.api.auth.domain.oauth2.member.dto; +import javax.validation.constraints.*; + +import lombok.*; + import com.inhabas.api.auth.domain.oauth2.member.security.masking.Masked; import com.inhabas.api.auth.domain.oauth2.member.security.masking.MaskingType; -import lombok.*; import org.hibernate.validator.constraints.Length; -import javax.validation.constraints.*; - @Getter @Setter @NoArgsConstructor(access = AccessLevel.PROTECTED) @AllArgsConstructor public class NotApprovedMemberManagementDto { - @NotBlank - @Length(max = 50) - private String name; - - @NotNull - @Positive - private Long memberId; + @NotBlank + @Length(max = 50) + private String name; - @NotNull - private String studentId; + @NotNull @Positive private Long memberId; - @Pattern(regexp = "^(010)-\\d{4}-\\d{4}$") - @Masked(type = MaskingType.PHONE) - private String phoneNumber; + @NotNull private String studentId; - @Email - private String email; + @Pattern(regexp = "^(010)-\\d{4}-\\d{4}$") + @Masked(type = MaskingType.PHONE) + private String phoneNumber; - @NotNull - @Positive - private Integer grade; + @Email private String email; - @NotBlank - @Length(max = 50) - private String major; + @NotNull @Positive private Integer grade; + @NotBlank + @Length(max = 50) + private String major; } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/ProfileDetailDto.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/ProfileDetailDto.java index 612ccf81..f77f96d6 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/ProfileDetailDto.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/ProfileDetailDto.java @@ -10,14 +10,14 @@ @NoArgsConstructor public class ProfileDetailDto { - private String major; - private Integer grade; - private String phoneNumber; + private String major; + private Integer grade; + private String phoneNumber; - @Builder - public ProfileDetailDto(String major, Integer grade, String phoneNumber) { - this.major = major; - this.grade = grade; - this.phoneNumber = phoneNumber; - } + @Builder + public ProfileDetailDto(String major, Integer grade, String phoneNumber) { + this.major = major; + this.grade = grade; + this.phoneNumber = phoneNumber; + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/ProfileIntroDto.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/ProfileIntroDto.java index ef8b54bc..34f22bd7 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/ProfileIntroDto.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/ProfileIntroDto.java @@ -10,12 +10,12 @@ @NoArgsConstructor public class ProfileIntroDto { - private String introduce; - private Boolean isHOF; + private String introduce; + private Boolean isHOF; - @Builder - public ProfileIntroDto(String introduce, Boolean isHOF) { - this.introduce = introduce; - this.isHOF = isHOF; - } + @Builder + public ProfileIntroDto(String introduce, Boolean isHOF) { + this.introduce = introduce; + this.isHOF = isHOF; + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/ProfileNameDto.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/ProfileNameDto.java index 7105d6f0..a0cd7332 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/ProfileNameDto.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/ProfileNameDto.java @@ -1,19 +1,18 @@ package com.inhabas.api.auth.domain.oauth2.member.dto; -import lombok.*; - import javax.validation.constraints.NotBlank; +import lombok.*; + @Getter @Setter @NoArgsConstructor public class ProfileNameDto { - @NotBlank - private String name; + @NotBlank private String name; - @Builder - public ProfileNameDto(String name) { - this.name = name; - } + @Builder + public ProfileNameDto(String name) { + this.name = name; + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/UpdateRequestDto.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/UpdateRequestDto.java index 1eec7675..38387be7 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/UpdateRequestDto.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/UpdateRequestDto.java @@ -1,9 +1,10 @@ package com.inhabas.api.auth.domain.oauth2.member.dto; -import io.swagger.v3.oas.annotations.media.Schema; +import java.util.List; + import lombok.*; -import java.util.List; +import io.swagger.v3.oas.annotations.media.Schema; @Getter @Setter @@ -11,9 +12,8 @@ @AllArgsConstructor public class UpdateRequestDto { - private List memberIdList; - - @Schema(example = "pass, fail") - private String state; + private List memberIdList; + @Schema(example = "pass, fail") + private String state; } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/UpdateRoleRequestDto.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/UpdateRoleRequestDto.java index a528a135..0f332b2d 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/UpdateRoleRequestDto.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/UpdateRoleRequestDto.java @@ -1,17 +1,17 @@ package com.inhabas.api.auth.domain.oauth2.member.dto; -import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.Role; +import java.util.List; + import lombok.*; -import java.util.List; +import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.Role; @Getter @Setter @NoArgsConstructor(access = AccessLevel.PROTECTED) @AllArgsConstructor public class UpdateRoleRequestDto { - private List memberIdList; - - private Role role; + private List memberIdList; + private Role role; } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/repository/MemberRepository.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/repository/MemberRepository.java index 26bfeecd..94d2ebd9 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/repository/MemberRepository.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/repository/MemberRepository.java @@ -1,23 +1,26 @@ package com.inhabas.api.auth.domain.oauth2.member.repository; +import java.util.List; +import java.util.Optional; + +import org.springframework.data.jpa.repository.JpaRepository; + import com.inhabas.api.auth.domain.oauth2.OAuth2Provider; import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.Role; import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.StudentId; import com.inhabas.api.auth.domain.oauth2.socialAccount.domain.valueObject.UID; -import org.springframework.data.jpa.repository.JpaRepository; - -import java.util.List; -import java.util.Optional; public interface MemberRepository extends JpaRepository, MemberRepositoryCustom { - List findAllById(Iterable memberIdList); - Member getByStudentId(StudentId studentId); - Member findByIbasInformation_Role(Role role); + List findAllById(Iterable memberIdList); + + Member getByStudentId(StudentId studentId); + + Member findByIbasInformation_Role(Role role); - // OAuth - boolean existsByProviderAndUid(OAuth2Provider provider, UID uid); - Optional findByProviderAndUid(OAuth2Provider provider, UID uid); + // OAuth + boolean existsByProviderAndUid(OAuth2Provider provider, UID uid); + Optional findByProviderAndUid(OAuth2Provider provider, UID uid); } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/repository/MemberRepositoryCustom.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/repository/MemberRepositoryCustom.java index 8c599539..fea244f7 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/repository/MemberRepositoryCustom.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/repository/MemberRepositoryCustom.java @@ -1,25 +1,24 @@ package com.inhabas.api.auth.domain.oauth2.member.repository; +import java.util.Collection; +import java.util.List; + import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.Role; import com.inhabas.api.auth.domain.oauth2.member.dto.MemberDuplicationQueryCondition; import com.inhabas.api.auth.domain.oauth2.member.security.MemberAuthorityProvider; -import java.util.Collection; -import java.util.List; - public interface MemberRepositoryCustom { - MemberAuthorityProvider.RoleDto fetchRoleByStudentId(Long id); - - boolean isDuplicated(MemberDuplicationQueryCondition condition); + MemberAuthorityProvider.RoleDto fetchRoleByStudentId(Long id); - List findAllByRoleAndStudentIdLike(Role role, String studentId); + boolean isDuplicated(MemberDuplicationQueryCondition condition); - List findAllByRoleAndNameLike(Role role, String name); + List findAllByRoleAndStudentIdLike(Role role, String studentId); - List findAllByRolesInAndStudentIdLike(Collection roles, String studentId); + List findAllByRoleAndNameLike(Role role, String name); - List findAllByRolesInAndNameLike(Collection roles, String name); + List findAllByRolesInAndStudentIdLike(Collection roles, String studentId); + List findAllByRolesInAndNameLike(Collection roles, String name); } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/repository/MemberRepositoryImpl.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/repository/MemberRepositoryImpl.java index 0bfe621b..5a188635 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/repository/MemberRepositoryImpl.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/repository/MemberRepositoryImpl.java @@ -1,5 +1,16 @@ package com.inhabas.api.auth.domain.oauth2.member.repository; +import static com.inhabas.api.auth.domain.oauth2.member.domain.entity.QMember.member; + +import java.util.Collection; +import java.util.List; +import java.util.Objects; + +import lombok.RequiredArgsConstructor; + +import org.springframework.stereotype.Repository; +import org.springframework.transaction.annotation.Transactional; + import com.inhabas.api.auth.domain.oauth2.OAuth2Provider; import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.Role; @@ -9,105 +20,90 @@ import com.querydsl.core.BooleanBuilder; import com.querydsl.core.types.dsl.BooleanExpression; import com.querydsl.jpa.impl.JPAQueryFactory; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Repository; -import org.springframework.transaction.annotation.Transactional; - -import java.util.Collection; -import java.util.List; -import java.util.Objects; - -import static com.inhabas.api.auth.domain.oauth2.member.domain.entity.QMember.member; - @Repository @Transactional @RequiredArgsConstructor public class MemberRepositoryImpl implements MemberRepositoryCustom { - private final JPAQueryFactory queryFactory; - - @Override - public MemberAuthorityProvider.RoleDto fetchRoleByStudentId(Long id) { - Role role = queryFactory - .select(member.ibasInformation.role).from(member) - .where(member.id.eq(id)) - .fetchOne(); - - return new MemberAuthorityProvider.RoleDto(role); - } - - @Override - public boolean isDuplicated(MemberDuplicationQueryCondition condition) { - - condition.verifyTwoParameters(); - - return !queryFactory.selectFrom(member) - .where(eqAny(condition)) - .limit(1).fetch().isEmpty(); - } - - @Override - public List findAllByRoleAndStudentIdLike(Role role, String studentId) { - - return queryFactory. - selectFrom(member) - .where(eqRole(role) - .and(member.studentId.id.like("%" + studentId + "%"))) - .fetch(); - - } - - @Override - public List findAllByRoleAndNameLike(Role role, String name) { - - return queryFactory. - selectFrom(member) - .where(eqRole(role) - .and(member.name.value.like("%" + name + "%"))) - .fetch(); - - } - - @Override - public List findAllByRolesInAndStudentIdLike(Collection roles, String studentId) { - - return queryFactory. - selectFrom(member) - .where(member.ibasInformation.role.in(roles) - .and(member.studentId.id.like("%" + studentId + "%"))) - .fetch(); - - } - - @Override - public List findAllByRolesInAndNameLike(Collection roles, String name) { - - return queryFactory. - selectFrom(member) - .where(member.ibasInformation.role.in(roles) - .and(member.name.value.like("%" + name + "%"))) - .fetch(); - - } - - - private BooleanExpression eqRole(Role role) { - return member.ibasInformation.role.eq(role); - } - - private BooleanBuilder eqAny(MemberDuplicationQueryCondition condition) { - BooleanBuilder booleanBuilder = new BooleanBuilder(); - - return booleanBuilder.or(eqProvider(condition.getProvider())) - .or(eqUid(condition.getUid())); - } - - private BooleanExpression eqUid(UID uid) { - return Objects.isNull(uid) ? null : member.uid.eq(uid); - } - - private BooleanExpression eqProvider(OAuth2Provider provider) { - return Objects.isNull(provider) ? null : member.provider.eq(provider); - } + private final JPAQueryFactory queryFactory; + + @Override + public MemberAuthorityProvider.RoleDto fetchRoleByStudentId(Long id) { + Role role = + queryFactory + .select(member.ibasInformation.role) + .from(member) + .where(member.id.eq(id)) + .fetchOne(); + + return new MemberAuthorityProvider.RoleDto(role); + } + + @Override + public boolean isDuplicated(MemberDuplicationQueryCondition condition) { + + condition.verifyTwoParameters(); + + return !queryFactory.selectFrom(member).where(eqAny(condition)).limit(1).fetch().isEmpty(); + } + + @Override + public List findAllByRoleAndStudentIdLike(Role role, String studentId) { + + return queryFactory + .selectFrom(member) + .where(eqRole(role).and(member.studentId.id.like("%" + studentId + "%"))) + .fetch(); + } + + @Override + public List findAllByRoleAndNameLike(Role role, String name) { + + return queryFactory + .selectFrom(member) + .where(eqRole(role).and(member.name.value.like("%" + name + "%"))) + .fetch(); + } + + @Override + public List findAllByRolesInAndStudentIdLike(Collection roles, String studentId) { + + return queryFactory + .selectFrom(member) + .where( + member + .ibasInformation + .role + .in(roles) + .and(member.studentId.id.like("%" + studentId + "%"))) + .fetch(); + } + + @Override + public List findAllByRolesInAndNameLike(Collection roles, String name) { + + return queryFactory + .selectFrom(member) + .where(member.ibasInformation.role.in(roles).and(member.name.value.like("%" + name + "%"))) + .fetch(); + } + + private BooleanExpression eqRole(Role role) { + return member.ibasInformation.role.eq(role); + } + + private BooleanBuilder eqAny(MemberDuplicationQueryCondition condition) { + BooleanBuilder booleanBuilder = new BooleanBuilder(); + + return booleanBuilder.or(eqProvider(condition.getProvider())).or(eqUid(condition.getUid())); + } + + private BooleanExpression eqUid(UID uid) { + return Objects.isNull(uid) ? null : member.uid.eq(uid); + } + + private BooleanExpression eqProvider(OAuth2Provider provider) { + return Objects.isNull(provider) ? null : member.provider.eq(provider); + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/repository/UpdateNameRequestRepository.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/repository/UpdateNameRequestRepository.java index c347fc1d..4badd664 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/repository/UpdateNameRequestRepository.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/repository/UpdateNameRequestRepository.java @@ -1,7 +1,7 @@ package com.inhabas.api.auth.domain.oauth2.member.repository; -import com.inhabas.api.auth.domain.oauth2.member.domain.entity.UpdateNameRequest; import org.springframework.data.jpa.repository.JpaRepository; -public interface UpdateNameRequestRepository extends JpaRepository { -} +import com.inhabas.api.auth.domain.oauth2.member.domain.entity.UpdateNameRequest; + +public interface UpdateNameRequestRepository extends JpaRepository {} diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/security/DefaultRoleHierarchy.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/security/DefaultRoleHierarchy.java index 313d064a..c750ad09 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/security/DefaultRoleHierarchy.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/security/DefaultRoleHierarchy.java @@ -1,69 +1,68 @@ package com.inhabas.api.auth.domain.oauth2.member.security; +import java.util.*; + import lombok.AccessLevel; import lombok.NoArgsConstructor; + import org.springframework.security.access.hierarchicalroles.RoleHierarchy; import org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl; import org.springframework.security.access.hierarchicalroles.RoleHierarchyUtils; import org.springframework.stereotype.Component; -import java.util.*; - @Component @NoArgsConstructor(access = AccessLevel.PROTECTED) public class DefaultRoleHierarchy implements Hierarchical { - /* 기존 권한에 ROLE PREFIX 추가해야함. */ - private static final String ADMIN = "ROLE_ADMIN"; - private static final String CHIEF = "ROLE_CHIEF"; - private static final String VICE_CHIEF = "ROLE_VICE_CHIEF"; - private static final String EXECUTIVES = "ROLE_EXECUTIVES"; - private static final String SECRETARY = "ROLE_SECRETARY"; - private static final String BASIC = "ROLE_BASIC"; - private static final String DEACTIVATED = "ROLE_DEACTIVATED"; - private static final String NOT_APPROVED = "ROLE_NOT_APPROVED"; - private static final String SIGNING_UP = "ROLE_SIGNING_UP"; - private static final String ANONYMOUS = "ROLE_ANONYMOUS"; - + /* 기존 권한에 ROLE PREFIX 추가해야함. */ + private static final String ADMIN = "ROLE_ADMIN"; + private static final String CHIEF = "ROLE_CHIEF"; + private static final String VICE_CHIEF = "ROLE_VICE_CHIEF"; + private static final String EXECUTIVES = "ROLE_EXECUTIVES"; + private static final String SECRETARY = "ROLE_SECRETARY"; + private static final String BASIC = "ROLE_BASIC"; + private static final String DEACTIVATED = "ROLE_DEACTIVATED"; + private static final String NOT_APPROVED = "ROLE_NOT_APPROVED"; + private static final String SIGNING_UP = "ROLE_SIGNING_UP"; + private static final String ANONYMOUS = "ROLE_ANONYMOUS"; - @Override - public RoleHierarchy getHierarchy() { + @Override + public RoleHierarchy getHierarchy() { - RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl(); + RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl(); - Map> roleHierarchyMap = new HashMap<>() {{ - put( - ADMIN, - Arrays.asList(CHIEF, VICE_CHIEF, EXECUTIVES, SECRETARY, BASIC, DEACTIVATED, NOT_APPROVED, ANONYMOUS)); + Map> roleHierarchyMap = + new HashMap<>() { + { put( + ADMIN, + Arrays.asList( CHIEF, - Arrays.asList(EXECUTIVES, SECRETARY, BASIC, DEACTIVATED, NOT_APPROVED, ANONYMOUS)); - put( VICE_CHIEF, - Arrays.asList(EXECUTIVES, SECRETARY, BASIC, DEACTIVATED, NOT_APPROVED, ANONYMOUS)); - put( EXECUTIVES, - Arrays.asList(BASIC, DEACTIVATED, NOT_APPROVED, ANONYMOUS)); - put( SECRETARY, - Arrays.asList(BASIC, DEACTIVATED, NOT_APPROVED, ANONYMOUS)); - put( BASIC, - Arrays.asList(DEACTIVATED, NOT_APPROVED, ANONYMOUS)); - put( DEACTIVATED, - Arrays.asList(NOT_APPROVED, ANONYMOUS)); - put( NOT_APPROVED, - Arrays.asList(ANONYMOUS)); + ANONYMOUS)); + put( + CHIEF, + Arrays.asList(EXECUTIVES, SECRETARY, BASIC, DEACTIVATED, NOT_APPROVED, ANONYMOUS)); put( - SIGNING_UP, - Arrays.asList(ANONYMOUS)); - }}; + VICE_CHIEF, + Arrays.asList(EXECUTIVES, SECRETARY, BASIC, DEACTIVATED, NOT_APPROVED, ANONYMOUS)); + put(EXECUTIVES, Arrays.asList(BASIC, DEACTIVATED, NOT_APPROVED, ANONYMOUS)); + put(SECRETARY, Arrays.asList(BASIC, DEACTIVATED, NOT_APPROVED, ANONYMOUS)); + put(BASIC, Arrays.asList(DEACTIVATED, NOT_APPROVED, ANONYMOUS)); + put(DEACTIVATED, Arrays.asList(NOT_APPROVED, ANONYMOUS)); + put(NOT_APPROVED, Arrays.asList(ANONYMOUS)); + put(SIGNING_UP, Arrays.asList(ANONYMOUS)); + } + }; - String roles = RoleHierarchyUtils.roleHierarchyFromMap(roleHierarchyMap); - roleHierarchy.setHierarchy(roles); + String roles = RoleHierarchyUtils.roleHierarchyFromMap(roleHierarchyMap); + roleHierarchy.setHierarchy(roles); - return roleHierarchy; - } + return roleHierarchy; + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/security/Hierarchical.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/security/Hierarchical.java index 393c6b48..7bee4422 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/security/Hierarchical.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/security/Hierarchical.java @@ -3,11 +3,10 @@ import org.springframework.security.access.hierarchicalroles.RoleHierarchy; /** - * 로그인된 사용자의 권한을 수직적으로 정의한다. (예로, 회장이면 일반 사용자의 모든 권한을 포함하도록 한다.) - * 리턴 객체를 Bean 으로 등록해서 SecurityExpressionHandler 에 주입해주어야 적용된다. - * 최종적으로는 주입된 SecurityExpressionHandler 빈을 등록해야한다. + * 로그인된 사용자의 권한을 수직적으로 정의한다. (예로, 회장이면 일반 사용자의 모든 권한을 포함하도록 한다.) 리턴 객체를 Bean 으로 등록해서 + * SecurityExpressionHandler 에 주입해주어야 적용된다. 최종적으로는 주입된 SecurityExpressionHandler 빈을 등록해야한다. */ public interface Hierarchical { - RoleHierarchy getHierarchy(); + RoleHierarchy getHierarchy(); } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/security/MemberAuthorityProvider.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/security/MemberAuthorityProvider.java index 6f3f7b47..15d297f3 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/security/MemberAuthorityProvider.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/security/MemberAuthorityProvider.java @@ -1,5 +1,17 @@ package com.inhabas.api.auth.domain.oauth2.member.security; +import static com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.Role.SIGNING_UP; + +import java.util.Collection; +import java.util.Collections; +import java.util.Objects; + +import lombok.RequiredArgsConstructor; + +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + import com.inhabas.api.auth.domain.error.authException.InvalidOAuth2InfoException; import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.Role; @@ -9,68 +21,59 @@ import com.inhabas.api.auth.domain.oauth2.userInfo.OAuth2UserInfo; import com.inhabas.api.auth.domain.oauth2.userInfo.OAuth2UserInfoAuthentication; import com.inhabas.api.auth.domain.token.securityFilter.UserPrincipalService; -import lombok.RequiredArgsConstructor; -import org.springframework.security.core.authority.SimpleGrantedAuthority; -import org.springframework.stereotype.Component; -import org.springframework.transaction.annotation.Transactional; - -import java.util.Collection; -import java.util.Collections; -import java.util.Objects; - -import static com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.Role.SIGNING_UP; @Component @RequiredArgsConstructor public class MemberAuthorityProvider implements UserAuthorityProvider { - private final UserPrincipalService userPrincipalService; - private final MemberRepository memberRepository; - private static final String ROLE_PREFIX = "ROLE_"; - - @Override - @Transactional - public Collection determineAuthorities(OAuth2UserInfo oAuth2UserInfo) { + private final UserPrincipalService userPrincipalService; + private final MemberRepository memberRepository; + private static final String ROLE_PREFIX = "ROLE_"; - OAuth2UserInfoAuthentication authentication = - new OAuth2UserInfoAuthentication(oAuth2UserInfo.getId(), oAuth2UserInfo.getProvider().toString(), oAuth2UserInfo.getEmail()); - Long memberId = (Long) userPrincipalService.loadUserPrincipal(authentication); + @Override + @Transactional + public Collection determineAuthorities(OAuth2UserInfo oAuth2UserInfo) { - if (Objects.isNull(memberId)) { // 기존회원이 아니면, member 테이블에 임시데이터 저장 - Member member = memberRepository.findByProviderAndUid( - oAuth2UserInfo.getProvider(), new UID(oAuth2UserInfo.getId())) - .orElseThrow(InvalidOAuth2InfoException::new); + OAuth2UserInfoAuthentication authentication = + new OAuth2UserInfoAuthentication( + oAuth2UserInfo.getId(), + oAuth2UserInfo.getProvider().toString(), + oAuth2UserInfo.getEmail()); + Long memberId = (Long) userPrincipalService.loadUserPrincipal(authentication); - member.setRole(SIGNING_UP); + if (Objects.isNull(memberId)) { // 기존회원이 아니면, member 테이블에 임시데이터 저장 + Member member = + memberRepository + .findByProviderAndUid(oAuth2UserInfo.getProvider(), new UID(oAuth2UserInfo.getId())) + .orElseThrow(InvalidOAuth2InfoException::new); - return Collections.singleton(new SimpleGrantedAuthority(ROLE_PREFIX + SIGNING_UP)); - } - else { - // 기존회원이면, - RoleDto roleDto = memberRepository.fetchRoleByStudentId(memberId); + member.setRole(SIGNING_UP); - if (roleDto.isEmpty()) - throw new InvalidOAuth2InfoException(); // 가입된 소셜 계정으로 회원 프로필을 찾을 수 없는 경우. + return Collections.singleton(new SimpleGrantedAuthority(ROLE_PREFIX + SIGNING_UP)); + } else { + // 기존회원이면, + RoleDto roleDto = memberRepository.fetchRoleByStudentId(memberId); - return Collections.singleton(new SimpleGrantedAuthority(ROLE_PREFIX + roleDto.getRole())); + if (roleDto.isEmpty()) + throw new InvalidOAuth2InfoException(); // 가입된 소셜 계정으로 회원 프로필을 찾을 수 없는 경우. - } + return Collections.singleton(new SimpleGrantedAuthority(ROLE_PREFIX + roleDto.getRole())); } + } - public static class RoleDto { - private final Role role; + public static class RoleDto { + private final Role role; - public RoleDto(Role role) { - this.role = role; - } - - public Role getRole() { - return role; - } + public RoleDto(Role role) { + this.role = role; + } - boolean isEmpty() { - return role == null; - } + public Role getRole() { + return role; } + boolean isEmpty() { + return role == null; + } + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/security/MemberPrincipalService.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/security/MemberPrincipalService.java index 9b6ee914..20d00a3c 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/security/MemberPrincipalService.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/security/MemberPrincipalService.java @@ -1,78 +1,82 @@ package com.inhabas.api.auth.domain.oauth2.member.security; +import java.util.Optional; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import org.springframework.security.core.Authentication; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + import com.inhabas.api.auth.domain.oauth2.OAuth2Provider; import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.Email; import com.inhabas.api.auth.domain.oauth2.socialAccount.domain.entity.MemberSocialAccount; -import com.inhabas.api.auth.domain.oauth2.socialAccount.repository.MemberSocialAccountRepository; import com.inhabas.api.auth.domain.oauth2.socialAccount.domain.valueObject.UID; +import com.inhabas.api.auth.domain.oauth2.socialAccount.repository.MemberSocialAccountRepository; import com.inhabas.api.auth.domain.oauth2.userInfo.OAuth2UserInfoAuthentication; import com.inhabas.api.auth.domain.token.securityFilter.SocialNotFoundException; import com.inhabas.api.auth.domain.token.securityFilter.UserPrincipalService; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.security.core.Authentication; -import org.springframework.stereotype.Component; -import org.springframework.transaction.annotation.Transactional; - -import java.util.Optional; @Component @RequiredArgsConstructor @Slf4j public class MemberPrincipalService implements UserPrincipalService { - private final MemberSocialAccountRepository memberSocialAccountRepository; - - /** - * (1) uid 와 provider 로 기존회원을 검색한다. - * 다만 database 레거시 호환성을 위해, 기존회원이지만 uid 가 존재하지 않는 경우를 추가로 고려해야한다. - * 이 경우에는 (1)으로 검색되지 않는다.
- * 따라서 추가로 (2) provider 와 email 로 검색한 후, 회원이 존재하면 uid 를 채워준다. - * @return StudentId - * @exception SocialNotFoundException 최종적으로 가입되지 않은 회원이라고 판단되면 오류를 발생시킨다. - * @see Inhabas.com/issues/102 - * */ - @Transactional - @Override - public Object loadUserPrincipal(Authentication authentication) { - - OAuth2UserInfoAuthentication oauth2UserInfoToken = (OAuth2UserInfoAuthentication) authentication; - OAuth2Provider provider = OAuth2Provider.convert(oauth2UserInfoToken.getProvider()); - UID uid = new UID(oauth2UserInfoToken.getUid()); - Email email = new Email(oauth2UserInfoToken.getEmail()); - - try { - Long memberId = this.getMemberId(provider, uid, email).orElseThrow(SocialNotFoundException::new); - return memberId; - } catch (SocialNotFoundException e) { - log.info(e.getMessage()); - return null; - } + private final MemberSocialAccountRepository memberSocialAccountRepository; + + /** + * (1) uid 와 provider 로 기존회원을 검색한다. 다만 database 레거시 호환성을 위해, 기존회원이지만 uid 가 존재하지 않는 경우를 추가로 고려해야한다. + * 이 경우에는 (1)으로 검색되지 않는다.
+ * 따라서 추가로 (2) provider 와 email 로 검색한 후, 회원이 존재하면 uid 를 채워준다. + * + * @return StudentId + * @exception SocialNotFoundException 최종적으로 가입되지 않은 회원이라고 판단되면 오류를 발생시킨다. + * @see Inhabas.com/issues/102 + */ + @Transactional + @Override + public Object loadUserPrincipal(Authentication authentication) { + + OAuth2UserInfoAuthentication oauth2UserInfoToken = + (OAuth2UserInfoAuthentication) authentication; + OAuth2Provider provider = OAuth2Provider.convert(oauth2UserInfoToken.getProvider()); + UID uid = new UID(oauth2UserInfoToken.getUid()); + Email email = new Email(oauth2UserInfoToken.getEmail()); + + try { + Long memberId = + this.getMemberId(provider, uid, email).orElseThrow(SocialNotFoundException::new); + return memberId; + } catch (SocialNotFoundException e) { + log.info(e.getMessage()); + return null; } + } + private Optional getMemberId(OAuth2Provider provider, UID uid, Email email) { - private Optional getMemberId(OAuth2Provider provider, UID uid, Email email) { - - return memberSocialAccountRepository.findMemberIdByUidAndProvider(uid, provider) - .or(() -> this.findByEmailAndProviderForLegacy(email, provider, uid)); - } - + return memberSocialAccountRepository + .findMemberIdByUidAndProvider(uid, provider) + .or(() -> this.findByEmailAndProviderForLegacy(email, provider, uid)); + } - private Optional findByEmailAndProviderForLegacy(Email email, OAuth2Provider provider, UID uid) { + private Optional findByEmailAndProviderForLegacy( + Email email, OAuth2Provider provider, UID uid) { - Optional memberSocialAccount = - memberSocialAccountRepository.findMemberSocialAccountByEmailAndProvider(email, provider); + Optional memberSocialAccount = + memberSocialAccountRepository.findMemberSocialAccountByEmailAndProvider(email, provider); - if (memberSocialAccount.isPresent()) { + if (memberSocialAccount.isPresent()) { - MemberSocialAccount socialAccount = memberSocialAccount.get(); - socialAccount.SetUID(uid); - memberSocialAccountRepository.save(socialAccount); - return Optional.of(socialAccount.getMember().getId()); + MemberSocialAccount socialAccount = memberSocialAccount.get(); + socialAccount.SetUID(uid); + memberSocialAccountRepository.save(socialAccount); + return Optional.of(socialAccount.getMember().getId()); - } else { + } else { - return Optional.empty(); - } + return Optional.empty(); } + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/security/masking/CustomObjectMapper.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/security/masking/CustomObjectMapper.java index 6d6a6c55..43be8a65 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/security/masking/CustomObjectMapper.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/security/masking/CustomObjectMapper.java @@ -1,24 +1,25 @@ package com.inhabas.api.auth.domain.oauth2.member.security.masking; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; @Configuration public class CustomObjectMapper { - @Bean - public ObjectMapper objectMapper() { - ObjectMapper objectMapper = new ObjectMapper(); + @Bean + public ObjectMapper objectMapper() { + ObjectMapper objectMapper = new ObjectMapper(); - SimpleModule module = new SimpleModule(); - module.addSerializer(String.class, new StringPropertyMasker()); - objectMapper.registerModule(module); + SimpleModule module = new SimpleModule(); + module.addSerializer(String.class, new StringPropertyMasker()); + objectMapper.registerModule(module); - objectMapper.registerModule(new JavaTimeModule()); + objectMapper.registerModule(new JavaTimeModule()); - return objectMapper; - } -} \ No newline at end of file + return objectMapper; + } +} diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/security/masking/Masked.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/security/masking/Masked.java index 01d1391d..eae05e43 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/security/masking/Masked.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/security/masking/Masked.java @@ -1,17 +1,16 @@ package com.inhabas.api.auth.domain.oauth2.member.security.masking; -import com.fasterxml.jackson.databind.annotation.JsonSerialize; - import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; + @Target({ElementType.ANNOTATION_TYPE, ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) @JsonSerialize(using = StringPropertyMasker.class) public @interface Masked { - MaskingType type(); - -} \ No newline at end of file + MaskingType type(); +} diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/security/masking/Masking.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/security/masking/Masking.java index c7a81e8e..1fdd1faa 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/security/masking/Masking.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/security/masking/Masking.java @@ -1,55 +1,60 @@ package com.inhabas.api.auth.domain.oauth2.member.security.masking; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.context.SecurityContextHolder; - import java.util.Collection; import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.context.SecurityContextHolder; + public class Masking { - public static String mask(MaskingType type, String value) { - if (type == null) return value; - - String str; - switch (type) { - case PHONE: - str = phoneMaskOf(value); - break; - case EMAIL: - str = emailMaskOf(value); - break; - default: - str = value; - break; - } - return str; + public static String mask(MaskingType type, String value) { + if (type == null) return value; + + String str; + switch (type) { + case PHONE: + str = phoneMaskOf(value); + break; + case EMAIL: + str = emailMaskOf(value); + break; + default: + str = value; + break; } - - private static String phoneMaskOf(String value){ - - // 총무 권한이 있는 유저만 접근 가능 - Collection authorities = SecurityContextHolder.getContext().getAuthentication().getAuthorities(); - boolean hasAnyRole = authorities.stream() - .map(GrantedAuthority::getAuthority) - .anyMatch(auth -> auth.equals("ROLE_SECRETARY") || auth.equals("ROLE_CHIEF") || auth.equals("ROLE_VICE_CHIEF")); - - if (!hasAnyRole) { - // 010-****-**** - String regex = "(\\d{3})-?(\\d{4})-?(\\d{4})$"; - Matcher matcher = Pattern.compile(regex).matcher(value); - if (matcher.find()) { - return matcher.group(1) + "-****-****"; - } - } - - return value; + return str; + } + + private static String phoneMaskOf(String value) { + + // 총무 권한이 있는 유저만 접근 가능 + Collection authorities = + SecurityContextHolder.getContext().getAuthentication().getAuthorities(); + boolean hasAnyRole = + authorities.stream() + .map(GrantedAuthority::getAuthority) + .anyMatch( + auth -> + auth.equals("ROLE_SECRETARY") + || auth.equals("ROLE_CHIEF") + || auth.equals("ROLE_VICE_CHIEF")); + + if (!hasAnyRole) { + // 010-****-**** + String regex = "(\\d{3})-?(\\d{4})-?(\\d{4})$"; + Matcher matcher = Pattern.compile(regex).matcher(value); + if (matcher.find()) { + return matcher.group(1) + "-****-****"; + } } + return value; + } - private static String emailMaskOf(String value){ - // abc****@gmail.com - return value.replaceAll("(?<=.{3}).(?=[^@]*?@)", "*"); - } -} \ No newline at end of file + private static String emailMaskOf(String value) { + // abc****@gmail.com + return value.replaceAll("(?<=.{3}).(?=[^@]*?@)", "*"); + } +} diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/security/masking/MaskingType.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/security/masking/MaskingType.java index 1d6dc547..3125ca32 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/security/masking/MaskingType.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/security/masking/MaskingType.java @@ -1,6 +1,6 @@ package com.inhabas.api.auth.domain.oauth2.member.security.masking; public enum MaskingType { - PHONE, - EMAIL, -} \ No newline at end of file + PHONE, + EMAIL, +} diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/security/masking/StringPropertyMasker.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/security/masking/StringPropertyMasker.java index 009914d9..63568d62 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/security/masking/StringPropertyMasker.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/security/masking/StringPropertyMasker.java @@ -1,5 +1,7 @@ package com.inhabas.api.auth.domain.oauth2.member.security.masking; +import java.io.IOException; + import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.BeanProperty; import com.fasterxml.jackson.databind.JsonSerializer; @@ -7,34 +9,34 @@ import com.fasterxml.jackson.databind.ser.ContextualSerializer; import com.fasterxml.jackson.databind.ser.std.StdSerializer; -import java.io.IOException; - public class StringPropertyMasker extends StdSerializer implements ContextualSerializer { - private MaskingType maskingType; + private MaskingType maskingType; - protected StringPropertyMasker() { - super(String.class); - } + protected StringPropertyMasker() { + super(String.class); + } - protected StringPropertyMasker(MaskingType maskingType) { - super(String.class); - this.maskingType = maskingType; - } + protected StringPropertyMasker(MaskingType maskingType) { + super(String.class); + this.maskingType = maskingType; + } - @Override - public void serialize(String value, JsonGenerator gen, SerializerProvider provider) throws IOException { - gen.writeString(Masking.mask(maskingType, value)); - } + @Override + public void serialize(String value, JsonGenerator gen, SerializerProvider provider) + throws IOException { + gen.writeString(Masking.mask(maskingType, value)); + } - @Override - public JsonSerializer createContextual(SerializerProvider serializerProvider, BeanProperty property) { - if (property != null) { - Masked masked = property.getAnnotation(Masked.class); - if (masked != null) { - // 필드에 @Masked 애노테이션이 있는 경우, 애노테이션의 값에 따라 적절한 마스킹 로직을 선택하여 반환합니다. - return new StringPropertyMasker(masked.type()); - } - } - return this; + @Override + public JsonSerializer createContextual( + SerializerProvider serializerProvider, BeanProperty property) { + if (property != null) { + Masked masked = property.getAnnotation(Masked.class); + if (masked != null) { + // 필드에 @Masked 애노테이션이 있는 경우, 애노테이션의 값에 따라 적절한 마스킹 로직을 선택하여 반환합니다. + return new StringPropertyMasker(masked.type()); + } } -} \ No newline at end of file + return this; + } +} diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/service/MemberDuplicationChecker.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/service/MemberDuplicationChecker.java index c3b6e38a..d3319a5a 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/service/MemberDuplicationChecker.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/service/MemberDuplicationChecker.java @@ -5,7 +5,7 @@ public interface MemberDuplicationChecker { - Boolean isDuplicatedMember(MemberDuplicationQueryCondition condition); + Boolean isDuplicatedMember(MemberDuplicationQueryCondition condition); - Boolean isDuplicatedMember(Member member); + Boolean isDuplicatedMember(Member member); } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/service/MemberDuplicationCheckerImpl.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/service/MemberDuplicationCheckerImpl.java index 9a5f6296..2aea4dcd 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/service/MemberDuplicationCheckerImpl.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/service/MemberDuplicationCheckerImpl.java @@ -1,24 +1,26 @@ package com.inhabas.api.auth.domain.oauth2.member.service; +import lombok.RequiredArgsConstructor; + +import org.springframework.stereotype.Component; + import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; import com.inhabas.api.auth.domain.oauth2.member.dto.MemberDuplicationQueryCondition; import com.inhabas.api.auth.domain.oauth2.member.repository.MemberRepository; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Component; @Component @RequiredArgsConstructor public class MemberDuplicationCheckerImpl implements MemberDuplicationChecker { - private final MemberRepository memberRepository; + private final MemberRepository memberRepository; - @Override - public Boolean isDuplicatedMember(MemberDuplicationQueryCondition condition) { - return memberRepository.isDuplicated(condition); - } + @Override + public Boolean isDuplicatedMember(MemberDuplicationQueryCondition condition) { + return memberRepository.isDuplicated(condition); + } - @Override - public Boolean isDuplicatedMember(Member member) { - return memberRepository.existsByProviderAndUid(member.getProvider(), member.getUid()); - } + @Override + public Boolean isDuplicatedMember(Member member) { + return memberRepository.existsByProviderAndUid(member.getProvider(), member.getUid()); + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/service/MemberService.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/service/MemberService.java index d24ba021..69aaf9d6 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/service/MemberService.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/service/MemberService.java @@ -1,37 +1,43 @@ package com.inhabas.api.auth.domain.oauth2.member.service; +import java.util.List; + +import org.springframework.data.domain.Pageable; + import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.Role; import com.inhabas.api.auth.domain.oauth2.member.dto.*; import com.inhabas.api.auth.domain.oauth2.userInfo.OAuth2UserInfo; -import org.springframework.data.domain.Pageable; - -import java.util.List; public interface MemberService { - // 가입 관련 - void changeRole(Member member, Role role); - void finishSignUp(Member member); + // 가입 관련 + void changeRole(Member member, Role role); + + void finishSignUp(Member member); + + // 회원관리 관련 + List getNotApprovedMembersBySearchAndRole(String search); + + List getApprovedMembersBySearchAndRole(String search); + + void updateUnapprovedMembers(List memberIdList, String state); + + void updateApprovedMembers(List memberIdList, Role role); + ContactDto getChiefContact(); - // 회원관리 관련 - List getNotApprovedMembersBySearchAndRole(String search); - List getApprovedMembersBySearchAndRole(String search); - void updateUnapprovedMembers(List memberIdList, String state); - void updateApprovedMembers(List memberIdList, Role role); - ContactDto getChiefContact(); - List getPagedDtoList(Pageable pageable, List dtoList); + List getPagedDtoList(Pageable pageable, List dtoList); + // OAuth 관련 + void updateSocialAccountInfo(OAuth2UserInfo oAuth2UserInfo); - // OAuth 관련 - void updateSocialAccountInfo(OAuth2UserInfo oAuth2UserInfo); + // 내 정보 관련 + MyProfileDto getMyProfile(Long memberId); + void updateMyProfileDetail(Long memberId, ProfileDetailDto profileDetailDto); - // 내 정보 관련 - MyProfileDto getMyProfile(Long memberId); - void updateMyProfileDetail(Long memberId, ProfileDetailDto profileDetailDto); - void updateMyProfileIntro(Long memberId, ProfileIntroDto profileIntroDto); - void requestMyProfileName(Long memberId, ProfileNameDto profileNameDto); + void updateMyProfileIntro(Long memberId, ProfileIntroDto profileIntroDto); + void requestMyProfileName(Long memberId, ProfileNameDto profileNameDto); } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/service/MemberServiceImpl.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/service/MemberServiceImpl.java index 60e5ada6..583423f2 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/service/MemberServiceImpl.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/service/MemberServiceImpl.java @@ -1,5 +1,20 @@ package com.inhabas.api.auth.domain.oauth2.member.service; +import static com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.Role.*; + +import java.time.LocalDateTime; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; import com.inhabas.api.auth.domain.oauth2.member.domain.entity.UpdateNameRequest; @@ -10,239 +25,218 @@ import com.inhabas.api.auth.domain.oauth2.member.repository.UpdateNameRequestRepository; import com.inhabas.api.auth.domain.oauth2.socialAccount.domain.valueObject.UID; import com.inhabas.api.auth.domain.oauth2.userInfo.OAuth2UserInfo; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; -import org.springframework.data.domain.Pageable; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.time.LocalDateTime; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.stream.Collectors; - -import static com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.Role.*; - @Slf4j @Service @RequiredArgsConstructor public class MemberServiceImpl implements MemberService { - private static final Role DEFAULT_ROLE_AFTER_FINISH_SIGNUP = NOT_APPROVED; - private static final List OLD_ROLES = Arrays.asList(ADMIN, CHIEF, VICE_CHIEF, EXECUTIVES, SECRETARY, BASIC, DEACTIVATED); - private static final String PASS_STATE = "pass"; - private static final String FAIL_STATE = "fail"; - private final MemberRepository memberRepository; - private final UpdateNameRequestRepository updateNameRequestRepository; - private final MemberDuplicationChecker duplicationChecker; - - - @Transactional - public void changeRole(Member member, Role role) { - member.setRole(role); - memberRepository.save(member); + private static final Role DEFAULT_ROLE_AFTER_FINISH_SIGNUP = NOT_APPROVED; + private static final List OLD_ROLES = + Arrays.asList(ADMIN, CHIEF, VICE_CHIEF, EXECUTIVES, SECRETARY, BASIC, DEACTIVATED); + private static final String PASS_STATE = "pass"; + private static final String FAIL_STATE = "fail"; + private final MemberRepository memberRepository; + private final UpdateNameRequestRepository updateNameRequestRepository; + private final MemberDuplicationChecker duplicationChecker; + + @Transactional + public void changeRole(Member member, Role role) { + member.setRole(role); + memberRepository.save(member); + } + + @Override + @Transactional + public void finishSignUp(Member member) { + member.finishSignUp(); + this.changeRole(member, DEFAULT_ROLE_AFTER_FINISH_SIGNUP); + } + + @Override + @Transactional(readOnly = true) + public List getNotApprovedMembersBySearchAndRole(String search) { + final List members = + StringUtils.isNumeric(search) + ? memberRepository.findAllByRoleAndStudentIdLike( + DEFAULT_ROLE_AFTER_FINISH_SIGNUP, search) + : memberRepository.findAllByRoleAndNameLike(DEFAULT_ROLE_AFTER_FINISH_SIGNUP, search); + + return members.stream() + .map( + member -> + new NotApprovedMemberManagementDto( + member.getName(), + member.getId(), + member.getStudentId(), + member.getPhone(), + member.getEmail(), + member.getSchoolInformation().getGrade(), + member.getSchoolInformation().getMajor())) + .collect(Collectors.toList()); + } + + @Override + @Transactional(readOnly = true) + public List getApprovedMembersBySearchAndRole(String search) { + final List members = + StringUtils.isNumeric(search) + ? memberRepository.findAllByRolesInAndStudentIdLike(OLD_ROLES, search) + : memberRepository.findAllByRolesInAndNameLike(OLD_ROLES, search); + + return members.stream() + .map( + member -> + new ApprovedMemberManagementDto( + member.getName(), + member.getId(), + member.getStudentId(), + member.getPhone(), + member.getRole(), + member.getSchoolInformation().getGeneration(), + member.getSchoolInformation().getMajor())) + .collect(Collectors.toList()); + } + + @Override + @Transactional + public void updateUnapprovedMembers(List memberIdList, String state) { + + List members = memberRepository.findAllById(memberIdList); + boolean allNewMembers = + members.stream() + .allMatch(member -> DEFAULT_ROLE_AFTER_FINISH_SIGNUP.equals(member.getRole())); + + if (!allNewMembers || !(state.equals(PASS_STATE) || state.equals(FAIL_STATE))) { + throw new InvalidInputException(); } + if (state.equals(PASS_STATE)) { + for (Member member : members) member.setRole(DEACTIVATED); - @Override - @Transactional - public void finishSignUp(Member member) { - member.finishSignUp(); - this.changeRole(member, DEFAULT_ROLE_AFTER_FINISH_SIGNUP); - } - - @Override - @Transactional(readOnly = true) - public List getNotApprovedMembersBySearchAndRole(String search) { - final List members = StringUtils.isNumeric(search) - ? memberRepository.findAllByRoleAndStudentIdLike(DEFAULT_ROLE_AFTER_FINISH_SIGNUP, search) - : memberRepository.findAllByRoleAndNameLike(DEFAULT_ROLE_AFTER_FINISH_SIGNUP, search); - - return members.stream() - .map(member -> new NotApprovedMemberManagementDto( - member.getName(), - member.getId(), - member.getStudentId(), - member.getPhone(), - member.getEmail(), - member.getSchoolInformation().getGrade(), - member.getSchoolInformation().getMajor())) - .collect(Collectors.toList()); + memberRepository.saveAll(members); + } else { + // 이메일 전송 추가 예정 + memberRepository.deleteAll(members); } + } - @Override - @Transactional(readOnly = true) - public List getApprovedMembersBySearchAndRole(String search) { - final List members = StringUtils.isNumeric(search) - ? memberRepository.findAllByRolesInAndStudentIdLike(OLD_ROLES, search) - : memberRepository.findAllByRolesInAndNameLike(OLD_ROLES, search); - - return members.stream() - .map(member -> new ApprovedMemberManagementDto( - member.getName(), - member.getId(), - member.getStudentId(), - member.getPhone(), - member.getRole(), - member.getSchoolInformation().getGeneration(), - member.getSchoolInformation().getMajor())) - .collect(Collectors.toList()); + @Override + @Transactional + public void updateApprovedMembers(List memberIdList, Role role) { + // 변경 가능한 ROLE 인지 확인 + if (!OLD_ROLES.contains(role)) { + throw new InvalidInputException(); } - @Override - @Transactional - public void updateUnapprovedMembers(List memberIdList, String state) { - - List members = memberRepository.findAllById(memberIdList); - boolean allNewMembers = members.stream().allMatch( - member -> DEFAULT_ROLE_AFTER_FINISH_SIGNUP.equals(member.getRole())); - - if (!allNewMembers || !(state.equals(PASS_STATE) || state.equals(FAIL_STATE))) { - throw new InvalidInputException(); - } - - if (state.equals(PASS_STATE)) { - for (Member member : members) - member.setRole(DEACTIVATED); - - memberRepository.saveAll(members); - - } else { - // 이메일 전송 추가 예정 - memberRepository.deleteAll(members); - } + List members = memberRepository.findAllById(memberIdList); + boolean allApprovedMembers = + members.stream().allMatch(member -> OLD_ROLES.contains(member.getRole())); + if (!allApprovedMembers) { + throw new InvalidInputException(); } - @Override - @Transactional - public void updateApprovedMembers(List memberIdList, Role role) { - - // 변경 가능한 ROLE 인지 확인 - if (!OLD_ROLES.contains(role)) { - throw new InvalidInputException(); - } + for (Member member : members) member.setRole(role); - List members = memberRepository.findAllById(memberIdList); - boolean allApprovedMembers = members.stream().allMatch( - member -> OLD_ROLES.contains(member.getRole())); + memberRepository.saveAll(members); + } - if (!allApprovedMembers) { - throw new InvalidInputException(); - } + @Override + @Transactional(readOnly = true) + public ContactDto getChiefContact() { - for (Member member : members) - member.setRole(role); + Member chief = memberRepository.findByIbasInformation_Role(CHIEF); - memberRepository.saveAll(members); - - } + return new ContactDto(chief.getName(), chief.getPhone(), chief.getEmail()); + } - @Override - @Transactional(readOnly = true) - public ContactDto getChiefContact() { + @Override + @Transactional(readOnly = true) + public List getPagedDtoList(Pageable pageable, List dtoList) { - Member chief = memberRepository.findByIbasInformation_Role(CHIEF); - - return new ContactDto(chief.getName(), chief.getPhone(), chief.getEmail()); + int start = (int) pageable.getOffset(); + int end = Math.min((start + pageable.getPageSize()), dtoList.size()); + // 시작 인덱스가 리스트 크기보다 크거나 같은 경우, 빈 리스트 반환 + if (start >= dtoList.size()) { + return Collections.emptyList(); } - @Override - @Transactional(readOnly = true) - public List getPagedDtoList(Pageable pageable, List dtoList) { + return dtoList.subList(start, end); + } - int start = (int) pageable.getOffset(); - int end = Math.min((start + pageable.getPageSize()), dtoList.size()); + @Override + @Transactional + public void updateSocialAccountInfo(OAuth2UserInfo oAuth2UserInfo) { - // 시작 인덱스가 리스트 크기보다 크거나 같은 경우, 빈 리스트 반환 - if (start >= dtoList.size()) { - return Collections.emptyList(); - } + Member member = + memberRepository + .findByProviderAndUid(oAuth2UserInfo.getProvider(), new UID(oAuth2UserInfo.getId())) + .orElse(new Member(oAuth2UserInfo)) + .setLastLoginTime(LocalDateTime.now()); - return dtoList.subList(start, end); + memberRepository.save(member); + } - } + @Override + @Transactional(readOnly = true) + public MyProfileDto getMyProfile(Long memberId) { + Member member = memberRepository.findById(memberId).orElseThrow(MemberNotFoundException::new); - @Override - @Transactional - public void updateSocialAccountInfo(OAuth2UserInfo oAuth2UserInfo) { + return MyProfileDto.builder() + .name(member.getName()) + .studentId(member.getStudentId()) + .major(member.getSchoolInformation().getMajor()) + .grade(member.getSchoolInformation().getGrade()) + .email(member.getEmail()) + .picture(member.getPicture()) + .phoneNumber(member.getPhone()) + .role(member.getRole()) + .type(member.getSchoolInformation().getMemberType()) + .introduce(member.getIbasInformation().getIntroduce()) + .build(); + } - Member member = memberRepository. - findByProviderAndUid(oAuth2UserInfo.getProvider(), new UID(oAuth2UserInfo.getId())) - .orElse(new Member(oAuth2UserInfo)) - .setLastLoginTime(LocalDateTime.now()); + @Override + @Transactional + public void updateMyProfileDetail(Long memberId, ProfileDetailDto profileDetailDto) { - memberRepository.save(member); + Member member = memberRepository.findById(memberId).orElseThrow(MemberNotFoundException::new); - } + if (profileDetailDto.getMajor() != null) + member.getSchoolInformation().setMajor(profileDetailDto.getMajor()); + if (profileDetailDto.getPhoneNumber() != null) + member.setPhone(profileDetailDto.getPhoneNumber()); + if (profileDetailDto.getGrade() != null) + member.getSchoolInformation().setGrade(profileDetailDto.getGrade()); + } - @Override - @Transactional(readOnly = true) - public MyProfileDto getMyProfile(Long memberId) { + @Override + @Transactional + public void updateMyProfileIntro(Long memberId, ProfileIntroDto profileIntroDto) { - Member member = memberRepository.findById(memberId).orElseThrow(MemberNotFoundException::new); + Member member = memberRepository.findById(memberId).orElseThrow(MemberNotFoundException::new); - return MyProfileDto.builder() - .name(member.getName()) - .studentId(member.getStudentId()) - .major(member.getSchoolInformation().getMajor()) - .grade(member.getSchoolInformation().getGrade()) - .email(member.getEmail()) - .picture(member.getPicture()) - .phoneNumber(member.getPhone()) - .role(member.getRole()) - .type(member.getSchoolInformation().getMemberType()) - .introduce(member.getIbasInformation().getIntroduce()).build(); + if (profileIntroDto.getIsHOF() != null) + member.getIbasInformation().setIsHOF(profileIntroDto.getIsHOF()); - } - - @Override - @Transactional - public void updateMyProfileDetail(Long memberId, ProfileDetailDto profileDetailDto) { - - Member member = memberRepository.findById(memberId).orElseThrow(MemberNotFoundException::new); - - if(profileDetailDto.getMajor() != null) - member.getSchoolInformation().setMajor(profileDetailDto.getMajor()); - if(profileDetailDto.getPhoneNumber() != null) - member.setPhone(profileDetailDto.getPhoneNumber()); - if(profileDetailDto.getGrade() != null) - member.getSchoolInformation().setGrade(profileDetailDto.getGrade()); - - } - - @Override - @Transactional - public void updateMyProfileIntro(Long memberId, ProfileIntroDto profileIntroDto) { + member.getIbasInformation().setIntroduce(profileIntroDto.getIntroduce()); + } - Member member = memberRepository.findById(memberId).orElseThrow(MemberNotFoundException::new); + @Override + @Transactional + public void requestMyProfileName(Long memberId, ProfileNameDto profileNameDto) { - if (profileIntroDto.getIsHOF() != null) - member.getIbasInformation().setIsHOF(profileIntroDto.getIsHOF()); + Member member = memberRepository.findById(memberId).orElseThrow(MemberNotFoundException::new); - member.getIbasInformation().setIntroduce(profileIntroDto.getIntroduce()); + UpdateNameRequest updateNameRequest = + UpdateNameRequest.builder().member(member).name(profileNameDto.getName()).build(); - } - - @Override - @Transactional - public void requestMyProfileName(Long memberId, ProfileNameDto profileNameDto) { - - Member member = memberRepository.findById(memberId).orElseThrow(MemberNotFoundException::new); - - UpdateNameRequest updateNameRequest = UpdateNameRequest.builder() - .member(member) - .name(profileNameDto.getName()). - build(); - - updateNameRequestRepository.save(updateNameRequest); - - } + updateNameRequestRepository.save(updateNameRequest); + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/socialAccount/domain/entity/MemberSocialAccount.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/socialAccount/domain/entity/MemberSocialAccount.java index d7e662ea..ea0209c9 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/socialAccount/domain/entity/MemberSocialAccount.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/socialAccount/domain/entity/MemberSocialAccount.java @@ -1,62 +1,66 @@ package com.inhabas.api.auth.domain.oauth2.socialAccount.domain.entity; -import com.inhabas.api.auth.domain.oauth2.OAuth2Provider; -import com.inhabas.api.auth.domain.oauth2.socialAccount.domain.valueObject.UID; -import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; -import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.Email; +import javax.persistence.*; + import lombok.AccessLevel; import lombok.NoArgsConstructor; -import javax.persistence.*; +import com.inhabas.api.auth.domain.oauth2.OAuth2Provider; +import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; +import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.Email; +import com.inhabas.api.auth.domain.oauth2.socialAccount.domain.valueObject.UID; @Entity -@Table(name = "USER_SOCIALACCOUNT", - uniqueConstraints = { @UniqueConstraint(name = "user_socialaccount_uid_provider_uindex", columnNames = {"PROVIDER", "UID"})}) // +@Table( + name = "USER_SOCIALACCOUNT", + uniqueConstraints = { + @UniqueConstraint( + name = "user_socialaccount_uid_provider_uindex", + columnNames = {"PROVIDER", "UID"}) + }) // @NoArgsConstructor(access = AccessLevel.PROTECTED) public class MemberSocialAccount { - @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @OneToOne(fetch = FetchType.LAZY, optional = false) - @JoinColumn(name = "USER_ID") - private Member member; + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; - @Embedded - private Email email; + @OneToOne(fetch = FetchType.LAZY, optional = false) + @JoinColumn(name = "USER_ID") + private Member member; - @Embedded - private UID uid; + @Embedded private Email email; - @Column(name = "PROVIDER") - @Enumerated(EnumType.STRING) - private OAuth2Provider provider; + @Embedded private UID uid; - public UID getUid() { - return uid; - } + @Column(name = "PROVIDER") + @Enumerated(EnumType.STRING) + private OAuth2Provider provider; - public Email getEmail() { - return email; - } + public UID getUid() { + return uid; + } + public Email getEmail() { + return email; + } - public MemberSocialAccount(Member member, String email, String uid, OAuth2Provider provider) { - this.member = member; - this.email = new Email(email); - this.uid = new UID(uid); - this.provider = provider; - } + public MemberSocialAccount(Member member, String email, String uid, OAuth2Provider provider) { + this.member = member; + this.email = new Email(email); + this.uid = new UID(uid); + this.provider = provider; + } - public Long getId() { - return this.id; - } + public Long getId() { + return this.id; + } - public Member getMember() { - return this.member; - } + public Member getMember() { + return this.member; + } - public void SetUID(UID uid) { - this.uid = uid; - } + public void SetUID(UID uid) { + this.uid = uid; + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/socialAccount/domain/exception/NoSuchSocialAccountException.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/socialAccount/domain/exception/NoSuchSocialAccountException.java index 272663ee..8b5c50b7 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/socialAccount/domain/exception/NoSuchSocialAccountException.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/socialAccount/domain/exception/NoSuchSocialAccountException.java @@ -2,7 +2,7 @@ public class NoSuchSocialAccountException extends RuntimeException { - public NoSuchSocialAccountException() { - super("해당 소셜 계정이 존재하지 않습니다,"); - } + public NoSuchSocialAccountException() { + super("해당 소셜 계정이 존재하지 않습니다,"); + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/socialAccount/domain/valueObject/UID.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/socialAccount/domain/valueObject/UID.java index b714b709..a6b19cc6 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/socialAccount/domain/valueObject/UID.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/socialAccount/domain/valueObject/UID.java @@ -1,40 +1,38 @@ package com.inhabas.api.auth.domain.oauth2.socialAccount.domain.valueObject; -import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; +import java.util.Objects; import javax.persistence.Column; import javax.persistence.Embeddable; import javax.persistence.Transient; -import java.util.Objects; + +import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; @Embeddable public class UID { - @Column(name = "UID", nullable = false) - private String value; + @Column(name = "UID", nullable = false) + private String value; - @Transient - private final int MAX_SIZE = 255; + @Transient private final int MAX_SIZE = 255; - public UID() {} + public UID() {} - public UID(String value) { - if (validate(value)) - this.value = value; - else - throw new InvalidInputException(); - } + public UID(String value) { + if (validate(value)) this.value = value; + else throw new InvalidInputException(); + } - private boolean validate(Object value) { - if (Objects.isNull(value)) return false; - if (!(value instanceof String)) return false; + private boolean validate(Object value) { + if (Objects.isNull(value)) return false; + if (!(value instanceof String)) return false; - String o = (String) value; - if (o.isBlank()) return false; - return o.length() <= MAX_SIZE; - } + String o = (String) value; + if (o.isBlank()) return false; + return o.length() <= MAX_SIZE; + } - public String getValue() { - return value; - } + public String getValue() { + return value; + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/socialAccount/repository/MemberSocialAccountRepository.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/socialAccount/repository/MemberSocialAccountRepository.java index ae207d34..f8baeb45 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/socialAccount/repository/MemberSocialAccountRepository.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/socialAccount/repository/MemberSocialAccountRepository.java @@ -1,16 +1,18 @@ package com.inhabas.api.auth.domain.oauth2.socialAccount.repository; +import java.util.Optional; + +import org.springframework.data.jpa.repository.JpaRepository; + import com.inhabas.api.auth.domain.oauth2.OAuth2Provider; import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.Email; import com.inhabas.api.auth.domain.oauth2.socialAccount.domain.entity.MemberSocialAccount; -import org.springframework.data.jpa.repository.JpaRepository; - -import java.util.Optional; public interface MemberSocialAccountRepository - extends JpaRepository, MemberSocialAccountRepositoryCustom { + extends JpaRepository, MemberSocialAccountRepositoryCustom { - Optional findMemberSocialAccountByEmailAndProvider(Email email, OAuth2Provider provider); + Optional findMemberSocialAccountByEmailAndProvider( + Email email, OAuth2Provider provider); - boolean existsByMember_Id(Long memberId); + boolean existsByMember_Id(Long memberId); } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/socialAccount/repository/MemberSocialAccountRepositoryCustom.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/socialAccount/repository/MemberSocialAccountRepositoryCustom.java index ddbb61ad..fcf3d695 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/socialAccount/repository/MemberSocialAccountRepositoryCustom.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/socialAccount/repository/MemberSocialAccountRepositoryCustom.java @@ -1,11 +1,11 @@ package com.inhabas.api.auth.domain.oauth2.socialAccount.repository; +import java.util.Optional; + import com.inhabas.api.auth.domain.oauth2.OAuth2Provider; import com.inhabas.api.auth.domain.oauth2.socialAccount.domain.valueObject.UID; -import java.util.Optional; - public interface MemberSocialAccountRepositoryCustom { - Optional findMemberIdByUidAndProvider(UID uid, OAuth2Provider provider); + Optional findMemberIdByUidAndProvider(UID uid, OAuth2Provider provider); } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/socialAccount/repository/MemberSocialAccountRepositoryImpl.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/socialAccount/repository/MemberSocialAccountRepositoryImpl.java index bb372868..139487ed 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/socialAccount/repository/MemberSocialAccountRepositoryImpl.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/socialAccount/repository/MemberSocialAccountRepositoryImpl.java @@ -1,30 +1,32 @@ package com.inhabas.api.auth.domain.oauth2.socialAccount.repository; +import static com.inhabas.api.auth.domain.oauth2.socialAccount.domain.entity.QMemberSocialAccount.memberSocialAccount; + +import java.util.Optional; + +import lombok.RequiredArgsConstructor; + import com.inhabas.api.auth.domain.oauth2.OAuth2Provider; import com.inhabas.api.auth.domain.oauth2.socialAccount.domain.valueObject.UID; import com.querydsl.core.types.dsl.BooleanExpression; import com.querydsl.jpa.impl.JPAQueryFactory; -import lombok.RequiredArgsConstructor; - -import java.util.Optional; - -import static com.inhabas.api.auth.domain.oauth2.socialAccount.domain.entity.QMemberSocialAccount.memberSocialAccount; @RequiredArgsConstructor public class MemberSocialAccountRepositoryImpl implements MemberSocialAccountRepositoryCustom { - private final JPAQueryFactory jpaQueryFactory; + private final JPAQueryFactory jpaQueryFactory; - @Override - public Optional findMemberIdByUidAndProvider(UID uid, OAuth2Provider provider) { - return Optional.ofNullable(jpaQueryFactory - .select(memberSocialAccount.member.id) - .where(eqSocialAccount(uid, provider)) - .from(memberSocialAccount) - .fetchOne()); - } + @Override + public Optional findMemberIdByUidAndProvider(UID uid, OAuth2Provider provider) { + return Optional.ofNullable( + jpaQueryFactory + .select(memberSocialAccount.member.id) + .where(eqSocialAccount(uid, provider)) + .from(memberSocialAccount) + .fetchOne()); + } - private BooleanExpression eqSocialAccount(UID uid, OAuth2Provider provider) { - return memberSocialAccount.uid.eq(uid).and(memberSocialAccount.provider.eq(provider)); - } + private BooleanExpression eqSocialAccount(UID uid, OAuth2Provider provider) { + return memberSocialAccount.uid.eq(uid).and(memberSocialAccount.provider.eq(provider)); + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/userAuthorityProvider/DefaultUserAuthorityProvider.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/userAuthorityProvider/DefaultUserAuthorityProvider.java index f53a91b1..c2d86e1c 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/userAuthorityProvider/DefaultUserAuthorityProvider.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/userAuthorityProvider/DefaultUserAuthorityProvider.java @@ -1,17 +1,17 @@ package com.inhabas.api.auth.domain.oauth2.userAuthorityProvider; -import com.inhabas.api.auth.domain.oauth2.userInfo.OAuth2UserInfo; -import org.springframework.security.core.authority.SimpleGrantedAuthority; - import java.util.Collection; import java.util.Collections; +import org.springframework.security.core.authority.SimpleGrantedAuthority; + +import com.inhabas.api.auth.domain.oauth2.userInfo.OAuth2UserInfo; public class DefaultUserAuthorityProvider implements UserAuthorityProvider { - @Override - public Collection determineAuthorities(OAuth2UserInfo oAuth2UserInfo) { + @Override + public Collection determineAuthorities(OAuth2UserInfo oAuth2UserInfo) { - return Collections.singleton(new SimpleGrantedAuthority("ROLE_ANONYMOUS")); - } + return Collections.singleton(new SimpleGrantedAuthority("ROLE_ANONYMOUS")); + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/userAuthorityProvider/UserAuthorityProvider.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/userAuthorityProvider/UserAuthorityProvider.java index a70d139b..b8d79221 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/userAuthorityProvider/UserAuthorityProvider.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/userAuthorityProvider/UserAuthorityProvider.java @@ -1,23 +1,23 @@ package com.inhabas.api.auth.domain.oauth2.userAuthorityProvider; -import com.inhabas.api.auth.domain.oauth2.userInfo.OAuth2UserInfo; +import java.util.Collection; + import org.springframework.security.core.authority.SimpleGrantedAuthority; -import java.util.Collection; +import com.inhabas.api.auth.domain.oauth2.userInfo.OAuth2UserInfo; /** - * OAuth 2.0 인증이 끝난 후에, 로그인하려는 유저에게 부여할 권한을 결정한다. - * 아래와 같은 상황에서는, 이 인터페이스를 상속받아서 구현해야한다.
+ * OAuth 2.0 인증이 끝난 후에, 로그인하려는 유저에게 부여할 권한을 결정한다. 아래와 같은 상황에서는, 이 인터페이스를 상속받아서 구현해야한다.
* *
    - *
  1. 기존 회원인지 아닌지를 확인하고 그에 따른 권한을 부여할 때
  2. - *
  3. 회원 등급에 따라 다른 권한을 부여하고 싶을 때
  4. - *
  5. 커스터마이징한 권한을 부여하고 싶을 때
  6. + *
  7. 기존 회원인지 아닌지를 확인하고 그에 따른 권한을 부여할 때 + *
  8. 회원 등급에 따라 다른 권한을 부여하고 싶을 때 + *
  9. 커스터마이징한 권한을 부여하고 싶을 때 *
* * 기본 구현체는 {@link DefaultUserAuthorityProvider}이고, 이 때에는 모든 사용자의 권한이 {@code ROLE_ANONYMOUS} 로 지정된다. */ public interface UserAuthorityProvider { - Collection determineAuthorities(OAuth2UserInfo oAuth2UserInfo); + Collection determineAuthorities(OAuth2UserInfo oAuth2UserInfo); } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/userInfo/GoogleOAuth2UserInfo.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/userInfo/GoogleOAuth2UserInfo.java index dbfd3551..ece3a19d 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/userInfo/GoogleOAuth2UserInfo.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/userInfo/GoogleOAuth2UserInfo.java @@ -1,45 +1,45 @@ package com.inhabas.api.auth.domain.oauth2.userInfo; -import com.inhabas.api.auth.domain.oauth2.OAuth2Provider; - import java.util.Map; import java.util.Objects; +import com.inhabas.api.auth.domain.oauth2.OAuth2Provider; + public class GoogleOAuth2UserInfo extends OAuth2UserInfo { - private static final String KEY_ID = "sub"; - private static final String KEY_NAME = "name"; - private static final String KEY_EMAIL = "email"; - private static final String KEY_IMAGE_URL = "picture"; - - public GoogleOAuth2UserInfo(Map attributes) { - super(OAuth2Provider.GOOGLE, attributes); - } - - @Override - public String getId() { - return Objects.toString(this.attributes.get(KEY_ID)); - } - - @Override - public String getName() { - return (String) this.attributes.get(KEY_NAME); - } - - @Override - public String getEmail() { - return (String) this.attributes.get(KEY_EMAIL); - } - - @Override - public String getImageUrl() { - return (String) this.attributes.get(KEY_IMAGE_URL); - } - - @Override - public Map getExtraData() { - return this.attributes; - } + private static final String KEY_ID = "sub"; + private static final String KEY_NAME = "name"; + private static final String KEY_EMAIL = "email"; + private static final String KEY_IMAGE_URL = "picture"; + + public GoogleOAuth2UserInfo(Map attributes) { + super(OAuth2Provider.GOOGLE, attributes); + } + + @Override + public String getId() { + return Objects.toString(this.attributes.get(KEY_ID)); + } + + @Override + public String getName() { + return (String) this.attributes.get(KEY_NAME); + } + + @Override + public String getEmail() { + return (String) this.attributes.get(KEY_EMAIL); + } + + @Override + public String getImageUrl() { + return (String) this.attributes.get(KEY_IMAGE_URL); + } + + @Override + public Map getExtraData() { + return this.attributes; + } } /* attribute 는 아래와 같은 형식 { diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/userInfo/KakaoOAuth2UserInfo.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/userInfo/KakaoOAuth2UserInfo.java index 1fcf67d0..51521127 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/userInfo/KakaoOAuth2UserInfo.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/userInfo/KakaoOAuth2UserInfo.java @@ -1,59 +1,58 @@ package com.inhabas.api.auth.domain.oauth2.userInfo; -import com.inhabas.api.auth.domain.oauth2.OAuth2Provider; - import java.util.Map; import java.util.Objects; +import com.inhabas.api.auth.domain.oauth2.OAuth2Provider; public class KakaoOAuth2UserInfo extends OAuth2UserInfo { - private static final String KEY_ID = "id"; - private static final String KEY_NAME = "nickname"; - private static final String KEY_EMAIL = "email"; - private static final String KEY_IMAGE_URL = "profile_image_url"; - private static final String KEY_EXTRA_DATA = "kakao_account"; + private static final String KEY_ID = "id"; + private static final String KEY_NAME = "nickname"; + private static final String KEY_EMAIL = "email"; + private static final String KEY_IMAGE_URL = "profile_image_url"; + private static final String KEY_EXTRA_DATA = "kakao_account"; - public KakaoOAuth2UserInfo(Map attributes) { - super(OAuth2Provider.KAKAO, attributes); - } + public KakaoOAuth2UserInfo(Map attributes) { + super(OAuth2Provider.KAKAO, attributes); + } - @Override - public String getId() { + @Override + public String getId() { - return Objects.toString(attributes.get(KEY_ID)); - } + return Objects.toString(attributes.get(KEY_ID)); + } - @Override - public String getName() { + @Override + public String getName() { - return (String) this.getProfile().get(KEY_NAME); - } + return (String) this.getProfile().get(KEY_NAME); + } - @Override - public String getEmail() { + @Override + public String getEmail() { - return (String) this.getExtraData().get(KEY_EMAIL); - } + return (String) this.getExtraData().get(KEY_EMAIL); + } - @Override - public String getImageUrl() { + @Override + public String getImageUrl() { - return (String) this.getProfile().get(KEY_IMAGE_URL); - } + return (String) this.getProfile().get(KEY_IMAGE_URL); + } - @SuppressWarnings({"unchecked"}) - @Override - public Map getExtraData() { + @SuppressWarnings({"unchecked"}) + @Override + public Map getExtraData() { - return (Map) attributes.get(KEY_EXTRA_DATA); - } + return (Map) attributes.get(KEY_EXTRA_DATA); + } - @SuppressWarnings({"unchecked"}) - private Map getProfile() { + @SuppressWarnings({"unchecked"}) + private Map getProfile() { - return (Map) this.getExtraData().get("profile"); - } + return (Map) this.getExtraData().get("profile"); + } } /* attribute 는 아래와 같은 형식 diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/userInfo/NaverOAuth2UserInfo.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/userInfo/NaverOAuth2UserInfo.java index 84a164ed..062d9304 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/userInfo/NaverOAuth2UserInfo.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/userInfo/NaverOAuth2UserInfo.java @@ -1,47 +1,47 @@ package com.inhabas.api.auth.domain.oauth2.userInfo; -import com.inhabas.api.auth.domain.oauth2.OAuth2Provider; - import java.util.Map; import java.util.Objects; -public class NaverOAuth2UserInfo extends OAuth2UserInfo { - - private static final String KEY_ID = "id"; - private static final String KEY_NAME = "name"; - private static final String KEY_EMAIL = "email"; - private static final String KEY_IMAGE_URL = "profile_image"; - private static final String KEY_EXTRA_DATA = "response"; - - public NaverOAuth2UserInfo(Map attributes) { - super(OAuth2Provider.NAVER, attributes); - } - - @Override - public String getId() { - return Objects.toString(this.getExtraData().get(KEY_ID)); - } - - @Override - public String getName() { - return (String) this.getExtraData().get(KEY_NAME); - } - - @Override - public String getEmail() { - return (String) this.getExtraData().get(KEY_EMAIL); - } +import com.inhabas.api.auth.domain.oauth2.OAuth2Provider; - @Override - public String getImageUrl() { - return (String) this.getExtraData().get(KEY_IMAGE_URL); - } +public class NaverOAuth2UserInfo extends OAuth2UserInfo { - @SuppressWarnings({"unchecked"}) - @Override - public Map getExtraData() { - return (Map) this.attributes.get(KEY_EXTRA_DATA); - } + private static final String KEY_ID = "id"; + private static final String KEY_NAME = "name"; + private static final String KEY_EMAIL = "email"; + private static final String KEY_IMAGE_URL = "profile_image"; + private static final String KEY_EXTRA_DATA = "response"; + + public NaverOAuth2UserInfo(Map attributes) { + super(OAuth2Provider.NAVER, attributes); + } + + @Override + public String getId() { + return Objects.toString(this.getExtraData().get(KEY_ID)); + } + + @Override + public String getName() { + return (String) this.getExtraData().get(KEY_NAME); + } + + @Override + public String getEmail() { + return (String) this.getExtraData().get(KEY_EMAIL); + } + + @Override + public String getImageUrl() { + return (String) this.getExtraData().get(KEY_IMAGE_URL); + } + + @SuppressWarnings({"unchecked"}) + @Override + public Map getExtraData() { + return (Map) this.attributes.get(KEY_EXTRA_DATA); + } } /* attribute 는 아래와 같은 형식 { diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/userInfo/OAuth2UserInfo.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/userInfo/OAuth2UserInfo.java index fde6863c..9be34ce5 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/userInfo/OAuth2UserInfo.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/userInfo/OAuth2UserInfo.java @@ -1,35 +1,44 @@ package com.inhabas.api.auth.domain.oauth2.userInfo; -import com.inhabas.api.auth.domain.oauth2.OAuth2Provider; -import org.springframework.util.StringUtils; - import java.util.Collections; import java.util.Map; +import org.springframework.util.StringUtils; + +import com.inhabas.api.auth.domain.oauth2.OAuth2Provider; + public abstract class OAuth2UserInfo { - protected Map attributes; - protected OAuth2Provider provider; - public OAuth2UserInfo(OAuth2Provider provider, Map attributes) { - this.provider = provider; - this.attributes = attributes; - } - public OAuth2Provider getProvider() { - return provider; - } - public Map getAttributes() { - return Collections.unmodifiableMap(attributes); - } - public abstract String getId(); - public abstract String getName(); - public abstract String getEmail(); - public abstract String getImageUrl(); - public abstract Map getExtraData(); - - public boolean validateNecessaryFields() { - return StringUtils.hasText(this.getEmail()) - && StringUtils.hasText(this.getId()) - && StringUtils.hasText(this.getName()) - && StringUtils.hasText(this.getImageUrl()); - } + protected Map attributes; + protected OAuth2Provider provider; + + public OAuth2UserInfo(OAuth2Provider provider, Map attributes) { + this.provider = provider; + this.attributes = attributes; + } + + public OAuth2Provider getProvider() { + return provider; + } + + public Map getAttributes() { + return Collections.unmodifiableMap(attributes); + } + + public abstract String getId(); + + public abstract String getName(); + + public abstract String getEmail(); + + public abstract String getImageUrl(); + + public abstract Map getExtraData(); + + public boolean validateNecessaryFields() { + return StringUtils.hasText(this.getEmail()) + && StringUtils.hasText(this.getId()) + && StringUtils.hasText(this.getName()) + && StringUtils.hasText(this.getImageUrl()); + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/userInfo/OAuth2UserInfoAuthentication.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/userInfo/OAuth2UserInfoAuthentication.java index d87fb827..c701f2e2 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/userInfo/OAuth2UserInfoAuthentication.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/userInfo/OAuth2UserInfoAuthentication.java @@ -1,45 +1,52 @@ package com.inhabas.api.auth.domain.oauth2.userInfo; -import com.inhabas.api.auth.domain.token.TokenAuthenticationResult; -import org.springframework.security.core.GrantedAuthority; - import java.util.Collection; -public class OAuth2UserInfoAuthentication extends TokenAuthenticationResult { - - private final String uid; - - private final String provider; - - private final String email; - - public OAuth2UserInfoAuthentication(String uid, String provider, String email) { - super(null); - this.uid = uid; - this.provider = provider; - this.email = email; - } - - protected OAuth2UserInfoAuthentication(String uid, String provider, String email, Collection authorities) { - super(authorities); - this.uid = uid; - this.provider = provider; - this.email = email; - } - - public String getUid() { - return uid; - } +import org.springframework.security.core.GrantedAuthority; - public String getProvider() { - return provider; - } +import com.inhabas.api.auth.domain.token.TokenAuthenticationResult; - public String getEmail() { return email; } +public class OAuth2UserInfoAuthentication extends TokenAuthenticationResult { - @Deprecated - @Override - public Object getCredentials() { - return null; - } + private final String uid; + + private final String provider; + + private final String email; + + public OAuth2UserInfoAuthentication(String uid, String provider, String email) { + super(null); + this.uid = uid; + this.provider = provider; + this.email = email; + } + + protected OAuth2UserInfoAuthentication( + String uid, + String provider, + String email, + Collection authorities) { + super(authorities); + this.uid = uid; + this.provider = provider; + this.email = email; + } + + public String getUid() { + return uid; + } + + public String getProvider() { + return provider; + } + + public String getEmail() { + return email; + } + + @Deprecated + @Override + public Object getCredentials() { + return null; + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/userInfo/OAuth2UserInfoFactory.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/userInfo/OAuth2UserInfoFactory.java index 39433c27..017f5432 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/userInfo/OAuth2UserInfoFactory.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/userInfo/OAuth2UserInfoFactory.java @@ -1,37 +1,37 @@ package com.inhabas.api.auth.domain.oauth2.userInfo; -import com.inhabas.api.auth.domain.oauth2.OAuth2Provider; -import com.inhabas.api.auth.domain.error.authException.UnsupportedOAuth2ProviderException; +import java.util.Map; + import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken; -import java.util.Map; +import com.inhabas.api.auth.domain.error.authException.UnsupportedOAuth2ProviderException; +import com.inhabas.api.auth.domain.oauth2.OAuth2Provider; public interface OAuth2UserInfoFactory { - static OAuth2UserInfo getOAuth2UserInfo(String registrationId, Map attributes) { - - OAuth2UserInfo userInfo = null; - OAuth2Provider oAuth2Provider = OAuth2Provider.convert(registrationId); - switch (oAuth2Provider) { - case GOOGLE: - userInfo = new GoogleOAuth2UserInfo(attributes); - break; - case NAVER: - userInfo = new NaverOAuth2UserInfo(attributes); - break; - case KAKAO: - userInfo = new KakaoOAuth2UserInfo(attributes); - break; - default: - throw new UnsupportedOAuth2ProviderException(); - } + static OAuth2UserInfo getOAuth2UserInfo(String registrationId, Map attributes) { - return userInfo; + OAuth2UserInfo userInfo = null; + OAuth2Provider oAuth2Provider = OAuth2Provider.convert(registrationId); + switch (oAuth2Provider) { + case GOOGLE: + userInfo = new GoogleOAuth2UserInfo(attributes); + break; + case NAVER: + userInfo = new NaverOAuth2UserInfo(attributes); + break; + case KAKAO: + userInfo = new KakaoOAuth2UserInfo(attributes); + break; + default: + throw new UnsupportedOAuth2ProviderException(); } - static OAuth2UserInfo getOAuth2UserInfo(OAuth2AuthenticationToken auth2AuthenticationToken) { - return OAuth2UserInfoFactory.getOAuth2UserInfo( - auth2AuthenticationToken.getAuthorizedClientRegistrationId(), - auth2AuthenticationToken.getPrincipal().getAttributes() - ); - } + return userInfo; + } + + static OAuth2UserInfo getOAuth2UserInfo(OAuth2AuthenticationToken auth2AuthenticationToken) { + return OAuth2UserInfoFactory.getOAuth2UserInfo( + auth2AuthenticationToken.getAuthorizedClientRegistrationId(), + auth2AuthenticationToken.getPrincipal().getAttributes()); + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/CustomRequestMatcher.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/CustomRequestMatcher.java index 2416c6c8..6f491bbe 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/CustomRequestMatcher.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/CustomRequestMatcher.java @@ -1,31 +1,26 @@ package com.inhabas.api.auth.domain.token; +import javax.servlet.http.HttpServletRequest; + import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import org.springframework.security.web.util.matcher.RequestMatcher; -import javax.servlet.http.HttpServletRequest; - -/** - * 기존 matches와 달리 request와 일치하지 않으면 True 반환 - */ +/** 기존 matches와 달리 request와 일치하지 않으면 True 반환 */ public class CustomRequestMatcher implements RequestMatcher { - private final AntPathRequestMatcher antPathRequestMatcher; - private final String httpMethod; - - public CustomRequestMatcher(String path, String httpMethod) { - - this.httpMethod = httpMethod; - this.antPathRequestMatcher = new AntPathRequestMatcher(path, httpMethod); - - } + private final AntPathRequestMatcher antPathRequestMatcher; + private final String httpMethod; - @Override - public boolean matches(HttpServletRequest request) { + public CustomRequestMatcher(String path, String httpMethod) { - String requestMethod = request.getMethod(); - return !(httpMethod.equalsIgnoreCase(requestMethod) && antPathRequestMatcher.matches(request)); + this.httpMethod = httpMethod; + this.antPathRequestMatcher = new AntPathRequestMatcher(path, httpMethod); + } - } + @Override + public boolean matches(HttpServletRequest request) { + String requestMethod = request.getMethod(); + return !(httpMethod.equalsIgnoreCase(requestMethod) && antPathRequestMatcher.matches(request)); + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/JwtAccessDeniedHandler.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/JwtAccessDeniedHandler.java index fe921bfa..85413c89 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/JwtAccessDeniedHandler.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/JwtAccessDeniedHandler.java @@ -1,36 +1,41 @@ package com.inhabas.api.auth.domain.token; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.inhabas.api.auth.domain.error.ErrorResponse; +import static com.inhabas.api.auth.domain.error.ErrorCode.AUTHORITY_INVALID; + +import java.io.IOException; +import java.io.OutputStream; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + import lombok.extern.slf4j.Slf4j; + import org.springframework.http.MediaType; import org.springframework.security.access.AccessDeniedException; import org.springframework.security.web.access.AccessDeniedHandler; import org.springframework.stereotype.Component; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.io.OutputStream; - -import static com.inhabas.api.auth.domain.error.ErrorCode.AUTHORITY_INVALID; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.inhabas.api.auth.domain.error.ErrorResponse; @Component @Slf4j public class JwtAccessDeniedHandler implements AccessDeniedHandler { - - @Override - public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) - throws IOException, ServletException { - log.error(accessDeniedException.getLocalizedMessage()); - response.setStatus(AUTHORITY_INVALID.getStatus()); - response.setContentType(MediaType.APPLICATION_JSON_VALUE); - try (OutputStream os = response.getOutputStream()) { - ObjectMapper objectMapper = new ObjectMapper(); - objectMapper.writeValue(os, ErrorResponse.of(AUTHORITY_INVALID)); - os.flush(); - } + @Override + public void handle( + HttpServletRequest request, + HttpServletResponse response, + AccessDeniedException accessDeniedException) + throws IOException, ServletException { + log.error(accessDeniedException.getLocalizedMessage()); + response.setStatus(AUTHORITY_INVALID.getStatus()); + response.setContentType(MediaType.APPLICATION_JSON_VALUE); + try (OutputStream os = response.getOutputStream()) { + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.writeValue(os, ErrorResponse.of(AUTHORITY_INVALID)); + os.flush(); } + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/RefreshRequestDto.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/RefreshRequestDto.java index 5fdf1e54..ad039e62 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/RefreshRequestDto.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/RefreshRequestDto.java @@ -5,6 +5,5 @@ @Data public class RefreshRequestDto { - private String refreshToken; - + private String refreshToken; } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/TokenAuthenticationResult.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/TokenAuthenticationResult.java index ce6d6fea..222265a6 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/TokenAuthenticationResult.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/TokenAuthenticationResult.java @@ -1,30 +1,30 @@ package com.inhabas.api.auth.domain.token; +import java.util.Collection; + import org.springframework.security.authentication.AbstractAuthenticationToken; import org.springframework.security.core.GrantedAuthority; -import java.util.Collection; - public abstract class TokenAuthenticationResult extends AbstractAuthenticationToken { - private Object principal; + private Object principal; - /** - * Creates a token with the supplied array of authorities. - * - * @param authorities the collection of GrantedAuthoritys for the principal - * represented by this authentication object. - */ - public TokenAuthenticationResult(Collection authorities) { - super(authorities); - } + /** + * Creates a token with the supplied array of authorities. + * + * @param authorities the collection of GrantedAuthoritys for the principal represented + * by this authentication object. + */ + public TokenAuthenticationResult(Collection authorities) { + super(authorities); + } - @Override - public Object getPrincipal() { - return principal; - } + @Override + public Object getPrincipal() { + return principal; + } - public void setPrincipal(Object principal) { - this.principal = principal; - } + public void setPrincipal(Object principal) { + this.principal = principal; + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/TokenDto.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/TokenDto.java index ecde64d1..2ec88db1 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/TokenDto.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/TokenDto.java @@ -6,16 +6,17 @@ @Getter public class TokenDto { - private final String grantType; - private final String accessToken; - private final String refreshToken; - private final Long expiresIn; + private final String grantType; + private final String accessToken; + private final String refreshToken; + private final Long expiresIn; - @Builder - public TokenDto(String grantType, String accessToken, String refreshToken, Long accessTokenExpireDate) { - this.grantType = grantType; - this.accessToken = accessToken; - this.refreshToken = refreshToken; - this.expiresIn = accessTokenExpireDate; - } + @Builder + public TokenDto( + String grantType, String accessToken, String refreshToken, Long accessTokenExpireDate) { + this.grantType = grantType; + this.accessToken = accessToken; + this.refreshToken = refreshToken; + this.expiresIn = accessTokenExpireDate; + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/TokenReIssuer.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/TokenReIssuer.java index 1ff46708..3bcdbc39 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/TokenReIssuer.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/TokenReIssuer.java @@ -2,10 +2,7 @@ import com.inhabas.api.auth.domain.token.exception.InvalidTokenException; -import javax.servlet.http.HttpServletRequest; - public interface TokenReIssuer { - TokenDto reissueAccessToken(String refreshToken) throws InvalidTokenException; - + TokenDto reissueAccessToken(String refreshToken) throws InvalidTokenException; } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/TokenResolver.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/TokenResolver.java index 6152c18f..bffb1d09 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/TokenResolver.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/TokenResolver.java @@ -4,11 +4,9 @@ public interface TokenResolver { - /** - * - * @param request HttpServletRequest - * @return a resolved token from request header, otherwise null - */ - String resolveAccessTokenOrNull(HttpServletRequest request); - + /** + * @param request HttpServletRequest + * @return a resolved token from request header, otherwise null + */ + String resolveAccessTokenOrNull(HttpServletRequest request); } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/TokenUtil.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/TokenUtil.java index 223e6a4b..a4e02139 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/TokenUtil.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/TokenUtil.java @@ -1,31 +1,33 @@ package com.inhabas.api.auth.domain.token; -import io.jsonwebtoken.JwtException; import org.springframework.security.core.Authentication; +import io.jsonwebtoken.JwtException; + public interface TokenUtil { - void validate(String token); + void validate(String token); - Authentication getAuthentication(String token); + Authentication getAuthentication(String token); - TokenDto reissueAccessTokenUsing(String refreshToken) throws JwtException; + TokenDto reissueAccessTokenUsing(String refreshToken) throws JwtException; - /** - * @param authentication the result of OAuth 2.0 authentication - * @return jwt token string - */ - String createAccessToken(Authentication authentication); + /** + * @param authentication the result of OAuth 2.0 authentication + * @return jwt token string + */ + String createAccessToken(Authentication authentication); - /** - * Some transactions may occur here whenever need to save refresh tokens. - * @param authentication the result of OAuth 2.0 authentication - * @return jwt token string - */ - String createRefreshToken(Authentication authentication); + /** + * Some transactions may occur here whenever need to save refresh tokens. + * + * @param authentication the result of OAuth 2.0 authentication + * @return jwt token string + */ + String createRefreshToken(Authentication authentication); - /** - * @return get {@code expires_in} response parameter value of the access token in seconds - */ - Long getExpiration(); + /** + * @return get {@code expires_in} response parameter value of the access token in seconds + */ + Long getExpiration(); } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/controller/JwtTokenController.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/controller/JwtTokenController.java index 373fe6ea..66d7dc7d 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/controller/JwtTokenController.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/controller/JwtTokenController.java @@ -1,33 +1,37 @@ package com.inhabas.api.auth.domain.token.controller; +import lombok.RequiredArgsConstructor; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + import com.inhabas.api.auth.domain.token.RefreshRequestDto; import com.inhabas.api.auth.domain.token.TokenDto; import com.inhabas.api.auth.domain.token.TokenReIssuer; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; -import lombok.RequiredArgsConstructor; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RestController; @RestController @RequiredArgsConstructor public class JwtTokenController { - private final TokenReIssuer tokenReIssuer; + private final TokenReIssuer tokenReIssuer; - @PostMapping("/token/refresh") - @Operation(summary = "access token 재발급을 요청한다.", description = "request 헤더 Authenticate 에 refreshToken 넣어서 보내줘야함.") - @ApiResponses({ - @ApiResponse(responseCode = "200"), - @ApiResponse(responseCode = "401", description = "유효하지 않은 refreshToken") - }) - public ResponseEntity reissueAccessToken(@RequestBody RefreshRequestDto refreshToken) { + @PostMapping("/token/refresh") + @Operation( + summary = "access token 재발급을 요청한다.", + description = "request 헤더 Authenticate 에 refreshToken 넣어서 보내줘야함.") + @ApiResponses({ + @ApiResponse(responseCode = "200"), + @ApiResponse(responseCode = "401", description = "유효하지 않은 refreshToken") + }) + public ResponseEntity reissueAccessToken(@RequestBody RefreshRequestDto refreshToken) { - TokenDto newAccessToken = tokenReIssuer.reissueAccessToken(refreshToken.getRefreshToken()); + TokenDto newAccessToken = tokenReIssuer.reissueAccessToken(refreshToken.getRefreshToken()); - return ResponseEntity.ok(newAccessToken); - } + return ResponseEntity.ok(newAccessToken); + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/exception/ExpiredTokenException.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/exception/ExpiredTokenException.java index 23858e72..887185b4 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/exception/ExpiredTokenException.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/exception/ExpiredTokenException.java @@ -3,11 +3,9 @@ import com.inhabas.api.auth.domain.error.ErrorCode; import com.inhabas.api.auth.domain.error.authException.CustomAuthException; - public class ExpiredTokenException extends CustomAuthException { - public ExpiredTokenException() { - super(ErrorCode.JWT_EXPIRED); - } - + public ExpiredTokenException() { + super(ErrorCode.JWT_EXPIRED); + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/exception/InvalidTokenException.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/exception/InvalidTokenException.java index 1292c236..66131c1d 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/exception/InvalidTokenException.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/exception/InvalidTokenException.java @@ -3,11 +3,9 @@ import com.inhabas.api.auth.domain.error.ErrorCode; import com.inhabas.api.auth.domain.error.authException.CustomAuthException; - public class InvalidTokenException extends CustomAuthException { - public InvalidTokenException() { - super(ErrorCode.JWT_INVALID); - } - + public InvalidTokenException() { + super(ErrorCode.JWT_INVALID); + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/exception/TokenMissingException.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/exception/TokenMissingException.java index 299b9553..764c66c5 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/exception/TokenMissingException.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/exception/TokenMissingException.java @@ -5,8 +5,7 @@ public class TokenMissingException extends CustomAuthException { - public TokenMissingException() { - super(ErrorCode.JWT_MISSING); - } - -} \ No newline at end of file + public TokenMissingException() { + super(ErrorCode.JWT_MISSING); + } +} diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/jwtUtils/JwtAuthenticationProvider.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/jwtUtils/JwtAuthenticationProvider.java index 86b647e7..f3ecaa03 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/jwtUtils/JwtAuthenticationProvider.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/jwtUtils/JwtAuthenticationProvider.java @@ -2,6 +2,7 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; + import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; @@ -12,18 +13,16 @@ @RequiredArgsConstructor public class JwtAuthenticationProvider implements AuthenticationProvider { - private final JwtTokenUtil jwtTokenUtil; - - @Override - public Authentication authenticate(Authentication authentication) throws AuthenticationException { - final String jwt = (String)authentication.getPrincipal(); - return jwtTokenUtil.getAuthentication(jwt); - - } + private final JwtTokenUtil jwtTokenUtil; - @Override - public boolean supports(Class authentication) { - return JwtAuthenticationToken.class.isAssignableFrom(authentication); - } + @Override + public Authentication authenticate(Authentication authentication) throws AuthenticationException { + final String jwt = (String) authentication.getPrincipal(); + return jwtTokenUtil.getAuthentication(jwt); + } + @Override + public boolean supports(Class authentication) { + return JwtAuthenticationToken.class.isAssignableFrom(authentication); + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/jwtUtils/JwtAuthenticationResult.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/jwtUtils/JwtAuthenticationResult.java index cb622218..9f969b99 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/jwtUtils/JwtAuthenticationResult.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/jwtUtils/JwtAuthenticationResult.java @@ -1,17 +1,22 @@ package com.inhabas.api.auth.domain.token.jwtUtils; -import com.inhabas.api.auth.domain.oauth2.userInfo.OAuth2UserInfoAuthentication; +import java.util.Collection; + import org.springframework.security.core.GrantedAuthority; -import java.util.Collection; +import com.inhabas.api.auth.domain.oauth2.userInfo.OAuth2UserInfoAuthentication; public class JwtAuthenticationResult extends OAuth2UserInfoAuthentication { - private final Long memberId; - - public JwtAuthenticationResult(Long memberId, String uid, String provider, String email, Collection authorities) { - super(uid, provider, email, authorities); - this.memberId = memberId; - } + private final Long memberId; + public JwtAuthenticationResult( + Long memberId, + String uid, + String provider, + String email, + Collection authorities) { + super(uid, provider, email, authorities); + this.memberId = memberId; + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/jwtUtils/JwtAuthenticationToken.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/jwtUtils/JwtAuthenticationToken.java index 68592381..7457529e 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/jwtUtils/JwtAuthenticationToken.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/jwtUtils/JwtAuthenticationToken.java @@ -1,28 +1,27 @@ package com.inhabas.api.auth.domain.token.jwtUtils; +import java.util.Collection; + import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.GrantedAuthority; -import java.util.Collection; - public class JwtAuthenticationToken extends UsernamePasswordAuthenticationToken { - private JwtAuthenticationToken(Object principal, Object credentials, - Collection authorities) { - super(principal, credentials, authorities); - } - - private JwtAuthenticationToken(Object principal, Object credentials) { - super(principal, credentials); - } + private JwtAuthenticationToken( + Object principal, Object credentials, Collection authorities) { + super(principal, credentials, authorities); + } - public static JwtAuthenticationToken of(String jwt) { - return new JwtAuthenticationToken(jwt, jwt); - } + private JwtAuthenticationToken(Object principal, Object credentials) { + super(principal, credentials); + } - public static JwtAuthenticationToken of(Object principal, Object credentials, - Collection authorities) { - return new JwtAuthenticationToken(principal, credentials, authorities); - } + public static JwtAuthenticationToken of(String jwt) { + return new JwtAuthenticationToken(jwt, jwt); + } + public static JwtAuthenticationToken of( + Object principal, Object credentials, Collection authorities) { + return new JwtAuthenticationToken(principal, credentials, authorities); + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/jwtUtils/JwtTokenReIssuer.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/jwtUtils/JwtTokenReIssuer.java index 14c0168a..71e54fdb 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/jwtUtils/JwtTokenReIssuer.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/jwtUtils/JwtTokenReIssuer.java @@ -1,5 +1,7 @@ package com.inhabas.api.auth.domain.token.jwtUtils; +import lombok.RequiredArgsConstructor; + import com.inhabas.api.auth.domain.token.TokenDto; import com.inhabas.api.auth.domain.token.TokenReIssuer; import com.inhabas.api.auth.domain.token.TokenResolver; @@ -7,25 +9,24 @@ import com.inhabas.api.auth.domain.token.exception.InvalidTokenException; import com.inhabas.api.auth.domain.token.jwtUtils.refreshToken.RefreshTokenNotFoundException; import com.inhabas.api.auth.domain.token.jwtUtils.refreshToken.RefreshTokenRepository; -import lombok.RequiredArgsConstructor; @RequiredArgsConstructor public class JwtTokenReIssuer implements TokenReIssuer { - private final TokenUtil tokenUtil; - private final TokenResolver tokenResolver; - private final RefreshTokenRepository refreshTokenRepository; + private final TokenUtil tokenUtil; + private final TokenResolver tokenResolver; + private final RefreshTokenRepository refreshTokenRepository; + @Override + public TokenDto reissueAccessToken(String refreshToken) + throws InvalidTokenException, RefreshTokenNotFoundException { - @Override - public TokenDto reissueAccessToken(String refreshToken) throws InvalidTokenException, RefreshTokenNotFoundException { + tokenUtil.validate(refreshToken); - tokenUtil.validate(refreshToken); - - if (!refreshTokenRepository.existsByRefreshToken(refreshToken)) { - throw new RefreshTokenNotFoundException(); - } - - return tokenUtil.reissueAccessTokenUsing(refreshToken); + if (!refreshTokenRepository.existsByRefreshToken(refreshToken)) { + throw new RefreshTokenNotFoundException(); } + + return tokenUtil.reissueAccessTokenUsing(refreshToken); + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/jwtUtils/JwtTokenResolver.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/jwtUtils/JwtTokenResolver.java index 5a21cf44..e112f30f 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/jwtUtils/JwtTokenResolver.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/jwtUtils/JwtTokenResolver.java @@ -1,23 +1,23 @@ package com.inhabas.api.auth.domain.token.jwtUtils; -import com.inhabas.api.auth.domain.token.TokenResolver; +import javax.servlet.http.HttpServletRequest; + import org.springframework.util.StringUtils; -import javax.servlet.http.HttpServletRequest; +import com.inhabas.api.auth.domain.token.TokenResolver; public class JwtTokenResolver implements TokenResolver { - private static final String AUTHORIZATION_HEADER = "Authorization"; - private static final String AUTHORIZATION_TYPE = "Bearer "; + private static final String AUTHORIZATION_HEADER = "Authorization"; + private static final String AUTHORIZATION_TYPE = "Bearer "; - @Override - public String resolveAccessTokenOrNull(HttpServletRequest request) { + @Override + public String resolveAccessTokenOrNull(HttpServletRequest request) { - String bearerToken = request.getHeader(AUTHORIZATION_HEADER); + String bearerToken = request.getHeader(AUTHORIZATION_HEADER); - if (StringUtils.hasText(bearerToken) && bearerToken.startsWith(AUTHORIZATION_TYPE)) - return bearerToken.substring(7); - else - return null; - } + if (StringUtils.hasText(bearerToken) && bearerToken.startsWith(AUTHORIZATION_TYPE)) + return bearerToken.substring(7); + else return null; + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/jwtUtils/JwtTokenUtil.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/jwtUtils/JwtTokenUtil.java index 3583caf5..021dcc7c 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/jwtUtils/JwtTokenUtil.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/jwtUtils/JwtTokenUtil.java @@ -1,5 +1,20 @@ package com.inhabas.api.auth.domain.token.jwtUtils; +import java.security.Key; +import java.util.Date; +import java.util.List; +import java.util.stream.Collectors; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken; +import org.springframework.stereotype.Component; + import com.inhabas.api.auth.domain.oauth2.CustomOAuth2User; import com.inhabas.api.auth.domain.oauth2.userInfo.OAuth2UserInfo; import com.inhabas.api.auth.domain.oauth2.userInfo.OAuth2UserInfoFactory; @@ -13,19 +28,6 @@ import io.jsonwebtoken.io.Decoders; import io.jsonwebtoken.security.Keys; import io.jsonwebtoken.security.SignatureException; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.authority.SimpleGrantedAuthority; -import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken; -import org.springframework.stereotype.Component; - -import java.security.Key; -import java.util.Date; -import java.util.List; -import java.util.stream.Collectors; // https://github.com/jwtk/jjwt @Slf4j @@ -33,155 +35,152 @@ @RequiredArgsConstructor public class JwtTokenUtil implements TokenUtil { - private final RefreshTokenRepository refreshTokenRepository; - - @Value("${jwt.secretKey}") - private String SECRET_KEY; - private final Long ACCESS_TOKEN_VALID_MILLISECOND = 30 * 60 * 1000L; // 0.5 hour - private static final Long REFRESH_TOKEN_VALID_MILLI_SECOND = 7 * 24 * 60 * 60 * 1000L; // 7 days - private static final String PROVIDER = "provider"; - private static final String AUTHORITY = "authorities"; - private static final String EMAIL = "email"; - private static final String MEMBER_ID = "memberId"; - - - @Override - public String createAccessToken(Authentication authentication) { - - return createToken(authentication, ACCESS_TOKEN_VALID_MILLISECOND); - } - - - @Override - public String createRefreshToken(Authentication authentication) { - - String token = this.createToken(authentication, REFRESH_TOKEN_VALID_MILLI_SECOND); - refreshTokenRepository.save(new RefreshToken(token)); - return token; - } - - - @Override - public Long getExpiration() { - return this.ACCESS_TOKEN_VALID_MILLISECOND / 1000; - } - - - private String createToken(Authentication authentication, Long expiration) { - - assert authentication != null; - - OAuth2UserInfo oAuth2UserInfo = OAuth2UserInfoFactory.getOAuth2UserInfo((OAuth2AuthenticationToken) authentication); - String provider = oAuth2UserInfo.getProvider().toString(); - String uid = oAuth2UserInfo.getId(); - String email = oAuth2UserInfo.getEmail(); - - CustomOAuth2User customOAuth2User = (CustomOAuth2User) authentication.getPrincipal(); - Long memberId = customOAuth2User.getMemberId(); - - List authorities = authentication.getAuthorities() - .stream() - .map(GrantedAuthority::getAuthority) - .collect(Collectors.toList()); - - Date now = new Date(); - Date expiryDate = new Date(now.getTime() + expiration); - final Key key = Keys.hmacShaKeyFor(Decoders.BASE64.decode(SECRET_KEY)); - - return Jwts.builder() - .setHeaderParam(Header.TYPE, Header.JWT_TYPE) - .setSubject(uid) - .claim(MEMBER_ID, memberId) - .claim(PROVIDER, provider) - .claim(EMAIL, email) - .claim(AUTHORITY, authorities) - .setIssuedAt(now) - .setExpiration(expiryDate) - .signWith(key, SignatureAlgorithm.HS512) - .compact(); - } - - - @Override - public void validate(String token) { - - try { - Jwts.parserBuilder().setSigningKey(SECRET_KEY).build().parseClaimsJws(token); - } catch (SecurityException ex) { - log.error("Invalid JWT signature"); - throw new InvalidTokenException(); - } catch (MalformedJwtException ex) { - log.error("Invalid JWT token"); - throw new InvalidTokenException(); - } catch (ExpiredJwtException ex) { - log.error("Expired JWT token"); - throw new ExpiredTokenException(); - } catch (UnsupportedJwtException ex) { - log.error("Unsupported JWT token"); - throw new InvalidTokenException(); - } catch (SignatureException ex) { - log.error("JWT signature does not match"); - throw new InvalidTokenException(); - } catch (IllegalArgumentException ex) { - log.error("JWT claims string is empty."); - throw new InvalidTokenException(); - } + private final RefreshTokenRepository refreshTokenRepository; + + @Value("${jwt.secretKey}") + private String SECRET_KEY; + + private final Long ACCESS_TOKEN_VALID_MILLISECOND = 30 * 60 * 1000L; // 0.5 hour + private static final Long REFRESH_TOKEN_VALID_MILLI_SECOND = 7 * 24 * 60 * 60 * 1000L; // 7 days + private static final String PROVIDER = "provider"; + private static final String AUTHORITY = "authorities"; + private static final String EMAIL = "email"; + private static final String MEMBER_ID = "memberId"; + + @Override + public String createAccessToken(Authentication authentication) { + + return createToken(authentication, ACCESS_TOKEN_VALID_MILLISECOND); + } + + @Override + public String createRefreshToken(Authentication authentication) { + + String token = this.createToken(authentication, REFRESH_TOKEN_VALID_MILLI_SECOND); + refreshTokenRepository.save(new RefreshToken(token)); + return token; + } + + @Override + public Long getExpiration() { + return this.ACCESS_TOKEN_VALID_MILLISECOND / 1000; + } + + private String createToken(Authentication authentication, Long expiration) { + + assert authentication != null; + + OAuth2UserInfo oAuth2UserInfo = + OAuth2UserInfoFactory.getOAuth2UserInfo((OAuth2AuthenticationToken) authentication); + String provider = oAuth2UserInfo.getProvider().toString(); + String uid = oAuth2UserInfo.getId(); + String email = oAuth2UserInfo.getEmail(); + + CustomOAuth2User customOAuth2User = (CustomOAuth2User) authentication.getPrincipal(); + Long memberId = customOAuth2User.getMemberId(); + + List authorities = + authentication.getAuthorities().stream() + .map(GrantedAuthority::getAuthority) + .collect(Collectors.toList()); + + Date now = new Date(); + Date expiryDate = new Date(now.getTime() + expiration); + final Key key = Keys.hmacShaKeyFor(Decoders.BASE64.decode(SECRET_KEY)); + + return Jwts.builder() + .setHeaderParam(Header.TYPE, Header.JWT_TYPE) + .setSubject(uid) + .claim(MEMBER_ID, memberId) + .claim(PROVIDER, provider) + .claim(EMAIL, email) + .claim(AUTHORITY, authorities) + .setIssuedAt(now) + .setExpiration(expiryDate) + .signWith(key, SignatureAlgorithm.HS512) + .compact(); + } + + @Override + public void validate(String token) { + + try { + Jwts.parserBuilder().setSigningKey(SECRET_KEY).build().parseClaimsJws(token); + } catch (SecurityException ex) { + log.error("Invalid JWT signature"); + throw new InvalidTokenException(); + } catch (MalformedJwtException ex) { + log.error("Invalid JWT token"); + throw new InvalidTokenException(); + } catch (ExpiredJwtException ex) { + log.error("Expired JWT token"); + throw new ExpiredTokenException(); + } catch (UnsupportedJwtException ex) { + log.error("Unsupported JWT token"); + throw new InvalidTokenException(); + } catch (SignatureException ex) { + log.error("JWT signature does not match"); + throw new InvalidTokenException(); + } catch (IllegalArgumentException ex) { + log.error("JWT claims string is empty."); + throw new InvalidTokenException(); } + } - /* web request 에 대한 인증 정보를 반환함. */ - @Override - public JwtAuthenticationToken getAuthentication(String token) throws JwtException { - - Claims claims = this.parseClaims(token); + /* web request 에 대한 인증 정보를 반환함. */ + @Override + public JwtAuthenticationToken getAuthentication(String token) throws JwtException { - Long memberId = claims.get(MEMBER_ID, Long.class); - List rawAuthorities = claims.get(AUTHORITY, List.class); + Claims claims = this.parseClaims(token); - List grantedAuthorities = rawAuthorities.stream() - .filter(authority -> authority instanceof String) - .map(authority -> new SimpleGrantedAuthority((String) authority)) - .collect(Collectors.toList()); + Long memberId = claims.get(MEMBER_ID, Long.class); + List rawAuthorities = claims.get(AUTHORITY, List.class); - return JwtAuthenticationToken.of(memberId, token, grantedAuthorities); - } + List grantedAuthorities = + rawAuthorities.stream() + .filter(authority -> authority instanceof String) + .map(authority -> new SimpleGrantedAuthority((String) authority)) + .collect(Collectors.toList()); + return JwtAuthenticationToken.of(memberId, token, grantedAuthorities); + } - /* 토큰 body 에 넣어둔 사용자 정보를 가져옴 - * validation 검사를 먼저 꼭 해야함! */ - private Claims parseClaims(String token) throws JwtException { - return Jwts.parserBuilder().setSigningKey(SECRET_KEY).build().parseClaimsJws(token).getBody(); - } + /* 토큰 body 에 넣어둔 사용자 정보를 가져옴 + * validation 검사를 먼저 꼭 해야함! */ + private Claims parseClaims(String token) throws JwtException { + return Jwts.parserBuilder().setSigningKey(SECRET_KEY).build().parseClaimsJws(token).getBody(); + } - @Override - public TokenDto reissueAccessTokenUsing(String refreshToken) throws InvalidTokenException { - - try { - Claims claims = this.parseClaims(refreshToken); - return this.createAccessTokenOnly(claims); - - } catch (JwtException e) { - throw new InvalidTokenException(); - } - } + @Override + public TokenDto reissueAccessTokenUsing(String refreshToken) throws InvalidTokenException { + try { + Claims claims = this.parseClaims(refreshToken); + return this.createAccessTokenOnly(claims); - private TokenDto createAccessTokenOnly(Claims claims) { - Date now = new Date(); - final Key key = Keys.hmacShaKeyFor(Decoders.BASE64.decode(SECRET_KEY)); - - String accessToken = Jwts.builder() - .setHeaderParam(Header.TYPE, Header.JWT_TYPE) - .setClaims(claims) - .setIssuedAt(now) - .setExpiration(new Date(now.getTime() + ACCESS_TOKEN_VALID_MILLISECOND)) - .signWith(key, SignatureAlgorithm.HS512) - .compact(); - - return TokenDto.builder() - .grantType("Bearer") - .accessToken(accessToken) - .refreshToken("") - .accessTokenExpireDate(ACCESS_TOKEN_VALID_MILLISECOND) - .build(); + } catch (JwtException e) { + throw new InvalidTokenException(); } + } + + private TokenDto createAccessTokenOnly(Claims claims) { + Date now = new Date(); + final Key key = Keys.hmacShaKeyFor(Decoders.BASE64.decode(SECRET_KEY)); + + String accessToken = + Jwts.builder() + .setHeaderParam(Header.TYPE, Header.JWT_TYPE) + .setClaims(claims) + .setIssuedAt(now) + .setExpiration(new Date(now.getTime() + ACCESS_TOKEN_VALID_MILLISECOND)) + .signWith(key, SignatureAlgorithm.HS512) + .compact(); + + return TokenDto.builder() + .grantType("Bearer") + .accessToken(accessToken) + .refreshToken("") + .accessTokenExpireDate(ACCESS_TOKEN_VALID_MILLISECOND) + .build(); + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/jwtUtils/refreshToken/RefreshToken.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/jwtUtils/refreshToken/RefreshToken.java index b0b164dd..81259f68 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/jwtUtils/refreshToken/RefreshToken.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/jwtUtils/refreshToken/RefreshToken.java @@ -1,26 +1,29 @@ package com.inhabas.api.auth.domain.token.jwtUtils.refreshToken; import java.time.LocalDateTime; + import javax.persistence.*; import lombok.AccessLevel; import lombok.Getter; import lombok.NoArgsConstructor; -@Entity @Getter +@Entity +@Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) public class RefreshToken { - @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; - @Column(columnDefinition = "TEXT") - private String refreshToken; + @Column(columnDefinition = "TEXT") + private String refreshToken; - private LocalDateTime created; + private LocalDateTime created; - public RefreshToken(String refreshToken) { - this.refreshToken = refreshToken; - this.created = LocalDateTime.now(); - } + public RefreshToken(String refreshToken) { + this.refreshToken = refreshToken; + this.created = LocalDateTime.now(); + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/jwtUtils/refreshToken/RefreshTokenNotFoundException.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/jwtUtils/refreshToken/RefreshTokenNotFoundException.java index ad3f9b5c..9079606e 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/jwtUtils/refreshToken/RefreshTokenNotFoundException.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/jwtUtils/refreshToken/RefreshTokenNotFoundException.java @@ -1,13 +1,13 @@ package com.inhabas.api.auth.domain.token.jwtUtils.refreshToken; public class RefreshTokenNotFoundException extends RuntimeException { - private static final String defaultMessage = "Cannot found such refreshToken!!"; + private static final String defaultMessage = "Cannot found such refreshToken!!"; - public RefreshTokenNotFoundException() { - super(defaultMessage); - } + public RefreshTokenNotFoundException() { + super(defaultMessage); + } - public RefreshTokenNotFoundException(String message) { - super(message); - } + public RefreshTokenNotFoundException(String message) { + super(message); + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/jwtUtils/refreshToken/RefreshTokenRepository.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/jwtUtils/refreshToken/RefreshTokenRepository.java index 3ccebbe2..3a5687c7 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/jwtUtils/refreshToken/RefreshTokenRepository.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/jwtUtils/refreshToken/RefreshTokenRepository.java @@ -4,6 +4,5 @@ public interface RefreshTokenRepository extends JpaRepository { - boolean existsByRefreshToken(String refreshToken); - + boolean existsByRefreshToken(String refreshToken); } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/securityFilter/DefaultUserPrincipalService.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/securityFilter/DefaultUserPrincipalService.java index e18382bb..57a00c30 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/securityFilter/DefaultUserPrincipalService.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/securityFilter/DefaultUserPrincipalService.java @@ -4,8 +4,8 @@ public class DefaultUserPrincipalService implements UserPrincipalService { - @Override - public Object loadUserPrincipal(Authentication authentication) { - return null; - } + @Override + public Object loadUserPrincipal(Authentication authentication) { + return null; + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/securityFilter/InvalidJwtTokenHandler.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/securityFilter/InvalidJwtTokenHandler.java index 1f1c4dba..6bbd92e2 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/securityFilter/InvalidJwtTokenHandler.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/securityFilter/InvalidJwtTokenHandler.java @@ -4,16 +4,17 @@ public class InvalidJwtTokenHandler extends TokenAuthenticationFailureHandler { - /** - * Performs the redirect or forward to the {@code defaultFailureUrl} if set, otherwise - * returns a 401 error code. - *

- * If redirecting or forwarding, {@code saveException} will be called to cache the - * exception for use in the target view. - * @see SimpleUrlAuthenticationFailureHandler - */ - public InvalidJwtTokenHandler() { - super(); - setAllowSessionCreation(false); - } + /** + * Performs the redirect or forward to the {@code defaultFailureUrl} if set, otherwise returns a + * 401 error code. + * + *

If redirecting or forwarding, {@code saveException} will be called to cache the exception + * for use in the target view. + * + * @see SimpleUrlAuthenticationFailureHandler + */ + public InvalidJwtTokenHandler() { + super(); + setAllowSessionCreation(false); + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/securityFilter/JwtAuthenticationEntryPoint.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/securityFilter/JwtAuthenticationEntryPoint.java index 2748d14c..72bf2b92 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/securityFilter/JwtAuthenticationEntryPoint.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/securityFilter/JwtAuthenticationEntryPoint.java @@ -1,36 +1,42 @@ package com.inhabas.api.auth.domain.token.securityFilter; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.inhabas.api.auth.domain.error.ErrorResponse; +import static com.inhabas.api.auth.domain.error.ErrorCode.AUTHORITY_INVALID; + +import java.io.IOException; +import java.io.OutputStream; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + import lombok.extern.slf4j.Slf4j; + import org.springframework.http.MediaType; import org.springframework.security.core.AuthenticationException; import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.stereotype.Component; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.io.OutputStream; - -import static com.inhabas.api.auth.domain.error.ErrorCode.AUTHORITY_INVALID; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.inhabas.api.auth.domain.error.ErrorResponse; @Component @Slf4j public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint { - @Override - public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException { - - log.error("Unexpected JWT error"); - response.setStatus(AUTHORITY_INVALID.getStatus()); - response.setContentType(MediaType.APPLICATION_JSON_VALUE); - try (OutputStream os = response.getOutputStream()) { - ObjectMapper objectMapper = new ObjectMapper(); - objectMapper.writeValue(os, ErrorResponse.of(AUTHORITY_INVALID)); - os.flush(); - } + @Override + public void commence( + HttpServletRequest request, + HttpServletResponse response, + AuthenticationException authException) + throws IOException, ServletException { + log.error("Unexpected JWT error"); + response.setStatus(AUTHORITY_INVALID.getStatus()); + response.setContentType(MediaType.APPLICATION_JSON_VALUE); + try (OutputStream os = response.getOutputStream()) { + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.writeValue(os, ErrorResponse.of(AUTHORITY_INVALID)); + os.flush(); } + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/securityFilter/JwtAuthenticationFilter.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/securityFilter/JwtAuthenticationFilter.java index 9f8a0cc7..dae574bb 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/securityFilter/JwtAuthenticationFilter.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/securityFilter/JwtAuthenticationFilter.java @@ -1,12 +1,18 @@ package com.inhabas.api.auth.domain.token.securityFilter; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.inhabas.api.auth.domain.error.ErrorResponse; -import com.inhabas.api.auth.domain.error.authException.CustomAuthException; -import com.inhabas.api.auth.domain.token.TokenResolver; -import com.inhabas.api.auth.domain.token.jwtUtils.JwtAuthenticationToken; -import com.inhabas.api.auth.domain.token.jwtUtils.JwtTokenUtil; +import static com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.Role.ANONYMOUS; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.Collections; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + import lombok.extern.slf4j.Slf4j; + import org.springframework.http.MediaType; import org.springframework.security.authentication.AnonymousAuthenticationToken; import org.springframework.security.core.Authentication; @@ -16,73 +22,73 @@ import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter; import org.springframework.security.web.util.matcher.RequestMatcher; -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.io.OutputStream; -import java.util.Collections; - -import static com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.Role.ANONYMOUS; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.inhabas.api.auth.domain.error.ErrorResponse; +import com.inhabas.api.auth.domain.error.authException.CustomAuthException; +import com.inhabas.api.auth.domain.token.TokenResolver; +import com.inhabas.api.auth.domain.token.jwtUtils.JwtAuthenticationToken; +import com.inhabas.api.auth.domain.token.jwtUtils.JwtTokenUtil; @Slf4j public class JwtAuthenticationFilter extends AbstractAuthenticationProcessingFilter { - private final JwtTokenUtil jwtTokenUtil; - private final TokenResolver tokenResolver; - private static final String ROLE_PREFIX = "ROLE_"; + private final JwtTokenUtil jwtTokenUtil; + private final TokenResolver tokenResolver; + private static final String ROLE_PREFIX = "ROLE_"; - - public JwtAuthenticationFilter( - RequestMatcher requestMatcher, - JwtTokenUtil jwtTokenUtil, - TokenResolver tokenResolver) { + public JwtAuthenticationFilter( + RequestMatcher requestMatcher, JwtTokenUtil jwtTokenUtil, TokenResolver tokenResolver) { - super(requestMatcher); // only work for requests with this pattern - this.jwtTokenUtil = jwtTokenUtil; - this.tokenResolver = tokenResolver; - } + super(requestMatcher); // only work for requests with this pattern + this.jwtTokenUtil = jwtTokenUtil; + this.tokenResolver = tokenResolver; + } - @Override - public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) - throws AuthenticationException, IOException, ServletException { - - final String token = tokenResolver.resolveAccessTokenOrNull(request); - - if (token != null) { - jwtTokenUtil.validate(token); - final JwtAuthenticationToken authRequest = JwtAuthenticationToken.of(token); - return this.getAuthenticationManager().authenticate(authRequest); - } else { - log.info("Anonymous user request"); - return new AnonymousAuthenticationToken("anonymous", this.hashCode(), - Collections.singleton(new SimpleGrantedAuthority(ROLE_PREFIX + ANONYMOUS))); - } - } + @Override + public Authentication attemptAuthentication( + HttpServletRequest request, HttpServletResponse response) + throws AuthenticationException, IOException, ServletException { - @Override - protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, - Authentication authResult) throws IOException, ServletException { - SecurityContextHolder.getContext().setAuthentication(authResult); - log.debug("jwt token authentication success!"); + final String token = tokenResolver.resolveAccessTokenOrNull(request); - chain.doFilter(request, response); + if (token != null) { + jwtTokenUtil.validate(token); + final JwtAuthenticationToken authRequest = JwtAuthenticationToken.of(token); + return this.getAuthenticationManager().authenticate(authRequest); + } else { + log.info("Anonymous user request"); + return new AnonymousAuthenticationToken( + "anonymous", + this.hashCode(), + Collections.singleton(new SimpleGrantedAuthority(ROLE_PREFIX + ANONYMOUS))); } + } - @Override - protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, - AuthenticationException failed) throws IOException, ServletException { - SecurityContextHolder.clearContext(); - log.info("Failed to process authentication request", failed); - response.setStatus(((CustomAuthException)failed).getErrorCode().getStatus()); - response.setContentType(MediaType.APPLICATION_JSON_VALUE); - try (OutputStream os = response.getOutputStream()) { - ObjectMapper objectMapper = new ObjectMapper(); - objectMapper.writeValue(os, ErrorResponse.of(((CustomAuthException)failed).getErrorCode())); - os.flush(); - } + @Override + protected void successfulAuthentication( + HttpServletRequest request, + HttpServletResponse response, + FilterChain chain, + Authentication authResult) + throws IOException, ServletException { + SecurityContextHolder.getContext().setAuthentication(authResult); + log.debug("jwt token authentication success!"); - } + chain.doFilter(request, response); + } + @Override + protected void unsuccessfulAuthentication( + HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) + throws IOException, ServletException { + SecurityContextHolder.clearContext(); + log.info("Failed to process authentication request", failed); + response.setStatus(((CustomAuthException) failed).getErrorCode().getStatus()); + response.setContentType(MediaType.APPLICATION_JSON_VALUE); + try (OutputStream os = response.getOutputStream()) { + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.writeValue(os, ErrorResponse.of(((CustomAuthException) failed).getErrorCode())); + os.flush(); + } + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/securityFilter/SocialNotFoundException.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/securityFilter/SocialNotFoundException.java index e4729815..7f0401c3 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/securityFilter/SocialNotFoundException.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/securityFilter/SocialNotFoundException.java @@ -1,11 +1,11 @@ package com.inhabas.api.auth.domain.token.securityFilter; -import com.inhabas.api.auth.domain.error.authException.CustomAuthException; import com.inhabas.api.auth.domain.error.ErrorCode; +import com.inhabas.api.auth.domain.error.authException.CustomAuthException; public class SocialNotFoundException extends CustomAuthException { - public SocialNotFoundException() { - super(ErrorCode.SOCIAL_NOT_FOUND); - } + public SocialNotFoundException() { + super(ErrorCode.SOCIAL_NOT_FOUND); + } } diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/securityFilter/TokenAuthenticationFailureHandler.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/securityFilter/TokenAuthenticationFailureHandler.java index 8850982f..28305db2 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/securityFilter/TokenAuthenticationFailureHandler.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/securityFilter/TokenAuthenticationFailureHandler.java @@ -2,6 +2,5 @@ import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler; -public abstract class TokenAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler { - -} +public abstract class TokenAuthenticationFailureHandler + extends SimpleUrlAuthenticationFailureHandler {} diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/securityFilter/UserPrincipalService.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/securityFilter/UserPrincipalService.java index 752f24e1..f95d0ab1 100644 --- a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/securityFilter/UserPrincipalService.java +++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/securityFilter/UserPrincipalService.java @@ -3,13 +3,11 @@ import org.springframework.security.core.Authentication; /** - * 인증 과정에서 얻은 사용자 정보를 바탕으로, 기존에 db에 저장되어 있는 사용자 정보를 얻어오도록 한다. - * spring security 에서 principal 에 해당하는 객체를 반환하도록 한다. - * 구현은 이 패키지를 사용하는 하위 종속 모듈에 맡긴다. - * 따로 이 인터페이스를 구현하지 않으면 {@code DefaultUserPrincipalService} 가 기본으로 설정되는데 - * 단순히 null 을 반환한다. + * 인증 과정에서 얻은 사용자 정보를 바탕으로, 기존에 db에 저장되어 있는 사용자 정보를 얻어오도록 한다. spring security 에서 principal 에 해당하는 + * 객체를 반환하도록 한다. 구현은 이 패키지를 사용하는 하위 종속 모듈에 맡긴다. 따로 이 인터페이스를 구현하지 않으면 {@code + * DefaultUserPrincipalService} 가 기본으로 설정되는데 단순히 null 을 반환한다. */ public interface UserPrincipalService { - Object loadUserPrincipal(S authentication); + Object loadUserPrincipal(S authentication); } diff --git a/module-auth/src/test/java/com/inhabas/api/auth/TestApplication.java b/module-auth/src/test/java/com/inhabas/api/auth/TestApplication.java index 7ba34a29..cd2668fa 100644 --- a/module-auth/src/test/java/com/inhabas/api/auth/TestApplication.java +++ b/module-auth/src/test/java/com/inhabas/api/auth/TestApplication.java @@ -6,8 +6,7 @@ @SpringBootApplication public class TestApplication { - public static void main(String[] args) { - SpringApplication.run(TestApplication.class, args); - } + public static void main(String[] args) { + SpringApplication.run(TestApplication.class, args); + } } - diff --git a/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/OAuth2ProviderTest.java b/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/OAuth2ProviderTest.java index 9c33933b..1eb053fe 100644 --- a/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/OAuth2ProviderTest.java +++ b/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/OAuth2ProviderTest.java @@ -1,29 +1,31 @@ package com.inhabas.api.auth.domain.oauth2; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; +import static org.assertj.core.api.Assertions.assertThat; import java.util.Arrays; -import static org.assertj.core.api.Assertions.assertThat; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; public class OAuth2ProviderTest { - @DisplayName("Provider 길이는 30자 초과하면 안된다.") - @Test - public void ProviderLengthMustNotBeGreaterThan30() { - assertThat( + @DisplayName("Provider 길이는 30자 초과하면 안된다.") + @Test + public void ProviderLengthMustNotBeGreaterThan30() { + assertThat( Arrays.stream(OAuth2Provider.values()) - .filter(provider -> provider.toString().length() > 30) - .findAny()).isEmpty(); - } + .filter(provider -> provider.toString().length() > 30) + .findAny()) + .isEmpty(); + } - @DisplayName("Provider 값이 blank 값이면 안된다.") - @Test - public void ProviderValueMustNotBeBlank() { - assertThat( - Arrays.stream(OAuth2Provider.values()) - .filter(provider -> provider.toString().isBlank()) - .findAny()).isEmpty(); - } + @DisplayName("Provider 값이 blank 값이면 안된다.") + @Test + public void ProviderValueMustNotBeBlank() { + assertThat( + Arrays.stream(OAuth2Provider.values()) + .filter(provider -> provider.toString().isBlank()) + .findAny()) + .isEmpty(); + } } diff --git a/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/cookie/CookieUtilsTest.java b/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/cookie/CookieUtilsTest.java index ee985b46..31af7b3b 100644 --- a/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/cookie/CookieUtilsTest.java +++ b/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/cookie/CookieUtilsTest.java @@ -1,141 +1,153 @@ package com.inhabas.api.auth.domain.oauth2.cookie; -import org.apache.commons.codec.binary.Base64; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.mock.web.MockHttpServletRequest; -import org.springframework.mock.web.MockHttpServletResponse; -import org.springframework.security.oauth2.core.AuthorizationGrantType; -import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertTrue; -import javax.servlet.http.Cookie; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.util.Optional; import java.util.Set; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertTrue; +import javax.servlet.http.Cookie; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; +import org.springframework.security.oauth2.core.AuthorizationGrantType; +import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest; + +import org.apache.commons.codec.binary.Base64; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; public class CookieUtilsTest { - @DisplayName("request 에서 쿠키를 꺼낸다.") - @Test - public void resolveCookieFromRequest() { - //given - MockHttpServletRequest request = new MockHttpServletRequest(); - Cookie cookie = new Cookie("myCookie", "hello"); - cookie.setMaxAge(180); - request.setCookies(cookie); - - //when - Optional myCookie = CookieUtils.resolveCookie(request, "myCookie"); - - //then - assertThat(myCookie.isPresent()).isTrue(); - assertThat(myCookie.get().getValue()).isEqualTo("hello"); - assertThat(myCookie.get().getMaxAge()).isEqualTo(180); - - } - - @DisplayName("response 에 쿠키를 저장한다.") - @Test - public void saveCookieToResponse() { - //given - MockHttpServletResponse response = new MockHttpServletResponse(); - String cookieName = "myCookie"; - String cookieContents = "hello"; - - //when - CookieUtils.setCookie(response, cookieName, cookieContents, 180); - - //then - Cookie resolvedCookie = response.getCookie(cookieName); - assert resolvedCookie != null; - - assertThat(resolvedCookie.getName()).isEqualTo(cookieName); - assertThat(resolvedCookie.getValue()).isEqualTo(cookieContents); - assertThat(resolvedCookie.getMaxAge()).isEqualTo(180); - } - - @DisplayName("request 에서 쿠키를 지운다.") - @Test - public void removeCookieOfRequest() { - //given - MockHttpServletResponse response = new MockHttpServletResponse(); - MockHttpServletRequest request = new MockHttpServletRequest(); - Cookie cookie = new Cookie("myCookie", "hello"); - cookie.setMaxAge(180); - request.setCookies(cookie); - - //when - CookieUtils.deleteCookie(request, response, "myCookie"); - - //then - Cookie deletedCookie = response.getCookie("myCookie"); - assert deletedCookie != null; - assertThat(deletedCookie.getMaxAge()).isEqualTo(0); - assertThat(deletedCookie.getValue()).isEqualTo(""); - } - - @DisplayName("성공적으로 serialize 한다.") - @Test - public void serializingTest() throws InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchMethodException { - //reflection - Constructor constructor = - OAuth2AuthorizationRequest.Builder.class.getDeclaredConstructor(AuthorizationGrantType.class); - constructor.setAccessible(true); - - //given - OAuth2AuthorizationRequest.Builder builder = - (OAuth2AuthorizationRequest.Builder) constructor.newInstance(AuthorizationGrantType.AUTHORIZATION_CODE); - OAuth2AuthorizationRequest request = builder.authorizationUri("https://kauth.kakao.com/oauth/authorize") - .clientId("1234") - .redirectUri("http://localhost/api/login/oauth2/code/kakao") - .scopes(Set.of("gender", "profile_image", "account_email", "profile_nickname")) - .state("state1934") - .additionalParameters(java.util.Map.of()) - .attributes(java.util.Map.of("registration_id", "kakao")).build(); - - //when - String serializedRequest = CookieUtils.serialize(request); - - //then - assertTrue(Base64.isBase64(serializedRequest)); - } - - @DisplayName("성공적으로 deserialize 한다.") - @Test - public void deserializingTest() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException { - - //reflection - Constructor constructor = - OAuth2AuthorizationRequest.Builder.class.getDeclaredConstructor(AuthorizationGrantType.class); - constructor.setAccessible(true); - - //given - OAuth2AuthorizationRequest.Builder builder = - (OAuth2AuthorizationRequest.Builder) constructor.newInstance(AuthorizationGrantType.AUTHORIZATION_CODE); - OAuth2AuthorizationRequest originalRequest = builder.authorizationUri("https://kauth.kakao.com/oauth/authorize") - .clientId("1234") - .redirectUri("http://localhost/api/login/oauth2/code/kakao") - .scopes(Set.of("gender", "profile_image", "account_email", "profile_nickname")) - .state("state1934") - .additionalParameters(java.util.Map.of()) - .attributes(java.util.Map.of("registration_id", "kakao")).build(); - - String serializedRequest = CookieUtils.serialize(originalRequest); - Cookie cookie = new Cookie("base64", serializedRequest); - - //when - OAuth2AuthorizationRequest deserializedRequest = - CookieUtils.deserialize(cookie, OAuth2AuthorizationRequest.class); - - //then - assertThat(deserializedRequest) - .usingRecursiveComparison() - .isEqualTo(originalRequest); - - } + @DisplayName("request 에서 쿠키를 꺼낸다.") + @Test + public void resolveCookieFromRequest() { + // given + MockHttpServletRequest request = new MockHttpServletRequest(); + Cookie cookie = new Cookie("myCookie", "hello"); + cookie.setMaxAge(180); + request.setCookies(cookie); + + // when + Optional myCookie = CookieUtils.resolveCookie(request, "myCookie"); + + // then + assertThat(myCookie.isPresent()).isTrue(); + assertThat(myCookie.get().getValue()).isEqualTo("hello"); + assertThat(myCookie.get().getMaxAge()).isEqualTo(180); + } + + @DisplayName("response 에 쿠키를 저장한다.") + @Test + public void saveCookieToResponse() { + // given + MockHttpServletResponse response = new MockHttpServletResponse(); + String cookieName = "myCookie"; + String cookieContents = "hello"; + + // when + CookieUtils.setCookie(response, cookieName, cookieContents, 180); + + // then + Cookie resolvedCookie = response.getCookie(cookieName); + assert resolvedCookie != null; + + assertThat(resolvedCookie.getName()).isEqualTo(cookieName); + assertThat(resolvedCookie.getValue()).isEqualTo(cookieContents); + assertThat(resolvedCookie.getMaxAge()).isEqualTo(180); + } + + @DisplayName("request 에서 쿠키를 지운다.") + @Test + public void removeCookieOfRequest() { + // given + MockHttpServletResponse response = new MockHttpServletResponse(); + MockHttpServletRequest request = new MockHttpServletRequest(); + Cookie cookie = new Cookie("myCookie", "hello"); + cookie.setMaxAge(180); + request.setCookies(cookie); + + // when + CookieUtils.deleteCookie(request, response, "myCookie"); + + // then + Cookie deletedCookie = response.getCookie("myCookie"); + assert deletedCookie != null; + assertThat(deletedCookie.getMaxAge()).isEqualTo(0); + assertThat(deletedCookie.getValue()).isEqualTo(""); + } + + @DisplayName("성공적으로 serialize 한다.") + @Test + public void serializingTest() + throws InvocationTargetException, InstantiationException, IllegalAccessException, + NoSuchMethodException { + // reflection + Constructor constructor = + OAuth2AuthorizationRequest.Builder.class.getDeclaredConstructor( + AuthorizationGrantType.class); + constructor.setAccessible(true); + + // given + OAuth2AuthorizationRequest.Builder builder = + (OAuth2AuthorizationRequest.Builder) + constructor.newInstance(AuthorizationGrantType.AUTHORIZATION_CODE); + OAuth2AuthorizationRequest request = + builder + .authorizationUri("https://kauth.kakao.com/oauth/authorize") + .clientId("1234") + .redirectUri("http://localhost/api/login/oauth2/code/kakao") + .scopes(Set.of("gender", "profile_image", "account_email", "profile_nickname")) + .state("state1934") + .additionalParameters(java.util.Map.of()) + .attributes(java.util.Map.of("registration_id", "kakao")) + .build(); + + // when + String serializedRequest = CookieUtils.serialize(request); + + // then + assertTrue(Base64.isBase64(serializedRequest)); + } + + @DisplayName("성공적으로 deserialize 한다.") + @Test + public void deserializingTest() + throws NoSuchMethodException, InvocationTargetException, InstantiationException, + IllegalAccessException { + + // reflection + Constructor constructor = + OAuth2AuthorizationRequest.Builder.class.getDeclaredConstructor( + AuthorizationGrantType.class); + constructor.setAccessible(true); + + // given + OAuth2AuthorizationRequest.Builder builder = + (OAuth2AuthorizationRequest.Builder) + constructor.newInstance(AuthorizationGrantType.AUTHORIZATION_CODE); + OAuth2AuthorizationRequest originalRequest = + builder + .authorizationUri("https://kauth.kakao.com/oauth/authorize") + .clientId("1234") + .redirectUri("http://localhost/api/login/oauth2/code/kakao") + .scopes(Set.of("gender", "profile_image", "account_email", "profile_nickname")) + .state("state1934") + .additionalParameters(java.util.Map.of()) + .attributes(java.util.Map.of("registration_id", "kakao")) + .build(); + + String serializedRequest = CookieUtils.serialize(originalRequest); + Cookie cookie = new Cookie("base64", serializedRequest); + + // when + OAuth2AuthorizationRequest deserializedRequest = + CookieUtils.deserialize(cookie, OAuth2AuthorizationRequest.class); + + // then + assertThat(deserializedRequest).usingRecursiveComparison().isEqualTo(originalRequest); + } } diff --git a/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/cookie/HttpCookieOAuth2AuthorizationRequestRepositoryTest.java b/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/cookie/HttpCookieOAuth2AuthorizationRequestRepositoryTest.java index 323080b1..1c8677a7 100644 --- a/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/cookie/HttpCookieOAuth2AuthorizationRequestRepositoryTest.java +++ b/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/cookie/HttpCookieOAuth2AuthorizationRequestRepositoryTest.java @@ -1,189 +1,196 @@ package com.inhabas.api.auth.domain.oauth2.cookie; -import org.apache.commons.codec.binary.Base64; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.mock.web.MockHttpServletRequest; -import org.springframework.mock.web.MockHttpServletResponse; -import org.springframework.security.oauth2.core.AuthorizationGrantType; -import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest; - -import javax.servlet.http.Cookie; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.util.Set; -import java.util.function.Predicate; - import static com.inhabas.api.auth.domain.oauth2.cookie.HttpCookieOAuth2AuthorizationRequestRepository.OAUTH2_AUTHORIZATION_REQUEST_COOKIE_NAME; import static com.inhabas.api.auth.domain.oauth2.cookie.HttpCookieOAuth2AuthorizationRequestRepository.REDIRECT_URL_PARAM_COOKIE_NAME; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertTrue; -public class HttpCookieOAuth2AuthorizationRequestRepositoryTest { - - - private final HttpCookieOAuth2AuthorizationRequestRepository httpCookieOAuth2AuthorizationRequestRepository = - new HttpCookieOAuth2AuthorizationRequestRepository(); - - - @DisplayName("Request 쿠키에서 OAuth2AuthorizationRequest 객체를 복원한다.") - @Test - public void loadAuthorizationRequestTest() throws NoSuchMethodException { - //given - OAuth2AuthorizationRequest oAuth2AuthorizationRequest = createOAuth2AuthorizationRequest(); - Cookie cookie = new Cookie(OAUTH2_AUTHORIZATION_REQUEST_COOKIE_NAME, CookieUtils.serialize(oAuth2AuthorizationRequest)); - cookie.setPath("/"); - cookie.setHttpOnly(true); - cookie.setMaxAge(180); - - MockHttpServletRequest request = new MockHttpServletRequest(); - request.setCookies(cookie); - - //when - OAuth2AuthorizationRequest restoredOAuth2AuthorizationRequest = - httpCookieOAuth2AuthorizationRequestRepository.loadAuthorizationRequest(request); - - //then - assertThat(restoredOAuth2AuthorizationRequest) - .usingRecursiveComparison() - .isEqualTo(oAuth2AuthorizationRequest); - } - - - @DisplayName("OAuth2AuthorizationRequest 가 null 이면 관련 쿠키는 아무것도 없다.") - @Test - public void saveAuthorizationRequestNullTest() { - //given - MockHttpServletRequest request = new MockHttpServletRequest(); - MockHttpServletResponse response = new MockHttpServletResponse(); - - //when - httpCookieOAuth2AuthorizationRequestRepository.saveAuthorizationRequest(null, request, response); - - //then - assertThat(response.getCookies()) - .filteredOn(cookie -> - cookie.getName().equals(OAUTH2_AUTHORIZATION_REQUEST_COOKIE_NAME) || - cookie.getName().equals(REDIRECT_URL_PARAM_COOKIE_NAME)) - .allMatch(cookieIsNull()); - } - - - @DisplayName("OAuth2AuthorizationRequest 를 성공적으로 쿠키로 저장한다.") - @Test - public void saveAuthorizationRequestTest() throws NoSuchMethodException { - //given - MockHttpServletRequest request = new MockHttpServletRequest(); - MockHttpServletResponse response = new MockHttpServletResponse(); - OAuth2AuthorizationRequest oAuth2AuthorizationRequest = this.createOAuth2AuthorizationRequest(); - - //when - httpCookieOAuth2AuthorizationRequestRepository.saveAuthorizationRequest(oAuth2AuthorizationRequest, request, response); - - //then - // 쿠키 한가지 존재하는지 확인. - Cookie savedCookie = response.getCookie(OAUTH2_AUTHORIZATION_REQUEST_COOKIE_NAME); - assert savedCookie != null; - assertTrue(Base64.isBase64(savedCookie.getValue())); - } - - - @DisplayName("OAuth2AuthorizationRequest 를 쿠키로 저장할 때, redirect_url 도 쿠키로 저장한다.") - @Test - public void saveAuthorizationRequestWithRedirectUrlTest() throws NoSuchMethodException { - //given - MockHttpServletRequest request = new MockHttpServletRequest(); - MockHttpServletResponse response = new MockHttpServletResponse(); - OAuth2AuthorizationRequest oAuth2AuthorizationRequest = this.createOAuth2AuthorizationRequest(); - - request.setParameter(REDIRECT_URL_PARAM_COOKIE_NAME, "/index.html"); - - //when - httpCookieOAuth2AuthorizationRequestRepository.saveAuthorizationRequest(oAuth2AuthorizationRequest, request, response); - - //then - // 쿠키 두가지 존재하는 지 확인 - assertThat(response.getCookies()) - .filteredOn(cookie -> - cookie.getName().equals(OAUTH2_AUTHORIZATION_REQUEST_COOKIE_NAME) || - cookie.getName().equals(REDIRECT_URL_PARAM_COOKIE_NAME)) - .allMatch(cookie -> !cookie.getValue().isBlank()); - } - - - @DisplayName("OAuth2AuthorizationRequest 를 성공적으로 쿠키에서 삭제한다. (redirectUrl 쿠키는 삭제되지 않는다.)") - @Test - public void removeAuthorizationRequestTest() throws NoSuchMethodException { - //given - MockHttpServletRequest request = new MockHttpServletRequest(); - MockHttpServletResponse response = new MockHttpServletResponse(); - OAuth2AuthorizationRequest oAuth2AuthorizationRequest = this.createOAuth2AuthorizationRequest(); - - Cookie serializedAuthorizationRequest = new Cookie(OAUTH2_AUTHORIZATION_REQUEST_COOKIE_NAME, CookieUtils.serialize(oAuth2AuthorizationRequest)); - request.setCookies(serializedAuthorizationRequest); - - //when - OAuth2AuthorizationRequest returnedRequest = - httpCookieOAuth2AuthorizationRequestRepository.removeAuthorizationRequest(request, response); - - //then - Cookie cookie = response.getCookie(OAUTH2_AUTHORIZATION_REQUEST_COOKIE_NAME); - assert cookie != null; - assertTrue(cookie.getValue().isBlank() && cookie.getMaxAge() == 0); - - } - - - @DisplayName("OAuth2AuthorizationRequest 를 성공적으로 쿠키에서 삭제한다. (redirectUrl 쿠키도 삭제된다.)") - @Test - public void removeAuthorizationRequestTotally() { - //given - MockHttpServletRequest request = new MockHttpServletRequest(); - MockHttpServletResponse response = new MockHttpServletResponse(); - - //when - httpCookieOAuth2AuthorizationRequestRepository.clearCookies(request, response); - - //then - assertThat(response.getCookies()) - .filteredOn(cookie -> - cookie.getName().equals(OAUTH2_AUTHORIZATION_REQUEST_COOKIE_NAME) || - cookie.getName().equals(REDIRECT_URL_PARAM_COOKIE_NAME)) - .allMatch(cookieIsNull()); - } - +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.Set; +import java.util.function.Predicate; +import javax.servlet.http.Cookie; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; +import org.springframework.security.oauth2.core.AuthorizationGrantType; +import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest; +import org.apache.commons.codec.binary.Base64; - private Predicate cookieIsNull() { - return cookie -> - cookie.getValue().isBlank() && cookie.getMaxAge() == 0; - } +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +public class HttpCookieOAuth2AuthorizationRequestRepositoryTest { - private OAuth2AuthorizationRequest createOAuth2AuthorizationRequest() throws NoSuchMethodException { - //reflection - Constructor constructor = - OAuth2AuthorizationRequest.Builder.class.getDeclaredConstructor(AuthorizationGrantType.class); - constructor.setAccessible(true); - - //construct - try { - OAuth2AuthorizationRequest.Builder builder = - (OAuth2AuthorizationRequest.Builder) constructor.newInstance(AuthorizationGrantType.AUTHORIZATION_CODE); - - return builder.authorizationUri("https://kauth.kakao.com/oauth/authorize") - .clientId("1234") - .redirectUri("http://localhost/api/login/oauth2/code/kakao") - .scopes(Set.of("gender", "profile_image", "account_email", "profile_nickname")) - .state("state1934") - .additionalParameters(java.util.Map.of()) - .attributes(java.util.Map.of("registration_id", "kakao")).build(); - - } catch (InvocationTargetException | InstantiationException | IllegalAccessException ignored) { - return null; - } + private final HttpCookieOAuth2AuthorizationRequestRepository + httpCookieOAuth2AuthorizationRequestRepository = + new HttpCookieOAuth2AuthorizationRequestRepository(); + + @DisplayName("Request 쿠키에서 OAuth2AuthorizationRequest 객체를 복원한다.") + @Test + public void loadAuthorizationRequestTest() throws NoSuchMethodException { + // given + OAuth2AuthorizationRequest oAuth2AuthorizationRequest = createOAuth2AuthorizationRequest(); + Cookie cookie = + new Cookie( + OAUTH2_AUTHORIZATION_REQUEST_COOKIE_NAME, + CookieUtils.serialize(oAuth2AuthorizationRequest)); + cookie.setPath("/"); + cookie.setHttpOnly(true); + cookie.setMaxAge(180); + + MockHttpServletRequest request = new MockHttpServletRequest(); + request.setCookies(cookie); + + // when + OAuth2AuthorizationRequest restoredOAuth2AuthorizationRequest = + httpCookieOAuth2AuthorizationRequestRepository.loadAuthorizationRequest(request); + + // then + assertThat(restoredOAuth2AuthorizationRequest) + .usingRecursiveComparison() + .isEqualTo(oAuth2AuthorizationRequest); + } + + @DisplayName("OAuth2AuthorizationRequest 가 null 이면 관련 쿠키는 아무것도 없다.") + @Test + public void saveAuthorizationRequestNullTest() { + // given + MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletResponse response = new MockHttpServletResponse(); + + // when + httpCookieOAuth2AuthorizationRequestRepository.saveAuthorizationRequest( + null, request, response); + + // then + assertThat(response.getCookies()) + .filteredOn( + cookie -> + cookie.getName().equals(OAUTH2_AUTHORIZATION_REQUEST_COOKIE_NAME) + || cookie.getName().equals(REDIRECT_URL_PARAM_COOKIE_NAME)) + .allMatch(cookieIsNull()); + } + + @DisplayName("OAuth2AuthorizationRequest 를 성공적으로 쿠키로 저장한다.") + @Test + public void saveAuthorizationRequestTest() throws NoSuchMethodException { + // given + MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletResponse response = new MockHttpServletResponse(); + OAuth2AuthorizationRequest oAuth2AuthorizationRequest = this.createOAuth2AuthorizationRequest(); + + // when + httpCookieOAuth2AuthorizationRequestRepository.saveAuthorizationRequest( + oAuth2AuthorizationRequest, request, response); + + // then + // 쿠키 한가지 존재하는지 확인. + Cookie savedCookie = response.getCookie(OAUTH2_AUTHORIZATION_REQUEST_COOKIE_NAME); + assert savedCookie != null; + assertTrue(Base64.isBase64(savedCookie.getValue())); + } + + @DisplayName("OAuth2AuthorizationRequest 를 쿠키로 저장할 때, redirect_url 도 쿠키로 저장한다.") + @Test + public void saveAuthorizationRequestWithRedirectUrlTest() throws NoSuchMethodException { + // given + MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletResponse response = new MockHttpServletResponse(); + OAuth2AuthorizationRequest oAuth2AuthorizationRequest = this.createOAuth2AuthorizationRequest(); + + request.setParameter(REDIRECT_URL_PARAM_COOKIE_NAME, "/index.html"); + + // when + httpCookieOAuth2AuthorizationRequestRepository.saveAuthorizationRequest( + oAuth2AuthorizationRequest, request, response); + + // then + // 쿠키 두가지 존재하는 지 확인 + assertThat(response.getCookies()) + .filteredOn( + cookie -> + cookie.getName().equals(OAUTH2_AUTHORIZATION_REQUEST_COOKIE_NAME) + || cookie.getName().equals(REDIRECT_URL_PARAM_COOKIE_NAME)) + .allMatch(cookie -> !cookie.getValue().isBlank()); + } + + @DisplayName("OAuth2AuthorizationRequest 를 성공적으로 쿠키에서 삭제한다. (redirectUrl 쿠키는 삭제되지 않는다.)") + @Test + public void removeAuthorizationRequestTest() throws NoSuchMethodException { + // given + MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletResponse response = new MockHttpServletResponse(); + OAuth2AuthorizationRequest oAuth2AuthorizationRequest = this.createOAuth2AuthorizationRequest(); + + Cookie serializedAuthorizationRequest = + new Cookie( + OAUTH2_AUTHORIZATION_REQUEST_COOKIE_NAME, + CookieUtils.serialize(oAuth2AuthorizationRequest)); + request.setCookies(serializedAuthorizationRequest); + + // when + OAuth2AuthorizationRequest returnedRequest = + httpCookieOAuth2AuthorizationRequestRepository.removeAuthorizationRequest( + request, response); + + // then + Cookie cookie = response.getCookie(OAUTH2_AUTHORIZATION_REQUEST_COOKIE_NAME); + assert cookie != null; + assertTrue(cookie.getValue().isBlank() && cookie.getMaxAge() == 0); + } + + @DisplayName("OAuth2AuthorizationRequest 를 성공적으로 쿠키에서 삭제한다. (redirectUrl 쿠키도 삭제된다.)") + @Test + public void removeAuthorizationRequestTotally() { + // given + MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletResponse response = new MockHttpServletResponse(); + + // when + httpCookieOAuth2AuthorizationRequestRepository.clearCookies(request, response); + + // then + assertThat(response.getCookies()) + .filteredOn( + cookie -> + cookie.getName().equals(OAUTH2_AUTHORIZATION_REQUEST_COOKIE_NAME) + || cookie.getName().equals(REDIRECT_URL_PARAM_COOKIE_NAME)) + .allMatch(cookieIsNull()); + } + + private Predicate cookieIsNull() { + return cookie -> cookie.getValue().isBlank() && cookie.getMaxAge() == 0; + } + + private OAuth2AuthorizationRequest createOAuth2AuthorizationRequest() + throws NoSuchMethodException { + // reflection + Constructor constructor = + OAuth2AuthorizationRequest.Builder.class.getDeclaredConstructor( + AuthorizationGrantType.class); + constructor.setAccessible(true); + + // construct + try { + OAuth2AuthorizationRequest.Builder builder = + (OAuth2AuthorizationRequest.Builder) + constructor.newInstance(AuthorizationGrantType.AUTHORIZATION_CODE); + + return builder + .authorizationUri("https://kauth.kakao.com/oauth/authorize") + .clientId("1234") + .redirectUri("http://localhost/api/login/oauth2/code/kakao") + .scopes(Set.of("gender", "profile_image", "account_email", "profile_nickname")) + .state("state1934") + .additionalParameters(java.util.Map.of()) + .attributes(java.util.Map.of("registration_id", "kakao")) + .build(); + + } catch (InvocationTargetException | InstantiationException | IllegalAccessException ignored) { + return null; } - + } } diff --git a/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/handler/Oauth2AuthenticationFailureHandlerTest.java b/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/handler/Oauth2AuthenticationFailureHandlerTest.java index a6e8d16c..1bc74188 100644 --- a/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/handler/Oauth2AuthenticationFailureHandlerTest.java +++ b/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/handler/Oauth2AuthenticationFailureHandlerTest.java @@ -1,88 +1,90 @@ package com.inhabas.api.auth.domain.oauth2.handler; -import com.inhabas.api.auth.AuthProperties; -import com.inhabas.api.auth.domain.oauth2.cookie.HttpCookieOAuth2AuthorizationRequestRepository; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; +import static com.inhabas.api.auth.domain.oauth2.cookie.HttpCookieOAuth2AuthorizationRequestRepository.REDIRECT_URL_PARAM_COOKIE_NAME; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.BDDMockito.given; + +import java.io.IOException; + +import javax.servlet.http.Cookie; + import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.security.core.AuthenticationException; import org.springframework.security.oauth2.core.OAuth2AuthenticationException; import org.springframework.security.oauth2.core.OAuth2ErrorCodes; -import javax.servlet.http.Cookie; -import java.io.IOException; +import com.inhabas.api.auth.AuthProperties; +import com.inhabas.api.auth.domain.oauth2.cookie.HttpCookieOAuth2AuthorizationRequestRepository; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; -import static com.inhabas.api.auth.domain.oauth2.cookie.HttpCookieOAuth2AuthorizationRequestRepository.REDIRECT_URL_PARAM_COOKIE_NAME; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.BDDMockito.given; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; @ExtendWith(MockitoExtension.class) public class Oauth2AuthenticationFailureHandlerTest { - @InjectMocks - private Oauth2AuthenticationFailureHandler oauth2AuthenticationFailureHandler; + @InjectMocks private Oauth2AuthenticationFailureHandler oauth2AuthenticationFailureHandler; - @Mock - private HttpCookieOAuth2AuthorizationRequestRepository httpCookieOAuth2AuthorizationRequestRepository; + @Mock + private HttpCookieOAuth2AuthorizationRequestRepository + httpCookieOAuth2AuthorizationRequestRepository; - @Mock - private AuthProperties authProperties; + @Mock private AuthProperties authProperties; - @Mock - private AuthProperties.OAuth2 oauth2Utils; + @Mock private AuthProperties.OAuth2 oauth2Utils; - @BeforeEach - public void setUp() { - given(authProperties.getOauth2()).willReturn(oauth2Utils); - } + @BeforeEach + public void setUp() { + given(authProperties.getOauth2()).willReturn(oauth2Utils); + } - @DisplayName("FailureHandler 호출 시, 허락된 defaultURL 로 정상적으로 리다이렉트 된다.") - @Test - public void redirectToDefaultTest() throws IOException { - //given - String errorCode = OAuth2ErrorCodes.INVALID_REQUEST; - MockHttpServletRequest request = new MockHttpServletRequest(); - MockHttpServletResponse response = new MockHttpServletResponse(); - AuthenticationException authenticationException = new OAuth2AuthenticationException(errorCode); + @DisplayName("FailureHandler 호출 시, 허락된 defaultURL 로 정상적으로 리다이렉트 된다.") + @Test + public void redirectToDefaultTest() throws IOException { + // given + String errorCode = OAuth2ErrorCodes.INVALID_REQUEST; + MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletResponse response = new MockHttpServletResponse(); + AuthenticationException authenticationException = new OAuth2AuthenticationException(errorCode); - Cookie redirectCookie = new Cookie(REDIRECT_URL_PARAM_COOKIE_NAME, "https://www.inhabas.com"); - request.setCookies(redirectCookie); + Cookie redirectCookie = new Cookie(REDIRECT_URL_PARAM_COOKIE_NAME, "https://www.inhabas.com"); + request.setCookies(redirectCookie); - given(oauth2Utils.getDefaultRedirectUri()).willReturn("https://www.inhabas.com"); + given(oauth2Utils.getDefaultRedirectUri()).willReturn("https://www.inhabas.com"); - //when - oauth2AuthenticationFailureHandler.onAuthenticationFailure(request, response, authenticationException); + // when + oauth2AuthenticationFailureHandler.onAuthenticationFailure( + request, response, authenticationException); - //then - assertThat(response.getRedirectedUrl()) - .isEqualTo("https://www.inhabas.com?error=" + errorCode); - } + // then + assertThat(response.getRedirectedUrl()).isEqualTo("https://www.inhabas.com?error=" + errorCode); + } - @DisplayName("유효하지 않은 redirect_url 은 허용하지 않는다.") - @Test - public void validateRedirectUrlTest() throws IOException { - //given - String errorCode = OAuth2ErrorCodes.INVALID_REQUEST; - MockHttpServletRequest request = new MockHttpServletRequest(); - MockHttpServletResponse response = new MockHttpServletResponse(); - AuthenticationException authenticationException = new OAuth2AuthenticationException(errorCode); + @DisplayName("유효하지 않은 redirect_url 은 허용하지 않는다.") + @Test + public void validateRedirectUrlTest() throws IOException { + // given + String errorCode = OAuth2ErrorCodes.INVALID_REQUEST; + MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletResponse response = new MockHttpServletResponse(); + AuthenticationException authenticationException = new OAuth2AuthenticationException(errorCode); - Cookie redirectCookie = new Cookie(REDIRECT_URL_PARAM_COOKIE_NAME, "https://www.unauthorized_url.com"); - request.setCookies(redirectCookie); + Cookie redirectCookie = + new Cookie(REDIRECT_URL_PARAM_COOKIE_NAME, "https://www.unauthorized_url.com"); + request.setCookies(redirectCookie); - given(oauth2Utils.getDefaultRedirectUri()).willReturn("https://www.inhabas.com"); + given(oauth2Utils.getDefaultRedirectUri()).willReturn("https://www.inhabas.com"); - //when - oauth2AuthenticationFailureHandler.onAuthenticationFailure(request, response, authenticationException); + // when + oauth2AuthenticationFailureHandler.onAuthenticationFailure( + request, response, authenticationException); - //then - assertThat(response.getRedirectedUrl()) - .isEqualTo("https://www.inhabas.com?error=" + errorCode); - } + // then + assertThat(response.getRedirectedUrl()).isEqualTo("https://www.inhabas.com?error=" + errorCode); + } } diff --git a/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/handler/Oauth2AuthenticationSuccessHandlerTest.java b/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/handler/Oauth2AuthenticationSuccessHandlerTest.java index b42d4fdc..e3072b51 100644 --- a/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/handler/Oauth2AuthenticationSuccessHandlerTest.java +++ b/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/handler/Oauth2AuthenticationSuccessHandlerTest.java @@ -1,135 +1,126 @@ package com.inhabas.api.auth.domain.oauth2.handler; +import static com.inhabas.api.auth.domain.oauth2.cookie.HttpCookieOAuth2AuthorizationRequestRepository.REDIRECT_URL_PARAM_COOKIE_NAME; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.mockito.BDDMockito.then; +import static org.mockito.Mockito.times; + +import java.io.IOException; +import java.util.Collections; +import java.util.Map; +import java.util.Set; + +import javax.servlet.http.Cookie; + +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken; +import org.springframework.security.oauth2.core.user.DefaultOAuth2User; + import com.inhabas.api.auth.AuthProperties; import com.inhabas.api.auth.domain.error.authException.UnauthorizedRedirectUrlException; import com.inhabas.api.auth.domain.oauth2.cookie.HttpCookieOAuth2AuthorizationRequestRepository; import com.inhabas.api.auth.domain.token.TokenUtil; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; -import org.springframework.mock.web.MockHttpServletRequest; -import org.springframework.mock.web.MockHttpServletResponse; -import org.springframework.security.core.authority.SimpleGrantedAuthority; -import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken; -import org.springframework.security.oauth2.core.user.DefaultOAuth2User; - -import javax.servlet.http.Cookie; -import java.io.IOException; -import java.util.Collections; -import java.util.Map; -import java.util.Set; - -import static com.inhabas.api.auth.domain.oauth2.cookie.HttpCookieOAuth2AuthorizationRequestRepository.REDIRECT_URL_PARAM_COOKIE_NAME; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.given; -import static org.mockito.BDDMockito.then; -import static org.mockito.Mockito.times; @ExtendWith(MockitoExtension.class) public class Oauth2AuthenticationSuccessHandlerTest { - @InjectMocks - private Oauth2AuthenticationSuccessHandler successHandler; - - @Mock - private TokenUtil tokenUtil; + @InjectMocks private Oauth2AuthenticationSuccessHandler successHandler; - @Mock - private HttpCookieOAuth2AuthorizationRequestRepository requestRepository; + @Mock private TokenUtil tokenUtil; - @Mock - private AuthProperties authProperties; + @Mock private HttpCookieOAuth2AuthorizationRequestRepository requestRepository; - @Mock - private AuthProperties.OAuth2 oAuth2Utils; + @Mock private AuthProperties authProperties; - private DefaultOAuth2User defaultOAuth2User; - private final Set basicAuthorities = - Collections.singleton(new SimpleGrantedAuthority("ROLE_BASIC")); + @Mock private AuthProperties.OAuth2 oAuth2Utils; + private DefaultOAuth2User defaultOAuth2User; + private final Set basicAuthorities = + Collections.singleton(new SimpleGrantedAuthority("ROLE_BASIC")); - @BeforeEach - public void setUp() { - given(authProperties.getOauth2()).willReturn(oAuth2Utils); - defaultOAuth2User = new DefaultOAuth2User( - basicAuthorities, - Map.of("id", 1234, "properties", "blahblah"), - "id" - ); - } + @BeforeEach + public void setUp() { + given(authProperties.getOauth2()).willReturn(oAuth2Utils); + defaultOAuth2User = + new DefaultOAuth2User(basicAuthorities, Map.of("id", 1234, "properties", "blahblah"), "id"); + } - @DisplayName("SuccessHandler 호출 시, targetURL 로 정상적으로 리다이렉트 된다.") - @Test - public void redirectToTargetUrlTest() throws IOException { + @DisplayName("SuccessHandler 호출 시, targetURL 로 정상적으로 리다이렉트 된다.") + @Test + public void redirectToTargetUrlTest() throws IOException { - //given - MockHttpServletRequest request = new MockHttpServletRequest(); - MockHttpServletResponse response = new MockHttpServletResponse(); - OAuth2AuthenticationToken authenticationToken = - new OAuth2AuthenticationToken(defaultOAuth2User, basicAuthorities, "google"); + // given + MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletResponse response = new MockHttpServletResponse(); + OAuth2AuthenticationToken authenticationToken = + new OAuth2AuthenticationToken(defaultOAuth2User, basicAuthorities, "google"); - Cookie redirectCookie = new Cookie(REDIRECT_URL_PARAM_COOKIE_NAME, - "https://www.inhabas.com"); - request.setCookies(redirectCookie); + Cookie redirectCookie = new Cookie(REDIRECT_URL_PARAM_COOKIE_NAME, "https://www.inhabas.com"); + request.setCookies(redirectCookie); - given(oAuth2Utils.isAuthorizedRedirectUri(any())).willReturn(true); + given(oAuth2Utils.isAuthorizedRedirectUri(any())).willReturn(true); - //when - successHandler.onAuthenticationSuccess(request, response, authenticationToken); + // when + successHandler.onAuthenticationSuccess(request, response, authenticationToken); - //then - assertThat(response.getRedirectedUrl()) - .contains("https://www.inhabas.com", "accessToken", "refreshToken", "expiresIn", - "imageUrl"); - } + // then + assertThat(response.getRedirectedUrl()) + .contains( + "https://www.inhabas.com", "accessToken", "refreshToken", "expiresIn", "imageUrl"); + } - @DisplayName("인가되지 않은 redirect_url 요청 시, UnauthorizedRedirectUriException 발생") - @Test - public void unAuthorizedTargetUrlTest() { + @DisplayName("인가되지 않은 redirect_url 요청 시, UnauthorizedRedirectUriException 발생") + @Test + public void unAuthorizedTargetUrlTest() { - //given - MockHttpServletRequest request = new MockHttpServletRequest(); - MockHttpServletResponse response = new MockHttpServletResponse(); - OAuth2AuthenticationToken authenticationToken = - new OAuth2AuthenticationToken(defaultOAuth2User, basicAuthorities, "google"); + // given + MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletResponse response = new MockHttpServletResponse(); + OAuth2AuthenticationToken authenticationToken = + new OAuth2AuthenticationToken(defaultOAuth2User, basicAuthorities, "google"); - Cookie redirectCookie = new Cookie(REDIRECT_URL_PARAM_COOKIE_NAME, - "https://www.inhabas.com"); - request.setCookies(redirectCookie); + Cookie redirectCookie = new Cookie(REDIRECT_URL_PARAM_COOKIE_NAME, "https://www.inhabas.com"); + request.setCookies(redirectCookie); - given(oAuth2Utils.isAuthorizedRedirectUri(any())).willReturn(false); + given(oAuth2Utils.isAuthorizedRedirectUri(any())).willReturn(false); - //when - Assertions.assertThrows(UnauthorizedRedirectUrlException.class, - () -> successHandler.onAuthenticationSuccess(request, response, - authenticationToken)); - } + // when + Assertions.assertThrows( + UnauthorizedRedirectUrlException.class, + () -> successHandler.onAuthenticationSuccess(request, response, authenticationToken)); + } - @DisplayName("정상적으로 로그인 처리가 되고, 인증과정에서 생성된 쿠키는 삭제된다.") - @Test - public void clearCookieAfterHandleOAuth2Authentication() throws IOException { - //given - MockHttpServletRequest request = new MockHttpServletRequest(); - MockHttpServletResponse response = new MockHttpServletResponse(); - OAuth2AuthenticationToken authenticationToken = - new OAuth2AuthenticationToken(defaultOAuth2User, basicAuthorities, "google"); + @DisplayName("정상적으로 로그인 처리가 되고, 인증과정에서 생성된 쿠키는 삭제된다.") + @Test + public void clearCookieAfterHandleOAuth2Authentication() throws IOException { + // given + MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletResponse response = new MockHttpServletResponse(); + OAuth2AuthenticationToken authenticationToken = + new OAuth2AuthenticationToken(defaultOAuth2User, basicAuthorities, "google"); - Cookie redirectCookie = new Cookie(REDIRECT_URL_PARAM_COOKIE_NAME, - "https://www.inhabas.com"); - request.setCookies(redirectCookie); + Cookie redirectCookie = new Cookie(REDIRECT_URL_PARAM_COOKIE_NAME, "https://www.inhabas.com"); + request.setCookies(redirectCookie); - given(oAuth2Utils.isAuthorizedRedirectUri(any())).willReturn(true); + given(oAuth2Utils.isAuthorizedRedirectUri(any())).willReturn(true); - //when - successHandler.onAuthenticationSuccess(request, response, authenticationToken); + // when + successHandler.onAuthenticationSuccess(request, response, authenticationToken); - //when - then(requestRepository).should(times(1)).clearCookies(any(), any()); - } + // when + then(requestRepository).should(times(1)).clearCookies(any(), any()); + } } diff --git a/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/majorInfo/domain/valueObject/CollegeTest.java b/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/majorInfo/domain/valueObject/CollegeTest.java index 27a89473..cf8ddd24 100644 --- a/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/majorInfo/domain/valueObject/CollegeTest.java +++ b/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/majorInfo/domain/valueObject/CollegeTest.java @@ -1,53 +1,51 @@ package com.inhabas.api.auth.domain.oauth2.majorInfo.domain.valueObject; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; + import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; + import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertThrows; - public class CollegeTest { - @DisplayName("College 타입에 제목을 저장한다.") - @Test - public void College_is_OK() { + @DisplayName("College 타입에 제목을 저장한다.") + @Test + public void College_is_OK() { - //given - String collegeString = "사회과학대학"; + // given + String collegeString = "사회과학대학"; - //when - College college = new College(collegeString); + // when + College college = new College(collegeString); - //then - assertThat(college.getValue()).isEqualTo("사회과학대학"); - } + // then + assertThat(college.getValue()).isEqualTo("사회과학대학"); + } - @DisplayName("College 타입에 너무 긴 이름을 저장한다. 20자 이상") - @Test - public void College_is_too_long() { + @DisplayName("College 타입에 너무 긴 이름을 저장한다. 20자 이상") + @Test + public void College_is_too_long() { - //given - String collegeString = "지금이문장은10자임".repeat(20); + // given + String collegeString = "지금이문장은10자임".repeat(20); - //then - assertThrows(InvalidInputException.class, - () -> new College(collegeString)); - } + // then + assertThrows(InvalidInputException.class, () -> new College(collegeString)); + } - @DisplayName("College 은 null 일 수 없습니다.") - @Test - public void College_cannot_be_Null() { + @DisplayName("College 은 null 일 수 없습니다.") + @Test + public void College_cannot_be_Null() { - assertThrows(InvalidInputException.class, - () -> new College(null)); - } + assertThrows(InvalidInputException.class, () -> new College(null)); + } - @DisplayName("College 은 빈 문자열일 수 없습니다.") - @Test - public void College_cannot_be_Blank() { + @DisplayName("College 은 빈 문자열일 수 없습니다.") + @Test + public void College_cannot_be_Blank() { - assertThrows(InvalidInputException.class, - () -> new College("\t")); - } + assertThrows(InvalidInputException.class, () -> new College("\t")); + } } diff --git a/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/majorInfo/domain/valueObject/MajorTest.java b/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/majorInfo/domain/valueObject/MajorTest.java index c3b1a9c3..5f7e74fa 100644 --- a/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/majorInfo/domain/valueObject/MajorTest.java +++ b/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/majorInfo/domain/valueObject/MajorTest.java @@ -4,50 +4,48 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; + import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; public class MajorTest { - @DisplayName("Major 타입에 제목을 저장한다.") - @Test - public void Major_is_OK() { + @DisplayName("Major 타입에 제목을 저장한다.") + @Test + public void Major_is_OK() { - //given - String majorString = "컴퓨터공학과"; + // given + String majorString = "컴퓨터공학과"; - //when - Major major = new Major(majorString); + // when + Major major = new Major(majorString); - //then - assertThat(major.getValue()).isEqualTo("컴퓨터공학과"); - } + // then + assertThat(major.getValue()).isEqualTo("컴퓨터공학과"); + } - @DisplayName("Major 타입에 너무 긴 이름을 저장한다. 50자 이상") - @Test - public void Major_is_too_long() { + @DisplayName("Major 타입에 너무 긴 이름을 저장한다. 50자 이상") + @Test + public void Major_is_too_long() { - //given - String majorString = "지금이문장은10자임".repeat(50); + // given + String majorString = "지금이문장은10자임".repeat(50); - //then - assertThrows(InvalidInputException.class, - () -> new Major(majorString)); - } + // then + assertThrows(InvalidInputException.class, () -> new Major(majorString)); + } - @DisplayName("Major 은 null 일 수 없습니다.") - @Test - public void Major_cannot_be_Null() { + @DisplayName("Major 은 null 일 수 없습니다.") + @Test + public void Major_cannot_be_Null() { - assertThrows(InvalidInputException.class, - () -> new Major(null)); - } + assertThrows(InvalidInputException.class, () -> new Major(null)); + } - @DisplayName("Major 은 빈 문자열일 수 없습니다.") - @Test - public void Major_cannot_be_Blank() { + @DisplayName("Major 은 빈 문자열일 수 없습니다.") + @Test + public void Major_cannot_be_Blank() { - assertThrows(InvalidInputException.class, - () -> new Major("\t")); - } + assertThrows(InvalidInputException.class, () -> new Major("\t")); + } } diff --git a/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/majorInfo/usecase/MajorInfoServiceTest.java b/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/majorInfo/usecase/MajorInfoServiceTest.java index eb079408..d23eac87 100644 --- a/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/majorInfo/usecase/MajorInfoServiceTest.java +++ b/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/majorInfo/usecase/MajorInfoServiceTest.java @@ -1,100 +1,99 @@ package com.inhabas.api.auth.domain.oauth2.majorInfo.usecase; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.tuple; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.BDDMockito.given; +import static org.mockito.BDDMockito.then; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.times; + +import java.util.ArrayList; +import java.util.List; + +import org.springframework.test.util.ReflectionTestUtils; import com.inhabas.api.auth.domain.oauth2.majorInfo.domain.MajorInfo; import com.inhabas.api.auth.domain.oauth2.majorInfo.dto.MajorInfoDto; import com.inhabas.api.auth.domain.oauth2.majorInfo.dto.MajorInfoSaveDto; import com.inhabas.api.auth.domain.oauth2.majorInfo.repository.MajorInfoRepository; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import org.springframework.test.util.ReflectionTestUtils; -import java.util.ArrayList; -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.tuple; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.BDDMockito.given; -import static org.mockito.BDDMockito.then; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.times; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; @ExtendWith(MockitoExtension.class) public class MajorInfoServiceTest { - @InjectMocks - private MajorInfoServiceImpl majorInfoService; + @InjectMocks private MajorInfoServiceImpl majorInfoService; - @Mock - private MajorInfoRepository majorInfoRepository; + @Mock private MajorInfoRepository majorInfoRepository; - @DisplayName("모든 학과 정보를 불러온다.") - @Test - public void findAllTest() { + @DisplayName("모든 학과 정보를 불러온다.") + @Test + public void findAllTest() { - //given - MajorInfo majorInfo1 = new MajorInfo("공과대학", "기계공학과"); - MajorInfo majorInfo2 = new MajorInfo("자연과학대학", "수학과"); - MajorInfo majorInfo3 = new MajorInfo("경영대학", "경영학과"); - ReflectionTestUtils.setField(majorInfo1, "id", 1); - ReflectionTestUtils.setField(majorInfo2, "id", 2); - ReflectionTestUtils.setField(majorInfo3, "id", 3); - List majorInfos = new ArrayList<>() {{ + // given + MajorInfo majorInfo1 = new MajorInfo("공과대학", "기계공학과"); + MajorInfo majorInfo2 = new MajorInfo("자연과학대학", "수학과"); + MajorInfo majorInfo3 = new MajorInfo("경영대학", "경영학과"); + ReflectionTestUtils.setField(majorInfo1, "id", 1); + ReflectionTestUtils.setField(majorInfo2, "id", 2); + ReflectionTestUtils.setField(majorInfo3, "id", 3); + List majorInfos = + new ArrayList<>() { + { add(majorInfo1); add(majorInfo2); add(majorInfo3); - }}; - - given(majorInfoRepository.findAll()).willReturn(majorInfos); - - //when - List allMajorInfoDTOs = majorInfoService.getAllMajorInfo(); - - //then - then(majorInfoRepository).should(times(1)).findAll(); - assertThat(allMajorInfoDTOs) - .hasSize(3) - .extracting("id", "college", "major") - .contains( - tuple(1, "공과대학", "기계공학과"), - tuple(2, "자연과학대학", "수학과"), - tuple(3, "경영대학", "경영학과")); - } - - @DisplayName("새로운 학과를 추가한다.") - @Test - public void saveMajorInfoTest() { - - //given - MajorInfoSaveDto newMajor = new MajorInfoSaveDto("경영대학", "글로벌금융학과"); - given(majorInfoRepository.save(any(MajorInfo.class))) - .willReturn(new MajorInfo("경영대학", "글로벌금융학과")); - - //when - majorInfoService.saveMajorInfo(newMajor); - - //then - then(majorInfoRepository).should(times(1)).save(any(MajorInfo.class)); - } - - @DisplayName("기존 전공 정보를 삭제한다.") - @Test - public void deleteMajorInfoTest() { - - //given - Integer tempMajorInfoId = 1; - doNothing().when(majorInfoRepository).deleteById(anyInt()); - - //when - majorInfoService.deleteMajorInfo(tempMajorInfoId); - - //then - then(majorInfoRepository).should(times(1)).deleteById(anyInt()); - } + } + }; + + given(majorInfoRepository.findAll()).willReturn(majorInfos); + + // when + List allMajorInfoDTOs = majorInfoService.getAllMajorInfo(); + + // then + then(majorInfoRepository).should(times(1)).findAll(); + assertThat(allMajorInfoDTOs) + .hasSize(3) + .extracting("id", "college", "major") + .contains(tuple(1, "공과대학", "기계공학과"), tuple(2, "자연과학대학", "수학과"), tuple(3, "경영대학", "경영학과")); + } + + @DisplayName("새로운 학과를 추가한다.") + @Test + public void saveMajorInfoTest() { + + // given + MajorInfoSaveDto newMajor = new MajorInfoSaveDto("경영대학", "글로벌금융학과"); + given(majorInfoRepository.save(any(MajorInfo.class))) + .willReturn(new MajorInfo("경영대학", "글로벌금융학과")); + + // when + majorInfoService.saveMajorInfo(newMajor); + + // then + then(majorInfoRepository).should(times(1)).save(any(MajorInfo.class)); + } + + @DisplayName("기존 전공 정보를 삭제한다.") + @Test + public void deleteMajorInfoTest() { + + // given + Integer tempMajorInfoId = 1; + doNothing().when(majorInfoRepository).deleteById(anyInt()); + + // when + majorInfoService.deleteMajorInfo(tempMajorInfoId); + + // then + then(majorInfoRepository).should(times(1)).deleteById(anyInt()); + } } diff --git a/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/member/domain/entity/MemberTest.java b/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/member/domain/entity/MemberTest.java index 89fd0c64..47a92554 100644 --- a/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/member/domain/entity/MemberTest.java +++ b/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/member/domain/entity/MemberTest.java @@ -1,102 +1,108 @@ package com.inhabas.api.auth.domain.oauth2.member.domain.entity; +import static com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.MemberType.UNDERGRADUATE; +import static com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.Role.*; + +import java.util.HashMap; +import java.util.Map; import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.Role; import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.SchoolInformation; import com.inhabas.api.auth.domain.oauth2.userInfo.GoogleOAuth2UserInfo; import com.inhabas.api.auth.domain.oauth2.userInfo.OAuth2UserInfo; -import java.util.HashMap; -import java.util.Map; - -import static com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.MemberType.UNDERGRADUATE; -import static com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.Role.*; - public class MemberTest { - private static Member afterSignUpMember(Role role) { + private static Member afterSignUpMember(Role role) { - Map attributes = new HashMap<>() {{ + Map attributes = + new HashMap<>() { + { put("provider", "GOOGLE"); put("sub", "3232322332323223"); put("picture", "/static/image.jpg"); put("email", "my@gmail.com"); put("name", "조승현"); put("locale", "ko"); - }}; - OAuth2UserInfo user = new GoogleOAuth2UserInfo(attributes); - Member member = new Member(user); - member.setRole(role); - - // 회원정보 저장 - member.setStudentId("12171707"); - member.setPhone("010-1111-1111"); - member.setName("조승현"); - member.setSchoolInformation(new SchoolInformation("컴퓨터공학과", 1, 1, UNDERGRADUATE)); - return member; - - } - - public static Member chiefMember() { - return afterSignUpMember(CHIEF); - } - - public static Member executivesMember() { - return afterSignUpMember(EXECUTIVES); - } - - public static Member secretaryMember() { - return afterSignUpMember(SECRETARY); - } - - public static Member basicMember() { - return afterSignUpMember(BASIC); - } - - public static Member deactivatedMember() { - return afterSignUpMember(DEACTIVATED); - } - - public static Member notapprovedMember() { - return afterSignUpMember(NOT_APPROVED); - } - - public static Member signingUpMemberAfterProfile() { - return afterSignUpMember(SIGNING_UP); - } - - public static Member signingUpMember1() { - - Map attributes = new HashMap<>() {{ + } + }; + OAuth2UserInfo user = new GoogleOAuth2UserInfo(attributes); + Member member = new Member(user); + member.setRole(role); + + // 회원정보 저장 + member.setStudentId("12171707"); + member.setPhone("010-1111-1111"); + member.setName("조승현"); + member.setSchoolInformation(new SchoolInformation("컴퓨터공학과", 1, 1, UNDERGRADUATE)); + return member; + } + + public static Member chiefMember() { + return afterSignUpMember(CHIEF); + } + + public static Member executivesMember() { + return afterSignUpMember(EXECUTIVES); + } + + public static Member secretaryMember() { + return afterSignUpMember(SECRETARY); + } + + public static Member basicMember() { + return afterSignUpMember(BASIC); + } + + public static Member deactivatedMember() { + return afterSignUpMember(DEACTIVATED); + } + + public static Member notapprovedMember() { + return afterSignUpMember(NOT_APPROVED); + } + + public static Member signingUpMemberAfterProfile() { + return afterSignUpMember(SIGNING_UP); + } + + public static Member signingUpMember1() { + + Map attributes = + new HashMap<>() { + { put("provider", "GOOGLE"); put("sub", "1249846925629348"); put("picture", "/static/image.jpg"); put("email", "my@gmail.com"); put("name", "유동현"); put("locale", "ko"); - }}; - OAuth2UserInfo user = new GoogleOAuth2UserInfo(attributes); - Member member = new Member(user); - member.setRole(SIGNING_UP); + } + }; + OAuth2UserInfo user = new GoogleOAuth2UserInfo(attributes); + Member member = new Member(user); + member.setRole(SIGNING_UP); - return member; - } + return member; + } - public static Member signingUpMember2() { + public static Member signingUpMember2() { - Map attributes = new HashMap<>() {{ + Map attributes = + new HashMap<>() { + { put("provider", "GOOGLE"); put("sub", "3232322332323223"); put("picture", "/static/image.jpg"); put("email", "my2@gmail.com"); put("name", "조승현"); put("locale", "ko"); - }}; - OAuth2UserInfo user = new GoogleOAuth2UserInfo(attributes); - Member member = new Member(user); - member.setRole(SIGNING_UP); - - return member; - } - + } + }; + OAuth2UserInfo user = new GoogleOAuth2UserInfo(attributes); + Member member = new Member(user); + member.setRole(SIGNING_UP); + + return member; + } } diff --git a/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/EmailTest.java b/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/EmailTest.java index 877f0028..b361f65e 100644 --- a/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/EmailTest.java +++ b/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/EmailTest.java @@ -1,64 +1,60 @@ package com.inhabas.api.auth.domain.oauth2.member.domain.valueObject; -import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; - import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertThrows; -public class EmailTest { - - @DisplayName("괜찮은 이메일 목록") - @Test - public void createEmailTest() { - assertDoesNotThrow(()->new Email("gildong13-dev@naver.com")); - assertDoesNotThrow(()->new Email("gildong1239.1234@inha.edu")); - assertDoesNotThrow(()->new Email("gildong@gmail.com")); - } - - @DisplayName("Email 타입에 이메일을 저장한다.") - @Test - public void Email_is_OK() { - //when - Email email = new Email("my@email.com"); - - //then - assertThat(email.getValue()).isEqualTo("my@email.com"); - } - - @DisplayName("Email 타입에 너무 긴 이메일 저장을 시도한다.") - @Test - public void Email_is_too_long() { - //given - String tooLongFileName = "세글자".repeat(100); - - //when - assertThrows(InvalidInputException.class, - () -> new Email(tooLongFileName)); - } - - @DisplayName("Email 에 null 은 허용 안된다.") - @Test - public void Email_cannot_be_null() { - assertThrows(InvalidInputException.class, - () -> new Email(null)); - } - - @DisplayName("Email 이 빈 문자열이면 안된다.") - @Test - public void Email_cannot_be_blank_string() { - assertThrows(InvalidInputException.class, - () -> new Email(" ")); - } +import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; - @DisplayName("Email 이 regex.") - @Test - public void Email_must_be_Email_regex() { +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; - assertThrows(InvalidInputException.class, - () -> new Email("DEV!L@email.###")); +public class EmailTest { - } + @DisplayName("괜찮은 이메일 목록") + @Test + public void createEmailTest() { + assertDoesNotThrow(() -> new Email("gildong13-dev@naver.com")); + assertDoesNotThrow(() -> new Email("gildong1239.1234@inha.edu")); + assertDoesNotThrow(() -> new Email("gildong@gmail.com")); + } + + @DisplayName("Email 타입에 이메일을 저장한다.") + @Test + public void Email_is_OK() { + // when + Email email = new Email("my@email.com"); + + // then + assertThat(email.getValue()).isEqualTo("my@email.com"); + } + + @DisplayName("Email 타입에 너무 긴 이메일 저장을 시도한다.") + @Test + public void Email_is_too_long() { + // given + String tooLongFileName = "세글자".repeat(100); + + // when + assertThrows(InvalidInputException.class, () -> new Email(tooLongFileName)); + } + + @DisplayName("Email 에 null 은 허용 안된다.") + @Test + public void Email_cannot_be_null() { + assertThrows(InvalidInputException.class, () -> new Email(null)); + } + + @DisplayName("Email 이 빈 문자열이면 안된다.") + @Test + public void Email_cannot_be_blank_string() { + assertThrows(InvalidInputException.class, () -> new Email(" ")); + } + + @DisplayName("Email 이 regex.") + @Test + public void Email_must_be_Email_regex() { + + assertThrows(InvalidInputException.class, () -> new Email("DEV!L@email.###")); + } } diff --git a/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/GenerationTest.java b/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/GenerationTest.java index fea06bed..507ab93c 100644 --- a/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/GenerationTest.java +++ b/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/GenerationTest.java @@ -4,34 +4,29 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; + import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; public class GenerationTest { - @DisplayName("Generation 타입에 기수를 지정") - @Test - public void Semester_is_OK() { - //given - Generation firstGeneration = new Generation(1); - Generation secondGeneration = new Generation(2); + @DisplayName("Generation 타입에 기수를 지정") + @Test + public void Semester_is_OK() { + // given + Generation firstGeneration = new Generation(1); + Generation secondGeneration = new Generation(2); - //then - assertThat(firstGeneration.getValue()).isEqualTo(1); - assertThat(secondGeneration.getValue()).isEqualTo(2); - } + // then + assertThat(firstGeneration.getValue()).isEqualTo(1); + assertThat(secondGeneration.getValue()).isEqualTo(2); + } - @DisplayName("존재할 수 없는 기수를 지정") - @Test - public void No_Such_Semester() { - //when - assertThrows( - InvalidInputException.class, - () -> new Generation(-1) - ); - assertThrows( - InvalidInputException.class, - () -> new Generation(0) - ); - } + @DisplayName("존재할 수 없는 기수를 지정") + @Test + public void No_Such_Semester() { + // when + assertThrows(InvalidInputException.class, () -> new Generation(-1)); + assertThrows(InvalidInputException.class, () -> new Generation(0)); + } } diff --git a/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/GradeTest.java b/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/GradeTest.java index 84227259..836c571a 100644 --- a/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/GradeTest.java +++ b/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/GradeTest.java @@ -1,33 +1,31 @@ package com.inhabas.api.auth.domain.oauth2.member.domain.valueObject; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; + import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; + import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertThrows; - public class GradeTest { - @DisplayName("Grade 타입에 기수를 지정") - @Test - public void Grade_is_OK() { - //given - Grade normalGrade = new Grade(1); - Grade nullGrade = new Grade(); + @DisplayName("Grade 타입에 기수를 지정") + @Test + public void Grade_is_OK() { + // given + Grade normalGrade = new Grade(1); + Grade nullGrade = new Grade(); - //then - assertThat(normalGrade.getValue()).isEqualTo(1); - assertThat(nullGrade.getValue()).isEqualTo(0); - } + // then + assertThat(normalGrade.getValue()).isEqualTo(1); + assertThat(nullGrade.getValue()).isEqualTo(0); + } - @DisplayName("존재할 수 없는 Grade 지정") - @Test - public void No_Such_Grade() { - //when - assertThrows( - InvalidInputException.class, - () -> new Grade(-1) - ); - } + @DisplayName("존재할 수 없는 Grade 지정") + @Test + public void No_Such_Grade() { + // when + assertThrows(InvalidInputException.class, () -> new Grade(-1)); + } } diff --git a/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/IntroduceTest.java b/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/IntroduceTest.java index 5224d3a1..7c3a332c 100644 --- a/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/IntroduceTest.java +++ b/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/IntroduceTest.java @@ -1,45 +1,43 @@ package com.inhabas.api.auth.domain.oauth2.member.domain.valueObject; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; + import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; + import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertThrows; - public class IntroduceTest { - @DisplayName("자기소개란 작성") - @Test - public void Introduce_is_OK() { - //given - String introduceString = "아이엠 그라운드 자기소개 하기."; - - //when - Introduce introduce = new Introduce(introduceString); - - //then - assertThat(introduce.getValue()).isEqualTo("아이엠 그라운드 자기소개 하기."); - } - - @DisplayName("자기소개가 너무 길다. 300자 이상.") - @Test - public void Introduce_is_too_long() { - //given - String introduceString = "지금이문장은10자임".repeat(50); // 500자 - - //then - assertThrows( - InvalidInputException.class, - ()-> new Introduce(introduceString) - ); - } - - @DisplayName("Introduce value 가 null 이면 빈 문자열로 설정된다.") - @Test - public void Null_value_introduce_is_empty_string() { - Introduce introduce = new Introduce(null); - - assertThat(introduce.getValue()).isEqualTo(""); - } + @DisplayName("자기소개란 작성") + @Test + public void Introduce_is_OK() { + // given + String introduceString = "아이엠 그라운드 자기소개 하기."; + + // when + Introduce introduce = new Introduce(introduceString); + + // then + assertThat(introduce.getValue()).isEqualTo("아이엠 그라운드 자기소개 하기."); + } + + @DisplayName("자기소개가 너무 길다. 300자 이상.") + @Test + public void Introduce_is_too_long() { + // given + String introduceString = "지금이문장은10자임".repeat(50); // 500자 + + // then + assertThrows(InvalidInputException.class, () -> new Introduce(introduceString)); + } + + @DisplayName("Introduce value 가 null 이면 빈 문자열로 설정된다.") + @Test + public void Null_value_introduce_is_empty_string() { + Introduce introduce = new Introduce(null); + + assertThat(introduce.getValue()).isEqualTo(""); + } } diff --git a/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/MemberTypeTest.java b/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/MemberTypeTest.java index 8ddbbf85..869b1c2f 100644 --- a/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/MemberTypeTest.java +++ b/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/MemberTypeTest.java @@ -1,30 +1,31 @@ package com.inhabas.api.auth.domain.oauth2.member.domain.valueObject; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; +import static org.assertj.core.api.Assertions.assertThat; import java.util.Arrays; -import static org.assertj.core.api.Assertions.assertThat; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; public class MemberTypeTest { - @DisplayName("MemberType 길이는 15자 초과하면 안된다.") - @Test - public void MemberTypeLengthMustNotBeGreaterThan15() { - assertThat( - Arrays.stream(MemberType.values()) - .filter(memberType -> memberType.toString().length() > 15) - .findAny()).isEmpty(); - - } + @DisplayName("MemberType 길이는 15자 초과하면 안된다.") + @Test + public void MemberTypeLengthMustNotBeGreaterThan15() { + assertThat( + Arrays.stream(MemberType.values()) + .filter(memberType -> memberType.toString().length() > 15) + .findAny()) + .isEmpty(); + } - @DisplayName("MemberType 값이 blank 값이면 안된다.") - @Test - public void MemberTypeValueMustNotBeBlank() { - assertThat( - Arrays.stream(MemberType.values()) - .filter(memberType -> memberType.toString().isBlank()) - .findAny()).isEmpty(); - } + @DisplayName("MemberType 값이 blank 값이면 안된다.") + @Test + public void MemberTypeValueMustNotBeBlank() { + assertThat( + Arrays.stream(MemberType.values()) + .filter(memberType -> memberType.toString().isBlank()) + .findAny()) + .isEmpty(); + } } diff --git a/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/NameTest.java b/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/NameTest.java index 59876e07..20fcbbbc 100644 --- a/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/NameTest.java +++ b/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/NameTest.java @@ -4,48 +4,44 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; + import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; public class NameTest { - @DisplayName("Name 타입에 유저 이름 저장") - @Test - public void UserName_is_OK() { - //given - String username = "홍길동"; - - //when - Name name = new Name(username); - - //then - assertThat(name.getValue()).isEqualTo("홍길동"); - } - - @DisplayName("Name 타입에 너무 긴 유저 이름 저장 시도. 50자 이상") - @Test - public void UserName_is_too_long() { - //given - String username = "홍길동".repeat(17); // 51자 - - //when - assertThrows( - InvalidInputException.class, - ()-> new Name(username) - ); - } - - @DisplayName("이름은 null 일 수 없다.") - @Test - public void Username_cannot_be_null() { - assertThrows(InvalidInputException.class, - ()-> new Name(null)); - } - - @DisplayName("이름은 빈 문자열일 수 없다.") - @Test - public void Username_cannot_be_blank() { - assertThrows(InvalidInputException.class, - ()-> new Name("")); - } + @DisplayName("Name 타입에 유저 이름 저장") + @Test + public void UserName_is_OK() { + // given + String username = "홍길동"; + + // when + Name name = new Name(username); + + // then + assertThat(name.getValue()).isEqualTo("홍길동"); + } + + @DisplayName("Name 타입에 너무 긴 유저 이름 저장 시도. 50자 이상") + @Test + public void UserName_is_too_long() { + // given + String username = "홍길동".repeat(17); // 51자 + + // when + assertThrows(InvalidInputException.class, () -> new Name(username)); + } + + @DisplayName("이름은 null 일 수 없다.") + @Test + public void Username_cannot_be_null() { + assertThrows(InvalidInputException.class, () -> new Name(null)); + } + + @DisplayName("이름은 빈 문자열일 수 없다.") + @Test + public void Username_cannot_be_blank() { + assertThrows(InvalidInputException.class, () -> new Name("")); + } } diff --git a/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/PhoneTest.java b/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/PhoneTest.java index b0213af9..8eaf8e2a 100644 --- a/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/PhoneTest.java +++ b/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/PhoneTest.java @@ -1,59 +1,52 @@ package com.inhabas.api.auth.domain.oauth2.member.domain.valueObject; -import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; import java.util.Arrays; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertThrows; +import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; -public class PhoneTest { +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; - @DisplayName("Phone 타입에 핸드폰 번호를 저장") - @Test - public void Phone_is_OK() { - //given - String number = "010-1111-1111"; - - //when - Phone phone = new Phone(number); - - //then - assertThat(phone.getValue()).isEqualTo("010-1111-1111"); - } - - @DisplayName("잘못된 핸드폰 번호 저장 시도") - @Test - public void Phone_is_Wrong() { - //given - String[] wrongNumbers = { - "010-111-1111", - "011-1111-1111", - "02-503-1234", - "010)111-1111", - "01023452345" - }; - - //then - Arrays.stream(wrongNumbers).forEach( - number -> assertThrows(InvalidInputException.class, ()-> new Phone(number)) - ); - } - - @DisplayName("핸드폰 번호에 null 이 저장될 수 없다.") - @Test - public void Phone_cannot_be_Null() { - assertThrows(InvalidInputException.class, - () -> new Phone(null)); - } - - @DisplayName("핸드폰 번호에 빈 문자열이 저장될 수 없다.") - @Test - public void Phone_cannot_be_Blank() { - assertThrows(InvalidInputException.class, - () -> new Phone(" ")); - } +public class PhoneTest { + @DisplayName("Phone 타입에 핸드폰 번호를 저장") + @Test + public void Phone_is_OK() { + // given + String number = "010-1111-1111"; + + // when + Phone phone = new Phone(number); + + // then + assertThat(phone.getValue()).isEqualTo("010-1111-1111"); + } + + @DisplayName("잘못된 핸드폰 번호 저장 시도") + @Test + public void Phone_is_Wrong() { + // given + String[] wrongNumbers = { + "010-111-1111", "011-1111-1111", "02-503-1234", "010)111-1111", "01023452345" + }; + + // then + Arrays.stream(wrongNumbers) + .forEach(number -> assertThrows(InvalidInputException.class, () -> new Phone(number))); + } + + @DisplayName("핸드폰 번호에 null 이 저장될 수 없다.") + @Test + public void Phone_cannot_be_Null() { + assertThrows(InvalidInputException.class, () -> new Phone(null)); + } + + @DisplayName("핸드폰 번호에 빈 문자열이 저장될 수 없다.") + @Test + public void Phone_cannot_be_Blank() { + assertThrows(InvalidInputException.class, () -> new Phone(" ")); + } } diff --git a/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/StudentIdTest.java b/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/StudentIdTest.java index c2f9f82d..be19081d 100644 --- a/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/StudentIdTest.java +++ b/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/StudentIdTest.java @@ -1,45 +1,41 @@ package com.inhabas.api.auth.domain.oauth2.member.domain.valueObject; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; + import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; + import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertThrows; - public class StudentIdTest { - @DisplayName("StudentId 타입에 유저 이름 저장") - @Test - public void StudentId_is_OK() { - //given - String id = "12171707"; - - //when - StudentId studentId = new StudentId(id); - - //then - assertThat(studentId.getValue()).isEqualTo("12171707"); - } - - @DisplayName("StudentId 타입에 잘못된 StudentId 저장 시도. 30자 이상") - @Test - public void StudentId_is_too_long() { - //given - String id = "2023".repeat(10); // 40자 - - //when - assertThrows( - InvalidInputException.class, - ()-> new StudentId(id) - ); - } - - @DisplayName("학번은 null 일 수 없다.") - @Test - public void StudentId_cannot_be_null() { - assertThrows(InvalidInputException.class, - ()-> new StudentId(null)); - } - + @DisplayName("StudentId 타입에 유저 이름 저장") + @Test + public void StudentId_is_OK() { + // given + String id = "12171707"; + + // when + StudentId studentId = new StudentId(id); + + // then + assertThat(studentId.getValue()).isEqualTo("12171707"); + } + + @DisplayName("StudentId 타입에 잘못된 StudentId 저장 시도. 30자 이상") + @Test + public void StudentId_is_too_long() { + // given + String id = "2023".repeat(10); // 40자 + + // when + assertThrows(InvalidInputException.class, () -> new StudentId(id)); + } + + @DisplayName("학번은 null 일 수 없다.") + @Test + public void StudentId_cannot_be_null() { + assertThrows(InvalidInputException.class, () -> new StudentId(null)); + } } diff --git a/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/member/repository/MemberRepositoryTest.java b/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/member/repository/MemberRepositoryTest.java index e8c65274..39e88f17 100644 --- a/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/member/repository/MemberRepositoryTest.java +++ b/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/member/repository/MemberRepositoryTest.java @@ -1,5 +1,23 @@ package com.inhabas.api.auth.domain.oauth2.member.repository; +import static com.inhabas.api.auth.domain.oauth2.OAuth2Provider.GOOGLE; +import static com.inhabas.api.auth.domain.oauth2.member.domain.entity.MemberTest.*; +import static com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.Role.NOT_APPROVED; +import static com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.Role.SIGNING_UP; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.*; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager; +import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.transaction.annotation.Transactional; + import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; import com.inhabas.api.auth.domain.oauth2.member.dto.MemberDuplicationQueryCondition; @@ -7,203 +25,180 @@ import com.inhabas.api.auth.domain.oauth2.userInfo.GoogleOAuth2UserInfo; import com.inhabas.api.auth.domain.oauth2.userInfo.OAuth2UserInfo; import com.inhabas.api.auth.testAnnotation.DefaultDataJpaTest; + import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager; -import org.springframework.dao.DataIntegrityViolationException; -import org.springframework.transaction.annotation.Transactional; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.stream.Collectors; - -import static com.inhabas.api.auth.domain.oauth2.OAuth2Provider.GOOGLE; -import static com.inhabas.api.auth.domain.oauth2.member.domain.entity.MemberTest.*; -import static com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.Role.NOT_APPROVED; -import static com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.Role.SIGNING_UP; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.*; @DefaultDataJpaTest public class MemberRepositoryTest { - @Autowired - MemberRepository memberRepository; - @Autowired - TestEntityManager em; - - - @DisplayName("저장 후 반환 값은 처음과 같다.") - @Test - @Transactional - public void save() { - - //when - Member saveMember = memberRepository.save(signingUpMember1()); - - //then - assertThat(saveMember) - .usingRecursiveComparison() - .ignoringFields("ibasInformation.dateJoined", "id", "lastLogin") - .isEqualTo(signingUpMember1()); - - } - - @DisplayName("idList 로 사용자를 찾을 수 있다.") - @Test - @Transactional - public void find_all_by_id() { - - //given - memberRepository.save(signingUpMember1()); - memberRepository.save(signingUpMember2()); - List allMember = memberRepository.findAll(); - List allId = allMember.stream().map(Member::getId).collect(Collectors.toList()); - - - //when - List memberList = memberRepository.findAllById(allId); - - //then - assertThat(memberList).containsExactlyInAnyOrderElementsOf(allMember); - - } - - @DisplayName("Role로 하나의 사용자를 조회한다.") - @Test - @Transactional - public void findAll() { - - //given - Member save1 = memberRepository.save(signingUpMember1()); - - //when - Member member = memberRepository.findByIbasInformation_Role(SIGNING_UP); - - //then - assertThat(member).isEqualTo(save1); - - } - - @DisplayName("같은 provider_uid 저장 시 DataIntegrityViolationException 예외") - @Test - @Transactional - public void 같은_provider_uid_저장_예외() { - //given - memberRepository.save(signingUpMember1()); - - //then - assertThrows(DataIntegrityViolationException.class, - () -> memberRepository.saveAndFlush(signingUpMember1())); - } - - @DisplayName("provider_uid 중복검사 시 true 를 반환") - @Test - @Transactional - public void provider_uid_존재한다() { - - //given - Map attributes = new HashMap<>() {{ + @Autowired MemberRepository memberRepository; + @Autowired TestEntityManager em; + + @DisplayName("저장 후 반환 값은 처음과 같다.") + @Test + @Transactional + public void save() { + + // when + Member saveMember = memberRepository.save(signingUpMember1()); + + // then + assertThat(saveMember) + .usingRecursiveComparison() + .ignoringFields("ibasInformation.dateJoined", "id", "lastLogin") + .isEqualTo(signingUpMember1()); + } + + @DisplayName("idList 로 사용자를 찾을 수 있다.") + @Test + @Transactional + public void find_all_by_id() { + + // given + memberRepository.save(signingUpMember1()); + memberRepository.save(signingUpMember2()); + List allMember = memberRepository.findAll(); + List allId = allMember.stream().map(Member::getId).collect(Collectors.toList()); + + // when + List memberList = memberRepository.findAllById(allId); + + // then + assertThat(memberList).containsExactlyInAnyOrderElementsOf(allMember); + } + + @DisplayName("Role로 하나의 사용자를 조회한다.") + @Test + @Transactional + public void findAll() { + + // given + Member save1 = memberRepository.save(signingUpMember1()); + + // when + Member member = memberRepository.findByIbasInformation_Role(SIGNING_UP); + + // then + assertThat(member).isEqualTo(save1); + } + + @DisplayName("같은 provider_uid 저장 시 DataIntegrityViolationException 예외") + @Test + @Transactional + public void 같은_provider_uid_저장_예외() { + // given + memberRepository.save(signingUpMember1()); + + // then + assertThrows( + DataIntegrityViolationException.class, + () -> memberRepository.saveAndFlush(signingUpMember1())); + } + + @DisplayName("provider_uid 중복검사 시 true 를 반환") + @Test + @Transactional + public void provider_uid_존재한다() { + + // given + Map attributes = + new HashMap<>() { + { put("provider", "GOOGLE"); put("sub", "1249846925629348"); put("picture", "/static/image.jpg"); put("email", "my@gmail.com"); put("name", "유동현"); put("locale", "ko"); - }}; - OAuth2UserInfo user = new GoogleOAuth2UserInfo(attributes); - Member save1 = new Member(user); - memberRepository.save(save1); - - //when - boolean isExist = memberRepository.existsByProviderAndUid(GOOGLE, new UID("1249846925629348")); - - //then - assertTrue(isExist); - - } - - @DisplayName("provider_uid 중복검사 시 false 를 반환") - @Test - @Transactional - public void provider_uid_존재하지_않는다() { - - //when - boolean isExist = memberRepository.existsByProviderAndUid(GOOGLE, new UID("1249846925629348")); - - //then - assertFalse(isExist); - - } - - @DisplayName("provider_uid 로 사용자를 찾는다") - @Test - @Transactional - public void find_by_provider_uid() { - - //given - Member save1 = memberRepository.save(signingUpMember1()); - - //when - Optional member = memberRepository.findByProviderAndUid(GOOGLE, new UID("1249846925629348")); - - //then - assertTrue(member.isPresent()); - assertEquals(save1.getId(), member.get().getId()); - - } - - - - - // Custom - @DisplayName("중복 검사 쿼리 provider 없는 경우") - @Test - @Transactional - public void validateNoneFields() { - - //given - memberRepository.save(signingUpMember1()); - - //then - assertThrows(InvalidInputException.class, - () -> memberRepository.isDuplicated(new MemberDuplicationQueryCondition(null, "1249846925629348"))); - - } - - - @DisplayName("모든 필드 중복되는 경우") - @Test - @Transactional - public void validateAllFields() { - - //given - memberRepository.save(signingUpMember1()); - - //when - boolean result = memberRepository.isDuplicated(new MemberDuplicationQueryCondition(GOOGLE, "1249846925629348")); - - //then - assertTrue(result); - - } - - // 회원가입 이후 구현 - @DisplayName("Role, StudentId 로 회원 검색") - @Test - @Transactional - public void search_by_role_studentId() { - //given - memberRepository.save(notapprovedMember()); - - //when - List members = memberRepository.findAllByRoleAndStudentIdLike(NOT_APPROVED, "12171707"); - - //then - assertThat(members.size()).isEqualTo(1); - } - + } + }; + OAuth2UserInfo user = new GoogleOAuth2UserInfo(attributes); + Member save1 = new Member(user); + memberRepository.save(save1); + + // when + boolean isExist = memberRepository.existsByProviderAndUid(GOOGLE, new UID("1249846925629348")); + + // then + assertTrue(isExist); + } + + @DisplayName("provider_uid 중복검사 시 false 를 반환") + @Test + @Transactional + public void provider_uid_존재하지_않는다() { + + // when + boolean isExist = memberRepository.existsByProviderAndUid(GOOGLE, new UID("1249846925629348")); + + // then + assertFalse(isExist); + } + + @DisplayName("provider_uid 로 사용자를 찾는다") + @Test + @Transactional + public void find_by_provider_uid() { + + // given + Member save1 = memberRepository.save(signingUpMember1()); + + // when + Optional member = + memberRepository.findByProviderAndUid(GOOGLE, new UID("1249846925629348")); + + // then + assertTrue(member.isPresent()); + assertEquals(save1.getId(), member.get().getId()); + } + + // Custom + @DisplayName("중복 검사 쿼리 provider 없는 경우") + @Test + @Transactional + public void validateNoneFields() { + + // given + memberRepository.save(signingUpMember1()); + + // then + assertThrows( + InvalidInputException.class, + () -> + memberRepository.isDuplicated( + new MemberDuplicationQueryCondition(null, "1249846925629348"))); + } + + @DisplayName("모든 필드 중복되는 경우") + @Test + @Transactional + public void validateAllFields() { + + // given + memberRepository.save(signingUpMember1()); + + // when + boolean result = + memberRepository.isDuplicated( + new MemberDuplicationQueryCondition(GOOGLE, "1249846925629348")); + + // then + assertTrue(result); + } + + // 회원가입 이후 구현 + @DisplayName("Role, StudentId 로 회원 검색") + @Test + @Transactional + public void search_by_role_studentId() { + // given + memberRepository.save(notapprovedMember()); + + // when + List members = memberRepository.findAllByRoleAndStudentIdLike(NOT_APPROVED, "12171707"); + + // then + assertThat(members.size()).isEqualTo(1); + } } diff --git a/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/member/repository/UpdateNameRequestRepositoryTest.java b/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/member/repository/UpdateNameRequestRepositoryTest.java index f7de25aa..c4942774 100644 --- a/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/member/repository/UpdateNameRequestRepositoryTest.java +++ b/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/member/repository/UpdateNameRequestRepositoryTest.java @@ -1,44 +1,40 @@ package com.inhabas.api.auth.domain.oauth2.member.repository; +import static org.assertj.core.api.Assertions.assertThat; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.transaction.annotation.Transactional; + import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; import com.inhabas.api.auth.domain.oauth2.member.domain.entity.MemberTest; import com.inhabas.api.auth.domain.oauth2.member.domain.entity.UpdateNameRequest; import com.inhabas.api.auth.testAnnotation.DefaultDataJpaTest; + import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.transaction.annotation.Transactional; - -import static org.assertj.core.api.Assertions.assertThat; @DefaultDataJpaTest class UpdateNameRequestRepositoryTest { - @Autowired - MemberRepository memberRepository; - @Autowired - UpdateNameRequestRepository updateNameRequestRepository; - - @DisplayName("객체 하나를 저장한다.") - @Test - @Transactional - public void saveTest() { - //given - Member member = MemberTest.basicMember(); - Member savedMember = memberRepository.save(member); - - UpdateNameRequest updateNameRequest = UpdateNameRequest.builder() - .member(savedMember) - .name("조변경") - .build(); + @Autowired MemberRepository memberRepository; + @Autowired UpdateNameRequestRepository updateNameRequestRepository; - //when - UpdateNameRequest result = updateNameRequestRepository.save(updateNameRequest); + @DisplayName("객체 하나를 저장한다.") + @Test + @Transactional + public void saveTest() { + // given + Member member = MemberTest.basicMember(); + Member savedMember = memberRepository.save(member); - //then - assertThat(result.getName()).isEqualTo(updateNameRequest.getName()); - assertThat(result.getMember().getId()).isEqualTo(savedMember.getId()); + UpdateNameRequest updateNameRequest = + UpdateNameRequest.builder().member(savedMember).name("조변경").build(); - } + // when + UpdateNameRequest result = updateNameRequestRepository.save(updateNameRequest); -} \ No newline at end of file + // then + assertThat(result.getName()).isEqualTo(updateNameRequest.getName()); + assertThat(result.getMember().getId()).isEqualTo(savedMember.getId()); + } +} diff --git a/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/member/security/MemberAuthorityProviderTest.java b/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/member/security/MemberAuthorityProviderTest.java index 393af32a..997dec48 100644 --- a/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/member/security/MemberAuthorityProviderTest.java +++ b/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/member/security/MemberAuthorityProviderTest.java @@ -1,79 +1,74 @@ package com.inhabas.api.auth.domain.oauth2.member.security; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; + +import java.util.Collection; +import java.util.Optional; + +import org.springframework.security.core.authority.SimpleGrantedAuthority; + import com.inhabas.api.auth.domain.oauth2.OAuth2Provider; import com.inhabas.api.auth.domain.oauth2.member.domain.entity.MemberTest; import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.Role; import com.inhabas.api.auth.domain.oauth2.member.repository.MemberRepository; import com.inhabas.api.auth.domain.oauth2.userInfo.OAuth2UserInfo; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import org.springframework.security.core.authority.SimpleGrantedAuthority; -import java.util.Collection; -import java.util.Optional; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.given; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; @ExtendWith(MockitoExtension.class) public class MemberAuthorityProviderTest { - @InjectMocks - private MemberAuthorityProvider memberAuthorityProvider; - - @Mock - private MemberRepository memberRepository; - - @Mock - private MemberPrincipalService memberPrincipalService; - - @Mock - private OAuth2UserInfo oAuth2UserInfo; + @InjectMocks private MemberAuthorityProvider memberAuthorityProvider; + @Mock private MemberRepository memberRepository; - @BeforeEach - public void setUp() { - given(oAuth2UserInfo.getEmail()).willReturn("my@gmail.com"); - given(oAuth2UserInfo.getId()).willReturn("12345"); - given(oAuth2UserInfo.getProvider()).willReturn(OAuth2Provider.GOOGLE); - } + @Mock private MemberPrincipalService memberPrincipalService; + @Mock private OAuth2UserInfo oAuth2UserInfo; - @Test - @DisplayName("기존회원의 권한을 들고온다.") - public void memberLoginTest() { + @BeforeEach + public void setUp() { + given(oAuth2UserInfo.getEmail()).willReturn("my@gmail.com"); + given(oAuth2UserInfo.getId()).willReturn("12345"); + given(oAuth2UserInfo.getProvider()).willReturn(OAuth2Provider.GOOGLE); + } - given(memberPrincipalService.loadUserPrincipal(any())).willReturn(1L); - MemberAuthorityProvider.RoleDto roleDto = - new MemberAuthorityProvider.RoleDto(Role.BASIC); - given(memberRepository.fetchRoleByStudentId(any())).willReturn(roleDto); + @Test + @DisplayName("기존회원의 권한을 들고온다.") + public void memberLoginTest() { - //when - Collection simpleGrantedAuthorities = - memberAuthorityProvider.determineAuthorities(oAuth2UserInfo); + given(memberPrincipalService.loadUserPrincipal(any())).willReturn(1L); + MemberAuthorityProvider.RoleDto roleDto = new MemberAuthorityProvider.RoleDto(Role.BASIC); + given(memberRepository.fetchRoleByStudentId(any())).willReturn(roleDto); - //then - assertThat(simpleGrantedAuthorities).containsExactly(new SimpleGrantedAuthority("ROLE_BASIC")); + // when + Collection simpleGrantedAuthorities = + memberAuthorityProvider.determineAuthorities(oAuth2UserInfo); - } + // then + assertThat(simpleGrantedAuthorities).containsExactly(new SimpleGrantedAuthority("ROLE_BASIC")); + } - @Test - @DisplayName("OAuth 인증을 했지만 회원가입을 완료하지 않았다면 SIGNING_UP 권한 부여") - public void cannotFindProfileMappedFromSocialAccount() { - given(memberPrincipalService.loadUserPrincipal(any())).willReturn(null); - given(memberRepository.findByProviderAndUid(any(), any())) - .willReturn(Optional.of(MemberTest.signingUpMember1())); + @Test + @DisplayName("OAuth 인증을 했지만 회원가입을 완료하지 않았다면 SIGNING_UP 권한 부여") + public void cannotFindProfileMappedFromSocialAccount() { + given(memberPrincipalService.loadUserPrincipal(any())).willReturn(null); + given(memberRepository.findByProviderAndUid(any(), any())) + .willReturn(Optional.of(MemberTest.signingUpMember1())); - Collection simpleGrantedAuthorities = - memberAuthorityProvider.determineAuthorities(oAuth2UserInfo); + Collection simpleGrantedAuthorities = + memberAuthorityProvider.determineAuthorities(oAuth2UserInfo); - //then - assertThat(simpleGrantedAuthorities).containsExactly(new SimpleGrantedAuthority("ROLE_SIGNING_UP")); - } + // then + assertThat(simpleGrantedAuthorities) + .containsExactly(new SimpleGrantedAuthority("ROLE_SIGNING_UP")); + } } diff --git a/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/member/security/MemberPrincipalServiceTest.java b/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/member/security/MemberPrincipalServiceTest.java index 5ea08bc8..a31a9351 100644 --- a/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/member/security/MemberPrincipalServiceTest.java +++ b/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/member/security/MemberPrincipalServiceTest.java @@ -1,46 +1,48 @@ package com.inhabas.api.auth.domain.oauth2.member.security; -import com.inhabas.api.auth.domain.oauth2.socialAccount.repository.MemberSocialAccountRepository; -import com.inhabas.api.auth.domain.oauth2.userInfo.OAuth2UserInfoAuthentication; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -import java.util.Optional; - import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.given; import static org.mockito.BDDMockito.then; import static org.mockito.Mockito.times; -@ExtendWith(MockitoExtension.class) -public class MemberPrincipalServiceTest { - - @InjectMocks - private MemberPrincipalService memberPrincipalService; - - @Mock - private MemberSocialAccountRepository memberSocialAccountRepository; +import java.util.Optional; - @Test - @DisplayName("기존회원을 uid 와 provider 로 찾는다.") - public void findMemberByUidAndProvider() { - //given - given(memberSocialAccountRepository.findMemberIdByUidAndProvider(any(), any())) - .willReturn(Optional.of(1L)); +import com.inhabas.api.auth.domain.oauth2.socialAccount.repository.MemberSocialAccountRepository; +import com.inhabas.api.auth.domain.oauth2.userInfo.OAuth2UserInfoAuthentication; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; - //when - Long memberId - = (Long) memberPrincipalService.loadUserPrincipal(new OAuth2UserInfoAuthentication("1234579123", "KAKAO", "my@gmail.com")); +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; - //then - assertThat(memberId).isEqualTo(1L); - then(memberSocialAccountRepository).should(times(1)).findMemberIdByUidAndProvider(any(), any()); - then(memberSocialAccountRepository).should(times(0)).findMemberSocialAccountByEmailAndProvider(any(), any()); - } +@ExtendWith(MockitoExtension.class) +public class MemberPrincipalServiceTest { + @InjectMocks private MemberPrincipalService memberPrincipalService; + + @Mock private MemberSocialAccountRepository memberSocialAccountRepository; + + @Test + @DisplayName("기존회원을 uid 와 provider 로 찾는다.") + public void findMemberByUidAndProvider() { + // given + given(memberSocialAccountRepository.findMemberIdByUidAndProvider(any(), any())) + .willReturn(Optional.of(1L)); + + // when + Long memberId = + (Long) + memberPrincipalService.loadUserPrincipal( + new OAuth2UserInfoAuthentication("1234579123", "KAKAO", "my@gmail.com")); + + // then + assertThat(memberId).isEqualTo(1L); + then(memberSocialAccountRepository).should(times(1)).findMemberIdByUidAndProvider(any(), any()); + then(memberSocialAccountRepository) + .should(times(0)) + .findMemberSocialAccountByEmailAndProvider(any(), any()); + } } diff --git a/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/member/service/MemberDuplicationCheckerTest.java b/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/member/service/MemberDuplicationCheckerTest.java index 019aa9e1..f68503aa 100644 --- a/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/member/service/MemberDuplicationCheckerTest.java +++ b/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/member/service/MemberDuplicationCheckerTest.java @@ -1,76 +1,80 @@ package com.inhabas.api.auth.domain.oauth2.member.service; +import static com.inhabas.api.auth.domain.oauth2.member.domain.entity.MemberTest.signingUpMember1; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.mockito.BDDMockito.then; +import static org.mockito.Mockito.times; + import com.inhabas.api.auth.domain.oauth2.OAuth2Provider; import com.inhabas.api.auth.domain.oauth2.member.dto.MemberDuplicationQueryCondition; import com.inhabas.api.auth.domain.oauth2.member.repository.MemberRepository; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import static com.inhabas.api.auth.domain.oauth2.member.domain.entity.MemberTest.signingUpMember1; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.given; -import static org.mockito.BDDMockito.then; -import static org.mockito.Mockito.times; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; @ExtendWith(MockitoExtension.class) public class MemberDuplicationCheckerTest { - @InjectMocks - MemberDuplicationCheckerImpl memberDuplicationChecker; - - @Mock - MemberRepository memberRepository; - - @DisplayName("회원 필드 전체를 중복검사한 결과 신규회원이다. ") - @Test - public void nonDuplicatedMemberTest() { - //given - given(memberRepository.existsByProviderAndUid(any(), any())).willReturn(false); - - //when - Assertions.assertFalse(memberDuplicationChecker.isDuplicatedMember(signingUpMember1())); - then(memberRepository).should(times(1)).existsByProviderAndUid(any(), any()); - } - - - @DisplayName("회원 필드 전체를 중복검사한 결과 중복회원이다.") - @Test - public void duplicatedMemberTest() { - //given - given(memberRepository.existsByProviderAndUid(any(), any())).willReturn(true); - - //when - Assertions.assertTrue(memberDuplicationChecker.isDuplicatedMember(signingUpMember1())); - then(memberRepository).should(times(1)).existsByProviderAndUid(any(), any()); - } - - - @DisplayName("db 에 없는 회원 uid 를 중복검사한다.") - @Test - public void notDuplicatedUidTest() { - //given - given(memberRepository.isDuplicated(any(MemberDuplicationQueryCondition.class))).willReturn(false); - - //when - Assertions.assertFalse(memberDuplicationChecker.isDuplicatedMember( - new MemberDuplicationQueryCondition(OAuth2Provider.GOOGLE, "12312312312312"))); - then(memberRepository).should(times(1)).isDuplicated(any(MemberDuplicationQueryCondition.class)); - } - - @DisplayName("db 에 존재하는 uid 를 중복검사한다.") - @Test - public void duplicatedUidTest() { - given(memberRepository.isDuplicated(any(MemberDuplicationQueryCondition.class))).willReturn(true); - - //when - Assertions.assertTrue(memberDuplicationChecker.isDuplicatedMember( - new MemberDuplicationQueryCondition(OAuth2Provider.GOOGLE, "12312312312312"))); - then(memberRepository).should(times(1)).isDuplicated(any(MemberDuplicationQueryCondition.class)); - } - + @InjectMocks MemberDuplicationCheckerImpl memberDuplicationChecker; + + @Mock MemberRepository memberRepository; + + @DisplayName("회원 필드 전체를 중복검사한 결과 신규회원이다. ") + @Test + public void nonDuplicatedMemberTest() { + // given + given(memberRepository.existsByProviderAndUid(any(), any())).willReturn(false); + + // when + Assertions.assertFalse(memberDuplicationChecker.isDuplicatedMember(signingUpMember1())); + then(memberRepository).should(times(1)).existsByProviderAndUid(any(), any()); + } + + @DisplayName("회원 필드 전체를 중복검사한 결과 중복회원이다.") + @Test + public void duplicatedMemberTest() { + // given + given(memberRepository.existsByProviderAndUid(any(), any())).willReturn(true); + + // when + Assertions.assertTrue(memberDuplicationChecker.isDuplicatedMember(signingUpMember1())); + then(memberRepository).should(times(1)).existsByProviderAndUid(any(), any()); + } + + @DisplayName("db 에 없는 회원 uid 를 중복검사한다.") + @Test + public void notDuplicatedUidTest() { + // given + given(memberRepository.isDuplicated(any(MemberDuplicationQueryCondition.class))) + .willReturn(false); + + // when + Assertions.assertFalse( + memberDuplicationChecker.isDuplicatedMember( + new MemberDuplicationQueryCondition(OAuth2Provider.GOOGLE, "12312312312312"))); + then(memberRepository) + .should(times(1)) + .isDuplicated(any(MemberDuplicationQueryCondition.class)); + } + + @DisplayName("db 에 존재하는 uid 를 중복검사한다.") + @Test + public void duplicatedUidTest() { + given(memberRepository.isDuplicated(any(MemberDuplicationQueryCondition.class))) + .willReturn(true); + + // when + Assertions.assertTrue( + memberDuplicationChecker.isDuplicatedMember( + new MemberDuplicationQueryCondition(OAuth2Provider.GOOGLE, "12312312312312"))); + then(memberRepository) + .should(times(1)) + .isDuplicated(any(MemberDuplicationQueryCondition.class)); + } } diff --git a/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/member/service/MemberServiceTest.java b/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/member/service/MemberServiceTest.java index 31d4f699..e72bdec8 100644 --- a/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/member/service/MemberServiceTest.java +++ b/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/member/service/MemberServiceTest.java @@ -1,211 +1,200 @@ package com.inhabas.api.auth.domain.oauth2.member.service; +import static com.inhabas.api.auth.domain.oauth2.member.domain.entity.MemberTest.*; +import static com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.Role.EXECUTIVES; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.mockito.BDDMockito.then; +import static org.mockito.Mockito.times; + +import java.util.List; +import java.util.Optional; import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; import com.inhabas.api.auth.domain.oauth2.member.dto.*; import com.inhabas.api.auth.domain.oauth2.member.repository.MemberRepository; import com.inhabas.api.auth.domain.oauth2.member.repository.UpdateNameRequestRepository; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -import java.util.List; -import java.util.Optional; - -import static com.inhabas.api.auth.domain.oauth2.member.domain.entity.MemberTest.*; -import static com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.Role.EXECUTIVES; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.given; -import static org.mockito.BDDMockito.then; -import static org.mockito.Mockito.times; @ExtendWith(MockitoExtension.class) public class MemberServiceTest { - @InjectMocks - MemberServiceImpl memberService; - @Mock - MemberRepository memberRepository; - @Mock - UpdateNameRequestRepository updateNameRequestRepository; - - - @DisplayName("미승인 회원을 [역할과 {학번 or 이름}] 으로 조회한다.") - @Test - void getNotApprovedMembersBySearchAndRoleTest() { - //given - Member member = notapprovedMember(); - given(memberRepository.findAllByRoleAndStudentIdLike(any(), any())).willReturn(List.of(member)); - NotApprovedMemberManagementDto notApprovedMemberManagementDto = - new NotApprovedMemberManagementDto( - member.getName(), - member.getId(), - member.getStudentId(), - member.getPhone(), - member.getEmail(), - member.getSchoolInformation().getGrade(), - member.getSchoolInformation().getMajor()); - - //when - List notApprovedMemberManagementDtos = - memberService.getNotApprovedMembersBySearchAndRole("12171707"); - - //then - assertThat(notApprovedMemberManagementDtos.get(0).getMemberId()).isEqualTo(notApprovedMemberManagementDto.getMemberId()); - - } - - @DisplayName("비활동이상 회원을 [역할과 {학번 or 이름}] 으로 조회한다.") - @Test - void getApprovedMembersBySearchAndRole() { - //given - Member member = deactivatedMember(); - given(memberRepository.findAllByRolesInAndStudentIdLike(any(), any())).willReturn(List.of(member)); - ApprovedMemberManagementDto approvedMemberManagementDto = - new ApprovedMemberManagementDto( - member.getName(), - member.getId(), - member.getStudentId(), - member.getPhone(), - member.getRole(), - member.getSchoolInformation().getGeneration(), - member.getSchoolInformation().getMajor()); - - //when - List approvedMemberManagementDtos = - memberService.getApprovedMembersBySearchAndRole("12171707"); - - //then - assertThat(approvedMemberManagementDtos.get(0).getMemberId()).isEqualTo(approvedMemberManagementDto.getMemberId()); - - } - - @DisplayName("미승인 회원들을 합격하거나 불합격한다.") - @ParameterizedTest - @ValueSource(strings = {"pass", "fail"}) - void updateUnapprovedMembersTest(String state) { - //given - Member member = notapprovedMember(); - given(memberRepository.findAllById(any())).willReturn(List.of(member)); - - //when - memberService.updateUnapprovedMembers(any(), state); - - //then - if (state.equals("pass")) - then(memberRepository).should(times(1)).saveAll(any()); - else if (state.equals("fail")) - then(memberRepository).should(times(1)).deleteAll(any()); - - } - - @DisplayName("비활동 이상 회원들의 역할을 가능한 만큼만 수정한다.") - @Test - void updateApprovedMembersTest() { - //given - Member member = deactivatedMember(); - given(memberRepository.findAllById(any())).willReturn(List.of(member)); - - //when - memberService.updateApprovedMembers(List.of(1L), EXECUTIVES); - - //then - then(memberRepository).should(times(1)).saveAll(any()); - - } - - @DisplayName("회장 연락처 조회한다.") - @Test - public void getChiefContactTest() { - //given - Member member = chiefMember(); - given(memberRepository.findByIbasInformation_Role(any())).willReturn(member); - - //when - ContactDto chiefContact = memberService.getChiefContact(); - - //then - assertThat(chiefContact.getEmail()).isEqualTo(member.getEmail()); - assertThat(chiefContact.getPhoneNumber()).isEqualTo(member.getPhone()); - assertThat(chiefContact.getName()).isEqualTo(member.getName()); - } - - @DisplayName("내 정보를 조회한다.") - @Test - void getMyProfileTest() { - //given - Member member = basicMember(); - given(memberRepository.findById(any())).willReturn(Optional.of(member)); - - //when - MyProfileDto myProfileDto = memberService.getMyProfile(any()); - - //then - assertThat(myProfileDto.getName()).isEqualTo(member.getName()); - assertThat(myProfileDto.getStudentId()).isEqualTo(member.getStudentId()); - assertThat(myProfileDto.getMajor()).isEqualTo(member.getSchoolInformation().getMajor()); - assertThat(myProfileDto.getGrade()).isEqualTo(member.getSchoolInformation().getGrade()); - assertThat(myProfileDto.getEmail()).isEqualTo(member.getEmail()); - assertThat(myProfileDto.getPhoneNumber()).isEqualTo(member.getPhone()); - assertThat(myProfileDto.getRole()).isEqualTo(member.getRole()); - assertThat(myProfileDto.getType()).isEqualTo(member.getSchoolInformation().getMemberType()); - assertThat(myProfileDto.getIntroduce()).isEqualTo(member.getIbasInformation().getIntroduce()); - - } - - @DisplayName("내 정보 [학년, 전공, 전화번호] 를 수정한다.") - @Test - void updateMyProfileDetailTest() { - //given - Member member = basicMember(); - given(memberRepository.findById(any())).willReturn(Optional.of(member)); - ProfileDetailDto profileDetailDto = new ProfileDetailDto("경영학과", null, null); - - //when - memberService.updateMyProfileDetail(any(), profileDetailDto); - - //then - assertThat(member.getSchoolInformation().getMajor()).isEqualTo(profileDetailDto.getMajor()); - - } - - @DisplayName("내 정보 [자기소개] 를 수정한다.") - @Test - void updateMyProfileIntroTest() { - //given - Member member = basicMember(); - given(memberRepository.findById(any())).willReturn(Optional.of(member)); - ProfileIntroDto profileIntroDto = new ProfileIntroDto("HELLO", true); - - //when - memberService.updateMyProfileIntro(any(), profileIntroDto); - - //then - assertThat(member.getIbasInformation().getIntroduce()).isEqualTo(profileIntroDto.getIntroduce()); - assertThat(member.getIbasInformation().getIsHOF()).isEqualTo(profileIntroDto.getIsHOF()); - - } - - @DisplayName("내 정보 [이름] 을 수정 요청을 한다.") - @Test - void requestMyProfileNameTest() { - //given - Member member = basicMember(); - given(memberRepository.findById(any())).willReturn(Optional.of(member)); - ProfileNameDto profileNameDto = new ProfileNameDto("유동현"); - - //when - memberService.requestMyProfileName(any(), profileNameDto); - - //then - then(updateNameRequestRepository).should(times(1)).save(any()); - - } - + @InjectMocks MemberServiceImpl memberService; + @Mock MemberRepository memberRepository; + @Mock UpdateNameRequestRepository updateNameRequestRepository; + + @DisplayName("미승인 회원을 [역할과 {학번 or 이름}] 으로 조회한다.") + @Test + void getNotApprovedMembersBySearchAndRoleTest() { + // given + Member member = notapprovedMember(); + given(memberRepository.findAllByRoleAndStudentIdLike(any(), any())).willReturn(List.of(member)); + NotApprovedMemberManagementDto notApprovedMemberManagementDto = + new NotApprovedMemberManagementDto( + member.getName(), + member.getId(), + member.getStudentId(), + member.getPhone(), + member.getEmail(), + member.getSchoolInformation().getGrade(), + member.getSchoolInformation().getMajor()); + + // when + List notApprovedMemberManagementDtos = + memberService.getNotApprovedMembersBySearchAndRole("12171707"); + + // then + assertThat(notApprovedMemberManagementDtos.get(0).getMemberId()) + .isEqualTo(notApprovedMemberManagementDto.getMemberId()); + } + + @DisplayName("비활동이상 회원을 [역할과 {학번 or 이름}] 으로 조회한다.") + @Test + void getApprovedMembersBySearchAndRole() { + // given + Member member = deactivatedMember(); + given(memberRepository.findAllByRolesInAndStudentIdLike(any(), any())) + .willReturn(List.of(member)); + ApprovedMemberManagementDto approvedMemberManagementDto = + new ApprovedMemberManagementDto( + member.getName(), + member.getId(), + member.getStudentId(), + member.getPhone(), + member.getRole(), + member.getSchoolInformation().getGeneration(), + member.getSchoolInformation().getMajor()); + + // when + List approvedMemberManagementDtos = + memberService.getApprovedMembersBySearchAndRole("12171707"); + + // then + assertThat(approvedMemberManagementDtos.get(0).getMemberId()) + .isEqualTo(approvedMemberManagementDto.getMemberId()); + } + + @DisplayName("미승인 회원들을 합격하거나 불합격한다.") + @ParameterizedTest + @ValueSource(strings = {"pass", "fail"}) + void updateUnapprovedMembersTest(String state) { + // given + Member member = notapprovedMember(); + given(memberRepository.findAllById(any())).willReturn(List.of(member)); + + // when + memberService.updateUnapprovedMembers(any(), state); + + // then + if (state.equals("pass")) then(memberRepository).should(times(1)).saveAll(any()); + else if (state.equals("fail")) then(memberRepository).should(times(1)).deleteAll(any()); + } + + @DisplayName("비활동 이상 회원들의 역할을 가능한 만큼만 수정한다.") + @Test + void updateApprovedMembersTest() { + // given + Member member = deactivatedMember(); + given(memberRepository.findAllById(any())).willReturn(List.of(member)); + + // when + memberService.updateApprovedMembers(List.of(1L), EXECUTIVES); + + // then + then(memberRepository).should(times(1)).saveAll(any()); + } + + @DisplayName("회장 연락처 조회한다.") + @Test + public void getChiefContactTest() { + // given + Member member = chiefMember(); + given(memberRepository.findByIbasInformation_Role(any())).willReturn(member); + + // when + ContactDto chiefContact = memberService.getChiefContact(); + + // then + assertThat(chiefContact.getEmail()).isEqualTo(member.getEmail()); + assertThat(chiefContact.getPhoneNumber()).isEqualTo(member.getPhone()); + assertThat(chiefContact.getName()).isEqualTo(member.getName()); + } + + @DisplayName("내 정보를 조회한다.") + @Test + void getMyProfileTest() { + // given + Member member = basicMember(); + given(memberRepository.findById(any())).willReturn(Optional.of(member)); + + // when + MyProfileDto myProfileDto = memberService.getMyProfile(any()); + + // then + assertThat(myProfileDto.getName()).isEqualTo(member.getName()); + assertThat(myProfileDto.getStudentId()).isEqualTo(member.getStudentId()); + assertThat(myProfileDto.getMajor()).isEqualTo(member.getSchoolInformation().getMajor()); + assertThat(myProfileDto.getGrade()).isEqualTo(member.getSchoolInformation().getGrade()); + assertThat(myProfileDto.getEmail()).isEqualTo(member.getEmail()); + assertThat(myProfileDto.getPhoneNumber()).isEqualTo(member.getPhone()); + assertThat(myProfileDto.getRole()).isEqualTo(member.getRole()); + assertThat(myProfileDto.getType()).isEqualTo(member.getSchoolInformation().getMemberType()); + assertThat(myProfileDto.getIntroduce()).isEqualTo(member.getIbasInformation().getIntroduce()); + } + + @DisplayName("내 정보 [학년, 전공, 전화번호] 를 수정한다.") + @Test + void updateMyProfileDetailTest() { + // given + Member member = basicMember(); + given(memberRepository.findById(any())).willReturn(Optional.of(member)); + ProfileDetailDto profileDetailDto = new ProfileDetailDto("경영학과", null, null); + + // when + memberService.updateMyProfileDetail(any(), profileDetailDto); + + // then + assertThat(member.getSchoolInformation().getMajor()).isEqualTo(profileDetailDto.getMajor()); + } + + @DisplayName("내 정보 [자기소개] 를 수정한다.") + @Test + void updateMyProfileIntroTest() { + // given + Member member = basicMember(); + given(memberRepository.findById(any())).willReturn(Optional.of(member)); + ProfileIntroDto profileIntroDto = new ProfileIntroDto("HELLO", true); + + // when + memberService.updateMyProfileIntro(any(), profileIntroDto); + + // then + assertThat(member.getIbasInformation().getIntroduce()) + .isEqualTo(profileIntroDto.getIntroduce()); + assertThat(member.getIbasInformation().getIsHOF()).isEqualTo(profileIntroDto.getIsHOF()); + } + + @DisplayName("내 정보 [이름] 을 수정 요청을 한다.") + @Test + void requestMyProfileNameTest() { + // given + Member member = basicMember(); + given(memberRepository.findById(any())).willReturn(Optional.of(member)); + ProfileNameDto profileNameDto = new ProfileNameDto("유동현"); + + // when + memberService.requestMyProfileName(any(), profileNameDto); + + // then + then(updateNameRequestRepository).should(times(1)).save(any()); + } } diff --git a/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/socialAccount/domain/valueObject/UidTest.java b/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/socialAccount/domain/valueObject/UidTest.java index 97d127ea..3b1b8dc4 100644 --- a/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/socialAccount/domain/valueObject/UidTest.java +++ b/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/socialAccount/domain/valueObject/UidTest.java @@ -1,52 +1,50 @@ package com.inhabas.api.auth.domain.oauth2.socialAccount.domain.valueObject; -import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; - import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertThrows; -public class UidTest { +import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; - @DisplayName("UID 타입에 uid 를 저장한다.") - @Test - public void UID_is_OK() { - //given - String uidString = "1234"; - - //when - UID uid = new UID(uidString); - - //then - assertThat(uid.getValue()).isEqualTo("1234"); - } - - @DisplayName("UID 타입에 너무 긴 제목을 저장한다. 191자 초과") - @Test - public void UID_is_too_long() { - //given - String okString = "지금이문장은10자임".repeat(19) + "."; - String notOkString = "지금이문장은10자임".repeat(100) + ".."; - - //then - assertDoesNotThrow(() -> new UID(okString)); - assertThrows(InvalidInputException.class, () -> new UID(notOkString)); - } - - @DisplayName("UID 은 null 일 수 없습니다.") - @Test - public void UID_cannot_be_Null() { - assertThrows(InvalidInputException.class, - () -> new UID(null)); - } - - @DisplayName("UID 은 빈 문자열일 수 없습니다.") - @Test - public void UID_cannot_be_Blank() { - assertThrows(InvalidInputException.class, - () -> new UID("\t")); - } +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +public class UidTest { + @DisplayName("UID 타입에 uid 를 저장한다.") + @Test + public void UID_is_OK() { + // given + String uidString = "1234"; + + // when + UID uid = new UID(uidString); + + // then + assertThat(uid.getValue()).isEqualTo("1234"); + } + + @DisplayName("UID 타입에 너무 긴 제목을 저장한다. 191자 초과") + @Test + public void UID_is_too_long() { + // given + String okString = "지금이문장은10자임".repeat(19) + "."; + String notOkString = "지금이문장은10자임".repeat(100) + ".."; + + // then + assertDoesNotThrow(() -> new UID(okString)); + assertThrows(InvalidInputException.class, () -> new UID(notOkString)); + } + + @DisplayName("UID 은 null 일 수 없습니다.") + @Test + public void UID_cannot_be_Null() { + assertThrows(InvalidInputException.class, () -> new UID(null)); + } + + @DisplayName("UID 은 빈 문자열일 수 없습니다.") + @Test + public void UID_cannot_be_Blank() { + assertThrows(InvalidInputException.class, () -> new UID("\t")); + } } diff --git a/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/socialAccount/repository/MemberSocialAccountRepositoryTest.java b/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/socialAccount/repository/MemberSocialAccountRepositoryTest.java index 461b6272..c75c0ed0 100644 --- a/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/socialAccount/repository/MemberSocialAccountRepositoryTest.java +++ b/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/socialAccount/repository/MemberSocialAccountRepositoryTest.java @@ -1,61 +1,65 @@ package com.inhabas.api.auth.domain.oauth2.socialAccount.repository; +import static com.inhabas.api.auth.domain.oauth2.OAuth2Provider.GOOGLE; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.Optional; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager; + import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; import com.inhabas.api.auth.domain.oauth2.member.domain.entity.MemberTest; import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.Email; import com.inhabas.api.auth.domain.oauth2.socialAccount.domain.entity.MemberSocialAccount; import com.inhabas.api.auth.domain.oauth2.socialAccount.domain.valueObject.UID; import com.inhabas.api.auth.testAnnotation.DefaultDataJpaTest; + import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager; - -import java.util.Optional; - -import static com.inhabas.api.auth.domain.oauth2.OAuth2Provider.GOOGLE; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertTrue; @DefaultDataJpaTest public class MemberSocialAccountRepositoryTest { - @Autowired - private MemberSocialAccountRepository memberSocialAccountRepository; - - @Autowired - private TestEntityManager em; + @Autowired private MemberSocialAccountRepository memberSocialAccountRepository; - @DisplayName("소셜계정으로 회원의 학번을 가져온다.") - @Test - public void getStudentIdBySocialAccount() { - //given - Member member = em.persist(MemberTest.signingUpMember1()); - memberSocialAccountRepository.save(new MemberSocialAccount(member, "my@gmail.com", "1234", GOOGLE)); + @Autowired private TestEntityManager em; - //when - Optional id = - memberSocialAccountRepository.findMemberIdByUidAndProvider(new UID("1234"), GOOGLE); + @DisplayName("소셜계정으로 회원의 학번을 가져온다.") + @Test + public void getStudentIdBySocialAccount() { + // given + Member member = em.persist(MemberTest.signingUpMember1()); + memberSocialAccountRepository.save( + new MemberSocialAccount(member, "my@gmail.com", "1234", GOOGLE)); - //then - assertTrue(id.isPresent()); - assertThat(id.get()).isEqualTo(member.getId()); - } + // when + Optional id = + memberSocialAccountRepository.findMemberIdByUidAndProvider(new UID("1234"), GOOGLE); - @DisplayName("memberId로 회원가입이 되어있는지 확인한다.") - @Test - public void checkSignUp() { - //given - Member member = em.persist(MemberTest.basicMember()); - memberSocialAccountRepository.save(new MemberSocialAccount(member, "my@gmail.com", "1234", GOOGLE)); - Optional memberSocialAccount = - memberSocialAccountRepository.findMemberSocialAccountByEmailAndProvider(new Email("my@gmail.com"), GOOGLE); + // then + assertTrue(id.isPresent()); + assertThat(id.get()).isEqualTo(member.getId()); + } - //when - boolean check = memberSocialAccountRepository.existsByMember_Id(memberSocialAccount.get().getMember().getId()); + @DisplayName("memberId로 회원가입이 되어있는지 확인한다.") + @Test + public void checkSignUp() { + // given + Member member = em.persist(MemberTest.basicMember()); + memberSocialAccountRepository.save( + new MemberSocialAccount(member, "my@gmail.com", "1234", GOOGLE)); + Optional memberSocialAccount = + memberSocialAccountRepository.findMemberSocialAccountByEmailAndProvider( + new Email("my@gmail.com"), GOOGLE); - //then - assertThat(check).isEqualTo(true); - } + // when + boolean check = + memberSocialAccountRepository.existsByMember_Id( + memberSocialAccount.get().getMember().getId()); + // then + assertThat(check).isEqualTo(true); + } } diff --git a/module-auth/src/test/java/com/inhabas/api/auth/domain/token/JwtControllerTest.java b/module-auth/src/test/java/com/inhabas/api/auth/domain/token/JwtControllerTest.java index 7a02abff..dba9f263 100644 --- a/module-auth/src/test/java/com/inhabas/api/auth/domain/token/JwtControllerTest.java +++ b/module-auth/src/test/java/com/inhabas/api/auth/domain/token/JwtControllerTest.java @@ -8,10 +8,6 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.inhabas.api.auth.domain.token.controller.JwtTokenController; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; @@ -20,37 +16,41 @@ import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MockMvc; -@ComponentScan(basePackages = "com.inhabas.api.auth.domain.token.controller") -@WebMvcTest(value = JwtTokenController.class, excludeAutoConfiguration = SecurityAutoConfiguration.class) -public class JwtControllerTest { - - @Autowired - private MockMvc mockMvc; - - @MockBean - private TokenReIssuer tokenReIssuer; - - @Autowired - private ObjectMapper objectMapper; - +import com.fasterxml.jackson.databind.ObjectMapper; +import com.inhabas.api.auth.domain.token.controller.JwtTokenController; - @DisplayName("accessToken 재발급") - @Test - public void reissueAccessTokenTest() throws Exception { - //given - TokenDto expectedNewTokenDto = - new TokenDto("Bearer", "accessToken", "", 1L); - given(tokenReIssuer.reissueAccessToken(any())).willReturn(expectedNewTokenDto); - String requestJson = "{\"refreshToken\":\"helloworld\"}"; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; - //when - mockMvc.perform(post("/token/refresh") - .with(csrf()) - .contentType(MediaType.APPLICATION_JSON) - .content(requestJson)) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.grantType").value(equalTo("Bearer"))) - .andExpect(jsonPath("$.accessToken").value(equalTo("accessToken"))); - } +@ComponentScan(basePackages = "com.inhabas.api.auth.domain.token.controller") +@WebMvcTest( + value = JwtTokenController.class, + excludeAutoConfiguration = SecurityAutoConfiguration.class) +public class JwtControllerTest { + @Autowired private MockMvc mockMvc; + + @MockBean private TokenReIssuer tokenReIssuer; + + @Autowired private ObjectMapper objectMapper; + + @DisplayName("accessToken 재발급") + @Test + public void reissueAccessTokenTest() throws Exception { + // given + TokenDto expectedNewTokenDto = new TokenDto("Bearer", "accessToken", "", 1L); + given(tokenReIssuer.reissueAccessToken(any())).willReturn(expectedNewTokenDto); + String requestJson = "{\"refreshToken\":\"helloworld\"}"; + + // when + mockMvc + .perform( + post("/token/refresh") + .with(csrf()) + .contentType(MediaType.APPLICATION_JSON) + .content(requestJson)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.grantType").value(equalTo("Bearer"))) + .andExpect(jsonPath("$.accessToken").value(equalTo("accessToken"))); + } } diff --git a/module-auth/src/test/java/com/inhabas/api/auth/domain/token/JwtTokenReIssueTest.java b/module-auth/src/test/java/com/inhabas/api/auth/domain/token/JwtTokenReIssueTest.java index 84e609e5..989014e7 100644 --- a/module-auth/src/test/java/com/inhabas/api/auth/domain/token/JwtTokenReIssueTest.java +++ b/module-auth/src/test/java/com/inhabas/api/auth/domain/token/JwtTokenReIssueTest.java @@ -1,78 +1,73 @@ package com.inhabas.api.auth.domain.token; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.mockito.BDDMockito.then; +import static org.mockito.Mockito.*; + +import javax.servlet.http.HttpServletRequest; + import com.inhabas.api.auth.domain.token.exception.InvalidTokenException; import com.inhabas.api.auth.domain.token.jwtUtils.JwtTokenReIssuer; import com.inhabas.api.auth.domain.token.jwtUtils.JwtTokenUtil; import com.inhabas.api.auth.domain.token.jwtUtils.refreshToken.RefreshTokenNotFoundException; import com.inhabas.api.auth.domain.token.jwtUtils.refreshToken.RefreshTokenRepository; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import javax.servlet.http.HttpServletRequest; - -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.given; -import static org.mockito.BDDMockito.then; -import static org.mockito.Mockito.*; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; @ExtendWith(MockitoExtension.class) public class JwtTokenReIssueTest { - @InjectMocks - private JwtTokenReIssuer tokenReIssuer; - - @Mock - private RefreshTokenRepository refreshTokenRepository; - - @Mock - private HttpServletRequest request; + @InjectMocks private JwtTokenReIssuer tokenReIssuer; - @Mock - private TokenResolver tokenResolver; + @Mock private RefreshTokenRepository refreshTokenRepository; - @Mock - private JwtTokenUtil jwtTokenUtil; + @Mock private HttpServletRequest request; + @Mock private TokenResolver tokenResolver; - @DisplayName("accessToken 을 재발급한다.") - @Test - public void reissueAccessTokenTest() { + @Mock private JwtTokenUtil jwtTokenUtil; - //given - given(refreshTokenRepository.existsByRefreshToken(any())).willReturn(true); + @DisplayName("accessToken 을 재발급한다.") + @Test + public void reissueAccessTokenTest() { - //when - tokenReIssuer.reissueAccessToken("refreshToken"); + // given + given(refreshTokenRepository.existsByRefreshToken(any())).willReturn(true); - //then - then(jwtTokenUtil).should(times(1)).reissueAccessTokenUsing(any()); - } + // when + tokenReIssuer.reissueAccessToken("refreshToken"); + // then + then(jwtTokenUtil).should(times(1)).reissueAccessTokenUsing(any()); + } - @DisplayName("db에 refreshToken 이 없으면, 유효한 토큰이어도 RefreshTokenNotFoundException 발생") - @Test - public void refreshTokenNotFoundExceptionTest() { - //given - given(refreshTokenRepository.existsByRefreshToken(any())).willReturn(false); + @DisplayName("db에 refreshToken 이 없으면, 유효한 토큰이어도 RefreshTokenNotFoundException 발생") + @Test + public void refreshTokenNotFoundExceptionTest() { + // given + given(refreshTokenRepository.existsByRefreshToken(any())).willReturn(false); - //when - assertThrows(RefreshTokenNotFoundException.class, - () -> tokenReIssuer.reissueAccessToken("refreshToken")); - } + // when + assertThrows( + RefreshTokenNotFoundException.class, + () -> tokenReIssuer.reissueAccessToken("refreshToken")); + } - @DisplayName("유효하지 않은 refreshToken 은 InvalidJwtTokenException") - @Test - public void invalidRefreshTokenTest() { - //given - doThrow(InvalidTokenException.class).when(jwtTokenUtil).validate(any()); + @DisplayName("유효하지 않은 refreshToken 은 InvalidJwtTokenException") + @Test + public void invalidRefreshTokenTest() { + // given + doThrow(InvalidTokenException.class).when(jwtTokenUtil).validate(any()); - //then - assertThrows(InvalidTokenException.class, - () -> tokenReIssuer.reissueAccessToken("refreshToken")); - } + // then + assertThrows( + InvalidTokenException.class, () -> tokenReIssuer.reissueAccessToken("refreshToken")); + } } diff --git a/module-auth/src/test/java/com/inhabas/api/auth/domain/token/JwtTokenResolverTest.java b/module-auth/src/test/java/com/inhabas/api/auth/domain/token/JwtTokenResolverTest.java index 6077dc1d..31937bab 100644 --- a/module-auth/src/test/java/com/inhabas/api/auth/domain/token/JwtTokenResolverTest.java +++ b/module-auth/src/test/java/com/inhabas/api/auth/domain/token/JwtTokenResolverTest.java @@ -1,63 +1,62 @@ package com.inhabas.api.auth.domain.token; +import static org.assertj.core.api.Assertions.assertThat; + +import org.springframework.mock.web.MockHttpServletRequest; + import com.inhabas.api.auth.domain.token.jwtUtils.JwtTokenResolver; import org.assertj.core.api.Assertions; + import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import org.springframework.mock.web.MockHttpServletRequest; - -import static org.assertj.core.api.Assertions.assertThat; - public class JwtTokenResolverTest { - private static final String VALID_AUTHORIZATION_HEADER = "Bearer header.body.signature"; - private static final String VALID_AUTHORIZATION_HEADER_RESULT = "header.body.signature"; - private static final String INVALID_AUTHORIZATION_HEADER = "No-Bearer header.body.signature"; - private static final String AUTHORIZATION = "Authorization"; - private final JwtTokenResolver jwtTokenResolver = new JwtTokenResolver(); - - @DisplayName("http request Authorization header 로부터 토큰을 꺼낸다.") - @Test - public void resolveTokenFromHttpRequestTest() { - - //given - MockHttpServletRequest request = new MockHttpServletRequest(); - request.addHeader(AUTHORIZATION, VALID_AUTHORIZATION_HEADER); - - //when - String resolvedToken = jwtTokenResolver.resolveAccessTokenOrNull(request); - - //then - assertThat(resolvedToken).isEqualTo(VALID_AUTHORIZATION_HEADER_RESULT); - } - - @DisplayName("http request 에 Authorization header 가 설정되어 있지 않아서 null을 반환한다.") - @Test - public void cannotResolveTokenFromHttpRequestTest() { - //given - MockHttpServletRequest request = new MockHttpServletRequest(); - - //when - String resolvedToken = jwtTokenResolver.resolveAccessTokenOrNull(request); - - //then - Assertions.assertThat(resolvedToken).isNull(); - - } - - @DisplayName("Bearer 토큰이 아니면 null 을 반환한다.") - @Test - public void cannotResolveInvalidTokenFromHttpRequestTest() { - //given - MockHttpServletRequest request = new MockHttpServletRequest(); - request.addHeader("Authorization", "No-Bearer header.body.signature"); - - //when - String resolvedToken = jwtTokenResolver.resolveAccessTokenOrNull(request); - - //then - Assertions.assertThat(resolvedToken).isNull(); - - } + private static final String VALID_AUTHORIZATION_HEADER = "Bearer header.body.signature"; + private static final String VALID_AUTHORIZATION_HEADER_RESULT = "header.body.signature"; + private static final String INVALID_AUTHORIZATION_HEADER = "No-Bearer header.body.signature"; + private static final String AUTHORIZATION = "Authorization"; + private final JwtTokenResolver jwtTokenResolver = new JwtTokenResolver(); + + @DisplayName("http request Authorization header 로부터 토큰을 꺼낸다.") + @Test + public void resolveTokenFromHttpRequestTest() { + + // given + MockHttpServletRequest request = new MockHttpServletRequest(); + request.addHeader(AUTHORIZATION, VALID_AUTHORIZATION_HEADER); + + // when + String resolvedToken = jwtTokenResolver.resolveAccessTokenOrNull(request); + + // then + assertThat(resolvedToken).isEqualTo(VALID_AUTHORIZATION_HEADER_RESULT); + } + + @DisplayName("http request 에 Authorization header 가 설정되어 있지 않아서 null을 반환한다.") + @Test + public void cannotResolveTokenFromHttpRequestTest() { + // given + MockHttpServletRequest request = new MockHttpServletRequest(); + + // when + String resolvedToken = jwtTokenResolver.resolveAccessTokenOrNull(request); + + // then + Assertions.assertThat(resolvedToken).isNull(); + } + + @DisplayName("Bearer 토큰이 아니면 null 을 반환한다.") + @Test + public void cannotResolveInvalidTokenFromHttpRequestTest() { + // given + MockHttpServletRequest request = new MockHttpServletRequest(); + request.addHeader("Authorization", "No-Bearer header.body.signature"); + + // when + String resolvedToken = jwtTokenResolver.resolveAccessTokenOrNull(request); + + // then + Assertions.assertThat(resolvedToken).isNull(); + } } diff --git a/module-auth/src/test/java/com/inhabas/api/auth/domain/token/JwtTokenUtilTest.java b/module-auth/src/test/java/com/inhabas/api/auth/domain/token/JwtTokenUtilTest.java index 54cfe57d..0787369e 100644 --- a/module-auth/src/test/java/com/inhabas/api/auth/domain/token/JwtTokenUtilTest.java +++ b/module-auth/src/test/java/com/inhabas/api/auth/domain/token/JwtTokenUtilTest.java @@ -1,120 +1,122 @@ package com.inhabas.api.auth.domain.token; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken; +import org.springframework.test.util.ReflectionTestUtils; + import com.inhabas.api.auth.domain.oauth2.CustomOAuth2User; import com.inhabas.api.auth.domain.token.exception.InvalidTokenException; import com.inhabas.api.auth.domain.token.jwtUtils.JwtAuthenticationToken; import com.inhabas.api.auth.domain.token.jwtUtils.JwtTokenUtil; import com.inhabas.api.auth.domain.token.jwtUtils.refreshToken.RefreshTokenRepository; import org.assertj.core.api.Assertions; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import org.springframework.security.core.authority.SimpleGrantedAuthority; -import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken; -import org.springframework.test.util.ReflectionTestUtils; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; -import static org.junit.jupiter.api.Assertions.assertThrows; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; @ExtendWith(MockitoExtension.class) public class JwtTokenUtilTest { - @Mock - private RefreshTokenRepository refreshTokenRepository; - - @InjectMocks - private JwtTokenUtil jwtTokenUtil; - - @BeforeEach - void setUp() { - ReflectionTestUtils.setField(jwtTokenUtil, "SECRET_KEY", "TESTTESTTESTTESTTESTTESTTESTTEST" + - "TESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTEST"); - } - - @DisplayName("access 토큰을 발급한다.") - @Test - public void createJwtTokenTest() { - //given - List authorities = - List.of(new SimpleGrantedAuthority("ROLE_ANONYMOUS")); - Map attributes = new HashMap<>() {{ + @Mock private RefreshTokenRepository refreshTokenRepository; + + @InjectMocks private JwtTokenUtil jwtTokenUtil; + + @BeforeEach + void setUp() { + ReflectionTestUtils.setField( + jwtTokenUtil, + "SECRET_KEY", + "TESTTESTTESTTESTTESTTESTTESTTEST" + + "TESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTESTTEST"); + } + + @DisplayName("access 토큰을 발급한다.") + @Test + public void createJwtTokenTest() { + // given + List authorities = + List.of(new SimpleGrantedAuthority("ROLE_ANONYMOUS")); + Map attributes = + new HashMap<>() { + { put("sub", "1249846925629348"); put("name", "유동현"); put("picture", "blahblah"); put("email", "my@gmail.com"); put("locale", "ko"); - }}; - OAuth2AuthenticationToken authentication = new OAuth2AuthenticationToken( - new CustomOAuth2User(authorities, attributes, "sub", 1L), - authorities, "google"); - - - - //when - String accessToken = jwtTokenUtil.createAccessToken(authentication); - - //then - assertThat(accessToken).isNotNull(); - assertThat(accessToken.chars() - .filter(ch -> ch == '.') - .count()) - .isEqualTo(2); - } - - - @DisplayName("토큰 생성 시 인증결과객체는 필수로 주어져야 한다.") - @Test - public void nullAuthenticationTokenTest() { - - assertThrows(AssertionError.class, - () -> jwtTokenUtil.createAccessToken(null)); - } - - - @DisplayName("토큰을 정상적으로 decode") - @Test - public void getAuthenticationUsingToken() { - //given - List authorities = List.of(new SimpleGrantedAuthority("ROLE_ANONYMOUS")); - Map attributes = new HashMap<>() {{ + } + }; + OAuth2AuthenticationToken authentication = + new OAuth2AuthenticationToken( + new CustomOAuth2User(authorities, attributes, "sub", 1L), authorities, "google"); + + // when + String accessToken = jwtTokenUtil.createAccessToken(authentication); + + // then + assertThat(accessToken).isNotNull(); + assertThat(accessToken.chars().filter(ch -> ch == '.').count()).isEqualTo(2); + } + + @DisplayName("토큰 생성 시 인증결과객체는 필수로 주어져야 한다.") + @Test + public void nullAuthenticationTokenTest() { + + assertThrows(AssertionError.class, () -> jwtTokenUtil.createAccessToken(null)); + } + + @DisplayName("토큰을 정상적으로 decode") + @Test + public void getAuthenticationUsingToken() { + // given + List authorities = + List.of(new SimpleGrantedAuthority("ROLE_ANONYMOUS")); + Map attributes = + new HashMap<>() { + { put("sub", "1249846925629348"); put("name", "유동현"); put("picture", "blahblah"); put("email", "my@gmail.com"); put("locale", "ko"); - }}; - OAuth2AuthenticationToken authentication = new OAuth2AuthenticationToken( - new CustomOAuth2User(authorities, attributes, "sub",1L), - authorities, "google"); - - String accessToken = jwtTokenUtil.createAccessToken(authentication); - - //when - JwtAuthenticationToken authenticationToken = jwtTokenUtil.getAuthentication(accessToken); - - //then - assertThat(authenticationToken.getPrincipal()).isEqualTo(1L); - assertThat(authenticationToken.getAuthorities()).isEqualTo(authorities); - } - - - @DisplayName("access 토큰을 재발급한다.") - @Test - public void reissueAccessToken() { - - //given - List authorities = - List.of(new SimpleGrantedAuthority("ROLE_USER")); - Map attributes = new HashMap<>() {{ + } + }; + OAuth2AuthenticationToken authentication = + new OAuth2AuthenticationToken( + new CustomOAuth2User(authorities, attributes, "sub", 1L), authorities, "google"); + + String accessToken = jwtTokenUtil.createAccessToken(authentication); + + // when + JwtAuthenticationToken authenticationToken = jwtTokenUtil.getAuthentication(accessToken); + + // then + assertThat(authenticationToken.getPrincipal()).isEqualTo(1L); + assertThat(authenticationToken.getAuthorities()).isEqualTo(authorities); + } + + @DisplayName("access 토큰을 재발급한다.") + @Test + public void reissueAccessToken() { + + // given + List authorities = List.of(new SimpleGrantedAuthority("ROLE_USER")); + Map attributes = + new HashMap<>() { + { put("sub", "1234567889"); put("name", "유동현"); put("given_name", "동현"); @@ -123,65 +125,66 @@ public void reissueAccessToken() { put("picture", "blahblah"); put("email", "my@gmail.com"); put("locale", "ko"); - }}; - OAuth2AuthenticationToken authentication = new OAuth2AuthenticationToken( - new CustomOAuth2User(authorities, attributes, "sub",1L), - authorities, - "google"); - String refreshToken = jwtTokenUtil.createRefreshToken(authentication); - - //when - TokenDto newTokenDto = jwtTokenUtil.reissueAccessTokenUsing(refreshToken); - - //then - //check new token dto - assertThat(newTokenDto.getRefreshToken()).isBlank(); - assertThat(newTokenDto.getExpiresIn()).isNotNull(); - assertThat(newTokenDto.getGrantType()).isEqualTo("Bearer"); - String newAccessToken = newTokenDto.getAccessToken(); - Assertions.assertThat(newAccessToken) - .isNotBlank(); - - //validation check for newly issued access token - JwtAuthenticationToken authenticateNewAccessToken = jwtTokenUtil.getAuthentication(newAccessToken); - - - assertThat(authenticateNewAccessToken.getPrincipal()).isEqualTo(1L); - assertThat(authenticateNewAccessToken.getAuthorities()).isEqualTo(authorities); - assertThat(authenticateNewAccessToken.getAuthorities()) - .extracting("role") - .contains("ROLE_USER"); - - } - - @DisplayName("유효하지 않은 토큰 string 을 검사한다.") - @Test - public void validateInvalidToken() { - - assertThrows(InvalidTokenException.class, - () -> jwtTokenUtil.validate("invalid-token-string")); - } - - @DisplayName("유효한 토큰 string 을 검사한다.") - @Test - public void validateValidToken() { - //given - List authorities = - List.of(new SimpleGrantedAuthority("ROLE_ANONYMOUS"), new SimpleGrantedAuthority("TEAM_IT")); - Map attributes = new HashMap<>() {{ + } + }; + OAuth2AuthenticationToken authentication = + new OAuth2AuthenticationToken( + new CustomOAuth2User(authorities, attributes, "sub", 1L), authorities, "google"); + String refreshToken = jwtTokenUtil.createRefreshToken(authentication); + + // when + TokenDto newTokenDto = jwtTokenUtil.reissueAccessTokenUsing(refreshToken); + + // then + // check new token dto + assertThat(newTokenDto.getRefreshToken()).isBlank(); + assertThat(newTokenDto.getExpiresIn()).isNotNull(); + assertThat(newTokenDto.getGrantType()).isEqualTo("Bearer"); + String newAccessToken = newTokenDto.getAccessToken(); + Assertions.assertThat(newAccessToken).isNotBlank(); + + // validation check for newly issued access token + JwtAuthenticationToken authenticateNewAccessToken = + jwtTokenUtil.getAuthentication(newAccessToken); + + assertThat(authenticateNewAccessToken.getPrincipal()).isEqualTo(1L); + assertThat(authenticateNewAccessToken.getAuthorities()).isEqualTo(authorities); + assertThat(authenticateNewAccessToken.getAuthorities()) + .extracting("role") + .contains("ROLE_USER"); + } + + @DisplayName("유효하지 않은 토큰 string 을 검사한다.") + @Test + public void validateInvalidToken() { + + assertThrows(InvalidTokenException.class, () -> jwtTokenUtil.validate("invalid-token-string")); + } + + @DisplayName("유효한 토큰 string 을 검사한다.") + @Test + public void validateValidToken() { + // given + List authorities = + List.of( + new SimpleGrantedAuthority("ROLE_ANONYMOUS"), new SimpleGrantedAuthority("TEAM_IT")); + Map attributes = + new HashMap<>() { + { put("sub", "1249846925629348"); put("name", "유동현"); put("picture", "blahblah"); put("email", "my@gmail.com"); put("locale", "ko"); - }}; - OAuth2AuthenticationToken authentication = new OAuth2AuthenticationToken( - new CustomOAuth2User(authorities, attributes, "sub",1L), - authorities, "google"); + } + }; + OAuth2AuthenticationToken authentication = + new OAuth2AuthenticationToken( + new CustomOAuth2User(authorities, attributes, "sub", 1L), authorities, "google"); - String accessToken = jwtTokenUtil.createAccessToken(authentication); + String accessToken = jwtTokenUtil.createAccessToken(authentication); - //then - assertDoesNotThrow(() -> jwtTokenUtil.validate(accessToken)); - } + // then + assertDoesNotThrow(() -> jwtTokenUtil.validate(accessToken)); + } } diff --git a/module-auth/src/test/java/com/inhabas/api/auth/domain/token/RefreshTokenRepositoryTest.java b/module-auth/src/test/java/com/inhabas/api/auth/domain/token/RefreshTokenRepositoryTest.java index 719a4f88..59f0de5f 100644 --- a/module-auth/src/test/java/com/inhabas/api/auth/domain/token/RefreshTokenRepositoryTest.java +++ b/module-auth/src/test/java/com/inhabas/api/auth/domain/token/RefreshTokenRepositoryTest.java @@ -1,40 +1,40 @@ package com.inhabas.api.auth.domain.token; +import org.springframework.beans.factory.annotation.Autowired; + import com.inhabas.api.auth.domain.token.jwtUtils.refreshToken.RefreshToken; import com.inhabas.api.auth.domain.token.jwtUtils.refreshToken.RefreshTokenRepository; import com.inhabas.api.auth.testAnnotation.DefaultDataJpaTest; import org.assertj.core.api.Assertions; + import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; @DefaultDataJpaTest public class RefreshTokenRepositoryTest { - @Autowired - private RefreshTokenRepository refreshTokenRepository; + @Autowired private RefreshTokenRepository refreshTokenRepository; - @DisplayName("리프레시 토큰이 db 에 존재한다.") - @Test - public void existRefreshTokenTest() { - //given - String jws = "header.claims.signature"; - RefreshToken refreshToken = new RefreshToken(jws); + @DisplayName("리프레시 토큰이 db 에 존재한다.") + @Test + public void existRefreshTokenTest() { + // given + String jws = "header.claims.signature"; + RefreshToken refreshToken = new RefreshToken(jws); - refreshTokenRepository.save(refreshToken); + refreshTokenRepository.save(refreshToken); - //then - Assertions.assertThat(refreshTokenRepository.existsByRefreshToken(jws)).isTrue(); - } + // then + Assertions.assertThat(refreshTokenRepository.existsByRefreshToken(jws)).isTrue(); + } - @DisplayName("리프레시 토큰이 db 에 존재하지 않는다.") - @Test - public void notExistRefreshTokenTest() { - //given - String jws = "header.claims.signature"; + @DisplayName("리프레시 토큰이 db 에 존재하지 않는다.") + @Test + public void notExistRefreshTokenTest() { + // given + String jws = "header.claims.signature"; - //then - Assertions.assertThat(refreshTokenRepository.existsByRefreshToken(jws)).isFalse(); - } + // then + Assertions.assertThat(refreshTokenRepository.existsByRefreshToken(jws)).isFalse(); + } } diff --git a/module-auth/src/test/java/com/inhabas/api/auth/domain/token/TokenAuthenticationProcessingFilterTest.java b/module-auth/src/test/java/com/inhabas/api/auth/domain/token/TokenAuthenticationProcessingFilterTest.java index 331e2ead..caec1bdb 100644 --- a/module-auth/src/test/java/com/inhabas/api/auth/domain/token/TokenAuthenticationProcessingFilterTest.java +++ b/module-auth/src/test/java/com/inhabas/api/auth/domain/token/TokenAuthenticationProcessingFilterTest.java @@ -1,48 +1,48 @@ -//package com.inhabas.api.auth.domain.token; -// -//import static org.junit.jupiter.api.Assertions.assertNull; -//import static org.junit.jupiter.api.Assertions.assertTrue; -//import static org.mockito.ArgumentMatchers.any; -//import static org.mockito.BDDMockito.given; -//import static org.mockito.Mockito.doNothing; -//import static org.mockito.Mockito.times; -//import static org.mockito.Mockito.verify; -// -//import com.inhabas.api.auth.domain.token.jwtUtils.JwtTokenProvider; -//import com.inhabas.api.auth.domain.token.jwtUtils.JwtTokenResolver; -//import com.inhabas.api.auth.domain.token.jwtUtils.refreshToken.RefreshTokenRepository; -//import com.inhabas.api.auth.domain.token.securityFilter.InvalidJwtTokenHandler; -//import com.inhabas.api.auth.domain.token.securityFilter.TokenAuthenticationProcessingFilter; -//import com.inhabas.api.auth.domain.token.securityFilter.UserPrincipalService; -//import java.io.IOException; -//import java.lang.reflect.InvocationTargetException; -//import java.lang.reflect.Method; -//import java.util.HashMap; -//import java.util.List; -//import java.util.Map; -//import javax.servlet.FilterChain; -//import javax.servlet.ServletException; -//import javax.servlet.http.HttpServletRequest; -//import javax.servlet.http.HttpServletResponse; -//import org.junit.jupiter.api.BeforeEach; -//import org.junit.jupiter.api.DisplayName; -//import org.junit.jupiter.api.Test; -//import org.junit.jupiter.api.extension.ExtendWith; -//import org.mockito.InjectMocks; -//import org.mockito.Mock; -//import org.mockito.Spy; -//import org.mockito.junit.jupiter.MockitoExtension; -//import org.springframework.context.annotation.Import; -//import org.springframework.mock.web.MockHttpServletRequest; -//import org.springframework.mock.web.MockHttpServletResponse; -//import org.springframework.security.core.authority.SimpleGrantedAuthority; -//import org.springframework.security.core.context.SecurityContextHolder; -//import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken; -//import org.springframework.security.oauth2.core.user.DefaultOAuth2User; -// -//@ExtendWith(MockitoExtension.class) -//@Import({RefreshTokenRepository.class}) -//public class TokenAuthenticationProcessingFilterTest { +// package com.inhabas.api.auth.domain.token; +// +// import static org.junit.jupiter.api.Assertions.assertNull; +// import static org.junit.jupiter.api.Assertions.assertTrue; +// import static org.mockito.ArgumentMatchers.any; +// import static org.mockito.BDDMockito.given; +// import static org.mockito.Mockito.doNothing; +// import static org.mockito.Mockito.times; +// import static org.mockito.Mockito.verify; +// +// import com.inhabas.api.auth.domain.token.jwtUtils.JwtTokenProvider; +// import com.inhabas.api.auth.domain.token.jwtUtils.JwtTokenResolver; +// import com.inhabas.api.auth.domain.token.jwtUtils.refreshToken.RefreshTokenRepository; +// import com.inhabas.api.auth.domain.token.securityFilter.InvalidJwtTokenHandler; +// import com.inhabas.api.auth.domain.token.securityFilter.TokenAuthenticationProcessingFilter; +// import com.inhabas.api.auth.domain.token.securityFilter.UserPrincipalService; +// import java.io.IOException; +// import java.lang.reflect.InvocationTargetException; +// import java.lang.reflect.Method; +// import java.util.HashMap; +// import java.util.List; +// import java.util.Map; +// import javax.servlet.FilterChain; +// import javax.servlet.ServletException; +// import javax.servlet.http.HttpServletRequest; +// import javax.servlet.http.HttpServletResponse; +// import org.junit.jupiter.api.BeforeEach; +// import org.junit.jupiter.api.DisplayName; +// import org.junit.jupiter.api.Test; +// import org.junit.jupiter.api.extension.ExtendWith; +// import org.mockito.InjectMocks; +// import org.mockito.Mock; +// import org.mockito.Spy; +// import org.mockito.junit.jupiter.MockitoExtension; +// import org.springframework.context.annotation.Import; +// import org.springframework.mock.web.MockHttpServletRequest; +// import org.springframework.mock.web.MockHttpServletResponse; +// import org.springframework.security.core.authority.SimpleGrantedAuthority; +// import org.springframework.security.core.context.SecurityContextHolder; +// import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken; +// import org.springframework.security.oauth2.core.user.DefaultOAuth2User; +// +// @ExtendWith(MockitoExtension.class) +// @Import({RefreshTokenRepository.class}) +// public class TokenAuthenticationProcessingFilterTest { // // @Mock // private RefreshTokenRepository refreshTokenRepository; @@ -72,7 +72,8 @@ // // @DisplayName("jwt 토큰으로 인증을 성공한다.") // @Test -// public void successfulAuthenticationTest() throws ServletException, IOException, NoSuchMethodException, InvocationTargetException, IllegalAccessException { +// public void successfulAuthenticationTest() throws ServletException, IOException, +// NoSuchMethodException, InvocationTargetException, IllegalAccessException { // //given // MockHttpServletRequest request = new MockHttpServletRequest(); // MockHttpServletResponse response = new MockHttpServletResponse(); @@ -84,9 +85,12 @@ // given(userPrincipalService.loadUserPrincipal(any())).willReturn(12171652); // // //when -// Method doFilterInternal = tokenAuthenticationProcessingFilter.getClass().getDeclaredMethod("doFilterInternal", HttpServletRequest.class, HttpServletResponse.class, FilterChain.class); +// Method doFilterInternal = +// tokenAuthenticationProcessingFilter.getClass().getDeclaredMethod("doFilterInternal", +// HttpServletRequest.class, HttpServletResponse.class, FilterChain.class); // doFilterInternal.setAccessible(true); -// doFilterInternal.invoke(tokenAuthenticationProcessingFilter, request, response, filterChain); +// doFilterInternal.invoke(tokenAuthenticationProcessingFilter, request, response, +// filterChain); // // //then // verify(filterChain, times(1)).doFilter(any(), any()); @@ -95,7 +99,8 @@ // // @DisplayName("유효하지 않은 jwt 토큰으로 인증을 시도하면, 400 request") // @Test -// public void invalidJwtTokenResponse() throws ServletException, IOException, NoSuchMethodException, InvocationTargetException, IllegalAccessException { +// public void invalidJwtTokenResponse() throws ServletException, IOException, +// NoSuchMethodException, InvocationTargetException, IllegalAccessException { // // custom exception code 가 필요할 수도 // //given // MockHttpServletRequest request = new MockHttpServletRequest(); @@ -105,9 +110,12 @@ // request.addHeader("Authorization", "Bearer " + accessToken); // // //when -// Method doFilterInternal = tokenAuthenticationProcessingFilter.getClass().getDeclaredMethod("doFilterInternal", HttpServletRequest.class, HttpServletResponse.class, FilterChain.class); +// Method doFilterInternal = +// tokenAuthenticationProcessingFilter.getClass().getDeclaredMethod("doFilterInternal", +// HttpServletRequest.class, HttpServletResponse.class, FilterChain.class); // doFilterInternal.setAccessible(true); -// doFilterInternal.invoke(tokenAuthenticationProcessingFilter, request, response, filterChain); +// doFilterInternal.invoke(tokenAuthenticationProcessingFilter, request, response, +// filterChain); // // //then // assertNull(SecurityContextHolder.getContext().getAuthentication()); @@ -132,7 +140,8 @@ // // private OAuth2AuthenticationToken getAuthentication() { // List authorities = -// List.of(new SimpleGrantedAuthority("ROLE_ANONYMOUS"), new SimpleGrantedAuthority("TEAM_IT")); +// List.of(new SimpleGrantedAuthority("ROLE_ANONYMOUS"), new +// SimpleGrantedAuthority("TEAM_IT")); // Map attributes = new HashMap<>() {{ // put("sub", "1249846925629348"); // put("name", "유동현"); @@ -145,4 +154,4 @@ // } // // -//} +// } diff --git a/module-auth/src/test/java/com/inhabas/api/auth/testAnnotation/DefaultDataJpaTest.java b/module-auth/src/test/java/com/inhabas/api/auth/testAnnotation/DefaultDataJpaTest.java index 10288381..e06ce630 100644 --- a/module-auth/src/test/java/com/inhabas/api/auth/testAnnotation/DefaultDataJpaTest.java +++ b/module-auth/src/test/java/com/inhabas/api/auth/testAnnotation/DefaultDataJpaTest.java @@ -1,15 +1,16 @@ package com.inhabas.api.auth.testAnnotation; -import com.inhabas.api.JpaConfig; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; import org.springframework.context.annotation.Import; import org.springframework.test.context.ActiveProfiles; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; +import com.inhabas.api.JpaConfig; @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @@ -17,5 +18,4 @@ @ActiveProfiles("test") @Import(JpaConfig.class) @AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) -public @interface DefaultDataJpaTest { -} \ No newline at end of file +public @interface DefaultDataJpaTest {} diff --git a/module-fileStorage/src/main/java/com/inhabas/api/config/S3Config.java b/module-fileStorage/src/main/java/com/inhabas/api/config/S3Config.java index d1873e97..28f91dbd 100644 --- a/module-fileStorage/src/main/java/com/inhabas/api/config/S3Config.java +++ b/module-fileStorage/src/main/java/com/inhabas/api/config/S3Config.java @@ -1,34 +1,37 @@ package com.inhabas.api.config; -import com.amazonaws.auth.AWSStaticCredentialsProvider; -import com.amazonaws.auth.BasicAWSCredentials; -import com.amazonaws.services.s3.AmazonS3Client; -import com.amazonaws.services.s3.AmazonS3ClientBuilder; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.context.annotation.Profile; +import com.amazonaws.auth.AWSStaticCredentialsProvider; +import com.amazonaws.auth.BasicAWSCredentials; +import com.amazonaws.services.s3.AmazonS3Client; +import com.amazonaws.services.s3.AmazonS3ClientBuilder; + @Configuration @Profile({"dev", "local", "test", "integration_test"}) public class S3Config { - @Value("${cloud.aws.credentials.accessKey}") - private String accessKey; - @Value("${cloud.aws.credentials.secretKey}") - private String secretKey; - @Value("${cloud.aws.region.static}") - private String region; + @Value("${cloud.aws.credentials.accessKey}") + private String accessKey; + + @Value("${cloud.aws.credentials.secretKey}") + private String secretKey; - @Bean - @Primary - public AmazonS3Client amazonS3Client() { - BasicAWSCredentials awsCredentials = new BasicAWSCredentials(accessKey, secretKey); - return (AmazonS3Client) AmazonS3ClientBuilder.standard() - .withRegion(region) - .withCredentials(new AWSStaticCredentialsProvider(awsCredentials)) - .build(); - } + @Value("${cloud.aws.region.static}") + private String region; + @Bean + @Primary + public AmazonS3Client amazonS3Client() { + BasicAWSCredentials awsCredentials = new BasicAWSCredentials(accessKey, secretKey); + return (AmazonS3Client) + AmazonS3ClientBuilder.standard() + .withRegion(region) + .withCredentials(new AWSStaticCredentialsProvider(awsCredentials)) + .build(); + } } diff --git a/module-fileStorage/src/main/java/com/inhabas/api/domain/file/usecase/S3Service.java b/module-fileStorage/src/main/java/com/inhabas/api/domain/file/usecase/S3Service.java index 9547ed00..26f7d99f 100644 --- a/module-fileStorage/src/main/java/com/inhabas/api/domain/file/usecase/S3Service.java +++ b/module-fileStorage/src/main/java/com/inhabas/api/domain/file/usecase/S3Service.java @@ -1,14 +1,14 @@ package com.inhabas.api.domain.file.usecase; -import com.amazonaws.services.s3.model.S3ObjectInputStream; import org.springframework.web.multipart.MultipartFile; -public interface S3Service { +import com.amazonaws.services.s3.model.S3ObjectInputStream; - String uploadS3File(MultipartFile multipartFile, String dirName); +public interface S3Service { - S3ObjectInputStream downloadS3File(String dirName); + String uploadS3File(MultipartFile multipartFile, String dirName); - void deleteS3File(String fileUrl); + S3ObjectInputStream downloadS3File(String dirName); + void deleteS3File(String fileUrl); } diff --git a/module-fileStorage/src/main/java/com/inhabas/api/domain/file/usecase/S3ServiceImpl.java b/module-fileStorage/src/main/java/com/inhabas/api/domain/file/usecase/S3ServiceImpl.java index 5e36372b..70ea3031 100644 --- a/module-fileStorage/src/main/java/com/inhabas/api/domain/file/usecase/S3ServiceImpl.java +++ b/module-fileStorage/src/main/java/com/inhabas/api/domain/file/usecase/S3ServiceImpl.java @@ -1,102 +1,104 @@ package com.inhabas.api.domain.file.usecase; -import com.amazonaws.services.s3.AmazonS3Client; -import com.amazonaws.services.s3.model.*; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + import lombok.RequiredArgsConstructor; + import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; +import com.amazonaws.services.s3.AmazonS3Client; +import com.amazonaws.services.s3.model.*; @Service @RequiredArgsConstructor -public class S3ServiceImpl implements S3Service{ - - @Value("${cloud.aws.s3.bucket}") - private String bucket; - - private final AmazonS3Client s3Client; +public class S3ServiceImpl implements S3Service { - @Override - public String uploadS3File(MultipartFile multipartFile, String dirName) { + @Value("${cloud.aws.s3.bucket}") + private String bucket; - String fileName = dirName + "_" + multipartFile.getOriginalFilename(); + private final AmazonS3Client s3Client; - try { - String contentType = getContentType(fileName); + @Override + public String uploadS3File(MultipartFile multipartFile, String dirName) { - ObjectMetadata metadata = new ObjectMetadata(); - metadata.setContentType(contentType); - metadata.setContentLength(multipartFile.getSize()); + String fileName = dirName + "_" + multipartFile.getOriginalFilename(); - s3Client.putObject(new PutObjectRequest(bucket, fileName, multipartFile.getInputStream(), metadata) - .withCannedAcl(CannedAccessControlList.PublicRead)); - } catch (IOException e) { - e.printStackTrace(); - throw new RuntimeException(); - } + try { + String contentType = getContentType(fileName); - printS3ObjectSummaries(); + ObjectMetadata metadata = new ObjectMetadata(); + metadata.setContentType(contentType); + metadata.setContentLength(multipartFile.getSize()); - return s3Client.getUrl(bucket, fileName).toString(); + s3Client.putObject( + new PutObjectRequest(bucket, fileName, multipartFile.getInputStream(), metadata) + .withCannedAcl(CannedAccessControlList.PublicRead)); + } catch (IOException e) { + e.printStackTrace(); + throw new RuntimeException(); } - @Override - public S3ObjectInputStream downloadS3File(String dirName) { - - S3Object s3Object = s3Client.getObject(new GetObjectRequest(bucket, dirName)); - return s3Object.getObjectContent(); - + printS3ObjectSummaries(); + + return s3Client.getUrl(bucket, fileName).toString(); + } + + @Override + public S3ObjectInputStream downloadS3File(String dirName) { + + S3Object s3Object = s3Client.getObject(new GetObjectRequest(bucket, dirName)); + return s3Object.getObjectContent(); + } + + @Override + public void deleteS3File(String fileUrl) { + s3Client.deleteObject(new DeleteObjectRequest(bucket, fileUrl)); + } + + private String getContentType(String fileName) throws IOException { + + String ext = getExtension(fileName); + Map contentTypeMap = new HashMap<>(); + + contentTypeMap.put("xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); + contentTypeMap.put("xls", "application/vnd.ms-excel"); + contentTypeMap.put("gif", "image/gif"); + contentTypeMap.put("jpeg", "image/jpeg"); + contentTypeMap.put("png", "image/png"); + contentTypeMap.put("doc", "application/msword"); + contentTypeMap.put( + "docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"); + contentTypeMap.put( + "ppt", "application/vnd.openxmlformats-officedocument.presentationml.presentation"); + contentTypeMap.put("txt", "text/plain"); + contentTypeMap.put("pdf", "application/pdf"); + contentTypeMap.put("zip", "application/zip"); + contentTypeMap.put("csv", "text/csv"); + + if (!contentTypeMap.containsKey(ext)) { + throw new IOException(); } + return contentTypeMap.get(ext); + } - @Override - public void deleteS3File(String fileUrl) { - s3Client.deleteObject(new DeleteObjectRequest(bucket, fileUrl)); + private void printS3ObjectSummaries() { + ListObjectsV2Result listObjectsV2Result = s3Client.listObjectsV2(bucket); + for (S3ObjectSummary object : listObjectsV2Result.getObjectSummaries()) { + System.out.println("object = " + object.toString()); } + } - private String getContentType(String fileName) throws IOException { - - String ext = getExtension(fileName); - Map contentTypeMap = new HashMap<>(); - - contentTypeMap.put("xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); - contentTypeMap.put("xls", "application/vnd.ms-excel"); - contentTypeMap.put("gif", "image/gif"); - contentTypeMap.put("jpeg", "image/jpeg"); - contentTypeMap.put("png", "image/png"); - contentTypeMap.put("doc", "application/msword"); - contentTypeMap.put("docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"); - contentTypeMap.put("ppt", "application/vnd.openxmlformats-officedocument.presentationml.presentation"); - contentTypeMap.put("txt", "text/plain"); - contentTypeMap.put("pdf", "application/pdf"); - contentTypeMap.put("zip", "application/zip"); - contentTypeMap.put("csv", "text/csv"); - - if (!contentTypeMap.containsKey(ext)) { - throw new IOException(); - } - return contentTypeMap.get(ext); + private String getExtension(String fileName) { + int lastIndex = fileName.lastIndexOf("."); + if (lastIndex > 0 && lastIndex < fileName.length() - 1) { + return fileName.substring(lastIndex + 1).toLowerCase(); + } else { + return ""; } - - private void printS3ObjectSummaries() { - ListObjectsV2Result listObjectsV2Result = s3Client.listObjectsV2(bucket); - for (S3ObjectSummary object : listObjectsV2Result.getObjectSummaries()) { - System.out.println("object = " + object.toString()); - } - } - - private String getExtension(String fileName) { - int lastIndex = fileName.lastIndexOf("."); - - if (lastIndex > 0 && lastIndex < fileName.length() - 1) { - return fileName.substring(lastIndex + 1).toLowerCase(); - } else { - return ""; - } - } - + } } diff --git a/module-jpa/src/main/java/com/inhabas/api/JpaConfig.java b/module-jpa/src/main/java/com/inhabas/api/JpaConfig.java index 0659d2ea..51b37774 100644 --- a/module-jpa/src/main/java/com/inhabas/api/JpaConfig.java +++ b/module-jpa/src/main/java/com/inhabas/api/JpaConfig.java @@ -1,22 +1,22 @@ package com.inhabas.api; -import com.querydsl.jpa.impl.JPAQueryFactory; +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; + import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.jpa.repository.config.EnableJpaAuditing; -import javax.persistence.EntityManager; -import javax.persistence.PersistenceContext; +import com.querydsl.jpa.impl.JPAQueryFactory; @Configuration @EnableJpaAuditing public class JpaConfig { - @PersistenceContext - private EntityManager em; + @PersistenceContext private EntityManager em; - @Bean - public JPAQueryFactory jpaQueryFactory() { - return new JPAQueryFactory(em); - } + @Bean + public JPAQueryFactory jpaQueryFactory() { + return new JPAQueryFactory(em); + } } diff --git a/module-jpa/src/main/java/com/inhabas/api/sshTunneling/SshDataSourceConfig.java b/module-jpa/src/main/java/com/inhabas/api/sshTunneling/SshDataSourceConfig.java index 973efe31..a9ee3fab 100644 --- a/module-jpa/src/main/java/com/inhabas/api/sshTunneling/SshDataSourceConfig.java +++ b/module-jpa/src/main/java/com/inhabas/api/sshTunneling/SshDataSourceConfig.java @@ -1,7 +1,10 @@ package com.inhabas.api.sshTunneling; +import javax.sql.DataSource; + import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; + import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties; import org.springframework.boot.jdbc.DataSourceBuilder; import org.springframework.context.annotation.Bean; @@ -9,29 +12,26 @@ import org.springframework.context.annotation.Primary; import org.springframework.context.annotation.Profile; -import javax.sql.DataSource; - @Slf4j @Profile("local_ssh") @Configuration @RequiredArgsConstructor public class SshDataSourceConfig { - private final SshTunnelingInitializer initializer; - - @Bean("dataSource") - @Primary - public DataSource dataSource(DataSourceProperties properties) { + private final SshTunnelingInitializer initializer; - Integer forwardedPort = initializer.buildSshConnection(); - String url = properties.getUrl().replace("[forwardedPort]", Integer.toString(forwardedPort)); - log.info(url); - return DataSourceBuilder.create() - .url(url) - .username(properties.getUsername()) - .password(properties.getPassword()) - .driverClassName(properties.getDriverClassName()) - .build(); - } + @Bean("dataSource") + @Primary + public DataSource dataSource(DataSourceProperties properties) { + Integer forwardedPort = initializer.buildSshConnection(); + String url = properties.getUrl().replace("[forwardedPort]", Integer.toString(forwardedPort)); + log.info(url); + return DataSourceBuilder.create() + .url(url) + .username(properties.getUsername()) + .password(properties.getPassword()) + .driverClassName(properties.getDriverClassName()) + .build(); + } } diff --git a/module-jpa/src/main/java/com/inhabas/api/sshTunneling/SshTunnelingInitializer.java b/module-jpa/src/main/java/com/inhabas/api/sshTunneling/SshTunnelingInitializer.java index 34c16429..a65c42df 100644 --- a/module-jpa/src/main/java/com/inhabas/api/sshTunneling/SshTunnelingInitializer.java +++ b/module-jpa/src/main/java/com/inhabas/api/sshTunneling/SshTunnelingInitializer.java @@ -1,77 +1,77 @@ package com.inhabas.api.sshTunneling; -import com.jcraft.jsch.JSch; -import com.jcraft.jsch.Session; +import static java.lang.System.exit; + +import java.util.Properties; + +import javax.annotation.PreDestroy; +import javax.validation.constraints.NotNull; + import lombok.Setter; import lombok.extern.slf4j.Slf4j; + import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Component; import org.springframework.validation.annotation.Validated; -import javax.annotation.PreDestroy; -import javax.validation.constraints.NotNull; -import java.util.Properties; - -import static java.lang.System.exit; +import com.jcraft.jsch.JSch; +import com.jcraft.jsch.Session; @Slf4j @Profile("local_ssh") @Component @ConfigurationProperties(prefix = "ssh") -@Validated @Setter +@Validated +@Setter public class SshTunnelingInitializer { - @NotNull private String remoteJumpHost; - @NotNull private String user; - @NotNull private int sshPort; - @NotNull private String privateKey; - @NotNull private int databasePort; + @NotNull private String remoteJumpHost; + @NotNull private String user; + @NotNull private int sshPort; + @NotNull private String privateKey; + @NotNull private int databasePort; - private Session session; + private Session session; - @PreDestroy - public void closeSSH() { - if (session.isConnected()) - session.disconnect(); - } + @PreDestroy + public void closeSSH() { + if (session.isConnected()) session.disconnect(); + } - public Integer buildSshConnection() { + public Integer buildSshConnection() { - Integer forwardedPort = null; + Integer forwardedPort = null; - try { - log.info("{}@{}:{}:{} with privateKey",user, remoteJumpHost, sshPort, databasePort); + try { + log.info("{}@{}:{}:{} with privateKey", user, remoteJumpHost, sshPort, databasePort); - log.info("start ssh tunneling.."); - JSch jSch = new JSch(); + log.info("start ssh tunneling.."); + JSch jSch = new JSch(); - log.info("creating ssh session"); - jSch.addIdentity(privateKey); - session = jSch.getSession(user, remoteJumpHost, sshPort); - Properties config = new Properties(); - config.put("StrictHostKeyChecking", "no"); - session.setConfig(config); - log.info("complete creating ssh session"); + log.info("creating ssh session"); + jSch.addIdentity(privateKey); + session = jSch.getSession(user, remoteJumpHost, sshPort); + Properties config = new Properties(); + config.put("StrictHostKeyChecking", "no"); + session.setConfig(config); + log.info("complete creating ssh session"); - log.info("start connecting ssh connection"); - session.connect(); - log.info("success connecting ssh connection "); + log.info("start connecting ssh connection"); + session.connect(); + log.info("success connecting ssh connection "); - log.info("start forwarding"); - forwardedPort = session.setPortForwardingL(0, "localhost", databasePort); - log.info("successfully connected to database"); + log.info("start forwarding"); + forwardedPort = session.setPortForwardingL(0, "localhost", databasePort); + log.info("successfully connected to database"); - } catch (Exception e){ - log.error("fail to make ssh tunneling"); - this.closeSSH(); - e.printStackTrace(); - exit(1); - } - - return forwardedPort; + } catch (Exception e) { + log.error("fail to make ssh tunneling"); + this.closeSSH(); + e.printStackTrace(); + exit(1); } -} - - + return forwardedPort; + } +} diff --git a/resource-server/src/main/java/com/inhabas/api/ApiApplication.java b/resource-server/src/main/java/com/inhabas/api/ApiApplication.java index cb3bcfbb..800df582 100644 --- a/resource-server/src/main/java/com/inhabas/api/ApiApplication.java +++ b/resource-server/src/main/java/com/inhabas/api/ApiApplication.java @@ -9,9 +9,9 @@ @SpringBootApplication public class ApiApplication { - public static void main(String[] args) { - SpringApplication app = new SpringApplication(ApiApplication.class); - app.addListeners(new ApplicationPidFileWriter()); - app.run(args); - } -} \ No newline at end of file + public static void main(String[] args) { + SpringApplication app = new SpringApplication(ApiApplication.class); + app.addListeners(new ApplicationPidFileWriter()); + app.run(args); + } +} diff --git a/resource-server/src/main/java/com/inhabas/api/config/CloudConfig.java b/resource-server/src/main/java/com/inhabas/api/config/CloudConfig.java index 83a2e55a..c44ce21a 100644 --- a/resource-server/src/main/java/com/inhabas/api/config/CloudConfig.java +++ b/resource-server/src/main/java/com/inhabas/api/config/CloudConfig.java @@ -5,5 +5,4 @@ @Configuration @EnableDiscoveryClient -public class CloudConfig { -} +public class CloudConfig {} diff --git a/resource-server/src/main/java/com/inhabas/api/config/SwaggerConfig.java b/resource-server/src/main/java/com/inhabas/api/config/SwaggerConfig.java index b7b8e389..aeaf9386 100644 --- a/resource-server/src/main/java/com/inhabas/api/config/SwaggerConfig.java +++ b/resource-server/src/main/java/com/inhabas/api/config/SwaggerConfig.java @@ -1,5 +1,9 @@ package com.inhabas.api.config; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; + import io.swagger.v3.oas.models.Components; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.info.Info; @@ -8,106 +12,95 @@ import io.swagger.v3.oas.models.servers.Server; import org.apache.http.HttpHeaders; import org.springdoc.core.GroupedOpenApi; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Profile; @Configuration public class SwaggerConfig { - private final static String DOMAIN = "https://dev.inhabas.com/api"; - - private Info apiInfo() { - return new Info() - .version("v1.0.0") - .title("Inhabas API") - .description("spring-api docs"); - } - - private SecurityScheme securityScheme() { - return new SecurityScheme() - .type(SecurityScheme.Type.HTTP) - .scheme("bearer") - .bearerFormat("JWT") - .in(SecurityScheme.In.HEADER) - .name(HttpHeaders.AUTHORIZATION); - } - - private SecurityRequirement securityRequirement() { - SecurityRequirement requirement = new SecurityRequirement(); - requirement.addList("JWT"); - return requirement; + private static final String DOMAIN = "https://dev.inhabas.com/api"; + + private Info apiInfo() { + return new Info().version("v1.0.0").title("Inhabas API").description("spring-api docs"); + } + + private SecurityScheme securityScheme() { + return new SecurityScheme() + .type(SecurityScheme.Type.HTTP) + .scheme("bearer") + .bearerFormat("JWT") + .in(SecurityScheme.In.HEADER) + .name(HttpHeaders.AUTHORIZATION); + } + + private SecurityRequirement securityRequirement() { + SecurityRequirement requirement = new SecurityRequirement(); + requirement.addList("JWT"); + return requirement; + } + + private OpenAPI createOpenAPI( + Info info, + SecurityScheme securityScheme, + SecurityRequirement securityRequirement, + Server... servers) { + OpenAPI openAPI = + new OpenAPI() + .components(new Components().addSecuritySchemes("JWT", securityScheme)) + .addSecurityItem(securityRequirement) + .info(info); + + for (Server server : servers) { + openAPI.addServersItem(server); } - private OpenAPI createOpenAPI(Info info, SecurityScheme securityScheme, SecurityRequirement securityRequirement, Server... servers) { - OpenAPI openAPI = new OpenAPI() - .components(new Components().addSecuritySchemes("JWT", securityScheme)) - .addSecurityItem(securityRequirement) - .info(info); - - for (Server server : servers) { - openAPI.addServersItem(server); - } - - return openAPI; - } - - @Bean - @Profile("dev") - public OpenAPI devOpenAPI() { - // HTTPS 서버 URL 설정 - Server server = new Server().url(DOMAIN); - - return createOpenAPI(apiInfo(), securityScheme(), securityRequirement(), server); - } - @Bean - public GroupedOpenApi getAllApi() { - - return GroupedOpenApi - .builder() - .group("All") - .pathsToMatch("/**") - .build(); - - } - - @Bean - public GroupedOpenApi getBasicApi() { - - return GroupedOpenApi - .builder() - .group("기본") - .pathsToMatch("/policy/**", "/menu/**", "/menus/**", "/member/chief") - .build(); - - } - - @Bean - public GroupedOpenApi getMemberApi() { - - return GroupedOpenApi - .builder() - .group("회원 관련") - .pathsToMatch("/signUp/**", "/members/**", "/member/**", "/myInfo/**") - .pathsToExclude("/member/chief") - .build(); - - } - - @Bean - public GroupedOpenApi getIBASApi() { - - return GroupedOpenApi - .builder() - .group("IBAS 관련") - .pathsToMatch("/club/**", "/**/**/**/comment/**", "/**/**/**/comments") - .build(); - - } - - @Bean - @Profile("local") - public OpenAPI localOpenAPI() { - return createOpenAPI(apiInfo(), securityScheme(), securityRequirement()); - } -} \ No newline at end of file + return openAPI; + } + + @Bean + @Profile("dev") + public OpenAPI devOpenAPI() { + // HTTPS 서버 URL 설정 + Server server = new Server().url(DOMAIN); + + return createOpenAPI(apiInfo(), securityScheme(), securityRequirement(), server); + } + + @Bean + public GroupedOpenApi getAllApi() { + + return GroupedOpenApi.builder().group("All").pathsToMatch("/**").build(); + } + + @Bean + public GroupedOpenApi getBasicApi() { + + return GroupedOpenApi.builder() + .group("기본") + .pathsToMatch("/policy/**", "/menu/**", "/menus/**", "/member/chief") + .build(); + } + + @Bean + public GroupedOpenApi getMemberApi() { + + return GroupedOpenApi.builder() + .group("회원 관련") + .pathsToMatch("/signUp/**", "/members/**", "/member/**", "/myInfo/**") + .pathsToExclude("/member/chief") + .build(); + } + + @Bean + public GroupedOpenApi getIBASApi() { + + return GroupedOpenApi.builder() + .group("IBAS 관련") + .pathsToMatch("/club/**", "/**/**/**/comment/**", "/**/**/**/comments") + .build(); + } + + @Bean + @Profile("local") + public OpenAPI localOpenAPI() { + return createOpenAPI(apiInfo(), securityScheme(), securityRequirement()); + } +} diff --git a/resource-server/src/main/java/com/inhabas/api/config/WebConfig.java b/resource-server/src/main/java/com/inhabas/api/config/WebConfig.java index 479443a6..27e05d1d 100644 --- a/resource-server/src/main/java/com/inhabas/api/config/WebConfig.java +++ b/resource-server/src/main/java/com/inhabas/api/config/WebConfig.java @@ -1,16 +1,18 @@ package com.inhabas.api.config; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.PropertyNamingStrategies; import io.swagger.v3.core.jackson.ModelResolver; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; @Configuration public class WebConfig { - @Bean - public ModelResolver modelResolver(ObjectMapper objectMapper) { - return new ModelResolver(objectMapper.setPropertyNamingStrategy(PropertyNamingStrategies.LOWER_CAMEL_CASE)); - } + @Bean + public ModelResolver modelResolver(ObjectMapper objectMapper) { + return new ModelResolver( + objectMapper.setPropertyNamingStrategy(PropertyNamingStrategies.LOWER_CAMEL_CASE)); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/config/WebSecurityConfig.java b/resource-server/src/main/java/com/inhabas/api/config/WebSecurityConfig.java index 1e8a026b..931255ec 100644 --- a/resource-server/src/main/java/com/inhabas/api/config/WebSecurityConfig.java +++ b/resource-server/src/main/java/com/inhabas/api/config/WebSecurityConfig.java @@ -1,14 +1,12 @@ package com.inhabas.api.config; -import com.inhabas.api.auth.AuthBeansConfig; -import com.inhabas.api.auth.domain.oauth2.member.security.Hierarchical; -import com.inhabas.api.auth.domain.token.CustomRequestMatcher; -import com.inhabas.api.auth.domain.token.JwtAccessDeniedHandler; -import com.inhabas.api.auth.domain.token.jwtUtils.JwtAuthenticationProvider; -import com.inhabas.api.auth.domain.token.jwtUtils.JwtTokenUtil; -import com.inhabas.api.auth.domain.token.securityFilter.JwtAuthenticationEntryPoint; -import com.inhabas.api.auth.domain.token.securityFilter.JwtAuthenticationFilter; +import static com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.Role.*; + +import java.util.ArrayList; +import java.util.List; + import lombok.RequiredArgsConstructor; + import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Profile; import org.springframework.core.annotation.Order; @@ -28,148 +26,174 @@ import org.springframework.security.web.util.matcher.RequestMatcher; import org.springframework.web.cors.CorsUtils; -import java.util.ArrayList; -import java.util.List; - -import static com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.Role.*; +import com.inhabas.api.auth.AuthBeansConfig; +import com.inhabas.api.auth.domain.oauth2.member.security.Hierarchical; +import com.inhabas.api.auth.domain.token.CustomRequestMatcher; +import com.inhabas.api.auth.domain.token.JwtAccessDeniedHandler; +import com.inhabas.api.auth.domain.token.jwtUtils.JwtAuthenticationProvider; +import com.inhabas.api.auth.domain.token.jwtUtils.JwtTokenUtil; +import com.inhabas.api.auth.domain.token.securityFilter.JwtAuthenticationEntryPoint; +import com.inhabas.api.auth.domain.token.securityFilter.JwtAuthenticationFilter; /** - * api 엔드포인트에 대한 여러 보안 설정을 담당함. 인증 관련 보안 설정은 {@link com.inhabas.api.auth.AuthSecurityConfig AuthSecurityConfig} 참고 + * api 엔드포인트에 대한 여러 보안 설정을 담당함. 인증 관련 보안 설정은 {@link com.inhabas.api.auth.AuthSecurityConfig + * AuthSecurityConfig} 참고 */ public class WebSecurityConfig { - private static final String[] AUTH_WHITELIST_SWAGGER = {"/swagger-ui/**", "/swagger/**", "/docs/**"}; - private static final String[] AUTH_WHITELIST_STATIC = {"/static/css/**", "/static/js/**", "*.ico"}; - private static final String[] AUTH_WHITELIST_TOKEN = {"/token/**"}; - private static final String[] AUTH_WHITELIST_PATH = {"/menu/**", "/menus", "/member/chief", "/error"}; - private static final String[] AUTH_WHITELIST_SIGNUP = {"/signUp/schedule", "/signUp/questionnaires", - "/signUp/majorInfo"}; - private static final String[] AUTH_WHITELIST_CLUB = {"/club/histories", "/club/history/**"}; - private static final String[] AUTH_WHITELIST_POLICY = {"/policy/**"}; - private static final String[] AUTH_WHITELIST_CLUB_ACTIVITY = {"/club/activity/**", "/club/activities"}; - private static final String[] AUTH_WHITELIST_COMMENT = {"/board/**/**/comments", "/board/**/**/comment", "/comment/**"}; - - @Order(1) - @EnableGlobalMethodSecurity(prePostEnabled = true, jsr250Enabled = true) - @EnableWebSecurity - @RequiredArgsConstructor - @Profile({"local", "dev", "default_mvc_test", "production", "integration_test"}) - public static class ApiSecurityForDev extends WebSecurityConfigurerAdapter { - - private final JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint; - private final JwtAccessDeniedHandler jwtAccessDeniedHandler; - private final Hierarchical hierarchy; - private final JwtTokenUtil jwtTokenUtil; - private final JwtAuthenticationProvider jwtAuthenticationProvider; - private final AuthBeansConfig authBeansConfig; - - - @Override - public void configure(AuthenticationManagerBuilder auth) throws Exception { - auth.authenticationProvider(jwtAuthenticationProvider); - } - - @Override - public void configure(WebSecurity web) throws Exception { - web.ignoring() - .antMatchers(HttpMethod.GET, AUTH_WHITELIST_POLICY) - .antMatchers(HttpMethod.GET, AUTH_WHITELIST_SIGNUP) - .antMatchers(HttpMethod.GET, AUTH_WHITELIST_CLUB) - .antMatchers(AUTH_WHITELIST_SWAGGER) - .antMatchers(AUTH_WHITELIST_STATIC) - .antMatchers(AUTH_WHITELIST_PATH); - } - - @Override - protected void configure(HttpSecurity http) throws Exception { - http - // OAuth 관련 경로 제외 모든 경로 - .requestMatchers() - .antMatchers("/**") - .and() - .anonymous() - .authorities("ROLE_" + ANONYMOUS) - .and() - // HTTP 기본 인증 비활성화 - .httpBasic() - .disable() - // 세션 생성 금지 - .sessionManagement() - .sessionCreationPolicy(SessionCreationPolicy.STATELESS) - .and() - // API이므로 CORS 활성화, CSRF 비활성화 - .cors() - .and() - .csrf() - .disable() - - // 인증 예외 처리시 jwtAuthenticationEntryPoint 사용 - .exceptionHandling() - .authenticationEntryPoint(jwtAuthenticationEntryPoint) - .accessDeniedHandler(jwtAccessDeniedHandler) - .and() - .authorizeRequests() - // 권한 부여 표현식 - .expressionHandler(expressionHandler()) - // Preflight 방식 - .requestMatchers(CorsUtils::isPreFlightRequest).permitAll() - // 회원 관리 - .antMatchers("/members/**", "/member/**").hasAnyRole(SECRETARY.toString(), EXECUTIVES.toString()) - // 회계내역 - .antMatchers("/budget/history/**", "/budget/histories", - "/budget/application/**", "/budget/applications").hasRole(SECRETARY.toString()) - // 강의 - .antMatchers("/lecture/**/status").hasRole(EXECUTIVES.toString()) - .antMatchers("/lecture/**").hasRole(DEACTIVATED.toString()) - - // 회원가입 일정 수정 - .antMatchers(HttpMethod.PUT, "/signUp/schedule").hasAnyRole(CHIEF.toString(), VICE_CHIEF.toString()) - - // 회원가입은 ANONYMOUS 권한은 명시적으로 부여받은 상태에서만 가능 - .antMatchers("/signUp/check").hasRole(ANONYMOUS.toString()) - .antMatchers("/signUp/**").hasRole(SIGNING_UP.toString()) - - // 동아리 연혁 수정 - .antMatchers("/club/history/**").hasRole(EXECUTIVES.toString()) - - // 정책 수정 - .antMatchers(HttpMethod.PUT, "/policy/**").hasAnyRole(CHIEF.toString(), VICE_CHIEF.toString()) - - // 그 외 - .anyRequest().hasRole(ANONYMOUS.toString()); - - http.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class); - - } - - @Bean - public SecurityExpressionHandler expressionHandler() { - DefaultWebSecurityExpressionHandler webSecurityExpressionHandler = new DefaultWebSecurityExpressionHandler(); - webSecurityExpressionHandler.setRoleHierarchy(hierarchy.getHierarchy()); - return webSecurityExpressionHandler; - } - - public JwtAuthenticationFilter jwtAuthenticationFilter() throws Exception { - final List skipPaths = new ArrayList<>(); - - for (String path : AUTH_WHITELIST_CLUB_ACTIVITY) { - skipPaths.add(new CustomRequestMatcher(path, "GET")); - } - - for (String path : AUTH_WHITELIST_TOKEN) { - skipPaths.add(new CustomRequestMatcher(path, "POST")); - } - - final RequestMatcher requestMatcher = new AndRequestMatcher(skipPaths); - final JwtAuthenticationFilter filter = new JwtAuthenticationFilter( - requestMatcher, - jwtTokenUtil, - authBeansConfig.tokenResolver() - ); - - filter.setAuthenticationManager(super.authenticationManager()); - return filter; - } + private static final String[] AUTH_WHITELIST_SWAGGER = { + "/swagger-ui/**", "/swagger/**", "/docs/**" + }; + private static final String[] AUTH_WHITELIST_STATIC = { + "/static/css/**", "/static/js/**", "*.ico" + }; + private static final String[] AUTH_WHITELIST_TOKEN = {"/token/**"}; + private static final String[] AUTH_WHITELIST_PATH = { + "/menu/**", "/menus", "/member/chief", "/error" + }; + private static final String[] AUTH_WHITELIST_SIGNUP = { + "/signUp/schedule", "/signUp/questionnaires", "/signUp/majorInfo" + }; + private static final String[] AUTH_WHITELIST_CLUB = {"/club/histories", "/club/history/**"}; + private static final String[] AUTH_WHITELIST_POLICY = {"/policy/**"}; + private static final String[] AUTH_WHITELIST_CLUB_ACTIVITY = { + "/club/activity/**", "/club/activities" + }; + private static final String[] AUTH_WHITELIST_COMMENT = { + "/board/**/**/comments", "/board/**/**/comment", "/comment/**" + }; + + @Order(1) + @EnableGlobalMethodSecurity(prePostEnabled = true, jsr250Enabled = true) + @EnableWebSecurity + @RequiredArgsConstructor + @Profile({"local", "dev", "default_mvc_test", "production", "integration_test"}) + public static class ApiSecurityForDev extends WebSecurityConfigurerAdapter { + + private final JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint; + private final JwtAccessDeniedHandler jwtAccessDeniedHandler; + private final Hierarchical hierarchy; + private final JwtTokenUtil jwtTokenUtil; + private final JwtAuthenticationProvider jwtAuthenticationProvider; + private final AuthBeansConfig authBeansConfig; + + @Override + public void configure(AuthenticationManagerBuilder auth) throws Exception { + auth.authenticationProvider(jwtAuthenticationProvider); + } + + @Override + public void configure(WebSecurity web) throws Exception { + web.ignoring() + .antMatchers(HttpMethod.GET, AUTH_WHITELIST_POLICY) + .antMatchers(HttpMethod.GET, AUTH_WHITELIST_SIGNUP) + .antMatchers(HttpMethod.GET, AUTH_WHITELIST_CLUB) + .antMatchers(AUTH_WHITELIST_SWAGGER) + .antMatchers(AUTH_WHITELIST_STATIC) + .antMatchers(AUTH_WHITELIST_PATH); + } + + @Override + protected void configure(HttpSecurity http) throws Exception { + http + // OAuth 관련 경로 제외 모든 경로 + .requestMatchers() + .antMatchers("/**") + .and() + .anonymous() + .authorities("ROLE_" + ANONYMOUS) + .and() + // HTTP 기본 인증 비활성화 + .httpBasic() + .disable() + // 세션 생성 금지 + .sessionManagement() + .sessionCreationPolicy(SessionCreationPolicy.STATELESS) + .and() + // API이므로 CORS 활성화, CSRF 비활성화 + .cors() + .and() + .csrf() + .disable() + + // 인증 예외 처리시 jwtAuthenticationEntryPoint 사용 + .exceptionHandling() + .authenticationEntryPoint(jwtAuthenticationEntryPoint) + .accessDeniedHandler(jwtAccessDeniedHandler) + .and() + .authorizeRequests() + // 권한 부여 표현식 + .expressionHandler(expressionHandler()) + // Preflight 방식 + .requestMatchers(CorsUtils::isPreFlightRequest) + .permitAll() + // 회원 관리 + .antMatchers("/members/**", "/member/**") + .hasAnyRole(SECRETARY.toString(), EXECUTIVES.toString()) + // 회계내역 + .antMatchers( + "/budget/history/**", + "/budget/histories", + "/budget/application/**", + "/budget/applications") + .hasRole(SECRETARY.toString()) + // 강의 + .antMatchers("/lecture/**/status") + .hasRole(EXECUTIVES.toString()) + .antMatchers("/lecture/**") + .hasRole(DEACTIVATED.toString()) + + // 회원가입 일정 수정 + .antMatchers(HttpMethod.PUT, "/signUp/schedule") + .hasAnyRole(CHIEF.toString(), VICE_CHIEF.toString()) + + // 회원가입은 ANONYMOUS 권한은 명시적으로 부여받은 상태에서만 가능 + .antMatchers("/signUp/check") + .hasRole(ANONYMOUS.toString()) + .antMatchers("/signUp/**") + .hasRole(SIGNING_UP.toString()) + + // 동아리 연혁 수정 + .antMatchers("/club/history/**") + .hasRole(EXECUTIVES.toString()) + + // 정책 수정 + .antMatchers(HttpMethod.PUT, "/policy/**") + .hasAnyRole(CHIEF.toString(), VICE_CHIEF.toString()) + + // 그 외 + .anyRequest() + .hasRole(ANONYMOUS.toString()); + + http.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class); + } + + @Bean + public SecurityExpressionHandler expressionHandler() { + DefaultWebSecurityExpressionHandler webSecurityExpressionHandler = + new DefaultWebSecurityExpressionHandler(); + webSecurityExpressionHandler.setRoleHierarchy(hierarchy.getHierarchy()); + return webSecurityExpressionHandler; + } + + public JwtAuthenticationFilter jwtAuthenticationFilter() throws Exception { + final List skipPaths = new ArrayList<>(); + + for (String path : AUTH_WHITELIST_CLUB_ACTIVITY) { + skipPaths.add(new CustomRequestMatcher(path, "GET")); + } + + for (String path : AUTH_WHITELIST_TOKEN) { + skipPaths.add(new CustomRequestMatcher(path, "POST")); + } + + final RequestMatcher requestMatcher = new AndRequestMatcher(skipPaths); + final JwtAuthenticationFilter filter = + new JwtAuthenticationFilter( + requestMatcher, jwtTokenUtil, authBeansConfig.tokenResolver()); + filter.setAuthenticationManager(super.authenticationManager()); + return filter; } + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/BaseEntity.java b/resource-server/src/main/java/com/inhabas/api/domain/BaseEntity.java index a6ec71ed..902fe85a 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/BaseEntity.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/BaseEntity.java @@ -1,26 +1,32 @@ package com.inhabas.api.domain; -import lombok.Getter; -import org.springframework.data.annotation.CreatedDate; -import org.springframework.data.annotation.LastModifiedDate; -import org.springframework.data.jpa.domain.support.AuditingEntityListener; +import java.time.LocalDateTime; import javax.persistence.Column; import javax.persistence.EntityListeners; import javax.persistence.MappedSuperclass; -import java.time.LocalDateTime; + +import lombok.Getter; + +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.annotation.LastModifiedDate; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; @MappedSuperclass @EntityListeners(AuditingEntityListener.class) @Getter public abstract class BaseEntity { - @CreatedDate - @Column(nullable = false, updatable = false, insertable = false, columnDefinition = "DATETIME(0) DEFAULT CURRENT_TIMESTAMP") - private LocalDateTime dateCreated; + @CreatedDate + @Column( + nullable = false, + updatable = false, + insertable = false, + columnDefinition = "DATETIME(0) DEFAULT CURRENT_TIMESTAMP") + private LocalDateTime dateCreated; - @CreatedDate - @LastModifiedDate - @Column(columnDefinition = "DATETIME(0)") - private LocalDateTime dateUpdated; + @CreatedDate + @LastModifiedDate + @Column(columnDefinition = "DATETIME(0)") + private LocalDateTime dateUpdated; } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/domain/AlbumBoard.java b/resource-server/src/main/java/com/inhabas/api/domain/board/domain/AlbumBoard.java index c2ec5c82..e39d42d9 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/board/domain/AlbumBoard.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/board/domain/AlbumBoard.java @@ -1,18 +1,21 @@ package com.inhabas.api.domain.board.domain; -import com.inhabas.api.domain.board.domain.valueObject.Content; -import com.inhabas.api.domain.board.domain.valueObject.Title; -import com.inhabas.api.domain.comment.domain.Comment; -import com.inhabas.api.domain.file.domain.BoardFile; -import com.inhabas.api.domain.menu.domain.Menu; +import java.util.ArrayList; +import java.util.List; + +import javax.persistence.*; + import lombok.AccessLevel; import lombok.Builder; import lombok.NoArgsConstructor; + import org.springframework.data.jpa.domain.support.AuditingEntityListener; -import javax.persistence.*; -import java.util.ArrayList; -import java.util.List; +import com.inhabas.api.domain.board.domain.valueObject.Content; +import com.inhabas.api.domain.board.domain.valueObject.Title; +import com.inhabas.api.domain.comment.domain.Comment; +import com.inhabas.api.domain.file.domain.BoardFile; +import com.inhabas.api.domain.menu.domain.Menu; @Entity @Table(name = "ALBUM_BOARD") @@ -21,39 +24,36 @@ @DiscriminatorValue("ALBUM") public class AlbumBoard extends BaseBoard { - @Column - private Content content; + @Column private Content content; - @OneToMany(mappedBy = "parentBoard", cascade = CascadeType.ALL, orphanRemoval = true) - protected List comments = new ArrayList<>(); + @OneToMany(mappedBy = "parentBoard", cascade = CascadeType.ALL, orphanRemoval = true) + protected List comments = new ArrayList<>(); - @Builder - public AlbumBoard(String title, Menu menu, String content) { - super(title, menu); - this.content = new Content(content); - } - - public String getContent() { - return content.getValue(); - } + @Builder + public AlbumBoard(String title, Menu menu, String content) { + super(title, menu); + this.content = new Content(content); + } - public void updateText(String title, String content) { - this.title = new Title(title); - this.content = new Content(content); - } - - public void updateFiles(List files) { + public String getContent() { + return content.getValue(); + } - if (this.files != null) { - this.files.clear(); - } else { - this.files = new ArrayList<>(); - } + public void updateText(String title, String content) { + this.title = new Title(title); + this.content = new Content(content); + } - for (BoardFile file : files) { - addFile(file); - } + public void updateFiles(List files) { + if (this.files != null) { + this.files.clear(); + } else { + this.files = new ArrayList<>(); } + for (BoardFile file : files) { + addFile(file); + } + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/domain/BaseBoard.java b/resource-server/src/main/java/com/inhabas/api/domain/board/domain/BaseBoard.java index f8b7c10c..27eea3cc 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/board/domain/BaseBoard.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/board/domain/BaseBoard.java @@ -1,5 +1,17 @@ package com.inhabas.api.domain.board.domain; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +import javax.persistence.*; + +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import org.springframework.data.jpa.domain.support.AuditingEntityListener; + import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; import com.inhabas.api.domain.BaseEntity; @@ -8,15 +20,6 @@ import com.inhabas.api.domain.comment.domain.Comment; import com.inhabas.api.domain.file.domain.BoardFile; import com.inhabas.api.domain.menu.domain.Menu; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.NoArgsConstructor; -import org.springframework.data.jpa.domain.support.AuditingEntityListener; - -import javax.persistence.*; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; @Getter @Entity @@ -26,64 +29,61 @@ @EntityListeners(AuditingEntityListener.class) public abstract class BaseBoard extends BaseEntity { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - protected Long id; - - @Embedded - protected Title title; + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + protected Long id; - @ManyToOne(fetch = FetchType.LAZY, optional = false) - @JoinColumn(name = "USER_ID", foreignKey = @ForeignKey(name = "FK_BOARD_OF_USER_ID")) - protected Member writer; + @Embedded protected Title title; - @ManyToOne(fetch = FetchType.LAZY, optional = false) - @JoinColumn(name = "MENU_ID", foreignKey = @ForeignKey(name = "FK_BOARD_OF_MENU_ID")) - protected Menu menu; + @ManyToOne(fetch = FetchType.LAZY, optional = false) + @JoinColumn(name = "USER_ID", foreignKey = @ForeignKey(name = "FK_BOARD_OF_USER_ID")) + protected Member writer; - @OneToMany(mappedBy = "board", cascade = CascadeType.ALL, orphanRemoval = true) - protected List files = new ArrayList<>(); + @ManyToOne(fetch = FetchType.LAZY, optional = false) + @JoinColumn(name = "MENU_ID", foreignKey = @ForeignKey(name = "FK_BOARD_OF_MENU_ID")) + protected Menu menu; - @OneToMany(mappedBy = "parentBoard", cascade = CascadeType.ALL, orphanRemoval = true) - protected List comments = new ArrayList<>(); + @OneToMany(mappedBy = "board", cascade = CascadeType.ALL, orphanRemoval = true) + protected List files = new ArrayList<>(); - public T writtenBy(Member writer, Class boardClass){ + @OneToMany(mappedBy = "parentBoard", cascade = CascadeType.ALL, orphanRemoval = true) + protected List comments = new ArrayList<>(); - if (Objects.isNull(this.writer)) { - this.writer = writer; - if (!boardClass.isInstance(this)) { - throw new InvalidInputException(); - } - return boardClass.cast(this); - } - else { - throw new WriterUnmodifiableException(); - } - } + public T writtenBy(Member writer, Class boardClass) { - public boolean isWrittenBy(Member writer) { - return this.writer.equals(writer); + if (Objects.isNull(this.writer)) { + this.writer = writer; + if (!boardClass.isInstance(this)) { + throw new InvalidInputException(); + } + return boardClass.cast(this); + } else { + throw new WriterUnmodifiableException(); } + } - public String getTitle() { - return title.getValue(); - } + public boolean isWrittenBy(Member writer) { + return this.writer.equals(writer); + } - public BaseBoard(String title, Menu menu) { - this.title = new Title(title); - this.menu = menu; - } + public String getTitle() { + return title.getValue(); + } - public void addFile(BoardFile file) { - if (this.files == null) { - this.files = new ArrayList<>(); - } + public BaseBoard(String title, Menu menu) { + this.title = new Title(title); + this.menu = menu; + } - this.files.add(file); + public void addFile(BoardFile file) { + if (this.files == null) { + this.files = new ArrayList<>(); } - public void addComment(Comment newComment) { - comments.add(newComment); - } + this.files.add(file); + } + public void addComment(Comment newComment) { + comments.add(newComment); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/domain/NormalBoard.java b/resource-server/src/main/java/com/inhabas/api/domain/board/domain/NormalBoard.java index d230375d..a64a6d9a 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/board/domain/NormalBoard.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/board/domain/NormalBoard.java @@ -1,19 +1,21 @@ package com.inhabas.api.domain.board.domain; -import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; -import com.inhabas.api.domain.board.exception.OnlyWriterModifiableException; -import com.inhabas.api.domain.board.domain.valueObject.Content; -import com.inhabas.api.domain.board.domain.valueObject.Title; -import com.inhabas.api.domain.comment.domain.Comment; -import com.inhabas.api.domain.file.domain.BoardFile; +import java.util.*; + +import javax.persistence.*; + import lombok.AccessLevel; import lombok.Getter; import lombok.NoArgsConstructor; -import org.springframework.data.jpa.domain.support.AuditingEntityListener; -import javax.persistence.*; -import java.util.*; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; +import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; +import com.inhabas.api.domain.board.domain.valueObject.Content; +import com.inhabas.api.domain.board.domain.valueObject.Title; +import com.inhabas.api.domain.board.exception.OnlyWriterModifiableException; +import com.inhabas.api.domain.comment.domain.Comment; +import com.inhabas.api.domain.file.domain.BoardFile; @Entity @Table(name = "normal_board") @@ -24,61 +26,56 @@ @DiscriminatorValue("NORMAL") public class NormalBoard extends BaseBoard { - @Embedded - protected Content content; + @Embedded protected Content content; - @OneToMany(mappedBy = "parentBoard", cascade = CascadeType.ALL, orphanRemoval = true) - protected List comments = new ArrayList<>(); + @OneToMany(mappedBy = "parentBoard", cascade = CascadeType.ALL, orphanRemoval = true) + protected List comments = new ArrayList<>(); + /* constructor */ - /* constructor */ + public NormalBoard(String title, String contents) { + this.title = new Title(title); + this.content = new Content(contents); + } - public NormalBoard(String title, String contents) { - this.title = new Title(title); - this.content = new Content(contents); - } + /* getter */ + public String getContent() { + return content.getValue(); + } - /* getter */ + public List getFiles() { + return Collections.unmodifiableList(files); + } - public String getContent() { - return content.getValue(); - } + /* relation method */ - public List getFiles() { - return Collections.unmodifiableList(files); - } + public NormalBoard addFiles(Set UploadFiles) { + if (Objects.nonNull(UploadFiles)) UploadFiles.forEach(this::addFile); + return this; + } - /* relation method */ + public void addFile(BoardFile uploadFile) { + files.add(uploadFile); + uploadFile.toBoard(this); + } - public NormalBoard addFiles(Set UploadFiles) { - if (Objects.nonNull(UploadFiles)) - UploadFiles.forEach(this::addFile); + public void addComment(Comment newComment) { + comments.add(newComment); + } - return this; - } - - public void addFile(BoardFile uploadFile) { - files.add(uploadFile); - uploadFile.toBoard(this); - } + public void modify(String title, String contents, Member writer) { - public void addComment(Comment newComment) { - comments.add(newComment); + if (cannotModifiableBy(writer)) { + throw new OnlyWriterModifiableException(); } - public void modify(String title, String contents, Member writer) { - - if (cannotModifiableBy(writer)) { - throw new OnlyWriterModifiableException(); - } + this.title = new Title(title); + this.content = new Content(contents); + } - this.title = new Title(title); - this.content = new Content(contents); - } - - public boolean cannotModifiableBy(Member writer) { - return !this.writer.equals(writer); - } + public boolean cannotModifiableBy(Member writer) { + return !this.writer.equals(writer); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/domain/valueObject/Content.java b/resource-server/src/main/java/com/inhabas/api/domain/board/domain/valueObject/Content.java index 7549f7ad..47f6142f 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/board/domain/valueObject/Content.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/board/domain/valueObject/Content.java @@ -1,41 +1,38 @@ package com.inhabas.api.domain.board.domain.valueObject; - import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; +import java.util.Objects; import javax.persistence.Column; import javax.persistence.Embeddable; import javax.persistence.Transient; -import java.util.Objects; + +import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; @Embeddable public class Content { - @Column(name = "CONTENT", columnDefinition = "MEDIUMTEXT", nullable = false) - private String value; - - @Transient - private final int MAX_SIZE = 2 << 24 - 1; //16MB + @Column(name = "CONTENT", columnDefinition = "MEDIUMTEXT", nullable = false) + private String value; - public Content() {} + @Transient private final int MAX_SIZE = 2 << 24 - 1; // 16MB - public Content(String value) { - if (validate(value)) - this.value = value; - else - throw new InvalidInputException(); - } + public Content() {} - private boolean validate(Object value) { - if (Objects.isNull(value)) return false; - if (!(value instanceof String)) return false; + public Content(String value) { + if (validate(value)) this.value = value; + else throw new InvalidInputException(); + } - String o = (String) value; - if (o.isBlank()) return false; - return o.length() < MAX_SIZE; - } + private boolean validate(Object value) { + if (Objects.isNull(value)) return false; + if (!(value instanceof String)) return false; - public String getValue() { - return value; - } + String o = (String) value; + if (o.isBlank()) return false; + return o.length() < MAX_SIZE; + } + public String getValue() { + return value; + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/domain/valueObject/Title.java b/resource-server/src/main/java/com/inhabas/api/domain/board/domain/valueObject/Title.java index d22f6391..6536ec97 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/board/domain/valueObject/Title.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/board/domain/valueObject/Title.java @@ -1,40 +1,38 @@ package com.inhabas.api.domain.board.domain.valueObject; -import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; +import java.util.Objects; import javax.persistence.Column; import javax.persistence.Embeddable; import javax.persistence.Transient; -import java.util.Objects; + +import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; @Embeddable public class Title { - @Column(name = "TITLE", length = 100, nullable = false) - private String value; + @Column(name = "TITLE", length = 100, nullable = false) + private String value; - @Transient - private final int MAX_LENGTH = 100; + @Transient private final int MAX_LENGTH = 100; - public Title() {} + public Title() {} - public Title(String value) { - if (validate(value)) - this.value = value; - else - throw new InvalidInputException(); - } + public Title(String value) { + if (validate(value)) this.value = value; + else throw new InvalidInputException(); + } - private boolean validate(Object value) { - if (Objects.isNull(value)) return false; - if (!(value instanceof String)) return false; + private boolean validate(Object value) { + if (Objects.isNull(value)) return false; + if (!(value instanceof String)) return false; - String o = (String) value; - if (o.isBlank()) return false; - return o.length() < MAX_LENGTH; - } + String o = (String) value; + if (o.isBlank()) return false; + return o.length() < MAX_LENGTH; + } - public String getValue() { - return value; - } + public String getValue() { + return value; + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/dto/BoardDto.java b/resource-server/src/main/java/com/inhabas/api/domain/board/dto/BoardDto.java index 3280bbc6..a06da371 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/board/dto/BoardDto.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/board/dto/BoardDto.java @@ -1,23 +1,25 @@ package com.inhabas.api.domain.board.dto; -import com.fasterxml.jackson.annotation.JsonFormat; -import com.fasterxml.jackson.annotation.JsonUnwrapped; -import com.inhabas.api.domain.menu.domain.valueObject.MenuId; import java.time.LocalDateTime; + import lombok.AllArgsConstructor; import lombok.Getter; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonUnwrapped; +import com.inhabas.api.domain.menu.domain.valueObject.MenuId; + @Getter @AllArgsConstructor public class BoardDto { - private Integer id; - private String title; - private String contents; - private String writerName; - @JsonUnwrapped - private MenuId menuId; + private Integer id; + private String title; + private String contents; + private String writerName; + @JsonUnwrapped private MenuId menuId; + + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss") + private LocalDateTime created; - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern="yyyy-MM-dd'T'HH:mm:ss") - private LocalDateTime created; - private LocalDateTime updated; + private LocalDateTime updated; } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/dto/SaveBoardDto.java b/resource-server/src/main/java/com/inhabas/api/domain/board/dto/SaveBoardDto.java index 64cbefe3..84afb64d 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/board/dto/SaveBoardDto.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/board/dto/SaveBoardDto.java @@ -1,29 +1,30 @@ package com.inhabas.api.domain.board.dto; -import com.inhabas.api.domain.menu.domain.valueObject.MenuId; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; + import lombok.AccessLevel; import lombok.Getter; import lombok.NoArgsConstructor; + +import com.inhabas.api.domain.menu.domain.valueObject.MenuId; import org.hibernate.validator.constraints.Length; @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) public class SaveBoardDto { - @NotBlank(message = "제목을 입력하세요.") - @Length(max = 100, message = "제목은 최대 100자입니다.") - private String title; + @NotBlank(message = "제목을 입력하세요.") + @Length(max = 100, message = "제목은 최대 100자입니다.") + private String title; - @NotBlank(message = "본문을 입력하세요.") - private String contents; + @NotBlank(message = "본문을 입력하세요.") + private String contents; - @NotNull - private MenuId menuId; + @NotNull private MenuId menuId; - public SaveBoardDto(String title, String contents, MenuId menuId) { - this.title = title; - this.contents = contents; - this.menuId = menuId; - } + public SaveBoardDto(String title, String contents, MenuId menuId) { + this.title = title; + this.contents = contents; + this.menuId = menuId; + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/dto/UpdateBoardDto.java b/resource-server/src/main/java/com/inhabas/api/domain/board/dto/UpdateBoardDto.java index 05aefcf7..8f5aaec8 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/board/dto/UpdateBoardDto.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/board/dto/UpdateBoardDto.java @@ -1,30 +1,29 @@ package com.inhabas.api.domain.board.dto; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; -@Getter @Setter +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter @NoArgsConstructor public class UpdateBoardDto { - @NotNull - private Long id; - - @NotBlank(message = "제목을 입력하세요.") - @Size(max = 100, message = "제목은 최대 100자입니다.") - private String title; + @NotNull private Long id; - @NotBlank(message = "본문을 입력하세요") - private String contents; + @NotBlank(message = "제목을 입력하세요.") + @Size(max = 100, message = "제목은 최대 100자입니다.") + private String title; - public UpdateBoardDto(Long id, String title, String contents) { - this.id = id; - this.title = title; - this.contents = contents; - } + @NotBlank(message = "본문을 입력하세요") + private String contents; + public UpdateBoardDto(Long id, String title, String contents) { + this.id = id; + this.title = title; + this.contents = contents; + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/exception/OnlyWriterModifiableException.java b/resource-server/src/main/java/com/inhabas/api/domain/board/exception/OnlyWriterModifiableException.java index d73ef34f..628dfe0c 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/board/exception/OnlyWriterModifiableException.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/board/exception/OnlyWriterModifiableException.java @@ -4,12 +4,11 @@ public class OnlyWriterModifiableException extends AccessDeniedException { - public OnlyWriterModifiableException() { - super("다른 작성자가 작성한 글은 수정할 수 없습니다!"); - } - - public OnlyWriterModifiableException(String msg) { - super(msg); - } + public OnlyWriterModifiableException() { + super("다른 작성자가 작성한 글은 수정할 수 없습니다!"); + } + public OnlyWriterModifiableException(String msg) { + super(msg); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/exception/OnlyWriterUpdateException.java b/resource-server/src/main/java/com/inhabas/api/domain/board/exception/OnlyWriterUpdateException.java index fef1d71a..5fb9525b 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/board/exception/OnlyWriterUpdateException.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/board/exception/OnlyWriterUpdateException.java @@ -5,8 +5,7 @@ public class OnlyWriterUpdateException extends BusinessException { - public OnlyWriterUpdateException() { - super(ErrorCode.ONLY_WRITER_UPDATE); - } - + public OnlyWriterUpdateException() { + super(ErrorCode.ONLY_WRITER_UPDATE); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/exception/S3UploadFailedException.java b/resource-server/src/main/java/com/inhabas/api/domain/board/exception/S3UploadFailedException.java index 73ba18b5..2b287a18 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/board/exception/S3UploadFailedException.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/board/exception/S3UploadFailedException.java @@ -5,8 +5,7 @@ public class S3UploadFailedException extends BusinessException { - public S3UploadFailedException() { - super(ErrorCode.S3_UPLOAD_FAILED); - } - + public S3UploadFailedException() { + super(ErrorCode.S3_UPLOAD_FAILED); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/exception/WriterUnmodifiableException.java b/resource-server/src/main/java/com/inhabas/api/domain/board/exception/WriterUnmodifiableException.java index 963079c1..a1fcdc36 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/board/exception/WriterUnmodifiableException.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/board/exception/WriterUnmodifiableException.java @@ -5,8 +5,7 @@ public class WriterUnmodifiableException extends BusinessException { - public WriterUnmodifiableException() { - super(ErrorCode.WRITER_UNMODIFIABLE); - } - -} \ No newline at end of file + public WriterUnmodifiableException() { + super(ErrorCode.WRITER_UNMODIFIABLE); + } +} diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/repository/BaseBoardRepository.java b/resource-server/src/main/java/com/inhabas/api/domain/board/repository/BaseBoardRepository.java index eac06128..8fae3619 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/board/repository/BaseBoardRepository.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/board/repository/BaseBoardRepository.java @@ -1,7 +1,7 @@ package com.inhabas.api.domain.board.repository; -import com.inhabas.api.domain.board.domain.BaseBoard; import org.springframework.data.jpa.repository.JpaRepository; -public interface BaseBoardRepository extends JpaRepository { -} +import com.inhabas.api.domain.board.domain.BaseBoard; + +public interface BaseBoardRepository extends JpaRepository {} diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/repository/NormalBoardRepository.java b/resource-server/src/main/java/com/inhabas/api/domain/board/repository/NormalBoardRepository.java index 9b3b834a..49122501 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/board/repository/NormalBoardRepository.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/board/repository/NormalBoardRepository.java @@ -1,7 +1,8 @@ package com.inhabas.api.domain.board.repository; -import com.inhabas.api.domain.board.domain.NormalBoard; import org.springframework.data.jpa.repository.JpaRepository; -public interface NormalBoardRepository extends JpaRepository, NormalBoardRepositoryCustom { -} \ No newline at end of file +import com.inhabas.api.domain.board.domain.NormalBoard; + +public interface NormalBoardRepository + extends JpaRepository, NormalBoardRepositoryCustom {} diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/repository/NormalBoardRepositoryCustom.java b/resource-server/src/main/java/com/inhabas/api/domain/board/repository/NormalBoardRepositoryCustom.java index cbb98da0..90c5fedb 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/board/repository/NormalBoardRepositoryCustom.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/board/repository/NormalBoardRepositoryCustom.java @@ -1,13 +1,15 @@ package com.inhabas.api.domain.board.repository; -import com.inhabas.api.domain.board.dto.BoardDto; import java.util.Optional; + import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; +import com.inhabas.api.domain.board.dto.BoardDto; + public interface NormalBoardRepositoryCustom { - Page findAllByMenuId(Integer menuId, Pageable pageable); - Optional findDtoById(Long id); + Page findAllByMenuId(Integer menuId, Pageable pageable); + Optional findDtoById(Long id); } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/repository/NormalBoardRepositoryImpl.java b/resource-server/src/main/java/com/inhabas/api/domain/board/repository/NormalBoardRepositoryImpl.java index db37b632..59d9df4a 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/board/repository/NormalBoardRepositoryImpl.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/board/repository/NormalBoardRepositoryImpl.java @@ -1,78 +1,88 @@ package com.inhabas.api.domain.board.repository; -import static com.inhabas.api.domain.board.domain.QNormalBoard.normalBoard; import static com.inhabas.api.auth.domain.oauth2.member.domain.entity.QMember.member; +import static com.inhabas.api.domain.board.domain.QNormalBoard.normalBoard; -import com.inhabas.api.domain.board.dto.BoardDto; -import com.querydsl.core.types.Projections; -import com.querydsl.core.types.dsl.BooleanExpression; -import com.querydsl.core.types.dsl.Expressions; -import com.querydsl.jpa.impl.JPAQueryFactory; import java.util.List; import java.util.Optional; + import lombok.RequiredArgsConstructor; + import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; +import com.inhabas.api.domain.board.dto.BoardDto; +import com.querydsl.core.types.Projections; +import com.querydsl.core.types.dsl.BooleanExpression; +import com.querydsl.core.types.dsl.Expressions; +import com.querydsl.jpa.impl.JPAQueryFactory; + @RequiredArgsConstructor public class NormalBoardRepositoryImpl implements NormalBoardRepositoryCustom { - private final JPAQueryFactory queryFactory; + private final JPAQueryFactory queryFactory; - @Override - public Page findAllByMenuId(Integer menuId, Pageable pageable) { - List results = queryFactory.select(Projections.constructor(BoardDto.class, - normalBoard.id, - normalBoard.title.value, - Expressions.asString("").as("content"), - member.name.value, - normalBoard.menu.id, - normalBoard.dateCreated, - normalBoard.dateUpdated)) - .from(normalBoard) - .innerJoin(member).on(eqMemberId()) - .where(eqMenuId(menuId)) - .offset(pageable.getOffset()) - .limit(pageable.getPageSize()) - .orderBy(normalBoard.dateCreated.desc()) - .fetch(); + @Override + public Page findAllByMenuId(Integer menuId, Pageable pageable) { + List results = + queryFactory + .select( + Projections.constructor( + BoardDto.class, + normalBoard.id, + normalBoard.title.value, + Expressions.asString("").as("content"), + member.name.value, + normalBoard.menu.id, + normalBoard.dateCreated, + normalBoard.dateUpdated)) + .from(normalBoard) + .innerJoin(member) + .on(eqMemberId()) + .where(eqMenuId(menuId)) + .offset(pageable.getOffset()) + .limit(pageable.getPageSize()) + .orderBy(normalBoard.dateCreated.desc()) + .fetch(); - return new PageImpl<>(results, pageable, this.getCount(menuId)); - } + return new PageImpl<>(results, pageable, this.getCount(menuId)); + } - private BooleanExpression eqMenuId(Integer menuId) { - return normalBoard.menu.id.eq(menuId); - } + private BooleanExpression eqMenuId(Integer menuId) { + return normalBoard.menu.id.eq(menuId); + } - // 캐시 필요함. - private Integer getCount(Integer menuId) { - return queryFactory.selectFrom(normalBoard) - .where(eqMenuId(menuId)) - .fetch() - .size(); - } + // 캐시 필요함. + private Integer getCount(Integer menuId) { + return queryFactory.selectFrom(normalBoard).where(eqMenuId(menuId)).fetch().size(); + } - @Override - public Optional findDtoById(Long id) { + @Override + public Optional findDtoById(Long id) { - BoardDto target = queryFactory.select(Projections.constructor(BoardDto.class, - Expressions.asNumber(id).as("id"), - normalBoard.title.value, - normalBoard.content.value, - member.name.value, - normalBoard.menu.id, - normalBoard.dateCreated, - normalBoard.dateUpdated)) - .from(normalBoard) - .innerJoin(member).on(eqMemberId()) - .where(normalBoard.id.eq(id)) - .fetchOne(); + BoardDto target = + queryFactory + .select( + Projections.constructor( + BoardDto.class, + Expressions.asNumber(id).as("id"), + normalBoard.title.value, + normalBoard.content.value, + member.name.value, + normalBoard.menu.id, + normalBoard.dateCreated, + normalBoard.dateUpdated)) + .from(normalBoard) + .innerJoin(member) + .on(eqMemberId()) + .where(normalBoard.id.eq(id)) + .fetchOne(); - return Optional.ofNullable(target); - } + return Optional.ofNullable(target); + } - private BooleanExpression eqMemberId() { - return normalBoard.writer.id.eq(member.id); - } -} \ No newline at end of file + private BooleanExpression eqMemberId() { + return normalBoard.writer.id.eq(member.id); + } +} diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/usecase/BoardSecurityChecker.java b/resource-server/src/main/java/com/inhabas/api/domain/board/usecase/BoardSecurityChecker.java index 11cdab0a..734f4a1d 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/board/usecase/BoardSecurityChecker.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/board/usecase/BoardSecurityChecker.java @@ -1,5 +1,20 @@ package com.inhabas.api.domain.board.usecase; +import static com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.Role.ANONYMOUS; + +import java.util.Collection; +import java.util.Collections; + +import javax.persistence.EntityNotFoundException; + +import lombok.RequiredArgsConstructor; + +import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Service; + import com.inhabas.api.auth.domain.error.authException.InvalidAuthorityException; import com.inhabas.api.auth.domain.error.businessException.NotFoundException; import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; @@ -13,95 +28,83 @@ import com.inhabas.api.domain.comment.repository.CommentRepository; import com.inhabas.api.domain.menu.domain.Menu; import com.inhabas.api.domain.menu.repository.MenuRepository; -import lombok.RequiredArgsConstructor; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.authority.SimpleGrantedAuthority; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.stereotype.Service; - -import javax.persistence.EntityNotFoundException; -import java.util.Collection; -import java.util.Collections; - -import static com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.Role.ANONYMOUS; @Service @RequiredArgsConstructor public class BoardSecurityChecker { - private final BaseBoardRepository baseBoardRepository; - private final MemberRepository memberRepository; - private final MenuRepository menuRepository; - private final CommentRepository commentRepository; - private final DefaultRoleHierarchy roleHierarchy; - - public final static String READ_BOARD_LIST = "readBoardList"; - public final static String CREATE_BOARD = "createBoard"; - public final static String READ_BOARD = "readBoard"; - public final static String CREATE_COMMENT = "createComment"; - public final static String READ_COMMENT = "readComment"; - public final static String ROLE_PREFIX = "ROLE_"; - - - public boolean boardWriterOnly(Long boardId) { - - Long memberId = (Long) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); - Member member = memberRepository.findById(memberId).orElseThrow(MemberNotFoundException::new); - BaseBoard baseBoard = baseBoardRepository.findById(boardId) - .orElseThrow(EntityNotFoundException::new); - - return baseBoard.isWrittenBy(member); - + private final BaseBoardRepository baseBoardRepository; + private final MemberRepository memberRepository; + private final MenuRepository menuRepository; + private final CommentRepository commentRepository; + private final DefaultRoleHierarchy roleHierarchy; + + public static final String READ_BOARD_LIST = "readBoardList"; + public static final String CREATE_BOARD = "createBoard"; + public static final String READ_BOARD = "readBoard"; + public static final String CREATE_COMMENT = "createComment"; + public static final String READ_COMMENT = "readComment"; + public static final String ROLE_PREFIX = "ROLE_"; + + public boolean boardWriterOnly(Long boardId) { + + Long memberId = (Long) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); + Member member = memberRepository.findById(memberId).orElseThrow(MemberNotFoundException::new); + BaseBoard baseBoard = + baseBoardRepository.findById(boardId).orElseThrow(EntityNotFoundException::new); + + return baseBoard.isWrittenBy(member); + } + + public boolean commentWriterOnly(Long commentId) { + + Long memberId = (Long) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); + Comment comment = + commentRepository.findById(commentId).orElseThrow(EntityNotFoundException::new); + + return comment.isWrittenBy(memberId); + } + + public boolean checkMenuAccess(Integer menuId, String action) { + + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Collection authorities; + if (authentication == null) { + authorities = Collections.singleton(new SimpleGrantedAuthority(ROLE_PREFIX + ANONYMOUS)); + } else { + authorities = + roleHierarchy + .getHierarchy() + .getReachableGrantedAuthorities(authentication.getAuthorities()); } - public boolean commentWriterOnly(Long commentId) { - - Long memberId = (Long) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); - Comment comment = commentRepository.findById(commentId).orElseThrow(EntityNotFoundException::new); - - return comment.isWrittenBy(memberId); - + Menu menu = menuRepository.findById(menuId).orElseThrow(NotFoundException::new); + Role required = null; + switch (action) { + case READ_BOARD_LIST: + required = menu.getType().getReadBoardListRole(); + break; + case CREATE_BOARD: + required = menu.getType().getCreateBoardRole(); + break; + case READ_BOARD: + required = menu.getType().getReadBoardRole(); + break; + case CREATE_COMMENT: + required = menu.getType().getCreateCommentRole(); + break; + case READ_COMMENT: + required = menu.getType().getReadCommentRole(); + break; } - - public boolean checkMenuAccess(Integer menuId, String action) { - - Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); - Collection authorities; - if (authentication == null) { - authorities = Collections.singleton(new SimpleGrantedAuthority(ROLE_PREFIX + ANONYMOUS)); - } else { - authorities = roleHierarchy.getHierarchy().getReachableGrantedAuthorities(authentication.getAuthorities()); - } - - Menu menu = menuRepository.findById(menuId).orElseThrow(NotFoundException::new); - Role required = null; - switch (action) { - case READ_BOARD_LIST: - required = menu.getType().getReadBoardListRole(); - break; - case CREATE_BOARD: - required = menu.getType().getCreateBoardRole(); - break; - case READ_BOARD: - required = menu.getType().getReadBoardRole(); - break; - case CREATE_COMMENT: - required = menu.getType().getCreateCommentRole(); - break; - case READ_COMMENT: - required = menu.getType().getReadCommentRole(); - break; - } - - String finalRequired = ROLE_PREFIX + required; - if (required == null || authorities.stream().noneMatch(grantedAuthority -> grantedAuthority.getAuthority().equals(finalRequired))) { - throw new InvalidAuthorityException(); - } - - return true; - + String finalRequired = ROLE_PREFIX + required; + if (required == null + || authorities.stream() + .noneMatch(grantedAuthority -> grantedAuthority.getAuthority().equals(finalRequired))) { + throw new InvalidAuthorityException(); } + return true; + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/usecase/BoardService.java b/resource-server/src/main/java/com/inhabas/api/domain/board/usecase/BoardService.java index 4922896c..ff870c68 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/board/usecase/BoardService.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/board/usecase/BoardService.java @@ -1,20 +1,20 @@ package com.inhabas.api.domain.board.usecase; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; + import com.inhabas.api.domain.board.dto.BoardDto; import com.inhabas.api.domain.board.dto.SaveBoardDto; import com.inhabas.api.domain.board.dto.UpdateBoardDto; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; public interface BoardService { - Long write(Long memberId, SaveBoardDto saveBoardDto); - - Long update(Long memberId, UpdateBoardDto updateBoardDto); + Long write(Long memberId, SaveBoardDto saveBoardDto); - void delete(Long memberId, Long boardId); + Long update(Long memberId, UpdateBoardDto updateBoardDto); - BoardDto getBoard(Long boardId); + void delete(Long memberId, Long boardId); - Page getBoardList(Integer menuId, Pageable pageable); + BoardDto getBoard(Long boardId); + Page getBoardList(Integer menuId, Pageable pageable); } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/usecase/BoardServiceImpl.java b/resource-server/src/main/java/com/inhabas/api/domain/board/usecase/BoardServiceImpl.java index 8469ca5c..53bb6fed 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/board/usecase/BoardServiceImpl.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/board/usecase/BoardServiceImpl.java @@ -1,5 +1,14 @@ package com.inhabas.api.domain.board.usecase; +import javax.transaction.Transactional; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; + import com.inhabas.api.auth.domain.error.businessException.NotFoundException; import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; import com.inhabas.api.auth.domain.oauth2.member.domain.exception.MemberNotFoundException; @@ -11,13 +20,6 @@ import com.inhabas.api.domain.board.exception.OnlyWriterModifiableException; import com.inhabas.api.domain.board.repository.NormalBoardRepository; import com.inhabas.api.domain.menu.repository.MenuRepository; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.stereotype.Service; - -import javax.transaction.Transactional; @Service @Slf4j @@ -25,58 +27,56 @@ @RequiredArgsConstructor public class BoardServiceImpl implements BoardService { - private final NormalBoardRepository boardRepository; - private final MenuRepository menuRepository; - private final MemberRepository memberRepository; + private final NormalBoardRepository boardRepository; + private final MenuRepository menuRepository; + private final MemberRepository memberRepository; - @Override - public Long write(Long memberId, SaveBoardDto saveBoardDto) { + @Override + public Long write(Long memberId, SaveBoardDto saveBoardDto) { - Member writer = memberRepository.findById(memberId).orElseThrow(MemberNotFoundException::new); + Member writer = memberRepository.findById(memberId).orElseThrow(MemberNotFoundException::new); - NormalBoard normalBoard = new NormalBoard(saveBoardDto.getTitle(), saveBoardDto.getContents()) - .writtenBy(writer, NormalBoard.class); + NormalBoard normalBoard = + new NormalBoard(saveBoardDto.getTitle(), saveBoardDto.getContents()) + .writtenBy(writer, NormalBoard.class); - return boardRepository.save(normalBoard).getId(); - } - - @Override - public Long update(Long memberId, UpdateBoardDto updateBoardDto) { + return boardRepository.save(normalBoard).getId(); + } - NormalBoard savedBoard = boardRepository.findById(updateBoardDto.getId()) - .orElseThrow(NotFoundException::new); - Member writer = memberRepository.findById(memberId).orElseThrow(MemberNotFoundException::new); + @Override + public Long update(Long memberId, UpdateBoardDto updateBoardDto) { - savedBoard.modify(updateBoardDto.getTitle(), updateBoardDto.getContents(), writer); + NormalBoard savedBoard = + boardRepository.findById(updateBoardDto.getId()).orElseThrow(NotFoundException::new); + Member writer = memberRepository.findById(memberId).orElseThrow(MemberNotFoundException::new); - return boardRepository.save(savedBoard).getId(); - } + savedBoard.modify(updateBoardDto.getTitle(), updateBoardDto.getContents(), writer); - @Override - public void delete(Long memberId, Long boardId) { + return boardRepository.save(savedBoard).getId(); + } - NormalBoard board = boardRepository.findById(boardId) - .orElseThrow(NotFoundException::new); - Member writer = memberRepository.findById(memberId).orElseThrow(MemberNotFoundException::new); + @Override + public void delete(Long memberId, Long boardId) { - if (board.cannotModifiableBy(writer)) { - throw new OnlyWriterModifiableException(); - } + NormalBoard board = boardRepository.findById(boardId).orElseThrow(NotFoundException::new); + Member writer = memberRepository.findById(memberId).orElseThrow(MemberNotFoundException::new); - boardRepository.deleteById(boardId); + if (board.cannotModifiableBy(writer)) { + throw new OnlyWriterModifiableException(); } - @Override - public BoardDto getBoard(Long id) { + boardRepository.deleteById(boardId); + } - return boardRepository.findDtoById(id) - .orElseThrow(NotFoundException::new); - } + @Override + public BoardDto getBoard(Long id) { - @Override - public Page getBoardList(Integer menuId, Pageable pageable) { + return boardRepository.findDtoById(id).orElseThrow(NotFoundException::new); + } - return boardRepository.findAllByMenuId(menuId, pageable); - } + @Override + public Page getBoardList(Integer menuId, Pageable pageable) { + return boardRepository.findAllByMenuId(menuId, pageable); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/budget/ApplicationCannotModifiableException.java b/resource-server/src/main/java/com/inhabas/api/domain/budget/ApplicationCannotModifiableException.java index 6a164be2..77f33394 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/budget/ApplicationCannotModifiableException.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/budget/ApplicationCannotModifiableException.java @@ -4,11 +4,11 @@ public class ApplicationCannotModifiableException extends AccessDeniedException { - public ApplicationCannotModifiableException() { - super("다른 사람이 작성한 내역은 수정할 수 없습니다!"); - } + public ApplicationCannotModifiableException() { + super("다른 사람이 작성한 내역은 수정할 수 없습니다!"); + } - public ApplicationCannotModifiableException(String msg) { - super(msg); - } + public ApplicationCannotModifiableException(String msg) { + super(msg); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/budget/ApplicationNotFoundException.java b/resource-server/src/main/java/com/inhabas/api/domain/budget/ApplicationNotFoundException.java index 30504f66..86769d16 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/budget/ApplicationNotFoundException.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/budget/ApplicationNotFoundException.java @@ -2,11 +2,11 @@ public class ApplicationNotFoundException extends RuntimeException { - public ApplicationNotFoundException() { - super("cannot find such budget support application!"); - } + public ApplicationNotFoundException() { + super("cannot find such budget support application!"); + } - public ApplicationNotFoundException(String message) { - super(message); - } + public ApplicationNotFoundException(String message) { + super(message); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/budget/BudgetHistoryNotFoundException.java b/resource-server/src/main/java/com/inhabas/api/domain/budget/BudgetHistoryNotFoundException.java index 15e5127d..1fd9354f 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/budget/BudgetHistoryNotFoundException.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/budget/BudgetHistoryNotFoundException.java @@ -2,11 +2,11 @@ public class BudgetHistoryNotFoundException extends RuntimeException { - public BudgetHistoryNotFoundException() { - super("cannot find such budget history!"); - } + public BudgetHistoryNotFoundException() { + super("cannot find such budget history!"); + } - public BudgetHistoryNotFoundException(String message) { - super(message); - } + public BudgetHistoryNotFoundException(String message) { + super(message); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/budget/HistoryCannotModifiableException.java b/resource-server/src/main/java/com/inhabas/api/domain/budget/HistoryCannotModifiableException.java index 9bc35b24..49a1def9 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/budget/HistoryCannotModifiableException.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/budget/HistoryCannotModifiableException.java @@ -4,11 +4,11 @@ public class HistoryCannotModifiableException extends AccessDeniedException { - public HistoryCannotModifiableException() { - super("다른 담당자가 작성한 내역은 수정할 수 없습니다!"); - } + public HistoryCannotModifiableException() { + super("다른 담당자가 작성한 내역은 수정할 수 없습니다!"); + } - public HistoryCannotModifiableException(String msg) { - super(msg); - } + public HistoryCannotModifiableException(String msg) { + super(msg); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/budget/domain/BudgetHistory.java b/resource-server/src/main/java/com/inhabas/api/domain/budget/domain/BudgetHistory.java index a217f4a2..f32b7b57 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/budget/domain/BudgetHistory.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/budget/domain/BudgetHistory.java @@ -1,5 +1,16 @@ package com.inhabas.api.domain.budget.domain; +import java.time.LocalDateTime; + +import javax.persistence.*; + +import lombok.AccessLevel; +import lombok.Builder; +import lombok.NoArgsConstructor; + +import org.springframework.data.jpa.domain.support.AuditingEntityListener; + +import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.StudentId; import com.inhabas.api.domain.BaseEntity; import com.inhabas.api.domain.budget.BudgetHistoryNotFoundException; import com.inhabas.api.domain.budget.HistoryCannotModifiableException; @@ -7,14 +18,6 @@ import com.inhabas.api.domain.budget.domain.valueObject.Details; import com.inhabas.api.domain.budget.domain.valueObject.Price; import com.inhabas.api.domain.budget.domain.valueObject.Title; -import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.StudentId; -import lombok.AccessLevel; -import lombok.Builder; -import lombok.NoArgsConstructor; -import org.springframework.data.jpa.domain.support.AuditingEntityListener; - -import javax.persistence.*; -import java.time.LocalDateTime; @Entity @EntityListeners(AuditingEntityListener.class) @@ -22,74 +25,86 @@ @Table(name = "budget_history") public class BudgetHistory extends BaseEntity { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Integer id; - - @AttributeOverride(name = "value", column = @Column(name = "income", nullable = false)) - private Price income; - - @AttributeOverride(name = "value", column = @Column(name = "outcome", nullable = false)) - private Price outcome; - - @Column(name = "date_used", nullable = false) - private LocalDateTime dateUsed; - - private Title title; - - private Details details; - - private Account account; - -// private List receipts; - - @Embedded - @AttributeOverride(name = "id", column = @Column(name = "person_in_charge", nullable = false)) - private StudentId personInCharge; - - @Embedded - @AttributeOverride(name = "id", column = @Column(name = "person_received", nullable = false)) - private StudentId personReceived; - - public StudentId getPersonReceived() { - return personReceived; + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer id; + + @AttributeOverride(name = "value", column = @Column(name = "income", nullable = false)) + private Price income; + + @AttributeOverride(name = "value", column = @Column(name = "outcome", nullable = false)) + private Price outcome; + + @Column(name = "date_used", nullable = false) + private LocalDateTime dateUsed; + + private Title title; + + private Details details; + + private Account account; + + // private List receipts; + + @Embedded + @AttributeOverride(name = "id", column = @Column(name = "person_in_charge", nullable = false)) + private StudentId personInCharge; + + @Embedded + @AttributeOverride(name = "id", column = @Column(name = "person_received", nullable = false)) + private StudentId personReceived; + + public StudentId getPersonReceived() { + return personReceived; + } + + public StudentId getPersonInCharge() { + return personInCharge; + } + + public boolean cannotModifiableBy(StudentId CFO) { + return !this.personInCharge.equals(CFO); + } + + @Builder + public BudgetHistory( + Integer income, + Integer outcome, + LocalDateTime dateUsed, + String title, + String details, + StudentId personInCharge, + StudentId personReceived) { + this.income = new Price(income); + this.outcome = new Price(outcome); + this.dateUsed = dateUsed; + this.title = new Title(title); + this.details = new Details(details); + this.personInCharge = personInCharge; + this.personReceived = personReceived; + } + + public void modify( + StudentId currentCFO, + Integer income, + Integer outcome, + LocalDateTime dateUsed, + String title, + String details, + StudentId personReceived) { + + if (this.id == null) { + throw new BudgetHistoryNotFoundException( + "cannot modify this entity, because not persisted ever!"); } - public StudentId getPersonInCharge() { - return personInCharge; - } - - public boolean cannotModifiableBy(StudentId CFO) { - return !this.personInCharge.equals(CFO); - } - - @Builder - public BudgetHistory(Integer income, Integer outcome, LocalDateTime dateUsed, - String title, String details, StudentId personInCharge, StudentId personReceived) { - this.income = new Price(income); - this.outcome = new Price(outcome); - this.dateUsed = dateUsed; - this.title = new Title(title); - this.details = new Details(details); - this.personInCharge = personInCharge; - this.personReceived = personReceived; - } + if (this.cannotModifiableBy(currentCFO)) throw new HistoryCannotModifiableException(); - public void modify(StudentId currentCFO, Integer income, Integer outcome, LocalDateTime dateUsed, - String title, String details, StudentId personReceived) { - - if (this.id == null) { - throw new BudgetHistoryNotFoundException("cannot modify this entity, because not persisted ever!"); - } - - if (this.cannotModifiableBy(currentCFO)) - throw new HistoryCannotModifiableException(); - - this.title = new Title(title); - this.details = new Details(details); - this.dateUsed = dateUsed; - this.income = new Price(income); - this.outcome = new Price(outcome); - this.personReceived = personReceived; - } + this.title = new Title(title); + this.details = new Details(details); + this.dateUsed = dateUsed; + this.income = new Price(income); + this.outcome = new Price(outcome); + this.personReceived = personReceived; + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/budget/domain/BudgetSupportApplication.java b/resource-server/src/main/java/com/inhabas/api/domain/budget/domain/BudgetSupportApplication.java index 58efcee8..bfad8583 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/budget/domain/BudgetSupportApplication.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/budget/domain/BudgetSupportApplication.java @@ -1,137 +1,144 @@ package com.inhabas.api.domain.budget.domain; +import java.time.LocalDateTime; + +import javax.persistence.*; + +import lombok.AccessLevel; +import lombok.Builder; +import lombok.NoArgsConstructor; + +import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.StudentId; import com.inhabas.api.domain.BaseEntity; import com.inhabas.api.domain.budget.ApplicationCannotModifiableException; import com.inhabas.api.domain.budget.ApplicationNotFoundException; import com.inhabas.api.domain.budget.domain.converter.StatusConverter; import com.inhabas.api.domain.budget.domain.valueObject.*; -import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.StudentId; -import lombok.AccessLevel; -import lombok.Builder; -import lombok.NoArgsConstructor; - -import javax.persistence.*; -import java.time.LocalDateTime; @Entity @Table(name = "budget_support_application") @NoArgsConstructor(access = AccessLevel.PROTECTED) public class BudgetSupportApplication extends BaseEntity { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Integer id; - - private Title title; - - private LocalDateTime dateUsed; + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer id; - private Details details; + private Title title; - @AttributeOverride(name = "value", column = @Column(name = "outcome", nullable = false)) - private Price outcome; + private LocalDateTime dateUsed; - private ApplicantAccount applicantAccount; + private Details details; - @AttributeOverride(name = "id", column = @Column(nullable = false, name = "applicant")) - private StudentId applicationWriter; + @AttributeOverride(name = "value", column = @Column(name = "outcome", nullable = false)) + private Price outcome; - @AttributeOverride(name = "id", column = @Column(name = "person_in_charge")) - private StudentId personInCharge; - - @Convert(converter = StatusConverter.class) - @Column(nullable = false) - private ApplicationStatus status; - - private RejectReason rejectReason; - - //private List receipts; - - - @Builder - public BudgetSupportApplication(String title, LocalDateTime dateUsed, String details, Integer outcome, - String account, StudentId applicationWriter) { - this.title = new Title(title); - this.dateUsed = dateUsed; - this.details = new Details(details); - this.outcome = new Price(outcome); - this.applicantAccount = new ApplicantAccount(account); - this.applicationWriter = applicationWriter; - this.status = ApplicationStatus.WAITING; - } + private ApplicantAccount applicantAccount; - public void modify(String title, LocalDateTime dateUsed, String details, Integer outcome, String account, StudentId currentApplicant) { - - if (this.id == null) - throw new ApplicationNotFoundException("cannot modify this entity, because not persisted ever!"); - - if (this.cannotModifiableBy(currentApplicant)) - throw new ApplicationCannotModifiableException(); - - this.title = new Title(title); - this.dateUsed = dateUsed; - this.details = new Details(details); - this.outcome = new Price(outcome); - this.applicantAccount = new ApplicantAccount(account); - this.status = ApplicationStatus.WAITING; - } - - public boolean cannotModifiableBy(StudentId currentApplicant) { - return !this.applicationWriter.equals(currentApplicant); - } - - - - public void approve(StudentId personInCharge) { - - this.status = ApplicationStatus.APPROVED; - this.personInCharge = personInCharge; - } - - public void waiting(StudentId personInCharge) { - - this.status = ApplicationStatus.WAITING; - this.personInCharge = personInCharge; - } - - public void deny(String reason, StudentId personInCharge) { - - this.rejectReason = new RejectReason(reason); - this.status = ApplicationStatus.DENIED; - this.personInCharge = personInCharge; - } - - public void process(StudentId personInCharge) { - - if (this.isProcessed()) - throw new ApplicationCannotModifiableException("이미 처리가 완료된 예산지원 내역입니다."); - - this.status = ApplicationStatus.PROCESSED; - this.personInCharge = personInCharge; - } - - private boolean isProcessed() { - return this.status == ApplicationStatus.PROCESSED; - } + @AttributeOverride(name = "id", column = @Column(nullable = false, name = "applicant")) + private StudentId applicationWriter; - /** - * 예산지원신청을 완전히 다 처리하고 나면 자동적으로 회계처리내역에 추가되도록 하기 위해서, 회계내역 엔티티로 변환한다. - */ - public BudgetHistory makeHistory() { - - if (this.isProcessed() && this.personInCharge != null) { - return BudgetHistory.builder() - .title(this.title.getValue()) - .dateUsed(this.dateUsed) - .details(this.details.getValue()) - .income(0) - .outcome(this.outcome.getValue()) - .personInCharge(this.personInCharge) - .personReceived(this.applicationWriter) - .build(); - } - else { - throw new RuntimeException("회계기록 중에 오류가 발생하였습니다!"); - } + @AttributeOverride(name = "id", column = @Column(name = "person_in_charge")) + private StudentId personInCharge; + + @Convert(converter = StatusConverter.class) + @Column(nullable = false) + private ApplicationStatus status; + + private RejectReason rejectReason; + + // private List receipts; + + @Builder + public BudgetSupportApplication( + String title, + LocalDateTime dateUsed, + String details, + Integer outcome, + String account, + StudentId applicationWriter) { + this.title = new Title(title); + this.dateUsed = dateUsed; + this.details = new Details(details); + this.outcome = new Price(outcome); + this.applicantAccount = new ApplicantAccount(account); + this.applicationWriter = applicationWriter; + this.status = ApplicationStatus.WAITING; + } + + public void modify( + String title, + LocalDateTime dateUsed, + String details, + Integer outcome, + String account, + StudentId currentApplicant) { + + if (this.id == null) + throw new ApplicationNotFoundException( + "cannot modify this entity, because not persisted ever!"); + + if (this.cannotModifiableBy(currentApplicant)) throw new ApplicationCannotModifiableException(); + + this.title = new Title(title); + this.dateUsed = dateUsed; + this.details = new Details(details); + this.outcome = new Price(outcome); + this.applicantAccount = new ApplicantAccount(account); + this.status = ApplicationStatus.WAITING; + } + + public boolean cannotModifiableBy(StudentId currentApplicant) { + return !this.applicationWriter.equals(currentApplicant); + } + + public void approve(StudentId personInCharge) { + + this.status = ApplicationStatus.APPROVED; + this.personInCharge = personInCharge; + } + + public void waiting(StudentId personInCharge) { + + this.status = ApplicationStatus.WAITING; + this.personInCharge = personInCharge; + } + + public void deny(String reason, StudentId personInCharge) { + + this.rejectReason = new RejectReason(reason); + this.status = ApplicationStatus.DENIED; + this.personInCharge = personInCharge; + } + + public void process(StudentId personInCharge) { + + if (this.isProcessed()) + throw new ApplicationCannotModifiableException("이미 처리가 완료된 예산지원 내역입니다."); + + this.status = ApplicationStatus.PROCESSED; + this.personInCharge = personInCharge; + } + + private boolean isProcessed() { + return this.status == ApplicationStatus.PROCESSED; + } + + /** 예산지원신청을 완전히 다 처리하고 나면 자동적으로 회계처리내역에 추가되도록 하기 위해서, 회계내역 엔티티로 변환한다. */ + public BudgetHistory makeHistory() { + + if (this.isProcessed() && this.personInCharge != null) { + return BudgetHistory.builder() + .title(this.title.getValue()) + .dateUsed(this.dateUsed) + .details(this.details.getValue()) + .income(0) + .outcome(this.outcome.getValue()) + .personInCharge(this.personInCharge) + .personReceived(this.applicationWriter) + .build(); + } else { + throw new RuntimeException("회계기록 중에 오류가 발생하였습니다!"); } + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/budget/domain/converter/StatusConverter.java b/resource-server/src/main/java/com/inhabas/api/domain/budget/domain/converter/StatusConverter.java index d9315cdd..02435255 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/budget/domain/converter/StatusConverter.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/budget/domain/converter/StatusConverter.java @@ -1,27 +1,27 @@ package com.inhabas.api.domain.budget.domain.converter; -import com.inhabas.api.domain.budget.domain.valueObject.ApplicationStatus; +import java.util.Objects; import javax.persistence.AttributeConverter; import javax.persistence.Converter; -import java.util.Objects; + +import com.inhabas.api.domain.budget.domain.valueObject.ApplicationStatus; @Converter public class StatusConverter implements AttributeConverter { - @Override - public Integer convertToDatabaseColumn(ApplicationStatus status) { + @Override + public Integer convertToDatabaseColumn(ApplicationStatus status) { - return status.getValue(); - } + return status.getValue(); + } - @Override - public ApplicationStatus convertToEntityAttribute(Integer dbData) { + @Override + public ApplicationStatus convertToEntityAttribute(Integer dbData) { - for (ApplicationStatus status: ApplicationStatus.values()){ - if (Objects.equals(status.getValue(), dbData)) - return status; - } - return ApplicationStatus.WAITING; + for (ApplicationStatus status : ApplicationStatus.values()) { + if (Objects.equals(status.getValue(), dbData)) return status; } + return ApplicationStatus.WAITING; + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/budget/domain/valueObject/Account.java b/resource-server/src/main/java/com/inhabas/api/domain/budget/domain/valueObject/Account.java index a880d7e4..7e9eda6b 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/budget/domain/valueObject/Account.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/budget/domain/valueObject/Account.java @@ -1,51 +1,49 @@ package com.inhabas.api.domain.budget.domain.valueObject; -import com.inhabas.api.domain.budget.domain.BudgetHistory; +import java.util.Objects; import javax.persistence.Column; import javax.persistence.Embeddable; import javax.persistence.Transient; -import java.util.Objects; + +import com.inhabas.api.domain.budget.domain.BudgetHistory; /** - * {@code ApplicantAccount} 와 다르게 Nullable 하다. 예산을 지원하는 경우에는 지원자에게 필수적으로 송금을 해야하는데 반해서, - * 총무가 예산 내역을 스스로 등록하는 경우에는 송금이 이루어지지 않는 경우가 존재한다. 따라서 {@code BudgetHistory} 에서는 - * Nullable 한 계좌값을 사용한다. + * {@code ApplicantAccount} 와 다르게 Nullable 하다. 예산을 지원하는 경우에는 지원자에게 필수적으로 송금을 해야하는데 반해서, 총무가 예산 내역을 + * 스스로 등록하는 경우에는 송금이 이루어지지 않는 경우가 존재한다. 따라서 {@code BudgetHistory} 에서는 Nullable 한 계좌값을 사용한다. + * * @see ApplicantAccount * @see BudgetHistory */ @Embeddable public class Account { - @Column(name = "account", length = 100) - private String value; - - @Transient - private final int MAX_LENGTH = 100; - - public Account() {} - - /** - * String 타입이 아니거나 최대 길이를 넘으면 오류를 던짐. - * 어떤 문자열을 갖고 있는 경우에는 해당 문자열로 값을 설정하고, 공백 문자열로만 이루어져있으면 null 로 설정. - */ - public Account(String value) { - if (validate(value)) - this.value = ((value == null || value.isBlank()) ? null : value); - else - throw new IllegalArgumentException(); - } - - private boolean validate(Object value) { - if (Objects.isNull(value)) return true; - if (!(value instanceof String)) return false; - - String o = (String) value; - if (o.isBlank()) return true; - return o.length() < MAX_LENGTH; - } - - public String getValue() { - return value; - } + @Column(name = "account", length = 100) + private String value; + + @Transient private final int MAX_LENGTH = 100; + + public Account() {} + + /** + * String 타입이 아니거나 최대 길이를 넘으면 오류를 던짐. 어떤 문자열을 갖고 있는 경우에는 해당 문자열로 값을 설정하고, 공백 문자열로만 이루어져있으면 null 로 + * 설정. + */ + public Account(String value) { + if (validate(value)) this.value = ((value == null || value.isBlank()) ? null : value); + else throw new IllegalArgumentException(); + } + + private boolean validate(Object value) { + if (Objects.isNull(value)) return true; + if (!(value instanceof String)) return false; + + String o = (String) value; + if (o.isBlank()) return true; + return o.length() < MAX_LENGTH; + } + + public String getValue() { + return value; + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/budget/domain/valueObject/ApplicantAccount.java b/resource-server/src/main/java/com/inhabas/api/domain/budget/domain/valueObject/ApplicantAccount.java index e04c453a..85023132 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/budget/domain/valueObject/ApplicantAccount.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/budget/domain/valueObject/ApplicantAccount.java @@ -1,38 +1,36 @@ package com.inhabas.api.domain.budget.domain.valueObject; +import java.util.Objects; + import javax.persistence.Column; import javax.persistence.Embeddable; import javax.persistence.Transient; -import java.util.Objects; @Embeddable public class ApplicantAccount { - @Column(name = "account", length = 100, nullable = false) - private String value; + @Column(name = "account", length = 100, nullable = false) + private String value; - @Transient - private final int MAX_LENGTH = 100; + @Transient private final int MAX_LENGTH = 100; - public ApplicantAccount() {} + public ApplicantAccount() {} - public ApplicantAccount(String value) { - if (validate(value)) - this.value = value; - else - throw new IllegalArgumentException(); - } + public ApplicantAccount(String value) { + if (validate(value)) this.value = value; + else throw new IllegalArgumentException(); + } - private boolean validate(Object value) { - if (Objects.isNull(value)) return false; - if (!(value instanceof String)) return false; + private boolean validate(Object value) { + if (Objects.isNull(value)) return false; + if (!(value instanceof String)) return false; - String o = (String) value; - if (o.isBlank()) return false; - return o.length() < MAX_LENGTH; - } + String o = (String) value; + if (o.isBlank()) return false; + return o.length() < MAX_LENGTH; + } - public String getValue() { - return value; - } + public String getValue() { + return value; + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/budget/domain/valueObject/ApplicationStatus.java b/resource-server/src/main/java/com/inhabas/api/domain/budget/domain/valueObject/ApplicationStatus.java index 359fb342..a5244314 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/budget/domain/valueObject/ApplicationStatus.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/budget/domain/valueObject/ApplicationStatus.java @@ -1,20 +1,19 @@ package com.inhabas.api.domain.budget.domain.valueObject; public enum ApplicationStatus { + WAITING("승인 대기", 1), + DENIED("승인 거절", 2), + APPROVED("승인 완료", 3), + PROCESSED("처리 완료", 4), + ; - WAITING("승인 대기", 1), - DENIED("승인 거절", 2), - APPROVED("승인 완료", 3), - PROCESSED("처리 완료", 4), - ; + private final Integer value; - private final Integer value; + ApplicationStatus(String describe, Integer value) { + this.value = value; + } - ApplicationStatus(String describe, Integer value) { - this.value = value; - } - - public Integer getValue() { - return value; - } + public Integer getValue() { + return value; + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/budget/domain/valueObject/Details.java b/resource-server/src/main/java/com/inhabas/api/domain/budget/domain/valueObject/Details.java index 5a957a9c..20e2046e 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/budget/domain/valueObject/Details.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/budget/domain/valueObject/Details.java @@ -1,38 +1,36 @@ package com.inhabas.api.domain.budget.domain.valueObject; +import java.util.Objects; + import javax.persistence.Column; import javax.persistence.Embeddable; import javax.persistence.Transient; -import java.util.Objects; @Embeddable public class Details { - @Column(name = "details", length = 300, nullable = false) - private String value; + @Column(name = "details", length = 300, nullable = false) + private String value; - @Transient - private final int MAX_LENGTH = 300; + @Transient private final int MAX_LENGTH = 300; - public Details() {} + public Details() {} - public Details(String value) { - if (validate(value)) - this.value = value; - else - throw new IllegalArgumentException(); - } + public Details(String value) { + if (validate(value)) this.value = value; + else throw new IllegalArgumentException(); + } - private boolean validate(Object value) { - if (Objects.isNull(value)) return false; - if (!(value instanceof String)) return false; + private boolean validate(Object value) { + if (Objects.isNull(value)) return false; + if (!(value instanceof String)) return false; - String o = (String) value; - if (o.isBlank()) return false; - return o.length() < MAX_LENGTH; - } + String o = (String) value; + if (o.isBlank()) return false; + return o.length() < MAX_LENGTH; + } - public String getValue() { - return value; - } + public String getValue() { + return value; + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/budget/domain/valueObject/Price.java b/resource-server/src/main/java/com/inhabas/api/domain/budget/domain/valueObject/Price.java index 6227b6ca..0dae4e75 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/budget/domain/valueObject/Price.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/budget/domain/valueObject/Price.java @@ -1,31 +1,30 @@ package com.inhabas.api.domain.budget.domain.valueObject; -import lombok.Getter; +import java.util.Objects; import javax.persistence.Column; import javax.persistence.Embeddable; -import java.util.Objects; + +import lombok.Getter; @Getter @Embeddable public class Price { - @Column(nullable = false) - private Integer value; + @Column(nullable = false) + private Integer value; - public Price() {} + public Price() {} - public Price(Integer value) { - if (validate(value)) - this.value = value; - else - throw new IllegalArgumentException(); - } + public Price(Integer value) { + if (validate(value)) this.value = value; + else throw new IllegalArgumentException(); + } - boolean validate(Object value) { - if (Objects.isNull(value)) return false; - if (!(value instanceof Integer)) return false; - int o = (Integer) value; - return 0 <= o; // 가격은 양수만 가능 - } + boolean validate(Object value) { + if (Objects.isNull(value)) return false; + if (!(value instanceof Integer)) return false; + int o = (Integer) value; + return 0 <= o; // 가격은 양수만 가능 + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/budget/domain/valueObject/RejectReason.java b/resource-server/src/main/java/com/inhabas/api/domain/budget/domain/valueObject/RejectReason.java index 88496b0a..33370e49 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/budget/domain/valueObject/RejectReason.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/budget/domain/valueObject/RejectReason.java @@ -1,41 +1,39 @@ package com.inhabas.api.domain.budget.domain.valueObject; -import lombok.Getter; +import java.util.Objects; import javax.persistence.Column; import javax.persistence.Embeddable; import javax.persistence.Transient; -import java.util.Objects; + +import lombok.Getter; @Getter @Embeddable public class RejectReason { - @Column(name = "reject_reason", length = 200) - private String value; + @Column(name = "reject_reason", length = 200) + private String value; - @Transient - private final int MAX_LENGTH = 200; + @Transient private final int MAX_LENGTH = 200; - public RejectReason() {} + public RejectReason() {} - public RejectReason(String value) { - if (validate(value)) - this.value = value; - else - throw new IllegalArgumentException(); - } + public RejectReason(String value) { + if (validate(value)) this.value = value; + else throw new IllegalArgumentException(); + } - private boolean validate(Object value) { - if (Objects.isNull(value)) return false; - if (!(value instanceof String)) return false; + private boolean validate(Object value) { + if (Objects.isNull(value)) return false; + if (!(value instanceof String)) return false; - String o = (String) value; - if (o.isBlank()) return false; - return o.length() < MAX_LENGTH; - } + String o = (String) value; + if (o.isBlank()) return false; + return o.length() < MAX_LENGTH; + } - public String getValue() { - return value; - } + public String getValue() { + return value; + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/budget/domain/valueObject/Title.java b/resource-server/src/main/java/com/inhabas/api/domain/budget/domain/valueObject/Title.java index b2f6191d..2f2e032e 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/budget/domain/valueObject/Title.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/budget/domain/valueObject/Title.java @@ -1,38 +1,36 @@ package com.inhabas.api.domain.budget.domain.valueObject; +import java.util.Objects; + import javax.persistence.Column; import javax.persistence.Embeddable; import javax.persistence.Transient; -import java.util.Objects; @Embeddable public class Title { - @Column(name = "title", length = 100, nullable = false) - private String value; + @Column(name = "title", length = 100, nullable = false) + private String value; - @Transient - private final int MAX_LENGTH = 100; + @Transient private final int MAX_LENGTH = 100; - public Title() {} + public Title() {} - public Title(String value) { - if (validate(value)) - this.value = value; - else - throw new IllegalArgumentException(); - } + public Title(String value) { + if (validate(value)) this.value = value; + else throw new IllegalArgumentException(); + } - private boolean validate(Object value) { - if (Objects.isNull(value)) return false; - if (!(value instanceof String)) return false; + private boolean validate(Object value) { + if (Objects.isNull(value)) return false; + if (!(value instanceof String)) return false; - String o = (String) value; - if (o.isBlank()) return false; - return o.length() < MAX_LENGTH; - } + String o = (String) value; + if (o.isBlank()) return false; + return o.length() < MAX_LENGTH; + } - public String getValue() { - return value; - } + public String getValue() { + return value; + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/budget/dto/BudgetApplicationDetailDto.java b/resource-server/src/main/java/com/inhabas/api/domain/budget/dto/BudgetApplicationDetailDto.java index f2e43715..e3d09e32 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/budget/dto/BudgetApplicationDetailDto.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/budget/dto/BudgetApplicationDetailDto.java @@ -1,41 +1,42 @@ package com.inhabas.api.domain.budget.dto; -import com.fasterxml.jackson.annotation.JsonFormat; -import com.inhabas.api.domain.budget.domain.valueObject.ApplicationStatus; +import java.time.LocalDateTime; + import lombok.AllArgsConstructor; import lombok.Getter; -import java.time.LocalDateTime; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.inhabas.api.domain.budget.domain.valueObject.ApplicationStatus; @Getter @AllArgsConstructor public class BudgetApplicationDetailDto { - private Integer id; + private Integer id; - private String title; + private String title; - @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss") - private LocalDateTime dateUsed; + @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss") + private LocalDateTime dateUsed; - @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss") - private LocalDateTime dateCreated; + @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss") + private LocalDateTime dateCreated; - private String details; + private String details; - private Integer outcome; + private Integer outcome; - private String accounts; + private String accounts; - private Integer applicationWriterId; + private Integer applicationWriterId; - private String applicationWriterName; + private String applicationWriterName; - private Integer memberIdInCharge; + private Integer memberIdInCharge; - private String memberNameInCharge; + private String memberNameInCharge; - private ApplicationStatus status; + private ApplicationStatus status; - private String rejectReason; + private String rejectReason; } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/budget/dto/BudgetApplicationListDto.java b/resource-server/src/main/java/com/inhabas/api/domain/budget/dto/BudgetApplicationListDto.java index b7329590..1d3e94cd 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/budget/dto/BudgetApplicationListDto.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/budget/dto/BudgetApplicationListDto.java @@ -1,26 +1,27 @@ package com.inhabas.api.domain.budget.dto; -import com.fasterxml.jackson.annotation.JsonFormat; -import com.inhabas.api.domain.budget.domain.valueObject.ApplicationStatus; +import java.time.LocalDateTime; + import lombok.AllArgsConstructor; import lombok.Getter; -import java.time.LocalDateTime; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.inhabas.api.domain.budget.domain.valueObject.ApplicationStatus; @Getter @AllArgsConstructor public class BudgetApplicationListDto { - private Integer applicationId; + private Integer applicationId; - private String title; + private String title; - private Integer applicantId; + private Integer applicantId; - private String applicantName; + private String applicantName; - @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss") - private LocalDateTime dateCreated; + @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss") + private LocalDateTime dateCreated; - private ApplicationStatus status; + private ApplicationStatus status; } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/budget/dto/BudgetApplicationRegisterForm.java b/resource-server/src/main/java/com/inhabas/api/domain/budget/dto/BudgetApplicationRegisterForm.java index 5e81b71a..3995af92 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/budget/dto/BudgetApplicationRegisterForm.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/budget/dto/BudgetApplicationRegisterForm.java @@ -1,54 +1,54 @@ package com.inhabas.api.domain.budget.dto; -import com.fasterxml.jackson.annotation.JsonFormat; -import com.inhabas.api.domain.budget.domain.BudgetSupportApplication; -import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.StudentId; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.NoArgsConstructor; +import java.time.LocalDateTime; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; import javax.validation.constraints.Past; import javax.validation.constraints.Positive; -import java.time.LocalDateTime; + +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.StudentId; +import com.inhabas.api.domain.budget.domain.BudgetSupportApplication; @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) public class BudgetApplicationRegisterForm { - @NotBlank - private String title; - - @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss") - @Past @NotNull - private LocalDateTime dateUsed; - - @NotBlank - private String details; - - @NotNull @Positive - private Integer outcome; - - @NotBlank - private String accounts; - - public BudgetApplicationRegisterForm(String title, LocalDateTime dateUsed, String details, Integer outcome, String accounts) { - this.title = title; - this.dateUsed = dateUsed; - this.details = details; - this.outcome = outcome; - this.accounts = accounts; - } - - public BudgetSupportApplication toEntity(StudentId applicationWriter) { - return BudgetSupportApplication.builder() - .title(this.title) - .dateUsed(this.dateUsed) - .details(this.details) - .outcome(this.outcome) - .account(this.accounts) - .applicationWriter(applicationWriter) - .build(); - } + @NotBlank private String title; + + @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss") + @Past + @NotNull + private LocalDateTime dateUsed; + + @NotBlank private String details; + + @NotNull @Positive private Integer outcome; + + @NotBlank private String accounts; + + public BudgetApplicationRegisterForm( + String title, LocalDateTime dateUsed, String details, Integer outcome, String accounts) { + this.title = title; + this.dateUsed = dateUsed; + this.details = details; + this.outcome = outcome; + this.accounts = accounts; + } + + public BudgetSupportApplication toEntity(StudentId applicationWriter) { + return BudgetSupportApplication.builder() + .title(this.title) + .dateUsed(this.dateUsed) + .details(this.details) + .outcome(this.outcome) + .account(this.accounts) + .applicationWriter(applicationWriter) + .build(); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/budget/dto/BudgetApplicationStatusChangeRequest.java b/resource-server/src/main/java/com/inhabas/api/domain/budget/dto/BudgetApplicationStatusChangeRequest.java index 13e4d67e..405ece80 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/budget/dto/BudgetApplicationStatusChangeRequest.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/budget/dto/BudgetApplicationStatusChangeRequest.java @@ -1,23 +1,23 @@ package com.inhabas.api.domain.budget.dto; -import com.inhabas.api.domain.budget.domain.valueObject.ApplicationStatus; +import javax.validation.constraints.NotNull; + import lombok.AccessLevel; import lombok.Getter; import lombok.NoArgsConstructor; -import javax.validation.constraints.NotNull; +import com.inhabas.api.domain.budget.domain.valueObject.ApplicationStatus; @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) public class BudgetApplicationStatusChangeRequest { - @NotNull - private ApplicationStatus status; + @NotNull private ApplicationStatus status; - private String rejectReason; + private String rejectReason; - public BudgetApplicationStatusChangeRequest(String status, String rejectReason) { - this.status = ApplicationStatus.valueOf(status); - this.rejectReason = rejectReason; - } + public BudgetApplicationStatusChangeRequest(String status, String rejectReason) { + this.status = ApplicationStatus.valueOf(status); + this.rejectReason = rejectReason; + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/budget/dto/BudgetApplicationUpdateForm.java b/resource-server/src/main/java/com/inhabas/api/domain/budget/dto/BudgetApplicationUpdateForm.java index eb0fca6b..682f2fbc 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/budget/dto/BudgetApplicationUpdateForm.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/budget/dto/BudgetApplicationUpdateForm.java @@ -1,25 +1,29 @@ package com.inhabas.api.domain.budget.dto; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.NoArgsConstructor; +import java.time.LocalDateTime; import javax.validation.constraints.NotNull; import javax.validation.constraints.Positive; -import java.time.LocalDateTime; + +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) public class BudgetApplicationUpdateForm extends BudgetApplicationRegisterForm { - @NotNull - @Positive - private Integer applicationId; + @NotNull @Positive private Integer applicationId; - public BudgetApplicationUpdateForm(String title, LocalDateTime dateUsed, String details, Integer outcome, - String accounts, Integer applicationId) { + public BudgetApplicationUpdateForm( + String title, + LocalDateTime dateUsed, + String details, + Integer outcome, + String accounts, + Integer applicationId) { - super(title, dateUsed, details, outcome, accounts); - this.applicationId = applicationId; - } + super(title, dateUsed, details, outcome, accounts); + this.applicationId = applicationId; + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/budget/dto/BudgetHistoryCreateForm.java b/resource-server/src/main/java/com/inhabas/api/domain/budget/dto/BudgetHistoryCreateForm.java index af38e961..3d6b5a5e 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/budget/dto/BudgetHistoryCreateForm.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/budget/dto/BudgetHistoryCreateForm.java @@ -1,9 +1,7 @@ package com.inhabas.api.domain.budget.dto; -import com.fasterxml.jackson.annotation.JsonFormat; -import com.inhabas.api.domain.budget.domain.BudgetHistory; -import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.StudentId; import java.time.LocalDateTime; + import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; import javax.validation.constraints.Past; @@ -13,50 +11,55 @@ import lombok.Getter; import lombok.NoArgsConstructor; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.StudentId; +import com.inhabas.api.domain.budget.domain.BudgetHistory; + @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) public class BudgetHistoryCreateForm { - @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss") - @Past @NotNull - private LocalDateTime dateUsed; - - @NotBlank - private String title; - - private String details; - - @NotNull - private StudentId personReceived; - - @PositiveOrZero @NotNull - private Integer income; - - @PositiveOrZero @NotNull - private Integer outcome; - - public BudgetHistoryCreateForm(LocalDateTime dateUsed, String title, String details, - @NotNull String personReceived, Integer income, Integer outcome) { - this.dateUsed = dateUsed; - this.title = title; - this.details = details; - this.personReceived = new StudentId(personReceived); - this.income = income; - this.outcome = outcome; - - if (this.details.isBlank()) - this.details = this.title; - } - - public BudgetHistory toEntity(StudentId CFO) { - return BudgetHistory.builder() - .title(this.title) - .details(this.details) - .income(this.income) - .outcome(this.outcome) - .dateUsed(this.dateUsed) - .personReceived(this.getPersonReceived()) - .personInCharge(CFO) - .build(); - } + @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss") + @Past + @NotNull + private LocalDateTime dateUsed; + + @NotBlank private String title; + + private String details; + + @NotNull private StudentId personReceived; + + @PositiveOrZero @NotNull private Integer income; + + @PositiveOrZero @NotNull private Integer outcome; + + public BudgetHistoryCreateForm( + LocalDateTime dateUsed, + String title, + String details, + @NotNull String personReceived, + Integer income, + Integer outcome) { + this.dateUsed = dateUsed; + this.title = title; + this.details = details; + this.personReceived = new StudentId(personReceived); + this.income = income; + this.outcome = outcome; + + if (this.details.isBlank()) this.details = this.title; + } + + public BudgetHistory toEntity(StudentId CFO) { + return BudgetHistory.builder() + .title(this.title) + .details(this.details) + .income(this.income) + .outcome(this.outcome) + .dateUsed(this.dateUsed) + .personReceived(this.getPersonReceived()) + .personInCharge(CFO) + .build(); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/budget/dto/BudgetHistoryDetailDto.java b/resource-server/src/main/java/com/inhabas/api/domain/budget/dto/BudgetHistoryDetailDto.java index 7a2f03b8..cc870765 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/budget/dto/BudgetHistoryDetailDto.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/budget/dto/BudgetHistoryDetailDto.java @@ -1,37 +1,37 @@ package com.inhabas.api.domain.budget.dto; +import java.time.LocalDateTime; + import lombok.AllArgsConstructor; import lombok.Getter; -import java.time.LocalDateTime; - @Getter @AllArgsConstructor public class BudgetHistoryDetailDto { - private Integer id; + private Integer id; - private LocalDateTime dateUsed; + private LocalDateTime dateUsed; - private LocalDateTime dateCreated; + private LocalDateTime dateCreated; - private LocalDateTime dateModified; + private LocalDateTime dateModified; - private String title; + private String title; - private Integer income; + private Integer income; - private Integer outcome; + private Integer outcome; - private String details; + private String details; - private String account; + private String account; - private Integer receivedMemberId; + private Integer receivedMemberId; - private String receivedMemberName; + private String receivedMemberName; - private Integer memberIdInCharge; + private Integer memberIdInCharge; - private String memberNameInCharge; + private String memberNameInCharge; } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/budget/dto/BudgetHistoryListResponse.java b/resource-server/src/main/java/com/inhabas/api/domain/budget/dto/BudgetHistoryListResponse.java index 2e390119..4e47bd3c 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/budget/dto/BudgetHistoryListResponse.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/budget/dto/BudgetHistoryListResponse.java @@ -1,18 +1,18 @@ package com.inhabas.api.domain.budget.dto; import lombok.Getter; + import org.springframework.data.domain.Page; @Getter public class BudgetHistoryListResponse { - private Page page; + private Page page; - private Integer balance; + private Integer balance; - public BudgetHistoryListResponse( - Page page, Integer balance) { - this.page = page; - this.balance = balance; - } + public BudgetHistoryListResponse(Page page, Integer balance) { + this.page = page; + this.balance = balance; + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/budget/dto/BudgetHistoryModifyForm.java b/resource-server/src/main/java/com/inhabas/api/domain/budget/dto/BudgetHistoryModifyForm.java index 4088ca02..591cbffd 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/budget/dto/BudgetHistoryModifyForm.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/budget/dto/BudgetHistoryModifyForm.java @@ -1,8 +1,10 @@ package com.inhabas.api.domain.budget.dto; import java.time.LocalDateTime; + import javax.validation.constraints.NotNull; import javax.validation.constraints.Positive; + import lombok.AccessLevel; import lombok.Getter; import lombok.NoArgsConstructor; @@ -11,13 +13,17 @@ @NoArgsConstructor(access = AccessLevel.PROTECTED) public class BudgetHistoryModifyForm extends BudgetHistoryCreateForm { - @NotNull @Positive - private Integer id; + @NotNull @Positive private Integer id; - public BudgetHistoryModifyForm(LocalDateTime dateUsed, String title, - String details, String personReceived, Integer income, Integer outcome, - Integer historyId) { - super(dateUsed, title, details, personReceived, income, outcome); - this.id = historyId; - } + public BudgetHistoryModifyForm( + LocalDateTime dateUsed, + String title, + String details, + String personReceived, + Integer income, + Integer outcome, + Integer historyId) { + super(dateUsed, title, details, personReceived, income, outcome); + this.id = historyId; + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/budget/repository/BudgetApplicationRepository.java b/resource-server/src/main/java/com/inhabas/api/domain/budget/repository/BudgetApplicationRepository.java index 06affa5c..918943e3 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/budget/repository/BudgetApplicationRepository.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/budget/repository/BudgetApplicationRepository.java @@ -1,8 +1,8 @@ package com.inhabas.api.domain.budget.repository; -import com.inhabas.api.domain.budget.domain.BudgetSupportApplication; import org.springframework.data.jpa.repository.JpaRepository; +import com.inhabas.api.domain.budget.domain.BudgetSupportApplication; + public interface BudgetApplicationRepository - extends JpaRepository, BudgetApplicationRepositoryCustom { -} + extends JpaRepository, BudgetApplicationRepositoryCustom {} diff --git a/resource-server/src/main/java/com/inhabas/api/domain/budget/repository/BudgetApplicationRepositoryCustom.java b/resource-server/src/main/java/com/inhabas/api/domain/budget/repository/BudgetApplicationRepositoryCustom.java index 0d2c8c95..90d2b244 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/budget/repository/BudgetApplicationRepositoryCustom.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/budget/repository/BudgetApplicationRepositoryCustom.java @@ -1,16 +1,17 @@ package com.inhabas.api.domain.budget.repository; -import com.inhabas.api.domain.budget.domain.valueObject.ApplicationStatus; -import com.inhabas.api.domain.budget.dto.BudgetApplicationDetailDto; -import com.inhabas.api.domain.budget.dto.BudgetApplicationListDto; +import java.util.Optional; + import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; -import java.util.Optional; +import com.inhabas.api.domain.budget.domain.valueObject.ApplicationStatus; +import com.inhabas.api.domain.budget.dto.BudgetApplicationDetailDto; +import com.inhabas.api.domain.budget.dto.BudgetApplicationListDto; public interface BudgetApplicationRepositoryCustom { - Optional findDtoById(Integer applicationId); + Optional findDtoById(Integer applicationId); - Page search(ApplicationStatus status, Pageable pageable); + Page search(ApplicationStatus status, Pageable pageable); } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/budget/repository/BudgetApplicationRepositoryImpl.java b/resource-server/src/main/java/com/inhabas/api/domain/budget/repository/BudgetApplicationRepositoryImpl.java index 416985ff..8bccf2c0 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/budget/repository/BudgetApplicationRepositoryImpl.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/budget/repository/BudgetApplicationRepositoryImpl.java @@ -2,6 +2,13 @@ import static com.inhabas.api.domain.budget.domain.QBudgetSupportApplication.budgetSupportApplication; +import java.util.List; +import java.util.Optional; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; + import com.inhabas.api.auth.domain.oauth2.member.domain.entity.QMember; import com.inhabas.api.domain.budget.domain.valueObject.ApplicationStatus; import com.inhabas.api.domain.budget.dto.BudgetApplicationDetailDto; @@ -10,89 +17,92 @@ import com.querydsl.core.types.dsl.BooleanExpression; import com.querydsl.jpa.impl.JPAQuery; import com.querydsl.jpa.impl.JPAQueryFactory; -import java.util.List; -import java.util.Optional; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageImpl; -import org.springframework.data.domain.Pageable; public class BudgetApplicationRepositoryImpl implements BudgetApplicationRepositoryCustom { - private final JPAQueryFactory queryFactory; - private final QMember applicant = new QMember("applicant"); - private final QMember pic = new QMember("pic"); - - public BudgetApplicationRepositoryImpl(JPAQueryFactory queryFactory) { - this.queryFactory = queryFactory; - } - - @Override - public Optional findDtoById(Integer applicationId) { - - return Optional.ofNullable( - getDtoJPAQuery() - .where(budgetSupportApplication.id.eq(applicationId)) - .fetchOne() - ); - } - - @Override - public Page search(ApplicationStatus status, Pageable pageable) { - - List result = - queryFactory.select( - Projections.constructor(BudgetApplicationListDto.class, - budgetSupportApplication.id, - budgetSupportApplication.title.value, - budgetSupportApplication.applicationWriter.id, - applicant.name.value, - budgetSupportApplication.dateCreated, - budgetSupportApplication.status - )) - .from(budgetSupportApplication) - .innerJoin(applicant).on(budgetSupportApplication.applicationWriter.eq(applicant.studentId)) - .where(sameStatus(status).and(budgetSupportApplication.status.ne(ApplicationStatus.PROCESSED))) - .offset(pageable.getOffset()) - .limit(pageable.getPageSize()) - .orderBy(budgetSupportApplication.dateUsed.desc()) - .fetch(); - - return new PageImpl<>(result, pageable, getCount(status)); - } - - private BooleanExpression sameStatus(ApplicationStatus status) { - - return status == null ? budgetSupportApplication.status.ne(ApplicationStatus.PROCESSED) - : budgetSupportApplication.status.eq(status); - } - - // 쿼리 결과 EHCACHE 등으로 캐시할 필요가 있음. 카운트 쿼리가 비효율적임. - private Integer getCount(ApplicationStatus status) { - return queryFactory - .selectFrom(budgetSupportApplication) - .where(sameStatus(status)) - .fetch().size(); - } - - private JPAQuery getDtoJPAQuery() { - return queryFactory.select( - Projections.constructor(BudgetApplicationDetailDto.class, - budgetSupportApplication.id, - budgetSupportApplication.title.value, - budgetSupportApplication.dateUsed, - budgetSupportApplication.dateCreated, - budgetSupportApplication.details.value, - budgetSupportApplication.outcome.value, - budgetSupportApplication.applicantAccount.value, - budgetSupportApplication.applicationWriter.id, - applicant.name.value, - budgetSupportApplication.personInCharge.id, - pic.name.value, - budgetSupportApplication.status, - budgetSupportApplication.rejectReason.value - )) - .from(budgetSupportApplication) - .innerJoin(applicant).on(budgetSupportApplication.applicationWriter.eq(applicant.studentId)) - .leftJoin(pic).on(budgetSupportApplication.personInCharge.eq(pic.studentId)); // 총무가 아직 승인 또는 거절 안했을수 있기 때문에 null 일 수 있다. - } + private final JPAQueryFactory queryFactory; + private final QMember applicant = new QMember("applicant"); + private final QMember pic = new QMember("pic"); + + public BudgetApplicationRepositoryImpl(JPAQueryFactory queryFactory) { + this.queryFactory = queryFactory; + } + + @Override + public Optional findDtoById(Integer applicationId) { + + return Optional.ofNullable( + getDtoJPAQuery().where(budgetSupportApplication.id.eq(applicationId)).fetchOne()); + } + + @Override + public Page search(ApplicationStatus status, Pageable pageable) { + + List result = + queryFactory + .select( + Projections.constructor( + BudgetApplicationListDto.class, + budgetSupportApplication.id, + budgetSupportApplication.title.value, + budgetSupportApplication.applicationWriter.id, + applicant.name.value, + budgetSupportApplication.dateCreated, + budgetSupportApplication.status)) + .from(budgetSupportApplication) + .innerJoin(applicant) + .on(budgetSupportApplication.applicationWriter.eq(applicant.studentId)) + .where( + sameStatus(status) + .and(budgetSupportApplication.status.ne(ApplicationStatus.PROCESSED))) + .offset(pageable.getOffset()) + .limit(pageable.getPageSize()) + .orderBy(budgetSupportApplication.dateUsed.desc()) + .fetch(); + + return new PageImpl<>(result, pageable, getCount(status)); + } + + private BooleanExpression sameStatus(ApplicationStatus status) { + + return status == null + ? budgetSupportApplication.status.ne(ApplicationStatus.PROCESSED) + : budgetSupportApplication.status.eq(status); + } + + // 쿼리 결과 EHCACHE 등으로 캐시할 필요가 있음. 카운트 쿼리가 비효율적임. + private Integer getCount(ApplicationStatus status) { + return queryFactory + .selectFrom(budgetSupportApplication) + .where(sameStatus(status)) + .fetch() + .size(); + } + + private JPAQuery getDtoJPAQuery() { + return queryFactory + .select( + Projections.constructor( + BudgetApplicationDetailDto.class, + budgetSupportApplication.id, + budgetSupportApplication.title.value, + budgetSupportApplication.dateUsed, + budgetSupportApplication.dateCreated, + budgetSupportApplication.details.value, + budgetSupportApplication.outcome.value, + budgetSupportApplication.applicantAccount.value, + budgetSupportApplication.applicationWriter.id, + applicant.name.value, + budgetSupportApplication.personInCharge.id, + pic.name.value, + budgetSupportApplication.status, + budgetSupportApplication.rejectReason.value)) + .from(budgetSupportApplication) + .innerJoin(applicant) + .on(budgetSupportApplication.applicationWriter.eq(applicant.studentId)) + .leftJoin(pic) + .on( + budgetSupportApplication.personInCharge.eq( + pic.studentId)); // 총무가 아직 승인 또는 거절 안했을수 있기 때문에 null 일 수 있다. + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/budget/repository/BudgetHistoryRepository.java b/resource-server/src/main/java/com/inhabas/api/domain/budget/repository/BudgetHistoryRepository.java index 2ed85793..1d1f91e2 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/budget/repository/BudgetHistoryRepository.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/budget/repository/BudgetHistoryRepository.java @@ -1,11 +1,13 @@ package com.inhabas.api.domain.budget.repository; -import com.inhabas.api.domain.budget.domain.BudgetHistory; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; -public interface BudgetHistoryRepository extends JpaRepository, BudgetHistoryRepositoryCustom { +import com.inhabas.api.domain.budget.domain.BudgetHistory; + +public interface BudgetHistoryRepository + extends JpaRepository, BudgetHistoryRepositoryCustom { - @Query("SELECT sum(e.income.value)-sum(e.outcome.value) from BudgetHistory e") - Integer getBalance(); + @Query("SELECT sum(e.income.value)-sum(e.outcome.value) from BudgetHistory e") + Integer getBalance(); } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/budget/repository/BudgetHistoryRepositoryCustom.java b/resource-server/src/main/java/com/inhabas/api/domain/budget/repository/BudgetHistoryRepositoryCustom.java index cbc1fb3a..b7000af1 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/budget/repository/BudgetHistoryRepositoryCustom.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/budget/repository/BudgetHistoryRepositoryCustom.java @@ -1,17 +1,18 @@ package com.inhabas.api.domain.budget.repository; -import com.inhabas.api.domain.budget.dto.BudgetHistoryDetailDto; +import java.util.List; +import java.util.Optional; + import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; -import java.util.List; -import java.util.Optional; +import com.inhabas.api.domain.budget.dto.BudgetHistoryDetailDto; public interface BudgetHistoryRepositoryCustom { - Page search(Integer year, Pageable pageable); + Page search(Integer year, Pageable pageable); - Optional findDtoById(Integer id); + Optional findDtoById(Integer id); - List findAllYear(); + List findAllYear(); } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/budget/repository/BudgetHistoryRepositoryImpl.java b/resource-server/src/main/java/com/inhabas/api/domain/budget/repository/BudgetHistoryRepositoryImpl.java index a9354540..f135f497 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/budget/repository/BudgetHistoryRepositoryImpl.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/budget/repository/BudgetHistoryRepositoryImpl.java @@ -1,5 +1,14 @@ package com.inhabas.api.domain.budget.repository; +import static com.inhabas.api.domain.budget.domain.QBudgetHistory.budgetHistory; + +import java.util.List; +import java.util.Optional; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; + import com.inhabas.api.auth.domain.oauth2.member.domain.entity.QMember; import com.inhabas.api.domain.budget.dto.BudgetHistoryDetailDto; import com.querydsl.core.types.Projections; @@ -7,98 +16,81 @@ import com.querydsl.core.types.dsl.Expressions; import com.querydsl.jpa.impl.JPAQuery; import com.querydsl.jpa.impl.JPAQueryFactory; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageImpl; -import org.springframework.data.domain.Pageable; - -import java.util.List; -import java.util.Optional; - -import static com.inhabas.api.domain.budget.domain.QBudgetHistory.budgetHistory; public class BudgetHistoryRepositoryImpl implements BudgetHistoryRepositoryCustom { - private final JPAQueryFactory queryFactory; - private final QMember memberInCharge = new QMember("inCharge"); - private final QMember memberReceived = new QMember("received"); - - - public BudgetHistoryRepositoryImpl(JPAQueryFactory queryFactory) { - this.queryFactory = queryFactory; - } - - - @Override - public Optional findDtoById(Integer id) { - - return Optional.ofNullable( - getDtoJPAQuery() - .where(budgetHistory.id.eq(id)) - .fetchOne()); - } - - - @Override - public Page search(Integer year, Pageable pageable) { - - List result = getDtoJPAQuery() - .where(createdIn(year)) - .offset(pageable.getOffset()) - .limit(pageable.getPageSize()) - .orderBy(budgetHistory.dateUsed.desc()) - .fetch(); - - return new PageImpl<>(result, pageable, getCount(year)); - } - - - @Override - public List findAllYear() { - return queryFactory - .select(budgetHistory.dateUsed.year()) - .from(budgetHistory) - .distinct() - .orderBy(budgetHistory.dateUsed.desc()) - .fetch(); - } - - - private BooleanExpression createdIn(Integer year) { - return year == null ? - Expressions.asBoolean(true).isTrue() - : budgetHistory.dateUsed.year().eq(year); - } - - - // need to cache such as EHCACHE later. - private Integer getCount(Integer year) { - return queryFactory.selectFrom(budgetHistory) - .where(createdIn(year)) - .fetch() - .size(); - } - - - private JPAQuery getDtoJPAQuery() { - - return queryFactory.select( - Projections.constructor(BudgetHistoryDetailDto.class, - budgetHistory.id, - budgetHistory.dateUsed, - budgetHistory.dateCreated, - budgetHistory.dateUpdated, - budgetHistory.title.value, - budgetHistory.income.value, - budgetHistory.outcome.value, - budgetHistory.details.value, - budgetHistory.account.value, - budgetHistory.personReceived.id, - memberReceived.name.value, - budgetHistory.personInCharge.id, - memberInCharge.name.value - )) - .from(budgetHistory) - .innerJoin(memberInCharge).on(memberInCharge.studentId.id.eq(budgetHistory.personInCharge.id)) - .innerJoin(memberReceived).on(memberReceived.studentId.id.eq(budgetHistory.personReceived.id)); - } + private final JPAQueryFactory queryFactory; + private final QMember memberInCharge = new QMember("inCharge"); + private final QMember memberReceived = new QMember("received"); + + public BudgetHistoryRepositoryImpl(JPAQueryFactory queryFactory) { + this.queryFactory = queryFactory; + } + + @Override + public Optional findDtoById(Integer id) { + + return Optional.ofNullable(getDtoJPAQuery().where(budgetHistory.id.eq(id)).fetchOne()); + } + + @Override + public Page search(Integer year, Pageable pageable) { + + List result = + getDtoJPAQuery() + .where(createdIn(year)) + .offset(pageable.getOffset()) + .limit(pageable.getPageSize()) + .orderBy(budgetHistory.dateUsed.desc()) + .fetch(); + + return new PageImpl<>(result, pageable, getCount(year)); + } + + @Override + public List findAllYear() { + return queryFactory + .select(budgetHistory.dateUsed.year()) + .from(budgetHistory) + .distinct() + .orderBy(budgetHistory.dateUsed.desc()) + .fetch(); + } + + private BooleanExpression createdIn(Integer year) { + return year == null + ? Expressions.asBoolean(true).isTrue() + : budgetHistory.dateUsed.year().eq(year); + } + + // need to cache such as EHCACHE later. + private Integer getCount(Integer year) { + return queryFactory.selectFrom(budgetHistory).where(createdIn(year)).fetch().size(); + } + + private JPAQuery getDtoJPAQuery() { + + return queryFactory + .select( + Projections.constructor( + BudgetHistoryDetailDto.class, + budgetHistory.id, + budgetHistory.dateUsed, + budgetHistory.dateCreated, + budgetHistory.dateUpdated, + budgetHistory.title.value, + budgetHistory.income.value, + budgetHistory.outcome.value, + budgetHistory.details.value, + budgetHistory.account.value, + budgetHistory.personReceived.id, + memberReceived.name.value, + budgetHistory.personInCharge.id, + memberInCharge.name.value)) + .from(budgetHistory) + .innerJoin(memberInCharge) + .on(memberInCharge.studentId.id.eq(budgetHistory.personInCharge.id)) + .innerJoin(memberReceived) + .on(memberReceived.studentId.id.eq(budgetHistory.personReceived.id)); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/budget/usecase/BudgetApplicationProcessor.java b/resource-server/src/main/java/com/inhabas/api/domain/budget/usecase/BudgetApplicationProcessor.java index 205af2b8..fab8c61e 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/budget/usecase/BudgetApplicationProcessor.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/budget/usecase/BudgetApplicationProcessor.java @@ -1,9 +1,10 @@ package com.inhabas.api.domain.budget.usecase; -import com.inhabas.api.domain.budget.dto.BudgetApplicationStatusChangeRequest; import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.StudentId; +import com.inhabas.api.domain.budget.dto.BudgetApplicationStatusChangeRequest; public interface BudgetApplicationProcessor { - void process(Integer applicationId, BudgetApplicationStatusChangeRequest request, StudentId inCharge); + void process( + Integer applicationId, BudgetApplicationStatusChangeRequest request, StudentId inCharge); } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/budget/usecase/BudgetApplicationProcessorImpl.java b/resource-server/src/main/java/com/inhabas/api/domain/budget/usecase/BudgetApplicationProcessorImpl.java index e971afbd..d99f4e25 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/budget/usecase/BudgetApplicationProcessorImpl.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/budget/usecase/BudgetApplicationProcessorImpl.java @@ -1,51 +1,54 @@ package com.inhabas.api.domain.budget.usecase; +import lombok.RequiredArgsConstructor; + +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.StudentId; import com.inhabas.api.domain.budget.ApplicationNotFoundException; import com.inhabas.api.domain.budget.domain.BudgetSupportApplication; import com.inhabas.api.domain.budget.dto.BudgetApplicationStatusChangeRequest; import com.inhabas.api.domain.budget.repository.BudgetApplicationRepository; import com.inhabas.api.domain.budget.repository.BudgetHistoryRepository; -import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.StudentId; -import lombok.RequiredArgsConstructor; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; @Service - @RequiredArgsConstructor public class BudgetApplicationProcessorImpl implements BudgetApplicationProcessor { - private final BudgetApplicationRepository applicationRepository; - private final BudgetHistoryRepository historyRepository; - - - @PreAuthorize("hasRole('SECRETARY')") - @Transactional - @Override - public void process(Integer applicationId, BudgetApplicationStatusChangeRequest request, StudentId inCharge) { - - BudgetSupportApplication application = applicationRepository.findById(applicationId) - .orElseThrow(ApplicationNotFoundException::new); - - switch (request.getStatus()) { - case WAITING: - application.waiting(inCharge); - break; - - case APPROVED: - application.approve(inCharge); - break; - - case DENIED: - application.deny(request.getRejectReason(), inCharge); - break; - - case PROCESSED: - application.process(inCharge); - historyRepository.save(application.makeHistory()); // application to history - applicationRepository.save(application); - break; - } + private final BudgetApplicationRepository applicationRepository; + private final BudgetHistoryRepository historyRepository; + + @PreAuthorize("hasRole('SECRETARY')") + @Transactional + @Override + public void process( + Integer applicationId, BudgetApplicationStatusChangeRequest request, StudentId inCharge) { + + BudgetSupportApplication application = + applicationRepository + .findById(applicationId) + .orElseThrow(ApplicationNotFoundException::new); + + switch (request.getStatus()) { + case WAITING: + application.waiting(inCharge); + break; + + case APPROVED: + application.approve(inCharge); + break; + + case DENIED: + application.deny(request.getRejectReason(), inCharge); + break; + + case PROCESSED: + application.process(inCharge); + historyRepository.save(application.makeHistory()); // application to history + applicationRepository.save(application); + break; } + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/budget/usecase/BudgetApplicationService.java b/resource-server/src/main/java/com/inhabas/api/domain/budget/usecase/BudgetApplicationService.java index 823f1fd2..abf08259 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/budget/usecase/BudgetApplicationService.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/budget/usecase/BudgetApplicationService.java @@ -1,23 +1,24 @@ package com.inhabas.api.domain.budget.usecase; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; + +import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.StudentId; import com.inhabas.api.domain.budget.domain.valueObject.ApplicationStatus; import com.inhabas.api.domain.budget.dto.BudgetApplicationDetailDto; import com.inhabas.api.domain.budget.dto.BudgetApplicationListDto; import com.inhabas.api.domain.budget.dto.BudgetApplicationRegisterForm; import com.inhabas.api.domain.budget.dto.BudgetApplicationUpdateForm; -import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.StudentId; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; public interface BudgetApplicationService { - void registerApplication(BudgetApplicationRegisterForm form, StudentId applicant); + void registerApplication(BudgetApplicationRegisterForm form, StudentId applicant); - void updateApplication(BudgetApplicationUpdateForm form, StudentId applicant); + void updateApplication(BudgetApplicationUpdateForm form, StudentId applicant); - void deleteApplication(Integer applicationId, StudentId applicant); + void deleteApplication(Integer applicationId, StudentId applicant); - BudgetApplicationDetailDto getApplicationDetails(Integer applicationId); + BudgetApplicationDetailDto getApplicationDetails(Integer applicationId); - Page getApplications(ApplicationStatus status, Pageable pageable); + Page getApplications(ApplicationStatus status, Pageable pageable); } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/budget/usecase/BudgetApplicationServiceImpl.java b/resource-server/src/main/java/com/inhabas/api/domain/budget/usecase/BudgetApplicationServiceImpl.java index 46bef739..54391ef9 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/budget/usecase/BudgetApplicationServiceImpl.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/budget/usecase/BudgetApplicationServiceImpl.java @@ -1,5 +1,13 @@ package com.inhabas.api.domain.budget.usecase; +import lombok.RequiredArgsConstructor; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.StudentId; import com.inhabas.api.domain.budget.ApplicationCannotModifiableException; import com.inhabas.api.domain.budget.ApplicationNotFoundException; import com.inhabas.api.domain.budget.domain.BudgetSupportApplication; @@ -9,66 +17,64 @@ import com.inhabas.api.domain.budget.dto.BudgetApplicationRegisterForm; import com.inhabas.api.domain.budget.dto.BudgetApplicationUpdateForm; import com.inhabas.api.domain.budget.repository.BudgetApplicationRepository; -import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.StudentId; -import lombok.RequiredArgsConstructor; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; @Service @Transactional(readOnly = true) @RequiredArgsConstructor public class BudgetApplicationServiceImpl implements BudgetApplicationService { - private final BudgetApplicationRepository repository; - - - @Transactional - @Override - public void registerApplication(BudgetApplicationRegisterForm form, StudentId applicant) { + private final BudgetApplicationRepository repository; - BudgetSupportApplication application = form.toEntity(applicant); - repository.save(application); - } + @Transactional + @Override + public void registerApplication(BudgetApplicationRegisterForm form, StudentId applicant) { - @Transactional - @Override - public void updateApplication(BudgetApplicationUpdateForm form, StudentId applicant) { + BudgetSupportApplication application = form.toEntity(applicant); + repository.save(application); + } - BudgetSupportApplication application = repository.findById(form.getApplicationId()) - .orElseThrow(ApplicationNotFoundException::new); + @Transactional + @Override + public void updateApplication(BudgetApplicationUpdateForm form, StudentId applicant) { - application.modify( - form.getTitle(), form.getDateUsed(), form.getDetails(), form.getOutcome(), form.getAccounts(), applicant); + BudgetSupportApplication application = + repository.findById(form.getApplicationId()).orElseThrow(ApplicationNotFoundException::new); - repository.save(application); - } + application.modify( + form.getTitle(), + form.getDateUsed(), + form.getDetails(), + form.getOutcome(), + form.getAccounts(), + applicant); - @Transactional - @Override - public void deleteApplication(Integer applicationId, StudentId applicant) { + repository.save(application); + } - BudgetSupportApplication application = repository.findById(applicationId) - .orElseThrow(ApplicationNotFoundException::new); + @Transactional + @Override + public void deleteApplication(Integer applicationId, StudentId applicant) { - if (application.cannotModifiableBy(applicant)) { - throw new ApplicationCannotModifiableException(); - } + BudgetSupportApplication application = + repository.findById(applicationId).orElseThrow(ApplicationNotFoundException::new); - repository.deleteById(applicationId); + if (application.cannotModifiableBy(applicant)) { + throw new ApplicationCannotModifiableException(); } - @Override - public BudgetApplicationDetailDto getApplicationDetails(Integer applicationId) { + repository.deleteById(applicationId); + } - return repository.findDtoById(applicationId) - .orElseThrow(ApplicationNotFoundException::new); - } + @Override + public BudgetApplicationDetailDto getApplicationDetails(Integer applicationId) { - @Override - public Page getApplications(ApplicationStatus status, Pageable pageable) { + return repository.findDtoById(applicationId).orElseThrow(ApplicationNotFoundException::new); + } - return repository.search(status, pageable); - } + @Override + public Page getApplications( + ApplicationStatus status, Pageable pageable) { + + return repository.search(status, pageable); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/budget/usecase/BudgetHistoryService.java b/resource-server/src/main/java/com/inhabas/api/domain/budget/usecase/BudgetHistoryService.java index 1a16cad3..0afb060b 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/budget/usecase/BudgetHistoryService.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/budget/usecase/BudgetHistoryService.java @@ -1,25 +1,26 @@ package com.inhabas.api.domain.budget.usecase; +import java.util.List; + +import org.springframework.data.domain.Pageable; + +import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.StudentId; import com.inhabas.api.domain.budget.dto.BudgetHistoryCreateForm; import com.inhabas.api.domain.budget.dto.BudgetHistoryDetailDto; import com.inhabas.api.domain.budget.dto.BudgetHistoryListResponse; import com.inhabas.api.domain.budget.dto.BudgetHistoryModifyForm; -import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.StudentId; -import java.util.List; - -import org.springframework.data.domain.Pageable; public interface BudgetHistoryService { - void createNewHistory(BudgetHistoryCreateForm form, StudentId CFO); + void createNewHistory(BudgetHistoryCreateForm form, StudentId CFO); - void modifyHistory(BudgetHistoryModifyForm historyId, StudentId CFO); + void modifyHistory(BudgetHistoryModifyForm historyId, StudentId CFO); - void deleteHistory(Integer historyId, StudentId CFO); + void deleteHistory(Integer historyId, StudentId CFO); - BudgetHistoryListResponse searchHistoryList(Integer year, Pageable pageable); + BudgetHistoryListResponse searchHistoryList(Integer year, Pageable pageable); - BudgetHistoryDetailDto getHistory(Integer id); + BudgetHistoryDetailDto getHistory(Integer id); - List getAllYearOfHistory(); + List getAllYearOfHistory(); } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/budget/usecase/BudgetHistoryServiceImpl.java b/resource-server/src/main/java/com/inhabas/api/domain/budget/usecase/BudgetHistoryServiceImpl.java index ba9b657f..7d6bd246 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/budget/usecase/BudgetHistoryServiceImpl.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/budget/usecase/BudgetHistoryServiceImpl.java @@ -1,84 +1,88 @@ package com.inhabas.api.domain.budget.usecase; -import com.inhabas.api.domain.budget.HistoryCannotModifiableException; +import java.util.List; + +import lombok.RequiredArgsConstructor; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.StudentId; import com.inhabas.api.domain.budget.BudgetHistoryNotFoundException; +import com.inhabas.api.domain.budget.HistoryCannotModifiableException; import com.inhabas.api.domain.budget.domain.BudgetHistory; import com.inhabas.api.domain.budget.dto.BudgetHistoryCreateForm; import com.inhabas.api.domain.budget.dto.BudgetHistoryDetailDto; import com.inhabas.api.domain.budget.dto.BudgetHistoryListResponse; import com.inhabas.api.domain.budget.dto.BudgetHistoryModifyForm; import com.inhabas.api.domain.budget.repository.BudgetHistoryRepository; -import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.StudentId; -import lombok.RequiredArgsConstructor; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.util.List; - @Service @Transactional(readOnly = true) @RequiredArgsConstructor public class BudgetHistoryServiceImpl implements BudgetHistoryService { - private final BudgetHistoryRepository repository; - - @Override - @Transactional - public void createNewHistory(BudgetHistoryCreateForm form, StudentId CFO) { + private final BudgetHistoryRepository repository; - BudgetHistory newHistory = form.toEntity(CFO); + @Override + @Transactional + public void createNewHistory(BudgetHistoryCreateForm form, StudentId CFO) { - repository.save(newHistory); - } - - @Override - @Transactional - public void modifyHistory(BudgetHistoryModifyForm form, StudentId CFO) { + BudgetHistory newHistory = form.toEntity(CFO); - BudgetHistory budgetHistory = repository.findById(form.getId()) - .orElseThrow(BudgetHistoryNotFoundException::new); + repository.save(newHistory); + } - budgetHistory.modify( - CFO, form.getIncome(), form.getOutcome(), form.getDateUsed(), - form.getTitle(), form.getDetails(), form.getPersonReceived()); + @Override + @Transactional + public void modifyHistory(BudgetHistoryModifyForm form, StudentId CFO) { - repository.save(budgetHistory); - } + BudgetHistory budgetHistory = + repository.findById(form.getId()).orElseThrow(BudgetHistoryNotFoundException::new); + budgetHistory.modify( + CFO, + form.getIncome(), + form.getOutcome(), + form.getDateUsed(), + form.getTitle(), + form.getDetails(), + form.getPersonReceived()); - @Override - @Transactional - public void deleteHistory(Integer historyId, StudentId CFO) { + repository.save(budgetHistory); + } - BudgetHistory budgetHistory = repository.findById(historyId) - .orElseThrow(BudgetHistoryNotFoundException::new); + @Override + @Transactional + public void deleteHistory(Integer historyId, StudentId CFO) { - if (budgetHistory.cannotModifiableBy(CFO)) { - throw new HistoryCannotModifiableException(); - } + BudgetHistory budgetHistory = + repository.findById(historyId).orElseThrow(BudgetHistoryNotFoundException::new); - repository.deleteById(historyId); + if (budgetHistory.cannotModifiableBy(CFO)) { + throw new HistoryCannotModifiableException(); } - @Override - public BudgetHistoryListResponse searchHistoryList(Integer year, Pageable pageable) { + repository.deleteById(historyId); + } - Page listPage = repository.search(year, pageable); - Integer balance = repository.getBalance(); - return new BudgetHistoryListResponse(listPage, balance); - } + @Override + public BudgetHistoryListResponse searchHistoryList(Integer year, Pageable pageable) { - @Override - public BudgetHistoryDetailDto getHistory(Integer id) { - return repository.findDtoById(id) - .orElseThrow(BudgetHistoryNotFoundException::new); - } + Page listPage = repository.search(year, pageable); + Integer balance = repository.getBalance(); + return new BudgetHistoryListResponse(listPage, balance); + } - @Override - public List getAllYearOfHistory() { - return repository.findAllYear(); - } + @Override + public BudgetHistoryDetailDto getHistory(Integer id) { + return repository.findDtoById(id).orElseThrow(BudgetHistoryNotFoundException::new); + } + + @Override + public List getAllYearOfHistory() { + return repository.findAllYear(); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/club/domain/ClubHistory.java b/resource-server/src/main/java/com/inhabas/api/domain/club/domain/ClubHistory.java index 184fcd7f..12bebf6a 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/club/domain/ClubHistory.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/club/domain/ClubHistory.java @@ -1,19 +1,21 @@ package com.inhabas.api.domain.club.domain; -import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; -import com.inhabas.api.domain.BaseEntity; -import com.inhabas.api.domain.board.domain.valueObject.Content; -import com.inhabas.api.domain.board.domain.valueObject.Title; -import com.inhabas.api.domain.club.dto.SaveClubHistoryDto; +import java.time.LocalDateTime; + +import javax.persistence.*; + import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; -import org.springframework.data.annotation.CreatedDate; + import org.springframework.data.jpa.domain.support.AuditingEntityListener; -import javax.persistence.*; -import java.time.LocalDateTime; +import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; +import com.inhabas.api.domain.BaseEntity; +import com.inhabas.api.domain.board.domain.valueObject.Content; +import com.inhabas.api.domain.board.domain.valueObject.Title; +import com.inhabas.api.domain.club.dto.SaveClubHistoryDto; @Entity @Table(name = "CLUB_HISTORY") @@ -22,36 +24,33 @@ @EntityListeners(AuditingEntityListener.class) public class ClubHistory extends BaseEntity { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @ManyToOne(fetch = FetchType.LAZY, optional = false) - @JoinColumn(name = "USER_ID", foreignKey = @ForeignKey(name = "FK_MEMBER_OF_CLUB_HISTORY")) - private Member member; + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; - @Embedded - private Title title; + @ManyToOne(fetch = FetchType.LAZY, optional = false) + @JoinColumn(name = "USER_ID", foreignKey = @ForeignKey(name = "FK_MEMBER_OF_CLUB_HISTORY")) + private Member member; - @Embedded - private Content content; + @Embedded private Title title; - @Column(name = "DATE_HISTORY", nullable = false, columnDefinition = "DATETIME(0)") - private LocalDateTime dateHistory; + @Embedded private Content content; - @Builder - public ClubHistory(Member member, Title title, Content content, LocalDateTime dateHistory) { - this.member = member; - this.title = title; - this.content = content; - this.dateHistory = dateHistory; - } + @Column(name = "DATE_HISTORY", nullable = false, columnDefinition = "DATETIME(0)") + private LocalDateTime dateHistory; - public void updateClubHistory(Member member, SaveClubHistoryDto saveClubHistoryDto) { - this.member = member; - this.title = new Title(saveClubHistoryDto.getTitle()); - this.content = new Content(saveClubHistoryDto.getContent()); - this.dateHistory = saveClubHistoryDto.getDateHistory(); - } + @Builder + public ClubHistory(Member member, Title title, Content content, LocalDateTime dateHistory) { + this.member = member; + this.title = title; + this.content = content; + this.dateHistory = dateHistory; + } + public void updateClubHistory(Member member, SaveClubHistoryDto saveClubHistoryDto) { + this.member = member; + this.title = new Title(saveClubHistoryDto.getTitle()); + this.content = new Content(saveClubHistoryDto.getContent()); + this.dateHistory = saveClubHistoryDto.getDateHistory(); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/club/dto/ClubActivityDetailDto.java b/resource-server/src/main/java/com/inhabas/api/domain/club/dto/ClubActivityDetailDto.java index c86d0866..255330ac 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/club/dto/ClubActivityDetailDto.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/club/dto/ClubActivityDetailDto.java @@ -1,59 +1,59 @@ package com.inhabas.api.domain.club.dto; -import com.fasterxml.jackson.annotation.JsonFormat; -import com.inhabas.api.domain.file.dto.FileDownloadDto; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; +import java.time.LocalDateTime; +import java.util.List; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; import javax.validation.constraints.Positive; -import java.time.LocalDateTime; -import java.util.List; + +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.inhabas.api.domain.file.dto.FileDownloadDto; +import io.swagger.v3.oas.annotations.media.Schema; @Getter @NoArgsConstructor public class ClubActivityDetailDto { - @NotNull - @Positive - private Long id; - - @NotBlank - private String title; - - @NotBlank - private String content; - - @NotBlank - private String writerName; - - @NotNull - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern="yyyy-MM-dd'T'HH:mm:ss") - @Schema(type="string" , example = "2024-11-01T00:00:00") - private LocalDateTime dateCreated; - - - @NotNull - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern="yyyy-MM-dd'T'HH:mm:ss") - @Schema(type="string" , example = "2024-11-01T00:00:00") - private LocalDateTime dateUpdated; - - @NotNull - private List files; - - @Builder - public ClubActivityDetailDto(Long id, String title, String content, String writerName, LocalDateTime dateCreated, - LocalDateTime dateUpdated, List files) { - this.id = id; - this.title = title; - this.content = content; - this.writerName = writerName; - this.dateCreated = dateCreated; - this.dateUpdated = dateUpdated; - this.files = files; - } - + @NotNull @Positive private Long id; + + @NotBlank private String title; + + @NotBlank private String content; + + @NotBlank private String writerName; + + @NotNull + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss") + @Schema(type = "string", example = "2024-11-01T00:00:00") + private LocalDateTime dateCreated; + + @NotNull + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss") + @Schema(type = "string", example = "2024-11-01T00:00:00") + private LocalDateTime dateUpdated; + + @NotNull private List files; + + @Builder + public ClubActivityDetailDto( + Long id, + String title, + String content, + String writerName, + LocalDateTime dateCreated, + LocalDateTime dateUpdated, + List files) { + this.id = id; + this.title = title; + this.content = content; + this.writerName = writerName; + this.dateCreated = dateCreated; + this.dateUpdated = dateUpdated; + this.files = files; + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/club/dto/ClubActivityDto.java b/resource-server/src/main/java/com/inhabas/api/domain/club/dto/ClubActivityDto.java index 897608d4..df9eb358 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/club/dto/ClubActivityDto.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/club/dto/ClubActivityDto.java @@ -1,52 +1,54 @@ package com.inhabas.api.domain.club.dto; -import com.fasterxml.jackson.annotation.JsonFormat; -import com.inhabas.api.domain.file.dto.FileDownloadDto; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; +import java.time.LocalDateTime; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; import javax.validation.constraints.Positive; -import java.time.LocalDateTime; + +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.inhabas.api.domain.file.dto.FileDownloadDto; +import io.swagger.v3.oas.annotations.media.Schema; @Getter @NoArgsConstructor public class ClubActivityDto { - @NotNull - @Positive - private Long id; - - @NotBlank - private String title; - - @NotBlank - private String writerName; - - @NotNull - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern="yyyy-MM-dd'T'HH:mm:ss") - @Schema(type="string" , example = "2024-11-01T00:00:00") - private LocalDateTime dateCreated; - - @NotNull - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern="yyyy-MM-dd'T'HH:mm:ss") - @Schema(type="string" , example = "2024-11-01T00:00:00") - private LocalDateTime dateUpdated; - - private FileDownloadDto thumbnail; - - @Builder - public ClubActivityDto(Long id, String title, String writerName, LocalDateTime dateCreated, - LocalDateTime dateUpdated, FileDownloadDto thumbnail) { - this.id = id; - this.title = title; - this.writerName = writerName; - this.dateCreated = dateCreated; - this.dateUpdated = dateUpdated; - this.thumbnail = thumbnail; - } - + @NotNull @Positive private Long id; + + @NotBlank private String title; + + @NotBlank private String writerName; + + @NotNull + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss") + @Schema(type = "string", example = "2024-11-01T00:00:00") + private LocalDateTime dateCreated; + + @NotNull + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss") + @Schema(type = "string", example = "2024-11-01T00:00:00") + private LocalDateTime dateUpdated; + + private FileDownloadDto thumbnail; + + @Builder + public ClubActivityDto( + Long id, + String title, + String writerName, + LocalDateTime dateCreated, + LocalDateTime dateUpdated, + FileDownloadDto thumbnail) { + this.id = id; + this.title = title; + this.writerName = writerName; + this.dateCreated = dateCreated; + this.dateUpdated = dateUpdated; + this.thumbnail = thumbnail; + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/club/dto/ClubHistoryDto.java b/resource-server/src/main/java/com/inhabas/api/domain/club/dto/ClubHistoryDto.java index 607a8be0..d7edf8dd 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/club/dto/ClubHistoryDto.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/club/dto/ClubHistoryDto.java @@ -1,53 +1,50 @@ package com.inhabas.api.domain.club.dto; -import com.fasterxml.jackson.annotation.JsonFormat; -import com.inhabas.api.domain.club.domain.ClubHistory; -import io.swagger.v3.oas.annotations.media.Schema; +import java.time.LocalDateTime; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Positive; + import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; -import javax.validation.constraints.NotNull; -import javax.validation.constraints.Positive; -import java.time.LocalDateTime; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.inhabas.api.domain.club.domain.ClubHistory; +import io.swagger.v3.oas.annotations.media.Schema; @Getter @NoArgsConstructor public class ClubHistoryDto { - @NotNull - @Positive - private Long id; - - @NotNull - private String title; - - @NotNull - private String content; - - @NotNull - @Positive - private Long writerId; - - @NotNull - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss") - @Schema(type = "string", example = "2023-11-01T00:00:00") - private LocalDateTime dateHistory; - - @Builder - public ClubHistoryDto(Long id, String title, String content, Long writerId, LocalDateTime dateHistory) { - this.id = id; - this.title = title; - this.content = content; - this.writerId = writerId; - this.dateHistory = dateHistory; - } - - public ClubHistoryDto(ClubHistory clubHistory) { - this.id = clubHistory.getId(); - this.title = clubHistory.getTitle().getValue(); - this.content = clubHistory.getContent().getValue(); - this.writerId = clubHistory.getMember().getId(); - this.dateHistory = clubHistory.getDateHistory(); - } + @NotNull @Positive private Long id; + + @NotNull private String title; + + @NotNull private String content; + + @NotNull @Positive private Long writerId; + + @NotNull + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss") + @Schema(type = "string", example = "2023-11-01T00:00:00") + private LocalDateTime dateHistory; + + @Builder + public ClubHistoryDto( + Long id, String title, String content, Long writerId, LocalDateTime dateHistory) { + this.id = id; + this.title = title; + this.content = content; + this.writerId = writerId; + this.dateHistory = dateHistory; + } + + public ClubHistoryDto(ClubHistory clubHistory) { + this.id = clubHistory.getId(); + this.title = clubHistory.getTitle().getValue(); + this.content = clubHistory.getContent().getValue(); + this.writerId = clubHistory.getMember().getId(); + this.dateHistory = clubHistory.getDateHistory(); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/club/dto/SaveClubActivityDto.java b/resource-server/src/main/java/com/inhabas/api/domain/club/dto/SaveClubActivityDto.java index 988911d2..b84c845f 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/club/dto/SaveClubActivityDto.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/club/dto/SaveClubActivityDto.java @@ -1,31 +1,30 @@ package com.inhabas.api.domain.club.dto; +import java.util.ArrayList; +import java.util.List; + +import javax.validation.constraints.NotBlank; + import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; -import org.springframework.web.multipart.MultipartFile; -import javax.validation.constraints.NotBlank; -import java.util.ArrayList; -import java.util.List; +import org.springframework.web.multipart.MultipartFile; @Getter @NoArgsConstructor public class SaveClubActivityDto { - @NotBlank - private String title; - - @NotBlank - private String content; + @NotBlank private String title; - private List files; + @NotBlank private String content; - @Builder - public SaveClubActivityDto(String title, String content, List files) { - this.title = title; - this.content = content; - this.files = (files != null) ? files : new ArrayList<>(); - } + private List files; + @Builder + public SaveClubActivityDto(String title, String content, List files) { + this.title = title; + this.content = content; + this.files = (files != null) ? files : new ArrayList<>(); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/club/dto/SaveClubHistoryDto.java b/resource-server/src/main/java/com/inhabas/api/domain/club/dto/SaveClubHistoryDto.java index 792d6333..1f2b7d83 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/club/dto/SaveClubHistoryDto.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/club/dto/SaveClubHistoryDto.java @@ -1,32 +1,33 @@ package com.inhabas.api.domain.club.dto; -import com.fasterxml.jackson.annotation.JsonFormat; -import io.swagger.v3.oas.annotations.media.Schema; +import java.time.LocalDateTime; + +import javax.validation.constraints.NotNull; + import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; -import javax.validation.constraints.NotNull; -import java.time.LocalDateTime; +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; @Getter @NoArgsConstructor public class SaveClubHistoryDto { - private String title; - - private String content; + private String title; - @NotNull - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss") - @Schema(type = "string", example = "2023-11-01T00:00:00") - private LocalDateTime dateHistory; + private String content; - @Builder - public SaveClubHistoryDto(String title, String content, LocalDateTime dateHistory) { - this.title = title; - this.content = content; - this.dateHistory = dateHistory; - } + @NotNull + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss") + @Schema(type = "string", example = "2023-11-01T00:00:00") + private LocalDateTime dateHistory; + @Builder + public SaveClubHistoryDto(String title, String content, LocalDateTime dateHistory) { + this.title = title; + this.content = content; + this.dateHistory = dateHistory; + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/club/repository/ClubActivityRepository.java b/resource-server/src/main/java/com/inhabas/api/domain/club/repository/ClubActivityRepository.java index f8471d23..47819252 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/club/repository/ClubActivityRepository.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/club/repository/ClubActivityRepository.java @@ -1,7 +1,7 @@ package com.inhabas.api.domain.club.repository; -import com.inhabas.api.domain.board.domain.AlbumBoard; import org.springframework.data.jpa.repository.JpaRepository; -public interface ClubActivityRepository extends JpaRepository { -} +import com.inhabas.api.domain.board.domain.AlbumBoard; + +public interface ClubActivityRepository extends JpaRepository {} diff --git a/resource-server/src/main/java/com/inhabas/api/domain/club/repository/ClubHistoryRepository.java b/resource-server/src/main/java/com/inhabas/api/domain/club/repository/ClubHistoryRepository.java index 1f737caf..81940882 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/club/repository/ClubHistoryRepository.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/club/repository/ClubHistoryRepository.java @@ -1,7 +1,7 @@ package com.inhabas.api.domain.club.repository; -import com.inhabas.api.domain.club.domain.ClubHistory; import org.springframework.data.jpa.repository.JpaRepository; -public interface ClubHistoryRepository extends JpaRepository { -} +import com.inhabas.api.domain.club.domain.ClubHistory; + +public interface ClubHistoryRepository extends JpaRepository {} diff --git a/resource-server/src/main/java/com/inhabas/api/domain/club/usecase/ClubActivityService.java b/resource-server/src/main/java/com/inhabas/api/domain/club/usecase/ClubActivityService.java index 48d576c4..68e08344 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/club/usecase/ClubActivityService.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/club/usecase/ClubActivityService.java @@ -1,21 +1,20 @@ package com.inhabas.api.domain.club.usecase; +import java.util.List; + import com.inhabas.api.domain.club.dto.ClubActivityDetailDto; import com.inhabas.api.domain.club.dto.ClubActivityDto; import com.inhabas.api.domain.club.dto.SaveClubActivityDto; -import java.util.List; - public interface ClubActivityService { - List getClubActivities(); - - Long writeClubActivity(Long memberId, SaveClubActivityDto saveClubActivityDto); + List getClubActivities(); - ClubActivityDetailDto getClubActivity(Long boardId); + Long writeClubActivity(Long memberId, SaveClubActivityDto saveClubActivityDto); - void updateClubActivity(Long boardId, SaveClubActivityDto saveClubActivityDto); + ClubActivityDetailDto getClubActivity(Long boardId); - void deleteClubActivity(Long boardId); + void updateClubActivity(Long boardId, SaveClubActivityDto saveClubActivityDto); + void deleteClubActivity(Long boardId); } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/club/usecase/ClubActivityServiceImpl.java b/resource-server/src/main/java/com/inhabas/api/domain/club/usecase/ClubActivityServiceImpl.java index ef83d3b7..78aa6b7c 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/club/usecase/ClubActivityServiceImpl.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/club/usecase/ClubActivityServiceImpl.java @@ -1,5 +1,15 @@ package com.inhabas.api.domain.club.usecase; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import java.util.stream.Collectors; + +import lombok.RequiredArgsConstructor; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + import com.inhabas.api.auth.domain.error.businessException.NotFoundException; import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; import com.inhabas.api.auth.domain.oauth2.member.domain.exception.MemberNotFoundException; @@ -16,149 +26,145 @@ import com.inhabas.api.domain.file.usecase.S3Service; import com.inhabas.api.domain.menu.domain.Menu; import com.inhabas.api.domain.menu.repository.MenuRepository; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; -import java.util.stream.Collectors; @Service @RequiredArgsConstructor public class ClubActivityServiceImpl implements ClubActivityService { - private final ClubActivityRepository clubActivityRepository; - - private final BoardSecurityChecker boardSecurityChecker; - - private final MemberRepository memberRepository; - - private final MenuRepository menuRepository; - - private final S3Service s3Service; - - private static final String CLUB_ACTIVITY_MENU_NAME = "동아리 활동"; - - private static final String DIR_NAME = "clubActivity/"; - - - @Override - @Transactional(readOnly = true) - public List getClubActivities() { - - List clubActivityList = clubActivityRepository.findAll(); - - return clubActivityList.stream().map(obj -> { - String fileName = obj.getFiles().isEmpty() ? null : obj.getFiles().get(0).getName(); - String fileUrl = obj.getFiles().isEmpty() ? null : obj.getFiles().get(0).getUrl(); - return ClubActivityDto.builder() - .id(obj.getId()) - .title(obj.getTitle()) - .writerName(obj.getWriter().getName()) - .dateCreated(obj.getDateCreated()) - .dateUpdated(obj.getDateUpdated()) - .thumbnail(new FileDownloadDto(fileName, fileUrl)) - .build(); - }).collect(Collectors.toList()); - + private final ClubActivityRepository clubActivityRepository; + + private final BoardSecurityChecker boardSecurityChecker; + + private final MemberRepository memberRepository; + + private final MenuRepository menuRepository; + + private final S3Service s3Service; + + private static final String CLUB_ACTIVITY_MENU_NAME = "동아리 활동"; + + private static final String DIR_NAME = "clubActivity/"; + + @Override + @Transactional(readOnly = true) + public List getClubActivities() { + + List clubActivityList = clubActivityRepository.findAll(); + + return clubActivityList.stream() + .map( + obj -> { + String fileName = obj.getFiles().isEmpty() ? null : obj.getFiles().get(0).getName(); + String fileUrl = obj.getFiles().isEmpty() ? null : obj.getFiles().get(0).getUrl(); + return ClubActivityDto.builder() + .id(obj.getId()) + .title(obj.getTitle()) + .writerName(obj.getWriter().getName()) + .dateCreated(obj.getDateCreated()) + .dateUpdated(obj.getDateUpdated()) + .thumbnail(new FileDownloadDto(fileName, fileUrl)) + .build(); + }) + .collect(Collectors.toList()); + } + + @Override + @Transactional + public Long writeClubActivity(Long memberId, SaveClubActivityDto saveClubActivityDto) { + + Member writer = memberRepository.findById(memberId).orElseThrow(MemberNotFoundException::new); + Menu menu = + menuRepository + .findByName_Value(CLUB_ACTIVITY_MENU_NAME) + .orElseThrow(NotFoundException::new); + + AlbumBoard clubActivity = + AlbumBoard.builder() + .menu(menu) + .title(saveClubActivityDto.getTitle()) + .content(saveClubActivityDto.getContent()) + .build() + .writtenBy(writer, AlbumBoard.class); + + return updateClubActivityFiles(saveClubActivityDto, clubActivity); + } + + @Override + @Transactional(readOnly = true) + public ClubActivityDetailDto getClubActivity(Long boardId) { + + AlbumBoard clubActivity = + clubActivityRepository.findById(boardId).orElseThrow(NotFoundException::new); + List fileDownloadDtoList = null; + if (!clubActivity.getFiles().isEmpty()) { + fileDownloadDtoList = + clubActivity.getFiles().stream() + .map(obj -> FileDownloadDto.builder().name(obj.getName()).url(obj.getUrl()).build()) + .collect(Collectors.toList()); } - @Override - @Transactional - public Long writeClubActivity(Long memberId, SaveClubActivityDto saveClubActivityDto) { - - Member writer = memberRepository.findById(memberId).orElseThrow(MemberNotFoundException::new); - Menu menu = menuRepository.findByName_Value(CLUB_ACTIVITY_MENU_NAME).orElseThrow(NotFoundException::new); - - AlbumBoard clubActivity = AlbumBoard.builder() - .menu(menu) - .title(saveClubActivityDto.getTitle()) - .content(saveClubActivityDto.getContent()) - .build() - .writtenBy(writer, AlbumBoard.class); - - return updateClubActivityFiles(saveClubActivityDto, clubActivity); - - } - - @Override - @Transactional(readOnly = true) - public ClubActivityDetailDto getClubActivity(Long boardId) { - - AlbumBoard clubActivity = clubActivityRepository.findById(boardId).orElseThrow(NotFoundException::new); - List fileDownloadDtoList = null; - if (!clubActivity.getFiles().isEmpty()) { - fileDownloadDtoList = clubActivity.getFiles().stream().map(obj -> - FileDownloadDto.builder() - .name(obj.getName()) - .url(obj.getUrl()) - .build() - ).collect(Collectors.toList()); + return ClubActivityDetailDto.builder() + .id(clubActivity.getId()) + .title(clubActivity.getTitle()) + .content(clubActivity.getContent()) + .writerName(clubActivity.getWriter().getName()) + .dateCreated(clubActivity.getDateCreated()) + .dateUpdated(clubActivity.getDateUpdated()) + .files(fileDownloadDtoList) + .build(); + } + + @Override + @Transactional + public void updateClubActivity(Long boardId, SaveClubActivityDto saveClubActivityDto) { + + AlbumBoard clubActivity = + clubActivityRepository.findById(boardId).orElseThrow(NotFoundException::new); + updateClubActivityFiles(saveClubActivityDto, clubActivity); + } + + @Override + @Transactional + public void deleteClubActivity(Long boardId) { + + clubActivityRepository.deleteById(boardId); + } + + private Long updateClubActivityFiles( + SaveClubActivityDto saveClubActivityDto, AlbumBoard clubActivity) { + List updateFiles = new ArrayList<>(); + List urlListForDelete = new ArrayList<>(); + + if (saveClubActivityDto.getFiles() != null) { + clubActivity.updateText(saveClubActivityDto.getTitle(), saveClubActivityDto.getContent()); + try { + updateFiles = + saveClubActivityDto.getFiles().stream() + .map( + file -> { + String url = s3Service.uploadS3File(file, generateRandomUrl()); + urlListForDelete.add(url); + return BoardFile.builder() + .name(file.getOriginalFilename()) + .url(url) + .board(clubActivity) + .build(); + }) + .collect(Collectors.toList()); + + } catch (RuntimeException e) { + for (String url : urlListForDelete) { + s3Service.deleteS3File(url); } - - return ClubActivityDetailDto.builder() - .id(clubActivity.getId()) - .title(clubActivity.getTitle()) - .content(clubActivity.getContent()) - .writerName(clubActivity.getWriter().getName()) - .dateCreated(clubActivity.getDateCreated()) - .dateUpdated(clubActivity.getDateUpdated()) - .files(fileDownloadDtoList) - .build(); - + throw new S3UploadFailedException(); + } } - @Override - @Transactional - public void updateClubActivity(Long boardId, SaveClubActivityDto saveClubActivityDto) { - - AlbumBoard clubActivity = clubActivityRepository.findById(boardId).orElseThrow(NotFoundException::new); - updateClubActivityFiles(saveClubActivityDto, clubActivity); - - } - - @Override - @Transactional - public void deleteClubActivity(Long boardId) { - - clubActivityRepository.deleteById(boardId); - - } - - private Long updateClubActivityFiles(SaveClubActivityDto saveClubActivityDto, AlbumBoard clubActivity) { - List updateFiles = new ArrayList<>(); - List urlListForDelete = new ArrayList<>(); - - if (saveClubActivityDto.getFiles() != null) { - clubActivity.updateText(saveClubActivityDto.getTitle(), saveClubActivityDto.getContent()); - try { - updateFiles = saveClubActivityDto.getFiles().stream().map(file -> { - String url = s3Service.uploadS3File(file, generateRandomUrl()); - urlListForDelete.add(url); - return BoardFile.builder() - .name(file.getOriginalFilename()) - .url(url) - .board(clubActivity) - .build(); - }).collect(Collectors.toList()); - - } catch (RuntimeException e) { - for (String url : urlListForDelete) { - s3Service.deleteS3File(url); - } - throw new S3UploadFailedException(); - } - } - - clubActivity.updateFiles(updateFiles); - return clubActivityRepository.save(clubActivity).getId(); - - } - - private String generateRandomUrl() { - return DIR_NAME + UUID.randomUUID(); - } + clubActivity.updateFiles(updateFiles); + return clubActivityRepository.save(clubActivity).getId(); + } + private String generateRandomUrl() { + return DIR_NAME + UUID.randomUUID(); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/club/usecase/ClubHistoryService.java b/resource-server/src/main/java/com/inhabas/api/domain/club/usecase/ClubHistoryService.java index 4e572f19..5f7952d9 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/club/usecase/ClubHistoryService.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/club/usecase/ClubHistoryService.java @@ -1,21 +1,19 @@ package com.inhabas.api.domain.club.usecase; +import java.util.List; + import com.inhabas.api.domain.club.dto.ClubHistoryDto; import com.inhabas.api.domain.club.dto.SaveClubHistoryDto; -import java.util.List; - public interface ClubHistoryService { - Long writeClubHistory(Long memberId, SaveClubHistoryDto saveClubHistoryDto); - - ClubHistoryDto findClubHistory(Long clubHistoryId); + Long writeClubHistory(Long memberId, SaveClubHistoryDto saveClubHistoryDto); - List getClubHistories(); + ClubHistoryDto findClubHistory(Long clubHistoryId); - void updateClubHistory(Long memberId, Long clubHistoryId, SaveClubHistoryDto saveClubHistoryDto); + List getClubHistories(); - void deleteClubHistory(Long clubHistoryId); + void updateClubHistory(Long memberId, Long clubHistoryId, SaveClubHistoryDto saveClubHistoryDto); + void deleteClubHistory(Long clubHistoryId); } - diff --git a/resource-server/src/main/java/com/inhabas/api/domain/club/usecase/ClubHistoryServiceImpl.java b/resource-server/src/main/java/com/inhabas/api/domain/club/usecase/ClubHistoryServiceImpl.java index 3ce3bddc..1aa74a8f 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/club/usecase/ClubHistoryServiceImpl.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/club/usecase/ClubHistoryServiceImpl.java @@ -1,5 +1,14 @@ package com.inhabas.api.domain.club.usecase; +import java.util.List; +import java.util.stream.Collectors; + +import lombok.RequiredArgsConstructor; + +import org.springframework.data.domain.Sort; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + import com.inhabas.api.auth.domain.error.businessException.NotFoundException; import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; import com.inhabas.api.auth.domain.oauth2.member.domain.exception.MemberNotFoundException; @@ -10,81 +19,71 @@ import com.inhabas.api.domain.club.dto.ClubHistoryDto; import com.inhabas.api.domain.club.dto.SaveClubHistoryDto; import com.inhabas.api.domain.club.repository.ClubHistoryRepository; -import lombok.RequiredArgsConstructor; -import org.springframework.data.domain.Sort; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.util.List; -import java.util.stream.Collectors; @Service @RequiredArgsConstructor public class ClubHistoryServiceImpl implements ClubHistoryService { - private final ClubHistoryRepository clubHistoryRepository; - - private final MemberRepository memberRepository; - - - @Override - @Transactional - public Long writeClubHistory(Long memberId, SaveClubHistoryDto saveClubHistoryDto) { - - Member writer = memberRepository.findById(memberId).orElseThrow(MemberNotFoundException::new); - ClubHistory clubHistory = ClubHistory.builder() - .member(writer) - .title(new Title(saveClubHistoryDto.getTitle())) - .content(new Content(saveClubHistoryDto.getContent())) - .dateHistory(saveClubHistoryDto.getDateHistory()) - .build(); - - ClubHistory result = clubHistoryRepository.save(clubHistory); - - return result.getId(); + private final ClubHistoryRepository clubHistoryRepository; - } + private final MemberRepository memberRepository; - @Override - @Transactional(readOnly = true) - public ClubHistoryDto findClubHistory(Long clubHistoryId) { + @Override + @Transactional + public Long writeClubHistory(Long memberId, SaveClubHistoryDto saveClubHistoryDto) { - ClubHistory clubHistory = clubHistoryRepository.findById(clubHistoryId).orElseThrow(NotFoundException::new); + Member writer = memberRepository.findById(memberId).orElseThrow(MemberNotFoundException::new); + ClubHistory clubHistory = + ClubHistory.builder() + .member(writer) + .title(new Title(saveClubHistoryDto.getTitle())) + .content(new Content(saveClubHistoryDto.getContent())) + .dateHistory(saveClubHistoryDto.getDateHistory()) + .build(); - return new ClubHistoryDto(clubHistory); + ClubHistory result = clubHistoryRepository.save(clubHistory); - } + return result.getId(); + } - @Override - @Transactional(readOnly = true) - public List getClubHistories() { + @Override + @Transactional(readOnly = true) + public ClubHistoryDto findClubHistory(Long clubHistoryId) { - Sort sort = Sort.by(Sort.Direction.DESC, "dateHistory"); - List clubHistoryList = clubHistoryRepository.findAll(sort); + ClubHistory clubHistory = + clubHistoryRepository.findById(clubHistoryId).orElseThrow(NotFoundException::new); - return clubHistoryList.stream() - .map(ClubHistoryDto::new) - .collect(Collectors.toList()); + return new ClubHistoryDto(clubHistory); + } - } + @Override + @Transactional(readOnly = true) + public List getClubHistories() { - @Override - @Transactional - public void updateClubHistory(Long memberId, Long clubHistoryId, SaveClubHistoryDto saveClubHistoryDto) { + Sort sort = Sort.by(Sort.Direction.DESC, "dateHistory"); + List clubHistoryList = clubHistoryRepository.findAll(sort); - ClubHistory clubHistory = clubHistoryRepository.findById(clubHistoryId).orElseThrow(NotFoundException::new); - Member writer = memberRepository.findById(memberId).orElseThrow(MemberNotFoundException::new); + return clubHistoryList.stream().map(ClubHistoryDto::new).collect(Collectors.toList()); + } - clubHistory.updateClubHistory(writer, saveClubHistoryDto); + @Override + @Transactional + public void updateClubHistory( + Long memberId, Long clubHistoryId, SaveClubHistoryDto saveClubHistoryDto) { - } + ClubHistory clubHistory = + clubHistoryRepository.findById(clubHistoryId).orElseThrow(NotFoundException::new); + Member writer = memberRepository.findById(memberId).orElseThrow(MemberNotFoundException::new); - @Override - @Transactional - public void deleteClubHistory(Long clubHistoryId) { + clubHistory.updateClubHistory(writer, saveClubHistoryDto); + } - ClubHistory clubHistory = clubHistoryRepository.findById(clubHistoryId).orElseThrow(NotFoundException::new); - clubHistoryRepository.delete(clubHistory); + @Override + @Transactional + public void deleteClubHistory(Long clubHistoryId) { - } + ClubHistory clubHistory = + clubHistoryRepository.findById(clubHistoryId).orElseThrow(NotFoundException::new); + clubHistoryRepository.delete(clubHistory); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/comment/domain/Comment.java b/resource-server/src/main/java/com/inhabas/api/domain/comment/domain/Comment.java index 57bd8aa5..0a2202cf 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/comment/domain/Comment.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/comment/domain/Comment.java @@ -1,19 +1,22 @@ package com.inhabas.api.domain.comment.domain; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Objects; + +import javax.persistence.*; + +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +import org.springframework.data.jpa.domain.support.AuditingEntityListener; + import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; import com.inhabas.api.domain.BaseEntity; import com.inhabas.api.domain.board.domain.BaseBoard; import com.inhabas.api.domain.board.exception.WriterUnmodifiableException; import com.inhabas.api.domain.comment.domain.valueObject.Content; -import lombok.AccessLevel; -import lombok.NoArgsConstructor; -import org.springframework.data.jpa.domain.support.AuditingEntityListener; - -import javax.persistence.*; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Objects; @Entity @Table(name = "COMMENT") @@ -21,134 +24,135 @@ @NoArgsConstructor(access = AccessLevel.PROTECTED) public class Comment extends BaseEntity { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @ManyToOne(fetch = FetchType.LAZY, optional = false) - @JoinColumn(name = "USER_ID", foreignKey = @ForeignKey(name = "FK_COMMENT_OF_USER_ID")) - private Member writer; - - @Embedded - private Content content; - - @ManyToOne(fetch = FetchType.LAZY, optional = false) - @JoinColumn(name = "BOARD_ID", foreignKey = @ForeignKey(name = "FK_COMMENT_OF_BOARD_ID")) - private BaseBoard parentBoard; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "PARENT_COMMENT", foreignKey = @ForeignKey(name = "FK_COMMENT_OF_COMMENT_REF_ID")) - private Comment parentComment; - - @OneToMany(mappedBy = "parentComment", cascade = CascadeType.ALL, orphanRemoval = true) - private final List childrenComment = new ArrayList<>(); - - @Column(nullable = false) - private Boolean isDeleted = false; - - - /* constructor */ - - public Comment(String content, Member writer, BaseBoard parentBoard) { - this.content = new Content(content); - this.writtenBy(writer); - this.toBoard(parentBoard); - } - - /* getter */ - - public Long getId() { - return id; - } - - public Member getWriter() { - return writer; - } - - public BaseBoard getParentBoard() { - return parentBoard; - } - - public Comment getParentComment() { - return parentComment; - } - - public List getChildrenComment() { - return Collections.unmodifiableList(childrenComment); - } - - public String getContent() { - return this.content.getValue(); - } - - public Boolean getIsDeleted() { - return isDeleted; - } - - - public Long update(String content) { - this.content = new Content(content); - return this.id; - } - - - /* relation methods */ - - public Comment toBoard(BaseBoard newBoard) { - if (Objects.nonNull(this.parentBoard)) - throw new IllegalStateException("댓글을 다른 게시글로 옮길 수 없습니다."); - - this.parentBoard = newBoard; - newBoard.addComment(this); - - return this; - } - - public Comment writtenBy(Member writer) { - if (Objects.nonNull(writer)) - this.writer = writer; - else - throw new WriterUnmodifiableException(); - return this; - } - - public Comment replyTo(Comment parentComment) { - this.parentComment = parentComment; - parentComment.addReply(this); - - return this; - } - - private void addReply(Comment reply) { - this.childrenComment.add(reply); - } - - public void updateIsDeleted(Boolean isDeleted) { - this.isDeleted = isDeleted; - } + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; - /* others */ + @ManyToOne(fetch = FetchType.LAZY, optional = false) + @JoinColumn(name = "USER_ID", foreignKey = @ForeignKey(name = "FK_COMMENT_OF_USER_ID")) + private Member writer; - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(Comment.class.isAssignableFrom(o.getClass()))) return false; - Comment comment = (Comment) o; - return getId().equals(comment.getId()) - && getWriter().equals(comment.getWriter()) - && getContent().equals(comment.getContent()) - && getParentBoard().equals(comment.getParentBoard()) - && Objects.equals(getParentComment(), comment.getParentComment()) - && Objects.equals(getChildrenComment(), comment.getChildrenComment()); - } + @Embedded private Content content; - @Override - public int hashCode() { - return Objects.hash(getId(), getWriter(), getContent(), getParentBoard(), getParentComment(), getChildrenComment()); - } + @ManyToOne(fetch = FetchType.LAZY, optional = false) + @JoinColumn(name = "BOARD_ID", foreignKey = @ForeignKey(name = "FK_COMMENT_OF_BOARD_ID")) + private BaseBoard parentBoard; - public boolean isWrittenBy(Long writerId) { - return writer.isSameMember(writerId); - } + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn( + name = "PARENT_COMMENT", + foreignKey = @ForeignKey(name = "FK_COMMENT_OF_COMMENT_REF_ID")) + private Comment parentComment; + @OneToMany(mappedBy = "parentComment", cascade = CascadeType.ALL, orphanRemoval = true) + private final List childrenComment = new ArrayList<>(); + + @Column(nullable = false) + private Boolean isDeleted = false; + + /* constructor */ + + public Comment(String content, Member writer, BaseBoard parentBoard) { + this.content = new Content(content); + this.writtenBy(writer); + this.toBoard(parentBoard); + } + + /* getter */ + + public Long getId() { + return id; + } + + public Member getWriter() { + return writer; + } + + public BaseBoard getParentBoard() { + return parentBoard; + } + + public Comment getParentComment() { + return parentComment; + } + + public List getChildrenComment() { + return Collections.unmodifiableList(childrenComment); + } + + public String getContent() { + return this.content.getValue(); + } + + public Boolean getIsDeleted() { + return isDeleted; + } + + public Long update(String content) { + this.content = new Content(content); + return this.id; + } + + /* relation methods */ + + public Comment toBoard(BaseBoard newBoard) { + if (Objects.nonNull(this.parentBoard)) + throw new IllegalStateException("댓글을 다른 게시글로 옮길 수 없습니다."); + + this.parentBoard = newBoard; + newBoard.addComment(this); + + return this; + } + + public Comment writtenBy(Member writer) { + if (Objects.nonNull(writer)) this.writer = writer; + else throw new WriterUnmodifiableException(); + return this; + } + + public Comment replyTo(Comment parentComment) { + this.parentComment = parentComment; + parentComment.addReply(this); + + return this; + } + + private void addReply(Comment reply) { + this.childrenComment.add(reply); + } + + public void updateIsDeleted(Boolean isDeleted) { + this.isDeleted = isDeleted; + } + + /* others */ + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(Comment.class.isAssignableFrom(o.getClass()))) return false; + Comment comment = (Comment) o; + return getId().equals(comment.getId()) + && getWriter().equals(comment.getWriter()) + && getContent().equals(comment.getContent()) + && getParentBoard().equals(comment.getParentBoard()) + && Objects.equals(getParentComment(), comment.getParentComment()) + && Objects.equals(getChildrenComment(), comment.getChildrenComment()); + } + + @Override + public int hashCode() { + return Objects.hash( + getId(), + getWriter(), + getContent(), + getParentBoard(), + getParentComment(), + getChildrenComment()); + } + + public boolean isWrittenBy(Long writerId) { + return writer.isSameMember(writerId); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/comment/domain/valueObject/Content.java b/resource-server/src/main/java/com/inhabas/api/domain/comment/domain/valueObject/Content.java index 4d220c8d..fd992105 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/comment/domain/valueObject/Content.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/comment/domain/valueObject/Content.java @@ -1,40 +1,38 @@ package com.inhabas.api.domain.comment.domain.valueObject; -import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; +import java.util.Objects; import javax.persistence.Column; import javax.persistence.Embeddable; import javax.persistence.Transient; -import java.util.Objects; + +import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; @Embeddable public class Content { - @Column(name = "CONTENT", length = 500, nullable = false) - private String value; + @Column(name = "CONTENT", length = 500, nullable = false) + private String value; - @Transient - private final int MAX_LENGTH = 500; + @Transient private final int MAX_LENGTH = 500; - public Content() {} + public Content() {} - public Content(String value) { - if (validate(value)) - this.value = value; - else - throw new InvalidInputException(); - } + public Content(String value) { + if (validate(value)) this.value = value; + else throw new InvalidInputException(); + } - private boolean validate(Object value) { - if (Objects.isNull(value)) return false; - if (!(value instanceof String)) return false; + private boolean validate(Object value) { + if (Objects.isNull(value)) return false; + if (!(value instanceof String)) return false; - String o = (String) value; - if (o.isBlank()) return false; - return o.length() < MAX_LENGTH; - } + String o = (String) value; + if (o.isBlank()) return false; + return o.length() < MAX_LENGTH; + } - public String getValue() { - return value; - } + public String getValue() { + return value; + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/comment/dto/CommentDetailDto.java b/resource-server/src/main/java/com/inhabas/api/domain/comment/dto/CommentDetailDto.java index 854d6b0a..d7902c5d 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/comment/dto/CommentDetailDto.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/comment/dto/CommentDetailDto.java @@ -1,60 +1,61 @@ package com.inhabas.api.domain.comment.dto; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Positive; + +import lombok.Getter; +import lombok.NoArgsConstructor; + import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonProperty; import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; import com.inhabas.api.domain.comment.domain.Comment; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotNull; -import javax.validation.constraints.Positive; -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; @Getter @NoArgsConstructor public class CommentDetailDto { - @NotNull - @Positive - private Long id; - - @JsonProperty("writer") - private WriterInfo writerInfo; + @NotNull @Positive private Long id; - @NotBlank - private String content; + @JsonProperty("writer") + private WriterInfo writerInfo; - private List childrenComment = new ArrayList<>(); + @NotBlank private String content; - private static final String DELETED_MESSAGE = "삭제된 댓글입니다."; + private List childrenComment = new ArrayList<>(); - @NotBlank - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern="yyyy-MM-dd'T'HH:mm:ss") - @Schema(type="string" , example = "2024-11-01T00:00:00") - private LocalDateTime dateUpdated; + private static final String DELETED_MESSAGE = "삭제된 댓글입니다."; + @NotBlank + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss") + @Schema(type = "string", example = "2024-11-01T00:00:00") + private LocalDateTime dateUpdated; + public static CommentDetailDto fromEntity(Comment comment) { + return comment.getIsDeleted() + ? new CommentDetailDto( + comment.getId(), comment.getWriter(), DELETED_MESSAGE, comment.getDateUpdated()) + : new CommentDetailDto( + comment.getId(), comment.getWriter(), comment.getContent(), comment.getDateUpdated()); + } - public static CommentDetailDto fromEntity(Comment comment) { - return comment.getIsDeleted() ? - new CommentDetailDto(comment.getId(), comment.getWriter(), DELETED_MESSAGE, comment.getDateUpdated()) : - new CommentDetailDto(comment.getId(), comment.getWriter(), comment.getContent(), comment.getDateUpdated() - ); - } - - public CommentDetailDto(Long id, Member writer, - String content, LocalDateTime dateUpdated) { - this.id = id; - if (writer != null) { - this.writerInfo = new WriterInfo(writer.getId(), writer.getName(), - writer.getSchoolInformation().getMajor(), writer.getPicture()); - } - this.content = content; - this.dateUpdated = dateUpdated; + public CommentDetailDto(Long id, Member writer, String content, LocalDateTime dateUpdated) { + this.id = id; + if (writer != null) { + this.writerInfo = + new WriterInfo( + writer.getId(), + writer.getName(), + writer.getSchoolInformation().getMajor(), + writer.getPicture()); } + this.content = content; + this.dateUpdated = dateUpdated; + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/comment/dto/CommentSaveDto.java b/resource-server/src/main/java/com/inhabas/api/domain/comment/dto/CommentSaveDto.java index 13777a36..1e1f4dde 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/comment/dto/CommentSaveDto.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/comment/dto/CommentSaveDto.java @@ -1,31 +1,32 @@ package com.inhabas.api.domain.comment.dto; -import com.fasterxml.jackson.annotation.JsonIgnore; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Positive; + import lombok.AccessLevel; import lombok.Getter; import lombok.NoArgsConstructor; -import org.hibernate.validator.constraints.Length; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.Positive; +import com.fasterxml.jackson.annotation.JsonIgnore; +import org.hibernate.validator.constraints.Length; @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) public class CommentSaveDto { - @NotBlank @Length(max = 499, message = "500자 이하여야 합니다.") - private String content; + @NotBlank + @Length(max = 499, message = "500자 이하여야 합니다.") + private String content; - @Positive - private Long parentCommentId; + @Positive private Long parentCommentId; - public CommentSaveDto(String content, Long parentCommentId) { - this.content = content; - this.parentCommentId = parentCommentId; - } + public CommentSaveDto(String content, Long parentCommentId) { + this.content = content; + this.parentCommentId = parentCommentId; + } - @JsonIgnore - public boolean isNotRootComment() { - return this.parentCommentId != null; - } + @JsonIgnore + public boolean isNotRootComment() { + return this.parentCommentId != null; + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/comment/dto/CommentUpdateDto.java b/resource-server/src/main/java/com/inhabas/api/domain/comment/dto/CommentUpdateDto.java index c03020c5..639f9685 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/comment/dto/CommentUpdateDto.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/comment/dto/CommentUpdateDto.java @@ -1,22 +1,24 @@ package com.inhabas.api.domain.comment.dto; +import javax.validation.constraints.NotBlank; + import lombok.AccessLevel; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; -import org.hibernate.validator.constraints.Length; -import javax.validation.constraints.NotBlank; +import org.hibernate.validator.constraints.Length; -@Setter @Getter +@Setter +@Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) public class CommentUpdateDto { - @NotBlank @Length(max = 499, message = "500자 이하여야 합니다.") - private String content; - - public CommentUpdateDto(String content) { - this.content = content; - } + @NotBlank + @Length(max = 499, message = "500자 이하여야 합니다.") + private String content; + public CommentUpdateDto(String content) { + this.content = content; + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/comment/dto/WriterInfo.java b/resource-server/src/main/java/com/inhabas/api/domain/comment/dto/WriterInfo.java index e70b4d2e..e82badc6 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/comment/dto/WriterInfo.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/comment/dto/WriterInfo.java @@ -1,33 +1,28 @@ package com.inhabas.api.domain.comment.dto; -import lombok.Getter; -import lombok.NoArgsConstructor; - import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; import javax.validation.constraints.Positive; +import lombok.Getter; +import lombok.NoArgsConstructor; + @Getter @NoArgsConstructor public class WriterInfo { - @NotNull - @Positive - private Long id; - - @NotBlank - private String name; + @NotNull @Positive private Long id; - @NotBlank - private String major; + @NotBlank private String name; - private String pictureUrl; + @NotBlank private String major; - public WriterInfo(Long id, String name, String major, String pictureUrl) { - this.id = id; - this.name = name; - this.major = major; - this.pictureUrl = pictureUrl; - } + private String pictureUrl; -} \ No newline at end of file + public WriterInfo(Long id, String name, String major, String pictureUrl) { + this.id = id; + this.name = name; + this.major = major; + this.pictureUrl = pictureUrl; + } +} diff --git a/resource-server/src/main/java/com/inhabas/api/domain/comment/repository/CommentRepository.java b/resource-server/src/main/java/com/inhabas/api/domain/comment/repository/CommentRepository.java index a0e942ac..1ac2191e 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/comment/repository/CommentRepository.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/comment/repository/CommentRepository.java @@ -1,10 +1,9 @@ package com.inhabas.api.domain.comment.repository; -import com.inhabas.api.domain.comment.domain.Comment; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; -@Repository -public interface CommentRepository extends JpaRepository, CustomCommentRepository { +import com.inhabas.api.domain.comment.domain.Comment; -} +@Repository +public interface CommentRepository extends JpaRepository, CustomCommentRepository {} diff --git a/resource-server/src/main/java/com/inhabas/api/domain/comment/repository/CommentRepositoryImpl.java b/resource-server/src/main/java/com/inhabas/api/domain/comment/repository/CommentRepositoryImpl.java index dd6f2553..097364f1 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/comment/repository/CommentRepositoryImpl.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/comment/repository/CommentRepositoryImpl.java @@ -2,53 +2,60 @@ import static com.inhabas.api.domain.comment.domain.QComment.comment; -import com.inhabas.api.domain.comment.domain.Comment; -import com.inhabas.api.domain.comment.dto.CommentDetailDto; -import com.querydsl.jpa.impl.JPAQueryFactory; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; + import lombok.RequiredArgsConstructor; +import com.inhabas.api.domain.comment.domain.Comment; +import com.inhabas.api.domain.comment.dto.CommentDetailDto; +import com.querydsl.jpa.impl.JPAQueryFactory; + @RequiredArgsConstructor public class CommentRepositoryImpl implements CustomCommentRepository { - private final JPAQueryFactory queryFactory; - - @Override - public List findAllByParentBoardIdOrderByCreated(Long boardId) { - List comments = queryFactory.selectFrom(comment) - .innerJoin(comment.writer).fetchJoin() - .leftJoin(comment.parentComment).fetchJoin() - .where(comment.parentBoard.id.eq(boardId)) - .orderBy(comment.dateCreated.asc(), comment.parentComment.id.asc().nullsFirst(), comment.id.asc()) - .fetch(); - - return convertToNestedStructure(comments); - } - - private List convertToNestedStructure(List commentList) { - - List result = new ArrayList<>(); - Map map = new HashMap<>(); - - commentList.forEach(c -> { - CommentDetailDto dto = CommentDetailDto.fromEntity(c); - - map.put(dto.getId(), dto); - if(isRootComment(c)) - result.add(dto); - else - map.get(c.getParentComment().getId()).getChildrenComment().add(dto); - + private final JPAQueryFactory queryFactory; + + @Override + public List findAllByParentBoardIdOrderByCreated(Long boardId) { + List comments = + queryFactory + .selectFrom(comment) + .innerJoin(comment.writer) + .fetchJoin() + .leftJoin(comment.parentComment) + .fetchJoin() + .where(comment.parentBoard.id.eq(boardId)) + .orderBy( + comment.dateCreated.asc(), + comment.parentComment.id.asc().nullsFirst(), + comment.id.asc()) + .fetch(); + + return convertToNestedStructure(comments); + } + + private List convertToNestedStructure(List commentList) { + + List result = new ArrayList<>(); + Map map = new HashMap<>(); + + commentList.forEach( + c -> { + CommentDetailDto dto = CommentDetailDto.fromEntity(c); + + map.put(dto.getId(), dto); + if (isRootComment(c)) result.add(dto); + else map.get(c.getParentComment().getId()).getChildrenComment().add(dto); }); - return result; - } + return result; + } - private boolean isRootComment(Comment c) { - return Objects.isNull(c.getParentComment()); - } + private boolean isRootComment(Comment c) { + return Objects.isNull(c.getParentComment()); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/comment/repository/CustomCommentRepository.java b/resource-server/src/main/java/com/inhabas/api/domain/comment/repository/CustomCommentRepository.java index 188f1cf7..edbbb071 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/comment/repository/CustomCommentRepository.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/comment/repository/CustomCommentRepository.java @@ -1,11 +1,10 @@ package com.inhabas.api.domain.comment.repository; -import com.inhabas.api.domain.comment.dto.CommentDetailDto; - import java.util.List; -public interface CustomCommentRepository { +import com.inhabas.api.domain.comment.dto.CommentDetailDto; - List findAllByParentBoardIdOrderByCreated(Long boardId); +public interface CustomCommentRepository { + List findAllByParentBoardIdOrderByCreated(Long boardId); } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/comment/usecase/CommentService.java b/resource-server/src/main/java/com/inhabas/api/domain/comment/usecase/CommentService.java index ae580609..cac4a1e5 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/comment/usecase/CommentService.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/comment/usecase/CommentService.java @@ -1,19 +1,18 @@ package com.inhabas.api.domain.comment.usecase; +import java.util.List; + import com.inhabas.api.domain.comment.dto.CommentDetailDto; import com.inhabas.api.domain.comment.dto.CommentSaveDto; import com.inhabas.api.domain.comment.dto.CommentUpdateDto; -import java.util.List; - public interface CommentService { - List getComments(Integer menuId, Long boardId); - - Long create(CommentSaveDto commentSaveDto, Integer menuId, Long boardId, Long memberId); + List getComments(Integer menuId, Long boardId); - Long update(Long commentId, CommentUpdateDto commentUpdateDto); + Long create(CommentSaveDto commentSaveDto, Integer menuId, Long boardId, Long memberId); - void delete(Long boardId); + Long update(Long commentId, CommentUpdateDto commentUpdateDto); + void delete(Long boardId); } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/comment/usecase/CommentServiceImpl.java b/resource-server/src/main/java/com/inhabas/api/domain/comment/usecase/CommentServiceImpl.java index 811c6a87..e5996059 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/comment/usecase/CommentServiceImpl.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/comment/usecase/CommentServiceImpl.java @@ -1,5 +1,14 @@ package com.inhabas.api.domain.comment.usecase; +import java.util.List; + +import javax.persistence.EntityManager; + +import lombok.RequiredArgsConstructor; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + import com.inhabas.api.auth.domain.error.businessException.NotFoundException; import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; import com.inhabas.api.auth.domain.oauth2.member.repository.MemberRepository; @@ -9,62 +18,48 @@ import com.inhabas.api.domain.comment.dto.CommentSaveDto; import com.inhabas.api.domain.comment.dto.CommentUpdateDto; import com.inhabas.api.domain.comment.repository.CommentRepository; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import javax.persistence.EntityManager; -import java.util.List; @Service @RequiredArgsConstructor public class CommentServiceImpl implements CommentService { - private final EntityManager em; - private final CommentRepository commentRepository; - private final MemberRepository memberRepository; - - @Transactional(readOnly = true) - public List getComments(Integer menuId, Long boardId) { - - return commentRepository.findAllByParentBoardIdOrderByCreated(boardId); - } - + private final EntityManager em; + private final CommentRepository commentRepository; + private final MemberRepository memberRepository; - @Transactional - public Long create(CommentSaveDto commentSaveDto, Integer menuId, Long boardId, Long memberId) { + @Transactional(readOnly = true) + public List getComments(Integer menuId, Long boardId) { - BaseBoard parentBoard = em.getReference(BaseBoard.class, boardId); - Member writer = em.getReference(Member.class, memberId); - Comment newComment = new Comment(commentSaveDto.getContent(), writer, parentBoard); + return commentRepository.findAllByParentBoardIdOrderByCreated(boardId); + } - if (commentSaveDto.isNotRootComment()) { - Comment parentComment = em.getReference(Comment.class, commentSaveDto.getParentCommentId()); - newComment.replyTo(parentComment); - } + @Transactional + public Long create(CommentSaveDto commentSaveDto, Integer menuId, Long boardId, Long memberId) { - return commentRepository.save(newComment).getId(); + BaseBoard parentBoard = em.getReference(BaseBoard.class, boardId); + Member writer = em.getReference(Member.class, memberId); + Comment newComment = new Comment(commentSaveDto.getContent(), writer, parentBoard); + if (commentSaveDto.isNotRootComment()) { + Comment parentComment = em.getReference(Comment.class, commentSaveDto.getParentCommentId()); + newComment.replyTo(parentComment); } + return commentRepository.save(newComment).getId(); + } - @Transactional - public Long update(Long commentId, CommentUpdateDto commentUpdateDto) { - - Comment oldComment = commentRepository.findById(commentId) - .orElseThrow(NotFoundException::new); - - return oldComment.update(commentUpdateDto.getContent()); + @Transactional + public Long update(Long commentId, CommentUpdateDto commentUpdateDto) { - } - - @Transactional - public void delete(Long commentId) { + Comment oldComment = commentRepository.findById(commentId).orElseThrow(NotFoundException::new); - Comment comment = commentRepository.findById(commentId) - .orElseThrow(NotFoundException::new); - comment.updateIsDeleted(true); + return oldComment.update(commentUpdateDto.getContent()); + } - } + @Transactional + public void delete(Long commentId) { + Comment comment = commentRepository.findById(commentId).orElseThrow(NotFoundException::new); + comment.updateIsDeleted(true); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/contest/domain/ContestBoard.java b/resource-server/src/main/java/com/inhabas/api/domain/contest/domain/ContestBoard.java index 10351041..cae468c0 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/contest/domain/ContestBoard.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/contest/domain/ContestBoard.java @@ -1,21 +1,22 @@ package com.inhabas.api.domain.contest.domain; -import com.inhabas.api.domain.board.domain.NormalBoard; -import com.inhabas.api.domain.board.domain.valueObject.Content; -import com.inhabas.api.domain.board.domain.valueObject.Title; -import com.inhabas.api.domain.contest.domain.valueObject.Association; -import com.inhabas.api.domain.contest.domain.valueObject.Topic; -import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.StudentId; -import lombok.AccessLevel; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; +import java.time.LocalDate; import javax.persistence.Column; import javax.persistence.Embedded; import javax.persistence.Entity; import javax.persistence.Table; -import java.time.LocalDate; + +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import com.inhabas.api.domain.board.domain.NormalBoard; +import com.inhabas.api.domain.board.domain.valueObject.Content; +import com.inhabas.api.domain.board.domain.valueObject.Title; +import com.inhabas.api.domain.contest.domain.valueObject.Association; +import com.inhabas.api.domain.contest.domain.valueObject.Topic; @Entity @Table(name = "contest_board") @@ -23,47 +24,49 @@ @NoArgsConstructor(access = AccessLevel.PROTECTED) public class ContestBoard extends NormalBoard { - @Embedded - private Topic topic; + @Embedded private Topic topic; - @Embedded - private Association association; + @Embedded private Association association; - @Column - private LocalDate start; + @Column private LocalDate start; - @Column - private LocalDate deadline; + @Column private LocalDate deadline; - /* Getter */ - public String getAssociation(){ - return association.getValue(); - } + /* Getter */ + public String getAssociation() { + return association.getValue(); + } - public String getTopic(){ - return topic.getValue(); - } + public String getTopic() { + return topic.getValue(); + } - /* Constructor */ + /* Constructor */ - @Builder - public ContestBoard(String title, String contents, String association, String topic, LocalDate start, LocalDate deadline){ + @Builder + public ContestBoard( + String title, + String contents, + String association, + String topic, + LocalDate start, + LocalDate deadline) { - this.title = new Title(title); - this.content = new Content(contents); - this.association = new Association(association); - this.topic = new Topic(topic); - this.start = start; - this.deadline = deadline; - } + this.title = new Title(title); + this.content = new Content(contents); + this.association = new Association(association); + this.topic = new Topic(topic); + this.start = start; + this.deadline = deadline; + } -// public void modify(String title, String contents, String association, String topic, -// LocalDate start, LocalDate deadline, StudentId loginMember) { -// -// super.modify(title, contents, loginMember); -// this.association = new Association(association); -// this.topic = new Topic(topic); -// this.start = start; -// this.deadline = deadline; -// } + // public void modify(String title, String contents, String association, String topic, + // LocalDate start, LocalDate deadline, StudentId loginMember) { + // + // super.modify(title, contents, loginMember); + // this.association = new Association(association); + // this.topic = new Topic(topic); + // this.start = start; + // this.deadline = deadline; + // } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/contest/domain/valueObject/Association.java b/resource-server/src/main/java/com/inhabas/api/domain/contest/domain/valueObject/Association.java index d193da36..29181ca5 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/contest/domain/valueObject/Association.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/contest/domain/valueObject/Association.java @@ -1,38 +1,36 @@ package com.inhabas.api.domain.contest.domain.valueObject; +import java.util.Objects; + import javax.persistence.Column; import javax.persistence.Embeddable; import javax.persistence.Transient; -import java.util.Objects; @Embeddable public class Association { - - @Column(name = "association", length = 100, nullable = false) - private String value; - - @Transient - private final int MAX_LENGTH = 100; - - public Association() {} - - public Association(String value) { - if (validate(value)) - this.value = value; - else - throw new IllegalArgumentException(); - } - - private boolean validate(Object value) { - if (Objects.isNull(value)) return false; - if (!(value instanceof String)) return false; - - String o = (String) value; - if (o.isBlank()) return false; - return o.length() < MAX_LENGTH; - } - - public String getValue() { - return value; - } + + @Column(name = "association", length = 100, nullable = false) + private String value; + + @Transient private final int MAX_LENGTH = 100; + + public Association() {} + + public Association(String value) { + if (validate(value)) this.value = value; + else throw new IllegalArgumentException(); + } + + private boolean validate(Object value) { + if (Objects.isNull(value)) return false; + if (!(value instanceof String)) return false; + + String o = (String) value; + if (o.isBlank()) return false; + return o.length() < MAX_LENGTH; + } + + public String getValue() { + return value; + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/contest/domain/valueObject/Topic.java b/resource-server/src/main/java/com/inhabas/api/domain/contest/domain/valueObject/Topic.java index e7fe645d..648378a4 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/contest/domain/valueObject/Topic.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/contest/domain/valueObject/Topic.java @@ -1,37 +1,35 @@ package com.inhabas.api.domain.contest.domain.valueObject; +import java.util.Objects; + import javax.persistence.Column; import javax.persistence.Embeddable; import javax.persistence.Transient; -import java.util.Objects; @Embeddable public class Topic { - @Column(name = "topic", length = 500, nullable = false) - private String value; + @Column(name = "topic", length = 500, nullable = false) + private String value; - @Transient - private final int MAX_LENGTH = 500; + @Transient private final int MAX_LENGTH = 500; - public Topic() { } + public Topic() {} - public Topic(String value){ - if(validate(value)) - this.value = value; - else - throw new IllegalArgumentException(); - } + public Topic(String value) { + if (validate(value)) this.value = value; + else throw new IllegalArgumentException(); + } - private boolean validate(Object value){ - if(Objects.isNull(value)) return false; - if(!(value instanceof String)) return false; + private boolean validate(Object value) { + if (Objects.isNull(value)) return false; + if (!(value instanceof String)) return false; - String o = (String) value; - if (o.isBlank()) return false; - return o.length() < MAX_LENGTH; - } + String o = (String) value; + if (o.isBlank()) return false; + return o.length() < MAX_LENGTH; + } - public String getValue() { - return value; - } + public String getValue() { + return value; + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/contest/dto/DetailContestBoardDto.java b/resource-server/src/main/java/com/inhabas/api/domain/contest/dto/DetailContestBoardDto.java index 75e73d40..6082af3f 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/contest/dto/DetailContestBoardDto.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/contest/dto/DetailContestBoardDto.java @@ -1,32 +1,35 @@ package com.inhabas.api.domain.contest.dto; -import com.fasterxml.jackson.annotation.JsonFormat; +import java.time.LocalDate; +import java.time.LocalDateTime; + import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; -import java.time.LocalDate; -import java.time.LocalDateTime; +import com.fasterxml.jackson.annotation.JsonFormat; @Getter @Builder @AllArgsConstructor public class DetailContestBoardDto { - private Integer id; - private String writerName; - private String title; - private String contents; - private String association; - private String topic; - - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern="yyyy-MM-dd") - private LocalDate start; - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern="yyyy-MM-dd") - private LocalDate deadline; - - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern="yyyy-MM-dd'T'HH:mm:ss") - private LocalDateTime created; - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern="yyyy-MM-dd'T'HH:mm:ss") - private LocalDateTime updated; + private Integer id; + private String writerName; + private String title; + private String contents; + private String association; + private String topic; + + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd") + private LocalDate start; + + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd") + private LocalDate deadline; + + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss") + private LocalDateTime created; + + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss") + private LocalDateTime updated; } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/contest/dto/ListContestBoardDto.java b/resource-server/src/main/java/com/inhabas/api/domain/contest/dto/ListContestBoardDto.java index ad27bf1e..3309804a 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/contest/dto/ListContestBoardDto.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/contest/dto/ListContestBoardDto.java @@ -1,18 +1,21 @@ package com.inhabas.api.domain.contest.dto; -import com.fasterxml.jackson.annotation.JsonFormat; +import java.time.LocalDate; + import lombok.AllArgsConstructor; import lombok.Getter; -import java.time.LocalDate; +import com.fasterxml.jackson.annotation.JsonFormat; @Getter @AllArgsConstructor public class ListContestBoardDto { - private String title; - private String topic; - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern="yyyy-MM-dd") - private LocalDate start; - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern="yyyy-MM-dd") - private LocalDate deadline; + private String title; + private String topic; + + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd") + private LocalDate start; + + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd") + private LocalDate deadline; } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/contest/dto/SaveContestBoardDto.java b/resource-server/src/main/java/com/inhabas/api/domain/contest/dto/SaveContestBoardDto.java index 4637da45..95e5048e 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/contest/dto/SaveContestBoardDto.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/contest/dto/SaveContestBoardDto.java @@ -1,40 +1,42 @@ package com.inhabas.api.domain.contest.dto; +import java.time.LocalDate; + +import javax.validation.constraints.Future; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; -import org.hibernate.validator.constraints.Length; -import javax.validation.constraints.Future; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotNull; -import java.time.LocalDate; +import org.hibernate.validator.constraints.Length; @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) @AllArgsConstructor public class SaveContestBoardDto { - @NotBlank(message = "제목을 입력하세요.") - @Length(max = 100, message = "제목은 최대 100자입니다.") - private String title; + @NotBlank(message = "제목을 입력하세요.") + @Length(max = 100, message = "제목은 최대 100자입니다.") + private String title; - @NotBlank(message = "본문을 입력하세요.") - private String contents; + @NotBlank(message = "본문을 입력하세요.") + private String contents; - @Length(max = 100, message = "100자 이내로 작성해주세요.") - @NotBlank(message = "협회기관을 입력하세요.") - private String association; + @Length(max = 100, message = "100자 이내로 작성해주세요.") + @NotBlank(message = "협회기관을 입력하세요.") + private String association; - @Length(max = 500, message = "500자 이내로 작성해주세요.") - @NotBlank(message = "공모전 주제를 입력하세요.") - private String topic; + @Length(max = 500, message = "500자 이내로 작성해주세요.") + @NotBlank(message = "공모전 주제를 입력하세요.") + private String topic; - @NotNull(message = "공모전 모집 시작일을 등록해주세요.") - private LocalDate start; + @NotNull(message = "공모전 모집 시작일을 등록해주세요.") + private LocalDate start; - @NotNull(message = "공모전 모집 마감일을 등록해주세요.") - @Future (message = "이미 모집기간이 종료된 공모전은 등록할 수 없습니다.") - private LocalDate deadline; + @NotNull(message = "공모전 모집 마감일을 등록해주세요.") + @Future(message = "이미 모집기간이 종료된 공모전은 등록할 수 없습니다.") + private LocalDate deadline; } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/contest/dto/UpdateContestBoardDto.java b/resource-server/src/main/java/com/inhabas/api/domain/contest/dto/UpdateContestBoardDto.java index e4f02f62..287362b1 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/contest/dto/UpdateContestBoardDto.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/contest/dto/UpdateContestBoardDto.java @@ -1,43 +1,44 @@ package com.inhabas.api.domain.contest.dto; +import java.time.LocalDate; + +import javax.validation.constraints.Future; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; -import org.hibernate.validator.constraints.Length; -import javax.validation.constraints.Future; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotNull; -import java.time.LocalDate; +import org.hibernate.validator.constraints.Length; @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) @AllArgsConstructor public class UpdateContestBoardDto { - @NotNull(message = "수정할 게시글을 선택해주세요.") - private Integer id; + @NotNull(message = "수정할 게시글을 선택해주세요.") + private Integer id; - @NotBlank(message = "제목을 입력하세요.") - @Length(max = 100, message = "제목은 최대 100자입니다.") - private String title; + @NotBlank(message = "제목을 입력하세요.") + @Length(max = 100, message = "제목은 최대 100자입니다.") + private String title; - @NotBlank(message = "본문을 입력하세요.") - private String contents; + @NotBlank(message = "본문을 입력하세요.") + private String contents; - @Length(max = 100, message = "100자 이내로 작성해주세요.") - @NotBlank(message = "협회기관을 입력하세요.") - private String association; + @Length(max = 100, message = "100자 이내로 작성해주세요.") + @NotBlank(message = "협회기관을 입력하세요.") + private String association; - @Length(max = 500, message = "500자 이내로 작성해주세요.") - @NotBlank(message = "공모전 주제를 입력하세요.") - private String topic; + @Length(max = 500, message = "500자 이내로 작성해주세요.") + @NotBlank(message = "공모전 주제를 입력하세요.") + private String topic; - @NotNull(message = "공모전 모집 시작일을 등록해주세요.") - private LocalDate start; + @NotNull(message = "공모전 모집 시작일을 등록해주세요.") + private LocalDate start; - @NotNull(message = "공모전 모집 마감일을 등록해주세요.") - @Future(message = "이미 모집기간이 종료된 공모전은 등록할 수 없습니다.") - private LocalDate deadline; + @NotNull(message = "공모전 모집 마감일을 등록해주세요.") + @Future(message = "이미 모집기간이 종료된 공모전은 등록할 수 없습니다.") + private LocalDate deadline; } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/contest/repository/ContestBoardRepository.java b/resource-server/src/main/java/com/inhabas/api/domain/contest/repository/ContestBoardRepository.java index 4067aede..cf482e5e 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/contest/repository/ContestBoardRepository.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/contest/repository/ContestBoardRepository.java @@ -1,7 +1,8 @@ package com.inhabas.api.domain.contest.repository; -import com.inhabas.api.domain.contest.domain.ContestBoard; import org.springframework.data.jpa.repository.JpaRepository; -public interface ContestBoardRepository extends JpaRepository, ContestBoardRepositoryCustom{ -} \ No newline at end of file +import com.inhabas.api.domain.contest.domain.ContestBoard; + +public interface ContestBoardRepository + extends JpaRepository, ContestBoardRepositoryCustom {} diff --git a/resource-server/src/main/java/com/inhabas/api/domain/contest/repository/ContestBoardRepositoryCustom.java b/resource-server/src/main/java/com/inhabas/api/domain/contest/repository/ContestBoardRepositoryCustom.java index e5939c0c..50a25b7b 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/contest/repository/ContestBoardRepositoryCustom.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/contest/repository/ContestBoardRepositoryCustom.java @@ -1,17 +1,9 @@ package com.inhabas.api.domain.contest.repository; -import com.inhabas.api.domain.menu.domain.valueObject.MenuId; -import com.inhabas.api.domain.contest.dto.DetailContestBoardDto; -import com.inhabas.api.domain.contest.dto.ListContestBoardDto; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; - -import java.util.Optional; - public interface ContestBoardRepositoryCustom { -// Optional findDtoById(Integer id); -// -// Page findAllByMenuId(MenuId menuId, Pageable pageable); + // Optional findDtoById(Integer id); + // + // Page findAllByMenuId(MenuId menuId, Pageable pageable); } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/contest/repository/ContestBoardRepositoryImpl.java b/resource-server/src/main/java/com/inhabas/api/domain/contest/repository/ContestBoardRepositoryImpl.java index ccbbbaec..5a7a81f5 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/contest/repository/ContestBoardRepositoryImpl.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/contest/repository/ContestBoardRepositoryImpl.java @@ -1,106 +1,100 @@ package com.inhabas.api.domain.contest.repository; - import static com.inhabas.api.domain.contest.domain.QContestBoard.contestBoard; -import static com.inhabas.api.auth.domain.oauth2.member.domain.entity.QMember.member; -import com.inhabas.api.domain.contest.dto.DetailContestBoardDto; -import com.inhabas.api.domain.contest.dto.ListContestBoardDto; -import com.inhabas.api.domain.menu.domain.valueObject.MenuId; -import com.querydsl.core.types.Order; -import com.querydsl.core.types.OrderSpecifier; -import com.querydsl.core.types.Path; -import com.querydsl.core.types.Projections; -import com.querydsl.core.types.dsl.BooleanExpression; -import com.querydsl.core.types.dsl.Expressions; -import com.querydsl.jpa.impl.JPAQueryFactory; + import java.util.ArrayList; import java.util.List; -import java.util.Optional; + import lombok.RequiredArgsConstructor; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageImpl; + import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; +import com.querydsl.core.types.Order; +import com.querydsl.core.types.OrderSpecifier; +import com.querydsl.core.types.Path; +import com.querydsl.core.types.dsl.Expressions; +import com.querydsl.jpa.impl.JPAQueryFactory; + @RequiredArgsConstructor public class ContestBoardRepositoryImpl implements ContestBoardRepositoryCustom { - private final JPAQueryFactory queryFactory; + private final JPAQueryFactory queryFactory; -// @Override -// public Optional findDtoById(Integer id) { -// return Optional.ofNullable(queryFactory -// .select(Projections.constructor(DetailContestBoardDto.class, -// Expressions.asNumber(id).as("id"), -// member.name.value, -// contestBoard.title.value, -// contestBoard.content.value, -// contestBoard.association.value, -// contestBoard.topic.value, -// contestBoard.start, -// contestBoard.deadline, -// contestBoard.dateCreated, -// contestBoard.dateUpdated -// )) -// .from(contestBoard) -// .innerJoin(member).on(contestBoard.writerId.eq(member.studentId)) -// .limit(1) -// .fetchOne()); -// } + // @Override + // public Optional findDtoById(Integer id) { + // return Optional.ofNullable(queryFactory + // .select(Projections.constructor(DetailContestBoardDto.class, + // Expressions.asNumber(id).as("id"), + // member.name.value, + // contestBoard.title.value, + // contestBoard.content.value, + // contestBoard.association.value, + // contestBoard.topic.value, + // contestBoard.start, + // contestBoard.deadline, + // contestBoard.dateCreated, + // contestBoard.dateUpdated + // )) + // .from(contestBoard) + // .innerJoin(member).on(contestBoard.writerId.eq(member.studentId)) + // .limit(1) + // .fetchOne()); + // } - // 보류 - @SuppressWarnings({"unchecked"}) - public static OrderSpecifier getSortedColumn(Order order, Path parent, String fieldName){ - Path fieldPath = Expressions.path(Object.class, parent, fieldName); - return new OrderSpecifier(order, fieldPath); - } + // 보류 + @SuppressWarnings({"unchecked"}) + public static OrderSpecifier getSortedColumn(Order order, Path parent, String fieldName) { + Path fieldPath = Expressions.path(Object.class, parent, fieldName); + return new OrderSpecifier(order, fieldPath); + } - @SuppressWarnings({"unchecked"}) - private List getAllOrderSpecifiers(Pageable pageable) { - List ORDERS = new ArrayList<>(); - if (pageable.getSort() != null){ - for (Sort.Order order : pageable.getSort()){ - Order direction = order.getDirection().isAscending() - ? Order.ASC : Order.DESC; - switch(order.getProperty()){ - case "id": - OrderSpecifier orderId = getSortedColumn(direction, contestBoard, "id"); - ORDERS.add(orderId); - break; - case "deadline": - OrderSpecifier orderDeadline = getSortedColumn(direction, contestBoard, "deadline"); - ORDERS.add(orderDeadline); - break; - default: - break; - } - } - } else { - OrderSpecifier orderDeadline = getSortedColumn(Order.DESC, contestBoard, "deadline"); + @SuppressWarnings({"unchecked"}) + private List getAllOrderSpecifiers(Pageable pageable) { + List ORDERS = new ArrayList<>(); + if (pageable.getSort() != null) { + for (Sort.Order order : pageable.getSort()) { + Order direction = order.getDirection().isAscending() ? Order.ASC : Order.DESC; + switch (order.getProperty()) { + case "id": + OrderSpecifier orderId = getSortedColumn(direction, contestBoard, "id"); + ORDERS.add(orderId); + break; + case "deadline": + OrderSpecifier orderDeadline = getSortedColumn(direction, contestBoard, "deadline"); ORDERS.add(orderDeadline); + break; + default: + break; } - return ORDERS; + } + } else { + OrderSpecifier orderDeadline = getSortedColumn(Order.DESC, contestBoard, "deadline"); + ORDERS.add(orderDeadline); } + return ORDERS; + } -// @Override -// public Page findAllByMenuId(MenuId menuId, Pageable pageable) { -// List ORDERS = getAllOrderSpecifiers(pageable); -// List results = queryFactory.select(Projections.constructor(ListContestBoardDto.class, -// contestBoard.title.value, -// contestBoard.topic.value, -// contestBoard.start, -// contestBoard.deadline)) -// .from(contestBoard) -// .where(menuEq(menuId)) -// .offset(pageable.getOffset()) -// .limit(pageable.getPageSize()) -// .orderBy(ORDERS.stream().toArray(OrderSpecifier[]::new)) -// .fetch(); -// return new PageImpl<>(results, pageable, results.size()); -// } + // @Override + // public Page findAllByMenuId(MenuId menuId, Pageable pageable) { + // List ORDERS = getAllOrderSpecifiers(pageable); + // List results = + // queryFactory.select(Projections.constructor(ListContestBoardDto.class, + // contestBoard.title.value, + // contestBoard.topic.value, + // contestBoard.start, + // contestBoard.deadline)) + // .from(contestBoard) + // .where(menuEq(menuId)) + // .offset(pageable.getOffset()) + // .limit(pageable.getPageSize()) + // .orderBy(ORDERS.stream().toArray(OrderSpecifier[]::new)) + // .fetch(); + // return new PageImpl<>(results, pageable, results.size()); + // } -// private BooleanExpression menuEq(MenuId menuId) { -// return contestBoard.menuId.eq(menuId); -// } + // private BooleanExpression menuEq(MenuId menuId) { + // return contestBoard.menuId.eq(menuId); + // } -} \ No newline at end of file +} diff --git a/resource-server/src/main/java/com/inhabas/api/domain/contest/usecase/ContestBoardService.java b/resource-server/src/main/java/com/inhabas/api/domain/contest/usecase/ContestBoardService.java index 6865db78..9549007b 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/contest/usecase/ContestBoardService.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/contest/usecase/ContestBoardService.java @@ -1,23 +1,14 @@ package com.inhabas.api.domain.contest.usecase; -import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.StudentId; -import com.inhabas.api.domain.menu.domain.valueObject.MenuId; -import com.inhabas.api.domain.contest.dto.DetailContestBoardDto; -import com.inhabas.api.domain.contest.dto.ListContestBoardDto; -import com.inhabas.api.domain.contest.dto.SaveContestBoardDto; -import com.inhabas.api.domain.contest.dto.UpdateContestBoardDto; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; - public interface ContestBoardService { -// Integer write(StudentId studentId, SaveContestBoardDto dto); -// -// Integer update(StudentId studentId, UpdateContestBoardDto dto); -// -// void delete(StudentId studentId, Integer id); -// -// DetailContestBoardDto getBoard(Integer id); -// -// Page getBoardList(MenuId menuId, Pageable pageable); + // Integer write(StudentId studentId, SaveContestBoardDto dto); + // + // Integer update(StudentId studentId, UpdateContestBoardDto dto); + // + // void delete(StudentId studentId, Integer id); + // + // DetailContestBoardDto getBoard(Integer id); + // + // Page getBoardList(MenuId menuId, Pageable pageable); } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/contest/usecase/ContestBoardServiceImpl.java b/resource-server/src/main/java/com/inhabas/api/domain/contest/usecase/ContestBoardServiceImpl.java index 260fe7a4..b153a452 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/contest/usecase/ContestBoardServiceImpl.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/contest/usecase/ContestBoardServiceImpl.java @@ -1,73 +1,75 @@ package com.inhabas.api.domain.contest.usecase; -import com.inhabas.api.domain.contest.repository.ContestBoardRepository; +import javax.transaction.Transactional; + import lombok.RequiredArgsConstructor; + import org.springframework.stereotype.Service; -import javax.transaction.Transactional; +import com.inhabas.api.domain.contest.repository.ContestBoardRepository; @Service @Transactional @RequiredArgsConstructor public class ContestBoardServiceImpl implements ContestBoardService { - private final ContestBoardRepository contestBoardRepository; + private final ContestBoardRepository contestBoardRepository; -// @Override -// public Integer write(StudentId studentId, SaveContestBoardDto dto) { -// -// ContestBoard contestBoard = ContestBoard.builder() -// .title(dto.getTitle()) -// .contents(dto.getContent()) -// .association(dto.getAssociation()) -// .topic(dto.getTopic()) -// .start(dto.getStart()) -// .deadline(dto.getDeadline()) -// .build() -// .writtenBy(studentId); -// return contestBoardRepository.save(contestBoard).getId(); -// } -// -// @Override -// public Integer update(StudentId studentId, UpdateContestBoardDto dto) { -// -// ContestBoard contestBoard = contestBoardRepository.findById(dto.getId()) -// .orElseThrow(BoardNotFoundException::new); -// -// contestBoard.modify( -// dto.getTitle(), -// dto.getContent(), -// dto.getAssociation(), -// dto.getTopic(), -// dto.getStart(), -// dto.getDeadline(), -// studentId); -// -// return contestBoardRepository.save(contestBoard).getId(); -// } -// -// -// @Override -// public void delete(StudentId studentId, Integer boardId) { -// -// ContestBoard contestBoard = contestBoardRepository.findById(boardId) -// .orElseThrow(BoardNotFoundException::new); -// -// if (contestBoard.cannotModifiableBy(studentId)) { -// throw new OnlyWriterModifiableException("삭제 권한이 없습니다."); -// } -// -// contestBoardRepository.deleteById(boardId); -// } -// -// @Override -// public DetailContestBoardDto getBoard(Integer id) { -// return contestBoardRepository.findDtoById(id) -// .orElseThrow(BoardNotFoundException::new); -// } -// -// @Override -// public Page getBoardList(MenuId menuId, Pageable pageable) { -// return contestBoardRepository.findAllByMenuId(menuId, pageable); -// } + // @Override + // public Integer write(StudentId studentId, SaveContestBoardDto dto) { + // + // ContestBoard contestBoard = ContestBoard.builder() + // .title(dto.getTitle()) + // .contents(dto.getContent()) + // .association(dto.getAssociation()) + // .topic(dto.getTopic()) + // .start(dto.getStart()) + // .deadline(dto.getDeadline()) + // .build() + // .writtenBy(studentId); + // return contestBoardRepository.save(contestBoard).getId(); + // } + // + // @Override + // public Integer update(StudentId studentId, UpdateContestBoardDto dto) { + // + // ContestBoard contestBoard = contestBoardRepository.findById(dto.getId()) + // .orElseThrow(BoardNotFoundException::new); + // + // contestBoard.modify( + // dto.getTitle(), + // dto.getContent(), + // dto.getAssociation(), + // dto.getTopic(), + // dto.getStart(), + // dto.getDeadline(), + // studentId); + // + // return contestBoardRepository.save(contestBoard).getId(); + // } + // + // + // @Override + // public void delete(StudentId studentId, Integer boardId) { + // + // ContestBoard contestBoard = contestBoardRepository.findById(boardId) + // .orElseThrow(BoardNotFoundException::new); + // + // if (contestBoard.cannotModifiableBy(studentId)) { + // throw new OnlyWriterModifiableException("삭제 권한이 없습니다."); + // } + // + // contestBoardRepository.deleteById(boardId); + // } + // + // @Override + // public DetailContestBoardDto getBoard(Integer id) { + // return contestBoardRepository.findDtoById(id) + // .orElseThrow(BoardNotFoundException::new); + // } + // + // @Override + // public Page getBoardList(MenuId menuId, Pageable pageable) { + // return contestBoardRepository.findAllByMenuId(menuId, pageable); + // } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/file/domain/BaseFile.java b/resource-server/src/main/java/com/inhabas/api/domain/file/domain/BaseFile.java index 289ee135..0717712b 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/file/domain/BaseFile.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/file/domain/BaseFile.java @@ -1,16 +1,19 @@ package com.inhabas.api.domain.file.domain; -import com.inhabas.api.domain.file.domain.valueObject.FileName; -import com.inhabas.api.domain.file.domain.valueObject.FileUrl; +import java.time.LocalDateTime; +import java.util.Objects; + +import javax.persistence.*; + import lombok.AccessLevel; import lombok.Getter; import lombok.NoArgsConstructor; + import org.springframework.data.annotation.CreatedDate; import org.springframework.data.jpa.domain.support.AuditingEntityListener; -import javax.persistence.*; -import java.time.LocalDateTime; -import java.util.Objects; +import com.inhabas.api.domain.file.domain.valueObject.FileName; +import com.inhabas.api.domain.file.domain.valueObject.FileUrl; @Getter @MappedSuperclass @@ -18,47 +21,49 @@ @EntityListeners(AuditingEntityListener.class) public class BaseFile { - @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - protected Long id; - - @Embedded - protected FileName name; + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + protected Long id; - @Embedded - protected FileUrl url; + @Embedded protected FileName name; - @CreatedDate - @Column(nullable = false, updatable = false, insertable = false, columnDefinition = "DATETIME(0) DEFAULT CURRENT_TIMESTAMP") - protected LocalDateTime dateCreated; + @Embedded protected FileUrl url; - public BaseFile(String name, String url) { - this.name = new FileName(name); - this.url = new FileUrl(url); - this.dateCreated = LocalDateTime.now(); - } + @CreatedDate + @Column( + nullable = false, + updatable = false, + insertable = false, + columnDefinition = "DATETIME(0) DEFAULT CURRENT_TIMESTAMP") + protected LocalDateTime dateCreated; - public String getName() { - return this.name.getValue(); - } + public BaseFile(String name, String url) { + this.name = new FileName(name); + this.url = new FileUrl(url); + this.dateCreated = LocalDateTime.now(); + } - public String getUrl() { - return this.url.getValue(); - } + public String getName() { + return this.name.getValue(); + } - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(BaseFile.class.isAssignableFrom(o.getClass()))) return false; - BaseFile baseFile = (BaseFile) o; - return getId().equals(baseFile.getId()) - && getName().equals(baseFile.getName()) - && Objects.equals(getUrl(), baseFile.getUrl()) - && getDateCreated().equals(baseFile.getDateCreated()); - } + public String getUrl() { + return this.url.getValue(); + } - @Override - public int hashCode() { - return Objects.hash(getId(), getName(), getUrl(), getDateCreated()); - } + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(BaseFile.class.isAssignableFrom(o.getClass()))) return false; + BaseFile baseFile = (BaseFile) o; + return getId().equals(baseFile.getId()) + && getName().equals(baseFile.getName()) + && Objects.equals(getUrl(), baseFile.getUrl()) + && getDateCreated().equals(baseFile.getDateCreated()); + } + @Override + public int hashCode() { + return Objects.hash(getId(), getName(), getUrl(), getDateCreated()); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/file/domain/BoardFile.java b/resource-server/src/main/java/com/inhabas/api/domain/file/domain/BoardFile.java index 4c3d0a7b..65c71823 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/file/domain/BoardFile.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/file/domain/BoardFile.java @@ -1,52 +1,56 @@ package com.inhabas.api.domain.file.domain; -import com.inhabas.api.domain.board.domain.BaseBoard; +import java.util.Objects; + +import javax.persistence.*; + import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; + import org.springframework.data.jpa.domain.support.AuditingEntityListener; -import javax.persistence.*; -import java.util.Objects; +import com.inhabas.api.domain.board.domain.BaseBoard; -@Entity @Getter +@Entity +@Getter @Table(name = "BOARD_FILE") @EntityListeners(AuditingEntityListener.class) @NoArgsConstructor(access = AccessLevel.PROTECTED) public class BoardFile extends BaseFile { - @ManyToOne(fetch = FetchType.LAZY, optional = false) - @JoinColumn(name = "BOARD_ID", foreignKey = @ForeignKey(name = "FK_FILE_OF_BOARD")) - private BaseBoard board; + @ManyToOne(fetch = FetchType.LAZY, optional = false) + @JoinColumn(name = "BOARD_ID", foreignKey = @ForeignKey(name = "FK_FILE_OF_BOARD")) + private BaseBoard board; - // boardFile 과 baseBoard 의 연관관계 편의 메소드 - - @Builder - public BoardFile(String name, String url, BaseBoard board) { - super(name, url); - this.board = board; - } + // boardFile 과 baseBoard 의 연관관계 편의 메소드 - public void toBoard(T newParentBoard) { - // 기존의 file-board 연관관계를 끊는다. - if (Objects.nonNull(this.board)) { - this.board.getFiles().remove(this); - } - this.board = newParentBoard; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(BoardFile.class.isAssignableFrom(o.getClass()))) return false; - if (!super.equals(o)) return false; - BoardFile boardFile = (BoardFile) o; - return getBoard().getId().equals(boardFile.getBoard().getId()); - } + @Builder + public BoardFile(String name, String url, BaseBoard board) { + super(name, url); + this.board = board; + } - @Override - public int hashCode() { - return Objects.hash(super.hashCode(), getBoard()); + public void toBoard(T newParentBoard) { + // 기존의 file-board 연관관계를 끊는다. + if (Objects.nonNull(this.board)) { + this.board.getFiles().remove(this); } + this.board = newParentBoard; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(BoardFile.class.isAssignableFrom(o.getClass()))) return false; + if (!super.equals(o)) return false; + BoardFile boardFile = (BoardFile) o; + return getBoard().getId().equals(boardFile.getBoard().getId()); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), getBoard()); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/file/domain/valueObject/FileName.java b/resource-server/src/main/java/com/inhabas/api/domain/file/domain/valueObject/FileName.java index 452a0bfd..179524b1 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/file/domain/valueObject/FileName.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/file/domain/valueObject/FileName.java @@ -1,46 +1,40 @@ package com.inhabas.api.domain.file.domain.valueObject; -import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; +import static com.inhabas.api.global.util.FileUtil.isValidFileName; + +import java.util.Objects; import javax.persistence.Column; import javax.persistence.Embeddable; import javax.persistence.Transient; -import java.util.Objects; - -import static com.inhabas.api.global.util.FileUtil.isValidFileName; - +import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; @Embeddable public class FileName { - @Column(name = "NAME") - private String value; - - @Transient - private final int MAX_LENGTH = 300; - + @Column(name = "NAME") + private String value; - public FileName(String value) { - if (validate(value)) - this.value = value; - else - throw new InvalidInputException(); - } + @Transient private final int MAX_LENGTH = 300; - public FileName() {} + public FileName(String value) { + if (validate(value)) this.value = value; + else throw new InvalidInputException(); + } - public String getValue() { - return this.value; - } + public FileName() {} - private boolean validate(Object value) { - if (Objects.isNull(value)) return false; - if (!(value instanceof String)) return false; + public String getValue() { + return this.value; + } - String o = (String) value; - if (o.isBlank()) return false; - return o.length() < MAX_LENGTH && isValidFileName(o); - } + private boolean validate(Object value) { + if (Objects.isNull(value)) return false; + if (!(value instanceof String)) return false; + String o = (String) value; + if (o.isBlank()) return false; + return o.length() < MAX_LENGTH && isValidFileName(o); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/file/domain/valueObject/FileUrl.java b/resource-server/src/main/java/com/inhabas/api/domain/file/domain/valueObject/FileUrl.java index 6faf170b..296e9f5c 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/file/domain/valueObject/FileUrl.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/file/domain/valueObject/FileUrl.java @@ -1,41 +1,38 @@ package com.inhabas.api.domain.file.domain.valueObject; -import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; +import java.util.Objects; import javax.persistence.Column; import javax.persistence.Embeddable; import javax.persistence.Transient; -import java.util.Objects; + +import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; @Embeddable public class FileUrl { - @Column(name = "URL") - private String value; - - @Transient - private final int MAX_LENGTH = 1000; + @Column(name = "URL") + private String value; - public FileUrl() {} + @Transient private final int MAX_LENGTH = 1000; - public FileUrl(String value) { - if (validate(value)) - this.value = value; - else - throw new InvalidInputException(); - } + public FileUrl() {} - private boolean validate(Object value) { - if (Objects.isNull(value)) return false; - if (!(value instanceof String)) return false; + public FileUrl(String value) { + if (validate(value)) this.value = value; + else throw new InvalidInputException(); + } - String o = (String) value; - if (o.isBlank()) return false; - return o.length() < MAX_LENGTH; - } + private boolean validate(Object value) { + if (Objects.isNull(value)) return false; + if (!(value instanceof String)) return false; - public String getValue() { - return this.value; - } + String o = (String) value; + if (o.isBlank()) return false; + return o.length() < MAX_LENGTH; + } + public String getValue() { + return this.value; + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/file/dto/FileDownloadDto.java b/resource-server/src/main/java/com/inhabas/api/domain/file/dto/FileDownloadDto.java index 31dd744c..7c5cbf7b 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/file/dto/FileDownloadDto.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/file/dto/FileDownloadDto.java @@ -1,25 +1,22 @@ package com.inhabas.api.domain.file.dto; +import javax.validation.constraints.NotBlank; + import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; -import javax.validation.constraints.NotBlank; - @Getter @NoArgsConstructor public class FileDownloadDto { - @NotBlank - private String name; - - @NotBlank - private String url; + @NotBlank private String name; - @Builder - public FileDownloadDto(String name, String url) { - this.name = name; - this.url = url; - } + @NotBlank private String url; + @Builder + public FileDownloadDto(String name, String url) { + this.name = name; + this.url = url; + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/file/dto/FileUploadDto.java b/resource-server/src/main/java/com/inhabas/api/domain/file/dto/FileUploadDto.java index ab4eea65..5079b384 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/file/dto/FileUploadDto.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/file/dto/FileUploadDto.java @@ -3,21 +3,21 @@ import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; + import org.springframework.web.multipart.MultipartFile; @Getter @NoArgsConstructor public class FileUploadDto { - private String name; - private String url; - private MultipartFile multipartFile; - - @Builder - public FileUploadDto(String url, String name, MultipartFile multipartFile) { - this.url = url; - this.name = name; - this.multipartFile = multipartFile; - } + private String name; + private String url; + private MultipartFile multipartFile; + @Builder + public FileUploadDto(String url, String name, MultipartFile multipartFile) { + this.url = url; + this.name = name; + this.multipartFile = multipartFile; + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/file/repository/BoardFileRepository.java b/resource-server/src/main/java/com/inhabas/api/domain/file/repository/BoardFileRepository.java index b1fc2694..79fd365c 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/file/repository/BoardFileRepository.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/file/repository/BoardFileRepository.java @@ -1,7 +1,7 @@ package com.inhabas.api.domain.file.repository; -import com.inhabas.api.domain.file.domain.BoardFile; import org.springframework.data.jpa.repository.JpaRepository; -public interface BoardFileRepository extends JpaRepository { -} +import com.inhabas.api.domain.file.domain.BoardFile; + +public interface BoardFileRepository extends JpaRepository {} diff --git a/resource-server/src/main/java/com/inhabas/api/domain/lecture/LectureCannotModifiableException.java b/resource-server/src/main/java/com/inhabas/api/domain/lecture/LectureCannotModifiableException.java index 980673b6..8f8e2eec 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/lecture/LectureCannotModifiableException.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/lecture/LectureCannotModifiableException.java @@ -4,11 +4,11 @@ public class LectureCannotModifiableException extends AccessDeniedException { - public LectureCannotModifiableException() { - super("다른 담당자의 강의를 수정할 수 없습니다."); - } + public LectureCannotModifiableException() { + super("다른 담당자의 강의를 수정할 수 없습니다."); + } - public LectureCannotModifiableException(String msg) { - super(msg); - } + public LectureCannotModifiableException(String msg) { + super(msg); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/lecture/domain/Lecture.java b/resource-server/src/main/java/com/inhabas/api/domain/lecture/domain/Lecture.java index a9111328..c8e449ae 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/lecture/domain/Lecture.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/lecture/domain/Lecture.java @@ -1,133 +1,158 @@ package com.inhabas.api.domain.lecture.domain; +import java.time.LocalDateTime; + +import javax.persistence.*; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +import lombok.AccessLevel; +import lombok.Builder; +import lombok.NoArgsConstructor; + +import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.StudentId; import com.inhabas.api.domain.BaseEntity; import com.inhabas.api.domain.lecture.LectureCannotModifiableException; import com.inhabas.api.domain.lecture.domain.converter.LectureStatusConverter; import com.inhabas.api.domain.lecture.domain.valueObject.LectureStatus; -import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.StudentId; -import lombok.AccessLevel; -import lombok.Builder; -import lombok.NoArgsConstructor; import org.hibernate.validator.constraints.Length; -import javax.persistence.*; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotNull; -import java.time.LocalDateTime; - @Entity @Table(name = "lecture") @NoArgsConstructor(access = AccessLevel.PROTECTED) public class Lecture extends BaseEntity { - @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - private Integer id; - - @NotBlank @Length(max = 100) - private String title; - - @Embedded - @AttributeOverride(name = "id", column = @Column(name = "chief", nullable = false, updatable = false)) - private StudentId chief; - - @Convert(converter = LectureStatusConverter.class) - @NotNull - private LectureStatus status; - - @NotNull - private LocalDateTime applyDeadline; - - @NotBlank @Length(max = 20) - private String daysOfWeek; - - @NotNull @Length(max = 300) - private String place; - - @NotNull @Length(max = 300) - private String introduction; - - @NotNull @Length(max = 16777215) - @Column(columnDefinition = "MEDIUMTEXT", nullable = false) - private String curriculumDetails; - - private int participantsLimits; - - @Column(columnDefinition = "TINYINT", nullable = false) - private Integer method; - - @Length(max = 200) - private String rejectReason; - - @Column(columnDefinition = "TINYINT", nullable = false) - private Boolean paid; - - @Builder - public Lecture(String title, StudentId chief, LocalDateTime applyDeadline, String daysOfWeek, String place, String introduction, String curriculumDetails, int participantsLimits, Integer method) { - this.title = title; - this.chief = chief; - this.status = LectureStatus.WAITING; - this.applyDeadline = applyDeadline; - this.daysOfWeek = daysOfWeek; - this.place = place; - this.introduction = introduction; - this.curriculumDetails = curriculumDetails; - this.participantsLimits = participantsLimits; - this.method = method; - this.rejectReason = null; - this.paid = false; - } - - public void update(StudentId studentId, String title, LocalDateTime applyDeadline, String daysOfWeek, String place, String introduction, String curriculumDetails, int participantsLimits, Integer method) { - - if (this.id == null) - throw new EntityNotFoundException("생성되지 않은 엔티티는 수정할 수 없습니다."); - - if (notModifiableBy(studentId)) - throw new LectureCannotModifiableException(); - - this.title = title; - this.applyDeadline = applyDeadline; - this.daysOfWeek = daysOfWeek; - this.place = place; - this.introduction = introduction; - this.curriculumDetails = curriculumDetails; - this.participantsLimits = participantsLimits; - this.method = method; - } - - public boolean notModifiableBy(StudentId studentId) { - return !this.chief.equals(studentId); - } - - public boolean isHeldBy(StudentId studentId) { - return this.chief.equals(studentId); - } - - /** - * 개설 신청된 강의를 승인 또는 거절하는 함수 - * @param status {@code LectureStatus.PROGRESSING}, {@code LectureStatus.DENIED} 둘 중 하나만 가능 - * @param rejectReason null 이어도 된다. - */ - public void approveOrDeny(LectureStatus status, String rejectReason) { - - if (status == null) - throw new IllegalArgumentException("status 값은 null 일 수 없습니다."); - else if (status == LectureStatus.TERMINATED) - throw new IllegalArgumentException("강제로 강의를 종료시킬 수 없습니다."); - else if (status == LectureStatus.WAITING) - throw new IllegalArgumentException("강의를 대기 상태롤 돌릴 수 없습니다."); - - this.status = status; - this.rejectReason = rejectReason; - } - - /** - * 이미 진행된 강의는 삭제할 수 없다. - * @return 승인 대기 상태 또는 거절 상태라면 true - */ - public boolean canBeDeleted() { - - return status == LectureStatus.WAITING || status == LectureStatus.DENIED; - } - + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer id; + + @NotBlank + @Length(max = 100) + private String title; + + @Embedded + @AttributeOverride( + name = "id", + column = @Column(name = "chief", nullable = false, updatable = false)) + private StudentId chief; + + @Convert(converter = LectureStatusConverter.class) + @NotNull + private LectureStatus status; + + @NotNull private LocalDateTime applyDeadline; + + @NotBlank + @Length(max = 20) + private String daysOfWeek; + + @NotNull + @Length(max = 300) + private String place; + + @NotNull + @Length(max = 300) + private String introduction; + + @NotNull + @Length(max = 16777215) + @Column(columnDefinition = "MEDIUMTEXT", nullable = false) + private String curriculumDetails; + + private int participantsLimits; + + @Column(columnDefinition = "TINYINT", nullable = false) + private Integer method; + + @Length(max = 200) + private String rejectReason; + + @Column(columnDefinition = "TINYINT", nullable = false) + private Boolean paid; + + @Builder + public Lecture( + String title, + StudentId chief, + LocalDateTime applyDeadline, + String daysOfWeek, + String place, + String introduction, + String curriculumDetails, + int participantsLimits, + Integer method) { + this.title = title; + this.chief = chief; + this.status = LectureStatus.WAITING; + this.applyDeadline = applyDeadline; + this.daysOfWeek = daysOfWeek; + this.place = place; + this.introduction = introduction; + this.curriculumDetails = curriculumDetails; + this.participantsLimits = participantsLimits; + this.method = method; + this.rejectReason = null; + this.paid = false; + } + + public void update( + StudentId studentId, + String title, + LocalDateTime applyDeadline, + String daysOfWeek, + String place, + String introduction, + String curriculumDetails, + int participantsLimits, + Integer method) { + + if (this.id == null) throw new EntityNotFoundException("생성되지 않은 엔티티는 수정할 수 없습니다."); + + if (notModifiableBy(studentId)) throw new LectureCannotModifiableException(); + + this.title = title; + this.applyDeadline = applyDeadline; + this.daysOfWeek = daysOfWeek; + this.place = place; + this.introduction = introduction; + this.curriculumDetails = curriculumDetails; + this.participantsLimits = participantsLimits; + this.method = method; + } + + public boolean notModifiableBy(StudentId studentId) { + return !this.chief.equals(studentId); + } + + public boolean isHeldBy(StudentId studentId) { + return this.chief.equals(studentId); + } + + /** + * 개설 신청된 강의를 승인 또는 거절하는 함수 + * + * @param status {@code LectureStatus.PROGRESSING}, {@code LectureStatus.DENIED} 둘 중 하나만 가능 + * @param rejectReason null 이어도 된다. + */ + public void approveOrDeny(LectureStatus status, String rejectReason) { + + if (status == null) throw new IllegalArgumentException("status 값은 null 일 수 없습니다."); + else if (status == LectureStatus.TERMINATED) + throw new IllegalArgumentException("강제로 강의를 종료시킬 수 없습니다."); + else if (status == LectureStatus.WAITING) + throw new IllegalArgumentException("강의를 대기 상태롤 돌릴 수 없습니다."); + + this.status = status; + this.rejectReason = rejectReason; + } + + /** + * 이미 진행된 강의는 삭제할 수 없다. + * + * @return 승인 대기 상태 또는 거절 상태라면 true + */ + public boolean canBeDeleted() { + + return status == LectureStatus.WAITING || status == LectureStatus.DENIED; + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/lecture/domain/Student.java b/resource-server/src/main/java/com/inhabas/api/domain/lecture/domain/Student.java index 4e464db3..ce7ccdcf 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/lecture/domain/Student.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/lecture/domain/Student.java @@ -1,63 +1,72 @@ package com.inhabas.api.domain.lecture.domain; -import com.inhabas.api.domain.BaseEntity; -import com.inhabas.api.domain.lecture.domain.converter.StudentStatusConverter; -import com.inhabas.api.domain.lecture.domain.valueObject.StudentStatus; -import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.StudentId; +import javax.persistence.*; + import lombok.AccessLevel; import lombok.NoArgsConstructor; + import org.springframework.security.access.AccessDeniedException; -import javax.persistence.*; +import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.StudentId; +import com.inhabas.api.domain.BaseEntity; +import com.inhabas.api.domain.lecture.domain.converter.StudentStatusConverter; +import com.inhabas.api.domain.lecture.domain.valueObject.StudentStatus; @Entity -@Table(name = "lecture_students", - uniqueConstraints = {@UniqueConstraint(name = "lecture_students_unique_index", columnNames = {"lecture_id", "user_id"})}) +@Table( + name = "lecture_students", + uniqueConstraints = { + @UniqueConstraint( + name = "lecture_students_unique_index", + columnNames = {"lecture_id", "user_id"}) + }) @NoArgsConstructor(access = AccessLevel.PROTECTED) public class Student extends BaseEntity { - @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - private Integer id; + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer id; - @ManyToOne(fetch = FetchType.LAZY, optional = false) - private Lecture lecture; + @ManyToOne(fetch = FetchType.LAZY, optional = false) + private Lecture lecture; - @Embedded - @AttributeOverride(name = "id", column = @Column(name = "user_id", updatable = false, nullable = false)) - private StudentId studentId; + @Embedded + @AttributeOverride( + name = "id", + column = @Column(name = "user_id", updatable = false, nullable = false)) + private StudentId studentId; - @Convert(converter = StudentStatusConverter.class) - @Column(columnDefinition = "TINYINT(4)") - private StudentStatus status; + @Convert(converter = StudentStatusConverter.class) + @Column(columnDefinition = "TINYINT(4)") + private StudentStatus status; - public Student(Lecture lecture, StudentId studentId) { + public Student(Lecture lecture, StudentId studentId) { - if (lecture.isHeldBy(studentId)) - throw new IllegalArgumentException("강의자는 자신의 강의에 수강생으로 등록될 수 없습니다."); + if (lecture.isHeldBy(studentId)) + throw new IllegalArgumentException("강의자는 자신의 강의에 수강생으로 등록될 수 없습니다."); - this.lecture = lecture; - this.studentId = studentId; - this.status = StudentStatus.PROGRESS; - } + this.lecture = lecture; + this.studentId = studentId; + this.status = StudentStatus.PROGRESS; + } - public Student changeStatusByLecturer(StudentStatus status, StudentId lecturerId) { + public Student changeStatusByLecturer(StudentStatus status, StudentId lecturerId) { - if (!lecture.isHeldBy(lecturerId)) - throw new AccessDeniedException("강의자만 수강생 정보를 변경할 수 있습니다"); + if (!lecture.isHeldBy(lecturerId)) throw new AccessDeniedException("강의자만 수강생 정보를 변경할 수 있습니다"); - if (status != StudentStatus.BLOCKED && status != StudentStatus.PROGRESS) - throw new IllegalArgumentException("해당 상태로는 변경할 수 없습니다!"); + if (status != StudentStatus.BLOCKED && status != StudentStatus.PROGRESS) + throw new IllegalArgumentException("해당 상태로는 변경할 수 없습니다!"); - this.status = status; - return this; - } + this.status = status; + return this; + } - public Integer getId() { - return id; - } + public Integer getId() { + return id; + } - public void exitLecture() { + public void exitLecture() { - this.status = StudentStatus.EXIT; - } + this.status = StudentStatus.EXIT; + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/lecture/domain/converter/LectureStatusConverter.java b/resource-server/src/main/java/com/inhabas/api/domain/lecture/domain/converter/LectureStatusConverter.java index db05855c..2cba4d2b 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/lecture/domain/converter/LectureStatusConverter.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/lecture/domain/converter/LectureStatusConverter.java @@ -1,27 +1,27 @@ package com.inhabas.api.domain.lecture.domain.converter; -import com.inhabas.api.domain.lecture.domain.valueObject.LectureStatus; +import java.util.Objects; import javax.persistence.AttributeConverter; import javax.persistence.Converter; -import java.util.Objects; + +import com.inhabas.api.domain.lecture.domain.valueObject.LectureStatus; @Converter public class LectureStatusConverter implements AttributeConverter { - @Override - public Integer convertToDatabaseColumn(LectureStatus status) { + @Override + public Integer convertToDatabaseColumn(LectureStatus status) { - return status.getValue(); - } + return status.getValue(); + } - @Override - public LectureStatus convertToEntityAttribute(Integer dbData) { + @Override + public LectureStatus convertToEntityAttribute(Integer dbData) { - for (LectureStatus status: LectureStatus.values()){ - if (Objects.equals(status.getValue(), dbData)) - return status; - } - return LectureStatus.WAITING; + for (LectureStatus status : LectureStatus.values()) { + if (Objects.equals(status.getValue(), dbData)) return status; } -} \ No newline at end of file + return LectureStatus.WAITING; + } +} diff --git a/resource-server/src/main/java/com/inhabas/api/domain/lecture/domain/converter/StudentStatusConverter.java b/resource-server/src/main/java/com/inhabas/api/domain/lecture/domain/converter/StudentStatusConverter.java index 63882ba0..2ae1ea6f 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/lecture/domain/converter/StudentStatusConverter.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/lecture/domain/converter/StudentStatusConverter.java @@ -1,25 +1,25 @@ package com.inhabas.api.domain.lecture.domain.converter; -import com.inhabas.api.domain.lecture.domain.valueObject.StudentStatus; +import java.util.Objects; import javax.persistence.AttributeConverter; -import java.util.Objects; + +import com.inhabas.api.domain.lecture.domain.valueObject.StudentStatus; public class StudentStatusConverter implements AttributeConverter { - @Override - public Integer convertToDatabaseColumn(StudentStatus attribute) { + @Override + public Integer convertToDatabaseColumn(StudentStatus attribute) { - return attribute.getValue(); - } + return attribute.getValue(); + } - @Override - public StudentStatus convertToEntityAttribute(Integer dbData) { + @Override + public StudentStatus convertToEntityAttribute(Integer dbData) { - for (StudentStatus status: StudentStatus.values()){ - if (Objects.equals(status.getValue(), dbData)) - return status; - } - return StudentStatus.PROGRESS; + for (StudentStatus status : StudentStatus.values()) { + if (Objects.equals(status.getValue(), dbData)) return status; } + return StudentStatus.PROGRESS; + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/lecture/domain/valueObject/LectureStatus.java b/resource-server/src/main/java/com/inhabas/api/domain/lecture/domain/valueObject/LectureStatus.java index 2336ae66..73d26653 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/lecture/domain/valueObject/LectureStatus.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/lecture/domain/valueObject/LectureStatus.java @@ -1,20 +1,19 @@ package com.inhabas.api.domain.lecture.domain.valueObject; public enum LectureStatus { - WAITING("승인 대기", 1), - DENIED("승인 거절", 2), - PROGRESSING("진행 중", 3), - TERMINATED("종료", 4), - ; + WAITING("승인 대기", 1), + DENIED("승인 거절", 2), + PROGRESSING("진행 중", 3), + TERMINATED("종료", 4), + ; - private final Integer value; + private final Integer value; - LectureStatus(String describe, Integer value) { - this.value = value; - } - - public Integer getValue() { - return value; - } + LectureStatus(String describe, Integer value) { + this.value = value; + } + public Integer getValue() { + return value; + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/lecture/domain/valueObject/StudentStatus.java b/resource-server/src/main/java/com/inhabas/api/domain/lecture/domain/valueObject/StudentStatus.java index 19da295f..6d6baa61 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/lecture/domain/valueObject/StudentStatus.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/lecture/domain/valueObject/StudentStatus.java @@ -1,19 +1,17 @@ package com.inhabas.api.domain.lecture.domain.valueObject; public enum StudentStatus { + EXIT("탈주", -1), + BLOCKED("수강 정지", 0), + PROGRESS("진행 중", 1); - EXIT("탈주", -1), - BLOCKED("수강 정지", 0), - PROGRESS("진행 중", 1) - ; + private final Integer value; - private final Integer value; + StudentStatus(String describe, Integer value) { + this.value = value; + } - StudentStatus(String describe, Integer value) { - this.value = value; - } - - public Integer getValue() { - return value; - } + public Integer getValue() { + return value; + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/lecture/dto/LectureDetailDto.java b/resource-server/src/main/java/com/inhabas/api/domain/lecture/dto/LectureDetailDto.java index e35291d7..2c690761 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/lecture/dto/LectureDetailDto.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/lecture/dto/LectureDetailDto.java @@ -1,92 +1,108 @@ package com.inhabas.api.domain.lecture.dto; -import com.fasterxml.jackson.annotation.JsonFormat; -import com.inhabas.api.domain.lecture.domain.valueObject.LectureStatus; +import java.time.LocalDateTime; +import java.util.List; + import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; -import java.time.LocalDateTime; -import java.util.List; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.inhabas.api.domain.lecture.domain.valueObject.LectureStatus; @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) public class LectureDetailDto { - private Integer id; + private Integer id; - private String title; + private String title; - private MemberInfo chief; + private MemberInfo chief; - private List coInstructors; + private List coInstructors; - @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss") - private LocalDateTime applyDeadLine; + @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss") + private LocalDateTime applyDeadLine; - private String daysOfWeeks; + private String daysOfWeeks; - private String place; + private String place; - private String introduction; + private String introduction; - private String curriculumDetails; + private String curriculumDetails; - private Integer participantsLimits; + private Integer participantsLimits; - private Integer method; + private Integer method; - private LectureStatus state; + private LectureStatus state; - private String rejectReason; + private String rejectReason; - private Boolean paid; + private Boolean paid; - @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss") - private LocalDateTime created; + @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss") + private LocalDateTime created; - @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss") - private LocalDateTime updated; + @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss") + private LocalDateTime updated; - @Builder - public LectureDetailDto(Integer id, String title, MemberInfo chief, LocalDateTime applyDeadLine, String daysOfWeeks, String place, String introduction, String curriculumDetails, Integer participantsLimits, Integer method, LectureStatus state, String rejectReason, Boolean paid, LocalDateTime created, LocalDateTime updated) { - this.id = id; - this.title = title; - this.chief = chief; - this.coInstructors = List.of(); - this.applyDeadLine = applyDeadLine; - this.daysOfWeeks = daysOfWeeks; - this.place = place; - this.introduction = introduction; - this.curriculumDetails = curriculumDetails; - this.participantsLimits = participantsLimits; - this.method = method; - this.state = state; - this.rejectReason = rejectReason; - this.paid = paid; - this.created = created; - this.updated = updated; - } + @Builder + public LectureDetailDto( + Integer id, + String title, + MemberInfo chief, + LocalDateTime applyDeadLine, + String daysOfWeeks, + String place, + String introduction, + String curriculumDetails, + Integer participantsLimits, + Integer method, + LectureStatus state, + String rejectReason, + Boolean paid, + LocalDateTime created, + LocalDateTime updated) { + this.id = id; + this.title = title; + this.chief = chief; + this.coInstructors = List.of(); + this.applyDeadLine = applyDeadLine; + this.daysOfWeeks = daysOfWeeks; + this.place = place; + this.introduction = introduction; + this.curriculumDetails = curriculumDetails; + this.participantsLimits = participantsLimits; + this.method = method; + this.state = state; + this.rejectReason = rejectReason; + this.paid = paid; + this.created = created; + this.updated = updated; + } - public LectureDetailDto setCoInstructors(List list) { - this.coInstructors = list; - return this; - } + public LectureDetailDto setCoInstructors(List list) { + this.coInstructors = list; + return this; + } - @Getter - public static final class MemberInfo { + @Getter + public static final class MemberInfo { - private final Integer id; + private final Integer id; - private final String major; + private final String major; - private final String name; + private final String name; - public MemberInfo(Integer id, String major, String name) { - this.id = id; - this.major = major; - this.name = name; - } + public MemberInfo(Integer id, String major, String name) { + this.id = id; + this.major = major; + this.name = name; } + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/lecture/dto/LectureListDto.java b/resource-server/src/main/java/com/inhabas/api/domain/lecture/dto/LectureListDto.java index 9bb6aea8..583488eb 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/lecture/dto/LectureListDto.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/lecture/dto/LectureListDto.java @@ -1,47 +1,57 @@ package com.inhabas.api.domain.lecture.dto; -import com.fasterxml.jackson.annotation.JsonFormat; -import com.inhabas.api.domain.lecture.domain.valueObject.LectureStatus; +import java.time.LocalDateTime; + import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; -import java.time.LocalDateTime; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.inhabas.api.domain.lecture.domain.valueObject.LectureStatus; @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) public class LectureListDto { - private Integer lectureId; + private Integer lectureId; - private String title; + private String title; - private Integer chiefId; + private Integer chiefId; - private String introduction; + private String introduction; - @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss") - private LocalDateTime applyDeadline; + @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss") + private LocalDateTime applyDeadline; - private LectureStatus status; + private LectureStatus status; - private Integer method; + private Integer method; - private Integer participantsLimits; + private Integer participantsLimits; - private Integer theNumberOfCurrentParticipants; + private Integer theNumberOfCurrentParticipants; - @Builder - public LectureListDto(Integer lectureId, String title, Integer chiefId, String introduction, LocalDateTime applyDeadline, LectureStatus status, Integer method, Integer participantsLimits, Integer theNumberOfCurrentParticipants) { - this.lectureId = lectureId; - this.title = title; - this.chiefId = chiefId; - this.introduction = introduction; - this.applyDeadline = applyDeadline; - this.status = status; - this.method = method; - this.participantsLimits = participantsLimits; - this.theNumberOfCurrentParticipants = theNumberOfCurrentParticipants; - } + @Builder + public LectureListDto( + Integer lectureId, + String title, + Integer chiefId, + String introduction, + LocalDateTime applyDeadline, + LectureStatus status, + Integer method, + Integer participantsLimits, + Integer theNumberOfCurrentParticipants) { + this.lectureId = lectureId; + this.title = title; + this.chiefId = chiefId; + this.introduction = introduction; + this.applyDeadline = applyDeadline; + this.status = status; + this.method = method; + this.participantsLimits = participantsLimits; + this.theNumberOfCurrentParticipants = theNumberOfCurrentParticipants; + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/lecture/dto/LectureRegisterForm.java b/resource-server/src/main/java/com/inhabas/api/domain/lecture/dto/LectureRegisterForm.java index 9dcc9963..631672e1 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/lecture/dto/LectureRegisterForm.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/lecture/dto/LectureRegisterForm.java @@ -1,71 +1,84 @@ package com.inhabas.api.domain.lecture.dto; -import com.fasterxml.jackson.annotation.JsonFormat; -import com.inhabas.api.domain.lecture.domain.Lecture; -import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.StudentId; +import java.time.LocalDateTime; + +import javax.validation.constraints.Future; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + import lombok.AccessLevel; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.experimental.SuperBuilder; -import org.hibernate.validator.constraints.Length; -import javax.validation.constraints.Future; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotNull; -import java.time.LocalDateTime; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.StudentId; +import com.inhabas.api.domain.lecture.domain.Lecture; +import org.hibernate.validator.constraints.Length; @SuperBuilder @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) public class LectureRegisterForm { - @NotBlank - @Length(max = 100) - private String title; + @NotBlank + @Length(max = 100) + private String title; - @NotNull @Future - @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss") - private LocalDateTime applyDeadLine; + @NotNull + @Future + @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss") + private LocalDateTime applyDeadLine; - @NotBlank @Length(max = 20) - private String daysOfWeeks; + @NotBlank + @Length(max = 20) + private String daysOfWeeks; - @NotNull @Length(max = 300) - private String place; + @NotNull + @Length(max = 300) + private String place; - @NotNull @Length(max = 300) - private String introduction; + @NotNull + @Length(max = 300) + private String introduction; - @NotNull @Length(max = 16777215) - private String curriculumDetails; + @NotNull + @Length(max = 16777215) + private String curriculumDetails; - @NotNull - private Integer participantsLimits; + @NotNull private Integer participantsLimits; - @NotNull - private Integer method; + @NotNull private Integer method; - public LectureRegisterForm(String title, LocalDateTime applyDeadLine, String daysOfWeeks, String place, String introduction, String curriculumDetails, Integer participantsLimits, Integer method) { - this.title = title; - this.applyDeadLine = applyDeadLine; - this.daysOfWeeks = daysOfWeeks; - this.place = place; - this.introduction = introduction; - this.curriculumDetails = curriculumDetails; - this.participantsLimits = participantsLimits; - this.method = method; - } + public LectureRegisterForm( + String title, + LocalDateTime applyDeadLine, + String daysOfWeeks, + String place, + String introduction, + String curriculumDetails, + Integer participantsLimits, + Integer method) { + this.title = title; + this.applyDeadLine = applyDeadLine; + this.daysOfWeeks = daysOfWeeks; + this.place = place; + this.introduction = introduction; + this.curriculumDetails = curriculumDetails; + this.participantsLimits = participantsLimits; + this.method = method; + } - public Lecture toEntity(StudentId studentId) { - return Lecture.builder() - .applyDeadline(applyDeadLine) - .chief(studentId) - .daysOfWeek(daysOfWeeks) - .curriculumDetails(curriculumDetails) - .introduction(introduction) - .method(method) - .title(title) - .participantsLimits(participantsLimits) - .place(place) - .build(); - } + public Lecture toEntity(StudentId studentId) { + return Lecture.builder() + .applyDeadline(applyDeadLine) + .chief(studentId) + .daysOfWeek(daysOfWeeks) + .curriculumDetails(curriculumDetails) + .introduction(introduction) + .method(method) + .title(title) + .participantsLimits(participantsLimits) + .place(place) + .build(); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/lecture/dto/LectureStatusUpdateRequest.java b/resource-server/src/main/java/com/inhabas/api/domain/lecture/dto/LectureStatusUpdateRequest.java index b6b61ae0..55d62e3b 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/lecture/dto/LectureStatusUpdateRequest.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/lecture/dto/LectureStatusUpdateRequest.java @@ -1,22 +1,20 @@ package com.inhabas.api.domain.lecture.dto; -import com.inhabas.api.domain.lecture.domain.valueObject.LectureStatus; +import javax.validation.constraints.NotNull; + import lombok.AccessLevel; import lombok.Getter; import lombok.NoArgsConstructor; -import org.hibernate.validator.constraints.Length; -import javax.validation.constraints.NotNull; +import com.inhabas.api.domain.lecture.domain.valueObject.LectureStatus; +import org.hibernate.validator.constraints.Length; @Getter @NoArgsConstructor(access = AccessLevel.PUBLIC) public class LectureStatusUpdateRequest { - @NotNull - private LectureStatus status; - - @Length(max = 200) - private String rejectReason; - + @NotNull private LectureStatus status; + @Length(max = 200) + private String rejectReason; } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/lecture/dto/LectureUpdateForm.java b/resource-server/src/main/java/com/inhabas/api/domain/lecture/dto/LectureUpdateForm.java index e9353ad8..fbfadef4 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/lecture/dto/LectureUpdateForm.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/lecture/dto/LectureUpdateForm.java @@ -1,20 +1,18 @@ package com.inhabas.api.domain.lecture.dto; +import javax.validation.constraints.NotNull; + import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.experimental.SuperBuilder; -import javax.validation.constraints.NotNull; - - @Getter @SuperBuilder @AllArgsConstructor @NoArgsConstructor(access = AccessLevel.PROTECTED) public class LectureUpdateForm extends LectureRegisterForm { - @NotNull - private Integer id; + @NotNull private Integer id; } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/lecture/dto/StudentListDto.java b/resource-server/src/main/java/com/inhabas/api/domain/lecture/dto/StudentListDto.java index 076d35bf..8ae2992e 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/lecture/dto/StudentListDto.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/lecture/dto/StudentListDto.java @@ -1,40 +1,49 @@ package com.inhabas.api.domain.lecture.dto; -import com.inhabas.api.domain.lecture.domain.valueObject.StudentStatus; import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; +import com.inhabas.api.domain.lecture.domain.valueObject.StudentStatus; + @Getter @NoArgsConstructor(access = AccessLevel.PUBLIC) public class StudentListDto { - private String name; + private String name; - private Integer memberId; + private Integer memberId; - private String phoneNumber; + private String phoneNumber; - private String email; + private String email; - private Integer assignmentCount; + private Integer assignmentCount; - private Integer attendanceCount; + private Integer attendanceCount; - private StudentStatus status; + private StudentStatus status; - private Integer sid; + private Integer sid; - @Builder - public StudentListDto(String name, Integer memberId, String phoneNumber, String email, Integer assignmentCount, Integer attendanceCount, StudentStatus status, Integer sid) { - this.name = name; - this.memberId = memberId; - this.phoneNumber = phoneNumber; - this.email = email; - this.assignmentCount = assignmentCount; - this.attendanceCount = attendanceCount; - this.status = status; - this.sid = sid; - } + @Builder + public StudentListDto( + String name, + Integer memberId, + String phoneNumber, + String email, + Integer assignmentCount, + Integer attendanceCount, + StudentStatus status, + Integer sid) { + this.name = name; + this.memberId = memberId; + this.phoneNumber = phoneNumber; + this.email = email; + this.assignmentCount = assignmentCount; + this.attendanceCount = attendanceCount; + this.status = status; + this.sid = sid; + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/lecture/repository/LectureRepository.java b/resource-server/src/main/java/com/inhabas/api/domain/lecture/repository/LectureRepository.java index 0ee3a9fb..061d3473 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/lecture/repository/LectureRepository.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/lecture/repository/LectureRepository.java @@ -1,7 +1,8 @@ package com.inhabas.api.domain.lecture.repository; -import com.inhabas.api.domain.lecture.domain.Lecture; import org.springframework.data.jpa.repository.JpaRepository; -public interface LectureRepository extends JpaRepository, LectureRepositoryCustom { -} +import com.inhabas.api.domain.lecture.domain.Lecture; + +public interface LectureRepository + extends JpaRepository, LectureRepositoryCustom {} diff --git a/resource-server/src/main/java/com/inhabas/api/domain/lecture/repository/LectureRepositoryCustom.java b/resource-server/src/main/java/com/inhabas/api/domain/lecture/repository/LectureRepositoryCustom.java index 17babbcf..316059d3 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/lecture/repository/LectureRepositoryCustom.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/lecture/repository/LectureRepositoryCustom.java @@ -1,15 +1,16 @@ package com.inhabas.api.domain.lecture.repository; -import com.inhabas.api.domain.lecture.dto.LectureDetailDto; -import com.inhabas.api.domain.lecture.dto.LectureListDto; +import java.util.Optional; + import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; -import java.util.Optional; +import com.inhabas.api.domain.lecture.dto.LectureDetailDto; +import com.inhabas.api.domain.lecture.dto.LectureListDto; public interface LectureRepositoryCustom { - Optional getDetails(Integer id); + Optional getDetails(Integer id); - Page getList(Pageable pageable); + Page getList(Pageable pageable); } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/lecture/repository/LectureRepositoryImpl.java b/resource-server/src/main/java/com/inhabas/api/domain/lecture/repository/LectureRepositoryImpl.java index a149c86c..f9cf74d5 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/lecture/repository/LectureRepositoryImpl.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/lecture/repository/LectureRepositoryImpl.java @@ -1,5 +1,17 @@ package com.inhabas.api.domain.lecture.repository; +import static com.inhabas.api.auth.domain.oauth2.member.domain.entity.QMember.member; +import static com.inhabas.api.domain.lecture.domain.QLecture.lecture; + +import java.util.List; +import java.util.Optional; + +import lombok.RequiredArgsConstructor; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; + import com.inhabas.api.auth.domain.oauth2.member.domain.entity.QMember; import com.inhabas.api.domain.lecture.domain.valueObject.LectureStatus; import com.inhabas.api.domain.lecture.dto.LectureDetailDto; @@ -7,78 +19,76 @@ import com.querydsl.core.types.Projections; import com.querydsl.core.types.dsl.Expressions; import com.querydsl.jpa.impl.JPAQueryFactory; -import lombok.RequiredArgsConstructor; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageImpl; -import org.springframework.data.domain.Pageable; -import java.util.List; -import java.util.Optional; - -import static com.inhabas.api.domain.lecture.domain.QLecture.lecture; -import static com.inhabas.api.auth.domain.oauth2.member.domain.entity.QMember.member; @RequiredArgsConstructor public class LectureRepositoryImpl implements LectureRepositoryCustom { - private final JPAQueryFactory queryFactory; + private final JPAQueryFactory queryFactory; - private final QMember member2 = new QMember("member2"); + private final QMember member2 = new QMember("member2"); - public Optional getDetails(Integer id) { + public Optional getDetails(Integer id) { - return Optional.ofNullable(queryFactory - .select(Projections.constructor(LectureDetailDto.class, - lecture.id, - lecture.title, - Projections.constructor(LectureDetailDto.MemberInfo.class, - lecture.chief.id, - member.schoolInformation.major.value, - member.name.value), - lecture.applyDeadline, - lecture.daysOfWeek, - lecture.place, - lecture.introduction, - lecture.curriculumDetails, - lecture.participantsLimits, - lecture.method, - lecture.status, - lecture.rejectReason, - lecture.paid, - lecture.dateCreated, - lecture.dateUpdated - )) - .from(lecture) - .innerJoin(member).on(member.studentId.eq(lecture.chief)) - .where(lecture.id.eq(id)) - .fetchOne()); - } + return Optional.ofNullable( + queryFactory + .select( + Projections.constructor( + LectureDetailDto.class, + lecture.id, + lecture.title, + Projections.constructor( + LectureDetailDto.MemberInfo.class, + lecture.chief.id, + member.schoolInformation.major.value, + member.name.value), + lecture.applyDeadline, + lecture.daysOfWeek, + lecture.place, + lecture.introduction, + lecture.curriculumDetails, + lecture.participantsLimits, + lecture.method, + lecture.status, + lecture.rejectReason, + lecture.paid, + lecture.dateCreated, + lecture.dateUpdated)) + .from(lecture) + .innerJoin(member) + .on(member.studentId.eq(lecture.chief)) + .where(lecture.id.eq(id)) + .fetchOne()); + } - public Page getList(Pageable pageable) { + public Page getList(Pageable pageable) { - List list = queryFactory - .select(Projections.constructor(LectureListDto.class, - lecture.id, - lecture.title, - lecture.chief.id, - lecture.introduction, - lecture.applyDeadline, - lecture.status, - lecture.method, - lecture.participantsLimits, - Expressions.asNumber(0) - )).from(lecture) - .where(lecture.status.in(LectureStatus.PROGRESSING, LectureStatus.TERMINATED)) - .offset(pageable.getOffset()) - .limit(pageable.getPageSize()) - .orderBy(lecture.dateCreated.desc()) - .orderBy(lecture.status.asc()) - .fetch(); + List list = + queryFactory + .select( + Projections.constructor( + LectureListDto.class, + lecture.id, + lecture.title, + lecture.chief.id, + lecture.introduction, + lecture.applyDeadline, + lecture.status, + lecture.method, + lecture.participantsLimits, + Expressions.asNumber(0))) + .from(lecture) + .where(lecture.status.in(LectureStatus.PROGRESSING, LectureStatus.TERMINATED)) + .offset(pageable.getOffset()) + .limit(pageable.getPageSize()) + .orderBy(lecture.dateCreated.desc()) + .orderBy(lecture.status.asc()) + .fetch(); - return new PageImpl<>(list, pageable, getCount()); - } + return new PageImpl<>(list, pageable, getCount()); + } - private Integer getCount() { + private Integer getCount() { - return queryFactory.selectFrom(lecture).fetch().size(); - } + return queryFactory.selectFrom(lecture).fetch().size(); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/lecture/repository/StudentRepository.java b/resource-server/src/main/java/com/inhabas/api/domain/lecture/repository/StudentRepository.java index 83f6f3ae..8da32dab 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/lecture/repository/StudentRepository.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/lecture/repository/StudentRepository.java @@ -1,19 +1,21 @@ package com.inhabas.api.domain.lecture.repository; -import com.inhabas.api.domain.lecture.domain.Student; -import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.StudentId; +import java.util.List; +import java.util.Optional; + import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; -import java.util.List; -import java.util.Optional; +import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.StudentId; +import com.inhabas.api.domain.lecture.domain.Student; -public interface StudentRepository extends JpaRepository, StudentRepositoryCustom { +public interface StudentRepository + extends JpaRepository, StudentRepositoryCustom { - Optional findByLectureIdAndStudentId(Integer lectureId, StudentId studentId); + Optional findByLectureIdAndStudentId(Integer lectureId, StudentId studentId); - Optional findByLectureIdAndId(Integer lectureId, Integer sid); + Optional findByLectureIdAndId(Integer lectureId, Integer sid); - @Query("select s from Student s where s.id in :integers and s.lecture.id = :lectureId ") - List findAllById(Iterable integers, Integer lectureId); + @Query("select s from Student s where s.id in :integers and s.lecture.id = :lectureId ") + List findAllById(Iterable integers, Integer lectureId); } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/lecture/repository/StudentRepositoryCustom.java b/resource-server/src/main/java/com/inhabas/api/domain/lecture/repository/StudentRepositoryCustom.java index aa2912b9..5b963ad0 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/lecture/repository/StudentRepositoryCustom.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/lecture/repository/StudentRepositoryCustom.java @@ -1,10 +1,11 @@ package com.inhabas.api.domain.lecture.repository; -import com.inhabas.api.domain.lecture.dto.StudentListDto; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; +import com.inhabas.api.domain.lecture.dto.StudentListDto; + public interface StudentRepositoryCustom { - Page searchStudents(Integer lectureId, Pageable pageable); + Page searchStudents(Integer lectureId, Pageable pageable); } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/lecture/repository/StudentRepositoryImpl.java b/resource-server/src/main/java/com/inhabas/api/domain/lecture/repository/StudentRepositoryImpl.java index f44b22c9..ffbc94d3 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/lecture/repository/StudentRepositoryImpl.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/lecture/repository/StudentRepositoryImpl.java @@ -1,52 +1,59 @@ package com.inhabas.api.domain.lecture.repository; -import com.inhabas.api.domain.lecture.dto.StudentListDto; -import com.querydsl.core.types.Projections; -import com.querydsl.core.types.dsl.Expressions; -import com.querydsl.jpa.impl.JPAQueryFactory; +import static com.inhabas.api.auth.domain.oauth2.member.domain.entity.QMember.member; +import static com.inhabas.api.domain.lecture.domain.QStudent.student; + +import java.util.List; + import lombok.RequiredArgsConstructor; + import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; -import java.util.List; - -import static com.inhabas.api.domain.lecture.domain.QStudent.student; -import static com.inhabas.api.auth.domain.oauth2.member.domain.entity.QMember.member; +import com.inhabas.api.domain.lecture.dto.StudentListDto; +import com.querydsl.core.types.Projections; +import com.querydsl.core.types.dsl.Expressions; +import com.querydsl.jpa.impl.JPAQueryFactory; @RequiredArgsConstructor public class StudentRepositoryImpl implements StudentRepositoryCustom { - private final JPAQueryFactory queryFactory; - - public Page searchStudents(Integer lectureId, Pageable pageable) { - - List students = queryFactory.select(Projections.constructor(StudentListDto.class, - member.name.value, - member.studentId.id, - member.phone.value, - member.email.value, - Expressions.asNumber(0), - Expressions.asNumber(0), - student.status, - student.id - )) - .from(student) - .innerJoin(member).on(member.studentId.eq(student.studentId)) - .where(student.lecture.id.eq(lectureId)) - .offset(pageable.getOffset()) - .limit(pageable.getPageSize()) - .orderBy(student.studentId.id.asc()) - .fetch(); - - return new PageImpl<>(students, pageable, getCount(lectureId)); - } - - private Integer getCount(Integer lectureId) { - return queryFactory.select(student.id) - .from(student) - .where(student.lecture.id.eq(lectureId)) - .fetch() - .size(); - } + private final JPAQueryFactory queryFactory; + + public Page searchStudents(Integer lectureId, Pageable pageable) { + + List students = + queryFactory + .select( + Projections.constructor( + StudentListDto.class, + member.name.value, + member.studentId.id, + member.phone.value, + member.email.value, + Expressions.asNumber(0), + Expressions.asNumber(0), + student.status, + student.id)) + .from(student) + .innerJoin(member) + .on(member.studentId.eq(student.studentId)) + .where(student.lecture.id.eq(lectureId)) + .offset(pageable.getOffset()) + .limit(pageable.getPageSize()) + .orderBy(student.studentId.id.asc()) + .fetch(); + + return new PageImpl<>(students, pageable, getCount(lectureId)); + } + + private Integer getCount(Integer lectureId) { + return queryFactory + .select(student.id) + .from(student) + .where(student.lecture.id.eq(lectureId)) + .fetch() + .size(); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/lecture/usecase/LectureSecurityChecker.java b/resource-server/src/main/java/com/inhabas/api/domain/lecture/usecase/LectureSecurityChecker.java index a4a55069..6aeeb8c9 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/lecture/usecase/LectureSecurityChecker.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/lecture/usecase/LectureSecurityChecker.java @@ -1,27 +1,30 @@ package com.inhabas.api.domain.lecture.usecase; -import com.inhabas.api.domain.lecture.domain.Lecture; -import com.inhabas.api.domain.lecture.repository.LectureRepository; -import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.StudentId; +import javax.persistence.EntityNotFoundException; + import lombok.RequiredArgsConstructor; + import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Service; -import javax.persistence.EntityNotFoundException; +import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.StudentId; +import com.inhabas.api.domain.lecture.domain.Lecture; +import com.inhabas.api.domain.lecture.repository.LectureRepository; @Service @RequiredArgsConstructor public class LectureSecurityChecker { - private final LectureRepository lectureRepository; + private final LectureRepository lectureRepository; - public boolean instructorOnly(Integer lectureId) { + public boolean instructorOnly(Integer lectureId) { - StudentId currentStudentId = (StudentId) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); + StudentId currentStudentId = + (StudentId) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); - Lecture lecture = lectureRepository.findById(lectureId) - .orElseThrow(EntityNotFoundException::new); + Lecture lecture = + lectureRepository.findById(lectureId).orElseThrow(EntityNotFoundException::new); - return lecture.isHeldBy(currentStudentId); - } + return lecture.isHeldBy(currentStudentId); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/lecture/usecase/LectureService.java b/resource-server/src/main/java/com/inhabas/api/domain/lecture/usecase/LectureService.java index f494d131..90df4698 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/lecture/usecase/LectureService.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/lecture/usecase/LectureService.java @@ -1,21 +1,22 @@ package com.inhabas.api.domain.lecture.usecase; -import com.inhabas.api.domain.lecture.dto.*; -import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.StudentId; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; +import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.StudentId; +import com.inhabas.api.domain.lecture.dto.*; + public interface LectureService { - void create(LectureRegisterForm form, StudentId studentId); + void create(LectureRegisterForm form, StudentId studentId); - void update(LectureUpdateForm form, StudentId studentId); + void update(LectureUpdateForm form, StudentId studentId); - void delete(Integer lectureId, StudentId studentId); + void delete(Integer lectureId, StudentId studentId); - LectureDetailDto get(Integer lectureId); + LectureDetailDto get(Integer lectureId); - Page getList(Pageable pageable); + Page getList(Pageable pageable); - void approveOrDeny(Integer lectureId, LectureStatusUpdateRequest request); + void approveOrDeny(Integer lectureId, LectureStatusUpdateRequest request); } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/lecture/usecase/LectureServiceImpl.java b/resource-server/src/main/java/com/inhabas/api/domain/lecture/usecase/LectureServiceImpl.java index 3bbf63a8..a18b9be3 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/lecture/usecase/LectureServiceImpl.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/lecture/usecase/LectureServiceImpl.java @@ -1,80 +1,85 @@ package com.inhabas.api.domain.lecture.usecase; -import com.inhabas.api.domain.lecture.LectureCannotModifiableException; -import com.inhabas.api.domain.lecture.domain.Lecture; -import com.inhabas.api.domain.lecture.dto.*; -import com.inhabas.api.domain.lecture.repository.LectureRepository; -import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.StudentId; +import javax.persistence.EntityNotFoundException; + import lombok.RequiredArgsConstructor; + import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import javax.persistence.EntityNotFoundException; +import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.StudentId; +import com.inhabas.api.domain.lecture.LectureCannotModifiableException; +import com.inhabas.api.domain.lecture.domain.Lecture; +import com.inhabas.api.domain.lecture.dto.*; +import com.inhabas.api.domain.lecture.repository.LectureRepository; @Service @RequiredArgsConstructor public class LectureServiceImpl implements LectureService { - private final LectureRepository repository; + private final LectureRepository repository; - @Transactional - @Override - public void create(LectureRegisterForm form, StudentId studentId) { + @Transactional + @Override + public void create(LectureRegisterForm form, StudentId studentId) { - Lecture lecture = form.toEntity(studentId); - repository.save(lecture); - } + Lecture lecture = form.toEntity(studentId); + repository.save(lecture); + } - @Transactional - @Override - public void update(LectureUpdateForm form, StudentId studentId) { + @Transactional + @Override + public void update(LectureUpdateForm form, StudentId studentId) { - Lecture lecture = repository.findById(form.getId()) - .orElseThrow(EntityNotFoundException::new); + Lecture lecture = repository.findById(form.getId()).orElseThrow(EntityNotFoundException::new); - lecture.update(studentId, form.getTitle(), form.getApplyDeadLine(), form.getDaysOfWeeks(), form.getPlace(), - form.getIntroduction(), form.getCurriculumDetails(), form.getParticipantsLimits(), form.getMethod()); - } + lecture.update( + studentId, + form.getTitle(), + form.getApplyDeadLine(), + form.getDaysOfWeeks(), + form.getPlace(), + form.getIntroduction(), + form.getCurriculumDetails(), + form.getParticipantsLimits(), + form.getMethod()); + } - @Transactional - @Override - public void delete(Integer lectureId, StudentId studentId) { + @Transactional + @Override + public void delete(Integer lectureId, StudentId studentId) { - Lecture lecture = repository.findById(lectureId) - .orElseThrow(EntityNotFoundException::new); + Lecture lecture = repository.findById(lectureId).orElseThrow(EntityNotFoundException::new); - if (lecture.notModifiableBy(studentId)) - throw new LectureCannotModifiableException(); + if (lecture.notModifiableBy(studentId)) throw new LectureCannotModifiableException(); - if (!lecture.canBeDeleted()) - throw new LectureCannotModifiableException("이미 진행된 강의는 삭제할 수 없습니다."); + if (!lecture.canBeDeleted()) + throw new LectureCannotModifiableException("이미 진행된 강의는 삭제할 수 없습니다."); - repository.delete(lecture); - } + repository.delete(lecture); + } - @Transactional(readOnly = true) - @Override - public LectureDetailDto get(Integer lectureId) { + @Transactional(readOnly = true) + @Override + public LectureDetailDto get(Integer lectureId) { - return repository.getDetails(lectureId) - .orElseThrow(EntityNotFoundException::new); - } + return repository.getDetails(lectureId).orElseThrow(EntityNotFoundException::new); + } - @Transactional(readOnly = true) - @Override - public Page getList(Pageable pageable) { + @Transactional(readOnly = true) + @Override + public Page getList(Pageable pageable) { - return repository.getList(pageable); - } + return repository.getList(pageable); + } - @Override - public void approveOrDeny(Integer lectureId, LectureStatusUpdateRequest request) { + @Override + public void approveOrDeny(Integer lectureId, LectureStatusUpdateRequest request) { - Lecture lecture = repository.findById(lectureId) - .orElseThrow(EntityNotFoundException::new); + Lecture lecture = repository.findById(lectureId).orElseThrow(EntityNotFoundException::new); - lecture.approveOrDeny(request.getStatus(), request.getRejectReason()); - } + lecture.approveOrDeny(request.getStatus(), request.getRejectReason()); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/lecture/usecase/LectureStudentService.java b/resource-server/src/main/java/com/inhabas/api/domain/lecture/usecase/LectureStudentService.java index c276cf0b..9ae9b97b 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/lecture/usecase/LectureStudentService.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/lecture/usecase/LectureStudentService.java @@ -1,26 +1,30 @@ package com.inhabas.api.domain.lecture.usecase; -import com.inhabas.api.domain.lecture.domain.valueObject.StudentStatus; -import com.inhabas.api.domain.lecture.dto.StudentListDto; -import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.StudentId; +import java.util.Map; + import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; -import java.util.Map; +import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.StudentId; +import com.inhabas.api.domain.lecture.domain.valueObject.StudentStatus; +import com.inhabas.api.domain.lecture.dto.StudentListDto; public interface LectureStudentService { - void enroll(Integer lectureId, StudentId studentId); + void enroll(Integer lectureId, StudentId studentId); - /** - * 학생 한명의 상태를 {@code PROGRESS} 또는 {@code BLOCKED} 상태로 변경한다. 탈주시킬 수 없다. - * @param studentId 학번이 아닌 강의등록명단에서의 id - */ - void changeStatusOfOneStudentByLecturer(Integer studentId, StudentId lecturerId, StudentStatus status, Integer lectureId); + /** + * 학생 한명의 상태를 {@code PROGRESS} 또는 {@code BLOCKED} 상태로 변경한다. 탈주시킬 수 없다. + * + * @param studentId 학번이 아닌 강의등록명단에서의 id + */ + void changeStatusOfOneStudentByLecturer( + Integer studentId, StudentId lecturerId, StudentStatus status, Integer lectureId); - void changeStatusOfStudentsByLecturer(Map list, StudentId lecturerId, Integer lectureId); + void changeStatusOfStudentsByLecturer( + Map list, StudentId lecturerId, Integer lectureId); - void exitBySelf(Integer lectureId, StudentId studentId); + void exitBySelf(Integer lectureId, StudentId studentId); - Page searchStudents(Integer lectureId, Pageable pageable); + Page searchStudents(Integer lectureId, Pageable pageable); } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/lecture/usecase/LectureStudentServiceImpl.java b/resource-server/src/main/java/com/inhabas/api/domain/lecture/usecase/LectureStudentServiceImpl.java index bc087f9b..f2e2e0a2 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/lecture/usecase/LectureStudentServiceImpl.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/lecture/usecase/LectureStudentServiceImpl.java @@ -1,81 +1,86 @@ package com.inhabas.api.domain.lecture.usecase; -import com.inhabas.api.domain.lecture.domain.Lecture; -import com.inhabas.api.domain.lecture.domain.Student; -import com.inhabas.api.domain.lecture.domain.valueObject.StudentStatus; -import com.inhabas.api.domain.lecture.dto.StudentListDto; -import com.inhabas.api.domain.lecture.repository.LectureRepository; -import com.inhabas.api.domain.lecture.repository.StudentRepository; -import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.StudentId; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +import javax.persistence.EntityNotFoundException; + import lombok.RequiredArgsConstructor; + import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import javax.persistence.EntityNotFoundException; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; +import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.StudentId; +import com.inhabas.api.domain.lecture.domain.Lecture; +import com.inhabas.api.domain.lecture.domain.Student; +import com.inhabas.api.domain.lecture.domain.valueObject.StudentStatus; +import com.inhabas.api.domain.lecture.dto.StudentListDto; +import com.inhabas.api.domain.lecture.repository.LectureRepository; +import com.inhabas.api.domain.lecture.repository.StudentRepository; @Service @RequiredArgsConstructor public class LectureStudentServiceImpl implements LectureStudentService { - private final StudentRepository studentRepository; - private final LectureRepository lectureRepository; - - @Transactional - @Override - public void enroll(Integer lectureId, StudentId studentId) { - - Lecture lecture = lectureRepository.findById(lectureId) - .orElseThrow(EntityNotFoundException::new); - Student student = new Student(lecture, studentId); - - studentRepository.save(student); - } + private final StudentRepository studentRepository; + private final LectureRepository lectureRepository; - @Transactional - @Override - public void changeStatusOfOneStudentByLecturer(Integer studentId, StudentId lecturerId, StudentStatus status, Integer lectureId) { + @Transactional + @Override + public void enroll(Integer lectureId, StudentId studentId) { - studentRepository.findByLectureIdAndId(lectureId, studentId) - .orElseThrow(EntityNotFoundException::new) - .changeStatusByLecturer(status, lecturerId); - } + Lecture lecture = + lectureRepository.findById(lectureId).orElseThrow(EntityNotFoundException::new); + Student student = new Student(lecture, studentId); + studentRepository.save(student); + } - @Transactional - @Override - public void changeStatusOfStudentsByLecturer(Map list, StudentId instructorId, Integer lectureId) { + @Transactional + @Override + public void changeStatusOfOneStudentByLecturer( + Integer studentId, StudentId lecturerId, StudentStatus status, Integer lectureId) { - Set keySet = list.keySet(); + studentRepository + .findByLectureIdAndId(lectureId, studentId) + .orElseThrow(EntityNotFoundException::new) + .changeStatusByLecturer(status, lecturerId); + } - List students = studentRepository.findAllById(keySet, lectureId) - .stream() - .map(student -> student.changeStatusByLecturer(list.get(student.getId()), instructorId)) - .collect(Collectors.toList()); + @Transactional + @Override + public void changeStatusOfStudentsByLecturer( + Map list, StudentId instructorId, Integer lectureId) { - studentRepository.saveAll(students); - } + Set keySet = list.keySet(); + List students = + studentRepository.findAllById(keySet, lectureId).stream() + .map(student -> student.changeStatusByLecturer(list.get(student.getId()), instructorId)) + .collect(Collectors.toList()); - @Transactional - @Override - public void exitBySelf(Integer lectureId, StudentId studentId) { + studentRepository.saveAll(students); + } - Student student = studentRepository.findByLectureIdAndStudentId(lectureId, studentId) - .orElseThrow(EntityNotFoundException::new); + @Transactional + @Override + public void exitBySelf(Integer lectureId, StudentId studentId) { - student.exitLecture(); - } + Student student = + studentRepository + .findByLectureIdAndStudentId(lectureId, studentId) + .orElseThrow(EntityNotFoundException::new); + student.exitLecture(); + } - @Override - public Page searchStudents(Integer lectureId, Pageable pageable) { + @Override + public Page searchStudents(Integer lectureId, Pageable pageable) { - return studentRepository.searchStudents(lectureId, pageable); - } + return studentRepository.searchStudents(lectureId, pageable); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/menu/domain/Menu.java b/resource-server/src/main/java/com/inhabas/api/domain/menu/domain/Menu.java index beb4e89e..2c296bfc 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/menu/domain/Menu.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/menu/domain/Menu.java @@ -1,63 +1,70 @@ package com.inhabas.api.domain.menu.domain; -import com.inhabas.api.domain.BaseEntity; -import com.inhabas.api.domain.menu.domain.valueObject.Description; -import com.inhabas.api.domain.menu.domain.valueObject.MenuName; -import com.inhabas.api.domain.menu.domain.valueObject.MenuType; +import javax.persistence.*; + import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; + import org.springframework.data.jpa.domain.support.AuditingEntityListener; -import javax.persistence.*; +import com.inhabas.api.domain.BaseEntity; +import com.inhabas.api.domain.menu.domain.valueObject.Description; +import com.inhabas.api.domain.menu.domain.valueObject.MenuName; +import com.inhabas.api.domain.menu.domain.valueObject.MenuType; @Entity @Getter @EntityListeners(AuditingEntityListener.class) @NoArgsConstructor(access = AccessLevel.PROTECTED) -@Table(name = "MENU", - uniqueConstraints = { @UniqueConstraint(name = "UniqueNumberAndStatus", columnNames = { "MENU_GROUP_ID", "PRIORITY" })}, - indexes = {@Index(name = "MENU_GROUP_INDEX", columnList = "MENU_GROUP_ID ASC"), - @Index(name = "PRIORITY_INDEX", columnList = "PRIORITY ASC")}) +@Table( + name = "MENU", + uniqueConstraints = { + @UniqueConstraint( + name = "UniqueNumberAndStatus", + columnNames = {"MENU_GROUP_ID", "PRIORITY"}) + }, + indexes = { + @Index(name = "MENU_GROUP_INDEX", columnList = "MENU_GROUP_ID ASC"), + @Index(name = "PRIORITY_INDEX", columnList = "PRIORITY ASC") + }) public class Menu extends BaseEntity { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Integer id; - - @ManyToOne(fetch = FetchType.LAZY, optional = false) - @JoinColumn(name = "MENU_GROUP_ID", foreignKey = @ForeignKey(name = "MENU_GROUP_ID_FK")) - private MenuGroup menuGroup; + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer id; - @Column(name = "PRIORITY", nullable = false) - private Integer priority; + @ManyToOne(fetch = FetchType.LAZY, optional = false) + @JoinColumn(name = "MENU_GROUP_ID", foreignKey = @ForeignKey(name = "MENU_GROUP_ID_FK")) + private MenuGroup menuGroup; - @Embedded - private MenuName name; + @Column(name = "PRIORITY", nullable = false) + private Integer priority; - @Enumerated(EnumType.STRING) - @Column(name = "TYPE", length = 20, nullable = false) - private MenuType type; + @Embedded private MenuName name; - @Embedded - private Description description; + @Enumerated(EnumType.STRING) + @Column(name = "TYPE", length = 20, nullable = false) + private MenuType type; - public String getName() { - return name.getValue(); - } + @Embedded private Description description; - public String getDescription() { - return description.getValue(); - } + public String getName() { + return name.getValue(); + } - @Builder - public Menu(MenuGroup menuGroup, Integer priority, MenuType type, String name, String description) { - this.menuGroup = menuGroup; - this.priority = priority; - this.type = type; - this.name = new MenuName(name); - this.description = new Description(description); - } + public String getDescription() { + return description.getValue(); + } + @Builder + public Menu( + MenuGroup menuGroup, Integer priority, MenuType type, String name, String description) { + this.menuGroup = menuGroup; + this.priority = priority; + this.type = type; + this.name = new MenuName(name); + this.description = new Description(description); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/menu/domain/MenuGroup.java b/resource-server/src/main/java/com/inhabas/api/domain/menu/domain/MenuGroup.java index 9cc79b5a..62c1fd12 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/menu/domain/MenuGroup.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/menu/domain/MenuGroup.java @@ -1,29 +1,30 @@ package com.inhabas.api.domain.menu.domain; -import com.inhabas.api.domain.BaseEntity; -import com.inhabas.api.domain.menu.domain.valueObject.MenuGroupName; +import javax.persistence.*; + import lombok.AccessLevel; import lombok.Getter; import lombok.NoArgsConstructor; -import javax.persistence.*; +import com.inhabas.api.domain.BaseEntity; +import com.inhabas.api.domain.menu.domain.valueObject.MenuGroupName; @Entity @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) public class MenuGroup extends BaseEntity { - @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - private Integer id; + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer id; - @Embedded - private MenuGroupName name; + @Embedded private MenuGroupName name; - public String getName() { - return name.getValue(); - } + public String getName() { + return name.getValue(); + } - public MenuGroup(String name) { - this.name = new MenuGroupName(name); - } + public MenuGroup(String name) { + this.name = new MenuGroupName(name); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/menu/domain/valueObject/Description.java b/resource-server/src/main/java/com/inhabas/api/domain/menu/domain/valueObject/Description.java index ece38e41..7408830b 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/menu/domain/valueObject/Description.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/menu/domain/valueObject/Description.java @@ -1,40 +1,38 @@ package com.inhabas.api.domain.menu.domain.valueObject; -import lombok.AccessLevel; -import lombok.NoArgsConstructor; +import java.util.Objects; import javax.persistence.Column; import javax.persistence.Embeddable; import javax.persistence.Transient; -import java.util.Objects; + +import lombok.AccessLevel; +import lombok.NoArgsConstructor; @Embeddable @NoArgsConstructor(access = AccessLevel.PROTECTED) public class Description { - @Column(name = "DESCRIPTION", length = 50) - private String value; + @Column(name = "DESCRIPTION", length = 50) + private String value; - @Transient - private final int MAX_LENGTH = 50; + @Transient private final int MAX_LENGTH = 50; - public Description(String value) { - if (validate(value)) - this.value = value; - else - throw new IllegalArgumentException(); - } + public Description(String value) { + if (validate(value)) this.value = value; + else throw new IllegalArgumentException(); + } - private boolean validate(Object value) { - if (Objects.isNull(value)) return false; - if (!(value instanceof String)) return false; + private boolean validate(Object value) { + if (Objects.isNull(value)) return false; + if (!(value instanceof String)) return false; - String o = (String) value; - if (o.isBlank()) return false; - return o.length() < MAX_LENGTH; - } + String o = (String) value; + if (o.isBlank()) return false; + return o.length() < MAX_LENGTH; + } - public String getValue() { - return value; - } + public String getValue() { + return value; + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/menu/domain/valueObject/MenuGroupName.java b/resource-server/src/main/java/com/inhabas/api/domain/menu/domain/valueObject/MenuGroupName.java index fb4dd495..7685ad32 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/menu/domain/valueObject/MenuGroupName.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/menu/domain/valueObject/MenuGroupName.java @@ -1,37 +1,35 @@ package com.inhabas.api.domain.menu.domain.valueObject; +import java.util.Objects; + import javax.persistence.Column; import javax.persistence.Embeddable; import javax.persistence.Transient; -import java.util.Objects; @Embeddable public class MenuGroupName { - @Column(name = "NAME", length = 10, nullable = false) - private String value; + @Column(name = "NAME", length = 10, nullable = false) + private String value; - @Transient - private final int MAX_LENGTH = 10; + @Transient private final int MAX_LENGTH = 10; - public MenuGroupName() {} + public MenuGroupName() {} - public MenuGroupName(String value) { - if (validate(value)) - this.value = value; - else - throw new IllegalArgumentException(); - } + public MenuGroupName(String value) { + if (validate(value)) this.value = value; + else throw new IllegalArgumentException(); + } - private boolean validate(Object value) { - if (Objects.isNull(value)) return false; - if (!(value instanceof String)) return false; + private boolean validate(Object value) { + if (Objects.isNull(value)) return false; + if (!(value instanceof String)) return false; - String o = (String) value; - if (o.isBlank()) return false; - return o.length() < MAX_LENGTH; - } + String o = (String) value; + if (o.isBlank()) return false; + return o.length() < MAX_LENGTH; + } - public String getValue() { - return value; - } + public String getValue() { + return value; + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/menu/domain/valueObject/MenuId.java b/resource-server/src/main/java/com/inhabas/api/domain/menu/domain/valueObject/MenuId.java index 199d83f9..baef2f47 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/menu/domain/valueObject/MenuId.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/menu/domain/valueObject/MenuId.java @@ -1,49 +1,52 @@ package com.inhabas.api.domain.menu.domain.valueObject; -import com.fasterxml.jackson.annotation.JsonProperty; import java.io.Serializable; import java.util.Objects; + import javax.persistence.Column; import javax.persistence.Embeddable; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; + import lombok.AccessLevel; import lombok.NoArgsConstructor; +import com.fasterxml.jackson.annotation.JsonProperty; + @Embeddable @NoArgsConstructor(access = AccessLevel.PROTECTED) public class MenuId implements Serializable { - private static final long serialVersionUID = -7661257651938513762L; + private static final long serialVersionUID = -7661257651938513762L; - @JsonProperty("menuId") - @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "ID") - private Integer id; + @JsonProperty("menuId") + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "ID") + private Integer id; - public MenuId(Integer id) { - this.id = id; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - MenuId menuId = (MenuId) o; - return id.equals(menuId.id); - } + public MenuId(Integer id) { + this.id = id; + } - @Override - public int hashCode() { - return Objects.hash(id); + @Override + public boolean equals(Object o) { + if (this == o) { + return true; } - - @Override - public String toString() { - return String.valueOf(this.id); + if (o == null || getClass() != o.getClass()) { + return false; } + MenuId menuId = (MenuId) o; + return id.equals(menuId.id); + } + + @Override + public int hashCode() { + return Objects.hash(id); + } + + @Override + public String toString() { + return String.valueOf(this.id); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/menu/domain/valueObject/MenuName.java b/resource-server/src/main/java/com/inhabas/api/domain/menu/domain/valueObject/MenuName.java index ed330d31..f38f6084 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/menu/domain/valueObject/MenuName.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/menu/domain/valueObject/MenuName.java @@ -1,37 +1,35 @@ package com.inhabas.api.domain.menu.domain.valueObject; +import java.util.Objects; + import javax.persistence.Column; import javax.persistence.Embeddable; import javax.persistence.Transient; -import java.util.Objects; @Embeddable public class MenuName { - @Column(name = "NAME", length = 15, nullable = false) - private String value; + @Column(name = "NAME", length = 15, nullable = false) + private String value; - @Transient - private final int MAX_LENGTH = 15; + @Transient private final int MAX_LENGTH = 15; - public MenuName() {} + public MenuName() {} - public MenuName(String value) { - if (validate(value)) - this.value = value; - else - throw new IllegalArgumentException(); - } + public MenuName(String value) { + if (validate(value)) this.value = value; + else throw new IllegalArgumentException(); + } - private boolean validate(Object value) { - if (Objects.isNull(value)) return false; - if (!(value instanceof String)) return false; + private boolean validate(Object value) { + if (Objects.isNull(value)) return false; + if (!(value instanceof String)) return false; - String o = (String) value; - if (o.isBlank()) return false; - return o.length() < MAX_LENGTH; - } + String o = (String) value; + if (o.isBlank()) return false; + return o.length() < MAX_LENGTH; + } - public String getValue() { - return value; - } + public String getValue() { + return value; + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/menu/domain/valueObject/MenuType.java b/resource-server/src/main/java/com/inhabas/api/domain/menu/domain/valueObject/MenuType.java index 45adfc64..5ce6225f 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/menu/domain/valueObject/MenuType.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/menu/domain/valueObject/MenuType.java @@ -1,62 +1,67 @@ package com.inhabas.api.domain.menu.domain.valueObject; -import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.Role; +import static com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.Role.*; + import lombok.Getter; -import static com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.Role.*; +import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.Role; @Getter public enum MenuType { - // 관리자에 의해 추가, 삭제 불가능한 메뉴,(메뉴 순서와 이름만 변경가능하다.) - - // 동아리 소개 - INTRODUCE(ANONYMOUS, EXECUTIVES, ANONYMOUS, ADMIN, ADMIN), - // 동아리 활동 - ALBUM(ANONYMOUS, EXECUTIVES, ANONYMOUS, DEACTIVATED, ANONYMOUS), - // 명예의 전당 - HALL_OF_FAME(ANONYMOUS, ADMIN, ANONYMOUS, ADMIN, ADMIN), - // 공지사항 - NORMAL_NOTICE(DEACTIVATED, EXECUTIVES, DEACTIVATED, DEACTIVATED, DEACTIVATED), - // 자유게시판, 질문게시판, 건의 사항 - NORMAL_PUBLIC(DEACTIVATED, DEACTIVATED, DEACTIVATED, DEACTIVATED, DEACTIVATED), - // 공개 자료실 - NORMAL_STORAGE(ANONYMOUS, BASIC, ANONYMOUS, DEACTIVATED, ANONYMOUS), - // 회장단 게시판 - NORMAL_EXECUTIVES(SECRETARY, SECRETARY, SECRETARY, SECRETARY, SECRETARY), - // 강의 - LECTURE(BASIC, BASIC, BASIC, BASIC, BASIC), - // 스터디 - STUDY(BASIC, BASIC, BASIC, BASIC, BASIC), - // 취미활동 - HOBBY(BASIC, BASIC, BASIC, BASIC, BASIC), - // 대기중인 강의 관리 - LECTURE_EXECUTIVES(EXECUTIVES, ADMIN, EXECUTIVES, ADMIN, ADMIN), - // 지원금 신청 - BUDGET_SUPPORT(BASIC, BASIC, BASIC, ADMIN, ADMIN), - // 회계 내역 - BUDGET_ACCOUNT(DEACTIVATED, DEACTIVATED, DEACTIVATED, ADMIN, ADMIN), - // 알파테스터, 베타테스터 - TESTER(DEACTIVATED, BASIC, DEACTIVATED, DEACTIVATED, DEACTIVATED), - // 공모전 - CONTEST(ANONYMOUS, BASIC, ANONYMOUS, DEACTIVATED, BASIC), - - // 관리자가 추가, 삭제 가능한 메뉴.(NormalBoard 연관) - LIST(ANONYMOUS, ANONYMOUS, ANONYMOUS, ANONYMOUS, ANONYMOUS), // 리스트형 게시판 메뉴 - CARD(ANONYMOUS, ANONYMOUS, ANONYMOUS, ANONYMOUS, ANONYMOUS), // 카드형 게시판 메뉴 - ; - - private final Role readBoardListRole; - private final Role createBoardRole; - private final Role readBoardRole; - private final Role createCommentRole; - private final Role readCommentRole; - - MenuType(Role readBoardListRole, Role createBoardRole, Role readBoardRole, Role createCommentRole, Role readCommentRole) { - this.readBoardListRole = readBoardListRole; - this.createBoardRole = createBoardRole; - this.readBoardRole = readBoardRole; - this.createCommentRole = createCommentRole; - this.readCommentRole = readCommentRole; - } + // 관리자에 의해 추가, 삭제 불가능한 메뉴,(메뉴 순서와 이름만 변경가능하다.) + + // 동아리 소개 + INTRODUCE(ANONYMOUS, EXECUTIVES, ANONYMOUS, ADMIN, ADMIN), + // 동아리 활동 + ALBUM(ANONYMOUS, EXECUTIVES, ANONYMOUS, DEACTIVATED, ANONYMOUS), + // 명예의 전당 + HALL_OF_FAME(ANONYMOUS, ADMIN, ANONYMOUS, ADMIN, ADMIN), + // 공지사항 + NORMAL_NOTICE(DEACTIVATED, EXECUTIVES, DEACTIVATED, DEACTIVATED, DEACTIVATED), + // 자유게시판, 질문게시판, 건의 사항 + NORMAL_PUBLIC(DEACTIVATED, DEACTIVATED, DEACTIVATED, DEACTIVATED, DEACTIVATED), + // 공개 자료실 + NORMAL_STORAGE(ANONYMOUS, BASIC, ANONYMOUS, DEACTIVATED, ANONYMOUS), + // 회장단 게시판 + NORMAL_EXECUTIVES(SECRETARY, SECRETARY, SECRETARY, SECRETARY, SECRETARY), + // 강의 + LECTURE(BASIC, BASIC, BASIC, BASIC, BASIC), + // 스터디 + STUDY(BASIC, BASIC, BASIC, BASIC, BASIC), + // 취미활동 + HOBBY(BASIC, BASIC, BASIC, BASIC, BASIC), + // 대기중인 강의 관리 + LECTURE_EXECUTIVES(EXECUTIVES, ADMIN, EXECUTIVES, ADMIN, ADMIN), + // 지원금 신청 + BUDGET_SUPPORT(BASIC, BASIC, BASIC, ADMIN, ADMIN), + // 회계 내역 + BUDGET_ACCOUNT(DEACTIVATED, DEACTIVATED, DEACTIVATED, ADMIN, ADMIN), + // 알파테스터, 베타테스터 + TESTER(DEACTIVATED, BASIC, DEACTIVATED, DEACTIVATED, DEACTIVATED), + // 공모전 + CONTEST(ANONYMOUS, BASIC, ANONYMOUS, DEACTIVATED, BASIC), + + // 관리자가 추가, 삭제 가능한 메뉴.(NormalBoard 연관) + LIST(ANONYMOUS, ANONYMOUS, ANONYMOUS, ANONYMOUS, ANONYMOUS), // 리스트형 게시판 메뉴 + CARD(ANONYMOUS, ANONYMOUS, ANONYMOUS, ANONYMOUS, ANONYMOUS), // 카드형 게시판 메뉴 + ; + + private final Role readBoardListRole; + private final Role createBoardRole; + private final Role readBoardRole; + private final Role createCommentRole; + private final Role readCommentRole; + MenuType( + Role readBoardListRole, + Role createBoardRole, + Role readBoardRole, + Role createCommentRole, + Role readCommentRole) { + this.readBoardListRole = readBoardListRole; + this.createBoardRole = createBoardRole; + this.readBoardRole = readBoardRole; + this.createCommentRole = createCommentRole; + this.readCommentRole = readCommentRole; + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/menu/dto/MenuDto.java b/resource-server/src/main/java/com/inhabas/api/domain/menu/dto/MenuDto.java index e6634a14..fc474fcc 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/menu/dto/MenuDto.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/menu/dto/MenuDto.java @@ -1,46 +1,50 @@ package com.inhabas.api.domain.menu.dto; +import lombok.Getter; + import com.fasterxml.jackson.annotation.JsonUnwrapped; import com.inhabas.api.domain.menu.domain.Menu; import com.inhabas.api.domain.menu.domain.valueObject.MenuId; import com.inhabas.api.domain.menu.domain.valueObject.MenuType; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Getter; @Getter public class MenuDto { - @JsonUnwrapped - - @Schema(description = "메뉴의 고유 식별자", example = "1") - private MenuId id; - @Schema(description = "메뉴의 우선순위", example = "1") - private Integer priority; - @Schema(description = "메뉴의 이름", example = "동아리 소개") - private String name; - @Schema(description = "메뉴의 타입", example = "LIST") - private String type; - @Schema(description = "메뉴의 설명", example = "동아리 소개 메뉴입니다.") - private String description; - - public MenuDto(MenuId id, Integer priority, String name, MenuType type, String description) { - this.id = id; - this.priority = priority; - this.name = name; - this.type = type.toString(); - this.description = description; - } - - - public MenuDto(Integer id, Integer priority, String name, MenuType type, String description) { - this.id = new MenuId(id); - this.priority = priority; - this.name = name; - this.type = type.toString(); - this.description = description; - } - - public static MenuDto convert(Menu menu) { - return new MenuDto(menu.getId(), menu.getPriority(), menu.getName(), menu.getType(), menu.getDescription()); - } + @JsonUnwrapped + @Schema(description = "메뉴의 고유 식별자", example = "1") + private MenuId id; + + @Schema(description = "메뉴의 우선순위", example = "1") + private Integer priority; + + @Schema(description = "메뉴의 이름", example = "동아리 소개") + private String name; + + @Schema(description = "메뉴의 타입", example = "LIST") + private String type; + + @Schema(description = "메뉴의 설명", example = "동아리 소개 메뉴입니다.") + private String description; + + public MenuDto(MenuId id, Integer priority, String name, MenuType type, String description) { + this.id = id; + this.priority = priority; + this.name = name; + this.type = type.toString(); + this.description = description; + } + + public MenuDto(Integer id, Integer priority, String name, MenuType type, String description) { + this.id = new MenuId(id); + this.priority = priority; + this.name = name; + this.type = type.toString(); + this.description = description; + } + + public static MenuDto convert(Menu menu) { + return new MenuDto( + menu.getId(), menu.getPriority(), menu.getName(), menu.getType(), menu.getDescription()); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/menu/dto/MenuGroupDto.java b/resource-server/src/main/java/com/inhabas/api/domain/menu/dto/MenuGroupDto.java index 2e8d89dc..ef8c1a6a 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/menu/dto/MenuGroupDto.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/menu/dto/MenuGroupDto.java @@ -1,23 +1,23 @@ package com.inhabas.api.domain.menu.dto; -import com.fasterxml.jackson.annotation.JsonUnwrapped; +import java.util.List; + import lombok.Getter; -import java.util.List; +import com.fasterxml.jackson.annotation.JsonUnwrapped; @Getter public class MenuGroupDto { - private Integer id; + private Integer id; - private String groupName; + private String groupName; - @JsonUnwrapped - private List menuList; + @JsonUnwrapped private List menuList; - public MenuGroupDto(Integer id, String groupName, List menuList) { - this.id = id; - this.groupName = groupName; - this.menuList = menuList; - } + public MenuGroupDto(Integer id, String groupName, List menuList) { + this.id = id; + this.groupName = groupName; + this.menuList = menuList; + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/menu/repository/MenuGroupRepository.java b/resource-server/src/main/java/com/inhabas/api/domain/menu/repository/MenuGroupRepository.java index 35d4bd99..ca3ca03d 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/menu/repository/MenuGroupRepository.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/menu/repository/MenuGroupRepository.java @@ -1,7 +1,7 @@ package com.inhabas.api.domain.menu.repository; -import com.inhabas.api.domain.menu.domain.MenuGroup; import org.springframework.data.jpa.repository.JpaRepository; -public interface MenuGroupRepository extends JpaRepository { -} +import com.inhabas.api.domain.menu.domain.MenuGroup; + +public interface MenuGroupRepository extends JpaRepository {} diff --git a/resource-server/src/main/java/com/inhabas/api/domain/menu/repository/MenuRepository.java b/resource-server/src/main/java/com/inhabas/api/domain/menu/repository/MenuRepository.java index 21be1793..b00f9e6e 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/menu/repository/MenuRepository.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/menu/repository/MenuRepository.java @@ -1,11 +1,11 @@ package com.inhabas.api.domain.menu.repository; -import com.inhabas.api.domain.menu.domain.Menu; +import java.util.Optional; + import org.springframework.data.jpa.repository.JpaRepository; -import java.util.Optional; +import com.inhabas.api.domain.menu.domain.Menu; public interface MenuRepository extends JpaRepository, MenuRepositoryCustom { - Optional findByName_Value(String clubActivityMenuName); - + Optional findByName_Value(String clubActivityMenuName); } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/menu/repository/MenuRepositoryCustom.java b/resource-server/src/main/java/com/inhabas/api/domain/menu/repository/MenuRepositoryCustom.java index 70fcf697..aca619a4 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/menu/repository/MenuRepositoryCustom.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/menu/repository/MenuRepositoryCustom.java @@ -1,13 +1,14 @@ package com.inhabas.api.domain.menu.repository; +import java.util.List; +import java.util.Optional; + import com.inhabas.api.domain.menu.domain.Menu; import com.inhabas.api.domain.menu.domain.valueObject.MenuId; import com.inhabas.api.domain.menu.dto.MenuGroupDto; -import java.util.List; -import java.util.Optional; public interface MenuRepositoryCustom { - List findAllMenuByMenuGroup(); + List findAllMenuByMenuGroup(); - Optional findById(MenuId menuId); + Optional findById(MenuId menuId); } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/menu/repository/MenuRepositoryImpl.java b/resource-server/src/main/java/com/inhabas/api/domain/menu/repository/MenuRepositoryImpl.java index 54c2a3a0..d66d0225 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/menu/repository/MenuRepositoryImpl.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/menu/repository/MenuRepositoryImpl.java @@ -3,6 +3,12 @@ import static com.inhabas.api.domain.menu.domain.QMenu.menu; import static com.querydsl.core.group.GroupBy.list; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +import lombok.RequiredArgsConstructor; + import com.inhabas.api.domain.menu.domain.Menu; import com.inhabas.api.domain.menu.domain.valueObject.MenuId; import com.inhabas.api.domain.menu.dto.MenuDto; @@ -10,38 +16,43 @@ import com.querydsl.core.group.GroupBy; import com.querydsl.core.types.Projections; import com.querydsl.jpa.impl.JPAQueryFactory; -import java.util.List; -import java.util.Optional; -import java.util.stream.Collectors; -import lombok.RequiredArgsConstructor; @RequiredArgsConstructor public class MenuRepositoryImpl implements MenuRepositoryCustom { - private final JPAQueryFactory jpaQueryFactory; - - public List findAllMenuByMenuGroup() { - return jpaQueryFactory - .from(menu) - .orderBy(menu.menuGroup.id.asc()) - .orderBy(menu.priority.asc()) - .transform(GroupBy.groupBy(menu.menuGroup) - .as(list(Projections.constructor(MenuDto.class, - menu.id, - menu.priority, - menu.name.value, - menu.type, // enum type - menu.description.value))) - ).entrySet().stream() - .map(entry -> new MenuGroupDto(entry.getKey().getId(), entry.getKey().getName(), entry.getValue())) - .collect(Collectors.toList()); - } - - @Override - public Optional findById(MenuId menuId) { - return Optional.ofNullable( - jpaQueryFactory.selectFrom(menu) - .where(menu.id.eq(Integer.parseInt(menuId.toString()))) - .fetchOne()); - } + private final JPAQueryFactory jpaQueryFactory; + + public List findAllMenuByMenuGroup() { + return jpaQueryFactory + .from(menu) + .orderBy(menu.menuGroup.id.asc()) + .orderBy(menu.priority.asc()) + .transform( + GroupBy.groupBy(menu.menuGroup) + .as( + list( + Projections.constructor( + MenuDto.class, + menu.id, + menu.priority, + menu.name.value, + menu.type, // enum type + menu.description.value)))) + .entrySet() + .stream() + .map( + entry -> + new MenuGroupDto( + entry.getKey().getId(), entry.getKey().getName(), entry.getValue())) + .collect(Collectors.toList()); + } + + @Override + public Optional findById(MenuId menuId) { + return Optional.ofNullable( + jpaQueryFactory + .selectFrom(menu) + .where(menu.id.eq(Integer.parseInt(menuId.toString()))) + .fetchOne()); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/menu/usecase/MenuService.java b/resource-server/src/main/java/com/inhabas/api/domain/menu/usecase/MenuService.java index 1804a423..27b2eede 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/menu/usecase/MenuService.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/menu/usecase/MenuService.java @@ -1,14 +1,14 @@ package com.inhabas.api.domain.menu.usecase; +import java.util.List; + import com.inhabas.api.domain.menu.domain.valueObject.MenuId; import com.inhabas.api.domain.menu.dto.MenuDto; import com.inhabas.api.domain.menu.dto.MenuGroupDto; -import java.util.List; - public interface MenuService { - List getAllMenuInfo(); + List getAllMenuInfo(); - MenuDto getMenuInfoById(MenuId menuId); + MenuDto getMenuInfoById(MenuId menuId); } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/menu/usecase/MenuServiceImpl.java b/resource-server/src/main/java/com/inhabas/api/domain/menu/usecase/MenuServiceImpl.java index a41de2f8..b1d38c00 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/menu/usecase/MenuServiceImpl.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/menu/usecase/MenuServiceImpl.java @@ -1,36 +1,38 @@ package com.inhabas.api.domain.menu.usecase; +import java.util.List; + +import lombok.RequiredArgsConstructor; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + import com.inhabas.api.auth.domain.error.businessException.NotFoundException; import com.inhabas.api.domain.menu.domain.Menu; import com.inhabas.api.domain.menu.domain.valueObject.MenuId; -import com.inhabas.api.domain.menu.repository.MenuRepository; import com.inhabas.api.domain.menu.dto.MenuDto; import com.inhabas.api.domain.menu.dto.MenuGroupDto; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.util.List; +import com.inhabas.api.domain.menu.repository.MenuRepository; @Service @RequiredArgsConstructor public class MenuServiceImpl implements MenuService { - private final MenuRepository menuRepository; + private final MenuRepository menuRepository; - @Override - @Transactional(readOnly = true) - public List getAllMenuInfo() { - return menuRepository.findAllMenuByMenuGroup(); - } + @Override + @Transactional(readOnly = true) + public List getAllMenuInfo() { + return menuRepository.findAllMenuByMenuGroup(); + } - @Override - @Transactional(readOnly = true) - public MenuDto getMenuInfoById(MenuId menuId) { + @Override + @Transactional(readOnly = true) + public MenuDto getMenuInfoById(MenuId menuId) { - Menu menu = menuRepository.findById(menuId) - .orElseThrow(NotFoundException::new); + Menu menu = menuRepository.findById(menuId).orElseThrow(NotFoundException::new); - return new MenuDto(menuId, menu.getPriority(), menu.getName(), menu.getType(), menu.getDescription()); - } + return new MenuDto( + menuId, menu.getPriority(), menu.getName(), menu.getType(), menu.getDescription()); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/policy/domain/PolicyTerm.java b/resource-server/src/main/java/com/inhabas/api/domain/policy/domain/PolicyTerm.java index cad7768a..4830c4fc 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/policy/domain/PolicyTerm.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/policy/domain/PolicyTerm.java @@ -1,14 +1,15 @@ package com.inhabas.api.domain.policy.domain; -import com.inhabas.api.domain.BaseEntity; -import com.inhabas.api.domain.board.domain.valueObject.Content; -import com.inhabas.api.domain.policy.dto.SavePolicyTernDto; +import javax.persistence.*; + import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; -import javax.persistence.*; +import com.inhabas.api.domain.BaseEntity; +import com.inhabas.api.domain.board.domain.valueObject.Content; +import com.inhabas.api.domain.policy.dto.SavePolicyTernDto; @Entity @NoArgsConstructor(access = AccessLevel.PROTECTED) @@ -16,25 +17,23 @@ @Getter public class PolicyTerm extends BaseEntity { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @ManyToOne(fetch = FetchType.LAZY, optional = false) - @JoinColumn(name = "POLICY_TYPE_ID") - private PolicyType policyType; + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; - @Embedded - private Content content; + @ManyToOne(fetch = FetchType.LAZY, optional = false) + @JoinColumn(name = "POLICY_TYPE_ID") + private PolicyType policyType; - @Builder - public PolicyTerm(PolicyType policyType, String content) { - this.policyType = policyType; - this.content = new Content(content); - } + @Embedded private Content content; - public void updatePolicyTerm(SavePolicyTernDto savePolicyTernDto) { - this.content = new Content(savePolicyTernDto.getContent()); - } + @Builder + public PolicyTerm(PolicyType policyType, String content) { + this.policyType = policyType; + this.content = new Content(content); + } + public void updatePolicyTerm(SavePolicyTernDto savePolicyTernDto) { + this.content = new Content(savePolicyTernDto.getContent()); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/policy/domain/PolicyType.java b/resource-server/src/main/java/com/inhabas/api/domain/policy/domain/PolicyType.java index fc7f0f86..53e576c2 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/policy/domain/PolicyType.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/policy/domain/PolicyType.java @@ -1,26 +1,26 @@ package com.inhabas.api.domain.policy.domain; -import com.inhabas.api.domain.board.domain.valueObject.Title; +import javax.persistence.*; + import lombok.AccessLevel; import lombok.Getter; import lombok.NoArgsConstructor; -import javax.persistence.*; +import com.inhabas.api.domain.board.domain.valueObject.Title; @Entity @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) public class PolicyType { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @Column(name = "TITLE") - private Title title; + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; - public PolicyType(String title) { - this.title = new Title(title); - } + @Column(name = "TITLE") + private Title title; + public PolicyType(String title) { + this.title = new Title(title); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/policy/dto/PolicyTermDto.java b/resource-server/src/main/java/com/inhabas/api/domain/policy/dto/PolicyTermDto.java index 0484afc3..99c07118 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/policy/dto/PolicyTermDto.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/policy/dto/PolicyTermDto.java @@ -1,25 +1,22 @@ package com.inhabas.api.domain.policy.dto; +import javax.validation.constraints.NotNull; + import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; -import javax.validation.constraints.NotNull; - @Getter @NoArgsConstructor public class PolicyTermDto { - @NotNull - private String title; - - @NotNull - private String content; + @NotNull private String title; - @Builder - public PolicyTermDto(String title, String content) { - this.title = title; - this.content = content; - } + @NotNull private String content; + @Builder + public PolicyTermDto(String title, String content) { + this.title = title; + this.content = content; + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/policy/dto/SavePolicyTernDto.java b/resource-server/src/main/java/com/inhabas/api/domain/policy/dto/SavePolicyTernDto.java index 1f7d91ff..7c97a62a 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/policy/dto/SavePolicyTernDto.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/policy/dto/SavePolicyTernDto.java @@ -1,21 +1,19 @@ package com.inhabas.api.domain.policy.dto; +import javax.validation.constraints.NotNull; + import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; -import javax.validation.constraints.NotNull; - @Getter @NoArgsConstructor public class SavePolicyTernDto { - @NotNull - private String content; - - @Builder - public SavePolicyTernDto(String content) { - this.content = content; - } + @NotNull private String content; + @Builder + public SavePolicyTernDto(String content) { + this.content = content; + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/policy/respository/PolicyTermRepository.java b/resource-server/src/main/java/com/inhabas/api/domain/policy/respository/PolicyTermRepository.java index 2df87b15..5b027db5 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/policy/respository/PolicyTermRepository.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/policy/respository/PolicyTermRepository.java @@ -1,7 +1,7 @@ package com.inhabas.api.domain.policy.respository; -import com.inhabas.api.domain.policy.domain.PolicyTerm; import org.springframework.data.jpa.repository.JpaRepository; -public interface PolicyTermRepository extends JpaRepository { -} +import com.inhabas.api.domain.policy.domain.PolicyTerm; + +public interface PolicyTermRepository extends JpaRepository {} diff --git a/resource-server/src/main/java/com/inhabas/api/domain/policy/usecase/PolicyTermService.java b/resource-server/src/main/java/com/inhabas/api/domain/policy/usecase/PolicyTermService.java index 7e6d5b59..563d0d13 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/policy/usecase/PolicyTermService.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/policy/usecase/PolicyTermService.java @@ -5,8 +5,7 @@ public interface PolicyTermService { - PolicyTermDto findPolicyTerm(Long policyTermId); - - void updatePolicyTerm(Long policyTermId, SavePolicyTernDto savePolicyTernDto); + PolicyTermDto findPolicyTerm(Long policyTermId); + void updatePolicyTerm(Long policyTermId, SavePolicyTernDto savePolicyTernDto); } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/policy/usecase/PolicyTermServiceImpl.java b/resource-server/src/main/java/com/inhabas/api/domain/policy/usecase/PolicyTermServiceImpl.java index 6f86d2d9..b1f8e052 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/policy/usecase/PolicyTermServiceImpl.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/policy/usecase/PolicyTermServiceImpl.java @@ -1,40 +1,41 @@ package com.inhabas.api.domain.policy.usecase; +import lombok.RequiredArgsConstructor; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + import com.inhabas.api.auth.domain.error.businessException.NotFoundException; import com.inhabas.api.domain.policy.domain.PolicyTerm; import com.inhabas.api.domain.policy.dto.PolicyTermDto; import com.inhabas.api.domain.policy.dto.SavePolicyTernDto; import com.inhabas.api.domain.policy.respository.PolicyTermRepository; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; @Service @RequiredArgsConstructor -public class PolicyTermServiceImpl implements PolicyTermService{ - - private final PolicyTermRepository policyTermRepository; - - @Override - @Transactional(readOnly = true) - public PolicyTermDto findPolicyTerm(Long policyTermId) { - - PolicyTerm policyTerm = policyTermRepository.findById(policyTermId).orElseThrow(NotFoundException::new); +public class PolicyTermServiceImpl implements PolicyTermService { - return PolicyTermDto.builder() - .title(policyTerm.getPolicyType().getTitle().getValue()) - .content(policyTerm.getContent().getValue()) - .build(); + private final PolicyTermRepository policyTermRepository; - } + @Override + @Transactional(readOnly = true) + public PolicyTermDto findPolicyTerm(Long policyTermId) { - @Override - @Transactional - public void updatePolicyTerm(Long policyTermId, SavePolicyTernDto savePolicyTernDto) { + PolicyTerm policyTerm = + policyTermRepository.findById(policyTermId).orElseThrow(NotFoundException::new); - PolicyTerm policyTerm = policyTermRepository.findById(policyTermId).orElseThrow(NotFoundException::new); - policyTerm.updatePolicyTerm(savePolicyTernDto); + return PolicyTermDto.builder() + .title(policyTerm.getPolicyType().getTitle().getValue()) + .content(policyTerm.getContent().getValue()) + .build(); + } - } + @Override + @Transactional + public void updatePolicyTerm(Long policyTermId, SavePolicyTernDto savePolicyTernDto) { + PolicyTerm policyTerm = + policyTermRepository.findById(policyTermId).orElseThrow(NotFoundException::new); + policyTerm.updatePolicyTerm(savePolicyTernDto); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/questionnaire/domain/Questionnaire.java b/resource-server/src/main/java/com/inhabas/api/domain/questionnaire/domain/Questionnaire.java index 6472b38f..14289ce8 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/questionnaire/domain/Questionnaire.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/questionnaire/domain/Questionnaire.java @@ -1,24 +1,26 @@ package com.inhabas.api.domain.questionnaire.domain; +import javax.persistence.*; + import lombok.AccessLevel; import lombok.Getter; import lombok.NoArgsConstructor; -import javax.persistence.*; - -@Entity @Getter +@Entity +@Getter @Table(name = "QUESTIONNAIRE") @NoArgsConstructor(access = AccessLevel.PROTECTED) public class Questionnaire { - @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; - @Column(name = "QUESTION", nullable = false) - private String question; + @Column(name = "QUESTION", nullable = false) + private String question; - public Questionnaire(Long id, String question) { - this.id = id; - this.question = question; - } + public Questionnaire(Long id, String question) { + this.id = id; + this.question = question; + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/questionnaire/dto/QuestionnaireDto.java b/resource-server/src/main/java/com/inhabas/api/domain/questionnaire/dto/QuestionnaireDto.java index b09d192c..c9cb310f 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/questionnaire/dto/QuestionnaireDto.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/questionnaire/dto/QuestionnaireDto.java @@ -9,8 +9,7 @@ @AllArgsConstructor public class QuestionnaireDto { - private Long id; - - private String question; + private Long id; + private String question; } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/questionnaire/repository/QuestionnaireRepository.java b/resource-server/src/main/java/com/inhabas/api/domain/questionnaire/repository/QuestionnaireRepository.java index e7c53b58..a12de5d2 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/questionnaire/repository/QuestionnaireRepository.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/questionnaire/repository/QuestionnaireRepository.java @@ -1,12 +1,12 @@ package com.inhabas.api.domain.questionnaire.repository; -import com.inhabas.api.domain.questionnaire.domain.Questionnaire; +import java.util.List; + import org.springframework.data.jpa.repository.JpaRepository; -import java.util.List; +import com.inhabas.api.domain.questionnaire.domain.Questionnaire; public interface QuestionnaireRepository extends JpaRepository { - Long countByIdIn(List idList); - + Long countByIdIn(List idList); } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/questionnaire/usecase/QuestionnaireService.java b/resource-server/src/main/java/com/inhabas/api/domain/questionnaire/usecase/QuestionnaireService.java index 63902fcf..11b5f063 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/questionnaire/usecase/QuestionnaireService.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/questionnaire/usecase/QuestionnaireService.java @@ -1,10 +1,10 @@ package com.inhabas.api.domain.questionnaire.usecase; -import com.inhabas.api.domain.questionnaire.dto.QuestionnaireDto; - import java.util.List; +import com.inhabas.api.domain.questionnaire.dto.QuestionnaireDto; + public interface QuestionnaireService { - List getQuestionnaire(); + List getQuestionnaire(); } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/questionnaire/usecase/QuestionnaireServiceImpl.java b/resource-server/src/main/java/com/inhabas/api/domain/questionnaire/usecase/QuestionnaireServiceImpl.java index 2e4c5a9c..d9f101d6 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/questionnaire/usecase/QuestionnaireServiceImpl.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/questionnaire/usecase/QuestionnaireServiceImpl.java @@ -1,25 +1,27 @@ package com.inhabas.api.domain.questionnaire.usecase; -import com.inhabas.api.domain.questionnaire.repository.QuestionnaireRepository; -import com.inhabas.api.domain.questionnaire.dto.QuestionnaireDto; +import java.util.List; +import java.util.stream.Collectors; + import lombok.RequiredArgsConstructor; + import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.List; -import java.util.stream.Collectors; +import com.inhabas.api.domain.questionnaire.dto.QuestionnaireDto; +import com.inhabas.api.domain.questionnaire.repository.QuestionnaireRepository; @Service @RequiredArgsConstructor public class QuestionnaireServiceImpl implements QuestionnaireService { - private final QuestionnaireRepository questionnaireRepository; + private final QuestionnaireRepository questionnaireRepository; - @Transactional(readOnly = true) - public List getQuestionnaire() { + @Transactional(readOnly = true) + public List getQuestionnaire() { - return questionnaireRepository.findAll().stream() - .map(q->new QuestionnaireDto(q.getId(), q.getQuestion())) - .collect(Collectors.toList()); - } + return questionnaireRepository.findAll().stream() + .map(q -> new QuestionnaireDto(q.getId(), q.getQuestion())) + .collect(Collectors.toList()); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/signUp/domain/entity/Answer.java b/resource-server/src/main/java/com/inhabas/api/domain/signUp/domain/entity/Answer.java index fc8f366a..1c15be97 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/signUp/domain/entity/Answer.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/signUp/domain/entity/Answer.java @@ -1,44 +1,50 @@ package com.inhabas.api.domain.signUp.domain.entity; -import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; -import com.inhabas.api.domain.BaseEntity; -import com.inhabas.api.domain.questionnaire.domain.Questionnaire; +import javax.persistence.*; + import lombok.AccessLevel; import lombok.Getter; import lombok.NoArgsConstructor; -import javax.persistence.*; +import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; +import com.inhabas.api.domain.BaseEntity; +import com.inhabas.api.domain.questionnaire.domain.Questionnaire; @Entity - @Table(name = "ANSWER", - uniqueConstraints = { @UniqueConstraint(name = "UNIQUE_USER_ID_QUESTIONNAIRE_ID", - columnNames = {"USER_ID", "QUESTIONNAIRE_ID"})}) +@Table( + name = "ANSWER", + uniqueConstraints = { + @UniqueConstraint( + name = "UNIQUE_USER_ID_QUESTIONNAIRE_ID", + columnNames = {"USER_ID", "QUESTIONNAIRE_ID"}) + }) @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) public class Answer extends BaseEntity { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @ManyToOne(fetch = FetchType.LAZY, optional = false) - @JoinColumn(name = "USER_ID", foreignKey = @ForeignKey(name = "FK_ANSWER_OF_MEMBER")) - private Member member; - - @ManyToOne(fetch = FetchType.LAZY, optional = false) - @JoinColumn(name = "QUESTIONNAIRE_ID", foreignKey = @ForeignKey(name = "FK_ANSWER_OF_QUESTION_ID")) - private Questionnaire questionnaire; - - @Column(name = "CONTENT", length = 1000) - private String content; - - public void setContent(String content) { - this.content = content; - } - - - public Answer(Member member, Questionnaire questionnaire, String content) { - this.member = member; - this.questionnaire = questionnaire; - this.content = content; - } + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY, optional = false) + @JoinColumn(name = "USER_ID", foreignKey = @ForeignKey(name = "FK_ANSWER_OF_MEMBER")) + private Member member; + + @ManyToOne(fetch = FetchType.LAZY, optional = false) + @JoinColumn( + name = "QUESTIONNAIRE_ID", + foreignKey = @ForeignKey(name = "FK_ANSWER_OF_QUESTION_ID")) + private Questionnaire questionnaire; + + @Column(name = "CONTENT", length = 1000) + private String content; + + public void setContent(String content) { + this.content = content; + } + + public Answer(Member member, Questionnaire questionnaire, String content) { + this.member = member; + this.questionnaire = questionnaire; + this.content = content; + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/signUp/dto/AnswerDto.java b/resource-server/src/main/java/com/inhabas/api/domain/signUp/dto/AnswerDto.java index 3b94dc16..104946cd 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/signUp/dto/AnswerDto.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/signUp/dto/AnswerDto.java @@ -1,21 +1,20 @@ package com.inhabas.api.domain.signUp.dto; +import javax.validation.constraints.Positive; + import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; -import org.hibernate.validator.constraints.Length; -import javax.validation.constraints.Positive; +import org.hibernate.validator.constraints.Length; @Data @NoArgsConstructor @AllArgsConstructor public class AnswerDto { - @Positive - private Long questionId; - - @Length(max = 1000) - private String content; + @Positive private Long questionId; + @Length(max = 1000) + private String content; } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/signUp/dto/SignUpDto.java b/resource-server/src/main/java/com/inhabas/api/domain/signUp/dto/SignUpDto.java index 2dc987f8..25d43b4d 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/signUp/dto/SignUpDto.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/signUp/dto/SignUpDto.java @@ -1,55 +1,64 @@ package com.inhabas.api.domain.signUp.dto; -import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.MemberType; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; -import org.hibernate.validator.constraints.Length; - import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; import javax.validation.constraints.Pattern; import javax.validation.constraints.Positive; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.MemberType; +import io.swagger.v3.oas.annotations.media.Schema; +import org.hibernate.validator.constraints.Length; + @Data @NoArgsConstructor public class SignUpDto { - @NotBlank - @Length(max = 50) - @Schema(example = "조승현") - private String name; - - @NotBlank - @Length(max = 50) - @Schema(example = "컴퓨터공학과") - private String major; - - @Pattern(regexp = "^(010)-\\d{4}-\\d{4}$") - @Schema(example = "010-0101-0101") - private String phoneNumber; - - @NotNull - @Pattern(regexp = "\\d+") - @Schema(example = "12171707") - private String studentId; - - @NotNull - @Schema(example = "UNDERGRADUATE", allowableValues = {"UNDERGRADUATE", "BACHELOR", "GRADUATED", "PROFESSOR", "OTHER"} ) - private MemberType memberType; - - @Positive - @Schema(example = "1") - private Integer grade; - - @Builder - public SignUpDto(String name, String major, String phoneNumber, String studentId, MemberType memberType, Integer grade) { - this.name = name; - this.major = major; - this.phoneNumber = phoneNumber; - this.studentId = studentId; - this.memberType = memberType; - this.grade = grade; - } + @NotBlank + @Length(max = 50) + @Schema(example = "조승현") + private String name; + + @NotBlank + @Length(max = 50) + @Schema(example = "컴퓨터공학과") + private String major; + + @Pattern(regexp = "^(010)-\\d{4}-\\d{4}$") + @Schema(example = "010-0101-0101") + private String phoneNumber; + + @NotNull + @Pattern(regexp = "\\d+") + @Schema(example = "12171707") + private String studentId; + + @NotNull + @Schema( + example = "UNDERGRADUATE", + allowableValues = {"UNDERGRADUATE", "BACHELOR", "GRADUATED", "PROFESSOR", "OTHER"}) + private MemberType memberType; + + @Positive + @Schema(example = "1") + private Integer grade; + + @Builder + public SignUpDto( + String name, + String major, + String phoneNumber, + String studentId, + MemberType memberType, + Integer grade) { + this.name = name; + this.major = major; + this.phoneNumber = phoneNumber; + this.studentId = studentId; + this.memberType = memberType; + this.grade = grade; + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/signUp/exception/NotWriteAnswersException.java b/resource-server/src/main/java/com/inhabas/api/domain/signUp/exception/NotWriteAnswersException.java index 58f4c6e0..1e470fe3 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/signUp/exception/NotWriteAnswersException.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/signUp/exception/NotWriteAnswersException.java @@ -5,8 +5,7 @@ public class NotWriteAnswersException extends BusinessException { - public NotWriteAnswersException() { - super(ErrorCode.NOT_WRITE_ANSWERS); - } - -} \ No newline at end of file + public NotWriteAnswersException() { + super(ErrorCode.NOT_WRITE_ANSWERS); + } +} diff --git a/resource-server/src/main/java/com/inhabas/api/domain/signUp/exception/NotWriteProfileException.java b/resource-server/src/main/java/com/inhabas/api/domain/signUp/exception/NotWriteProfileException.java index 5e5ff406..1eb17136 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/signUp/exception/NotWriteProfileException.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/signUp/exception/NotWriteProfileException.java @@ -5,8 +5,7 @@ public class NotWriteProfileException extends BusinessException { - public NotWriteProfileException() { - super(ErrorCode.NOT_WRITE_PROFILE); - } - -} \ No newline at end of file + public NotWriteProfileException() { + super(ErrorCode.NOT_WRITE_PROFILE); + } +} diff --git a/resource-server/src/main/java/com/inhabas/api/domain/signUp/repository/AnswerRepository.java b/resource-server/src/main/java/com/inhabas/api/domain/signUp/repository/AnswerRepository.java index 3470bb45..bd103858 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/signUp/repository/AnswerRepository.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/signUp/repository/AnswerRepository.java @@ -1,12 +1,12 @@ package com.inhabas.api.domain.signUp.repository; -import com.inhabas.api.domain.signUp.domain.entity.Answer; +import java.util.List; + import org.springframework.data.jpa.repository.JpaRepository; -import java.util.List; +import com.inhabas.api.domain.signUp.domain.entity.Answer; public interface AnswerRepository extends JpaRepository { - List findByMember_Id(Long memberId); - + List findByMember_Id(Long memberId); } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/signUp/usecase/AnswerService.java b/resource-server/src/main/java/com/inhabas/api/domain/signUp/usecase/AnswerService.java index a58a5cfa..088cbd3b 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/signUp/usecase/AnswerService.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/signUp/usecase/AnswerService.java @@ -1,13 +1,12 @@ package com.inhabas.api.domain.signUp.usecase; -import com.inhabas.api.domain.signUp.dto.AnswerDto; - import java.util.List; -public interface AnswerService { +import com.inhabas.api.domain.signUp.dto.AnswerDto; - void saveAnswers(List submittedAnswers, Long memberId); +public interface AnswerService { - List getAnswers(Long memberId); + void saveAnswers(List submittedAnswers, Long memberId); + List getAnswers(Long memberId); } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/signUp/usecase/AnswerServiceImpl.java b/resource-server/src/main/java/com/inhabas/api/domain/signUp/usecase/AnswerServiceImpl.java index 15098a00..e3553200 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/signUp/usecase/AnswerServiceImpl.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/signUp/usecase/AnswerServiceImpl.java @@ -1,100 +1,110 @@ package com.inhabas.api.domain.signUp.usecase; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import javax.persistence.EntityNotFoundException; + +import lombok.RequiredArgsConstructor; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; import com.inhabas.api.auth.domain.oauth2.member.domain.exception.MemberNotFoundException; import com.inhabas.api.auth.domain.oauth2.member.repository.MemberRepository; +import com.inhabas.api.domain.questionnaire.domain.Questionnaire; +import com.inhabas.api.domain.questionnaire.repository.QuestionnaireRepository; import com.inhabas.api.domain.signUp.domain.entity.Answer; import com.inhabas.api.domain.signUp.dto.AnswerDto; import com.inhabas.api.domain.signUp.repository.AnswerRepository; -import com.inhabas.api.domain.questionnaire.domain.Questionnaire; -import com.inhabas.api.domain.questionnaire.repository.QuestionnaireRepository; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import javax.persistence.EntityNotFoundException; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; @Service @RequiredArgsConstructor public class AnswerServiceImpl implements AnswerService { - private final AnswerRepository answerRepository; - private final MemberRepository memberRepository; - private final QuestionnaireRepository questionnaireRepository; - - - @Override - @Transactional - public void saveAnswers(List submittedAnswers, Long memberId) { - - Member currentMember = memberRepository.findById(memberId).orElseThrow(MemberNotFoundException::new); - - this.questionnaireIdsCheck(submittedAnswers); - - // 기존 답변 가져오기 - Map existingAnswers = answerRepository.findByMember_Id(memberId).stream() - .collect(Collectors.toMap(answer -> answer.getQuestionnaire().getId(), answer -> answer)); - - // 새 답변 또는 업데이트된 답변 준비 - List answersToUpdate = submittedAnswers.stream() - .map(dto -> { - Questionnaire questionnaire = questionnaireRepository.findById(dto.getQuestionId()) - .orElseThrow(() -> new EntityNotFoundException("Questionnaire not found with id: " + dto.getQuestionId())); - - Answer existingAnswer = existingAnswers.get(dto.getQuestionId()); - if (existingAnswer != null) { - existingAnswer.setContent(dto.getContent()); - return existingAnswer; - } else { - return new Answer(currentMember, questionnaire, dto.getContent()); - } + private final AnswerRepository answerRepository; + private final MemberRepository memberRepository; + private final QuestionnaireRepository questionnaireRepository; + + @Override + @Transactional + public void saveAnswers(List submittedAnswers, Long memberId) { + + Member currentMember = + memberRepository.findById(memberId).orElseThrow(MemberNotFoundException::new); + + this.questionnaireIdsCheck(submittedAnswers); + + // 기존 답변 가져오기 + Map existingAnswers = + answerRepository.findByMember_Id(memberId).stream() + .collect( + Collectors.toMap(answer -> answer.getQuestionnaire().getId(), answer -> answer)); + + // 새 답변 또는 업데이트된 답변 준비 + List answersToUpdate = + submittedAnswers.stream() + .map( + dto -> { + Questionnaire questionnaire = + questionnaireRepository + .findById(dto.getQuestionId()) + .orElseThrow( + () -> + new EntityNotFoundException( + "Questionnaire not found with id: " + dto.getQuestionId())); + + Answer existingAnswer = existingAnswers.get(dto.getQuestionId()); + if (existingAnswer != null) { + existingAnswer.setContent(dto.getContent()); + return existingAnswer; + } else { + return new Answer(currentMember, questionnaire, dto.getContent()); + } }) - .collect(Collectors.toList()); + .collect(Collectors.toList()); - answerRepository.saveAll(answersToUpdate); + answerRepository.saveAll(answersToUpdate); + } - } - - private void questionnaireIdsCheck(List submittedAnswers) throws IllegalArgumentException{ - - List questionIds = submittedAnswers.stream() - .map(AnswerDto::getQuestionId) - .collect(Collectors.toList()); - - List questionnaireList = questionnaireRepository.findAll(); - List questionnaireIdList = questionnaireList.stream() - .map(Questionnaire::getId) - .collect(Collectors.toList()); - - if (questionnaireRepository.countByIdIn(questionIds) != questionnaireIdList.size()) { - throw new IllegalArgumentException("Some question IDs are invalid"); - } - } - - @Override - public List getAnswers(Long memberId) { - - Member member = memberRepository.findById(memberId).orElseThrow(MemberNotFoundException::new); + private void questionnaireIdsCheck(List submittedAnswers) + throws IllegalArgumentException { - List questionnaires = questionnaireRepository.findAll(); + List questionIds = + submittedAnswers.stream().map(AnswerDto::getQuestionId).collect(Collectors.toList()); - Map answersByQuestionnaire = answerRepository.findByMember_Id(memberId) - .stream() - .collect(Collectors.toMap( - answer -> answer.getQuestionnaire().getId(), - answer -> answer - )); + List questionnaireList = questionnaireRepository.findAll(); + List questionnaireIdList = + questionnaireList.stream().map(Questionnaire::getId).collect(Collectors.toList()); - return questionnaires.stream() - .map(questionnaire -> { - Long questionnaireId = questionnaire.getId(); - Answer answer = answersByQuestionnaire.getOrDefault(questionnaireId, new Answer(member, questionnaire, null)); - return new AnswerDto(questionnaireId, answer.getContent()); - }) - .collect(Collectors.toList()); + if (questionnaireRepository.countByIdIn(questionIds) != questionnaireIdList.size()) { + throw new IllegalArgumentException("Some question IDs are invalid"); } - + } + + @Override + public List getAnswers(Long memberId) { + + Member member = memberRepository.findById(memberId).orElseThrow(MemberNotFoundException::new); + + List questionnaires = questionnaireRepository.findAll(); + + Map answersByQuestionnaire = + answerRepository.findByMember_Id(memberId).stream() + .collect( + Collectors.toMap(answer -> answer.getQuestionnaire().getId(), answer -> answer)); + + return questionnaires.stream() + .map( + questionnaire -> { + Long questionnaireId = questionnaire.getId(); + Answer answer = + answersByQuestionnaire.getOrDefault( + questionnaireId, new Answer(member, questionnaire, null)); + return new AnswerDto(questionnaireId, answer.getContent()); + }) + .collect(Collectors.toList()); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/signUp/usecase/SignUpService.java b/resource-server/src/main/java/com/inhabas/api/domain/signUp/usecase/SignUpService.java index 7f5d5cd0..bb4ae155 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/signUp/usecase/SignUpService.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/signUp/usecase/SignUpService.java @@ -1,28 +1,27 @@ package com.inhabas.api.domain.signUp.usecase; +import java.util.List; + import com.inhabas.api.auth.domain.oauth2.majorInfo.dto.MajorInfoDto; +import com.inhabas.api.domain.questionnaire.dto.QuestionnaireDto; import com.inhabas.api.domain.signUp.dto.AnswerDto; import com.inhabas.api.domain.signUp.dto.SignUpDto; -import com.inhabas.api.domain.questionnaire.dto.QuestionnaireDto; - -import java.util.List; public interface SignUpService { - void saveSignUpForm(SignUpDto signUpDto, Long memberId); - - SignUpDto loadSignUpForm(Long memberId); + void saveSignUpForm(SignUpDto signUpDto, Long memberId); - void completeSignUp(List answerDtoList, Long memberId); + SignUpDto loadSignUpForm(Long memberId); - List getQuestionnaire(); + void completeSignUp(List answerDtoList, Long memberId); - void saveAnswers(List answerDtoList, Long memberId); + List getQuestionnaire(); - List getAnswers(Long memberId); + void saveAnswers(List answerDtoList, Long memberId); - List getMajorInfo(); + List getAnswers(Long memberId); - boolean isSignedUp(Long memberId); + List getMajorInfo(); + boolean isSignedUp(Long memberId); } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/signUp/usecase/SignUpServiceImpl.java b/resource-server/src/main/java/com/inhabas/api/domain/signUp/usecase/SignUpServiceImpl.java index fffdee61..4fba762c 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/signUp/usecase/SignUpServiceImpl.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/signUp/usecase/SignUpServiceImpl.java @@ -1,150 +1,157 @@ package com.inhabas.api.domain.signUp.usecase; +import static com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.MemberType.PROFESSOR; + +import java.util.List; + +import lombok.RequiredArgsConstructor; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + import com.inhabas.api.auth.domain.oauth2.majorInfo.dto.MajorInfoDto; import com.inhabas.api.auth.domain.oauth2.majorInfo.usecase.MajorInfoService; import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; import com.inhabas.api.auth.domain.oauth2.member.domain.exception.MemberNotFoundException; -import com.inhabas.api.auth.domain.oauth2.member.service.MemberService; import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.SchoolInformation; import com.inhabas.api.auth.domain.oauth2.member.repository.MemberRepository; +import com.inhabas.api.auth.domain.oauth2.member.service.MemberService; import com.inhabas.api.auth.domain.oauth2.socialAccount.domain.entity.MemberSocialAccount; import com.inhabas.api.auth.domain.oauth2.socialAccount.repository.MemberSocialAccountRepository; import com.inhabas.api.domain.questionnaire.dto.QuestionnaireDto; import com.inhabas.api.domain.questionnaire.usecase.QuestionnaireService; -import com.inhabas.api.domain.signUp.exception.NotWriteAnswersException; -import com.inhabas.api.domain.signUp.exception.NotWriteProfileException; import com.inhabas.api.domain.signUp.dto.AnswerDto; import com.inhabas.api.domain.signUp.dto.SignUpDto; +import com.inhabas.api.domain.signUp.exception.NotWriteAnswersException; +import com.inhabas.api.domain.signUp.exception.NotWriteProfileException; import com.inhabas.api.domain.signUpSchedule.usecase.SignUpScheduler; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.util.List; - -import static com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.MemberType.PROFESSOR; @Service @RequiredArgsConstructor public class SignUpServiceImpl implements SignUpService { - private final MajorInfoService majorInfoService; - private final MemberRepository memberRepository; - private final MemberSocialAccountRepository memberSocialAccountRepository; - private final MemberService memberService; - private final SignUpScheduler signUpScheduler; - private final QuestionnaireService questionnaireService; - private final AnswerService answerService; - - - @Override - @Transactional - public void saveSignUpForm(SignUpDto signUpForm, Long memberId) { - - Integer generation = signUpScheduler.getSchedule().getGeneration(); - Member member = memberRepository.findById(memberId).orElseThrow(MemberNotFoundException::new); - - member.setName(signUpForm.getName()); - member.setPhone(signUpForm.getPhoneNumber()); - member.setStudentId(signUpForm.getStudentId()); - - if (signUpForm.getGrade() != null) { - member.setSchoolInformation(new SchoolInformation(signUpForm.getMajor(), signUpForm.getGrade(), - generation, signUpForm.getMemberType())); - } else { - // 교수 - member.setSchoolInformation(new SchoolInformation(signUpForm.getMajor(), - generation, signUpForm.getMemberType())); - completeSignUp(null, memberId); - } - + private final MajorInfoService majorInfoService; + private final MemberRepository memberRepository; + private final MemberSocialAccountRepository memberSocialAccountRepository; + private final MemberService memberService; + private final SignUpScheduler signUpScheduler; + private final QuestionnaireService questionnaireService; + private final AnswerService answerService; + + @Override + @Transactional + public void saveSignUpForm(SignUpDto signUpForm, Long memberId) { + + Integer generation = signUpScheduler.getSchedule().getGeneration(); + Member member = memberRepository.findById(memberId).orElseThrow(MemberNotFoundException::new); + + member.setName(signUpForm.getName()); + member.setPhone(signUpForm.getPhoneNumber()); + member.setStudentId(signUpForm.getStudentId()); + + if (signUpForm.getGrade() != null) { + member.setSchoolInformation( + new SchoolInformation( + signUpForm.getMajor(), + signUpForm.getGrade(), + generation, + signUpForm.getMemberType())); + } else { + // 교수 + member.setSchoolInformation( + new SchoolInformation(signUpForm.getMajor(), generation, signUpForm.getMemberType())); + completeSignUp(null, memberId); } + } - @Override - public void completeSignUp(List answerDtoList, Long memberId) { - - Member member = memberRepository.findById(memberId).orElseThrow(MemberNotFoundException::new); - - if (notYetWroteProfile(member)) { - throw new NotWriteProfileException(); - } + @Override + public void completeSignUp(List answerDtoList, Long memberId) { - // 교수일 경우 이 과정 스킵 - if (member.getSchoolInformation().getMemberType() != PROFESSOR - && isContentNullInAnyDto(answerDtoList)) { - throw new NotWriteAnswersException(); - } else if (member.getSchoolInformation().getMemberType() != PROFESSOR - && !isContentNullInAnyDto(answerDtoList)) { - saveAnswers(answerDtoList, memberId); - } - - memberSocialAccountRepository.save(new MemberSocialAccount(member, member.getEmail(), - member.getUid().getValue(), member.getProvider())); - memberService.finishSignUp(member); + Member member = memberRepository.findById(memberId).orElseThrow(MemberNotFoundException::new); + if (notYetWroteProfile(member)) { + throw new NotWriteProfileException(); } - public boolean isContentNullInAnyDto(List answerDtoList) { - if (answerDtoList == null || answerDtoList.isEmpty()) { - return true; - } - for (AnswerDto dto : answerDtoList) { - if (dto.getContent() == null) { - return true; - } - } - return false; + // 교수일 경우 이 과정 스킵 + if (member.getSchoolInformation().getMemberType() != PROFESSOR + && isContentNullInAnyDto(answerDtoList)) { + throw new NotWriteAnswersException(); + } else if (member.getSchoolInformation().getMemberType() != PROFESSOR + && !isContentNullInAnyDto(answerDtoList)) { + saveAnswers(answerDtoList, memberId); } - private boolean notYetWroteProfile(Member member) { - - return member.getSchoolInformation() == null - || member.getSchoolInformation().getMemberType() == null - || member.getSchoolInformation().getMajor() == null - || member.getStudentId() == null || member.getPhone() == null; - - } + memberSocialAccountRepository.save( + new MemberSocialAccount( + member, member.getEmail(), member.getUid().getValue(), member.getProvider())); + memberService.finishSignUp(member); + } - @Override - public List getQuestionnaire() { - return questionnaireService.getQuestionnaire(); + public boolean isContentNullInAnyDto(List answerDtoList) { + if (answerDtoList == null || answerDtoList.isEmpty()) { + return true; } - - @Override - public void saveAnswers(List answerDtoList, Long memberId) { - answerService.saveAnswers(answerDtoList, memberId); + for (AnswerDto dto : answerDtoList) { + if (dto.getContent() == null) { + return true; + } } - - @Override - public List getAnswers(Long memberId) { - return answerService.getAnswers(memberId); - } - - @Override - public List getMajorInfo() { - return majorInfoService.getAllMajorInfo(); - } - - @Override - public boolean isSignedUp(Long memberId) { - return memberSocialAccountRepository.existsByMember_Id(memberId); - } - - @Override - @Transactional(readOnly = true) - public SignUpDto loadSignUpForm(Long memberId) { - - Member member = memberRepository.findById(memberId).orElseThrow(MemberNotFoundException::new); - - return SignUpDto.builder() - .studentId(member.getStudentId()) - .phoneNumber(member.getPhone()) - .name(member.getName()) - .major(member.getSchoolInformation() == null ? null : member.getSchoolInformation().getMajor()) - .memberType(member.getSchoolInformation() == null ? null : member.getSchoolInformation().getMemberType()) - .grade(member.getSchoolInformation() == null ? null : member.getSchoolInformation().getGrade()) - .build(); - - } - + return false; + } + + private boolean notYetWroteProfile(Member member) { + + return member.getSchoolInformation() == null + || member.getSchoolInformation().getMemberType() == null + || member.getSchoolInformation().getMajor() == null + || member.getStudentId() == null + || member.getPhone() == null; + } + + @Override + public List getQuestionnaire() { + return questionnaireService.getQuestionnaire(); + } + + @Override + public void saveAnswers(List answerDtoList, Long memberId) { + answerService.saveAnswers(answerDtoList, memberId); + } + + @Override + public List getAnswers(Long memberId) { + return answerService.getAnswers(memberId); + } + + @Override + public List getMajorInfo() { + return majorInfoService.getAllMajorInfo(); + } + + @Override + public boolean isSignedUp(Long memberId) { + return memberSocialAccountRepository.existsByMember_Id(memberId); + } + + @Override + @Transactional(readOnly = true) + public SignUpDto loadSignUpForm(Long memberId) { + + Member member = memberRepository.findById(memberId).orElseThrow(MemberNotFoundException::new); + + return SignUpDto.builder() + .studentId(member.getStudentId()) + .phoneNumber(member.getPhone()) + .name(member.getName()) + .major( + member.getSchoolInformation() == null ? null : member.getSchoolInformation().getMajor()) + .memberType( + member.getSchoolInformation() == null + ? null + : member.getSchoolInformation().getMemberType()) + .grade( + member.getSchoolInformation() == null ? null : member.getSchoolInformation().getGrade()) + .build(); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/signUpSchedule/domain/entity/SignUpSchedule.java b/resource-server/src/main/java/com/inhabas/api/domain/signUpSchedule/domain/entity/SignUpSchedule.java index c18ced88..2b28f7f6 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/signUpSchedule/domain/entity/SignUpSchedule.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/signUpSchedule/domain/entity/SignUpSchedule.java @@ -1,88 +1,107 @@ package com.inhabas.api.domain.signUpSchedule.domain.entity; -import com.inhabas.api.auth.domain.error.ErrorCode; -import com.inhabas.api.domain.signUpSchedule.exception.InvalidDateException; +import java.time.LocalDateTime; + +import javax.persistence.*; + import lombok.AccessLevel; import lombok.Getter; import lombok.NoArgsConstructor; -import javax.persistence.*; -import java.time.LocalDateTime; - +import com.inhabas.api.auth.domain.error.ErrorCode; +import com.inhabas.api.domain.signUpSchedule.exception.InvalidDateException; /** * This entity exists only one in database table. No reason for many entities.
* It's nothing but messy and confusing to create multiple signUpSchedule.
- * Be cautious not to make multi schedule or remove all the schedules. Do offer really necessary api. + * Be cautious not to make multi schedule or remove all the schedules. Do offer really necessary + * api. */ -@Entity @Getter +@Entity +@Getter @Table(name = "SIGNUP_SCHEDULE") @NoArgsConstructor(access = AccessLevel.PROTECTED) public class SignUpSchedule { - @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @Column(name = "GENERATION", nullable = false) - private Integer generation; - - @Column(name = "SIGNUP_START", nullable = false) - private LocalDateTime signupStartDate; - - @Column(name = "SIGNUP_END", nullable = false) - private LocalDateTime signupEndDate; - - @Column(name = "INTERVIEW_START", nullable = false) - private LocalDateTime interviewStartDate; - - @Column(name = "INTERVIEW_END", nullable = false) - private LocalDateTime interviewEndDate; - - @Column(name = "RESULT_ANNOUNCE_DATE", nullable = false) - private LocalDateTime resultAnnounceDate; - - public SignUpSchedule(Integer generation, LocalDateTime signupStartDate, LocalDateTime signupEndDate, - LocalDateTime interviewStartDate, LocalDateTime interviewEndDate, LocalDateTime resultAnnounceDate) { - - this.update(generation, signupStartDate, signupEndDate, interviewStartDate, interviewEndDate, resultAnnounceDate); - } - - public void update(Integer generation, LocalDateTime signupStartDate, LocalDateTime signupEndDate, - LocalDateTime interviewStartDate, LocalDateTime interviewEndDate, LocalDateTime resultAnnounceDate) { - this.generation = generation; - setSignUpDate(signupStartDate, signupEndDate); - setInterviewDate(interviewStartDate, interviewEndDate); - setResultAnnounceDate(signupEndDate, interviewEndDate, resultAnnounceDate); + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "GENERATION", nullable = false) + private Integer generation; + + @Column(name = "SIGNUP_START", nullable = false) + private LocalDateTime signupStartDate; + + @Column(name = "SIGNUP_END", nullable = false) + private LocalDateTime signupEndDate; + + @Column(name = "INTERVIEW_START", nullable = false) + private LocalDateTime interviewStartDate; + + @Column(name = "INTERVIEW_END", nullable = false) + private LocalDateTime interviewEndDate; + + @Column(name = "RESULT_ANNOUNCE_DATE", nullable = false) + private LocalDateTime resultAnnounceDate; + + public SignUpSchedule( + Integer generation, + LocalDateTime signupStartDate, + LocalDateTime signupEndDate, + LocalDateTime interviewStartDate, + LocalDateTime interviewEndDate, + LocalDateTime resultAnnounceDate) { + + this.update( + generation, + signupStartDate, + signupEndDate, + interviewStartDate, + interviewEndDate, + resultAnnounceDate); + } + + public void update( + Integer generation, + LocalDateTime signupStartDate, + LocalDateTime signupEndDate, + LocalDateTime interviewStartDate, + LocalDateTime interviewEndDate, + LocalDateTime resultAnnounceDate) { + this.generation = generation; + setSignUpDate(signupStartDate, signupEndDate); + setInterviewDate(interviewStartDate, interviewEndDate); + setResultAnnounceDate(signupEndDate, interviewEndDate, resultAnnounceDate); + } + + private void setSignUpDate(LocalDateTime signupStartDate, LocalDateTime signupEndDate) { + if (signupEndDate.isAfter(signupStartDate)) { + this.signupStartDate = signupStartDate; + this.signupEndDate = signupEndDate; + } else { + throw new InvalidDateException(ErrorCode.INVALID_SIGNUP_DATE); } - - private void setSignUpDate(LocalDateTime signupStartDate, LocalDateTime signupEndDate) { - if (signupEndDate.isAfter(signupStartDate)) { - this.signupStartDate = signupStartDate; - this.signupEndDate = signupEndDate; - } - else { - throw new InvalidDateException(ErrorCode.INVALID_SIGNUP_DATE); - } - } - - private void setInterviewDate(LocalDateTime interviewStartDate, LocalDateTime interviewEndDate) { - if (interviewEndDate.isAfter(interviewStartDate)) { - this.interviewStartDate = interviewStartDate; - this.interviewEndDate = interviewEndDate; - } - else { - throw new InvalidDateException(ErrorCode.INVALID_INTERVIEW_DATE); - } + } + + private void setInterviewDate(LocalDateTime interviewStartDate, LocalDateTime interviewEndDate) { + if (interviewEndDate.isAfter(interviewStartDate)) { + this.interviewStartDate = interviewStartDate; + this.interviewEndDate = interviewEndDate; + } else { + throw new InvalidDateException(ErrorCode.INVALID_INTERVIEW_DATE); } + } - private void setResultAnnounceDate( - LocalDateTime signupEndDate, LocalDateTime interviewEndDate, LocalDateTime resultAnnounceDate) { + private void setResultAnnounceDate( + LocalDateTime signupEndDate, + LocalDateTime interviewEndDate, + LocalDateTime resultAnnounceDate) { - if (resultAnnounceDate.isAfter(signupEndDate) && resultAnnounceDate.isAfter(interviewEndDate)) { - this.resultAnnounceDate = resultAnnounceDate; - } - else { - throw new InvalidDateException(ErrorCode.INVALID_ANNOUNCE_DATE); - } + if (resultAnnounceDate.isAfter(signupEndDate) && resultAnnounceDate.isAfter(interviewEndDate)) { + this.resultAnnounceDate = resultAnnounceDate; + } else { + throw new InvalidDateException(ErrorCode.INVALID_ANNOUNCE_DATE); } + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/signUpSchedule/dto/SignUpScheduleDto.java b/resource-server/src/main/java/com/inhabas/api/domain/signUpSchedule/dto/SignUpScheduleDto.java index bf1366dc..14ee407d 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/signUpSchedule/dto/SignUpScheduleDto.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/signUpSchedule/dto/SignUpScheduleDto.java @@ -1,57 +1,60 @@ package com.inhabas.api.domain.signUpSchedule.dto; -import com.fasterxml.jackson.annotation.JsonFormat; -import com.inhabas.api.domain.signUpSchedule.domain.entity.SignUpSchedule; -import io.swagger.v3.oas.annotations.media.Schema; +import java.time.LocalDateTime; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Positive; + import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; -import javax.validation.constraints.NotNull; -import javax.validation.constraints.Positive; -import java.time.LocalDateTime; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.inhabas.api.domain.signUpSchedule.domain.entity.SignUpSchedule; +import io.swagger.v3.oas.annotations.media.Schema; @Data @NoArgsConstructor @AllArgsConstructor public class SignUpScheduleDto { - @NotNull @Positive - @Schema(defaultValue = "1") - private Integer generation; - - @NotNull - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern="yyyy-MM-dd'T'HH:mm:ss") - @Schema(type="string" , example = "2023-11-01T00:00:00") - private LocalDateTime signupStartDate; - - @NotNull - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern="yyyy-MM-dd'T'HH:mm:ss") - @Schema(type="string" , example = "2024-11-01T00:00:00") - private LocalDateTime signupEndDate; - - @NotNull - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern="yyyy-MM-dd'T'HH:mm:ss") - @Schema(type="string" , example = "2024-11-01T00:00:00") - private LocalDateTime interviewStartDate; - - @NotNull - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern="yyyy-MM-dd'T'HH:mm:ss") - @Schema(type="string" , example = "2024-11-01T00:00:00") - private LocalDateTime interviewEndDate; - - @NotNull - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern="yyyy-MM-dd'T'HH:mm:ss") - @Schema(type="string" , example = "2024-11-01T00:00:00") - private LocalDateTime resultAnnounceDate; - - public static SignUpScheduleDto from(SignUpSchedule signUpSchedule) { - return new SignUpScheduleDto( - signUpSchedule.getGeneration(), - signUpSchedule.getSignupStartDate(), - signUpSchedule.getSignupEndDate(), - signUpSchedule.getInterviewStartDate(), - signUpSchedule.getInterviewEndDate(), - signUpSchedule.getResultAnnounceDate()); - } + @NotNull + @Positive + @Schema(defaultValue = "1") + private Integer generation; + + @NotNull + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss") + @Schema(type = "string", example = "2023-11-01T00:00:00") + private LocalDateTime signupStartDate; + + @NotNull + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss") + @Schema(type = "string", example = "2024-11-01T00:00:00") + private LocalDateTime signupEndDate; + + @NotNull + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss") + @Schema(type = "string", example = "2024-11-01T00:00:00") + private LocalDateTime interviewStartDate; + + @NotNull + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss") + @Schema(type = "string", example = "2024-11-01T00:00:00") + private LocalDateTime interviewEndDate; + + @NotNull + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss") + @Schema(type = "string", example = "2024-11-01T00:00:00") + private LocalDateTime resultAnnounceDate; + + public static SignUpScheduleDto from(SignUpSchedule signUpSchedule) { + return new SignUpScheduleDto( + signUpSchedule.getGeneration(), + signUpSchedule.getSignupStartDate(), + signUpSchedule.getSignupEndDate(), + signUpSchedule.getInterviewStartDate(), + signUpSchedule.getInterviewEndDate(), + signUpSchedule.getResultAnnounceDate()); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/signUpSchedule/exception/InvalidDateException.java b/resource-server/src/main/java/com/inhabas/api/domain/signUpSchedule/exception/InvalidDateException.java index aa32cf46..e76d8f7b 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/signUpSchedule/exception/InvalidDateException.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/signUpSchedule/exception/InvalidDateException.java @@ -5,8 +5,7 @@ public class InvalidDateException extends BusinessException { - public InvalidDateException(ErrorCode errorCode) { - super(errorCode); - } - + public InvalidDateException(ErrorCode errorCode) { + super(errorCode); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/signUpSchedule/exception/SignUpNotAvailableException.java b/resource-server/src/main/java/com/inhabas/api/domain/signUpSchedule/exception/SignUpNotAvailableException.java index 0e099a29..a5339773 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/signUpSchedule/exception/SignUpNotAvailableException.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/signUpSchedule/exception/SignUpNotAvailableException.java @@ -5,8 +5,7 @@ public class SignUpNotAvailableException extends BusinessException { - public SignUpNotAvailableException() { - super(ErrorCode.SIGNUP_NOT_AVAILABLE); - } - + public SignUpNotAvailableException() { + super(ErrorCode.SIGNUP_NOT_AVAILABLE); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/signUpSchedule/repository/SignUpScheduleRepository.java b/resource-server/src/main/java/com/inhabas/api/domain/signUpSchedule/repository/SignUpScheduleRepository.java index 5fa2c4d6..c3cd513f 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/signUpSchedule/repository/SignUpScheduleRepository.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/signUpSchedule/repository/SignUpScheduleRepository.java @@ -1,7 +1,7 @@ package com.inhabas.api.domain.signUpSchedule.repository; -import com.inhabas.api.domain.signUpSchedule.domain.entity.SignUpSchedule; import org.springframework.data.jpa.repository.JpaRepository; -public interface SignUpScheduleRepository extends JpaRepository { -} +import com.inhabas.api.domain.signUpSchedule.domain.entity.SignUpSchedule; + +public interface SignUpScheduleRepository extends JpaRepository {} diff --git a/resource-server/src/main/java/com/inhabas/api/domain/signUpSchedule/usecase/SignUpAvailabilityChecker.java b/resource-server/src/main/java/com/inhabas/api/domain/signUpSchedule/usecase/SignUpAvailabilityChecker.java index 44fbfc33..1c661d44 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/signUpSchedule/usecase/SignUpAvailabilityChecker.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/signUpSchedule/usecase/SignUpAvailabilityChecker.java @@ -2,5 +2,5 @@ public interface SignUpAvailabilityChecker { - boolean isAvailable(); + boolean isAvailable(); } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/signUpSchedule/usecase/SignUpAvailabilityCheckerImpl.java b/resource-server/src/main/java/com/inhabas/api/domain/signUpSchedule/usecase/SignUpAvailabilityCheckerImpl.java index 76e9bd45..2436e9c7 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/signUpSchedule/usecase/SignUpAvailabilityCheckerImpl.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/signUpSchedule/usecase/SignUpAvailabilityCheckerImpl.java @@ -1,20 +1,23 @@ package com.inhabas.api.domain.signUpSchedule.usecase; -import com.inhabas.api.domain.signUpSchedule.dto.SignUpScheduleDto; import java.time.LocalDateTime; + import lombok.RequiredArgsConstructor; + import org.springframework.stereotype.Component; +import com.inhabas.api.domain.signUpSchedule.dto.SignUpScheduleDto; + @Component @RequiredArgsConstructor public class SignUpAvailabilityCheckerImpl implements SignUpAvailabilityChecker { - private final SignUpScheduler signUpScheduler; + private final SignUpScheduler signUpScheduler; - public boolean isAvailable() { - SignUpScheduleDto schedule = signUpScheduler.getSchedule(); - LocalDateTime now = LocalDateTime.now(); + public boolean isAvailable() { + SignUpScheduleDto schedule = signUpScheduler.getSchedule(); + LocalDateTime now = LocalDateTime.now(); - return schedule.getSignupStartDate().isBefore(now) && schedule.getSignupEndDate().isAfter(now); - } + return schedule.getSignupStartDate().isBefore(now) && schedule.getSignupEndDate().isAfter(now); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/signUpSchedule/usecase/SignUpScheduler.java b/resource-server/src/main/java/com/inhabas/api/domain/signUpSchedule/usecase/SignUpScheduler.java index e2f09c2d..c7e662cb 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/signUpSchedule/usecase/SignUpScheduler.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/signUpSchedule/usecase/SignUpScheduler.java @@ -2,10 +2,9 @@ import com.inhabas.api.domain.signUpSchedule.dto.SignUpScheduleDto; - public interface SignUpScheduler { - void updateSchedule(SignUpScheduleDto signUpScheduleDto); + void updateSchedule(SignUpScheduleDto signUpScheduleDto); - SignUpScheduleDto getSchedule(); + SignUpScheduleDto getSchedule(); } diff --git a/resource-server/src/main/java/com/inhabas/api/domain/signUpSchedule/usecase/SignUpSchedulerStrict.java b/resource-server/src/main/java/com/inhabas/api/domain/signUpSchedule/usecase/SignUpSchedulerStrict.java index 06d4f737..5e6cda25 100644 --- a/resource-server/src/main/java/com/inhabas/api/domain/signUpSchedule/usecase/SignUpSchedulerStrict.java +++ b/resource-server/src/main/java/com/inhabas/api/domain/signUpSchedule/usecase/SignUpSchedulerStrict.java @@ -1,89 +1,89 @@ package com.inhabas.api.domain.signUpSchedule.usecase; -import com.inhabas.api.domain.signUpSchedule.domain.entity.SignUpSchedule; -import com.inhabas.api.domain.signUpSchedule.dto.SignUpScheduleDto; -import com.inhabas.api.domain.signUpSchedule.repository.SignUpScheduleRepository; +import java.time.LocalDateTime; + import lombok.RequiredArgsConstructor; + import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.time.LocalDateTime; +import com.inhabas.api.domain.signUpSchedule.domain.entity.SignUpSchedule; +import com.inhabas.api.domain.signUpSchedule.dto.SignUpScheduleDto; +import com.inhabas.api.domain.signUpSchedule.repository.SignUpScheduleRepository; -/** - * This Scheduler has a strict duty to leave only one signup-schedule. - */ +/** This Scheduler has a strict duty to leave only one signup-schedule. */ @Service @RequiredArgsConstructor public class SignUpSchedulerStrict implements SignUpScheduler { - private final SignUpScheduleRepository scheduleRepository; + private final SignUpScheduleRepository scheduleRepository; - @Override - @Transactional - public void updateSchedule(SignUpScheduleDto signUpScheduleDto) { - this.clearDirtySchedules(); - SignUpSchedule signUpSchedule = this.getScheduleEntity(); - signUpSchedule.update( - signUpScheduleDto.getGeneration(), - signUpScheduleDto.getSignupStartDate(), - signUpScheduleDto.getSignupEndDate(), - signUpScheduleDto.getInterviewStartDate(), - signUpScheduleDto.getInterviewEndDate(), - signUpScheduleDto.getResultAnnounceDate()); - scheduleRepository.save(signUpSchedule); - } + @Override + @Transactional + public void updateSchedule(SignUpScheduleDto signUpScheduleDto) { + this.clearDirtySchedules(); + SignUpSchedule signUpSchedule = this.getScheduleEntity(); + signUpSchedule.update( + signUpScheduleDto.getGeneration(), + signUpScheduleDto.getSignupStartDate(), + signUpScheduleDto.getSignupEndDate(), + signUpScheduleDto.getInterviewStartDate(), + signUpScheduleDto.getInterviewEndDate(), + signUpScheduleDto.getResultAnnounceDate()); + scheduleRepository.save(signUpSchedule); + } - @Override - public SignUpScheduleDto getSchedule() { - SignUpSchedule signUpSchedule = this.getScheduleEntity(); + @Override + public SignUpScheduleDto getSchedule() { + SignUpSchedule signUpSchedule = this.getScheduleEntity(); - return new SignUpScheduleDto( - signUpSchedule.getGeneration(), - signUpSchedule.getSignupStartDate(), - signUpSchedule.getSignupEndDate(), - signUpSchedule.getInterviewStartDate(), - signUpSchedule.getInterviewEndDate(), - signUpSchedule.getResultAnnounceDate()); - } + return new SignUpScheduleDto( + signUpSchedule.getGeneration(), + signUpSchedule.getSignupStartDate(), + signUpSchedule.getSignupEndDate(), + signUpSchedule.getInterviewStartDate(), + signUpSchedule.getInterviewEndDate(), + signUpSchedule.getResultAnnounceDate()); + } - private SignUpSchedule getDefaultSchedule() { - return new SignUpSchedule(999, - LocalDateTime.of(1970, 1, 1, 0, 0, 0), - LocalDateTime.of(1970, 1, 2, 0, 0, 0), - LocalDateTime.of(1970, 1, 3, 0, 0, 0), - LocalDateTime.of(1970, 1, 4, 0, 0, 0), - LocalDateTime.of(1970, 1, 5, 0, 0, 0)); - } + private SignUpSchedule getDefaultSchedule() { + return new SignUpSchedule( + 999, + LocalDateTime.of(1970, 1, 1, 0, 0, 0), + LocalDateTime.of(1970, 1, 2, 0, 0, 0), + LocalDateTime.of(1970, 1, 3, 0, 0, 0), + LocalDateTime.of(1970, 1, 4, 0, 0, 0), + LocalDateTime.of(1970, 1, 5, 0, 0, 0)); + } - @Transactional - protected SignUpSchedule createDefaultSchedule() { - return scheduleRepository.save(this.getDefaultSchedule()); - } + @Transactional + protected SignUpSchedule createDefaultSchedule() { + return scheduleRepository.save(this.getDefaultSchedule()); + } - /** - * A SignUpSchedule Entity will be guaranteed in any case. - * @return existing ScheduleEntity otherwise DefaultScheduleEntity - */ - @Transactional - protected SignUpSchedule getScheduleEntity() { + /** + * A SignUpSchedule Entity will be guaranteed in any case. + * + * @return existing ScheduleEntity otherwise DefaultScheduleEntity + */ + @Transactional + protected SignUpSchedule getScheduleEntity() { - SignUpSchedule signUpSchedule; - try { - signUpSchedule = scheduleRepository.findAll().get(0); - } catch (IndexOutOfBoundsException e) { - signUpSchedule = this.createDefaultSchedule(); - } - return signUpSchedule; + SignUpSchedule signUpSchedule; + try { + signUpSchedule = scheduleRepository.findAll().get(0); + } catch (IndexOutOfBoundsException e) { + signUpSchedule = this.createDefaultSchedule(); } + return signUpSchedule; + } - - /** - * In case of multiple SignUpSchedules, delete all the entities.
- * Must create any Schedule entity after calling this method. - */ - @Transactional - protected void clearDirtySchedules() { - if (scheduleRepository.findAll().size() > 1) - scheduleRepository.deleteAll(); - } + /** + * In case of multiple SignUpSchedules, delete all the entities.
+ * Must create any Schedule entity after calling this method. + */ + @Transactional + protected void clearDirtySchedules() { + if (scheduleRepository.findAll().size() > 1) scheduleRepository.deleteAll(); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/global/dto/PageInfoDto.java b/resource-server/src/main/java/com/inhabas/api/global/dto/PageInfoDto.java index 74ac3f9b..12618a59 100644 --- a/resource-server/src/main/java/com/inhabas/api/global/dto/PageInfoDto.java +++ b/resource-server/src/main/java/com/inhabas/api/global/dto/PageInfoDto.java @@ -1,24 +1,22 @@ package com.inhabas.api.global.dto; -import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; + import org.springframework.data.domain.Page; @Data @NoArgsConstructor public class PageInfoDto { - private int pageNumber; - private int pageSize; - private int totalPages; - private long totalElements; - - - public PageInfoDto(Page page) { - this.pageNumber = page.getNumber(); - this.pageSize = page.getSize(); - this.totalPages = page.getTotalPages(); - this.totalElements = page.getTotalElements(); - } + private int pageNumber; + private int pageSize; + private int totalPages; + private long totalElements; + public PageInfoDto(Page page) { + this.pageNumber = page.getNumber(); + this.pageSize = page.getSize(); + this.totalPages = page.getTotalPages(); + this.totalElements = page.getTotalElements(); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/global/dto/PagedMemberResponseDto.java b/resource-server/src/main/java/com/inhabas/api/global/dto/PagedMemberResponseDto.java index 61f45309..1b051df0 100644 --- a/resource-server/src/main/java/com/inhabas/api/global/dto/PagedMemberResponseDto.java +++ b/resource-server/src/main/java/com/inhabas/api/global/dto/PagedMemberResponseDto.java @@ -1,27 +1,24 @@ package com.inhabas.api.global.dto; +import java.util.List; + +import javax.validation.constraints.NotNull; + import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; -import javax.validation.constraints.NotNull; -import java.util.List; - @Data @NoArgsConstructor public class PagedMemberResponseDto { - @NotNull - private PageInfoDto pageInfo; - - @NotNull - private List data; - + @NotNull private PageInfoDto pageInfo; - @Builder - public PagedMemberResponseDto(PageInfoDto pageInfo, List data) { - this.pageInfo = pageInfo; - this.data = data; - } + @NotNull private List data; + @Builder + public PagedMemberResponseDto(PageInfoDto pageInfo, List data) { + this.pageInfo = pageInfo; + this.data = data; + } } diff --git a/resource-server/src/main/java/com/inhabas/api/global/util/FileUtil.java b/resource-server/src/main/java/com/inhabas/api/global/util/FileUtil.java index 72f491f2..2ec8312a 100644 --- a/resource-server/src/main/java/com/inhabas/api/global/util/FileUtil.java +++ b/resource-server/src/main/java/com/inhabas/api/global/util/FileUtil.java @@ -2,56 +2,59 @@ public class FileUtil { - private static final String INVALID_CHARS_REGEX = "[\\\\/:*?\"<>|]"; - private static final String[] RESERVED_NAMES = {"con", "nul", "prn", "aux", "com1", "com2", "com3", "com4", "lpt1", "lpt2", "lpt3", "lpt4"}; - private static final String[] DANGEROUS_EXTENSIONS = {"exe", "bat", "cmd", "sh", "js", "jsp", "php", "asp", "html"}; - - public static boolean isValidFileName(String fileName) { - - if (fileName == null || fileName.trim().isEmpty()) { - return false; - } - - // Check for invalid characters - if (fileName.matches(INVALID_CHARS_REGEX)) { - return false; - } - - // Check for path traversal attacks - if (fileName.contains("../") || fileName.contains("..\\")) { - return false; - } - - // Check for reserved names - String fileOnlyName = fileName.toLowerCase().replaceAll("\\.[^.]+$", ""); - for (String reservedName : RESERVED_NAMES) { - if (fileOnlyName.equals(reservedName)) { - return false; - } - } - - // Check for dangerous extensions - String extension = getExtension(fileName).toLowerCase(); - for (String dangerousExtension : DANGEROUS_EXTENSIONS) { - if (extension.equals(dangerousExtension)) { - return false; - } - } - - return true; + private static final String INVALID_CHARS_REGEX = "[\\\\/:*?\"<>|]"; + private static final String[] RESERVED_NAMES = { + "con", "nul", "prn", "aux", "com1", "com2", "com3", "com4", "lpt1", "lpt2", "lpt3", "lpt4" + }; + private static final String[] DANGEROUS_EXTENSIONS = { + "exe", "bat", "cmd", "sh", "js", "jsp", "php", "asp", "html" + }; + + public static boolean isValidFileName(String fileName) { + + if (fileName == null || fileName.trim().isEmpty()) { + return false; } - public static String getExtension(String fileName) { - int lastIndex = fileName.lastIndexOf("."); - if (lastIndex > 0) { - return fileName.substring(lastIndex + 1); - } else { - return ""; - } + // Check for invalid characters + if (fileName.matches(INVALID_CHARS_REGEX)) { + return false; } - public static String getNameWithoutExtension(String fileName) { - return fileName.substring(0, fileName.lastIndexOf(".")); + // Check for path traversal attacks + if (fileName.contains("../") || fileName.contains("..\\")) { + return false; } + // Check for reserved names + String fileOnlyName = fileName.toLowerCase().replaceAll("\\.[^.]+$", ""); + for (String reservedName : RESERVED_NAMES) { + if (fileOnlyName.equals(reservedName)) { + return false; + } + } + + // Check for dangerous extensions + String extension = getExtension(fileName).toLowerCase(); + for (String dangerousExtension : DANGEROUS_EXTENSIONS) { + if (extension.equals(dangerousExtension)) { + return false; + } + } + + return true; + } + + public static String getExtension(String fileName) { + int lastIndex = fileName.lastIndexOf("."); + if (lastIndex > 0) { + return fileName.substring(lastIndex + 1); + } else { + return ""; + } + } + + public static String getNameWithoutExtension(String fileName) { + return fileName.substring(0, fileName.lastIndexOf(".")); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/global/util/PageUtil.java b/resource-server/src/main/java/com/inhabas/api/global/util/PageUtil.java index 0249f1ab..dbaf0450 100644 --- a/resource-server/src/main/java/com/inhabas/api/global/util/PageUtil.java +++ b/resource-server/src/main/java/com/inhabas/api/global/util/PageUtil.java @@ -1,24 +1,22 @@ package com.inhabas.api.global.util; -import org.springframework.data.domain.Pageable; - import java.util.Collections; import java.util.List; -public class PageUtil { - - public static List getPagedDtoList(Pageable pageable, List dtoList) { +import org.springframework.data.domain.Pageable; - int start = (int) pageable.getOffset(); - int end = Math.min((start + pageable.getPageSize()), dtoList.size()); +public class PageUtil { - // 시작 인덱스가 리스트 크기보다 크거나 같은 경우, 빈 리스트 반환 - if (start >= dtoList.size()) { - return Collections.emptyList(); - } + public static List getPagedDtoList(Pageable pageable, List dtoList) { - return dtoList.subList(start, end); + int start = (int) pageable.getOffset(); + int end = Math.min((start + pageable.getPageSize()), dtoList.size()); + // 시작 인덱스가 리스트 크기보다 크거나 같은 경우, 빈 리스트 반환 + if (start >= dtoList.size()) { + return Collections.emptyList(); } + return dtoList.subList(start, end); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/global/util/StringUtil.java b/resource-server/src/main/java/com/inhabas/api/global/util/StringUtil.java index aa675b15..e5bacbdf 100644 --- a/resource-server/src/main/java/com/inhabas/api/global/util/StringUtil.java +++ b/resource-server/src/main/java/com/inhabas/api/global/util/StringUtil.java @@ -2,9 +2,9 @@ public class StringUtil { - private static final String ONLY_DIGIT_PATTERN = "\\d+"; + private static final String ONLY_DIGIT_PATTERN = "\\d+"; - public static boolean isNumeric(String str) { - return str.matches(ONLY_DIGIT_PATTERN); - } + public static boolean isNumeric(String str) { + return str.matches(ONLY_DIGIT_PATTERN); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/web/BoardController.java b/resource-server/src/main/java/com/inhabas/api/web/BoardController.java index d76f7b9f..3b9e9b28 100644 --- a/resource-server/src/main/java/com/inhabas/api/web/BoardController.java +++ b/resource-server/src/main/java/com/inhabas/api/web/BoardController.java @@ -1,20 +1,11 @@ package com.inhabas.api.web; -import com.inhabas.api.domain.board.dto.SaveBoardDto; -import com.inhabas.api.domain.board.dto.UpdateBoardDto; -import com.inhabas.api.web.argumentResolver.Authenticated; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.responses.ApiResponses; -import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; -import javax.validation.Valid; +import org.springframework.web.bind.annotation.*; +import io.swagger.v3.oas.annotations.tags.Tag; @Slf4j @Tag(name = "게시글 관리") @@ -22,71 +13,74 @@ @RequiredArgsConstructor public class BoardController { -// private final BoardService boardService; + // private final BoardService boardService; -// @Operation(summary = "게시글 단일 조회") -// @GetMapping("/board/{id}") -// @ApiResponses({ -// @ApiResponse(responseCode = "200"), -// @ApiResponse(responseCode = "400", description = "잘못된 게시글 조회 URL 요청"), -// @ApiResponse(responseCode = "403", description = "클라이언트의 접근 권한이 없음") -// }) -// public ResponseEntity getBoard(@PathVariable Integer id) { -// -// return new ResponseEntity<>(boardService.getBoard(id), HttpStatus.OK); -// } + // @Operation(summary = "게시글 단일 조회") + // @GetMapping("/board/{id}") + // @ApiResponses({ + // @ApiResponse(responseCode = "200"), + // @ApiResponse(responseCode = "400", description = "잘못된 게시글 조회 URL 요청"), + // @ApiResponse(responseCode = "403", description = "클라이언트의 접근 권한이 없음") + // }) + // public ResponseEntity getBoard(@PathVariable Integer id) { + // + // return new ResponseEntity<>(boardService.getBoard(id), HttpStatus.OK); + // } -// @Operation(summary = "게시글 목록 조회") -// @GetMapping("/boards") -// @ApiResponses({ -// @ApiResponse(responseCode = "200"), -// @ApiResponse(responseCode = "400", description = "잘못된 게시글 목록 조회 URL 요청"), -// @ApiResponse(responseCode = "403", description = "클라이언트의 접근 권한이 없음") -// }) -// public ResponseEntity> getBoardList( -// @PageableDefault(size = 15, direction = Direction.DESC, sort = "created") Pageable pageable, -// @RequestParam("menu_id") MenuId menuId) { -// -// return new ResponseEntity<>(boardService.getBoardList(menuId, pageable), HttpStatus.OK); -// } + // @Operation(summary = "게시글 목록 조회") + // @GetMapping("/boards") + // @ApiResponses({ + // @ApiResponse(responseCode = "200"), + // @ApiResponse(responseCode = "400", description = "잘못된 게시글 목록 조회 URL 요청"), + // @ApiResponse(responseCode = "403", description = "클라이언트의 접근 권한이 없음") + // }) + // public ResponseEntity> getBoardList( + // @PageableDefault(size = 15, direction = Direction.DESC, sort = "created") Pageable + // pageable, + // @RequestParam("menu_id") MenuId menuId) { + // + // return new ResponseEntity<>(boardService.getBoardList(menuId, pageable), HttpStatus.OK); + // } -// @Operation(summary = "게시글 추가") -// @PostMapping("/board") -// @ApiResponses({ -// @ApiResponse(responseCode = "201"), -// @ApiResponse(responseCode = "400", description = "잘못된 게시글 폼 데이터 요청"), -// @ApiResponse(responseCode = "403", description = "클라이언트의 접근 권한이 없음") -// }) -// public ResponseEntity addBoard( -// @Authenticated Long memberId, @Valid @RequestBody SaveBoardDto saveBoardDto) { -// -// return new ResponseEntity<>(boardService.write(memberId, saveBoardDto), HttpStatus.CREATED); -// } -// -// @Operation(summary = "게시글 수정") -// @PutMapping("/board") -// @ApiResponses({ -// @ApiResponse(responseCode = "200"), -// @ApiResponse(responseCode = "400", description = "잘못된 게시글 폼 데이터 요청"), -// @ApiResponse(responseCode = "403", description = "클라이언트의 접근 권한이 없음") -// }) -// public ResponseEntity updateBoard( -// @Authenticated Long memberId, @Valid @RequestBody UpdateBoardDto updateBoardDto) { -// -// return new ResponseEntity<>(boardService.update(memberId, updateBoardDto), HttpStatus.OK); -// } -// -// @Operation(description = "게시글 삭제") -// @DeleteMapping("/board/{id}") -// @ApiResponses({ -// @ApiResponse(responseCode = "204"), -// @ApiResponse(responseCode = "400", description = "잘못된 게시글 삭제 요청"), -// @ApiResponse(responseCode = "403", description = "클라이언트의 접근 권한이 없음") -// }) -// public ResponseEntity deleteBoard( -// @Authenticated Long memberId, @PathVariable Long id) { -// -// boardService.delete(memberId, id); -// return new ResponseEntity<>(HttpStatus.NO_CONTENT); -// } + // @Operation(summary = "게시글 추가") + // @PostMapping("/board") + // @ApiResponses({ + // @ApiResponse(responseCode = "201"), + // @ApiResponse(responseCode = "400", description = "잘못된 게시글 폼 데이터 요청"), + // @ApiResponse(responseCode = "403", description = "클라이언트의 접근 권한이 없음") + // }) + // public ResponseEntity addBoard( + // @Authenticated Long memberId, @Valid @RequestBody SaveBoardDto saveBoardDto) { + // + // return new ResponseEntity<>(boardService.write(memberId, saveBoardDto), + // HttpStatus.CREATED); + // } + // + // @Operation(summary = "게시글 수정") + // @PutMapping("/board") + // @ApiResponses({ + // @ApiResponse(responseCode = "200"), + // @ApiResponse(responseCode = "400", description = "잘못된 게시글 폼 데이터 요청"), + // @ApiResponse(responseCode = "403", description = "클라이언트의 접근 권한이 없음") + // }) + // public ResponseEntity updateBoard( + // @Authenticated Long memberId, @Valid @RequestBody UpdateBoardDto updateBoardDto) { + // + // return new ResponseEntity<>(boardService.update(memberId, updateBoardDto), + // HttpStatus.OK); + // } + // + // @Operation(description = "게시글 삭제") + // @DeleteMapping("/board/{id}") + // @ApiResponses({ + // @ApiResponse(responseCode = "204"), + // @ApiResponse(responseCode = "400", description = "잘못된 게시글 삭제 요청"), + // @ApiResponse(responseCode = "403", description = "클라이언트의 접근 권한이 없음") + // }) + // public ResponseEntity deleteBoard( + // @Authenticated Long memberId, @PathVariable Long id) { + // + // boardService.delete(memberId, id); + // return new ResponseEntity<>(HttpStatus.NO_CONTENT); + // } } diff --git a/resource-server/src/main/java/com/inhabas/api/web/BudgetApplicationController.java b/resource-server/src/main/java/com/inhabas/api/web/BudgetApplicationController.java index 108dc28a..3be40e2b 100644 --- a/resource-server/src/main/java/com/inhabas/api/web/BudgetApplicationController.java +++ b/resource-server/src/main/java/com/inhabas/api/web/BudgetApplicationController.java @@ -1,16 +1,9 @@ package com.inhabas.api.web; -import com.inhabas.api.domain.budget.domain.valueObject.ApplicationStatus; -import com.inhabas.api.domain.budget.dto.*; -import com.inhabas.api.domain.budget.usecase.BudgetApplicationService; -import com.inhabas.api.domain.budget.usecase.BudgetApplicationProcessor; -import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.StudentId; -import com.inhabas.api.web.argumentResolver.Authenticated; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.responses.ApiResponses; -import io.swagger.v3.oas.annotations.tags.Tag; +import javax.validation.Valid; + import lombok.RequiredArgsConstructor; + import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; @@ -19,95 +12,111 @@ import org.springframework.lang.Nullable; import org.springframework.web.bind.annotation.*; -import javax.validation.Valid; +import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.StudentId; +import com.inhabas.api.domain.budget.domain.valueObject.ApplicationStatus; +import com.inhabas.api.domain.budget.dto.*; +import com.inhabas.api.domain.budget.usecase.BudgetApplicationProcessor; +import com.inhabas.api.domain.budget.usecase.BudgetApplicationService; +import com.inhabas.api.web.argumentResolver.Authenticated; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.tags.Tag; @RestController @Tag(name = "예산 지원 신청") @RequiredArgsConstructor public class BudgetApplicationController { - private final BudgetApplicationService budgetApplicationService; - private final BudgetApplicationProcessor applicationProcessor; - - @Operation(summary = "새로운 예산지원신청글을 추가한다.") - @PostMapping("/budget/application") - @ApiResponses({ - @ApiResponse(responseCode = "204"), - @ApiResponse(responseCode = "400", description = "잘못된 입력"), - }) - public ResponseEntity createApplication( - @Authenticated StudentId loginMember, @Valid @RequestBody BudgetApplicationRegisterForm form) { - - budgetApplicationService.registerApplication(form, loginMember); - - return ResponseEntity.noContent().build(); - } - - @Operation(summary = "예산지원신청글을 수정한다.") - @PutMapping("/budget/application") - @ApiResponses({ - @ApiResponse(responseCode = "204"), - @ApiResponse(responseCode = "400", description = "잘못된 입력, 또는 게시글이 존재하지 않는 경우"), - @ApiResponse(responseCode = "401", description = "글쓴이가 아니면 수정 불가") - }) - public ResponseEntity modifyApplication( - @Authenticated StudentId loginMember, @Valid @RequestBody BudgetApplicationUpdateForm form) { - - budgetApplicationService.updateApplication(form, loginMember); - - return ResponseEntity.noContent().build(); - } - - @Operation(summary = "예산지원신청글을 삭제한다.") - @DeleteMapping("/budget/application/{applicationId}") - @ApiResponses({ - @ApiResponse(responseCode = "204"), - @ApiResponse(responseCode = "400", description = "잘못된 입력, 또는 게시글이 존재하지 않는 경우"), - @ApiResponse(responseCode = "401", description = "글쓴이가 아니면 삭제 불가") - }) - public ResponseEntity deleteApplication( - @Authenticated StudentId loginMember, @PathVariable Integer applicationId) { - - budgetApplicationService.deleteApplication(applicationId, loginMember); - - return ResponseEntity.noContent().build(); - } - - @Operation(summary = "예산지원신청글 내용을 조회한다.") - @GetMapping("/budget/application/{applicationId}") - - public ResponseEntity getApplication(@PathVariable Integer applicationId) { - - BudgetApplicationDetailDto details = budgetApplicationService.getApplicationDetails(applicationId); - - return ResponseEntity.ok(details); - } - - @Operation(summary = "예산지원 요청 게시글 목록을 조회한다.") - @GetMapping("/budget/applications") - @ApiResponse(responseCode = "200", description = "검색 결과를 pagination 적용해서 반환, status 값 안주면 전체 상태를 검색함.") - public ResponseEntity> getApplications( - @Nullable @RequestParam ApplicationStatus status, - @PageableDefault(size = 15, sort = "dateUsed", direction = Sort.Direction.DESC) Pageable pageable) { - - Page page = budgetApplicationService.getApplications(status, pageable); - - return ResponseEntity.ok(page); - } - - @Operation(summary = "총무가 예산지원요청글의 상태를 변경한다.") - @PutMapping("/budget/application/{applicationId}/status") - @ApiResponses({ - @ApiResponse(responseCode = "204"), - @ApiResponse(responseCode = "400", description = "잘못된 status 정보이거나, 또는 게시글이 존재하지 않는 경우"), - @ApiResponse(responseCode = "401", description = "이미 처리완료된 상태이거나, 총무가 아니면 변경 불가.") - }) - public ResponseEntity changeApplicationStatus( - @Authenticated StudentId loginMember, @PathVariable Integer applicationId, - @RequestBody BudgetApplicationStatusChangeRequest request) { - - applicationProcessor.process(applicationId, request, loginMember); - - return ResponseEntity.noContent().build(); - } + private final BudgetApplicationService budgetApplicationService; + private final BudgetApplicationProcessor applicationProcessor; + + @Operation(summary = "새로운 예산지원신청글을 추가한다.") + @PostMapping("/budget/application") + @ApiResponses({ + @ApiResponse(responseCode = "204"), + @ApiResponse(responseCode = "400", description = "잘못된 입력"), + }) + public ResponseEntity createApplication( + @Authenticated StudentId loginMember, + @Valid @RequestBody BudgetApplicationRegisterForm form) { + + budgetApplicationService.registerApplication(form, loginMember); + + return ResponseEntity.noContent().build(); + } + + @Operation(summary = "예산지원신청글을 수정한다.") + @PutMapping("/budget/application") + @ApiResponses({ + @ApiResponse(responseCode = "204"), + @ApiResponse(responseCode = "400", description = "잘못된 입력, 또는 게시글이 존재하지 않는 경우"), + @ApiResponse(responseCode = "401", description = "글쓴이가 아니면 수정 불가") + }) + public ResponseEntity modifyApplication( + @Authenticated StudentId loginMember, @Valid @RequestBody BudgetApplicationUpdateForm form) { + + budgetApplicationService.updateApplication(form, loginMember); + + return ResponseEntity.noContent().build(); + } + + @Operation(summary = "예산지원신청글을 삭제한다.") + @DeleteMapping("/budget/application/{applicationId}") + @ApiResponses({ + @ApiResponse(responseCode = "204"), + @ApiResponse(responseCode = "400", description = "잘못된 입력, 또는 게시글이 존재하지 않는 경우"), + @ApiResponse(responseCode = "401", description = "글쓴이가 아니면 삭제 불가") + }) + public ResponseEntity deleteApplication( + @Authenticated StudentId loginMember, @PathVariable Integer applicationId) { + + budgetApplicationService.deleteApplication(applicationId, loginMember); + + return ResponseEntity.noContent().build(); + } + + @Operation(summary = "예산지원신청글 내용을 조회한다.") + @GetMapping("/budget/application/{applicationId}") + public ResponseEntity getApplication( + @PathVariable Integer applicationId) { + + BudgetApplicationDetailDto details = + budgetApplicationService.getApplicationDetails(applicationId); + + return ResponseEntity.ok(details); + } + + @Operation(summary = "예산지원 요청 게시글 목록을 조회한다.") + @GetMapping("/budget/applications") + @ApiResponse( + responseCode = "200", + description = "검색 결과를 pagination 적용해서 반환, status 값 안주면 전체 상태를 검색함.") + public ResponseEntity> getApplications( + @Nullable @RequestParam ApplicationStatus status, + @PageableDefault(size = 15, sort = "dateUsed", direction = Sort.Direction.DESC) + Pageable pageable) { + + Page page = + budgetApplicationService.getApplications(status, pageable); + + return ResponseEntity.ok(page); + } + + @Operation(summary = "총무가 예산지원요청글의 상태를 변경한다.") + @PutMapping("/budget/application/{applicationId}/status") + @ApiResponses({ + @ApiResponse(responseCode = "204"), + @ApiResponse(responseCode = "400", description = "잘못된 status 정보이거나, 또는 게시글이 존재하지 않는 경우"), + @ApiResponse(responseCode = "401", description = "이미 처리완료된 상태이거나, 총무가 아니면 변경 불가.") + }) + public ResponseEntity changeApplicationStatus( + @Authenticated StudentId loginMember, + @PathVariable Integer applicationId, + @RequestBody BudgetApplicationStatusChangeRequest request) { + + applicationProcessor.process(applicationId, request, loginMember); + + return ResponseEntity.noContent().build(); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/web/BudgetHistoryController.java b/resource-server/src/main/java/com/inhabas/api/web/BudgetHistoryController.java index 7f4fc4a9..320058f3 100644 --- a/resource-server/src/main/java/com/inhabas/api/web/BudgetHistoryController.java +++ b/resource-server/src/main/java/com/inhabas/api/web/BudgetHistoryController.java @@ -1,25 +1,16 @@ package com.inhabas.api.web; -import com.inhabas.api.domain.budget.dto.BudgetHistoryCreateForm; -import com.inhabas.api.domain.budget.dto.BudgetHistoryDetailDto; -import com.inhabas.api.domain.budget.dto.BudgetHistoryListResponse; -import com.inhabas.api.domain.budget.dto.BudgetHistoryModifyForm; -import com.inhabas.api.domain.budget.usecase.BudgetHistoryService; -import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.StudentId; -import com.inhabas.api.web.argumentResolver.Authenticated; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.responses.ApiResponses; -import io.swagger.v3.oas.annotations.tags.Tag; import java.util.List; + import javax.validation.Valid; + import lombok.RequiredArgsConstructor; + import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort.Direction; import org.springframework.data.web.PageableDefault; import org.springframework.http.ResponseEntity; import org.springframework.lang.Nullable; -import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -29,89 +20,102 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; +import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.StudentId; +import com.inhabas.api.domain.budget.dto.BudgetHistoryCreateForm; +import com.inhabas.api.domain.budget.dto.BudgetHistoryDetailDto; +import com.inhabas.api.domain.budget.dto.BudgetHistoryListResponse; +import com.inhabas.api.domain.budget.dto.BudgetHistoryModifyForm; +import com.inhabas.api.domain.budget.usecase.BudgetHistoryService; +import com.inhabas.api.web.argumentResolver.Authenticated; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.tags.Tag; + @RestController @Tag(name = "회계내역") @RequiredArgsConstructor public class BudgetHistoryController { - private final BudgetHistoryService budgetHistoryService; - - @Operation(summary = "새로운 회계 내역을 추가한다.") - @PostMapping("/budget/history") - @ApiResponses({ - @ApiResponse(responseCode = "204"), - @ApiResponse(responseCode = "400", description = "잘못된 입력"), - @ApiResponse(responseCode = "401", description = "총무가 아니면 접근 불가") - }) - public ResponseEntity createNewHistory( - @Authenticated StudentId studentId, @Valid @RequestBody BudgetHistoryCreateForm form) { - - budgetHistoryService.createNewHistory(form, studentId); - - return ResponseEntity.noContent().build(); - } - - @Operation(summary = "회계 내역을 수정한다.") - @PutMapping("/budget/history") - @ApiResponses({ - @ApiResponse(responseCode = "204"), - @ApiResponse(responseCode = "400", description = "잘못된 입력, 또는 id가 존재하지 않는 경우"), - @ApiResponse(responseCode = "401", description = "총무가 아니면 접근 불가, 다른 총무가 작성한 것 수정 불가") - }) - public ResponseEntity modifyHistory( - @Authenticated StudentId studentId, @Valid @RequestBody BudgetHistoryModifyForm form) { - - budgetHistoryService.modifyHistory(form, studentId); - - return ResponseEntity.noContent().build(); - } - - @Operation(summary = "회계 내역을 삭제한다.") - @DeleteMapping("/budget/history/{historyId}") - @ApiResponses({ - @ApiResponse(responseCode = "204"), - @ApiResponse(responseCode = "400", description = "잘못된 입력, 또는 id가 존재하지 않는 경우"), - @ApiResponse(responseCode = "401", description = "총무가 아니면 접근 불가, 다른 총무가 작성한 것 삭제 불가") - }) - public ResponseEntity deleteHistory( - @Authenticated StudentId studentId, - @PathVariable Integer historyId) { - - budgetHistoryService.deleteHistory(historyId, studentId); - - return ResponseEntity.noContent().build(); - } - - @Operation(summary = "단일 회계 내역을 조회한다.") - @GetMapping("/budget/history/{historyId}") - @ApiResponses({ - @ApiResponse(responseCode = "200"), - @ApiResponse(responseCode = "400", description = "잘못된 입력, 또는 id가 존재하지 않는 경우"), - }) - public ResponseEntity getBudgetHistory(@PathVariable Integer historyId) { - - BudgetHistoryDetailDto history = budgetHistoryService.getHistory(historyId); - - return ResponseEntity.ok(history); - } - - @Operation(summary = "회계 내역을 검색한다.") - @GetMapping("/budget/histories") - @ApiResponse(responseCode = "200", description = "검색 결과를 pagination 적용해서 현재 잔고와 함께 반환, year 값 안주면 전체기간으로 적용됨.") - public ResponseEntity searchBudgetHistory( - @Nullable @RequestParam Integer year, - @PageableDefault(size = 15, sort = "dateUsed", direction = Direction.DESC) Pageable pageable) { - BudgetHistoryListResponse response = budgetHistoryService.searchHistoryList( - year, pageable); - - return ResponseEntity.ok(response); - } - - @Operation(summary = "회계 내역이 작성된 기간동안의 연도 목록을 가져온다.") - @GetMapping("/budget/histories/years") - @ApiResponse(responseCode = "200") - public ResponseEntity> getAllYearsOfHistory() { - - return ResponseEntity.ok(budgetHistoryService.getAllYearOfHistory()); - } + private final BudgetHistoryService budgetHistoryService; + + @Operation(summary = "새로운 회계 내역을 추가한다.") + @PostMapping("/budget/history") + @ApiResponses({ + @ApiResponse(responseCode = "204"), + @ApiResponse(responseCode = "400", description = "잘못된 입력"), + @ApiResponse(responseCode = "401", description = "총무가 아니면 접근 불가") + }) + public ResponseEntity createNewHistory( + @Authenticated StudentId studentId, @Valid @RequestBody BudgetHistoryCreateForm form) { + + budgetHistoryService.createNewHistory(form, studentId); + + return ResponseEntity.noContent().build(); + } + + @Operation(summary = "회계 내역을 수정한다.") + @PutMapping("/budget/history") + @ApiResponses({ + @ApiResponse(responseCode = "204"), + @ApiResponse(responseCode = "400", description = "잘못된 입력, 또는 id가 존재하지 않는 경우"), + @ApiResponse(responseCode = "401", description = "총무가 아니면 접근 불가, 다른 총무가 작성한 것 수정 불가") + }) + public ResponseEntity modifyHistory( + @Authenticated StudentId studentId, @Valid @RequestBody BudgetHistoryModifyForm form) { + + budgetHistoryService.modifyHistory(form, studentId); + + return ResponseEntity.noContent().build(); + } + + @Operation(summary = "회계 내역을 삭제한다.") + @DeleteMapping("/budget/history/{historyId}") + @ApiResponses({ + @ApiResponse(responseCode = "204"), + @ApiResponse(responseCode = "400", description = "잘못된 입력, 또는 id가 존재하지 않는 경우"), + @ApiResponse(responseCode = "401", description = "총무가 아니면 접근 불가, 다른 총무가 작성한 것 삭제 불가") + }) + public ResponseEntity deleteHistory( + @Authenticated StudentId studentId, @PathVariable Integer historyId) { + + budgetHistoryService.deleteHistory(historyId, studentId); + + return ResponseEntity.noContent().build(); + } + + @Operation(summary = "단일 회계 내역을 조회한다.") + @GetMapping("/budget/history/{historyId}") + @ApiResponses({ + @ApiResponse(responseCode = "200"), + @ApiResponse(responseCode = "400", description = "잘못된 입력, 또는 id가 존재하지 않는 경우"), + }) + public ResponseEntity getBudgetHistory(@PathVariable Integer historyId) { + + BudgetHistoryDetailDto history = budgetHistoryService.getHistory(historyId); + + return ResponseEntity.ok(history); + } + + @Operation(summary = "회계 내역을 검색한다.") + @GetMapping("/budget/histories") + @ApiResponse( + responseCode = "200", + description = "검색 결과를 pagination 적용해서 현재 잔고와 함께 반환, year 값 안주면 전체기간으로 적용됨.") + public ResponseEntity searchBudgetHistory( + @Nullable @RequestParam Integer year, + @PageableDefault(size = 15, sort = "dateUsed", direction = Direction.DESC) + Pageable pageable) { + BudgetHistoryListResponse response = budgetHistoryService.searchHistoryList(year, pageable); + + return ResponseEntity.ok(response); + } + + @Operation(summary = "회계 내역이 작성된 기간동안의 연도 목록을 가져온다.") + @GetMapping("/budget/histories/years") + @ApiResponse(responseCode = "200") + public ResponseEntity> getAllYearsOfHistory() { + + return ResponseEntity.ok(budgetHistoryService.getAllYearOfHistory()); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/web/ClubActivityController.java b/resource-server/src/main/java/com/inhabas/api/web/ClubActivityController.java index df231a58..d28ee61b 100644 --- a/resource-server/src/main/java/com/inhabas/api/web/ClubActivityController.java +++ b/resource-server/src/main/java/com/inhabas/api/web/ClubActivityController.java @@ -1,5 +1,20 @@ package com.inhabas.api.web; +import java.net.URI; +import java.util.List; + +import lombok.RequiredArgsConstructor; + +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.servlet.support.ServletUriComponentsBuilder; + import com.inhabas.api.auth.domain.error.ErrorResponse; import com.inhabas.api.domain.club.dto.ClubActivityDetailDto; import com.inhabas.api.domain.club.dto.ClubActivityDto; @@ -18,172 +33,188 @@ import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.security.SecurityRequirements; import io.swagger.v3.oas.annotations.tags.Tag; -import lombok.RequiredArgsConstructor; -import org.springframework.data.domain.PageImpl; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.web.bind.annotation.*; -import org.springframework.web.multipart.MultipartFile; -import org.springframework.web.servlet.support.ServletUriComponentsBuilder; -import java.net.URI; -import java.util.List; - -@Tag(name = "동아리 활동", - description = "동아리 활동 관련 API") +@Tag(name = "동아리 활동", description = "동아리 활동 관련 API") @RestController @RequiredArgsConstructor public class ClubActivityController { - private final ClubActivityService clubActivityService; - - - @Operation(summary = "동아리 활동 목록 조회", - description = "동아리 활동 목록 조회 (썸네일은 첫 사진 첨부파일)") - @ApiResponses(value = { - @ApiResponse(responseCode = "200", content = {@Content( - schema = @Schema(implementation = PagedMemberResponseDto.class))}), - }) - @SecurityRequirements(value = {}) - @GetMapping("/club/activities") - @PreAuthorize("@boardSecurityChecker.checkMenuAccess(2, T(com.inhabas.api.domain.board.usecase.BoardSecurityChecker).READ_BOARD_LIST)") - public ResponseEntity> getClubActivities( - @Parameter(description = "페이지", example = "0") @RequestParam(name = "page", defaultValue = "0") int page, - @Parameter(description = "페이지당 개수", example = "10") @RequestParam(name = "size", defaultValue = "10") int size - ) { - - Pageable pageable = PageRequest.of(page, size); - List allDtos = clubActivityService.getClubActivities(); - List pagedDtos = PageUtil.getPagedDtoList(pageable, allDtos); - - PageImpl ClubActivityDtoPage = - new PageImpl<>(pagedDtos, pageable, allDtos.size()); - PageInfoDto pageInfoDto = new PageInfoDto(ClubActivityDtoPage); - - return ResponseEntity.ok(new PagedMemberResponseDto<>(pageInfoDto, pagedDtos)); - - } - - @Operation(summary = "동아리 활동 글 생성", - description = "동아리 활동 글 생성 (운영진 이상)") - @ApiResponses(value = { - @ApiResponse(responseCode = "201", description = "'Location' 헤더에 생성된 리소스의 URI 가 포함됩니다."), - @ApiResponse(responseCode = "400 ", description = "입력값이 없거나, 타입이 유효하지 않습니다.", content = @Content( + private final ClubActivityService clubActivityService; + + @Operation(summary = "동아리 활동 목록 조회", description = "동아리 활동 목록 조회 (썸네일은 첫 사진 첨부파일)") + @ApiResponses( + value = { + @ApiResponse( + responseCode = "200", + content = {@Content(schema = @Schema(implementation = PagedMemberResponseDto.class))}), + }) + @SecurityRequirements(value = {}) + @GetMapping("/club/activities") + @PreAuthorize( + "@boardSecurityChecker.checkMenuAccess(2, T(com.inhabas.api.domain.board.usecase.BoardSecurityChecker).READ_BOARD_LIST)") + public ResponseEntity> getClubActivities( + @Parameter(description = "페이지", example = "0") + @RequestParam(name = "page", defaultValue = "0") + int page, + @Parameter(description = "페이지당 개수", example = "10") + @RequestParam(name = "size", defaultValue = "10") + int size) { + + Pageable pageable = PageRequest.of(page, size); + List allDtos = clubActivityService.getClubActivities(); + List pagedDtos = PageUtil.getPagedDtoList(pageable, allDtos); + + PageImpl ClubActivityDtoPage = + new PageImpl<>(pagedDtos, pageable, allDtos.size()); + PageInfoDto pageInfoDto = new PageInfoDto(ClubActivityDtoPage); + + return ResponseEntity.ok(new PagedMemberResponseDto<>(pageInfoDto, pagedDtos)); + } + + @Operation(summary = "동아리 활동 글 생성", description = "동아리 활동 글 생성 (운영진 이상)") + @ApiResponses( + value = { + @ApiResponse(responseCode = "201", description = "'Location' 헤더에 생성된 리소스의 URI 가 포함됩니다."), + @ApiResponse( + responseCode = "400 ", + description = "입력값이 없거나, 타입이 유효하지 않습니다.", + content = + @Content( schema = @Schema(implementation = ErrorResponse.class), - examples = @ExampleObject( - value = "{\"status\": 400, \"code\": \"G003\", \"message\": \"입력값이 없거나, 타입이 유효하지 않습니다.\"}" - ) - )) - }) - @PostMapping(path = "/club/activity", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) - @PreAuthorize("@boardSecurityChecker.checkMenuAccess(2, T(com.inhabas.api.domain.board.usecase.BoardSecurityChecker).CREATE_BOARD)") - public ResponseEntity writeClubActivity(@Authenticated Long memberId, - @RequestPart("title") String title, - @RequestPart("content") String content, - @RequestPart(value = "files", required = false) List files) { - - - SaveClubActivityDto saveClubActivityDto = new SaveClubActivityDto(title, content, files); - - Long newClubActivityId = clubActivityService.writeClubActivity(memberId, saveClubActivityDto); - URI location = ServletUriComponentsBuilder.fromCurrentRequest() - .path("/club/activity/{boardId}") - .buildAndExpand(newClubActivityId) - .toUri(); - - return ResponseEntity.created(location).build(); - - } - - @Operation(summary = "동아리 활동 글 단일 조회", - description = "동아리 활동 글 단일 조회") - @ApiResponses(value = { - @ApiResponse(responseCode = "200"), - @ApiResponse(responseCode = "400 ", description = "입력값이 없거나, 타입이 유효하지 않습니다.", content = @Content( + examples = + @ExampleObject( + value = + "{\"status\": 400, \"code\": \"G003\", \"message\": \"입력값이 없거나, 타입이 유효하지 않습니다.\"}"))) + }) + @PostMapping(path = "/club/activity", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) + @PreAuthorize( + "@boardSecurityChecker.checkMenuAccess(2, T(com.inhabas.api.domain.board.usecase.BoardSecurityChecker).CREATE_BOARD)") + public ResponseEntity writeClubActivity( + @Authenticated Long memberId, + @RequestPart("title") String title, + @RequestPart("content") String content, + @RequestPart(value = "files", required = false) List files) { + + SaveClubActivityDto saveClubActivityDto = new SaveClubActivityDto(title, content, files); + + Long newClubActivityId = clubActivityService.writeClubActivity(memberId, saveClubActivityDto); + URI location = + ServletUriComponentsBuilder.fromCurrentRequest() + .path("/club/activity/{boardId}") + .buildAndExpand(newClubActivityId) + .toUri(); + + return ResponseEntity.created(location).build(); + } + + @Operation(summary = "동아리 활동 글 단일 조회", description = "동아리 활동 글 단일 조회") + @ApiResponses( + value = { + @ApiResponse(responseCode = "200"), + @ApiResponse( + responseCode = "400 ", + description = "입력값이 없거나, 타입이 유효하지 않습니다.", + content = + @Content( schema = @Schema(implementation = ErrorResponse.class), - examples = @ExampleObject( - value = "{\"status\": 400, \"code\": \"G003\", \"message\": \"입력값이 없거나, 타입이 유효하지 않습니다.\"}" - ) - )), - @ApiResponse(responseCode = "404", description = "데이터가 존재하지 않습니다.", content = @Content( + examples = + @ExampleObject( + value = + "{\"status\": 400, \"code\": \"G003\", \"message\": \"입력값이 없거나, 타입이 유효하지 않습니다.\"}"))), + @ApiResponse( + responseCode = "404", + description = "데이터가 존재하지 않습니다.", + content = + @Content( schema = @Schema(implementation = ErrorResponse.class), - examples = @ExampleObject( - value = "{\"status\": 404, \"code\": \"G004\", \"message\": \"데이터가 존재하지 않습니다.\"}" - ) - )) - }) - @SecurityRequirements(value = {}) - @GetMapping("/club/activity/{boardId}") - @PreAuthorize("@boardSecurityChecker.checkMenuAccess(2, T(com.inhabas.api.domain.board.usecase.BoardSecurityChecker).READ_BOARD)") - public ResponseEntity findClubActivity(@PathVariable Long boardId) { - - ClubActivityDetailDto clubActivityDetailDto = clubActivityService.getClubActivity(boardId); - - return ResponseEntity.ok(clubActivityDetailDto); - - } - - @Operation(summary = "동아리 활동 글 수정", - description = "동아리 활동 글 수정 (작성자, 회장만)") - @ApiResponses(value = { - @ApiResponse(responseCode = "204"), - @ApiResponse(responseCode = "400 ", description = "입력값이 없거나, 타입이 유효하지 않습니다.", content = @Content( + examples = + @ExampleObject( + value = + "{\"status\": 404, \"code\": \"G004\", \"message\": \"데이터가 존재하지 않습니다.\"}"))) + }) + @SecurityRequirements(value = {}) + @GetMapping("/club/activity/{boardId}") + @PreAuthorize( + "@boardSecurityChecker.checkMenuAccess(2, T(com.inhabas.api.domain.board.usecase.BoardSecurityChecker).READ_BOARD)") + public ResponseEntity findClubActivity(@PathVariable Long boardId) { + + ClubActivityDetailDto clubActivityDetailDto = clubActivityService.getClubActivity(boardId); + + return ResponseEntity.ok(clubActivityDetailDto); + } + + @Operation(summary = "동아리 활동 글 수정", description = "동아리 활동 글 수정 (작성자, 회장만)") + @ApiResponses( + value = { + @ApiResponse(responseCode = "204"), + @ApiResponse( + responseCode = "400 ", + description = "입력값이 없거나, 타입이 유효하지 않습니다.", + content = + @Content( schema = @Schema(implementation = ErrorResponse.class), - examples = @ExampleObject( - value = "{\"status\": 400, \"code\": \"G003\", \"message\": \"입력값이 없거나, 타입이 유효하지 않습니다.\"}" - ) - )), - @ApiResponse(responseCode = "404", description = "데이터가 존재하지 않습니다.", content = @Content( + examples = + @ExampleObject( + value = + "{\"status\": 400, \"code\": \"G003\", \"message\": \"입력값이 없거나, 타입이 유효하지 않습니다.\"}"))), + @ApiResponse( + responseCode = "404", + description = "데이터가 존재하지 않습니다.", + content = + @Content( schema = @Schema(implementation = ErrorResponse.class), - examples = @ExampleObject( - value = "{\"status\": 404, \"code\": \"G004\", \"message\": \"데이터가 존재하지 않습니다.\"}" - ) - )) - }) - @PostMapping(path = "/club/activity/{boardId}", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) - @PreAuthorize("@boardSecurityChecker.boardWriterOnly(#boardId) or hasRole('VICE_CHIEF')") - public ResponseEntity updateClubActivity(@Authenticated Long memberId, - @PathVariable Long boardId, - @RequestPart("title") String title, - @RequestPart("content") String content, - @RequestPart(value = "files", required = false) List files) { - - SaveClubActivityDto saveClubActivityDto = new SaveClubActivityDto(title, content, files); - clubActivityService.updateClubActivity(boardId, saveClubActivityDto); - - return ResponseEntity.noContent().build(); - - } - - @Operation(summary = "동아리 활동 글 삭제", - description = "동아리 활동 글 삭제 (작성자, 회장만)") - @ApiResponses(value = { - @ApiResponse(responseCode = "204"), - @ApiResponse(responseCode = "400 ", description = "입력값이 없거나, 타입이 유효하지 않습니다.", content = @Content( + examples = + @ExampleObject( + value = + "{\"status\": 404, \"code\": \"G004\", \"message\": \"데이터가 존재하지 않습니다.\"}"))) + }) + @PostMapping(path = "/club/activity/{boardId}", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) + @PreAuthorize("@boardSecurityChecker.boardWriterOnly(#boardId) or hasRole('VICE_CHIEF')") + public ResponseEntity updateClubActivity( + @Authenticated Long memberId, + @PathVariable Long boardId, + @RequestPart("title") String title, + @RequestPart("content") String content, + @RequestPart(value = "files", required = false) List files) { + + SaveClubActivityDto saveClubActivityDto = new SaveClubActivityDto(title, content, files); + clubActivityService.updateClubActivity(boardId, saveClubActivityDto); + + return ResponseEntity.noContent().build(); + } + + @Operation(summary = "동아리 활동 글 삭제", description = "동아리 활동 글 삭제 (작성자, 회장만)") + @ApiResponses( + value = { + @ApiResponse(responseCode = "204"), + @ApiResponse( + responseCode = "400 ", + description = "입력값이 없거나, 타입이 유효하지 않습니다.", + content = + @Content( schema = @Schema(implementation = ErrorResponse.class), - examples = @ExampleObject( - value = "{\"status\": 400, \"code\": \"G003\", \"message\": \"입력값이 없거나, 타입이 유효하지 않습니다.\"}" - ) - )), - @ApiResponse(responseCode = "404", description = "데이터가 존재하지 않습니다.", content = @Content( + examples = + @ExampleObject( + value = + "{\"status\": 400, \"code\": \"G003\", \"message\": \"입력값이 없거나, 타입이 유효하지 않습니다.\"}"))), + @ApiResponse( + responseCode = "404", + description = "데이터가 존재하지 않습니다.", + content = + @Content( schema = @Schema(implementation = ErrorResponse.class), - examples = @ExampleObject( - value = "{\"status\": 404, \"code\": \"G004\", \"message\": \"데이터가 존재하지 않습니다.\"}" - ) - )) - }) - @DeleteMapping("/club/activity/{boardId}") - @PreAuthorize("@boardSecurityChecker.boardWriterOnly(#boardId) or hasRole('VICE_CHIEF')") - public ResponseEntity deleteClubActivity(@Authenticated Long memberId, - @PathVariable Long boardId) { - - clubActivityService.deleteClubActivity(boardId); - - return ResponseEntity.noContent().build(); - - } - + examples = + @ExampleObject( + value = + "{\"status\": 404, \"code\": \"G004\", \"message\": \"데이터가 존재하지 않습니다.\"}"))) + }) + @DeleteMapping("/club/activity/{boardId}") + @PreAuthorize("@boardSecurityChecker.boardWriterOnly(#boardId) or hasRole('VICE_CHIEF')") + public ResponseEntity deleteClubActivity( + @Authenticated Long memberId, @PathVariable Long boardId) { + + clubActivityService.deleteClubActivity(boardId); + + return ResponseEntity.noContent().build(); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/web/ClubHistoryController.java b/resource-server/src/main/java/com/inhabas/api/web/ClubHistoryController.java index ab1bfaeb..e0d10fe9 100644 --- a/resource-server/src/main/java/com/inhabas/api/web/ClubHistoryController.java +++ b/resource-server/src/main/java/com/inhabas/api/web/ClubHistoryController.java @@ -1,5 +1,16 @@ package com.inhabas.api.web; +import java.net.URI; +import java.util.List; + +import javax.validation.Valid; + +import lombok.RequiredArgsConstructor; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.servlet.support.ServletUriComponentsBuilder; + import com.inhabas.api.auth.domain.error.ErrorResponse; import com.inhabas.api.domain.club.dto.ClubHistoryDto; import com.inhabas.api.domain.club.dto.SaveClubHistoryDto; @@ -13,139 +24,158 @@ import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.security.SecurityRequirements; import io.swagger.v3.oas.annotations.tags.Tag; -import lombok.RequiredArgsConstructor; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; -import org.springframework.web.servlet.support.ServletUriComponentsBuilder; - -import javax.validation.Valid; -import java.net.URI; -import java.util.List; @Tag(name = "동아리 소개", description = "동아리 소개 관련") @RestController @RequiredArgsConstructor public class ClubHistoryController { - private final ClubHistoryService clubHistoryService; - - @Operation(summary = "동아리 연혁 조회", - description = "동아리 연혁 조회") - @ApiResponses(value = { - @ApiResponse(responseCode = "200", content = { @Content( - schema = @Schema(implementation = ClubHistoryDto.class, - type = "array")) }), - }) - @SecurityRequirements(value = {}) - @GetMapping("/club/histories") - public ResponseEntity> getClubHistories() { - - List clubHistoryDtoList = clubHistoryService.getClubHistories(); - return ResponseEntity.ok(clubHistoryDtoList); - - } - - @Operation(summary = "동아리 연혁 단일 조회", - description = "동아리 연혁 단일 조회") - @ApiResponses(value = { - @ApiResponse(responseCode = "200", content = { @Content( - schema = @Schema(implementation = ClubHistoryDto.class)) + private final ClubHistoryService clubHistoryService; + + @Operation(summary = "동아리 연혁 조회", description = "동아리 연혁 조회") + @ApiResponses( + value = { + @ApiResponse( + responseCode = "200", + content = { + @Content(schema = @Schema(implementation = ClubHistoryDto.class, type = "array")) }), - @ApiResponse(responseCode = "400 ", description = "입력값이 없거나, 타입이 유효하지 않습니다.", content = @Content( + }) + @SecurityRequirements(value = {}) + @GetMapping("/club/histories") + public ResponseEntity> getClubHistories() { + + List clubHistoryDtoList = clubHistoryService.getClubHistories(); + return ResponseEntity.ok(clubHistoryDtoList); + } + + @Operation(summary = "동아리 연혁 단일 조회", description = "동아리 연혁 단일 조회") + @ApiResponses( + value = { + @ApiResponse( + responseCode = "200", + content = {@Content(schema = @Schema(implementation = ClubHistoryDto.class))}), + @ApiResponse( + responseCode = "400 ", + description = "입력값이 없거나, 타입이 유효하지 않습니다.", + content = + @Content( schema = @Schema(implementation = ErrorResponse.class), - examples = @ExampleObject( - value = "{\"status\": 400, \"code\": \"G003\", \"message\": \"입력값이 없거나, 타입이 유효하지 않습니다.\"}" - ) - )), - @ApiResponse(responseCode = "404", description = "데이터가 존재하지 않습니다.", content = @Content( + examples = + @ExampleObject( + value = + "{\"status\": 400, \"code\": \"G003\", \"message\": \"입력값이 없거나, 타입이 유효하지 않습니다.\"}"))), + @ApiResponse( + responseCode = "404", + description = "데이터가 존재하지 않습니다.", + content = + @Content( schema = @Schema(implementation = ErrorResponse.class), - examples = @ExampleObject( - value = "{\"status\": 404, \"code\": \"G004\", \"message\": \"데이터가 존재하지 않습니다.\"}" - ) - )) - }) - @SecurityRequirements(value = {}) - @GetMapping("/club/history/{clubHistoryId}") - public ResponseEntity findClubHistory(@PathVariable Long clubHistoryId) { - - ClubHistoryDto clubHistoryDto = clubHistoryService.findClubHistory(clubHistoryId); - return ResponseEntity.ok(clubHistoryDto); - - } - - @Operation(summary = "동아리 연혁 생성", - description = "동아리 연혁 생성") - @ApiResponses(value = { - @ApiResponse(responseCode = "201", description = "'Location' 헤더에 생성된 리소스의 URI 가 포함됩니다."), - @ApiResponse(responseCode = "400 ", description = "입력값이 없거나, 타입이 유효하지 않습니다.", content = @Content( + examples = + @ExampleObject( + value = + "{\"status\": 404, \"code\": \"G004\", \"message\": \"데이터가 존재하지 않습니다.\"}"))) + }) + @SecurityRequirements(value = {}) + @GetMapping("/club/history/{clubHistoryId}") + public ResponseEntity findClubHistory(@PathVariable Long clubHistoryId) { + + ClubHistoryDto clubHistoryDto = clubHistoryService.findClubHistory(clubHistoryId); + return ResponseEntity.ok(clubHistoryDto); + } + + @Operation(summary = "동아리 연혁 생성", description = "동아리 연혁 생성") + @ApiResponses( + value = { + @ApiResponse(responseCode = "201", description = "'Location' 헤더에 생성된 리소스의 URI 가 포함됩니다."), + @ApiResponse( + responseCode = "400 ", + description = "입력값이 없거나, 타입이 유효하지 않습니다.", + content = + @Content( schema = @Schema(implementation = ErrorResponse.class), - examples = @ExampleObject( - value = "{\"status\": 400, \"code\": \"G003\", \"message\": \"입력값이 없거나, 타입이 유효하지 않습니다.\"}" - ) - )) - }) - @PostMapping("/club/history") - public ResponseEntity writeClubHistory(@Authenticated Long memberId, @Valid @RequestBody SaveClubHistoryDto saveClubHistoryDto) { - - Long newClubHistoryId = clubHistoryService.writeClubHistory(memberId, saveClubHistoryDto); - URI location = ServletUriComponentsBuilder.fromCurrentRequest() - .path("/club/history/{clubHistoryId}") - .buildAndExpand(newClubHistoryId) - .toUri(); - return ResponseEntity.created(location).build(); - - } - - @Operation(summary = "동아리 연혁 수정", - description = "동아리 연혁 수정") - @ApiResponses(value = { - @ApiResponse(responseCode = "204"), - @ApiResponse(responseCode = "400 ", description = "입력값이 없거나, 타입이 유효하지 않습니다.", content = @Content( + examples = + @ExampleObject( + value = + "{\"status\": 400, \"code\": \"G003\", \"message\": \"입력값이 없거나, 타입이 유효하지 않습니다.\"}"))) + }) + @PostMapping("/club/history") + public ResponseEntity writeClubHistory( + @Authenticated Long memberId, @Valid @RequestBody SaveClubHistoryDto saveClubHistoryDto) { + + Long newClubHistoryId = clubHistoryService.writeClubHistory(memberId, saveClubHistoryDto); + URI location = + ServletUriComponentsBuilder.fromCurrentRequest() + .path("/club/history/{clubHistoryId}") + .buildAndExpand(newClubHistoryId) + .toUri(); + return ResponseEntity.created(location).build(); + } + + @Operation(summary = "동아리 연혁 수정", description = "동아리 연혁 수정") + @ApiResponses( + value = { + @ApiResponse(responseCode = "204"), + @ApiResponse( + responseCode = "400 ", + description = "입력값이 없거나, 타입이 유효하지 않습니다.", + content = + @Content( schema = @Schema(implementation = ErrorResponse.class), - examples = @ExampleObject( - value = "{\"status\": 400, \"code\": \"G003\", \"message\": \"입력값이 없거나, 타입이 유효하지 않습니다.\"}" - ) - )), - @ApiResponse(responseCode = "404", description = "데이터가 존재하지 않습니다.", content = @Content( + examples = + @ExampleObject( + value = + "{\"status\": 400, \"code\": \"G003\", \"message\": \"입력값이 없거나, 타입이 유효하지 않습니다.\"}"))), + @ApiResponse( + responseCode = "404", + description = "데이터가 존재하지 않습니다.", + content = + @Content( schema = @Schema(implementation = ErrorResponse.class), - examples = @ExampleObject( - value = "{\"status\": 404, \"code\": \"G004\", \"message\": \"데이터가 존재하지 않습니다.\"}" - ) - )) - - }) - @PutMapping("/club/history/{clubHistoryId}") - public ResponseEntity updateClubHistory(@PathVariable Long clubHistoryId, @Authenticated Long memberId, - @Valid @RequestBody SaveClubHistoryDto saveClubHistoryDto) { - - clubHistoryService.updateClubHistory(memberId, clubHistoryId, saveClubHistoryDto); - return ResponseEntity.noContent().build(); - - } - - @Operation(summary = "동아리 연혁 삭제", - description = "동아리 연혁 삭제") - @ApiResponses(value = { - @ApiResponse(responseCode = "204"), - @ApiResponse(responseCode = "400 ", description = "입력값이 없거나, 타입이 유효하지 않습니다.", content = @Content( + examples = + @ExampleObject( + value = + "{\"status\": 404, \"code\": \"G004\", \"message\": \"데이터가 존재하지 않습니다.\"}"))) + }) + @PutMapping("/club/history/{clubHistoryId}") + public ResponseEntity updateClubHistory( + @PathVariable Long clubHistoryId, + @Authenticated Long memberId, + @Valid @RequestBody SaveClubHistoryDto saveClubHistoryDto) { + + clubHistoryService.updateClubHistory(memberId, clubHistoryId, saveClubHistoryDto); + return ResponseEntity.noContent().build(); + } + + @Operation(summary = "동아리 연혁 삭제", description = "동아리 연혁 삭제") + @ApiResponses( + value = { + @ApiResponse(responseCode = "204"), + @ApiResponse( + responseCode = "400 ", + description = "입력값이 없거나, 타입이 유효하지 않습니다.", + content = + @Content( schema = @Schema(implementation = ErrorResponse.class), - examples = @ExampleObject( - value = "{\"status\": 400, \"code\": \"G003\", \"message\": \"입력값이 없거나, 타입이 유효하지 않습니다.\"}" - ) - )), - @ApiResponse(responseCode = "404", description = "데이터가 존재하지 않습니다.", content = @Content( + examples = + @ExampleObject( + value = + "{\"status\": 400, \"code\": \"G003\", \"message\": \"입력값이 없거나, 타입이 유효하지 않습니다.\"}"))), + @ApiResponse( + responseCode = "404", + description = "데이터가 존재하지 않습니다.", + content = + @Content( schema = @Schema(implementation = ErrorResponse.class), - examples = @ExampleObject( - value = "{\"status\": 404, \"code\": \"G004\", \"message\": \"데이터가 존재하지 않습니다.\"}" - ) - )) - }) - @DeleteMapping ("/club/history/{clubHistoryId}") - public ResponseEntity deleteClubHistory(@PathVariable Long clubHistoryId) { - - clubHistoryService.deleteClubHistory(clubHistoryId); - return ResponseEntity.noContent().build(); - - } - + examples = + @ExampleObject( + value = + "{\"status\": 404, \"code\": \"G004\", \"message\": \"데이터가 존재하지 않습니다.\"}"))) + }) + @DeleteMapping("/club/history/{clubHistoryId}") + public ResponseEntity deleteClubHistory(@PathVariable Long clubHistoryId) { + + clubHistoryService.deleteClubHistory(clubHistoryId); + return ResponseEntity.noContent().build(); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/web/CommentController.java b/resource-server/src/main/java/com/inhabas/api/web/CommentController.java index 19469143..0fe95e83 100644 --- a/resource-server/src/main/java/com/inhabas/api/web/CommentController.java +++ b/resource-server/src/main/java/com/inhabas/api/web/CommentController.java @@ -1,5 +1,18 @@ package com.inhabas.api.web; +import java.net.URI; +import java.util.List; + +import javax.validation.Valid; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.servlet.support.ServletUriComponentsBuilder; + import com.inhabas.api.auth.domain.error.ErrorResponse; import com.inhabas.api.domain.comment.dto.CommentDetailDto; import com.inhabas.api.domain.comment.dto.CommentSaveDto; @@ -13,145 +26,171 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.tags.Tag; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.http.ResponseEntity; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.web.bind.annotation.*; -import org.springframework.web.servlet.support.ServletUriComponentsBuilder; - -import javax.validation.Valid; -import java.net.URI; -import java.util.List; @Slf4j -@Tag(name = "댓글 관리", description = "댓글은 게시판 종류 상관없이 같이 사용 / menuId로 CRUD 권한을 각각 확인함. 자물쇠 표기가" + - "되어있지만 비회원이 접근 가능한 경우 토큰이 없어도 됨") +@Tag( + name = "댓글 관리", + description = + "댓글은 게시판 종류 상관없이 같이 사용 / menuId로 CRUD 권한을 각각 확인함. 자물쇠 표기가" + + "되어있지만 비회원이 접근 가능한 경우 토큰이 없어도 됨") @RestController @RequiredArgsConstructor public class CommentController { - private final CommentServiceImpl commentService; - - @Operation(summary = "해당 게시글의 댓글을 반환한다.", - description = "댓글에 대한 조회 권한은 해당 게시판의 조회 권한을 따른다. ") - @ApiResponses(value = { - @ApiResponse(responseCode = "200", content = {@Content( - schema = @Schema(implementation = CommentDetailDto.class))}), - @ApiResponse(responseCode = "400 ", description = "입력값이 없거나, 타입이 유효하지 않습니다.", content = @Content( + private final CommentServiceImpl commentService; + + @Operation(summary = "해당 게시글의 댓글을 반환한다.", description = "댓글에 대한 조회 권한은 해당 게시판의 조회 권한을 따른다. ") + @ApiResponses( + value = { + @ApiResponse( + responseCode = "200", + content = {@Content(schema = @Schema(implementation = CommentDetailDto.class))}), + @ApiResponse( + responseCode = "400 ", + description = "입력값이 없거나, 타입이 유효하지 않습니다.", + content = + @Content( schema = @Schema(implementation = ErrorResponse.class), - examples = @ExampleObject( - value = "{\"status\": 400, \"code\": \"G003\", \"message\": \"입력값이 없거나, 타입이 유효하지 않습니다.\"}" - ) - )), - @ApiResponse(responseCode = "404", description = "데이터가 존재하지 않습니다.", content = @Content( + examples = + @ExampleObject( + value = + "{\"status\": 400, \"code\": \"G003\", \"message\": \"입력값이 없거나, 타입이 유효하지 않습니다.\"}"))), + @ApiResponse( + responseCode = "404", + description = "데이터가 존재하지 않습니다.", + content = + @Content( schema = @Schema(implementation = ErrorResponse.class), - examples = @ExampleObject( - value = "{\"status\": 404, \"code\": \"G004\", \"message\": \"데이터가 존재하지 않습니다.\"}" - ) - )) - }) - @GetMapping("/board/{menuId}/{boardId}/comments") - @PreAuthorize("@boardSecurityChecker.checkMenuAccess(#menuId, T(com.inhabas.api.domain.board.usecase.BoardSecurityChecker).READ_COMMENT)") - public ResponseEntity> getCommentsOfBoard( - @PathVariable(name = "menuId") Integer menuId, - @PathVariable(name = "boardId") Long boardId) { - - return ResponseEntity.ok(commentService.getComments(menuId, boardId)); - - } - - @Operation(summary = "댓글을 생성하기 위한 요청을 한다.", - description = "parent_comment_id 값이 주어지면 대댓글, 아무값도 없으면 그냥 댓글 / 댓글에 대한 생성 권한은 해당 게시판의 생성 권한을 따른다. ") - @ApiResponses(value = { - @ApiResponse(responseCode = "200", content = {@Content( - schema = @Schema(implementation = CommentDetailDto.class))}), - @ApiResponse(responseCode = "400 ", description = "입력값이 없거나, 타입이 유효하지 않습니다.", content = @Content( + examples = + @ExampleObject( + value = + "{\"status\": 404, \"code\": \"G004\", \"message\": \"데이터가 존재하지 않습니다.\"}"))) + }) + @GetMapping("/board/{menuId}/{boardId}/comments") + @PreAuthorize( + "@boardSecurityChecker.checkMenuAccess(#menuId, T(com.inhabas.api.domain.board.usecase.BoardSecurityChecker).READ_COMMENT)") + public ResponseEntity> getCommentsOfBoard( + @PathVariable(name = "menuId") Integer menuId, @PathVariable(name = "boardId") Long boardId) { + + return ResponseEntity.ok(commentService.getComments(menuId, boardId)); + } + + @Operation( + summary = "댓글을 생성하기 위한 요청을 한다.", + description = + "parent_comment_id 값이 주어지면 대댓글, 아무값도 없으면 그냥 댓글 / 댓글에 대한 생성 권한은 해당 게시판의 생성 권한을 따른다. ") + @ApiResponses( + value = { + @ApiResponse( + responseCode = "200", + content = {@Content(schema = @Schema(implementation = CommentDetailDto.class))}), + @ApiResponse( + responseCode = "400 ", + description = "입력값이 없거나, 타입이 유효하지 않습니다.", + content = + @Content( schema = @Schema(implementation = ErrorResponse.class), - examples = @ExampleObject( - value = "{\"status\": 400, \"code\": \"G003\", \"message\": \"입력값이 없거나, 타입이 유효하지 않습니다.\"}" - ) - )), - @ApiResponse(responseCode = "404", description = "데이터가 존재하지 않습니다.", content = @Content( + examples = + @ExampleObject( + value = + "{\"status\": 400, \"code\": \"G003\", \"message\": \"입력값이 없거나, 타입이 유효하지 않습니다.\"}"))), + @ApiResponse( + responseCode = "404", + description = "데이터가 존재하지 않습니다.", + content = + @Content( schema = @Schema(implementation = ErrorResponse.class), - examples = @ExampleObject( - value = "{\"status\": 404, \"code\": \"G004\", \"message\": \"데이터가 존재하지 않습니다.\"}" - ) - )) - }) - @PostMapping("/board/{menuId}/{boardId}/comment") - @PreAuthorize("@boardSecurityChecker.checkMenuAccess(#menuId, T(com.inhabas.api.domain.board.usecase.BoardSecurityChecker).CREATE_COMMENT)") - public ResponseEntity createNewComment( - @Authenticated Long memberId, - @PathVariable(name = "menuId") Integer menuId, - @PathVariable(name = "boardId") Long boardId, - @Valid @RequestBody CommentSaveDto commentSaveDto) { - - commentService.create(commentSaveDto, menuId, boardId, memberId); - URI location = ServletUriComponentsBuilder.fromCurrentRequest() - .path("/board/{menuId}/{boardId}/comments") - .buildAndExpand(menuId, boardId) - .toUri(); - - return ResponseEntity.created(location).build(); - - } - - @Operation(summary = "댓글을 수정하기 위한 요청을 한다.", - description = "작성자, 부회장 이상 권한을 가진 유저만 가능") - @ApiResponses(value = { - @ApiResponse(responseCode = "204"), - @ApiResponse(responseCode = "400 ", description = "입력값이 없거나, 타입이 유효하지 않습니다.", content = @Content( + examples = + @ExampleObject( + value = + "{\"status\": 404, \"code\": \"G004\", \"message\": \"데이터가 존재하지 않습니다.\"}"))) + }) + @PostMapping("/board/{menuId}/{boardId}/comment") + @PreAuthorize( + "@boardSecurityChecker.checkMenuAccess(#menuId, T(com.inhabas.api.domain.board.usecase.BoardSecurityChecker).CREATE_COMMENT)") + public ResponseEntity createNewComment( + @Authenticated Long memberId, + @PathVariable(name = "menuId") Integer menuId, + @PathVariable(name = "boardId") Long boardId, + @Valid @RequestBody CommentSaveDto commentSaveDto) { + + commentService.create(commentSaveDto, menuId, boardId, memberId); + URI location = + ServletUriComponentsBuilder.fromCurrentRequest() + .path("/board/{menuId}/{boardId}/comments") + .buildAndExpand(menuId, boardId) + .toUri(); + + return ResponseEntity.created(location).build(); + } + + @Operation(summary = "댓글을 수정하기 위한 요청을 한다.", description = "작성자, 부회장 이상 권한을 가진 유저만 가능") + @ApiResponses( + value = { + @ApiResponse(responseCode = "204"), + @ApiResponse( + responseCode = "400 ", + description = "입력값이 없거나, 타입이 유효하지 않습니다.", + content = + @Content( schema = @Schema(implementation = ErrorResponse.class), - examples = @ExampleObject( - value = "{\"status\": 400, \"code\": \"G003\", \"message\": \"입력값이 없거나, 타입이 유효하지 않습니다.\"}" - ) - )), - @ApiResponse(responseCode = "404", description = "데이터가 존재하지 않습니다.", content = @Content( + examples = + @ExampleObject( + value = + "{\"status\": 400, \"code\": \"G003\", \"message\": \"입력값이 없거나, 타입이 유효하지 않습니다.\"}"))), + @ApiResponse( + responseCode = "404", + description = "데이터가 존재하지 않습니다.", + content = + @Content( schema = @Schema(implementation = ErrorResponse.class), - examples = @ExampleObject( - value = "{\"status\": 404, \"code\": \"G004\", \"message\": \"데이터가 존재하지 않습니다.\"}" - ) - )) - }) - @PutMapping("/comment/{commentId}") - @PreAuthorize("@boardSecurityChecker.commentWriterOnly(#commentId) or hasRole('VICE_CHIEF')") - public ResponseEntity updateComment( - @Authenticated Long memberId, - @PathVariable Long commentId, - @Valid @RequestBody CommentUpdateDto commentUpdateDto) { - - commentService.update(commentId, commentUpdateDto); - return ResponseEntity.noContent().build(); - - } - - @Operation(summary = "댓글 삭제 요청을 한다.", - description = "작성자, 부회장 이상 권한을 가진 유저만 가능") - @ApiResponses(value = { - @ApiResponse(responseCode = "204"), - @ApiResponse(responseCode = "400 ", description = "입력값이 없거나, 타입이 유효하지 않습니다.", content = @Content( + examples = + @ExampleObject( + value = + "{\"status\": 404, \"code\": \"G004\", \"message\": \"데이터가 존재하지 않습니다.\"}"))) + }) + @PutMapping("/comment/{commentId}") + @PreAuthorize("@boardSecurityChecker.commentWriterOnly(#commentId) or hasRole('VICE_CHIEF')") + public ResponseEntity updateComment( + @Authenticated Long memberId, + @PathVariable Long commentId, + @Valid @RequestBody CommentUpdateDto commentUpdateDto) { + + commentService.update(commentId, commentUpdateDto); + return ResponseEntity.noContent().build(); + } + + @Operation(summary = "댓글 삭제 요청을 한다.", description = "작성자, 부회장 이상 권한을 가진 유저만 가능") + @ApiResponses( + value = { + @ApiResponse(responseCode = "204"), + @ApiResponse( + responseCode = "400 ", + description = "입력값이 없거나, 타입이 유효하지 않습니다.", + content = + @Content( schema = @Schema(implementation = ErrorResponse.class), - examples = @ExampleObject( - value = "{\"status\": 400, \"code\": \"G003\", \"message\": \"입력값이 없거나, 타입이 유효하지 않습니다.\"}" - ) - )), - @ApiResponse(responseCode = "404", description = "데이터가 존재하지 않습니다.", content = @Content( + examples = + @ExampleObject( + value = + "{\"status\": 400, \"code\": \"G003\", \"message\": \"입력값이 없거나, 타입이 유효하지 않습니다.\"}"))), + @ApiResponse( + responseCode = "404", + description = "데이터가 존재하지 않습니다.", + content = + @Content( schema = @Schema(implementation = ErrorResponse.class), - examples = @ExampleObject( - value = "{\"status\": 404, \"code\": \"G004\", \"message\": \"데이터가 존재하지 않습니다.\"}" - ) - )) - }) - @DeleteMapping("/comment/{commentId}") - @PreAuthorize("@boardSecurityChecker.commentWriterOnly(#commentId) or hasRole('VICE_CHIEF')") - public ResponseEntity deleteComment( - @Authenticated Long memberId, - @PathVariable Long commentId) { - - commentService.delete(commentId); - return ResponseEntity.noContent().build(); - - } - + examples = + @ExampleObject( + value = + "{\"status\": 404, \"code\": \"G004\", \"message\": \"데이터가 존재하지 않습니다.\"}"))) + }) + @DeleteMapping("/comment/{commentId}") + @PreAuthorize("@boardSecurityChecker.commentWriterOnly(#commentId) or hasRole('VICE_CHIEF')") + public ResponseEntity deleteComment( + @Authenticated Long memberId, @PathVariable Long commentId) { + + commentService.delete(commentId); + return ResponseEntity.noContent().build(); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/web/ContestBoardController.java b/resource-server/src/main/java/com/inhabas/api/web/ContestBoardController.java index eeb59dc5..ba94bf63 100644 --- a/resource-server/src/main/java/com/inhabas/api/web/ContestBoardController.java +++ b/resource-server/src/main/java/com/inhabas/api/web/ContestBoardController.java @@ -1,97 +1,83 @@ package com.inhabas.api.web; -import com.inhabas.api.domain.menu.domain.valueObject.MenuId; -import com.inhabas.api.web.argumentResolver.Authenticated; -import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.StudentId; -import com.inhabas.api.domain.contest.dto.DetailContestBoardDto; -import com.inhabas.api.domain.contest.dto.ListContestBoardDto; -import com.inhabas.api.domain.contest.dto.SaveContestBoardDto; -import com.inhabas.api.domain.contest.dto.UpdateContestBoardDto; -import com.inhabas.api.domain.contest.usecase.ContestBoardService; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.responses.ApiResponses; -import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Sort.Direction; -import org.springframework.data.web.PageableDefault; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; + import org.springframework.web.bind.annotation.*; -import javax.validation.Valid; +import com.inhabas.api.domain.contest.usecase.ContestBoardService; +import io.swagger.v3.oas.annotations.tags.Tag; @Tag(name = "공모전 관리") @RestController @RequiredArgsConstructor public class ContestBoardController { - private final ContestBoardService boardService; -// -// @Operation(description = "공모전 게시판의 게시글 단일 조회") -// @GetMapping("/contest/{id}") -// @ApiResponses({ -// @ApiResponse(responseCode = "200"), -// @ApiResponse(responseCode = "400", description = "잘못된 게시글 조회 URL 요청"), -// @ApiResponse(responseCode = "403", description = "클라이언트의 접근 권한이 없음") -// }) -// public ResponseEntity getBoard(@PathVariable Integer id) { -// -// return new ResponseEntity<>(boardService.getBoard(id), HttpStatus.OK); -// } -// -// @Operation(description = "공모전 게시판의 모든 게시글 조회") -// @GetMapping("/contests") -// @ApiResponses({ -// @ApiResponse(responseCode = "200"), -// @ApiResponse(responseCode = "400", description = "잘못된 게시글 목록 조회 URL 요청"), -// @ApiResponse(responseCode = "403", description = "클라이언트의 접근 권한이 없음") -// }) -// public ResponseEntity> getBoardList( -// @RequestParam("menu_id") MenuId menuId, -// @PageableDefault(size = 8, direction = Direction.DESC, sort = "created") Pageable pageable) { -// -// return new ResponseEntity<>(boardService.getBoardList(menuId, pageable), HttpStatus.OK); -// } -// -// @Operation(description = "공모전 게시판 게시글 추가") -// @PostMapping("/contest") -// @ApiResponses({ -// @ApiResponse(responseCode = "201"), -// @ApiResponse(responseCode = "400", description = "잘못된 게시글 폼 데이터 요청"), -// @ApiResponse(responseCode = "403", description = "클라이언트의 접근 권한이 없음") -// }) -// public ResponseEntity addBoard(@Authenticated StudentId studentId, @Valid @RequestBody SaveContestBoardDto dto) { -// return new ResponseEntity<>(boardService.write(studentId, dto), HttpStatus.CREATED); -// } -// -// @Operation(description = "공모전 게시판의 게시글 수정") -// @PutMapping("/contest") -// @ApiResponses({ -// @ApiResponse(responseCode = "200"), -// @ApiResponse(responseCode = "400", description = "잘못된 게시글 폼 데이터 요청"), -// @ApiResponse(responseCode = "403", description = "클라이언트의 접근 권한이 없음") -// }) -// public ResponseEntity updateBoard( -// @Authenticated StudentId studentId, @Valid @RequestBody UpdateContestBoardDto dto) { -// -// return new ResponseEntity<>(boardService.update(studentId, dto), HttpStatus.OK); -// } -// -// @Operation(description = "공모전 게시판의 게시글 삭제") -// @DeleteMapping("/contest/{id}") -// @ApiResponses({ -// @ApiResponse(responseCode = "204"), -// @ApiResponse(responseCode = "400", description = "잘못된 게시글 삭제 요청"), -// @ApiResponse(responseCode = "403", description = "클라이언트의 접근 권한이 없음") -// }) -// public ResponseEntity deleteBoard( -// @Authenticated StudentId studentId, @PathVariable Integer id) { -// -// boardService.delete(studentId, id); -// return new ResponseEntity<>(HttpStatus.NO_CONTENT); -// } + private final ContestBoardService boardService; + // + // @Operation(description = "공모전 게시판의 게시글 단일 조회") + // @GetMapping("/contest/{id}") + // @ApiResponses({ + // @ApiResponse(responseCode = "200"), + // @ApiResponse(responseCode = "400", description = "잘못된 게시글 조회 URL 요청"), + // @ApiResponse(responseCode = "403", description = "클라이언트의 접근 권한이 없음") + // }) + // public ResponseEntity getBoard(@PathVariable Integer id) { + // + // return new ResponseEntity<>(boardService.getBoard(id), HttpStatus.OK); + // } + // + // @Operation(description = "공모전 게시판의 모든 게시글 조회") + // @GetMapping("/contests") + // @ApiResponses({ + // @ApiResponse(responseCode = "200"), + // @ApiResponse(responseCode = "400", description = "잘못된 게시글 목록 조회 URL 요청"), + // @ApiResponse(responseCode = "403", description = "클라이언트의 접근 권한이 없음") + // }) + // public ResponseEntity> getBoardList( + // @RequestParam("menu_id") MenuId menuId, + // @PageableDefault(size = 8, direction = Direction.DESC, sort = "created") Pageable + // pageable) { + // + // return new ResponseEntity<>(boardService.getBoardList(menuId, pageable), HttpStatus.OK); + // } + // + // @Operation(description = "공모전 게시판 게시글 추가") + // @PostMapping("/contest") + // @ApiResponses({ + // @ApiResponse(responseCode = "201"), + // @ApiResponse(responseCode = "400", description = "잘못된 게시글 폼 데이터 요청"), + // @ApiResponse(responseCode = "403", description = "클라이언트의 접근 권한이 없음") + // }) + // public ResponseEntity addBoard(@Authenticated StudentId studentId, @Valid + // @RequestBody SaveContestBoardDto dto) { + // return new ResponseEntity<>(boardService.write(studentId, dto), HttpStatus.CREATED); + // } + // + // @Operation(description = "공모전 게시판의 게시글 수정") + // @PutMapping("/contest") + // @ApiResponses({ + // @ApiResponse(responseCode = "200"), + // @ApiResponse(responseCode = "400", description = "잘못된 게시글 폼 데이터 요청"), + // @ApiResponse(responseCode = "403", description = "클라이언트의 접근 권한이 없음") + // }) + // public ResponseEntity updateBoard( + // @Authenticated StudentId studentId, @Valid @RequestBody UpdateContestBoardDto dto) { + // + // return new ResponseEntity<>(boardService.update(studentId, dto), HttpStatus.OK); + // } + // + // @Operation(description = "공모전 게시판의 게시글 삭제") + // @DeleteMapping("/contest/{id}") + // @ApiResponses({ + // @ApiResponse(responseCode = "204"), + // @ApiResponse(responseCode = "400", description = "잘못된 게시글 삭제 요청"), + // @ApiResponse(responseCode = "403", description = "클라이언트의 접근 권한이 없음") + // }) + // public ResponseEntity deleteBoard( + // @Authenticated StudentId studentId, @PathVariable Integer id) { + // + // boardService.delete(studentId, id); + // return new ResponseEntity<>(HttpStatus.NO_CONTENT); + // } } diff --git a/resource-server/src/main/java/com/inhabas/api/web/ExceptionController.java b/resource-server/src/main/java/com/inhabas/api/web/ExceptionController.java index 2c824833..79e25367 100644 --- a/resource-server/src/main/java/com/inhabas/api/web/ExceptionController.java +++ b/resource-server/src/main/java/com/inhabas/api/web/ExceptionController.java @@ -1,13 +1,13 @@ package com.inhabas.api.web; -import com.inhabas.api.auth.domain.error.ErrorResponse; -import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; -import com.inhabas.api.auth.domain.error.businessException.NotFoundException; -import com.inhabas.api.domain.signUp.exception.NotWriteAnswersException; -import com.inhabas.api.domain.signUp.exception.NotWriteProfileException; -import com.inhabas.api.domain.signUpSchedule.exception.InvalidDateException; -import com.inhabas.api.domain.signUpSchedule.exception.SignUpNotAvailableException; +import static com.inhabas.api.auth.domain.error.ErrorCode.*; +import static org.springframework.http.HttpStatus.BAD_REQUEST; +import static org.springframework.http.HttpStatus.FORBIDDEN; + +import javax.validation.ConstraintViolationException; + import lombok.extern.slf4j.Slf4j; + import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.http.converter.HttpMessageNotReadableException; @@ -18,93 +18,100 @@ import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException; import org.springframework.web.servlet.NoHandlerFoundException; -import javax.validation.ConstraintViolationException; - -import static com.inhabas.api.auth.domain.error.ErrorCode.*; -import static org.springframework.http.HttpStatus.BAD_REQUEST; -import static org.springframework.http.HttpStatus.FORBIDDEN; +import com.inhabas.api.auth.domain.error.ErrorResponse; +import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; +import com.inhabas.api.auth.domain.error.businessException.NotFoundException; +import com.inhabas.api.domain.signUp.exception.NotWriteAnswersException; +import com.inhabas.api.domain.signUp.exception.NotWriteProfileException; +import com.inhabas.api.domain.signUpSchedule.exception.InvalidDateException; +import com.inhabas.api.domain.signUpSchedule.exception.SignUpNotAvailableException; @Slf4j @RestControllerAdvice public class ExceptionController { - @ExceptionHandler - protected ResponseEntity handleMethodArgumentTypeMismatchException(MethodArgumentTypeMismatchException e) { - log.error("Invalid method argument type", e); - final ErrorResponse response = ErrorResponse.of(INVALID_INPUT_VALUE); - return new ResponseEntity<>(response, BAD_REQUEST); - } - - @ExceptionHandler - @ResponseStatus - public ResponseEntity handleNoHandlerFoundException(NoHandlerFoundException e){ - log.error("Not found", e); - final ErrorResponse response = ErrorResponse.of(NOT_FOUND); - return new ResponseEntity<>(response, HttpStatus.NOT_FOUND); - } - - @ExceptionHandler(NotFoundException.class) - public ResponseEntity handleNoHandlerFoundException(NotFoundException e){ - log.error("Not found", e); - final ErrorResponse response = ErrorResponse.of(NOT_FOUND); - return new ResponseEntity<>(response, HttpStatus.NOT_FOUND); - } - - @ExceptionHandler - protected ResponseEntity handleConstraintViolationException(ConstraintViolationException e) { - log.error("Database ConstraintViolation occurred", e); - final ErrorResponse response = ErrorResponse.of(INVALID_INPUT_VALUE); - return new ResponseEntity<>(response, BAD_REQUEST); - } - - @ExceptionHandler(InvalidInputException.class) - protected ResponseEntity handleInvalidInputException(InvalidInputException e) { - log.error("Invalid input value", e); - final ErrorResponse response = ErrorResponse.of(INVALID_INPUT_VALUE); - return new ResponseEntity<>(response, BAD_REQUEST); - } - - @ExceptionHandler(InvalidDateException.class) - protected ResponseEntity handleInvalidDateException(InvalidDateException e) { - log.error("Invalid SignUp date", e); - final ErrorResponse response = ErrorResponse.of(e.getErrorCode()); - return new ResponseEntity<>(response, BAD_REQUEST); - } - - @ExceptionHandler(SignUpNotAvailableException.class) - protected ResponseEntity handleNotAllowedSignUpException(SignUpNotAvailableException e) { - log.error("Not registration period now", e); - final ErrorResponse response = ErrorResponse.of(SIGNUP_NOT_AVAILABLE); - return new ResponseEntity<>(response, FORBIDDEN); - } - - @ExceptionHandler(NotWriteProfileException.class) - protected ResponseEntity handleNotWriteProfileException(NotWriteProfileException e) { - log.error("Must write profile before signup", e); - final ErrorResponse response = ErrorResponse.of(NOT_WRITE_PROFILE); - return new ResponseEntity<>(response, BAD_REQUEST); - } - - @ExceptionHandler(NotWriteAnswersException.class) - protected ResponseEntity handleNotWriteAnswersException(NotWriteAnswersException e) { - log.error("Must write answers before signup", e); - final ErrorResponse response = ErrorResponse.of(NOT_WRITE_ANSWERS); - return new ResponseEntity<>(response, BAD_REQUEST); - } - - @ExceptionHandler({HttpMessageNotReadableException.class}) - protected ResponseEntity handleHttpMessageNotReadableException(HttpMessageNotReadableException e) { - log.error("The request does not have the proper DTO format.", e); - final ErrorResponse response = ErrorResponse.of(INVALID_INPUT_VALUE); - return new ResponseEntity<>(response, BAD_REQUEST); - } - - //400 - @ExceptionHandler(MethodArgumentNotValidException.class) - protected ResponseEntity processValidationError(MethodArgumentNotValidException e) { - log.error("Validation test failed", e); - final ErrorResponse response = ErrorResponse.of(INVALID_INPUT_VALUE); - return new ResponseEntity<>(response, BAD_REQUEST); - } - -} \ No newline at end of file + @ExceptionHandler + protected ResponseEntity handleMethodArgumentTypeMismatchException( + MethodArgumentTypeMismatchException e) { + log.error("Invalid method argument type", e); + final ErrorResponse response = ErrorResponse.of(INVALID_INPUT_VALUE); + return new ResponseEntity<>(response, BAD_REQUEST); + } + + @ExceptionHandler + @ResponseStatus + public ResponseEntity handleNoHandlerFoundException(NoHandlerFoundException e) { + log.error("Not found", e); + final ErrorResponse response = ErrorResponse.of(NOT_FOUND); + return new ResponseEntity<>(response, HttpStatus.NOT_FOUND); + } + + @ExceptionHandler(NotFoundException.class) + public ResponseEntity handleNoHandlerFoundException(NotFoundException e) { + log.error("Not found", e); + final ErrorResponse response = ErrorResponse.of(NOT_FOUND); + return new ResponseEntity<>(response, HttpStatus.NOT_FOUND); + } + + @ExceptionHandler + protected ResponseEntity handleConstraintViolationException( + ConstraintViolationException e) { + log.error("Database ConstraintViolation occurred", e); + final ErrorResponse response = ErrorResponse.of(INVALID_INPUT_VALUE); + return new ResponseEntity<>(response, BAD_REQUEST); + } + + @ExceptionHandler(InvalidInputException.class) + protected ResponseEntity handleInvalidInputException(InvalidInputException e) { + log.error("Invalid input value", e); + final ErrorResponse response = ErrorResponse.of(INVALID_INPUT_VALUE); + return new ResponseEntity<>(response, BAD_REQUEST); + } + + @ExceptionHandler(InvalidDateException.class) + protected ResponseEntity handleInvalidDateException(InvalidDateException e) { + log.error("Invalid SignUp date", e); + final ErrorResponse response = ErrorResponse.of(e.getErrorCode()); + return new ResponseEntity<>(response, BAD_REQUEST); + } + + @ExceptionHandler(SignUpNotAvailableException.class) + protected ResponseEntity handleNotAllowedSignUpException( + SignUpNotAvailableException e) { + log.error("Not registration period now", e); + final ErrorResponse response = ErrorResponse.of(SIGNUP_NOT_AVAILABLE); + return new ResponseEntity<>(response, FORBIDDEN); + } + + @ExceptionHandler(NotWriteProfileException.class) + protected ResponseEntity handleNotWriteProfileException( + NotWriteProfileException e) { + log.error("Must write profile before signup", e); + final ErrorResponse response = ErrorResponse.of(NOT_WRITE_PROFILE); + return new ResponseEntity<>(response, BAD_REQUEST); + } + + @ExceptionHandler(NotWriteAnswersException.class) + protected ResponseEntity handleNotWriteAnswersException( + NotWriteAnswersException e) { + log.error("Must write answers before signup", e); + final ErrorResponse response = ErrorResponse.of(NOT_WRITE_ANSWERS); + return new ResponseEntity<>(response, BAD_REQUEST); + } + + @ExceptionHandler({HttpMessageNotReadableException.class}) + protected ResponseEntity handleHttpMessageNotReadableException( + HttpMessageNotReadableException e) { + log.error("The request does not have the proper DTO format.", e); + final ErrorResponse response = ErrorResponse.of(INVALID_INPUT_VALUE); + return new ResponseEntity<>(response, BAD_REQUEST); + } + + // 400 + @ExceptionHandler(MethodArgumentNotValidException.class) + protected ResponseEntity processValidationError(MethodArgumentNotValidException e) { + log.error("Validation test failed", e); + final ErrorResponse response = ErrorResponse.of(INVALID_INPUT_VALUE); + return new ResponseEntity<>(response, BAD_REQUEST); + } +} diff --git a/resource-server/src/main/java/com/inhabas/api/web/LectureController.java b/resource-server/src/main/java/com/inhabas/api/web/LectureController.java index 59ea788a..749aa9c2 100644 --- a/resource-server/src/main/java/com/inhabas/api/web/LectureController.java +++ b/resource-server/src/main/java/com/inhabas/api/web/LectureController.java @@ -1,194 +1,204 @@ package com.inhabas.api.web; +import java.util.Map; + +import javax.validation.Valid; +import javax.validation.constraints.NotNull; + +import lombok.RequiredArgsConstructor; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.web.PageableDefault; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.StudentId; import com.inhabas.api.domain.lecture.domain.valueObject.StudentStatus; import com.inhabas.api.domain.lecture.dto.*; import com.inhabas.api.domain.lecture.usecase.LectureService; import com.inhabas.api.domain.lecture.usecase.LectureStudentService; -import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.StudentId; import com.inhabas.api.web.argumentResolver.Authenticated; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.tags.Tag; -import lombok.RequiredArgsConstructor; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.data.web.PageableDefault; -import org.springframework.http.ResponseEntity; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.web.bind.annotation.*; - -import javax.validation.Valid; -import javax.validation.constraints.NotNull; -import java.util.Map; @Tag(name = "강의실 관리") @RestController @RequiredArgsConstructor public class LectureController { - private final LectureService lectureService; - private final LectureStudentService studentService; - - @Operation(summary = "강의실 단건 조회") - @ApiResponses({ - @ApiResponse(responseCode = "200"), - @ApiResponse(responseCode = "400", description = "잘못된 id"), - }) - @GetMapping("/lecture/{id}") - public ResponseEntity getLectureDetails(@PathVariable Integer id) { - - return ResponseEntity.ok(lectureService.get(id)); - } - - @Operation(summary = "강의실 목록 조회") - @ApiResponses({ - @ApiResponse(responseCode = "200"), - @ApiResponse(responseCode = "400", description = "잘못된 요청"), - }) - @GetMapping("/lectures") - public ResponseEntity> getLectureList( - @PageableDefault(value = 6) Pageable pageable) { - - return ResponseEntity.ok(lectureService.getList(pageable)); - } - - @Operation(summary = "강의실 등록") - @ApiResponses({ - @ApiResponse(responseCode = "204"), - @ApiResponse(responseCode = "400", description = "잘못된 요청"), - }) - @PostMapping("/lecture") - public ResponseEntity createLecture( - @Authenticated StudentId studentId, @Valid @RequestBody LectureRegisterForm form) { - - lectureService.create(form, studentId); - - return ResponseEntity.noContent().build(); - } - - @Operation(summary = "강의실 수정") - @ApiResponses({ - @ApiResponse(responseCode = "204"), - @ApiResponse(responseCode = "400", description = "잘못된 요청"), - @ApiResponse(responseCode = "401", description = "작성자가 아닌 경우 접근 불가"), - }) - @PutMapping("/lecture") - public ResponseEntity updateLecture( - @Authenticated StudentId studentId, @Valid @RequestBody LectureUpdateForm form) { - - lectureService.update(form, studentId); - - return ResponseEntity.noContent().build(); - } - - @Operation(summary = "강의실 삭제") - @ApiResponses({ - @ApiResponse(responseCode = "204"), - @ApiResponse(responseCode = "400", description = "잘못된 요청"), - @ApiResponse(responseCode = "401", description = "작성자가 아닌 경우 접근 불가"), - }) - @DeleteMapping("/lecture/{id}") - @PreAuthorize("@lectureSecurityChecker.instructorOnly(#id)") - public ResponseEntity deleteLecture( - @Authenticated StudentId studentId, @PathVariable Integer id) { - - lectureService.delete(id, studentId); - - return ResponseEntity.noContent().build(); - } - - @Operation(summary = "강의실 상태 정보 변경 (강의 개설 승인 및 거절)", - description = "종료 상태로는 변경 불가. 회장단만 변경 가능.") - @ApiResponses({ - @ApiResponse(responseCode = "204"), - @ApiResponse(responseCode = "400", description = "status 값은 입력 필수"), - @ApiResponse(responseCode = "403", description = "클라이언트의 접근 권한이 없음") - }) - @PutMapping("/lecture/{id}/status") - public ResponseEntity updateLectureStatus(@PathVariable Integer id, @Valid @RequestBody LectureStatusUpdateRequest request) { - - lectureService.approveOrDeny(id, request); - - return ResponseEntity.noContent().build(); - } - - @Operation(summary = "수강생이 강의실 직접 신청하여 등록") - @ApiResponses({ - @ApiResponse(responseCode = "204"), - @ApiResponse(responseCode = "400", description = "잘못된 lecture_id 값"), - }) - @PostMapping("/lecture/{id}/student") - public ResponseEntity enroll( - @Authenticated StudentId studentId, @PathVariable Integer id) { - - studentService.enroll(id, studentId); - - return ResponseEntity.noContent().build(); - } - - @Operation(summary = "수강생 한명의 수강상태를 변경", - description = "'정상수강' or '수강정지' 만 가능 / sId 는 학번이 아니고 강의등록명단 상의 번호임을 명심할 것.") - @ApiResponses({ - @ApiResponse(responseCode = "204"), - @ApiResponse(responseCode = "400", description = "잘못된 요청"), - @ApiResponse(responseCode = "401", description = "강의자만 변경가능"), - }) - @PutMapping("/lecture/{lectureId}/student/{sid}/status") - @PreAuthorize("@lectureSecurityChecker.instructorOnly(#lectureId)") - public ResponseEntity changeStudentStatus( - @Authenticated StudentId currentUser, @PathVariable Integer sid, @PathVariable Integer lectureId, - @NotNull @RequestBody StudentStatus status) { - - studentService.changeStatusOfOneStudentByLecturer(sid, currentUser, status, lectureId); - - return ResponseEntity.noContent().build(); - } - - @Operation(summary = "다수의 수강생 상태를 일괄 변경", - description = "'정상수강' or '수강정지' 만 가능 / 단 한명이라도 오류가 발생하면 전체 rollback 됨.") - @ApiResponses({ - @ApiResponse(responseCode = "204"), - @ApiResponse(responseCode = "400", description = "잘못된 요청"), - @ApiResponse(responseCode = "401", description = "강의자만 변경가능") - }) - @PutMapping("/lecture/{lectureId}/students/status") - @PreAuthorize("@lectureSecurityChecker.instructorOnly(#lectureId)") - public ResponseEntity changeStudentsStatus( - @Authenticated StudentId studentId, @PathVariable Integer lectureId, - @io.swagger.v3.oas.annotations.parameters.RequestBody(description = "additionalProp 대신 studentId 값에 해당하는 정수값을 넣어야함. 단 학번이 아니라 강의등록명단 상의 번호임을 명심할 것") - @NotNull @RequestBody Map list) { - - studentService.changeStatusOfStudentsByLecturer(list, studentId, lectureId); - - return ResponseEntity.noContent().build(); - } - - @Operation(summary = "수강생이 강의실을 탈퇴한다.") - @ApiResponses({ - @ApiResponse(responseCode = "204"), - @ApiResponse(responseCode = "400", description = "잘못된 요청"), - }) - @DeleteMapping("/lecture/{id}/student") - public ResponseEntity exit( - @Authenticated StudentId studentId, @PathVariable Integer id) { - - studentService.exitBySelf(id, studentId); - - return ResponseEntity.noContent().build(); - } - - @Operation(summary = "수강생들의 수강상태정보를 불러온다.") - @ApiResponses({ - @ApiResponse(responseCode = "200"), - @ApiResponse(responseCode = "400", description = "잘못된 요청"), - @ApiResponse(responseCode = "401", description = "강의자만 조회가능") - }) - @GetMapping("/lecture/{id}/students") - @PreAuthorize("@lectureSecurityChecker.instructorOnly(#id)") - public ResponseEntity> searchStudents( - @PathVariable Integer id, @PageableDefault(size = 25) Pageable pageable) { - - return ResponseEntity.ok(studentService.searchStudents(id, pageable)); - } + private final LectureService lectureService; + private final LectureStudentService studentService; + + @Operation(summary = "강의실 단건 조회") + @ApiResponses({ + @ApiResponse(responseCode = "200"), + @ApiResponse(responseCode = "400", description = "잘못된 id"), + }) + @GetMapping("/lecture/{id}") + public ResponseEntity getLectureDetails(@PathVariable Integer id) { + + return ResponseEntity.ok(lectureService.get(id)); + } + + @Operation(summary = "강의실 목록 조회") + @ApiResponses({ + @ApiResponse(responseCode = "200"), + @ApiResponse(responseCode = "400", description = "잘못된 요청"), + }) + @GetMapping("/lectures") + public ResponseEntity> getLectureList( + @PageableDefault(value = 6) Pageable pageable) { + + return ResponseEntity.ok(lectureService.getList(pageable)); + } + + @Operation(summary = "강의실 등록") + @ApiResponses({ + @ApiResponse(responseCode = "204"), + @ApiResponse(responseCode = "400", description = "잘못된 요청"), + }) + @PostMapping("/lecture") + public ResponseEntity createLecture( + @Authenticated StudentId studentId, @Valid @RequestBody LectureRegisterForm form) { + + lectureService.create(form, studentId); + + return ResponseEntity.noContent().build(); + } + + @Operation(summary = "강의실 수정") + @ApiResponses({ + @ApiResponse(responseCode = "204"), + @ApiResponse(responseCode = "400", description = "잘못된 요청"), + @ApiResponse(responseCode = "401", description = "작성자가 아닌 경우 접근 불가"), + }) + @PutMapping("/lecture") + public ResponseEntity updateLecture( + @Authenticated StudentId studentId, @Valid @RequestBody LectureUpdateForm form) { + + lectureService.update(form, studentId); + + return ResponseEntity.noContent().build(); + } + + @Operation(summary = "강의실 삭제") + @ApiResponses({ + @ApiResponse(responseCode = "204"), + @ApiResponse(responseCode = "400", description = "잘못된 요청"), + @ApiResponse(responseCode = "401", description = "작성자가 아닌 경우 접근 불가"), + }) + @DeleteMapping("/lecture/{id}") + @PreAuthorize("@lectureSecurityChecker.instructorOnly(#id)") + public ResponseEntity deleteLecture( + @Authenticated StudentId studentId, @PathVariable Integer id) { + + lectureService.delete(id, studentId); + + return ResponseEntity.noContent().build(); + } + + @Operation(summary = "강의실 상태 정보 변경 (강의 개설 승인 및 거절)", description = "종료 상태로는 변경 불가. 회장단만 변경 가능.") + @ApiResponses({ + @ApiResponse(responseCode = "204"), + @ApiResponse(responseCode = "400", description = "status 값은 입력 필수"), + @ApiResponse(responseCode = "403", description = "클라이언트의 접근 권한이 없음") + }) + @PutMapping("/lecture/{id}/status") + public ResponseEntity updateLectureStatus( + @PathVariable Integer id, @Valid @RequestBody LectureStatusUpdateRequest request) { + + lectureService.approveOrDeny(id, request); + + return ResponseEntity.noContent().build(); + } + + @Operation(summary = "수강생이 강의실 직접 신청하여 등록") + @ApiResponses({ + @ApiResponse(responseCode = "204"), + @ApiResponse(responseCode = "400", description = "잘못된 lecture_id 값"), + }) + @PostMapping("/lecture/{id}/student") + public ResponseEntity enroll(@Authenticated StudentId studentId, @PathVariable Integer id) { + + studentService.enroll(id, studentId); + + return ResponseEntity.noContent().build(); + } + + @Operation( + summary = "수강생 한명의 수강상태를 변경", + description = "'정상수강' or '수강정지' 만 가능 / sId 는 학번이 아니고 강의등록명단 상의 번호임을 명심할 것.") + @ApiResponses({ + @ApiResponse(responseCode = "204"), + @ApiResponse(responseCode = "400", description = "잘못된 요청"), + @ApiResponse(responseCode = "401", description = "강의자만 변경가능"), + }) + @PutMapping("/lecture/{lectureId}/student/{sid}/status") + @PreAuthorize("@lectureSecurityChecker.instructorOnly(#lectureId)") + public ResponseEntity changeStudentStatus( + @Authenticated StudentId currentUser, + @PathVariable Integer sid, + @PathVariable Integer lectureId, + @NotNull @RequestBody StudentStatus status) { + + studentService.changeStatusOfOneStudentByLecturer(sid, currentUser, status, lectureId); + + return ResponseEntity.noContent().build(); + } + + @Operation( + summary = "다수의 수강생 상태를 일괄 변경", + description = "'정상수강' or '수강정지' 만 가능 / 단 한명이라도 오류가 발생하면 전체 rollback 됨.") + @ApiResponses({ + @ApiResponse(responseCode = "204"), + @ApiResponse(responseCode = "400", description = "잘못된 요청"), + @ApiResponse(responseCode = "401", description = "강의자만 변경가능") + }) + @PutMapping("/lecture/{lectureId}/students/status") + @PreAuthorize("@lectureSecurityChecker.instructorOnly(#lectureId)") + public ResponseEntity changeStudentsStatus( + @Authenticated StudentId studentId, + @PathVariable Integer lectureId, + @io.swagger.v3.oas.annotations.parameters.RequestBody( + description = + "additionalProp 대신 studentId 값에 해당하는 정수값을 넣어야함. 단 학번이 아니라 강의등록명단 상의 번호임을 명심할 것") + @NotNull + @RequestBody + Map list) { + + studentService.changeStatusOfStudentsByLecturer(list, studentId, lectureId); + + return ResponseEntity.noContent().build(); + } + + @Operation(summary = "수강생이 강의실을 탈퇴한다.") + @ApiResponses({ + @ApiResponse(responseCode = "204"), + @ApiResponse(responseCode = "400", description = "잘못된 요청"), + }) + @DeleteMapping("/lecture/{id}/student") + public ResponseEntity exit(@Authenticated StudentId studentId, @PathVariable Integer id) { + + studentService.exitBySelf(id, studentId); + + return ResponseEntity.noContent().build(); + } + + @Operation(summary = "수강생들의 수강상태정보를 불러온다.") + @ApiResponses({ + @ApiResponse(responseCode = "200"), + @ApiResponse(responseCode = "400", description = "잘못된 요청"), + @ApiResponse(responseCode = "401", description = "강의자만 조회가능") + }) + @GetMapping("/lecture/{id}/students") + @PreAuthorize("@lectureSecurityChecker.instructorOnly(#id)") + public ResponseEntity> searchStudents( + @PathVariable Integer id, @PageableDefault(size = 25) Pageable pageable) { + + return ResponseEntity.ok(studentService.searchStudents(id, pageable)); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/web/MemberController.java b/resource-server/src/main/java/com/inhabas/api/web/MemberController.java index 511e0b40..953c2373 100644 --- a/resource-server/src/main/java/com/inhabas/api/web/MemberController.java +++ b/resource-server/src/main/java/com/inhabas/api/web/MemberController.java @@ -1,8 +1,19 @@ package com.inhabas.api.web; +import java.util.List; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + import com.inhabas.api.auth.domain.error.ErrorResponse; -import com.inhabas.api.auth.domain.oauth2.member.service.MemberService; import com.inhabas.api.auth.domain.oauth2.member.dto.*; +import com.inhabas.api.auth.domain.oauth2.member.service.MemberService; import com.inhabas.api.domain.signUp.dto.AnswerDto; import com.inhabas.api.domain.signUp.usecase.AnswerService; import com.inhabas.api.global.dto.PageInfoDto; @@ -16,15 +27,6 @@ import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.security.SecurityRequirements; import io.swagger.v3.oas.annotations.tags.Tag; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.data.domain.PageImpl; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; - -import java.util.List; @Slf4j @Tag(name = "회원관리", description = "회원 정보 조회, 수정 / 총무, 회장단 이상") @@ -32,133 +34,158 @@ @RequiredArgsConstructor public class MemberController { - private final MemberService memberService; - private final AnswerService answerService; - - - @Operation(summary = "(신입)미승인 멤버 정보 목록 조회", - description = "신입 멤버 정보 목록 조회 (미승인 → 비활동 처리하기위해)") - @ApiResponses(value = { - @ApiResponse(responseCode = "200", content = { @Content( - schema = @Schema(implementation = PagedMemberResponseDto.class)) }), - }) - @GetMapping("/members/unapproved") - public ResponseEntity> getUnapprovedMembers( - @Parameter(description = "페이지", example = "0") @RequestParam(name = "page", defaultValue = "0") int page, - @Parameter(description = "페이지당 개수", example = "10") @RequestParam(name = "size", defaultValue = "10") int size, - @Parameter(description = "검색어 (학번 or 이름)", example = "홍길동") @RequestParam(name = "search", defaultValue = "") String search - ) { - - Pageable pageable = PageRequest.of(page, size); - List allDtos = memberService.getNotApprovedMembersBySearchAndRole(search); - List pagedDtos = memberService.getPagedDtoList(pageable, allDtos); - - PageImpl newMemberManagementDtoPage = - new PageImpl<>(pagedDtos, pageable, allDtos.size()); - PageInfoDto pageInfoDto = new PageInfoDto(newMemberManagementDtoPage); - - return ResponseEntity.ok(new PagedMemberResponseDto<>(pageInfoDto, pagedDtos)); - - } - - - @Operation(summary = "(신입)미승인 멤버 -> 비활동 멤버로 변경 / 가입 거절 처리", - description = "(신입)미승인 멤버 비활동 멤버로 변경 / 가입 거절 처리") - @ApiResponses(value = { - @ApiResponse(responseCode = "204"), - @ApiResponse(responseCode = "400 ", description = "입력값이 없거나, 타입이 유효하지 않습니다.", content = @Content( + private final MemberService memberService; + private final AnswerService answerService; + + @Operation(summary = "(신입)미승인 멤버 정보 목록 조회", description = "신입 멤버 정보 목록 조회 (미승인 → 비활동 처리하기위해)") + @ApiResponses( + value = { + @ApiResponse( + responseCode = "200", + content = {@Content(schema = @Schema(implementation = PagedMemberResponseDto.class))}), + }) + @GetMapping("/members/unapproved") + public ResponseEntity> + getUnapprovedMembers( + @Parameter(description = "페이지", example = "0") + @RequestParam(name = "page", defaultValue = "0") + int page, + @Parameter(description = "페이지당 개수", example = "10") + @RequestParam(name = "size", defaultValue = "10") + int size, + @Parameter(description = "검색어 (학번 or 이름)", example = "홍길동") + @RequestParam(name = "search", defaultValue = "") + String search) { + + Pageable pageable = PageRequest.of(page, size); + List allDtos = + memberService.getNotApprovedMembersBySearchAndRole(search); + List pagedDtos = + memberService.getPagedDtoList(pageable, allDtos); + + PageImpl newMemberManagementDtoPage = + new PageImpl<>(pagedDtos, pageable, allDtos.size()); + PageInfoDto pageInfoDto = new PageInfoDto(newMemberManagementDtoPage); + + return ResponseEntity.ok(new PagedMemberResponseDto<>(pageInfoDto, pagedDtos)); + } + + @Operation( + summary = "(신입)미승인 멤버 -> 비활동 멤버로 변경 / 가입 거절 처리", + description = "(신입)미승인 멤버 비활동 멤버로 변경 / 가입 거절 처리") + @ApiResponses( + value = { + @ApiResponse(responseCode = "204"), + @ApiResponse( + responseCode = "400 ", + description = "입력값이 없거나, 타입이 유효하지 않습니다.", + content = + @Content( schema = @Schema(implementation = ErrorResponse.class), - examples = @ExampleObject( - value = "{\"status\": 400, \"code\": \"G003\", \"message\": \"입력값이 없거나, 타입이 유효하지 않습니다.\"}" - ) - )), - }) - @PutMapping("/members/unapproved") - public ResponseEntity updateUnapprovedMembers(@RequestBody UpdateRequestDto updateRequestDto) { - - memberService.updateUnapprovedMembers(updateRequestDto.getMemberIdList(), updateRequestDto.getState()); - return ResponseEntity.noContent().build(); - - } - - - @Operation(summary = "특정 신입 멤버 지원서 조회 (아직 미구현)", - description = "특정 신입 멤버 지원서 조회") - @ApiResponses(value = { - @ApiResponse(responseCode = "200"), - @ApiResponse(responseCode = "404", description = "데이터가 존재하지 않습니다.", content = @Content( + examples = + @ExampleObject( + value = + "{\"status\": 400, \"code\": \"G003\", \"message\": \"입력값이 없거나, 타입이 유효하지 않습니다.\"}"))), + }) + @PutMapping("/members/unapproved") + public ResponseEntity updateUnapprovedMembers( + @RequestBody UpdateRequestDto updateRequestDto) { + + memberService.updateUnapprovedMembers( + updateRequestDto.getMemberIdList(), updateRequestDto.getState()); + return ResponseEntity.noContent().build(); + } + + @Operation(summary = "특정 신입 멤버 지원서 조회 (아직 미구현)", description = "특정 신입 멤버 지원서 조회") + @ApiResponses( + value = { + @ApiResponse(responseCode = "200"), + @ApiResponse( + responseCode = "404", + description = "데이터가 존재하지 않습니다.", + content = + @Content( schema = @Schema(implementation = ErrorResponse.class), - examples = @ExampleObject( - value = "{\"status\": 404, \"code\": \"G004\", \"message\": \"데이터가 존재하지 않습니다.\"}" - ) - )) - }) - @GetMapping("/members/{memberId}/application") - public ResponseEntity> getUnapprovedMemberApplication(@PathVariable Long memberId) { - - List answers = answerService.getAnswers(memberId); - return ResponseEntity.ok(answers); - - } - - - @Operation(summary = "비활동 이상 모든 멤버 목록 조회", - description = "이름, 학번 검색 가능") - @ApiResponses(value = { - @ApiResponse(responseCode = "200", content = { @Content( - schema = @Schema(implementation = PagedMemberResponseDto.class)) }), - }) - @GetMapping("/members") - public ResponseEntity> getApprovedMembers( - @Parameter(description = "페이지", example = "0") @RequestParam(name = "page", defaultValue = "0") int page, - @Parameter(description = "페이지당 개수", example = "10") @RequestParam(name = "size", defaultValue = "10") int size, - @Parameter(description = "검색어 (학번 or 이름)", example = "홍길동") @RequestParam(name = "search", defaultValue = "") String search - ) { - - Pageable pageable = PageRequest.of(page, size); - List allDtos = memberService.getApprovedMembersBySearchAndRole(search); - List pagedDtos = memberService.getPagedDtoList(pageable, allDtos); - - PageImpl oldMemberManagementDtoPage = - new PageImpl<>(pagedDtos, pageable, allDtos.size()); - PageInfoDto pageInfoDto = new PageInfoDto(oldMemberManagementDtoPage); - - return ResponseEntity.ok(new PagedMemberResponseDto<>(pageInfoDto, pagedDtos)); - - } - - - @Operation(summary = "비활동 이상 멤버 권한 수정", - description = "변경 가능 권한 [ADMIN, CHIEF, VICE_CHIEF, EXECUTIVES, SECRETARY, BASIC, DEACTIVATED]") - @ApiResponses(value = { - @ApiResponse(responseCode = "204"), - @ApiResponse(responseCode = "400 ", description = "입력값이 없거나, 타입이 유효하지 않습니다.", content = @Content( + examples = + @ExampleObject( + value = + "{\"status\": 404, \"code\": \"G004\", \"message\": \"데이터가 존재하지 않습니다.\"}"))) + }) + @GetMapping("/members/{memberId}/application") + public ResponseEntity> getUnapprovedMemberApplication( + @PathVariable Long memberId) { + + List answers = answerService.getAnswers(memberId); + return ResponseEntity.ok(answers); + } + + @Operation(summary = "비활동 이상 모든 멤버 목록 조회", description = "이름, 학번 검색 가능") + @ApiResponses( + value = { + @ApiResponse( + responseCode = "200", + content = {@Content(schema = @Schema(implementation = PagedMemberResponseDto.class))}), + }) + @GetMapping("/members") + public ResponseEntity> getApprovedMembers( + @Parameter(description = "페이지", example = "0") + @RequestParam(name = "page", defaultValue = "0") + int page, + @Parameter(description = "페이지당 개수", example = "10") + @RequestParam(name = "size", defaultValue = "10") + int size, + @Parameter(description = "검색어 (학번 or 이름)", example = "홍길동") + @RequestParam(name = "search", defaultValue = "") + String search) { + + Pageable pageable = PageRequest.of(page, size); + List allDtos = + memberService.getApprovedMembersBySearchAndRole(search); + List pagedDtos = memberService.getPagedDtoList(pageable, allDtos); + + PageImpl oldMemberManagementDtoPage = + new PageImpl<>(pagedDtos, pageable, allDtos.size()); + PageInfoDto pageInfoDto = new PageInfoDto(oldMemberManagementDtoPage); + + return ResponseEntity.ok(new PagedMemberResponseDto<>(pageInfoDto, pagedDtos)); + } + + @Operation( + summary = "비활동 이상 멤버 권한 수정", + description = + "변경 가능 권한 [ADMIN, CHIEF, VICE_CHIEF, EXECUTIVES, SECRETARY, BASIC, DEACTIVATED]") + @ApiResponses( + value = { + @ApiResponse(responseCode = "204"), + @ApiResponse( + responseCode = "400 ", + description = "입력값이 없거나, 타입이 유효하지 않습니다.", + content = + @Content( schema = @Schema(implementation = ErrorResponse.class), - examples = @ExampleObject( - value = "{\"status\": 400, \"code\": \"G003\", \"message\": \"입력값이 없거나, 타입이 유효하지 않습니다.\"}" - ) - )), - }) - @PutMapping("/members/approved") - public ResponseEntity updateApprovedMembers(@RequestBody UpdateRoleRequestDto updateRoleRequestDto) { - - memberService.updateApprovedMembers(updateRoleRequestDto.getMemberIdList(), updateRoleRequestDto.getRole()); - return ResponseEntity.noContent().build(); - - } - - - @Operation(summary = "회장 연락처 조회", - description = "CHIEF 의 이름, 전화번호, 이메일") - @SecurityRequirements(value = {}) - @ApiResponses(value = { - @ApiResponse(responseCode = "200"), - }) - @GetMapping("/member/chief") - public ResponseEntity getChiefContact() { - - return ResponseEntity.ok(memberService.getChiefContact()); - - } - + examples = + @ExampleObject( + value = + "{\"status\": 400, \"code\": \"G003\", \"message\": \"입력값이 없거나, 타입이 유효하지 않습니다.\"}"))), + }) + @PutMapping("/members/approved") + public ResponseEntity updateApprovedMembers( + @RequestBody UpdateRoleRequestDto updateRoleRequestDto) { + + memberService.updateApprovedMembers( + updateRoleRequestDto.getMemberIdList(), updateRoleRequestDto.getRole()); + return ResponseEntity.noContent().build(); + } + + @Operation(summary = "회장 연락처 조회", description = "CHIEF 의 이름, 전화번호, 이메일") + @SecurityRequirements(value = {}) + @ApiResponses( + value = { + @ApiResponse(responseCode = "200"), + }) + @GetMapping("/member/chief") + public ResponseEntity getChiefContact() { + + return ResponseEntity.ok(memberService.getChiefContact()); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/web/MenuController.java b/resource-server/src/main/java/com/inhabas/api/web/MenuController.java index a9fad532..000b63cf 100644 --- a/resource-server/src/main/java/com/inhabas/api/web/MenuController.java +++ b/resource-server/src/main/java/com/inhabas/api/web/MenuController.java @@ -1,5 +1,14 @@ package com.inhabas.api.web; +import java.util.List; + +import lombok.RequiredArgsConstructor; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RestController; + import com.inhabas.api.auth.domain.error.ErrorResponse; import com.inhabas.api.domain.menu.domain.valueObject.MenuId; import com.inhabas.api.domain.menu.dto.MenuDto; @@ -13,66 +22,69 @@ import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.security.SecurityRequirements; import io.swagger.v3.oas.annotations.tags.Tag; -import java.util.List; -import lombok.RequiredArgsConstructor; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RestController; @Tag(name = "메뉴 관리") @RestController @RequiredArgsConstructor public class MenuController { - private final MenuService menuService; + private final MenuService menuService; - @GetMapping("/menus") - @SecurityRequirements(value = {}) - @Operation(summary = "모든 메뉴 정보를 가져온다.") - @ApiResponse(responseCode = "200", content = @Content( - array = @ArraySchema(schema = @Schema(implementation = MenuGroupDto.class)), - examples = @ExampleObject( - value = "{\"id\": 1, \"groupName\": \"IBAS\", \"menuList\": [{\"menuId\": 1, \"priority\": 1, \"name\": \"동아리 소개\", \"type\": \"INTRODUCE\", \"description\": \"동아리 소개 메뉴입니다.\"}]}" - ) - )) - public ResponseEntity> getTotalMenuInfo() { - List allMenuInfo = menuService.getAllMenuInfo(); + @GetMapping("/menus") + @SecurityRequirements(value = {}) + @Operation(summary = "모든 메뉴 정보를 가져온다.") + @ApiResponse( + responseCode = "200", + content = + @Content( + array = @ArraySchema(schema = @Schema(implementation = MenuGroupDto.class)), + examples = + @ExampleObject( + value = + "{\"id\": 1, \"groupName\": \"IBAS\", \"menuList\": [{\"menuId\": 1, \"priority\": 1, \"name\": \"동아리 소개\", \"type\": \"INTRODUCE\", \"description\": \"동아리 소개 메뉴입니다.\"}]}"))) + public ResponseEntity> getTotalMenuInfo() { + List allMenuInfo = menuService.getAllMenuInfo(); - return ResponseEntity.ok(allMenuInfo); - } + return ResponseEntity.ok(allMenuInfo); + } - @GetMapping("/menu/{menuId}") - @Operation(summary = "id 에 해당하는 메뉴 정보를 가져온다.") - @SecurityRequirements(value = {}) - @Parameter( - name = "menuId", - description = "메뉴의 고유 식별자", - required = true, - in = ParameterIn.PATH, - schema = @Schema(type = "integer", format = "int64") - ) - @ApiResponses({ - @ApiResponse(responseCode = "200", content = @Content( - schema = @Schema(implementation = MenuDto.class), - examples = @ExampleObject( - value = "{ \"menuId\": 1, \"priority\": 1, \"name\": \"동아리 소개\", \"type\": \"INTRODUCE\", \"description\": \"동아리 소개 메뉴입니다.\" }" - ) - )), - @ApiResponse(responseCode = "404", description = "데이터가 존재하지 않습니다.", content = @Content( - schema = @Schema(implementation = ErrorResponse.class), - examples = @ExampleObject( - value = "{\"status\": 404, \"code\": \"G004\", \"message\": \"데이터가 존재하지 않습니다.\"}" - ) - )) - }) - public ResponseEntity getMenuInfo(@PathVariable MenuId menuId) { - MenuDto menu = menuService.getMenuInfoById(menuId); + @GetMapping("/menu/{menuId}") + @Operation(summary = "id 에 해당하는 메뉴 정보를 가져온다.") + @SecurityRequirements(value = {}) + @Parameter( + name = "menuId", + description = "메뉴의 고유 식별자", + required = true, + in = ParameterIn.PATH, + schema = @Schema(type = "integer", format = "int64")) + @ApiResponses({ + @ApiResponse( + responseCode = "200", + content = + @Content( + schema = @Schema(implementation = MenuDto.class), + examples = + @ExampleObject( + value = + "{ \"menuId\": 1, \"priority\": 1, \"name\": \"동아리 소개\", \"type\": \"INTRODUCE\", \"description\": \"동아리 소개 메뉴입니다.\" }"))), + @ApiResponse( + responseCode = "404", + description = "데이터가 존재하지 않습니다.", + content = + @Content( + schema = @Schema(implementation = ErrorResponse.class), + examples = + @ExampleObject( + value = + "{\"status\": 404, \"code\": \"G004\", \"message\": \"데이터가 존재하지 않습니다.\"}"))) + }) + public ResponseEntity getMenuInfo(@PathVariable MenuId menuId) { + MenuDto menu = menuService.getMenuInfoById(menuId); - if (menu != null) { - return ResponseEntity.ok(menu); - } else { - return ResponseEntity.notFound().build(); - } + if (menu != null) { + return ResponseEntity.ok(menu); + } else { + return ResponseEntity.notFound().build(); } + } } diff --git a/resource-server/src/main/java/com/inhabas/api/web/MyProfileController.java b/resource-server/src/main/java/com/inhabas/api/web/MyProfileController.java index a11fd808..4de31ed2 100644 --- a/resource-server/src/main/java/com/inhabas/api/web/MyProfileController.java +++ b/resource-server/src/main/java/com/inhabas/api/web/MyProfileController.java @@ -1,5 +1,16 @@ package com.inhabas.api.web; +import javax.validation.Valid; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + import com.inhabas.api.auth.domain.error.ErrorResponse; import com.inhabas.api.auth.domain.oauth2.member.dto.MyProfileDto; import com.inhabas.api.auth.domain.oauth2.member.dto.ProfileDetailDto; @@ -14,15 +25,6 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.tags.Tag; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RestController; - -import javax.validation.Valid; @Slf4j @RestController @@ -30,89 +32,108 @@ @RequiredArgsConstructor public class MyProfileController { - private final MemberService memberService; + private final MemberService memberService; + @Operation(summary = "내 정보 조회", description = "사용자 자신의 정보만 조회 가능") + @ApiResponses( + value = { + @ApiResponse( + responseCode = "200", + content = {@Content(schema = @Schema(implementation = MyProfileDto.class))}), + }) + @GetMapping("/myInfo") + public ResponseEntity getMyProfile(@Authenticated Long memberId) { + return ResponseEntity.ok(memberService.getMyProfile(memberId)); + } - @Operation(summary = "내 정보 조회", description = "사용자 자신의 정보만 조회 가능") - @ApiResponses(value = { - @ApiResponse(responseCode = "200", content = {@Content( - schema = @Schema(implementation = MyProfileDto.class))}), - }) - @GetMapping("/myInfo") - public ResponseEntity getMyProfile(@Authenticated Long memberId) { - return ResponseEntity.ok(memberService.getMyProfile(memberId)); - } - - @Operation(summary = "내 [학과, 학년, 전화번호] 수정", - description = "학과, 학년, 전화번호 수정. ") - @ApiResponses(value = { - @ApiResponse(responseCode = "204"), - @ApiResponse(responseCode = "400 ", description = "입력값이 없거나, 타입이 유효하지 않습니다.", content = @Content( + @Operation(summary = "내 [학과, 학년, 전화번호] 수정", description = "학과, 학년, 전화번호 수정. ") + @ApiResponses( + value = { + @ApiResponse(responseCode = "204"), + @ApiResponse( + responseCode = "400 ", + description = "입력값이 없거나, 타입이 유효하지 않습니다.", + content = + @Content( schema = @Schema(implementation = ErrorResponse.class), - examples = @ExampleObject( - value = "{\"status\": 400, \"code\": \"G003\", \"message\": \"입력값이 없거나, 타입이 유효하지 않습니다.\"}" - ) - )), - }) - @PutMapping("/myInfo/detail") - public ResponseEntity updateMyProfileDetail(@Authenticated Long memberId, - @Valid @RequestBody ProfileDetailDto profileDetailDto) { - memberService.updateMyProfileDetail(memberId, profileDetailDto); - return ResponseEntity.noContent().build(); - } + examples = + @ExampleObject( + value = + "{\"status\": 400, \"code\": \"G003\", \"message\": \"입력값이 없거나, 타입이 유효하지 않습니다.\"}"))), + }) + @PutMapping("/myInfo/detail") + public ResponseEntity updateMyProfileDetail( + @Authenticated Long memberId, @Valid @RequestBody ProfileDetailDto profileDetailDto) { + memberService.updateMyProfileDetail(memberId, profileDetailDto); + return ResponseEntity.noContent().build(); + } - @Operation(summary = "내 프로필 자기소개 수정", description = "자기소개, 공개여부 수정") - @ApiResponses(value = { - @ApiResponse(responseCode = "204"), - @ApiResponse(responseCode = "400 ", description = "입력값이 없거나, 타입이 유효하지 않습니다.", content = @Content( + @Operation(summary = "내 프로필 자기소개 수정", description = "자기소개, 공개여부 수정") + @ApiResponses( + value = { + @ApiResponse(responseCode = "204"), + @ApiResponse( + responseCode = "400 ", + description = "입력값이 없거나, 타입이 유효하지 않습니다.", + content = + @Content( schema = @Schema(implementation = ErrorResponse.class), - examples = @ExampleObject( - value = "{\"status\": 400, \"code\": \"G003\", \"message\": \"입력값이 없거나, 타입이 유효하지 않습니다.\"}" - ) - )), - }) - @PutMapping("/myInfo/intro") - public ResponseEntity updateMyProfileIntro(@Authenticated Long memberId, - @Valid @RequestBody ProfileIntroDto profileIntroDto) { - memberService.updateMyProfileIntro(memberId, profileIntroDto); - return ResponseEntity.noContent().build(); - } + examples = + @ExampleObject( + value = + "{\"status\": 400, \"code\": \"G003\", \"message\": \"입력값이 없거나, 타입이 유효하지 않습니다.\"}"))), + }) + @PutMapping("/myInfo/intro") + public ResponseEntity updateMyProfileIntro( + @Authenticated Long memberId, @Valid @RequestBody ProfileIntroDto profileIntroDto) { + memberService.updateMyProfileIntro(memberId, profileIntroDto); + return ResponseEntity.noContent().build(); + } - @Operation(summary = "내 프로필 사진 수정", description = "프로필 사진 수정") - @ApiResponses(value = { - @ApiResponse(responseCode = "204"), - @ApiResponse(responseCode = "400 ", description = "입력값이 없거나, 타입이 유효하지 않습니다.", content = @Content( + @Operation(summary = "내 프로필 사진 수정", description = "프로필 사진 수정") + @ApiResponses( + value = { + @ApiResponse(responseCode = "204"), + @ApiResponse( + responseCode = "400 ", + description = "입력값이 없거나, 타입이 유효하지 않습니다.", + content = + @Content( schema = @Schema(implementation = ErrorResponse.class), - examples = @ExampleObject( - value = "{\"status\": 400, \"code\": \"G003\", \"message\": \"입력값이 없거나, 타입이 유효하지 않습니다.\"}" - ) - )), - }) - @PutMapping("/myInfo/image") - public ResponseEntity updateMyProfileImage(@Authenticated Long memberId) { + examples = + @ExampleObject( + value = + "{\"status\": 400, \"code\": \"G003\", \"message\": \"입력값이 없거나, 타입이 유효하지 않습니다.\"}"))), + }) + @PutMapping("/myInfo/image") + public ResponseEntity updateMyProfileImage(@Authenticated Long memberId) { - // 첨부파일 문제로 보류 - return ResponseEntity.noContent().build(); - } + // 첨부파일 문제로 보류 + return ResponseEntity.noContent().build(); + } - @Operation(summary = "내 정보 이름 수정", description = "이름 수정, 회장의 승인 필요") - @ApiResponses(value = { - @ApiResponse(responseCode = "204"), - @ApiResponse(responseCode = "400 ", description = "입력값이 없거나, 타입이 유효하지 않습니다.", content = @Content( + @Operation(summary = "내 정보 이름 수정", description = "이름 수정, 회장의 승인 필요") + @ApiResponses( + value = { + @ApiResponse(responseCode = "204"), + @ApiResponse( + responseCode = "400 ", + description = "입력값이 없거나, 타입이 유효하지 않습니다.", + content = + @Content( schema = @Schema(implementation = ErrorResponse.class), - examples = @ExampleObject( - value = "{\"status\": 400, \"code\": \"G003\", \"message\": \"입력값이 없거나, 타입이 유효하지 않습니다.\"}" - ) - )), - }) - @PutMapping("/myInfo/name") - public ResponseEntity requestMyProfileName(@Authenticated Long memberId, - @Valid @RequestBody ProfileNameDto profileNameDto) { - memberService.requestMyProfileName(memberId, profileNameDto); - return ResponseEntity.noContent().build(); - } - + examples = + @ExampleObject( + value = + "{\"status\": 400, \"code\": \"G003\", \"message\": \"입력값이 없거나, 타입이 유효하지 않습니다.\"}"))), + }) + @PutMapping("/myInfo/name") + public ResponseEntity requestMyProfileName( + @Authenticated Long memberId, @Valid @RequestBody ProfileNameDto profileNameDto) { + memberService.requestMyProfileName(memberId, profileNameDto); + return ResponseEntity.noContent().build(); + } - // [모임, 글, 댓글, 예산신청 조회] 추후 개발 예정 + // [모임, 글, 댓글, 예산신청 조회] 추후 개발 예정 } diff --git a/resource-server/src/main/java/com/inhabas/api/web/PolicyTermController.java b/resource-server/src/main/java/com/inhabas/api/web/PolicyTermController.java index ad28cb23..06e6b02c 100644 --- a/resource-server/src/main/java/com/inhabas/api/web/PolicyTermController.java +++ b/resource-server/src/main/java/com/inhabas/api/web/PolicyTermController.java @@ -1,5 +1,12 @@ package com.inhabas.api.web; +import javax.validation.Valid; + +import lombok.RequiredArgsConstructor; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + import com.inhabas.api.auth.domain.error.ErrorResponse; import com.inhabas.api.domain.policy.dto.PolicyTermDto; import com.inhabas.api.domain.policy.dto.SavePolicyTernDto; @@ -12,71 +19,77 @@ import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.security.SecurityRequirements; import io.swagger.v3.oas.annotations.tags.Tag; -import lombok.RequiredArgsConstructor; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; - -import javax.validation.Valid; @Tag(name = "정책 관리") @RestController @RequiredArgsConstructor public class PolicyTermController { - private final PolicyTermService policyTermService; - - @GetMapping("/policy/{policyTermId}") - @SecurityRequirements(value = {}) - @Operation(summary = "해당 정책을 조회한다.", - description = "policyTermId는 1,2,3만 존재") - @ApiResponses({ - @ApiResponse(responseCode = "200", content = @Content( - schema = @Schema(implementation = PolicyTermDto.class) - )), - @ApiResponse(responseCode = "400 ", description = "입력값이 없거나, 타입이 유효하지 않습니다.", content = @Content( - schema = @Schema(implementation = ErrorResponse.class), - examples = @ExampleObject( - value = "{\"status\": 400, \"code\": \"G003\", \"message\": \"입력값이 없거나, 타입이 유효하지 않습니다.\"}" - ) - )), - @ApiResponse(responseCode = "404", description = "데이터가 존재하지 않습니다.", content = @Content( - schema = @Schema(implementation = ErrorResponse.class), - examples = @ExampleObject( - value = "{\"status\": 404, \"code\": \"G004\", \"message\": \"데이터가 존재하지 않습니다.\"}" - ) - )) - }) - public ResponseEntity findPolicyTerm(@PathVariable Long policyTermId) { - - PolicyTermDto policyTermDto = policyTermService.findPolicyTerm(policyTermId); - return ResponseEntity.ok(policyTermDto); - - } + private final PolicyTermService policyTermService; - @PutMapping("/policy/{policyTermId}") - @Operation(summary = "해당 정책을 수정한다.", - description = "policyTermId는 1,2,3만 존재") - @ApiResponses({ - @ApiResponse(responseCode = "204"), - @ApiResponse(responseCode = "400 ", description = "입력값이 없거나, 타입이 유효하지 않습니다.", content = @Content( - schema = @Schema(implementation = ErrorResponse.class), - examples = @ExampleObject( - value = "{\"status\": 400, \"code\": \"G003\", \"message\": \"입력값이 없거나, 타입이 유효하지 않습니다.\"}" - ) - )), - @ApiResponse(responseCode = "404", description = "데이터가 존재하지 않습니다.", content = @Content( - schema = @Schema(implementation = ErrorResponse.class), - examples = @ExampleObject( - value = "{\"status\": 404, \"code\": \"G004\", \"message\": \"데이터가 존재하지 않습니다.\"}" - ) - )) - }) - public ResponseEntity updatePolicyTerm(@PathVariable Long policyTermId, - @Valid @RequestBody SavePolicyTernDto savePolicyTernDto) { + @GetMapping("/policy/{policyTermId}") + @SecurityRequirements(value = {}) + @Operation(summary = "해당 정책을 조회한다.", description = "policyTermId는 1,2,3만 존재") + @ApiResponses({ + @ApiResponse( + responseCode = "200", + content = @Content(schema = @Schema(implementation = PolicyTermDto.class))), + @ApiResponse( + responseCode = "400 ", + description = "입력값이 없거나, 타입이 유효하지 않습니다.", + content = + @Content( + schema = @Schema(implementation = ErrorResponse.class), + examples = + @ExampleObject( + value = + "{\"status\": 400, \"code\": \"G003\", \"message\": \"입력값이 없거나, 타입이 유효하지 않습니다.\"}"))), + @ApiResponse( + responseCode = "404", + description = "데이터가 존재하지 않습니다.", + content = + @Content( + schema = @Schema(implementation = ErrorResponse.class), + examples = + @ExampleObject( + value = + "{\"status\": 404, \"code\": \"G004\", \"message\": \"데이터가 존재하지 않습니다.\"}"))) + }) + public ResponseEntity findPolicyTerm(@PathVariable Long policyTermId) { - policyTermService.updatePolicyTerm(policyTermId, savePolicyTernDto); - return ResponseEntity.noContent().build(); + PolicyTermDto policyTermDto = policyTermService.findPolicyTerm(policyTermId); + return ResponseEntity.ok(policyTermDto); + } - } + @PutMapping("/policy/{policyTermId}") + @Operation(summary = "해당 정책을 수정한다.", description = "policyTermId는 1,2,3만 존재") + @ApiResponses({ + @ApiResponse(responseCode = "204"), + @ApiResponse( + responseCode = "400 ", + description = "입력값이 없거나, 타입이 유효하지 않습니다.", + content = + @Content( + schema = @Schema(implementation = ErrorResponse.class), + examples = + @ExampleObject( + value = + "{\"status\": 400, \"code\": \"G003\", \"message\": \"입력값이 없거나, 타입이 유효하지 않습니다.\"}"))), + @ApiResponse( + responseCode = "404", + description = "데이터가 존재하지 않습니다.", + content = + @Content( + schema = @Schema(implementation = ErrorResponse.class), + examples = + @ExampleObject( + value = + "{\"status\": 404, \"code\": \"G004\", \"message\": \"데이터가 존재하지 않습니다.\"}"))) + }) + public ResponseEntity updatePolicyTerm( + @PathVariable Long policyTermId, @Valid @RequestBody SavePolicyTernDto savePolicyTernDto) { + policyTermService.updatePolicyTerm(policyTermId, savePolicyTernDto); + return ResponseEntity.noContent().build(); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/web/SignUpController.java b/resource-server/src/main/java/com/inhabas/api/web/SignUpController.java index 1c64aad7..a57843b3 100644 --- a/resource-server/src/main/java/com/inhabas/api/web/SignUpController.java +++ b/resource-server/src/main/java/com/inhabas/api/web/SignUpController.java @@ -1,5 +1,14 @@ package com.inhabas.api.web; +import java.util.*; + +import javax.validation.Valid; + +import lombok.RequiredArgsConstructor; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + import com.inhabas.api.auth.domain.error.ErrorResponse; import com.inhabas.api.auth.domain.oauth2.majorInfo.dto.MajorInfoDto; import com.inhabas.api.domain.questionnaire.dto.QuestionnaireDto; @@ -15,204 +24,232 @@ import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.security.SecurityRequirements; import io.swagger.v3.oas.annotations.tags.Tag; -import lombok.RequiredArgsConstructor; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; - -import javax.validation.Valid; -import java.util.*; @Tag(name = "회원가입", description = "회원가입 기간이 아니면 403 Forbidden") @RestController @RequiredArgsConstructor public class SignUpController { - private final SignUpService signUpService; - - - @GetMapping("/signUp/check") - @Operation(summary = "요청을 보낸 사용자가 회원가입을 했는지 확인한다.", - description = "회원가입을 이미 했다면 true, 아니면 false") - @ApiResponses({ - @ApiResponse(responseCode = "200", content = @Content( - schema = @Schema(implementation = SignUpDto.class))), - @ApiResponse(responseCode = "403 ", description = "회원가입 기간이 아닙니다.", content = @Content( - schema = @Schema(implementation = ErrorResponse.class), - examples = @ExampleObject( - value = "{\"status\": 403, \"code\": \"S001\", \"message\": \"회원가입 기간이 아닙니다.\"}" - ) - )) - }) - public ResponseEntity> signUpCheck( - @Authenticated Long memberId) { - boolean check = signUpService.isSignedUp(memberId); - return ResponseEntity.ok(Collections.singletonMap("check", check)); - } - - - @Operation(summary = "회원가입 시 자신의 개인정보를 저장한다.") - @ApiResponses({ - @ApiResponse(responseCode = "204"), - @ApiResponse(responseCode = "400 ", description = "입력값이 없거나, 타입이 유효하지 않습니다.", content = @Content( - schema = @Schema(implementation = ErrorResponse.class), - examples = @ExampleObject( - value = "{\"status\": 400, \"code\": \"G003\", \"message\": \"입력값이 없거나, 타입이 유효하지 않습니다.\"}" - ) - )), - @ApiResponse(responseCode = "403 ", description = "회원가입 기간이 아닙니다.", content = @Content( - schema = @Schema(implementation = ErrorResponse.class), - examples = @ExampleObject( - value = "{\"status\": 403, \"code\": \"S001\", \"message\": \"회원가입 기간이 아닙니다.\"}" - ) - )) - }) - @PostMapping("/signUp") - public ResponseEntity saveStudentProfile( - @Authenticated Long memberId, @Valid @RequestBody SignUpDto form) { - - signUpService.saveSignUpForm(form, memberId); - - return ResponseEntity.noContent().build(); - - } - - /* profile */ - - @GetMapping("/signUp") - @Operation(summary = "자신이 임시저장한 개인정보를 불러온다.", - description = "저장한 이력이 없다면 모두 null 반환") - @ApiResponses({ - @ApiResponse(responseCode = "200", content = @Content( - schema = @Schema(implementation = SignUpDto.class))), - @ApiResponse(responseCode = "403 ", description = "회원가입 기간이 아닙니다.", content = @Content( - schema = @Schema(implementation = ErrorResponse.class), - examples = @ExampleObject( - value = "{\"status\": 403, \"code\": \"S001\", \"message\": \"회원가입 기간이 아닙니다.\"}" - ) - )) - }) - public ResponseEntity loadProfile( - @Authenticated Long memberId) { - - SignUpDto form = signUpService.loadSignUpForm(memberId); - - return ResponseEntity.ok(form); - - } - - - @Operation(summary = "회원가입에 필요한 전공 정보를 모두 불러온다.") - @ApiResponses({ - @ApiResponse(responseCode = "200", content = @Content( - schema = @Schema(implementation = SignUpDto.class))), - @ApiResponse(responseCode = "403 ", description = "회원가입 기간이 아닙니다.", content = @Content( - schema = @Schema(implementation = ErrorResponse.class), - examples = @ExampleObject( - value = "{\"status\": 403, \"code\": \"S001\", \"message\": \"회원가입 기간이 아닙니다.\"}" - ) - )) - }) - - @SecurityRequirements(value = {}) - @GetMapping("/signUp/majorInfo") - public ResponseEntity> loadAllMajorInfo() { - - return ResponseEntity.ok(signUpService.getMajorInfo()); - - } - - - /* questionnaire */ - - @Operation(summary = "회원가입에 필요한 질문들을 불러온다.") - @ApiResponses({ - @ApiResponse(responseCode = "200", content = @Content( - schema = @Schema(implementation = QuestionnaireDto.class))), - @ApiResponse(responseCode = "403 ", description = "회원가입 기간이 아닙니다.", content = @Content( - schema = @Schema(implementation = ErrorResponse.class), - examples = @ExampleObject( - value = "{\"status\": 403, \"code\": \"S001\", \"message\": \"회원가입 기간이 아닙니다.\"}" - ) - )) - }) - @SecurityRequirements(value = {}) - @GetMapping("/signUp/questionnaires") - public ResponseEntity> loadQuestionnaire() { - - return ResponseEntity.ok(signUpService.getQuestionnaire()); - - } - - /* answer */ - - @GetMapping("/signUp/answers") - @Operation(summary = "회원가입 도중 자신이 임시 저장한 질문지 답변을 불러온다.") - @ApiResponses({ - @ApiResponse(responseCode = "200", content = @Content( - schema = @Schema(implementation = AnswerDto.class))), - @ApiResponse(responseCode = "403 ", description = "회원가입 기간이 아닙니다.", content = @Content( - schema = @Schema(implementation = ErrorResponse.class), - examples = @ExampleObject( - value = "{\"status\": 403, \"code\": \"S001\", \"message\": \"회원가입 기간이 아닙니다.\"}" - ) - )) - }) - public ResponseEntity> loadAnswers(@Authenticated Long memberId) { - - List answers = signUpService.getAnswers(memberId); - - return ResponseEntity.ok(answers); - } - - @PostMapping("/signUp/answers") - @Operation(summary = "회원가입 시 자신이 작성한 답변을 임시 저장한다.") - @ApiResponses({ - @ApiResponse(responseCode = "200"), - @ApiResponse(responseCode = "400 ", description = "입력값이 없거나, 타입이 유효하지 않습니다.", content = @Content( - schema = @Schema(implementation = ErrorResponse.class), - examples = @ExampleObject( - value = "{\"status\": 400, \"code\": \"G003\", \"message\": \"입력값이 없거나, 타입이 유효하지 않습니다.\"}" - ) - )), - @ApiResponse(responseCode = "403 ", description = "회원가입 기간이 아닙니다.", content = @Content( - schema = @Schema(implementation = ErrorResponse.class), - examples = @ExampleObject( - value = "{\"status\": 403, \"code\": \"S001\", \"message\": \"회원가입 기간이 아닙니다.\"}" - ) - )) - }) - public ResponseEntity saveAnswers( - @Authenticated Long memberId, @Valid @RequestBody List answers) { - - signUpService.saveAnswers(answers, memberId); - - return ResponseEntity.ok().build(); - - } - - /* finish signUp */ - @PutMapping("/signUp") - @Operation(summary = "회원가입을 완료한다") - @ApiResponses({ - @ApiResponse(responseCode = "204"), - @ApiResponse(responseCode = "400 ", description = "입력값이 없거나, 타입이 유효하지 않습니다.", content = @Content( - schema = @Schema(implementation = ErrorResponse.class), - examples = @ExampleObject( - value = "{\"status\": 400, \"code\": \"G003\", \"message\": \"입력값이 없거나, 타입이 유효하지 않습니다.\"}" - ) - )), - @ApiResponse(responseCode = "403 ", description = "회원가입 기간이 아닙니다.", content = @Content( - schema = @Schema(implementation = ErrorResponse.class), - examples = @ExampleObject( - value = "{\"status\": 403, \"code\": \"S001\", \"message\": \"회원가입 기간이 아닙니다.\"}" - ) - )) - }) - public ResponseEntity finishSignUp(@Authenticated Long memberId, @Valid @RequestBody Optional> answers) { - - signUpService.completeSignUp(answers.orElse(new ArrayList<>()), memberId); - return ResponseEntity.noContent().build(); - - } - + private final SignUpService signUpService; + + @GetMapping("/signUp/check") + @Operation(summary = "요청을 보낸 사용자가 회원가입을 했는지 확인한다.", description = "회원가입을 이미 했다면 true, 아니면 false") + @ApiResponses({ + @ApiResponse( + responseCode = "200", + content = @Content(schema = @Schema(implementation = SignUpDto.class))), + @ApiResponse( + responseCode = "403 ", + description = "회원가입 기간이 아닙니다.", + content = + @Content( + schema = @Schema(implementation = ErrorResponse.class), + examples = + @ExampleObject( + value = + "{\"status\": 403, \"code\": \"S001\", \"message\": \"회원가입 기간이 아닙니다.\"}"))) + }) + public ResponseEntity> signUpCheck(@Authenticated Long memberId) { + boolean check = signUpService.isSignedUp(memberId); + return ResponseEntity.ok(Collections.singletonMap("check", check)); + } + + @Operation(summary = "회원가입 시 자신의 개인정보를 저장한다.") + @ApiResponses({ + @ApiResponse(responseCode = "204"), + @ApiResponse( + responseCode = "400 ", + description = "입력값이 없거나, 타입이 유효하지 않습니다.", + content = + @Content( + schema = @Schema(implementation = ErrorResponse.class), + examples = + @ExampleObject( + value = + "{\"status\": 400, \"code\": \"G003\", \"message\": \"입력값이 없거나, 타입이 유효하지 않습니다.\"}"))), + @ApiResponse( + responseCode = "403 ", + description = "회원가입 기간이 아닙니다.", + content = + @Content( + schema = @Schema(implementation = ErrorResponse.class), + examples = + @ExampleObject( + value = + "{\"status\": 403, \"code\": \"S001\", \"message\": \"회원가입 기간이 아닙니다.\"}"))) + }) + @PostMapping("/signUp") + public ResponseEntity saveStudentProfile( + @Authenticated Long memberId, @Valid @RequestBody SignUpDto form) { + + signUpService.saveSignUpForm(form, memberId); + + return ResponseEntity.noContent().build(); + } + + /* profile */ + + @GetMapping("/signUp") + @Operation(summary = "자신이 임시저장한 개인정보를 불러온다.", description = "저장한 이력이 없다면 모두 null 반환") + @ApiResponses({ + @ApiResponse( + responseCode = "200", + content = @Content(schema = @Schema(implementation = SignUpDto.class))), + @ApiResponse( + responseCode = "403 ", + description = "회원가입 기간이 아닙니다.", + content = + @Content( + schema = @Schema(implementation = ErrorResponse.class), + examples = + @ExampleObject( + value = + "{\"status\": 403, \"code\": \"S001\", \"message\": \"회원가입 기간이 아닙니다.\"}"))) + }) + public ResponseEntity loadProfile(@Authenticated Long memberId) { + + SignUpDto form = signUpService.loadSignUpForm(memberId); + + return ResponseEntity.ok(form); + } + + @Operation(summary = "회원가입에 필요한 전공 정보를 모두 불러온다.") + @ApiResponses({ + @ApiResponse( + responseCode = "200", + content = @Content(schema = @Schema(implementation = SignUpDto.class))), + @ApiResponse( + responseCode = "403 ", + description = "회원가입 기간이 아닙니다.", + content = + @Content( + schema = @Schema(implementation = ErrorResponse.class), + examples = + @ExampleObject( + value = + "{\"status\": 403, \"code\": \"S001\", \"message\": \"회원가입 기간이 아닙니다.\"}"))) + }) + @SecurityRequirements(value = {}) + @GetMapping("/signUp/majorInfo") + public ResponseEntity> loadAllMajorInfo() { + + return ResponseEntity.ok(signUpService.getMajorInfo()); + } + + /* questionnaire */ + + @Operation(summary = "회원가입에 필요한 질문들을 불러온다.") + @ApiResponses({ + @ApiResponse( + responseCode = "200", + content = @Content(schema = @Schema(implementation = QuestionnaireDto.class))), + @ApiResponse( + responseCode = "403 ", + description = "회원가입 기간이 아닙니다.", + content = + @Content( + schema = @Schema(implementation = ErrorResponse.class), + examples = + @ExampleObject( + value = + "{\"status\": 403, \"code\": \"S001\", \"message\": \"회원가입 기간이 아닙니다.\"}"))) + }) + @SecurityRequirements(value = {}) + @GetMapping("/signUp/questionnaires") + public ResponseEntity> loadQuestionnaire() { + + return ResponseEntity.ok(signUpService.getQuestionnaire()); + } + + /* answer */ + + @GetMapping("/signUp/answers") + @Operation(summary = "회원가입 도중 자신이 임시 저장한 질문지 답변을 불러온다.") + @ApiResponses({ + @ApiResponse( + responseCode = "200", + content = @Content(schema = @Schema(implementation = AnswerDto.class))), + @ApiResponse( + responseCode = "403 ", + description = "회원가입 기간이 아닙니다.", + content = + @Content( + schema = @Schema(implementation = ErrorResponse.class), + examples = + @ExampleObject( + value = + "{\"status\": 403, \"code\": \"S001\", \"message\": \"회원가입 기간이 아닙니다.\"}"))) + }) + public ResponseEntity> loadAnswers(@Authenticated Long memberId) { + + List answers = signUpService.getAnswers(memberId); + + return ResponseEntity.ok(answers); + } + + @PostMapping("/signUp/answers") + @Operation(summary = "회원가입 시 자신이 작성한 답변을 임시 저장한다.") + @ApiResponses({ + @ApiResponse(responseCode = "200"), + @ApiResponse( + responseCode = "400 ", + description = "입력값이 없거나, 타입이 유효하지 않습니다.", + content = + @Content( + schema = @Schema(implementation = ErrorResponse.class), + examples = + @ExampleObject( + value = + "{\"status\": 400, \"code\": \"G003\", \"message\": \"입력값이 없거나, 타입이 유효하지 않습니다.\"}"))), + @ApiResponse( + responseCode = "403 ", + description = "회원가입 기간이 아닙니다.", + content = + @Content( + schema = @Schema(implementation = ErrorResponse.class), + examples = + @ExampleObject( + value = + "{\"status\": 403, \"code\": \"S001\", \"message\": \"회원가입 기간이 아닙니다.\"}"))) + }) + public ResponseEntity saveAnswers( + @Authenticated Long memberId, @Valid @RequestBody List answers) { + + signUpService.saveAnswers(answers, memberId); + + return ResponseEntity.ok().build(); + } + + /* finish signUp */ + @PutMapping("/signUp") + @Operation(summary = "회원가입을 완료한다") + @ApiResponses({ + @ApiResponse(responseCode = "204"), + @ApiResponse( + responseCode = "400 ", + description = "입력값이 없거나, 타입이 유효하지 않습니다.", + content = + @Content( + schema = @Schema(implementation = ErrorResponse.class), + examples = + @ExampleObject( + value = + "{\"status\": 400, \"code\": \"G003\", \"message\": \"입력값이 없거나, 타입이 유효하지 않습니다.\"}"))), + @ApiResponse( + responseCode = "403 ", + description = "회원가입 기간이 아닙니다.", + content = + @Content( + schema = @Schema(implementation = ErrorResponse.class), + examples = + @ExampleObject( + value = + "{\"status\": 403, \"code\": \"S001\", \"message\": \"회원가입 기간이 아닙니다.\"}"))) + }) + public ResponseEntity finishSignUp( + @Authenticated Long memberId, @Valid @RequestBody Optional> answers) { + + signUpService.completeSignUp(answers.orElse(new ArrayList<>()), memberId); + return ResponseEntity.noContent().build(); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/web/SignUpScheduleController.java b/resource-server/src/main/java/com/inhabas/api/web/SignUpScheduleController.java index 4094ace2..658eb0b2 100644 --- a/resource-server/src/main/java/com/inhabas/api/web/SignUpScheduleController.java +++ b/resource-server/src/main/java/com/inhabas/api/web/SignUpScheduleController.java @@ -1,5 +1,12 @@ package com.inhabas.api.web; +import javax.validation.Valid; + +import lombok.RequiredArgsConstructor; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + import com.inhabas.api.auth.domain.error.ErrorResponse; import com.inhabas.api.domain.signUpSchedule.dto.SignUpScheduleDto; import com.inhabas.api.domain.signUpSchedule.usecase.SignUpScheduler; @@ -11,55 +18,56 @@ import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.security.SecurityRequirements; import io.swagger.v3.oas.annotations.tags.Tag; -import lombok.RequiredArgsConstructor; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; - -import javax.validation.Valid; -@Tag(name="회원가입 일정", description = "회원가입 일정 조회, 수정 / 회장만") +@Tag(name = "회원가입 일정", description = "회원가입 일정 조회, 수정 / 회장만") @RestController @RequestMapping("/signUp/schedule") @RequiredArgsConstructor public class SignUpScheduleController { - private final SignUpScheduler signUpScheduler; - - - @Operation(summary = "회원가입 관련 일정을 조회한다.", - description = "일정은 하나만 반환한다.") - @SecurityRequirements(value = {}) - @ApiResponse(responseCode = "200", content = { - @Content(schema = @Schema(implementation = SignUpScheduleDto.class)) - }) - @GetMapping - public ResponseEntity getSignUpSchedule() { - - return ResponseEntity.ok(signUpScheduler.getSchedule()); - - } + private final SignUpScheduler signUpScheduler; - @Operation(summary = "회원가입 관련 일정을 수정한다.") - @ApiResponses({ - @ApiResponse(responseCode = "204"), - @ApiResponse(responseCode = "400", description = "등록 마감일이 시작일보다 앞설 수 없습니다.", - content = @Content( - schema = @Schema(implementation = ErrorResponse.class), - examples = { - @ExampleObject(name = "등록 마감일 오류", value = "{\"status\": 400, \"code\": \"S002\", \"message\": \"등록 마감일이 시작일보다 앞설 수 없습니다.\"}"), - @ExampleObject(name = "면접 마감일 오류", value = "{\"status\": 400, \"code\": \"S003\", \"message\": \"면접 마감일이 시작일보다 앞설 수 없습니다.\"}"), - @ExampleObject(name = "결과 발표일 오류", value = "{\"status\": 400, \"code\": \"S004\", \"message\": \"결과 발표일이 면접 마감일보다 앞설 수 없습니다.\"}") - } - ) - ) - }) - @PutMapping - public ResponseEntity updateSignUpSchedule(@Valid @RequestBody SignUpScheduleDto signUpScheduleDto) { + @Operation(summary = "회원가입 관련 일정을 조회한다.", description = "일정은 하나만 반환한다.") + @SecurityRequirements(value = {}) + @ApiResponse( + responseCode = "200", + content = {@Content(schema = @Schema(implementation = SignUpScheduleDto.class))}) + @GetMapping + public ResponseEntity getSignUpSchedule() { - signUpScheduler.updateSchedule(signUpScheduleDto); + return ResponseEntity.ok(signUpScheduler.getSchedule()); + } - return ResponseEntity.noContent().build(); + @Operation(summary = "회원가입 관련 일정을 수정한다.") + @ApiResponses({ + @ApiResponse(responseCode = "204"), + @ApiResponse( + responseCode = "400", + description = "등록 마감일이 시작일보다 앞설 수 없습니다.", + content = + @Content( + schema = @Schema(implementation = ErrorResponse.class), + examples = { + @ExampleObject( + name = "등록 마감일 오류", + value = + "{\"status\": 400, \"code\": \"S002\", \"message\": \"등록 마감일이 시작일보다 앞설 수 없습니다.\"}"), + @ExampleObject( + name = "면접 마감일 오류", + value = + "{\"status\": 400, \"code\": \"S003\", \"message\": \"면접 마감일이 시작일보다 앞설 수 없습니다.\"}"), + @ExampleObject( + name = "결과 발표일 오류", + value = + "{\"status\": 400, \"code\": \"S004\", \"message\": \"결과 발표일이 면접 마감일보다 앞설 수 없습니다.\"}") + })) + }) + @PutMapping + public ResponseEntity updateSignUpSchedule( + @Valid @RequestBody SignUpScheduleDto signUpScheduleDto) { - } + signUpScheduler.updateSchedule(signUpScheduleDto); + return ResponseEntity.noContent().build(); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/web/argumentResolver/ArgumentResolverConfig.java b/resource-server/src/main/java/com/inhabas/api/web/argumentResolver/ArgumentResolverConfig.java index a93c4192..c87d5148 100644 --- a/resource-server/src/main/java/com/inhabas/api/web/argumentResolver/ArgumentResolverConfig.java +++ b/resource-server/src/main/java/com/inhabas/api/web/argumentResolver/ArgumentResolverConfig.java @@ -1,7 +1,9 @@ package com.inhabas.api.web.argumentResolver; import java.util.List; + import lombok.RequiredArgsConstructor; + import org.springframework.context.annotation.Configuration; import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @@ -10,11 +12,11 @@ @RequiredArgsConstructor public class ArgumentResolverConfig implements WebMvcConfigurer { - private final LoginMemberArgumentResolver loginMemberArgumentResolver; + private final LoginMemberArgumentResolver loginMemberArgumentResolver; - @Override - public void addArgumentResolvers(List resolvers) { - resolvers.add(loginMemberArgumentResolver); - WebMvcConfigurer.super.addArgumentResolvers(resolvers); - } + @Override + public void addArgumentResolvers(List resolvers) { + resolvers.add(loginMemberArgumentResolver); + WebMvcConfigurer.super.addArgumentResolvers(resolvers); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/web/argumentResolver/Authenticated.java b/resource-server/src/main/java/com/inhabas/api/web/argumentResolver/Authenticated.java index 355d3ac6..e70d51cb 100644 --- a/resource-server/src/main/java/com/inhabas/api/web/argumentResolver/Authenticated.java +++ b/resource-server/src/main/java/com/inhabas/api/web/argumentResolver/Authenticated.java @@ -1,14 +1,13 @@ package com.inhabas.api.web.argumentResolver; -import io.swagger.v3.oas.annotations.Parameter; - import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import io.swagger.v3.oas.annotations.Parameter; + @Target(ElementType.PARAMETER) @Retention(RetentionPolicy.RUNTIME) @Parameter(hidden = true) -public @interface Authenticated { -} +public @interface Authenticated {} diff --git a/resource-server/src/main/java/com/inhabas/api/web/argumentResolver/LoginMemberArgumentResolver.java b/resource-server/src/main/java/com/inhabas/api/web/argumentResolver/LoginMemberArgumentResolver.java index a7b2f459..5cf13d44 100644 --- a/resource-server/src/main/java/com/inhabas/api/web/argumentResolver/LoginMemberArgumentResolver.java +++ b/resource-server/src/main/java/com/inhabas/api/web/argumentResolver/LoginMemberArgumentResolver.java @@ -1,7 +1,7 @@ package com.inhabas.api.web.argumentResolver; -import com.inhabas.api.auth.domain.token.exception.TokenMissingException; import lombok.extern.slf4j.Slf4j; + import org.springframework.core.MethodParameter; import org.springframework.security.core.Authentication; import org.springframework.security.core.GrantedAuthority; @@ -12,35 +12,40 @@ import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.method.support.ModelAndViewContainer; +import com.inhabas.api.auth.domain.token.exception.TokenMissingException; + @Slf4j @Component public class LoginMemberArgumentResolver implements HandlerMethodArgumentResolver { - @Override - public boolean supportsParameter(MethodParameter parameter) { - return parameter.hasParameterAnnotation(Authenticated.class); - } - - /** - * SecurityContextHolder에서 받아온 authentication을 기준으로 memberId를 찾아 반환한다. - * @param parameter @Authenticated 어노테이션에 의해 받아온 파라미터. - * @return Long memberId / null일 경우 null을 반환할 수 있음. - */ - @Override - public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) { - - Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); - - // login not processed, anonymous user! - for (GrantedAuthority authority : authentication.getAuthorities()) { - if ("ROLE_ANONYMOUS".equals(authority.getAuthority())) { - log.error("Anonymous cannot access"); - throw new TokenMissingException(); - } - } - - return (Long) authentication.getPrincipal(); - + @Override + public boolean supportsParameter(MethodParameter parameter) { + return parameter.hasParameterAnnotation(Authenticated.class); + } + + /** + * SecurityContextHolder에서 받아온 authentication을 기준으로 memberId를 찾아 반환한다. + * + * @param parameter @Authenticated 어노테이션에 의해 받아온 파라미터. + * @return Long memberId / null일 경우 null을 반환할 수 있음. + */ + @Override + public Object resolveArgument( + MethodParameter parameter, + ModelAndViewContainer mavContainer, + NativeWebRequest webRequest, + WebDataBinderFactory binderFactory) { + + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + + // login not processed, anonymous user! + for (GrantedAuthority authority : authentication.getAuthorities()) { + if ("ROLE_ANONYMOUS".equals(authority.getAuthority())) { + log.error("Anonymous cannot access"); + throw new TokenMissingException(); + } } + return (Long) authentication.getPrincipal(); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/web/converter/MenuIdConverter.java b/resource-server/src/main/java/com/inhabas/api/web/converter/MenuIdConverter.java index 8d052675..eb7523a7 100644 --- a/resource-server/src/main/java/com/inhabas/api/web/converter/MenuIdConverter.java +++ b/resource-server/src/main/java/com/inhabas/api/web/converter/MenuIdConverter.java @@ -1,25 +1,25 @@ package com.inhabas.api.web.converter; -import com.inhabas.api.domain.menu.domain.valueObject.MenuId; import org.springframework.core.convert.converter.Converter; import org.springframework.stereotype.Component; +import com.inhabas.api.domain.menu.domain.valueObject.MenuId; + public class MenuIdConverter { - @Component - public static class StringToMenuIdConverter implements Converter { - @Override - public MenuId convert(String source){ - return new MenuId(Integer.parseInt(source)); - } + @Component + public static class StringToMenuIdConverter implements Converter { + @Override + public MenuId convert(String source) { + return new MenuId(Integer.parseInt(source)); } + } - @Component - public static class MenuIdToStringConverter implements Converter{ - @Override - public String convert(MenuId source){ - return source.toString(); - } + @Component + public static class MenuIdToStringConverter implements Converter { + @Override + public String convert(MenuId source) { + return source.toString(); } - + } } diff --git a/resource-server/src/main/java/com/inhabas/api/web/interceptor/InterceptorConfig.java b/resource-server/src/main/java/com/inhabas/api/web/interceptor/InterceptorConfig.java index 4ceaf765..88956caf 100644 --- a/resource-server/src/main/java/com/inhabas/api/web/interceptor/InterceptorConfig.java +++ b/resource-server/src/main/java/com/inhabas/api/web/interceptor/InterceptorConfig.java @@ -1,30 +1,35 @@ package com.inhabas.api.web.interceptor; -import com.inhabas.api.domain.signUpSchedule.usecase.SignUpAvailabilityChecker; import lombok.RequiredArgsConstructor; + import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import com.inhabas.api.domain.signUpSchedule.usecase.SignUpAvailabilityChecker; + @Configuration @RequiredArgsConstructor public class InterceptorConfig implements WebMvcConfigurer { - private final SignUpAvailabilityChecker signUpAvailabilityChecker; - private static final String[] WHITELIST_SIGNUP_SCHEDULE = {"/signUp/schedule", "/signUp/check", - "/signUp/questionnaires", "/signUp/majorInfo"}; + private final SignUpAvailabilityChecker signUpAvailabilityChecker; + private static final String[] WHITELIST_SIGNUP_SCHEDULE = { + "/signUp/schedule", "/signUp/check", "/signUp/questionnaires", "/signUp/majorInfo" + }; - @Bean - SignUpControllerInterceptor signUpControllerInterceptor() { - return new SignUpControllerInterceptor(signUpAvailabilityChecker); - } + @Bean + SignUpControllerInterceptor signUpControllerInterceptor() { + return new SignUpControllerInterceptor(signUpAvailabilityChecker); + } - @Override - public void addInterceptors(InterceptorRegistry registry) { - registry.addInterceptor(signUpControllerInterceptor()) - .addPathPatterns("/signUp/**").excludePathPatterns(WHITELIST_SIGNUP_SCHEDULE); + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry + .addInterceptor(signUpControllerInterceptor()) + .addPathPatterns("/signUp/**") + .excludePathPatterns(WHITELIST_SIGNUP_SCHEDULE); - WebMvcConfigurer.super.addInterceptors(registry); - } + WebMvcConfigurer.super.addInterceptors(registry); + } } diff --git a/resource-server/src/main/java/com/inhabas/api/web/interceptor/SignUpControllerInterceptor.java b/resource-server/src/main/java/com/inhabas/api/web/interceptor/SignUpControllerInterceptor.java index d7a693d3..3d7128c1 100644 --- a/resource-server/src/main/java/com/inhabas/api/web/interceptor/SignUpControllerInterceptor.java +++ b/resource-server/src/main/java/com/inhabas/api/web/interceptor/SignUpControllerInterceptor.java @@ -1,25 +1,25 @@ package com.inhabas.api.web.interceptor; -import com.inhabas.api.domain.signUpSchedule.usecase.SignUpAvailabilityChecker; -import com.inhabas.api.domain.signUpSchedule.exception.SignUpNotAvailableException; -import lombok.RequiredArgsConstructor; -import org.springframework.web.servlet.HandlerInterceptor; - import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import lombok.RequiredArgsConstructor; + +import org.springframework.web.servlet.HandlerInterceptor; + +import com.inhabas.api.domain.signUpSchedule.exception.SignUpNotAvailableException; +import com.inhabas.api.domain.signUpSchedule.usecase.SignUpAvailabilityChecker; @RequiredArgsConstructor public class SignUpControllerInterceptor implements HandlerInterceptor { - private final SignUpAvailabilityChecker availabilityChecker; + private final SignUpAvailabilityChecker availabilityChecker; - @Override - public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { - if (availabilityChecker.isAvailable()) { - return true; - } - else - throw new SignUpNotAvailableException(); - } + @Override + public boolean preHandle( + HttpServletRequest request, HttpServletResponse response, Object handler) { + if (availabilityChecker.isAvailable()) { + return true; + } else throw new SignUpNotAvailableException(); + } } diff --git a/resource-server/src/test/java/com/inhabas/api/ApiApplicationTests.java b/resource-server/src/test/java/com/inhabas/api/ApiApplicationTests.java index e8e9a0a1..057762a0 100644 --- a/resource-server/src/test/java/com/inhabas/api/ApiApplicationTests.java +++ b/resource-server/src/test/java/com/inhabas/api/ApiApplicationTests.java @@ -1,15 +1,14 @@ package com.inhabas.api; -import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.ActiveProfiles; +import org.junit.jupiter.api.Test; + @SpringBootTest @ActiveProfiles("test") class ApiApplicationTests { - @Test - void contextLoads() { - } - + @Test + void contextLoads() {} } diff --git a/resource-server/src/test/java/com/inhabas/api/domain/BaseEntityTest.java b/resource-server/src/test/java/com/inhabas/api/domain/BaseEntityTest.java index f558ba5a..4f1d0d53 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/BaseEntityTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/BaseEntityTest.java @@ -1,79 +1,73 @@ package com.inhabas.api.domain; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager; +import org.springframework.context.annotation.Import; + import com.inhabas.api.JpaConfig; -import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; -import com.inhabas.api.domain.board.domain.NormalBoard; import com.inhabas.api.domain.menu.domain.Menu; import com.inhabas.api.domain.menu.domain.MenuGroup; import com.inhabas.api.domain.menu.domain.valueObject.MenuType; import com.inhabas.testAnnotataion.DefaultDataJpaTest; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager; -import org.springframework.context.annotation.Import; -import java.time.LocalDateTime; - -import static com.inhabas.api.domain.member.domain.entity.MemberTest.basicMember1; -import static org.assertj.core.api.Assertions.assertThat; +import org.junit.jupiter.api.BeforeEach; @DefaultDataJpaTest @Import(JpaConfig.class) public class BaseEntityTest { - @Autowired - TestEntityManager em; + @Autowired TestEntityManager em; - Menu freeBoardMenu; + Menu freeBoardMenu; - @BeforeEach - public void setUp() { - MenuGroup boardMenuGroup = em.persist(new MenuGroup("게시판")); - freeBoardMenu = em.persist( - Menu.builder() + @BeforeEach + public void setUp() { + MenuGroup boardMenuGroup = em.persist(new MenuGroup("게시판")); + freeBoardMenu = + em.persist( + Menu.builder() .menuGroup(boardMenuGroup) .priority(2) .type(MenuType.LIST) .name("자유게시판") .description("부원이 자유롭게 사용할 수 있는 게시판입니다.") .build()); - } + } -// @Test -// public void createdTimeTest() { -// //given -// Member member = em.persist(basicMember1()); -// NormalBoard board = new NormalBoard("title", "content") -// .writtenBy(member.getId()) -// .inMenu(freeBoardMenu.getId()); -// -// //when -// em.persist(board); -// -// //then -// assertThat(board.getDateCreated()).isNotNull(); -// assertThat(board.getDateCreated()).isInstanceOf(LocalDateTime.class); -// } + // @Test + // public void createdTimeTest() { + // //given + // Member member = em.persist(basicMember1()); + // NormalBoard board = new NormalBoard("title", "content") + // .writtenBy(member.getId()) + // .inMenu(freeBoardMenu.getId()); + // + // //when + // em.persist(board); + // + // //then + // assertThat(board.getDateCreated()).isNotNull(); + // assertThat(board.getDateCreated()).isInstanceOf(LocalDateTime.class); + // } -// @Test -// public void updatedTimeTest() { -// //given -// Member member = em.persist(basicMember1()); -// NormalBoard board = new NormalBoard("title", "content") -// .writtenBy(member.getId()) -// .inMenu(freeBoardMenu.getId()); -// em.persist(board); -// -// //when -// board.modify("title2", "modified content", member.getId()); -// em.merge(board); -// em.flush();em.clear(); -// -// //then -// NormalBoard find = em.find(NormalBoard.class, board.getId()); -// assertThat(find.getDateUpdated()).isNotNull(); -// assertThat(find.getDateUpdated()).isInstanceOf(LocalDateTime.class); -// } + // @Test + // public void updatedTimeTest() { + // //given + // Member member = em.persist(basicMember1()); + // NormalBoard board = new NormalBoard("title", "content") + // .writtenBy(member.getId()) + // .inMenu(freeBoardMenu.getId()); + // em.persist(board); + // + // //when + // board.modify("title2", "modified content", member.getId()); + // em.merge(board); + // em.flush();em.clear(); + // + // //then + // NormalBoard find = em.find(NormalBoard.class, board.getId()); + // assertThat(find.getDateUpdated()).isNotNull(); + // assertThat(find.getDateUpdated()).isInstanceOf(LocalDateTime.class); + // } } diff --git a/resource-server/src/test/java/com/inhabas/api/domain/board/domain/AlbumBoardTest.java b/resource-server/src/test/java/com/inhabas/api/domain/board/domain/AlbumBoardTest.java index db35caf1..82fd2cc3 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/board/domain/AlbumBoardTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/board/domain/AlbumBoardTest.java @@ -1,79 +1,72 @@ package com.inhabas.api.domain.board.domain; +import java.util.ArrayList; +import java.util.List; + import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; import com.inhabas.api.domain.file.domain.BoardFile; import com.inhabas.api.domain.menu.domain.Menu; import org.assertj.core.api.Assertions; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; -import java.util.ArrayList; -import java.util.List; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; class AlbumBoardTest { - @Mock - private Menu menu; - - @Mock - private Member writer; - - private AlbumBoard albumBoard; - - @BeforeEach - public void setUp() { - - MockitoAnnotations.openMocks(this); - - String title = "title1"; - String content = "content1"; - albumBoard = new AlbumBoard(title, menu, content); - - } + @Mock private Menu menu; - @DisplayName("올바른 AlbumBoard 를 생성한다.") - @Test - public void ConstructorTest() { - //then - Assertions.assertThat(albumBoard.getTitle()).isEqualTo("title1"); - Assertions.assertThat(albumBoard.getContent()).isEqualTo("content1"); + @Mock private Member writer; - } + private AlbumBoard albumBoard; - @DisplayName("AlbumBoard text 부분을 수정한다.") - @Test - public void updateTextTest() { - //given - String newTitle = "newTitle"; - String newContent = "newContent"; + @BeforeEach + public void setUp() { - //when - albumBoard.updateText(newTitle, newContent); + MockitoAnnotations.openMocks(this); - //then - Assertions.assertThat(albumBoard.getTitle()).isEqualTo(newTitle); - Assertions.assertThat(albumBoard.getContent()).isEqualTo(newContent); + String title = "title1"; + String content = "content1"; + albumBoard = new AlbumBoard(title, menu, content); + } - } + @DisplayName("올바른 AlbumBoard 를 생성한다.") + @Test + public void ConstructorTest() { + // then + Assertions.assertThat(albumBoard.getTitle()).isEqualTo("title1"); + Assertions.assertThat(albumBoard.getContent()).isEqualTo("content1"); + } - @DisplayName("AlbumBoard file 부분을 수정한다.") - @Test - public void updateFilesTest() { - //given - List files = new ArrayList<>(); - BoardFile file = new BoardFile("fileName", "/hello", albumBoard); - files.add(file); + @DisplayName("AlbumBoard text 부분을 수정한다.") + @Test + public void updateTextTest() { + // given + String newTitle = "newTitle"; + String newContent = "newContent"; - //when - albumBoard.updateFiles(files); + // when + albumBoard.updateText(newTitle, newContent); - //then - Assertions.assertThat(albumBoard.getFiles().get(0)).isEqualTo(file); + // then + Assertions.assertThat(albumBoard.getTitle()).isEqualTo(newTitle); + Assertions.assertThat(albumBoard.getContent()).isEqualTo(newContent); + } - } + @DisplayName("AlbumBoard file 부분을 수정한다.") + @Test + public void updateFilesTest() { + // given + List files = new ArrayList<>(); + BoardFile file = new BoardFile("fileName", "/hello", albumBoard); + files.add(file); + // when + albumBoard.updateFiles(files); -} \ No newline at end of file + // then + Assertions.assertThat(albumBoard.getFiles().get(0)).isEqualTo(file); + } +} diff --git a/resource-server/src/test/java/com/inhabas/api/domain/board/domain/BaseBoardTest.java b/resource-server/src/test/java/com/inhabas/api/domain/board/domain/BaseBoardTest.java index 0454d4aa..10ed56cf 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/board/domain/BaseBoardTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/board/domain/BaseBoardTest.java @@ -1,93 +1,91 @@ package com.inhabas.api.domain.board.domain; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.Mockito.*; + +import org.springframework.test.util.ReflectionTestUtils; + import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; import com.inhabas.api.domain.board.exception.WriterUnmodifiableException; import com.inhabas.api.domain.comment.domain.Comment; import com.inhabas.api.domain.file.domain.BoardFile; import com.inhabas.api.domain.member.domain.entity.MemberTest; import com.inhabas.api.domain.menu.domain.Menu; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; -import org.springframework.test.util.ReflectionTestUtils; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.mockito.Mockito.*; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; class BaseBoardTest { - @Mock - private Menu menu; - - private BaseBoard baseBoard; - - @BeforeEach - void setUp() { - MockitoAnnotations.openMocks(this); - String title = "title1"; - Member member = MemberTest.chiefMember(); - ReflectionTestUtils.setField(member, "id", 1L); - baseBoard = mock(BaseBoard.class, withSettings().useConstructor(title, menu).defaultAnswer(CALLS_REAL_METHODS)); - baseBoard.writtenBy(member, BaseBoard.class); - } - - @Test - void ConstructorTest() { - //then - assertThat("title1").isEqualTo(baseBoard.getTitle()); - assertThat(menu).isEqualTo(baseBoard.menu); - - } - - @Test - void writtenByWriterUnmodifiableTest() { - //given - Member newMember = mock(Member.class); - - //when, then - assertThatThrownBy(() -> baseBoard.writtenBy(newMember, BaseBoard.class)) - .isInstanceOf(WriterUnmodifiableException.class) - .hasMessage("글 작성자를 변경 할 수 없습니다."); - - } - - @Test - void isWrittenByTest() { - //given - Member anotherMember = MemberTest.basicMember1(); - ReflectionTestUtils.setField(anotherMember, "id", 2L); - - //when, then - assertThat(baseBoard.isWrittenBy(anotherMember)).isFalse(); - - } - - @Test - void addFileTest() { - //given - BoardFile file = mock(BoardFile.class); - - //when - baseBoard.addFile(file); - - //then - assertThat(baseBoard.files.contains(file)).isTrue(); - - } - - @Test - void addCommentTest() { - //given - Comment comment = mock(Comment.class); - - //when - baseBoard.addComment(comment); - - //then - assertThat(baseBoard.comments.contains(comment)).isTrue(); - - } - -} \ No newline at end of file + @Mock private Menu menu; + + private BaseBoard baseBoard; + + @BeforeEach + void setUp() { + MockitoAnnotations.openMocks(this); + String title = "title1"; + Member member = MemberTest.chiefMember(); + ReflectionTestUtils.setField(member, "id", 1L); + baseBoard = + mock( + BaseBoard.class, + withSettings().useConstructor(title, menu).defaultAnswer(CALLS_REAL_METHODS)); + baseBoard.writtenBy(member, BaseBoard.class); + } + + @Test + void ConstructorTest() { + // then + assertThat("title1").isEqualTo(baseBoard.getTitle()); + assertThat(menu).isEqualTo(baseBoard.menu); + } + + @Test + void writtenByWriterUnmodifiableTest() { + // given + Member newMember = mock(Member.class); + + // when, then + assertThatThrownBy(() -> baseBoard.writtenBy(newMember, BaseBoard.class)) + .isInstanceOf(WriterUnmodifiableException.class) + .hasMessage("글 작성자를 변경 할 수 없습니다."); + } + + @Test + void isWrittenByTest() { + // given + Member anotherMember = MemberTest.basicMember1(); + ReflectionTestUtils.setField(anotherMember, "id", 2L); + + // when, then + assertThat(baseBoard.isWrittenBy(anotherMember)).isFalse(); + } + + @Test + void addFileTest() { + // given + BoardFile file = mock(BoardFile.class); + + // when + baseBoard.addFile(file); + + // then + assertThat(baseBoard.files.contains(file)).isTrue(); + } + + @Test + void addCommentTest() { + // given + Comment comment = mock(Comment.class); + + // when + baseBoard.addComment(comment); + + // then + assertThat(baseBoard.comments.contains(comment)).isTrue(); + } +} diff --git a/resource-server/src/test/java/com/inhabas/api/domain/board/domain/NormalBoardTest.java b/resource-server/src/test/java/com/inhabas/api/domain/board/domain/NormalBoardTest.java index 27d4e8c8..d112c4b6 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/board/domain/NormalBoardTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/board/domain/NormalBoardTest.java @@ -4,20 +4,21 @@ public class NormalBoardTest { - public static NormalBoard getBoard1() { - return new NormalBoard("이건 제목", "이건 내용입니다."); - } - public static NormalBoard getBoard2() { - return new NormalBoard("이건 공지", "이건 공지입니다."); - } - public static NormalBoard getBoard3() { - return new NormalBoard("이건 공지2", "이건 공지2입니다."); - } + public static NormalBoard getBoard1() { + return new NormalBoard("이건 제목", "이건 내용입니다."); + } - public static NormalBoard getTestBoard(Integer id) { - NormalBoard board = new NormalBoard("이건 공지2", "이건 공지2입니다."); - ReflectionTestUtils.setField(board, "id", id); - return board; - } + public static NormalBoard getBoard2() { + return new NormalBoard("이건 공지", "이건 공지입니다."); + } + public static NormalBoard getBoard3() { + return new NormalBoard("이건 공지2", "이건 공지2입니다."); + } + + public static NormalBoard getTestBoard(Integer id) { + NormalBoard board = new NormalBoard("이건 공지2", "이건 공지2입니다."); + ReflectionTestUtils.setField(board, "id", id); + return board; + } } diff --git a/resource-server/src/test/java/com/inhabas/api/domain/board/domain/valueObject/AlbumExampleTest.java b/resource-server/src/test/java/com/inhabas/api/domain/board/domain/valueObject/AlbumExampleTest.java index 4af24802..5f83c8eb 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/board/domain/valueObject/AlbumExampleTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/board/domain/valueObject/AlbumExampleTest.java @@ -1,35 +1,28 @@ package com.inhabas.api.domain.board.domain.valueObject; +import org.springframework.test.util.ReflectionTestUtils; + import com.inhabas.api.domain.board.domain.AlbumBoard; import com.inhabas.api.domain.menu.domain.Menu; import com.inhabas.api.domain.menu.domain.MenuGroup; import com.inhabas.api.domain.menu.domain.valueObject.MenuType; -import org.springframework.test.util.ReflectionTestUtils; public class AlbumExampleTest { - public static AlbumBoard getAlbumBoard1(Menu menu) { - return new AlbumBoard( - "제목1", - menu, - "내용1"); - } - - public static AlbumBoard getAlbumBoard2() { - return new AlbumBoard( - "제목2", - new Menu(new MenuGroup("IBAS"),2, MenuType.ALBUM,"동아리 활동", "설명"), - "내용2"); - } - + public static AlbumBoard getAlbumBoard1(Menu menu) { + return new AlbumBoard("제목1", menu, "내용1"); + } - public static AlbumBoard getAlbumBoardWithId(Long id) { - AlbumBoard board = new AlbumBoard( - "제목2", - new Menu(new MenuGroup("IBAS"),2, MenuType.ALBUM,"동아리 활동", "설명"), - "내용2"); - ReflectionTestUtils.setField(board, "id", id); - return board; - } + public static AlbumBoard getAlbumBoard2() { + return new AlbumBoard( + "제목2", new Menu(new MenuGroup("IBAS"), 2, MenuType.ALBUM, "동아리 활동", "설명"), "내용2"); + } + public static AlbumBoard getAlbumBoardWithId(Long id) { + AlbumBoard board = + new AlbumBoard( + "제목2", new Menu(new MenuGroup("IBAS"), 2, MenuType.ALBUM, "동아리 활동", "설명"), "내용2"); + ReflectionTestUtils.setField(board, "id", id); + return board; + } } diff --git a/resource-server/src/test/java/com/inhabas/api/domain/board/domain/valueObject/BoardContentTest.java b/resource-server/src/test/java/com/inhabas/api/domain/board/domain/valueObject/BoardContentTest.java index 325de019..440055d4 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/board/domain/valueObject/BoardContentTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/board/domain/valueObject/BoardContentTest.java @@ -1,48 +1,49 @@ package com.inhabas.api.domain.board.domain.valueObject; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; + import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; - public class BoardContentTest { - @DisplayName("Content 타입에 게시글 내용을 저장한다.") - @Test - public void Content_is_OK() { - String contentString = ".".repeat(16777215); // 16 MB - 1 - - Content content = new Content(contentString); - - assertThat(content.getValue()).isEqualTo(contentString); - } - - @DisplayName("Content 타입에 너무 긴 게시글을 저장한다. (16 MB - 1 byte) 이상") - @Test - public void Contents_is_too_long() { - String contentString = ".".repeat(16777215 + 1); // 16 MB - 1 byte - - //then - assertThatThrownBy(() -> new Content(contentString)) - .isInstanceOf(InvalidInputException.class) - .hasMessage("입력값이 없거나, 타입이 유효하지 않습니다."); - } - - @DisplayName("Content 타입에 공백을 저장할 수 없다.") - @Test - public void Contents_is_Empty() { - assertThatThrownBy(() -> new Content("")) - .isInstanceOf(InvalidInputException.class) - .hasMessage("입력값이 없거나, 타입이 유효하지 않습니다."); - } - - @DisplayName("Content 타입에 null 은 허용 안된다.") - @Test - public void Contents_is_Null() { - assertThatThrownBy(() -> new Content(null)) - .isInstanceOf(InvalidInputException.class) - .hasMessage("입력값이 없거나, 타입이 유효하지 않습니다."); - } + @DisplayName("Content 타입에 게시글 내용을 저장한다.") + @Test + public void Content_is_OK() { + String contentString = ".".repeat(16777215); // 16 MB - 1 + + Content content = new Content(contentString); + + assertThat(content.getValue()).isEqualTo(contentString); + } + + @DisplayName("Content 타입에 너무 긴 게시글을 저장한다. (16 MB - 1 byte) 이상") + @Test + public void Contents_is_too_long() { + String contentString = ".".repeat(16777215 + 1); // 16 MB - 1 byte + + // then + assertThatThrownBy(() -> new Content(contentString)) + .isInstanceOf(InvalidInputException.class) + .hasMessage("입력값이 없거나, 타입이 유효하지 않습니다."); + } + + @DisplayName("Content 타입에 공백을 저장할 수 없다.") + @Test + public void Contents_is_Empty() { + assertThatThrownBy(() -> new Content("")) + .isInstanceOf(InvalidInputException.class) + .hasMessage("입력값이 없거나, 타입이 유효하지 않습니다."); + } + + @DisplayName("Content 타입에 null 은 허용 안된다.") + @Test + public void Contents_is_Null() { + assertThatThrownBy(() -> new Content(null)) + .isInstanceOf(InvalidInputException.class) + .hasMessage("입력값이 없거나, 타입이 유효하지 않습니다."); + } } diff --git a/resource-server/src/test/java/com/inhabas/api/domain/board/domain/valueObject/TitleTest.java b/resource-server/src/test/java/com/inhabas/api/domain/board/domain/valueObject/TitleTest.java index f8ed47d8..4c9afa83 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/board/domain/valueObject/TitleTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/board/domain/valueObject/TitleTest.java @@ -4,49 +4,50 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; + import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; public class TitleTest { - @DisplayName("Title 타입에 제목을 저장한다.") - @Test - public void Title_is_OK() { - //given - String titleString = "게시판 제목입니다."; - - //when - Title title = new Title(titleString); - - //then - assertThat(title.getValue()).isEqualTo("게시판 제목입니다."); - } - - @DisplayName("Title 타입에 너무 긴 제목을 저장한다. 100자 이상") - @Test - public void Title_is_too_long() { - //given - String titleString = "지금이문장은10자임".repeat(10); - - //then - assertThatThrownBy(() -> new Title(titleString)) - .isInstanceOf(InvalidInputException.class) - .hasMessage("입력값이 없거나, 타입이 유효하지 않습니다."); - } - - @DisplayName("제목은 null 일 수 없습니다.") - @Test - public void Title_cannot_be_Null() { - assertThatThrownBy(() -> new Title(null)) - .isInstanceOf(InvalidInputException.class) - .hasMessage("입력값이 없거나, 타입이 유효하지 않습니다."); - } - - @DisplayName("제목은 빈 문자열일 수 없습니다.") - @Test - public void Title_cannot_be_Blank() { - assertThatThrownBy(() -> new Title("")) - .isInstanceOf(InvalidInputException.class) - .hasMessage("입력값이 없거나, 타입이 유효하지 않습니다."); - } + @DisplayName("Title 타입에 제목을 저장한다.") + @Test + public void Title_is_OK() { + // given + String titleString = "게시판 제목입니다."; + + // when + Title title = new Title(titleString); + + // then + assertThat(title.getValue()).isEqualTo("게시판 제목입니다."); + } + + @DisplayName("Title 타입에 너무 긴 제목을 저장한다. 100자 이상") + @Test + public void Title_is_too_long() { + // given + String titleString = "지금이문장은10자임".repeat(10); + + // then + assertThatThrownBy(() -> new Title(titleString)) + .isInstanceOf(InvalidInputException.class) + .hasMessage("입력값이 없거나, 타입이 유효하지 않습니다."); + } + + @DisplayName("제목은 null 일 수 없습니다.") + @Test + public void Title_cannot_be_Null() { + assertThatThrownBy(() -> new Title(null)) + .isInstanceOf(InvalidInputException.class) + .hasMessage("입력값이 없거나, 타입이 유효하지 않습니다."); + } + + @DisplayName("제목은 빈 문자열일 수 없습니다.") + @Test + public void Title_cannot_be_Blank() { + assertThatThrownBy(() -> new Title("")) + .isInstanceOf(InvalidInputException.class) + .hasMessage("입력값이 없거나, 타입이 유효하지 않습니다."); + } } diff --git a/resource-server/src/test/java/com/inhabas/api/domain/board/dto/SaveBoardDtoTest.java b/resource-server/src/test/java/com/inhabas/api/domain/board/dto/SaveBoardDtoTest.java index 9794dceb..51d93cda 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/board/dto/SaveBoardDtoTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/board/dto/SaveBoardDtoTest.java @@ -1,14 +1,17 @@ package com.inhabas.api.domain.board.dto; + import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; -import com.inhabas.api.domain.board.dto.SaveBoardDto; -import com.inhabas.api.domain.menu.domain.valueObject.MenuId; import java.util.Set; + import javax.validation.ConstraintViolation; import javax.validation.Validation; import javax.validation.Validator; import javax.validation.ValidatorFactory; + +import com.inhabas.api.domain.menu.domain.valueObject.MenuId; + import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.DisplayName; @@ -16,62 +19,61 @@ public class SaveBoardDtoTest { - private static ValidatorFactory validatorFactory; - private static Validator validator; - - @BeforeAll - public static void init() { - validatorFactory = Validation.buildDefaultValidatorFactory(); - validator = validatorFactory.getValidator(); - } - - @AfterAll - public static void close() { - validatorFactory.close(); - } - - @DisplayName("SaveBoardDto 객체를 정상적으로 생성한다.") - @Test - public void SaveBoardDto_is_OK(){ - //given - SaveBoardDto saveBoardDto = new SaveBoardDto("title", "content", new MenuId(1)); - - //when - Set> violations = validator.validate(saveBoardDto); - - // then - assertTrue(violations.isEmpty()); - } - - @DisplayName("SaveBoardDto의 content 필드가 null 이면 validation 실패") - @Test - public void Contents_is_null() { - // given - SaveBoardDto saveBoardDto = new SaveBoardDto("title", null, new MenuId(1)); - - // when - Set> violations = validator.validate(saveBoardDto); - - // then - assertEquals(1, violations.size()); - assertEquals("본문을 입력하세요.", violations.iterator().next().getMessage()); - } - - @DisplayName("게시글의 제목이 100자 이상을 넘긴 경우 validation 통과하지 못함.") - @Test - public void Title_is_too_long() { - //given - String title = "title".repeat(20) + "."; - String contents = "그냥 본문 내용입니다."; - - SaveBoardDto saveBoardDto = new SaveBoardDto(title, contents, new MenuId(1)); - - // when - Set> violations = validator.validate(saveBoardDto); - - // then - assertEquals(1, violations.size()); - assertEquals("제목은 최대 100자입니다.", violations.iterator().next().getMessage()); - } - + private static ValidatorFactory validatorFactory; + private static Validator validator; + + @BeforeAll + public static void init() { + validatorFactory = Validation.buildDefaultValidatorFactory(); + validator = validatorFactory.getValidator(); + } + + @AfterAll + public static void close() { + validatorFactory.close(); + } + + @DisplayName("SaveBoardDto 객체를 정상적으로 생성한다.") + @Test + public void SaveBoardDto_is_OK() { + // given + SaveBoardDto saveBoardDto = new SaveBoardDto("title", "content", new MenuId(1)); + + // when + Set> violations = validator.validate(saveBoardDto); + + // then + assertTrue(violations.isEmpty()); + } + + @DisplayName("SaveBoardDto의 content 필드가 null 이면 validation 실패") + @Test + public void Contents_is_null() { + // given + SaveBoardDto saveBoardDto = new SaveBoardDto("title", null, new MenuId(1)); + + // when + Set> violations = validator.validate(saveBoardDto); + + // then + assertEquals(1, violations.size()); + assertEquals("본문을 입력하세요.", violations.iterator().next().getMessage()); + } + + @DisplayName("게시글의 제목이 100자 이상을 넘긴 경우 validation 통과하지 못함.") + @Test + public void Title_is_too_long() { + // given + String title = "title".repeat(20) + "."; + String contents = "그냥 본문 내용입니다."; + + SaveBoardDto saveBoardDto = new SaveBoardDto(title, contents, new MenuId(1)); + + // when + Set> violations = validator.validate(saveBoardDto); + + // then + assertEquals(1, violations.size()); + assertEquals("제목은 최대 100자입니다.", violations.iterator().next().getMessage()); + } } diff --git a/resource-server/src/test/java/com/inhabas/api/domain/board/dto/UpdateBoardDtoTest.java b/resource-server/src/test/java/com/inhabas/api/domain/board/dto/UpdateBoardDtoTest.java index 42005f5e..e128a266 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/board/dto/UpdateBoardDtoTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/board/dto/UpdateBoardDtoTest.java @@ -3,10 +3,12 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import java.util.Set; + import javax.validation.ConstraintViolation; import javax.validation.Validation; import javax.validation.Validator; import javax.validation.ValidatorFactory; + import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.DisplayName; @@ -14,44 +16,44 @@ public class UpdateBoardDtoTest { - private static ValidatorFactory validatorFactory; - private static Validator validator; - - @BeforeAll - public static void init() { - validatorFactory = Validation.buildDefaultValidatorFactory(); - validator = validatorFactory.getValidator(); - } - - @AfterAll - public static void close() { - validatorFactory.close(); - } - - @DisplayName("UpdateBoardDto를 정상적으로 생성한다. ") - @Test - public void UpdateBoardDto_is_OK() { - //given - UpdateBoardDto updateBoardDto = new UpdateBoardDto(1L, "title", "content"); - - // when - Set> violations = validator.validate(updateBoardDto); - - // then - assertEquals(0, violations.size()); - } - - @DisplayName("본문에 공백이 입력되었을 경우 테스트를 통과하지 못함.") - @Test - public void Contents_is_empty() { - //given - UpdateBoardDto updateBoardDto = new UpdateBoardDto(2L, "title", " "); - - // when - Set> violations = validator.validate(updateBoardDto); - - // then - assertEquals(1, violations.size()); - assertEquals("본문을 입력하세요", violations.iterator().next().getMessage()); - } + private static ValidatorFactory validatorFactory; + private static Validator validator; + + @BeforeAll + public static void init() { + validatorFactory = Validation.buildDefaultValidatorFactory(); + validator = validatorFactory.getValidator(); + } + + @AfterAll + public static void close() { + validatorFactory.close(); + } + + @DisplayName("UpdateBoardDto를 정상적으로 생성한다. ") + @Test + public void UpdateBoardDto_is_OK() { + // given + UpdateBoardDto updateBoardDto = new UpdateBoardDto(1L, "title", "content"); + + // when + Set> violations = validator.validate(updateBoardDto); + + // then + assertEquals(0, violations.size()); + } + + @DisplayName("본문에 공백이 입력되었을 경우 테스트를 통과하지 못함.") + @Test + public void Contents_is_empty() { + // given + UpdateBoardDto updateBoardDto = new UpdateBoardDto(2L, "title", " "); + + // when + Set> violations = validator.validate(updateBoardDto); + + // then + assertEquals(1, violations.size()); + assertEquals("본문을 입력하세요", violations.iterator().next().getMessage()); + } } diff --git a/resource-server/src/test/java/com/inhabas/api/domain/board/repository/NormalBoardRepositoryTest.java b/resource-server/src/test/java/com/inhabas/api/domain/board/repository/NormalBoardRepositoryTest.java index f2d60f9e..f5b264cf 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/board/repository/NormalBoardRepositoryTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/board/repository/NormalBoardRepositoryTest.java @@ -1,206 +1,185 @@ package com.inhabas.api.domain.board.repository; -import static com.inhabas.api.domain.member.domain.entity.MemberTest.basicMember1; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertAll; -import static org.junit.jupiter.api.Assertions.assertTrue; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager; import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; import com.inhabas.api.domain.board.domain.NormalBoard; -import com.inhabas.api.domain.board.domain.NormalBoardTest; -import com.inhabas.api.domain.board.dto.BoardDto; import com.inhabas.api.domain.menu.domain.Menu; -import com.inhabas.api.domain.menu.domain.MenuGroup; -import com.inhabas.api.domain.menu.domain.valueObject.MenuId; -import com.inhabas.api.domain.menu.domain.valueObject.MenuType; import com.inhabas.testAnnotataion.DefaultDataJpaTest; -import java.util.ArrayList; -import java.util.List; -import javax.persistence.EntityNotFoundException; -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.boot.test.autoconfigure.orm.jpa.TestEntityManager; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Sort.Direction; @DefaultDataJpaTest public class NormalBoardRepositoryTest { - @Autowired - NormalBoardRepository boardRepository; - @Autowired - TestEntityManager em; - - NormalBoard FREE_BOARD; - NormalBoard NOTICE_BOARD; - NormalBoard NOTICE_BOARD_2; - Menu freeBoardMenu; - Member writer; - -// @BeforeEach -// public void setUp() { -// writer = em.persist(basicMember1()); -// MenuGroup boardMenuGroup = em.persist(new MenuGroup("게시판")); -// Menu noticeBoardMenu = em.persist( -// Menu.builder() -// .menuGroup(boardMenuGroup) -// .priority(1) -// .type(MenuType.LIST) -// .name("공지사항") -// .description("부원이 알아야 할 내용을 게시합니다.") -// .build()); -// freeBoardMenu = em.persist( -// Menu.builder() -// .menuGroup(boardMenuGroup) -// .priority(2) -// .type(MenuType.LIST) -// .name("자유게시판") -// .description("부원이 자유롭게 사용할 수 있는 게시판입니다.") -// .build()); -// -// FREE_BOARD = NormalBoardTest.getBoard1() -// .writtenBy(writer.getId()).inMenu(freeBoardMenu.getId()); -// NOTICE_BOARD = NormalBoardTest.getBoard2() -// .writtenBy(writer.getId()).inMenu(noticeBoardMenu.getId()); -// NOTICE_BOARD_2 = NormalBoardTest.getBoard3() -// .writtenBy(writer.getId()).inMenu(noticeBoardMenu.getId()); -// } - - -// @DisplayName("저장 후 반환값이 처음과 같다.") -// @Test -// public void save() { -// Member saveMember = em.find(Member.class, basicMember1().getId()); -// -// //when -// NormalBoard saveBoard = boardRepository.save(FREE_BOARD); -// -// //then -// assertAll( -// () -> assertThat(saveBoard.getId()).isNotNull(), -// () -> assertThat(saveBoard.getDateCreated()).isNotNull(), -// () -> assertThat(saveBoard.getTitle()).isEqualTo(FREE_BOARD.getTitle()), -// () -> assertThat(saveBoard.getContent()).isEqualTo(FREE_BOARD.getContent()), -// () -> assertThat(saveBoard.getWriterId()).isEqualTo(saveMember.getId()) -// ); -// } - -// @DisplayName("id에 해당하는 게시글을 dto 로 반환한다.") -// @Test -// public void findDtoById() { -// //given -// boardRepository.save(FREE_BOARD); -// boardRepository.save(NOTICE_BOARD); -// -// //when -// BoardDto find = boardRepository.findDtoById(NOTICE_BOARD.getId()) -// .orElseThrow(EntityNotFoundException::new); -// -// //then -// assertAll( -// () -> assertThat(find.getId()).isEqualTo(NOTICE_BOARD.getId()), -// () -> assertThat(find.getTitle()).isEqualTo(NOTICE_BOARD.getTitle()), -// () -> assertThat(find.getContent()).isEqualTo(NOTICE_BOARD.getContent()), -// () -> assertThat(find.getMenuId()).isEqualTo(NOTICE_BOARD.getMenuId()), -// () -> assertThat(find.getWriterName()).isEqualTo(writer.getName()) -// ); -// } - -// @DisplayName("게시글을 수정한다.") -// @Test -// public void update() { -// //given -// Member saveMember = em.find(Member.class, basicMember1().getId()); -// boardRepository.save(FREE_BOARD); -// -// //when -// FREE_BOARD.modify("제목이 수정되었습니다.", "내용이 수정되었습니다.", saveMember.getId()); -// NormalBoard findBoard = boardRepository.findById(FREE_BOARD.getId()) -// .orElseThrow(EntityNotFoundException::new); -// -// //then -// assertThat(findBoard.getContent()).isEqualTo("내용이 수정되었습니다."); -// assertThat(findBoard.getTitle()).isEqualTo("제목이 수정되었습니다."); -// } - -// @DisplayName("id 로 게시글을 삭제한다.") -// @Test -// public void deleteById() { -// //given -// boardRepository.save(FREE_BOARD); -// -// //when -// boardRepository.deleteById(FREE_BOARD.getId()); -// -// //then -// assertTrue(boardRepository.findById(FREE_BOARD.getId()).isEmpty()); -// } -// -// @DisplayName("모든 게시글을 조회한다.") -// @Test -// public void findAll() { -// //given -// boardRepository.save(FREE_BOARD); -// boardRepository.save(NOTICE_BOARD); - - -// //then -// assertThat(boards).contains(FREE_BOARD, NOTICE_BOARD); -// assertThat(boards.size()).isEqualTo(2); -// } - -// @DisplayName("메뉴 id 에 해당하는 게시글들을 갖고 온다.") -// @Test -// public void findAllByMenuId() { -// //given -// boardRepository.save(FREE_BOARD); -// boardRepository.save(NOTICE_BOARD); -// boardRepository.save(NOTICE_BOARD_2); -// MenuId freeBoardMenuId = FREE_BOARD.getMenuId(); -// MenuId noticeBoardMenuId = NOTICE_BOARD.getMenuId(); -// -// //when -// Page freeBoards = boardRepository.findAllByMenuId(freeBoardMenuId, Pageable.ofSize(5)); -// Page noticeBoards = boardRepository.findAllByMenuId(noticeBoardMenuId, Pageable.ofSize(5)); -// -// //then -// assertThat(freeBoards.getTotalElements()).isEqualTo(1); -// freeBoards.forEach( -// board->assertThat(board.getMenuId()).isEqualTo(freeBoardMenuId)); -// -// assertThat(noticeBoards.getTotalElements()).isEqualTo(2); -// noticeBoards.forEach( -// board->assertThat(board.getMenuId()).isEqualTo(noticeBoardMenuId)); -// } - -// @DisplayName("게시글 목록 페이지를 잘 불러온다.") -// @Test -// public void getBoardListPageTest() { -// //given -// ArrayList boards = new ArrayList<>(); -// for (int i = 0; i < 30; i++) { -// boards.add(new NormalBoard("이건 제목" + i, "이건 내용입니다.") -// .writtenBy(writer.getId()) -// .inMenu(freeBoardMenu.getId())); -// } -// boardRepository.saveAll(boards); -// -// //when -// Page page = -// boardRepository.findAllByMenuId( -// freeBoardMenu.getId(), -// PageRequest.of(2, 11, Direction.DESC, "created") -// ); -// -// //then -// assertThat(page.getTotalElements()).isEqualTo(30); -// assertThat(page.getTotalPages()).isEqualTo(3); -// assertThat(page.getNumber()).isEqualTo(2); -// assertThat(page.getNumberOfElements()).isEqualTo(8); -// } + @Autowired NormalBoardRepository boardRepository; + @Autowired TestEntityManager em; + + NormalBoard FREE_BOARD; + NormalBoard NOTICE_BOARD; + NormalBoard NOTICE_BOARD_2; + Menu freeBoardMenu; + Member writer; + + // @BeforeEach + // public void setUp() { + // writer = em.persist(basicMember1()); + // MenuGroup boardMenuGroup = em.persist(new MenuGroup("게시판")); + // Menu noticeBoardMenu = em.persist( + // Menu.builder() + // .menuGroup(boardMenuGroup) + // .priority(1) + // .type(MenuType.LIST) + // .name("공지사항") + // .description("부원이 알아야 할 내용을 게시합니다.") + // .build()); + // freeBoardMenu = em.persist( + // Menu.builder() + // .menuGroup(boardMenuGroup) + // .priority(2) + // .type(MenuType.LIST) + // .name("자유게시판") + // .description("부원이 자유롭게 사용할 수 있는 게시판입니다.") + // .build()); + // + // FREE_BOARD = NormalBoardTest.getBoard1() + // .writtenBy(writer.getId()).inMenu(freeBoardMenu.getId()); + // NOTICE_BOARD = NormalBoardTest.getBoard2() + // .writtenBy(writer.getId()).inMenu(noticeBoardMenu.getId()); + // NOTICE_BOARD_2 = NormalBoardTest.getBoard3() + // .writtenBy(writer.getId()).inMenu(noticeBoardMenu.getId()); + // } + + // @DisplayName("저장 후 반환값이 처음과 같다.") + // @Test + // public void save() { + // Member saveMember = em.find(Member.class, basicMember1().getId()); + // + // //when + // NormalBoard saveBoard = boardRepository.save(FREE_BOARD); + // + // //then + // assertAll( + // () -> assertThat(saveBoard.getId()).isNotNull(), + // () -> assertThat(saveBoard.getDateCreated()).isNotNull(), + // () -> assertThat(saveBoard.getTitle()).isEqualTo(FREE_BOARD.getTitle()), + // () -> assertThat(saveBoard.getContent()).isEqualTo(FREE_BOARD.getContent()), + // () -> assertThat(saveBoard.getWriterId()).isEqualTo(saveMember.getId()) + // ); + // } + + // @DisplayName("id에 해당하는 게시글을 dto 로 반환한다.") + // @Test + // public void findDtoById() { + // //given + // boardRepository.save(FREE_BOARD); + // boardRepository.save(NOTICE_BOARD); + // + // //when + // BoardDto find = boardRepository.findDtoById(NOTICE_BOARD.getId()) + // .orElseThrow(EntityNotFoundException::new); + // + // //then + // assertAll( + // () -> assertThat(find.getId()).isEqualTo(NOTICE_BOARD.getId()), + // () -> assertThat(find.getTitle()).isEqualTo(NOTICE_BOARD.getTitle()), + // () -> assertThat(find.getContent()).isEqualTo(NOTICE_BOARD.getContent()), + // () -> assertThat(find.getMenuId()).isEqualTo(NOTICE_BOARD.getMenuId()), + // () -> assertThat(find.getWriterName()).isEqualTo(writer.getName()) + // ); + // } + + // @DisplayName("게시글을 수정한다.") + // @Test + // public void update() { + // //given + // Member saveMember = em.find(Member.class, basicMember1().getId()); + // boardRepository.save(FREE_BOARD); + // + // //when + // FREE_BOARD.modify("제목이 수정되었습니다.", "내용이 수정되었습니다.", saveMember.getId()); + // NormalBoard findBoard = boardRepository.findById(FREE_BOARD.getId()) + // .orElseThrow(EntityNotFoundException::new); + // + // //then + // assertThat(findBoard.getContent()).isEqualTo("내용이 수정되었습니다."); + // assertThat(findBoard.getTitle()).isEqualTo("제목이 수정되었습니다."); + // } + + // @DisplayName("id 로 게시글을 삭제한다.") + // @Test + // public void deleteById() { + // //given + // boardRepository.save(FREE_BOARD); + // + // //when + // boardRepository.deleteById(FREE_BOARD.getId()); + // + // //then + // assertTrue(boardRepository.findById(FREE_BOARD.getId()).isEmpty()); + // } + // + // @DisplayName("모든 게시글을 조회한다.") + // @Test + // public void findAll() { + // //given + // boardRepository.save(FREE_BOARD); + // boardRepository.save(NOTICE_BOARD); + + // //then + // assertThat(boards).contains(FREE_BOARD, NOTICE_BOARD); + // assertThat(boards.size()).isEqualTo(2); + // } + + // @DisplayName("메뉴 id 에 해당하는 게시글들을 갖고 온다.") + // @Test + // public void findAllByMenuId() { + // //given + // boardRepository.save(FREE_BOARD); + // boardRepository.save(NOTICE_BOARD); + // boardRepository.save(NOTICE_BOARD_2); + // MenuId freeBoardMenuId = FREE_BOARD.getMenuId(); + // MenuId noticeBoardMenuId = NOTICE_BOARD.getMenuId(); + // + // //when + // Page freeBoards = boardRepository.findAllByMenuId(freeBoardMenuId, + // Pageable.ofSize(5)); + // Page noticeBoards = boardRepository.findAllByMenuId(noticeBoardMenuId, + // Pageable.ofSize(5)); + // + // //then + // assertThat(freeBoards.getTotalElements()).isEqualTo(1); + // freeBoards.forEach( + // board->assertThat(board.getMenuId()).isEqualTo(freeBoardMenuId)); + // + // assertThat(noticeBoards.getTotalElements()).isEqualTo(2); + // noticeBoards.forEach( + // board->assertThat(board.getMenuId()).isEqualTo(noticeBoardMenuId)); + // } + + // @DisplayName("게시글 목록 페이지를 잘 불러온다.") + // @Test + // public void getBoardListPageTest() { + // //given + // ArrayList boards = new ArrayList<>(); + // for (int i = 0; i < 30; i++) { + // boards.add(new NormalBoard("이건 제목" + i, "이건 내용입니다.") + // .writtenBy(writer.getId()) + // .inMenu(freeBoardMenu.getId())); + // } + // boardRepository.saveAll(boards); + // + // //when + // Page page = + // boardRepository.findAllByMenuId( + // freeBoardMenu.getId(), + // PageRequest.of(2, 11, Direction.DESC, "created") + // ); + // + // //then + // assertThat(page.getTotalElements()).isEqualTo(30); + // assertThat(page.getTotalPages()).isEqualTo(3); + // assertThat(page.getNumber()).isEqualTo(2); + // assertThat(page.getNumberOfElements()).isEqualTo(8); + // } } diff --git a/resource-server/src/test/java/com/inhabas/api/domain/board/usecase/BoardServiceTest.java b/resource-server/src/test/java/com/inhabas/api/domain/board/usecase/BoardServiceTest.java index daf390a1..958072bb 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/board/usecase/BoardServiceTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/board/usecase/BoardServiceTest.java @@ -1,175 +1,154 @@ package com.inhabas.api.domain.board.usecase; -import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.StudentId; -import com.inhabas.api.domain.board.domain.NormalBoard; -import com.inhabas.api.domain.board.dto.BoardDto; -import com.inhabas.api.domain.board.dto.SaveBoardDto; -import com.inhabas.api.domain.board.dto.UpdateBoardDto; +import static org.mockito.BDDMockito.*; + +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; + import com.inhabas.api.domain.board.repository.NormalBoardRepository; -import com.inhabas.api.domain.menu.domain.valueObject.MenuId; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageImpl; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Sort; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.setup.MockMvcBuilders; - -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.*; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.extension.ExtendWith; @ExtendWith(MockitoExtension.class) public class BoardServiceTest { - @InjectMocks - BoardServiceImpl boardService; + @InjectMocks BoardServiceImpl boardService; - @Mock - NormalBoardRepository boardRepository; + @Mock NormalBoardRepository boardRepository; - private MockMvc mockMvc; + private MockMvc mockMvc; - @BeforeEach - void setUp() { - mockMvc = MockMvcBuilders.standaloneSetup(boardService).build(); - } + @BeforeEach + void setUp() { + mockMvc = MockMvcBuilders.standaloneSetup(boardService).build(); + } -// @DisplayName("게시판을 성공적으로 생성한다.") -// @Test -// public void createBoard() { -// //given -// SaveBoardDto saveBoardDto = new SaveBoardDto("title", "content", new MenuId(1)); -// NormalBoard normalBoard = new NormalBoard("title", "content"); -// given(boardRepository.save(any())).willReturn(normalBoard); -// -// // when -// Integer returnedId = boardService.write(new StudentId("12201863"), saveBoardDto); -// -// // then -// then(boardRepository).should(times(1)).save(any()); -// } -// -// @DisplayName("게시판의 목록을 조회한다.") -// @Test -// public void getBoardList() { -// //given -// PageRequest pageable = PageRequest.of(0, 10, Sort.Direction.ASC, "created"); -// -// BoardDto boardDto1 = -// new BoardDto(1, "title", "content", "mingyeom", -// new MenuId(1), LocalDateTime.now(), LocalDateTime.now()); -// BoardDto boardDto2 = -// new BoardDto(2, "title", "content", "minji", -// new MenuId(1), LocalDateTime.now(), LocalDateTime.now()); -// -// List results = new ArrayList<>(); -// results.add(boardDto1); -// results.add(boardDto2); -// Page expectedBoardDto = new PageImpl<>(results, pageable, results.size()); -// -// given(boardRepository.findAllByMenuId(any(), any())).willReturn(expectedBoardDto); -// -// //when -// Page returnedBoardList = boardService.getBoardList(new MenuId(1), pageable); -// -// //then -// then(boardRepository).should(times(1)).findAllByMenuId(any(), any()); -// assertThat(returnedBoardList).isEqualTo(expectedBoardDto); -// } -// -// @DisplayName("게시글 단일 조회에 성공한다.") -// @Test -// public void getDetailBoard() { -// //given -// BoardDto boardDto = -// new BoardDto(1, "title", "content", "김민겸", -// new MenuId(1), LocalDateTime.now(), null); -// given(boardRepository.findDtoById(any())).willReturn(Optional.of(boardDto)); -// -// // when -// boardService.getBoard(1); -// -// // then -// then(boardRepository).should(times(1)).findDtoById(any()); -// } -// -// @DisplayName("게시글을 성공적으로 삭제한다.") -// @Test -// public void deleteBoard() { -// //given -// StudentId writer = new StudentId("12201863"); -// NormalBoard board = new NormalBoard("Title", "Content").writtenBy(writer); -// given(boardRepository.findById(anyInt())).willReturn(Optional.of(board)); -// doNothing().when(boardRepository).deleteById(any()); -// -// // when -// boardService.delete(writer, 1); -// -// // then -// then(boardRepository).should(times(1)).deleteById(any()); -// } -// -// @DisplayName("게시글을 수정한다.") -// @Test -// public void updateBoard() { -// //given -// StudentId memberId = new StudentId("12201863"); -// NormalBoard savedNormalBoard = new NormalBoard("Origin Title", -// "Origin Content").writtenBy(memberId); -// NormalBoard updatedNormalBoard = new NormalBoard("Title", "Content").writtenBy( -// memberId); -// -// given(boardRepository.findById(anyInt())).willReturn(Optional.of(savedNormalBoard)); -// given(boardRepository.save(any())).willReturn(updatedNormalBoard); -// -// UpdateBoardDto updateBoardDto = new UpdateBoardDto(1, "수정된 제목", "수정된 내용"); -// -// // when -// Integer returnedId = boardService.update(memberId, updateBoardDto); -// -// // then -// then(boardRepository).should(times(1)).save(any()); -// } -// -// @DisplayName("작성자가 아니면 게시글 수정에 실패한다.") -// @Test -// public void failToUpdateBoard() { -// //given -// StudentId badUser = new StudentId("44444444"); -// StudentId originWriter = new StudentId("12201863"); -// NormalBoard board = new NormalBoard("Title", "Content").writtenBy(originWriter); -// given(boardRepository.findById(anyInt())).willReturn(Optional.of(board)); -// -// // when -// Assertions.assertThrows(BoardCannotModifiableException.class, -// () -> boardService.update(badUser, new UpdateBoardDto(1, "수정된 제목", "수정된 내용"))); -// } -// -// @DisplayName("작성자가 아니면 게시글 삭제에 실패한다.") -// @Test -// public void failToDeleteBoard() { -// //given -// StudentId badUser = new StudentId("44444444"); -// StudentId originWriter = new StudentId("12201863"); -// NormalBoard board = new NormalBoard("Title", "Content").writtenBy(originWriter); -// given(boardRepository.findById(anyInt())).willReturn(Optional.of(board)); -// -// // when -// Assertions.assertThrows(BoardCannotModifiableException.class, -// () -> boardService.delete(badUser, 1)); -// } + // @DisplayName("게시판을 성공적으로 생성한다.") + // @Test + // public void createBoard() { + // //given + // SaveBoardDto saveBoardDto = new SaveBoardDto("title", "content", new MenuId(1)); + // NormalBoard normalBoard = new NormalBoard("title", "content"); + // given(boardRepository.save(any())).willReturn(normalBoard); + // + // // when + // Integer returnedId = boardService.write(new StudentId("12201863"), saveBoardDto); + // + // // then + // then(boardRepository).should(times(1)).save(any()); + // } + // + // @DisplayName("게시판의 목록을 조회한다.") + // @Test + // public void getBoardList() { + // //given + // PageRequest pageable = PageRequest.of(0, 10, Sort.Direction.ASC, "created"); + // + // BoardDto boardDto1 = + // new BoardDto(1, "title", "content", "mingyeom", + // new MenuId(1), LocalDateTime.now(), LocalDateTime.now()); + // BoardDto boardDto2 = + // new BoardDto(2, "title", "content", "minji", + // new MenuId(1), LocalDateTime.now(), LocalDateTime.now()); + // + // List results = new ArrayList<>(); + // results.add(boardDto1); + // results.add(boardDto2); + // Page expectedBoardDto = new PageImpl<>(results, pageable, results.size()); + // + // given(boardRepository.findAllByMenuId(any(), any())).willReturn(expectedBoardDto); + // + // //when + // Page returnedBoardList = boardService.getBoardList(new MenuId(1), pageable); + // + // //then + // then(boardRepository).should(times(1)).findAllByMenuId(any(), any()); + // assertThat(returnedBoardList).isEqualTo(expectedBoardDto); + // } + // + // @DisplayName("게시글 단일 조회에 성공한다.") + // @Test + // public void getDetailBoard() { + // //given + // BoardDto boardDto = + // new BoardDto(1, "title", "content", "김민겸", + // new MenuId(1), LocalDateTime.now(), null); + // given(boardRepository.findDtoById(any())).willReturn(Optional.of(boardDto)); + // + // // when + // boardService.getBoard(1); + // + // // then + // then(boardRepository).should(times(1)).findDtoById(any()); + // } + // + // @DisplayName("게시글을 성공적으로 삭제한다.") + // @Test + // public void deleteBoard() { + // //given + // StudentId writer = new StudentId("12201863"); + // NormalBoard board = new NormalBoard("Title", "Content").writtenBy(writer); + // given(boardRepository.findById(anyInt())).willReturn(Optional.of(board)); + // doNothing().when(boardRepository).deleteById(any()); + // + // // when + // boardService.delete(writer, 1); + // + // // then + // then(boardRepository).should(times(1)).deleteById(any()); + // } + // + // @DisplayName("게시글을 수정한다.") + // @Test + // public void updateBoard() { + // //given + // StudentId memberId = new StudentId("12201863"); + // NormalBoard savedNormalBoard = new NormalBoard("Origin Title", + // "Origin Content").writtenBy(memberId); + // NormalBoard updatedNormalBoard = new NormalBoard("Title", "Content").writtenBy( + // memberId); + // + // given(boardRepository.findById(anyInt())).willReturn(Optional.of(savedNormalBoard)); + // given(boardRepository.save(any())).willReturn(updatedNormalBoard); + // + // UpdateBoardDto updateBoardDto = new UpdateBoardDto(1, "수정된 제목", "수정된 내용"); + // + // // when + // Integer returnedId = boardService.update(memberId, updateBoardDto); + // + // // then + // then(boardRepository).should(times(1)).save(any()); + // } + // + // @DisplayName("작성자가 아니면 게시글 수정에 실패한다.") + // @Test + // public void failToUpdateBoard() { + // //given + // StudentId badUser = new StudentId("44444444"); + // StudentId originWriter = new StudentId("12201863"); + // NormalBoard board = new NormalBoard("Title", "Content").writtenBy(originWriter); + // given(boardRepository.findById(anyInt())).willReturn(Optional.of(board)); + // + // // when + // Assertions.assertThrows(BoardCannotModifiableException.class, + // () -> boardService.update(badUser, new UpdateBoardDto(1, "수정된 제목", "수정된 내용"))); + // } + // + // @DisplayName("작성자가 아니면 게시글 삭제에 실패한다.") + // @Test + // public void failToDeleteBoard() { + // //given + // StudentId badUser = new StudentId("44444444"); + // StudentId originWriter = new StudentId("12201863"); + // NormalBoard board = new NormalBoard("Title", "Content").writtenBy(originWriter); + // given(boardRepository.findById(anyInt())).willReturn(Optional.of(board)); + // + // // when + // Assertions.assertThrows(BoardCannotModifiableException.class, + // () -> boardService.delete(badUser, 1)); + // } } diff --git a/resource-server/src/test/java/com/inhabas/api/domain/budget/converter/StatusAttributeConverterTest.java b/resource-server/src/test/java/com/inhabas/api/domain/budget/converter/StatusAttributeConverterTest.java index 6834a1db..839c1cce 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/budget/converter/StatusAttributeConverterTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/budget/converter/StatusAttributeConverterTest.java @@ -1,117 +1,117 @@ package com.inhabas.api.domain.budget.converter; +import static com.inhabas.api.domain.budget.domain.valueObject.ApplicationStatus.*; + +import javax.persistence.EntityManager; + +import org.springframework.beans.factory.annotation.Autowired; + import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; -import com.inhabas.api.domain.budget.domain.BudgetSupportApplication; -import com.inhabas.api.domain.budget.domain.valueObject.ApplicationStatus; import com.inhabas.api.domain.budget.repository.BudgetApplicationRepository; import com.inhabas.api.domain.member.domain.entity.MemberTest; import com.inhabas.testAnnotataion.DefaultDataJpaTest; -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.test.util.ReflectionTestUtils; - -import javax.persistence.EntityManager; -import javax.persistence.Query; -import java.time.LocalDateTime; -import static com.inhabas.api.domain.budget.domain.valueObject.ApplicationStatus.*; -import static org.assertj.core.api.Assertions.assertThat; +import org.junit.jupiter.api.BeforeEach; @DefaultDataJpaTest public class StatusAttributeConverterTest { - @Autowired - private BudgetApplicationRepository repository; + @Autowired private BudgetApplicationRepository repository; - @Autowired - private EntityManager em; + @Autowired private EntityManager em; - private Member member; + private Member member; - @BeforeEach - public void setUp() { - member = MemberTest.basicMember1(); - em.persist(member); - } + @BeforeEach + public void setUp() { + member = MemberTest.basicMember1(); + em.persist(member); + } -// @DisplayName("Waiting 상태가 db에 1로 저장된다.") -// @Test -// public void convertWaitingStatusTo1Test() { -// //given -// BudgetSupportApplication application = -// new BudgetSupportApplication("스터디 지원금 신청", -// LocalDateTime.of(2020, 1, 1, 1, 1, 1), -// "머신러닝 논문 스터디 온라인 강의비 청구", 10000, "국민 123 홍길동", member.getId()); -// repository.save(application); -// -// Query query = em.createNativeQuery("select * from budget_support_application where status = :status", BudgetSupportApplication.class); -// query.setParameter("status", 1); -// BudgetSupportApplication result = (BudgetSupportApplication) query.getSingleResult(); -// -// -// ApplicationStatus status = (ApplicationStatus) ReflectionTestUtils.getField(result, "status"); -// assertThat(status).isEqualTo(ApplicationStatus.WAITING); -// } + // @DisplayName("Waiting 상태가 db에 1로 저장된다.") + // @Test + // public void convertWaitingStatusTo1Test() { + // //given + // BudgetSupportApplication application = + // new BudgetSupportApplication("스터디 지원금 신청", + // LocalDateTime.of(2020, 1, 1, 1, 1, 1), + // "머신러닝 논문 스터디 온라인 강의비 청구", 10000, "국민 123 홍길동", member.getId()); + // repository.save(application); + // + // Query query = em.createNativeQuery("select * from budget_support_application where + // status = :status", BudgetSupportApplication.class); + // query.setParameter("status", 1); + // BudgetSupportApplication result = (BudgetSupportApplication) query.getSingleResult(); + // + // + // ApplicationStatus status = (ApplicationStatus) ReflectionTestUtils.getField(result, + // "status"); + // assertThat(status).isEqualTo(ApplicationStatus.WAITING); + // } -// @DisplayName("APPROVED 상태가 db에 3로 저장된다.") -// @Test -// public void convertApprovedStatusTo2Test() { -// //given -// BudgetSupportApplication application = -// new BudgetSupportApplication("스터디 지원금 신청", -// LocalDateTime.of(2020, 1, 1, 1, 1, 1), -// "머신러닝 논문 스터디 온라인 강의비 청구", 10000, "국민 123 홍길동", member.getId()); -// ReflectionTestUtils.setField(application, "status", APPROVED); -// repository.save(application); -// -// Query query = em.createNativeQuery("select * from budget_support_application where status = :status", BudgetSupportApplication.class); -// query.setParameter("status", 3); -// BudgetSupportApplication result = (BudgetSupportApplication) query.getSingleResult(); -// -// -// ApplicationStatus status = (ApplicationStatus) ReflectionTestUtils.getField(result, "status"); -// assertThat(status).isEqualTo(ApplicationStatus.APPROVED); -// } + // @DisplayName("APPROVED 상태가 db에 3로 저장된다.") + // @Test + // public void convertApprovedStatusTo2Test() { + // //given + // BudgetSupportApplication application = + // new BudgetSupportApplication("스터디 지원금 신청", + // LocalDateTime.of(2020, 1, 1, 1, 1, 1), + // "머신러닝 논문 스터디 온라인 강의비 청구", 10000, "국민 123 홍길동", member.getId()); + // ReflectionTestUtils.setField(application, "status", APPROVED); + // repository.save(application); + // + // Query query = em.createNativeQuery("select * from budget_support_application where + // status = :status", BudgetSupportApplication.class); + // query.setParameter("status", 3); + // BudgetSupportApplication result = (BudgetSupportApplication) query.getSingleResult(); + // + // + // ApplicationStatus status = (ApplicationStatus) ReflectionTestUtils.getField(result, + // "status"); + // assertThat(status).isEqualTo(ApplicationStatus.APPROVED); + // } -// @DisplayName("DENIED 상태가 db에 2로 저장된다.") -// @Test -// public void convertDeniedStatusTo3Test() { -// //given -// BudgetSupportApplication application = -// new BudgetSupportApplication("스터디 지원금 신청", -// LocalDateTime.of(2020, 1, 1, 1, 1, 1), -// "머신러닝 논문 스터디 온라인 강의비 청구", 10000, "국민 123 홍길동", member.getId()); -// ReflectionTestUtils.setField(application, "status", DENIED); -// repository.save(application); -// -// Query query = em.createNativeQuery("select * from budget_support_application where status = :status", BudgetSupportApplication.class); -// query.setParameter("status", 2); -// BudgetSupportApplication result = (BudgetSupportApplication) query.getSingleResult(); -// -// -// ApplicationStatus status = (ApplicationStatus) ReflectionTestUtils.getField(result, "status"); -// assertThat(status).isEqualTo(ApplicationStatus.DENIED); -// } + // @DisplayName("DENIED 상태가 db에 2로 저장된다.") + // @Test + // public void convertDeniedStatusTo3Test() { + // //given + // BudgetSupportApplication application = + // new BudgetSupportApplication("스터디 지원금 신청", + // LocalDateTime.of(2020, 1, 1, 1, 1, 1), + // "머신러닝 논문 스터디 온라인 강의비 청구", 10000, "국민 123 홍길동", member.getId()); + // ReflectionTestUtils.setField(application, "status", DENIED); + // repository.save(application); + // + // Query query = em.createNativeQuery("select * from budget_support_application where + // status = :status", BudgetSupportApplication.class); + // query.setParameter("status", 2); + // BudgetSupportApplication result = (BudgetSupportApplication) query.getSingleResult(); + // + // + // ApplicationStatus status = (ApplicationStatus) ReflectionTestUtils.getField(result, + // "status"); + // assertThat(status).isEqualTo(ApplicationStatus.DENIED); + // } -// @DisplayName("PROCESSED 상태가 db에 4로 저장된다.") -// @Test -// public void convertProcessedStatusTo3Test() { -// //given -// BudgetSupportApplication application = -// new BudgetSupportApplication("스터디 지원금 신청", -// LocalDateTime.of(2020, 1, 1, 1, 1, 1), -// "머신러닝 논문 스터디 온라인 강의비 청구", 10000, "국민 123 홍길동", member.getId()); -// ReflectionTestUtils.setField(application, "status", PROCESSED); -// repository.save(application); -// -// Query query = em.createNativeQuery("select * from budget_support_application where status = :status", BudgetSupportApplication.class); -// query.setParameter("status", 4); -// BudgetSupportApplication result = (BudgetSupportApplication) query.getSingleResult(); -// -// -// ApplicationStatus status = (ApplicationStatus) ReflectionTestUtils.getField(result, "status"); -// assertThat(status).isEqualTo(ApplicationStatus.PROCESSED); -// } + // @DisplayName("PROCESSED 상태가 db에 4로 저장된다.") + // @Test + // public void convertProcessedStatusTo3Test() { + // //given + // BudgetSupportApplication application = + // new BudgetSupportApplication("스터디 지원금 신청", + // LocalDateTime.of(2020, 1, 1, 1, 1, 1), + // "머신러닝 논문 스터디 온라인 강의비 청구", 10000, "국민 123 홍길동", member.getId()); + // ReflectionTestUtils.setField(application, "status", PROCESSED); + // repository.save(application); + // + // Query query = em.createNativeQuery("select * from budget_support_application where + // status = :status", BudgetSupportApplication.class); + // query.setParameter("status", 4); + // BudgetSupportApplication result = (BudgetSupportApplication) query.getSingleResult(); + // + // + // ApplicationStatus status = (ApplicationStatus) ReflectionTestUtils.getField(result, + // "status"); + // assertThat(status).isEqualTo(ApplicationStatus.PROCESSED); + // } } diff --git a/resource-server/src/test/java/com/inhabas/api/domain/budget/repository/BudgetApplicationRepositoryTest.java b/resource-server/src/test/java/com/inhabas/api/domain/budget/repository/BudgetApplicationRepositoryTest.java index fba1c1b5..fad7a665 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/budget/repository/BudgetApplicationRepositoryTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/budget/repository/BudgetApplicationRepositoryTest.java @@ -1,118 +1,106 @@ package com.inhabas.api.domain.budget.repository; -import static org.assertj.core.api.Assertions.assertThat; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager; import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; -import com.inhabas.api.domain.budget.domain.BudgetSupportApplication; -import com.inhabas.api.domain.budget.domain.valueObject.ApplicationStatus; -import com.inhabas.api.domain.budget.dto.BudgetApplicationDetailDto; -import com.inhabas.api.domain.budget.dto.BudgetApplicationListDto; import com.inhabas.api.domain.member.domain.entity.MemberTest; import com.inhabas.testAnnotataion.DefaultDataJpaTest; -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; + 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.boot.test.autoconfigure.orm.jpa.TestEntityManager; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Sort; -import org.springframework.test.util.ReflectionTestUtils; @DefaultDataJpaTest public class BudgetApplicationRepositoryTest { - @Autowired - private BudgetApplicationRepository repository; + @Autowired private BudgetApplicationRepository repository; - @Autowired - private TestEntityManager em; + @Autowired private TestEntityManager em; - private Member member; + private Member member; - @BeforeEach - public void setUp() { - member = em.persist(MemberTest.basicMember1()); - } + @BeforeEach + public void setUp() { + member = em.persist(MemberTest.basicMember1()); + } -// @Test -// public void findDtoByIdTest() { -// //given -// BudgetSupportApplication application = -// new BudgetSupportApplication("스터디 지원금 신청", -// LocalDateTime.of(2020, 1, 1, 1, 1, 1), -// "머신러닝 논문 스터디 온라인 강의비 청구", 10000, "국민 123 홍길동", member.getId()); -// repository.save(application); -// Integer id = (Integer) ReflectionTestUtils.getField(application, "id"); -// -// //when -// BudgetApplicationDetailDto detailDto = repository.findDtoById(id) -// .orElseThrow(); -// -// //then -// assertThat(getField(detailDto, "id")).isEqualTo(id); -// assertThat(getField(detailDto, "outcome")).isEqualTo(10000); -// assertThat(getField(detailDto, "applicationWriterName")).isEqualTo("유동현"); -// assertThat(getField(detailDto, "memberIdInCharge")).isNull(); -// } + // @Test + // public void findDtoByIdTest() { + // //given + // BudgetSupportApplication application = + // new BudgetSupportApplication("스터디 지원금 신청", + // LocalDateTime.of(2020, 1, 1, 1, 1, 1), + // "머신러닝 논문 스터디 온라인 강의비 청구", 10000, "국민 123 홍길동", member.getId()); + // repository.save(application); + // Integer id = (Integer) ReflectionTestUtils.getField(application, "id"); + // + // //when + // BudgetApplicationDetailDto detailDto = repository.findDtoById(id) + // .orElseThrow(); + // + // //then + // assertThat(getField(detailDto, "id")).isEqualTo(id); + // assertThat(getField(detailDto, "outcome")).isEqualTo(10000); + // assertThat(getField(detailDto, "applicationWriterName")).isEqualTo("유동현"); + // assertThat(getField(detailDto, "memberIdInCharge")).isNull(); + // } -// @DisplayName("처리 완료된 것을 제외한 모든 예산지원신청서를 검색한다.") -// @Test -// public void searchAllTest() { -// //given -// List applicationList = new ArrayList<>(); -// for (int i = 0; i < 20; i++) { -// BudgetSupportApplication application = -// new BudgetSupportApplication("스터디 지원금 신청", -// LocalDateTime.of(2020, 1, 1, 1, 1, 1), -// "머신러닝 논문 스터디 온라인 강의비 청구", 10000, "국민 123 홍길동", member.getId()); -// ReflectionTestUtils.setField(application, "status", ApplicationStatus.values()[i % 4]); -// applicationList.add(application); -// } -// repository.saveAll(applicationList); -// -// //when -// Page page = -// repository.search(null, PageRequest.of(1, 10, Sort.Direction.DESC, "dateUsed")); -// -// //then -// assertThat(page.getTotalElements()).isEqualTo(15); -// assertThat(page.getNumberOfElements()).isEqualTo(5); -// assertThat(page.getTotalPages()).isEqualTo(2); -// } -// -// private Object getField(Object target, String fieldName) { -// return ReflectionTestUtils.getField(target, fieldName); -// } + // @DisplayName("처리 완료된 것을 제외한 모든 예산지원신청서를 검색한다.") + // @Test + // public void searchAllTest() { + // //given + // List applicationList = new ArrayList<>(); + // for (int i = 0; i < 20; i++) { + // BudgetSupportApplication application = + // new BudgetSupportApplication("스터디 지원금 신청", + // LocalDateTime.of(2020, 1, 1, 1, 1, 1), + // "머신러닝 논문 스터디 온라인 강의비 청구", 10000, "국민 123 홍길동", member.getId()); + // ReflectionTestUtils.setField(application, "status", ApplicationStatus.values()[i % + // 4]); + // applicationList.add(application); + // } + // repository.saveAll(applicationList); + // + // //when + // Page page = + // repository.search(null, PageRequest.of(1, 10, Sort.Direction.DESC, "dateUsed")); + // + // //then + // assertThat(page.getTotalElements()).isEqualTo(15); + // assertThat(page.getNumberOfElements()).isEqualTo(5); + // assertThat(page.getTotalPages()).isEqualTo(2); + // } + // + // private Object getField(Object target, String fieldName) { + // return ReflectionTestUtils.getField(target, fieldName); + // } -// @DisplayName("특정 상태의 예산지원신청서만 검색한다.") -// @Test -// public void searchSpecificApplicationsTest() { -// //given -// List applicationList = new ArrayList<>(); -// for (int i = 0; i < 20; i++) { -// BudgetSupportApplication application = -// new BudgetSupportApplication("스터디 지원금 신청", -// LocalDateTime.of(2020, 1, 1, 1, 1, 1), -// "머신러닝 논문 스터디 온라인 강의비 청구", 10000, "국민 123 홍길동", member.getId()); -// ReflectionTestUtils.setField(application, "status", ApplicationStatus.values()[i % 4]); -// applicationList.add(application); -// } -// repository.saveAll(applicationList); -// -// //when -// Page page = -// repository.search(ApplicationStatus.DENIED, PageRequest.of(0, 15, Sort.Direction.DESC, "dateUsed")); -// -// //then -// assertThat(page.getTotalElements()).isEqualTo(5); -// assertThat(page.getNumberOfElements()).isEqualTo(5); -// assertThat(page.getTotalPages()).isEqualTo(1); -// assertThat(page.getContent()) -// .extracting("status") -// .containsOnly(ApplicationStatus.DENIED); -// } + // @DisplayName("특정 상태의 예산지원신청서만 검색한다.") + // @Test + // public void searchSpecificApplicationsTest() { + // //given + // List applicationList = new ArrayList<>(); + // for (int i = 0; i < 20; i++) { + // BudgetSupportApplication application = + // new BudgetSupportApplication("스터디 지원금 신청", + // LocalDateTime.of(2020, 1, 1, 1, 1, 1), + // "머신러닝 논문 스터디 온라인 강의비 청구", 10000, "국민 123 홍길동", member.getId()); + // ReflectionTestUtils.setField(application, "status", ApplicationStatus.values()[i % + // 4]); + // applicationList.add(application); + // } + // repository.saveAll(applicationList); + // + // //when + // Page page = + // repository.search(ApplicationStatus.DENIED, PageRequest.of(0, 15, + // Sort.Direction.DESC, "dateUsed")); + // + // //then + // assertThat(page.getTotalElements()).isEqualTo(5); + // assertThat(page.getNumberOfElements()).isEqualTo(5); + // assertThat(page.getTotalPages()).isEqualTo(1); + // assertThat(page.getContent()) + // .extracting("status") + // .containsOnly(ApplicationStatus.DENIED); + // } } diff --git a/resource-server/src/test/java/com/inhabas/api/domain/budget/repository/BudgetHistoryRepositoryTest.java b/resource-server/src/test/java/com/inhabas/api/domain/budget/repository/BudgetHistoryRepositoryTest.java index 992fabb7..cb44c708 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/budget/repository/BudgetHistoryRepositoryTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/budget/repository/BudgetHistoryRepositoryTest.java @@ -1,206 +1,188 @@ package com.inhabas.api.domain.budget.repository; -import static com.inhabas.api.domain.member.domain.entity.MemberTest.basicMember1; -import static com.inhabas.api.domain.member.domain.entity.MemberTest.basicMember2; -import static org.assertj.core.api.Assertions.assertThat; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager; -import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.StudentId; -import com.inhabas.api.domain.budget.domain.BudgetHistory; -import com.inhabas.api.domain.budget.dto.BudgetHistoryDetailDto; import com.inhabas.testAnnotataion.DefaultDataJpaTest; -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; -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.boot.test.autoconfigure.orm.jpa.TestEntityManager; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Sort.Direction; -import org.springframework.test.util.ReflectionTestUtils; @DefaultDataJpaTest public class BudgetHistoryRepositoryTest { - @Autowired - private TestEntityManager em; - @Autowired - private BudgetHistoryRepository budgetHistoryRepository; + @Autowired private TestEntityManager em; + @Autowired private BudgetHistoryRepository budgetHistoryRepository; - private StudentId received, inCharge; + private StudentId received, inCharge; -// @BeforeEach -// public void setUp() { -// Member member1 = basicMember1(); -// Member member2 = basicMember2(); -// em.persist(member1); -// em.persist(member2); -// received = member1.getId(); -// inCharge = member2.getId(); -// } + // @BeforeEach + // public void setUp() { + // Member member1 = basicMember1(); + // Member member2 = basicMember2(); + // em.persist(member1); + // em.persist(member2); + // received = member1.getId(); + // inCharge = member2.getId(); + // } -// @DisplayName("예산 내역을 하나 조회한다.") -// @Test -// public void fetchOneBudgetHistoryTest() { -// //given -// BudgetHistory history = budgetHistoryRepository.save( -// BudgetHistory.builder() -// .title("간식비") -// .details("과자") -// .income(0) -// .outcome(500000) -// .dateUsed(LocalDateTime.of(2000, 1, 1, 1, 1, 1)) -// .personReceived(received) -// .personInCharge(inCharge) -// .build()); -// Integer id = (Integer) ReflectionTestUtils.getField(history, "id"); -// -// //when -// BudgetHistoryDetailDto budgetHistoryDetailDto = budgetHistoryRepository.findDtoById(id) -// .orElseThrow(); -// -// //then -// assertThat(getField(budgetHistoryDetailDto, "dateCreated")).isNotNull(); -// assertThat(getField(budgetHistoryDetailDto, "title")).isEqualTo("간식비"); -// assertThat(getField(budgetHistoryDetailDto, "outcome")).isEqualTo(500000); -// assertThat(getField(budgetHistoryDetailDto, "receivedMemberName")).isEqualTo("유동현"); -// assertThat(getField(budgetHistoryDetailDto, "memberNameInCharge")).isEqualTo("김민겸"); -// } -// -// private Object getField(Object target, String field) { -// return ReflectionTestUtils.getField(target, field); -// } -// -// @DisplayName("예산 내역 페이지 객체를 가져온다.") -// @Test -// public void fetchBudgetHistoryPageTest() { -// -// //given -// List histories = new ArrayList<>(); -// for (int i = 1; i < 31; i++) { -// histories.add( -// BudgetHistory.builder() -// .title("간식비" + i) -// .details("과자" + i) -// .income(0) -// .outcome(500000) -// .dateUsed(LocalDateTime.of(2000, 1, i, 1, 1, 1)) -// .personReceived(received) -// .personInCharge(inCharge) -// .build()); -// } -// budgetHistoryRepository.saveAll(histories); -// -// //when -// Page page = budgetHistoryRepository.search(null, -// PageRequest.of(1, 20, Direction.DESC, "dateUsed")); -// -// //then -// assertThat(page.getTotalElements()).isEqualTo(30); -// assertThat(page.getNumberOfElements()).isEqualTo(10); -// assertThat(page.getTotalPages()).isEqualTo(2); -// assertThat(page.getContent().get(0)).extracting("title").isEqualTo("간식비10"); -// } -// -// @DisplayName("2021년도 예산 내역만 가져온다.") -// @Test -// public void searchBudgetHistoryByYearTest() { -// -// //given -// List histories = new ArrayList<>(); -// for (int i = 1; i < 21; i++) { -// histories.add( -// BudgetHistory.builder() -// .title("간식비2000") -// .details("과자2000") -// .income(0) -// .outcome(500000) -// .dateUsed(LocalDateTime.of(2000 + (i / 15), 1, 1, 1, 1, 1)) -// .personReceived(received) -// .personInCharge(inCharge) -// .build()); -// } -// budgetHistoryRepository.saveAll(histories); -// -// //when -// Page page = budgetHistoryRepository.search(2001, -// PageRequest.of(0, 15, Direction.DESC, "dateUsed")); -// -// //then -// assertThat(page.getTotalElements()).isEqualTo(6); -// assertThat(page.getNumberOfElements()).isEqualTo(6); -// assertThat(page.getTotalPages()).isEqualTo(1); -// } -// -// @DisplayName("회계내역이 있는 년도를 모두 가져온다.") -// @Test -// public void getAllYearOfHistory() { -// //given -// List histories = new ArrayList<>(); -// for (int i = 1; i < 21; i++) { -// histories.add( -// BudgetHistory.builder() -// .title("간식비2000") -// .details("과자2000") -// .income(0) -// .outcome(500000) -// .dateUsed(LocalDateTime.of(2000 + (i / 3), 1, 1, 1, 1, 1)) -// .personReceived(received) -// .personInCharge(inCharge) -// .build()); -// } -// budgetHistoryRepository.saveAll(histories); -// -// //when -// List allYear = budgetHistoryRepository.findAllYear(); -// -// //then -// assertThat(allYear).containsExactly(2006, 2005, 2004, 2003, 2002, 2001, 2000); -// assertThat(allYear).hasSize(7); -// } -// -// @DisplayName("잔액을 구한다.") -// @Test -// public void getBalanceTest() { -// //given -// budgetHistoryRepository.save( -// BudgetHistory.builder() -// .title("간식비") -// .details("과자") -// .income(0) -// .outcome(500000) -// .dateUsed(LocalDateTime.of(2000, 1, 1, 1, 1, 1)) -// .personReceived(received) -// .personInCharge(inCharge) -// .build()); -// budgetHistoryRepository.save( -// BudgetHistory.builder() -// .title("동아리 지원금") -// .details("학사 지원") -// .income(3000000) -// .outcome(0) -// .dateUsed(LocalDateTime.of(2000, 1, 1, 1, 1, 1)) -// .personReceived(inCharge) -// .personInCharge(inCharge) -// .build()); -// budgetHistoryRepository.save( -// BudgetHistory.builder() -// .title("강의 지원금") -// .details("강의 결제 비용") -// .income(0) -// .outcome(200000) -// .dateUsed(LocalDateTime.of(2000, 1, 1, 1, 1, 1)) -// .personReceived(received) -// .personInCharge(inCharge) -// .build()); -// -// //when -// Integer balance = budgetHistoryRepository.getBalance(); -// -// //then -// assertThat(balance).isEqualTo(2300000); -// } + // @DisplayName("예산 내역을 하나 조회한다.") + // @Test + // public void fetchOneBudgetHistoryTest() { + // //given + // BudgetHistory history = budgetHistoryRepository.save( + // BudgetHistory.builder() + // .title("간식비") + // .details("과자") + // .income(0) + // .outcome(500000) + // .dateUsed(LocalDateTime.of(2000, 1, 1, 1, 1, 1)) + // .personReceived(received) + // .personInCharge(inCharge) + // .build()); + // Integer id = (Integer) ReflectionTestUtils.getField(history, "id"); + // + // //when + // BudgetHistoryDetailDto budgetHistoryDetailDto = budgetHistoryRepository.findDtoById(id) + // .orElseThrow(); + // + // //then + // assertThat(getField(budgetHistoryDetailDto, "dateCreated")).isNotNull(); + // assertThat(getField(budgetHistoryDetailDto, "title")).isEqualTo("간식비"); + // assertThat(getField(budgetHistoryDetailDto, "outcome")).isEqualTo(500000); + // assertThat(getField(budgetHistoryDetailDto, "receivedMemberName")).isEqualTo("유동현"); + // assertThat(getField(budgetHistoryDetailDto, "memberNameInCharge")).isEqualTo("김민겸"); + // } + // + // private Object getField(Object target, String field) { + // return ReflectionTestUtils.getField(target, field); + // } + // + // @DisplayName("예산 내역 페이지 객체를 가져온다.") + // @Test + // public void fetchBudgetHistoryPageTest() { + // + // //given + // List histories = new ArrayList<>(); + // for (int i = 1; i < 31; i++) { + // histories.add( + // BudgetHistory.builder() + // .title("간식비" + i) + // .details("과자" + i) + // .income(0) + // .outcome(500000) + // .dateUsed(LocalDateTime.of(2000, 1, i, 1, 1, 1)) + // .personReceived(received) + // .personInCharge(inCharge) + // .build()); + // } + // budgetHistoryRepository.saveAll(histories); + // + // //when + // Page page = budgetHistoryRepository.search(null, + // PageRequest.of(1, 20, Direction.DESC, "dateUsed")); + // + // //then + // assertThat(page.getTotalElements()).isEqualTo(30); + // assertThat(page.getNumberOfElements()).isEqualTo(10); + // assertThat(page.getTotalPages()).isEqualTo(2); + // assertThat(page.getContent().get(0)).extracting("title").isEqualTo("간식비10"); + // } + // + // @DisplayName("2021년도 예산 내역만 가져온다.") + // @Test + // public void searchBudgetHistoryByYearTest() { + // + // //given + // List histories = new ArrayList<>(); + // for (int i = 1; i < 21; i++) { + // histories.add( + // BudgetHistory.builder() + // .title("간식비2000") + // .details("과자2000") + // .income(0) + // .outcome(500000) + // .dateUsed(LocalDateTime.of(2000 + (i / 15), 1, 1, 1, 1, 1)) + // .personReceived(received) + // .personInCharge(inCharge) + // .build()); + // } + // budgetHistoryRepository.saveAll(histories); + // + // //when + // Page page = budgetHistoryRepository.search(2001, + // PageRequest.of(0, 15, Direction.DESC, "dateUsed")); + // + // //then + // assertThat(page.getTotalElements()).isEqualTo(6); + // assertThat(page.getNumberOfElements()).isEqualTo(6); + // assertThat(page.getTotalPages()).isEqualTo(1); + // } + // + // @DisplayName("회계내역이 있는 년도를 모두 가져온다.") + // @Test + // public void getAllYearOfHistory() { + // //given + // List histories = new ArrayList<>(); + // for (int i = 1; i < 21; i++) { + // histories.add( + // BudgetHistory.builder() + // .title("간식비2000") + // .details("과자2000") + // .income(0) + // .outcome(500000) + // .dateUsed(LocalDateTime.of(2000 + (i / 3), 1, 1, 1, 1, 1)) + // .personReceived(received) + // .personInCharge(inCharge) + // .build()); + // } + // budgetHistoryRepository.saveAll(histories); + // + // //when + // List allYear = budgetHistoryRepository.findAllYear(); + // + // //then + // assertThat(allYear).containsExactly(2006, 2005, 2004, 2003, 2002, 2001, 2000); + // assertThat(allYear).hasSize(7); + // } + // + // @DisplayName("잔액을 구한다.") + // @Test + // public void getBalanceTest() { + // //given + // budgetHistoryRepository.save( + // BudgetHistory.builder() + // .title("간식비") + // .details("과자") + // .income(0) + // .outcome(500000) + // .dateUsed(LocalDateTime.of(2000, 1, 1, 1, 1, 1)) + // .personReceived(received) + // .personInCharge(inCharge) + // .build()); + // budgetHistoryRepository.save( + // BudgetHistory.builder() + // .title("동아리 지원금") + // .details("학사 지원") + // .income(3000000) + // .outcome(0) + // .dateUsed(LocalDateTime.of(2000, 1, 1, 1, 1, 1)) + // .personReceived(inCharge) + // .personInCharge(inCharge) + // .build()); + // budgetHistoryRepository.save( + // BudgetHistory.builder() + // .title("강의 지원금") + // .details("강의 결제 비용") + // .income(0) + // .outcome(200000) + // .dateUsed(LocalDateTime.of(2000, 1, 1, 1, 1, 1)) + // .personReceived(received) + // .personInCharge(inCharge) + // .build()); + // + // //when + // Integer balance = budgetHistoryRepository.getBalance(); + // + // //then + // assertThat(balance).isEqualTo(2300000); + // } } diff --git a/resource-server/src/test/java/com/inhabas/api/domain/budget/usecase/BudgetApplicationProcessorTest.java b/resource-server/src/test/java/com/inhabas/api/domain/budget/usecase/BudgetApplicationProcessorTest.java index c6bc9950..ab30f0f3 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/budget/usecase/BudgetApplicationProcessorTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/budget/usecase/BudgetApplicationProcessorTest.java @@ -7,6 +7,11 @@ import static org.mockito.BDDMockito.then; import static org.mockito.Mockito.times; +import java.time.LocalDateTime; +import java.util.Optional; + +import org.springframework.test.util.ReflectionTestUtils; + import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.StudentId; import com.inhabas.api.domain.budget.domain.BudgetHistory; import com.inhabas.api.domain.budget.domain.BudgetSupportApplication; @@ -15,154 +20,158 @@ import com.inhabas.api.domain.budget.dto.BudgetApplicationStatusChangeRequest; import com.inhabas.api.domain.budget.repository.BudgetApplicationRepository; import com.inhabas.api.domain.budget.repository.BudgetHistoryRepository; -import java.time.LocalDateTime; -import java.util.Optional; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; -import org.springframework.test.util.ReflectionTestUtils; @ExtendWith(MockitoExtension.class) public class BudgetApplicationProcessorTest { - @InjectMocks - private BudgetApplicationProcessorImpl processor; - - @Mock - private BudgetApplicationRepository applicationRepository; - @Mock - private BudgetHistoryRepository historyRepository; - - @DisplayName("대기중인 요청을 승인한다.") - @Test - public void waitingToApproveTest() { - //given - BudgetSupportApplication application = BudgetSupportApplication.builder() - .title("title") - .dateUsed(LocalDateTime.of(2020, 1, 1, 1, 1, 1)) - .details("details") - .outcome(10000) - .applicationWriter(new StudentId("12171652")) - .account("기업 1234 홍길동") - .build(); - given(applicationRepository.findById(anyInt())).willReturn(Optional.of(application)); - - //when - BudgetApplicationStatusChangeRequest request = - new BudgetApplicationStatusChangeRequest("APPROVED", null); - processor.process(1, request, new StudentId("18165249")); - - //then - then(applicationRepository).should(times(1)).findById(anyInt()); - ApplicationStatus status = (ApplicationStatus) ReflectionTestUtils.getField(application, "status"); - assertThat(status).isEqualTo(ApplicationStatus.APPROVED); - } - - @DisplayName("대기중인 요청을 거절한다.") - @Test - public void waitingToDenyTest() { - //given - BudgetSupportApplication application = BudgetSupportApplication.builder() - .title("title") - .dateUsed(LocalDateTime.of(2020, 1, 1, 1, 1, 1)) - .details("details") - .outcome(10000) - .applicationWriter(new StudentId("12171652")) - .account("기업 1234 홍길동") - .build(); - given(applicationRepository.findById(anyInt())).willReturn(Optional.of(application)); - - //when - BudgetApplicationStatusChangeRequest request = - new BudgetApplicationStatusChangeRequest("DENIED", "중복 요청"); - processor.process(1, request, new StudentId("18165249")); - - //then - then(applicationRepository).should(times(1)).findById(anyInt()); - ApplicationStatus status = (ApplicationStatus) ReflectionTestUtils.getField(application, "status"); - assertThat(status).isEqualTo(ApplicationStatus.DENIED); - } - - @DisplayName("대기중인 요청을 거절할 때, 거절 사유는 필수이다.") - @Test - public void rejectReasonIsNecessaryToDenyTest() { - //given - BudgetSupportApplication application = BudgetSupportApplication.builder() - .title("title") - .dateUsed(LocalDateTime.of(2020, 1, 1, 1, 1, 1)) - .details("details") - .outcome(10000) - .applicationWriter(new StudentId("12171652")) - .account("기업 1234 홍길동") - .build(); - given(applicationRepository.findById(anyInt())).willReturn(Optional.of(application)); - - //when - BudgetApplicationStatusChangeRequest request = - new BudgetApplicationStatusChangeRequest("DENIED", null); - - //then - Assertions.assertThrows(IllegalArgumentException.class, - () -> processor.process(1, request, new StudentId("18165249"))); - then(applicationRepository).should(times(1)).findById(anyInt()); - } - - - @DisplayName("대기중인 요청을 완료처리한다.") - @Test - public void waitingToProcessTest() { - //given - BudgetSupportApplication application = BudgetSupportApplication.builder() - .title("title") - .dateUsed(LocalDateTime.of(2020, 1, 1, 1, 1, 1)) - .details("details") - .outcome(10000) - .applicationWriter(new StudentId("12171652")) - .account("기업 1234 홍길동") - .build(); - given(applicationRepository.findById(anyInt())).willReturn(Optional.of(application)); - given(historyRepository.save(any(BudgetHistory.class))).willReturn(null); - - //when - BudgetApplicationStatusChangeRequest request = - new BudgetApplicationStatusChangeRequest("PROCESSED", null); - processor.process(1, request, new StudentId("18165249")); - - //then - then(applicationRepository).should(times(1)).findById(anyInt()); - then(historyRepository).should(times(1)).save(any(BudgetHistory.class)); - ApplicationStatus status = (ApplicationStatus) ReflectionTestUtils.getField(application, "status"); - assertThat(status).isEqualTo(ApplicationStatus.PROCESSED); - } - - @DisplayName("거절했던 신청이 수정된 뒤에 승인한다.") - @Test - public void deniedToApprovedTest() { - //given - BudgetSupportApplication application = BudgetSupportApplication.builder() - .title("title") - .dateUsed(LocalDateTime.of(2020, 1, 1, 1, 1, 1)) - .details("details") - .outcome(10000) - .applicationWriter(new StudentId("12171652")) - .account("기업 1234 홍길동") - .build(); - ReflectionTestUtils.setField(application, "status", ApplicationStatus.DENIED); - ReflectionTestUtils.setField(application, "rejectReason", new RejectReason("계좌번호 미기재")); - given(applicationRepository.findById(anyInt())).willReturn(Optional.of(application)); - - //when - BudgetApplicationStatusChangeRequest request = - new BudgetApplicationStatusChangeRequest("APPROVED", null); - processor.process(1, request, new StudentId("18165249")); - - //then - then(applicationRepository).should(times(1)).findById(anyInt()); - ApplicationStatus status = (ApplicationStatus) ReflectionTestUtils.getField(application, "status"); - assertThat(status).isEqualTo(ApplicationStatus.APPROVED); - } + @InjectMocks private BudgetApplicationProcessorImpl processor; + + @Mock private BudgetApplicationRepository applicationRepository; + @Mock private BudgetHistoryRepository historyRepository; + + @DisplayName("대기중인 요청을 승인한다.") + @Test + public void waitingToApproveTest() { + // given + BudgetSupportApplication application = + BudgetSupportApplication.builder() + .title("title") + .dateUsed(LocalDateTime.of(2020, 1, 1, 1, 1, 1)) + .details("details") + .outcome(10000) + .applicationWriter(new StudentId("12171652")) + .account("기업 1234 홍길동") + .build(); + given(applicationRepository.findById(anyInt())).willReturn(Optional.of(application)); + + // when + BudgetApplicationStatusChangeRequest request = + new BudgetApplicationStatusChangeRequest("APPROVED", null); + processor.process(1, request, new StudentId("18165249")); + + // then + then(applicationRepository).should(times(1)).findById(anyInt()); + ApplicationStatus status = + (ApplicationStatus) ReflectionTestUtils.getField(application, "status"); + assertThat(status).isEqualTo(ApplicationStatus.APPROVED); + } + + @DisplayName("대기중인 요청을 거절한다.") + @Test + public void waitingToDenyTest() { + // given + BudgetSupportApplication application = + BudgetSupportApplication.builder() + .title("title") + .dateUsed(LocalDateTime.of(2020, 1, 1, 1, 1, 1)) + .details("details") + .outcome(10000) + .applicationWriter(new StudentId("12171652")) + .account("기업 1234 홍길동") + .build(); + given(applicationRepository.findById(anyInt())).willReturn(Optional.of(application)); + + // when + BudgetApplicationStatusChangeRequest request = + new BudgetApplicationStatusChangeRequest("DENIED", "중복 요청"); + processor.process(1, request, new StudentId("18165249")); + + // then + then(applicationRepository).should(times(1)).findById(anyInt()); + ApplicationStatus status = + (ApplicationStatus) ReflectionTestUtils.getField(application, "status"); + assertThat(status).isEqualTo(ApplicationStatus.DENIED); + } + + @DisplayName("대기중인 요청을 거절할 때, 거절 사유는 필수이다.") + @Test + public void rejectReasonIsNecessaryToDenyTest() { + // given + BudgetSupportApplication application = + BudgetSupportApplication.builder() + .title("title") + .dateUsed(LocalDateTime.of(2020, 1, 1, 1, 1, 1)) + .details("details") + .outcome(10000) + .applicationWriter(new StudentId("12171652")) + .account("기업 1234 홍길동") + .build(); + given(applicationRepository.findById(anyInt())).willReturn(Optional.of(application)); + + // when + BudgetApplicationStatusChangeRequest request = + new BudgetApplicationStatusChangeRequest("DENIED", null); + + // then + Assertions.assertThrows( + IllegalArgumentException.class, + () -> processor.process(1, request, new StudentId("18165249"))); + then(applicationRepository).should(times(1)).findById(anyInt()); + } + + @DisplayName("대기중인 요청을 완료처리한다.") + @Test + public void waitingToProcessTest() { + // given + BudgetSupportApplication application = + BudgetSupportApplication.builder() + .title("title") + .dateUsed(LocalDateTime.of(2020, 1, 1, 1, 1, 1)) + .details("details") + .outcome(10000) + .applicationWriter(new StudentId("12171652")) + .account("기업 1234 홍길동") + .build(); + given(applicationRepository.findById(anyInt())).willReturn(Optional.of(application)); + given(historyRepository.save(any(BudgetHistory.class))).willReturn(null); + + // when + BudgetApplicationStatusChangeRequest request = + new BudgetApplicationStatusChangeRequest("PROCESSED", null); + processor.process(1, request, new StudentId("18165249")); + + // then + then(applicationRepository).should(times(1)).findById(anyInt()); + then(historyRepository).should(times(1)).save(any(BudgetHistory.class)); + ApplicationStatus status = + (ApplicationStatus) ReflectionTestUtils.getField(application, "status"); + assertThat(status).isEqualTo(ApplicationStatus.PROCESSED); + } + + @DisplayName("거절했던 신청이 수정된 뒤에 승인한다.") + @Test + public void deniedToApprovedTest() { + // given + BudgetSupportApplication application = + BudgetSupportApplication.builder() + .title("title") + .dateUsed(LocalDateTime.of(2020, 1, 1, 1, 1, 1)) + .details("details") + .outcome(10000) + .applicationWriter(new StudentId("12171652")) + .account("기업 1234 홍길동") + .build(); + ReflectionTestUtils.setField(application, "status", ApplicationStatus.DENIED); + ReflectionTestUtils.setField(application, "rejectReason", new RejectReason("계좌번호 미기재")); + given(applicationRepository.findById(anyInt())).willReturn(Optional.of(application)); + + // when + BudgetApplicationStatusChangeRequest request = + new BudgetApplicationStatusChangeRequest("APPROVED", null); + processor.process(1, request, new StudentId("18165249")); + + // then + then(applicationRepository).should(times(1)).findById(anyInt()); + ApplicationStatus status = + (ApplicationStatus) ReflectionTestUtils.getField(application, "status"); + assertThat(status).isEqualTo(ApplicationStatus.APPROVED); + } } diff --git a/resource-server/src/test/java/com/inhabas/api/domain/budget/usecase/BudgetApplicationServiceTest.java b/resource-server/src/test/java/com/inhabas/api/domain/budget/usecase/BudgetApplicationServiceTest.java index 26140f25..e307c00a 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/budget/usecase/BudgetApplicationServiceTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/budget/usecase/BudgetApplicationServiceTest.java @@ -1,7 +1,18 @@ package com.inhabas.api.domain.budget.usecase; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.BDDMockito.given; +import static org.mockito.BDDMockito.then; +import static org.mockito.Mockito.times; + +import java.time.LocalDateTime; +import java.util.Optional; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; + import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.StudentId; -import com.inhabas.api.domain.budget.ApplicationCannotModifiableException; import com.inhabas.api.domain.budget.ApplicationNotFoundException; import com.inhabas.api.domain.budget.domain.BudgetSupportApplication; import com.inhabas.api.domain.budget.domain.valueObject.ApplicationStatus; @@ -9,243 +20,238 @@ import com.inhabas.api.domain.budget.dto.BudgetApplicationRegisterForm; import com.inhabas.api.domain.budget.dto.BudgetApplicationUpdateForm; import com.inhabas.api.domain.budget.repository.BudgetApplicationRepository; -import com.inhabas.api.domain.member.domain.entity.MemberTest; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.test.util.ReflectionTestUtils; - -import java.time.LocalDateTime; -import java.util.Optional; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.BDDMockito.given; -import static org.mockito.BDDMockito.then; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.times; @ExtendWith(MockitoExtension.class) public class BudgetApplicationServiceTest { - @InjectMocks - private BudgetApplicationServiceImpl budgetApplicationService; - - @Mock - private BudgetApplicationRepository repository; - - private StudentId applicantId; - - @BeforeEach - public void setUp() { -// applicantId = MemberTest.basicMember1().getId(); - } - - @DisplayName("예산 지원 신청서를 제출한다.") - @Test - public void registerBudgetApplicationTest() { - //given - BudgetApplicationRegisterForm form = new BudgetApplicationRegisterForm("스터디 운영비", - LocalDateTime.of(2020, 1, 1, 1, 1, 1), - "간식비", 10000, "k뱅크 1234556 홍길동"); - - given(repository.save(any(BudgetSupportApplication.class))).willReturn(null); - - //when - budgetApplicationService.registerApplication(form, applicantId); - - //then - then(repository).should(times(1)).save(any(BudgetSupportApplication.class)); - } - -// @DisplayName("예산 지원 신청서를 수정한다.") -// @Test -// public void updateBudgetApplicationTest() { -// //given -// BudgetSupportApplication original = BudgetSupportApplication.builder() -// .title("스터디 운영비") -// .details("과자") -// .dateUsed(LocalDateTime.of(2020, 1, 1, 1, 1, 1)) -// .outcome(10000) -// .account("국민 1234 홍길동") -// .applicationWriter(applicantId) -// .build(); -// ReflectionTestUtils.setField(original, "id", 1); -// given(repository.findById(anyInt())).willReturn(Optional.of(original)); -// -// given(repository.save(any())).willReturn(null); -// BudgetApplicationUpdateForm form = new BudgetApplicationUpdateForm("스터디 운영비", -// LocalDateTime.of(2020, 1, 1, 1, 1, 1), -// "간식비", 10000, "k뱅크 1234556 홍길동", 13); -// -// //when -// budgetApplicationService.updateApplication(form, applicantId); -// -// //then -// then(repository).should(times(1)).save(any(BudgetSupportApplication.class)); -// } - -// @DisplayName("본인이 작성하지 않은 신청서는 수정할 수 없다.") -// @Test -// public void cannotUpdateOtherApplicationsTest() { -// //given -// BudgetSupportApplication original = BudgetSupportApplication.builder() -// .title("스터디 운영비") -// .details("과자") -// .dateUsed(LocalDateTime.of(2020, 1, 1, 1, 1, 1)) -// .outcome(10000) -// .account("국민 1234 홍길동") -// .applicationWriter(applicantId) -// .build(); -// ReflectionTestUtils.setField(original, "id", 1); -// given(repository.findById(anyInt())).willReturn(Optional.of(original)); -// -// BudgetApplicationUpdateForm form = new BudgetApplicationUpdateForm("스터디 운영비", -// LocalDateTime.of(2020, 1, 1, 1, 1, 1), -// "간식비", 10000, "k뱅크 1234556 홍길동", 1); -// -// //when -// Assertions.assertThrows(ApplicationCannotModifiableException.class, -// () -> budgetApplicationService.updateApplication(form, new StudentId("12"))); -// -// //then -// then(repository).should(times(1)).findById(anyInt()); -// then(repository).should(times(0)).save(any(BudgetSupportApplication.class)); -// } - - @DisplayName("수정 시 존재하지 않는 신청서 id 이면 NotFoundException 을 발생시킨다.") - @Test - public void throwNotFoundExceptionWhenUpdating() { - //given - BudgetApplicationUpdateForm form = new BudgetApplicationUpdateForm("스터디 운영비", - LocalDateTime.of(2020, 1, 1, 1, 1, 1), - "간식비", 10000, "k뱅크 1234556 홍길동", 13); - given(repository.findById(anyInt())).willReturn(Optional.empty()); - - //when - Assertions.assertThrows(ApplicationNotFoundException.class, - () -> budgetApplicationService.updateApplication(form, applicantId)); - - //then - then(repository).should(times(1)).findById(anyInt()); - then(repository).should(times(0)).save(any(BudgetSupportApplication.class)); - } - -// @DisplayName("예산 지원 신청서를 삭제한다.") -// @Test -// public void deleteBudgetApplicationTest() { -// //given -// BudgetSupportApplication original = BudgetSupportApplication.builder() -// .title("스터디 운영비") -// .details("과자") -// .dateUsed(LocalDateTime.of(2020, 1, 1, 1, 1, 1)) -// .outcome(10000) -// .account("국민 1234 홍길동") -// .applicationWriter(applicantId) -// .build(); -// ReflectionTestUtils.setField(original, "id", 1); -// -// given(repository.findById(anyInt())).willReturn(Optional.of(original)); -// doNothing().when(repository).deleteById(anyInt()); -// -// //when -// budgetApplicationService.deleteApplication(1, applicantId); -// -// //then -// then(repository).should(times(1)).deleteById(anyInt()); -// } - -// @DisplayName("본인이 작성하지 않은 신청서는 삭제할 수 없다.") -// @Test -// public void cannotDeleteOtherApplicationsTest() { -// //given -// BudgetSupportApplication original = BudgetSupportApplication.builder() -// .title("스터디 운영비") -// .details("과자") -// .dateUsed(LocalDateTime.of(2020, 1, 1, 1, 1, 1)) -// .outcome(10000) -// .account("국민 1234 홍길동") -// .applicationWriter(applicantId) -// .build(); -// ReflectionTestUtils.setField(original, "id", 1); -// given(repository.findById(anyInt())).willReturn(Optional.of(original)); -// -// //when -// Assertions.assertThrows(ApplicationCannotModifiableException.class, -// () -> budgetApplicationService.deleteApplication(1, new StudentId("12"))); -// -// //then -// then(repository).should(times(1)).findById(anyInt()); -// then(repository).should(times(0)).deleteById(anyInt()); -// } - - @DisplayName("삭제 시 존재하지 않는 신청서 id 이면 NotFoundException 을 발생시킨다.") - @Test - public void throwNotFoundExceptionWhenDeleting() { - //given - given(repository.findById(anyInt())).willReturn(Optional.empty()); - - //when - Assertions.assertThrows(ApplicationNotFoundException.class, - () -> budgetApplicationService.deleteApplication(1, applicantId)); - - //then - then(repository).should(times(1)).findById(anyInt()); - then(repository).should(times(0)).deleteById(anyInt()); - } - - @DisplayName("예산 지원 신청서를 조회한다.") - @Test - public void getBudgetApplicationDetailsTest() { - //given - BudgetApplicationDetailDto detailDto = - new BudgetApplicationDetailDto(1, "", - LocalDateTime.of(2020,1,1,1,1,1), - LocalDateTime.of(2020,6,3,2,1,1), - "", 10000, "", - 12171652, "유동현", - 12345678, "김민겸", - ApplicationStatus.WAITING, ""); - given(repository.findDtoById(anyInt())).willReturn(Optional.of(detailDto)); - - //when - budgetApplicationService.getApplicationDetails(1); - - //then - then(repository).should(times(1)).findDtoById(anyInt()); - } - - @DisplayName("id 에 해당하는 예산 지원 신청서가 존재하지 않으면 NotFoundException 을 던진다.") - @Test - public void throwNotFoundExceptionWhenGetting() { - //given - given(repository.findDtoById(anyInt())).willReturn(Optional.empty()); - - //when - Assertions.assertThrows(ApplicationNotFoundException.class, - ()-> budgetApplicationService.getApplicationDetails(1)); - - //then - then(repository).should(times(1)).findDtoById(anyInt()); - } - - @DisplayName("예산 지원 신청서 목록을 조회한다.") - @Test - public void getBudgetApplicationListTest() { - //given - given(repository.search(any(), any(Pageable.class))).willReturn(Page.empty()); - - //when - budgetApplicationService.getApplications(null, Pageable.ofSize(15)); - - //then - then(repository).should(times(1)).search(any(), any(Pageable.class)); - } + @InjectMocks private BudgetApplicationServiceImpl budgetApplicationService; + + @Mock private BudgetApplicationRepository repository; + + private StudentId applicantId; + + @BeforeEach + public void setUp() { + // applicantId = MemberTest.basicMember1().getId(); + } + + @DisplayName("예산 지원 신청서를 제출한다.") + @Test + public void registerBudgetApplicationTest() { + // given + BudgetApplicationRegisterForm form = + new BudgetApplicationRegisterForm( + "스터디 운영비", LocalDateTime.of(2020, 1, 1, 1, 1, 1), "간식비", 10000, "k뱅크 1234556 홍길동"); + + given(repository.save(any(BudgetSupportApplication.class))).willReturn(null); + + // when + budgetApplicationService.registerApplication(form, applicantId); + + // then + then(repository).should(times(1)).save(any(BudgetSupportApplication.class)); + } + + // @DisplayName("예산 지원 신청서를 수정한다.") + // @Test + // public void updateBudgetApplicationTest() { + // //given + // BudgetSupportApplication original = BudgetSupportApplication.builder() + // .title("스터디 운영비") + // .details("과자") + // .dateUsed(LocalDateTime.of(2020, 1, 1, 1, 1, 1)) + // .outcome(10000) + // .account("국민 1234 홍길동") + // .applicationWriter(applicantId) + // .build(); + // ReflectionTestUtils.setField(original, "id", 1); + // given(repository.findById(anyInt())).willReturn(Optional.of(original)); + // + // given(repository.save(any())).willReturn(null); + // BudgetApplicationUpdateForm form = new BudgetApplicationUpdateForm("스터디 운영비", + // LocalDateTime.of(2020, 1, 1, 1, 1, 1), + // "간식비", 10000, "k뱅크 1234556 홍길동", 13); + // + // //when + // budgetApplicationService.updateApplication(form, applicantId); + // + // //then + // then(repository).should(times(1)).save(any(BudgetSupportApplication.class)); + // } + + // @DisplayName("본인이 작성하지 않은 신청서는 수정할 수 없다.") + // @Test + // public void cannotUpdateOtherApplicationsTest() { + // //given + // BudgetSupportApplication original = BudgetSupportApplication.builder() + // .title("스터디 운영비") + // .details("과자") + // .dateUsed(LocalDateTime.of(2020, 1, 1, 1, 1, 1)) + // .outcome(10000) + // .account("국민 1234 홍길동") + // .applicationWriter(applicantId) + // .build(); + // ReflectionTestUtils.setField(original, "id", 1); + // given(repository.findById(anyInt())).willReturn(Optional.of(original)); + // + // BudgetApplicationUpdateForm form = new BudgetApplicationUpdateForm("스터디 운영비", + // LocalDateTime.of(2020, 1, 1, 1, 1, 1), + // "간식비", 10000, "k뱅크 1234556 홍길동", 1); + // + // //when + // Assertions.assertThrows(ApplicationCannotModifiableException.class, + // () -> budgetApplicationService.updateApplication(form, new StudentId("12"))); + // + // //then + // then(repository).should(times(1)).findById(anyInt()); + // then(repository).should(times(0)).save(any(BudgetSupportApplication.class)); + // } + + @DisplayName("수정 시 존재하지 않는 신청서 id 이면 NotFoundException 을 발생시킨다.") + @Test + public void throwNotFoundExceptionWhenUpdating() { + // given + BudgetApplicationUpdateForm form = + new BudgetApplicationUpdateForm( + "스터디 운영비", LocalDateTime.of(2020, 1, 1, 1, 1, 1), "간식비", 10000, "k뱅크 1234556 홍길동", 13); + given(repository.findById(anyInt())).willReturn(Optional.empty()); + + // when + Assertions.assertThrows( + ApplicationNotFoundException.class, + () -> budgetApplicationService.updateApplication(form, applicantId)); + + // then + then(repository).should(times(1)).findById(anyInt()); + then(repository).should(times(0)).save(any(BudgetSupportApplication.class)); + } + + // @DisplayName("예산 지원 신청서를 삭제한다.") + // @Test + // public void deleteBudgetApplicationTest() { + // //given + // BudgetSupportApplication original = BudgetSupportApplication.builder() + // .title("스터디 운영비") + // .details("과자") + // .dateUsed(LocalDateTime.of(2020, 1, 1, 1, 1, 1)) + // .outcome(10000) + // .account("국민 1234 홍길동") + // .applicationWriter(applicantId) + // .build(); + // ReflectionTestUtils.setField(original, "id", 1); + // + // given(repository.findById(anyInt())).willReturn(Optional.of(original)); + // doNothing().when(repository).deleteById(anyInt()); + // + // //when + // budgetApplicationService.deleteApplication(1, applicantId); + // + // //then + // then(repository).should(times(1)).deleteById(anyInt()); + // } + + // @DisplayName("본인이 작성하지 않은 신청서는 삭제할 수 없다.") + // @Test + // public void cannotDeleteOtherApplicationsTest() { + // //given + // BudgetSupportApplication original = BudgetSupportApplication.builder() + // .title("스터디 운영비") + // .details("과자") + // .dateUsed(LocalDateTime.of(2020, 1, 1, 1, 1, 1)) + // .outcome(10000) + // .account("국민 1234 홍길동") + // .applicationWriter(applicantId) + // .build(); + // ReflectionTestUtils.setField(original, "id", 1); + // given(repository.findById(anyInt())).willReturn(Optional.of(original)); + // + // //when + // Assertions.assertThrows(ApplicationCannotModifiableException.class, + // () -> budgetApplicationService.deleteApplication(1, new StudentId("12"))); + // + // //then + // then(repository).should(times(1)).findById(anyInt()); + // then(repository).should(times(0)).deleteById(anyInt()); + // } + + @DisplayName("삭제 시 존재하지 않는 신청서 id 이면 NotFoundException 을 발생시킨다.") + @Test + public void throwNotFoundExceptionWhenDeleting() { + // given + given(repository.findById(anyInt())).willReturn(Optional.empty()); + + // when + Assertions.assertThrows( + ApplicationNotFoundException.class, + () -> budgetApplicationService.deleteApplication(1, applicantId)); + + // then + then(repository).should(times(1)).findById(anyInt()); + then(repository).should(times(0)).deleteById(anyInt()); + } + + @DisplayName("예산 지원 신청서를 조회한다.") + @Test + public void getBudgetApplicationDetailsTest() { + // given + BudgetApplicationDetailDto detailDto = + new BudgetApplicationDetailDto( + 1, + "", + LocalDateTime.of(2020, 1, 1, 1, 1, 1), + LocalDateTime.of(2020, 6, 3, 2, 1, 1), + "", + 10000, + "", + 12171652, + "유동현", + 12345678, + "김민겸", + ApplicationStatus.WAITING, + ""); + given(repository.findDtoById(anyInt())).willReturn(Optional.of(detailDto)); + + // when + budgetApplicationService.getApplicationDetails(1); + + // then + then(repository).should(times(1)).findDtoById(anyInt()); + } + + @DisplayName("id 에 해당하는 예산 지원 신청서가 존재하지 않으면 NotFoundException 을 던진다.") + @Test + public void throwNotFoundExceptionWhenGetting() { + // given + given(repository.findDtoById(anyInt())).willReturn(Optional.empty()); + + // when + Assertions.assertThrows( + ApplicationNotFoundException.class, + () -> budgetApplicationService.getApplicationDetails(1)); + + // then + then(repository).should(times(1)).findDtoById(anyInt()); + } + + @DisplayName("예산 지원 신청서 목록을 조회한다.") + @Test + public void getBudgetApplicationListTest() { + // given + given(repository.search(any(), any(Pageable.class))).willReturn(Page.empty()); + + // when + budgetApplicationService.getApplications(null, Pageable.ofSize(15)); + + // then + then(repository).should(times(1)).search(any(), any(Pageable.class)); + } } diff --git a/resource-server/src/test/java/com/inhabas/api/domain/budget/usecase/BudgetHistoryServiceTest.java b/resource-server/src/test/java/com/inhabas/api/domain/budget/usecase/BudgetHistoryServiceTest.java index 8c24d384..5dbb42d4 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/budget/usecase/BudgetHistoryServiceTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/budget/usecase/BudgetHistoryServiceTest.java @@ -1,248 +1,273 @@ package com.inhabas.api.domain.budget.usecase; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.BDDMockito.given; +import static org.mockito.BDDMockito.then; +import static org.mockito.Mockito.times; + +import java.time.LocalDateTime; +import java.util.Optional; + +import org.springframework.data.domain.Pageable; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.test.util.ReflectionTestUtils; + import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.StudentId; -import com.inhabas.api.domain.budget.HistoryCannotModifiableException; import com.inhabas.api.domain.budget.BudgetHistoryNotFoundException; +import com.inhabas.api.domain.budget.HistoryCannotModifiableException; import com.inhabas.api.domain.budget.domain.BudgetHistory; import com.inhabas.api.domain.budget.dto.BudgetHistoryCreateForm; import com.inhabas.api.domain.budget.dto.BudgetHistoryDetailDto; import com.inhabas.api.domain.budget.dto.BudgetHistoryModifyForm; import com.inhabas.api.domain.budget.repository.BudgetHistoryRepository; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import org.springframework.data.domain.Pageable; -import org.springframework.security.access.AccessDeniedException; -import org.springframework.test.util.ReflectionTestUtils; -import java.time.LocalDateTime; -import java.util.Optional; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.BDDMockito.given; -import static org.mockito.BDDMockito.then; -import static org.mockito.Mockito.times; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; @ExtendWith(MockitoExtension.class) public class BudgetHistoryServiceTest { - @InjectMocks - private BudgetHistoryServiceImpl budgetHistoryService; - - @Mock - private BudgetHistoryRepository repository; - - @DisplayName("총무가 회계내역을 추가한다.") - @Test - public void createBudgetHistoryTest() { - - //given - BudgetHistoryCreateForm form = new BudgetHistoryCreateForm( - LocalDateTime.of(2000, 1, 1, 1, 1, 1), - "서버운영비", "aws 작년 서버비용", "12345678", 0, 500000); - StudentId cfo = new StudentId("12171652"); - given(repository.save(any(BudgetHistory.class))).willReturn(null); - - //when - budgetHistoryService.createNewHistory(form, cfo); - - //then - then(repository).should(times(1)).save(any(BudgetHistory.class)); - } - - @DisplayName("총무가 회계내역을 수정한다.") - @Test - public void modifyBudgetHistoryTest() { - //when - StudentId CFO = new StudentId("12171652"); - BudgetHistory history = BudgetHistory.builder() - .title("서버 운영비") - .details("작년 aws 운영 비용") - .income(0) - .outcome(500000) - .dateUsed(LocalDateTime.of(2000, 1, 1, 1, 1, 1)) - .personReceived(new StudentId("10982942")) - .personInCharge(CFO) - .build(); - ReflectionTestUtils.setField(history, "id", 1); - given(repository.findById(any())).willReturn(Optional.of(history)); - - //when - BudgetHistoryModifyForm form = new BudgetHistoryModifyForm( - LocalDateTime.of(2000, 1, 1, 1, 1, 1), - "서버운영비", "aws 작년 서버비용", "12345678", 0, 500000, 1); - budgetHistoryService.modifyHistory(form, CFO); - - //then - then(repository).should(times(1)).findById(any()); - then(repository).should(times(1)).save(any(BudgetHistory.class)); - } - - @DisplayName("총무는 이전의 다른 총무가 작성한 내역을 수정할 수 없다.") - @Test - public void cannotModifyBudgetHistoryOfOtherCFO() { - //given - StudentId previousCFO = new StudentId("12171652"); - StudentId currentCFO = new StudentId("99999999"); - BudgetHistory history = BudgetHistory.builder() - .title("서버 운영비") - .details("작년 aws 운영 비용") - .income(0) - .outcome(500000) - .dateUsed(LocalDateTime.of(2000, 1, 1, 1, 1, 1)) - .personReceived(new StudentId("10982942")) - .personInCharge(previousCFO) - .build(); - ReflectionTestUtils.setField(history, "id", 1); - given(repository.findById(any())).willReturn(Optional.of(history)); - - //when - BudgetHistoryModifyForm form = new BudgetHistoryModifyForm( - LocalDateTime.of(2000, 1, 1, 1, 1, 1), - "서버운영비", "aws 작년 서버비용", "12345678", 0, 500000, 1); - Assertions.assertThrows(AccessDeniedException.class, - () -> budgetHistoryService.modifyHistory(form, currentCFO)); - } - - @DisplayName("수정 시도할 때 히스토리 내역이 존재하지 않으면 오류를 던진다.") - @Test - public void raiseNotFoundExceptionWhenModifyingTest() { - //given - given(repository.findById(any())).willReturn(Optional.empty()); - - //when - BudgetHistoryModifyForm form = new BudgetHistoryModifyForm( - LocalDateTime.of(2000, 1, 1, 1, 1, 1), - "서버운영비", "aws 작년 서버비용", "12345678", 0, 500000, 1); - Assertions.assertThrows(BudgetHistoryNotFoundException.class, - () -> budgetHistoryService.modifyHistory(form, new StudentId("12171652"))); - } - - @DisplayName("총무가 회계 내역을 삭제한다.") - @Test - public void deleteBudgetHistoryTest() { - //given - StudentId CFO = new StudentId("12171652"); - Integer historyId = 1; - BudgetHistory history = BudgetHistory.builder() - .title("서버 운영비") - .details("작년 aws 운영 비용") - .income(0) - .outcome(500000) - .dateUsed(LocalDateTime.of(2000, 1, 1, 1, 1, 1)) - .personReceived(new StudentId("10982942")) - .personInCharge(CFO) - .build(); - ReflectionTestUtils.setField(history, "id", historyId); - given(repository.findById(any())).willReturn(Optional.of(history)); - - //when - budgetHistoryService.deleteHistory(historyId, CFO); - - //then - then(repository).should(times(1)).findById(anyInt()); - then(repository).should(times(1)).deleteById(anyInt()); - } - - @DisplayName("이전의 다른 담당자가 작성했던 기록은 삭제할 수 없다.") - @Test - public void cannotDeleteBudgetHistoryTest() { - //given - StudentId previousCFO = new StudentId("12171652"); - StudentId currentCFO = new StudentId("99999999"); - Integer historyId = 1; - BudgetHistory history = BudgetHistory.builder() - .title("서버 운영비") - .details("작년 aws 운영 비용") - .income(0) - .outcome(500000) - .dateUsed(LocalDateTime.of(2000, 1, 1, 1, 1, 1)) - .personReceived(new StudentId("10982942")) - .personInCharge(previousCFO) - .build(); - ReflectionTestUtils.setField(history, "id", historyId); - given(repository.findById(any())).willReturn(Optional.of(history)); - - //when - Assertions.assertThrows(HistoryCannotModifiableException.class, - () -> budgetHistoryService.deleteHistory(historyId, currentCFO)); - - //then - then(repository).should(times(1)).findById(anyInt()); - } - - @DisplayName("존재하지 않는 기록을 삭제하려고 하면 예외를 던진다.") - @Test - public void raiseNotFoundExceptionWhenDeletingTest() { - //given - given(repository.findById(any())).willReturn(Optional.empty()); - - //when - Assertions.assertThrows(BudgetHistoryNotFoundException.class, - () -> budgetHistoryService.deleteHistory(1, new StudentId("12171652"))); - - //then - then(repository).should(times(1)).findById(anyInt()); - } - - @DisplayName("회계내역을 한 페이지를 출력한다.") - @Test - public void getListOfBudgetHistoryTest() { - //given - given(repository.search(any(), any())).willReturn(null); - - //when - budgetHistoryService.searchHistoryList(null, Pageable.ofSize(15)); - - //then - then(repository).should(times(1)).search(any(), any()); - } - - @DisplayName("회계내역을 id 로 조회한다.") - @Test - public void getOneBudgetHistoryTest() { - //given - given(repository.findDtoById(anyInt())) - .willReturn(Optional.of(new BudgetHistoryDetailDto( - null, null, null, null, null, null, - null, null, null, null, - null, null, null))); - - //when - budgetHistoryService.getHistory(2); - - //then - then(repository).should(times(1)).findDtoById(anyInt()); - } - - @DisplayName("id 에 해당하는 회계내역이 없는 경우, NotFoundException을 던진다.") - @Test - public void cannotFindBudgetHistoryFindById() { - //given - given(repository.findDtoById(anyInt())).willReturn(Optional.empty()); - - //when - Assertions.assertThrows(BudgetHistoryNotFoundException.class, - () -> budgetHistoryService.getHistory(2)); - - then(repository).should(times(1)).findDtoById(anyInt()); - } - - @DisplayName("기록이 존재하는 년도를 모두 가져온다.") - @Test - public void fetchAllYearOfHistoryTest() { - //given - given(repository.findAllYear()).willReturn(null); - - //when - budgetHistoryService.getAllYearOfHistory(); - - //then - then(repository).should(times(1)).findAllYear(); - } + @InjectMocks private BudgetHistoryServiceImpl budgetHistoryService; + + @Mock private BudgetHistoryRepository repository; + + @DisplayName("총무가 회계내역을 추가한다.") + @Test + public void createBudgetHistoryTest() { + + // given + BudgetHistoryCreateForm form = + new BudgetHistoryCreateForm( + LocalDateTime.of(2000, 1, 1, 1, 1, 1), "서버운영비", "aws 작년 서버비용", "12345678", 0, 500000); + StudentId cfo = new StudentId("12171652"); + given(repository.save(any(BudgetHistory.class))).willReturn(null); + + // when + budgetHistoryService.createNewHistory(form, cfo); + + // then + then(repository).should(times(1)).save(any(BudgetHistory.class)); + } + + @DisplayName("총무가 회계내역을 수정한다.") + @Test + public void modifyBudgetHistoryTest() { + // when + StudentId CFO = new StudentId("12171652"); + BudgetHistory history = + BudgetHistory.builder() + .title("서버 운영비") + .details("작년 aws 운영 비용") + .income(0) + .outcome(500000) + .dateUsed(LocalDateTime.of(2000, 1, 1, 1, 1, 1)) + .personReceived(new StudentId("10982942")) + .personInCharge(CFO) + .build(); + ReflectionTestUtils.setField(history, "id", 1); + given(repository.findById(any())).willReturn(Optional.of(history)); + + // when + BudgetHistoryModifyForm form = + new BudgetHistoryModifyForm( + LocalDateTime.of(2000, 1, 1, 1, 1, 1), + "서버운영비", + "aws 작년 서버비용", + "12345678", + 0, + 500000, + 1); + budgetHistoryService.modifyHistory(form, CFO); + + // then + then(repository).should(times(1)).findById(any()); + then(repository).should(times(1)).save(any(BudgetHistory.class)); + } + + @DisplayName("총무는 이전의 다른 총무가 작성한 내역을 수정할 수 없다.") + @Test + public void cannotModifyBudgetHistoryOfOtherCFO() { + // given + StudentId previousCFO = new StudentId("12171652"); + StudentId currentCFO = new StudentId("99999999"); + BudgetHistory history = + BudgetHistory.builder() + .title("서버 운영비") + .details("작년 aws 운영 비용") + .income(0) + .outcome(500000) + .dateUsed(LocalDateTime.of(2000, 1, 1, 1, 1, 1)) + .personReceived(new StudentId("10982942")) + .personInCharge(previousCFO) + .build(); + ReflectionTestUtils.setField(history, "id", 1); + given(repository.findById(any())).willReturn(Optional.of(history)); + + // when + BudgetHistoryModifyForm form = + new BudgetHistoryModifyForm( + LocalDateTime.of(2000, 1, 1, 1, 1, 1), + "서버운영비", + "aws 작년 서버비용", + "12345678", + 0, + 500000, + 1); + Assertions.assertThrows( + AccessDeniedException.class, () -> budgetHistoryService.modifyHistory(form, currentCFO)); + } + + @DisplayName("수정 시도할 때 히스토리 내역이 존재하지 않으면 오류를 던진다.") + @Test + public void raiseNotFoundExceptionWhenModifyingTest() { + // given + given(repository.findById(any())).willReturn(Optional.empty()); + + // when + BudgetHistoryModifyForm form = + new BudgetHistoryModifyForm( + LocalDateTime.of(2000, 1, 1, 1, 1, 1), + "서버운영비", + "aws 작년 서버비용", + "12345678", + 0, + 500000, + 1); + Assertions.assertThrows( + BudgetHistoryNotFoundException.class, + () -> budgetHistoryService.modifyHistory(form, new StudentId("12171652"))); + } + + @DisplayName("총무가 회계 내역을 삭제한다.") + @Test + public void deleteBudgetHistoryTest() { + // given + StudentId CFO = new StudentId("12171652"); + Integer historyId = 1; + BudgetHistory history = + BudgetHistory.builder() + .title("서버 운영비") + .details("작년 aws 운영 비용") + .income(0) + .outcome(500000) + .dateUsed(LocalDateTime.of(2000, 1, 1, 1, 1, 1)) + .personReceived(new StudentId("10982942")) + .personInCharge(CFO) + .build(); + ReflectionTestUtils.setField(history, "id", historyId); + given(repository.findById(any())).willReturn(Optional.of(history)); + + // when + budgetHistoryService.deleteHistory(historyId, CFO); + + // then + then(repository).should(times(1)).findById(anyInt()); + then(repository).should(times(1)).deleteById(anyInt()); + } + + @DisplayName("이전의 다른 담당자가 작성했던 기록은 삭제할 수 없다.") + @Test + public void cannotDeleteBudgetHistoryTest() { + // given + StudentId previousCFO = new StudentId("12171652"); + StudentId currentCFO = new StudentId("99999999"); + Integer historyId = 1; + BudgetHistory history = + BudgetHistory.builder() + .title("서버 운영비") + .details("작년 aws 운영 비용") + .income(0) + .outcome(500000) + .dateUsed(LocalDateTime.of(2000, 1, 1, 1, 1, 1)) + .personReceived(new StudentId("10982942")) + .personInCharge(previousCFO) + .build(); + ReflectionTestUtils.setField(history, "id", historyId); + given(repository.findById(any())).willReturn(Optional.of(history)); + + // when + Assertions.assertThrows( + HistoryCannotModifiableException.class, + () -> budgetHistoryService.deleteHistory(historyId, currentCFO)); + + // then + then(repository).should(times(1)).findById(anyInt()); + } + + @DisplayName("존재하지 않는 기록을 삭제하려고 하면 예외를 던진다.") + @Test + public void raiseNotFoundExceptionWhenDeletingTest() { + // given + given(repository.findById(any())).willReturn(Optional.empty()); + + // when + Assertions.assertThrows( + BudgetHistoryNotFoundException.class, + () -> budgetHistoryService.deleteHistory(1, new StudentId("12171652"))); + + // then + then(repository).should(times(1)).findById(anyInt()); + } + + @DisplayName("회계내역을 한 페이지를 출력한다.") + @Test + public void getListOfBudgetHistoryTest() { + // given + given(repository.search(any(), any())).willReturn(null); + + // when + budgetHistoryService.searchHistoryList(null, Pageable.ofSize(15)); + + // then + then(repository).should(times(1)).search(any(), any()); + } + + @DisplayName("회계내역을 id 로 조회한다.") + @Test + public void getOneBudgetHistoryTest() { + // given + given(repository.findDtoById(anyInt())) + .willReturn( + Optional.of( + new BudgetHistoryDetailDto( + null, null, null, null, null, null, null, null, null, null, null, null, null))); + + // when + budgetHistoryService.getHistory(2); + + // then + then(repository).should(times(1)).findDtoById(anyInt()); + } + + @DisplayName("id 에 해당하는 회계내역이 없는 경우, NotFoundException을 던진다.") + @Test + public void cannotFindBudgetHistoryFindById() { + // given + given(repository.findDtoById(anyInt())).willReturn(Optional.empty()); + + // when + Assertions.assertThrows( + BudgetHistoryNotFoundException.class, () -> budgetHistoryService.getHistory(2)); + + then(repository).should(times(1)).findDtoById(anyInt()); + } + + @DisplayName("기록이 존재하는 년도를 모두 가져온다.") + @Test + public void fetchAllYearOfHistoryTest() { + // given + given(repository.findAllYear()).willReturn(null); + + // when + budgetHistoryService.getAllYearOfHistory(); + + // then + then(repository).should(times(1)).findAllYear(); + } } diff --git a/resource-server/src/test/java/com/inhabas/api/domain/budget/valueObject/AccountTest.java b/resource-server/src/test/java/com/inhabas/api/domain/budget/valueObject/AccountTest.java index 9b25952a..d418cfee 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/budget/valueObject/AccountTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/budget/valueObject/AccountTest.java @@ -1,57 +1,57 @@ package com.inhabas.api.domain.budget.valueObject; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; + import com.inhabas.api.domain.budget.domain.valueObject.Account; + import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertThrows; - public class AccountTest { - @DisplayName("Account 타입에 문자열을 저장한다.") - @Test - public void normalAccountTest() { - //given - String accountString = "계좌 정보입니다."; + @DisplayName("Account 타입에 문자열을 저장한다.") + @Test + public void normalAccountTest() { + // given + String accountString = "계좌 정보입니다."; - //when - Account account = new Account(accountString); + // when + Account account = new Account(accountString); - //then - assertThat(account.getValue()).isEqualTo("계좌 정보입니다."); - } + // then + assertThat(account.getValue()).isEqualTo("계좌 정보입니다."); + } - @DisplayName("Account 타입에 너무 긴 문자열을 저장한다. 100자 이상") - @Test - public void tooLongAccountTest() { - //given - String accountString = "지금이문장은10자임".repeat(10); + @DisplayName("Account 타입에 너무 긴 문자열을 저장한다. 100자 이상") + @Test + public void tooLongAccountTest() { + // given + String accountString = "지금이문장은10자임".repeat(10); - //then - assertThrows(IllegalArgumentException.class, - () -> new Account(accountString)); - } + // then + assertThrows(IllegalArgumentException.class, () -> new Account(accountString)); + } - @DisplayName("계좌정보는 null 이어도 됩니다.") - @Test - public void accountCannotBeNull() { + @DisplayName("계좌정보는 null 이어도 됩니다.") + @Test + public void accountCannotBeNull() { - //when - Account account = new Account(null); + // when + Account account = new Account(null); - //then - assertThat(account.getValue()).isNull(); - } + // then + assertThat(account.getValue()).isNull(); + } - @DisplayName("계좌정보가 빈 문자열이면 null 로 변환됩니다.") - @Test - public void applicantAccountCannotBeNullBlank() { + @DisplayName("계좌정보가 빈 문자열이면 null 로 변환됩니다.") + @Test + public void applicantAccountCannotBeNullBlank() { - //when - Account account = new Account("\t"); + // when + Account account = new Account("\t"); - //then - assertThat(account.getValue()).isNull(); - } + // then + assertThat(account.getValue()).isNull(); + } } diff --git a/resource-server/src/test/java/com/inhabas/api/domain/budget/valueObject/ApplicantAccountTest.java b/resource-server/src/test/java/com/inhabas/api/domain/budget/valueObject/ApplicantAccountTest.java index 67abb45e..de9d67e4 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/budget/valueObject/ApplicantAccountTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/budget/valueObject/ApplicantAccountTest.java @@ -1,49 +1,47 @@ package com.inhabas.api.domain.budget.valueObject; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; + import com.inhabas.api.domain.budget.domain.valueObject.ApplicantAccount; + import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertThrows; - public class ApplicantAccountTest { - @DisplayName("Account 타입에 문자열을 저장한다.") - @Test - public void normalApplicantAccountTest() { - //given - String accountString = "계좌 정보입니다."; - - //when - ApplicantAccount applicantAccount = new ApplicantAccount(accountString); - - //then - assertThat(applicantAccount.getValue()).isEqualTo("계좌 정보입니다."); - } - - @DisplayName("Account 타입에 너무 긴 문자열을 저장한다. 100자 이상") - @Test - public void tooLongApplicantAccountTest() { - //given - String accountString = "지금이문장은10자임".repeat(10); - - //then - assertThrows(IllegalArgumentException.class, - () -> new ApplicantAccount(accountString)); - } - - @DisplayName("계좌정보는 null 일 수 없습니다.") - @Test - public void applicantAccountCannotBeNull() { - assertThrows(IllegalArgumentException.class, - () -> new ApplicantAccount(null)); - } - - @DisplayName("계좌정보는 빈 문자열일 수 없습니다.") - @Test - public void applicantAccountCannotBeNullBlank() { - assertThrows(IllegalArgumentException.class, - () -> new ApplicantAccount("\t")); - } + @DisplayName("Account 타입에 문자열을 저장한다.") + @Test + public void normalApplicantAccountTest() { + // given + String accountString = "계좌 정보입니다."; + + // when + ApplicantAccount applicantAccount = new ApplicantAccount(accountString); + + // then + assertThat(applicantAccount.getValue()).isEqualTo("계좌 정보입니다."); + } + + @DisplayName("Account 타입에 너무 긴 문자열을 저장한다. 100자 이상") + @Test + public void tooLongApplicantAccountTest() { + // given + String accountString = "지금이문장은10자임".repeat(10); + + // then + assertThrows(IllegalArgumentException.class, () -> new ApplicantAccount(accountString)); + } + + @DisplayName("계좌정보는 null 일 수 없습니다.") + @Test + public void applicantAccountCannotBeNull() { + assertThrows(IllegalArgumentException.class, () -> new ApplicantAccount(null)); + } + + @DisplayName("계좌정보는 빈 문자열일 수 없습니다.") + @Test + public void applicantAccountCannotBeNullBlank() { + assertThrows(IllegalArgumentException.class, () -> new ApplicantAccount("\t")); + } } diff --git a/resource-server/src/test/java/com/inhabas/api/domain/budget/valueObject/DetailTest.java b/resource-server/src/test/java/com/inhabas/api/domain/budget/valueObject/DetailTest.java index 73d0b303..f050071a 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/budget/valueObject/DetailTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/budget/valueObject/DetailTest.java @@ -1,49 +1,47 @@ package com.inhabas.api.domain.budget.valueObject; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; + import com.inhabas.api.domain.budget.domain.valueObject.Details; + import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertThrows; - public class DetailTest { - @DisplayName("Details 타입에 문자열을 저장한다.") - @Test - public void normalDetailsTest() { - //given - String detailsString = "예산 내역 상세 내용입니다."; - - //when - Details details = new Details(detailsString); - - //then - assertThat(details.getValue()).isEqualTo("예산 내역 상세 내용입니다."); - } - - @DisplayName("Details 타입에 너무 긴 문자열을 저장한다. 300자 이상") - @Test - public void tooLongDetailsTest() { - //given - String detailsString = "지금이문장은10자임".repeat(30); - - //then - assertThrows(IllegalArgumentException.class, - () -> new Details(detailsString)); - } - - @DisplayName("예산 내역 제목은 null 일 수 없습니다.") - @Test - public void detailsCannotBeNullTest() { - assertThrows(IllegalArgumentException.class, - () -> new Details(null)); - } - - @DisplayName("예산 상세내역 은 빈 문자열일 수 없습니다.") - @Test - public void detailsCannotBeBlankTest() { - assertThrows(IllegalArgumentException.class, - () -> new Details("\t")); - } + @DisplayName("Details 타입에 문자열을 저장한다.") + @Test + public void normalDetailsTest() { + // given + String detailsString = "예산 내역 상세 내용입니다."; + + // when + Details details = new Details(detailsString); + + // then + assertThat(details.getValue()).isEqualTo("예산 내역 상세 내용입니다."); + } + + @DisplayName("Details 타입에 너무 긴 문자열을 저장한다. 300자 이상") + @Test + public void tooLongDetailsTest() { + // given + String detailsString = "지금이문장은10자임".repeat(30); + + // then + assertThrows(IllegalArgumentException.class, () -> new Details(detailsString)); + } + + @DisplayName("예산 내역 제목은 null 일 수 없습니다.") + @Test + public void detailsCannotBeNullTest() { + assertThrows(IllegalArgumentException.class, () -> new Details(null)); + } + + @DisplayName("예산 상세내역 은 빈 문자열일 수 없습니다.") + @Test + public void detailsCannotBeBlankTest() { + assertThrows(IllegalArgumentException.class, () -> new Details("\t")); + } } diff --git a/resource-server/src/test/java/com/inhabas/api/domain/budget/valueObject/PriceTest.java b/resource-server/src/test/java/com/inhabas/api/domain/budget/valueObject/PriceTest.java index 0603be24..e42e7073 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/budget/valueObject/PriceTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/budget/valueObject/PriceTest.java @@ -1,48 +1,48 @@ package com.inhabas.api.domain.budget.valueObject; +import static org.assertj.core.api.Assertions.assertThat; + import com.inhabas.api.domain.budget.domain.valueObject.Price; + import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import static org.assertj.core.api.Assertions.assertThat; - public class PriceTest { - @DisplayName("가격을 생성한다.") - @Test - public void normalPriceTest() { - //given - Integer price = 10000; - - //when - Price priceObj = new Price(price); - - //then - assertThat(priceObj.getValue()).isEqualTo(10000); - } - - @DisplayName("가격은 0 이 될 수 있다.") - @Test - public void zeroPriceTest() { - //given - Integer price = 0; - - //when - Price priceObj = new Price(price); - - //then - assertThat(priceObj.getValue()).isEqualTo(0); - } - - @DisplayName("음수 가격은 생성될 수 없다.") - @Test - public void minusPriceCannotBeProducedTest() { - //given - Integer minusPrice = -10000; - - //when - Assertions.assertThrows(IllegalArgumentException.class, - ()->new Price(minusPrice)); - } + @DisplayName("가격을 생성한다.") + @Test + public void normalPriceTest() { + // given + Integer price = 10000; + + // when + Price priceObj = new Price(price); + + // then + assertThat(priceObj.getValue()).isEqualTo(10000); + } + + @DisplayName("가격은 0 이 될 수 있다.") + @Test + public void zeroPriceTest() { + // given + Integer price = 0; + + // when + Price priceObj = new Price(price); + + // then + assertThat(priceObj.getValue()).isEqualTo(0); + } + + @DisplayName("음수 가격은 생성될 수 없다.") + @Test + public void minusPriceCannotBeProducedTest() { + // given + Integer minusPrice = -10000; + + // when + Assertions.assertThrows(IllegalArgumentException.class, () -> new Price(minusPrice)); + } } diff --git a/resource-server/src/test/java/com/inhabas/api/domain/budget/valueObject/RejectReasonTest.java b/resource-server/src/test/java/com/inhabas/api/domain/budget/valueObject/RejectReasonTest.java index 2a62bd39..c2673cdf 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/budget/valueObject/RejectReasonTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/budget/valueObject/RejectReasonTest.java @@ -1,49 +1,47 @@ package com.inhabas.api.domain.budget.valueObject; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; + import com.inhabas.api.domain.budget.domain.valueObject.RejectReason; + import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertThrows; - public class RejectReasonTest { - @DisplayName("RejectReason 타입에 문자열을 저장한다.") - @Test - public void normalRejectReasonTest() { - //given - String rejectString = "거부이유입니다."; - - //when - RejectReason rejectReason = new RejectReason(rejectString); - - //then - assertThat(rejectReason.getValue()).isEqualTo("거부이유입니다."); - } - - @DisplayName("RejectReason 타입에 너무 긴 문자열을 저장한다. 200자 이상") - @Test - public void tooLongRejectReasonTest() { - //given - String rejectString = "지금이문장은10자임".repeat(20); - - //then - assertThrows(IllegalArgumentException.class, - () -> new RejectReason(rejectString)); - } - - @DisplayName("거부이유는 null 일 수 없습니다.") - @Test - public void rejectReasonCannotBeNullTest() { - assertThrows(IllegalArgumentException.class, - () -> new RejectReason(null)); - } - - @DisplayName("거부이유는 빈 문자열일 수 없습니다.") - @Test - public void rejectReasonCannotBeBlankTest() { - assertThrows(IllegalArgumentException.class, - () -> new RejectReason("\t")); - } + @DisplayName("RejectReason 타입에 문자열을 저장한다.") + @Test + public void normalRejectReasonTest() { + // given + String rejectString = "거부이유입니다."; + + // when + RejectReason rejectReason = new RejectReason(rejectString); + + // then + assertThat(rejectReason.getValue()).isEqualTo("거부이유입니다."); + } + + @DisplayName("RejectReason 타입에 너무 긴 문자열을 저장한다. 200자 이상") + @Test + public void tooLongRejectReasonTest() { + // given + String rejectString = "지금이문장은10자임".repeat(20); + + // then + assertThrows(IllegalArgumentException.class, () -> new RejectReason(rejectString)); + } + + @DisplayName("거부이유는 null 일 수 없습니다.") + @Test + public void rejectReasonCannotBeNullTest() { + assertThrows(IllegalArgumentException.class, () -> new RejectReason(null)); + } + + @DisplayName("거부이유는 빈 문자열일 수 없습니다.") + @Test + public void rejectReasonCannotBeBlankTest() { + assertThrows(IllegalArgumentException.class, () -> new RejectReason("\t")); + } } diff --git a/resource-server/src/test/java/com/inhabas/api/domain/budget/valueObject/TitleTest.java b/resource-server/src/test/java/com/inhabas/api/domain/budget/valueObject/TitleTest.java index 49aaa045..061c92f2 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/budget/valueObject/TitleTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/budget/valueObject/TitleTest.java @@ -1,49 +1,47 @@ package com.inhabas.api.domain.budget.valueObject; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; + import com.inhabas.api.domain.budget.domain.valueObject.Title; + import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertThrows; - public class TitleTest { - @DisplayName("Title 타입에 제목을 저장한다.") - @Test - public void Title_is_OK() { - //given - String titleString = "예산 내역 제목입니다."; - - //when - Title title = new Title(titleString); - - //then - assertThat(title.getValue()).isEqualTo("예산 내역 제목입니다."); - } - - @DisplayName("Title 타입에 너무 긴 제목을 저장한다. 100자 이상") - @Test - public void Title_is_too_long() { - //given - String titleString = "지금이문장은10자임".repeat(10); - - //then - assertThrows(IllegalArgumentException.class, - () -> new Title(titleString)); - } - - @DisplayName("예산 내역 제목은 null 일 수 없습니다.") - @Test - public void Title_cannot_be_Null() { - assertThrows(IllegalArgumentException.class, - () -> new Title(null)); - } - - @DisplayName("예산 내역 제목은 빈 문자열일 수 없습니다.") - @Test - public void Title_cannot_be_Blank() { - assertThrows(IllegalArgumentException.class, - () -> new Title("\t")); - } + @DisplayName("Title 타입에 제목을 저장한다.") + @Test + public void Title_is_OK() { + // given + String titleString = "예산 내역 제목입니다."; + + // when + Title title = new Title(titleString); + + // then + assertThat(title.getValue()).isEqualTo("예산 내역 제목입니다."); + } + + @DisplayName("Title 타입에 너무 긴 제목을 저장한다. 100자 이상") + @Test + public void Title_is_too_long() { + // given + String titleString = "지금이문장은10자임".repeat(10); + + // then + assertThrows(IllegalArgumentException.class, () -> new Title(titleString)); + } + + @DisplayName("예산 내역 제목은 null 일 수 없습니다.") + @Test + public void Title_cannot_be_Null() { + assertThrows(IllegalArgumentException.class, () -> new Title(null)); + } + + @DisplayName("예산 내역 제목은 빈 문자열일 수 없습니다.") + @Test + public void Title_cannot_be_Blank() { + assertThrows(IllegalArgumentException.class, () -> new Title("\t")); + } } diff --git a/resource-server/src/test/java/com/inhabas/api/domain/club/domain/entity/ClubHistoryTest.java b/resource-server/src/test/java/com/inhabas/api/domain/club/domain/entity/ClubHistoryTest.java index 091784ee..7367a0a2 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/club/domain/entity/ClubHistoryTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/club/domain/entity/ClubHistoryTest.java @@ -1,45 +1,46 @@ package com.inhabas.api.domain.club.domain.entity; +import static org.assertj.core.api.Assertions.assertThat; + +import java.time.LocalDateTime; + import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; import com.inhabas.api.domain.board.domain.valueObject.Content; import com.inhabas.api.domain.board.domain.valueObject.Title; import com.inhabas.api.domain.club.domain.ClubHistory; import com.inhabas.api.domain.club.dto.SaveClubHistoryDto; import com.inhabas.api.domain.member.domain.entity.MemberTest; -import org.junit.jupiter.api.Test; - -import java.time.LocalDateTime; - -import static org.assertj.core.api.Assertions.assertThat; +import org.junit.jupiter.api.Test; class ClubHistoryTest { - @Test - void updateClubHistory() { - //given - Member writer = MemberTest.chiefMember(); - ClubHistory clubHistory = ClubHistory.builder() - .member(writer) - .title(new Title("oldTitle")) - .content(new Content("oldContent")) - .dateHistory(LocalDateTime.now()) - .build(); - SaveClubHistoryDto saveClubHistoryDto = SaveClubHistoryDto.builder() - .title("title") - .content("content") - .dateHistory(LocalDateTime.now()) - .build(); - - //when - clubHistory.updateClubHistory(writer, saveClubHistoryDto); - - //then - assertThat(clubHistory) - .extracting(ClubHistory -> clubHistory.getTitle().getValue(), - ClubHistory -> clubHistory.getContent().getValue()) - .containsExactly(saveClubHistoryDto.getTitle(), saveClubHistoryDto.getContent()); - - } - -} \ No newline at end of file + @Test + void updateClubHistory() { + // given + Member writer = MemberTest.chiefMember(); + ClubHistory clubHistory = + ClubHistory.builder() + .member(writer) + .title(new Title("oldTitle")) + .content(new Content("oldContent")) + .dateHistory(LocalDateTime.now()) + .build(); + SaveClubHistoryDto saveClubHistoryDto = + SaveClubHistoryDto.builder() + .title("title") + .content("content") + .dateHistory(LocalDateTime.now()) + .build(); + + // when + clubHistory.updateClubHistory(writer, saveClubHistoryDto); + + // then + assertThat(clubHistory) + .extracting( + ClubHistory -> clubHistory.getTitle().getValue(), + ClubHistory -> clubHistory.getContent().getValue()) + .containsExactly(saveClubHistoryDto.getTitle(), saveClubHistoryDto.getContent()); + } +} diff --git a/resource-server/src/test/java/com/inhabas/api/domain/club/dto/ClubActivityDetailDtoTest.java b/resource-server/src/test/java/com/inhabas/api/domain/club/dto/ClubActivityDetailDtoTest.java index 5667eeeb..0a39f138 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/club/dto/ClubActivityDetailDtoTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/club/dto/ClubActivityDetailDtoTest.java @@ -1,57 +1,57 @@ package com.inhabas.api.domain.club.dto; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.*; + +import java.util.Set; import javax.validation.ConstraintViolation; import javax.validation.Validation; import javax.validation.Validator; import javax.validation.ValidatorFactory; -import java.util.Set; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; public class ClubActivityDetailDtoTest { - private static ValidatorFactory validatorFactory; - private static Validator validator; - - @BeforeAll - public static void init() { - validatorFactory = Validation.buildDefaultValidatorFactory(); - validator = validatorFactory.getValidator(); - } - - @AfterAll - public static void close() { - validatorFactory.close(); - } - - - @DisplayName("DTO validation 검사") - @Test - public void validationTest() { - //given - ClubActivityDetailDto clubActivityDetailDto = ClubActivityDetailDto.builder() - .id(-1L) - .title("") - .content("") - .writerName("") - .dateCreated(null) - .dateUpdated(null) - .files(null) - .build(); - - //when - Set> violations = validator.validate(clubActivityDetailDto); - - //then - final int allField = 7; - assertThat(violations).hasSize(allField); - - } - -} \ No newline at end of file + private static ValidatorFactory validatorFactory; + private static Validator validator; + + @BeforeAll + public static void init() { + validatorFactory = Validation.buildDefaultValidatorFactory(); + validator = validatorFactory.getValidator(); + } + + @AfterAll + public static void close() { + validatorFactory.close(); + } + + @DisplayName("DTO validation 검사") + @Test + public void validationTest() { + // given + ClubActivityDetailDto clubActivityDetailDto = + ClubActivityDetailDto.builder() + .id(-1L) + .title("") + .content("") + .writerName("") + .dateCreated(null) + .dateUpdated(null) + .files(null) + .build(); + + // when + Set> violations = + validator.validate(clubActivityDetailDto); + + // then + final int allField = 7; + assertThat(violations).hasSize(allField); + } +} diff --git a/resource-server/src/test/java/com/inhabas/api/domain/club/dto/ClubActivityDtoTest.java b/resource-server/src/test/java/com/inhabas/api/domain/club/dto/ClubActivityDtoTest.java index fe9e3cb0..4673e13d 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/club/dto/ClubActivityDtoTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/club/dto/ClubActivityDtoTest.java @@ -1,55 +1,54 @@ package com.inhabas.api.domain.club.dto; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Set; import javax.validation.ConstraintViolation; import javax.validation.Validation; import javax.validation.Validator; import javax.validation.ValidatorFactory; -import java.util.Set; -import static org.assertj.core.api.Assertions.assertThat; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; public class ClubActivityDtoTest { - private static ValidatorFactory validatorFactory; - private static Validator validator; - - @BeforeAll - public static void init() { - validatorFactory = Validation.buildDefaultValidatorFactory(); - validator = validatorFactory.getValidator(); - } - - @AfterAll - public static void close() { - validatorFactory.close(); - } - - - @DisplayName("DTO validation 검사") - @Test - public void validationTest() { - //given - ClubActivityDto clubActivityDto = ClubActivityDto.builder() - .id(-1L) - .title("") - .writerName("") - .dateCreated(null) - .dateUpdated(null) - .thumbnail(null) - .build(); - - //when - Set> violations = validator.validate(clubActivityDto); - - //then - final int allField = 5; - assertThat(violations).hasSize(allField); - - } - -} \ No newline at end of file + private static ValidatorFactory validatorFactory; + private static Validator validator; + + @BeforeAll + public static void init() { + validatorFactory = Validation.buildDefaultValidatorFactory(); + validator = validatorFactory.getValidator(); + } + + @AfterAll + public static void close() { + validatorFactory.close(); + } + + @DisplayName("DTO validation 검사") + @Test + public void validationTest() { + // given + ClubActivityDto clubActivityDto = + ClubActivityDto.builder() + .id(-1L) + .title("") + .writerName("") + .dateCreated(null) + .dateUpdated(null) + .thumbnail(null) + .build(); + + // when + Set> violations = validator.validate(clubActivityDto); + + // then + final int allField = 5; + assertThat(violations).hasSize(allField); + } +} diff --git a/resource-server/src/test/java/com/inhabas/api/domain/club/dto/ClubHistoryDtoTest.java b/resource-server/src/test/java/com/inhabas/api/domain/club/dto/ClubHistoryDtoTest.java index 7c6155d6..bdca9ec0 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/club/dto/ClubHistoryDtoTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/club/dto/ClubHistoryDtoTest.java @@ -1,73 +1,73 @@ package com.inhabas.api.domain.club.dto; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; +import static org.assertj.core.api.Assertions.assertThat; + +import java.time.LocalDateTime; +import java.util.Set; import javax.validation.ConstraintViolation; import javax.validation.Validation; import javax.validation.Validator; import javax.validation.ValidatorFactory; -import java.time.LocalDateTime; -import java.util.Set; -import static org.assertj.core.api.Assertions.assertThat; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; class ClubHistoryDtoTest { - private static ValidatorFactory validatorFactory; - private static Validator validator; - - @BeforeAll - public static void init() { - validatorFactory = Validation.buildDefaultValidatorFactory(); - validator = validatorFactory.getValidator(); - } - - @AfterAll - public static void close() { - validatorFactory.close(); - } - - @DisplayName("Id, writerId 가 Positive 가 아니면 validation 실패") - @Test - void Positive_Test() { - //given - ClubHistoryDto clubHistoryDto = ClubHistoryDto.builder() - .id(-1L) - .title("goodTitle") - .content("goodContent") - .writerId(-1L) - .dateHistory(LocalDateTime.now()) - .build(); - - //when - Set> violations = validator.validate(clubHistoryDto); - - //then - assertThat(violations).hasSize(2); - - } - - @DisplayName("Id, writerId, dateHistory 가 null 이면 validation 실패") - @Test - void NotNull_Test() { - //given - ClubHistoryDto clubHistoryDto = ClubHistoryDto.builder() - .id(null) - .title("goodTitle") - .content("goodContent") - .writerId(null) - .dateHistory(null) - .build(); - - //when - Set> violations = validator.validate(clubHistoryDto); - - //then - assertThat(violations).hasSize(3); - - } - -} \ No newline at end of file + private static ValidatorFactory validatorFactory; + private static Validator validator; + + @BeforeAll + public static void init() { + validatorFactory = Validation.buildDefaultValidatorFactory(); + validator = validatorFactory.getValidator(); + } + + @AfterAll + public static void close() { + validatorFactory.close(); + } + + @DisplayName("Id, writerId 가 Positive 가 아니면 validation 실패") + @Test + void Positive_Test() { + // given + ClubHistoryDto clubHistoryDto = + ClubHistoryDto.builder() + .id(-1L) + .title("goodTitle") + .content("goodContent") + .writerId(-1L) + .dateHistory(LocalDateTime.now()) + .build(); + + // when + Set> violations = validator.validate(clubHistoryDto); + + // then + assertThat(violations).hasSize(2); + } + + @DisplayName("Id, writerId, dateHistory 가 null 이면 validation 실패") + @Test + void NotNull_Test() { + // given + ClubHistoryDto clubHistoryDto = + ClubHistoryDto.builder() + .id(null) + .title("goodTitle") + .content("goodContent") + .writerId(null) + .dateHistory(null) + .build(); + + // when + Set> violations = validator.validate(clubHistoryDto); + + // then + assertThat(violations).hasSize(3); + } +} diff --git a/resource-server/src/test/java/com/inhabas/api/domain/club/dto/SaveClubActivityDtoTest.java b/resource-server/src/test/java/com/inhabas/api/domain/club/dto/SaveClubActivityDtoTest.java index 8a9262e8..51234bd9 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/club/dto/SaveClubActivityDtoTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/club/dto/SaveClubActivityDtoTest.java @@ -1,54 +1,49 @@ package com.inhabas.api.domain.club.dto; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.*; + +import java.util.Set; import javax.validation.ConstraintViolation; import javax.validation.Validation; import javax.validation.Validator; import javax.validation.ValidatorFactory; -import java.util.Set; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; public class SaveClubActivityDtoTest { - - private static ValidatorFactory validatorFactory; - private static Validator validator; - - @BeforeAll - public static void init() { - validatorFactory = Validation.buildDefaultValidatorFactory(); - validator = validatorFactory.getValidator(); - } - - @AfterAll - public static void close() { - validatorFactory.close(); - } - - - @DisplayName("DTO validation 검사") - @Test - public void validationTest() { - //given - SaveClubActivityDto saveClubActivityDto = SaveClubActivityDto.builder() - .title("") - .content("") - .files(null) - .build(); - - //when - Set> violations = validator.validate(saveClubActivityDto); - - //then - final int allFieldExceptFiles = 2; - assertThat(violations).hasSize(allFieldExceptFiles); - - } - -} \ No newline at end of file + private static ValidatorFactory validatorFactory; + private static Validator validator; + + @BeforeAll + public static void init() { + validatorFactory = Validation.buildDefaultValidatorFactory(); + validator = validatorFactory.getValidator(); + } + + @AfterAll + public static void close() { + validatorFactory.close(); + } + + @DisplayName("DTO validation 검사") + @Test + public void validationTest() { + // given + SaveClubActivityDto saveClubActivityDto = + SaveClubActivityDto.builder().title("").content("").files(null).build(); + + // when + Set> violations = + validator.validate(saveClubActivityDto); + + // then + final int allFieldExceptFiles = 2; + assertThat(violations).hasSize(allFieldExceptFiles); + } +} diff --git a/resource-server/src/test/java/com/inhabas/api/domain/club/dto/SaveClubHistoryDtoTest.java b/resource-server/src/test/java/com/inhabas/api/domain/club/dto/SaveClubHistoryDtoTest.java index 651c2d27..3aa41316 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/club/dto/SaveClubHistoryDtoTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/club/dto/SaveClubHistoryDtoTest.java @@ -1,50 +1,51 @@ package com.inhabas.api.domain.club.dto; -import org.assertj.core.api.Assertions; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; +import java.util.Set; import javax.validation.ConstraintViolation; import javax.validation.Validation; import javax.validation.Validator; import javax.validation.ValidatorFactory; -import java.util.Set; - -class SaveClubHistoryDtoTest { - - private static ValidatorFactory validatorFactory; - private static Validator validator; - @BeforeAll - public static void init() { - validatorFactory = Validation.buildDefaultValidatorFactory(); - validator = validatorFactory.getValidator(); - } - - @AfterAll - public static void close() { - validatorFactory.close(); - } - - - @DisplayName("dateHistory 가 null 이면 validation 실패") - @Test - void NotNull_Test() { - //given - SaveClubHistoryDto saveClubHistoryDto = SaveClubHistoryDto.builder() - .title("goodTitle") - .content("goodContent") - .dateHistory(null) - .build(); - - //when - Set> violations = validator.validate(saveClubHistoryDto); +import org.assertj.core.api.Assertions; - //then - Assertions.assertThat(violations.size()).isEqualTo(1); +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; - } +class SaveClubHistoryDtoTest { -} \ No newline at end of file + private static ValidatorFactory validatorFactory; + private static Validator validator; + + @BeforeAll + public static void init() { + validatorFactory = Validation.buildDefaultValidatorFactory(); + validator = validatorFactory.getValidator(); + } + + @AfterAll + public static void close() { + validatorFactory.close(); + } + + @DisplayName("dateHistory 가 null 이면 validation 실패") + @Test + void NotNull_Test() { + // given + SaveClubHistoryDto saveClubHistoryDto = + SaveClubHistoryDto.builder() + .title("goodTitle") + .content("goodContent") + .dateHistory(null) + .build(); + + // when + Set> violations = + validator.validate(saveClubHistoryDto); + + // then + Assertions.assertThat(violations.size()).isEqualTo(1); + } +} diff --git a/resource-server/src/test/java/com/inhabas/api/domain/club/usecase/ClubActivityServiceImplTest.java b/resource-server/src/test/java/com/inhabas/api/domain/club/usecase/ClubActivityServiceImplTest.java index 7917c022..4a8413bf 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/club/usecase/ClubActivityServiceImplTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/club/usecase/ClubActivityServiceImplTest.java @@ -1,5 +1,19 @@ package com.inhabas.api.domain.club.usecase; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.mockito.BDDMockito.then; +import static org.mockito.Mockito.*; + +import java.util.Arrays; +import java.util.List; +import java.util.Optional; + +import org.springframework.test.util.ReflectionTestUtils; +import org.springframework.web.multipart.MultipartFile; + import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; import com.inhabas.api.auth.domain.oauth2.member.repository.MemberRepository; import com.inhabas.api.domain.board.domain.AlbumBoard; @@ -14,180 +28,158 @@ import com.inhabas.api.domain.menu.domain.MenuGroup; import com.inhabas.api.domain.menu.domain.valueObject.MenuType; import com.inhabas.api.domain.menu.repository.MenuRepository; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import org.springframework.test.util.ReflectionTestUtils; -import org.springframework.web.multipart.MultipartFile; - -import java.util.Arrays; -import java.util.List; -import java.util.Optional; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.given; -import static org.mockito.BDDMockito.then; -import static org.mockito.Mockito.*; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; @ExtendWith(MockitoExtension.class) public class ClubActivityServiceImplTest { - @InjectMocks - private ClubActivityServiceImpl clubActivityService; - @Mock - private ClubActivityRepository clubActivityRepository; - @Mock - private MemberRepository memberRepository; - @Mock - private S3Service s3Service; - @Mock - private BoardSecurityChecker boardSecurityChecker; - @Mock - private MenuRepository menuRepository; - - - @DisplayName("동아리 활동 조회 성공") - @Test - public void getClubActivitiesTest_Success() { - //given - Member member = MemberTest.chiefMember(); - AlbumBoard clubActivity = AlbumBoard.builder() - .title("title") - .content("content") - .menu(mock(Menu.class)) - .build() - .writtenBy(member, AlbumBoard.class); - - given(clubActivityRepository.findAll()).willReturn(Arrays.asList(clubActivity)); - - //when - List clubActivityDtoList = clubActivityService.getClubActivities(); - - //then - assertThat(clubActivityDtoList).hasSize(1); - assertThat(clubActivityDtoList.get(0).getTitle()).isEqualTo(clubActivity.getTitle()); - - } - - @DisplayName("동아리 활동 생성 성공") - @Test - public void writeClubActivityTest_Success() { - //given - Long memberId = 1L; - Member member = MemberTest.chiefMember(); // 필요한 속성으로 Member 객체 초기화 - Menu menu = new Menu(mock(MenuGroup.class), 1, MenuType.ALBUM, "동아리 활동", "동아리 활동"); - SaveClubActivityDto saveClubActivityDto = new SaveClubActivityDto( - "title", "content", null); - - given(memberRepository.findById(memberId)).willReturn(Optional.of(member)); - given(menuRepository.findByName_Value(any())).willReturn(Optional.of(menu)); - given(clubActivityRepository.save(any(AlbumBoard.class))).willAnswer(invocation -> { - AlbumBoard savedClubActivity = invocation.getArgument(0); - ReflectionTestUtils.setField(savedClubActivity, "id", 1L); - return savedClubActivity; - }); - - // when - Long resultId = clubActivityService.writeClubActivity(memberId, saveClubActivityDto); - - // then - assertThat(resultId).isEqualTo(1L); - - } - - @DisplayName("동아리 활동 단일 조회 성공") - @Test - public void getClubActivityTest_Success() { - //given - AlbumBoard clubActivity = AlbumBoard.builder() - .title("title") - .content("content") - .menu(mock(Menu.class)) - .build() - .writtenBy(MemberTest.chiefMember(), AlbumBoard.class); - - given(clubActivityRepository.findById(any())).willReturn(Optional.of(clubActivity)); - - //when - ClubActivityDetailDto clubActivityDetailDto = clubActivityService.getClubActivity(1L); - - //then - assertThat(clubActivityDetailDto).as("Title and content of clubActivityDetailDto are equal to clubActivity") - .extracting("title", "content") - .containsExactly(clubActivity.getTitle(), clubActivity.getContent()); - - - } - - @DisplayName("동아리 활동 수정 성공") - @Test - public void updateClubActivityTest_Success() { - // given - Member member = MemberTest.chiefMember(); - AlbumBoard clubActivity = AlbumBoard.builder() - .title("title") - .content("content") - .menu(mock(Menu.class)) - .build() - .writtenBy(member, AlbumBoard.class); - ReflectionTestUtils.setField(clubActivity, "id", 1L); - SaveClubActivityDto saveClubActivityDto = new SaveClubActivityDto( - "title", "content", null); - given(clubActivityRepository.findById(any())).willReturn(Optional.ofNullable(clubActivity)); - given(clubActivityRepository.save(any())).willReturn(clubActivity); - - // when - clubActivityService.updateClubActivity(1L, saveClubActivityDto); - - // then - then(clubActivityRepository).should(times(1)).findById(any()); - then(clubActivityRepository).should(times(1)).save(any()); - - } - - @DisplayName("동아리 활동 수정 실패 (file storage)") - @Test - public void updateClubActivityTest_FileStorage_Failed() { - // given - Member member = MemberTest.chiefMember(); - AlbumBoard clubActivity = AlbumBoard.builder() - .title("title") - .content("content") - .menu(mock(Menu.class)) - .build() - .writtenBy(member, AlbumBoard.class); - MultipartFile file = mock(MultipartFile.class); - - SaveClubActivityDto saveClubActivityDto = new SaveClubActivityDto( - "title", "content", List.of(file)); - given(clubActivityRepository.findById(any())).willReturn(Optional.of(clubActivity)); - given(s3Service.uploadS3File(any(), any())).willThrow(RuntimeException.class); - - // when, then - assertThatThrownBy(() -> clubActivityService.updateClubActivity(1L, saveClubActivityDto)) - .isInstanceOf(RuntimeException.class) - .hasMessage("파일 업로드를 실패했습니다."); - - } - - @DisplayName("동아리 활동 삭제 성공") - @Test - public void deleteClubActivityTest_Success() { - //given - Long boardId = 1L; - doNothing().when(clubActivityRepository).deleteById(boardId); - - //when - clubActivityService.deleteClubActivity(boardId); - - //then - then(clubActivityRepository).should(times(1)).deleteById(boardId); - - } - -} \ No newline at end of file + @InjectMocks private ClubActivityServiceImpl clubActivityService; + @Mock private ClubActivityRepository clubActivityRepository; + @Mock private MemberRepository memberRepository; + @Mock private S3Service s3Service; + @Mock private BoardSecurityChecker boardSecurityChecker; + @Mock private MenuRepository menuRepository; + + @DisplayName("동아리 활동 조회 성공") + @Test + public void getClubActivitiesTest_Success() { + // given + Member member = MemberTest.chiefMember(); + AlbumBoard clubActivity = + AlbumBoard.builder() + .title("title") + .content("content") + .menu(mock(Menu.class)) + .build() + .writtenBy(member, AlbumBoard.class); + + given(clubActivityRepository.findAll()).willReturn(Arrays.asList(clubActivity)); + + // when + List clubActivityDtoList = clubActivityService.getClubActivities(); + + // then + assertThat(clubActivityDtoList).hasSize(1); + assertThat(clubActivityDtoList.get(0).getTitle()).isEqualTo(clubActivity.getTitle()); + } + + @DisplayName("동아리 활동 생성 성공") + @Test + public void writeClubActivityTest_Success() { + // given + Long memberId = 1L; + Member member = MemberTest.chiefMember(); // 필요한 속성으로 Member 객체 초기화 + Menu menu = new Menu(mock(MenuGroup.class), 1, MenuType.ALBUM, "동아리 활동", "동아리 활동"); + SaveClubActivityDto saveClubActivityDto = new SaveClubActivityDto("title", "content", null); + + given(memberRepository.findById(memberId)).willReturn(Optional.of(member)); + given(menuRepository.findByName_Value(any())).willReturn(Optional.of(menu)); + given(clubActivityRepository.save(any(AlbumBoard.class))) + .willAnswer( + invocation -> { + AlbumBoard savedClubActivity = invocation.getArgument(0); + ReflectionTestUtils.setField(savedClubActivity, "id", 1L); + return savedClubActivity; + }); + + // when + Long resultId = clubActivityService.writeClubActivity(memberId, saveClubActivityDto); + + // then + assertThat(resultId).isEqualTo(1L); + } + + @DisplayName("동아리 활동 단일 조회 성공") + @Test + public void getClubActivityTest_Success() { + // given + AlbumBoard clubActivity = + AlbumBoard.builder() + .title("title") + .content("content") + .menu(mock(Menu.class)) + .build() + .writtenBy(MemberTest.chiefMember(), AlbumBoard.class); + + given(clubActivityRepository.findById(any())).willReturn(Optional.of(clubActivity)); + + // when + ClubActivityDetailDto clubActivityDetailDto = clubActivityService.getClubActivity(1L); + + // then + assertThat(clubActivityDetailDto) + .as("Title and content of clubActivityDetailDto are equal to clubActivity") + .extracting("title", "content") + .containsExactly(clubActivity.getTitle(), clubActivity.getContent()); + } + + @DisplayName("동아리 활동 수정 성공") + @Test + public void updateClubActivityTest_Success() { + // given + Member member = MemberTest.chiefMember(); + AlbumBoard clubActivity = + AlbumBoard.builder() + .title("title") + .content("content") + .menu(mock(Menu.class)) + .build() + .writtenBy(member, AlbumBoard.class); + ReflectionTestUtils.setField(clubActivity, "id", 1L); + SaveClubActivityDto saveClubActivityDto = new SaveClubActivityDto("title", "content", null); + given(clubActivityRepository.findById(any())).willReturn(Optional.ofNullable(clubActivity)); + given(clubActivityRepository.save(any())).willReturn(clubActivity); + + // when + clubActivityService.updateClubActivity(1L, saveClubActivityDto); + + // then + then(clubActivityRepository).should(times(1)).findById(any()); + then(clubActivityRepository).should(times(1)).save(any()); + } + + @DisplayName("동아리 활동 수정 실패 (file storage)") + @Test + public void updateClubActivityTest_FileStorage_Failed() { + // given + Member member = MemberTest.chiefMember(); + AlbumBoard clubActivity = + AlbumBoard.builder() + .title("title") + .content("content") + .menu(mock(Menu.class)) + .build() + .writtenBy(member, AlbumBoard.class); + MultipartFile file = mock(MultipartFile.class); + + SaveClubActivityDto saveClubActivityDto = + new SaveClubActivityDto("title", "content", List.of(file)); + given(clubActivityRepository.findById(any())).willReturn(Optional.of(clubActivity)); + given(s3Service.uploadS3File(any(), any())).willThrow(RuntimeException.class); + + // when, then + assertThatThrownBy(() -> clubActivityService.updateClubActivity(1L, saveClubActivityDto)) + .isInstanceOf(RuntimeException.class) + .hasMessage("파일 업로드를 실패했습니다."); + } + + @DisplayName("동아리 활동 삭제 성공") + @Test + public void deleteClubActivityTest_Success() { + // given + Long boardId = 1L; + doNothing().when(clubActivityRepository).deleteById(boardId); + + // when + clubActivityService.deleteClubActivity(boardId); + + // then + then(clubActivityRepository).should(times(1)).deleteById(boardId); + } +} diff --git a/resource-server/src/test/java/com/inhabas/api/domain/club/usecase/ClubHistoryServiceImplTest.java b/resource-server/src/test/java/com/inhabas/api/domain/club/usecase/ClubHistoryServiceImplTest.java index cb0bb032..6c834e11 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/club/usecase/ClubHistoryServiceImplTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/club/usecase/ClubHistoryServiceImplTest.java @@ -1,5 +1,20 @@ package com.inhabas.api.domain.club.usecase; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.assertj.core.api.Assertions.tuple; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.mockito.BDDMockito.then; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Optional; + +import org.springframework.data.domain.Sort; +import org.springframework.test.util.ReflectionTestUtils; +import org.springframework.transaction.annotation.Transactional; + import com.inhabas.api.auth.domain.error.businessException.NotFoundException; import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; import com.inhabas.api.auth.domain.oauth2.member.domain.exception.MemberNotFoundException; @@ -11,188 +26,171 @@ import com.inhabas.api.domain.club.dto.SaveClubHistoryDto; import com.inhabas.api.domain.club.repository.ClubHistoryRepository; import com.inhabas.api.domain.member.domain.entity.MemberTest; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import org.springframework.data.domain.Sort; -import org.springframework.test.util.ReflectionTestUtils; -import org.springframework.transaction.annotation.Transactional; -import java.time.LocalDateTime; -import java.util.List; -import java.util.Optional; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.assertj.core.api.Assertions.tuple; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.given; -import static org.mockito.BDDMockito.then; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; @ExtendWith(MockitoExtension.class) public class ClubHistoryServiceImplTest { - @InjectMocks - ClubHistoryServiceImpl clubHistoryService; - @Mock - ClubHistoryRepository clubHistoryRepository; - @Mock - MemberRepository memberRepository; - - - @DisplayName("동아리 연혁 생성 성공") - @Test - @Transactional - void writeClubHistory_Success() { - //given - Long memberId = 1L; - Member member = MemberTest.chiefMember(); // 필요한 속성으로 Member 객체 초기화 - SaveClubHistoryDto saveClubHistoryDto = new SaveClubHistoryDto( - "title", "content", LocalDateTime.now()); - - given(memberRepository.findById(memberId)).willReturn(Optional.of(member)); - given(clubHistoryRepository.save(any(ClubHistory.class))).willAnswer(invocation -> { - ClubHistory savedClubHistory = invocation.getArgument(0); - ReflectionTestUtils.setField(savedClubHistory, "id", 1L); - return savedClubHistory; - }); - - // when - Long resultId = clubHistoryService.writeClubHistory(memberId, saveClubHistoryDto); - - // then - then(memberRepository).should().findById(memberId); - then(clubHistoryRepository).should().save(any(ClubHistory.class)); - assertThat(resultId).isEqualTo(1L); - } - - @DisplayName("동아리 연혁 생성 작성자가 존재하지 않을 시 Member nof found") - @Test - void writeClubHistory_Member_Not_Found() { - //given - SaveClubHistoryDto saveClubHistoryDto = new SaveClubHistoryDto( - "title", "content", LocalDateTime.now()); - given(memberRepository.findById(any())).willReturn(Optional.empty()); - - // then - assertThatThrownBy(() -> clubHistoryService.writeClubHistory(1L, saveClubHistoryDto)) - .isInstanceOf(MemberNotFoundException.class) - .hasMessage("존재 하지 않는 유저입니다."); - - } - - @DisplayName("동아리 연혁 단일 조회 성공") - @Test - void findClubHistory_Success() { - //given - ClubHistory clubHistory = ClubHistory.builder() - .member(MemberTest.chiefMember()) - .title(new Title("title")) - .content(new Content("content")) - .dateHistory(LocalDateTime.now()) - .build(); - given(clubHistoryRepository.findById(any())).willReturn(Optional.of(clubHistory)); - - //when - ClubHistoryDto clubHistoryDto = clubHistoryService.findClubHistory(any()); - - //then - then(clubHistoryRepository).should().findById(any()); - assertThat(clubHistoryDto).as("clubHistoryDto's title and content are equal to clubHistory") - .extracting("title", "content") - .containsExactly(clubHistory.getTitle().getValue(), clubHistory.getContent().getValue()); - - } - - @DisplayName("동아리 연혁 단일 조회 id가 존재하지 않으면 NOT_FOUND") - @Test - void findClubHistory_Not_Found() { - //given - given(clubHistoryRepository.findById(any())).willReturn(Optional.empty()); - - //then - assertThatThrownBy(() -> clubHistoryService.findClubHistory(any())) - .isInstanceOf(NotFoundException.class) - .hasMessage("데이터가 존재하지 않습니다."); - - } - - @DisplayName("동아리 연혁 조회 성공") - @Test - void getClubHistories_Success() { - //given - ClubHistory clubHistory = ClubHistory.builder() - .member(MemberTest.chiefMember()) - .title(new Title("title")) - .content(new Content("content")) - .dateHistory(LocalDateTime.now()) - .build(); - List clubHistoryList = List.of(clubHistory); - - Sort sort = Sort.by(Sort.Direction.DESC, "dateHistory"); - given(clubHistoryRepository.findAll(sort)).willReturn(clubHistoryList); - - //when - List clubHistoryDtoList = clubHistoryService.getClubHistories(); - - //then - then(clubHistoryRepository).should().findAll(sort); - assertThat(clubHistoryDtoList) - .hasSize(1) - .extracting("title", "content") - .contains(tuple(clubHistory.getTitle().getValue(), clubHistory.getContent().getValue())); - - } - - @DisplayName("동아리 연혁 수정 성공") - @Test - @Transactional - void updateClubHistory_Success() { - // given - Member member = MemberTest.chiefMember(); - ClubHistory clubHistory = ClubHistory.builder() - .member(member) - .title(new Title("title")) - .content(new Content("content")) - .dateHistory(LocalDateTime.now()) - .build(); - SaveClubHistoryDto saveClubHistoryDto = new SaveClubHistoryDto( - "title", "content", LocalDateTime.now()); - given(clubHistoryRepository.findById(any())).willReturn(Optional.ofNullable(clubHistory)); - given(memberRepository.findById(any())).willReturn(Optional.of(member)); - - // when - clubHistoryService.updateClubHistory(1L, 1L, saveClubHistoryDto); - - // then - then(clubHistoryRepository).should().findById(any()); - then(memberRepository).should().findById(any()); - - } - - @DisplayName("동아리 연혁 삭제 성공") - @Test - @Transactional - void deleteClubHistories_Success() { - //given - ClubHistory clubHistory = ClubHistory.builder() - .member(MemberTest.chiefMember()) - .title(new Title("title")) - .content(new Content("content")) - .dateHistory(LocalDateTime.now()) - .build(); - given(clubHistoryRepository.findById(any())).willReturn(Optional.ofNullable(clubHistory)); - - //when - clubHistoryService.deleteClubHistory(any()); - - //then - then(clubHistoryRepository).should().findById(any()); - then(clubHistoryRepository).should().delete(any()); - - } - -} \ No newline at end of file + @InjectMocks ClubHistoryServiceImpl clubHistoryService; + @Mock ClubHistoryRepository clubHistoryRepository; + @Mock MemberRepository memberRepository; + + @DisplayName("동아리 연혁 생성 성공") + @Test + @Transactional + void writeClubHistory_Success() { + // given + Long memberId = 1L; + Member member = MemberTest.chiefMember(); // 필요한 속성으로 Member 객체 초기화 + SaveClubHistoryDto saveClubHistoryDto = + new SaveClubHistoryDto("title", "content", LocalDateTime.now()); + + given(memberRepository.findById(memberId)).willReturn(Optional.of(member)); + given(clubHistoryRepository.save(any(ClubHistory.class))) + .willAnswer( + invocation -> { + ClubHistory savedClubHistory = invocation.getArgument(0); + ReflectionTestUtils.setField(savedClubHistory, "id", 1L); + return savedClubHistory; + }); + + // when + Long resultId = clubHistoryService.writeClubHistory(memberId, saveClubHistoryDto); + + // then + then(memberRepository).should().findById(memberId); + then(clubHistoryRepository).should().save(any(ClubHistory.class)); + assertThat(resultId).isEqualTo(1L); + } + + @DisplayName("동아리 연혁 생성 작성자가 존재하지 않을 시 Member nof found") + @Test + void writeClubHistory_Member_Not_Found() { + // given + SaveClubHistoryDto saveClubHistoryDto = + new SaveClubHistoryDto("title", "content", LocalDateTime.now()); + given(memberRepository.findById(any())).willReturn(Optional.empty()); + + // then + assertThatThrownBy(() -> clubHistoryService.writeClubHistory(1L, saveClubHistoryDto)) + .isInstanceOf(MemberNotFoundException.class) + .hasMessage("존재 하지 않는 유저입니다."); + } + + @DisplayName("동아리 연혁 단일 조회 성공") + @Test + void findClubHistory_Success() { + // given + ClubHistory clubHistory = + ClubHistory.builder() + .member(MemberTest.chiefMember()) + .title(new Title("title")) + .content(new Content("content")) + .dateHistory(LocalDateTime.now()) + .build(); + given(clubHistoryRepository.findById(any())).willReturn(Optional.of(clubHistory)); + + // when + ClubHistoryDto clubHistoryDto = clubHistoryService.findClubHistory(any()); + + // then + then(clubHistoryRepository).should().findById(any()); + assertThat(clubHistoryDto) + .as("clubHistoryDto's title and content are equal to clubHistory") + .extracting("title", "content") + .containsExactly(clubHistory.getTitle().getValue(), clubHistory.getContent().getValue()); + } + + @DisplayName("동아리 연혁 단일 조회 id가 존재하지 않으면 NOT_FOUND") + @Test + void findClubHistory_Not_Found() { + // given + given(clubHistoryRepository.findById(any())).willReturn(Optional.empty()); + + // then + assertThatThrownBy(() -> clubHistoryService.findClubHistory(any())) + .isInstanceOf(NotFoundException.class) + .hasMessage("데이터가 존재하지 않습니다."); + } + + @DisplayName("동아리 연혁 조회 성공") + @Test + void getClubHistories_Success() { + // given + ClubHistory clubHistory = + ClubHistory.builder() + .member(MemberTest.chiefMember()) + .title(new Title("title")) + .content(new Content("content")) + .dateHistory(LocalDateTime.now()) + .build(); + List clubHistoryList = List.of(clubHistory); + + Sort sort = Sort.by(Sort.Direction.DESC, "dateHistory"); + given(clubHistoryRepository.findAll(sort)).willReturn(clubHistoryList); + + // when + List clubHistoryDtoList = clubHistoryService.getClubHistories(); + + // then + then(clubHistoryRepository).should().findAll(sort); + assertThat(clubHistoryDtoList) + .hasSize(1) + .extracting("title", "content") + .contains(tuple(clubHistory.getTitle().getValue(), clubHistory.getContent().getValue())); + } + + @DisplayName("동아리 연혁 수정 성공") + @Test + @Transactional + void updateClubHistory_Success() { + // given + Member member = MemberTest.chiefMember(); + ClubHistory clubHistory = + ClubHistory.builder() + .member(member) + .title(new Title("title")) + .content(new Content("content")) + .dateHistory(LocalDateTime.now()) + .build(); + SaveClubHistoryDto saveClubHistoryDto = + new SaveClubHistoryDto("title", "content", LocalDateTime.now()); + given(clubHistoryRepository.findById(any())).willReturn(Optional.ofNullable(clubHistory)); + given(memberRepository.findById(any())).willReturn(Optional.of(member)); + + // when + clubHistoryService.updateClubHistory(1L, 1L, saveClubHistoryDto); + + // then + then(clubHistoryRepository).should().findById(any()); + then(memberRepository).should().findById(any()); + } + + @DisplayName("동아리 연혁 삭제 성공") + @Test + @Transactional + void deleteClubHistories_Success() { + // given + ClubHistory clubHistory = + ClubHistory.builder() + .member(MemberTest.chiefMember()) + .title(new Title("title")) + .content(new Content("content")) + .dateHistory(LocalDateTime.now()) + .build(); + given(clubHistoryRepository.findById(any())).willReturn(Optional.ofNullable(clubHistory)); + + // when + clubHistoryService.deleteClubHistory(any()); + + // then + then(clubHistoryRepository).should().findById(any()); + then(clubHistoryRepository).should().delete(any()); + } +} diff --git a/resource-server/src/test/java/com/inhabas/api/domain/comment/domain/CommentTest.java b/resource-server/src/test/java/com/inhabas/api/domain/comment/domain/CommentTest.java index 45171e75..f79eb536 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/comment/domain/CommentTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/comment/domain/CommentTest.java @@ -1,95 +1,91 @@ package com.inhabas.api.domain.comment.domain; +import static org.mockito.Mockito.mock; + +import org.springframework.test.util.ReflectionTestUtils; + import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; import com.inhabas.api.domain.board.domain.BaseBoard; import com.inhabas.api.domain.member.domain.entity.MemberTest; import org.assertj.core.api.Assertions; + import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import org.springframework.test.util.ReflectionTestUtils; - -import static org.mockito.Mockito.mock; public class CommentTest { - private Comment rootComment; - - @BeforeEach - void setUp() { - rootComment = new Comment("content", - mock(Member.class), mock(BaseBoard.class)); - } - - @DisplayName("생성자로 객체를 생성한다.") - @Test - void constructorTest() { - //given - String content = "content"; - Member member = MemberTest.chiefMember(); - BaseBoard baseBoard = mock(BaseBoard.class); - - //when - Comment comment = new Comment(content, member, baseBoard); - - //then - Assertions.assertThat(comment.getContent()).isEqualTo(content); - - } - - @DisplayName("작성자가 댓글 내용을 수정한다.") - @Test - void updateTest() { - //given - String content = "content"; - Member member = MemberTest.chiefMember(); - ReflectionTestUtils.setField(member, "id", 1L); - BaseBoard baseBoard = mock(BaseBoard.class); - - Comment comment = new Comment(content, member, baseBoard); - - //when - final String newContent = "new content"; - comment.update(newContent); - - //then - Assertions.assertThat(comment.getContent()).isEqualTo(newContent); - - } - - @DisplayName("rootComment 의 대댓글을 작성한다.") - @Test - void replyToTest() { - //given - String content = "content"; - Member member = MemberTest.chiefMember(); - BaseBoard baseBoard = mock(BaseBoard.class); - Comment comment = new Comment(content, member, baseBoard); - - //when - comment.replyTo(rootComment); - - //then - Assertions.assertThat(rootComment.getChildrenComment()).contains(comment); - - } - - @DisplayName("작성자와의 id와 동일한지 확인한다.") - @Test - void isWrittenByTest() { - //given - String content = "content"; - Member member = MemberTest.chiefMember(); - BaseBoard baseBoard = mock(BaseBoard.class); - ReflectionTestUtils.setField(member, "id", 1L); - Comment comment = new Comment(content, member, baseBoard); - - //when - boolean mustTrue = comment.isWrittenBy(1L); - - //then - Assertions.assertThat(mustTrue).isTrue(); - - } - -} \ No newline at end of file + private Comment rootComment; + + @BeforeEach + void setUp() { + rootComment = new Comment("content", mock(Member.class), mock(BaseBoard.class)); + } + + @DisplayName("생성자로 객체를 생성한다.") + @Test + void constructorTest() { + // given + String content = "content"; + Member member = MemberTest.chiefMember(); + BaseBoard baseBoard = mock(BaseBoard.class); + + // when + Comment comment = new Comment(content, member, baseBoard); + + // then + Assertions.assertThat(comment.getContent()).isEqualTo(content); + } + + @DisplayName("작성자가 댓글 내용을 수정한다.") + @Test + void updateTest() { + // given + String content = "content"; + Member member = MemberTest.chiefMember(); + ReflectionTestUtils.setField(member, "id", 1L); + BaseBoard baseBoard = mock(BaseBoard.class); + + Comment comment = new Comment(content, member, baseBoard); + + // when + final String newContent = "new content"; + comment.update(newContent); + + // then + Assertions.assertThat(comment.getContent()).isEqualTo(newContent); + } + + @DisplayName("rootComment 의 대댓글을 작성한다.") + @Test + void replyToTest() { + // given + String content = "content"; + Member member = MemberTest.chiefMember(); + BaseBoard baseBoard = mock(BaseBoard.class); + Comment comment = new Comment(content, member, baseBoard); + + // when + comment.replyTo(rootComment); + + // then + Assertions.assertThat(rootComment.getChildrenComment()).contains(comment); + } + + @DisplayName("작성자와의 id와 동일한지 확인한다.") + @Test + void isWrittenByTest() { + // given + String content = "content"; + Member member = MemberTest.chiefMember(); + BaseBoard baseBoard = mock(BaseBoard.class); + ReflectionTestUtils.setField(member, "id", 1L); + Comment comment = new Comment(content, member, baseBoard); + + // when + boolean mustTrue = comment.isWrittenBy(1L); + + // then + Assertions.assertThat(mustTrue).isTrue(); + } +} diff --git a/resource-server/src/test/java/com/inhabas/api/domain/comment/domain/valueObject/CommentContentTest.java b/resource-server/src/test/java/com/inhabas/api/domain/comment/domain/valueObject/CommentContentTest.java index 6ec357ef..51ab3bd6 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/comment/domain/valueObject/CommentContentTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/comment/domain/valueObject/CommentContentTest.java @@ -1,64 +1,61 @@ package com.inhabas.api.domain.comment.domain.valueObject; -import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; - import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -public class CommentContentTest { - - @DisplayName("Content 타입에 내용을 저장한다.") - @Test - public void Content_is_saved_well() { - //given - String contentString = "날씨 너무 좋지 않아? 개발하기 딱 좋은 날씨야! 같이 개발할래? 야 너두 할 수 있어"; - - //when - Content content = new Content(contentString); - - //then - assertThat(content.getValue()).isEqualTo(contentString); - - } - - @DisplayName("Content 타입에 너무 긴 내용을 입력한다. 500자 이상") - @Test - public void Content_is_too_long() { - //given - String longContent = "지금이문장은10자임".repeat(50); - - //then - assertThatThrownBy(() -> new Content(longContent)) - .isInstanceOf(InvalidInputException.class) - .hasMessage("입력값이 없거나, 타입이 유효하지 않습니다."); - - } - - @DisplayName("Content 타입에 null 은 안된다.") - @Test - public void Content_is_Null() { - //given - String nullContent = null; - - //then - assertThatThrownBy(() -> new Content(nullContent)) - .isInstanceOf(InvalidInputException.class) - .hasMessage("입력값이 없거나, 타입이 유효하지 않습니다."); - - } +import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; - @DisplayName("Content 타입에 공백댓글은 저장할 수 없다.") - @Test - public void Content_is_Blank() { - //given - String blankContent = " "; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; - //then - assertThatThrownBy(() -> new Content(blankContent)) - .isInstanceOf(InvalidInputException.class) - .hasMessage("입력값이 없거나, 타입이 유효하지 않습니다."); +public class CommentContentTest { - } + @DisplayName("Content 타입에 내용을 저장한다.") + @Test + public void Content_is_saved_well() { + // given + String contentString = "날씨 너무 좋지 않아? 개발하기 딱 좋은 날씨야! 같이 개발할래? 야 너두 할 수 있어"; + + // when + Content content = new Content(contentString); + + // then + assertThat(content.getValue()).isEqualTo(contentString); + } + + @DisplayName("Content 타입에 너무 긴 내용을 입력한다. 500자 이상") + @Test + public void Content_is_too_long() { + // given + String longContent = "지금이문장은10자임".repeat(50); + + // then + assertThatThrownBy(() -> new Content(longContent)) + .isInstanceOf(InvalidInputException.class) + .hasMessage("입력값이 없거나, 타입이 유효하지 않습니다."); + } + + @DisplayName("Content 타입에 null 은 안된다.") + @Test + public void Content_is_Null() { + // given + String nullContent = null; + + // then + assertThatThrownBy(() -> new Content(nullContent)) + .isInstanceOf(InvalidInputException.class) + .hasMessage("입력값이 없거나, 타입이 유효하지 않습니다."); + } + + @DisplayName("Content 타입에 공백댓글은 저장할 수 없다.") + @Test + public void Content_is_Blank() { + // given + String blankContent = " "; + + // then + assertThatThrownBy(() -> new Content(blankContent)) + .isInstanceOf(InvalidInputException.class) + .hasMessage("입력값이 없거나, 타입이 유효하지 않습니다."); + } } diff --git a/resource-server/src/test/java/com/inhabas/api/domain/comment/repository/CommentRepositoryTest.java b/resource-server/src/test/java/com/inhabas/api/domain/comment/repository/CommentRepositoryTest.java index ac32405e..e4784207 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/comment/repository/CommentRepositoryTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/comment/repository/CommentRepositoryTest.java @@ -1,5 +1,15 @@ package com.inhabas.api.domain.comment.repository; +import static com.inhabas.api.domain.member.domain.entity.MemberTest.basicMember1; +import static com.inhabas.api.domain.member.domain.entity.MemberTest.basicMember2; +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager; +import org.springframework.transaction.annotation.Transactional; + import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; import com.inhabas.api.domain.board.domain.AlbumBoard; import com.inhabas.api.domain.board.domain.valueObject.AlbumExampleTest; @@ -9,162 +19,142 @@ import com.inhabas.api.domain.menu.domain.MenuGroup; import com.inhabas.api.domain.menu.domain.valueObject.MenuType; import com.inhabas.testAnnotataion.DefaultDataJpaTest; + 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.boot.test.autoconfigure.orm.jpa.TestEntityManager; -import org.springframework.transaction.annotation.Transactional; - -import java.util.List; - -import static com.inhabas.api.domain.member.domain.entity.MemberTest.basicMember1; -import static com.inhabas.api.domain.member.domain.entity.MemberTest.basicMember2; -import static org.assertj.core.api.Assertions.assertThat; @DefaultDataJpaTest public class CommentRepositoryTest { - @Autowired - CommentRepository commentRepository; - @Autowired - TestEntityManager em; - - Member boardWriter, commentWriter; - AlbumBoard albumBoard; - Menu menu; - MenuGroup menuGroup; - - - @BeforeEach - public void setUp() { - - MenuGroup newMenuGroup = new MenuGroup("IBAS"); - menuGroup = em.persist(newMenuGroup); - Menu newMenu = new Menu(menuGroup, 2, MenuType.ALBUM, "동아리 활동", "설명"); - menu = em.persist(newMenu); - - boardWriter = em.persist(basicMember1()); - commentWriter = em.persist(basicMember2()); - albumBoard = em.persist( - AlbumExampleTest.getAlbumBoard1(menu) - .writtenBy(boardWriter, AlbumBoard.class) - ); - - - } - - @DisplayName("작성한 댓글과 저장된 댓글이 같다.") - @Test - @Transactional - public void Success_Save_Comment() { - //given - Comment newComment = new Comment("필력 좋다 쓴이야", commentWriter, albumBoard); - - //when - Comment saveComment = commentRepository.save(newComment); - em.clear(); - - //then - assertThat(saveComment.getContent()).isEqualTo("필력 좋다 쓴이야"); - assertThat(saveComment.getParentBoard().getId()).isEqualTo(albumBoard.getId()); - - } - - @DisplayName("대댓글을 성공적으로 등록한다.") - @Test - public void Success_Save_Reply() { - //given - Comment comment = new Comment("필력 좋다 쓴이야", commentWriter, albumBoard); - commentRepository.save(comment); - em.clear(); - - //when - Comment reply = new Comment("익1 고마워", boardWriter, albumBoard).replyTo(comment); - Comment savedReply = commentRepository.save(reply); - - //then - assertThat(savedReply.getContent()).isEqualTo("익1 고마워"); - assertThat(savedReply.getParentBoard().getId()).isEqualTo(albumBoard.getId()); - assertThat(savedReply.getParentComment().getId()).isEqualTo(comment.getId()); - - } - - @DisplayName("게시글의 모든 댓글을 계층 구조로 가져온다.") - @Test - public void Hierarchical_Comment_List() { - //given - // 댓글을 달았다. - Comment comment1 = new Comment("1) 필력 좋다 쓴이야", commentWriter, albumBoard); - commentRepository.save(comment1); - - // 대댓글을 달았다. - Comment reply1 = new Comment("1-1) 고마워", boardWriter, albumBoard).replyTo(comment1); - commentRepository.save(reply1); - - // 댓글을 달았다. - Comment comment2 = new Comment("2) 쓴이야 분발하자", commentWriter, albumBoard); - commentRepository.save(comment2); - - // 대댓글을 달았다. - Comment reply2_1 = new Comment("2-1) 너 누구야?", boardWriter, albumBoard).replyTo(comment2); - commentRepository.save(reply2_1); - - // 대대댓글을 달았다. - Comment reply2_2 = new Comment("2-2) 나? 김첨지", commentWriter, albumBoard).replyTo(reply2_1); - commentRepository.save(reply2_2); - em.clear(); - - //when - List commentList = commentRepository.findAllByParentBoardIdOrderByCreated(albumBoard.getId()); - - - //then - assertThat(commentList.size()).isEqualTo(2); // 루트 댓글은 2 개이다. - - // 첫번째 루트 댓글 - assertThat(commentList.get(0).getContent()).isEqualTo(comment1.getContent()); - // 첫번째 루트 댓글의 대댓글은 1개 - assertThat(commentList.get(0).getChildrenComment()) - .hasSize(1) - .extracting(CommentDetailDto::getContent) - .contains(reply1.getContent()); - - // 두번째 루트 댓글 - assertThat(commentList.get(1).getContent()).isEqualTo(comment2.getContent()); - // 두번째 루트 댓글의 대댓글은 1개 - assertThat(commentList.get(1).getChildrenComment()) - .hasSize(1) - .extracting(CommentDetailDto::getContent) - .containsExactly(reply2_1.getContent()); - - } - - @DisplayName("게시판이 삭제되면 해당 댓글이 모두 삭제된다.") - @Test - public void Remove_Board_Then_All_The_Comments_Of_The_Board_Are_Gone() { - //given - Comment comment = new Comment("root) 첫 댓글", commentWriter, albumBoard); - commentRepository.save(comment); - - Comment reply_1 = new Comment("reply1) 대댓글1", boardWriter, albumBoard).replyTo(comment); - commentRepository.save(reply_1); - - Comment reply_2 = new Comment("reply2) 대댓글2", commentWriter, albumBoard).replyTo(comment); - commentRepository.save(reply_2); - - Comment reply_3 = new Comment("reply3) 대댓글3", commentWriter, albumBoard).replyTo(comment); - commentRepository.save(reply_3); - em.clear(); - - //when - albumBoard = em.find(AlbumBoard.class, albumBoard.getId()); - em.remove(albumBoard); - - //then - List all = commentRepository.findAll(); - assertThat(all).hasSize(0); - - } - + @Autowired CommentRepository commentRepository; + @Autowired TestEntityManager em; + + Member boardWriter, commentWriter; + AlbumBoard albumBoard; + Menu menu; + MenuGroup menuGroup; + + @BeforeEach + public void setUp() { + + MenuGroup newMenuGroup = new MenuGroup("IBAS"); + menuGroup = em.persist(newMenuGroup); + Menu newMenu = new Menu(menuGroup, 2, MenuType.ALBUM, "동아리 활동", "설명"); + menu = em.persist(newMenu); + + boardWriter = em.persist(basicMember1()); + commentWriter = em.persist(basicMember2()); + albumBoard = + em.persist(AlbumExampleTest.getAlbumBoard1(menu).writtenBy(boardWriter, AlbumBoard.class)); + } + + @DisplayName("작성한 댓글과 저장된 댓글이 같다.") + @Test + @Transactional + public void Success_Save_Comment() { + // given + Comment newComment = new Comment("필력 좋다 쓴이야", commentWriter, albumBoard); + + // when + Comment saveComment = commentRepository.save(newComment); + em.clear(); + + // then + assertThat(saveComment.getContent()).isEqualTo("필력 좋다 쓴이야"); + assertThat(saveComment.getParentBoard().getId()).isEqualTo(albumBoard.getId()); + } + + @DisplayName("대댓글을 성공적으로 등록한다.") + @Test + public void Success_Save_Reply() { + // given + Comment comment = new Comment("필력 좋다 쓴이야", commentWriter, albumBoard); + commentRepository.save(comment); + em.clear(); + + // when + Comment reply = new Comment("익1 고마워", boardWriter, albumBoard).replyTo(comment); + Comment savedReply = commentRepository.save(reply); + + // then + assertThat(savedReply.getContent()).isEqualTo("익1 고마워"); + assertThat(savedReply.getParentBoard().getId()).isEqualTo(albumBoard.getId()); + assertThat(savedReply.getParentComment().getId()).isEqualTo(comment.getId()); + } + + @DisplayName("게시글의 모든 댓글을 계층 구조로 가져온다.") + @Test + public void Hierarchical_Comment_List() { + // given + // 댓글을 달았다. + Comment comment1 = new Comment("1) 필력 좋다 쓴이야", commentWriter, albumBoard); + commentRepository.save(comment1); + + // 대댓글을 달았다. + Comment reply1 = new Comment("1-1) 고마워", boardWriter, albumBoard).replyTo(comment1); + commentRepository.save(reply1); + + // 댓글을 달았다. + Comment comment2 = new Comment("2) 쓴이야 분발하자", commentWriter, albumBoard); + commentRepository.save(comment2); + + // 대댓글을 달았다. + Comment reply2_1 = new Comment("2-1) 너 누구야?", boardWriter, albumBoard).replyTo(comment2); + commentRepository.save(reply2_1); + + // 대대댓글을 달았다. + Comment reply2_2 = new Comment("2-2) 나? 김첨지", commentWriter, albumBoard).replyTo(reply2_1); + commentRepository.save(reply2_2); + em.clear(); + + // when + List commentList = + commentRepository.findAllByParentBoardIdOrderByCreated(albumBoard.getId()); + + // then + assertThat(commentList.size()).isEqualTo(2); // 루트 댓글은 2 개이다. + + // 첫번째 루트 댓글 + assertThat(commentList.get(0).getContent()).isEqualTo(comment1.getContent()); + // 첫번째 루트 댓글의 대댓글은 1개 + assertThat(commentList.get(0).getChildrenComment()) + .hasSize(1) + .extracting(CommentDetailDto::getContent) + .contains(reply1.getContent()); + + // 두번째 루트 댓글 + assertThat(commentList.get(1).getContent()).isEqualTo(comment2.getContent()); + // 두번째 루트 댓글의 대댓글은 1개 + assertThat(commentList.get(1).getChildrenComment()) + .hasSize(1) + .extracting(CommentDetailDto::getContent) + .containsExactly(reply2_1.getContent()); + } + + @DisplayName("게시판이 삭제되면 해당 댓글이 모두 삭제된다.") + @Test + public void Remove_Board_Then_All_The_Comments_Of_The_Board_Are_Gone() { + // given + Comment comment = new Comment("root) 첫 댓글", commentWriter, albumBoard); + commentRepository.save(comment); + + Comment reply_1 = new Comment("reply1) 대댓글1", boardWriter, albumBoard).replyTo(comment); + commentRepository.save(reply_1); + + Comment reply_2 = new Comment("reply2) 대댓글2", commentWriter, albumBoard).replyTo(comment); + commentRepository.save(reply_2); + + Comment reply_3 = new Comment("reply3) 대댓글3", commentWriter, albumBoard).replyTo(comment); + commentRepository.save(reply_3); + em.clear(); + + // when + albumBoard = em.find(AlbumBoard.class, albumBoard.getId()); + em.remove(albumBoard); + + // then + List all = commentRepository.findAll(); + assertThat(all).hasSize(0); + } } diff --git a/resource-server/src/test/java/com/inhabas/api/domain/comment/usecase/CommentServiceTest.java b/resource-server/src/test/java/com/inhabas/api/domain/comment/usecase/CommentServiceTest.java index 11d60d9f..303a526f 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/comment/usecase/CommentServiceTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/comment/usecase/CommentServiceTest.java @@ -1,5 +1,18 @@ package com.inhabas.api.domain.comment.usecase; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +import java.util.Optional; + +import javax.persistence.EntityManager; + +import org.springframework.test.util.ReflectionTestUtils; + import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; import com.inhabas.api.domain.board.domain.AlbumBoard; import com.inhabas.api.domain.board.domain.BaseBoard; @@ -13,152 +26,134 @@ import com.inhabas.api.domain.menu.domain.MenuExampleTest; import com.inhabas.api.domain.menu.domain.MenuGroup; import com.inhabas.api.domain.menu.domain.valueObject.MenuGroupExampleTest; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import org.springframework.test.util.ReflectionTestUtils; - -import javax.persistence.EntityManager; -import java.util.Optional; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatCode; -import static org.mockito.ArgumentMatchers.*; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; @ExtendWith(MockitoExtension.class) public class CommentServiceTest { - @Mock - private CommentRepository commentRepository; - @Mock - private EntityManager em; - - @InjectMocks - private CommentServiceImpl commentService; - - private Member proxyWriter; - private Menu proxyMenu; - private MenuGroup proxyMenuGroup; - private AlbumBoard proxyBoard; - - @BeforeEach - public void setUpMocking() { - proxyWriter = MemberTest.getTestBasicMember("12171652"); - ReflectionTestUtils.setField(proxyWriter, "id", 1L); - proxyMenuGroup = MenuGroupExampleTest.getMenuGroup1(); - ReflectionTestUtils.setField(proxyMenuGroup, "id", 1); - proxyMenu = MenuExampleTest.getMenu1(proxyMenuGroup); - ReflectionTestUtils.setField(proxyMenu, "id", 1); - proxyBoard = AlbumExampleTest.getAlbumBoard1(proxyMenu); - ReflectionTestUtils.setField(proxyBoard, "id", 1L); - } - - @DisplayName("새로운 댓글을 저장한다.") - @Test - public void SaveNewCommentTest() { - - //mocking - Comment comment = new Comment("이야 이게 댓글 기능이라고??", proxyWriter, proxyBoard); - ReflectionTestUtils.setField(comment, "id", 1L); - given(em.getReference(eq(Member.class), any())).willReturn(proxyWriter); - given(em.getReference(eq(BaseBoard.class), any())).willReturn(proxyBoard); - given(commentRepository.save(any(Comment.class))).willReturn(comment); - - //given - CommentSaveDto newCommentCreateRequest = new CommentSaveDto("이야 이게 댓글 기능이라고??", null); - - //when - Long returnId = commentService.create(newCommentCreateRequest, proxyMenu.getId(), - proxyBoard.getId(), proxyWriter.getId()); - - //then - assertThat(returnId).isNotNull(); - verify(commentRepository, times(1)) - .save(any(Comment.class)); - - } - - @DisplayName("대댓글을 성공적으로 등록한다.") - @Test - public void createReply() { - //mocking - Comment parentComment = new Comment("댓글이 잘 써지네요", proxyWriter, proxyBoard); - Comment reply = new Comment("이야 이게 댓글 기능이라고??", proxyWriter, proxyBoard); - ReflectionTestUtils.setField(parentComment, "id", 1L); - ReflectionTestUtils.setField(reply, "id", 2L); - given(em.getReference(eq(Member.class), any())).willReturn(proxyWriter); - given(em.getReference(eq(BaseBoard.class), any())).willReturn(proxyBoard); - given(em.getReference(eq(Comment.class), any())).willReturn(parentComment); - given(commentRepository.save(any(Comment.class))).willReturn(reply); - - //given - CommentSaveDto newCommentCreateRequest = new CommentSaveDto("이야 이게 댓글 기능이라고??", 1L); - - //when - Long returnId = commentService.create(newCommentCreateRequest, proxyMenu.getId(), - proxyBoard.getId(), proxyWriter.getId()); - - //then - assertThat(returnId).isEqualTo(2); - verify(commentRepository, times(1)) - .save(any(Comment.class)); - - } - - @DisplayName("댓글을 성공적으로 수정한다.") - @Test - public void UpdateCommentTest() { - //mocking - Long commentId = 1L; - given(commentRepository.findById(commentId)) - .willReturn(expectedCommentAfterFind(commentId, proxyWriter, proxyBoard)); - - //given - CommentUpdateDto commentUpdateDto = new CommentUpdateDto("내용 수정 좀 할게요."); - - //when - Long returnId = commentService.update(commentId, commentUpdateDto); - - //then - assertThat(returnId).isNotNull(); - } - - private Optional expectedCommentAfterFind(Long commentId, Member proxyWriter, BaseBoard proxyBoard) { - Comment comment = new Comment("이야 이게 댓글 기능이라고??", proxyWriter, proxyBoard); - ReflectionTestUtils.setField(comment, "id", commentId); - - return Optional.of(comment); - } - - @DisplayName("댓글 리스트를 찾는 메소드를 호출한다.") - @Test - public void getComments() { - //when - commentService.getComments(proxyBoard.getMenu().getId(), proxyBoard.getId()); - - //then - verify(commentRepository, times(1)) - .findAllByParentBoardIdOrderByCreated(proxyBoard.getId()); - } - - @DisplayName("댓글을 성공적으로 삭제한다.") - @Test - public void deleteComment() { - //given - given(commentRepository.findById(anyLong())) - .willReturn(expectedCommentAfterFind(1L, proxyWriter, proxyBoard)); - - //when then - assertThatCode(() -> commentService.delete(1L)) - .doesNotThrowAnyException(); - - } - + @Mock private CommentRepository commentRepository; + @Mock private EntityManager em; + + @InjectMocks private CommentServiceImpl commentService; + + private Member proxyWriter; + private Menu proxyMenu; + private MenuGroup proxyMenuGroup; + private AlbumBoard proxyBoard; + + @BeforeEach + public void setUpMocking() { + proxyWriter = MemberTest.getTestBasicMember("12171652"); + ReflectionTestUtils.setField(proxyWriter, "id", 1L); + proxyMenuGroup = MenuGroupExampleTest.getMenuGroup1(); + ReflectionTestUtils.setField(proxyMenuGroup, "id", 1); + proxyMenu = MenuExampleTest.getMenu1(proxyMenuGroup); + ReflectionTestUtils.setField(proxyMenu, "id", 1); + proxyBoard = AlbumExampleTest.getAlbumBoard1(proxyMenu); + ReflectionTestUtils.setField(proxyBoard, "id", 1L); + } + + @DisplayName("새로운 댓글을 저장한다.") + @Test + public void SaveNewCommentTest() { + + // mocking + Comment comment = new Comment("이야 이게 댓글 기능이라고??", proxyWriter, proxyBoard); + ReflectionTestUtils.setField(comment, "id", 1L); + given(em.getReference(eq(Member.class), any())).willReturn(proxyWriter); + given(em.getReference(eq(BaseBoard.class), any())).willReturn(proxyBoard); + given(commentRepository.save(any(Comment.class))).willReturn(comment); + + // given + CommentSaveDto newCommentCreateRequest = new CommentSaveDto("이야 이게 댓글 기능이라고??", null); + + // when + Long returnId = + commentService.create( + newCommentCreateRequest, proxyMenu.getId(), proxyBoard.getId(), proxyWriter.getId()); + + // then + assertThat(returnId).isNotNull(); + verify(commentRepository, times(1)).save(any(Comment.class)); + } + + @DisplayName("대댓글을 성공적으로 등록한다.") + @Test + public void createReply() { + // mocking + Comment parentComment = new Comment("댓글이 잘 써지네요", proxyWriter, proxyBoard); + Comment reply = new Comment("이야 이게 댓글 기능이라고??", proxyWriter, proxyBoard); + ReflectionTestUtils.setField(parentComment, "id", 1L); + ReflectionTestUtils.setField(reply, "id", 2L); + given(em.getReference(eq(Member.class), any())).willReturn(proxyWriter); + given(em.getReference(eq(BaseBoard.class), any())).willReturn(proxyBoard); + given(em.getReference(eq(Comment.class), any())).willReturn(parentComment); + given(commentRepository.save(any(Comment.class))).willReturn(reply); + + // given + CommentSaveDto newCommentCreateRequest = new CommentSaveDto("이야 이게 댓글 기능이라고??", 1L); + + // when + Long returnId = + commentService.create( + newCommentCreateRequest, proxyMenu.getId(), proxyBoard.getId(), proxyWriter.getId()); + + // then + assertThat(returnId).isEqualTo(2); + verify(commentRepository, times(1)).save(any(Comment.class)); + } + + @DisplayName("댓글을 성공적으로 수정한다.") + @Test + public void UpdateCommentTest() { + // mocking + Long commentId = 1L; + given(commentRepository.findById(commentId)) + .willReturn(expectedCommentAfterFind(commentId, proxyWriter, proxyBoard)); + + // given + CommentUpdateDto commentUpdateDto = new CommentUpdateDto("내용 수정 좀 할게요."); + + // when + Long returnId = commentService.update(commentId, commentUpdateDto); + + // then + assertThat(returnId).isNotNull(); + } + + private Optional expectedCommentAfterFind( + Long commentId, Member proxyWriter, BaseBoard proxyBoard) { + Comment comment = new Comment("이야 이게 댓글 기능이라고??", proxyWriter, proxyBoard); + ReflectionTestUtils.setField(comment, "id", commentId); + + return Optional.of(comment); + } + + @DisplayName("댓글 리스트를 찾는 메소드를 호출한다.") + @Test + public void getComments() { + // when + commentService.getComments(proxyBoard.getMenu().getId(), proxyBoard.getId()); + + // then + verify(commentRepository, times(1)).findAllByParentBoardIdOrderByCreated(proxyBoard.getId()); + } + + @DisplayName("댓글을 성공적으로 삭제한다.") + @Test + public void deleteComment() { + // given + given(commentRepository.findById(anyLong())) + .willReturn(expectedCommentAfterFind(1L, proxyWriter, proxyBoard)); + + // when then + assertThatCode(() -> commentService.delete(1L)).doesNotThrowAnyException(); + } } diff --git a/resource-server/src/test/java/com/inhabas/api/domain/contestBoard/ContestBoardTest.java b/resource-server/src/test/java/com/inhabas/api/domain/contestBoard/ContestBoardTest.java index 82f05eb1..bf836a7a 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/contestBoard/ContestBoardTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/contestBoard/ContestBoardTest.java @@ -1,40 +1,40 @@ package com.inhabas.api.domain.contestBoard; -import com.inhabas.api.domain.contest.domain.ContestBoard; - import java.time.LocalDate; +import com.inhabas.api.domain.contest.domain.ContestBoard; + public class ContestBoardTest { - public static ContestBoard getContestBoard1(){ - return ContestBoard.builder() - .title("공공데이터 개방, 활용 가속화 해커톤") - .contents("[공개해] 공공데이터 개방‧활용 가속화 해커톤 / 해커톤 내용은 다음과 같습니다. Pol, a bene parma, raptus vita") - .association("행정안전부/NIA/㈜씨에이에스") - .topic("공공데이터 포털(www.data.go.kr)에 개방된 데이터 및 API를 활용한 아이디어 기획 및 서비스 개발") - .start(LocalDate.of(2022, 1, 1)) - .deadline(LocalDate.of(2022, 3, 1)) - .build(); - } + public static ContestBoard getContestBoard1() { + return ContestBoard.builder() + .title("공공데이터 개방, 활용 가속화 해커톤") + .contents("[공개해] 공공데이터 개방‧활용 가속화 해커톤 / 해커톤 내용은 다음과 같습니다. Pol, a bene parma, raptus vita") + .association("행정안전부/NIA/㈜씨에이에스") + .topic("공공데이터 포털(www.data.go.kr)에 개방된 데이터 및 API를 활용한 아이디어 기획 및 서비스 개발") + .start(LocalDate.of(2022, 1, 1)) + .deadline(LocalDate.of(2022, 3, 1)) + .build(); + } - public static ContestBoard getContestBoard2(){ - return ContestBoard.builder() - .title("This is title") - .contents("This is contest") - .association("This is association") - .topic("This is topic") - .start(LocalDate.of(2022, 1, 1)) - .deadline(LocalDate.of(2022, 3, 20)) - .build(); - } + public static ContestBoard getContestBoard2() { + return ContestBoard.builder() + .title("This is title") + .contents("This is contest") + .association("This is association") + .topic("This is topic") + .start(LocalDate.of(2022, 1, 1)) + .deadline(LocalDate.of(2022, 3, 20)) + .build(); + } - public static ContestBoard getContestBoard3() { - return ContestBoard.builder() - .title("조선/해양산업 디지털 혁신을 위한 BIG DATA / AI 대학생 경진대회") - .contents("■ 1차 서류 접수 기간 : 2020년 12월 14(월) - 2020년 12월 21(목)\n") - .association("현대 중공업 그룹") - .topic("빅데이터/AI") - .start(LocalDate.of(2022, 1, 4)) - .deadline(LocalDate.of(2022, 2, 25)) - .build(); - } + public static ContestBoard getContestBoard3() { + return ContestBoard.builder() + .title("조선/해양산업 디지털 혁신을 위한 BIG DATA / AI 대학생 경진대회") + .contents("■ 1차 서류 접수 기간 : 2020년 12월 14(월) - 2020년 12월 21(목)\n") + .association("현대 중공업 그룹") + .topic("빅데이터/AI") + .start(LocalDate.of(2022, 1, 4)) + .deadline(LocalDate.of(2022, 2, 25)) + .build(); + } } diff --git a/resource-server/src/test/java/com/inhabas/api/domain/contestBoard/dto/SaveContestBoardDtoTest.java b/resource-server/src/test/java/com/inhabas/api/domain/contestBoard/dto/SaveContestBoardDtoTest.java index 7d92d38f..23beb1d3 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/contestBoard/dto/SaveContestBoardDtoTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/contestBoard/dto/SaveContestBoardDtoTest.java @@ -1,126 +1,134 @@ package com.inhabas.api.domain.contestBoard.dto; -import com.inhabas.api.domain.contest.dto.SaveContestBoardDto; -import org.junit.jupiter.api.*; +import static org.assertj.core.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; -import javax.validation.ConstraintViolation; -import javax.validation.Validation; -import javax.validation.Validator; -import javax.validation.ValidatorFactory; import java.time.LocalDate; import java.util.ArrayList; import java.util.List; import java.util.Set; -import static org.assertj.core.api.Assertions.*; -import static org.junit.jupiter.api.Assertions.assertEquals; +import javax.validation.ConstraintViolation; +import javax.validation.Validation; +import javax.validation.Validator; +import javax.validation.ValidatorFactory; + +import com.inhabas.api.domain.contest.dto.SaveContestBoardDto; +import org.junit.jupiter.api.*; public class SaveContestBoardDtoTest { - private static ValidatorFactory validatorFactory; - private static Validator validator; - - @BeforeAll - public static void init() { - validatorFactory = Validation.buildDefaultValidatorFactory(); - validator = validatorFactory.getValidator(); - - } - - @AfterAll - public static void close() { - validatorFactory.close(); - } - - @DisplayName("공모전 게시글 저장 시 모든 필드가 null일 경우") - @Test - public void FieldsAreNullError() { - //given - SaveContestBoardDto saveContestBoardDto = new SaveContestBoardDto(null, null, null, null, null, null); - - // when - Set> violations = validator.validate(saveContestBoardDto); - - // then - List errorMessage = new ArrayList<>(); - violations.forEach(error -> errorMessage.add(error.getMessage())); - - assertThat(errorMessage).contains( - "제목을 입력하세요.", - "본문을 입력하세요.", - "협회기관을 입력하세요.", - "공모전 주제를 입력하세요.", - "공모전 모집 시작일을 등록해주세요.", - "공모전 모집 마감일을 등록해주세요." - ); - } - - @DisplayName("공모전 게시글 저장 시 모든 필드가 Blank일 경우") - @Test - public void FieldsAreBlankedError() { - // given - SaveContestBoardDto saveContestBoardDto = new SaveContestBoardDto(" ", " ", " ", " ", null, null); - - //when - Set> violations = validator.validate(saveContestBoardDto); - - // then - List errorMessage = new ArrayList<>(); - violations.forEach(error -> errorMessage.add(error.getMessage())); - - assertThat(errorMessage).contains( - "제목을 입력하세요.", - "본문을 입력하세요.", - "협회기관을 입력하세요.", - "공모전 주제를 입력하세요.", - "공모전 모집 시작일을 등록해주세요.", - "공모전 모집 마감일을 등록해주세요." - ); - } - - @DisplayName("공모전 게시글 저장 시 제목, 협회기관명, 주제가 입력 길이를 초과하여 Validation 실패") - @Test - public void InputsAreExceededError() { - //given - SaveContestBoardDto saveContestBoardDto = new SaveContestBoardDto( - "title".repeat(20) + ".", - "content! Cucumber paste has to have a sun-dried, chilled sauerkraut component.", - "Assoc".repeat(20) + ".", - "topic".repeat(100)+ ".", - LocalDate.of(2022, 1, 1), - LocalDate.of(9999, 3, 3)); - - // when - Set> violations = validator.validate(saveContestBoardDto); - - // then - List errorMessage = new ArrayList<>(); - violations.forEach(error -> errorMessage.add(error.getMessage())); - - assertEquals(3, violations.size()); - assertThat(errorMessage).containsOnly( - "제목은 최대 100자입니다.", - "100자 이내로 작성해주세요.", - "500자 이내로 작성해주세요." - ); - } - - @DisplayName("공모전 게시글 저장 시 마감일자가 이미 지난 경우 Validation 실패") - @Test - public void DeadlineIsOutdatedError() { - //given - SaveContestBoardDto saveContestBoardDto = new SaveContestBoardDto("title", "content", "association", "topic", - LocalDate.of(2022, 1, 1), LocalDate.of(2022, 2, 1)); - - // when - Set> violations = validator.validate(saveContestBoardDto); - - // then - List errorMessage = new ArrayList<>(); - violations.forEach(error -> errorMessage.add(error.getMessage())); - - assertThat(errorMessage).containsOnly( - "이미 모집기간이 종료된 공모전은 등록할 수 없습니다." - ); - } + private static ValidatorFactory validatorFactory; + private static Validator validator; + + @BeforeAll + public static void init() { + validatorFactory = Validation.buildDefaultValidatorFactory(); + validator = validatorFactory.getValidator(); + } + + @AfterAll + public static void close() { + validatorFactory.close(); + } + + @DisplayName("공모전 게시글 저장 시 모든 필드가 null일 경우") + @Test + public void FieldsAreNullError() { + // given + SaveContestBoardDto saveContestBoardDto = + new SaveContestBoardDto(null, null, null, null, null, null); + + // when + Set> violations = + validator.validate(saveContestBoardDto); + + // then + List errorMessage = new ArrayList<>(); + violations.forEach(error -> errorMessage.add(error.getMessage())); + + assertThat(errorMessage) + .contains( + "제목을 입력하세요.", + "본문을 입력하세요.", + "협회기관을 입력하세요.", + "공모전 주제를 입력하세요.", + "공모전 모집 시작일을 등록해주세요.", + "공모전 모집 마감일을 등록해주세요."); + } + + @DisplayName("공모전 게시글 저장 시 모든 필드가 Blank일 경우") + @Test + public void FieldsAreBlankedError() { + // given + SaveContestBoardDto saveContestBoardDto = + new SaveContestBoardDto(" ", " ", " ", " ", null, null); + + // when + Set> violations = + validator.validate(saveContestBoardDto); + + // then + List errorMessage = new ArrayList<>(); + violations.forEach(error -> errorMessage.add(error.getMessage())); + + assertThat(errorMessage) + .contains( + "제목을 입력하세요.", + "본문을 입력하세요.", + "협회기관을 입력하세요.", + "공모전 주제를 입력하세요.", + "공모전 모집 시작일을 등록해주세요.", + "공모전 모집 마감일을 등록해주세요."); + } + + @DisplayName("공모전 게시글 저장 시 제목, 협회기관명, 주제가 입력 길이를 초과하여 Validation 실패") + @Test + public void InputsAreExceededError() { + // given + SaveContestBoardDto saveContestBoardDto = + new SaveContestBoardDto( + "title".repeat(20) + ".", + "content! Cucumber paste has to have a sun-dried, chilled sauerkraut component.", + "Assoc".repeat(20) + ".", + "topic".repeat(100) + ".", + LocalDate.of(2022, 1, 1), + LocalDate.of(9999, 3, 3)); + + // when + Set> violations = + validator.validate(saveContestBoardDto); + + // then + List errorMessage = new ArrayList<>(); + violations.forEach(error -> errorMessage.add(error.getMessage())); + + assertEquals(3, violations.size()); + assertThat(errorMessage) + .containsOnly("제목은 최대 100자입니다.", "100자 이내로 작성해주세요.", "500자 이내로 작성해주세요."); + } + + @DisplayName("공모전 게시글 저장 시 마감일자가 이미 지난 경우 Validation 실패") + @Test + public void DeadlineIsOutdatedError() { + // given + SaveContestBoardDto saveContestBoardDto = + new SaveContestBoardDto( + "title", + "content", + "association", + "topic", + LocalDate.of(2022, 1, 1), + LocalDate.of(2022, 2, 1)); + + // when + Set> violations = + validator.validate(saveContestBoardDto); + + // then + List errorMessage = new ArrayList<>(); + violations.forEach(error -> errorMessage.add(error.getMessage())); + + assertThat(errorMessage).containsOnly("이미 모집기간이 종료된 공모전은 등록할 수 없습니다."); + } } diff --git a/resource-server/src/test/java/com/inhabas/api/domain/contestBoard/dto/UpdateContestBoardDtoTest.java b/resource-server/src/test/java/com/inhabas/api/domain/contestBoard/dto/UpdateContestBoardDtoTest.java index 0e76c65e..6844eb9b 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/contestBoard/dto/UpdateContestBoardDtoTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/contestBoard/dto/UpdateContestBoardDtoTest.java @@ -3,105 +3,104 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; -import com.inhabas.api.domain.contest.dto.UpdateContestBoardDto; import java.time.LocalDate; import java.util.ArrayList; import java.util.List; import java.util.Set; + import javax.validation.ConstraintViolation; import javax.validation.Validation; import javax.validation.Validator; import javax.validation.ValidatorFactory; + +import com.inhabas.api.domain.contest.dto.UpdateContestBoardDto; + import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; - public class UpdateContestBoardDtoTest { - private static ValidatorFactory validatorFactory; - private static Validator validator; - private static List errorMessage; - - @BeforeAll - public static void init() { - validatorFactory = Validation.buildDefaultValidatorFactory(); - validator = validatorFactory.getValidator(); - - errorMessage = new ArrayList<>(); - } - - @AfterAll - public static void close() { - validatorFactory.close(); - } - - @DisplayName("공모전 게시글 수정 시 모든 필드가 null일 경우 테스트를 통과하지 못함.") - @Test - public void FieldsAreNullError() { - // given - UpdateContestBoardDto updateContestBoardDto = new UpdateContestBoardDto( - null, null, null, null, null, null, null ); - - // when - Set> violations = validator.validate(updateContestBoardDto); - violations.forEach(error -> errorMessage.add(error.getMessage())); - - // then - assertThat(errorMessage).contains( - "수정할 게시글을 선택해주세요.", - "제목을 입력하세요.", - "본문을 입력하세요.", - "협회기관을 입력하세요.", - "공모전 주제를 입력하세요.", - "공모전 모집 시작일을 등록해주세요.", - "공모전 모집 마감일을 등록해주세요." - ); - } - - @DisplayName("공모전 게시글 수정 시 공백이 입력되었을 경우 테스트를 통과하지 못함.") - @Test - public void FieldsAreBlankError() { - // given - UpdateContestBoardDto updateContestBoardDto = new UpdateContestBoardDto( - 1, " ", " ", " ", " ", LocalDate.of(2022, 1, 1), LocalDate.of(2023, 2, 10)); - - // when - Set> violations = validator.validate(updateContestBoardDto); - violations.forEach(error -> errorMessage.add(error.getMessage())); - - //then - assertThat(errorMessage).contains( - "제목을 입력하세요.", - "본문을 입력하세요.", - "협회기관을 입력하세요.", - "공모전 주제를 입력하세요." - ); - } - - @DisplayName("공모전 게시글 수정 시 제목, 협회기관명, 주제가 입력 길이를 초과하여 Validation 실패") - @Test - public void InputsAreExceededError() { - //given - UpdateContestBoardDto updateContestBoardDto = new UpdateContestBoardDto( - 1, - "title".repeat(20) + ".", - "content! Cucumber paste has to have a sun-dried, chilled sauerkraut component.", - "Assoc".repeat(20) + ".", - "topic".repeat(100)+ ".", - LocalDate.of(2022, 1, 1), - LocalDate.of(9999, 3, 3)); - - // when - Set> violations = validator.validate(updateContestBoardDto); - violations.forEach(error -> errorMessage.add(error.getMessage())); - - // then - assertEquals(3, violations.size()); - assertThat(errorMessage).containsOnly( - "제목은 최대 100자입니다.", - "100자 이내로 작성해주세요.", - "500자 이내로 작성해주세요." - ); - } + private static ValidatorFactory validatorFactory; + private static Validator validator; + private static List errorMessage; + + @BeforeAll + public static void init() { + validatorFactory = Validation.buildDefaultValidatorFactory(); + validator = validatorFactory.getValidator(); + + errorMessage = new ArrayList<>(); + } + + @AfterAll + public static void close() { + validatorFactory.close(); + } + + @DisplayName("공모전 게시글 수정 시 모든 필드가 null일 경우 테스트를 통과하지 못함.") + @Test + public void FieldsAreNullError() { + // given + UpdateContestBoardDto updateContestBoardDto = + new UpdateContestBoardDto(null, null, null, null, null, null, null); + + // when + Set> violations = + validator.validate(updateContestBoardDto); + violations.forEach(error -> errorMessage.add(error.getMessage())); + + // then + assertThat(errorMessage) + .contains( + "수정할 게시글을 선택해주세요.", + "제목을 입력하세요.", + "본문을 입력하세요.", + "협회기관을 입력하세요.", + "공모전 주제를 입력하세요.", + "공모전 모집 시작일을 등록해주세요.", + "공모전 모집 마감일을 등록해주세요."); + } + + @DisplayName("공모전 게시글 수정 시 공백이 입력되었을 경우 테스트를 통과하지 못함.") + @Test + public void FieldsAreBlankError() { + // given + UpdateContestBoardDto updateContestBoardDto = + new UpdateContestBoardDto( + 1, " ", " ", " ", " ", LocalDate.of(2022, 1, 1), LocalDate.of(2023, 2, 10)); + + // when + Set> violations = + validator.validate(updateContestBoardDto); + violations.forEach(error -> errorMessage.add(error.getMessage())); + + // then + assertThat(errorMessage).contains("제목을 입력하세요.", "본문을 입력하세요.", "협회기관을 입력하세요.", "공모전 주제를 입력하세요."); + } + + @DisplayName("공모전 게시글 수정 시 제목, 협회기관명, 주제가 입력 길이를 초과하여 Validation 실패") + @Test + public void InputsAreExceededError() { + // given + UpdateContestBoardDto updateContestBoardDto = + new UpdateContestBoardDto( + 1, + "title".repeat(20) + ".", + "content! Cucumber paste has to have a sun-dried, chilled sauerkraut component.", + "Assoc".repeat(20) + ".", + "topic".repeat(100) + ".", + LocalDate.of(2022, 1, 1), + LocalDate.of(9999, 3, 3)); + + // when + Set> violations = + validator.validate(updateContestBoardDto); + violations.forEach(error -> errorMessage.add(error.getMessage())); + + // then + assertEquals(3, violations.size()); + assertThat(errorMessage) + .containsOnly("제목은 최대 100자입니다.", "100자 이내로 작성해주세요.", "500자 이내로 작성해주세요."); + } } diff --git a/resource-server/src/test/java/com/inhabas/api/domain/contestBoard/repository/ContestBoardRepositoryTest.java b/resource-server/src/test/java/com/inhabas/api/domain/contestBoard/repository/ContestBoardRepositoryTest.java index 7a8c5cbb..a4b49414 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/contestBoard/repository/ContestBoardRepositoryTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/contestBoard/repository/ContestBoardRepositoryTest.java @@ -1,110 +1,99 @@ package com.inhabas.api.domain.contestBoard.repository; -import static com.inhabas.api.domain.member.domain.entity.MemberTest.basicMember1; -import static org.assertj.core.api.Assertions.assertThat; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager; import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; import com.inhabas.api.domain.contest.domain.ContestBoard; import com.inhabas.api.domain.contest.repository.ContestBoardRepository; -import com.inhabas.api.domain.contestBoard.ContestBoardTest; import com.inhabas.api.domain.menu.domain.Menu; -import com.inhabas.api.domain.menu.domain.MenuGroup; -import com.inhabas.api.domain.menu.domain.valueObject.MenuType; -import com.inhabas.api.domain.contest.dto.DetailContestBoardDto; -import com.inhabas.api.domain.contest.dto.ListContestBoardDto; import com.inhabas.testAnnotataion.DefaultDataJpaTest; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -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.boot.test.autoconfigure.orm.jpa.TestEntityManager; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Sort; @DefaultDataJpaTest public class ContestBoardRepositoryTest { - @Autowired - private ContestBoardRepository contestBoardRepository; + @Autowired private ContestBoardRepository contestBoardRepository; - @Autowired - TestEntityManager em; + @Autowired TestEntityManager em; - Menu menu; - ContestBoard board1; - ContestBoard board2; - ContestBoard board3; - Member writer; + Menu menu; + ContestBoard board1; + ContestBoard board2; + ContestBoard board3; + Member writer; -// @BeforeEach -// public void settingContestBoard(){ -// MenuGroup boardMenuGroup = em.persist(new MenuGroup("게시판")); -// writer = em.persist(basicMember1()); -// menu = em.persist( -// Menu.builder() -// .menuGroup(boardMenuGroup) -// .priority(1) -// .type(MenuType.LIST) -// .name("공모전게시판") -// .description("공모전 정보를 알려주는 게시판입니다.") -// .build()); -// -// board1 = ContestBoardTest.getContestBoard1() -// .writtenBy(writer.getId()).inMenu(menu.getId()); -// board2 = ContestBoardTest.getContestBoard2() -// .writtenBy(writer.getId()).inMenu(menu.getId()); -// board3 = ContestBoardTest.getContestBoard3() -// .writtenBy(writer.getId()).inMenu(menu.getId()); -// } + // @BeforeEach + // public void settingContestBoard(){ + // MenuGroup boardMenuGroup = em.persist(new MenuGroup("게시판")); + // writer = em.persist(basicMember1()); + // menu = em.persist( + // Menu.builder() + // .menuGroup(boardMenuGroup) + // .priority(1) + // .type(MenuType.LIST) + // .name("공모전게시판") + // .description("공모전 정보를 알려주는 게시판입니다.") + // .build()); + // + // board1 = ContestBoardTest.getContestBoard1() + // .writtenBy(writer.getId()).inMenu(menu.getId()); + // board2 = ContestBoardTest.getContestBoard2() + // .writtenBy(writer.getId()).inMenu(menu.getId()); + // board3 = ContestBoardTest.getContestBoard3() + // .writtenBy(writer.getId()).inMenu(menu.getId()); + // } -// @DisplayName("저장한 게시글의 Id를 참조하여 Dto를 반환한다.") -// @Test -// public void findDtoByIdTest() { -// //given -// ContestBoard savedContestBoard = contestBoardRepository.save(board1); -// -// DetailContestBoardDto expectedDto = DetailContestBoardDto.builder() -// .id(savedContestBoard.getId()) -// .writerName(writer.getName()) -// .title(savedContestBoard.getTitle()) -// .content(savedContestBoard.getContent()) -// .association(savedContestBoard.getAssociation()) -// .topic(savedContestBoard.getTopic()) -// .start(savedContestBoard.getStart()) -// .deadline(savedContestBoard.getDeadline()) -// .build(); -// -// // when -// Optional returnedDto = contestBoardRepository.findDtoById(savedContestBoard.getId()); -// -// // then -// assertThat(expectedDto) -// .usingRecursiveComparison() -// .ignoringFields("created", "updated") -// .isEqualTo(returnedDto.get()); -// } -// -// @DisplayName("특정 menuId를 기준으로 모든 게시글 Dto를 조회해 Page 객체를 반환한다.") -// @Test -// public void findAllByMenuIdTest() { -// //given -// List expectedDtoList = new ArrayList<>(); -// contestBoardRepository.save(board1); -// contestBoardRepository.save(board2); -// contestBoardRepository.save(board3); -// -// PageRequest pageable = PageRequest.of(0, 10, Sort.Direction.ASC, "deadline"); -// -// expectedDtoList.add(new ListContestBoardDto(board3.getTitle(), board3.getTopic(), board3.getStart(), board3.getDeadline())); -// expectedDtoList.add(new ListContestBoardDto(board1.getTitle(), board1.getTopic(), board1.getStart(), board1.getDeadline())); -// expectedDtoList.add(new ListContestBoardDto(board2.getTitle(), board2.getTopic(), board2.getStart(), board2.getDeadline())); -// -// // when -// List returnedDtoList = contestBoardRepository.findAllByMenuId(menu.getId(), pageable).getContent(); -// -// // then -// assertThat(returnedDtoList).usingRecursiveFieldByFieldElementComparator().isEqualTo(expectedDtoList); -// } + // @DisplayName("저장한 게시글의 Id를 참조하여 Dto를 반환한다.") + // @Test + // public void findDtoByIdTest() { + // //given + // ContestBoard savedContestBoard = contestBoardRepository.save(board1); + // + // DetailContestBoardDto expectedDto = DetailContestBoardDto.builder() + // .id(savedContestBoard.getId()) + // .writerName(writer.getName()) + // .title(savedContestBoard.getTitle()) + // .content(savedContestBoard.getContent()) + // .association(savedContestBoard.getAssociation()) + // .topic(savedContestBoard.getTopic()) + // .start(savedContestBoard.getStart()) + // .deadline(savedContestBoard.getDeadline()) + // .build(); + // + // // when + // Optional returnedDto = + // contestBoardRepository.findDtoById(savedContestBoard.getId()); + // + // // then + // assertThat(expectedDto) + // .usingRecursiveComparison() + // .ignoringFields("created", "updated") + // .isEqualTo(returnedDto.get()); + // } + // + // @DisplayName("특정 menuId를 기준으로 모든 게시글 Dto를 조회해 Page 객체를 반환한다.") + // @Test + // public void findAllByMenuIdTest() { + // //given + // List expectedDtoList = new ArrayList<>(); + // contestBoardRepository.save(board1); + // contestBoardRepository.save(board2); + // contestBoardRepository.save(board3); + // + // PageRequest pageable = PageRequest.of(0, 10, Sort.Direction.ASC, "deadline"); + // + // expectedDtoList.add(new ListContestBoardDto(board3.getTitle(), board3.getTopic(), + // board3.getStart(), board3.getDeadline())); + // expectedDtoList.add(new ListContestBoardDto(board1.getTitle(), board1.getTopic(), + // board1.getStart(), board1.getDeadline())); + // expectedDtoList.add(new ListContestBoardDto(board2.getTitle(), board2.getTopic(), + // board2.getStart(), board2.getDeadline())); + // + // // when + // List returnedDtoList = + // contestBoardRepository.findAllByMenuId(menu.getId(), pageable).getContent(); + // + // // then + // + // assertThat(returnedDtoList).usingRecursiveFieldByFieldElementComparator().isEqualTo(expectedDtoList); + // } } diff --git a/resource-server/src/test/java/com/inhabas/api/domain/contestBoard/usecase/ContestBoardServiceTest.java b/resource-server/src/test/java/com/inhabas/api/domain/contestBoard/usecase/ContestBoardServiceTest.java index 6f914122..7c4f86bd 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/contestBoard/usecase/ContestBoardServiceTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/contestBoard/usecase/ContestBoardServiceTest.java @@ -1,186 +1,185 @@ package com.inhabas.api.domain.contestBoard.usecase; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; - import com.inhabas.api.domain.contest.repository.ContestBoardRepository; import com.inhabas.api.domain.contest.usecase.ContestBoardServiceImpl; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + @ExtendWith(MockitoExtension.class) public class ContestBoardServiceTest { - @InjectMocks - ContestBoardServiceImpl contestBoardService; - - @Mock - ContestBoardRepository contestBoardRepository; - + @InjectMocks ContestBoardServiceImpl contestBoardService; - @DisplayName("공모전 게시글을 성공적으로 생성한다.") - @Test - public void createContestBoard() { -// //given -// StudentId StudentId = new StudentId("12201863"); -// SaveContestBoardDto saveContestBoardDto = -// new SaveContestBoardDto("title", "content", "association", "topic", -// LocalDate.of(2022, 1, 1), LocalDate.of(2022, 1, 26)); -// ContestBoard contestBoard = -// new ContestBoard("title", "content", "association", "topic", -// LocalDate.of(2022, 1, 1), LocalDate.of(2022, 1, 26)); -// -// given(contestBoardRepository.save(any())).willReturn(contestBoard); -// -// // when -// Integer returnedId = contestBoardService.write(StudentId, saveContestBoardDto); -// -// // then -// then(contestBoardRepository).should(times(1)).save(any()); - } + @Mock ContestBoardRepository contestBoardRepository; - @DisplayName("공모전 게시판의 목록을 조회한다.") - @Test - public void getContestBoardList() { -// //given -// Pageable pageable = PageRequest.of(0, 10, Sort.Direction.DESC, "deadline"); -// -// ListContestBoardDto contestBoardDto1 = -// new ListContestBoardDto("title1", "contents1", LocalDate.of(2022, 1, 1), -// LocalDate.of(2022, 3, 4)); -// ListContestBoardDto contestBoardDto2 = -// new ListContestBoardDto("title2", "contents2", LocalDate.of(2022, 1, 1), -// LocalDate.of(2022, 5, 28)); -// ListContestBoardDto contestBoardDto3 = -// new ListContestBoardDto("title2", "contents2", LocalDate.of(2022, 1, 1), -// LocalDate.of(2022, 2, 20)); -// -// List results = new ArrayList<>(); -// results.add(contestBoardDto3); -// results.add(contestBoardDto1); -// results.add(contestBoardDto2); -// -// Page expectedContestBoardDto = new PageImpl<>(results, pageable, -// results.size()); -// -// given(contestBoardRepository.findAllByMenuId(any(), any())).willReturn( -// expectedContestBoardDto); -// -// //when -// Page returnedBoardList = contestBoardService.getBoardList( -// new MenuId(1), pageable); -// -// //then -// assertThat(returnedBoardList).isEqualTo(expectedContestBoardDto); + @DisplayName("공모전 게시글을 성공적으로 생성한다.") + @Test + public void createContestBoard() { + // //given + // StudentId StudentId = new StudentId("12201863"); + // SaveContestBoardDto saveContestBoardDto = + // new SaveContestBoardDto("title", "content", "association", "topic", + // LocalDate.of(2022, 1, 1), LocalDate.of(2022, 1, 26)); + // ContestBoard contestBoard = + // new ContestBoard("title", "content", "association", "topic", + // LocalDate.of(2022, 1, 1), LocalDate.of(2022, 1, 26)); + // + // given(contestBoardRepository.save(any())).willReturn(contestBoard); + // + // // when + // Integer returnedId = contestBoardService.write(StudentId, saveContestBoardDto); + // + // // then + // then(contestBoardRepository).should(times(1)).save(any()); + } - } + @DisplayName("공모전 게시판의 목록을 조회한다.") + @Test + public void getContestBoardList() { + // //given + // Pageable pageable = PageRequest.of(0, 10, Sort.Direction.DESC, "deadline"); + // + // ListContestBoardDto contestBoardDto1 = + // new ListContestBoardDto("title1", "contents1", LocalDate.of(2022, 1, 1), + // LocalDate.of(2022, 3, 4)); + // ListContestBoardDto contestBoardDto2 = + // new ListContestBoardDto("title2", "contents2", LocalDate.of(2022, 1, 1), + // LocalDate.of(2022, 5, 28)); + // ListContestBoardDto contestBoardDto3 = + // new ListContestBoardDto("title2", "contents2", LocalDate.of(2022, 1, 1), + // LocalDate.of(2022, 2, 20)); + // + // List results = new ArrayList<>(); + // results.add(contestBoardDto3); + // results.add(contestBoardDto1); + // results.add(contestBoardDto2); + // + // Page expectedContestBoardDto = new PageImpl<>(results, pageable, + // results.size()); + // + // given(contestBoardRepository.findAllByMenuId(any(), any())).willReturn( + // expectedContestBoardDto); + // + // //when + // Page returnedBoardList = contestBoardService.getBoardList( + // new MenuId(1), pageable); + // + // //then + // assertThat(returnedBoardList).isEqualTo(expectedContestBoardDto); - @DisplayName("공모전 게시글 단일 조회에 성공한다.") - @Test - public void getDetailBoard() { -// //given -// DetailContestBoardDto contestBoardDto = -// new DetailContestBoardDto(1, "mingyeom", "title", "content", -// "association", "topic", LocalDate.of(2022, 1, 1), -// LocalDate.of(2022, 1, 29), LocalDateTime.now(), null); -// given(contestBoardRepository.findDtoById(any())).willReturn(Optional.of(contestBoardDto)); -// -// // when -// contestBoardService.getBoard(1); -// -// // then -// then(contestBoardRepository).should(times(1)).findDtoById(any()); - } + } + @DisplayName("공모전 게시글 단일 조회에 성공한다.") + @Test + public void getDetailBoard() { + // //given + // DetailContestBoardDto contestBoardDto = + // new DetailContestBoardDto(1, "mingyeom", "title", "content", + // "association", "topic", LocalDate.of(2022, 1, 1), + // LocalDate.of(2022, 1, 29), LocalDateTime.now(), null); + // + // given(contestBoardRepository.findDtoById(any())).willReturn(Optional.of(contestBoardDto)); + // + // // when + // contestBoardService.getBoard(1); + // + // // then + // then(contestBoardRepository).should(times(1)).findDtoById(any()); + } - @DisplayName("공모전 게시글을 성공적으로 삭제한다.") - @Test - public void deleteContestBoard() { -// //given -// StudentId StudentId = new StudentId("12201863"); -// ContestBoard contestBoard = -// new ContestBoard("title", "content", "association", "topic", -// LocalDate.of(2022, 1, 1), LocalDate.of(2022, 1, 26)) -// .writtenBy(StudentId); -// given(contestBoardRepository.findById(anyInt())).willReturn(Optional.of(contestBoard)); -// doNothing().when(contestBoardRepository).deleteById(any()); -// -// // when -// contestBoardService.delete(StudentId, 1); -// -// // then -// then(contestBoardRepository).should(times(1)).deleteById(any()); - } + @DisplayName("공모전 게시글을 성공적으로 삭제한다.") + @Test + public void deleteContestBoard() { + // //given + // StudentId StudentId = new StudentId("12201863"); + // ContestBoard contestBoard = + // new ContestBoard("title", "content", "association", "topic", + // LocalDate.of(2022, 1, 1), LocalDate.of(2022, 1, 26)) + // .writtenBy(StudentId); + // + // given(contestBoardRepository.findById(anyInt())).willReturn(Optional.of(contestBoard)); + // doNothing().when(contestBoardRepository).deleteById(any()); + // + // // when + // contestBoardService.delete(StudentId, 1); + // + // // then + // then(contestBoardRepository).should(times(1)).deleteById(any()); + } - @DisplayName("공모전 게시글을 수정한다.") - @Test - public void updateContestBoard() { -// //given -// StudentId StudentId = new StudentId("12201863"); -// ContestBoard expectedContestBoard = -// new ContestBoard("title", "content", "association", "topic", -// LocalDate.of(2022, 1, 1), LocalDate.of(2022, 1, 26)) -// .writtenBy(StudentId); -// -// given(contestBoardRepository.save(any())).willReturn(expectedContestBoard); -// given(contestBoardRepository.findById(any())).willReturn(Optional.of(expectedContestBoard)); -// -// UpdateContestBoardDto updateContestBoardDto = new UpdateContestBoardDto(1, "수정된 제목", -// "수정된 내용", "수정된 협회기관명", "수정된 공모전 주제", LocalDate.of(2022, 1, 1), -// LocalDate.of(2022, 1, 26)); -// -// // when -// contestBoardService.update(StudentId, updateContestBoardDto); -// -// // then -// then(contestBoardRepository).should(times(1)).save(any()); - } + @DisplayName("공모전 게시글을 수정한다.") + @Test + public void updateContestBoard() { + // //given + // StudentId StudentId = new StudentId("12201863"); + // ContestBoard expectedContestBoard = + // new ContestBoard("title", "content", "association", "topic", + // LocalDate.of(2022, 1, 1), LocalDate.of(2022, 1, 26)) + // .writtenBy(StudentId); + // + // given(contestBoardRepository.save(any())).willReturn(expectedContestBoard); + // + // given(contestBoardRepository.findById(any())).willReturn(Optional.of(expectedContestBoard)); + // + // UpdateContestBoardDto updateContestBoardDto = new UpdateContestBoardDto(1, "수정된 제목", + // "수정된 내용", "수정된 협회기관명", "수정된 공모전 주제", LocalDate.of(2022, 1, 1), + // LocalDate.of(2022, 1, 26)); + // + // // when + // contestBoardService.update(StudentId, updateContestBoardDto); + // + // // then + // then(contestBoardRepository).should(times(1)).save(any()); + } - @DisplayName("작성자가 아니면 수정할 수 없다.") - @Test - public void failToModifyTest() { -// //given -// StudentId badUser = new StudentId("44444444"); -// StudentId originalWriter = new StudentId("12201863"); -// ContestBoard expectedContestBoard = -// new ContestBoard("title", "content", "association", "topic", -// LocalDate.of(2022, 1, 1), LocalDate.of(2022, 1, 26)) -// .writtenBy(originalWriter); -// given(contestBoardRepository.findById(any())).willReturn(Optional.of(expectedContestBoard)); -// -// UpdateContestBoardDto updateContestBoardDto = new UpdateContestBoardDto(1, "수정된 제목", -// "수정된 내용", "수정된 협회기관명", "수정된 공모전 주제", LocalDate.of(2022, 1, 1), -// LocalDate.of(2022, 1, 26)); -// -// // when -// Assertions.assertThrows(OnlyWriterModifiableException.class, -// ()->contestBoardService.update(badUser, updateContestBoardDto)); -// -// //then -// then(contestBoardRepository).should(times(0)).save(any()); - } + @DisplayName("작성자가 아니면 수정할 수 없다.") + @Test + public void failToModifyTest() { + // //given + // StudentId badUser = new StudentId("44444444"); + // StudentId originalWriter = new StudentId("12201863"); + // ContestBoard expectedContestBoard = + // new ContestBoard("title", "content", "association", "topic", + // LocalDate.of(2022, 1, 1), LocalDate.of(2022, 1, 26)) + // .writtenBy(originalWriter); + // + // given(contestBoardRepository.findById(any())).willReturn(Optional.of(expectedContestBoard)); + // + // UpdateContestBoardDto updateContestBoardDto = new UpdateContestBoardDto(1, "수정된 제목", + // "수정된 내용", "수정된 협회기관명", "수정된 공모전 주제", LocalDate.of(2022, 1, 1), + // LocalDate.of(2022, 1, 26)); + // + // // when + // Assertions.assertThrows(OnlyWriterModifiableException.class, + // ()->contestBoardService.update(badUser, updateContestBoardDto)); + // + // //then + // then(contestBoardRepository).should(times(0)).save(any()); + } - @DisplayName("작성자가 아니면 삭제할 수 없다.") - @Test - public void failToDeleteTest() { -// //given -// StudentId badUser = new StudentId("44444444"); -// StudentId StudentId = new StudentId("12201863"); -// ContestBoard contestBoard = -// new ContestBoard("title", "content", "association", "topic", -// LocalDate.of(2022, 1, 1), LocalDate.of(2022, 1, 26)) -// .writtenBy(StudentId); -// given(contestBoardRepository.findById(anyInt())).willReturn(Optional.of(contestBoard)); -// -// // when -// Assertions.assertThrows(OnlyWriterModifiableException.class, -// ()->contestBoardService.delete(badUser, 1)); -// -// // then -// then(contestBoardRepository).should(times(0)).deleteById(any()); - } + @DisplayName("작성자가 아니면 삭제할 수 없다.") + @Test + public void failToDeleteTest() { + // //given + // StudentId badUser = new StudentId("44444444"); + // StudentId StudentId = new StudentId("12201863"); + // ContestBoard contestBoard = + // new ContestBoard("title", "content", "association", "topic", + // LocalDate.of(2022, 1, 1), LocalDate.of(2022, 1, 26)) + // .writtenBy(StudentId); + // + // given(contestBoardRepository.findById(anyInt())).willReturn(Optional.of(contestBoard)); + // + // // when + // Assertions.assertThrows(OnlyWriterModifiableException.class, + // ()->contestBoardService.delete(badUser, 1)); + // + // // then + // then(contestBoardRepository).should(times(0)).deleteById(any()); + } } diff --git a/resource-server/src/test/java/com/inhabas/api/domain/file/domain/BoardFileTest.java b/resource-server/src/test/java/com/inhabas/api/domain/file/domain/BoardFileTest.java index 9b1ec4e9..d1d13f5a 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/file/domain/BoardFileTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/file/domain/BoardFileTest.java @@ -1,29 +1,28 @@ package com.inhabas.api.domain.file.domain; +import static org.assertj.core.api.Assertions.assertThat; + import com.inhabas.api.domain.board.domain.BaseBoard; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; import org.mockito.Mockito; -import static org.assertj.core.api.Assertions.assertThat; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; public class BoardFileTest { - @DisplayName("Board 에 첨부되는 File 을 생성한다.") - @Test - void constructorTest() { - //given - String name = "fileName"; - String url = "fileUrl"; - BaseBoard baseBoard = Mockito.mock(BaseBoard.class); - - //when - BoardFile boardFile = new BoardFile(name, url, baseBoard); - - //then - assertThat(boardFile.getName()).isEqualTo(name); - assertThat(boardFile.getUrl()).isEqualTo(url); - - } - -} \ No newline at end of file + @DisplayName("Board 에 첨부되는 File 을 생성한다.") + @Test + void constructorTest() { + // given + String name = "fileName"; + String url = "fileUrl"; + BaseBoard baseBoard = Mockito.mock(BaseBoard.class); + + // when + BoardFile boardFile = new BoardFile(name, url, baseBoard); + + // then + assertThat(boardFile.getName()).isEqualTo(name); + assertThat(boardFile.getUrl()).isEqualTo(url); + } +} diff --git a/resource-server/src/test/java/com/inhabas/api/domain/file/domain/valueObject/FileNameTest.java b/resource-server/src/test/java/com/inhabas/api/domain/file/domain/valueObject/FileNameTest.java index 1d5b2585..84a8a594 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/file/domain/valueObject/FileNameTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/file/domain/valueObject/FileNameTest.java @@ -1,60 +1,58 @@ package com.inhabas.api.domain.file.domain.valueObject; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; + import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; - public class FileNameTest { - @DisplayName("FileName 타입에 파일 이름을 저장한다.") - @Test - public void FileName_is_OK() { - //when - FileName fileName = new FileName("filename_test_file.txt"); - - //then - assertThat(fileName.getValue()).isEqualTo("filename_test_file.txt"); - } - - @DisplayName("FileName 타입에 너무 긴 파일 이름 저장을 시도한다.") - @Test - public void FileName_is_too_long() { - //given - String tooLongFileName = "a".repeat(500) + "txt"; - - //when - assertThatThrownBy(() -> new FileName(tooLongFileName)) - .isInstanceOf(InvalidInputException.class) - .hasMessage("입력값이 없거나, 타입이 유효하지 않습니다."); - - } - - @DisplayName("FileName 에 null 은 허용 안된다.") - @Test - public void FileName_cannot_be_null() { - //given - String nullFileName = null; - - //when - assertThatThrownBy(() -> new FileName(nullFileName)) - .isInstanceOf(InvalidInputException.class) - .hasMessage("입력값이 없거나, 타입이 유효하지 않습니다."); - - } - - @DisplayName("FileName 이 빈 문자열이면 안된다.") - @Test - public void FileName_cannot_be_blank_string() { - //given - String blankFileName = " "; - - //when - assertThatThrownBy(() -> new FileName(blankFileName)) - .isInstanceOf(InvalidInputException.class) - .hasMessage("입력값이 없거나, 타입이 유효하지 않습니다."); - - } + @DisplayName("FileName 타입에 파일 이름을 저장한다.") + @Test + public void FileName_is_OK() { + // when + FileName fileName = new FileName("filename_test_file.txt"); + + // then + assertThat(fileName.getValue()).isEqualTo("filename_test_file.txt"); + } + + @DisplayName("FileName 타입에 너무 긴 파일 이름 저장을 시도한다.") + @Test + public void FileName_is_too_long() { + // given + String tooLongFileName = "a".repeat(500) + "txt"; + + // when + assertThatThrownBy(() -> new FileName(tooLongFileName)) + .isInstanceOf(InvalidInputException.class) + .hasMessage("입력값이 없거나, 타입이 유효하지 않습니다."); + } + + @DisplayName("FileName 에 null 은 허용 안된다.") + @Test + public void FileName_cannot_be_null() { + // given + String nullFileName = null; + + // when + assertThatThrownBy(() -> new FileName(nullFileName)) + .isInstanceOf(InvalidInputException.class) + .hasMessage("입력값이 없거나, 타입이 유효하지 않습니다."); + } + + @DisplayName("FileName 이 빈 문자열이면 안된다.") + @Test + public void FileName_cannot_be_blank_string() { + // given + String blankFileName = " "; + + // when + assertThatThrownBy(() -> new FileName(blankFileName)) + .isInstanceOf(InvalidInputException.class) + .hasMessage("입력값이 없거나, 타입이 유효하지 않습니다."); + } } diff --git a/resource-server/src/test/java/com/inhabas/api/domain/file/domain/valueObject/FileUrlTest.java b/resource-server/src/test/java/com/inhabas/api/domain/file/domain/valueObject/FileUrlTest.java index af1de238..865ebf54 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/file/domain/valueObject/FileUrlTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/file/domain/valueObject/FileUrlTest.java @@ -1,65 +1,63 @@ package com.inhabas.api.domain.file.domain.valueObject; -import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; - import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -public class FileUrlTest { - - @DisplayName("FileUrl 타입에 파일 경로를 저장한다.") - @Test - public void FileUrl_is_OK() { - //given - String url = "/file/board/"; - String filename = "file.txt"; - - //when - FileUrl fileURL = new FileUrl(url + filename); - - //then - assertThat(fileURL.getValue()).isEqualTo("/file/board/file.txt"); - } - - @DisplayName("FileUrl 타입에 너무 긴 경로 저장을 시도한다.") - @Test - public void FileUrl_is_too_long() { - //given - String url = "/" + "file".repeat(300); - String tooLongFileUrl = url + "file.txt"; - - //when - assertThatThrownBy(() -> new FileUrl(tooLongFileUrl)) - .isInstanceOf(InvalidInputException.class) - .hasMessage("입력값이 없거나, 타입이 유효하지 않습니다."); - - } - - @DisplayName("FileUrl 는 null이 될 수 없다.") - @Test - public void FileUrl_cannot_be_null() { - //given - String nullUrl = null; - - //when - assertThatThrownBy(() -> new FileUrl(nullUrl)) - .isInstanceOf(InvalidInputException.class) - .hasMessage("입력값이 없거나, 타입이 유효하지 않습니다."); - - } +import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; - @DisplayName("FileUrl 는 빈 문자열이 될 수 없다.") - @Test - public void FileUrl_cannot_be_blank() { - //given - String blankUrl = " "; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; - //when - assertThatThrownBy(() -> new FileUrl(blankUrl)) - .isInstanceOf(InvalidInputException.class) - .hasMessage("입력값이 없거나, 타입이 유효하지 않습니다."); +public class FileUrlTest { - } + @DisplayName("FileUrl 타입에 파일 경로를 저장한다.") + @Test + public void FileUrl_is_OK() { + // given + String url = "/file/board/"; + String filename = "file.txt"; + + // when + FileUrl fileURL = new FileUrl(url + filename); + + // then + assertThat(fileURL.getValue()).isEqualTo("/file/board/file.txt"); + } + + @DisplayName("FileUrl 타입에 너무 긴 경로 저장을 시도한다.") + @Test + public void FileUrl_is_too_long() { + // given + String url = "/" + "file".repeat(300); + String tooLongFileUrl = url + "file.txt"; + + // when + assertThatThrownBy(() -> new FileUrl(tooLongFileUrl)) + .isInstanceOf(InvalidInputException.class) + .hasMessage("입력값이 없거나, 타입이 유효하지 않습니다."); + } + + @DisplayName("FileUrl 는 null이 될 수 없다.") + @Test + public void FileUrl_cannot_be_null() { + // given + String nullUrl = null; + + // when + assertThatThrownBy(() -> new FileUrl(nullUrl)) + .isInstanceOf(InvalidInputException.class) + .hasMessage("입력값이 없거나, 타입이 유효하지 않습니다."); + } + + @DisplayName("FileUrl 는 빈 문자열이 될 수 없다.") + @Test + public void FileUrl_cannot_be_blank() { + // given + String blankUrl = " "; + + // when + assertThatThrownBy(() -> new FileUrl(blankUrl)) + .isInstanceOf(InvalidInputException.class) + .hasMessage("입력값이 없거나, 타입이 유효하지 않습니다."); + } } diff --git a/resource-server/src/test/java/com/inhabas/api/domain/file/dto/FileDownloadDtoTest.java b/resource-server/src/test/java/com/inhabas/api/domain/file/dto/FileDownloadDtoTest.java index 0ccd87e4..51dc1263 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/file/dto/FileDownloadDtoTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/file/dto/FileDownloadDtoTest.java @@ -1,49 +1,46 @@ package com.inhabas.api.domain.file.dto; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Set; import javax.validation.ConstraintViolation; import javax.validation.Validation; import javax.validation.Validator; import javax.validation.ValidatorFactory; -import java.util.Set; -import static org.assertj.core.api.Assertions.assertThat; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; public class FileDownloadDtoTest { - private static ValidatorFactory validatorFactory; - private static Validator validator; - - @BeforeAll - public static void init() { - validatorFactory = Validation.buildDefaultValidatorFactory(); - validator = validatorFactory.getValidator(); - } - - @AfterAll - public static void close() { - validatorFactory.close(); - } - - - @DisplayName("DTO validation 검사") - @Test - public void validationTest() { - //given - FileDownloadDto fileDownloadDto = FileDownloadDto.builder() - .name("fileName") - .url("http://localhost/upload") - .build(); - - //when - Set> violations = validator.validate(fileDownloadDto); - - //then - assertThat(violations).hasSize(0); - - } -} \ No newline at end of file + private static ValidatorFactory validatorFactory; + private static Validator validator; + + @BeforeAll + public static void init() { + validatorFactory = Validation.buildDefaultValidatorFactory(); + validator = validatorFactory.getValidator(); + } + + @AfterAll + public static void close() { + validatorFactory.close(); + } + + @DisplayName("DTO validation 검사") + @Test + public void validationTest() { + // given + FileDownloadDto fileDownloadDto = + FileDownloadDto.builder().name("fileName").url("http://localhost/upload").build(); + + // when + Set> violations = validator.validate(fileDownloadDto); + + // then + assertThat(violations).hasSize(0); + } +} diff --git a/resource-server/src/test/java/com/inhabas/api/domain/file/dto/FileUploadDtoTest.java b/resource-server/src/test/java/com/inhabas/api/domain/file/dto/FileUploadDtoTest.java index 9465cf1c..315b2621 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/file/dto/FileUploadDtoTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/file/dto/FileUploadDtoTest.java @@ -1,6 +1,3 @@ package com.inhabas.api.domain.file.dto; - -class FileUploadDtoTest { - -} \ No newline at end of file +class FileUploadDtoTest {} diff --git a/resource-server/src/test/java/com/inhabas/api/domain/lecture/repository/LectureRepositoryTest.java b/resource-server/src/test/java/com/inhabas/api/domain/lecture/repository/LectureRepositoryTest.java index ef2b14ac..fc7196f4 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/lecture/repository/LectureRepositoryTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/lecture/repository/LectureRepositoryTest.java @@ -1,102 +1,89 @@ package com.inhabas.api.domain.lecture.repository; -import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; -import com.inhabas.api.domain.lecture.domain.Lecture; -import com.inhabas.api.domain.lecture.domain.valueObject.LectureStatus; -import com.inhabas.api.domain.lecture.dto.LectureDetailDto; -import com.inhabas.api.domain.lecture.dto.LectureListDto; -import com.inhabas.testAnnotataion.DefaultDataJpaTest; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; +import static com.inhabas.api.domain.member.domain.entity.MemberTest.basicMember1; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageRequest; -import org.springframework.test.util.ReflectionTestUtils; -import java.time.LocalDateTime; -import java.util.ArrayList; +import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; +import com.inhabas.testAnnotataion.DefaultDataJpaTest; -import static com.inhabas.api.domain.member.domain.entity.MemberTest.basicMember1; -import static org.assertj.core.api.Assertions.assertThat; +import org.junit.jupiter.api.BeforeEach; @DefaultDataJpaTest public class LectureRepositoryTest { - @Autowired - private TestEntityManager em; + @Autowired private TestEntityManager em; - @Autowired - private LectureRepository repository; + @Autowired private LectureRepository repository; - private Member chief; + private Member chief; - @BeforeEach - public void setUp() { - chief = em.persist(basicMember1()); - } + @BeforeEach + public void setUp() { + chief = em.persist(basicMember1()); + } -// @DisplayName("강의글 단일 조회") -// @Test -// public void getTest() { -// -// //given -// Lecture entity = Lecture.builder() -// .title("절권도 배우기") -// .chief(chief.getId()) -// .applyDeadline(LocalDateTime.of(9011, 1, 1, 1, 1, 1)) -// .curriculumDetails("1주차: 빅데이터에 기반한 공격패턴분석
2주차: ...") -// .daysOfWeek("월 금") -// .introduction("호신술을 배워보자") -// .method(1) -// .participantsLimits(30) -// .place("6호관 옥상") -// .build(); -// entity = repository.save(entity); -// -// //when -// Integer id = (Integer) ReflectionTestUtils.getField(entity, "id"); -// LectureDetailDto detailDto = repository.getDetails(id) -// .orElse(null); -// -// //then -// assertThat(detailDto).isNotNull(); -// assertThat(detailDto.getChief().getId()).isEqualTo(12171234); -// assertThat(detailDto.getChief().getMajor()).isEqualTo("건축공학과"); -// assertThat(detailDto.getChief().getName()).isEqualTo("유동현"); -// } + // @DisplayName("강의글 단일 조회") + // @Test + // public void getTest() { + // + // //given + // Lecture entity = Lecture.builder() + // .title("절권도 배우기") + // .chief(chief.getId()) + // .applyDeadline(LocalDateTime.of(9011, 1, 1, 1, 1, 1)) + // .curriculumDetails("1주차: 빅데이터에 기반한 공격패턴분석
2주차: ...") + // .daysOfWeek("월 금") + // .introduction("호신술을 배워보자") + // .method(1) + // .participantsLimits(30) + // .place("6호관 옥상") + // .build(); + // entity = repository.save(entity); + // + // //when + // Integer id = (Integer) ReflectionTestUtils.getField(entity, "id"); + // LectureDetailDto detailDto = repository.getDetails(id) + // .orElse(null); + // + // //then + // assertThat(detailDto).isNotNull(); + // assertThat(detailDto.getChief().getId()).isEqualTo(12171234); + // assertThat(detailDto.getChief().getMajor()).isEqualTo("건축공학과"); + // assertThat(detailDto.getChief().getName()).isEqualTo("유동현"); + // } -// @DisplayName("강의글 목록 조회") -// @Test -// public void getListTest() { -// -// ArrayList lectures = new ArrayList<>(); -// -// for (int i = 0; i < 4; i++) { -// Lecture lecture = Lecture.builder() -// .title("절권도 배우기" + i) -// .chief(chief.getId()) -// .applyDeadline(LocalDateTime.of(9011, 1, 1, 1, 1, 1)) -// .curriculumDetails("1주차: 빅데이터에 기반한 공격패턴분석
2주차: ...") -// .daysOfWeek("월 금") -// .introduction("호신술을 배워보자") -// .method(1) -// .participantsLimits(30) -// .place("6호관 옥상") -// .build(); -// ReflectionTestUtils.setField(lecture, "status", LectureStatus.values()[i]); -// lectures.add(lecture); -// } -// repository.saveAll(lectures); -// -// //when -// Page page = repository.getList(PageRequest.of(0, 6)); -// -// //then -// assertThat(page.getTotalElements()).isEqualTo(2); -// assertThat(page.getNumberOfElements()).isEqualTo(2); -// assertThat(page.getTotalPages()).isEqualTo(1); -// assertThat(page.getContent().get(0)).extracting("title").isEqualTo("절권도 배우기3"); -// } + // @DisplayName("강의글 목록 조회") + // @Test + // public void getListTest() { + // + // ArrayList lectures = new ArrayList<>(); + // + // for (int i = 0; i < 4; i++) { + // Lecture lecture = Lecture.builder() + // .title("절권도 배우기" + i) + // .chief(chief.getId()) + // .applyDeadline(LocalDateTime.of(9011, 1, 1, 1, 1, 1)) + // .curriculumDetails("1주차: 빅데이터에 기반한 공격패턴분석
2주차: ...") + // .daysOfWeek("월 금") + // .introduction("호신술을 배워보자") + // .method(1) + // .participantsLimits(30) + // .place("6호관 옥상") + // .build(); + // ReflectionTestUtils.setField(lecture, "status", LectureStatus.values()[i]); + // lectures.add(lecture); + // } + // repository.saveAll(lectures); + // + // //when + // Page page = repository.getList(PageRequest.of(0, 6)); + // + // //then + // assertThat(page.getTotalElements()).isEqualTo(2); + // assertThat(page.getNumberOfElements()).isEqualTo(2); + // assertThat(page.getTotalPages()).isEqualTo(1); + // assertThat(page.getContent().get(0)).extracting("title").isEqualTo("절권도 배우기3"); + // } } diff --git a/resource-server/src/test/java/com/inhabas/api/domain/lecture/repository/StudentRepositoryTest.java b/resource-server/src/test/java/com/inhabas/api/domain/lecture/repository/StudentRepositoryTest.java index 4ed4aff8..dfe9d15b 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/lecture/repository/StudentRepositoryTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/lecture/repository/StudentRepositoryTest.java @@ -1,82 +1,64 @@ package com.inhabas.api.domain.lecture.repository; -import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; -import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.StudentId; -import com.inhabas.api.domain.lecture.domain.Lecture; -import com.inhabas.api.domain.lecture.domain.Student; -import com.inhabas.api.domain.lecture.dto.StudentListDto; -import com.inhabas.api.domain.member.domain.entity.MemberTest; -import com.inhabas.testAnnotataion.DefaultDataJpaTest; -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.boot.test.autoconfigure.orm.jpa.TestEntityManager; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageRequest; -import org.springframework.test.util.ReflectionTestUtils; -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; - -import static com.inhabas.api.domain.member.domain.entity.MemberTest.getTestBasicMember; -import static org.assertj.core.api.Assertions.assertThat; +import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; +import com.inhabas.api.domain.lecture.domain.Lecture; +import com.inhabas.testAnnotataion.DefaultDataJpaTest; @DefaultDataJpaTest public class StudentRepositoryTest { - @Autowired - private StudentRepository studentRepository; - - @Autowired - private TestEntityManager entityManager; - - private Member instructor; + @Autowired private StudentRepository studentRepository; - private Lecture lecture; + @Autowired private TestEntityManager entityManager; -// @BeforeEach -// public void setUp() { -// instructor = entityManager.persist(getTestBasicMember("12171652")); -// -// lecture = entityManager.persist(Lecture.builder() -// .title("절권도 배우기") -// .chief(instructor.getId()) -// .applyDeadline(LocalDateTime.of(9011, 1, 1, 1, 1, 1)) -// .curriculumDetails("1주차: 빅데이터에 기반한 공격패턴분석
2주차: ...") -// .daysOfWeek("월 금") -// .introduction("호신술을 배워보자") -// .method(1) -// .participantsLimits(30) -// .place("6호관 옥상") -// .build()); -// } + private Member instructor; + private Lecture lecture; -// -// @DisplayName("수강생 정보를 불러온다.") -// @Test -// public void searchStudentsTest() { -// -// //given -// List students = new ArrayList<>(); -// for (int i = 0; i < 10; i++) { -// entityManager.persist(getTestBasicMember(String.valueOf(100000+i), "010-0000-000" + i)); -// students.add(new Student(lecture, new StudentId(String.valueOf(100000+i)))); -// } -// studentRepository.saveAll(students); -// -// //when -// Integer lectureId = (Integer) ReflectionTestUtils.getField(lecture, "id"); -// Page page = studentRepository.searchStudents(lectureId, PageRequest.of(0, 25)); -// -// //then -// assertThat(page.getTotalElements()).isEqualTo(10); -// assertThat(page.getNumberOfElements()).isEqualTo(10); -// assertThat(page.getTotalPages()).isEqualTo(1); -// assertThat(page.getContent().get(0)).extracting("StudentId").isEqualTo(100000); -// } + // @BeforeEach + // public void setUp() { + // instructor = entityManager.persist(getTestBasicMember("12171652")); + // + // lecture = entityManager.persist(Lecture.builder() + // .title("절권도 배우기") + // .chief(instructor.getId()) + // .applyDeadline(LocalDateTime.of(9011, 1, 1, 1, 1, 1)) + // .curriculumDetails("1주차: 빅데이터에 기반한 공격패턴분석
2주차: ...") + // .daysOfWeek("월 금") + // .introduction("호신술을 배워보자") + // .method(1) + // .participantsLimits(30) + // .place("6호관 옥상") + // .build()); + // } + // + // @DisplayName("수강생 정보를 불러온다.") + // @Test + // public void searchStudentsTest() { + // + // //given + // List students = new ArrayList<>(); + // for (int i = 0; i < 10; i++) { + // entityManager.persist(getTestBasicMember(String.valueOf(100000+i), "010-0000-000" + + // i)); + // students.add(new Student(lecture, new StudentId(String.valueOf(100000+i)))); + // } + // studentRepository.saveAll(students); + // + // //when + // Integer lectureId = (Integer) ReflectionTestUtils.getField(lecture, "id"); + // Page page = studentRepository.searchStudents(lectureId, + // PageRequest.of(0, 25)); + // + // //then + // assertThat(page.getTotalElements()).isEqualTo(10); + // assertThat(page.getNumberOfElements()).isEqualTo(10); + // assertThat(page.getTotalPages()).isEqualTo(1); + // assertThat(page.getContent().get(0)).extracting("StudentId").isEqualTo(100000); + // } } diff --git a/resource-server/src/test/java/com/inhabas/api/domain/lecture/usecase/LectureSecurityCheckerTest.java b/resource-server/src/test/java/com/inhabas/api/domain/lecture/usecase/LectureSecurityCheckerTest.java index 5f344e20..08596505 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/lecture/usecase/LectureSecurityCheckerTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/lecture/usecase/LectureSecurityCheckerTest.java @@ -1,97 +1,79 @@ package com.inhabas.api.domain.lecture.usecase; -import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.StudentId; -import com.inhabas.api.domain.lecture.domain.Lecture; -import com.inhabas.api.domain.lecture.repository.LectureRepository; -import com.inhabas.api.web.LectureController; -import com.inhabas.testAnnotataion.NoSecureWebMvcTest; -import com.inhabas.testAnnotataion.WithMockJwtAuthenticationToken; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.annotation.Import; -import org.springframework.test.util.ReflectionTestUtils; - -import java.time.LocalDateTime; -import java.util.Optional; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.given; +import com.inhabas.api.domain.lecture.repository.LectureRepository; +import com.inhabas.api.web.LectureController; +import com.inhabas.testAnnotataion.NoSecureWebMvcTest; @NoSecureWebMvcTest(LectureController.class) @Import(LectureSecurityChecker.class) public class LectureSecurityCheckerTest { - @Autowired - private LectureSecurityChecker securityChecker; - - @MockBean - private LectureRepository repository; + @Autowired private LectureSecurityChecker securityChecker; - @MockBean - private LectureServiceImpl lectureService; + @MockBean private LectureRepository repository; - @MockBean - private LectureStudentServiceImpl studentService; + @MockBean private LectureServiceImpl lectureService; + @MockBean private LectureStudentServiceImpl studentService; -// @DisplayName("강의자만 접근할 수 있다.") -// @Test -// @WithMockJwtAuthenticationToken(memberId = 1L) -// public void instructorOnlyTest() { -// -// //given -// StudentId lecturerId = new StudentId("12171652"); -// Lecture lecture = Lecture.builder() -// .title("절권도 배우기") -// .chief(lecturerId) -// .applyDeadline(LocalDateTime.of(9011, 1, 1, 1, 1, 1)) -// .curriculumDetails("1주차: 빅데이터에 기반한 공격패턴분석
2주차: ...") -// .daysOfWeek("월 금") -// .introduction("호신술을 배워보자") -// .method(1) -// .participantsLimits(30) -// .place("6호관 옥상") -// .build(); -// ReflectionTestUtils.setField(lecture, "id", 1); -// given(repository.findById(any())).willReturn(Optional.of(lecture)); -// -// //when -// boolean result = securityChecker.instructorOnly(1); -// -// //then -// assertTrue(result); -// } -// -// @DisplayName("강의자가 아니어서 접근할 수 없다.") -// @Test -// @WithMockJwtAuthenticationToken(memberId = 11111111L) -// public void instructorOnlyDenyTest() { -// -// //given -// StudentId lecturerId = new StudentId("12171652"); -// Lecture lecture = Lecture.builder() -// .title("절권도 배우기") -// .chief(lecturerId) -// .applyDeadline(LocalDateTime.of(9011, 1, 1, 1, 1, 1)) -// .curriculumDetails("1주차: 빅데이터에 기반한 공격패턴분석
2주차: ...") -// .daysOfWeek("월 금") -// .introduction("호신술을 배워보자") -// .method(1) -// .participantsLimits(30) -// .place("6호관 옥상") -// .build(); -// ReflectionTestUtils.setField(lecture, "id", 1); -// given(repository.findById(any())).willReturn(Optional.of(lecture)); -// -// //when -// boolean result = securityChecker.instructorOnly(1); -// -// //then -// assertFalse(result); -// } + // @DisplayName("강의자만 접근할 수 있다.") + // @Test + // @WithMockJwtAuthenticationToken(memberId = 1L) + // public void instructorOnlyTest() { + // + // //given + // StudentId lecturerId = new StudentId("12171652"); + // Lecture lecture = Lecture.builder() + // .title("절권도 배우기") + // .chief(lecturerId) + // .applyDeadline(LocalDateTime.of(9011, 1, 1, 1, 1, 1)) + // .curriculumDetails("1주차: 빅데이터에 기반한 공격패턴분석
2주차: ...") + // .daysOfWeek("월 금") + // .introduction("호신술을 배워보자") + // .method(1) + // .participantsLimits(30) + // .place("6호관 옥상") + // .build(); + // ReflectionTestUtils.setField(lecture, "id", 1); + // given(repository.findById(any())).willReturn(Optional.of(lecture)); + // + // //when + // boolean result = securityChecker.instructorOnly(1); + // + // //then + // assertTrue(result); + // } + // + // @DisplayName("강의자가 아니어서 접근할 수 없다.") + // @Test + // @WithMockJwtAuthenticationToken(memberId = 11111111L) + // public void instructorOnlyDenyTest() { + // + // //given + // StudentId lecturerId = new StudentId("12171652"); + // Lecture lecture = Lecture.builder() + // .title("절권도 배우기") + // .chief(lecturerId) + // .applyDeadline(LocalDateTime.of(9011, 1, 1, 1, 1, 1)) + // .curriculumDetails("1주차: 빅데이터에 기반한 공격패턴분석
2주차: ...") + // .daysOfWeek("월 금") + // .introduction("호신술을 배워보자") + // .method(1) + // .participantsLimits(30) + // .place("6호관 옥상") + // .build(); + // ReflectionTestUtils.setField(lecture, "id", 1); + // given(repository.findById(any())).willReturn(Optional.of(lecture)); + // + // //when + // boolean result = securityChecker.instructorOnly(1); + // + // //then + // assertFalse(result); + // } } diff --git a/resource-server/src/test/java/com/inhabas/api/domain/lecture/usecase/LectureServiceImplTest.java b/resource-server/src/test/java/com/inhabas/api/domain/lecture/usecase/LectureServiceImplTest.java index f3a03d1d..9cd68a49 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/lecture/usecase/LectureServiceImplTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/lecture/usecase/LectureServiceImplTest.java @@ -1,363 +1,373 @@ package com.inhabas.api.domain.lecture.usecase; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.BDDMockito.given; +import static org.mockito.BDDMockito.then; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.times; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Optional; + +import org.springframework.data.domain.PageRequest; +import org.springframework.test.util.ReflectionTestUtils; + import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.StudentId; import com.inhabas.api.domain.lecture.LectureCannotModifiableException; import com.inhabas.api.domain.lecture.domain.Lecture; import com.inhabas.api.domain.lecture.domain.valueObject.LectureStatus; import com.inhabas.api.domain.lecture.dto.LectureDetailDto; import com.inhabas.api.domain.lecture.dto.LectureRegisterForm; -import com.inhabas.api.domain.lecture.dto.LectureUpdateForm; import com.inhabas.api.domain.lecture.dto.LectureStatusUpdateRequest; +import com.inhabas.api.domain.lecture.dto.LectureUpdateForm; import com.inhabas.api.domain.lecture.repository.LectureRepository; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import org.springframework.data.domain.PageRequest; -import org.springframework.test.util.ReflectionTestUtils; - -import java.time.LocalDateTime; -import java.util.List; -import java.util.Optional; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.BDDMockito.given; -import static org.mockito.BDDMockito.then; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.times; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; @ExtendWith(MockitoExtension.class) public class LectureServiceImplTest { - @InjectMocks - private LectureServiceImpl service; - - @Mock - private LectureRepository repository; - - @DisplayName("강의실 개설 글 작성") - @Test - public void createTest() { - - //given - StudentId chief = new StudentId("12171652"); - given(repository.save(any())).willReturn(null); - LectureRegisterForm form = LectureRegisterForm.builder() - .title("절권도 배우기") - .applyDeadLine(LocalDateTime.of(9011, 1, 1, 1, 1, 1)) - .curriculumDetails("1주차: 빅데이터에 기반한 공격패턴분석
2주차: ...") - .daysOfWeeks("월 금") - .introduction("호신술을 배워보자") - .method(1) - .participantsLimits(30) - .place("6호관 옥상") - .build(); - - //when - service.create(form, chief); - - //then - then(repository).should(times(1)).save(any()); - } - -// @DisplayName("강의실 정보 수정") -// @Test -// public void updateTest() { -// -// //given -// StudentId chief = new StudentId("12171652"); -// Lecture origin = Lecture.builder() -// .title("절권도 배우기") -// .chief(chief) -// .applyDeadline(LocalDateTime.of(9011, 1, 1, 1, 1, 1)) -// .curriculumDetails("1주차: 빅데이터에 기반한 공격패턴분석
2주차: ...") -// .daysOfWeek("월 금") -// .introduction("호신술을 배워보자") -// .method(1) -// .participantsLimits(30) -// .place("6호관 옥상") -// .build(); -// ReflectionTestUtils.setField(origin, "id", 1); -// given(repository.findById(anyInt())).willReturn(Optional.of(origin)); -// LectureUpdateForm form = LectureUpdateForm.builder() -// .id(1) -// .title("절권도 배우기") -// .applyDeadLine(LocalDateTime.of(9011, 1, 1, 1, 1, 1)) -// .curriculumDetails("1주차: 빅데이터에 기반한 공격패턴분석
2주차: ...") -// .daysOfWeeks("월 금") -// .introduction("호신술을 배워보자") -// .method(1) -// .participantsLimits(30) -// .place("6호관 옥상") -// .build(); -// -// //when -// service.update(form, new StudentId("12171652")); -// -// //then -// then(repository).should(times(1)).findById(any()); -// } - - @DisplayName("강의실 담당자 외에는 수정 불가") - @Test - public void cannotModifyTest() { - - //given - StudentId chief = new StudentId("12171652"); - StudentId attacker = new StudentId("1"); - Lecture origin = Lecture.builder() - .title("절권도 배우기") - .chief(chief) - .applyDeadline(LocalDateTime.of(9011, 1, 1, 1, 1, 1)) - .curriculumDetails("1주차: 빅데이터에 기반한 공격패턴분석
2주차: ...") - .daysOfWeek("월 금") - .introduction("호신술을 배워보자") - .method(1) - .participantsLimits(30) - .place("6호관 옥상") - .build(); - ReflectionTestUtils.setField(origin, "id", 1); - given(repository.findById(anyInt())).willReturn(Optional.of(origin)); - LectureUpdateForm form = LectureUpdateForm.builder() - .id(1) - .title("절권도 배우기") - .applyDeadLine(LocalDateTime.of(9011, 1, 1, 1, 1, 1)) - .curriculumDetails("1주차: 빅데이터에 기반한 공격패턴분석
2주차: ...") - .daysOfWeeks("월 금") - .introduction("호신술을 배워보자") - .method(1) - .participantsLimits(30) - .place("6호관 옥상") - .build(); - - //when - Assertions.assertThrows(LectureCannotModifiableException.class, - () -> service.update(form, attacker)); - - //then - then(repository).should(times(1)).findById(any()); - } - - @DisplayName("강의실 삭제") - @Test - public void deleteTest() { - - //given - StudentId chief = new StudentId("12171652"); - Lecture origin = Lecture.builder() - .title("절권도 배우기") - .chief(chief) - .applyDeadline(LocalDateTime.of(9011, 1, 1, 1, 1, 1)) - .curriculumDetails("1주차: 빅데이터에 기반한 공격패턴분석
2주차: ...") - .daysOfWeek("월 금") - .introduction("호신술을 배워보자") - .method(1) - .participantsLimits(30) - .place("6호관 옥상") - .build(); - ReflectionTestUtils.setField(origin, "id", 1); - given(repository.findById(anyInt())).willReturn(Optional.ofNullable(origin)); - doNothing().when(repository).delete(any()); - - //when - service.delete(1, chief); - - //then - then(repository).should(times(1)).findById(any()); - then(repository).should(times(1)).delete(any()); - } - - @DisplayName("강의실 담당자 외에는 삭제 불가") - @Test - public void cannotDeleteTest() { - - //given - StudentId chief = new StudentId("12171652"); - StudentId attacker = new StudentId("1"); - Lecture origin = Lecture.builder() - .title("절권도 배우기") - .chief(chief) - .applyDeadline(LocalDateTime.of(9011, 1, 1, 1, 1, 1)) - .curriculumDetails("1주차: 빅데이터에 기반한 공격패턴분석
2주차: ...") - .daysOfWeek("월 금") - .introduction("호신술을 배워보자") - .method(1) - .participantsLimits(30) - .place("6호관 옥상") - .build(); - ReflectionTestUtils.setField(origin, "id", 1); - given(repository.findById(anyInt())).willReturn(Optional.of(origin)); - - //when - Assertions.assertThrows(LectureCannotModifiableException.class, - () -> service.delete(1, attacker)); - - //then - then(repository).should(times(1)).findById(any()); - then(repository).should(times(0)).delete(any()); - } - - @DisplayName("강의실 정보 조회") - @Test - public void getTest() { - - //given - LectureDetailDto expectedDto = LectureDetailDto.builder() - .title("절권도 강의") - .chief(new LectureDetailDto.MemberInfo(12171652, "산업경영공학과", "유동현")) - .applyDeadLine(LocalDateTime.of(9022, 7, 31, 17, 11, 36)) - .created(LocalDateTime.of(9022, 7, 23, 17, 11, 36)) - .updated(null) - .daysOfWeeks("월 금") - .introduction("호신술을 배워보자") - .curriculumDetails("1주차: 빅데이터에 기반한 공격패턴분석
2주차: ...") - .method(1) - .paid(false) - .participantsLimits(30) - .place("구내식당") - .rejectReason(null) - .state(LectureStatus.WAITING) - .build() - .setCoInstructors(List.of( - new LectureDetailDto.MemberInfo(12345678, "스마트모빌리티공학과", "윤예진"), - new LectureDetailDto.MemberInfo(87654321, "통계학과", "나까무라철수") - )); - given(repository.getDetails(anyInt())).willReturn(Optional.of(expectedDto)); - - //when - service.get(1); - - //then - then(repository).should(times(1)).getDetails(any()); - } - - @DisplayName("강의실 목록 조회") - @Test - public void getListTest() { - - //given - given(repository.getList(any())).willReturn(null); - - //when - service.getList(PageRequest.of(0, 6)); - - //then - then(repository).should(times(1)).getList(any()); - } - - @DisplayName("대기 강의를 승인한다.") - @Test - public void approveTest() { - - //given - Lecture origin = Lecture.builder() - .title("절권도 배우기") - .chief(new StudentId("12171652")) - .applyDeadline(LocalDateTime.of(9011, 1, 1, 1, 1, 1)) - .curriculumDetails("1주차: 빅데이터에 기반한 공격패턴분석
2주차: ...") - .daysOfWeek("월 금") - .introduction("호신술을 배워보자") - .method(1) - .participantsLimits(30) - .place("6호관 옥상") - .build(); - ReflectionTestUtils.setField(origin, "id", 1); - given(repository.findById(any())).willReturn(Optional.of(origin)); - - //when - LectureStatusUpdateRequest request = new LectureStatusUpdateRequest(); - ReflectionTestUtils.setField(request, "status", LectureStatus.PROGRESSING); - service.approveOrDeny(1, request); - - //then - LectureStatus status = (LectureStatus) ReflectionTestUtils.getField(request, "status"); - assertThat(status).isEqualTo(LectureStatus.PROGRESSING); - } - - @DisplayName("대기 강의를 거절한다.") - @Test - public void denyTest() { - //given - Lecture origin = Lecture.builder() - .title("절권도 배우기") - .chief(new StudentId("12171652")) - .applyDeadline(LocalDateTime.of(9011, 1, 1, 1, 1, 1)) - .curriculumDetails("1주차: 빅데이터에 기반한 공격패턴분석
2주차: ...") - .daysOfWeek("월 금") - .introduction("호신술을 배워보자") - .method(1) - .participantsLimits(30) - .place("6호관 옥상") - .build(); - ReflectionTestUtils.setField(origin, "id", 1); - given(repository.findById(any())).willReturn(Optional.of(origin)); - - //when - LectureStatusUpdateRequest request = new LectureStatusUpdateRequest(); - ReflectionTestUtils.setField(request, "status", LectureStatus.DENIED); - service.approveOrDeny(1, request); - - //then - LectureStatus status = (LectureStatus) ReflectionTestUtils.getField(request, "status"); - assertThat(status).isEqualTo(LectureStatus.DENIED); - } - - @DisplayName("강의를 강제 종료시킬 수는 없다.") - @Test - public void cannotTerminateLectureTest() { - - //given - Lecture origin = Lecture.builder() - .title("절권도 배우기") - .chief(new StudentId("12171652")) - .applyDeadline(LocalDateTime.of(9011, 1, 1, 1, 1, 1)) - .curriculumDetails("1주차: 빅데이터에 기반한 공격패턴분석
2주차: ...") - .daysOfWeek("월 금") - .introduction("호신술을 배워보자") - .method(1) - .participantsLimits(30) - .place("6호관 옥상") - .build(); - ReflectionTestUtils.setField(origin, "id", 1); - given(repository.findById(any())).willReturn(Optional.of(origin)); - - //when - LectureStatusUpdateRequest request = new LectureStatusUpdateRequest(); - ReflectionTestUtils.setField(request, "status", LectureStatus.TERMINATED); - - Assertions.assertThrows(IllegalArgumentException.class, - () -> service.approveOrDeny(1, request)); - } - - @DisplayName("강의를 다시 대기 상태로 되돌릴 수 없다.") - @Test - public void cannotMakeLectureWaitedTest() { - - //given - Lecture origin = Lecture.builder() - .title("절권도 배우기") - .chief(new StudentId("12171652")) - .applyDeadline(LocalDateTime.of(9011, 1, 1, 1, 1, 1)) - .curriculumDetails("1주차: 빅데이터에 기반한 공격패턴분석
2주차: ...") - .daysOfWeek("월 금") - .introduction("호신술을 배워보자") - .method(1) - .participantsLimits(30) - .place("6호관 옥상") - .build(); - ReflectionTestUtils.setField(origin, "id", 1); - given(repository.findById(any())).willReturn(Optional.of(origin)); - - //when - LectureStatusUpdateRequest request = new LectureStatusUpdateRequest(); - ReflectionTestUtils.setField(request, "status", LectureStatus.WAITING); - - Assertions.assertThrows(IllegalArgumentException.class, - () -> service.approveOrDeny(1, request)); - } + @InjectMocks private LectureServiceImpl service; + + @Mock private LectureRepository repository; + + @DisplayName("강의실 개설 글 작성") + @Test + public void createTest() { + + // given + StudentId chief = new StudentId("12171652"); + given(repository.save(any())).willReturn(null); + LectureRegisterForm form = + LectureRegisterForm.builder() + .title("절권도 배우기") + .applyDeadLine(LocalDateTime.of(9011, 1, 1, 1, 1, 1)) + .curriculumDetails("1주차: 빅데이터에 기반한 공격패턴분석
2주차: ...") + .daysOfWeeks("월 금") + .introduction("호신술을 배워보자") + .method(1) + .participantsLimits(30) + .place("6호관 옥상") + .build(); + + // when + service.create(form, chief); + + // then + then(repository).should(times(1)).save(any()); + } + + // @DisplayName("강의실 정보 수정") + // @Test + // public void updateTest() { + // + // //given + // StudentId chief = new StudentId("12171652"); + // Lecture origin = Lecture.builder() + // .title("절권도 배우기") + // .chief(chief) + // .applyDeadline(LocalDateTime.of(9011, 1, 1, 1, 1, 1)) + // .curriculumDetails("1주차: 빅데이터에 기반한 공격패턴분석
2주차: ...") + // .daysOfWeek("월 금") + // .introduction("호신술을 배워보자") + // .method(1) + // .participantsLimits(30) + // .place("6호관 옥상") + // .build(); + // ReflectionTestUtils.setField(origin, "id", 1); + // given(repository.findById(anyInt())).willReturn(Optional.of(origin)); + // LectureUpdateForm form = LectureUpdateForm.builder() + // .id(1) + // .title("절권도 배우기") + // .applyDeadLine(LocalDateTime.of(9011, 1, 1, 1, 1, 1)) + // .curriculumDetails("1주차: 빅데이터에 기반한 공격패턴분석
2주차: ...") + // .daysOfWeeks("월 금") + // .introduction("호신술을 배워보자") + // .method(1) + // .participantsLimits(30) + // .place("6호관 옥상") + // .build(); + // + // //when + // service.update(form, new StudentId("12171652")); + // + // //then + // then(repository).should(times(1)).findById(any()); + // } + + @DisplayName("강의실 담당자 외에는 수정 불가") + @Test + public void cannotModifyTest() { + + // given + StudentId chief = new StudentId("12171652"); + StudentId attacker = new StudentId("1"); + Lecture origin = + Lecture.builder() + .title("절권도 배우기") + .chief(chief) + .applyDeadline(LocalDateTime.of(9011, 1, 1, 1, 1, 1)) + .curriculumDetails("1주차: 빅데이터에 기반한 공격패턴분석
2주차: ...") + .daysOfWeek("월 금") + .introduction("호신술을 배워보자") + .method(1) + .participantsLimits(30) + .place("6호관 옥상") + .build(); + ReflectionTestUtils.setField(origin, "id", 1); + given(repository.findById(anyInt())).willReturn(Optional.of(origin)); + LectureUpdateForm form = + LectureUpdateForm.builder() + .id(1) + .title("절권도 배우기") + .applyDeadLine(LocalDateTime.of(9011, 1, 1, 1, 1, 1)) + .curriculumDetails("1주차: 빅데이터에 기반한 공격패턴분석
2주차: ...") + .daysOfWeeks("월 금") + .introduction("호신술을 배워보자") + .method(1) + .participantsLimits(30) + .place("6호관 옥상") + .build(); + + // when + Assertions.assertThrows( + LectureCannotModifiableException.class, () -> service.update(form, attacker)); + + // then + then(repository).should(times(1)).findById(any()); + } + + @DisplayName("강의실 삭제") + @Test + public void deleteTest() { + + // given + StudentId chief = new StudentId("12171652"); + Lecture origin = + Lecture.builder() + .title("절권도 배우기") + .chief(chief) + .applyDeadline(LocalDateTime.of(9011, 1, 1, 1, 1, 1)) + .curriculumDetails("1주차: 빅데이터에 기반한 공격패턴분석
2주차: ...") + .daysOfWeek("월 금") + .introduction("호신술을 배워보자") + .method(1) + .participantsLimits(30) + .place("6호관 옥상") + .build(); + ReflectionTestUtils.setField(origin, "id", 1); + given(repository.findById(anyInt())).willReturn(Optional.ofNullable(origin)); + doNothing().when(repository).delete(any()); + + // when + service.delete(1, chief); + + // then + then(repository).should(times(1)).findById(any()); + then(repository).should(times(1)).delete(any()); + } + + @DisplayName("강의실 담당자 외에는 삭제 불가") + @Test + public void cannotDeleteTest() { + + // given + StudentId chief = new StudentId("12171652"); + StudentId attacker = new StudentId("1"); + Lecture origin = + Lecture.builder() + .title("절권도 배우기") + .chief(chief) + .applyDeadline(LocalDateTime.of(9011, 1, 1, 1, 1, 1)) + .curriculumDetails("1주차: 빅데이터에 기반한 공격패턴분석
2주차: ...") + .daysOfWeek("월 금") + .introduction("호신술을 배워보자") + .method(1) + .participantsLimits(30) + .place("6호관 옥상") + .build(); + ReflectionTestUtils.setField(origin, "id", 1); + given(repository.findById(anyInt())).willReturn(Optional.of(origin)); + + // when + Assertions.assertThrows( + LectureCannotModifiableException.class, () -> service.delete(1, attacker)); + + // then + then(repository).should(times(1)).findById(any()); + then(repository).should(times(0)).delete(any()); + } + + @DisplayName("강의실 정보 조회") + @Test + public void getTest() { + + // given + LectureDetailDto expectedDto = + LectureDetailDto.builder() + .title("절권도 강의") + .chief(new LectureDetailDto.MemberInfo(12171652, "산업경영공학과", "유동현")) + .applyDeadLine(LocalDateTime.of(9022, 7, 31, 17, 11, 36)) + .created(LocalDateTime.of(9022, 7, 23, 17, 11, 36)) + .updated(null) + .daysOfWeeks("월 금") + .introduction("호신술을 배워보자") + .curriculumDetails("1주차: 빅데이터에 기반한 공격패턴분석
2주차: ...") + .method(1) + .paid(false) + .participantsLimits(30) + .place("구내식당") + .rejectReason(null) + .state(LectureStatus.WAITING) + .build() + .setCoInstructors( + List.of( + new LectureDetailDto.MemberInfo(12345678, "스마트모빌리티공학과", "윤예진"), + new LectureDetailDto.MemberInfo(87654321, "통계학과", "나까무라철수"))); + given(repository.getDetails(anyInt())).willReturn(Optional.of(expectedDto)); + + // when + service.get(1); + + // then + then(repository).should(times(1)).getDetails(any()); + } + + @DisplayName("강의실 목록 조회") + @Test + public void getListTest() { + + // given + given(repository.getList(any())).willReturn(null); + + // when + service.getList(PageRequest.of(0, 6)); + + // then + then(repository).should(times(1)).getList(any()); + } + + @DisplayName("대기 강의를 승인한다.") + @Test + public void approveTest() { + + // given + Lecture origin = + Lecture.builder() + .title("절권도 배우기") + .chief(new StudentId("12171652")) + .applyDeadline(LocalDateTime.of(9011, 1, 1, 1, 1, 1)) + .curriculumDetails("1주차: 빅데이터에 기반한 공격패턴분석
2주차: ...") + .daysOfWeek("월 금") + .introduction("호신술을 배워보자") + .method(1) + .participantsLimits(30) + .place("6호관 옥상") + .build(); + ReflectionTestUtils.setField(origin, "id", 1); + given(repository.findById(any())).willReturn(Optional.of(origin)); + + // when + LectureStatusUpdateRequest request = new LectureStatusUpdateRequest(); + ReflectionTestUtils.setField(request, "status", LectureStatus.PROGRESSING); + service.approveOrDeny(1, request); + + // then + LectureStatus status = (LectureStatus) ReflectionTestUtils.getField(request, "status"); + assertThat(status).isEqualTo(LectureStatus.PROGRESSING); + } + + @DisplayName("대기 강의를 거절한다.") + @Test + public void denyTest() { + // given + Lecture origin = + Lecture.builder() + .title("절권도 배우기") + .chief(new StudentId("12171652")) + .applyDeadline(LocalDateTime.of(9011, 1, 1, 1, 1, 1)) + .curriculumDetails("1주차: 빅데이터에 기반한 공격패턴분석
2주차: ...") + .daysOfWeek("월 금") + .introduction("호신술을 배워보자") + .method(1) + .participantsLimits(30) + .place("6호관 옥상") + .build(); + ReflectionTestUtils.setField(origin, "id", 1); + given(repository.findById(any())).willReturn(Optional.of(origin)); + + // when + LectureStatusUpdateRequest request = new LectureStatusUpdateRequest(); + ReflectionTestUtils.setField(request, "status", LectureStatus.DENIED); + service.approveOrDeny(1, request); + + // then + LectureStatus status = (LectureStatus) ReflectionTestUtils.getField(request, "status"); + assertThat(status).isEqualTo(LectureStatus.DENIED); + } + + @DisplayName("강의를 강제 종료시킬 수는 없다.") + @Test + public void cannotTerminateLectureTest() { + + // given + Lecture origin = + Lecture.builder() + .title("절권도 배우기") + .chief(new StudentId("12171652")) + .applyDeadline(LocalDateTime.of(9011, 1, 1, 1, 1, 1)) + .curriculumDetails("1주차: 빅데이터에 기반한 공격패턴분석
2주차: ...") + .daysOfWeek("월 금") + .introduction("호신술을 배워보자") + .method(1) + .participantsLimits(30) + .place("6호관 옥상") + .build(); + ReflectionTestUtils.setField(origin, "id", 1); + given(repository.findById(any())).willReturn(Optional.of(origin)); + + // when + LectureStatusUpdateRequest request = new LectureStatusUpdateRequest(); + ReflectionTestUtils.setField(request, "status", LectureStatus.TERMINATED); + + Assertions.assertThrows( + IllegalArgumentException.class, () -> service.approveOrDeny(1, request)); + } + + @DisplayName("강의를 다시 대기 상태로 되돌릴 수 없다.") + @Test + public void cannotMakeLectureWaitedTest() { + + // given + Lecture origin = + Lecture.builder() + .title("절권도 배우기") + .chief(new StudentId("12171652")) + .applyDeadline(LocalDateTime.of(9011, 1, 1, 1, 1, 1)) + .curriculumDetails("1주차: 빅데이터에 기반한 공격패턴분석
2주차: ...") + .daysOfWeek("월 금") + .introduction("호신술을 배워보자") + .method(1) + .participantsLimits(30) + .place("6호관 옥상") + .build(); + ReflectionTestUtils.setField(origin, "id", 1); + given(repository.findById(any())).willReturn(Optional.of(origin)); + + // when + LectureStatusUpdateRequest request = new LectureStatusUpdateRequest(); + ReflectionTestUtils.setField(request, "status", LectureStatus.WAITING); + + Assertions.assertThrows( + IllegalArgumentException.class, () -> service.approveOrDeny(1, request)); + } } diff --git a/resource-server/src/test/java/com/inhabas/api/domain/lecture/usecase/LectureStudentServiceDBTest.java b/resource-server/src/test/java/com/inhabas/api/domain/lecture/usecase/LectureStudentServiceDBTest.java index 2124a876..3769bd43 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/lecture/usecase/LectureStudentServiceDBTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/lecture/usecase/LectureStudentServiceDBTest.java @@ -1,95 +1,79 @@ package com.inhabas.api.domain.lecture.usecase; +import javax.persistence.EntityManager; + +import org.springframework.beans.factory.annotation.Autowired; + import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; import com.inhabas.api.domain.lecture.domain.Lecture; -import com.inhabas.api.domain.lecture.domain.Student; import com.inhabas.api.domain.lecture.repository.LectureRepository; import com.inhabas.api.domain.lecture.repository.StudentRepository; import com.inhabas.testAnnotataion.DefaultDataJpaTest; -import org.assertj.core.api.Assertions; -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.dao.DataIntegrityViolationException; -import org.springframework.test.util.ReflectionTestUtils; - -import javax.persistence.EntityManager; -import java.time.LocalDateTime; -import java.util.List; - -import static com.inhabas.api.domain.member.domain.entity.MemberTest.basicMember1; -import static com.inhabas.api.domain.member.domain.entity.MemberTest.basicMember2; -import static org.junit.jupiter.api.Assertions.assertThrows; @DefaultDataJpaTest public class LectureStudentServiceDBTest { - @Autowired - private StudentRepository studentRepository; - - @Autowired - private LectureRepository lectureRepository; + @Autowired private StudentRepository studentRepository; - @Autowired - private EntityManager entityManager; + @Autowired private LectureRepository lectureRepository; - private LectureStudentService studentService; + @Autowired private EntityManager entityManager; - private Member lecturer; - private Member student; - private Lecture lecture; + private LectureStudentService studentService; -// @BeforeEach -// public void setUp() { -// studentService = new LectureStudentServiceImpl(studentRepository, lectureRepository); -// -// lecturer = basicMember1(); -// entityManager.persist(lecturer); -// -// student = basicMember2(); -// entityManager.persist(student); -// -// lecture = lectureRepository.save(Lecture.builder() -// .title("절권도 배우기") -// .chief(lecturer.getId()) -// .applyDeadline(LocalDateTime.of(9011, 1, 1, 1, 1, 1)) -// .curriculumDetails("1주차: 빅데이터에 기반한 공격패턴분석
2주차: ...") -// .daysOfWeek("월 금") -// .introduction("호신술을 배워보자") -// .method(1) -// .participantsLimits(30) -// .place("6호관 옥상") -// .build()); -// } + private Member lecturer; + private Member student; + private Lecture lecture; -// @DisplayName("수강생 등록") -// @Test -// public void enrollTest() { -// -// //given -// Integer id = (Integer) ReflectionTestUtils.getField(lecture, "id"); -// -// //when -// studentService.enroll(id, student.getId()); -// -// //then -// List students = studentRepository.findAll(); -// Assertions.assertThat(students).hasSize(1); -// } + // @BeforeEach + // public void setUp() { + // studentService = new LectureStudentServiceImpl(studentRepository, lectureRepository); + // + // lecturer = basicMember1(); + // entityManager.persist(lecturer); + // + // student = basicMember2(); + // entityManager.persist(student); + // + // lecture = lectureRepository.save(Lecture.builder() + // .title("절권도 배우기") + // .chief(lecturer.getId()) + // .applyDeadline(LocalDateTime.of(9011, 1, 1, 1, 1, 1)) + // .curriculumDetails("1주차: 빅데이터에 기반한 공격패턴분석
2주차: ...") + // .daysOfWeek("월 금") + // .introduction("호신술을 배워보자") + // .method(1) + // .participantsLimits(30) + // .place("6호관 옥상") + // .build()); + // } -// @DisplayName("중복 등록 시 unique constraint 위반") -// @Test -// public void uniqueConstraintTest() { -// -// //given -// Integer id = (Integer) ReflectionTestUtils.getField(lecture, "id"); -// studentService.enroll(id, student.getId()); -// -// //when -// assertThrows(DataIntegrityViolationException.class, -// ()->studentService.enroll(id, student.getId())); -// } + // @DisplayName("수강생 등록") + // @Test + // public void enrollTest() { + // + // //given + // Integer id = (Integer) ReflectionTestUtils.getField(lecture, "id"); + // + // //when + // studentService.enroll(id, student.getId()); + // + // //then + // List students = studentRepository.findAll(); + // Assertions.assertThat(students).hasSize(1); + // } + // @DisplayName("중복 등록 시 unique constraint 위반") + // @Test + // public void uniqueConstraintTest() { + // + // //given + // Integer id = (Integer) ReflectionTestUtils.getField(lecture, "id"); + // studentService.enroll(id, student.getId()); + // + // //when + // assertThrows(DataIntegrityViolationException.class, + // ()->studentService.enroll(id, student.getId())); + // } } diff --git a/resource-server/src/test/java/com/inhabas/api/domain/lecture/usecase/LectureStudentServiceMockTest.java b/resource-server/src/test/java/com/inhabas/api/domain/lecture/usecase/LectureStudentServiceMockTest.java index 751f5a4f..4bd65663 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/lecture/usecase/LectureStudentServiceMockTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/lecture/usecase/LectureStudentServiceMockTest.java @@ -1,141 +1,143 @@ package com.inhabas.api.domain.lecture.usecase; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.mockito.BDDMockito.then; +import static org.mockito.Mockito.times; + +import java.time.LocalDateTime; +import java.util.Optional; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.test.util.ReflectionTestUtils; + import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.StudentId; import com.inhabas.api.domain.lecture.domain.Lecture; import com.inhabas.api.domain.lecture.domain.Student; import com.inhabas.api.domain.lecture.domain.valueObject.StudentStatus; import com.inhabas.api.domain.lecture.repository.LectureRepository; import com.inhabas.api.domain.lecture.repository.StudentRepository; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageRequest; -import org.springframework.test.util.ReflectionTestUtils; -import java.time.LocalDateTime; -import java.util.Optional; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.given; -import static org.mockito.BDDMockito.then; -import static org.mockito.Mockito.times; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; @ExtendWith(MockitoExtension.class) public class LectureStudentServiceMockTest { - @InjectMocks - private LectureStudentServiceImpl studentService; - - @Mock - private StudentRepository studentRepository; - - @Mock - private LectureRepository lectureRepository; - - @DisplayName("수강생이 강의를 신청한다.") - @Test - public void enrollTest() { - - //given - StudentId lecturerId = new StudentId("12171652"); - Lecture lecture = Lecture.builder() - .title("절권도 배우기") - .chief(lecturerId) - .applyDeadline(LocalDateTime.of(9011, 1, 1, 1, 1, 1)) - .curriculumDetails("1주차: 빅데이터에 기반한 공격패턴분석
2주차: ...") - .daysOfWeek("월 금") - .introduction("호신술을 배워보자") - .method(1) - .participantsLimits(30) - .place("6호관 옥상") - .build(); - ReflectionTestUtils.setField(lecture, "id", 1); - given(lectureRepository.findById(any())).willReturn(Optional.of(lecture)); - given(studentRepository.save(any())).willReturn(null); - - //when - studentService.enroll(1, new StudentId("12212242")); - - //then - then(studentRepository).should(times(1)).save(any()); - then(lectureRepository).should(times(1)).findById(any()); - } - - - @DisplayName("강의자를 수강생으로 등록할 수는 없다.") - @Test - public void cannotEnrollLecturerTest() { - - //given - StudentId lecturerId = new StudentId("12171652"); - Lecture lecture = Lecture.builder() - .title("절권도 배우기") - .chief(lecturerId) - .applyDeadline(LocalDateTime.of(9011, 1, 1, 1, 1, 1)) - .curriculumDetails("1주차: 빅데이터에 기반한 공격패턴분석
2주차: ...") - .daysOfWeek("월 금") - .introduction("호신술을 배워보자") - .method(1) - .participantsLimits(30) - .place("6호관 옥상") - .build(); - ReflectionTestUtils.setField(lecture, "id", 1); - given(lectureRepository.findById(any())).willReturn(Optional.of(lecture)); - - //when - Assertions.assertThrows(IllegalArgumentException.class, - ()->studentService.enroll(1, lecturerId)); - } - - @DisplayName("수강생이 강의를 탈퇴한다.") - @Test - public void exitLecture() { - - //given - StudentId lecturerId = new StudentId("12171652"); - Lecture lecture = Lecture.builder() - .title("절권도 배우기") - .chief(lecturerId) - .applyDeadline(LocalDateTime.of(9011, 1, 1, 1, 1, 1)) - .curriculumDetails("1주차: 빅데이터에 기반한 공격패턴분석
2주차: ...") - .daysOfWeek("월 금") - .introduction("호신술을 배워보자") - .method(1) - .participantsLimits(30) - .place("6호관 옥상") - .build(); - ReflectionTestUtils.setField(lecture, "id", 1); - - StudentId studentId = new StudentId("11112222"); - Student student = new Student(lecture, studentId); - given(studentRepository.findByLectureIdAndStudentId(any(), any())).willReturn(Optional.of(student)); - - //when - studentService.exitBySelf(1, studentId); - - //then - StudentStatus status = (StudentStatus) ReflectionTestUtils.getField(student, "status"); - assertThat(status).isEqualTo(StudentStatus.EXIT); - then(studentRepository).should(times(1)).findByLectureIdAndStudentId(any(), any()); - } - - @DisplayName("수강생 정보 조회") - @Test - public void searchStudentsTest() { - - //given - given(studentRepository.searchStudents(any(), any())).willReturn(Page.empty()); - - //when - studentService.searchStudents(1, PageRequest.of(0, 25)); - - //then - then(studentRepository).should(times(1)).searchStudents(any(), any()); - } + @InjectMocks private LectureStudentServiceImpl studentService; + + @Mock private StudentRepository studentRepository; + + @Mock private LectureRepository lectureRepository; + + @DisplayName("수강생이 강의를 신청한다.") + @Test + public void enrollTest() { + + // given + StudentId lecturerId = new StudentId("12171652"); + Lecture lecture = + Lecture.builder() + .title("절권도 배우기") + .chief(lecturerId) + .applyDeadline(LocalDateTime.of(9011, 1, 1, 1, 1, 1)) + .curriculumDetails("1주차: 빅데이터에 기반한 공격패턴분석
2주차: ...") + .daysOfWeek("월 금") + .introduction("호신술을 배워보자") + .method(1) + .participantsLimits(30) + .place("6호관 옥상") + .build(); + ReflectionTestUtils.setField(lecture, "id", 1); + given(lectureRepository.findById(any())).willReturn(Optional.of(lecture)); + given(studentRepository.save(any())).willReturn(null); + + // when + studentService.enroll(1, new StudentId("12212242")); + + // then + then(studentRepository).should(times(1)).save(any()); + then(lectureRepository).should(times(1)).findById(any()); + } + + @DisplayName("강의자를 수강생으로 등록할 수는 없다.") + @Test + public void cannotEnrollLecturerTest() { + + // given + StudentId lecturerId = new StudentId("12171652"); + Lecture lecture = + Lecture.builder() + .title("절권도 배우기") + .chief(lecturerId) + .applyDeadline(LocalDateTime.of(9011, 1, 1, 1, 1, 1)) + .curriculumDetails("1주차: 빅데이터에 기반한 공격패턴분석
2주차: ...") + .daysOfWeek("월 금") + .introduction("호신술을 배워보자") + .method(1) + .participantsLimits(30) + .place("6호관 옥상") + .build(); + ReflectionTestUtils.setField(lecture, "id", 1); + given(lectureRepository.findById(any())).willReturn(Optional.of(lecture)); + + // when + Assertions.assertThrows( + IllegalArgumentException.class, () -> studentService.enroll(1, lecturerId)); + } + + @DisplayName("수강생이 강의를 탈퇴한다.") + @Test + public void exitLecture() { + + // given + StudentId lecturerId = new StudentId("12171652"); + Lecture lecture = + Lecture.builder() + .title("절권도 배우기") + .chief(lecturerId) + .applyDeadline(LocalDateTime.of(9011, 1, 1, 1, 1, 1)) + .curriculumDetails("1주차: 빅데이터에 기반한 공격패턴분석
2주차: ...") + .daysOfWeek("월 금") + .introduction("호신술을 배워보자") + .method(1) + .participantsLimits(30) + .place("6호관 옥상") + .build(); + ReflectionTestUtils.setField(lecture, "id", 1); + + StudentId studentId = new StudentId("11112222"); + Student student = new Student(lecture, studentId); + given(studentRepository.findByLectureIdAndStudentId(any(), any())) + .willReturn(Optional.of(student)); + + // when + studentService.exitBySelf(1, studentId); + + // then + StudentStatus status = (StudentStatus) ReflectionTestUtils.getField(student, "status"); + assertThat(status).isEqualTo(StudentStatus.EXIT); + then(studentRepository).should(times(1)).findByLectureIdAndStudentId(any(), any()); + } + + @DisplayName("수강생 정보 조회") + @Test + public void searchStudentsTest() { + + // given + given(studentRepository.searchStudents(any(), any())).willReturn(Page.empty()); + + // when + studentService.searchStudents(1, PageRequest.of(0, 25)); + + // then + then(studentRepository).should(times(1)).searchStudents(any(), any()); + } } diff --git a/resource-server/src/test/java/com/inhabas/api/domain/member/domain/entity/MemberTest.java b/resource-server/src/test/java/com/inhabas/api/domain/member/domain/entity/MemberTest.java index 71909083..7f053a0d 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/member/domain/entity/MemberTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/member/domain/entity/MemberTest.java @@ -1,5 +1,10 @@ package com.inhabas.api.domain.member.domain.entity; +import static com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.MemberType.UNDERGRADUATE; +import static com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.Role.*; + +import java.util.HashMap; +import java.util.Map; import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.IbasInformation; @@ -9,149 +14,164 @@ import com.inhabas.api.auth.domain.oauth2.userInfo.GoogleOAuth2UserInfo; import com.inhabas.api.auth.domain.oauth2.userInfo.OAuth2UserInfo; -import java.util.HashMap; -import java.util.Map; - -import static com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.MemberType.UNDERGRADUATE; -import static com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.Role.*; - public class MemberTest { - private static Member afterSignUpMember(Role role) { + private static Member afterSignUpMember(Role role) { - Map attributes = new HashMap<>() {{ + Map attributes = + new HashMap<>() { + { put("provider", "GOOGLE"); put("sub", "3232322332323223"); put("picture", "/static/image.jpg"); put("email", "my@gmail.com"); put("name", "조승현"); put("locale", "ko"); - }}; - OAuth2UserInfo user = new GoogleOAuth2UserInfo(attributes); - Member member = new Member(user); - member.setRole(role); - - // 회원정보 저장 - member.setStudentId("12171234"); - member.setPhone("010-1111-1111"); - member.setName("유동현"); - member.setSchoolInformation(new SchoolInformation("컴퓨터공학과", 1, 1, UNDERGRADUATE)); - return member; - - } - - public static Member chiefMember() { - return afterSignUpMember(CHIEF); - } - - public static Member executivesMember() { - return afterSignUpMember(EXECUTIVES); - } - - public static Member secretaryMember() { - return afterSignUpMember(SECRETARY); - } - - public static Member deactivatedMember() { - return afterSignUpMember(DEACTIVATED); - } - - public static Member notapprovedMember() { - return afterSignUpMember(NOT_APPROVED); - } - - public static Member basicMember1() { - Map attributes = new HashMap<>() {{ + } + }; + OAuth2UserInfo user = new GoogleOAuth2UserInfo(attributes); + Member member = new Member(user); + member.setRole(role); + + // 회원정보 저장 + member.setStudentId("12171234"); + member.setPhone("010-1111-1111"); + member.setName("유동현"); + member.setSchoolInformation(new SchoolInformation("컴퓨터공학과", 1, 1, UNDERGRADUATE)); + return member; + } + + public static Member chiefMember() { + return afterSignUpMember(CHIEF); + } + + public static Member executivesMember() { + return afterSignUpMember(EXECUTIVES); + } + + public static Member secretaryMember() { + return afterSignUpMember(SECRETARY); + } + + public static Member deactivatedMember() { + return afterSignUpMember(DEACTIVATED); + } + + public static Member notapprovedMember() { + return afterSignUpMember(NOT_APPROVED); + } + + public static Member basicMember1() { + Map attributes = + new HashMap<>() { + { put("provider", "GOOGLE"); put("sub", "121212121212112"); put("picture", "/static/image.jpg"); put("email", "yu@gmail.com"); put("name", "유동현"); put("locale", "ko"); - }}; - OAuth2UserInfo user = new GoogleOAuth2UserInfo(attributes); - Member member = new Member(user); - member.setRole(BASIC); - - // 회원정보 저장 - member.setStudentId("12171234"); - member.setPhone("010-1111-1111"); - member.setName("유동현"); - member.setSchoolInformation(new SchoolInformation("컴퓨터공학과", 1, 1, UNDERGRADUATE)); - return member; - } - - public static Member basicMember2() { - Map attributes = new HashMap<>() {{ + } + }; + OAuth2UserInfo user = new GoogleOAuth2UserInfo(attributes); + Member member = new Member(user); + member.setRole(BASIC); + + // 회원정보 저장 + member.setStudentId("12171234"); + member.setPhone("010-1111-1111"); + member.setName("유동현"); + member.setSchoolInformation(new SchoolInformation("컴퓨터공학과", 1, 1, UNDERGRADUATE)); + return member; + } + + public static Member basicMember2() { + Map attributes = + new HashMap<>() { + { put("provider", "GOOGLE"); put("sub", "3232322332323223"); put("picture", "/static/image.jpg"); put("email", "jo@gmail.com"); put("name", "조승현"); put("locale", "ko"); - }}; - OAuth2UserInfo user = new GoogleOAuth2UserInfo(attributes); - Member member = new Member(user); - member.setRole(BASIC); - - // 회원정보 저장 - member.setStudentId("12171234"); - member.setPhone("010-1111-1111"); - member.setName("조승현"); - member.setSchoolInformation(new SchoolInformation("컴퓨터공학과", 1, 1, UNDERGRADUATE)); - return member; - } - - public static Member signingUpMemberAfterProfile() { - return afterSignUpMember(SIGNING_UP); - } - - public static Member signingUpMember1() { - - Map attributes = new HashMap<>() {{ + } + }; + OAuth2UserInfo user = new GoogleOAuth2UserInfo(attributes); + Member member = new Member(user); + member.setRole(BASIC); + + // 회원정보 저장 + member.setStudentId("12171234"); + member.setPhone("010-1111-1111"); + member.setName("조승현"); + member.setSchoolInformation(new SchoolInformation("컴퓨터공학과", 1, 1, UNDERGRADUATE)); + return member; + } + + public static Member signingUpMemberAfterProfile() { + return afterSignUpMember(SIGNING_UP); + } + + public static Member signingUpMember1() { + + Map attributes = + new HashMap<>() { + { put("provider", "GOOGLE"); put("sub", "1249846925629348"); put("picture", "/static/image.jpg"); put("email", "my@gmail.com"); put("name", "유동현"); put("locale", "ko"); - }}; - OAuth2UserInfo user = new GoogleOAuth2UserInfo(attributes); - Member member = new Member(user); - member.setRole(SIGNING_UP); + } + }; + OAuth2UserInfo user = new GoogleOAuth2UserInfo(attributes); + Member member = new Member(user); + member.setRole(SIGNING_UP); - return member; - } + return member; + } - public static Member signingUpMember2() { + public static Member signingUpMember2() { - Map attributes = new HashMap<>() {{ + Map attributes = + new HashMap<>() { + { put("provider", "GOOGLE"); put("sub", "3232322332323223"); put("picture", "/static/image.jpg"); put("email", "my2@gmail.com"); put("name", "조승현"); put("locale", "ko"); - }}; - OAuth2UserInfo user = new GoogleOAuth2UserInfo(attributes); - Member member = new Member(user); - member.setRole(SIGNING_UP); - - return member; - } - - public static Member getTestBasicMember(String id) { - return new Member( - new StudentId(id), "유동현", "010-1111-1111", "my@gmail.com", "" - , SchoolInformation.ofUnderGraduate("건축공학과", 3) - , new IbasInformation(BASIC)); - } - - public static Member getTestBasicMember(String id, String phoneNumber) { - return new Member( - new StudentId(id), "유동현", phoneNumber, "my@gmail.com", "" - , SchoolInformation.ofUnderGraduate("건축공학과", 3) - , new IbasInformation(BASIC)); - } - + } + }; + OAuth2UserInfo user = new GoogleOAuth2UserInfo(attributes); + Member member = new Member(user); + member.setRole(SIGNING_UP); + + return member; + } + + public static Member getTestBasicMember(String id) { + return new Member( + new StudentId(id), + "유동현", + "010-1111-1111", + "my@gmail.com", + "", + SchoolInformation.ofUnderGraduate("건축공학과", 3), + new IbasInformation(BASIC)); + } + + public static Member getTestBasicMember(String id, String phoneNumber) { + return new Member( + new StudentId(id), + "유동현", + phoneNumber, + "my@gmail.com", + "", + SchoolInformation.ofUnderGraduate("건축공학과", 3), + new IbasInformation(BASIC)); + } } diff --git a/resource-server/src/test/java/com/inhabas/api/domain/menu/domain/MenuExampleTest.java b/resource-server/src/test/java/com/inhabas/api/domain/menu/domain/MenuExampleTest.java index cb1abe2f..53a88b0e 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/menu/domain/MenuExampleTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/menu/domain/MenuExampleTest.java @@ -4,12 +4,11 @@ public class MenuExampleTest { - public static Menu getMenu1(MenuGroup menuGroup) { - return new Menu(menuGroup, 1, MenuType.ALBUM, "동아리 활동", "동아리 활동 설명"); - } - - public static Menu getMenu2(MenuGroup menuGroup) { - return new Menu(menuGroup, 1, MenuType.STUDY, "강의", "강의 설명"); - } + public static Menu getMenu1(MenuGroup menuGroup) { + return new Menu(menuGroup, 1, MenuType.ALBUM, "동아리 활동", "동아리 활동 설명"); + } + public static Menu getMenu2(MenuGroup menuGroup) { + return new Menu(menuGroup, 1, MenuType.STUDY, "강의", "강의 설명"); + } } diff --git a/resource-server/src/test/java/com/inhabas/api/domain/menu/domain/valueObject/MenuCategoryDescriptionTest.java b/resource-server/src/test/java/com/inhabas/api/domain/menu/domain/valueObject/MenuCategoryDescriptionTest.java index f63d67a6..2973cec6 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/menu/domain/valueObject/MenuCategoryDescriptionTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/menu/domain/valueObject/MenuCategoryDescriptionTest.java @@ -1,42 +1,39 @@ package com.inhabas.api.domain.menu.domain.valueObject; -import com.inhabas.api.domain.menu.domain.valueObject.Description; +import static org.assertj.core.api.Assertions.assertThat; + import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import static org.assertj.core.api.Assertions.assertThat; - public class MenuCategoryDescriptionTest { - @DisplayName("게시판 설명으로 null 값은 허용 안됨.") - @Test - public void CategoryName_cannot_be_null() { - //when - Assertions.assertThrows(IllegalArgumentException.class, - () -> new Description(null)); - } - - @DisplayName("게시판 설명으로 빈 문자열은 허용 안됨.") - @Test - public void CategoryName_cannot_be_blank() { - //when - Assertions.assertThrows(IllegalArgumentException.class, - () -> new Description(" ")); - } - - @DisplayName("게시판 설명 50글자 이상은 허용 안됨.") - @Test - public void CategoryName_too_long() { - //given - String description = "이문장7글자임".repeat(7); - - //when : 49글자 정상 저장 - Description categoryName = new Description(description); - assertThat(categoryName.getValue()).isEqualTo(description); - - //when : 50글자 저장 안됨. - Assertions.assertThrows(IllegalArgumentException.class, - () -> new Description(description+".")); - } + @DisplayName("게시판 설명으로 null 값은 허용 안됨.") + @Test + public void CategoryName_cannot_be_null() { + // when + Assertions.assertThrows(IllegalArgumentException.class, () -> new Description(null)); + } + + @DisplayName("게시판 설명으로 빈 문자열은 허용 안됨.") + @Test + public void CategoryName_cannot_be_blank() { + // when + Assertions.assertThrows(IllegalArgumentException.class, () -> new Description(" ")); + } + + @DisplayName("게시판 설명 50글자 이상은 허용 안됨.") + @Test + public void CategoryName_too_long() { + // given + String description = "이문장7글자임".repeat(7); + + // when : 49글자 정상 저장 + Description categoryName = new Description(description); + assertThat(categoryName.getValue()).isEqualTo(description); + + // when : 50글자 저장 안됨. + Assertions.assertThrows( + IllegalArgumentException.class, () -> new Description(description + ".")); + } } diff --git a/resource-server/src/test/java/com/inhabas/api/domain/menu/domain/valueObject/MenuGroupExampleTest.java b/resource-server/src/test/java/com/inhabas/api/domain/menu/domain/valueObject/MenuGroupExampleTest.java index b426cbdc..9211aa0c 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/menu/domain/valueObject/MenuGroupExampleTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/menu/domain/valueObject/MenuGroupExampleTest.java @@ -4,12 +4,11 @@ public class MenuGroupExampleTest { - public static MenuGroup getMenuGroup1() { - return new MenuGroup("IBAS"); - } - - public static MenuGroup getMenuGroup2() { - return new MenuGroup("STUDY"); - } + public static MenuGroup getMenuGroup1() { + return new MenuGroup("IBAS"); + } + public static MenuGroup getMenuGroup2() { + return new MenuGroup("STUDY"); + } } diff --git a/resource-server/src/test/java/com/inhabas/api/domain/menu/domain/valueObject/MenuGroupNameTest.java b/resource-server/src/test/java/com/inhabas/api/domain/menu/domain/valueObject/MenuGroupNameTest.java index 30682e0e..1d028a2b 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/menu/domain/valueObject/MenuGroupNameTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/menu/domain/valueObject/MenuGroupNameTest.java @@ -1,51 +1,45 @@ package com.inhabas.api.domain.menu.domain.valueObject; -import com.inhabas.api.domain.menu.domain.valueObject.MenuGroupName; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; - import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + public class MenuGroupNameTest { - @DisplayName("MenuGroupName 타입에 메뉴이름 저장") - @Test - public void MenuGroupName_is_OK() { - //given - String menuGroupName = "게시판메뉴"; - - //when - MenuGroupName name = new MenuGroupName(menuGroupName); - - //then - assertThat(name.getValue()).isEqualTo("게시판메뉴"); - } - - @DisplayName("MenuGroupName 타입에 너무 긴 메뉴이름 저장 시도. 10자 이상") - @Test - public void MenuGroupName_is_too_long() { - //given - String menuGroupName = "게시판메뉴".repeat(2); // 10자 - - //when - assertThrows( - IllegalArgumentException.class, - ()-> new MenuGroupName(menuGroupName) - ); - } - - @DisplayName("메뉴그룹이름은 null 일 수 없다.") - @Test - public void MenuGroupName_cannot_be_null() { - assertThrows(IllegalArgumentException.class, - ()-> new MenuGroupName(null)); - } - - @DisplayName("메뉴그룹이름은 빈 문자열일 수 없다.") - @Test - public void MenuGroupName_cannot_be_blank() { - assertThrows(IllegalArgumentException.class, - ()-> new MenuGroupName(" ")); - } + @DisplayName("MenuGroupName 타입에 메뉴이름 저장") + @Test + public void MenuGroupName_is_OK() { + // given + String menuGroupName = "게시판메뉴"; + + // when + MenuGroupName name = new MenuGroupName(menuGroupName); + + // then + assertThat(name.getValue()).isEqualTo("게시판메뉴"); + } + + @DisplayName("MenuGroupName 타입에 너무 긴 메뉴이름 저장 시도. 10자 이상") + @Test + public void MenuGroupName_is_too_long() { + // given + String menuGroupName = "게시판메뉴".repeat(2); // 10자 + + // when + assertThrows(IllegalArgumentException.class, () -> new MenuGroupName(menuGroupName)); + } + + @DisplayName("메뉴그룹이름은 null 일 수 없다.") + @Test + public void MenuGroupName_cannot_be_null() { + assertThrows(IllegalArgumentException.class, () -> new MenuGroupName(null)); + } + + @DisplayName("메뉴그룹이름은 빈 문자열일 수 없다.") + @Test + public void MenuGroupName_cannot_be_blank() { + assertThrows(IllegalArgumentException.class, () -> new MenuGroupName(" ")); + } } diff --git a/resource-server/src/test/java/com/inhabas/api/domain/menu/domain/valueObject/MenuNameTest.java b/resource-server/src/test/java/com/inhabas/api/domain/menu/domain/valueObject/MenuNameTest.java index f3960fd6..ef70ecbd 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/menu/domain/valueObject/MenuNameTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/menu/domain/valueObject/MenuNameTest.java @@ -8,43 +8,38 @@ public class MenuNameTest { - @DisplayName("MenuName 타입에 메뉴이름 저장") - @Test - public void MenuName_is_OK() { - //given - String menuName = "게시판"; - - //when - MenuName name = new MenuName(menuName); - - //then - assertThat(name.getValue()).isEqualTo("게시판"); - } - - @DisplayName("MenuName 타입에 너무 긴 메뉴이름 저장 시도. 15자 이상") - @Test - public void MenuName_is_too_long() { - //given - String menuName = "게시판".repeat(5); // 15자 - - //when - assertThrows( - IllegalArgumentException.class, - ()-> new MenuName(menuName) - ); - } - - @DisplayName("메뉴이름은 null 일 수 없다.") - @Test - public void MenuName_cannot_be_null() { - assertThrows(IllegalArgumentException.class, - ()-> new MenuName(null)); - } - - @DisplayName("메뉴이름은 빈 문자열일 수 없다.") - @Test - public void MenuName_cannot_be_blank() { - assertThrows(IllegalArgumentException.class, - ()-> new MenuName(" ")); - } + @DisplayName("MenuName 타입에 메뉴이름 저장") + @Test + public void MenuName_is_OK() { + // given + String menuName = "게시판"; + + // when + MenuName name = new MenuName(menuName); + + // then + assertThat(name.getValue()).isEqualTo("게시판"); + } + + @DisplayName("MenuName 타입에 너무 긴 메뉴이름 저장 시도. 15자 이상") + @Test + public void MenuName_is_too_long() { + // given + String menuName = "게시판".repeat(5); // 15자 + + // when + assertThrows(IllegalArgumentException.class, () -> new MenuName(menuName)); + } + + @DisplayName("메뉴이름은 null 일 수 없다.") + @Test + public void MenuName_cannot_be_null() { + assertThrows(IllegalArgumentException.class, () -> new MenuName(null)); + } + + @DisplayName("메뉴이름은 빈 문자열일 수 없다.") + @Test + public void MenuName_cannot_be_blank() { + assertThrows(IllegalArgumentException.class, () -> new MenuName(" ")); + } } diff --git a/resource-server/src/test/java/com/inhabas/api/domain/menu/repository/MenuRepositoryTest.java b/resource-server/src/test/java/com/inhabas/api/domain/menu/repository/MenuRepositoryTest.java index c0f393cc..5e521eaf 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/menu/repository/MenuRepositoryTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/menu/repository/MenuRepositoryTest.java @@ -3,161 +3,184 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; +import java.util.Arrays; +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager; +import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.test.util.ReflectionTestUtils; + import com.inhabas.api.domain.menu.domain.Menu; import com.inhabas.api.domain.menu.domain.MenuGroup; import com.inhabas.api.domain.menu.domain.valueObject.MenuType; import com.inhabas.api.domain.menu.dto.MenuDto; import com.inhabas.api.domain.menu.dto.MenuGroupDto; import com.inhabas.testAnnotataion.DefaultDataJpaTest; -import java.util.Arrays; -import java.util.List; -import org.junit.jupiter.api.Test; + import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.DisplayName; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager; -import org.springframework.dao.DataIntegrityViolationException; -import org.springframework.test.util.ReflectionTestUtils; +import org.junit.jupiter.api.Test; @DefaultDataJpaTest public class MenuRepositoryTest { - @Autowired - MenuRepository menuRepository; - @Autowired - TestEntityManager em; - - - @BeforeEach - public void setUp() { - - } - - @DisplayName("새로운 메뉴를 만든다.") - @Test - public void CreateNewMenu() { - //given - MenuGroup menuGroup1 = em.persist(new MenuGroup("IBAS")); - Menu activityBoardMenu = new Menu(menuGroup1, 1, MenuType.LIST, "동아리 활동", "동아리원의 활동을 기록하는 게시판입니다."); - - //when - Menu saveActivityMenu = menuRepository.save(activityBoardMenu); - em.flush(); - - //then - assertThat(saveActivityMenu.getId()).isNotNull(); - assertThat(saveActivityMenu.getDateCreated()).isNotNull(); - assertThat(saveActivityMenu.getDateUpdated()).isNotNull(); - assertThat(saveActivityMenu) - .usingRecursiveComparison() - .ignoringFields("id", "dateCreated", "dateUpdated") - .isEqualTo(activityBoardMenu); - } - - @Disabled - @DisplayName("메뉴 이름을 수정한다.") - @Test - public void updateMenuName() { - //given - MenuGroup menuGroup = em.persist(new MenuGroup("게시판 목록")); - Menu noticeMenu = menuRepository.save(new Menu(menuGroup, 1, MenuType.LIST, "공지사항", "동아리 공지를 게시하는 게시판입니다.")); - - //when - String newName = "공지 사항"; - Menu param = new Menu(noticeMenu.getMenuGroup(), noticeMenu.getPriority(), noticeMenu.getType(), newName, noticeMenu.getDescription()); - Integer menuId = (Integer) ReflectionTestUtils.getField(param, "id"); - ReflectionTestUtils.setField(param, "id", menuId); - //Menu updated = menuRepository.save(param); // service 로 제대로 구현한 뒤에 테스트 해야함. - - //then - //assertThat(updated.getName()).isEqualTo(newName); - } - - @DisplayName("한 메뉴그룹에, priority 가 중복될 시 오류") - @Test - public void CannotSamePriorityValue() { - /* - 이 테스트는 데이터베이스의 unique key 제약 조건을 검사함. - 하지만 현재 테스트는 h2 인메모리 방식으로 테이블을 생성해서 진행 중. - 실제 db 상태와는 무관함. 추후 테스트 방식을 고려해봐야함. - */ - - //given - MenuGroup menuGroup1 = em.persist(new MenuGroup("IBAS")); - MenuGroup menuGroup2 = em.persist(new MenuGroup("게시판 목록")); - - //중복되지 않는 priority로 메뉴를 생성하고 저장 - Menu activityBoardMenu = new Menu(menuGroup1, 1, MenuType.LIST, "동아리 활동", "동아리원의 활동을 기록하는 게시판입니다."); - Menu noticeBoardMenu = new Menu(menuGroup2, 1, MenuType.LIST, "공지사항", "동아리 공지를 게시하는 게시판입니다."); - Menu freeBoardMenu = new Menu(menuGroup2, 2, MenuType.LIST, "자유게시판", "부원이 자유롭게 글을 작성할 수 있는 게시판입니다."); - menuRepository.save(activityBoardMenu); - menuRepository.save(noticeBoardMenu); - menuRepository.save(freeBoardMenu); - - //when - // 같은 그룹에서 동일한 priority로 메뉴를 생성하려 할 때 예외 발생. - assertThrows(DataIntegrityViolationException.class, - () -> menuRepository.save(new Menu(menuGroup2, 2, MenuType.LIST, "질문게시판", "궁금한 점을 질문하는 게시판입니다."))); - } - - @DisplayName("MenuGroup 별 메뉴를 모두 반환한다.") - @Test - public void findAllMenuGroupByMenuGroup() { - //given - MenuGroup menuGroup1 = em.persist(new MenuGroup("IBAS")); - MenuGroup menuGroup2 = em.persist(new MenuGroup("게시판 목록")); - MenuGroup menuGroup3 = em.persist(new MenuGroup("강의실")); - MenuGroup menuGroup4 = em.persist(new MenuGroup("프로젝트")); - MenuGroup menuGroup5 = em.persist(new MenuGroup("취미모임")); - - Menu menu11 = new Menu(menuGroup1, 1, MenuType.LIST, "동아리 활동", "동아리원의 활동을 기록하는 게시판입니다."); - Menu menu12 = new Menu(menuGroup1, 2, MenuType.LIST, "동아리 소개", "동아리를 소개하는 게시판입니다."); - Menu menu13 = new Menu(menuGroup1, 3, MenuType.LIST, "회계장부", "동아리 회계 내역을 공개합니다."); - Menu menu14 = new Menu(menuGroup1, 4, MenuType.LIST, "예산지원신청", "내부 활동에 필요한 예산을 신청할 수 있습니다."); - Menu menu21 = new Menu(menuGroup2, 1, MenuType.LIST, "공지사항", "동아리 공지를 게시하는 게시판입니다."); - Menu menu22 = new Menu(menuGroup2, 2, MenuType.LIST, "자유게시판", "부원이 자유롭게 작성하는 게시판입니다."); - Menu menu23 = new Menu(menuGroup2, 3, MenuType.LIST, "건의사항", "필요하다고 생각되는 사항들을 요청하는 게시판입니다."); - Menu menu24 = new Menu(menuGroup2, 4, MenuType.LIST, "자료실", "자료실입니다."); - Menu menu31 = new Menu(menuGroup3, 1, MenuType.LIST, "강의", "부원이 서로 가르치고 배우는 곳입니다."); - Menu menu32 = new Menu(menuGroup3, 2, MenuType.LIST, "스터디", "같이 공부하는 곳입니다.."); - Menu menu41 = new Menu(menuGroup4, 1, MenuType.LIST, "알파프로젝트", "동아리 내부 알파프로젝트 게시판입니다."); - Menu menu42 = new Menu(menuGroup4, 2, MenuType.LIST, "베타프로젝트", "동아리 내부 베타프로젝트 게시판입니다."); - Menu menu51 = new Menu(menuGroup5, 1, MenuType.LIST, "취미모임", "취미를 공유하며 친목을 다져보아요."); - List menuList = Arrays.asList(menu11, menu12, menu13, menu14, menu21, menu22, menu23, menu24, menu31, menu32, menu41, menu42, menu51); - - menuList = menuRepository.saveAllAndFlush(menuList); - em.clear(); - - //when - List allMenuInfo = menuRepository.findAllMenuByMenuGroup(); - - //then - MenuGroupDto menuGroupDto1 = new MenuGroupDto( - menuGroup1.getId(), - menuGroup1.getName(), - Arrays.asList(MenuDto.convert(menuList.get(0)), MenuDto.convert(menuList.get(1)), MenuDto.convert(menuList.get(2)), MenuDto.convert(menuList.get(3)))); - MenuGroupDto menuGroupDto2 = new MenuGroupDto( - menuGroup2.getId(), - menuGroup2.getName(), - Arrays.asList(MenuDto.convert(menuList.get(4)), MenuDto.convert(menuList.get(5)), MenuDto.convert(menuList.get(6)), MenuDto.convert(menuList.get(7)))); - MenuGroupDto menuGroupDto3 = new MenuGroupDto( - menuGroup3.getId(), - menuGroup3.getName(), - Arrays.asList(MenuDto.convert(menuList.get(8)), MenuDto.convert(menuList.get(9)))); - MenuGroupDto menuGroupDto4 = new MenuGroupDto( - menuGroup4.getId(), - menuGroup4.getName(), - Arrays.asList(MenuDto.convert(menuList.get(10)), MenuDto.convert(menuList.get(11)))); - MenuGroupDto menuGroupDto5 = new MenuGroupDto( - menuGroup5.getId(), - menuGroup5.getName(), - List.of(MenuDto.convert(menuList.get(12)))); - List expectedMenuGroupDtoList = Arrays.asList(menuGroupDto1, menuGroupDto2, menuGroupDto3, menuGroupDto4, menuGroupDto5); - - assertThat(allMenuInfo) - .usingRecursiveComparison() - .isEqualTo(expectedMenuGroupDtoList); - } - + @Autowired MenuRepository menuRepository; + @Autowired TestEntityManager em; + + @BeforeEach + public void setUp() {} + + @DisplayName("새로운 메뉴를 만든다.") + @Test + public void CreateNewMenu() { + // given + MenuGroup menuGroup1 = em.persist(new MenuGroup("IBAS")); + Menu activityBoardMenu = + new Menu(menuGroup1, 1, MenuType.LIST, "동아리 활동", "동아리원의 활동을 기록하는 게시판입니다."); + + // when + Menu saveActivityMenu = menuRepository.save(activityBoardMenu); + em.flush(); + + // then + assertThat(saveActivityMenu.getId()).isNotNull(); + assertThat(saveActivityMenu.getDateCreated()).isNotNull(); + assertThat(saveActivityMenu.getDateUpdated()).isNotNull(); + assertThat(saveActivityMenu) + .usingRecursiveComparison() + .ignoringFields("id", "dateCreated", "dateUpdated") + .isEqualTo(activityBoardMenu); + } + + @Disabled + @DisplayName("메뉴 이름을 수정한다.") + @Test + public void updateMenuName() { + // given + MenuGroup menuGroup = em.persist(new MenuGroup("게시판 목록")); + Menu noticeMenu = + menuRepository.save(new Menu(menuGroup, 1, MenuType.LIST, "공지사항", "동아리 공지를 게시하는 게시판입니다.")); + + // when + String newName = "공지 사항"; + Menu param = + new Menu( + noticeMenu.getMenuGroup(), + noticeMenu.getPriority(), + noticeMenu.getType(), + newName, + noticeMenu.getDescription()); + Integer menuId = (Integer) ReflectionTestUtils.getField(param, "id"); + ReflectionTestUtils.setField(param, "id", menuId); + // Menu updated = menuRepository.save(param); // service 로 제대로 구현한 뒤에 테스트 해야함. + + // then + // assertThat(updated.getName()).isEqualTo(newName); + } + + @DisplayName("한 메뉴그룹에, priority 가 중복될 시 오류") + @Test + public void CannotSamePriorityValue() { + /* + 이 테스트는 데이터베이스의 unique key 제약 조건을 검사함. + 하지만 현재 테스트는 h2 인메모리 방식으로 테이블을 생성해서 진행 중. + 실제 db 상태와는 무관함. 추후 테스트 방식을 고려해봐야함. + */ + + // given + MenuGroup menuGroup1 = em.persist(new MenuGroup("IBAS")); + MenuGroup menuGroup2 = em.persist(new MenuGroup("게시판 목록")); + + // 중복되지 않는 priority로 메뉴를 생성하고 저장 + Menu activityBoardMenu = + new Menu(menuGroup1, 1, MenuType.LIST, "동아리 활동", "동아리원의 활동을 기록하는 게시판입니다."); + Menu noticeBoardMenu = new Menu(menuGroup2, 1, MenuType.LIST, "공지사항", "동아리 공지를 게시하는 게시판입니다."); + Menu freeBoardMenu = + new Menu(menuGroup2, 2, MenuType.LIST, "자유게시판", "부원이 자유롭게 글을 작성할 수 있는 게시판입니다."); + menuRepository.save(activityBoardMenu); + menuRepository.save(noticeBoardMenu); + menuRepository.save(freeBoardMenu); + + // when + // 같은 그룹에서 동일한 priority로 메뉴를 생성하려 할 때 예외 발생. + assertThrows( + DataIntegrityViolationException.class, + () -> + menuRepository.save( + new Menu(menuGroup2, 2, MenuType.LIST, "질문게시판", "궁금한 점을 질문하는 게시판입니다."))); + } + + @DisplayName("MenuGroup 별 메뉴를 모두 반환한다.") + @Test + public void findAllMenuGroupByMenuGroup() { + // given + MenuGroup menuGroup1 = em.persist(new MenuGroup("IBAS")); + MenuGroup menuGroup2 = em.persist(new MenuGroup("게시판 목록")); + MenuGroup menuGroup3 = em.persist(new MenuGroup("강의실")); + MenuGroup menuGroup4 = em.persist(new MenuGroup("프로젝트")); + MenuGroup menuGroup5 = em.persist(new MenuGroup("취미모임")); + + Menu menu11 = new Menu(menuGroup1, 1, MenuType.LIST, "동아리 활동", "동아리원의 활동을 기록하는 게시판입니다."); + Menu menu12 = new Menu(menuGroup1, 2, MenuType.LIST, "동아리 소개", "동아리를 소개하는 게시판입니다."); + Menu menu13 = new Menu(menuGroup1, 3, MenuType.LIST, "회계장부", "동아리 회계 내역을 공개합니다."); + Menu menu14 = new Menu(menuGroup1, 4, MenuType.LIST, "예산지원신청", "내부 활동에 필요한 예산을 신청할 수 있습니다."); + Menu menu21 = new Menu(menuGroup2, 1, MenuType.LIST, "공지사항", "동아리 공지를 게시하는 게시판입니다."); + Menu menu22 = new Menu(menuGroup2, 2, MenuType.LIST, "자유게시판", "부원이 자유롭게 작성하는 게시판입니다."); + Menu menu23 = new Menu(menuGroup2, 3, MenuType.LIST, "건의사항", "필요하다고 생각되는 사항들을 요청하는 게시판입니다."); + Menu menu24 = new Menu(menuGroup2, 4, MenuType.LIST, "자료실", "자료실입니다."); + Menu menu31 = new Menu(menuGroup3, 1, MenuType.LIST, "강의", "부원이 서로 가르치고 배우는 곳입니다."); + Menu menu32 = new Menu(menuGroup3, 2, MenuType.LIST, "스터디", "같이 공부하는 곳입니다.."); + Menu menu41 = new Menu(menuGroup4, 1, MenuType.LIST, "알파프로젝트", "동아리 내부 알파프로젝트 게시판입니다."); + Menu menu42 = new Menu(menuGroup4, 2, MenuType.LIST, "베타프로젝트", "동아리 내부 베타프로젝트 게시판입니다."); + Menu menu51 = new Menu(menuGroup5, 1, MenuType.LIST, "취미모임", "취미를 공유하며 친목을 다져보아요."); + List menuList = + Arrays.asList( + menu11, menu12, menu13, menu14, menu21, menu22, menu23, menu24, menu31, menu32, menu41, + menu42, menu51); + + menuList = menuRepository.saveAllAndFlush(menuList); + em.clear(); + + // when + List allMenuInfo = menuRepository.findAllMenuByMenuGroup(); + + // then + MenuGroupDto menuGroupDto1 = + new MenuGroupDto( + menuGroup1.getId(), + menuGroup1.getName(), + Arrays.asList( + MenuDto.convert(menuList.get(0)), + MenuDto.convert(menuList.get(1)), + MenuDto.convert(menuList.get(2)), + MenuDto.convert(menuList.get(3)))); + MenuGroupDto menuGroupDto2 = + new MenuGroupDto( + menuGroup2.getId(), + menuGroup2.getName(), + Arrays.asList( + MenuDto.convert(menuList.get(4)), + MenuDto.convert(menuList.get(5)), + MenuDto.convert(menuList.get(6)), + MenuDto.convert(menuList.get(7)))); + MenuGroupDto menuGroupDto3 = + new MenuGroupDto( + menuGroup3.getId(), + menuGroup3.getName(), + Arrays.asList(MenuDto.convert(menuList.get(8)), MenuDto.convert(menuList.get(9)))); + MenuGroupDto menuGroupDto4 = + new MenuGroupDto( + menuGroup4.getId(), + menuGroup4.getName(), + Arrays.asList(MenuDto.convert(menuList.get(10)), MenuDto.convert(menuList.get(11)))); + MenuGroupDto menuGroupDto5 = + new MenuGroupDto( + menuGroup5.getId(), menuGroup5.getName(), List.of(MenuDto.convert(menuList.get(12)))); + List expectedMenuGroupDtoList = + Arrays.asList(menuGroupDto1, menuGroupDto2, menuGroupDto3, menuGroupDto4, menuGroupDto5); + + assertThat(allMenuInfo).usingRecursiveComparison().isEqualTo(expectedMenuGroupDtoList); + } } diff --git a/resource-server/src/test/java/com/inhabas/api/domain/menu/usecase/MenuServiceTest.java b/resource-server/src/test/java/com/inhabas/api/domain/menu/usecase/MenuServiceTest.java index a9d24292..fef682c8 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/menu/usecase/MenuServiceTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/menu/usecase/MenuServiceTest.java @@ -6,72 +6,71 @@ import static org.mockito.BDDMockito.then; import static org.mockito.Mockito.times; +import java.util.ArrayList; +import java.util.Optional; + +import org.springframework.test.util.ReflectionTestUtils; + import com.inhabas.api.auth.domain.error.businessException.NotFoundException; import com.inhabas.api.domain.menu.domain.Menu; import com.inhabas.api.domain.menu.domain.MenuGroup; import com.inhabas.api.domain.menu.domain.valueObject.MenuId; import com.inhabas.api.domain.menu.domain.valueObject.MenuType; -import com.inhabas.api.domain.menu.repository.MenuRepository; import com.inhabas.api.domain.menu.dto.MenuDto; -import java.util.ArrayList; -import java.util.Optional; +import com.inhabas.api.domain.menu.repository.MenuRepository; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; -import org.springframework.test.util.ReflectionTestUtils; @ExtendWith(MockitoExtension.class) public class MenuServiceTest { - @InjectMocks - MenuServiceImpl menuService; + @InjectMocks MenuServiceImpl menuService; - @Mock - MenuRepository menuRepository; + @Mock MenuRepository menuRepository; - @DisplayName("모든 메뉴 정보를 잘 들고오는지 테스트") - @Test - public void getAllMenuInfoTest() { + @DisplayName("모든 메뉴 정보를 잘 들고오는지 테스트") + @Test + public void getAllMenuInfoTest() { - given(menuRepository.findAllMenuByMenuGroup()).willReturn(new ArrayList<>()); + given(menuRepository.findAllMenuByMenuGroup()).willReturn(new ArrayList<>()); - //when - menuService.getAllMenuInfo(); + // when + menuService.getAllMenuInfo(); - then(menuRepository).should(times(1)).findAllMenuByMenuGroup(); - } + then(menuRepository).should(times(1)).findAllMenuByMenuGroup(); + } - @DisplayName("한 메뉴에 대한 정보를 잘 들고오는지 테스트") - @Test - public void getMenuInfoByIdTest() { - MenuGroup boardGroup = new MenuGroup("게시판"); - ReflectionTestUtils.setField(boardGroup, "id", 1); - Menu existMenu = new Menu(boardGroup, 1, MenuType.LIST, "자유게시판", "자유로운 게시판 입니다."); - ReflectionTestUtils.setField(existMenu, "id", 1); - given(menuRepository.findById(any(MenuId.class))).willReturn(Optional.of(existMenu)); + @DisplayName("한 메뉴에 대한 정보를 잘 들고오는지 테스트") + @Test + public void getMenuInfoByIdTest() { + MenuGroup boardGroup = new MenuGroup("게시판"); + ReflectionTestUtils.setField(boardGroup, "id", 1); + Menu existMenu = new Menu(boardGroup, 1, MenuType.LIST, "자유게시판", "자유로운 게시판 입니다."); + ReflectionTestUtils.setField(existMenu, "id", 1); + given(menuRepository.findById(any(MenuId.class))).willReturn(Optional.of(existMenu)); - //when - MenuDto returnedMenuDto = menuService.getMenuInfoById(new MenuId(1)); + // when + MenuDto returnedMenuDto = menuService.getMenuInfoById(new MenuId(1)); - //then - then(menuRepository).should(times(1)).findById(any(MenuId.class)); - assertThat(returnedMenuDto) - .usingRecursiveComparison() - .isEqualTo(MenuDto.convert(existMenu)); - } + // then + then(menuRepository).should(times(1)).findById(any(MenuId.class)); + assertThat(returnedMenuDto).usingRecursiveComparison().isEqualTo(MenuDto.convert(existMenu)); + } - @DisplayName("존재하지 않는 메뉴를 찾으려고 하면 NotFoundException") - @Test - public void FailToGetMenuInfoByIdTest() { + @DisplayName("존재하지 않는 메뉴를 찾으려고 하면 NotFoundException") + @Test + public void FailToGetMenuInfoByIdTest() { - given(menuRepository.findById(any(MenuId.class))).willReturn(Optional.empty()); + given(menuRepository.findById(any(MenuId.class))).willReturn(Optional.empty()); - //when - Assertions.assertThrows(NotFoundException.class, - () -> menuService.getMenuInfoById(new MenuId(1))); - } + // when + Assertions.assertThrows( + NotFoundException.class, () -> menuService.getMenuInfoById(new MenuId(1))); + } } diff --git a/resource-server/src/test/java/com/inhabas/api/domain/policy/domain/PolicyTermTest.java b/resource-server/src/test/java/com/inhabas/api/domain/policy/domain/PolicyTermTest.java index 75b1a12d..db3ac1f1 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/policy/domain/PolicyTermTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/policy/domain/PolicyTermTest.java @@ -2,39 +2,36 @@ import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; import org.assertj.core.api.Assertions; + import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; class PolicyTermTest { - @DisplayName("Content는 null 일 수 없다.") - @Test - void Content_Notnull() { - //given - PolicyType policyType = new PolicyType("goodTitle"); - String nullString = null; - - //then - Assertions.assertThatThrownBy(() -> new PolicyTerm(policyType, nullString)) - .isInstanceOf(InvalidInputException.class) - .hasMessage("입력값이 없거나, 타입이 유효하지 않습니다."); - - } - - @DisplayName("올바른 PolicyTerm을 생성한다.") - @Test - void createPolicyTerm() { - //given - PolicyType policyType = new PolicyType("goodTitle"); - String goodContent = "goodContent"; - - //when - PolicyTerm policyTerm = new PolicyTerm(policyType, goodContent); - - - //then - Assertions.assertThat(policyTerm.getContent().getValue()).isEqualTo(goodContent); - - } - -} \ No newline at end of file + @DisplayName("Content는 null 일 수 없다.") + @Test + void Content_Notnull() { + // given + PolicyType policyType = new PolicyType("goodTitle"); + String nullString = null; + + // then + Assertions.assertThatThrownBy(() -> new PolicyTerm(policyType, nullString)) + .isInstanceOf(InvalidInputException.class) + .hasMessage("입력값이 없거나, 타입이 유효하지 않습니다."); + } + + @DisplayName("올바른 PolicyTerm을 생성한다.") + @Test + void createPolicyTerm() { + // given + PolicyType policyType = new PolicyType("goodTitle"); + String goodContent = "goodContent"; + + // when + PolicyTerm policyTerm = new PolicyTerm(policyType, goodContent); + + // then + Assertions.assertThat(policyTerm.getContent().getValue()).isEqualTo(goodContent); + } +} diff --git a/resource-server/src/test/java/com/inhabas/api/domain/policy/domain/PolicyTypeTest.java b/resource-server/src/test/java/com/inhabas/api/domain/policy/domain/PolicyTypeTest.java index e25796c0..40c47cd7 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/policy/domain/PolicyTypeTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/policy/domain/PolicyTypeTest.java @@ -1,41 +1,37 @@ package com.inhabas.api.domain.policy.domain; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; import org.assertj.core.api.Assertions; + import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import static org.assertj.core.api.Assertions.assertThatThrownBy; - class PolicyTypeTest { - @DisplayName("Title은 null, empty일 수 없다.") - @Test - void Title_Notnull_NotEmpty() { - //given - String white = "\t"; - - //then - assertThatThrownBy(() -> new PolicyType(white)) - .isInstanceOf(InvalidInputException.class) - .hasMessage("입력값이 없거나, 타입이 유효하지 않습니다."); - - } - - @DisplayName("올바른 PolicyType을 생성한다.") - @Test - void createPolicyType() { - //given - String goodTitle = "good"; - - //when - PolicyType policyType = new PolicyType(goodTitle); - - //then - Assertions.assertThat(policyType.getTitle().getValue()).isEqualTo(goodTitle); - - } - - - -} \ No newline at end of file + @DisplayName("Title은 null, empty일 수 없다.") + @Test + void Title_Notnull_NotEmpty() { + // given + String white = "\t"; + + // then + assertThatThrownBy(() -> new PolicyType(white)) + .isInstanceOf(InvalidInputException.class) + .hasMessage("입력값이 없거나, 타입이 유효하지 않습니다."); + } + + @DisplayName("올바른 PolicyType을 생성한다.") + @Test + void createPolicyType() { + // given + String goodTitle = "good"; + + // when + PolicyType policyType = new PolicyType(goodTitle); + + // then + Assertions.assertThat(policyType.getTitle().getValue()).isEqualTo(goodTitle); + } +} diff --git a/resource-server/src/test/java/com/inhabas/api/domain/policy/dto/PolicyTermDtoTest.java b/resource-server/src/test/java/com/inhabas/api/domain/policy/dto/PolicyTermDtoTest.java index bacc4034..b83a2167 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/policy/dto/PolicyTermDtoTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/policy/dto/PolicyTermDtoTest.java @@ -1,50 +1,45 @@ package com.inhabas.api.domain.policy.dto; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Set; import javax.validation.ConstraintViolation; import javax.validation.Validation; import javax.validation.Validator; import javax.validation.ValidatorFactory; -import java.util.Set; -import static org.assertj.core.api.Assertions.assertThat; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; class PolicyTermDtoTest { - private static ValidatorFactory validatorFactory; - private static Validator validator; - - @BeforeAll - public static void init() { - validatorFactory = Validation.buildDefaultValidatorFactory(); - validator = validatorFactory.getValidator(); - } - - @AfterAll - public static void close() { - validatorFactory.close(); - } - - - @DisplayName("title, content 가 null 이면 validation 실패") - @Test - void NotNull_Test() { - //given - PolicyTermDto policyTermDto = PolicyTermDto.builder() - .title(null) - .content(null) - .build(); - - //when - Set> violations = validator.validate(policyTermDto); - - //then - assertThat(violations).hasSize(2); - - } - -} \ No newline at end of file + private static ValidatorFactory validatorFactory; + private static Validator validator; + + @BeforeAll + public static void init() { + validatorFactory = Validation.buildDefaultValidatorFactory(); + validator = validatorFactory.getValidator(); + } + + @AfterAll + public static void close() { + validatorFactory.close(); + } + + @DisplayName("title, content 가 null 이면 validation 실패") + @Test + void NotNull_Test() { + // given + PolicyTermDto policyTermDto = PolicyTermDto.builder().title(null).content(null).build(); + + // when + Set> violations = validator.validate(policyTermDto); + + // then + assertThat(violations).hasSize(2); + } +} diff --git a/resource-server/src/test/java/com/inhabas/api/domain/policy/dto/SavePolicyTernDtoTest.java b/resource-server/src/test/java/com/inhabas/api/domain/policy/dto/SavePolicyTernDtoTest.java index 202e4364..c7c1f975 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/policy/dto/SavePolicyTernDtoTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/policy/dto/SavePolicyTernDtoTest.java @@ -1,49 +1,45 @@ package com.inhabas.api.domain.policy.dto; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Set; import javax.validation.ConstraintViolation; import javax.validation.Validation; import javax.validation.Validator; import javax.validation.ValidatorFactory; -import java.util.Set; -import static org.assertj.core.api.Assertions.assertThat; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; class SavePolicyTernDtoTest { - private static ValidatorFactory validatorFactory; - private static Validator validator; - - @BeforeAll - public static void init() { - validatorFactory = Validation.buildDefaultValidatorFactory(); - validator = validatorFactory.getValidator(); - } - - @AfterAll - public static void close() { - validatorFactory.close(); - } - - - @DisplayName("title, content 가 null 이면 validation 실패") - @Test - void NotNull_Test() { - //given - SavePolicyTernDto savePolicyTernDto = SavePolicyTernDto.builder() - .content(null) - .build(); - - //when - Set> violations = validator.validate(savePolicyTernDto); - - //then - assertThat(violations).hasSize(1); - - } - -} \ No newline at end of file + private static ValidatorFactory validatorFactory; + private static Validator validator; + + @BeforeAll + public static void init() { + validatorFactory = Validation.buildDefaultValidatorFactory(); + validator = validatorFactory.getValidator(); + } + + @AfterAll + public static void close() { + validatorFactory.close(); + } + + @DisplayName("title, content 가 null 이면 validation 실패") + @Test + void NotNull_Test() { + // given + SavePolicyTernDto savePolicyTernDto = SavePolicyTernDto.builder().content(null).build(); + + // when + Set> violations = validator.validate(savePolicyTernDto); + + // then + assertThat(violations).hasSize(1); + } +} diff --git a/resource-server/src/test/java/com/inhabas/api/domain/policy/usecase/PolicyTermServiceTest.java b/resource-server/src/test/java/com/inhabas/api/domain/policy/usecase/PolicyTermServiceTest.java index de797c40..deb9735c 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/policy/usecase/PolicyTermServiceTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/policy/usecase/PolicyTermServiceTest.java @@ -1,104 +1,95 @@ package com.inhabas.api.domain.policy.usecase; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.*; + +import java.util.Objects; +import java.util.Optional; + import com.inhabas.api.auth.domain.error.businessException.NotFoundException; import com.inhabas.api.domain.policy.domain.PolicyTerm; import com.inhabas.api.domain.policy.domain.PolicyType; import com.inhabas.api.domain.policy.dto.PolicyTermDto; import com.inhabas.api.domain.policy.dto.SavePolicyTernDto; import com.inhabas.api.domain.policy.respository.PolicyTermRepository; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import java.util.Objects; -import java.util.Optional; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.*; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; @ExtendWith(MockitoExtension.class) public class PolicyTermServiceTest { - @InjectMocks - PolicyTermServiceImpl policyTermService; - - @Mock - PolicyTermRepository policyTermRepository; - - - @DisplayName("policyTermId로 policyTerm 을 조회한다.") - @Test - void findPolicyTermTest() { - //given - Long policyTermId = 1L; - PolicyType policyType = new PolicyType("title"); // PolicyType에 적절한 생성자 또는 setter 메소드가 필요합니다. - PolicyTerm policyTerm = PolicyTerm.builder() - .policyType(policyType) - .content("content") - .build(); - - given(policyTermRepository.findById(policyTermId)).willReturn(Optional.ofNullable(policyTerm)); - - //when - PolicyTermDto result = policyTermService.findPolicyTerm(policyTermId); - - //then - verify(policyTermRepository).findById(policyTermId); - assertThat(result.getTitle()).isEqualTo(Objects.requireNonNull(policyTerm).getPolicyType().getTitle().getValue()); - assertThat(result.getContent()).isEqualTo(policyTerm.getContent().getValue()); - - } - - @DisplayName("존재하지 않는 policyTermId 조회 시 NotFoundException") - @Test - void findPolicyTermTest_NotFound() { - //given - given(policyTermRepository.findById(any())).willReturn(Optional.empty()); - - //then - assertThatThrownBy(() -> policyTermService.findPolicyTerm(any())) - .isInstanceOf(NotFoundException.class) - .hasMessage("데이터가 존재하지 않습니다."); - - } - - @DisplayName("policyTerm 을 수정한다.") - @Test - void updatePolicyTermTest() { - //given - Long policyTermId = 1L; - SavePolicyTernDto savePolicyTermDto = new SavePolicyTernDto("content"); - PolicyTerm policyTerm = mock(PolicyTerm.class); - - given(policyTermRepository.findById(policyTermId)).willReturn(Optional.of(policyTerm)); - - //when - policyTermService.updatePolicyTerm(policyTermId, savePolicyTermDto); - - //then - verify(policyTermRepository).findById(policyTermId); - verify(policyTerm).updatePolicyTerm(savePolicyTermDto); - - } - - @DisplayName("존재하지 않는 policyTermId 수정 시 NotFoundException") - @Test - void updatePolicyTermTest_NotFound() { - //given - Long policyTermId = 1L; - SavePolicyTernDto savePolicyTermDto = new SavePolicyTernDto("content"); - - //then - assertThatThrownBy(() -> policyTermService.updatePolicyTerm(policyTermId, savePolicyTermDto)) - .isInstanceOf(NotFoundException.class) - .hasMessage("데이터가 존재하지 않습니다."); - - } - -} \ No newline at end of file + @InjectMocks PolicyTermServiceImpl policyTermService; + + @Mock PolicyTermRepository policyTermRepository; + + @DisplayName("policyTermId로 policyTerm 을 조회한다.") + @Test + void findPolicyTermTest() { + // given + Long policyTermId = 1L; + PolicyType policyType = new PolicyType("title"); // PolicyType에 적절한 생성자 또는 setter 메소드가 필요합니다. + PolicyTerm policyTerm = PolicyTerm.builder().policyType(policyType).content("content").build(); + + given(policyTermRepository.findById(policyTermId)).willReturn(Optional.ofNullable(policyTerm)); + + // when + PolicyTermDto result = policyTermService.findPolicyTerm(policyTermId); + + // then + verify(policyTermRepository).findById(policyTermId); + assertThat(result.getTitle()) + .isEqualTo(Objects.requireNonNull(policyTerm).getPolicyType().getTitle().getValue()); + assertThat(result.getContent()).isEqualTo(policyTerm.getContent().getValue()); + } + + @DisplayName("존재하지 않는 policyTermId 조회 시 NotFoundException") + @Test + void findPolicyTermTest_NotFound() { + // given + given(policyTermRepository.findById(any())).willReturn(Optional.empty()); + + // then + assertThatThrownBy(() -> policyTermService.findPolicyTerm(any())) + .isInstanceOf(NotFoundException.class) + .hasMessage("데이터가 존재하지 않습니다."); + } + + @DisplayName("policyTerm 을 수정한다.") + @Test + void updatePolicyTermTest() { + // given + Long policyTermId = 1L; + SavePolicyTernDto savePolicyTermDto = new SavePolicyTernDto("content"); + PolicyTerm policyTerm = mock(PolicyTerm.class); + + given(policyTermRepository.findById(policyTermId)).willReturn(Optional.of(policyTerm)); + + // when + policyTermService.updatePolicyTerm(policyTermId, savePolicyTermDto); + + // then + verify(policyTermRepository).findById(policyTermId); + verify(policyTerm).updatePolicyTerm(savePolicyTermDto); + } + + @DisplayName("존재하지 않는 policyTermId 수정 시 NotFoundException") + @Test + void updatePolicyTermTest_NotFound() { + // given + Long policyTermId = 1L; + SavePolicyTernDto savePolicyTermDto = new SavePolicyTernDto("content"); + + // then + assertThatThrownBy(() -> policyTermService.updatePolicyTerm(policyTermId, savePolicyTermDto)) + .isInstanceOf(NotFoundException.class) + .hasMessage("데이터가 존재하지 않습니다."); + } +} diff --git a/resource-server/src/test/java/com/inhabas/api/domain/questionnaire/repository/QuestionnaireRepositoryTest.java b/resource-server/src/test/java/com/inhabas/api/domain/questionnaire/repository/QuestionnaireRepositoryTest.java index 7c9e9f8e..578531a8 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/questionnaire/repository/QuestionnaireRepositoryTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/questionnaire/repository/QuestionnaireRepositoryTest.java @@ -1,43 +1,46 @@ package com.inhabas.api.domain.questionnaire.repository; -import com.inhabas.api.domain.questionnaire.domain.Questionnaire; -import com.inhabas.testAnnotataion.DefaultDataJpaTest; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.transaction.annotation.Transactional; +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; import java.util.ArrayList; import java.util.List; -import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.transaction.annotation.Transactional; + +import com.inhabas.api.domain.questionnaire.domain.Questionnaire; +import com.inhabas.testAnnotataion.DefaultDataJpaTest; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; @DefaultDataJpaTest class QuestionnaireRepositoryTest { - @Autowired - private QuestionnaireRepository questionnaireRepository; + @Autowired private QuestionnaireRepository questionnaireRepository; - @Test - @DisplayName("idList와 일치하는것이 몇개 포함되어 있는지 확인한다.") - @Transactional - public void countByIdIn() { - //given - ArrayList questionnaireInDatabase = new ArrayList<>() {{ + @Test + @DisplayName("idList와 일치하는것이 몇개 포함되어 있는지 확인한다.") + @Transactional + public void countByIdIn() { + // given + ArrayList questionnaireInDatabase = + new ArrayList<>() { + { add(new Questionnaire(1L, "지원동기 및 목표를 기술해주세요.")); add(new Questionnaire(2L, "프로그래밍 관련 언어를 다루어 본 적이 있다면 적어주세요.")); add(new Questionnaire(3L, "빅데이터 관련 활동 혹은 공모전 관련 경험이 있다면 적어주세요.")); add(new Questionnaire(4L, "추후 희망하는 진로가 무엇이며, 동아리 활동이 진로에 어떠한 영향을 줄 것이라고 생각하나요?")); add(new Questionnaire(5L, "어떤 경로로 IBAS를 알게 되셨나요?")); - }}; - questionnaireRepository.saveAll(questionnaireInDatabase); - - //when - List ids = List.of(1L, 2L, 3L); - Long shouldBeThree = questionnaireRepository.countByIdIn(ids); - - //then - assertThat(shouldBeThree).isEqualTo(3); - - } -} \ No newline at end of file + } + }; + questionnaireRepository.saveAll(questionnaireInDatabase); + + // when + List ids = List.of(1L, 2L, 3L); + Long shouldBeThree = questionnaireRepository.countByIdIn(ids); + + // then + assertThat(shouldBeThree).isEqualTo(3); + } +} diff --git a/resource-server/src/test/java/com/inhabas/api/domain/questionnaire/usecase/QuestionnaireServiceTest.java b/resource-server/src/test/java/com/inhabas/api/domain/questionnaire/usecase/QuestionnaireServiceTest.java index fe9d5558..b1ee49e4 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/questionnaire/usecase/QuestionnaireServiceTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/questionnaire/usecase/QuestionnaireServiceTest.java @@ -3,52 +3,55 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.BDDMockito.given; -import com.inhabas.api.domain.questionnaire.domain.Questionnaire; -import com.inhabas.api.domain.questionnaire.repository.QuestionnaireRepository; -import com.inhabas.api.domain.questionnaire.dto.QuestionnaireDto; import java.util.ArrayList; import java.util.List; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; + +import com.inhabas.api.domain.questionnaire.domain.Questionnaire; +import com.inhabas.api.domain.questionnaire.dto.QuestionnaireDto; +import com.inhabas.api.domain.questionnaire.repository.QuestionnaireRepository; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + @ExtendWith(MockitoExtension.class) public class QuestionnaireServiceTest { - @InjectMocks - private QuestionnaireServiceImpl questionnaireService; + @InjectMocks private QuestionnaireServiceImpl questionnaireService; - @Mock - private QuestionnaireRepository questionnaireRepository; + @Mock private QuestionnaireRepository questionnaireRepository; - @DisplayName("db 에 저장되어 있던 질문리스트를 dto 로 반환한다.") - @Test - public void getQuestionnaire() { - //given - ArrayList questionnaireInDatabase = new ArrayList<>(){{ + @DisplayName("db 에 저장되어 있던 질문리스트를 dto 로 반환한다.") + @Test + public void getQuestionnaire() { + // given + ArrayList questionnaireInDatabase = + new ArrayList<>() { + { add(new Questionnaire(1L, "지원동기 및 목표를 기술해주세요.")); add(new Questionnaire(2L, "프로그래밍 관련 언어를 다루어 본 적이 있다면 적어주세요.")); add(new Questionnaire(3L, "빅데이터 관련 활동 혹은 공모전 관련 경험이 있다면 적어주세요.")); add(new Questionnaire(4L, "추후 희망하는 진로가 무엇이며, 동아리 활동이 진로에 어떠한 영향을 줄 것이라고 생각하나요?")); add(new Questionnaire(5L, "어떤 경로로 IBAS를 알게 되셨나요?")); - }}; - - given(questionnaireRepository.findAll()).willReturn(questionnaireInDatabase); - - //when - List questionnaireDTOs = questionnaireService.getQuestionnaire(); - - //then - assertThat(questionnaireDTOs) - .extracting("question") - .containsExactly( - "지원동기 및 목표를 기술해주세요.", - "프로그래밍 관련 언어를 다루어 본 적이 있다면 적어주세요.", - "빅데이터 관련 활동 혹은 공모전 관련 경험이 있다면 적어주세요.", - "추후 희망하는 진로가 무엇이며, 동아리 활동이 진로에 어떠한 영향을 줄 것이라고 생각하나요?", - "어떤 경로로 IBAS를 알게 되셨나요?"); - } + } + }; + + given(questionnaireRepository.findAll()).willReturn(questionnaireInDatabase); + + // when + List questionnaireDTOs = questionnaireService.getQuestionnaire(); + + // then + assertThat(questionnaireDTOs) + .extracting("question") + .containsExactly( + "지원동기 및 목표를 기술해주세요.", + "프로그래밍 관련 언어를 다루어 본 적이 있다면 적어주세요.", + "빅데이터 관련 활동 혹은 공모전 관련 경험이 있다면 적어주세요.", + "추후 희망하는 진로가 무엇이며, 동아리 활동이 진로에 어떠한 영향을 줄 것이라고 생각하나요?", + "어떤 경로로 IBAS를 알게 되셨나요?"); + } } diff --git a/resource-server/src/test/java/com/inhabas/api/domain/signUp/SignUpIntegrationTest.java b/resource-server/src/test/java/com/inhabas/api/domain/signUp/SignUpIntegrationTest.java index 0c9fad1b..23976a8c 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/signUp/SignUpIntegrationTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/signUp/SignUpIntegrationTest.java @@ -1,5 +1,26 @@ package com.inhabas.api.domain.signUp; +import static com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.Role.*; +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import java.nio.charset.StandardCharsets; +import java.time.LocalDateTime; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.RequestPostProcessor; +import org.springframework.transaction.annotation.Transactional; + import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.inhabas.api.ApiApplication; @@ -8,10 +29,10 @@ import com.inhabas.api.auth.domain.oauth2.majorInfo.domain.MajorInfo; import com.inhabas.api.auth.domain.oauth2.majorInfo.repository.MajorInfoRepository; import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; -import com.inhabas.api.auth.domain.oauth2.member.service.MemberService; import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.MemberType; import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.Role; import com.inhabas.api.auth.domain.oauth2.member.repository.MemberRepository; +import com.inhabas.api.auth.domain.oauth2.member.service.MemberService; import com.inhabas.api.auth.domain.oauth2.socialAccount.domain.valueObject.UID; import com.inhabas.api.auth.domain.oauth2.userInfo.OAuth2UserInfo; import com.inhabas.api.auth.domain.oauth2.userInfo.OAuth2UserInfoFactory; @@ -24,310 +45,346 @@ import com.inhabas.api.domain.signUpSchedule.repository.SignUpScheduleRepository; import com.inhabas.testAnnotataion.CustomSpringBootTest; import com.inhabas.testAnnotataion.WithMockJwtAuthenticationToken; + import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInstance; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.MediaType; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.authority.SimpleGrantedAuthority; -import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.request.RequestPostProcessor; -import org.springframework.transaction.annotation.Transactional; - -import java.nio.charset.StandardCharsets; -import java.time.LocalDateTime; -import java.util.Arrays; -import java.util.List; -import java.util.Map; - -import static com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.Role.*; -import static org.assertj.core.api.Assertions.assertThat; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @CustomSpringBootTest(classes = ApiApplication.class) @TestInstance(TestInstance.Lifecycle.PER_CLASS) public class SignUpIntegrationTest { - @Autowired - private MockMvc mockMvc; - - @Autowired - private TokenUtil tokenUtil; - @Autowired - private ObjectMapper objectMapper; - @Autowired - private QuestionnaireRepository questionnaireRepository; - @Autowired - private MajorInfoRepository majorInfoRepository; - @Autowired - private MemberRepository memberRepository; - @Autowired - private MemberService memberService; - @Autowired - private SignUpScheduleRepository scheduleRepository; - - private static final String ROLE_PREFIX = "ROLE_"; - - private String token; - - @BeforeAll - public void setUp() { - 면접질문_설정(); - 전공정보_설정(); - 회원가입_가능한_기간(); - token = OAuth인증된_JWT_TOKEN(SIGNING_UP); - } - - - @Test - @Transactional - @WithMockJwtAuthenticationToken(memberRole = NOT_APPROVED) - public void 미승인회원_회원가입_비정상_접근() throws Exception { - forbiddenWhenAccessEverySignUpApi(NOT_APPROVED); - } - - @Test - @Transactional - @WithMockJwtAuthenticationToken(memberRole = DEACTIVATED) - public void 비활동회원_회원가입_비정상_접근() throws Exception { - forbiddenWhenAccessEverySignUpApi(DEACTIVATED); - } - - @Test - @Transactional - @WithMockJwtAuthenticationToken(memberRole = BASIC) - public void 기존_일반회원_회원가입_비정상_접근() throws Exception { - forbiddenWhenAccessEverySignUpApi(BASIC); - } - - @Test - @Transactional - @WithMockJwtAuthenticationToken(memberRole = EXECUTIVES) - public void 회장단_회원가입_비정상_접근() throws Exception { - forbiddenWhenAccessEverySignUpApi(EXECUTIVES); - } - - @Test - @Transactional - @WithMockJwtAuthenticationToken(memberRole = SIGNING_UP) - public void 회원가입_기간이_아닙니다() throws Exception { - /* 유동현은 IBAS 에 회원 가입하기 위해 - 소셜 로그인 후 회원 가입용 임시 토큰을 발급 받았다. - 회원가입이 불가능한 때에 요청을 보낸경우 */ - scheduleRepository.deleteAll(); - 회원가입_불가능한_기간(); - - /* OAuth2 인증이 완료되면 자동으로 회원가입 페이지로 리다이렉트 된다. - 이 때, 회원가입을 완료하지 않고 임시저장했던 프로필 정보가 있는지 불러온다. */ - String response = mockMvc.perform(get("/signUp").with(accessToken(token))) - .andExpect(status().isForbidden()) - .andReturn().getResponse().getContentAsString(StandardCharsets.UTF_8); - assertThat(response).isEqualTo("{\"status\":403,\"code\":\"S001\",\"message\":\"회원가입 기간이 아닙니다.\"}"); - } - - @Test - @Transactional - @WithMockJwtAuthenticationToken(memberRole = SIGNING_UP) - public void OAuth2_인증_후_비회원_신규_학생_회원가입() throws Exception { - /* 유동현은 IBAS 에 회원 가입하기 위해 - 소셜 로그인 후 회원 가입용 임시 토큰을 발급 받았다.*/ - mockMvc.perform(get("/signUp/check").with(accessToken(token))) - .andExpect(status().isOk()) - .andExpect(content().string("{\"check\":false}")); - - /* OAuth2 인증이 완료되고 회원가입을 하지 않았다면 회원가입 페이지로 리다이렉트 된다. - 이 때, 회원가입을 완료하지 않고 임시저장했던 프로필 정보가 있는지 불러오길 시도하지만 - 신규회원 가입이기 때문에, 소셜 이메일을 제외하고는 아무것도 받지 못한다. */ - mockMvc.perform(get("/signUp").with(accessToken(token))) - .andExpect(status().isOk()) - .andExpect(content().string("{\"name\":null,\"major\":null,\"phoneNumber\":null,\"studentId\":null,\"memberType\":null,\"grade\":null}")); - - /* 개인정보 입력을 위해, 전공 정보들이 로딩된다. */ - mockMvc.perform(get("/signUp/majorInfo").with(accessToken(token))) - .andExpect(status().isOk()); - - /* 프로필 입력을 완료하여 다음 버튼을 누르면, 개인정보가 임시저장된다. */ - mockMvc.perform(post("/signUp").with(accessToken(token)) - .contentType(MediaType.APPLICATION_JSON) - .content(jsonOf(SignUpDto.builder() - .name("유동현") - .major("컴퓨터공학과") - .phoneNumber("010-0000-0000") - .studentId("12171652") - .memberType(MemberType.UNDERGRADUATE) - .grade(1) - .build()))) - .andExpect(status().isNoContent()); - - /* 다음 페이지에서 면접용 질문 리스트가 로딩된다. */ - String questionList = mockMvc.perform(get("/signUp/questionnaires").with(accessToken(token))) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(StandardCharsets.UTF_8); - assertThat(questionList).isEqualTo("[" + - "{\"id\":1,\"question\":\"지원동기 및 목표를 기술해주세요.\"}," + - "{\"id\":2,\"question\":\"프로그래밍 관련 언어를 다루어 본 적이 있다면 적어주세요.\"}," + - "{\"id\":3,\"question\":\"빅데이터 관련 활동 혹은 공모전 관련 경험이 있다면 적어주세요.\"}," + - "{\"id\":4,\"question\":\"추후 희망하는 진로가 무엇이며, 동아리 활동이 진로에 어떠한 영향을 줄 것이라고 생각하나요?\"}," + - "{\"id\":5,\"question\":\"어떤 경로로 IBAS를 알게 되셨나요?\"}" + - "]"); - - /* 기존에 작성했던 답변을 가져오지만, 기존 답변이 없다. */ - mockMvc.perform(get("/signUp/answers").with(accessToken(token))) - .andExpect(status().isOk()) - .andExpect(content().string("[{\"questionId\":1,\"content\":null},{\"questionId\":2,\"content\":null},{\"questionId\":3,\"content\":null},{\"questionId\":4,\"content\":null},{\"questionId\":5,\"content\":null}]")); - - /* 면접 질문에 대답하고 임시저장 버튼을 클릭한다. */ - mockMvc.perform(post("/signUp/answers").with(accessToken(token)) - .contentType(MediaType.APPLICATION_JSON) - .content(jsonOf(Arrays.asList( - new AnswerDto(1L, "몰랑"), - new AnswerDto(2L, "아몰랑"), - new AnswerDto(3L, "아아몰랑"), - new AnswerDto(4L, "아모른다구"), - new AnswerDto(5L, "ㅎ"))))) - .andExpect(status().isOk()); - - /* 회원가입 신청을 완료한다. */ - mockMvc.perform(put("/signUp").with(accessToken(token)) - .contentType(MediaType.APPLICATION_JSON) - .content(jsonOf(Arrays.asList( - new AnswerDto(1L, ""), - new AnswerDto(2L, "아몰랑"), - new AnswerDto(3L, "아아몰랑"), - new AnswerDto(4L, "아모른다구"), - new AnswerDto(5L, "ㅎ"))))) - .andExpect(status().isNoContent()); - - - //then - Member 유동현 = memberRepository.findByProviderAndUid(OAuth2Provider.NAVER, new UID("N8ojJQXxxSxtO0CmEH3xtt5Y6ER09UEsRozkpbGAdOI")).orElseThrow(); - assertThat(유동현.getIbasInformation().getRole()).isEqualTo(NOT_APPROVED); - - } - - @Test - @Transactional - @WithMockJwtAuthenticationToken(memberRole = SIGNING_UP) - public void OAuth2_인증_후_비회원_신규_교수_회원가입() throws Exception { - /* 유동현 교수는 IBAS 에 회원 가입하기 위해 - 소셜 로그인 후 회원 가입용 임시 토큰을 발급 받았다.*/ - mockMvc.perform(get("/signUp/check").with(accessToken(token))) - .andExpect(status().isOk()) - .andExpect(content().string("{\"check\":false}")); - - /* OAuth2 인증이 완료되고 회원가입을 하지 않았다면 회원가입 페이지로 리다이렉트 된다. */ - - /* 개인정보 입력을 위해, 전공 정보들이 로딩된다. */ - String majorList = mockMvc.perform(get("/signUp/majorInfo").with(accessToken(token))) - .andExpect(status().isOk()) - .andReturn().getResponse().getContentAsString(StandardCharsets.UTF_8); - assertThat(majorList).isEqualTo("[" + - "{\"id\":1,\"college\":\"공과대학\",\"major\":\"기계공학과\"}," + - "{\"id\":2,\"college\":\"자연과학대학\",\"major\":\"수학과\"}," + - "{\"id\":3,\"college\":\"경영대학\",\"major\":\"경영학과\"}" + - "]"); - - /* 프로필 입력을 완료하여 다음 버튼을 누르면, 개인정보가 임시저장된다. */ - mockMvc.perform(post("/signUp").with(accessToken(token)) - .contentType(MediaType.APPLICATION_JSON) - .content(jsonOf(SignUpDto.builder() - .grade(1) - .studentId("228761") - .name("유동현") - .phoneNumber("010-0000-0000") - .major("컴퓨터공학과") - .memberType(MemberType.PROFESSOR) - .build()))) - .andExpect(status().isNoContent()); - - - /* 회원가입 신청을 완료한다. */ - mockMvc.perform(put("/signUp").with(accessToken(token))) - .andExpect(status().isNoContent()); - - //then - Member 유동현_교수 = memberRepository.findByProviderAndUid(OAuth2Provider.NAVER, new UID("N8ojJQXxxSxtO0CmEH3xtt5Y6ER09UEsRozkpbGAdOI")).orElseThrow(); - assertThat(유동현_교수.getIbasInformation().getRole()).isEqualTo(NOT_APPROVED); - } - - private void forbiddenWhenAccessEverySignUpApi(Role role) throws Exception { - //given - String token = OAuth인증된_JWT_TOKEN(role); - - mockMvc.perform(get("/signUp").with(accessToken(token))) - .andExpect(status().isForbidden()); - mockMvc.perform(post("/signUp").with(accessToken(token))) - .andExpect(status().isForbidden()); - mockMvc.perform(get("/signUp/answers").with(accessToken(token))) - .andExpect(status().isForbidden()); - mockMvc.perform(post("/signUp/answers").with(accessToken(token))) - .andExpect(status().isForbidden()); - } - - - // setUp - public static RequestPostProcessor accessToken(String accessToken) { - return request -> { - request.addHeader("Authorization", "Bearer " + accessToken); - return request; - }; - } - - private String OAuth인증된_JWT_TOKEN(Role role) { - List grantedAuthorities = List.of(new SimpleGrantedAuthority(ROLE_PREFIX+ role.toString())); - Map nameAttributeKey = Map.of( - "message", "success", - "response", Map.of( - "id", "N8ojJQXxxSxtO0CmEH3xtt5Y6ER09UEsRozkpbGAdOI", - "profile_image", "https://ssl.pstatic.net/static/pwe/address/img_profile.png", - "email", "5177jsh@naver.com", - "name", "조승현" - ) - ); - OAuth2UserInfo oAuth2UserInfo = OAuth2UserInfoFactory.getOAuth2UserInfo("NAVER", nameAttributeKey); - memberService.updateSocialAccountInfo(oAuth2UserInfo); - CustomOAuth2User customOAuth2User = new CustomOAuth2User(grantedAuthorities, nameAttributeKey, "response", 1L); - - return tokenUtil.createAccessToken(new OAuth2AuthenticationToken(customOAuth2User, grantedAuthorities, "NAVER")); - - } - - private void 면접질문_설정() { - questionnaireRepository.saveAll( - Arrays.asList( - new Questionnaire(1L, "지원동기 및 목표를 기술해주세요."), - new Questionnaire(2L, "프로그래밍 관련 언어를 다루어 본 적이 있다면 적어주세요."), - new Questionnaire(3L, "빅데이터 관련 활동 혹은 공모전 관련 경험이 있다면 적어주세요."), - new Questionnaire(4L, "추후 희망하는 진로가 무엇이며, 동아리 활동이 진로에 어떠한 영향을 줄 것이라고 생각하나요?"), - new Questionnaire(5L, "어떤 경로로 IBAS를 알게 되셨나요?"))); - } - - private void 전공정보_설정() { - majorInfoRepository.saveAll( - Arrays.asList( - new MajorInfo("공과대학", "기계공학과"), - new MajorInfo("자연과학대학", "수학과"), - new MajorInfo("경영대학", "경영학과")) - ); - } - - private String jsonOf(Object o) throws JsonProcessingException { - return objectMapper.writeValueAsString(o); - } - - private void 회원가입_가능한_기간() { - LocalDateTime now = LocalDateTime.now(); - scheduleRepository.save( - new SignUpSchedule(1, now.minusDays(1L), now.plusDays(1L), now.plusDays(1L), now.plusDays(2L), now.plusDays(3L))); - } - - private void 회원가입_불가능한_기간() { - LocalDateTime now = LocalDateTime.now(); - scheduleRepository.save( - new SignUpSchedule(1, now.minusDays(2L), now.minusDays(1L), now.plusDays(1L), now.plusDays(2L), now.plusDays(3L))); - } + @Autowired private MockMvc mockMvc; + + @Autowired private TokenUtil tokenUtil; + @Autowired private ObjectMapper objectMapper; + @Autowired private QuestionnaireRepository questionnaireRepository; + @Autowired private MajorInfoRepository majorInfoRepository; + @Autowired private MemberRepository memberRepository; + @Autowired private MemberService memberService; + @Autowired private SignUpScheduleRepository scheduleRepository; + + private static final String ROLE_PREFIX = "ROLE_"; + + private String token; + + @BeforeAll + public void setUp() { + 면접질문_설정(); + 전공정보_설정(); + 회원가입_가능한_기간(); + token = OAuth인증된_JWT_TOKEN(SIGNING_UP); + } + + @Test + @Transactional + @WithMockJwtAuthenticationToken(memberRole = NOT_APPROVED) + public void 미승인회원_회원가입_비정상_접근() throws Exception { + forbiddenWhenAccessEverySignUpApi(NOT_APPROVED); + } + + @Test + @Transactional + @WithMockJwtAuthenticationToken(memberRole = DEACTIVATED) + public void 비활동회원_회원가입_비정상_접근() throws Exception { + forbiddenWhenAccessEverySignUpApi(DEACTIVATED); + } + + @Test + @Transactional + @WithMockJwtAuthenticationToken(memberRole = BASIC) + public void 기존_일반회원_회원가입_비정상_접근() throws Exception { + forbiddenWhenAccessEverySignUpApi(BASIC); + } + + @Test + @Transactional + @WithMockJwtAuthenticationToken(memberRole = EXECUTIVES) + public void 회장단_회원가입_비정상_접근() throws Exception { + forbiddenWhenAccessEverySignUpApi(EXECUTIVES); + } + + @Test + @Transactional + @WithMockJwtAuthenticationToken(memberRole = SIGNING_UP) + public void 회원가입_기간이_아닙니다() throws Exception { + /* 유동현은 IBAS 에 회원 가입하기 위해 + 소셜 로그인 후 회원 가입용 임시 토큰을 발급 받았다. + 회원가입이 불가능한 때에 요청을 보낸경우 */ + scheduleRepository.deleteAll(); + 회원가입_불가능한_기간(); + + /* OAuth2 인증이 완료되면 자동으로 회원가입 페이지로 리다이렉트 된다. + 이 때, 회원가입을 완료하지 않고 임시저장했던 프로필 정보가 있는지 불러온다. */ + String response = + mockMvc + .perform(get("/signUp").with(accessToken(token))) + .andExpect(status().isForbidden()) + .andReturn() + .getResponse() + .getContentAsString(StandardCharsets.UTF_8); + assertThat(response) + .isEqualTo("{\"status\":403,\"code\":\"S001\",\"message\":\"회원가입 기간이 아닙니다.\"}"); + } + + @Test + @Transactional + @WithMockJwtAuthenticationToken(memberRole = SIGNING_UP) + public void OAuth2_인증_후_비회원_신규_학생_회원가입() throws Exception { + /* 유동현은 IBAS 에 회원 가입하기 위해 + 소셜 로그인 후 회원 가입용 임시 토큰을 발급 받았다.*/ + mockMvc + .perform(get("/signUp/check").with(accessToken(token))) + .andExpect(status().isOk()) + .andExpect(content().string("{\"check\":false}")); + + /* OAuth2 인증이 완료되고 회원가입을 하지 않았다면 회원가입 페이지로 리다이렉트 된다. + 이 때, 회원가입을 완료하지 않고 임시저장했던 프로필 정보가 있는지 불러오길 시도하지만 + 신규회원 가입이기 때문에, 소셜 이메일을 제외하고는 아무것도 받지 못한다. */ + mockMvc + .perform(get("/signUp").with(accessToken(token))) + .andExpect(status().isOk()) + .andExpect( + content() + .string( + "{\"name\":null,\"major\":null,\"phoneNumber\":null,\"studentId\":null,\"memberType\":null,\"grade\":null}")); + + /* 개인정보 입력을 위해, 전공 정보들이 로딩된다. */ + mockMvc.perform(get("/signUp/majorInfo").with(accessToken(token))).andExpect(status().isOk()); + + /* 프로필 입력을 완료하여 다음 버튼을 누르면, 개인정보가 임시저장된다. */ + mockMvc + .perform( + post("/signUp") + .with(accessToken(token)) + .contentType(MediaType.APPLICATION_JSON) + .content( + jsonOf( + SignUpDto.builder() + .name("유동현") + .major("컴퓨터공학과") + .phoneNumber("010-0000-0000") + .studentId("12171652") + .memberType(MemberType.UNDERGRADUATE) + .grade(1) + .build()))) + .andExpect(status().isNoContent()); + + /* 다음 페이지에서 면접용 질문 리스트가 로딩된다. */ + String questionList = + mockMvc + .perform(get("/signUp/questionnaires").with(accessToken(token))) + .andExpect(status().isOk()) + .andReturn() + .getResponse() + .getContentAsString(StandardCharsets.UTF_8); + assertThat(questionList) + .isEqualTo( + "[" + + "{\"id\":1,\"question\":\"지원동기 및 목표를 기술해주세요.\"}," + + "{\"id\":2,\"question\":\"프로그래밍 관련 언어를 다루어 본 적이 있다면 적어주세요.\"}," + + "{\"id\":3,\"question\":\"빅데이터 관련 활동 혹은 공모전 관련 경험이 있다면 적어주세요.\"}," + + "{\"id\":4,\"question\":\"추후 희망하는 진로가 무엇이며, 동아리 활동이 진로에 어떠한 영향을 줄 것이라고 생각하나요?\"}," + + "{\"id\":5,\"question\":\"어떤 경로로 IBAS를 알게 되셨나요?\"}" + + "]"); + + /* 기존에 작성했던 답변을 가져오지만, 기존 답변이 없다. */ + mockMvc + .perform(get("/signUp/answers").with(accessToken(token))) + .andExpect(status().isOk()) + .andExpect( + content() + .string( + "[{\"questionId\":1,\"content\":null},{\"questionId\":2,\"content\":null},{\"questionId\":3,\"content\":null},{\"questionId\":4,\"content\":null},{\"questionId\":5,\"content\":null}]")); + + /* 면접 질문에 대답하고 임시저장 버튼을 클릭한다. */ + mockMvc + .perform( + post("/signUp/answers") + .with(accessToken(token)) + .contentType(MediaType.APPLICATION_JSON) + .content( + jsonOf( + Arrays.asList( + new AnswerDto(1L, "몰랑"), + new AnswerDto(2L, "아몰랑"), + new AnswerDto(3L, "아아몰랑"), + new AnswerDto(4L, "아모른다구"), + new AnswerDto(5L, "ㅎ"))))) + .andExpect(status().isOk()); + + /* 회원가입 신청을 완료한다. */ + mockMvc + .perform( + put("/signUp") + .with(accessToken(token)) + .contentType(MediaType.APPLICATION_JSON) + .content( + jsonOf( + Arrays.asList( + new AnswerDto(1L, ""), + new AnswerDto(2L, "아몰랑"), + new AnswerDto(3L, "아아몰랑"), + new AnswerDto(4L, "아모른다구"), + new AnswerDto(5L, "ㅎ"))))) + .andExpect(status().isNoContent()); + + // then + Member 유동현 = + memberRepository + .findByProviderAndUid( + OAuth2Provider.NAVER, new UID("N8ojJQXxxSxtO0CmEH3xtt5Y6ER09UEsRozkpbGAdOI")) + .orElseThrow(); + assertThat(유동현.getIbasInformation().getRole()).isEqualTo(NOT_APPROVED); + } + + @Test + @Transactional + @WithMockJwtAuthenticationToken(memberRole = SIGNING_UP) + public void OAuth2_인증_후_비회원_신규_교수_회원가입() throws Exception { + /* 유동현 교수는 IBAS 에 회원 가입하기 위해 + 소셜 로그인 후 회원 가입용 임시 토큰을 발급 받았다.*/ + mockMvc + .perform(get("/signUp/check").with(accessToken(token))) + .andExpect(status().isOk()) + .andExpect(content().string("{\"check\":false}")); + + /* OAuth2 인증이 완료되고 회원가입을 하지 않았다면 회원가입 페이지로 리다이렉트 된다. */ + + /* 개인정보 입력을 위해, 전공 정보들이 로딩된다. */ + String majorList = + mockMvc + .perform(get("/signUp/majorInfo").with(accessToken(token))) + .andExpect(status().isOk()) + .andReturn() + .getResponse() + .getContentAsString(StandardCharsets.UTF_8); + assertThat(majorList) + .isEqualTo( + "[" + + "{\"id\":1,\"college\":\"공과대학\",\"major\":\"기계공학과\"}," + + "{\"id\":2,\"college\":\"자연과학대학\",\"major\":\"수학과\"}," + + "{\"id\":3,\"college\":\"경영대학\",\"major\":\"경영학과\"}" + + "]"); + + /* 프로필 입력을 완료하여 다음 버튼을 누르면, 개인정보가 임시저장된다. */ + mockMvc + .perform( + post("/signUp") + .with(accessToken(token)) + .contentType(MediaType.APPLICATION_JSON) + .content( + jsonOf( + SignUpDto.builder() + .grade(1) + .studentId("228761") + .name("유동현") + .phoneNumber("010-0000-0000") + .major("컴퓨터공학과") + .memberType(MemberType.PROFESSOR) + .build()))) + .andExpect(status().isNoContent()); + + /* 회원가입 신청을 완료한다. */ + mockMvc.perform(put("/signUp").with(accessToken(token))).andExpect(status().isNoContent()); + + // then + Member 유동현_교수 = + memberRepository + .findByProviderAndUid( + OAuth2Provider.NAVER, new UID("N8ojJQXxxSxtO0CmEH3xtt5Y6ER09UEsRozkpbGAdOI")) + .orElseThrow(); + assertThat(유동현_교수.getIbasInformation().getRole()).isEqualTo(NOT_APPROVED); + } + + private void forbiddenWhenAccessEverySignUpApi(Role role) throws Exception { + // given + String token = OAuth인증된_JWT_TOKEN(role); + + mockMvc.perform(get("/signUp").with(accessToken(token))).andExpect(status().isForbidden()); + mockMvc.perform(post("/signUp").with(accessToken(token))).andExpect(status().isForbidden()); + mockMvc + .perform(get("/signUp/answers").with(accessToken(token))) + .andExpect(status().isForbidden()); + mockMvc + .perform(post("/signUp/answers").with(accessToken(token))) + .andExpect(status().isForbidden()); + } + + // setUp + public static RequestPostProcessor accessToken(String accessToken) { + return request -> { + request.addHeader("Authorization", "Bearer " + accessToken); + return request; + }; + } + + private String OAuth인증된_JWT_TOKEN(Role role) { + List grantedAuthorities = + List.of(new SimpleGrantedAuthority(ROLE_PREFIX + role.toString())); + Map nameAttributeKey = + Map.of( + "message", + "success", + "response", + Map.of( + "id", "N8ojJQXxxSxtO0CmEH3xtt5Y6ER09UEsRozkpbGAdOI", + "profile_image", "https://ssl.pstatic.net/static/pwe/address/img_profile.png", + "email", "5177jsh@naver.com", + "name", "조승현")); + OAuth2UserInfo oAuth2UserInfo = + OAuth2UserInfoFactory.getOAuth2UserInfo("NAVER", nameAttributeKey); + memberService.updateSocialAccountInfo(oAuth2UserInfo); + CustomOAuth2User customOAuth2User = + new CustomOAuth2User(grantedAuthorities, nameAttributeKey, "response", 1L); + + return tokenUtil.createAccessToken( + new OAuth2AuthenticationToken(customOAuth2User, grantedAuthorities, "NAVER")); + } + + private void 면접질문_설정() { + questionnaireRepository.saveAll( + Arrays.asList( + new Questionnaire(1L, "지원동기 및 목표를 기술해주세요."), + new Questionnaire(2L, "프로그래밍 관련 언어를 다루어 본 적이 있다면 적어주세요."), + new Questionnaire(3L, "빅데이터 관련 활동 혹은 공모전 관련 경험이 있다면 적어주세요."), + new Questionnaire(4L, "추후 희망하는 진로가 무엇이며, 동아리 활동이 진로에 어떠한 영향을 줄 것이라고 생각하나요?"), + new Questionnaire(5L, "어떤 경로로 IBAS를 알게 되셨나요?"))); + } + + private void 전공정보_설정() { + majorInfoRepository.saveAll( + Arrays.asList( + new MajorInfo("공과대학", "기계공학과"), + new MajorInfo("자연과학대학", "수학과"), + new MajorInfo("경영대학", "경영학과"))); + } + + private String jsonOf(Object o) throws JsonProcessingException { + return objectMapper.writeValueAsString(o); + } + + private void 회원가입_가능한_기간() { + LocalDateTime now = LocalDateTime.now(); + scheduleRepository.save( + new SignUpSchedule( + 1, + now.minusDays(1L), + now.plusDays(1L), + now.plusDays(1L), + now.plusDays(2L), + now.plusDays(3L))); + } + + private void 회원가입_불가능한_기간() { + LocalDateTime now = LocalDateTime.now(); + scheduleRepository.save( + new SignUpSchedule( + 1, + now.minusDays(2L), + now.minusDays(1L), + now.plusDays(1L), + now.plusDays(2L), + now.plusDays(3L))); + } } diff --git a/resource-server/src/test/java/com/inhabas/api/domain/signUp/domain/entity/AnswerTest.java b/resource-server/src/test/java/com/inhabas/api/domain/signUp/domain/entity/AnswerTest.java index 421ec589..a96b489a 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/signUp/domain/entity/AnswerTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/signUp/domain/entity/AnswerTest.java @@ -1,31 +1,30 @@ package com.inhabas.api.domain.signUp.domain.entity; +import static org.assertj.core.api.Assertions.assertThat; + import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; import com.inhabas.api.domain.member.domain.entity.MemberTest; import com.inhabas.api.domain.questionnaire.domain.Questionnaire; + import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import static org.assertj.core.api.Assertions.assertThat; - class AnswerTest { - @Test - @DisplayName("생성자 객체 생성") - public void Answer() { - //given - Member member = MemberTest.getTestBasicMember("12171707"); - Questionnaire questionnaire = new Questionnaire(1L, "hello"); - String content = "Ok... bye"; - - //when - Answer answer = new Answer(member, questionnaire, content); - - //then - assertThat(member).isEqualTo(answer.getMember()); - assertThat(questionnaire).isEqualTo(answer.getQuestionnaire()); - assertThat(content).isEqualTo(answer.getContent()); - - } - -} \ No newline at end of file + @Test + @DisplayName("생성자 객체 생성") + public void Answer() { + // given + Member member = MemberTest.getTestBasicMember("12171707"); + Questionnaire questionnaire = new Questionnaire(1L, "hello"); + String content = "Ok... bye"; + + // when + Answer answer = new Answer(member, questionnaire, content); + + // then + assertThat(member).isEqualTo(answer.getMember()); + assertThat(questionnaire).isEqualTo(answer.getQuestionnaire()); + assertThat(content).isEqualTo(answer.getContent()); + } +} diff --git a/resource-server/src/test/java/com/inhabas/api/domain/signUp/repository/AnswerRepositoryTest.java b/resource-server/src/test/java/com/inhabas/api/domain/signUp/repository/AnswerRepositoryTest.java index 89690fd5..5080e5ee 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/signUp/repository/AnswerRepositoryTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/signUp/repository/AnswerRepositoryTest.java @@ -1,5 +1,12 @@ package com.inhabas.api.domain.signUp.repository; +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.transaction.annotation.Transactional; + import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; import com.inhabas.api.auth.domain.oauth2.member.repository.MemberRepository; import com.inhabas.api.domain.member.domain.entity.MemberTest; @@ -7,46 +14,35 @@ import com.inhabas.api.domain.questionnaire.repository.QuestionnaireRepository; import com.inhabas.api.domain.signUp.domain.entity.Answer; import com.inhabas.testAnnotataion.DefaultDataJpaTest; + import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.transaction.annotation.Transactional; - -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; - @DefaultDataJpaTest class AnswerRepositoryTest { - @Autowired - private QuestionnaireRepository questionnaireRepository; - - @Autowired - private AnswerRepository answerRepository; - - @Autowired - private MemberRepository memberRepository; + @Autowired private QuestionnaireRepository questionnaireRepository; + @Autowired private AnswerRepository answerRepository; - @Test - @Transactional - @DisplayName("memberId로 작성한 답변을 가져올 수 있다.") - void findByMember_Id() { - //given - Member member = memberRepository.save(MemberTest.signingUpMember1()); - Questionnaire questionnaire = new Questionnaire(1L, "hello"); - questionnaireRepository.save(questionnaire); - String content = "Ok... bye"; - Answer answer = new Answer(member, questionnaire, content); + @Autowired private MemberRepository memberRepository; - //when - answerRepository.save(answer); - List answers = answerRepository.findByMember_Id(member.getId()); + @Test + @Transactional + @DisplayName("memberId로 작성한 답변을 가져올 수 있다.") + void findByMember_Id() { + // given + Member member = memberRepository.save(MemberTest.signingUpMember1()); + Questionnaire questionnaire = new Questionnaire(1L, "hello"); + questionnaireRepository.save(questionnaire); + String content = "Ok... bye"; + Answer answer = new Answer(member, questionnaire, content); - //then - assertThat(answers).contains(answer); + // when + answerRepository.save(answer); + List answers = answerRepository.findByMember_Id(member.getId()); - } -} \ No newline at end of file + // then + assertThat(answers).contains(answer); + } +} diff --git a/resource-server/src/test/java/com/inhabas/api/domain/signUp/usecase/AnswerServiceTest.java b/resource-server/src/test/java/com/inhabas/api/domain/signUp/usecase/AnswerServiceTest.java index 80a34343..df748512 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/signUp/usecase/AnswerServiceTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/signUp/usecase/AnswerServiceTest.java @@ -1,5 +1,16 @@ package com.inhabas.api.domain.signUp.usecase; +import static com.inhabas.api.domain.member.domain.entity.MemberTest.signingUpMemberAfterProfile; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; import com.inhabas.api.auth.domain.oauth2.member.repository.MemberRepository; import com.inhabas.api.domain.questionnaire.domain.Questionnaire; @@ -7,102 +18,97 @@ import com.inhabas.api.domain.signUp.domain.entity.Answer; import com.inhabas.api.domain.signUp.dto.AnswerDto; import com.inhabas.api.domain.signUp.repository.AnswerRepository; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.ArgumentCaptor; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; - -import static com.inhabas.api.domain.member.domain.entity.MemberTest.signingUpMemberAfterProfile; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; @ExtendWith(MockitoExtension.class) public class AnswerServiceTest { - @InjectMocks - private AnswerServiceImpl answerService; - - @Mock - private AnswerRepository answerRepository; - - @Mock - private MemberRepository memberRepository; - - @Mock - private QuestionnaireRepository questionnaireRepository; - - private static final ArrayList questionnaires = new ArrayList<>() {{ - add(new Questionnaire(1L, "질문 1")); - add(new Questionnaire(2L, "질문 2")); - add(new Questionnaire(3L, "질문 3")); - }}; - - private static final Member member = signingUpMemberAfterProfile(); - - private static final ArrayList savedAnswers = new ArrayList<>() {{ - add(new Answer(member, questionnaires.get(0), "저는 꼭 이 동아리에 입부하고 싶습니다.")); - add(new Answer(member, questionnaires.get(1), "어렸을적부터 빅데이터를 발가락으로 전처리하며 놀았습니다.")); - add(new Answer(member, questionnaires.get(2), "외주를 받아 진행했던 적이 있는데, 아주 잘 되어 스타트업 창업을 진행했습니다.")); - }}; - - private static final ArrayList submittedAnswers = new ArrayList<>() {{ - add(new AnswerDto(1L, "저는 꼭 이 동아리에 입부하고 싶습니다.")); - add(new AnswerDto(2L, "어렸을적부터 빅데이터를 발가락으로 전처리하며 놀았습니다.")); - add(new AnswerDto(3L, "외주를 받아 진행했던 적이 있는데, 아주 잘 되어 스타트업 창업을 진행했습니다.")); - }}; - - @DisplayName("사용자가 작성한 답변이 엔티티로 잘 변환되는지 확인한다.") - @Test - public void saveAnswersTest() { - //given - given(memberRepository.findById(any())).willReturn(Optional.of(member)); - given(answerRepository.findByMember_Id(any())).willReturn(savedAnswers); - given(questionnaireRepository.findAll()).willReturn(questionnaires); - given(questionnaireRepository.countByIdIn(any())).willReturn(3L); - given(questionnaireRepository.findById(1L)).willReturn(Optional.ofNullable(questionnaires.get(0))); - given(questionnaireRepository.findById(2L)).willReturn(Optional.ofNullable(questionnaires.get(1))); - given(questionnaireRepository.findById(3L)).willReturn(Optional.ofNullable(questionnaires.get(2))); - - //when - answerService.saveAnswers(submittedAnswers, member.getId()); - - //then - @SuppressWarnings("unchecked") - ArgumentCaptor> argumentCaptor = ArgumentCaptor.forClass(ArrayList.class); - verify(answerRepository, times(1)).saveAll(argumentCaptor.capture()); - - assertThat(argumentCaptor.getValue()) - .usingRecursiveFieldByFieldElementComparator() - .isEqualTo(savedAnswers); - } - - - @DisplayName("사용자가 저장한 답변을 dto 로 변환해서 반환한다.") - @Test - public void getAnswersTest() { - //given - given(memberRepository.findById(any())).willReturn(Optional.of(member)); - given(questionnaireRepository.findAll()).willReturn(questionnaires); - given(answerRepository.findByMember_Id(any())).willReturn(savedAnswers); - - //when - List returnedDTOs = answerService.getAnswers(member.getId()); - - //then - assertThat(returnedDTOs) - .usingRecursiveComparison() - .isEqualTo(submittedAnswers); - - } - + @InjectMocks private AnswerServiceImpl answerService; + + @Mock private AnswerRepository answerRepository; + + @Mock private MemberRepository memberRepository; + + @Mock private QuestionnaireRepository questionnaireRepository; + + private static final ArrayList questionnaires = + new ArrayList<>() { + { + add(new Questionnaire(1L, "질문 1")); + add(new Questionnaire(2L, "질문 2")); + add(new Questionnaire(3L, "질문 3")); + } + }; + + private static final Member member = signingUpMemberAfterProfile(); + + private static final ArrayList savedAnswers = + new ArrayList<>() { + { + add(new Answer(member, questionnaires.get(0), "저는 꼭 이 동아리에 입부하고 싶습니다.")); + add(new Answer(member, questionnaires.get(1), "어렸을적부터 빅데이터를 발가락으로 전처리하며 놀았습니다.")); + add( + new Answer( + member, questionnaires.get(2), "외주를 받아 진행했던 적이 있는데, 아주 잘 되어 스타트업 창업을 진행했습니다.")); + } + }; + + private static final ArrayList submittedAnswers = + new ArrayList<>() { + { + add(new AnswerDto(1L, "저는 꼭 이 동아리에 입부하고 싶습니다.")); + add(new AnswerDto(2L, "어렸을적부터 빅데이터를 발가락으로 전처리하며 놀았습니다.")); + add(new AnswerDto(3L, "외주를 받아 진행했던 적이 있는데, 아주 잘 되어 스타트업 창업을 진행했습니다.")); + } + }; + + @DisplayName("사용자가 작성한 답변이 엔티티로 잘 변환되는지 확인한다.") + @Test + public void saveAnswersTest() { + // given + given(memberRepository.findById(any())).willReturn(Optional.of(member)); + given(answerRepository.findByMember_Id(any())).willReturn(savedAnswers); + given(questionnaireRepository.findAll()).willReturn(questionnaires); + given(questionnaireRepository.countByIdIn(any())).willReturn(3L); + given(questionnaireRepository.findById(1L)) + .willReturn(Optional.ofNullable(questionnaires.get(0))); + given(questionnaireRepository.findById(2L)) + .willReturn(Optional.ofNullable(questionnaires.get(1))); + given(questionnaireRepository.findById(3L)) + .willReturn(Optional.ofNullable(questionnaires.get(2))); + + // when + answerService.saveAnswers(submittedAnswers, member.getId()); + + // then + @SuppressWarnings("unchecked") + ArgumentCaptor> argumentCaptor = ArgumentCaptor.forClass(ArrayList.class); + verify(answerRepository, times(1)).saveAll(argumentCaptor.capture()); + + assertThat(argumentCaptor.getValue()) + .usingRecursiveFieldByFieldElementComparator() + .isEqualTo(savedAnswers); + } + + @DisplayName("사용자가 저장한 답변을 dto 로 변환해서 반환한다.") + @Test + public void getAnswersTest() { + // given + given(memberRepository.findById(any())).willReturn(Optional.of(member)); + given(questionnaireRepository.findAll()).willReturn(questionnaires); + given(answerRepository.findByMember_Id(any())).willReturn(savedAnswers); + + // when + List returnedDTOs = answerService.getAnswers(member.getId()); + + // then + assertThat(returnedDTOs).usingRecursiveComparison().isEqualTo(submittedAnswers); + } } diff --git a/resource-server/src/test/java/com/inhabas/api/domain/signUp/usecase/SignUpServiceTest.java b/resource-server/src/test/java/com/inhabas/api/domain/signUp/usecase/SignUpServiceTest.java index 659c66cb..2910ca69 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/signUp/usecase/SignUpServiceTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/signUp/usecase/SignUpServiceTest.java @@ -1,297 +1,292 @@ package com.inhabas.api.domain.signUp.usecase; +import static com.inhabas.api.domain.member.domain.entity.MemberTest.signingUpMember1; +import static com.inhabas.api.domain.member.domain.entity.MemberTest.signingUpMemberAfterProfile; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.mockito.BDDMockito.then; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +import org.springframework.test.util.ReflectionTestUtils; + import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; import com.inhabas.api.auth.domain.oauth2.majorInfo.dto.MajorInfoDto; import com.inhabas.api.auth.domain.oauth2.majorInfo.usecase.MajorInfoService; import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; -import com.inhabas.api.auth.domain.oauth2.member.service.MemberService; import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.MemberType; import com.inhabas.api.auth.domain.oauth2.member.repository.MemberRepository; +import com.inhabas.api.auth.domain.oauth2.member.service.MemberService; import com.inhabas.api.auth.domain.oauth2.socialAccount.repository.MemberSocialAccountRepository; import com.inhabas.api.domain.questionnaire.usecase.QuestionnaireService; -import com.inhabas.api.domain.signUp.exception.NotWriteAnswersException; -import com.inhabas.api.domain.signUp.exception.NotWriteProfileException; import com.inhabas.api.domain.signUp.dto.AnswerDto; import com.inhabas.api.domain.signUp.dto.SignUpDto; -import com.inhabas.api.domain.signUpSchedule.usecase.SignUpScheduler; +import com.inhabas.api.domain.signUp.exception.NotWriteAnswersException; +import com.inhabas.api.domain.signUp.exception.NotWriteProfileException; import com.inhabas.api.domain.signUpSchedule.dto.SignUpScheduleDto; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; +import com.inhabas.api.domain.signUpSchedule.usecase.SignUpScheduler; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import org.springframework.test.util.ReflectionTestUtils; - -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import static com.inhabas.api.domain.member.domain.entity.MemberTest.signingUpMember1; -import static com.inhabas.api.domain.member.domain.entity.MemberTest.signingUpMemberAfterProfile; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.given; -import static org.mockito.BDDMockito.then; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; @ExtendWith(MockitoExtension.class) public class SignUpServiceTest { - @InjectMocks - private SignUpServiceImpl signUpService; - @Mock - private MajorInfoService majorInfoService; - @Mock - private MemberRepository memberRepository; - @Mock - private MemberSocialAccountRepository memberSocialAccountRepository; - @Mock - private MemberService memberService; - @Mock - private SignUpScheduler signUpScheduler; - @Mock - private QuestionnaireService questionnaireService; - @Mock - private AnswerService answerService; - - - @DisplayName("(학생) 개인정보 값이 모두 채워진 상태로 제출되면 저장한다.") - @Test - public void isSignedUpTest() { - //given - given(memberSocialAccountRepository.existsByMember_Id(any())).willReturn(true); - - //when - boolean check = signUpService.isSignedUp(any()); - - //then - assertThat(check).isTrue(); - - } - - @DisplayName("(학생) 개인정보 값이 모두 채워진 상태로 제출되면 저장한다.") - @Test - public void saveSignUpFormTest() { - //given - Member member = signingUpMember1(); - SignUpDto signUpForm = SignUpDto.builder() - .name("유동현") - .major("컴퓨터공학과") - .phoneNumber("010-0000-1111") - .grade(1) - .studentId("12345678") - .memberType(MemberType.UNDERGRADUATE) - .build(); - - given(memberRepository.findById(any())).willReturn(Optional.of(member)); - SignUpScheduleDto signUpScheduleDto = new SignUpScheduleDto(); - ReflectionTestUtils.setField(signUpScheduleDto, "generation", 1); - given(signUpScheduler.getSchedule()).willReturn(signUpScheduleDto); - - //when - signUpService.saveSignUpForm(signUpForm, member.getId()); - - //then - assertThat(member.getName()).isEqualTo(signUpForm.getName()); - - } - - @DisplayName("(학생) 개인정보 값이 덜 채워진 상태로 제출되면 실패한다.") - @Test - public void doNotSaveSignUpFormTest() { - //given - Member member = signingUpMember1(); - SignUpDto signUpForm = SignUpDto.builder() - .name("유동현") - // .major("컴퓨터공학과") - .phoneNumber("010-0000-1111") - .grade(1) - .studentId("12345678") - .memberType(MemberType.UNDERGRADUATE) - .build(); - - given(memberRepository.findById(any())).willReturn(Optional.of(member)); - SignUpScheduleDto signUpScheduleDto = new SignUpScheduleDto(); - ReflectionTestUtils.setField(signUpScheduleDto, "generation", 1); - given(signUpScheduler.getSchedule()).willReturn(signUpScheduleDto); - - //when - assertThrows(InvalidInputException.class, - () -> signUpService.saveSignUpForm(signUpForm, member.getId())); - - } - - @DisplayName("(교수) 개인정보 값이 모두 채워진 상태로 제출되면 회원가입과정이 바로 끝난다.") - @Test - public void profSaveSignUpFormTest() { - //given - Member member = signingUpMember1(); - SignUpDto signUpForm = SignUpDto.builder() - .name("유동현") - .major("컴퓨터공학과") - .phoneNumber("010-0000-1111") - .studentId("12345678") - .memberType(MemberType.PROFESSOR) - .build(); - - SignUpScheduleDto signUpScheduleDto = new SignUpScheduleDto(); - ReflectionTestUtils.setField(signUpScheduleDto, "generation", 1); - given(signUpScheduler.getSchedule()).willReturn(signUpScheduleDto); - given(memberRepository.findById(any())).willReturn(Optional.of(member)); - - //when - signUpService.saveSignUpForm(signUpForm, member.getId()); - - //then - verify(memberService).finishSignUp(member); - - } - - @DisplayName("임시저장을 하지 않았던 회원 정보는 null 로 반환한다.") - @Test - public void noSavedMemberProfileTest() { - //given - Member member = signingUpMember1(); - given(memberRepository.findById(any())).willReturn(Optional.of(member)); - - //when - SignUpDto loadedForm = signUpService.loadSignUpForm(member.getId()); - - //then - SignUpDto expectResult = SignUpDto.builder() - .name(null) - .major(null) - .grade(null) - .phoneNumber(null) - .studentId(null) - .memberType(null) - .build(); - - assertThat(loadedForm) - .usingRecursiveComparison() - .isEqualTo(expectResult); - } - - @DisplayName("임시저장을 수행했던 회원 정보를 불러온다.") - @Test - public void loadMemberProfileTest() { - //given - Member member = signingUpMemberAfterProfile(); - given(memberRepository.findById(any())).willReturn(Optional.of(member)); - - //when - SignUpDto loadedForm = signUpService.loadSignUpForm(member.getId()); - - //then - SignUpDto expectResult = SignUpDto.builder() - .name(member.getName()) - .major(member.getSchoolInformation().getMajor()) - .grade(member.getSchoolInformation().getGrade()) - .phoneNumber(member.getPhone()) - .studentId(member.getStudentId()) - .memberType(member.getSchoolInformation().getMemberType()) - .build(); - - assertThat(loadedForm) - .usingRecursiveComparison() - .isEqualTo(expectResult); - } - - @DisplayName("모든 전공 정보를 불러온다.") - @Test - public void getMajorInfoTest() { - //given - given(majorInfoService.getAllMajorInfo()).willReturn(List.of(new MajorInfoDto(2, "공대", "전기공학과"))); - - //when - signUpService.getMajorInfo(); - - //then - then(majorInfoService).should(times(1)).getAllMajorInfo(); - } - - @DisplayName("모든 질문지 리스트를 불러온다.") - @Test - public void getQuestionnaire() { - //given - given(questionnaireService.getQuestionnaire()).willReturn(List.of()); - - //when - signUpService.getQuestionnaire(); - - //then - then(questionnaireService).should(times(1)).getQuestionnaire(); - } - - @DisplayName("답변을 작성하지 않아서 회원가입이 완료되지 않는다.") - @Test - public void notYetWriteAnswersTests() { - //given - Member member = signingUpMemberAfterProfile(); - given(memberRepository.findById(any())).willReturn(Optional.of(member)); - - - //then - assertThrows(NotWriteAnswersException.class, - ()->signUpService.completeSignUp(new ArrayList<>(), member.getId())); - } - - @DisplayName("회원정보를 입력하지 않아서 회원가입이 완료되지 않는다.") - @Test - public void notYetWriteProfileTests() { - //given - Member member = signingUpMember1(); - - //when - given(memberRepository.findById(any())).willReturn(Optional.of(member)); - - //then - assertThrows(NotWriteProfileException.class, - ()->signUpService.completeSignUp(null, member.getId())); - - } - - @DisplayName("특정 회원이 작성한 답변을 저장한다.") - @Test - public void saveAnswers() { - //given - Member member = signingUpMemberAfterProfile(); - ArrayList submittedAnswers = new ArrayList<>() {{ + @InjectMocks private SignUpServiceImpl signUpService; + @Mock private MajorInfoService majorInfoService; + @Mock private MemberRepository memberRepository; + @Mock private MemberSocialAccountRepository memberSocialAccountRepository; + @Mock private MemberService memberService; + @Mock private SignUpScheduler signUpScheduler; + @Mock private QuestionnaireService questionnaireService; + @Mock private AnswerService answerService; + + @DisplayName("(학생) 개인정보 값이 모두 채워진 상태로 제출되면 저장한다.") + @Test + public void isSignedUpTest() { + // given + given(memberSocialAccountRepository.existsByMember_Id(any())).willReturn(true); + + // when + boolean check = signUpService.isSignedUp(any()); + + // then + assertThat(check).isTrue(); + } + + @DisplayName("(학생) 개인정보 값이 모두 채워진 상태로 제출되면 저장한다.") + @Test + public void saveSignUpFormTest() { + // given + Member member = signingUpMember1(); + SignUpDto signUpForm = + SignUpDto.builder() + .name("유동현") + .major("컴퓨터공학과") + .phoneNumber("010-0000-1111") + .grade(1) + .studentId("12345678") + .memberType(MemberType.UNDERGRADUATE) + .build(); + + given(memberRepository.findById(any())).willReturn(Optional.of(member)); + SignUpScheduleDto signUpScheduleDto = new SignUpScheduleDto(); + ReflectionTestUtils.setField(signUpScheduleDto, "generation", 1); + given(signUpScheduler.getSchedule()).willReturn(signUpScheduleDto); + + // when + signUpService.saveSignUpForm(signUpForm, member.getId()); + + // then + assertThat(member.getName()).isEqualTo(signUpForm.getName()); + } + + @DisplayName("(학생) 개인정보 값이 덜 채워진 상태로 제출되면 실패한다.") + @Test + public void doNotSaveSignUpFormTest() { + // given + Member member = signingUpMember1(); + SignUpDto signUpForm = + SignUpDto.builder() + .name("유동현") + // .major("컴퓨터공학과") + .phoneNumber("010-0000-1111") + .grade(1) + .studentId("12345678") + .memberType(MemberType.UNDERGRADUATE) + .build(); + + given(memberRepository.findById(any())).willReturn(Optional.of(member)); + SignUpScheduleDto signUpScheduleDto = new SignUpScheduleDto(); + ReflectionTestUtils.setField(signUpScheduleDto, "generation", 1); + given(signUpScheduler.getSchedule()).willReturn(signUpScheduleDto); + + // when + assertThrows( + InvalidInputException.class, + () -> signUpService.saveSignUpForm(signUpForm, member.getId())); + } + + @DisplayName("(교수) 개인정보 값이 모두 채워진 상태로 제출되면 회원가입과정이 바로 끝난다.") + @Test + public void profSaveSignUpFormTest() { + // given + Member member = signingUpMember1(); + SignUpDto signUpForm = + SignUpDto.builder() + .name("유동현") + .major("컴퓨터공학과") + .phoneNumber("010-0000-1111") + .studentId("12345678") + .memberType(MemberType.PROFESSOR) + .build(); + + SignUpScheduleDto signUpScheduleDto = new SignUpScheduleDto(); + ReflectionTestUtils.setField(signUpScheduleDto, "generation", 1); + given(signUpScheduler.getSchedule()).willReturn(signUpScheduleDto); + given(memberRepository.findById(any())).willReturn(Optional.of(member)); + + // when + signUpService.saveSignUpForm(signUpForm, member.getId()); + + // then + verify(memberService).finishSignUp(member); + } + + @DisplayName("임시저장을 하지 않았던 회원 정보는 null 로 반환한다.") + @Test + public void noSavedMemberProfileTest() { + // given + Member member = signingUpMember1(); + given(memberRepository.findById(any())).willReturn(Optional.of(member)); + + // when + SignUpDto loadedForm = signUpService.loadSignUpForm(member.getId()); + + // then + SignUpDto expectResult = + SignUpDto.builder() + .name(null) + .major(null) + .grade(null) + .phoneNumber(null) + .studentId(null) + .memberType(null) + .build(); + + assertThat(loadedForm).usingRecursiveComparison().isEqualTo(expectResult); + } + + @DisplayName("임시저장을 수행했던 회원 정보를 불러온다.") + @Test + public void loadMemberProfileTest() { + // given + Member member = signingUpMemberAfterProfile(); + given(memberRepository.findById(any())).willReturn(Optional.of(member)); + + // when + SignUpDto loadedForm = signUpService.loadSignUpForm(member.getId()); + + // then + SignUpDto expectResult = + SignUpDto.builder() + .name(member.getName()) + .major(member.getSchoolInformation().getMajor()) + .grade(member.getSchoolInformation().getGrade()) + .phoneNumber(member.getPhone()) + .studentId(member.getStudentId()) + .memberType(member.getSchoolInformation().getMemberType()) + .build(); + + assertThat(loadedForm).usingRecursiveComparison().isEqualTo(expectResult); + } + + @DisplayName("모든 전공 정보를 불러온다.") + @Test + public void getMajorInfoTest() { + // given + given(majorInfoService.getAllMajorInfo()) + .willReturn(List.of(new MajorInfoDto(2, "공대", "전기공학과"))); + + // when + signUpService.getMajorInfo(); + + // then + then(majorInfoService).should(times(1)).getAllMajorInfo(); + } + + @DisplayName("모든 질문지 리스트를 불러온다.") + @Test + public void getQuestionnaire() { + // given + given(questionnaireService.getQuestionnaire()).willReturn(List.of()); + + // when + signUpService.getQuestionnaire(); + + // then + then(questionnaireService).should(times(1)).getQuestionnaire(); + } + + @DisplayName("답변을 작성하지 않아서 회원가입이 완료되지 않는다.") + @Test + public void notYetWriteAnswersTests() { + // given + Member member = signingUpMemberAfterProfile(); + given(memberRepository.findById(any())).willReturn(Optional.of(member)); + + // then + assertThrows( + NotWriteAnswersException.class, + () -> signUpService.completeSignUp(new ArrayList<>(), member.getId())); + } + + @DisplayName("회원정보를 입력하지 않아서 회원가입이 완료되지 않는다.") + @Test + public void notYetWriteProfileTests() { + // given + Member member = signingUpMember1(); + + // when + given(memberRepository.findById(any())).willReturn(Optional.of(member)); + + // then + assertThrows( + NotWriteProfileException.class, () -> signUpService.completeSignUp(null, member.getId())); + } + + @DisplayName("특정 회원이 작성한 답변을 저장한다.") + @Test + public void saveAnswers() { + // given + Member member = signingUpMemberAfterProfile(); + ArrayList submittedAnswers = + new ArrayList<>() { + { add(new AnswerDto(1L, "저는 꼭 이 동아리에 입부하고 싶습니다.")); add(new AnswerDto(2L, "어렸을적부터 빅데이터를 발가락으로 전처리하며 놀았습니다.")); add(new AnswerDto(3L, "외주를 받아 진행했던 적이 있는데, 아주 잘 되어 스타트업 창업을 진행했습니다.")); add(new AnswerDto(4L, "이 동아리에 입부한다면, 말하는 대로 코딩해주는 인공지능 모델을 개발하고 싶습니다.")); - }}; - - //when - signUpService.saveAnswers(submittedAnswers, member.getId()); - - //then - then(answerService).should(times(1)).saveAnswers(any(), any()); - - } - - @DisplayName("회원가입 완료 처리") - @Test - public void completeSignUpTest() { - //given - Member member = signingUpMemberAfterProfile(); - given(memberRepository.findById(any())).willReturn(Optional.of(member)); - ArrayList submittedAnswers = new ArrayList<>() {{ + } + }; + + // when + signUpService.saveAnswers(submittedAnswers, member.getId()); + + // then + then(answerService).should(times(1)).saveAnswers(any(), any()); + } + + @DisplayName("회원가입 완료 처리") + @Test + public void completeSignUpTest() { + // given + Member member = signingUpMemberAfterProfile(); + given(memberRepository.findById(any())).willReturn(Optional.of(member)); + ArrayList submittedAnswers = + new ArrayList<>() { + { add(new AnswerDto(1L, "저는 꼭 이 동아리에 입부하고 싶습니다.")); add(new AnswerDto(2L, "어렸을적부터 빅데이터를 발가락으로 전처리하며 놀았습니다.")); add(new AnswerDto(3L, "외주를 받아 진행했던 적이 있는데, 아주 잘 되어 스타트업 창업을 진행했습니다.")); add(new AnswerDto(4L, "이 동아리에 입부한다면, 말하는 대로 코딩해주는 인공지능 모델을 개발하고 싶습니다.")); - }}; - - //when - signUpService.completeSignUp(submittedAnswers, member.getId()); + } + }; - //then - then(memberService).should(times(1)).finishSignUp(any()); - } + // when + signUpService.completeSignUp(submittedAnswers, member.getId()); + // then + then(memberService).should(times(1)).finishSignUp(any()); + } } diff --git a/resource-server/src/test/java/com/inhabas/api/domain/signUpSchedule/domain/entity/SignUpScheduleTest.java b/resource-server/src/test/java/com/inhabas/api/domain/signUpSchedule/domain/entity/SignUpScheduleTest.java index 450f77ce..27740d64 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/signUpSchedule/domain/entity/SignUpScheduleTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/signUpSchedule/domain/entity/SignUpScheduleTest.java @@ -1,97 +1,123 @@ package com.inhabas.api.domain.signUpSchedule.domain.entity; -import com.inhabas.api.domain.signUpSchedule.exception.InvalidDateException; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; - -import java.time.LocalDateTime; - import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; +import java.time.LocalDateTime; -public class SignUpScheduleTest { - - @DisplayName("스케줄 엔티티를 생성한다.") - @Test - public void createSignUpScheduleEntityTest() { - //given - Integer generation = 1; - LocalDateTime signUpStart = LocalDateTime.of(1000, 1, 1, 0, 0, 0); - LocalDateTime signUpEnd = LocalDateTime.of(1000, 1, 2, 0, 0, 0); - LocalDateTime interviewStart = LocalDateTime.of(1000, 1, 3, 0, 0, 0); - LocalDateTime interviewEnd = LocalDateTime.of(1000, 1, 4, 0, 0, 0); - LocalDateTime resultAnnounce = LocalDateTime.of(1000, 1, 5, 0, 0, 0); - - //when - SignUpSchedule schedule = new SignUpSchedule(generation, signUpStart, signUpEnd, interviewStart, interviewEnd, resultAnnounce); - - //then - assertThat(schedule.getGeneration()).isEqualTo(generation); - assertThat(schedule.getSignupStartDate()).isEqualTo(signUpStart); - assertThat(schedule.getSignupEndDate()).isEqualTo(signUpEnd); - assertThat(schedule.getInterviewStartDate()).isEqualTo(interviewStart); - assertThat(schedule.getInterviewEndDate()).isEqualTo(interviewEnd); - assertThat(schedule.getResultAnnounceDate()).isEqualTo(resultAnnounce); - } - - @DisplayName("등록 날짜가 잘못된 스케줄 엔티티 생성을 시도한다.") - @Test - public void invalidSignUpScheduleTest() { - //given - Integer generation = 1; - LocalDateTime signUpStart = LocalDateTime.of(1000, 1, 2, 0, 0, 0); - LocalDateTime signUpEnd = LocalDateTime.of(1000, 1, 1, 0, 0, 0); - LocalDateTime interviewStart = LocalDateTime.of(1000, 1, 3, 0, 0, 0); - LocalDateTime interviewEnd = LocalDateTime.of(1000, 1, 4, 0, 0, 0); - LocalDateTime resultAnnounce = LocalDateTime.of(1000, 1, 5, 0, 0, 0); - - //when - InvalidDateException invalidDateException = assertThrows(InvalidDateException.class, - () -> new SignUpSchedule(generation, signUpStart, signUpEnd, interviewStart, interviewEnd, resultAnnounce)); - - //then - assertThat(invalidDateException.getMessage()).isEqualTo("등록 마감일이 시작일보다 앞설 수 없습니다."); - } - - @DisplayName("면접 날짜가 잘못된 스케줄 엔티티 생성을 시도한다.") - @Test - public void invalidInterviewScheduleTest() { - //given - Integer generation = 1; - LocalDateTime signUpStart = LocalDateTime.of(1000, 1, 1, 0, 0, 0); - LocalDateTime signUpEnd = LocalDateTime.of(1000, 1, 2, 0, 0, 0); - LocalDateTime interviewStart = LocalDateTime.of(1000, 1, 4, 0, 0, 0); - LocalDateTime interviewEnd = LocalDateTime.of(1000, 1, 3, 0, 0, 0); - LocalDateTime resultAnnounce = LocalDateTime.of(1000, 1, 5, 0, 0, 0); - - //when - InvalidDateException invalidDateException = assertThrows(InvalidDateException.class, - () -> new SignUpSchedule(generation, signUpStart, signUpEnd, interviewStart, interviewEnd, resultAnnounce)); - - //then - assertThat(invalidDateException.getMessage()).isEqualTo("면접 마감일이 시작일보다 앞설 수 없습니다."); - } - - @DisplayName("결과 공고 날짜가 잘못된 스케줄 엔티티 생성을 시도한다.") - @Test - public void invalidAnnounceScheduleTest() { - //given - Integer generation = 1; - LocalDateTime signUpStart = LocalDateTime.of(1000, 1, 2, 0, 0, 0); - LocalDateTime signUpEnd = LocalDateTime.of(1000, 1, 3, 0, 0, 0); - LocalDateTime interviewStart = LocalDateTime.of(1000, 1, 4, 0, 0, 0); - LocalDateTime interviewEnd = LocalDateTime.of(1000, 1, 5, 0, 0, 0); - LocalDateTime resultAnnounce = LocalDateTime.of(1000, 1, 1, 0, 0, 0); - - //when - InvalidDateException invalidDateException = assertThrows(InvalidDateException.class, - () -> new SignUpSchedule(generation, signUpStart, signUpEnd, interviewStart, interviewEnd, resultAnnounce)); - - //then - assertThat(invalidDateException.getMessage()).isEqualTo("결과 발표일이 면접 마감일보다 앞설 수 없습니다."); - } +import com.inhabas.api.domain.signUpSchedule.exception.InvalidDateException; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +public class SignUpScheduleTest { + @DisplayName("스케줄 엔티티를 생성한다.") + @Test + public void createSignUpScheduleEntityTest() { + // given + Integer generation = 1; + LocalDateTime signUpStart = LocalDateTime.of(1000, 1, 1, 0, 0, 0); + LocalDateTime signUpEnd = LocalDateTime.of(1000, 1, 2, 0, 0, 0); + LocalDateTime interviewStart = LocalDateTime.of(1000, 1, 3, 0, 0, 0); + LocalDateTime interviewEnd = LocalDateTime.of(1000, 1, 4, 0, 0, 0); + LocalDateTime resultAnnounce = LocalDateTime.of(1000, 1, 5, 0, 0, 0); + + // when + SignUpSchedule schedule = + new SignUpSchedule( + generation, signUpStart, signUpEnd, interviewStart, interviewEnd, resultAnnounce); + + // then + assertThat(schedule.getGeneration()).isEqualTo(generation); + assertThat(schedule.getSignupStartDate()).isEqualTo(signUpStart); + assertThat(schedule.getSignupEndDate()).isEqualTo(signUpEnd); + assertThat(schedule.getInterviewStartDate()).isEqualTo(interviewStart); + assertThat(schedule.getInterviewEndDate()).isEqualTo(interviewEnd); + assertThat(schedule.getResultAnnounceDate()).isEqualTo(resultAnnounce); + } + + @DisplayName("등록 날짜가 잘못된 스케줄 엔티티 생성을 시도한다.") + @Test + public void invalidSignUpScheduleTest() { + // given + Integer generation = 1; + LocalDateTime signUpStart = LocalDateTime.of(1000, 1, 2, 0, 0, 0); + LocalDateTime signUpEnd = LocalDateTime.of(1000, 1, 1, 0, 0, 0); + LocalDateTime interviewStart = LocalDateTime.of(1000, 1, 3, 0, 0, 0); + LocalDateTime interviewEnd = LocalDateTime.of(1000, 1, 4, 0, 0, 0); + LocalDateTime resultAnnounce = LocalDateTime.of(1000, 1, 5, 0, 0, 0); + + // when + InvalidDateException invalidDateException = + assertThrows( + InvalidDateException.class, + () -> + new SignUpSchedule( + generation, + signUpStart, + signUpEnd, + interviewStart, + interviewEnd, + resultAnnounce)); + + // then + assertThat(invalidDateException.getMessage()).isEqualTo("등록 마감일이 시작일보다 앞설 수 없습니다."); + } + + @DisplayName("면접 날짜가 잘못된 스케줄 엔티티 생성을 시도한다.") + @Test + public void invalidInterviewScheduleTest() { + // given + Integer generation = 1; + LocalDateTime signUpStart = LocalDateTime.of(1000, 1, 1, 0, 0, 0); + LocalDateTime signUpEnd = LocalDateTime.of(1000, 1, 2, 0, 0, 0); + LocalDateTime interviewStart = LocalDateTime.of(1000, 1, 4, 0, 0, 0); + LocalDateTime interviewEnd = LocalDateTime.of(1000, 1, 3, 0, 0, 0); + LocalDateTime resultAnnounce = LocalDateTime.of(1000, 1, 5, 0, 0, 0); + + // when + InvalidDateException invalidDateException = + assertThrows( + InvalidDateException.class, + () -> + new SignUpSchedule( + generation, + signUpStart, + signUpEnd, + interviewStart, + interviewEnd, + resultAnnounce)); + + // then + assertThat(invalidDateException.getMessage()).isEqualTo("면접 마감일이 시작일보다 앞설 수 없습니다."); + } + + @DisplayName("결과 공고 날짜가 잘못된 스케줄 엔티티 생성을 시도한다.") + @Test + public void invalidAnnounceScheduleTest() { + // given + Integer generation = 1; + LocalDateTime signUpStart = LocalDateTime.of(1000, 1, 2, 0, 0, 0); + LocalDateTime signUpEnd = LocalDateTime.of(1000, 1, 3, 0, 0, 0); + LocalDateTime interviewStart = LocalDateTime.of(1000, 1, 4, 0, 0, 0); + LocalDateTime interviewEnd = LocalDateTime.of(1000, 1, 5, 0, 0, 0); + LocalDateTime resultAnnounce = LocalDateTime.of(1000, 1, 1, 0, 0, 0); + + // when + InvalidDateException invalidDateException = + assertThrows( + InvalidDateException.class, + () -> + new SignUpSchedule( + generation, + signUpStart, + signUpEnd, + interviewStart, + interviewEnd, + resultAnnounce)); + + // then + assertThat(invalidDateException.getMessage()).isEqualTo("결과 발표일이 면접 마감일보다 앞설 수 없습니다."); + } } diff --git a/resource-server/src/test/java/com/inhabas/api/domain/signUpSchedule/domain/usecase/StrictSignUpSchedulerTest.java b/resource-server/src/test/java/com/inhabas/api/domain/signUpSchedule/domain/usecase/StrictSignUpSchedulerTest.java index 2a2fa3e6..cf201c8d 100644 --- a/resource-server/src/test/java/com/inhabas/api/domain/signUpSchedule/domain/usecase/StrictSignUpSchedulerTest.java +++ b/resource-server/src/test/java/com/inhabas/api/domain/signUpSchedule/domain/usecase/StrictSignUpSchedulerTest.java @@ -1,138 +1,144 @@ package com.inhabas.api.domain.signUpSchedule.domain.usecase; -import com.inhabas.api.domain.signUpSchedule.domain.entity.SignUpSchedule; -import com.inhabas.api.domain.signUpSchedule.dto.SignUpScheduleDto; -import com.inhabas.api.domain.signUpSchedule.repository.SignUpScheduleRepository; -import com.inhabas.api.domain.signUpSchedule.usecase.SignUpSchedulerStrict; -import com.inhabas.testAnnotataion.DefaultDataJpaTest; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.then; +import static org.mockito.Mockito.times; + +import java.time.LocalDateTime; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager; import org.springframework.boot.test.mock.mockito.SpyBean; import org.springframework.context.annotation.Import; import org.springframework.test.annotation.DirtiesContext; -import java.time.LocalDateTime; +import com.inhabas.api.domain.signUpSchedule.domain.entity.SignUpSchedule; +import com.inhabas.api.domain.signUpSchedule.dto.SignUpScheduleDto; +import com.inhabas.api.domain.signUpSchedule.repository.SignUpScheduleRepository; +import com.inhabas.api.domain.signUpSchedule.usecase.SignUpSchedulerStrict; +import com.inhabas.testAnnotataion.DefaultDataJpaTest; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.then; -import static org.mockito.Mockito.times; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; @DefaultDataJpaTest @Import(SignUpSchedulerStrict.class) @DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) public class StrictSignUpSchedulerTest { - @Autowired - SignUpSchedulerStrict signUpScheduler; - - @SpyBean - SignUpScheduleRepository signUpScheduleRepository; - - @Autowired - TestEntityManager entityManager; - - - @DisplayName("스케줄이 하나도 없으면 default 스케줄을 생성한다.") - @Test - public void initializeScheduleTest() { - //when - SignUpScheduleDto schedule = signUpScheduler.getSchedule(); - - //then - assertThat(schedule).isNotNull(); - assertThat(schedule.getSignupStartDate().toString()).isEqualTo("1970-01-01T00:00"); - then(signUpScheduleRepository).should(times(1)).save(any()); - then(signUpScheduleRepository).should(times(1)).findAll(); - } - - @DisplayName("기존 스케줄을 불러온다.") - @Test - public void getScheduleTest() { - //given - SignUpSchedule existingSchedule = new SignUpSchedule(999, - LocalDateTime.of(2022, 1, 1, 0, 0, 0), - LocalDateTime.of(2022, 1, 2, 0, 0, 0), - LocalDateTime.of(2022, 1, 3, 0, 0, 0), - LocalDateTime.of(2022, 1, 4, 0, 0, 0), - LocalDateTime.of(2022, 1, 5, 0, 0, 0)); - existingSchedule = entityManager.persist(existingSchedule); - - //when - SignUpScheduleDto schedule = signUpScheduler.getSchedule(); - - //then - assertThat(schedule).isNotNull(); - assertThat(schedule) - .usingRecursiveComparison() - .isEqualTo(SignUpScheduleDto.from(existingSchedule)); - then(signUpScheduleRepository).should(times(1)).findAll(); - } - - @DisplayName("기존의 스케줄을 변경한다.") - @Test - public void updateScheduleTest() { - //given - SignUpSchedule schedule = entityManager.persist(new SignUpSchedule(1, + @Autowired SignUpSchedulerStrict signUpScheduler; + + @SpyBean SignUpScheduleRepository signUpScheduleRepository; + + @Autowired TestEntityManager entityManager; + + @DisplayName("스케줄이 하나도 없으면 default 스케줄을 생성한다.") + @Test + public void initializeScheduleTest() { + // when + SignUpScheduleDto schedule = signUpScheduler.getSchedule(); + + // then + assertThat(schedule).isNotNull(); + assertThat(schedule.getSignupStartDate().toString()).isEqualTo("1970-01-01T00:00"); + then(signUpScheduleRepository).should(times(1)).save(any()); + then(signUpScheduleRepository).should(times(1)).findAll(); + } + + @DisplayName("기존 스케줄을 불러온다.") + @Test + public void getScheduleTest() { + // given + SignUpSchedule existingSchedule = + new SignUpSchedule( + 999, + LocalDateTime.of(2022, 1, 1, 0, 0, 0), + LocalDateTime.of(2022, 1, 2, 0, 0, 0), + LocalDateTime.of(2022, 1, 3, 0, 0, 0), + LocalDateTime.of(2022, 1, 4, 0, 0, 0), + LocalDateTime.of(2022, 1, 5, 0, 0, 0)); + existingSchedule = entityManager.persist(existingSchedule); + + // when + SignUpScheduleDto schedule = signUpScheduler.getSchedule(); + + // then + assertThat(schedule).isNotNull(); + assertThat(schedule) + .usingRecursiveComparison() + .isEqualTo(SignUpScheduleDto.from(existingSchedule)); + then(signUpScheduleRepository).should(times(1)).findAll(); + } + + @DisplayName("기존의 스케줄을 변경한다.") + @Test + public void updateScheduleTest() { + // given + SignUpSchedule schedule = + entityManager.persist( + new SignUpSchedule( + 1, LocalDateTime.of(2022, 1, 1, 0, 0, 0), LocalDateTime.of(2022, 1, 2, 0, 0, 0), LocalDateTime.of(2022, 1, 3, 0, 0, 0), LocalDateTime.of(2022, 1, 4, 0, 0, 0), LocalDateTime.of(2022, 1, 5, 0, 0, 0))); - SignUpScheduleDto signUpScheduleDto = SignUpScheduleDto.from(schedule); - - //when - signUpScheduler.updateSchedule(signUpScheduleDto); - - //then - then(signUpScheduleRepository).should(times(1)).save(any(SignUpSchedule.class)); - then(signUpScheduleRepository).should(times(2)).findAll(); - } - - @DisplayName("아무 데이터가 없을 때, 디폴트 값을 생성한 후 변경한다.") - @Test - public void updateBeforeInitializeScheduleTest() { - //given - SignUpScheduleDto signUpScheduleDto = new SignUpScheduleDto( - 1, LocalDateTime.of(2022, 1, 1, 0, 0, 0), - LocalDateTime.of(2022, 1, 2, 0, 0, 0), - LocalDateTime.of(2022, 1, 3, 0, 0, 0), - LocalDateTime.of(2022, 1, 4, 0, 0, 0), - LocalDateTime.of(2022, 1, 5, 0, 0, 0) - ); - - //when - signUpScheduler.updateSchedule(signUpScheduleDto); - - //then - then(signUpScheduleRepository).should(times(2)).save(any(SignUpSchedule.class)); - then(signUpScheduleRepository).should(times(2)).findAll(); - } - - @DisplayName("스케줄이 여러 개 있었을 때, 기존 정보를 모두 제거한 후 변경한다.") - @Test - public void updateBeforeDeleteAllScheduleTest() { - //given - SignUpSchedule schedule = new SignUpSchedule(1, - LocalDateTime.of(2022, 1, 1, 0, 0, 0), - LocalDateTime.of(2022, 1, 2, 0, 0, 0), - LocalDateTime.of(2022, 1, 3, 0, 0, 0), - LocalDateTime.of(2022, 1, 4, 0, 0, 0), - LocalDateTime.of(2022, 1, 5, 0, 0, 0)); - entityManager.persist(schedule); - entityManager.persist(schedule); - entityManager.persist(schedule); - - SignUpScheduleDto signUpScheduleDto = SignUpScheduleDto.from(schedule); - - //when - signUpScheduler.updateSchedule(signUpScheduleDto); - - //then - then(signUpScheduleRepository).should(times(1)).save(any(SignUpSchedule.class)); - then(signUpScheduleRepository).should(times(2)).findAll(); - } + SignUpScheduleDto signUpScheduleDto = SignUpScheduleDto.from(schedule); + + // when + signUpScheduler.updateSchedule(signUpScheduleDto); + + // then + then(signUpScheduleRepository).should(times(1)).save(any(SignUpSchedule.class)); + then(signUpScheduleRepository).should(times(2)).findAll(); + } + + @DisplayName("아무 데이터가 없을 때, 디폴트 값을 생성한 후 변경한다.") + @Test + public void updateBeforeInitializeScheduleTest() { + // given + SignUpScheduleDto signUpScheduleDto = + new SignUpScheduleDto( + 1, + LocalDateTime.of(2022, 1, 1, 0, 0, 0), + LocalDateTime.of(2022, 1, 2, 0, 0, 0), + LocalDateTime.of(2022, 1, 3, 0, 0, 0), + LocalDateTime.of(2022, 1, 4, 0, 0, 0), + LocalDateTime.of(2022, 1, 5, 0, 0, 0)); + + // when + signUpScheduler.updateSchedule(signUpScheduleDto); + + // then + then(signUpScheduleRepository).should(times(2)).save(any(SignUpSchedule.class)); + then(signUpScheduleRepository).should(times(2)).findAll(); + } + + @DisplayName("스케줄이 여러 개 있었을 때, 기존 정보를 모두 제거한 후 변경한다.") + @Test + public void updateBeforeDeleteAllScheduleTest() { + // given + SignUpSchedule schedule = + new SignUpSchedule( + 1, + LocalDateTime.of(2022, 1, 1, 0, 0, 0), + LocalDateTime.of(2022, 1, 2, 0, 0, 0), + LocalDateTime.of(2022, 1, 3, 0, 0, 0), + LocalDateTime.of(2022, 1, 4, 0, 0, 0), + LocalDateTime.of(2022, 1, 5, 0, 0, 0)); + entityManager.persist(schedule); + entityManager.persist(schedule); + entityManager.persist(schedule); + + SignUpScheduleDto signUpScheduleDto = SignUpScheduleDto.from(schedule); + + // when + signUpScheduler.updateSchedule(signUpScheduleDto); + + // then + then(signUpScheduleRepository).should(times(1)).save(any(SignUpSchedule.class)); + then(signUpScheduleRepository).should(times(2)).findAll(); + } } diff --git a/resource-server/src/test/java/com/inhabas/api/securityConfig/RoleHierarchyTest.java b/resource-server/src/test/java/com/inhabas/api/securityConfig/RoleHierarchyTest.java index 4f4a4d16..16fbc5e2 100644 --- a/resource-server/src/test/java/com/inhabas/api/securityConfig/RoleHierarchyTest.java +++ b/resource-server/src/test/java/com/inhabas/api/securityConfig/RoleHierarchyTest.java @@ -1,103 +1,86 @@ package com.inhabas.api.securityConfig; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -import com.inhabas.api.auth.AuthBeansConfig; -import com.inhabas.api.auth.domain.oauth2.member.security.Hierarchical; -import com.inhabas.api.auth.domain.token.JwtAccessDeniedHandler; -import com.inhabas.api.auth.domain.token.TokenResolver; -import com.inhabas.api.auth.domain.token.jwtUtils.JwtAuthenticationProvider; -import com.inhabas.api.auth.domain.token.jwtUtils.JwtTokenUtil; -import com.inhabas.api.auth.domain.token.securityFilter.JwtAuthenticationEntryPoint; -import com.inhabas.api.domain.board.usecase.BoardService; import com.inhabas.api.web.BoardController; import com.inhabas.testAnnotataion.DefaultWebMvcTest; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.security.test.context.support.WithMockUser; -import org.springframework.test.web.servlet.MockMvc; @DefaultWebMvcTest(BoardController.class) public class RoleHierarchyTest { -// @Autowired -// private MockMvc mockMvc; -// -// @Autowired -// BoardController boardController; -// -// @MockBean -// BoardService boardService; -// -// @MockBean -// MemberService memberService; -// -// @MockBean -// JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint; -// -// -// @Test -// @DisplayName("관리자는 일반회원 자료에 접근 가능하다.") -// @WithMockUser(roles = "ADMIN") -// public void adminCanAccessToResourceForBasicMember() throws Exception { -// 공지사항_게시판_접근(); -// } -// -// @Test -// @DisplayName("회장은 일반회원 자료에 접근 가능하다.") -// @WithMockUser(roles = "CHIEF") -// public void chiefCanAccessToResourceForBasicMember() throws Exception { -// 공지사항_게시판_접근(); -// } -// -// @Test -// @DisplayName("회장단은 일반회원 자료에 접근 가능하다.") -// @WithMockUser(roles = "EXECUTIVES") -// public void executivesCanAccessToResourceForBasicMember() throws Exception { -// 공지사항_게시판_접근(); -// } -// -// @Test -// @DisplayName("일반회원은 일반회원 자료에 접근 가능하다.") -// @WithMockUser(roles = "BASIC") -// public void basicMemberCanAccessToResourceForBasicMember() throws Exception { -// 공지사항_게시판_접근(); -// } -// -// @Test -// @DisplayName("비활동회원은 일반회원 자료에 접근 불가능하다.") -// @WithMockUser(roles = "DEACTIVATED") -// public void deactivatedMemberCannotAccessToResourceForBasicMember() throws Exception { -// 공지사항_게시판_접근_불가(); -// } -// -// @Test -// @DisplayName("미승인회원은 일반회원 자료에 접근 불가능하다.") -// @WithMockUser(roles = "NOT_APPROVED") -// public void notApprovedMemberCannotAccessToResourceForBasicMember() throws Exception { -// 공지사항_게시판_접근_불가(); -// } -// -// @Test -// @DisplayName("비회원은 일반회원 자료에 접근 불가능하다.") -// @WithMockUser(roles = "ANONYMOUS") -// public void anonymousCannotAccessToResourceForBasicMember() throws Exception { -// 공지사항_게시판_접근_불가(); -// } -// -// -// private void 공지사항_게시판_접근() throws Exception { -// mockMvc.perform(get("/boards") -// .param("menu_id", "6")) -// .andExpect(status().isOk()); -// } -// -// private void 공지사항_게시판_접근_불가() throws Exception { -// mockMvc.perform(get("/boards") -// .param("menu_id", "6")) -// .andExpect(status().isForbidden()); -// } + // @Autowired + // private MockMvc mockMvc; + // + // @Autowired + // BoardController boardController; + // + // @MockBean + // BoardService boardService; + // + // @MockBean + // MemberService memberService; + // + // @MockBean + // JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint; + // + // + // @Test + // @DisplayName("관리자는 일반회원 자료에 접근 가능하다.") + // @WithMockUser(roles = "ADMIN") + // public void adminCanAccessToResourceForBasicMember() throws Exception { + // 공지사항_게시판_접근(); + // } + // + // @Test + // @DisplayName("회장은 일반회원 자료에 접근 가능하다.") + // @WithMockUser(roles = "CHIEF") + // public void chiefCanAccessToResourceForBasicMember() throws Exception { + // 공지사항_게시판_접근(); + // } + // + // @Test + // @DisplayName("회장단은 일반회원 자료에 접근 가능하다.") + // @WithMockUser(roles = "EXECUTIVES") + // public void executivesCanAccessToResourceForBasicMember() throws Exception { + // 공지사항_게시판_접근(); + // } + // + // @Test + // @DisplayName("일반회원은 일반회원 자료에 접근 가능하다.") + // @WithMockUser(roles = "BASIC") + // public void basicMemberCanAccessToResourceForBasicMember() throws Exception { + // 공지사항_게시판_접근(); + // } + // + // @Test + // @DisplayName("비활동회원은 일반회원 자료에 접근 불가능하다.") + // @WithMockUser(roles = "DEACTIVATED") + // public void deactivatedMemberCannotAccessToResourceForBasicMember() throws Exception { + // 공지사항_게시판_접근_불가(); + // } + // + // @Test + // @DisplayName("미승인회원은 일반회원 자료에 접근 불가능하다.") + // @WithMockUser(roles = "NOT_APPROVED") + // public void notApprovedMemberCannotAccessToResourceForBasicMember() throws Exception { + // 공지사항_게시판_접근_불가(); + // } + // + // @Test + // @DisplayName("비회원은 일반회원 자료에 접근 불가능하다.") + // @WithMockUser(roles = "ANONYMOUS") + // public void anonymousCannotAccessToResourceForBasicMember() throws Exception { + // 공지사항_게시판_접근_불가(); + // } + // + // + // private void 공지사항_게시판_접근() throws Exception { + // mockMvc.perform(get("/boards") + // .param("menu_id", "6")) + // .andExpect(status().isOk()); + // } + // + // private void 공지사항_게시판_접근_불가() throws Exception { + // mockMvc.perform(get("/boards") + // .param("menu_id", "6")) + // .andExpect(status().isForbidden()); + // } } diff --git a/resource-server/src/test/java/com/inhabas/api/web/BoardControllerTest.java b/resource-server/src/test/java/com/inhabas/api/web/BoardControllerTest.java index b5fed084..f983f390 100644 --- a/resource-server/src/test/java/com/inhabas/api/web/BoardControllerTest.java +++ b/resource-server/src/test/java/com/inhabas/api/web/BoardControllerTest.java @@ -1,194 +1,171 @@ package com.inhabas.api.web; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.web.servlet.MockMvc; + import com.fasterxml.jackson.databind.ObjectMapper; import com.inhabas.api.auth.domain.oauth2.member.service.MemberService; import com.inhabas.api.domain.board.domain.NormalBoard; -import com.inhabas.api.domain.board.dto.BoardDto; import com.inhabas.api.domain.board.usecase.BoardService; -import com.inhabas.api.domain.menu.domain.valueObject.MenuId; import com.inhabas.testAnnotataion.NoSecureWebMvcTest; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageImpl; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Sort; -import org.springframework.http.MediaType; -import org.springframework.test.web.servlet.MockMvc; - -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.doNothing; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; -import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @NoSecureWebMvcTest(BoardController.class) public class BoardControllerTest { - @Autowired - private MockMvc mvc; - - @Autowired - private ObjectMapper objectMapper; - - @Autowired - BoardController boardController; - - @MockBean - BoardService boardService; - - @MockBean - MemberService memberService; - - @MockBean - NormalBoard normalBoard; - -// @DisplayName("게시글 저장을 요청한다.") -// @Test -// @WithMockJwtAuthenticationToken -// public void addNewBoard() throws Exception { -// //given -// SaveBoardDto saveBoardDto = new SaveBoardDto("This is title", "This is content", new MenuId(1)); -// given(boardService.write(any(), any(SaveBoardDto.class))).willReturn(1); -// -// // when -// mvc.perform(post("/board") -// .contentType(MediaType.APPLICATION_JSON) -// .content(objectMapper.writeValueAsString(saveBoardDto))) -// .andExpect(status().isCreated()) -// .andExpect(content().string("1")); -// } - -// @DisplayName("게시글 수정을 요청한다.") -// @Test -// @WithMockJwtAuthenticationToken -// public void updateBoard() throws Exception{ -// //given -// UpdateBoardDto updateBoardDto = new UpdateBoardDto(1, "제목을 수정하였습니다.", "내용을 수정하였습니다."); -// given(boardService.update(any(), any(UpdateBoardDto.class))).willReturn(1); -// -// // when -// mvc.perform(put("/board") -// .contentType(MediaType.APPLICATION_JSON) -// .content(objectMapper.writeValueAsString(updateBoardDto))) -// .andExpect(status().isOk()) -// .andExpect(content().string("1")); -// } - -// @DisplayName("게시글 삭제를 요청한다.") -// @Test -// public void deleteBoard() throws Exception{ -// //given -// doNothing().when(boardService).delete(any(), anyInt()); -// -// // when -// mvc.perform(delete("/board/1")) -// .andExpect(status().isNoContent()); -// } - -// @DisplayName("게시글 목록 조회를 요청한다.") -// @Test -// public void getBoardList() throws Exception { -// PageRequest pageable = PageRequest.of(2,1, Sort.Direction.ASC, "id"); -// -// List results = new ArrayList<>(); -// results.add(new BoardDto(1, "Shown Title1", null, "Mingyeom", -// new MenuId(2), LocalDateTime.now(), null)); -// results.add(new BoardDto(2, "Shown Title2", null, "Mingyeom", -// new MenuId(2), LocalDateTime.now(), null)); -// results.add(new BoardDto(3, "Shown Title3", null, "Mingyeom", -// new MenuId(2), LocalDateTime.now(), null)); -// -// Page expectedBoardDto = new PageImpl<>(results, pageable, results.size()); -// -// given(boardService.getBoardList(any(), any())).willReturn(expectedBoardDto); -// -// // when -// String responseBody = mvc.perform(get("/boards?menu_id=6") -// .contentType(MediaType.APPLICATION_JSON) -// .param("page", "2") -// .param("size", "1") -// .param("sort", "ASC") -// .param("properties", "id")) -// .andExpect(status().isOk()) -// .andDo(print()) -// .andReturn() -// .getResponse().getContentAsString(); -// -// // then -// assertThat(responseBody).isEqualTo(objectMapper.writeValueAsString(expectedBoardDto)); -// } - -// @DisplayName("게시글 단일 조회를 요청한다.") -// @Test -// public void getBoardDetail() throws Exception{ -// //given -// BoardDto boardDto = -// new BoardDto(1, "Shown Title", "Shown Content", "Mingyeom", -// new MenuId(1), LocalDateTime.now(), null); -// given(boardService.getBoard(anyLong())).willReturn(boardDto); -// -// // when -// String responseBody = mvc.perform(get("/board/1")) -// .andExpect(status().isOk()) -// .andReturn() -// .getResponse().getContentAsString(); -// -// // then -// assertThat(responseBody).isEqualTo(objectMapper.writeValueAsString(boardDto)); -// -// } - -// @DisplayName("게시글 작성 시 Title의 길이가 범위를 초과해 오류 발생") -// @Test -// @WithMockJwtAuthenticationToken -// public void TitleIsTooLongError() throws Exception { -// //given -// SaveBoardDto saveBoardDto = new SaveBoardDto("title".repeat(20) + ".", "content", new MenuId(1)); -// -// // when -// String errorMessage = Objects.requireNonNull( -// mvc.perform(post("/board") -// .contentType(MediaType.APPLICATION_JSON) -// .content(objectMapper.writeValueAsString(saveBoardDto))) -// .andExpect(status().isBadRequest()) -// .andReturn() -// .getResolvedException()) -// .getMessage(); -// -// // then -// assertThat(errorMessage).isNotBlank(); -// assertThat(errorMessage).contains("제목은 최대 100자입니다."); -// } - -// @DisplayName("게시글 작성 시 Contents가 null인 경우 오류 발생") -// @Test -// @WithMockJwtAuthenticationToken -// public void ContentIsNullError() throws Exception { -// //given -// SaveBoardDto saveBoardDto = new SaveBoardDto("title", " ", new MenuId(1)); -// -// // when -// String errorMessage = Objects.requireNonNull( -// mvc.perform(post("/board") -// .contentType(MediaType.APPLICATION_JSON) -// .content(objectMapper.writeValueAsString(saveBoardDto))) -// .andExpect(status().isBadRequest()) -// .andReturn() -// .getResolvedException()) -// .getMessage(); -// -// // then -// assertThat(errorMessage).isNotBlank(); -// assertThat(errorMessage).contains("본문을 입력하세요."); -// } + @Autowired private MockMvc mvc; + + @Autowired private ObjectMapper objectMapper; + + @Autowired BoardController boardController; + + @MockBean BoardService boardService; + + @MockBean MemberService memberService; + + @MockBean NormalBoard normalBoard; + + // @DisplayName("게시글 저장을 요청한다.") + // @Test + // @WithMockJwtAuthenticationToken + // public void addNewBoard() throws Exception { + // //given + // SaveBoardDto saveBoardDto = new SaveBoardDto("This is title", "This is content", new + // MenuId(1)); + // given(boardService.write(any(), any(SaveBoardDto.class))).willReturn(1); + // + // // when + // mvc.perform(post("/board") + // .contentType(MediaType.APPLICATION_JSON) + // .content(objectMapper.writeValueAsString(saveBoardDto))) + // .andExpect(status().isCreated()) + // .andExpect(content().string("1")); + // } + + // @DisplayName("게시글 수정을 요청한다.") + // @Test + // @WithMockJwtAuthenticationToken + // public void updateBoard() throws Exception{ + // //given + // UpdateBoardDto updateBoardDto = new UpdateBoardDto(1, "제목을 수정하였습니다.", "내용을 수정하였습니다."); + // given(boardService.update(any(), any(UpdateBoardDto.class))).willReturn(1); + // + // // when + // mvc.perform(put("/board") + // .contentType(MediaType.APPLICATION_JSON) + // .content(objectMapper.writeValueAsString(updateBoardDto))) + // .andExpect(status().isOk()) + // .andExpect(content().string("1")); + // } + + // @DisplayName("게시글 삭제를 요청한다.") + // @Test + // public void deleteBoard() throws Exception{ + // //given + // doNothing().when(boardService).delete(any(), anyInt()); + // + // // when + // mvc.perform(delete("/board/1")) + // .andExpect(status().isNoContent()); + // } + + // @DisplayName("게시글 목록 조회를 요청한다.") + // @Test + // public void getBoardList() throws Exception { + // PageRequest pageable = PageRequest.of(2,1, Sort.Direction.ASC, "id"); + // + // List results = new ArrayList<>(); + // results.add(new BoardDto(1, "Shown Title1", null, "Mingyeom", + // new MenuId(2), LocalDateTime.now(), null)); + // results.add(new BoardDto(2, "Shown Title2", null, "Mingyeom", + // new MenuId(2), LocalDateTime.now(), null)); + // results.add(new BoardDto(3, "Shown Title3", null, "Mingyeom", + // new MenuId(2), LocalDateTime.now(), null)); + // + // Page expectedBoardDto = new PageImpl<>(results, pageable, results.size()); + // + // given(boardService.getBoardList(any(), any())).willReturn(expectedBoardDto); + // + // // when + // String responseBody = mvc.perform(get("/boards?menu_id=6") + // .contentType(MediaType.APPLICATION_JSON) + // .param("page", "2") + // .param("size", "1") + // .param("sort", "ASC") + // .param("properties", "id")) + // .andExpect(status().isOk()) + // .andDo(print()) + // .andReturn() + // .getResponse().getContentAsString(); + // + // // then + // assertThat(responseBody).isEqualTo(objectMapper.writeValueAsString(expectedBoardDto)); + // } + + // @DisplayName("게시글 단일 조회를 요청한다.") + // @Test + // public void getBoardDetail() throws Exception{ + // //given + // BoardDto boardDto = + // new BoardDto(1, "Shown Title", "Shown Content", "Mingyeom", + // new MenuId(1), LocalDateTime.now(), null); + // given(boardService.getBoard(anyLong())).willReturn(boardDto); + // + // // when + // String responseBody = mvc.perform(get("/board/1")) + // .andExpect(status().isOk()) + // .andReturn() + // .getResponse().getContentAsString(); + // + // // then + // assertThat(responseBody).isEqualTo(objectMapper.writeValueAsString(boardDto)); + // + // } + + // @DisplayName("게시글 작성 시 Title의 길이가 범위를 초과해 오류 발생") + // @Test + // @WithMockJwtAuthenticationToken + // public void TitleIsTooLongError() throws Exception { + // //given + // SaveBoardDto saveBoardDto = new SaveBoardDto("title".repeat(20) + ".", "content", new + // MenuId(1)); + // + // // when + // String errorMessage = Objects.requireNonNull( + // mvc.perform(post("/board") + // .contentType(MediaType.APPLICATION_JSON) + // .content(objectMapper.writeValueAsString(saveBoardDto))) + // .andExpect(status().isBadRequest()) + // .andReturn() + // .getResolvedException()) + // .getMessage(); + // + // // then + // assertThat(errorMessage).isNotBlank(); + // assertThat(errorMessage).contains("제목은 최대 100자입니다."); + // } + + // @DisplayName("게시글 작성 시 Contents가 null인 경우 오류 발생") + // @Test + // @WithMockJwtAuthenticationToken + // public void ContentIsNullError() throws Exception { + // //given + // SaveBoardDto saveBoardDto = new SaveBoardDto("title", " ", new MenuId(1)); + // + // // when + // String errorMessage = Objects.requireNonNull( + // mvc.perform(post("/board") + // .contentType(MediaType.APPLICATION_JSON) + // .content(objectMapper.writeValueAsString(saveBoardDto))) + // .andExpect(status().isBadRequest()) + // .andReturn() + // .getResolvedException()) + // .getMessage(); + // + // // then + // assertThat(errorMessage).isNotBlank(); + // assertThat(errorMessage).contains("본문을 입력하세요."); + // } } diff --git a/resource-server/src/test/java/com/inhabas/api/web/BudgetApplicationControllerTest.java b/resource-server/src/test/java/com/inhabas/api/web/BudgetApplicationControllerTest.java index 47ab5428..15dfeda3 100644 --- a/resource-server/src/test/java/com/inhabas/api/web/BudgetApplicationControllerTest.java +++ b/resource-server/src/test/java/com/inhabas/api/web/BudgetApplicationControllerTest.java @@ -6,109 +6,103 @@ import static org.mockito.Mockito.times; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import com.inhabas.api.domain.budget.dto.BudgetApplicationRegisterForm; -import com.inhabas.api.domain.budget.dto.BudgetApplicationUpdateForm; -import com.inhabas.api.domain.budget.usecase.BudgetApplicationProcessor; -import com.inhabas.api.domain.budget.usecase.BudgetApplicationService; -import com.inhabas.testAnnotataion.NoSecureWebMvcTest; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.data.domain.Pageable; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MockMvc; +import com.inhabas.api.domain.budget.usecase.BudgetApplicationProcessor; +import com.inhabas.api.domain.budget.usecase.BudgetApplicationService; +import com.inhabas.testAnnotataion.NoSecureWebMvcTest; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + @NoSecureWebMvcTest(BudgetApplicationController.class) public class BudgetApplicationControllerTest { - @Autowired - private MockMvc mockMvc; - - @MockBean - private BudgetApplicationService service; - @MockBean - private BudgetApplicationProcessor processor; - - -// @DisplayName("지원서를 작성한다.") -// @Test -// public void createApplicationTest() throws Exception { -// -// mockMvc.perform(post("/budget/application") -// .contentType(MediaType.APPLICATION_JSON) -// .content("{\"title\":\"서버 사용비\", \"dateUsed\":\"2000-01-01T00:00:00\", \"details\":\"aws 크롤링 비용\", \"outcome\":50000, \"accounts\":\"카카오 01-00022-13204 유동현\"}")) -// .andExpect(status().isNoContent()); -// -// //then -// then(service).should(times(1)) -// .registerApplication(any(BudgetApplicationRegisterForm.class), any()); -// } - -// @DisplayName("지원서를 수정한다.") -// @Test -// public void modifyApplicationTest() throws Exception { -// -// mockMvc.perform(put("/budget/application") -// .contentType(MediaType.APPLICATION_JSON) -// .content("{\"id\":1,\"title\":\"서버 사용비\", \"dateUsed\":\"2000-01-01T00:00:00\", \"details\":\"aws 크롤링 비용\", \"outcome\":50000, \"accounts\":\"카카오 01-00022-13204 유동현\", \"applicationId\":1}")) -// .andExpect(status().isNoContent()); -// -// //then -// then(service).should(times(1)) -// .updateApplication(any(BudgetApplicationUpdateForm.class), any()); -// } - - @DisplayName("지원서를 삭제한다.") - @Test - public void deleteApplicationTest() throws Exception { - - mockMvc.perform(delete("/budget/application/1")) - .andExpect(status().isNoContent()); - - //then - then(service).should(times(1)) - .deleteApplication(anyInt(), any()); - } - - @DisplayName("지원서를 조회한다.") - @Test - public void getApplicationTest() throws Exception { - - mockMvc.perform(get("/budget/application/1")) - .andExpect(status().isOk()); - - //then - then(service).should(times(1)) - .getApplicationDetails(anyInt()); - } - - @DisplayName("지원서 목록을 검색한다.") - @Test - public void searchApplicationTest() throws Exception { - - mockMvc.perform(get("/budget/applications")) - .andExpect(status().isOk()); - - //then - then(service).should(times(1)) - .getApplications(any(), any(Pageable.class)); - } - - @DisplayName("예산지원신청글의 상태를 변경한다.") - @Test - public void changeApplicationStatusTest() throws Exception { - - mockMvc.perform(put("/budget/application/1/status") - .contentType(MediaType.APPLICATION_JSON) - .content("{\"status\":\"PROCESSED\", \"rejectReason\":\"\"}")) - .andExpect(status().isNoContent()); - - //then - then(processor).should(times(1)).process(anyInt(), any(), any()); - } + @Autowired private MockMvc mockMvc; + + @MockBean private BudgetApplicationService service; + @MockBean private BudgetApplicationProcessor processor; + + // @DisplayName("지원서를 작성한다.") + // @Test + // public void createApplicationTest() throws Exception { + // + // mockMvc.perform(post("/budget/application") + // .contentType(MediaType.APPLICATION_JSON) + // .content("{\"title\":\"서버 사용비\", \"dateUsed\":\"2000-01-01T00:00:00\", + // \"details\":\"aws 크롤링 비용\", \"outcome\":50000, \"accounts\":\"카카오 01-00022-13204 유동현\"}")) + // .andExpect(status().isNoContent()); + // + // //then + // then(service).should(times(1)) + // .registerApplication(any(BudgetApplicationRegisterForm.class), any()); + // } + + // @DisplayName("지원서를 수정한다.") + // @Test + // public void modifyApplicationTest() throws Exception { + // + // mockMvc.perform(put("/budget/application") + // .contentType(MediaType.APPLICATION_JSON) + // .content("{\"id\":1,\"title\":\"서버 사용비\", + // \"dateUsed\":\"2000-01-01T00:00:00\", \"details\":\"aws 크롤링 비용\", \"outcome\":50000, + // \"accounts\":\"카카오 01-00022-13204 유동현\", \"applicationId\":1}")) + // .andExpect(status().isNoContent()); + // + // //then + // then(service).should(times(1)) + // .updateApplication(any(BudgetApplicationUpdateForm.class), any()); + // } + + @DisplayName("지원서를 삭제한다.") + @Test + public void deleteApplicationTest() throws Exception { + + mockMvc.perform(delete("/budget/application/1")).andExpect(status().isNoContent()); + + // then + then(service).should(times(1)).deleteApplication(anyInt(), any()); + } + + @DisplayName("지원서를 조회한다.") + @Test + public void getApplicationTest() throws Exception { + + mockMvc.perform(get("/budget/application/1")).andExpect(status().isOk()); + + // then + then(service).should(times(1)).getApplicationDetails(anyInt()); + } + + @DisplayName("지원서 목록을 검색한다.") + @Test + public void searchApplicationTest() throws Exception { + + mockMvc.perform(get("/budget/applications")).andExpect(status().isOk()); + + // then + then(service).should(times(1)).getApplications(any(), any(Pageable.class)); + } + + @DisplayName("예산지원신청글의 상태를 변경한다.") + @Test + public void changeApplicationStatusTest() throws Exception { + + mockMvc + .perform( + put("/budget/application/1/status") + .contentType(MediaType.APPLICATION_JSON) + .content("{\"status\":\"PROCESSED\", \"rejectReason\":\"\"}")) + .andExpect(status().isNoContent()); + + // then + then(processor).should(times(1)).process(anyInt(), any(), any()); + } } diff --git a/resource-server/src/test/java/com/inhabas/api/web/BudgetHistoryControllerTest.java b/resource-server/src/test/java/com/inhabas/api/web/BudgetHistoryControllerTest.java index 98bb7a94..6062e021 100644 --- a/resource-server/src/test/java/com/inhabas/api/web/BudgetHistoryControllerTest.java +++ b/resource-server/src/test/java/com/inhabas/api/web/BudgetHistoryControllerTest.java @@ -1,164 +1,161 @@ package com.inhabas.api.web; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.groups.Tuple.tuple; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.BDDMockito.then; import static org.mockito.Mockito.times; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.web.servlet.MockMvc; + import com.inhabas.api.domain.budget.usecase.BudgetHistoryService; import com.inhabas.testAnnotataion.NoSecureWebMvcTest; + import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.http.MediaType; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.web.bind.MethodArgumentNotValidException; @NoSecureWebMvcTest(BudgetHistoryController.class) public class BudgetHistoryControllerTest { - @Autowired - private MockMvc mockMvc; - - @MockBean - private BudgetHistoryService budgetHistoryService; - - -// @DisplayName("예산내역 생성 시 form validation 을 통과하지 못한다.") -// @Test -// public void historyCreationFormTest() throws Exception { -// //given -// String jsonOfCreationForm = "{\"dateUsed\":\"2999-01-01T01:01:00\",\"title\":\" \",\"details\":\"aws 작년 비용\",\"personReceived\":12171652,\"income\":-1,\"outcome\":-1}"; -// -// //when -// Exception resolvedException = -// mockMvc.perform(post("/budget/history") -// .contentType(MediaType.APPLICATION_JSON) -// .content(jsonOfCreationForm)) -// .andExpect(status().isBadRequest()) -// .andReturn().getResolvedException(); -// -// //then -// MethodArgumentNotValidException validException = (MethodArgumentNotValidException) resolvedException; -// assert validException != null; -// assertThat(validException.getFieldErrorCount()).isEqualTo(4); -// assertThat(validException.getFieldErrors()) -// .extracting("defaultMessage", "field") -// .contains( -// tuple("must not be blank", "title"), -// tuple("must be greater than or equal to 0", "income"), -// tuple("must be greater than or equal to 0", "outcome"), -// tuple("must be a past date", "dateUsed")); -// -// then(budgetHistoryService).should(times(0)).createNewHistory(any(), any()); -// } - -// @DisplayName("예산내역 생성 시 validation 을 통과한다.") -// @Test -// public void budgetCreationFormWillPassValidationTest() throws Exception { -// //given -// String jsonOfCreationForm = "{\"dateUsed\":\"2000-01-01T01:01:00\",\"title\":\"서버 운영비\",\"details\":\"aws 작년 비용\",\"personReceived\":12171652,\"income\":0,\"outcome\":500000}"; -// -// //when -// mockMvc.perform(post("/budget/history") -// .contentType(MediaType.APPLICATION_JSON) -// .content(jsonOfCreationForm)) -// .andExpect(status().isNoContent()); -// -// then(budgetHistoryService).should(times(1)).createNewHistory(any(), any()); -// } - -// @DisplayName("예산내역 생성 시 form validation 을 통과하지 못한다.") -// @Test -// public void historyModificationFormTest() throws Exception { -// //given -// String jsonOfCreationForm = "{\"id\":1, \"dateUsed\":\"2999-01-01T01:01:00\",\"title\":\" \",\"details\":\"aws 작년 비용\",\"personReceived\":12171652,\"income\":-1,\"outcome\":-1}"; -// -// //when -// Exception resolvedException = -// mockMvc.perform(put("/budget/history") -// .contentType(MediaType.APPLICATION_JSON) -// .content(jsonOfCreationForm)) -// .andExpect(status().isBadRequest()) -// .andReturn().getResolvedException(); -// -// //then -// MethodArgumentNotValidException validException = (MethodArgumentNotValidException) resolvedException; -// assert validException != null; -// assertThat(validException.getFieldErrorCount()).isEqualTo(4); -// assertThat(validException.getFieldErrors()) -// .extracting("defaultMessage", "field") -// .contains( -// tuple("must not be blank", "title"), -// tuple("must be greater than or equal to 0", "income"), -// tuple("must be greater than or equal to 0", "outcome"), -// tuple("must be a past date", "dateUsed")); -// -// then(budgetHistoryService).should(times(0)).modifyHistory(any(), any()); -// } - -// @DisplayName("예산내역 수정 시 validation 을 통과한다.") -// @Test -// public void budgetModificationFormWillPassValidationTest() throws Exception { -// //given -// String jsonOfModificationForm = "{\"id\":1,\"dateUsed\":\"2000-01-01T01:01:00\",\"title\":\"서버 운영비\",\"details\":\"aws 작년 비용\",\"personReceived\":12171652,\"income\":0,\"outcome\":500000}"; -// -// //when -// mockMvc.perform(put("/budget/history") -// .contentType(MediaType.APPLICATION_JSON) -// .content(jsonOfModificationForm)) -// .andExpect(status().isNoContent()); -// -// then(budgetHistoryService).should(times(1)).modifyHistory(any(), any()); -// } - - @DisplayName("예산내역 삭제 시 validation 을 통과한다.") - @Test - public void budgetDeletionFormWillPassValidationTest() throws Exception { - //given - - //when - mockMvc.perform(delete("/budget/history/2")) - .andExpect(status().isNoContent()); - - then(budgetHistoryService).should(times(1)).deleteHistory(any(), any()); - } - - @DisplayName("회계내역 리스트를 불러온다.") - @Test - public void getListOfBudgetHistoryListTest() throws Exception { - - mockMvc.perform(get("/budget/histories")) - .andExpect(status().isOk()); - - then(budgetHistoryService).should(times(1)).searchHistoryList(any(), any()); - } - - @DisplayName("회계내역 정보 하나를 불러온다.") - @Test - public void fetchOneBudgetHistoryTest() throws Exception { - - mockMvc.perform(get("/budget/history/2")) - .andExpect(status().isOk()); - - then(budgetHistoryService).should(times(1)).getHistory(anyInt()); - } - - @DisplayName("회계 내역의 모든 연도를 불러온다.") - @Test - public void fetchAllYearsOfHistoryTest() throws Exception { - - mockMvc.perform(get("/budget/histories/years")) - .andExpect(status().isOk()); - - then(budgetHistoryService).should(times(1)).getAllYearOfHistory(); - } + @Autowired private MockMvc mockMvc; + + @MockBean private BudgetHistoryService budgetHistoryService; + + // @DisplayName("예산내역 생성 시 form validation 을 통과하지 못한다.") + // @Test + // public void historyCreationFormTest() throws Exception { + // //given + // String jsonOfCreationForm = "{\"dateUsed\":\"2999-01-01T01:01:00\",\"title\":\" + // \",\"details\":\"aws 작년 비용\",\"personReceived\":12171652,\"income\":-1,\"outcome\":-1}"; + // + // //when + // Exception resolvedException = + // mockMvc.perform(post("/budget/history") + // .contentType(MediaType.APPLICATION_JSON) + // .content(jsonOfCreationForm)) + // .andExpect(status().isBadRequest()) + // .andReturn().getResolvedException(); + // + // //then + // MethodArgumentNotValidException validException = (MethodArgumentNotValidException) + // resolvedException; + // assert validException != null; + // assertThat(validException.getFieldErrorCount()).isEqualTo(4); + // assertThat(validException.getFieldErrors()) + // .extracting("defaultMessage", "field") + // .contains( + // tuple("must not be blank", "title"), + // tuple("must be greater than or equal to 0", "income"), + // tuple("must be greater than or equal to 0", "outcome"), + // tuple("must be a past date", "dateUsed")); + // + // then(budgetHistoryService).should(times(0)).createNewHistory(any(), any()); + // } + + // @DisplayName("예산내역 생성 시 validation 을 통과한다.") + // @Test + // public void budgetCreationFormWillPassValidationTest() throws Exception { + // //given + // String jsonOfCreationForm = "{\"dateUsed\":\"2000-01-01T01:01:00\",\"title\":\"서버 + // 운영비\",\"details\":\"aws 작년 비용\",\"personReceived\":12171652,\"income\":0,\"outcome\":500000}"; + // + // //when + // mockMvc.perform(post("/budget/history") + // .contentType(MediaType.APPLICATION_JSON) + // .content(jsonOfCreationForm)) + // .andExpect(status().isNoContent()); + // + // then(budgetHistoryService).should(times(1)).createNewHistory(any(), any()); + // } + + // @DisplayName("예산내역 생성 시 form validation 을 통과하지 못한다.") + // @Test + // public void historyModificationFormTest() throws Exception { + // //given + // String jsonOfCreationForm = "{\"id\":1, + // \"dateUsed\":\"2999-01-01T01:01:00\",\"title\":\" \",\"details\":\"aws 작년 + // 비용\",\"personReceived\":12171652,\"income\":-1,\"outcome\":-1}"; + // + // //when + // Exception resolvedException = + // mockMvc.perform(put("/budget/history") + // .contentType(MediaType.APPLICATION_JSON) + // .content(jsonOfCreationForm)) + // .andExpect(status().isBadRequest()) + // .andReturn().getResolvedException(); + // + // //then + // MethodArgumentNotValidException validException = (MethodArgumentNotValidException) + // resolvedException; + // assert validException != null; + // assertThat(validException.getFieldErrorCount()).isEqualTo(4); + // assertThat(validException.getFieldErrors()) + // .extracting("defaultMessage", "field") + // .contains( + // tuple("must not be blank", "title"), + // tuple("must be greater than or equal to 0", "income"), + // tuple("must be greater than or equal to 0", "outcome"), + // tuple("must be a past date", "dateUsed")); + // + // then(budgetHistoryService).should(times(0)).modifyHistory(any(), any()); + // } + + // @DisplayName("예산내역 수정 시 validation 을 통과한다.") + // @Test + // public void budgetModificationFormWillPassValidationTest() throws Exception { + // //given + // String jsonOfModificationForm = + // "{\"id\":1,\"dateUsed\":\"2000-01-01T01:01:00\",\"title\":\"서버 운영비\",\"details\":\"aws 작년 + // 비용\",\"personReceived\":12171652,\"income\":0,\"outcome\":500000}"; + // + // //when + // mockMvc.perform(put("/budget/history") + // .contentType(MediaType.APPLICATION_JSON) + // .content(jsonOfModificationForm)) + // .andExpect(status().isNoContent()); + // + // then(budgetHistoryService).should(times(1)).modifyHistory(any(), any()); + // } + + @DisplayName("예산내역 삭제 시 validation 을 통과한다.") + @Test + public void budgetDeletionFormWillPassValidationTest() throws Exception { + // given + + // when + mockMvc.perform(delete("/budget/history/2")).andExpect(status().isNoContent()); + + then(budgetHistoryService).should(times(1)).deleteHistory(any(), any()); + } + + @DisplayName("회계내역 리스트를 불러온다.") + @Test + public void getListOfBudgetHistoryListTest() throws Exception { + + mockMvc.perform(get("/budget/histories")).andExpect(status().isOk()); + + then(budgetHistoryService).should(times(1)).searchHistoryList(any(), any()); + } + + @DisplayName("회계내역 정보 하나를 불러온다.") + @Test + public void fetchOneBudgetHistoryTest() throws Exception { + + mockMvc.perform(get("/budget/history/2")).andExpect(status().isOk()); + + then(budgetHistoryService).should(times(1)).getHistory(anyInt()); + } + + @DisplayName("회계 내역의 모든 연도를 불러온다.") + @Test + public void fetchAllYearsOfHistoryTest() throws Exception { + + mockMvc.perform(get("/budget/histories/years")).andExpect(status().isOk()); + + then(budgetHistoryService).should(times(1)).getAllYearOfHistory(); + } } diff --git a/resource-server/src/test/java/com/inhabas/api/web/ClubActivityControllerTest.java b/resource-server/src/test/java/com/inhabas/api/web/ClubActivityControllerTest.java index 85d42631..234aa544 100644 --- a/resource-server/src/test/java/com/inhabas/api/web/ClubActivityControllerTest.java +++ b/resource-server/src/test/java/com/inhabas/api/web/ClubActivityControllerTest.java @@ -1,24 +1,5 @@ package com.inhabas.api.web; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; -import com.inhabas.api.auth.domain.error.businessException.NotFoundException; -import com.inhabas.api.domain.club.dto.ClubActivityDetailDto; -import com.inhabas.api.domain.club.dto.ClubActivityDto; -import com.inhabas.api.domain.club.usecase.ClubActivityService; -import com.inhabas.testAnnotataion.NoSecureWebMvcTest; -import org.junit.jupiter.api.DisplayName; -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.MockMultipartFile; -import org.springframework.test.web.servlet.MockMvc; - -import java.nio.charset.StandardCharsets; -import java.time.LocalDateTime; -import java.util.List; - import static com.inhabas.api.auth.domain.error.ErrorCode.INVALID_INPUT_VALUE; import static com.inhabas.api.auth.domain.error.ErrorCode.NOT_FOUND; import static org.assertj.core.api.Assertions.assertThat; @@ -31,277 +12,291 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import java.nio.charset.StandardCharsets; +import java.time.LocalDateTime; +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.mock.web.MockMultipartFile; +import org.springframework.test.web.servlet.MockMvc; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; +import com.inhabas.api.auth.domain.error.businessException.NotFoundException; +import com.inhabas.api.domain.club.dto.ClubActivityDetailDto; +import com.inhabas.api.domain.club.dto.ClubActivityDto; +import com.inhabas.api.domain.club.usecase.ClubActivityService; +import com.inhabas.testAnnotataion.NoSecureWebMvcTest; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + @NoSecureWebMvcTest(ClubActivityController.class) public class ClubActivityControllerTest { - @Autowired - private MockMvc mvc; - - @Autowired - private ObjectMapper objectMapper; - - @MockBean - private ClubActivityService clubActivityService; - - - private String jsonOf(Object response) throws JsonProcessingException { - return objectMapper.writeValueAsString(response); - } - - - @DisplayName("동아리 활동 조회 성공 200") - @Test - void getClubActivities() throws Exception { - //given - ClubActivityDto clubActivityDto = ClubActivityDto.builder() - .id(1L) - .title("title") - .dateCreated(LocalDateTime.now()) - .dateUpdated(LocalDateTime.now()) - .writerName("jsh") - .thumbnail(null) - .build(); - List clubActivityDtoList = List.of(clubActivityDto); - given(clubActivityService.getClubActivities()).willReturn(clubActivityDtoList); - - //when - mvc.perform(get("/club/activities")) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.data[0].id").value(equalTo(1))) - .andExpect(jsonPath("$.data[0].title").value(equalTo("title"))) - .andExpect(jsonPath("$.data[0].writerName").value(equalTo("jsh"))) - .andExpect(jsonPath("$.data[0].thumbnail").value(equalTo(null))); - - } - - @DisplayName("동아리 활동 글 단일 조회 성공 200") - @Test - void findClubActivity() throws Exception { - //given - ClubActivityDetailDto clubActivityDetailDto = ClubActivityDetailDto.builder() - .id(1L) - .title("title") - .content("content") - .dateCreated(LocalDateTime.now()) - .dateUpdated(LocalDateTime.now()) - .writerName("jsh") - .files(null) - .build(); - given(clubActivityService.getClubActivity(any())).willReturn(clubActivityDetailDto); - - //when - String response = mvc.perform(get("/club/activity/{boardId}", 1L)) - .andExpect(status().isOk()) - .andReturn() - .getResponse() - .getContentAsString(StandardCharsets.UTF_8); - - //then - assertThat(response).isEqualTo(jsonOf(clubActivityDetailDto)); - - } - - @DisplayName("동아리 활동 글 단일 조회 데이터가 올바르지 않다면 400") - @Test - void findClubActivity_Invalid_Input() throws Exception { - //given - ClubActivityDetailDto clubActivityDetailDto = ClubActivityDetailDto.builder() - .id(1L) - .title("title") - .content("content") - .dateCreated(LocalDateTime.now()) - .dateUpdated(LocalDateTime.now()) - .writerName("jsh") - .files(null) - .build(); - given(clubActivityService.getClubActivity(any())).willReturn(clubActivityDetailDto); - - //when - String response = mvc.perform(get("/club/activity/{boardId}", "invalid")) - .andExpect(status().isBadRequest()) - .andReturn() - .getResponse() - .getContentAsString(StandardCharsets.UTF_8); - - //then - assertThat(response).contains(INVALID_INPUT_VALUE.getMessage()); - - } - - @DisplayName("동아리 활동 글 단일 조회 해당 id가 없다면 404") - @Test - void findClubActivity_Not_Found() throws Exception { - //given - doThrow(NotFoundException.class).when(clubActivityService).getClubActivity(any()); - - //when - String response = mvc.perform(get("/club/activity/{boardId}", 1L)) - .andExpect(status().isNotFound()) - .andReturn() - .getResponse() - .getContentAsString(StandardCharsets.UTF_8); - - //then - assertThat(response).contains(NOT_FOUND.getMessage()); - - } - - @DisplayName("동아리 활동 글 생성 성공 201") - @Test - void writeClubActivity() throws Exception { - //given - MockMultipartFile titlePart = new MockMultipartFile("title", "good title".getBytes(StandardCharsets.UTF_8)); - MockMultipartFile contentPart = new MockMultipartFile("content", "good content".getBytes(StandardCharsets.UTF_8)); - - given(clubActivityService.writeClubActivity(any(), any())).willReturn(1L); - - //when - String header = mvc.perform(multipart("/club/activity") - .file(titlePart) - .file(contentPart)) - .andExpect(status().isCreated()) - .andReturn() - .getResponse() - .getHeader("Location"); - - //then - System.out.println("header is " + header); - assertThat(header).contains("/club/activity/1"); - - } - - @DisplayName("동아리 활동 글 생성 데이터가 올바르지 않다면 성공 400") - @Test - void writeClubActivity_Invalid_Input() throws Exception { - //given - MockMultipartFile titlePart = new MockMultipartFile("title", "good title".getBytes(StandardCharsets.UTF_8)); - MockMultipartFile contentPart = new MockMultipartFile("content", "good content".getBytes(StandardCharsets.UTF_8)); - - doThrow(InvalidInputException.class).when(clubActivityService).writeClubActivity(any(), any()); - - //when - String response = mvc.perform(multipart("/club/activity") - .file(titlePart) - .file(contentPart)) - .andExpect(status().isBadRequest()) - .andReturn() - .getResponse() - .getContentAsString(StandardCharsets.UTF_8); - - //then - assertThat(response).contains(INVALID_INPUT_VALUE.getMessage()); - - } - - @DisplayName("동아리 활동 글 수정 성공 204") - @Test - void updateClubActivity() throws Exception { - //given - MockMultipartFile titlePart = new MockMultipartFile("title", "good title".getBytes(StandardCharsets.UTF_8)); - MockMultipartFile contentPart = new MockMultipartFile("content", "good content".getBytes(StandardCharsets.UTF_8)); - - doNothing().when(clubActivityService).updateClubActivity(any(), any()); - - //when then - mvc.perform(multipart("/club/activity/{boardId}", 1) - .file(titlePart) - .file(contentPart)) - .andExpect(status().isNoContent()); - - } - - @DisplayName("동아리 활동 글 수정 데이터가 올바르지 않다면 400") - @Test - void updateClubActivity_Invalid_Input() throws Exception { - //given - MockMultipartFile titlePart = new MockMultipartFile("title", "good title".getBytes(StandardCharsets.UTF_8)); - MockMultipartFile contentPart = new MockMultipartFile("content", "good content".getBytes(StandardCharsets.UTF_8)); - - doThrow(InvalidInputException.class).when(clubActivityService).updateClubActivity(any(), any()); - - //when - String response = mvc.perform(multipart("/club/activity/{boardId}", 1) - .file(titlePart) - .file(contentPart)) - .andExpect(status().isBadRequest()) - .andReturn() - .getResponse() - .getContentAsString(StandardCharsets.UTF_8); - - //then - assertThat(response).contains(INVALID_INPUT_VALUE.getMessage()); - - } - - @DisplayName("동아리 활동 글 수정 해당 id가 없다면 404") - @Test - void updateClubActivity_Not_Found() throws Exception { - //given - MockMultipartFile titlePart = new MockMultipartFile("title", "good title".getBytes(StandardCharsets.UTF_8)); - MockMultipartFile contentPart = new MockMultipartFile("content", "good content".getBytes(StandardCharsets.UTF_8)); - - doThrow(NotFoundException.class).when(clubActivityService).updateClubActivity(any(), any()); - - //when - String response = mvc.perform(multipart("/club/activity/{boardId}", 1) - .file(titlePart) - .file(contentPart)) - .andExpect(status().isNotFound()) - .andReturn() - .getResponse() - .getContentAsString(StandardCharsets.UTF_8); - - //then - assertThat(response).contains(NOT_FOUND.getMessage()); - - } - - @DisplayName("동아리 활동 글 삭제 성공 204") - @Test - void deleteClubActivity() throws Exception { - //given - doNothing().when(clubActivityService).deleteClubActivity(any()); - - //when then - mvc.perform(delete("/club/activity/{boardId}", 1L)) - .andExpect(status().isNoContent()); - - } - - @DisplayName("동아리 활동 글 삭제 데이터가 올바르지 않다면 400") - @Test - void deleteClubActivity_Invalid_Input() throws Exception { - //given - doNothing().when(clubActivityService).deleteClubActivity(any()); - - //when - String response = mvc.perform(delete("/club/activity/{boardId}", "invalid")) - .andExpect(status().isBadRequest()) - .andReturn() - .getResponse() - .getContentAsString(StandardCharsets.UTF_8); - - //then - assertThat(response).contains(INVALID_INPUT_VALUE.getMessage()); - - } - - @DisplayName("동아리 활동 글 삭제 해당 id가 없다면 404") - @Test - void deleteClubActivity_Not_Found() throws Exception { - //given - doThrow(NotFoundException.class).when(clubActivityService).deleteClubActivity(any()); - - //when - String response = mvc.perform(delete("/club/activity/{boardId}", 1)) - .andExpect(status().isNotFound()) - .andReturn() - .getResponse() - .getContentAsString(StandardCharsets.UTF_8); - - //then - assertThat(response).contains(NOT_FOUND.getMessage()); - - } - -} \ No newline at end of file + @Autowired private MockMvc mvc; + + @Autowired private ObjectMapper objectMapper; + + @MockBean private ClubActivityService clubActivityService; + + private String jsonOf(Object response) throws JsonProcessingException { + return objectMapper.writeValueAsString(response); + } + + @DisplayName("동아리 활동 조회 성공 200") + @Test + void getClubActivities() throws Exception { + // given + ClubActivityDto clubActivityDto = + ClubActivityDto.builder() + .id(1L) + .title("title") + .dateCreated(LocalDateTime.now()) + .dateUpdated(LocalDateTime.now()) + .writerName("jsh") + .thumbnail(null) + .build(); + List clubActivityDtoList = List.of(clubActivityDto); + given(clubActivityService.getClubActivities()).willReturn(clubActivityDtoList); + + // when + mvc.perform(get("/club/activities")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.data[0].id").value(equalTo(1))) + .andExpect(jsonPath("$.data[0].title").value(equalTo("title"))) + .andExpect(jsonPath("$.data[0].writerName").value(equalTo("jsh"))) + .andExpect(jsonPath("$.data[0].thumbnail").value(equalTo(null))); + } + + @DisplayName("동아리 활동 글 단일 조회 성공 200") + @Test + void findClubActivity() throws Exception { + // given + ClubActivityDetailDto clubActivityDetailDto = + ClubActivityDetailDto.builder() + .id(1L) + .title("title") + .content("content") + .dateCreated(LocalDateTime.now()) + .dateUpdated(LocalDateTime.now()) + .writerName("jsh") + .files(null) + .build(); + given(clubActivityService.getClubActivity(any())).willReturn(clubActivityDetailDto); + + // when + String response = + mvc.perform(get("/club/activity/{boardId}", 1L)) + .andExpect(status().isOk()) + .andReturn() + .getResponse() + .getContentAsString(StandardCharsets.UTF_8); + + // then + assertThat(response).isEqualTo(jsonOf(clubActivityDetailDto)); + } + + @DisplayName("동아리 활동 글 단일 조회 데이터가 올바르지 않다면 400") + @Test + void findClubActivity_Invalid_Input() throws Exception { + // given + ClubActivityDetailDto clubActivityDetailDto = + ClubActivityDetailDto.builder() + .id(1L) + .title("title") + .content("content") + .dateCreated(LocalDateTime.now()) + .dateUpdated(LocalDateTime.now()) + .writerName("jsh") + .files(null) + .build(); + given(clubActivityService.getClubActivity(any())).willReturn(clubActivityDetailDto); + + // when + String response = + mvc.perform(get("/club/activity/{boardId}", "invalid")) + .andExpect(status().isBadRequest()) + .andReturn() + .getResponse() + .getContentAsString(StandardCharsets.UTF_8); + + // then + assertThat(response).contains(INVALID_INPUT_VALUE.getMessage()); + } + + @DisplayName("동아리 활동 글 단일 조회 해당 id가 없다면 404") + @Test + void findClubActivity_Not_Found() throws Exception { + // given + doThrow(NotFoundException.class).when(clubActivityService).getClubActivity(any()); + + // when + String response = + mvc.perform(get("/club/activity/{boardId}", 1L)) + .andExpect(status().isNotFound()) + .andReturn() + .getResponse() + .getContentAsString(StandardCharsets.UTF_8); + + // then + assertThat(response).contains(NOT_FOUND.getMessage()); + } + + @DisplayName("동아리 활동 글 생성 성공 201") + @Test + void writeClubActivity() throws Exception { + // given + MockMultipartFile titlePart = + new MockMultipartFile("title", "good title".getBytes(StandardCharsets.UTF_8)); + MockMultipartFile contentPart = + new MockMultipartFile("content", "good content".getBytes(StandardCharsets.UTF_8)); + + given(clubActivityService.writeClubActivity(any(), any())).willReturn(1L); + + // when + String header = + mvc.perform(multipart("/club/activity").file(titlePart).file(contentPart)) + .andExpect(status().isCreated()) + .andReturn() + .getResponse() + .getHeader("Location"); + + // then + System.out.println("header is " + header); + assertThat(header).contains("/club/activity/1"); + } + + @DisplayName("동아리 활동 글 생성 데이터가 올바르지 않다면 성공 400") + @Test + void writeClubActivity_Invalid_Input() throws Exception { + // given + MockMultipartFile titlePart = + new MockMultipartFile("title", "good title".getBytes(StandardCharsets.UTF_8)); + MockMultipartFile contentPart = + new MockMultipartFile("content", "good content".getBytes(StandardCharsets.UTF_8)); + + doThrow(InvalidInputException.class).when(clubActivityService).writeClubActivity(any(), any()); + + // when + String response = + mvc.perform(multipart("/club/activity").file(titlePart).file(contentPart)) + .andExpect(status().isBadRequest()) + .andReturn() + .getResponse() + .getContentAsString(StandardCharsets.UTF_8); + + // then + assertThat(response).contains(INVALID_INPUT_VALUE.getMessage()); + } + + @DisplayName("동아리 활동 글 수정 성공 204") + @Test + void updateClubActivity() throws Exception { + // given + MockMultipartFile titlePart = + new MockMultipartFile("title", "good title".getBytes(StandardCharsets.UTF_8)); + MockMultipartFile contentPart = + new MockMultipartFile("content", "good content".getBytes(StandardCharsets.UTF_8)); + + doNothing().when(clubActivityService).updateClubActivity(any(), any()); + + // when then + mvc.perform(multipart("/club/activity/{boardId}", 1).file(titlePart).file(contentPart)) + .andExpect(status().isNoContent()); + } + + @DisplayName("동아리 활동 글 수정 데이터가 올바르지 않다면 400") + @Test + void updateClubActivity_Invalid_Input() throws Exception { + // given + MockMultipartFile titlePart = + new MockMultipartFile("title", "good title".getBytes(StandardCharsets.UTF_8)); + MockMultipartFile contentPart = + new MockMultipartFile("content", "good content".getBytes(StandardCharsets.UTF_8)); + + doThrow(InvalidInputException.class).when(clubActivityService).updateClubActivity(any(), any()); + + // when + String response = + mvc.perform(multipart("/club/activity/{boardId}", 1).file(titlePart).file(contentPart)) + .andExpect(status().isBadRequest()) + .andReturn() + .getResponse() + .getContentAsString(StandardCharsets.UTF_8); + + // then + assertThat(response).contains(INVALID_INPUT_VALUE.getMessage()); + } + + @DisplayName("동아리 활동 글 수정 해당 id가 없다면 404") + @Test + void updateClubActivity_Not_Found() throws Exception { + // given + MockMultipartFile titlePart = + new MockMultipartFile("title", "good title".getBytes(StandardCharsets.UTF_8)); + MockMultipartFile contentPart = + new MockMultipartFile("content", "good content".getBytes(StandardCharsets.UTF_8)); + + doThrow(NotFoundException.class).when(clubActivityService).updateClubActivity(any(), any()); + + // when + String response = + mvc.perform(multipart("/club/activity/{boardId}", 1).file(titlePart).file(contentPart)) + .andExpect(status().isNotFound()) + .andReturn() + .getResponse() + .getContentAsString(StandardCharsets.UTF_8); + + // then + assertThat(response).contains(NOT_FOUND.getMessage()); + } + + @DisplayName("동아리 활동 글 삭제 성공 204") + @Test + void deleteClubActivity() throws Exception { + // given + doNothing().when(clubActivityService).deleteClubActivity(any()); + + // when then + mvc.perform(delete("/club/activity/{boardId}", 1L)).andExpect(status().isNoContent()); + } + + @DisplayName("동아리 활동 글 삭제 데이터가 올바르지 않다면 400") + @Test + void deleteClubActivity_Invalid_Input() throws Exception { + // given + doNothing().when(clubActivityService).deleteClubActivity(any()); + + // when + String response = + mvc.perform(delete("/club/activity/{boardId}", "invalid")) + .andExpect(status().isBadRequest()) + .andReturn() + .getResponse() + .getContentAsString(StandardCharsets.UTF_8); + + // then + assertThat(response).contains(INVALID_INPUT_VALUE.getMessage()); + } + + @DisplayName("동아리 활동 글 삭제 해당 id가 없다면 404") + @Test + void deleteClubActivity_Not_Found() throws Exception { + // given + doThrow(NotFoundException.class).when(clubActivityService).deleteClubActivity(any()); + + // when + String response = + mvc.perform(delete("/club/activity/{boardId}", 1)) + .andExpect(status().isNotFound()) + .andReturn() + .getResponse() + .getContentAsString(StandardCharsets.UTF_8); + + // then + assertThat(response).contains(NOT_FOUND.getMessage()); + } +} diff --git a/resource-server/src/test/java/com/inhabas/api/web/ClubHistoryControllerTest.java b/resource-server/src/test/java/com/inhabas/api/web/ClubHistoryControllerTest.java index 9a5c6d2b..33db66c0 100644 --- a/resource-server/src/test/java/com/inhabas/api/web/ClubHistoryControllerTest.java +++ b/resource-server/src/test/java/com/inhabas/api/web/ClubHistoryControllerTest.java @@ -1,24 +1,5 @@ package com.inhabas.api.web; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; -import com.inhabas.api.auth.domain.error.businessException.NotFoundException; -import com.inhabas.api.domain.club.dto.ClubHistoryDto; -import com.inhabas.api.domain.club.dto.SaveClubHistoryDto; -import com.inhabas.api.domain.club.usecase.ClubHistoryService; -import com.inhabas.testAnnotataion.NoSecureWebMvcTest; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.http.MediaType; -import org.springframework.test.web.servlet.MockMvc; - -import java.nio.charset.StandardCharsets; -import java.time.LocalDateTime; -import java.util.List; - import static com.inhabas.api.auth.domain.error.ErrorCode.INVALID_INPUT_VALUE; import static com.inhabas.api.auth.domain.error.ErrorCode.NOT_FOUND; import static org.assertj.core.api.Assertions.assertThat; @@ -29,278 +10,307 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -@NoSecureWebMvcTest(ClubHistoryController.class) -public class ClubHistoryControllerTest { - - @Autowired - private MockMvc mvc; - - @Autowired - private ObjectMapper objectMapper; - - @MockBean - private ClubHistoryService clubHistoryService; - - - private String jsonOf(Object response) throws JsonProcessingException { - return objectMapper.writeValueAsString(response); - } - - @DisplayName("동아리 연혁 조회 성공 200") - @Test - void getClubHistories() throws Exception { - //given - ClubHistoryDto clubHistoryDto = ClubHistoryDto.builder() - .title("title") - .content("content") - .dateHistory(LocalDateTime.now()) - .build(); - List clubHistoryList = List.of(clubHistoryDto); - given(clubHistoryService.getClubHistories()).willReturn(clubHistoryList); - - //when - String response = mvc.perform(get("/club/histories")) - .andExpect(status().isOk()) - .andReturn() - .getResponse() - .getContentAsString(StandardCharsets.UTF_8); - - //then - assertThat(response).isEqualTo(jsonOf(clubHistoryList)); - - } - - @DisplayName("동아리 연혁 단일 조회 성공 200") - @Test - void findClubHistory() throws Exception { - //given - ClubHistoryDto clubHistoryDto = ClubHistoryDto.builder() - .title("title") - .content("content") - .dateHistory(LocalDateTime.now()) - .build(); - given(clubHistoryService.findClubHistory(any())).willReturn(clubHistoryDto); - - //when - String response = mvc.perform(get("/club/history/{clubHistoryId}", 1L)) - .andExpect(status().isOk()) - .andReturn() - .getResponse() - .getContentAsString(StandardCharsets.UTF_8); - - //then - assertThat(response).isEqualTo(jsonOf(clubHistoryDto)); - - } - - @DisplayName("동아리 연혁 단일 조회 데이터가 올바르지 않다면 400") - @Test - void findClubHistory_Invalid_Input() throws Exception { - //given - ClubHistoryDto clubHistoryDto = ClubHistoryDto.builder() - .title("title") - .content("content") - .dateHistory(LocalDateTime.now()) - .build(); - given(clubHistoryService.findClubHistory(any())).willReturn(clubHistoryDto); - - //when - String response = mvc.perform(get("/club/history/{clubHistoryId}", "invalid")) - .andExpect(status().isBadRequest()) - .andReturn() - .getResponse() - .getContentAsString(StandardCharsets.UTF_8); - - //then - assertThat(response).contains(INVALID_INPUT_VALUE.getMessage()); - - } - - @DisplayName("동아리 연혁 단일 조회 해당 id가 없다면 404") - @Test - void findClubHistory_Not_Found() throws Exception { - //given - doThrow(NotFoundException.class).when(clubHistoryService).findClubHistory(any()); - - //when - String response = mvc.perform(get("/club/history/{clubHistoryId}", 1L)) - .andExpect(status().isNotFound()) - .andReturn() - .getResponse() - .getContentAsString(StandardCharsets.UTF_8); - - //then - assertThat(response).contains(NOT_FOUND.getMessage()); - - } - - @DisplayName("동아리 연혁 생성 성공 201") - @Test - void writeClubHistories() throws Exception { - //given - SaveClubHistoryDto saveClubHistoryDto = SaveClubHistoryDto.builder() - .title("good title") - .content("good content") - .dateHistory(LocalDateTime.parse("2023-11-01T00:00:00")) - .build(); - given(clubHistoryService.writeClubHistory(any(), any())).willReturn(1L); - - //when - String header = mvc.perform(post("/club/history") - .contentType(MediaType.APPLICATION_JSON) - .content(jsonOf(saveClubHistoryDto))) - .andExpect(status().isCreated()) - .andReturn() - .getResponse() - .getHeader("Location"); - - //then - System.out.println("header is " + header); - assertThat(header).contains("/club/history/1"); - - } - - @DisplayName("동아리 연혁 생성 데이터가 올바르지 않다면 400") - @Test - void writeClubHistories_Invalid_Input() throws Exception { - //given - SaveClubHistoryDto saveClubHistoryDto = SaveClubHistoryDto.builder() - .title("meaningless") - .content("meaningless") - .dateHistory(LocalDateTime.now()) - .build(); - doThrow(InvalidInputException.class).when(clubHistoryService).writeClubHistory(any(), any()); - - //when - String response = mvc.perform(post("/club/history") - .contentType(MediaType.APPLICATION_JSON) - .content(jsonOf(saveClubHistoryDto))) - .andExpect(status().isBadRequest()) - .andReturn() - .getResponse() - .getContentAsString(StandardCharsets.UTF_8); - - //then - assertThat(response).contains(INVALID_INPUT_VALUE.getMessage()); - - } - - - @DisplayName("동아리 연혁 수정 성공 204") - @Test - void updateClubHistory() throws Exception { - //given - SaveClubHistoryDto saveClubHistoryDto = SaveClubHistoryDto.builder() - .title("meaningless") - .content("meaningless") - .dateHistory(LocalDateTime.now()) - .build(); - doNothing().when(clubHistoryService).updateClubHistory(any(), any(), any()); - - //when then - mvc.perform(put("/club/history/{clubHistoryId}", 1) - .contentType(MediaType.APPLICATION_JSON) - .content(jsonOf(saveClubHistoryDto))) - .andExpect(status().isNoContent()); - - } - - @DisplayName("동아리 연혁 수정 데이터가 올바르지 않다면 400") - @Test - void updateClubHistory_Invalid_Input() throws Exception { - //given - SaveClubHistoryDto saveClubHistoryDto = SaveClubHistoryDto.builder() - .title("meaningless") - .content("meaningless") - .dateHistory(LocalDateTime.now()) - .build(); - doThrow(InvalidInputException.class).when(clubHistoryService).updateClubHistory(any(), any(), any()); - - //when - String response = mvc.perform(put("/club/history/{clubHistoryId}", 1L) - .contentType(MediaType.APPLICATION_JSON) - .content(jsonOf(saveClubHistoryDto))) - .andExpect(status().isBadRequest()) - .andReturn() - .getResponse() - .getContentAsString(StandardCharsets.UTF_8); - - //then - assertThat(response).contains(INVALID_INPUT_VALUE.getMessage()); - - } - - @DisplayName("동아리 연혁 수정 해당 id가 존재하지 않다면 404") - @Test - void updateClubHistory_Not_Found() throws Exception { - //given - SaveClubHistoryDto saveClubHistoryDto = SaveClubHistoryDto.builder() - .title("meaningless") - .content("meaningless") - .dateHistory(LocalDateTime.now()) - .build(); - doThrow(NotFoundException.class).when(clubHistoryService).updateClubHistory(any(), any(), any()); - - //when - String response = mvc.perform(put("/club/history/{clubHistoryId}", 1L) - .contentType(MediaType.APPLICATION_JSON) - .content(jsonOf(saveClubHistoryDto))) - .andExpect(status().isNotFound()) - .andReturn() - .getResponse() - .getContentAsString(StandardCharsets.UTF_8); - - //then - assertThat(response).contains(NOT_FOUND.getMessage()); - - } - - @DisplayName("동아리 연혁 삭제 성공 204") - @Test - void deleteClubHistory() throws Exception { - //given - doNothing().when(clubHistoryService).deleteClubHistory(any()); - - //when then - mvc.perform(delete("/club/history/{clubHistoryId}", 1L)) - .andExpect(status().isNoContent()); - - } - - @DisplayName("동아리 연혁 삭제 데이터가 올바르지 않다면 400") - @Test - void deleteClubHistory_Invalid_Input() throws Exception { - //given - doNothing().when(clubHistoryService).deleteClubHistory(any()); - - //when - String response = mvc.perform(delete("/club/history/{clubHistoryId}", "invalid")) - .andExpect(status().isBadRequest()) - .andReturn() - .getResponse() - .getContentAsString(StandardCharsets.UTF_8); - - //then - assertThat(response).contains(INVALID_INPUT_VALUE.getMessage()); - - } +import java.nio.charset.StandardCharsets; +import java.time.LocalDateTime; +import java.util.List; - @DisplayName("동아리 연혁 삭제 해당 id가 없다면 404") - @Test - void deleteClubHistory_Not_Found() throws Exception { - //given - doThrow(NotFoundException.class).when(clubHistoryService).deleteClubHistory(any()); +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; - //when - String response = mvc.perform(delete("/club/history/{clubHistoryId}", 1L)) - .andExpect(status().isNotFound()) - .andReturn() - .getResponse() - .getContentAsString(StandardCharsets.UTF_8); +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; +import com.inhabas.api.auth.domain.error.businessException.NotFoundException; +import com.inhabas.api.domain.club.dto.ClubHistoryDto; +import com.inhabas.api.domain.club.dto.SaveClubHistoryDto; +import com.inhabas.api.domain.club.usecase.ClubHistoryService; +import com.inhabas.testAnnotataion.NoSecureWebMvcTest; - //then - assertThat(response).contains(NOT_FOUND.getMessage()); +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; - } +@NoSecureWebMvcTest(ClubHistoryController.class) +public class ClubHistoryControllerTest { -} \ No newline at end of file + @Autowired private MockMvc mvc; + + @Autowired private ObjectMapper objectMapper; + + @MockBean private ClubHistoryService clubHistoryService; + + private String jsonOf(Object response) throws JsonProcessingException { + return objectMapper.writeValueAsString(response); + } + + @DisplayName("동아리 연혁 조회 성공 200") + @Test + void getClubHistories() throws Exception { + // given + ClubHistoryDto clubHistoryDto = + ClubHistoryDto.builder() + .title("title") + .content("content") + .dateHistory(LocalDateTime.now()) + .build(); + List clubHistoryList = List.of(clubHistoryDto); + given(clubHistoryService.getClubHistories()).willReturn(clubHistoryList); + + // when + String response = + mvc.perform(get("/club/histories")) + .andExpect(status().isOk()) + .andReturn() + .getResponse() + .getContentAsString(StandardCharsets.UTF_8); + + // then + assertThat(response).isEqualTo(jsonOf(clubHistoryList)); + } + + @DisplayName("동아리 연혁 단일 조회 성공 200") + @Test + void findClubHistory() throws Exception { + // given + ClubHistoryDto clubHistoryDto = + ClubHistoryDto.builder() + .title("title") + .content("content") + .dateHistory(LocalDateTime.now()) + .build(); + given(clubHistoryService.findClubHistory(any())).willReturn(clubHistoryDto); + + // when + String response = + mvc.perform(get("/club/history/{clubHistoryId}", 1L)) + .andExpect(status().isOk()) + .andReturn() + .getResponse() + .getContentAsString(StandardCharsets.UTF_8); + + // then + assertThat(response).isEqualTo(jsonOf(clubHistoryDto)); + } + + @DisplayName("동아리 연혁 단일 조회 데이터가 올바르지 않다면 400") + @Test + void findClubHistory_Invalid_Input() throws Exception { + // given + ClubHistoryDto clubHistoryDto = + ClubHistoryDto.builder() + .title("title") + .content("content") + .dateHistory(LocalDateTime.now()) + .build(); + given(clubHistoryService.findClubHistory(any())).willReturn(clubHistoryDto); + + // when + String response = + mvc.perform(get("/club/history/{clubHistoryId}", "invalid")) + .andExpect(status().isBadRequest()) + .andReturn() + .getResponse() + .getContentAsString(StandardCharsets.UTF_8); + + // then + assertThat(response).contains(INVALID_INPUT_VALUE.getMessage()); + } + + @DisplayName("동아리 연혁 단일 조회 해당 id가 없다면 404") + @Test + void findClubHistory_Not_Found() throws Exception { + // given + doThrow(NotFoundException.class).when(clubHistoryService).findClubHistory(any()); + + // when + String response = + mvc.perform(get("/club/history/{clubHistoryId}", 1L)) + .andExpect(status().isNotFound()) + .andReturn() + .getResponse() + .getContentAsString(StandardCharsets.UTF_8); + + // then + assertThat(response).contains(NOT_FOUND.getMessage()); + } + + @DisplayName("동아리 연혁 생성 성공 201") + @Test + void writeClubHistories() throws Exception { + // given + SaveClubHistoryDto saveClubHistoryDto = + SaveClubHistoryDto.builder() + .title("good title") + .content("good content") + .dateHistory(LocalDateTime.parse("2023-11-01T00:00:00")) + .build(); + given(clubHistoryService.writeClubHistory(any(), any())).willReturn(1L); + + // when + String header = + mvc.perform( + post("/club/history") + .contentType(MediaType.APPLICATION_JSON) + .content(jsonOf(saveClubHistoryDto))) + .andExpect(status().isCreated()) + .andReturn() + .getResponse() + .getHeader("Location"); + + // then + System.out.println("header is " + header); + assertThat(header).contains("/club/history/1"); + } + + @DisplayName("동아리 연혁 생성 데이터가 올바르지 않다면 400") + @Test + void writeClubHistories_Invalid_Input() throws Exception { + // given + SaveClubHistoryDto saveClubHistoryDto = + SaveClubHistoryDto.builder() + .title("meaningless") + .content("meaningless") + .dateHistory(LocalDateTime.now()) + .build(); + doThrow(InvalidInputException.class).when(clubHistoryService).writeClubHistory(any(), any()); + + // when + String response = + mvc.perform( + post("/club/history") + .contentType(MediaType.APPLICATION_JSON) + .content(jsonOf(saveClubHistoryDto))) + .andExpect(status().isBadRequest()) + .andReturn() + .getResponse() + .getContentAsString(StandardCharsets.UTF_8); + + // then + assertThat(response).contains(INVALID_INPUT_VALUE.getMessage()); + } + + @DisplayName("동아리 연혁 수정 성공 204") + @Test + void updateClubHistory() throws Exception { + // given + SaveClubHistoryDto saveClubHistoryDto = + SaveClubHistoryDto.builder() + .title("meaningless") + .content("meaningless") + .dateHistory(LocalDateTime.now()) + .build(); + doNothing().when(clubHistoryService).updateClubHistory(any(), any(), any()); + + // when then + mvc.perform( + put("/club/history/{clubHistoryId}", 1) + .contentType(MediaType.APPLICATION_JSON) + .content(jsonOf(saveClubHistoryDto))) + .andExpect(status().isNoContent()); + } + + @DisplayName("동아리 연혁 수정 데이터가 올바르지 않다면 400") + @Test + void updateClubHistory_Invalid_Input() throws Exception { + // given + SaveClubHistoryDto saveClubHistoryDto = + SaveClubHistoryDto.builder() + .title("meaningless") + .content("meaningless") + .dateHistory(LocalDateTime.now()) + .build(); + doThrow(InvalidInputException.class) + .when(clubHistoryService) + .updateClubHistory(any(), any(), any()); + + // when + String response = + mvc.perform( + put("/club/history/{clubHistoryId}", 1L) + .contentType(MediaType.APPLICATION_JSON) + .content(jsonOf(saveClubHistoryDto))) + .andExpect(status().isBadRequest()) + .andReturn() + .getResponse() + .getContentAsString(StandardCharsets.UTF_8); + + // then + assertThat(response).contains(INVALID_INPUT_VALUE.getMessage()); + } + + @DisplayName("동아리 연혁 수정 해당 id가 존재하지 않다면 404") + @Test + void updateClubHistory_Not_Found() throws Exception { + // given + SaveClubHistoryDto saveClubHistoryDto = + SaveClubHistoryDto.builder() + .title("meaningless") + .content("meaningless") + .dateHistory(LocalDateTime.now()) + .build(); + doThrow(NotFoundException.class) + .when(clubHistoryService) + .updateClubHistory(any(), any(), any()); + + // when + String response = + mvc.perform( + put("/club/history/{clubHistoryId}", 1L) + .contentType(MediaType.APPLICATION_JSON) + .content(jsonOf(saveClubHistoryDto))) + .andExpect(status().isNotFound()) + .andReturn() + .getResponse() + .getContentAsString(StandardCharsets.UTF_8); + + // then + assertThat(response).contains(NOT_FOUND.getMessage()); + } + + @DisplayName("동아리 연혁 삭제 성공 204") + @Test + void deleteClubHistory() throws Exception { + // given + doNothing().when(clubHistoryService).deleteClubHistory(any()); + + // when then + mvc.perform(delete("/club/history/{clubHistoryId}", 1L)).andExpect(status().isNoContent()); + } + + @DisplayName("동아리 연혁 삭제 데이터가 올바르지 않다면 400") + @Test + void deleteClubHistory_Invalid_Input() throws Exception { + // given + doNothing().when(clubHistoryService).deleteClubHistory(any()); + + // when + String response = + mvc.perform(delete("/club/history/{clubHistoryId}", "invalid")) + .andExpect(status().isBadRequest()) + .andReturn() + .getResponse() + .getContentAsString(StandardCharsets.UTF_8); + + // then + assertThat(response).contains(INVALID_INPUT_VALUE.getMessage()); + } + + @DisplayName("동아리 연혁 삭제 해당 id가 없다면 404") + @Test + void deleteClubHistory_Not_Found() throws Exception { + // given + doThrow(NotFoundException.class).when(clubHistoryService).deleteClubHistory(any()); + + // when + String response = + mvc.perform(delete("/club/history/{clubHistoryId}", 1L)) + .andExpect(status().isNotFound()) + .andReturn() + .getResponse() + .getContentAsString(StandardCharsets.UTF_8); + + // then + assertThat(response).contains(NOT_FOUND.getMessage()); + } +} diff --git a/resource-server/src/test/java/com/inhabas/api/web/CommentControllerTest.java b/resource-server/src/test/java/com/inhabas/api/web/CommentControllerTest.java index d6eb3b33..1cae5b2f 100644 --- a/resource-server/src/test/java/com/inhabas/api/web/CommentControllerTest.java +++ b/resource-server/src/test/java/com/inhabas/api/web/CommentControllerTest.java @@ -1,5 +1,24 @@ package com.inhabas.api.web; +import static com.inhabas.api.auth.domain.error.ErrorCode.INVALID_INPUT_VALUE; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.doNothing; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import java.time.LocalDateTime; +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.filter.CharacterEncodingFilter; + import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; @@ -10,192 +29,174 @@ import com.inhabas.api.domain.comment.usecase.CommentServiceImpl; import com.inhabas.api.domain.member.domain.entity.MemberTest; import com.inhabas.testAnnotataion.NoSecureWebMvcTest; + 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.boot.test.mock.mockito.MockBean; -import org.springframework.http.MediaType; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.setup.MockMvcBuilders; -import org.springframework.web.context.WebApplicationContext; -import org.springframework.web.filter.CharacterEncodingFilter; - -import java.time.LocalDateTime; -import java.util.List; - -import static com.inhabas.api.auth.domain.error.ErrorCode.INVALID_INPUT_VALUE; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.*; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.doNothing; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @NoSecureWebMvcTest(CommentController.class) public class CommentControllerTest { - @Autowired - private MockMvc mvc; - - @Autowired - private WebApplicationContext wac; - - @Autowired - private ObjectMapper objectMapper; - - @MockBean - private CommentServiceImpl commentService; - - @MockBean - private BoardSecurityChecker boardSecurityChecker; - - @BeforeEach - void setUp() { - this.mvc = MockMvcBuilders.webAppContextSetup(wac) - .addFilters(new CharacterEncodingFilter("UTF-8", true)) - .build(); - } - - private String jsonOf(Object response) throws JsonProcessingException { - return objectMapper.writeValueAsString(response); - } - - @DisplayName("댓글 전체 조회 성공 200") - @Test - void getCommentsOfBoardTest() throws Exception { - //given - Member writer = MemberTest.chiefMember(); - List commentList = List.of(new CommentDetailDto[]{ - new CommentDetailDto(1L, writer, "contents1", LocalDateTime.now()), - new CommentDetailDto(2L, writer, "contents2", LocalDateTime.now()), - new CommentDetailDto(3L, writer, "contents3", LocalDateTime.now()) - }); - given(commentService.getComments(anyInt(), anyLong())).willReturn(commentList); - - //when - String response = mvc.perform(get("/board/{menuId}/{boardId}/comments", 1, 1L)) - .andExpect(status().isOk()) - .andReturn() - .getResponse() - .getContentAsString(); - - //then - assertThat(response).isEqualToIgnoringWhitespace( - objectMapper.writeValueAsString(commentList)); - - } - - @DisplayName("댓글 생성 성공 201") - @Test - void createNewCommentTest() throws Exception { - //given - Long newCommentId = 1L; - CommentSaveDto commentSaveDto = new CommentSaveDto("new content", null); - given(commentService.create(any(), anyInt(), anyLong(), anyLong())).willReturn(newCommentId); - - //when - String header = mvc.perform(post("/board/{menuId}/{boardId}/comment", 1, 1L) - .contentType(MediaType.APPLICATION_JSON) - .content(jsonOf(commentSaveDto))) - .andExpect(status().isCreated()) - .andReturn() - .getResponse() - .getHeader("Location"); - - //then - assertThat(header).contains("/board/1/1/comments"); - - } - - @DisplayName("대댓글 생성 성공 201") - @Test - void createNewReply() throws Exception { - //given - Long newReplyId = 2L; - CommentSaveDto commentSaveDto = new CommentSaveDto("new children content", 1L); - given(commentService.create(any(), anyInt(), anyLong(), anyLong())).willReturn(newReplyId); - - //when - String header = mvc.perform(post("/board/{menuId}/{boardId}/comment", 1, 1L) - .contentType(MediaType.APPLICATION_JSON) - .content(jsonOf(commentSaveDto))) - .andExpect(status().isCreated()) - .andReturn() - .getResponse() - .getHeader("Location"); - - //then - assertThat(header).contains("/board/1/1/comments"); - - } - - @DisplayName("댓글 생성 시 500자 이상의 댓글 400") - @Test - void tryToSaveTooLongContents() throws Exception { - //given - String tooLongContents = "-".repeat(500); - CommentSaveDto commentSaveDto = new CommentSaveDto(tooLongContents, null); - - //when - String errorMessage = mvc.perform(post("/board/{menuId}/{boardId}/comment", 1, 1L) - .contentType(MediaType.APPLICATION_JSON) - .content(jsonOf(commentSaveDto))) - .andExpect(status().isBadRequest()) - .andReturn() - .getResponse().getContentAsString(); - - //then - assertThat(errorMessage).contains(INVALID_INPUT_VALUE.getMessage()); - - } - - @DisplayName("댓글 수정 성공 204") - @Test - void updateComment() throws Exception { - //given - CommentUpdateDto commentUpdateDto = new CommentUpdateDto("update comment"); - given(commentService.update(anyLong(), any())).willReturn(1L); - - //when then - mvc.perform(put("/comment/{commentId}", 1L) - .contentType(MediaType.APPLICATION_JSON) - .content(jsonOf(commentUpdateDto))) - .andExpect(status().isNoContent()); - - } - - - @DisplayName("댓글 수정 시 500자 이상의 댓글 400") - @Test - void tryToUpdateTooLongContents() throws Exception { - //given - String tooLongContents = "-".repeat(500); - CommentUpdateDto param = new CommentUpdateDto(tooLongContents); - - //when - String errorMessage = mvc.perform(put("/comment/{commendId}", 1L) - .contentType(MediaType.APPLICATION_JSON) - .content(objectMapper.writeValueAsString(param))) - .andExpect(status().isBadRequest()) - .andReturn() - .getResponse().getContentAsString(); - - //then - assertThat(errorMessage).contains(INVALID_INPUT_VALUE.getMessage()); - - } - - @DisplayName("댓글 삭제 성공 204") - @Test - void deleteComment() throws Exception { - //given - doNothing().when(commentService).delete(anyLong()); - - //when - mvc.perform(delete("/comment/{commentId}", 1L)) - .andExpect(status().isNoContent()); - - } - + @Autowired private MockMvc mvc; + + @Autowired private WebApplicationContext wac; + + @Autowired private ObjectMapper objectMapper; + + @MockBean private CommentServiceImpl commentService; + + @MockBean private BoardSecurityChecker boardSecurityChecker; + + @BeforeEach + void setUp() { + this.mvc = + MockMvcBuilders.webAppContextSetup(wac) + .addFilters(new CharacterEncodingFilter("UTF-8", true)) + .build(); + } + + private String jsonOf(Object response) throws JsonProcessingException { + return objectMapper.writeValueAsString(response); + } + + @DisplayName("댓글 전체 조회 성공 200") + @Test + void getCommentsOfBoardTest() throws Exception { + // given + Member writer = MemberTest.chiefMember(); + List commentList = + List.of( + new CommentDetailDto[] { + new CommentDetailDto(1L, writer, "contents1", LocalDateTime.now()), + new CommentDetailDto(2L, writer, "contents2", LocalDateTime.now()), + new CommentDetailDto(3L, writer, "contents3", LocalDateTime.now()) + }); + given(commentService.getComments(anyInt(), anyLong())).willReturn(commentList); + + // when + String response = + mvc.perform(get("/board/{menuId}/{boardId}/comments", 1, 1L)) + .andExpect(status().isOk()) + .andReturn() + .getResponse() + .getContentAsString(); + + // then + assertThat(response).isEqualToIgnoringWhitespace(objectMapper.writeValueAsString(commentList)); + } + + @DisplayName("댓글 생성 성공 201") + @Test + void createNewCommentTest() throws Exception { + // given + Long newCommentId = 1L; + CommentSaveDto commentSaveDto = new CommentSaveDto("new content", null); + given(commentService.create(any(), anyInt(), anyLong(), anyLong())).willReturn(newCommentId); + + // when + String header = + mvc.perform( + post("/board/{menuId}/{boardId}/comment", 1, 1L) + .contentType(MediaType.APPLICATION_JSON) + .content(jsonOf(commentSaveDto))) + .andExpect(status().isCreated()) + .andReturn() + .getResponse() + .getHeader("Location"); + + // then + assertThat(header).contains("/board/1/1/comments"); + } + + @DisplayName("대댓글 생성 성공 201") + @Test + void createNewReply() throws Exception { + // given + Long newReplyId = 2L; + CommentSaveDto commentSaveDto = new CommentSaveDto("new children content", 1L); + given(commentService.create(any(), anyInt(), anyLong(), anyLong())).willReturn(newReplyId); + + // when + String header = + mvc.perform( + post("/board/{menuId}/{boardId}/comment", 1, 1L) + .contentType(MediaType.APPLICATION_JSON) + .content(jsonOf(commentSaveDto))) + .andExpect(status().isCreated()) + .andReturn() + .getResponse() + .getHeader("Location"); + + // then + assertThat(header).contains("/board/1/1/comments"); + } + + @DisplayName("댓글 생성 시 500자 이상의 댓글 400") + @Test + void tryToSaveTooLongContents() throws Exception { + // given + String tooLongContents = "-".repeat(500); + CommentSaveDto commentSaveDto = new CommentSaveDto(tooLongContents, null); + + // when + String errorMessage = + mvc.perform( + post("/board/{menuId}/{boardId}/comment", 1, 1L) + .contentType(MediaType.APPLICATION_JSON) + .content(jsonOf(commentSaveDto))) + .andExpect(status().isBadRequest()) + .andReturn() + .getResponse() + .getContentAsString(); + + // then + assertThat(errorMessage).contains(INVALID_INPUT_VALUE.getMessage()); + } + + @DisplayName("댓글 수정 성공 204") + @Test + void updateComment() throws Exception { + // given + CommentUpdateDto commentUpdateDto = new CommentUpdateDto("update comment"); + given(commentService.update(anyLong(), any())).willReturn(1L); + + // when then + mvc.perform( + put("/comment/{commentId}", 1L) + .contentType(MediaType.APPLICATION_JSON) + .content(jsonOf(commentUpdateDto))) + .andExpect(status().isNoContent()); + } + + @DisplayName("댓글 수정 시 500자 이상의 댓글 400") + @Test + void tryToUpdateTooLongContents() throws Exception { + // given + String tooLongContents = "-".repeat(500); + CommentUpdateDto param = new CommentUpdateDto(tooLongContents); + + // when + String errorMessage = + mvc.perform( + put("/comment/{commendId}", 1L) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(param))) + .andExpect(status().isBadRequest()) + .andReturn() + .getResponse() + .getContentAsString(); + + // then + assertThat(errorMessage).contains(INVALID_INPUT_VALUE.getMessage()); + } + + @DisplayName("댓글 삭제 성공 204") + @Test + void deleteComment() throws Exception { + // given + doNothing().when(commentService).delete(anyLong()); + + // when + mvc.perform(delete("/comment/{commentId}", 1L)).andExpect(status().isNoContent()); + } } diff --git a/resource-server/src/test/java/com/inhabas/api/web/ContestBoardControllerTest.java b/resource-server/src/test/java/com/inhabas/api/web/ContestBoardControllerTest.java index 30277b29..1523378f 100644 --- a/resource-server/src/test/java/com/inhabas/api/web/ContestBoardControllerTest.java +++ b/resource-server/src/test/java/com/inhabas/api/web/ContestBoardControllerTest.java @@ -1,188 +1,169 @@ package com.inhabas.api.web; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.doNothing; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.web.servlet.MockMvc; import com.fasterxml.jackson.databind.ObjectMapper; -import com.inhabas.testAnnotataion.WithMockJwtAuthenticationToken; -import com.inhabas.api.domain.contest.dto.DetailContestBoardDto; -import com.inhabas.api.domain.contest.dto.ListContestBoardDto; -import com.inhabas.api.domain.contest.dto.SaveContestBoardDto; -import com.inhabas.api.domain.contest.dto.UpdateContestBoardDto; import com.inhabas.api.domain.contest.usecase.ContestBoardService; import com.inhabas.testAnnotataion.NoSecureWebMvcTest; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageImpl; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Sort; -import org.springframework.http.MediaType; -import org.springframework.test.web.servlet.MockMvc; @NoSecureWebMvcTest(ContestBoardController.class) public class ContestBoardControllerTest { - @Autowired - private MockMvc mvc; - - @Autowired - private ObjectMapper objectMapper; + @Autowired private MockMvc mvc; - @MockBean - private ContestBoardService contestBoardService; + @Autowired private ObjectMapper objectMapper; + @MockBean private ContestBoardService contestBoardService; -// @DisplayName("공모전 게시글 저장을 요청한다.") -// @Test -// @WithMockJwtAuthenticationToken -// public void addNewContestBoard() throws Exception { -// //given -// SaveContestBoardDto saveContestBoardDto = new SaveContestBoardDto("title", "content", "association", "topic", LocalDate.of(2022, 1, 1), LocalDate.of(9022, 3, 26)); -// given(contestBoardService.write(any(), any(SaveContestBoardDto.class))).willReturn(1); -// -// // when -// mvc.perform(post("/contest") -// .contentType(MediaType.APPLICATION_JSON) -// .content(objectMapper.writeValueAsString(saveContestBoardDto))) -// .andExpect(status().isCreated()) -// .andExpect(content().string("1")); -// } + // @DisplayName("공모전 게시글 저장을 요청한다.") + // @Test + // @WithMockJwtAuthenticationToken + // public void addNewContestBoard() throws Exception { + // //given + // SaveContestBoardDto saveContestBoardDto = new SaveContestBoardDto("title", "content", + // "association", "topic", LocalDate.of(2022, 1, 1), LocalDate.of(9022, 3, 26)); + // given(contestBoardService.write(any(), any(SaveContestBoardDto.class))).willReturn(1); + // + // // when + // mvc.perform(post("/contest") + // .contentType(MediaType.APPLICATION_JSON) + // .content(objectMapper.writeValueAsString(saveContestBoardDto))) + // .andExpect(status().isCreated()) + // .andExpect(content().string("1")); + // } -// @DisplayName("공모전 게시글 수정을 요청한다.") -// @Test -// @WithMockJwtAuthenticationToken -// public void updateContestBoard() throws Exception{ -// //given -// UpdateContestBoardDto updateContestBoardDto = new UpdateContestBoardDto(1, "수정된 제목", "수정된 내용", "수정된 협회기관명", "수정된 공모전 주제", LocalDate.of(2022, 1, 1), LocalDate.of(9022, 3, 26)); -// given(contestBoardService.update(any(), any(UpdateContestBoardDto.class))).willReturn(1); -// -// // when -// mvc.perform(put("/contest") -// .contentType(MediaType.APPLICATION_JSON) -// .content(objectMapper.writeValueAsString(updateContestBoardDto))) -// .andExpect(status().isOk()) -// .andExpect(content().string("1")); -// } + // @DisplayName("공모전 게시글 수정을 요청한다.") + // @Test + // @WithMockJwtAuthenticationToken + // public void updateContestBoard() throws Exception{ + // //given + // UpdateContestBoardDto updateContestBoardDto = new UpdateContestBoardDto(1, "수정된 제목", + // "수정된 내용", "수정된 협회기관명", "수정된 공모전 주제", LocalDate.of(2022, 1, 1), LocalDate.of(9022, 3, 26)); + // given(contestBoardService.update(any(), + // any(UpdateContestBoardDto.class))).willReturn(1); + // + // // when + // mvc.perform(put("/contest") + // .contentType(MediaType.APPLICATION_JSON) + // .content(objectMapper.writeValueAsString(updateContestBoardDto))) + // .andExpect(status().isOk()) + // .andExpect(content().string("1")); + // } -// @DisplayName("공모전 게시글 삭제를 요청한다.") -// @Test -// public void deleteContestBoard() throws Exception{ -// //given -// doNothing().when(contestBoardService).delete(any(), anyInt()); -// -// // when -// mvc.perform(delete("/contest/1")) -// .andExpect(status().isNoContent()); -// } + // @DisplayName("공모전 게시글 삭제를 요청한다.") + // @Test + // public void deleteContestBoard() throws Exception{ + // //given + // doNothing().when(contestBoardService).delete(any(), anyInt()); + // + // // when + // mvc.perform(delete("/contest/1")) + // .andExpect(status().isNoContent()); + // } -// @DisplayName("공모전 게시판 목록 조회를 요청한다.") -// @Test -// public void getContestBoardList() throws Exception { -// PageRequest pageable = PageRequest.of(0,10, Sort.Direction.DESC, "id"); -// -// List results = new ArrayList<>(); -// results.add(new ListContestBoardDto("title1", "contents1", LocalDate.of(2022,1,1), LocalDate.of(2022, 1, 29))); -// results.add(new ListContestBoardDto("title2", "contents2", LocalDate.of(2022,1,1), LocalDate.of(2022, 1, 29))); -// results.add(new ListContestBoardDto("title3", "contents3", LocalDate.of(2022,1,1), LocalDate.of(2022, 1, 29))); -// -// Page expectedContestBoardDto = new PageImpl<>(results, pageable, results.size()); -// -// given(contestBoardService.getBoardList(any(), any())).willReturn(expectedContestBoardDto); -// -// // when -// String responseBody = mvc.perform(get("/contests?menu_id=9") -// .contentType(MediaType.APPLICATION_JSON) -// .characterEncoding("utf-8") -// .param("page", "0") -// .param("size", "10") -// .param("sort", "DESC") -// .param("properties", "id")) -// .andExpect(status().isOk()) -// .andReturn() -// .getResponse().getContentAsString(); -// -// // then -// assertThat(responseBody).isEqualTo(objectMapper.writeValueAsString(expectedContestBoardDto)); -// } + // @DisplayName("공모전 게시판 목록 조회를 요청한다.") + // @Test + // public void getContestBoardList() throws Exception { + // PageRequest pageable = PageRequest.of(0,10, Sort.Direction.DESC, "id"); + // + // List results = new ArrayList<>(); + // results.add(new ListContestBoardDto("title1", "contents1", LocalDate.of(2022,1,1), + // LocalDate.of(2022, 1, 29))); + // results.add(new ListContestBoardDto("title2", "contents2", LocalDate.of(2022,1,1), + // LocalDate.of(2022, 1, 29))); + // results.add(new ListContestBoardDto("title3", "contents3", LocalDate.of(2022,1,1), + // LocalDate.of(2022, 1, 29))); + // + // Page expectedContestBoardDto = new PageImpl<>(results, pageable, + // results.size()); + // + // given(contestBoardService.getBoardList(any(), + // any())).willReturn(expectedContestBoardDto); + // + // // when + // String responseBody = mvc.perform(get("/contests?menu_id=9") + // .contentType(MediaType.APPLICATION_JSON) + // .characterEncoding("utf-8") + // .param("page", "0") + // .param("size", "10") + // .param("sort", "DESC") + // .param("properties", "id")) + // .andExpect(status().isOk()) + // .andReturn() + // .getResponse().getContentAsString(); + // + // // then + // + // assertThat(responseBody).isEqualTo(objectMapper.writeValueAsString(expectedContestBoardDto)); + // } -// @DisplayName("공모전 게시글 단일 조회를 요청한다.") -// @Test -// public void getContestBoardDetail() throws Exception{ -// //given -// DetailContestBoardDto contestBoardDto = new DetailContestBoardDto(1, "mingyeom", "title", "content", "association","topic", LocalDate.of(2022,1,1), LocalDate.of(2022, 1, 29), LocalDateTime.now(), null); -// given(contestBoardService.getBoard(anyInt())).willReturn(contestBoardDto); -// -// // when -// String responseBody = mvc.perform(get("/contest/1")) -// .andExpect(status().isOk()) -// .andReturn() -// .getResponse().getContentAsString(); -// -// // then -// assertThat(responseBody).isEqualTo(objectMapper.writeValueAsString(contestBoardDto)); -// -// } + // @DisplayName("공모전 게시글 단일 조회를 요청한다.") + // @Test + // public void getContestBoardDetail() throws Exception{ + // //given + // DetailContestBoardDto contestBoardDto = new DetailContestBoardDto(1, "mingyeom", + // "title", "content", "association","topic", LocalDate.of(2022,1,1), LocalDate.of(2022, 1, 29), + // LocalDateTime.now(), null); + // given(contestBoardService.getBoard(anyInt())).willReturn(contestBoardDto); + // + // // when + // String responseBody = mvc.perform(get("/contest/1")) + // .andExpect(status().isOk()) + // .andReturn() + // .getResponse().getContentAsString(); + // + // // then + // assertThat(responseBody).isEqualTo(objectMapper.writeValueAsString(contestBoardDto)); + // + // } -// @DisplayName("공모전 게시글 작성 시 Title의 길이가 범위를 초과해 오류 발생") -// @Test -// @WithMockJwtAuthenticationToken -// public void TitleIsTooLongError() throws Exception { -// //given -// SaveContestBoardDto saveContestBoardDto = new SaveContestBoardDto("title".repeat(20)+ ".", "content", "association", "topic", LocalDate.of(2022, 1, 1), LocalDate.of(2022, 1,26)); -// -// -// // when -// String errorMessage = Objects.requireNonNull( -// mvc.perform(post("/contest") -// .contentType(MediaType.APPLICATION_JSON) -// .content(objectMapper.writeValueAsString(saveContestBoardDto))) -// .andExpect(status().isBadRequest()) -// .andReturn() -// .getResolvedException()) -// .getMessage(); -// -// // then -// assertThat(errorMessage).isNotBlank(); -// assertThat(errorMessage).contains("제목은 최대 100자입니다."); -// } + // @DisplayName("공모전 게시글 작성 시 Title의 길이가 범위를 초과해 오류 발생") + // @Test + // @WithMockJwtAuthenticationToken + // public void TitleIsTooLongError() throws Exception { + // //given + // SaveContestBoardDto saveContestBoardDto = new SaveContestBoardDto("title".repeat(20)+ + // ".", "content", "association", "topic", LocalDate.of(2022, 1, 1), LocalDate.of(2022, 1,26)); + // + // + // // when + // String errorMessage = Objects.requireNonNull( + // mvc.perform(post("/contest") + // .contentType(MediaType.APPLICATION_JSON) + // .content(objectMapper.writeValueAsString(saveContestBoardDto))) + // .andExpect(status().isBadRequest()) + // .andReturn() + // .getResolvedException()) + // .getMessage(); + // + // // then + // assertThat(errorMessage).isNotBlank(); + // assertThat(errorMessage).contains("제목은 최대 100자입니다."); + // } -// @DisplayName("공모전 게시글 작성 시 Contents가 null인 경우 오류 발생") -// @Test -// @WithMockJwtAuthenticationToken -// public void ContentIsNullError() throws Exception { -// //given -// SaveContestBoardDto saveContestBoardDto = new SaveContestBoardDto("title", " ", "association", "topic", LocalDate.of(2022, 1, 1), LocalDate.of(2022, 1,26)); -// -// // when -// String errorMessage = Objects.requireNonNull( -// mvc.perform(post("/contest") -// .contentType(MediaType.APPLICATION_JSON) -// .content(objectMapper.writeValueAsString(saveContestBoardDto))) -// .andExpect(status().isBadRequest()) -// .andReturn() -// .getResolvedException()) -// .getMessage(); -// -// // then -// assertThat(errorMessage).isNotBlank(); -// assertThat(errorMessage).contains("본문을 입력하세요."); -// } + // @DisplayName("공모전 게시글 작성 시 Contents가 null인 경우 오류 발생") + // @Test + // @WithMockJwtAuthenticationToken + // public void ContentIsNullError() throws Exception { + // //given + // SaveContestBoardDto saveContestBoardDto = new SaveContestBoardDto("title", " ", + // "association", "topic", LocalDate.of(2022, 1, 1), LocalDate.of(2022, 1,26)); + // + // // when + // String errorMessage = Objects.requireNonNull( + // mvc.perform(post("/contest") + // .contentType(MediaType.APPLICATION_JSON) + // .content(objectMapper.writeValueAsString(saveContestBoardDto))) + // .andExpect(status().isBadRequest()) + // .andReturn() + // .getResolvedException()) + // .getMessage(); + // + // // then + // assertThat(errorMessage).isNotBlank(); + // assertThat(errorMessage).contains("본문을 입력하세요."); + // } } diff --git a/resource-server/src/test/java/com/inhabas/api/web/LectureControllerTest.java b/resource-server/src/test/java/com/inhabas/api/web/LectureControllerTest.java index 6b8b0705..03bf5d69 100644 --- a/resource-server/src/test/java/com/inhabas/api/web/LectureControllerTest.java +++ b/resource-server/src/test/java/com/inhabas/api/web/LectureControllerTest.java @@ -1,422 +1,418 @@ package com.inhabas.api.web; -import com.inhabas.api.domain.lecture.domain.valueObject.LectureStatus; -import com.inhabas.api.domain.lecture.domain.valueObject.StudentStatus; -import com.inhabas.api.domain.lecture.dto.LectureDetailDto; -import com.inhabas.api.domain.lecture.dto.LectureListDto; -import com.inhabas.api.domain.lecture.dto.StudentListDto; -import com.inhabas.api.domain.lecture.usecase.LectureService; -import com.inhabas.api.domain.lecture.usecase.LectureStudentService; -import com.inhabas.testAnnotataion.NoSecureWebMvcTest; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.skyscreamer.jsonassert.JSONAssert; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.data.domain.PageImpl; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Sort; -import org.springframework.http.MediaType; -import org.springframework.test.web.servlet.MockMvc; - -import java.nio.charset.StandardCharsets; -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; - import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.given; import static org.mockito.BDDMockito.then; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.times; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; + +import com.inhabas.api.domain.lecture.usecase.LectureService; +import com.inhabas.api.domain.lecture.usecase.LectureStudentService; +import com.inhabas.testAnnotataion.NoSecureWebMvcTest; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + @NoSecureWebMvcTest(LectureController.class) public class LectureControllerTest { - @Autowired - private MockMvc mockMvc; - - @MockBean - private LectureService lectureService; - - @MockBean - private LectureStudentService studentService; - -// @DisplayName("강의 등록 uri 를 정상적으로 호출 및 응답.") -// @Test -// public void createLectureTest() throws Exception { -// -// //given -// doNothing().when(lectureService).create(any(), any()); -// -// //when -// mockMvc.perform(post("/lecture") -// .contentType(MediaType.APPLICATION_JSON) -// .content("{\n" + -// " \"title\": \"절권도 강의\",\n" + -// " \"applyDeadLine\": \"9022-07-31T16:51:33\",\n" + -// " \"daysOfWeeks\": \"월 수 금\",\n" + -// " \"place\": \"6호관 623 강의실\",\n" + -// " \"curriculumDetails\": \"1주차: 빅데이터에 기반한 공격패턴분석
2주차: ...\",\n" + -// " \"participantsLimits\": 30,\n" + -// " \"method\": 1,\n" + -// " \"introduction\": \"호신술을 배워보자\"\n" + -// "}")) -// .andExpect(status().isNoContent()); -// -// //then -// then(lectureService).should(times(1)).create(any(), any()); -// } - -// @DisplayName("강의 수정 uri 를 정상적으로 호출 및 응답") -// @Test -// public void updateLectureTest() throws Exception { -// -// //given -// doNothing().when(lectureService).update(any(), any()); -// -// //when -// mockMvc.perform(put("/lecture") -// .contentType(MediaType.APPLICATION_JSON) -// .content("{\n" + -// " \"id\": \"1\",\n" + -// " \"title\": \"절권도 강의\",\n" + -// " \"applyDeadLine\": \"9022-07-31T16:51:33\",\n" + -// " \"daysOfWeeks\": \"월 수 금\",\n" + -// " \"place\": \"6호관 623 강의실\",\n" + -// " \"curriculumDetails\": \"1주차: 빅데이터에 기반한 공격패턴분석
2주차: ...\",\n" + -// " \"participantsLimits\": 30,\n" + -// " \"method\": 1,\n" + -// " \"introduction\": \"호신술을 배워보자\"\n" + -// "}")) -// .andExpect(status().isNoContent()); -// -// //then -// then(lectureService).should(times(1)).update(any(), any()); -// } - - @DisplayName("강의 삭제 uri 를 정상적으로 호출 및 응답") - @Test - public void deleteLectureTest() throws Exception { - - //given - doNothing().when(lectureService).delete(any(), any()); - - //when - mockMvc.perform(delete("/lecture/1")) - .andExpect(status().isNoContent()); - - //then - then(lectureService).should(times(1)).delete(any(), any()); - } - -// @DisplayName("강의 조회 uri 를 정상적으로 호출 및 응답") -// @Test -// public void getLectureDetailsTest() throws Exception { -// -// //given -// LectureDetailDto expectedDto = LectureDetailDto.builder() -// .title("절권도 강의") -// .chief(new LectureDetailDto.MemberInfo(12171652, "산업경영공학과", "유동현")) -// .applyDeadLine(LocalDateTime.of(9022, 7, 31, 17, 11, 36)) -// .created(LocalDateTime.of(9022, 7, 23, 17, 11, 36)) -// .updated(null) -// .daysOfWeeks("월 금") -// .introduction("호신술을 배워보자") -// .curriculumDetails("1주차: 빅데이터에 기반한 공격패턴분석
2주차: ...") -// .method(1) -// .paid(false) -// .participantsLimits(30) -// .place("구내식당") -// .rejectReason(null) -// .state(LectureStatus.WAITING) -// .build() -// .setCoInstructors(List.of( -// new LectureDetailDto.MemberInfo(12345678, "스마트모빌리티공학과", "윤예진"), -// new LectureDetailDto.MemberInfo(87654321, "통계학과", "나까무라철수") -// )); -// given(lectureService.get(any())).willReturn(expectedDto); -// -// //when -// String response = mockMvc.perform(get("/lecture/1")) -// .andExpect(status().isOk()) -// .andReturn() -// .getResponse().getContentAsString(StandardCharsets.UTF_8); -// -// //then -// then(lectureService).should(times(1)).get(any()); -// JSONAssert.assertEquals("{" + -// " \"title\": \"절권도 강의\"," + -// " \"chief\": {" + -// " \"id\": 12171652," + -// " \"major\": \"산업경영공학과\"," + -// " \"name\": \"유동현\"" + -// " }," + -// " \"coInstructors\": [" + -// " {" + -// " \"id\": 12345678," + -// " \"major\": \"스마트모빌리티공학과\"," + -// " \"name\": \"윤예진\"" + -// " }," + -// " {" + -// " \"id\": 87654321," + -// " \"major\": \"통계학과\"," + -// " \"name\": \"나까무라철수\"" + -// " }" + -// " ]," + -// " \"applyDeadLine\": \"9022-07-31T17:11:36\"," + -// " \"daysOfWeeks\": \"월 금\"," + -// " \"place\": \"구내식당\"," + -// " \"introduction\": \"호신술을 배워보자\"," + -// " \"curriculumDetails\": \"1주차: 빅데이터에 기반한 공격패턴분석
2주차: ...\"," + -// " \"participantsLimits\": 30," + -// " \"method\": 1," + -// " \"state\": \"WAITING\"," + -// " \"rejectReason\": null," + -// " \"paid\": false," + -// " \"created\": \"9022-07-23T17:11:36\"," + -// " \"updated\": null" + -// "}", response, false); -// } - -// @DisplayName("강의 리스트 조회 uri 를 정상적으로 호출 및 응답") -// @Test -// public void getLectureListTest() throws Exception { -// -// //given -// List list = List.of( -// new LectureListDto(1, "title1", 1000001, "intro1", LocalDateTime.of(2001, 1, 1, 1, 1, 1), LectureStatus.PROGRESSING, 1, 30, 2), -// new LectureListDto(2, "title2", 1000002, "intro2", LocalDateTime.of(2002, 2, 2, 2, 2, 2), LectureStatus.PROGRESSING, 1, 31, 3), -// new LectureListDto(3, "title3", 1000003, "intro3", LocalDateTime.of(2003, 3, 3, 3, 3, 3), LectureStatus.PROGRESSING, 1, 32, 4) -// ); -// PageImpl page = new PageImpl<>(list, PageRequest.of(0, 6, Sort.Direction.DESC, "apply_deadline"), list.size()); -// given(lectureService.getList(any())).willReturn(page); -// -// //when -// String response = mockMvc.perform(get("/lectures")) -// .andExpect(status().isOk()) -// .andReturn() -// .getResponse().getContentAsString(StandardCharsets.UTF_8); -// -// //then -// then(lectureService).should(times(1)).getList(any()); -// JSONAssert.assertEquals("{\n" + -// " \"totalPages\": 1,\n" + -// " \"totalElements\": 3,\n" + -// " \"size\": 6,\n" + -// " \"content\": [\n" + -// " {\n" + -// " \"lectureId\": 3,\n" + -// " \"title\": \"title3\",\n" + -// " \"chiefId\": 1000003,\n" + -// " \"introduction\": \"intro3\",\n" + -// " \"applyDeadline\": \"2003-03-03T03:03:03\",\n" + -// " \"status\": \"PROGRESSING\",\n" + -// " \"method\": 1,\n" + -// " \"participantsLimits\": 32,\n" + -// " \"theNumberOfCurrentParticipants\": 4\n" + -// " },\n" + -// " {\n" + -// " \"lectureId\": 2,\n" + -// " \"title\": \"title2\",\n" + -// " \"chiefId\": 1000002,\n" + -// " \"introduction\": \"intro2\",\n" + -// " \"applyDeadline\": \"2002-02-02T02:02:02\",\n" + -// " \"status\": \"PROGRESSING\",\n" + -// " \"method\": 1,\n" + -// " \"participantsLimits\": 31,\n" + -// " \"theNumberOfCurrentParticipants\": 3\n" + -// " },\n" + -// " {\n" + -// " \"lectureId\": 1,\n" + -// " \"title\": \"title1\",\n" + -// " \"chiefId\": 1000001,\n" + -// " \"introduction\": \"intro1\",\n" + -// " \"applyDeadline\": \"2001-01-01T01:01:01\",\n" + -// " \"status\": \"PROGRESSING\",\n" + -// " \"method\": 1,\n" + -// " \"participantsLimits\": 30,\n" + -// " \"theNumberOfCurrentParticipants\": 2\n" + -// " }\n" + -// " ],\n" + -// " \"number\": 0,\n" + -// " \"sort\": {\n" + -// " \"empty\": false,\n" + -// " \"sorted\": true,\n" + -// " \"unsorted\": false\n" + -// " },\n" + -// " \"first\": true,\n" + -// " \"last\": true,\n" + -// " \"numberOfElements\": 3,\n" + -// " \"pageable\": {\n" + -// " \"offset\": 0,\n" + -// " \"sort\": {\n" + -// " \"empty\": false,\n" + -// " \"sorted\": true,\n" + -// " \"unsorted\": false\n" + -// " },\n" + -// " \"pageNumber\": 0,\n" + -// " \"pageSize\": 6,\n" + -// " \"paged\": true,\n" + -// " \"unpaged\": false\n" + -// " },\n" + -// " \"empty\": false\n" + -// "}", response, false); -// } - - @DisplayName("강의 상태 변경 api 를 호출한다.") - @Test - public void updateLectureStatusTest() throws Exception { - - //given - doNothing().when(lectureService).approveOrDeny(any(), any()); - - //when - mockMvc.perform(put("/lecture/1/status") - .contentType(MediaType.APPLICATION_JSON) - .content("{\n" + - " \"status\": \"PROGRESSING\",\n" + - " \"rejectReason\": null\n" + - "}")) - .andExpect(status().isNoContent()); - - //then - then(lectureService).should(times(1)).approveOrDeny(any(), any()); - } - - @DisplayName("수강생으로 등록한다.") - @Test - public void enrollTest() throws Exception { - - //given - doNothing().when(studentService).enroll(any(), any()); - - //when - mockMvc.perform(post("/lecture/1/student")) - .andExpect(status().isNoContent()); - - //then - then(studentService).should(times(1)).enroll(any(), any()); - } - - @DisplayName("수강생 한명의 수강상태를 변경한다.") - @Test - public void changeStudentStatusTest() throws Exception { - - doNothing().when(studentService).changeStatusOfOneStudentByLecturer(any(), any(), any(), any()); - - //when - mockMvc.perform(put("/lecture/1/student/121/status") - .contentType(MediaType.APPLICATION_JSON) - .content("\"BLOCKED\"")) - .andExpect(status().isNoContent()); - - //then - then(studentService).should(times(1)).changeStatusOfOneStudentByLecturer(any(), any(), any(), any()); - } - -// @DisplayName("다수의 수강생 상태를 변경한다.") -// @Test -// public void changeStudentsStatusTest() throws Exception { -// -// doNothing().when(studentService).changeStatusOfStudentsByLecturer(any(), any(), any()); -// -// //when -// mockMvc.perform(put("/lecture/1/students/status") -// .contentType(MediaType.APPLICATION_JSON) -// .content("[{\"12\":\"BLOCKED\"}, {\"15\":\"BLOCKED\"}]")) -// .andExpect(status().isNoContent()); -// -// //then -// then(studentService).should(times(1)).changeStatusOfStudentsByLecturer(any(), any(), any()); -// } - - @DisplayName("수강생이 강의를 탈퇴한다.") - @Test - public void exitLectureTest() throws Exception { - - doNothing().when(studentService).exitBySelf(any(), any()); - - //when - mockMvc.perform(delete("/lecture/1/student")) - .andExpect(status().isNoContent()); - - //then - then(studentService).should(times(1)).exitBySelf(any(), any()); - } - -// @DisplayName("수강생들의 정보를 조회한다.") -// @Test -// public void searchStudentsInformation() throws Exception { -// -// //given -// List students = new ArrayList<>(); -// for (int i = 0; i < 51; i++) { -// students.add( -// StudentListDto.builder() -// .name("홍길동"+i) -// .memberId(1000000+i) -// .email("my@gmail.com") -// .assignmentCount(0) -// .attendanceCount(0) -// .phoneNumber("010-0000-0000") -// .status(StudentStatus.PROGRESS) -// .sid(i) -// .build() -// ); -// } -// PageImpl page = -// new PageImpl<>(students.subList(50, students.size()), PageRequest.of(2, 25, Sort.Direction.ASC, "memberId"), students.size()); -// given(studentService.searchStudents(any(), any())).willReturn(page); -// -// //when -// String response = mockMvc.perform(get("/lecture/1/students")) -// .andExpect(status().isOk()) -// .andReturn().getResponse() -// .getContentAsString(StandardCharsets.UTF_8); -// -// //then -// then(studentService).should(times(1)).searchStudents(any(), any()); -// JSONAssert.assertEquals("{\n" + -// " \"totalPages\": 3,\n" + -// " \"totalElements\": 51,\n" + -// " \"size\": 25,\n" + -// " \"content\": [\n" + -// " {\n" + -// " \"name\": \"홍길동50\",\n" + -// " \"memberId\": 1000050,\n" + -// " \"phone\": \"010-0000-0000\",\n" + -// " \"email\": \"my@gmail.com\",\n" + -// " \"assignmentCount\": 0,\n" + -// " \"attendanceCount\": 0,\n" + -// " \"status\": \"PROGRESS\",\n" + -// " \"sid\": 50\n" + -// " }\n" + -// " ],\n" + -// " \"number\": 2,\n" + -// " \"sort\": {\n" + -// " \"empty\": false,\n" + -// " \"sorted\": true,\n" + -// " \"unsorted\": false\n" + -// " },\n" + -// " \"first\": false,\n" + -// " \"last\": true,\n" + -// " \"numberOfElements\": 1,\n" + -// " \"pageable\": {\n" + -// " \"offset\": 50,\n" + -// " \"sort\": {\n" + -// " \"empty\": false,\n" + -// " \"sorted\": true,\n" + -// " \"unsorted\": false\n" + -// " },\n" + -// " \"pageNumber\": 2,\n" + -// " \"pageSize\": 25,\n" + -// " \"paged\": true,\n" + -// " \"unpaged\": false\n" + -// " },\n" + -// " \"empty\": false\n" + -// "}", response, false); -// } + @Autowired private MockMvc mockMvc; + + @MockBean private LectureService lectureService; + + @MockBean private LectureStudentService studentService; + + // @DisplayName("강의 등록 uri 를 정상적으로 호출 및 응답.") + // @Test + // public void createLectureTest() throws Exception { + // + // //given + // doNothing().when(lectureService).create(any(), any()); + // + // //when + // mockMvc.perform(post("/lecture") + // .contentType(MediaType.APPLICATION_JSON) + // .content("{\n" + + // " \"title\": \"절권도 강의\",\n" + + // " \"applyDeadLine\": \"9022-07-31T16:51:33\",\n" + + // " \"daysOfWeeks\": \"월 수 금\",\n" + + // " \"place\": \"6호관 623 강의실\",\n" + + // " \"curriculumDetails\": \"1주차: 빅데이터에 기반한 공격패턴분석
2주차: + // ...\",\n" + + // " \"participantsLimits\": 30,\n" + + // " \"method\": 1,\n" + + // " \"introduction\": \"호신술을 배워보자\"\n" + + // "}")) + // .andExpect(status().isNoContent()); + // + // //then + // then(lectureService).should(times(1)).create(any(), any()); + // } + + // @DisplayName("강의 수정 uri 를 정상적으로 호출 및 응답") + // @Test + // public void updateLectureTest() throws Exception { + // + // //given + // doNothing().when(lectureService).update(any(), any()); + // + // //when + // mockMvc.perform(put("/lecture") + // .contentType(MediaType.APPLICATION_JSON) + // .content("{\n" + + // " \"id\": \"1\",\n" + + // " \"title\": \"절권도 강의\",\n" + + // " \"applyDeadLine\": \"9022-07-31T16:51:33\",\n" + + // " \"daysOfWeeks\": \"월 수 금\",\n" + + // " \"place\": \"6호관 623 강의실\",\n" + + // " \"curriculumDetails\": \"1주차: 빅데이터에 기반한 공격패턴분석
2주차: + // ...\",\n" + + // " \"participantsLimits\": 30,\n" + + // " \"method\": 1,\n" + + // " \"introduction\": \"호신술을 배워보자\"\n" + + // "}")) + // .andExpect(status().isNoContent()); + // + // //then + // then(lectureService).should(times(1)).update(any(), any()); + // } + + @DisplayName("강의 삭제 uri 를 정상적으로 호출 및 응답") + @Test + public void deleteLectureTest() throws Exception { + + // given + doNothing().when(lectureService).delete(any(), any()); + + // when + mockMvc.perform(delete("/lecture/1")).andExpect(status().isNoContent()); + + // then + then(lectureService).should(times(1)).delete(any(), any()); + } + + // @DisplayName("강의 조회 uri 를 정상적으로 호출 및 응답") + // @Test + // public void getLectureDetailsTest() throws Exception { + // + // //given + // LectureDetailDto expectedDto = LectureDetailDto.builder() + // .title("절권도 강의") + // .chief(new LectureDetailDto.MemberInfo(12171652, "산업경영공학과", "유동현")) + // .applyDeadLine(LocalDateTime.of(9022, 7, 31, 17, 11, 36)) + // .created(LocalDateTime.of(9022, 7, 23, 17, 11, 36)) + // .updated(null) + // .daysOfWeeks("월 금") + // .introduction("호신술을 배워보자") + // .curriculumDetails("1주차: 빅데이터에 기반한 공격패턴분석
2주차: ...") + // .method(1) + // .paid(false) + // .participantsLimits(30) + // .place("구내식당") + // .rejectReason(null) + // .state(LectureStatus.WAITING) + // .build() + // .setCoInstructors(List.of( + // new LectureDetailDto.MemberInfo(12345678, "스마트모빌리티공학과", "윤예진"), + // new LectureDetailDto.MemberInfo(87654321, "통계학과", "나까무라철수") + // )); + // given(lectureService.get(any())).willReturn(expectedDto); + // + // //when + // String response = mockMvc.perform(get("/lecture/1")) + // .andExpect(status().isOk()) + // .andReturn() + // .getResponse().getContentAsString(StandardCharsets.UTF_8); + // + // //then + // then(lectureService).should(times(1)).get(any()); + // JSONAssert.assertEquals("{" + + // " \"title\": \"절권도 강의\"," + + // " \"chief\": {" + + // " \"id\": 12171652," + + // " \"major\": \"산업경영공학과\"," + + // " \"name\": \"유동현\"" + + // " }," + + // " \"coInstructors\": [" + + // " {" + + // " \"id\": 12345678," + + // " \"major\": \"스마트모빌리티공학과\"," + + // " \"name\": \"윤예진\"" + + // " }," + + // " {" + + // " \"id\": 87654321," + + // " \"major\": \"통계학과\"," + + // " \"name\": \"나까무라철수\"" + + // " }" + + // " ]," + + // " \"applyDeadLine\": \"9022-07-31T17:11:36\"," + + // " \"daysOfWeeks\": \"월 금\"," + + // " \"place\": \"구내식당\"," + + // " \"introduction\": \"호신술을 배워보자\"," + + // " \"curriculumDetails\": \"1주차: 빅데이터에 기반한 공격패턴분석
2주차: ...\"," + + // " \"participantsLimits\": 30," + + // " \"method\": 1," + + // " \"state\": \"WAITING\"," + + // " \"rejectReason\": null," + + // " \"paid\": false," + + // " \"created\": \"9022-07-23T17:11:36\"," + + // " \"updated\": null" + + // "}", response, false); + // } + + // @DisplayName("강의 리스트 조회 uri 를 정상적으로 호출 및 응답") + // @Test + // public void getLectureListTest() throws Exception { + // + // //given + // List list = List.of( + // new LectureListDto(1, "title1", 1000001, "intro1", LocalDateTime.of(2001, 1, 1, + // 1, 1, 1), LectureStatus.PROGRESSING, 1, 30, 2), + // new LectureListDto(2, "title2", 1000002, "intro2", LocalDateTime.of(2002, 2, 2, + // 2, 2, 2), LectureStatus.PROGRESSING, 1, 31, 3), + // new LectureListDto(3, "title3", 1000003, "intro3", LocalDateTime.of(2003, 3, 3, + // 3, 3, 3), LectureStatus.PROGRESSING, 1, 32, 4) + // ); + // PageImpl page = new PageImpl<>(list, PageRequest.of(0, 6, + // Sort.Direction.DESC, "apply_deadline"), list.size()); + // given(lectureService.getList(any())).willReturn(page); + // + // //when + // String response = mockMvc.perform(get("/lectures")) + // .andExpect(status().isOk()) + // .andReturn() + // .getResponse().getContentAsString(StandardCharsets.UTF_8); + // + // //then + // then(lectureService).should(times(1)).getList(any()); + // JSONAssert.assertEquals("{\n" + + // " \"totalPages\": 1,\n" + + // " \"totalElements\": 3,\n" + + // " \"size\": 6,\n" + + // " \"content\": [\n" + + // " {\n" + + // " \"lectureId\": 3,\n" + + // " \"title\": \"title3\",\n" + + // " \"chiefId\": 1000003,\n" + + // " \"introduction\": \"intro3\",\n" + + // " \"applyDeadline\": \"2003-03-03T03:03:03\",\n" + + // " \"status\": \"PROGRESSING\",\n" + + // " \"method\": 1,\n" + + // " \"participantsLimits\": 32,\n" + + // " \"theNumberOfCurrentParticipants\": 4\n" + + // " },\n" + + // " {\n" + + // " \"lectureId\": 2,\n" + + // " \"title\": \"title2\",\n" + + // " \"chiefId\": 1000002,\n" + + // " \"introduction\": \"intro2\",\n" + + // " \"applyDeadline\": \"2002-02-02T02:02:02\",\n" + + // " \"status\": \"PROGRESSING\",\n" + + // " \"method\": 1,\n" + + // " \"participantsLimits\": 31,\n" + + // " \"theNumberOfCurrentParticipants\": 3\n" + + // " },\n" + + // " {\n" + + // " \"lectureId\": 1,\n" + + // " \"title\": \"title1\",\n" + + // " \"chiefId\": 1000001,\n" + + // " \"introduction\": \"intro1\",\n" + + // " \"applyDeadline\": \"2001-01-01T01:01:01\",\n" + + // " \"status\": \"PROGRESSING\",\n" + + // " \"method\": 1,\n" + + // " \"participantsLimits\": 30,\n" + + // " \"theNumberOfCurrentParticipants\": 2\n" + + // " }\n" + + // " ],\n" + + // " \"number\": 0,\n" + + // " \"sort\": {\n" + + // " \"empty\": false,\n" + + // " \"sorted\": true,\n" + + // " \"unsorted\": false\n" + + // " },\n" + + // " \"first\": true,\n" + + // " \"last\": true,\n" + + // " \"numberOfElements\": 3,\n" + + // " \"pageable\": {\n" + + // " \"offset\": 0,\n" + + // " \"sort\": {\n" + + // " \"empty\": false,\n" + + // " \"sorted\": true,\n" + + // " \"unsorted\": false\n" + + // " },\n" + + // " \"pageNumber\": 0,\n" + + // " \"pageSize\": 6,\n" + + // " \"paged\": true,\n" + + // " \"unpaged\": false\n" + + // " },\n" + + // " \"empty\": false\n" + + // "}", response, false); + // } + + @DisplayName("강의 상태 변경 api 를 호출한다.") + @Test + public void updateLectureStatusTest() throws Exception { + + // given + doNothing().when(lectureService).approveOrDeny(any(), any()); + + // when + mockMvc + .perform( + put("/lecture/1/status") + .contentType(MediaType.APPLICATION_JSON) + .content( + "{\n" + + " \"status\": \"PROGRESSING\",\n" + + " \"rejectReason\": null\n" + + "}")) + .andExpect(status().isNoContent()); + + // then + then(lectureService).should(times(1)).approveOrDeny(any(), any()); + } + + @DisplayName("수강생으로 등록한다.") + @Test + public void enrollTest() throws Exception { + + // given + doNothing().when(studentService).enroll(any(), any()); + + // when + mockMvc.perform(post("/lecture/1/student")).andExpect(status().isNoContent()); + + // then + then(studentService).should(times(1)).enroll(any(), any()); + } + + @DisplayName("수강생 한명의 수강상태를 변경한다.") + @Test + public void changeStudentStatusTest() throws Exception { + + doNothing().when(studentService).changeStatusOfOneStudentByLecturer(any(), any(), any(), any()); + + // when + mockMvc + .perform( + put("/lecture/1/student/121/status") + .contentType(MediaType.APPLICATION_JSON) + .content("\"BLOCKED\"")) + .andExpect(status().isNoContent()); + + // then + then(studentService) + .should(times(1)) + .changeStatusOfOneStudentByLecturer(any(), any(), any(), any()); + } + + // @DisplayName("다수의 수강생 상태를 변경한다.") + // @Test + // public void changeStudentsStatusTest() throws Exception { + // + // doNothing().when(studentService).changeStatusOfStudentsByLecturer(any(), any(), any()); + // + // //when + // mockMvc.perform(put("/lecture/1/students/status") + // .contentType(MediaType.APPLICATION_JSON) + // .content("[{\"12\":\"BLOCKED\"}, {\"15\":\"BLOCKED\"}]")) + // .andExpect(status().isNoContent()); + // + // //then + // then(studentService).should(times(1)).changeStatusOfStudentsByLecturer(any(), any(), + // any()); + // } + + @DisplayName("수강생이 강의를 탈퇴한다.") + @Test + public void exitLectureTest() throws Exception { + + doNothing().when(studentService).exitBySelf(any(), any()); + + // when + mockMvc.perform(delete("/lecture/1/student")).andExpect(status().isNoContent()); + + // then + then(studentService).should(times(1)).exitBySelf(any(), any()); + } + + // @DisplayName("수강생들의 정보를 조회한다.") + // @Test + // public void searchStudentsInformation() throws Exception { + // + // //given + // List students = new ArrayList<>(); + // for (int i = 0; i < 51; i++) { + // students.add( + // StudentListDto.builder() + // .name("홍길동"+i) + // .memberId(1000000+i) + // .email("my@gmail.com") + // .assignmentCount(0) + // .attendanceCount(0) + // .phoneNumber("010-0000-0000") + // .status(StudentStatus.PROGRESS) + // .sid(i) + // .build() + // ); + // } + // PageImpl page = + // new PageImpl<>(students.subList(50, students.size()), PageRequest.of(2, 25, + // Sort.Direction.ASC, "memberId"), students.size()); + // given(studentService.searchStudents(any(), any())).willReturn(page); + // + // //when + // String response = mockMvc.perform(get("/lecture/1/students")) + // .andExpect(status().isOk()) + // .andReturn().getResponse() + // .getContentAsString(StandardCharsets.UTF_8); + // + // //then + // then(studentService).should(times(1)).searchStudents(any(), any()); + // JSONAssert.assertEquals("{\n" + + // " \"totalPages\": 3,\n" + + // " \"totalElements\": 51,\n" + + // " \"size\": 25,\n" + + // " \"content\": [\n" + + // " {\n" + + // " \"name\": \"홍길동50\",\n" + + // " \"memberId\": 1000050,\n" + + // " \"phone\": \"010-0000-0000\",\n" + + // " \"email\": \"my@gmail.com\",\n" + + // " \"assignmentCount\": 0,\n" + + // " \"attendanceCount\": 0,\n" + + // " \"status\": \"PROGRESS\",\n" + + // " \"sid\": 50\n" + + // " }\n" + + // " ],\n" + + // " \"number\": 2,\n" + + // " \"sort\": {\n" + + // " \"empty\": false,\n" + + // " \"sorted\": true,\n" + + // " \"unsorted\": false\n" + + // " },\n" + + // " \"first\": false,\n" + + // " \"last\": true,\n" + + // " \"numberOfElements\": 1,\n" + + // " \"pageable\": {\n" + + // " \"offset\": 50,\n" + + // " \"sort\": {\n" + + // " \"empty\": false,\n" + + // " \"sorted\": true,\n" + + // " \"unsorted\": false\n" + + // " },\n" + + // " \"pageNumber\": 2,\n" + + // " \"pageSize\": 25,\n" + + // " \"paged\": true,\n" + + // " \"unpaged\": false\n" + + // " },\n" + + // " \"empty\": false\n" + + // "}", response, false); + // } } diff --git a/resource-server/src/test/java/com/inhabas/api/web/MemberControllerTest.java b/resource-server/src/test/java/com/inhabas/api/web/MemberControllerTest.java index d4b41624..597a5bbe 100644 --- a/resource-server/src/test/java/com/inhabas/api/web/MemberControllerTest.java +++ b/resource-server/src/test/java/com/inhabas/api/web/MemberControllerTest.java @@ -1,198 +1,196 @@ package com.inhabas.api.web; +import static com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.Role.BASIC; +import static org.hamcrest.Matchers.equalTo; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.doThrow; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import java.util.ArrayList; +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.data.domain.Pageable; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; + import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; -import com.inhabas.api.auth.domain.oauth2.member.service.MemberService; import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.Role; import com.inhabas.api.auth.domain.oauth2.member.dto.*; import com.inhabas.api.auth.domain.oauth2.member.repository.MemberRepository; +import com.inhabas.api.auth.domain.oauth2.member.service.MemberService; import com.inhabas.api.domain.member.domain.entity.MemberTest; import com.inhabas.api.domain.signUp.dto.AnswerDto; import com.inhabas.api.domain.signUp.usecase.AnswerService; import com.inhabas.testAnnotataion.NoSecureWebMvcTest; + import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.data.domain.Pageable; -import org.springframework.http.MediaType; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; - -import java.util.ArrayList; -import java.util.List; - -import static com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.Role.BASIC; -import static org.hamcrest.Matchers.equalTo; -import static org.mockito.ArgumentMatchers.*; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.doThrow; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @NoSecureWebMvcTest(MemberController.class) public class MemberControllerTest { - @Autowired - private MockMvc mvc; - @MockBean - private MemberService memberService; - @MockBean - private AnswerService answerService; - @MockBean - private MemberRepository memberRepository; - @Autowired - private ObjectMapper objectMapper; - - @DisplayName("(신입)미승인 멤버 정보 목록을 불러온다") - @Test - public void getUnapprovedMembers() throws Exception { - - // given - List dtoList = new ArrayList<>(); - NotApprovedMemberManagementDto dto1 = new NotApprovedMemberManagementDto( - "홍길동", 1L, "12171707", - "010-1234-2345", "abc1234@gmail.com", 1, "컴퓨터공학과"); - dtoList.add(dto1); - - given(memberService.getNotApprovedMembersBySearchAndRole(any())).willReturn(dtoList); - given(memberService.getPagedDtoList(any(Pageable.class), eq(dtoList))).willReturn(dtoList); - - // then - mvc.perform(get("/members/unapproved")) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.data[0].name").value(equalTo("홍길동"))) - .andExpect(jsonPath("$.data[0].memberId").value(equalTo(1))) - .andExpect(jsonPath("$.data[0].studentId").value(equalTo("12171707"))) - .andExpect(jsonPath("$.data[0].phoneNumber").value(equalTo("010-1234-2345"))) - .andExpect(jsonPath("$.data[0].email").value(equalTo("abc1234@gmail.com"))) - .andExpect(jsonPath("$.data[0].major").value(equalTo("컴퓨터공학과"))); - + @Autowired private MockMvc mvc; + @MockBean private MemberService memberService; + @MockBean private AnswerService answerService; + @MockBean private MemberRepository memberRepository; + @Autowired private ObjectMapper objectMapper; + + @DisplayName("(신입)미승인 멤버 정보 목록을 불러온다") + @Test + public void getUnapprovedMembers() throws Exception { + + // given + List dtoList = new ArrayList<>(); + NotApprovedMemberManagementDto dto1 = + new NotApprovedMemberManagementDto( + "홍길동", 1L, "12171707", "010-1234-2345", "abc1234@gmail.com", 1, "컴퓨터공학과"); + dtoList.add(dto1); + + given(memberService.getNotApprovedMembersBySearchAndRole(any())).willReturn(dtoList); + given(memberService.getPagedDtoList(any(Pageable.class), eq(dtoList))).willReturn(dtoList); + + // then + mvc.perform(get("/members/unapproved")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.data[0].name").value(equalTo("홍길동"))) + .andExpect(jsonPath("$.data[0].memberId").value(equalTo(1))) + .andExpect(jsonPath("$.data[0].studentId").value(equalTo("12171707"))) + .andExpect(jsonPath("$.data[0].phoneNumber").value(equalTo("010-1234-2345"))) + .andExpect(jsonPath("$.data[0].email").value(equalTo("abc1234@gmail.com"))) + .andExpect(jsonPath("$.data[0].major").value(equalTo("컴퓨터공학과"))); + } + + @DisplayName("(신입)미승인 멤버 -> 비활동 멤버로 변경할때 state가 pass, fail이면 204를 반환하고 아니면 400를 반환한다..") + @ParameterizedTest + @ValueSource(strings = {"pass", "fail", "hacker"}) + public void passOrFailUnapprovedMembers(String state) throws Exception { + // given + List memberIdList = List.of(1L); + List members = List.of(MemberTest.notapprovedMember()); + + if (state.equals("pass") || state.equals("fail")) { + // when + given(memberRepository.findAllById(memberIdList)).willReturn(members); + // then + mvc.perform( + put("/members/unapproved") + .contentType(MediaType.APPLICATION_JSON) + .content(jsonOf(new UpdateRequestDto(memberIdList, state)))) + .andExpect(status().isNoContent()); + } else { + // when + doThrow(new InvalidInputException()) + .when(memberService) + .updateUnapprovedMembers(anyList(), anyString()); + // then + mvc.perform( + put("/members/unapproved") + .contentType(MediaType.APPLICATION_JSON) + .content(jsonOf(new UpdateRequestDto(memberIdList, state)))) + .andExpect(status().isBadRequest()); } - - @DisplayName("(신입)미승인 멤버 -> 비활동 멤버로 변경할때 state가 pass, fail이면 204를 반환하고 아니면 400를 반환한다..") - @ParameterizedTest - @ValueSource(strings = {"pass", "fail", "hacker"}) - public void passOrFailUnapprovedMembers(String state) throws Exception { - //given - List memberIdList = List.of(1L); - List members = List.of(MemberTest.notapprovedMember()); - - if (state.equals("pass") || state.equals("fail")) { - //when - given(memberRepository.findAllById(memberIdList)).willReturn(members); - //then - mvc.perform(put("/members/unapproved") - .contentType(MediaType.APPLICATION_JSON) - .content(jsonOf(new UpdateRequestDto(memberIdList, state)))) - .andExpect(status().isNoContent()); - } else { - //when - doThrow(new InvalidInputException()).when(memberService).updateUnapprovedMembers(anyList(), anyString()); - //then - mvc.perform(put("/members/unapproved") - .contentType(MediaType.APPLICATION_JSON) - .content(jsonOf(new UpdateRequestDto(memberIdList, state)))) - .andExpect(status().isBadRequest()); - } + } + + @DisplayName("특정 신입 멤버 지원서를 조회한다.") + @Test + public void getUnapprovedMemberApplication() throws Exception { + + // given + List dtoList = new ArrayList<>(); + AnswerDto dto1 = new AnswerDto(1L, "안녕하세요. 예 안녕히계세요."); + dtoList.add(dto1); + + given(answerService.getAnswers(any())).willReturn(dtoList); + + // then + mvc.perform(get("/members/1/application")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.[0].questionId").value(equalTo(1))) + .andExpect(jsonPath("$.[0].content").value(equalTo("안녕하세요. 예 안녕히계세요."))); + } + + @DisplayName("비활동 이상 모든 멤버 목록을 조회한다.") + @Test + public void getApprovedMembers() throws Exception { + + // given + List dtoList = new ArrayList<>(); + ApprovedMemberManagementDto dto1 = + new ApprovedMemberManagementDto("홍길동", 1L, "12171707", "010-1234-2345", BASIC, 1, "컴퓨터공학과"); + dtoList.add(dto1); + + given(memberService.getApprovedMembersBySearchAndRole(any())).willReturn(dtoList); + given(memberService.getPagedDtoList(any(Pageable.class), eq(dtoList))).willReturn(dtoList); + + // then + mvc.perform(get("/members")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.data[0].name").value(equalTo("홍길동"))) + .andExpect(jsonPath("$.data[0].memberId").value(equalTo(1))) + .andExpect(jsonPath("$.data[0].studentId").value(equalTo("12171707"))) + .andExpect(jsonPath("$.data[0].phoneNumber").value(equalTo("010-1234-2345"))) + .andExpect(jsonPath("$.data[0].generation").value(equalTo(1))) + .andExpect(jsonPath("$.data[0].major").value(equalTo("컴퓨터공학과"))); + } + + @DisplayName("비활동 이상 멤버 권한을 변경할 때 가능한 권한이면 204, 아니면 400을 반환한다.") + @ParameterizedTest + @ValueSource(strings = {"ADMIN", "SIGNING_UP"}) + public void updateApprovedMembers(String roleString) throws Exception { + // given + List memberIdList = List.of(1L); + List members = List.of(MemberTest.deactivatedMember()); + + if (roleString.equals("ADMIN")) { + // when + given(memberRepository.findAllById(memberIdList)).willReturn(members); + // then + mvc.perform( + put("/members/approved") + .contentType(MediaType.APPLICATION_JSON) + .content(jsonOf(new UpdateRoleRequestDto(memberIdList, Role.ADMIN)))) + .andExpect(status().isNoContent()); + } else if (roleString.equals("SIGNING_UP")) { + // when + doThrow(new InvalidInputException()) + .when(memberService) + .updateApprovedMembers(anyList(), any()); + // then + mvc.perform( + MockMvcRequestBuilders.put("/members/approved") + .contentType(MediaType.APPLICATION_JSON) + .content(jsonOf(new UpdateRoleRequestDto(memberIdList, Role.SIGNING_UP)))) + .andExpect(status().isBadRequest()); } + } - @DisplayName("특정 신입 멤버 지원서를 조회한다.") - @Test - public void getUnapprovedMemberApplication() throws Exception { - - // given - List dtoList = new ArrayList<>(); - AnswerDto dto1 = new AnswerDto( - 1L, "안녕하세요. 예 안녕히계세요."); - dtoList.add(dto1); + @DisplayName("회장 연락처 정보를 불러온다") + @Test + public void getChiefContact() throws Exception { - given(answerService.getAnswers(any())).willReturn(dtoList); + given(memberService.getChiefContact()) + .willReturn(new ContactDto("강지훈", "010-0000-0000", "my@email.com")); - // then - mvc.perform(get("/members/1/application")) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.[0].questionId").value(equalTo(1))) - .andExpect(jsonPath("$.[0].content").value(equalTo("안녕하세요. 예 안녕히계세요."))); - - } - - @DisplayName("비활동 이상 모든 멤버 목록을 조회한다.") - @Test - public void getApprovedMembers() throws Exception { - - // given - List dtoList = new ArrayList<>(); - ApprovedMemberManagementDto dto1 = new ApprovedMemberManagementDto( - "홍길동", 1L, "12171707", - "010-1234-2345", BASIC, 1, "컴퓨터공학과"); - dtoList.add(dto1); - - given(memberService.getApprovedMembersBySearchAndRole(any())).willReturn(dtoList); - given(memberService.getPagedDtoList(any(Pageable.class), eq(dtoList))).willReturn(dtoList); - - // then - mvc.perform(get("/members")) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.data[0].name").value(equalTo("홍길동"))) - .andExpect(jsonPath("$.data[0].memberId").value(equalTo(1))) - .andExpect(jsonPath("$.data[0].studentId").value(equalTo("12171707"))) - .andExpect(jsonPath("$.data[0].phoneNumber").value(equalTo("010-1234-2345"))) - .andExpect(jsonPath("$.data[0].generation").value(equalTo(1))) - .andExpect(jsonPath("$.data[0].major").value(equalTo("컴퓨터공학과"))); - - } - - @DisplayName("비활동 이상 멤버 권한을 변경할 때 가능한 권한이면 204, 아니면 400을 반환한다.") - @ParameterizedTest - @ValueSource(strings = {"ADMIN", "SIGNING_UP"}) - public void updateApprovedMembers(String roleString) throws Exception { - //given - List memberIdList = List.of(1L); - List members = List.of(MemberTest.deactivatedMember()); - - if (roleString.equals("ADMIN")) { - //when - given(memberRepository.findAllById(memberIdList)).willReturn(members); - //then - mvc.perform(put("/members/approved") - .contentType(MediaType.APPLICATION_JSON) - .content(jsonOf(new UpdateRoleRequestDto(memberIdList, Role.ADMIN)))) - .andExpect(status().isNoContent()); - } else if (roleString.equals("SIGNING_UP")) { - //when - doThrow(new InvalidInputException()).when(memberService).updateApprovedMembers(anyList(), any()); - //then - mvc.perform(MockMvcRequestBuilders.put("/members/approved") - .contentType(MediaType.APPLICATION_JSON) - .content(jsonOf(new UpdateRoleRequestDto(memberIdList, Role.SIGNING_UP)))) - .andExpect(status().isBadRequest()); - } - } - - @DisplayName("회장 연락처 정보를 불러온다") - @Test - public void getChiefContact() throws Exception { - - given(memberService.getChiefContact()) - .willReturn(new ContactDto("강지훈", "010-0000-0000","my@email.com")); - - mvc.perform(get("/member/chief")) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.name").value(equalTo("강지훈"))) - .andExpect(jsonPath("$.phoneNumber").value(equalTo("010-0000-0000"))) - .andExpect(jsonPath("$.email").value(equalTo("my@email.com"))); - - } - - private String jsonOf(Object o) throws JsonProcessingException { - return objectMapper.writeValueAsString(o); - } + mvc.perform(get("/member/chief")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.name").value(equalTo("강지훈"))) + .andExpect(jsonPath("$.phoneNumber").value(equalTo("010-0000-0000"))) + .andExpect(jsonPath("$.email").value(equalTo("my@email.com"))); + } + private String jsonOf(Object o) throws JsonProcessingException { + return objectMapper.writeValueAsString(o); + } } diff --git a/resource-server/src/test/java/com/inhabas/api/web/MenuControllerTest.java b/resource-server/src/test/java/com/inhabas/api/web/MenuControllerTest.java index 4cee0cae..c2e4fb67 100644 --- a/resource-server/src/test/java/com/inhabas/api/web/MenuControllerTest.java +++ b/resource-server/src/test/java/com/inhabas/api/web/MenuControllerTest.java @@ -9,56 +9,67 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.web.servlet.MockMvc; + import com.inhabas.api.domain.menu.domain.valueObject.MenuId; import com.inhabas.api.domain.menu.domain.valueObject.MenuType; import com.inhabas.api.domain.menu.dto.MenuDto; import com.inhabas.api.domain.menu.dto.MenuGroupDto; import com.inhabas.api.domain.menu.usecase.MenuService; import com.inhabas.testAnnotataion.NoSecureWebMvcTest; -import java.util.List; + import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.test.web.servlet.MockMvc; @NoSecureWebMvcTest(MenuController.class) public class MenuControllerTest { - @MockBean - private MenuService menuService; - - @Autowired - private MockMvc mvc; + @MockBean private MenuService menuService; - @DisplayName("모든 메뉴 정보를 조회한다.") - @Test - public void getTotalMenuInfoTest() throws Exception { - given(menuService.getAllMenuInfo()).willReturn( - List.of(new MenuGroupDto(1, "IBAS", List.of(new MenuDto(new MenuId(6),1,"동아리 소개",MenuType.INTRODUCE, ""))))); + @Autowired private MockMvc mvc; - mvc.perform(get("/menus")) - .andDo(print()) - .andExpect(status().isOk()) - .andExpect(content().string("[{\"id\":1,\"groupName\":\"IBAS\",\"menuList\":[{\"menuId\":6,\"priority\":1,\"name\":\"ë\u008F\u0099ì\u0095\u0084리 ì\u0086\u008Cê°\u009C\",\"type\":\"INTRODUCE\",\"description\":\"\"}]}]")) - .andReturn(); + @DisplayName("모든 메뉴 정보를 조회한다.") + @Test + public void getTotalMenuInfoTest() throws Exception { + given(menuService.getAllMenuInfo()) + .willReturn( + List.of( + new MenuGroupDto( + 1, + "IBAS", + List.of(new MenuDto(new MenuId(6), 1, "동아리 소개", MenuType.INTRODUCE, ""))))); - then(menuService).should(times(1)).getAllMenuInfo(); - } + mvc.perform(get("/menus")) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect( + content() + .string( + "[{\"id\":1,\"groupName\":\"IBAS\",\"menuList\":[{\"menuId\":6,\"priority\":1,\"name\":\"ë\u008F\u0099ì\u0095\u0084리 ì\u0086\u008Cê°\u009C\",\"type\":\"INTRODUCE\",\"description\":\"\"}]}]")) + .andReturn(); - @DisplayName("단일 메뉴 정보를 조회한다.") - @Test - public void getMenuInfoByIdTest() throws Exception { + then(menuService).should(times(1)).getAllMenuInfo(); + } - given(menuService.getMenuInfoById(any())).willReturn( - new MenuDto(new MenuId(6),1,"공지사항",MenuType.LIST,"")); + @DisplayName("단일 메뉴 정보를 조회한다.") + @Test + public void getMenuInfoByIdTest() throws Exception { - mvc.perform(get("/menu/6")) - .andExpect(content().string("{\"menuId\":6,\"priority\":1,\"name\":\"ê³µì§\u0080ì\u0082¬í\u0095\u00AD\",\"type\":\"LIST\",\"description\":\"\"}")) - .andExpect(status().isOk()) - .andReturn(); + given(menuService.getMenuInfoById(any())) + .willReturn(new MenuDto(new MenuId(6), 1, "공지사항", MenuType.LIST, "")); - then(menuService).should(times(1)).getMenuInfoById(any()); - } + mvc.perform(get("/menu/6")) + .andExpect( + content() + .string( + "{\"menuId\":6,\"priority\":1,\"name\":\"ê³µì§\u0080ì\u0082¬í\u0095\u00AD\",\"type\":\"LIST\",\"description\":\"\"}")) + .andExpect(status().isOk()) + .andReturn(); + then(menuService).should(times(1)).getMenuInfoById(any()); + } } diff --git a/resource-server/src/test/java/com/inhabas/api/web/MyProfileControllerTest.java b/resource-server/src/test/java/com/inhabas/api/web/MyProfileControllerTest.java index 29fde442..7a7fc5d5 100644 --- a/resource-server/src/test/java/com/inhabas/api/web/MyProfileControllerTest.java +++ b/resource-server/src/test/java/com/inhabas/api/web/MyProfileControllerTest.java @@ -1,5 +1,20 @@ package com.inhabas.api.web; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.mockito.BDDMockito.willDoNothing; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import java.nio.charset.StandardCharsets; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; + import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.inhabas.api.auth.domain.oauth2.member.domain.entity.Member; @@ -10,164 +25,143 @@ import com.inhabas.api.auth.domain.oauth2.member.service.MemberService; import com.inhabas.api.domain.member.domain.entity.MemberTest; import com.inhabas.testAnnotataion.NoSecureWebMvcTest; + import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.http.MediaType; -import org.springframework.test.web.servlet.MockMvc; - -import java.nio.charset.StandardCharsets; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.given; -import static org.mockito.BDDMockito.willDoNothing; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @NoSecureWebMvcTest(MyProfileController.class) class MyProfileControllerTest { - @Autowired - private MockMvc mvc; - @MockBean - private MemberService memberService; - @Autowired - private ObjectMapper objectMapper; - - - private String jsonOf(Object o) throws JsonProcessingException { - return objectMapper.writeValueAsString(o); - } - - @DisplayName("내 정보를 조회한다.") - @Test - public void getMyProfileTest() throws Exception { - //given - Member member = MemberTest.basicMember1(); - MyProfileDto myProfileDto = MyProfileDto.builder() - .name(member.getName()) - .studentId(member.getStudentId()) - .major(member.getSchoolInformation().getMajor()) - .grade(member.getSchoolInformation().getGrade()) - .email(member.getEmail()) - .phoneNumber(member.getPhone()) - .role(member.getRole()) - .type(member.getSchoolInformation().getMemberType()) - .introduce(member.getIbasInformation().getIntroduce()) - .build(); - - //when - given(memberService.getMyProfile(any())).willReturn(myProfileDto); - - //then - String response = mvc.perform(get("/myInfo")) - .andExpect(status().isOk()) - .andReturn() - .getResponse() - .getContentAsString(StandardCharsets.UTF_8); - assertThat(response).isEqualTo(jsonOf(myProfileDto)); - - } - - @DisplayName("내 [학과, 학년, 전화번호] 수정") - @Test - public void updateMyProfileDetailTest() throws Exception { - //given - Member member = MemberTest.basicMember1(); - ProfileDetailDto profileDetailDto = ProfileDetailDto.builder() - .major(member.getSchoolInformation().getMajor()) - .grade(member.getSchoolInformation().getGrade()) - .phoneNumber(member.getPhone()) - .build(); - - //when - willDoNothing().given(memberService).updateMyProfileDetail(any(), any()); - - //then - mvc.perform(put("/myInfo/detail") - .contentType(MediaType.APPLICATION_JSON) - .content(jsonOf(profileDetailDto))) - .andExpect(status().isNoContent()); - - } - - @DisplayName("내 프로필 자기소개 수정") - @Test - public void updateMyProfileIntroTest() throws Exception { - //given - Member member = MemberTest.basicMember1(); - ProfileIntroDto profileIntroDto = ProfileIntroDto.builder() - .introduce(member.getIbasInformation().getIntroduce()) - .isHOF(member.getIbasInformation().getIsHOF()) - .build(); - - //when - willDoNothing().given(memberService).updateMyProfileIntro(any(), any()); - - //then - mvc.perform(put("/myInfo/intro") - .contentType(MediaType.APPLICATION_JSON) - .content(jsonOf(profileIntroDto))) - .andExpect(status().isNoContent()); - - } - - @DisplayName("내 프로필 사진 수정") - @Test - @Disabled - public void updateMyProfileImage() throws Exception { - // 첨부파일 문제로 보류 - } - - @DisplayName("내 정보 이름 수정") - @Test - public void requestMyProfileNameTest() throws Exception { - //given - ProfileNameDto profileNameDto = ProfileNameDto.builder() - .name("새이름") - .build(); - - //when - willDoNothing().given(memberService).requestMyProfileName(any(), any()); - - //then - mvc.perform(put("/myInfo/name") - .contentType(MediaType.APPLICATION_JSON) - .content(jsonOf(profileNameDto))) - .andExpect(status().isNoContent()); - - } - - @DisplayName("내 정보 이름 수정에서 이름은 NotBlank 를 보장한다.") - @Test - public void wrongRequestMyProfileNameTest() throws Exception { - //given - ProfileNameDto nullNameDto = ProfileNameDto.builder() - .name(null) - .build(); - ProfileNameDto emptyNameDto = ProfileNameDto.builder() - .name(" ") - .build(); - - - //when - willDoNothing().given(memberService).requestMyProfileName(any(), any()); - - //then - mvc.perform(put("/myInfo/name") - .contentType(MediaType.APPLICATION_JSON) - .content(jsonOf(nullNameDto))) - .andExpect(status().isBadRequest()); - - mvc.perform(put("/myInfo/name") - .contentType(MediaType.APPLICATION_JSON) - .content(jsonOf(emptyNameDto))) - .andExpect(status().isBadRequest()); - - } - -} \ No newline at end of file + @Autowired private MockMvc mvc; + @MockBean private MemberService memberService; + @Autowired private ObjectMapper objectMapper; + + private String jsonOf(Object o) throws JsonProcessingException { + return objectMapper.writeValueAsString(o); + } + + @DisplayName("내 정보를 조회한다.") + @Test + public void getMyProfileTest() throws Exception { + // given + Member member = MemberTest.basicMember1(); + MyProfileDto myProfileDto = + MyProfileDto.builder() + .name(member.getName()) + .studentId(member.getStudentId()) + .major(member.getSchoolInformation().getMajor()) + .grade(member.getSchoolInformation().getGrade()) + .email(member.getEmail()) + .phoneNumber(member.getPhone()) + .role(member.getRole()) + .type(member.getSchoolInformation().getMemberType()) + .introduce(member.getIbasInformation().getIntroduce()) + .build(); + + // when + given(memberService.getMyProfile(any())).willReturn(myProfileDto); + + // then + String response = + mvc.perform(get("/myInfo")) + .andExpect(status().isOk()) + .andReturn() + .getResponse() + .getContentAsString(StandardCharsets.UTF_8); + assertThat(response).isEqualTo(jsonOf(myProfileDto)); + } + + @DisplayName("내 [학과, 학년, 전화번호] 수정") + @Test + public void updateMyProfileDetailTest() throws Exception { + // given + Member member = MemberTest.basicMember1(); + ProfileDetailDto profileDetailDto = + ProfileDetailDto.builder() + .major(member.getSchoolInformation().getMajor()) + .grade(member.getSchoolInformation().getGrade()) + .phoneNumber(member.getPhone()) + .build(); + + // when + willDoNothing().given(memberService).updateMyProfileDetail(any(), any()); + + // then + mvc.perform( + put("/myInfo/detail") + .contentType(MediaType.APPLICATION_JSON) + .content(jsonOf(profileDetailDto))) + .andExpect(status().isNoContent()); + } + + @DisplayName("내 프로필 자기소개 수정") + @Test + public void updateMyProfileIntroTest() throws Exception { + // given + Member member = MemberTest.basicMember1(); + ProfileIntroDto profileIntroDto = + ProfileIntroDto.builder() + .introduce(member.getIbasInformation().getIntroduce()) + .isHOF(member.getIbasInformation().getIsHOF()) + .build(); + + // when + willDoNothing().given(memberService).updateMyProfileIntro(any(), any()); + + // then + mvc.perform( + put("/myInfo/intro") + .contentType(MediaType.APPLICATION_JSON) + .content(jsonOf(profileIntroDto))) + .andExpect(status().isNoContent()); + } + + @DisplayName("내 프로필 사진 수정") + @Test + @Disabled + public void updateMyProfileImage() throws Exception { + // 첨부파일 문제로 보류 + } + + @DisplayName("내 정보 이름 수정") + @Test + public void requestMyProfileNameTest() throws Exception { + // given + ProfileNameDto profileNameDto = ProfileNameDto.builder().name("새이름").build(); + + // when + willDoNothing().given(memberService).requestMyProfileName(any(), any()); + + // then + mvc.perform( + put("/myInfo/name") + .contentType(MediaType.APPLICATION_JSON) + .content(jsonOf(profileNameDto))) + .andExpect(status().isNoContent()); + } + + @DisplayName("내 정보 이름 수정에서 이름은 NotBlank 를 보장한다.") + @Test + public void wrongRequestMyProfileNameTest() throws Exception { + // given + ProfileNameDto nullNameDto = ProfileNameDto.builder().name(null).build(); + ProfileNameDto emptyNameDto = ProfileNameDto.builder().name(" ").build(); + + // when + willDoNothing().given(memberService).requestMyProfileName(any(), any()); + + // then + mvc.perform( + put("/myInfo/name") + .contentType(MediaType.APPLICATION_JSON) + .content(jsonOf(nullNameDto))) + .andExpect(status().isBadRequest()); + + mvc.perform( + put("/myInfo/name") + .contentType(MediaType.APPLICATION_JSON) + .content(jsonOf(emptyNameDto))) + .andExpect(status().isBadRequest()); + } +} diff --git a/resource-server/src/test/java/com/inhabas/api/web/PolicyTermControllerTest.java b/resource-server/src/test/java/com/inhabas/api/web/PolicyTermControllerTest.java index 84bc86ba..0ee87406 100644 --- a/resource-server/src/test/java/com/inhabas/api/web/PolicyTermControllerTest.java +++ b/resource-server/src/test/java/com/inhabas/api/web/PolicyTermControllerTest.java @@ -1,22 +1,5 @@ package com.inhabas.api.web; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; -import com.inhabas.api.auth.domain.error.businessException.NotFoundException; -import com.inhabas.api.domain.policy.dto.PolicyTermDto; -import com.inhabas.api.domain.policy.dto.SavePolicyTernDto; -import com.inhabas.api.domain.policy.usecase.PolicyTermService; -import com.inhabas.testAnnotataion.NoSecureWebMvcTest; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.http.MediaType; -import org.springframework.test.web.servlet.MockMvc; - -import java.nio.charset.StandardCharsets; - import static com.inhabas.api.auth.domain.error.ErrorCode.INVALID_INPUT_VALUE; import static com.inhabas.api.auth.domain.error.ErrorCode.NOT_FOUND; import static org.assertj.core.api.Assertions.assertThat; @@ -28,146 +11,153 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import java.nio.charset.StandardCharsets; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.inhabas.api.auth.domain.error.businessException.InvalidInputException; +import com.inhabas.api.auth.domain.error.businessException.NotFoundException; +import com.inhabas.api.domain.policy.dto.PolicyTermDto; +import com.inhabas.api.domain.policy.dto.SavePolicyTernDto; +import com.inhabas.api.domain.policy.usecase.PolicyTermService; +import com.inhabas.testAnnotataion.NoSecureWebMvcTest; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + @NoSecureWebMvcTest(PolicyTermController.class) public class PolicyTermControllerTest { - @Autowired - private MockMvc mvc; - - @MockBean - private PolicyTermService policyTermService; - - @Autowired - private ObjectMapper objectMapper; - - private String jsonOf(Object response) throws JsonProcessingException { - return objectMapper.writeValueAsString(response); - } - - - @DisplayName("정책 단일 조회 성공 200") - @Test - void findPolicyTerm() throws Exception { - //given - PolicyTermDto policyTermDto = PolicyTermDto.builder() - .title("title") - .content("content") - .build(); - given(policyTermService.findPolicyTerm(any())).willReturn(policyTermDto); - - //when - String response = mvc.perform(get("/policy/{policyTermId}", 1L)) - .andExpect(status().isOk()) - .andReturn() - .getResponse() - .getContentAsString(StandardCharsets.UTF_8); - - //then - assertThat(response).isEqualTo(jsonOf(policyTermDto)); - - } - - @DisplayName("정책 단일 조회 데이터가 올바르지 않다면 400") - @Test - void findPolicyTerm_Invalid_Input() throws Exception { - //given - PolicyTermDto policyTermDto = PolicyTermDto.builder() - .title("title") - .content("content") - .build(); - given(policyTermService.findPolicyTerm(any())).willReturn(policyTermDto); - - //when - String response = mvc.perform(get("/policy/{policyTermId}", "invalid")) - .andExpect(status().isBadRequest()) - .andReturn() - .getResponse() - .getContentAsString(StandardCharsets.UTF_8); - - //then - assertThat(response).contains(INVALID_INPUT_VALUE.getMessage()); - - } - - @DisplayName("정책 단일 조회 해당 id가 없다면 404") - @Test - void findPolicyTerm_Not_Found() throws Exception { - //given - doThrow(NotFoundException.class).when(policyTermService).findPolicyTerm(any()); - - //when - String response = mvc.perform(get("/policy/{policyTermId}", 1L)) - .andExpect(status().isNotFound()) - .andReturn() - .getResponse() - .getContentAsString(StandardCharsets.UTF_8); - - //then - assertThat(response).contains(NOT_FOUND.getMessage()); - - } - - @DisplayName("정책 수정 성공 204") - @Test - void updatePolicyTerm() throws Exception { - //given - SavePolicyTernDto savePolicyTernDto = SavePolicyTernDto.builder() - .content("meaningless") - .build(); - doNothing().when(policyTermService).updatePolicyTerm(any(), any()); - - //when then - mvc.perform(put("/policy/{policyTermId}", 1L) - .contentType(MediaType.APPLICATION_JSON) - .content(jsonOf(savePolicyTernDto))) - .andExpect(status().isNoContent()); - - } - - @DisplayName("정책 수정 데이터가 올바르지 않다면 400") - @Test - void updatePolicyTerm_Invalid_Input() throws Exception { - //given - SavePolicyTernDto savePolicyTernDto = SavePolicyTernDto.builder() - .content("meaningless") - .build(); - doThrow(InvalidInputException.class).when(policyTermService).updatePolicyTerm(any(), any()); - - //when - String response = mvc.perform(put("/policy/{policyTermId}", 1L) - .contentType(MediaType.APPLICATION_JSON) - .content(jsonOf(savePolicyTernDto))) - .andExpect(status().isBadRequest()) - .andReturn() - .getResponse() - .getContentAsString(StandardCharsets.UTF_8); - - //then - assertThat(response).contains(INVALID_INPUT_VALUE.getMessage()); - - } - - @DisplayName("정책 수정 해당 id가 존재하지 않다면 404") - @Test - void updatePolicyTerm_Not_Found() throws Exception { - //given - SavePolicyTernDto savePolicyTernDto = SavePolicyTernDto.builder() - .content("meaningless") - .build(); - doThrow(NotFoundException.class).when(policyTermService).updatePolicyTerm(any(), any()); - - //when - String response = mvc.perform(put("/policy/{policyTermId}", 1L) - .contentType(MediaType.APPLICATION_JSON) - .content(jsonOf(savePolicyTernDto))) - .andExpect(status().isNotFound()) - .andReturn() - .getResponse() - .getContentAsString(StandardCharsets.UTF_8); - - //then - assertThat(response).contains(NOT_FOUND.getMessage()); - - } - -} \ No newline at end of file + @Autowired private MockMvc mvc; + + @MockBean private PolicyTermService policyTermService; + + @Autowired private ObjectMapper objectMapper; + + private String jsonOf(Object response) throws JsonProcessingException { + return objectMapper.writeValueAsString(response); + } + + @DisplayName("정책 단일 조회 성공 200") + @Test + void findPolicyTerm() throws Exception { + // given + PolicyTermDto policyTermDto = PolicyTermDto.builder().title("title").content("content").build(); + given(policyTermService.findPolicyTerm(any())).willReturn(policyTermDto); + + // when + String response = + mvc.perform(get("/policy/{policyTermId}", 1L)) + .andExpect(status().isOk()) + .andReturn() + .getResponse() + .getContentAsString(StandardCharsets.UTF_8); + + // then + assertThat(response).isEqualTo(jsonOf(policyTermDto)); + } + + @DisplayName("정책 단일 조회 데이터가 올바르지 않다면 400") + @Test + void findPolicyTerm_Invalid_Input() throws Exception { + // given + PolicyTermDto policyTermDto = PolicyTermDto.builder().title("title").content("content").build(); + given(policyTermService.findPolicyTerm(any())).willReturn(policyTermDto); + + // when + String response = + mvc.perform(get("/policy/{policyTermId}", "invalid")) + .andExpect(status().isBadRequest()) + .andReturn() + .getResponse() + .getContentAsString(StandardCharsets.UTF_8); + + // then + assertThat(response).contains(INVALID_INPUT_VALUE.getMessage()); + } + + @DisplayName("정책 단일 조회 해당 id가 없다면 404") + @Test + void findPolicyTerm_Not_Found() throws Exception { + // given + doThrow(NotFoundException.class).when(policyTermService).findPolicyTerm(any()); + + // when + String response = + mvc.perform(get("/policy/{policyTermId}", 1L)) + .andExpect(status().isNotFound()) + .andReturn() + .getResponse() + .getContentAsString(StandardCharsets.UTF_8); + + // then + assertThat(response).contains(NOT_FOUND.getMessage()); + } + + @DisplayName("정책 수정 성공 204") + @Test + void updatePolicyTerm() throws Exception { + // given + SavePolicyTernDto savePolicyTernDto = + SavePolicyTernDto.builder().content("meaningless").build(); + doNothing().when(policyTermService).updatePolicyTerm(any(), any()); + + // when then + mvc.perform( + put("/policy/{policyTermId}", 1L) + .contentType(MediaType.APPLICATION_JSON) + .content(jsonOf(savePolicyTernDto))) + .andExpect(status().isNoContent()); + } + + @DisplayName("정책 수정 데이터가 올바르지 않다면 400") + @Test + void updatePolicyTerm_Invalid_Input() throws Exception { + // given + SavePolicyTernDto savePolicyTernDto = + SavePolicyTernDto.builder().content("meaningless").build(); + doThrow(InvalidInputException.class).when(policyTermService).updatePolicyTerm(any(), any()); + + // when + String response = + mvc.perform( + put("/policy/{policyTermId}", 1L) + .contentType(MediaType.APPLICATION_JSON) + .content(jsonOf(savePolicyTernDto))) + .andExpect(status().isBadRequest()) + .andReturn() + .getResponse() + .getContentAsString(StandardCharsets.UTF_8); + + // then + assertThat(response).contains(INVALID_INPUT_VALUE.getMessage()); + } + + @DisplayName("정책 수정 해당 id가 존재하지 않다면 404") + @Test + void updatePolicyTerm_Not_Found() throws Exception { + // given + SavePolicyTernDto savePolicyTernDto = + SavePolicyTernDto.builder().content("meaningless").build(); + doThrow(NotFoundException.class).when(policyTermService).updatePolicyTerm(any(), any()); + + // when + String response = + mvc.perform( + put("/policy/{policyTermId}", 1L) + .contentType(MediaType.APPLICATION_JSON) + .content(jsonOf(savePolicyTernDto))) + .andExpect(status().isNotFound()) + .andReturn() + .getResponse() + .getContentAsString(StandardCharsets.UTF_8); + + // then + assertThat(response).contains(NOT_FOUND.getMessage()); + } +} diff --git a/resource-server/src/test/java/com/inhabas/api/web/SignUpControllerTest.java b/resource-server/src/test/java/com/inhabas/api/web/SignUpControllerTest.java index 4cf4dac6..5105a118 100644 --- a/resource-server/src/test/java/com/inhabas/api/web/SignUpControllerTest.java +++ b/resource-server/src/test/java/com/inhabas/api/web/SignUpControllerTest.java @@ -1,5 +1,25 @@ package com.inhabas.api.web; +import static com.inhabas.api.auth.domain.error.ErrorCode.INVALID_INPUT_VALUE; +import static com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.MemberType.PROFESSOR; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; + import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.inhabas.api.auth.domain.oauth2.majorInfo.dto.MajorInfoDto; @@ -13,302 +33,319 @@ import com.inhabas.api.domain.signUp.dto.SignUpDto; import com.inhabas.api.domain.signUp.usecase.SignUpService; import com.inhabas.testAnnotataion.NoSecureWebMvcTest; + import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.http.MediaType; -import org.springframework.test.web.servlet.MockMvc; - -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; - -import static com.inhabas.api.auth.domain.error.ErrorCode.INVALID_INPUT_VALUE; -import static com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.MemberType.PROFESSOR; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.BDDMockito.given; -import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @NoSecureWebMvcTest(SignUpController.class) public class SignUpControllerTest { - @Autowired - private MockMvc mvc; - - @Autowired - private ObjectMapper objectMapper; - - @MockBean - private SignUpService signUpService; - - - private String jsonOf(Object response) throws JsonProcessingException { - return objectMapper.writeValueAsString(response); - } - - @DisplayName("요청을 보낸 사용자가 회원가입을 했는지 확인한다.") - @Test - public void 사용자가_회원가입을_했는지_확인한다() throws Exception { - //given - Map check = Collections.singletonMap("check", true); - given(signUpService.isSignedUp(any())).willReturn(true); - - //when - String response = mvc.perform(get("/signUp/check")) - .andExpect(status().isOk()) - .andReturn() - .getResponse() - .getContentAsString(StandardCharsets.UTF_8); - - //then - assertThat(response).isEqualTo(jsonOf(check)); - - } - - @DisplayName("임시 저장했던 개인정보를 불러온다.") - @Test - public void 임시저장했던_개인정보를_불러온다() throws Exception { - //given - SignUpDto expectedSavedForm = SignUpDto.builder() - .name("홍길동") - .major("의예과") - .phoneNumber("010-1234-5678") - .studentId("12121212") - .memberType(MemberType.UNDERGRADUATE) - .grade(1) - .build(); - - given(signUpService.loadSignUpForm(any())).willReturn(expectedSavedForm); - - //when - String response = mvc.perform(get("/signUp")) - .andExpect(status().isOk()) - .andReturn() - .getResponse() - .getContentAsString(StandardCharsets.UTF_8); - - //then - assertThat(response).isEqualTo(jsonOf(expectedSavedForm)); - - } - - @DisplayName("학생 회원가입 도중 개인정보를 저장한다.") - @Test - public void 학생_회원가입_도중_개인정보를_저장한다() throws Exception { - //given - SignUpDto signUpForm = SignUpDto.builder() - .name("유동현") - .major("컴퓨터공학과") - .phoneNumber("010-0000-1111") - .studentId("11112222") - .memberType(MemberType.UNDERGRADUATE) - .build(); - - mvc.perform(post("/signUp") - .with(csrf()) - .contentType(MediaType.APPLICATION_JSON) - .content(jsonOf(signUpForm))) - .andExpect(status().isNoContent()) - .andReturn(); - } - - @DisplayName("학생 개인정보를 빈칸으로 제출하면 안된다.") - @Test - public void 학생_개인정보를_빈칸으로_제출하면_안된다() throws Exception { - //given - SignUpDto signUpForm = SignUpDto.builder() - .name("") - .major("") - .phoneNumber("") - .studentId(null) - .memberType(null) - .build(); - - String response = mvc.perform(post("/signUp") - .with(csrf()) - .contentType(MediaType.APPLICATION_JSON) - .content(jsonOf(signUpForm))) - .andExpect(status().isBadRequest()) - .andReturn() - .getResponse().getContentAsString(StandardCharsets.UTF_8); - - assertThat(response).contains(INVALID_INPUT_VALUE.getMessage()); - - } - - @DisplayName("학생 개인정보 입력값이 정해진 범위를 초과하면 안된다.") - @Test - public void 학생_개인정보_입력값이_정해진_범위를_초과하면_안된다() throws Exception { - //given - SignUpDto signUpForm = SignUpDto.builder() - .name("홍길동만세".repeat(10) + ".") // 50자까지만 가능 - .major("금융데이터처리, 블록체인학과.") // 50자가지만 가능 - .phoneNumber("8210-1111-1111") // ^(010)-\d{4}-\d{4}$ - .studentId("123123123") - .memberType(MemberType.UNDERGRADUATE) - .build(); - - String response = mvc.perform(post("/signUp") - .with(csrf()) - .contentType(MediaType.APPLICATION_JSON) - .content(jsonOf(signUpForm))) - .andExpect(status().isBadRequest()) - .andReturn() - .getResponse().getContentAsString(StandardCharsets.UTF_8); - - assertThat(response).contains(INVALID_INPUT_VALUE.getMessage()); - - } - - @DisplayName("교수 회원가입 도중 개인정보를 저장한다.") - @Test - public void 교수_회원가입_도중_개인정보를_저장한다() throws Exception { - //given - SignUpDto signUpForm = SignUpDto.builder() - .name("유동현") - .major("컴퓨터공학과") - .phoneNumber("010-0000-1111") - .studentId("12121212") - .memberType(PROFESSOR) - .build(); - - mvc.perform(post("/signUp") - .with(csrf()) - .contentType(MediaType.APPLICATION_JSON) - .content(jsonOf(signUpForm))) - .andExpect(status().isNoContent()) - .andReturn(); - } - - - @DisplayName("회원가입에 필요한 전공정보를 모두 가져온다.") - @Test - public void 회원가입에_필요한_전공정보를_모두_가져온다() throws Exception { - //given - MajorInfoDto majorInfo1 = new MajorInfoDto(1, "공과대학", "기계공학과"); - MajorInfoDto majorInfo2 = new MajorInfoDto(2, "자연과학대학", "수학과"); - MajorInfoDto majorInfo3 = new MajorInfoDto(3, "경영대학", "경영학과"); - List majorInfos = new ArrayList<>() {{ + @Autowired private MockMvc mvc; + + @Autowired private ObjectMapper objectMapper; + + @MockBean private SignUpService signUpService; + + private String jsonOf(Object response) throws JsonProcessingException { + return objectMapper.writeValueAsString(response); + } + + @DisplayName("요청을 보낸 사용자가 회원가입을 했는지 확인한다.") + @Test + public void 사용자가_회원가입을_했는지_확인한다() throws Exception { + // given + Map check = Collections.singletonMap("check", true); + given(signUpService.isSignedUp(any())).willReturn(true); + + // when + String response = + mvc.perform(get("/signUp/check")) + .andExpect(status().isOk()) + .andReturn() + .getResponse() + .getContentAsString(StandardCharsets.UTF_8); + + // then + assertThat(response).isEqualTo(jsonOf(check)); + } + + @DisplayName("임시 저장했던 개인정보를 불러온다.") + @Test + public void 임시저장했던_개인정보를_불러온다() throws Exception { + // given + SignUpDto expectedSavedForm = + SignUpDto.builder() + .name("홍길동") + .major("의예과") + .phoneNumber("010-1234-5678") + .studentId("12121212") + .memberType(MemberType.UNDERGRADUATE) + .grade(1) + .build(); + + given(signUpService.loadSignUpForm(any())).willReturn(expectedSavedForm); + + // when + String response = + mvc.perform(get("/signUp")) + .andExpect(status().isOk()) + .andReturn() + .getResponse() + .getContentAsString(StandardCharsets.UTF_8); + + // then + assertThat(response).isEqualTo(jsonOf(expectedSavedForm)); + } + + @DisplayName("학생 회원가입 도중 개인정보를 저장한다.") + @Test + public void 학생_회원가입_도중_개인정보를_저장한다() throws Exception { + // given + SignUpDto signUpForm = + SignUpDto.builder() + .name("유동현") + .major("컴퓨터공학과") + .phoneNumber("010-0000-1111") + .studentId("11112222") + .memberType(MemberType.UNDERGRADUATE) + .build(); + + mvc.perform( + post("/signUp") + .with(csrf()) + .contentType(MediaType.APPLICATION_JSON) + .content(jsonOf(signUpForm))) + .andExpect(status().isNoContent()) + .andReturn(); + } + + @DisplayName("학생 개인정보를 빈칸으로 제출하면 안된다.") + @Test + public void 학생_개인정보를_빈칸으로_제출하면_안된다() throws Exception { + // given + SignUpDto signUpForm = + SignUpDto.builder() + .name("") + .major("") + .phoneNumber("") + .studentId(null) + .memberType(null) + .build(); + + String response = + mvc.perform( + post("/signUp") + .with(csrf()) + .contentType(MediaType.APPLICATION_JSON) + .content(jsonOf(signUpForm))) + .andExpect(status().isBadRequest()) + .andReturn() + .getResponse() + .getContentAsString(StandardCharsets.UTF_8); + + assertThat(response).contains(INVALID_INPUT_VALUE.getMessage()); + } + + @DisplayName("학생 개인정보 입력값이 정해진 범위를 초과하면 안된다.") + @Test + public void 학생_개인정보_입력값이_정해진_범위를_초과하면_안된다() throws Exception { + // given + SignUpDto signUpForm = + SignUpDto.builder() + .name("홍길동만세".repeat(10) + ".") // 50자까지만 가능 + .major("금융데이터처리, 블록체인학과.") // 50자가지만 가능 + .phoneNumber("8210-1111-1111") // ^(010)-\d{4}-\d{4}$ + .studentId("123123123") + .memberType(MemberType.UNDERGRADUATE) + .build(); + + String response = + mvc.perform( + post("/signUp") + .with(csrf()) + .contentType(MediaType.APPLICATION_JSON) + .content(jsonOf(signUpForm))) + .andExpect(status().isBadRequest()) + .andReturn() + .getResponse() + .getContentAsString(StandardCharsets.UTF_8); + + assertThat(response).contains(INVALID_INPUT_VALUE.getMessage()); + } + + @DisplayName("교수 회원가입 도중 개인정보를 저장한다.") + @Test + public void 교수_회원가입_도중_개인정보를_저장한다() throws Exception { + // given + SignUpDto signUpForm = + SignUpDto.builder() + .name("유동현") + .major("컴퓨터공학과") + .phoneNumber("010-0000-1111") + .studentId("12121212") + .memberType(PROFESSOR) + .build(); + + mvc.perform( + post("/signUp") + .with(csrf()) + .contentType(MediaType.APPLICATION_JSON) + .content(jsonOf(signUpForm))) + .andExpect(status().isNoContent()) + .andReturn(); + } + + @DisplayName("회원가입에 필요한 전공정보를 모두 가져온다.") + @Test + public void 회원가입에_필요한_전공정보를_모두_가져온다() throws Exception { + // given + MajorInfoDto majorInfo1 = new MajorInfoDto(1, "공과대학", "기계공학과"); + MajorInfoDto majorInfo2 = new MajorInfoDto(2, "자연과학대학", "수학과"); + MajorInfoDto majorInfo3 = new MajorInfoDto(3, "경영대학", "경영학과"); + List majorInfos = + new ArrayList<>() { + { add(majorInfo1); add(majorInfo2); add(majorInfo3); - }}; - given(signUpService.getMajorInfo()).willReturn(majorInfos); - - //when - String response = mvc.perform(get("/signUp/majorInfo")) - .andExpect(status().isOk()) - .andReturn() - .getResponse() - .getContentAsString(StandardCharsets.UTF_8); - - //then - assertThat(response).isEqualTo(jsonOf(majorInfos)); - } - - @DisplayName("회원가입에 필요한 질문들을 가져온다.") - @Test - public void 회원가입에_필요한_질문들을_가져온다() throws Exception { - //given - ArrayList questionnaireInDatabase = new ArrayList<>(){{ + } + }; + given(signUpService.getMajorInfo()).willReturn(majorInfos); + + // when + String response = + mvc.perform(get("/signUp/majorInfo")) + .andExpect(status().isOk()) + .andReturn() + .getResponse() + .getContentAsString(StandardCharsets.UTF_8); + + // then + assertThat(response).isEqualTo(jsonOf(majorInfos)); + } + + @DisplayName("회원가입에 필요한 질문들을 가져온다.") + @Test + public void 회원가입에_필요한_질문들을_가져온다() throws Exception { + // given + ArrayList questionnaireInDatabase = + new ArrayList<>() { + { add(new QuestionnaireDto(1L, "지원동기 및 목표를 기술해주세요.")); add(new QuestionnaireDto(2L, "프로그래밍 관련 언어를 다루어 본 적이 있다면 적어주세요.")); add(new QuestionnaireDto(3L, "빅데이터 관련 활동 혹은 공모전 관련 경험이 있다면 적어주세요.")); add(new QuestionnaireDto(4L, "추후 희망하는 진로가 무엇이며, 동아리 활동이 진로에 어떠한 영향을 줄 것이라고 생각하나요?")); add(new QuestionnaireDto(5L, "어떤 경로로 IBAS를 알게 되셨나요?")); - }}; - given(signUpService.getQuestionnaire()).willReturn(questionnaireInDatabase); - - //when - String response = mvc.perform(get("/signUp/questionnaires")) - .andExpect(status().isOk()) - .andReturn() - .getResponse() - .getContentAsString(StandardCharsets.UTF_8); - - //then - assertThat(response).isEqualTo(jsonOf(questionnaireInDatabase)); - } - - @DisplayName("임시저장했던 답변을 가져온다.") - @Test - public void 임시저장했던_답변을_가져온다() throws Exception { - //given - ArrayList savedDTOs = new ArrayList<>() {{ + } + }; + given(signUpService.getQuestionnaire()).willReturn(questionnaireInDatabase); + + // when + String response = + mvc.perform(get("/signUp/questionnaires")) + .andExpect(status().isOk()) + .andReturn() + .getResponse() + .getContentAsString(StandardCharsets.UTF_8); + + // then + assertThat(response).isEqualTo(jsonOf(questionnaireInDatabase)); + } + + @DisplayName("임시저장했던 답변을 가져온다.") + @Test + public void 임시저장했던_답변을_가져온다() throws Exception { + // given + ArrayList savedDTOs = + new ArrayList<>() { + { add(new AnswerDto(1L, "저는 꼭 이 동아리에 입부하고 싶습니다.")); add(new AnswerDto(2L, "어렸을적부터 빅데이터를 발가락으로 전처리하며 놀았습니다.")); add(new AnswerDto(3L, "외주를 받아 진행했던 적이 있는데, 아주 잘 되어 스타트업 창업을 진행했습니다.")); add(new AnswerDto(4L, "이 동아리에 입부한다면, 말하는 대로 코딩해주는 인공지능 모델을 개발하고 싶습니다.")); - }}; - given(signUpService.getAnswers(any())).willReturn(savedDTOs); - - //when - String response = mvc.perform(get("/signUp/answers")) - .andExpect(status().isOk()) - .andReturn() - .getResponse() - .getContentAsString(StandardCharsets.UTF_8); - - //then - assertThat(response).isEqualTo(jsonOf(savedDTOs)); - } - - @DisplayName("회원가입을 위한 답변을 저장한다.") - @Test - public void 회원가입을_위한_답변을_저장한다() throws Exception { - //given - Member member = MemberTest.signingUpMemberAfterProfile(); - ArrayList questionnaires = new ArrayList<>() {{ + } + }; + given(signUpService.getAnswers(any())).willReturn(savedDTOs); + + // when + String response = + mvc.perform(get("/signUp/answers")) + .andExpect(status().isOk()) + .andReturn() + .getResponse() + .getContentAsString(StandardCharsets.UTF_8); + + // then + assertThat(response).isEqualTo(jsonOf(savedDTOs)); + } + + @DisplayName("회원가입을 위한 답변을 저장한다.") + @Test + public void 회원가입을_위한_답변을_저장한다() throws Exception { + // given + Member member = MemberTest.signingUpMemberAfterProfile(); + ArrayList questionnaires = + new ArrayList<>() { + { add(new Questionnaire(1L, "질문 1")); add(new Questionnaire(2L, "질문 2")); add(new Questionnaire(3L, "질문 3")); - }}; + } + }; - ArrayList submittedAnswers = new ArrayList<>() {{ + ArrayList submittedAnswers = + new ArrayList<>() { + { add(new Answer(member, questionnaires.get(0), "저는 꼭 이 동아리에 입부하고 싶습니다.")); add(new Answer(member, questionnaires.get(1), "어렸을적부터 빅데이터를 발가락으로 전처리하며 놀았습니다.")); - add(new Answer(member, questionnaires.get(2), "외주를 받아 진행했던 적이 있는데, 아주 잘 되어 스타트업 창업을 진행했습니다.")); - }}; - - //when then - mvc.perform(post("/signUp/answers") - .with(csrf()) - .contentType(MediaType.APPLICATION_JSON) - .content(jsonOf(submittedAnswers))) - .andExpect(status().isOk()) - .andReturn(); - } - - @DisplayName("회원가입을 완료처리한다.") - @Test - public void 회원가입을_완료처리한다() throws Exception { - //given - Member member = MemberTest.signingUpMemberAfterProfile(); - ArrayList questionnaires = new ArrayList<>() {{ + add( + new Answer( + member, questionnaires.get(2), "외주를 받아 진행했던 적이 있는데, 아주 잘 되어 스타트업 창업을 진행했습니다.")); + } + }; + + // when then + mvc.perform( + post("/signUp/answers") + .with(csrf()) + .contentType(MediaType.APPLICATION_JSON) + .content(jsonOf(submittedAnswers))) + .andExpect(status().isOk()) + .andReturn(); + } + + @DisplayName("회원가입을 완료처리한다.") + @Test + public void 회원가입을_완료처리한다() throws Exception { + // given + Member member = MemberTest.signingUpMemberAfterProfile(); + ArrayList questionnaires = + new ArrayList<>() { + { add(new Questionnaire(1L, "질문 1")); add(new Questionnaire(2L, "질문 2")); add(new Questionnaire(3L, "질문 3")); - }}; + } + }; - ArrayList submittedAnswers = new ArrayList<>() {{ + ArrayList submittedAnswers = + new ArrayList<>() { + { add(new Answer(member, questionnaires.get(0), "저는 꼭 이 동아리에 입부하고 싶습니다.")); add(new Answer(member, questionnaires.get(1), "어렸을적부터 빅데이터를 발가락으로 전처리하며 놀았습니다.")); - add(new Answer(member, questionnaires.get(2), "외주를 받아 진행했던 적이 있는데, 아주 잘 되어 스타트업 창업을 진행했습니다.")); - }}; - - //when - mvc.perform(put("/signUp") - .with(csrf()) - .contentType(MediaType.APPLICATION_JSON) - .content(jsonOf(submittedAnswers))) - .andExpect(status().isNoContent()) - .andReturn(); - } - + add( + new Answer( + member, questionnaires.get(2), "외주를 받아 진행했던 적이 있는데, 아주 잘 되어 스타트업 창업을 진행했습니다.")); + } + }; + + // when + mvc.perform( + put("/signUp") + .with(csrf()) + .contentType(MediaType.APPLICATION_JSON) + .content(jsonOf(submittedAnswers))) + .andExpect(status().isNoContent()) + .andReturn(); + } } diff --git a/resource-server/src/test/java/com/inhabas/api/web/SignUpScheduleControllerTest.java b/resource-server/src/test/java/com/inhabas/api/web/SignUpScheduleControllerTest.java index 2a40501f..5d3941b5 100644 --- a/resource-server/src/test/java/com/inhabas/api/web/SignUpScheduleControllerTest.java +++ b/resource-server/src/test/java/com/inhabas/api/web/SignUpScheduleControllerTest.java @@ -1,21 +1,5 @@ package com.inhabas.api.web; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.inhabas.api.auth.domain.error.ErrorCode; -import com.inhabas.api.domain.signUpSchedule.dto.SignUpScheduleDto; -import com.inhabas.api.domain.signUpSchedule.exception.InvalidDateException; -import com.inhabas.api.domain.signUpSchedule.usecase.SignUpScheduler; -import com.inhabas.testAnnotataion.NoSecureWebMvcTest; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.http.MediaType; -import org.springframework.test.web.servlet.MockMvc; - -import java.nio.charset.StandardCharsets; -import java.time.LocalDateTime; - import static com.inhabas.api.auth.domain.error.ErrorCode.INVALID_INPUT_VALUE; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; @@ -26,87 +10,114 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -@NoSecureWebMvcTest(SignUpScheduleController.class) -public class SignUpScheduleControllerTest { +import java.nio.charset.StandardCharsets; +import java.time.LocalDateTime; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; - @Autowired - private ObjectMapper objectMapper; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.inhabas.api.auth.domain.error.ErrorCode; +import com.inhabas.api.domain.signUpSchedule.dto.SignUpScheduleDto; +import com.inhabas.api.domain.signUpSchedule.exception.InvalidDateException; +import com.inhabas.api.domain.signUpSchedule.usecase.SignUpScheduler; +import com.inhabas.testAnnotataion.NoSecureWebMvcTest; - @Autowired - private MockMvc mvc; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; - @MockBean - private SignUpScheduler signUpScheduler; +@NoSecureWebMvcTest(SignUpScheduleController.class) +public class SignUpScheduleControllerTest { - @DisplayName("회원가입 일정을 조회한다.") - @Test - public void getSignUpSchedule() throws Exception { - //given - SignUpScheduleDto existingSchedule = new SignUpScheduleDto(999, - LocalDateTime.of(2022, 1, 1, 0, 0, 0), - LocalDateTime.of(2022, 1, 2, 0, 0, 0), - LocalDateTime.of(2022, 1, 3, 0, 0, 0), - LocalDateTime.of(2022, 1, 4, 0, 0, 0), - LocalDateTime.of(2022, 1, 5, 0, 0, 0)); - given(signUpScheduler.getSchedule()).willReturn(existingSchedule); - - mvc.perform(get("/signUp/schedule")) - .andExpect(status().isOk()) - .andExpect(content().string(objectMapper.writeValueAsString(existingSchedule))); - } - - @DisplayName("회원가입 일정을 수정한다.") - @Test - public void updateSignUpSchedule() throws Exception { - String jsonRequest = objectMapper.writeValueAsString(new SignUpScheduleDto(999, + @Autowired private ObjectMapper objectMapper; + + @Autowired private MockMvc mvc; + + @MockBean private SignUpScheduler signUpScheduler; + + @DisplayName("회원가입 일정을 조회한다.") + @Test + public void getSignUpSchedule() throws Exception { + // given + SignUpScheduleDto existingSchedule = + new SignUpScheduleDto( + 999, + LocalDateTime.of(2022, 1, 1, 0, 0, 0), + LocalDateTime.of(2022, 1, 2, 0, 0, 0), + LocalDateTime.of(2022, 1, 3, 0, 0, 0), + LocalDateTime.of(2022, 1, 4, 0, 0, 0), + LocalDateTime.of(2022, 1, 5, 0, 0, 0)); + given(signUpScheduler.getSchedule()).willReturn(existingSchedule); + + mvc.perform(get("/signUp/schedule")) + .andExpect(status().isOk()) + .andExpect(content().string(objectMapper.writeValueAsString(existingSchedule))); + } + + @DisplayName("회원가입 일정을 수정한다.") + @Test + public void updateSignUpSchedule() throws Exception { + String jsonRequest = + objectMapper.writeValueAsString( + new SignUpScheduleDto( + 999, LocalDateTime.of(2022, 1, 1, 0, 0, 0), LocalDateTime.of(2022, 1, 2, 0, 0, 0), LocalDateTime.of(2022, 1, 3, 0, 0, 0), LocalDateTime.of(2022, 1, 4, 0, 0, 0), LocalDateTime.of(2022, 1, 5, 0, 0, 0))); - mvc.perform(put("/signUp/schedule") - .contentType(MediaType.APPLICATION_JSON) - .content(jsonRequest)) - .andExpect(status().isNoContent()); - } - - @DisplayName("회원 기수가 양의 정수가 아닌경우, 400") - @Test - public void invalidGenerationTest() throws Exception { - String jsonRequest = objectMapper.writeValueAsString(new SignUpScheduleDto(0, + mvc.perform( + put("/signUp/schedule").contentType(MediaType.APPLICATION_JSON).content(jsonRequest)) + .andExpect(status().isNoContent()); + } + + @DisplayName("회원 기수가 양의 정수가 아닌경우, 400") + @Test + public void invalidGenerationTest() throws Exception { + String jsonRequest = + objectMapper.writeValueAsString( + new SignUpScheduleDto( + 0, LocalDateTime.of(2022, 1, 1, 0, 0, 0), LocalDateTime.of(2022, 1, 2, 0, 0, 0), LocalDateTime.of(2022, 1, 3, 0, 0, 0), LocalDateTime.of(2022, 1, 4, 0, 0, 0), LocalDateTime.of(2022, 1, 5, 0, 0, 0))); - String response = mvc.perform(put("/signUp/schedule") - .contentType(MediaType.APPLICATION_JSON) - .content(jsonRequest)) - .andExpect(status().isBadRequest()) - .andReturn().getResponse() - .getContentAsString(StandardCharsets.UTF_8); - - assertThat(response).contains(INVALID_INPUT_VALUE.getMessage()); - - } - - @DisplayName("날짜가 잘못된 경우, 400") - @Test - public void invalidDateInfoTest() throws Exception { - doThrow(new InvalidDateException(ErrorCode.INVALID_SIGNUP_DATE)).when(signUpScheduler).updateSchedule(any()); - String jsonRequest = objectMapper.writeValueAsString(new SignUpScheduleDto(999, + String response = + mvc.perform( + put("/signUp/schedule") + .contentType(MediaType.APPLICATION_JSON) + .content(jsonRequest)) + .andExpect(status().isBadRequest()) + .andReturn() + .getResponse() + .getContentAsString(StandardCharsets.UTF_8); + + assertThat(response).contains(INVALID_INPUT_VALUE.getMessage()); + } + + @DisplayName("날짜가 잘못된 경우, 400") + @Test + public void invalidDateInfoTest() throws Exception { + doThrow(new InvalidDateException(ErrorCode.INVALID_SIGNUP_DATE)) + .when(signUpScheduler) + .updateSchedule(any()); + String jsonRequest = + objectMapper.writeValueAsString( + new SignUpScheduleDto( + 999, LocalDateTime.of(2022, 1, 5, 0, 0, 0), LocalDateTime.of(2022, 1, 4, 0, 0, 0), LocalDateTime.of(2022, 1, 3, 0, 0, 0), LocalDateTime.of(2022, 1, 2, 0, 0, 0), LocalDateTime.of(2022, 1, 1, 0, 0, 0))); - mvc.perform(put("/signUp/schedule") - .contentType(MediaType.APPLICATION_JSON) - .content(jsonRequest)) - .andExpect(status().isBadRequest()); - } - + mvc.perform( + put("/signUp/schedule").contentType(MediaType.APPLICATION_JSON).content(jsonRequest)) + .andExpect(status().isBadRequest()); + } } diff --git a/resource-server/src/test/java/com/inhabas/api/web/argumentResolver/ArgumentResolverTest.java b/resource-server/src/test/java/com/inhabas/api/web/argumentResolver/ArgumentResolverTest.java index d6bf097b..07acdace 100644 --- a/resource-server/src/test/java/com/inhabas/api/web/argumentResolver/ArgumentResolverTest.java +++ b/resource-server/src/test/java/com/inhabas/api/web/argumentResolver/ArgumentResolverTest.java @@ -1,72 +1,72 @@ package com.inhabas.api.web.argumentResolver; -import com.inhabas.api.auth.domain.token.jwtUtils.JwtAuthenticationToken; -import org.assertj.core.api.Assertions; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.List; + import org.springframework.core.MethodParameter; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.web.context.request.NativeWebRequest; -import java.util.List; +import com.inhabas.api.auth.domain.token.jwtUtils.JwtAuthenticationToken; +import org.assertj.core.api.Assertions; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; -import static org.assertj.core.api.Assertions.assertThat; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; @ExtendWith(MockitoExtension.class) public class ArgumentResolverTest { - @Mock - private MethodParameter parameter; - - @Mock - private NativeWebRequest request; - - @InjectMocks - private LoginMemberArgumentResolver loginMemberArgumentResolver; + @Mock private MethodParameter parameter; - @AfterEach - public void clearSecurityContest() { - SecurityContextHolder.clearContext(); - } + @Mock private NativeWebRequest request; + @InjectMocks private LoginMemberArgumentResolver loginMemberArgumentResolver; - @DisplayName("인증이 이루어지지 않았으면, null을 반환한다.") - @Test - public void returnNullIfNotAuthenticated() { - //when - Object invalidUser =loginMemberArgumentResolver.resolveArgument(parameter, null, request, null); + @AfterEach + public void clearSecurityContest() { + SecurityContextHolder.clearContext(); + } - //then - assertThat(invalidUser).isNull(); - } + @DisplayName("인증이 이루어지지 않았으면, null을 반환한다.") + @Test + public void returnNullIfNotAuthenticated() { + // when + Object invalidUser = + loginMemberArgumentResolver.resolveArgument(parameter, null, request, null); - @DisplayName("Jwt 토큰 인증된 회원의 Member Id를 반환한다.") - @Test - public void successToInjectJwtTokenIntegerIdIntoArguments() { - //given - Long memberId = 1L; + // then + assertThat(invalidUser).isNull(); + } - // jwt 토큰 인증 결과 - List grantedAuthorities = List.of(new SimpleGrantedAuthority("ROLE_TEST")); - JwtAuthenticationToken authentication = JwtAuthenticationToken.of(1L, "Nodata", grantedAuthorities); + @DisplayName("Jwt 토큰 인증된 회원의 Member Id를 반환한다.") + @Test + public void successToInjectJwtTokenIntegerIdIntoArguments() { + // given + Long memberId = 1L; - //authentication 객체를 컨텍스트에 설정. 최종 인증 끝 - SecurityContextHolder.getContext().setAuthentication(authentication); + // jwt 토큰 인증 결과 + List grantedAuthorities = + List.of(new SimpleGrantedAuthority("ROLE_TEST")); + JwtAuthenticationToken authentication = + JwtAuthenticationToken.of(1L, "Nodata", grantedAuthorities); - //when - Object profileId = loginMemberArgumentResolver.resolveArgument(parameter, null, request, null); + // authentication 객체를 컨텍스트에 설정. 최종 인증 끝 + SecurityContextHolder.getContext().setAuthentication(authentication); - // then - Assertions.assertThat(profileId).isNotNull(); - Assertions.assertThat(profileId).isEqualTo(memberId); - Assertions.assertThat(profileId).isInstanceOf(Long.class); - } + // when + Object profileId = loginMemberArgumentResolver.resolveArgument(parameter, null, request, null); + // then + Assertions.assertThat(profileId).isNotNull(); + Assertions.assertThat(profileId).isEqualTo(memberId); + Assertions.assertThat(profileId).isInstanceOf(Long.class); + } } diff --git a/resource-server/src/test/java/com/inhabas/api/web/configTest/WebConfigTest.java b/resource-server/src/test/java/com/inhabas/api/web/configTest/WebConfigTest.java index 207aadf6..338838e2 100644 --- a/resource-server/src/test/java/com/inhabas/api/web/configTest/WebConfigTest.java +++ b/resource-server/src/test/java/com/inhabas/api/web/configTest/WebConfigTest.java @@ -1,5 +1,8 @@ package com.inhabas.api.web.configTest; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Import; + import com.fasterxml.jackson.databind.PropertyNamingStrategies; import com.fasterxml.jackson.databind.PropertyNamingStrategy; import com.inhabas.api.config.WebConfig; @@ -7,27 +10,25 @@ import com.inhabas.testConfig.TestEmptyController; import io.swagger.v3.core.jackson.ModelResolver; import org.assertj.core.api.Assertions; + import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Import; @NoSecureWebMvcTest(TestEmptyController.class) @Import(WebConfig.class) public class WebConfigTest { - @Autowired - private ModelResolver modelResolver; + @Autowired private ModelResolver modelResolver; - @DisplayName("swagger 명세로 변환하는 modelResolver 는 LOWER_CAMEL_CASE 를 따른다.") - @Test - public void ModelResolverSnakeCaseTest() { - //when - PropertyNamingStrategy propertyNamingStrategy = modelResolver.objectMapper() - .getPropertyNamingStrategy(); + @DisplayName("swagger 명세로 변환하는 modelResolver 는 LOWER_CAMEL_CASE 를 따른다.") + @Test + public void ModelResolverSnakeCaseTest() { + // when + PropertyNamingStrategy propertyNamingStrategy = + modelResolver.objectMapper().getPropertyNamingStrategy(); - //then - Assertions.assertThat(propertyNamingStrategy) - .isEqualTo(PropertyNamingStrategies.LOWER_CAMEL_CASE); - } + // then + Assertions.assertThat(propertyNamingStrategy) + .isEqualTo(PropertyNamingStrategies.LOWER_CAMEL_CASE); + } } diff --git a/resource-server/src/test/java/com/inhabas/testAnnotataion/CustomSpringBootTest.java b/resource-server/src/test/java/com/inhabas/testAnnotataion/CustomSpringBootTest.java index 783dd82a..b913abe5 100644 --- a/resource-server/src/test/java/com/inhabas/testAnnotataion/CustomSpringBootTest.java +++ b/resource-server/src/test/java/com/inhabas/testAnnotataion/CustomSpringBootTest.java @@ -1,16 +1,17 @@ package com.inhabas.testAnnotataion; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.core.annotation.AliasFor; -import org.springframework.test.context.ActiveProfiles; - -import javax.transaction.Transactional; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import javax.transaction.Transactional; + +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.core.annotation.AliasFor; +import org.springframework.test.context.ActiveProfiles; + @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @ActiveProfiles({"integration_test"}) @@ -19,6 +20,6 @@ @SpringBootTest public @interface CustomSpringBootTest { - @AliasFor(annotation = SpringBootTest.class, attribute = "classes") - Class[] classes() default {}; + @AliasFor(annotation = SpringBootTest.class, attribute = "classes") + Class[] classes() default {}; } diff --git a/resource-server/src/test/java/com/inhabas/testAnnotataion/DefaultDataJpaTest.java b/resource-server/src/test/java/com/inhabas/testAnnotataion/DefaultDataJpaTest.java index 4c972b1f..f330c361 100644 --- a/resource-server/src/test/java/com/inhabas/testAnnotataion/DefaultDataJpaTest.java +++ b/resource-server/src/test/java/com/inhabas/testAnnotataion/DefaultDataJpaTest.java @@ -1,27 +1,27 @@ package com.inhabas.testAnnotataion; -import com.inhabas.api.JpaConfig; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; import org.springframework.context.annotation.Import; import org.springframework.test.context.ActiveProfiles; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; +import com.inhabas.api.JpaConfig; /** * - ActiveProfiles("test") 설정이유
- * : WebMvcTest 진행 시 cloud config 적용되어 외부 설정 파일을 읽어들이려고 시도함. - * bootstrap.yml 에 test 환경을 따로 명시하여, 테스트 진행 시에는 바로 테스트를 진행하도록 설정. - * 또 SecurityFilterChain 을 활성화하게 되면, web 관련 컴포넌트 뿐 아니라 연관된 의존성을 모두 불러와야 하므로, - * test 환경을 명시하여 security 관련 설정을 읽어오지 못하게 하는 역할. (default FilterChain이 사용됨.)

+ * : WebMvcTest 진행 시 cloud config 적용되어 외부 설정 파일을 읽어들이려고 시도함. bootstrap.yml 에 test 환경을 따로 명시하여, 테스트 + * 진행 시에는 바로 테스트를 진행하도록 설정. 또 SecurityFilterChain 을 활성화하게 되면, web 관련 컴포넌트 뿐 아니라 연관된 의존성을 모두 불러와야 + * 하므로, test 환경을 명시하여 security 관련 설정을 읽어오지 못하게 하는 역할. (default FilterChain이 사용됨.)
+ *
* - Import(JpaConfig.class) 설정이유
- * : QueryDsl 을 사용하기 위해 JPAQueryFactory 를 빈으로 등록하고 주입해야한다. - * 하지만 JPAQueryFactory 는 DataJpaTest 에 의해 자동 주입되지 않는다. - * DataJpaTest 는 spring-boot-start-data 패키지에 포함된 jpa 관련 컴포넌트만 가져온다. - * QueryDsl 은 다른 패키지에 속해있다. 따라서 JPAQueryFactory 를 수동으로 가져오기 위한 작업이다. + * : QueryDsl 을 사용하기 위해 JPAQueryFactory 를 빈으로 등록하고 주입해야한다. 하지만 JPAQueryFactory 는 DataJpaTest 에 의해 자동 + * 주입되지 않는다. DataJpaTest 는 spring-boot-start-data 패키지에 포함된 jpa 관련 컴포넌트만 가져온다. QueryDsl 은 다른 패키지에 + * 속해있다. 따라서 JPAQueryFactory 를 수동으로 가져오기 위한 작업이다. */ @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @@ -29,5 +29,4 @@ @ActiveProfiles("test") @Import(JpaConfig.class) @AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) -public @interface DefaultDataJpaTest { -} +public @interface DefaultDataJpaTest {} diff --git a/resource-server/src/test/java/com/inhabas/testAnnotataion/DefaultWebMvcTest.java b/resource-server/src/test/java/com/inhabas/testAnnotataion/DefaultWebMvcTest.java index 1d4311b6..32899d83 100644 --- a/resource-server/src/test/java/com/inhabas/testAnnotataion/DefaultWebMvcTest.java +++ b/resource-server/src/test/java/com/inhabas/testAnnotataion/DefaultWebMvcTest.java @@ -1,35 +1,38 @@ package com.inhabas.testAnnotataion; -import com.inhabas.api.auth.AuthBeansConfig; -import com.inhabas.api.auth.domain.oauth2.member.security.DefaultRoleHierarchy; -import com.inhabas.api.config.WebSecurityConfig; -import com.inhabas.testConfig.TestConfigurationForSecurity; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; + import org.springframework.boot.autoconfigure.security.oauth2.client.servlet.OAuth2ClientAutoConfiguration; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.context.annotation.Import; import org.springframework.core.annotation.AliasFor; import org.springframework.test.context.ActiveProfiles; +import com.inhabas.api.auth.domain.oauth2.member.security.DefaultRoleHierarchy; +import com.inhabas.testConfig.TestConfigurationForSecurity; + /** * - ActiveProfiles("test") 설정이유
- * : WebMvcTest 진행 시 cloud config 적용되어 외부 설정 파일을 읽어들이려고 시도함. - * bootstrap.yml 에 test 환경을 따로 명시하여, 테스트 진행 시에는 바로 테스트를 진행하도록 설정. - * 또 SecurityFilterChain 을 활성화하게 되면, web 관련 컴포넌트 뿐 아니라 연관된 의존성을 모두 불러와야 하므로, - * test 환경을 명시하여 security 관련 설정을 읽어오지 못하게 하는 역할. (default FilterChain이 사용됨.)

+ * : WebMvcTest 진행 시 cloud config 적용되어 외부 설정 파일을 읽어들이려고 시도함. bootstrap.yml 에 test 환경을 따로 명시하여, 테스트 + * 진행 시에는 바로 테스트를 진행하도록 설정. 또 SecurityFilterChain 을 활성화하게 되면, web 관련 컴포넌트 뿐 아니라 연관된 의존성을 모두 불러와야 + * 하므로, test 환경을 명시하여 security 관련 설정을 읽어오지 못하게 하는 역할. (default FilterChain이 사용됨.)
+ *
*/ @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @ActiveProfiles("test") // for disable cloud config & security filter chain -@WebMvcTest(excludeAutoConfiguration = {OAuth2ClientAutoConfiguration.class}) // disable autoload OAuth2-Client-Components from test properties +@WebMvcTest( + excludeAutoConfiguration = { + OAuth2ClientAutoConfiguration.class + }) // disable autoload OAuth2-Client-Components from test properties @Import({DefaultRoleHierarchy.class, TestConfigurationForSecurity.class}) public @interface DefaultWebMvcTest { - @AliasFor(annotation = WebMvcTest.class, attribute = "value") - Class[] value() default {}; + @AliasFor(annotation = WebMvcTest.class, attribute = "value") + Class[] value() default {}; - @AliasFor(annotation = WebMvcTest.class, attribute = "controllers") - Class[] controllers() default {}; + @AliasFor(annotation = WebMvcTest.class, attribute = "controllers") + Class[] controllers() default {}; } diff --git a/resource-server/src/test/java/com/inhabas/testAnnotataion/NoSecureWebMvcTest.java b/resource-server/src/test/java/com/inhabas/testAnnotataion/NoSecureWebMvcTest.java index d4deeb0d..34b43e62 100644 --- a/resource-server/src/test/java/com/inhabas/testAnnotataion/NoSecureWebMvcTest.java +++ b/resource-server/src/test/java/com/inhabas/testAnnotataion/NoSecureWebMvcTest.java @@ -1,10 +1,10 @@ package com.inhabas.testAnnotataion; -import com.inhabas.testConfig.InterceptorConfigMockBean; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; + import org.springframework.boot.autoconfigure.security.oauth2.client.servlet.OAuth2ClientAutoConfiguration; import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; @@ -12,22 +12,29 @@ import org.springframework.core.annotation.AliasFor; import org.springframework.test.context.ActiveProfiles; +import com.inhabas.testConfig.InterceptorConfigMockBean; + /** - * WebMvcTest(excludeAutoConfiguration = {SecurityAutoConfiguration.class, OAuth2ClientAutoConfiguration.class}) , - * default security filter 를 사용하지 않음. 테스트 설정 파일에서 OAuth2Client 정보를 읽어들이지 않음. + * WebMvcTest(excludeAutoConfiguration = {SecurityAutoConfiguration.class, + * OAuth2ClientAutoConfiguration.class}) , default security filter 를 사용하지 않음. 테스트 설정 파일에서 + * OAuth2Client 정보를 읽어들이지 않음. * * @see DefaultWebMvcTest */ @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @ActiveProfiles("no_security_mvc_test") // for disable cloud config & security filter chain -@WebMvcTest(excludeAutoConfiguration = {SecurityAutoConfiguration.class, OAuth2ClientAutoConfiguration.class}) // disable default spring-security configuration +@WebMvcTest( + excludeAutoConfiguration = { + SecurityAutoConfiguration.class, + OAuth2ClientAutoConfiguration.class + }) // disable default spring-security configuration @Import(InterceptorConfigMockBean.class) public @interface NoSecureWebMvcTest { - @AliasFor(annotation = WebMvcTest.class, attribute = "value") - Class[] value() default {}; + @AliasFor(annotation = WebMvcTest.class, attribute = "value") + Class[] value() default {}; - @AliasFor(annotation = WebMvcTest.class, attribute = "controllers") - Class[] controllers() default {}; + @AliasFor(annotation = WebMvcTest.class, attribute = "controllers") + Class[] controllers() default {}; } diff --git a/resource-server/src/test/java/com/inhabas/testAnnotataion/WithMockCustomOAuth2Account.java b/resource-server/src/test/java/com/inhabas/testAnnotataion/WithMockCustomOAuth2Account.java index f6be6472..625eb2d0 100644 --- a/resource-server/src/test/java/com/inhabas/testAnnotataion/WithMockCustomOAuth2Account.java +++ b/resource-server/src/test/java/com/inhabas/testAnnotataion/WithMockCustomOAuth2Account.java @@ -1,34 +1,35 @@ package com.inhabas.testAnnotataion; -import org.springframework.security.test.context.support.WithSecurityContext; - import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import org.springframework.security.test.context.support.WithSecurityContext; + /** * OAuth2 인증 결과를 securityContext 에 담아두기 위한 test 용 annotation.
* OAuth2 인증 후의 어떤 특정한 상황을 Mocking 하고 싶을 때 사용한다. + * * @see WithMockCustomOAuth2AccountSecurityContextFactory */ @Retention(RetentionPolicy.RUNTIME) @WithSecurityContext(factory = WithMockCustomOAuth2AccountSecurityContextFactory.class) public @interface WithMockCustomOAuth2Account { - String name() default "username"; + String name() default "username"; - String role() default "USER"; + String role() default "USER"; - String email() default "my@default.email"; + String email() default "my@default.email"; - String picture() default "https://get_my_picture.com"; + String picture() default "https://get_my_picture.com"; - String provider() default "google"; + String provider() default "google"; - int authUserId() default 1; + int authUserId() default 1; - boolean alreadyJoined() default true; + boolean alreadyJoined() default true; - boolean isActive() default true; + boolean isActive() default true; - int profileId() default 0; + int profileId() default 0; } diff --git a/resource-server/src/test/java/com/inhabas/testAnnotataion/WithMockCustomOAuth2AccountSecurityContextFactory.java b/resource-server/src/test/java/com/inhabas/testAnnotataion/WithMockCustomOAuth2AccountSecurityContextFactory.java index b15bc6da..bb0a7425 100644 --- a/resource-server/src/test/java/com/inhabas/testAnnotataion/WithMockCustomOAuth2AccountSecurityContextFactory.java +++ b/resource-server/src/test/java/com/inhabas/testAnnotataion/WithMockCustomOAuth2AccountSecurityContextFactory.java @@ -1,51 +1,52 @@ package com.inhabas.testAnnotataion; -import org.apache.commons.lang3.NotImplementedException; +import java.util.HashMap; + import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.test.context.support.WithSecurityContextFactory; -import java.util.HashMap; - +import org.apache.commons.lang3.NotImplementedException; /** * WithMockCustomOAuth2Account 어노테이션 정보를 기반으로 SecurityContext 를 설정한다. + * * @see WithMockCustomOAuth2Account */ public class WithMockCustomOAuth2AccountSecurityContextFactory implements WithSecurityContextFactory { - @Override - public SecurityContext createSecurityContext(WithMockCustomOAuth2Account customOAuth2Account) { - - SecurityContext context = SecurityContextHolder.createEmptyContext(); - - HashMap attributes = new HashMap<>(); - attributes.put("username", customOAuth2Account.name()); - attributes.put("email", customOAuth2Account.email()); - attributes.put("picture", customOAuth2Account.picture()); - attributes.put("role", customOAuth2Account.role()); - - throw new NotImplementedException("로그인 다시 구현해야함"); -// CustomOAuth2User principal = new CustomOAuth2User( -// List.of(new SimpleGrantedAuthority(customOAuth2Account.role())), -// attributes, -// "email", -// AuthUserDetail.builder() -// .id(customOAuth2Account.authUserId()) -// .email(customOAuth2Account.email()) -// .provider(customOAuth2Account.provider()) -// .profileId(customOAuth2Account.profileId()) -// .hasJoined(customOAuth2Account.alreadyJoined()) -// .isActive(customOAuth2Account.isActive()) -// .build()); -// -// OAuth2AuthenticationToken token = new OAuth2AuthenticationToken( -// principal, -// principal.getAuthorities(), -// customOAuth2Account.provider()); -// -// context.setAuthentication(token); -// return context; - } + @Override + public SecurityContext createSecurityContext(WithMockCustomOAuth2Account customOAuth2Account) { + + SecurityContext context = SecurityContextHolder.createEmptyContext(); + + HashMap attributes = new HashMap<>(); + attributes.put("username", customOAuth2Account.name()); + attributes.put("email", customOAuth2Account.email()); + attributes.put("picture", customOAuth2Account.picture()); + attributes.put("role", customOAuth2Account.role()); + + throw new NotImplementedException("로그인 다시 구현해야함"); + // CustomOAuth2User principal = new CustomOAuth2User( + // List.of(new SimpleGrantedAuthority(customOAuth2Account.role())), + // attributes, + // "email", + // AuthUserDetail.builder() + // .id(customOAuth2Account.authUserId()) + // .email(customOAuth2Account.email()) + // .provider(customOAuth2Account.provider()) + // .profileId(customOAuth2Account.profileId()) + // .hasJoined(customOAuth2Account.alreadyJoined()) + // .isActive(customOAuth2Account.isActive()) + // .build()); + // + // OAuth2AuthenticationToken token = new OAuth2AuthenticationToken( + // principal, + // principal.getAuthorities(), + // customOAuth2Account.provider()); + // + // context.setAuthentication(token); + // return context; + } } diff --git a/resource-server/src/test/java/com/inhabas/testAnnotataion/WithMockJwtAuthenticationToken.java b/resource-server/src/test/java/com/inhabas/testAnnotataion/WithMockJwtAuthenticationToken.java index 2866c17d..d8e47ddc 100644 --- a/resource-server/src/test/java/com/inhabas/testAnnotataion/WithMockJwtAuthenticationToken.java +++ b/resource-server/src/test/java/com/inhabas/testAnnotataion/WithMockJwtAuthenticationToken.java @@ -1,22 +1,24 @@ package com.inhabas.testAnnotataion; -import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.Role; -import org.springframework.security.test.context.support.WithSecurityContext; - import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import org.springframework.security.test.context.support.WithSecurityContext; + +import com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.Role; + /** - * Jwt 인증 결과를 securityContext 에 담아두기 위한 test 용 annotation. - * Jwt 인증 후의 어떤 특정한 상황을 Mocking 하고 싶을 때 사용한다.
+ * Jwt 인증 결과를 securityContext 에 담아두기 위한 test 용 annotation. Jwt 인증 후의 어떤 특정한 상황을 Mocking 하고 싶을 때 + * 사용한다.
* - memberId 가 default 이면 AuthUser 와 매핑되는 Member 는 null 이다. + * * @see WithMockJwtAuthenticationTokenSecurityContextFactory */ @Retention(RetentionPolicy.RUNTIME) @WithSecurityContext(factory = WithMockJwtAuthenticationTokenSecurityContextFactory.class) public @interface WithMockJwtAuthenticationToken { - long memberId() default 1L; - Role memberRole() default Role.BASIC; + long memberId() default 1L; + Role memberRole() default Role.BASIC; } diff --git a/resource-server/src/test/java/com/inhabas/testAnnotataion/WithMockJwtAuthenticationTokenSecurityContextFactory.java b/resource-server/src/test/java/com/inhabas/testAnnotataion/WithMockJwtAuthenticationTokenSecurityContextFactory.java index 7277f989..6e362f07 100644 --- a/resource-server/src/test/java/com/inhabas/testAnnotataion/WithMockJwtAuthenticationTokenSecurityContextFactory.java +++ b/resource-server/src/test/java/com/inhabas/testAnnotataion/WithMockJwtAuthenticationTokenSecurityContextFactory.java @@ -1,35 +1,37 @@ package com.inhabas.testAnnotataion; -import com.inhabas.api.auth.domain.token.jwtUtils.JwtAuthenticationToken; +import java.util.List; + import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.test.context.support.WithSecurityContextFactory; -import java.util.List; +import com.inhabas.api.auth.domain.token.jwtUtils.JwtAuthenticationToken; /** * WithMockJwtAuthenticationToken 어노테이션 정보를 기반으로 SecurityContext 를 설정한다.
* - memberId 가 default 이면 AuthUser 와 매핑되는 Member 는 null 이다. + * * @see WithMockJwtAuthenticationToken */ public class WithMockJwtAuthenticationTokenSecurityContextFactory - implements WithSecurityContextFactory { - - @Override - public SecurityContext createSecurityContext(WithMockJwtAuthenticationToken principalInfo) { + implements WithSecurityContextFactory { - SecurityContext context = SecurityContextHolder.createEmptyContext(); + @Override + public SecurityContext createSecurityContext(WithMockJwtAuthenticationToken principalInfo) { - Long memberId = principalInfo.memberId(); - String role = principalInfo.memberRole().toString(); // 기본은 BASIC. - List grantedAuthorities = List.of(new SimpleGrantedAuthority(role)); + SecurityContext context = SecurityContextHolder.createEmptyContext(); - JwtAuthenticationToken authentication = JwtAuthenticationToken.of(memberId, "TEST", grantedAuthorities); + Long memberId = principalInfo.memberId(); + String role = principalInfo.memberRole().toString(); // 기본은 BASIC. + List grantedAuthorities = List.of(new SimpleGrantedAuthority(role)); - context.setAuthentication(authentication); - return context; + JwtAuthenticationToken authentication = + JwtAuthenticationToken.of(memberId, "TEST", grantedAuthorities); - } + context.setAuthentication(authentication); + return context; + } } diff --git a/resource-server/src/test/java/com/inhabas/testConfig/InterceptorConfigMockBean.java b/resource-server/src/test/java/com/inhabas/testConfig/InterceptorConfigMockBean.java index 2601ffcc..8bb59ae8 100644 --- a/resource-server/src/test/java/com/inhabas/testConfig/InterceptorConfigMockBean.java +++ b/resource-server/src/test/java/com/inhabas/testConfig/InterceptorConfigMockBean.java @@ -1,12 +1,12 @@ package com.inhabas.testConfig; -import com.inhabas.api.web.interceptor.InterceptorConfig; import org.springframework.boot.test.context.TestConfiguration; import org.springframework.boot.test.mock.mockito.MockBean; +import com.inhabas.api.web.interceptor.InterceptorConfig; + @TestConfiguration public class InterceptorConfigMockBean { - @MockBean - public InterceptorConfig interceptorConfig; + @MockBean public InterceptorConfig interceptorConfig; } diff --git a/resource-server/src/test/java/com/inhabas/testConfig/TestConfigurationForSecurity.java b/resource-server/src/test/java/com/inhabas/testConfig/TestConfigurationForSecurity.java index a7eb94f0..ef169b31 100644 --- a/resource-server/src/test/java/com/inhabas/testConfig/TestConfigurationForSecurity.java +++ b/resource-server/src/test/java/com/inhabas/testConfig/TestConfigurationForSecurity.java @@ -1,5 +1,15 @@ package com.inhabas.testConfig; +import java.util.ArrayList; +import java.util.List; + +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.Bean; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.web.util.matcher.AndRequestMatcher; +import org.springframework.security.web.util.matcher.RequestMatcher; + import com.inhabas.api.auth.AuthBeansConfig; import com.inhabas.api.auth.domain.token.CustomRequestMatcher; import com.inhabas.api.auth.domain.token.JwtAccessDeniedHandler; @@ -8,49 +18,30 @@ import com.inhabas.api.auth.domain.token.securityFilter.JwtAuthenticationEntryPoint; import com.inhabas.api.auth.domain.token.securityFilter.JwtAuthenticationFilter; import com.inhabas.api.web.interceptor.InterceptorConfig; -import org.springframework.boot.test.context.TestConfiguration; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.context.annotation.Bean; -import org.springframework.security.authentication.AuthenticationManager; -import org.springframework.security.web.util.matcher.AndRequestMatcher; -import org.springframework.security.web.util.matcher.RequestMatcher; - -import java.util.ArrayList; -import java.util.List; @TestConfiguration public class TestConfigurationForSecurity { - @MockBean - InterceptorConfig interceptorConfig; - @MockBean - JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint; - @MockBean - JwtAccessDeniedHandler jwtAccessDeniedHandler; - @MockBean - JwtTokenUtil jwtTokenUtil; - @MockBean - JwtAuthenticationProvider jwtAuthenticationProvider; - @MockBean - AuthBeansConfig authBeansConfig; + @MockBean InterceptorConfig interceptorConfig; + @MockBean JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint; + @MockBean JwtAccessDeniedHandler jwtAccessDeniedHandler; + @MockBean JwtTokenUtil jwtTokenUtil; + @MockBean JwtAuthenticationProvider jwtAuthenticationProvider; + @MockBean AuthBeansConfig authBeansConfig; - @MockBean - private AuthenticationManager authenticationManager; + @MockBean private AuthenticationManager authenticationManager; - @Bean - public JwtAuthenticationFilter jwtAuthenticationFilter() throws Exception { - final List skipPaths = new ArrayList<>(); - skipPaths.add(new CustomRequestMatcher("/**", "GET")); - skipPaths.add(new CustomRequestMatcher("/**", "POST")); - skipPaths.add(new CustomRequestMatcher("/**", "DELETE")); - skipPaths.add(new CustomRequestMatcher("/**", "PUT")); - final RequestMatcher requestMatcher = new AndRequestMatcher(skipPaths); - final JwtAuthenticationFilter filter = new JwtAuthenticationFilter( - requestMatcher, - jwtTokenUtil, - authBeansConfig.tokenResolver() - ); - filter.setAuthenticationManager(authenticationManager); - return filter; - } + @Bean + public JwtAuthenticationFilter jwtAuthenticationFilter() throws Exception { + final List skipPaths = new ArrayList<>(); + skipPaths.add(new CustomRequestMatcher("/**", "GET")); + skipPaths.add(new CustomRequestMatcher("/**", "POST")); + skipPaths.add(new CustomRequestMatcher("/**", "DELETE")); + skipPaths.add(new CustomRequestMatcher("/**", "PUT")); + final RequestMatcher requestMatcher = new AndRequestMatcher(skipPaths); + final JwtAuthenticationFilter filter = + new JwtAuthenticationFilter(requestMatcher, jwtTokenUtil, authBeansConfig.tokenResolver()); + filter.setAuthenticationManager(authenticationManager); + return filter; + } } diff --git a/resource-server/src/test/java/com/inhabas/testConfig/TestEmptyController.java b/resource-server/src/test/java/com/inhabas/testConfig/TestEmptyController.java index e2900c49..28480d10 100644 --- a/resource-server/src/test/java/com/inhabas/testConfig/TestEmptyController.java +++ b/resource-server/src/test/java/com/inhabas/testConfig/TestEmptyController.java @@ -3,6 +3,4 @@ import org.springframework.web.bind.annotation.RestController; @RestController -public class TestEmptyController { - -} +public class TestEmptyController {}