diff --git a/.github/workflows/cd-dev.yml b/.github/workflows/cd-dev.yml index 7ccad43f..c680cad2 100644 --- a/.github/workflows/cd-dev.yml +++ b/.github/workflows/cd-dev.yml @@ -55,7 +55,6 @@ jobs: - name: πŸ“ Copy Files from S3 env: REGION: ${{ secrets.AWS_REGION }} - APPLE_KEY_NAME: ${{ secrets.APPLE_KEY_NAME }} S3_BUCKET: ${{ secrets.AWS_BUCKET_NAME }} run: | aws s3 cp --region $REGION \ @@ -67,8 +66,6 @@ jobs: aws s3 cp --region $REGION \ s3://$S3_BUCKET/dev/dev.env ./application.env - aws s3 cp --region $REGION \ - s3://$S3_BUCKET/dev/static/$APPLE_KEY ./$APPLE_KEY_NAME - name: πŸ”„ Transfer Files to Server uses: appleboy/scp-action@master @@ -77,7 +74,7 @@ jobs: username: ubuntu key: ${{ secrets.PEM_KEY_DEV }} port: 22 - source: "deploy.sh,switch.sh,valid.sh,application.env,${{ secrets.APPLE_KEY_NAME }}" + source: "deploy.sh,switch.sh,valid.sh,application.env" target: /home/ubuntu/deploy-temp/op - name: πŸš€SSH command deploy @@ -96,13 +93,11 @@ jobs: sudo mv /home/ubuntu/deploy-temp/op/switch.sh /home/ubuntu/script/op/switch.sh sudo mv /home/ubuntu/deploy-temp/op/valid.sh /home/ubuntu/script/op/valid.sh sudo mv /home/ubuntu/deploy-temp/op/application.env /home/ubuntu/env/op/application.env - sudo mv /home/ubuntu/deploy-temp/op/${{ secrets.APPLE_KEY_NAME }} /home/ubuntu/property/op/key/${{ secrets.APPLE_KEY_NAME }} sudo chmod +x /home/ubuntu/script/op/deploy.sh sudo chmod +x /home/ubuntu/script/op/switch.sh sudo chmod +x /home/ubuntu/script/op/valid.sh sudo chmod +r /home/ubuntu/env/op/application.env - sudo chmod +r /home/ubuntu/property/op/key/${{ secrets.APPLE_KEY }} /home/ubuntu/script/op/deploy.sh /home/ubuntu/script/op/switch.sh diff --git a/operation-api/src/main/java/org/sopt/makers/operation/auth/api/AuthApi.java b/operation-api/src/main/java/org/sopt/makers/operation/auth/api/AuthApi.java deleted file mode 100644 index 2b6846f5..00000000 --- a/operation-api/src/main/java/org/sopt/makers/operation/auth/api/AuthApi.java +++ /dev/null @@ -1,84 +0,0 @@ -package org.sopt.makers.operation.auth.api; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.security.SecurityRequirement; -import io.swagger.v3.oas.annotations.tags.Tag; -import org.sopt.makers.operation.auth.dto.request.AccessTokenRequest; -import org.sopt.makers.operation.dto.BaseResponse; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.RequestParam; - -@Tag(name = "SSO 기반 인증 κ΄€λ ¨ API") -public interface AuthApi { - - @Operation( - security = @SecurityRequirement(name = "Authorization"), - summary = "ν”Œλž«νΌ μΈκ°€μ½”λ“œ λ°˜ν™˜ API", - responses = { - @ApiResponse( - responseCode = "200", - description = "ν”Œλž«νΌ μΈκ°€μ½”λ“œ λ°˜ν™˜ 성곡" - ), - @ApiResponse( - responseCode = "400", - description = """ - 1. 쿼리 νŒŒλΌλ―Έν„° 쀑 데이터가 λ“€μ–΄μ˜€μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€.\n - 2. μœ νš¨ν•˜μ§€ μ•Šμ€ social type μž…λ‹ˆλ‹€.\n - 3. μœ νš¨ν•˜μ§€ μ•Šμ€ id token μž…λ‹ˆλ‹€.\n - 4. μœ νš¨ν•˜μ§€ μ•Šμ€ social code μž…λ‹ˆλ‹€. - """ - ), - @ApiResponse( - responseCode = "404", - description = """ - 1. λ“±λ‘λ˜μ§€ μ•Šμ€ νŒ€μž…λ‹ˆλ‹€.\n - 2. λ“±λ‘λœ μ†Œμ…œ 정보가 μ—†μŠ΅λ‹ˆλ‹€. - """ - ), - @ApiResponse( - responseCode = "500", - description = "μ„œλ²„ λ‚΄λΆ€ 였λ₯˜" - ) - } - ) - ResponseEntity> authorize( - @RequestParam String type, - @RequestParam String code, - @RequestParam String clientId, - @RequestParam String redirectUri - ); - - @Operation( - security = @SecurityRequirement(name = "Authorization"), - summary = "인증 토큰 λ°œκΈ‰ API", - responses = { - @ApiResponse( - responseCode = "200", - description = "토큰 λ°œκΈ‰ 성곡" - ), - @ApiResponse( - responseCode = "400", - description = """ - 1. grantType 데이터가 λ“€μ–΄μ˜€μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€.\n - 2. μœ νš¨ν•˜μ§€ μ•Šμ€ grantType μž…λ‹ˆλ‹€.\n - 3. ν”Œλž«νΌ μΈκ°€μ½”λ“œκ°€ λ“€μ–΄μ˜€μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€.\n - 4. 이미 μ‚¬μš©ν•œ ν”Œλž«νΌ μΈκ°€μ½”λ“œμž…λ‹ˆλ‹€.\n - 5. λ¦¬ν”„λ ˆμ‰¬ 토큰이 λ“€μ–΄μ˜€μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€. - """ - ), - @ApiResponse( - responseCode = "401", - description = """ - 1. 만료된 ν”Œλž«νΌ 인가 μ½”λ“œμž…λ‹ˆλ‹€.\n - 2. 만료된 λ¦¬ν”„λ ˆμ‰¬ ν† ν°μž…λ‹ˆλ‹€. - """ - ), - @ApiResponse( - responseCode = "500", - description = "μ„œλ²„ λ‚΄λΆ€ 였λ₯˜" - ) - } - ) - ResponseEntity> token(AccessTokenRequest accessTokenRequest); -} diff --git a/operation-api/src/main/java/org/sopt/makers/operation/auth/api/AuthApiController.java b/operation-api/src/main/java/org/sopt/makers/operation/auth/api/AuthApiController.java deleted file mode 100644 index 5bb181ab..00000000 --- a/operation-api/src/main/java/org/sopt/makers/operation/auth/api/AuthApiController.java +++ /dev/null @@ -1,138 +0,0 @@ -package org.sopt.makers.operation.auth.api; - -import static org.sopt.makers.operation.code.failure.auth.AuthFailureCode.EXPIRED_PLATFORM_CODE; -import static org.sopt.makers.operation.code.failure.auth.AuthFailureCode.EXPIRED_REFRESH_TOKEN; -import static org.sopt.makers.operation.code.failure.auth.AuthFailureCode.INVALID_GRANT_TYPE; -import static org.sopt.makers.operation.code.failure.auth.AuthFailureCode.INVALID_SOCIAL_TYPE; -import static org.sopt.makers.operation.code.failure.auth.AuthFailureCode.NOT_FOUNT_REGISTERED_TEAM; -import static org.sopt.makers.operation.code.failure.auth.AuthFailureCode.NOT_NULL_CODE; -import static org.sopt.makers.operation.code.failure.auth.AuthFailureCode.NOT_NULL_GRANT_TYPE; -import static org.sopt.makers.operation.code.failure.auth.AuthFailureCode.NOT_NULL_REFRESH_TOKEN; -import static org.sopt.makers.operation.code.failure.auth.AuthFailureCode.USED_PLATFORM_CODE; -import static org.sopt.makers.operation.code.success.auth.AuthSuccessCode.SUCCESS_GENERATE_TOKEN; -import static org.sopt.makers.operation.code.success.auth.AuthSuccessCode.SUCCESS_RETURN_REDIRECT_URL_WITH_PLATFORM_CODE; -import static org.sopt.makers.operation.jwt.JwtTokenType.PLATFORM_CODE; -import static org.sopt.makers.operation.jwt.JwtTokenType.REFRESH_TOKEN; - -import java.util.concurrent.ConcurrentHashMap; -import lombok.RequiredArgsConstructor; -import lombok.val; -import org.sopt.makers.operation.auth.dto.request.AccessTokenRequest; -import org.sopt.makers.operation.auth.dto.response.RedirectUrlResponse; -import org.sopt.makers.operation.auth.dto.response.TokenResponse; -import org.sopt.makers.operation.auth.service.AuthService; -import org.sopt.makers.operation.dto.BaseResponse; -import org.sopt.makers.operation.exception.AuthException; -import org.sopt.makers.operation.jwt.JwtTokenProvider; -import org.sopt.makers.operation.user.domain.SocialType; -import org.sopt.makers.operation.util.ApiResponseUtil; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.security.core.Authentication; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; - -@RestController -@RequiredArgsConstructor -@RequestMapping("/api/v1/auth") -public class AuthApiController implements AuthApi { - - private static final String AUTHORIZATION_CODE_GRANT_TYPE = "authorizationCode"; - private static final String REFRESH_TOKEN_GRANT_TYPE = "refreshToken"; - private static final String REDIRECT_URL_WITH_CODE_FORMAT = "%s?code=%s"; - - private final ConcurrentHashMap tempPlatformCode; - private final AuthService authService; - private final JwtTokenProvider jwtTokenProvider; - - @Override - @GetMapping("/authorize") - public ResponseEntity> authorize( - @RequestParam String type, - @RequestParam String code, - @RequestParam String clientId, - @RequestParam String redirectUri - ) { - if (!authService.checkRegisteredTeamOAuthInfo(clientId, redirectUri)) { - throw new AuthException(NOT_FOUNT_REGISTERED_TEAM); - } - if (!SocialType.isContains(type)) { - throw new AuthException(INVALID_SOCIAL_TYPE); - } - - val userId = findUserIdBySocialTypeAndCode(type, code); - val platformCode = generatePlatformCode(clientId, redirectUri, userId); - val redirectUrl = String.format(REDIRECT_URL_WITH_CODE_FORMAT, redirectUri, platformCode); - return ApiResponseUtil.success(SUCCESS_RETURN_REDIRECT_URL_WITH_PLATFORM_CODE, new RedirectUrlResponse(redirectUrl)); - } - - @Override - @PostMapping( - path = "/token", - consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE - ) - public ResponseEntity> token(AccessTokenRequest accessTokenRequest) { - if (accessTokenRequest.isNullGrantType()) { - throw new AuthException(NOT_NULL_GRANT_TYPE); - } - - val grantType = accessTokenRequest.grantType(); - if (!(grantType.equals(AUTHORIZATION_CODE_GRANT_TYPE) || grantType.equals(REFRESH_TOKEN_GRANT_TYPE))) { - throw new AuthException(INVALID_GRANT_TYPE); - } - - val tokenResponse = grantType.equals(AUTHORIZATION_CODE_GRANT_TYPE) ? - generateTokenResponseByAuthorizationCode(accessTokenRequest) : generateTokenResponseByRefreshToken(accessTokenRequest); - return ApiResponseUtil.success(SUCCESS_GENERATE_TOKEN, tokenResponse); - } - - private TokenResponse generateTokenResponseByAuthorizationCode(AccessTokenRequest accessTokenRequest) { - if (accessTokenRequest.isNullCode()) { - throw new AuthException(NOT_NULL_CODE); - } - if (!tempPlatformCode.contains(accessTokenRequest.code())) { - throw new AuthException(USED_PLATFORM_CODE); - } - tempPlatformCode.remove(accessTokenRequest.code()); - - if (!jwtTokenProvider.validatePlatformCode(accessTokenRequest.code(), accessTokenRequest.clientId(), accessTokenRequest.redirectUri())) { - throw new AuthException(EXPIRED_PLATFORM_CODE); - } - - val authentication = jwtTokenProvider.getAuthentication(accessTokenRequest.code(), PLATFORM_CODE); - return generateTokenResponse(authentication); - } - - private TokenResponse generateTokenResponseByRefreshToken(AccessTokenRequest accessTokenRequest) { - if (accessTokenRequest.isNullRefreshToken()) { - throw new AuthException(NOT_NULL_REFRESH_TOKEN); - } - if (!jwtTokenProvider.validateTokenExpiration(accessTokenRequest.refreshToken(), REFRESH_TOKEN)) { - throw new AuthException(EXPIRED_REFRESH_TOKEN); - } - - val authentication = jwtTokenProvider.getAuthentication(accessTokenRequest.refreshToken(), REFRESH_TOKEN); - return generateTokenResponse(authentication); - } - - private TokenResponse generateTokenResponse(Authentication authentication) { - val accessToken = jwtTokenProvider.generateAccessToken(authentication); - val refreshToken = jwtTokenProvider.generateRefreshToken(authentication); - return TokenResponse.of(accessToken, refreshToken); - } - - private Long findUserIdBySocialTypeAndCode(String type, String code) { - val socialType = SocialType.valueOf(type); - val userSocialId = authService.getSocialUserInfo(socialType, code); - return authService.getUserId(socialType, userSocialId); - } - - private String generatePlatformCode(String clientId, String redirectUri, Long userId) { - val platformCode = jwtTokenProvider.generatePlatformCode(clientId, redirectUri, userId); - tempPlatformCode.putIfAbsent(platformCode, platformCode); - return platformCode; - } -} diff --git a/operation-api/src/main/java/org/sopt/makers/operation/auth/dto/request/AccessTokenRequest.java b/operation-api/src/main/java/org/sopt/makers/operation/auth/dto/request/AccessTokenRequest.java deleted file mode 100644 index 045b4365..00000000 --- a/operation-api/src/main/java/org/sopt/makers/operation/auth/dto/request/AccessTokenRequest.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.sopt.makers.operation.auth.dto.request; - -public record AccessTokenRequest( - String grantType, - String clientId, - String redirectUri, - String code, - String refreshToken -) { - public boolean isNullGrantType() { - return grantType == null; - } - - public boolean isNullCode() { - return code == null; - } - - public boolean isNullRefreshToken() { - return refreshToken == null; - } -} diff --git a/operation-api/src/main/java/org/sopt/makers/operation/auth/dto/response/RedirectUrlResponse.java b/operation-api/src/main/java/org/sopt/makers/operation/auth/dto/response/RedirectUrlResponse.java deleted file mode 100644 index c45ffd85..00000000 --- a/operation-api/src/main/java/org/sopt/makers/operation/auth/dto/response/RedirectUrlResponse.java +++ /dev/null @@ -1,4 +0,0 @@ -package org.sopt.makers.operation.auth.dto.response; - -public record RedirectUrlResponse(String redirectUrl) { -} diff --git a/operation-api/src/main/java/org/sopt/makers/operation/auth/dto/response/TokenResponse.java b/operation-api/src/main/java/org/sopt/makers/operation/auth/dto/response/TokenResponse.java deleted file mode 100644 index faeb3436..00000000 --- a/operation-api/src/main/java/org/sopt/makers/operation/auth/dto/response/TokenResponse.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.sopt.makers.operation.auth.dto.response; - -public record TokenResponse(String tokenType, String accessToken, String refreshToken) { - private static final String BEARER_TOKEN_TYPE = "Bearer"; - - public static TokenResponse of(String accessToken, String refreshToken) { - return new TokenResponse(BEARER_TOKEN_TYPE, accessToken, refreshToken); - } -} diff --git a/operation-api/src/main/java/org/sopt/makers/operation/auth/service/AuthService.java b/operation-api/src/main/java/org/sopt/makers/operation/auth/service/AuthService.java deleted file mode 100644 index 0500d42a..00000000 --- a/operation-api/src/main/java/org/sopt/makers/operation/auth/service/AuthService.java +++ /dev/null @@ -1,11 +0,0 @@ -package org.sopt.makers.operation.auth.service; - -import org.sopt.makers.operation.user.domain.SocialType; - -public interface AuthService { - boolean checkRegisteredTeamOAuthInfo(String clientId, String redirectUri); - - String getSocialUserInfo(SocialType type, String code); - - Long getUserId(SocialType socialType, String userSocialId); -} diff --git a/operation-api/src/main/java/org/sopt/makers/operation/auth/service/AuthServiceImpl.java b/operation-api/src/main/java/org/sopt/makers/operation/auth/service/AuthServiceImpl.java deleted file mode 100644 index c5211228..00000000 --- a/operation-api/src/main/java/org/sopt/makers/operation/auth/service/AuthServiceImpl.java +++ /dev/null @@ -1,43 +0,0 @@ -package org.sopt.makers.operation.auth.service; - -import lombok.RequiredArgsConstructor; -import lombok.val; -import org.sopt.makers.operation.auth.repository.TeamOAuthInfoRepository; -import org.sopt.makers.operation.client.social.SocialLoginManager; -import org.sopt.makers.operation.exception.AuthException; -import org.sopt.makers.operation.user.domain.SocialType; -import org.sopt.makers.operation.user.repository.identityinfo.UserIdentityInfoRepository; -import org.springframework.stereotype.Service; - -import static org.sopt.makers.operation.code.failure.auth.AuthFailureCode.INVALID_SOCIAL_CODE; -import static org.sopt.makers.operation.code.failure.auth.AuthFailureCode.NOT_FOUND_USER_SOCIAL_IDENTITY_INFO; - -@Service -@RequiredArgsConstructor -public class AuthServiceImpl implements AuthService { - - private final SocialLoginManager socialLoginManager; - private final TeamOAuthInfoRepository teamOAuthInfoRepository; - private final UserIdentityInfoRepository userIdentityInfoRepository; - - @Override - public boolean checkRegisteredTeamOAuthInfo(String clientId, String redirectUri) { - return teamOAuthInfoRepository.existsByClientIdAndRedirectUri(clientId, redirectUri); - } - - @Override - public String getSocialUserInfo(SocialType type, String code) { - val idToken = socialLoginManager.getIdTokenByCode(type, code); - if (idToken == null) { - throw new AuthException(INVALID_SOCIAL_CODE); - } - return socialLoginManager.getUserInfo(idToken); - } - - @Override - public Long getUserId(SocialType socialType, String userSocialId) { - val userIdentityInfo = userIdentityInfoRepository.findBySocialTypeAndSocialId(socialType, userSocialId) - .orElseThrow(() -> new AuthException(NOT_FOUND_USER_SOCIAL_IDENTITY_INFO)); - return userIdentityInfo.getUserId(); - } -} diff --git a/operation-api/src/main/java/org/sopt/makers/operation/common/config/ConcurrentHashMapConfig.java b/operation-api/src/main/java/org/sopt/makers/operation/common/config/ConcurrentHashMapConfig.java deleted file mode 100644 index d7cc9f6a..00000000 --- a/operation-api/src/main/java/org/sopt/makers/operation/common/config/ConcurrentHashMapConfig.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.sopt.makers.operation.common.config; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -import java.util.concurrent.ConcurrentHashMap; - -@Configuration -public class ConcurrentHashMapConfig { - @Bean - public ConcurrentHashMap registerConcurrentHashMap() { - return new ConcurrentHashMap<>(); - } -} diff --git a/operation-api/src/main/java/org/sopt/makers/operation/common/handler/ErrorHandler.java b/operation-api/src/main/java/org/sopt/makers/operation/common/handler/ErrorHandler.java index c04fb9cd..d0a00f7e 100644 --- a/operation-api/src/main/java/org/sopt/makers/operation/common/handler/ErrorHandler.java +++ b/operation-api/src/main/java/org/sopt/makers/operation/common/handler/ErrorHandler.java @@ -86,12 +86,6 @@ public ResponseEntity> attendanceException(AttendanceException e return ApiResponseUtil.failure(ex.getFailureCode()); } - @ExceptionHandler(AuthException.class) - public ResponseEntity> authException(AuthException ex) { - log.error(ex.getMessage()); - return ApiResponseUtil.failure(ex.getFailureCode()); - } - @ExceptionHandler(PermissionException.class) public ResponseEntity> permissionException(PermissionException ex) { log.error(ex.getMessage()); diff --git a/operation-api/src/main/java/org/sopt/makers/operation/common/util/PermissionValidator.java b/operation-api/src/main/java/org/sopt/makers/operation/common/util/PermissionValidator.java deleted file mode 100644 index 920d6adb..00000000 --- a/operation-api/src/main/java/org/sopt/makers/operation/common/util/PermissionValidator.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.sopt.makers.operation.common.util; - -import lombok.RequiredArgsConstructor; -import lombok.val; - -import org.sopt.makers.operation.code.failure.PermissionFailureCode; -import org.sopt.makers.operation.code.failure.UserFailureCode; -import org.sopt.makers.operation.config.ValueConfig; -import org.sopt.makers.operation.exception.PermissionException; -import org.sopt.makers.operation.exception.UserException; -import org.sopt.makers.operation.user.repository.history.UserGenerationHistoryRepository; - -import org.springframework.context.annotation.Configuration; -import org.springframework.transaction.annotation.Transactional; - -@Configuration -@Transactional(readOnly = true) -@RequiredArgsConstructor -public class PermissionValidator { - - private final ValueConfig valueConfig; - private final UserGenerationHistoryRepository generationHistoryRepository; - - public void validateIsSelf(long requestUserId, long targetUserId) { - if (!checkIsSelf(requestUserId, targetUserId)) { - throw new PermissionException(PermissionFailureCode.NO_PERMISSION_ONLY_SELF); - } - } - - public void validateIsSelfOrExecutive(long requestUserId, long targetUserId) { - if (!checkIsSelf(requestUserId, targetUserId) || !checkIsExecutive(requestUserId)) { - throw new PermissionException(PermissionFailureCode.NO_PERMISSION_ONLY_SELF_INCLUDE_EXECUTIVE); - } - } - - private boolean checkIsSelf(long requesterId, long targetId) { - return requesterId == targetId; - } - - private boolean checkIsExecutive(long requesterId) { - val requesterCurrentHistory = generationHistoryRepository.findAllByUserId(requesterId).stream() - .filter(history -> history.getGeneration() == valueConfig.getGENERATION()) - .findFirst() - .orElseThrow(() -> new UserException(UserFailureCode.NOT_FOUND_HISTORY)); - return requesterCurrentHistory.isExecutive(); - } - -} diff --git a/operation-api/src/main/java/org/sopt/makers/operation/user/api/UserApi.java b/operation-api/src/main/java/org/sopt/makers/operation/user/api/UserApi.java deleted file mode 100644 index c0b8295d..00000000 --- a/operation-api/src/main/java/org/sopt/makers/operation/user/api/UserApi.java +++ /dev/null @@ -1,99 +0,0 @@ -package org.sopt.makers.operation.user.api; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.parameters.RequestBody; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.security.SecurityRequirement; -import lombok.NonNull; -import org.sopt.makers.operation.dto.BaseResponse; -import org.sopt.makers.operation.user.dto.request.UserModifyRequest; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.PathVariable; - -import java.security.Principal; - -public interface UserApi { - - @Operation( - security = @SecurityRequirement(name = "Authorization"), - summary = "본인 μœ μ € 정보 쑰회 API", - responses = { - @ApiResponse( - responseCode = "200", - description = "본인에 λŒ€ν•œ μœ μ € 정보 μ‘°νšŒκ°€ μ„±κ³΅ν•œ 경우" - ), - @ApiResponse( - responseCode = "400", - description = "μš”μ²­μ΄ 잘λͺ»λœ 경우" - ), - @ApiResponse( - responseCode = "404", - description = "ν•΄λ‹Ή 토큰에 λ‹΄κΈ΄ μœ μ € 정보에 ν•΄λ‹Ήν•˜λŠ” 데이터가 μ‘΄μž¬ν•˜μ§€ μ•Šμ€ 경우" - ), - @ApiResponse( - responseCode = "500", - description = "μ„œλ²„ λ‚΄λΆ€ 였λ₯˜κ°€ λ°œμƒν•œ 경우" - ) - } - ) - ResponseEntity> getUserInfoSelf( - @Parameter(hidden = true) @NonNull Principal principal); - - @Operation( - security = @SecurityRequirement(name = "Authorization"), - summary = "볡수 μœ μ € 정보 쑰회 API", - responses = { - @ApiResponse( - responseCode = "200", - description = "μ˜λ„ν–ˆλ˜ μœ μ € 정보 μ‘°νšŒκ°€ μ„±κ³΅ν•œ 경우" - ), - @ApiResponse( - responseCode = "400", - description = "μš”μ²­μ΄ 잘λͺ»λœ 경우" - ), - @ApiResponse( - responseCode = "404", - description = "쿼리 νŒŒλΌλ―Έν„°μ— λ‹΄κΈ΄ μœ μ € IDλ“€ 쀑 μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ” μœ μ €μ— λŒ€ν•œ IDκ°€ μ‘΄μž¬ν•˜λŠ” 경우" - ), - @ApiResponse( - responseCode = "500", - description = "μ„œλ²„ λ‚΄λΆ€ 였λ₯˜κ°€ λ°œμƒν•œ 경우" - ) - } - ) - ResponseEntity> getUserInfoOf( - @Parameter(hidden = true) @NonNull Principal principal, - @Parameter String targetUserIds); - - @Operation( - security = @SecurityRequirement(name = "Authorization"), - summary = "μœ μ € 정보 μˆ˜μ • API", - responses = { - @ApiResponse( - responseCode = "204", - description = "μœ μ € 정보 μˆ˜μ • μ„±κ³΅ν•œ 경우" - ), - @ApiResponse( - responseCode = "400", - description = """ - μš”μ²­μ΄ 잘λͺ»λœ 경우
- 1. Request DTO λ‚΄ Validation에 μ‹€νŒ¨ν•œ 경우(NotNull/NotEmpty) - 2. μž„μ›μ§„(Position != MEMBER)이 Team 변경을 μš”μ²­ν•œ 경우 - """ - ), - @ApiResponse( - responseCode = "404", - description = "ν•΄λ‹Ή 토큰에 λ‹΄κΈ΄ μœ μ € 정보에 ν•΄λ‹Ήν•˜λŠ” 데이터가 μ‘΄μž¬ν•˜μ§€ μ•Šμ€ 경우" - ), - @ApiResponse( - responseCode = "500", - description = "μ„œλ²„ λ‚΄λΆ€ 였λ₯˜κ°€ λ°œμƒν•œ 경우" - ) - } - ) - ResponseEntity> modifyUserInfoOf( - @Parameter(hidden = true) @NonNull Principal principal, - @PathVariable long userId, - @RequestBody UserModifyRequest userModifyRequest); -} diff --git a/operation-api/src/main/java/org/sopt/makers/operation/user/api/UserApiController.java b/operation-api/src/main/java/org/sopt/makers/operation/user/api/UserApiController.java deleted file mode 100644 index 78f88c6e..00000000 --- a/operation-api/src/main/java/org/sopt/makers/operation/user/api/UserApiController.java +++ /dev/null @@ -1,99 +0,0 @@ -package org.sopt.makers.operation.user.api; - -import jakarta.validation.Valid; -import lombok.val; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; - -import org.sopt.makers.operation.code.failure.UserFailureCode; -import org.sopt.makers.operation.common.util.CommonUtils; -import org.sopt.makers.operation.common.util.PermissionValidator; -import org.sopt.makers.operation.dto.BaseResponse; -import org.sopt.makers.operation.exception.ParameterDecodeCustomException; -import org.sopt.makers.operation.exception.UserException; -import org.sopt.makers.operation.user.dto.request.UserModifyRequest; -import org.sopt.makers.operation.user.service.UserService; -import org.sopt.makers.operation.util.ApiResponseUtil; - -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.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RestController; - -import java.net.URLDecoder; -import java.security.Principal; -import java.util.Arrays; -import java.util.List; -import java.io.UnsupportedEncodingException; -import java.util.Objects; - -import static org.sopt.makers.operation.code.success.UserSuccessCode.SUCCESS_GET_USER; -import static org.sopt.makers.operation.code.success.UserSuccessCode.SUCCESS_GET_USERS; -import static org.sopt.makers.operation.code.success.UserSuccessCode.SUCCESS_PUT_USER; - -@RestController -@RequiredArgsConstructor -@RequestMapping("/api/v1/internal/user") -public class UserApiController implements UserApi { - - private static final String DECODING_CHARSET = "UTF-8"; - private static final String DELIMITER_ID_PARAMETER = ","; - private static final String USER_IDS_PARAMETER_REGEX = "^(\\d+)((%20)*%2C(%20)*\\d+)*$"; - - private final UserService userService; - private final CommonUtils utils; - private final PermissionValidator permissionValidator; - - @Override - @GetMapping("/me") - public ResponseEntity> getUserInfoSelf( - @NonNull Principal principal - ) { - val userId = utils.getMemberId(principal); - val response = userService.getUserInfo(userId); - return ApiResponseUtil.success(SUCCESS_GET_USER, response); - } - - @Override - @GetMapping - public ResponseEntity> getUserInfoOf( - @NonNull Principal principal, - @NonNull @RequestParam("userIds") String targetUserIds - ) { - val userIds = getIdsFromParameter(targetUserIds); - val response = userService.getUserInfos(userIds); - return ApiResponseUtil.success(SUCCESS_GET_USERS, response); - } - - @Override - @PutMapping("/{userId}") - public ResponseEntity> modifyUserInfoOf( - @NonNull Principal principal, - @PathVariable("userId") long userId, - @Valid UserModifyRequest userModifyRequest - ) { - val requesterId = utils.getMemberId(principal); - permissionValidator.validateIsSelfOrExecutive(requesterId, userId); - userService.modifyUserInfo(userId, userModifyRequest); - return ApiResponseUtil.success(SUCCESS_PUT_USER); - } - - private List getIdsFromParameter(String parameter) { - if (Objects.isNull(parameter) || !parameter.matches(USER_IDS_PARAMETER_REGEX)) { - throw new UserException(UserFailureCode.INVALID_PARAMETER); - } - try { - val decodedParameter = URLDecoder.decode(parameter, DECODING_CHARSET); - return Arrays.stream(decodedParameter.split(DELIMITER_ID_PARAMETER)) - .filter(str -> !str.equals(DELIMITER_ID_PARAMETER)) - .map(id -> Long.parseLong(id.trim())) - .toList(); - } catch (UnsupportedEncodingException | NumberFormatException ex) { - throw new ParameterDecodeCustomException(UserFailureCode.INVALID_PARAMETER, parameter); - } - } - -} diff --git a/operation-api/src/main/java/org/sopt/makers/operation/user/dto/request/UserActivityModifyRequest.java b/operation-api/src/main/java/org/sopt/makers/operation/user/dto/request/UserActivityModifyRequest.java deleted file mode 100644 index 24849fd5..00000000 --- a/operation-api/src/main/java/org/sopt/makers/operation/user/dto/request/UserActivityModifyRequest.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.sopt.makers.operation.user.dto.request; - -import jakarta.validation.constraints.NotNull; -import org.sopt.makers.operation.user.domain.Team; -import org.sopt.makers.operation.user.domain.Part; -import org.sopt.makers.operation.user.domain.Position; - -public record UserActivityModifyRequest( - - @NotNull(message = ERROR_MESSAGE_FOR_NOT_NULL) - long activityId, - @NotNull(message = ERROR_MESSAGE_FOR_NOT_NULL) - int generation, - @NotNull(message = ERROR_MESSAGE_FOR_NOT_NULL) - Part part, - Team team, - @NotNull(message = ERROR_MESSAGE_FOR_NOT_NULL) - Position position -) { - private static final String ERROR_MESSAGE_FOR_NOT_NULL = "λŠ” ν•„μˆ˜ κ°’μž…λ‹ˆλ‹€."; -} diff --git a/operation-api/src/main/java/org/sopt/makers/operation/user/dto/request/UserModifyRequest.java b/operation-api/src/main/java/org/sopt/makers/operation/user/dto/request/UserModifyRequest.java deleted file mode 100644 index f7923c42..00000000 --- a/operation-api/src/main/java/org/sopt/makers/operation/user/dto/request/UserModifyRequest.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.sopt.makers.operation.user.dto.request; - -import com.fasterxml.jackson.annotation.JsonProperty; - -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; - -import java.util.List; - -public record UserModifyRequest( - @JsonProperty("name") - @NotNull(message = ERROR_MESSAGE_FOR_NOT_NULL) - String userName, - @JsonProperty("phone") - @NotNull(message = ERROR_MESSAGE_FOR_NOT_NULL) - String userPhone, - @JsonProperty("profileImage") - @NotNull(message = ERROR_MESSAGE_FOR_NOT_NULL) - String userProfileImage, - @JsonProperty("activities") - @NotEmpty(message = ERROR_MESSAGE_FOR_NOT_EMPTY) - List userActivities -) { - private static final String ERROR_MESSAGE_FOR_NOT_NULL = "λŠ” ν•„μˆ˜ κ°’μž…λ‹ˆλ‹€."; - private static final String ERROR_MESSAGE_FOR_NOT_EMPTY = "λŠ” ν•œ 개 이상이어야 ν•©λ‹ˆλ‹€."; -} diff --git a/operation-api/src/main/java/org/sopt/makers/operation/user/dto/response/UserActivityInfoResponse.java b/operation-api/src/main/java/org/sopt/makers/operation/user/dto/response/UserActivityInfoResponse.java deleted file mode 100644 index 0b151aac..00000000 --- a/operation-api/src/main/java/org/sopt/makers/operation/user/dto/response/UserActivityInfoResponse.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.sopt.makers.operation.user.dto.response; - -import lombok.Builder; - -import org.sopt.makers.operation.user.domain.Part; -import org.sopt.makers.operation.user.domain.Team; -import org.sopt.makers.operation.user.domain.Position; -import org.sopt.makers.operation.user.domain.UserGenerationHistory; - -import static lombok.AccessLevel.PRIVATE; - -@Builder(access = PRIVATE) -public record UserActivityInfoResponse( - long id, - int generation, - Part part, - Team team, - Position position -) { - public static UserActivityInfoResponse from(UserGenerationHistory history) { - return UserActivityInfoResponse.builder() - .id(history.getId()) - .generation(history.getGeneration()) - .part(history.getPart()) - .team(history.getTeam()) - .position(history.getPosition()) - .build(); - } -} diff --git a/operation-api/src/main/java/org/sopt/makers/operation/user/dto/response/UserInfoResponse.java b/operation-api/src/main/java/org/sopt/makers/operation/user/dto/response/UserInfoResponse.java deleted file mode 100644 index cddc3997..00000000 --- a/operation-api/src/main/java/org/sopt/makers/operation/user/dto/response/UserInfoResponse.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.sopt.makers.operation.user.dto.response; - -import java.util.List; - -import lombok.val; -import lombok.Builder; - -import org.sopt.makers.operation.user.domain.User; -import org.sopt.makers.operation.user.domain.UserGenerationHistory; - -import static lombok.AccessLevel.PRIVATE; - -@Builder(access = PRIVATE) -public record UserInfoResponse( - Long id, - String name, - String phone, - String profileImage, - List activities -) { - public static UserInfoResponse of(User user, List histories) { - val activities = histories.stream().map(UserActivityInfoResponse::from).toList(); - return UserInfoResponse.builder() - .id(user.getId()) - .name(user.getName()) - .phone(user.getPhone()) - .profileImage(user.getProfileImage()) - .activities(activities) - .build(); - } -} diff --git a/operation-api/src/main/java/org/sopt/makers/operation/user/dto/response/UserInfosResponse.java b/operation-api/src/main/java/org/sopt/makers/operation/user/dto/response/UserInfosResponse.java deleted file mode 100644 index fbf704e6..00000000 --- a/operation-api/src/main/java/org/sopt/makers/operation/user/dto/response/UserInfosResponse.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.sopt.makers.operation.user.dto.response; - -import java.util.List; - -import lombok.Builder; - -import static lombok.AccessLevel.PRIVATE; - -@Builder(access = PRIVATE) -public record UserInfosResponse( - List users -) { - public static UserInfosResponse of(List userInfos) { - return UserInfosResponse.builder() - .users(userInfos) - .build(); - } -} diff --git a/operation-api/src/main/java/org/sopt/makers/operation/user/service/UserService.java b/operation-api/src/main/java/org/sopt/makers/operation/user/service/UserService.java deleted file mode 100644 index 2c9c310f..00000000 --- a/operation-api/src/main/java/org/sopt/makers/operation/user/service/UserService.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.sopt.makers.operation.user.service; - -import java.util.List; - -import org.sopt.makers.operation.user.dto.request.UserModifyRequest; -import org.sopt.makers.operation.user.dto.response.UserInfoResponse; -import org.sopt.makers.operation.user.dto.response.UserInfosResponse; - -public interface UserService { - UserInfoResponse getUserInfo(long userId); - UserInfosResponse getUserInfos(List userIds); - - void modifyUserInfo(long userId, UserModifyRequest userModifyRequest); -} diff --git a/operation-api/src/main/java/org/sopt/makers/operation/user/service/UserServiceImpl.java b/operation-api/src/main/java/org/sopt/makers/operation/user/service/UserServiceImpl.java deleted file mode 100644 index 86a74ddf..00000000 --- a/operation-api/src/main/java/org/sopt/makers/operation/user/service/UserServiceImpl.java +++ /dev/null @@ -1,104 +0,0 @@ -package org.sopt.makers.operation.user.service; - -import java.util.List; -import java.util.Collections; - -import lombok.val; -import lombok.RequiredArgsConstructor; - -import org.sopt.makers.operation.user.dao.UserActivityInfoUpdateDao; -import org.sopt.makers.operation.user.dao.UserPersonalInfoUpdateDao; -import org.sopt.makers.operation.user.domain.User; -import org.sopt.makers.operation.user.domain.UserGenerationHistory; -import org.sopt.makers.operation.user.dto.request.UserActivityModifyRequest; -import org.sopt.makers.operation.user.dto.request.UserModifyRequest; - -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import org.sopt.makers.operation.user.repository.UserRepository; -import org.sopt.makers.operation.user.repository.history.UserGenerationHistoryRepository; -import org.sopt.makers.operation.user.dto.response.UserInfoResponse; -import org.sopt.makers.operation.user.dto.response.UserInfosResponse; - -import org.sopt.makers.operation.code.failure.UserFailureCode; -import org.sopt.makers.operation.exception.UserException; - -@Service -@RequiredArgsConstructor -@Transactional(readOnly = true) -public class UserServiceImpl implements UserService { - - private final UserRepository userRepository; - private final UserGenerationHistoryRepository generationHistoryRepository; - - @Override - public UserInfoResponse getUserInfo(final long userId) { - validateIds(Collections.singletonList(userId)); - val targetUser = userRepository.findUserById(userId); - val histories = generationHistoryRepository.findAllHistoryByUserId(userId); - return UserInfoResponse.of(targetUser, histories); - } - - @Override - public UserInfosResponse getUserInfos(final List userIds) { - validateIds(userIds); - val targetUsers = userRepository.findAllUsersById(userIds); - val userInfoResponses = targetUsers.stream() - .map(this::mergeUserInfoWithHistory).toList(); - return UserInfosResponse.of(userInfoResponses); - } - - @Override - @Transactional - public void modifyUserInfo(final long userId, final UserModifyRequest userModifyRequest) { - val targetUser = userRepository.findUserById(userId); - val userInfoUpdateDao = new UserPersonalInfoUpdateDao( - userModifyRequest.userName(), - userModifyRequest.userPhone(), - userModifyRequest.userProfileImage() - ); - targetUser.updateUserInfo(userInfoUpdateDao); - - modifyUserActivityInfos(userModifyRequest.userActivities()); - } - - private void modifyUserActivityInfos(final List activitiesModifyRequest) { - activitiesModifyRequest.forEach( - activityModifyRequest -> { - val targetActivity = generationHistoryRepository.findHistoryById(activityModifyRequest.activityId()); - validateIsAbleToUpdateActivity(targetActivity, activityModifyRequest); - - val activityInfoUpdateDao = new UserActivityInfoUpdateDao( - activityModifyRequest.team() - ); - targetActivity.updateActivityInfo(activityInfoUpdateDao); - }); - } - - private void validateIsAbleToUpdateActivity( - UserGenerationHistory currentActivity, UserActivityModifyRequest activityModifyRequest - ) { - if (currentActivity.isExecutive() - && !currentActivity.isBelongTeamTo(activityModifyRequest.team()) - ) { - throw new UserException(UserFailureCode.INVALID_USER_MODIFY_ACTIVITY_INFO); - } - } - - private void validateIds(List ids) { - if (ids.isEmpty() || ids.contains(null)) { - throw new UserException(UserFailureCode.INVALID_PARAMETER); - } - val isContainLittleThenOne = ids.stream().anyMatch(id -> id < 1); - if (isContainLittleThenOne) { - throw new UserException(UserFailureCode.INVALID_USER_IN_USER_LIST_PARAMETER); - } - } - - private UserInfoResponse mergeUserInfoWithHistory(User user) { - val histories = generationHistoryRepository.findAllHistoryByUserId(user.getId()); - return UserInfoResponse.of(user, histories); - } - -} diff --git a/operation-api/src/main/resources/application-dev.yml b/operation-api/src/main/resources/application-dev.yml index d20d74b7..6f08b243 100644 --- a/operation-api/src/main/resources/application-dev.yml +++ b/operation-api/src/main/resources/application-dev.yml @@ -61,22 +61,6 @@ springdoc: swagger-ui: path: /swagger-ui.html -oauth: - apple: - aud: ${OAUTH_APPLE_AUD} - sub: ${OAUTH_APPLE_SUB} - key: - id: ${OAUTH_APPLE_KEY_ID} - path: ${OAUTH_APPLE_KEY_PATH} - team: - id: ${OAUTH_APPLE_TEAM_ID} - google: - redirect: - url: ${OAUTH_GOOGLE_REDIRECT_URL} - client: - id: ${OAUTH_GOOGLE_CLIENT_ID} - secret: ${OAUTH_GOOGLE_CLIENT_SECRET} - cloud: aws: credentials: diff --git a/operation-api/src/main/resources/application-test.yml b/operation-api/src/main/resources/application-test.yml index 80d96f6d..bf0d4a4e 100644 --- a/operation-api/src/main/resources/application-test.yml +++ b/operation-api/src/main/resources/application-test.yml @@ -48,22 +48,6 @@ notification: key: test arn: test -oauth: - apple: - aud: test - sub: test - key: - id: test - path: test - team: - id: test - google: - redirect: - url: test - client: - id: test - secret: test - cloud: aws: credentials: diff --git a/operation-api/src/test/java/org/sopt/makers/operation/auth/api/AuthApiControllerTest.java b/operation-api/src/test/java/org/sopt/makers/operation/auth/api/AuthApiControllerTest.java deleted file mode 100644 index 9cc70ff5..00000000 --- a/operation-api/src/test/java/org/sopt/makers/operation/auth/api/AuthApiControllerTest.java +++ /dev/null @@ -1,323 +0,0 @@ -package org.sopt.makers.operation.auth.api; - -import com.fasterxml.jackson.databind.ObjectMapper; -import lombok.val; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.CsvSource; -import org.sopt.makers.operation.auth.service.AuthService; -import org.sopt.makers.operation.authentication.AdminAuthentication; -import org.sopt.makers.operation.common.handler.ErrorHandler; -import org.sopt.makers.operation.jwt.JwtTokenProvider; -import org.sopt.makers.operation.user.domain.SocialType; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration; -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.context.annotation.Import; -import org.springframework.http.MediaType; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.web.servlet.MockMvc; - -import java.util.concurrent.ConcurrentHashMap; - -import static org.mockito.BDDMockito.given; -import static org.sopt.makers.operation.jwt.JwtTokenType.PLATFORM_CODE; -import static org.sopt.makers.operation.jwt.JwtTokenType.REFRESH_TOKEN; -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.result.MockMvcResultMatchers.jsonPath; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -@ContextConfiguration(classes = AuthApiController.class) -@WebMvcTest(controllers = {AuthApiController.class}, excludeAutoConfiguration = {SecurityAutoConfiguration.class}) -@Import({AuthApiController.class, ErrorHandler.class}) -class AuthApiControllerTest { - @MockBean - AuthService authService; - @MockBean - JwtTokenProvider jwtTokenProvider; - @MockBean - ConcurrentHashMap tempPlatformCode; - @Autowired - MockMvc mockMvc; - @Autowired - ObjectMapper objectMapper; - final String authorizeUri = "/api/v1/auth/authorize"; - final String tokenUri = "/api/v1/auth/token"; - - @Nested - @DisplayName("API 톡신 성곡 ν…ŒμŠ€νŠΈ") - class SuccessTest { - @DisplayName("μœ νš¨ν•œ type, code, clientId, redirectUri 값이 듀어왔을 λ•Œ, ν”Œλž«νΌ μΈκ°€μ½”λ“œλ₯Ό λ°˜ν™˜ν•œλ‹€.") - @ParameterizedTest - @CsvSource({ - "APPLE,code,clientId,https://localhost:8080/auth/redirectUri" - }) - void successTest(String type, String code, String clientId, String redirectUri) throws Exception { - // given - given(authService.checkRegisteredTeamOAuthInfo(clientId, redirectUri)).willReturn(true); - val socialType = SocialType.valueOf(type); - given(authService.getSocialUserInfo(socialType, code)).willReturn("123"); - given(authService.getUserId(socialType, "123")).willReturn(1L); - given(jwtTokenProvider.generatePlatformCode(clientId, redirectUri, 1L)).willReturn("Platform Code"); - - // when, then - mockMvc.perform(get(authorizeUri) - .contentType(MediaType.APPLICATION_JSON) - .param("type", type) - .param("code", code) - .param("clientId", clientId) - .param("redirectUri", redirectUri)) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.message").value("ν”Œλž«νΌ μΈκ°€μ½”λ“œλ₯Ό ν¬ν•¨ν•œ redirect url λ°˜ν™˜ 성곡")) - .andExpect(jsonPath("$.data.redirectUrl").value("https://localhost:8080/auth/redirectUri?code=Platform Code")); - } - - @DisplayName("grantType 이 authorizationCode 이고, μœ νš¨ν•œ clientId, redirectUri, code 값이 듀어왔을 λ•Œ, μ•‘μ„ΈμŠ€ 토큰과 λ¦¬ν”„λ ˆμ‹œ 토큰을 λ°œκΈ‰ν•œλ‹€.") - @ParameterizedTest - @CsvSource({ - "authorizationCode,clientId,redirectUri,code" - }) - void tokenByAuthorizationCodeSuccessTest(String grantType, String clientId, String redirectUri, String code) throws Exception { - // given - val authentication = new AdminAuthentication(1L, null, null); - given(jwtTokenProvider.validatePlatformCode(code, clientId, redirectUri)).willReturn(true); - given(jwtTokenProvider.getAuthentication(code, PLATFORM_CODE)).willReturn(authentication); - given(jwtTokenProvider.generateAccessToken(authentication)).willReturn("access token"); - given(jwtTokenProvider.generateRefreshToken(authentication)).willReturn("refresh token"); - given(tempPlatformCode.contains(code)).willReturn(true); - - // when, then - mockMvc.perform(post(tokenUri) - .contentType(MediaType.APPLICATION_FORM_URLENCODED) - .param("grantType", grantType) - .param("clientId", clientId) - .param("redirectUri", redirectUri) - .param("code", code)) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.message").value("토큰 λ°œκΈ‰ 성곡")) - .andExpect(jsonPath("$.data.tokenType").value("Bearer")) - .andExpect(jsonPath("$.data.accessToken").value("access token")) - .andExpect(jsonPath("$.data.refreshToken").value("refresh token")); - } - - @DisplayName("grantType 이 refreshToken 이고, μœ νš¨ν•œ refreshToken 값이 듀어왔을 λ•Œ, μ•‘μ„ΈμŠ€ 토큰과 λ¦¬ν”„λ ˆμ‹œ 토큰을 λ°œκΈ‰ν•œλ‹€.") - @ParameterizedTest - @CsvSource({ - "refreshToken,refreshToken" - }) - void tokenByRefreshTokenSuccessTest(String grantType, String refreshToken) throws Exception { - // given - val authentication = new AdminAuthentication(1L, null, null); - given(jwtTokenProvider.validateTokenExpiration(refreshToken, REFRESH_TOKEN)).willReturn(true); - given(jwtTokenProvider.getAuthentication(refreshToken, REFRESH_TOKEN)).willReturn(authentication); - given(jwtTokenProvider.generateAccessToken(authentication)).willReturn("access token"); - given(jwtTokenProvider.generateRefreshToken(authentication)).willReturn("refresh token"); - - // when, then - mockMvc.perform(post(tokenUri) - .contentType(MediaType.APPLICATION_FORM_URLENCODED) - .param("grantType", grantType) - .param("refreshToken", refreshToken) - ) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.message").value("토큰 λ°œκΈ‰ 성곡")) - .andExpect(jsonPath("$.data.tokenType").value("Bearer")) - .andExpect(jsonPath("$.data.accessToken").value("access token")) - .andExpect(jsonPath("$.data.refreshToken").value("refresh token")); - } - } - - @Nested - @DisplayName("/authorize API 쿼리 νŒŒλΌλ―Έν„° μœ νš¨μ„± 검사 ν…ŒμŠ€νŠΈ") - class QueryParameterValidateTest { - - @DisplayName("type, code, clientId, redirectUri 쀑 ν•˜λ‚˜λΌλ„ null 이 λ“€μ–΄μ˜€λ©΄ 400을 λ°˜ν™˜ν•œλ‹€.") - @ParameterizedTest - @CsvSource({ - ",code,clientId,redirectUri", - "type,,clientId,redirectUri", - "type,code,,redirectUri", - "type,code,clientId," - }) - void validateTest(String type, String code, String clientId, String redirectUri) throws Exception { - // when, then - mockMvc.perform(get(authorizeUri) - .contentType(MediaType.APPLICATION_JSON) - .param("type", type) - .param("code", code) - .param("clientId", clientId) - .param("redirectUri", redirectUri)) - .andExpect(status().isBadRequest()); - } - - @DisplayName("λ“±λ‘λ˜μ§€ μ•Šμ€ clientId, redirectUri 라면 404λ₯Ό λ°˜ν™˜ν•œλ‹€.") - @ParameterizedTest - @CsvSource({ - "type,code,clientId,redirectUri" - }) - void validateTest2(String type, String code, String clientId, String redirectUri) throws Exception { - // given - given(authService.checkRegisteredTeamOAuthInfo(clientId, redirectUri)).willReturn(false); - - // when, then - mockMvc.perform(get(authorizeUri) - .contentType(MediaType.APPLICATION_JSON) - .param("type", type) - .param("code", code) - .param("clientId", clientId) - .param("redirectUri", redirectUri)) - .andExpect(status().isNotFound()) - .andExpect(jsonPath("$.message").value("λ“±λ‘λ˜μ§€ μ•Šμ€ νŒ€μž…λ‹ˆλ‹€.")); - ; - } - - @DisplayName("λ“±λ‘λ˜μ§€ μ•Šμ€ social type 이라면 400을 λ°˜ν™˜ν•œλ‹€.") - @ParameterizedTest - @CsvSource({ - "KAKAO,code,clientId,redirectUri" - }) - void validateTest3(String type, String code, String clientId, String redirectUri) throws Exception { - // given - given(authService.checkRegisteredTeamOAuthInfo(clientId, redirectUri)).willReturn(true); - - // when, then - mockMvc.perform(get(authorizeUri) - .contentType(MediaType.APPLICATION_JSON) - .param("type", type) - .param("code", code) - .param("clientId", clientId) - .param("redirectUri", redirectUri)) - .andExpect(status().isBadRequest()) - .andExpect(jsonPath("$.message").value("μœ νš¨ν•˜μ§€ μ•Šμ€ social type μž…λ‹ˆλ‹€.")); - } - } - - @Nested - @DisplayName("/token API 였λ₯˜ μΌ€μ΄μŠ€ ν…ŒμŠ€νŠΈ") - class TokenAPIErrorCaseTest { - - @DisplayName("grantType 이 null 일 λ•Œ 400 μ—λŸ¬λ₯Ό λ°˜ν™˜ν•œλ‹€.") - @ParameterizedTest - @CsvSource({ - ",clientId,redirectUri,code" - }) - void errorTest(String grantType, String clientId, String redirectUri, String code) throws Exception { - // when, then - mockMvc.perform(post(tokenUri) - .contentType(MediaType.APPLICATION_FORM_URLENCODED) - .param("grantType", grantType) - .param("clientId", clientId) - .param("redirectUri", redirectUri) - .param("code", code)) - .andExpect(status().isBadRequest()) - .andExpect(jsonPath("$.message").value("grantType 데이터가 λ“€μ–΄μ˜€μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€.")); - } - - @DisplayName("grantType 이 authorizationCode λ˜λŠ” refreshToken μ™Έμ˜ 값이 λ“€μ–΄μ˜¨λ‹€λ©΄ 400 μ—λŸ¬λ₯Ό λ°˜ν™˜ν•œλ‹€.") - @ParameterizedTest - @CsvSource({ - "error,clientId,redirectUri,code" - }) - void errorTest2(String grantType, String clientId, String redirectUri, String code) throws Exception { - // when, then - mockMvc.perform(post(tokenUri) - .contentType(MediaType.APPLICATION_FORM_URLENCODED) - .param("grantType", grantType) - .param("clientId", clientId) - .param("redirectUri", redirectUri) - .param("code", code)) - .andExpect(status().isBadRequest()) - .andExpect(jsonPath("$.message").value("μœ νš¨ν•˜μ§€ μ•Šμ€ grantType μž…λ‹ˆλ‹€.")); - } - - @DisplayName("grantType 이 authorizationCode 일 λ•Œ, code κ°’μœΌλ‘œ null 값이 λ“€μ–΄μ˜¨λ‹€λ©΄ 400 μ—λŸ¬λ₯Ό λ°˜ν™˜ν•œλ‹€.") - @ParameterizedTest - @CsvSource({ - "authorizationCode,clientId,redirectUri," - }) - void errorTest3(String grantType, String clientId, String redirectUri, String code) throws Exception { - // when, then - mockMvc.perform(post(tokenUri) - .contentType(MediaType.APPLICATION_FORM_URLENCODED) - .param("grantType", grantType) - .param("clientId", clientId) - .param("redirectUri", redirectUri) - .param("code", code)) - .andExpect(status().isBadRequest()) - .andExpect(jsonPath("$.message").value("ν”Œλž«νΌ μΈκ°€μ½”λ“œκ°€ λ“€μ–΄μ˜€μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€.")); - } - - @DisplayName("grantType 이 authorizationCode 일 λ•Œ, code 값이 hashmap인 tempPlatformCode 내에 μ—†λ‹€λ©΄ 400 μ—λŸ¬λ₯Ό λ°˜ν™˜ν•œλ‹€.") - @ParameterizedTest - @CsvSource({ - "authorizationCode,clientId,redirectUri,code" - }) - void errorTest4(String grantType, String clientId, String redirectUri, String code) throws Exception { - // given - given(tempPlatformCode.contains(code)).willReturn(false); - - // when, then - mockMvc.perform(post(tokenUri) - .contentType(MediaType.APPLICATION_FORM_URLENCODED) - .param("grantType", grantType) - .param("clientId", clientId) - .param("redirectUri", redirectUri) - .param("code", code)) - .andExpect(status().isBadRequest()) - .andExpect(jsonPath("$.message").value("이미 μ‚¬μš©ν•œ ν”Œλž«νΌ μΈκ°€μ½”λ“œμž…λ‹ˆλ‹€.")); - } - - @DisplayName("grantType 이 refreshToken 일 λ•Œ, refreshToken κ°’μœΌλ‘œ null 값이 λ“€μ–΄μ˜¨λ‹€λ©΄ 400 μ—λŸ¬λ₯Ό λ°˜ν™˜ν•œλ‹€.") - @ParameterizedTest - @CsvSource({ - "refreshToken," - }) - void errorTest5(String grantType, String refreshToken) throws Exception { - // when, then - mockMvc.perform(post(tokenUri) - .contentType(MediaType.APPLICATION_FORM_URLENCODED) - .param("grantType", grantType) - .param("refreshToken", refreshToken)) - .andExpect(status().isBadRequest()) - .andExpect(jsonPath("$.message").value("λ¦¬ν”„λ ˆμ‰¬ 토큰이 λ“€μ–΄μ˜€μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€.")); - } - - @DisplayName("grantType 이 authorizationCode 일 λ•Œ, code 값이 λ§Œλ£Œλ˜μ—ˆλ‹€λ©΄ 401 μ—λŸ¬λ₯Ό λ°˜ν™˜ν•œλ‹€.") - @ParameterizedTest - @CsvSource({ - "authorizationCode,clientId,redirectUri,code" - }) - void errorTest6(String grantType, String clientId, String redirectUri, String code) throws Exception { - given(jwtTokenProvider.validatePlatformCode(code, clientId, redirectUri)).willReturn(false); - given(tempPlatformCode.contains(code)).willReturn(true); - // when, then - mockMvc.perform(post(tokenUri) - .contentType(MediaType.APPLICATION_FORM_URLENCODED) - .param("grantType", grantType) - .param("clientId", clientId) - .param("redirectUri", redirectUri) - .param("code", code)) - .andExpect(status().isUnauthorized()) - .andExpect(jsonPath("$.message").value("만료된 ν”Œλž«νΌ μΈκ°€μ½”λ“œμž…λ‹ˆλ‹€.")); - } - - @DisplayName("grantType 이 refreshToken 일 λ•Œ, refreshToken 값이 λ§Œλ£Œλ˜μ—ˆλ‹€λ©΄ 401 μ—λŸ¬λ₯Ό λ°˜ν™˜ν•œλ‹€.") - @ParameterizedTest - @CsvSource({ - "refreshToken,refreshToken" - }) - void errorTest7(String grantType, String refreshToken) throws Exception { - given(jwtTokenProvider.validateTokenExpiration(refreshToken, REFRESH_TOKEN)).willReturn(false); - // when, then - mockMvc.perform(post(tokenUri) - .contentType(MediaType.APPLICATION_FORM_URLENCODED) - .param("grantType", grantType) - .param("refreshToken", refreshToken)) - .andExpect(status().isUnauthorized()) - .andExpect(jsonPath("$.message").value("만료된 λ¦¬ν”„λ ˆμ‰¬ ν† ν°μž…λ‹ˆλ‹€.")); - } - } -} \ No newline at end of file diff --git a/operation-api/src/test/java/org/sopt/makers/operation/auth/service/AuthServiceTest.java b/operation-api/src/test/java/org/sopt/makers/operation/auth/service/AuthServiceTest.java deleted file mode 100644 index 8e26991a..00000000 --- a/operation-api/src/test/java/org/sopt/makers/operation/auth/service/AuthServiceTest.java +++ /dev/null @@ -1,74 +0,0 @@ -package org.sopt.makers.operation.auth.service; - -import lombok.val; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; -import org.sopt.makers.operation.auth.repository.TeamOAuthInfoRepository; -import org.sopt.makers.operation.client.social.SocialLoginManager; -import org.sopt.makers.operation.exception.AuthException; -import org.sopt.makers.operation.user.domain.SocialType; -import org.sopt.makers.operation.user.repository.identityinfo.UserIdentityInfoRepository; - -import java.util.Optional; - -import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; -import static org.mockito.BDDMockito.given; - -@ExtendWith(MockitoExtension.class) -class AuthServiceTest { - @Mock - SocialLoginManager socialLoginManager; - @Mock - TeamOAuthInfoRepository teamOAuthInfoRepository; - @Mock - UserIdentityInfoRepository userIdentityInfoRepository; - - AuthService authService; - - @BeforeEach - void setUp() { - authService = new AuthServiceImpl(socialLoginManager, teamOAuthInfoRepository, userIdentityInfoRepository); - } - - @Nested - @DisplayName("getSocialUserInfo λ©”μ„œλ“œ ν…ŒμŠ€νŠΈ") - class GetSocialUserInfoMethodTest { - @DisplayName("socialLoginManager μœΌλ‘œλΆ€ν„° id token 값을 null 값을 λ°›μ•˜λ‹€λ©΄ AuthException 을 λ°˜ν™˜ν•œλ‹€.") - @Test - void test() { - // given - val socialType = SocialType.APPLE; - val code = "social code"; - given(socialLoginManager.getIdTokenByCode(socialType, code)).willReturn(null); - - // when, then - assertThatThrownBy(() -> authService.getSocialUserInfo(socialType, code)) - .isInstanceOf(AuthException.class) - .hasMessage("[AuthException] : μœ νš¨ν•˜μ§€ μ•Šμ€ social code μž…λ‹ˆλ‹€."); - } - } - - @Nested - @DisplayName("getUserId λ©”μ„œλ“œ ν…ŒμŠ€νŠΈ") - class GetUserIdMethodTest { - @DisplayName("사전에 λ“±λ‘λ˜μ§€ μ•Šμ€ social type, social id κ°€ 듀어왔을 λ•Œ, AuthException 을 λ°˜ν™˜ν•œλ‹€.") - @Test - void test() { - // given - val socialType = SocialType.APPLE; - val userSocialId = "user social id"; - given(userIdentityInfoRepository.findBySocialTypeAndSocialId(socialType, userSocialId)).willReturn(Optional.empty()); - - // when, then - assertThatThrownBy(() -> authService.getUserId(socialType, userSocialId)) - .isInstanceOf(AuthException.class) - .hasMessage("[AuthException] : λ“±λ‘λœ μ†Œμ…œ 정보가 μ—†μŠ΅λ‹ˆλ‹€."); - } - } - -} \ No newline at end of file diff --git a/operation-api/src/test/java/org/sopt/makers/operation/jwt/JwtTokenProviderTest.java b/operation-api/src/test/java/org/sopt/makers/operation/jwt/JwtTokenProviderTest.java deleted file mode 100644 index 035b9cfd..00000000 --- a/operation-api/src/test/java/org/sopt/makers/operation/jwt/JwtTokenProviderTest.java +++ /dev/null @@ -1,99 +0,0 @@ -package org.sopt.makers.operation.jwt; - -import io.jsonwebtoken.Claims; -import io.jsonwebtoken.Jwts; -import lombok.val; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; - -import java.nio.charset.StandardCharsets; -import java.util.Base64; - -import static org.assertj.core.api.AssertionsForClassTypes.assertThat; - -class JwtTokenProviderTest { - final String platformSecretKey = "123456789123456789123456789123456789123456789123456789"; - JwtTokenProvider jwtTokenProvider; - - @BeforeEach - void setUp() { - jwtTokenProvider = new JwtTokenProvider("", "", "", platformSecretKey); - } - - @Nested - @DisplayName("generatePlatformCode λ©”μ„œλ“œ ν…ŒμŠ€νŠΈ") - class GeneratePlatformCodeMethodTest { - - @DisplayName("iss:clientId, aud:redirectUri , sub:userId 인 jwt 토큰을 λ°œκΈ‰ν•œλ‹€.") - @Test - void test() { - // given - val clientId = "clientId"; - val redirectUri = "redirectUri"; - val userId = 1L; - - // when - String platformCode = jwtTokenProvider.generatePlatformCode(clientId, redirectUri, userId); - val claims = getClaimsFromToken(platformCode); - - // then - assertThat(claims.getIssuer()).isEqualTo("clientId"); - assertThat(claims.getAudience()).isEqualTo("redirectUri"); - assertThat(claims.getSubject()).isEqualTo("1"); - } - - private Claims getClaimsFromToken(String token) { - val encodedKey = encodeKey(platformSecretKey); - - return Jwts.parserBuilder() - .setSigningKey(encodedKey) - .build() - .parseClaimsJws(token) - .getBody(); - } - - private String encodeKey(String secretKey) { - return Base64.getEncoder().encodeToString(secretKey.getBytes(StandardCharsets.UTF_8)); - } - } - - @Nested - @DisplayName("validatePlatformCode λ©”μ„œλ“œ ν…ŒμŠ€νŠΈ") - class ValidatePlatformCodeMethodTest { - - @DisplayName("iss:clientId, aud:redirectUri , sub:userId 인 jwt 토큰과 clientId, redirectUri λ₯Ό μ•„κ·œλ¨ΌνŠΈλ‘œ λ„£μœΌλ©΄ true λ₯Ό λ°˜ν™˜ν•œλ‹€.") - @Test - void test() { - // given - val clientId = "clientId"; - val redirectUri = "redirectUri"; - val userId = 1L; - String platformCode = jwtTokenProvider.generatePlatformCode(clientId, redirectUri, userId); - - // when - val result = jwtTokenProvider.validatePlatformCode(platformCode, "clientId", "redirectUri"); - - // then - assertThat(result).isTrue(); - } - - @DisplayName("iss:clientId, aud:redirectUri , sub:userId 인 jwt 토큰과 notClientId, notRedirectUri λ₯Ό μ•„κ·œλ¨ΌνŠΈλ‘œ λ„£μœΌλ©΄ false λ₯Ό λ°˜ν™˜ν•œλ‹€.") - @Test - void test2() { - // given - val clientId = "clientId"; - val redirectUri = "redirectUri"; - val userId = 1L; - String platformCode = jwtTokenProvider.generatePlatformCode(clientId, redirectUri, userId); - - // when - val result = jwtTokenProvider.validatePlatformCode(platformCode, "notClientId", "notRedirectUri"); - - // then - assertThat(result).isFalse(); - } - } - -} \ No newline at end of file diff --git a/operation-api/src/test/java/org/sopt/makers/operation/user/api/UserApiControllerTest.java b/operation-api/src/test/java/org/sopt/makers/operation/user/api/UserApiControllerTest.java deleted file mode 100644 index ed54ada7..00000000 --- a/operation-api/src/test/java/org/sopt/makers/operation/user/api/UserApiControllerTest.java +++ /dev/null @@ -1,250 +0,0 @@ -package org.sopt.makers.operation.user.api; - -import java.security.Principal; -import java.util.List; - -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.ValueSource; -import org.junit.jupiter.api.extension.ExtendWith; - -import org.mockito.junit.jupiter.MockitoExtension; - -import org.sopt.makers.operation.common.util.PermissionValidator; -import org.sopt.makers.operation.user.domain.User; -import org.sopt.makers.operation.user.domain.Part; -import org.sopt.makers.operation.user.domain.Team; -import org.sopt.makers.operation.user.domain.Position; -import org.sopt.makers.operation.user.domain.UserGenerationHistory; -import org.sopt.makers.operation.user.dto.response.UserInfoResponse; -import org.sopt.makers.operation.user.dto.response.UserInfosResponse; -import org.sopt.makers.operation.user.service.UserService; -import org.sopt.makers.operation.jwt.JwtTokenProvider; -import org.sopt.makers.operation.common.util.CommonUtils; -import org.sopt.makers.operation.common.handler.ErrorHandler; - -import org.springframework.http.MediaType; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.context.annotation.Import; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; -import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration; - -import static org.mockito.Mockito.mock; -import static org.mockito.BDDMockito.given; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.ArgumentMatchers.anyList; - -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; - -@Import({UserApiController.class}) -@ExtendWith(MockitoExtension.class) -@ContextConfiguration( - classes = {UserApiController.class, ErrorHandler.class} -) -@WebMvcTest( - controllers = {UserApiController.class}, - excludeAutoConfiguration = {SecurityAutoConfiguration.class} -) -@DisplayName("[[ Unit Test ]] - User Controller ") -class UserApiControllerTest { - - final String userInfoSelfUri = "/api/v1/internal/user/me"; - final String userInfosUri = "/api/v1/internal/user"; - - @MockBean - UserService userService; - - @MockBean - JwtTokenProvider tokenProvider; - @MockBean - CommonUtils commonUtils; - - @MockBean - PermissionValidator permissionValidator; - - @Autowired - MockMvc mockMvc; - - @Nested - @DisplayName("[TEST] μ„±κ³΅ν•œ κ²½μš°μ— λŒ€ν•œ ν…ŒμŠ€νŠΈ") - class SuccessTest { - - @Test - @DisplayName("Case. μš”μ²­μž μžμ‹ μ— λŒ€ν•œ μœ μ € 정보 쑰회 성곡 - /internal/user/me") - void successUserInfoSelf() throws Exception { - User mockedUser = mock(User.class); - UserGenerationHistory mockedHistory = mock(UserGenerationHistory.class); - given(mockedUser.getId()).willReturn(1L); - given(mockedUser.getName()).willReturn("TestUser"); - given(mockedUser.getPhone()).willReturn("01012345678"); - given(mockedUser.getProfileImage()).willReturn("TestImageUrl"); - - given(mockedHistory.getId()).willReturn(1L); - given(mockedHistory.getPart()).willReturn(Part.SERVER); - given(mockedHistory.getGeneration()).willReturn(32); - given(mockedHistory.getTeam()).willReturn(Team.OPERATION); - given(mockedHistory.getPosition()).willReturn(Position.MEMBER); - - Principal mockPrincipal = mock(Principal.class); - given(mockPrincipal.getName()).willReturn("1"); - - UserInfoResponse expectServiceResult = UserInfoResponse.of(mockedUser, List.of(mockedHistory)); - given(userService.getUserInfo(anyLong())).willReturn(expectServiceResult); - - mockMvc.perform( - get(userInfoSelfUri) - .contentType(MediaType.APPLICATION_JSON) - .principal(mockPrincipal)) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.success").value("true")) - .andExpect(jsonPath("$.message").value("μœ μ € 정보 쑰회 성곡")) - - .andExpect(jsonPath("$.data.id").value("1")) - .andExpect(jsonPath("$.data.name").value("TestUser")) - .andExpect(jsonPath("$.data.phone").value("01012345678")) - .andExpect(jsonPath("$.data.profileImage").value("TestImageUrl")) - - .andExpect(jsonPath("$.data.activities[0].id").value("1")) - .andExpect(jsonPath("$.data.activities[0].generation").value("32")) - .andExpect(jsonPath("$.data.activities[0].part").value("SERVER")) - .andExpect(jsonPath("$.data.activities[0].team").value("OPERATION")) - .andExpect(jsonPath("$.data.activities[0].position").value("MEMBER")); - - } - - @Test - @DisplayName("Case. 볡수 μœ μ € 정보 쑰회 성곡 - /internal/user?userIds=") - void successUserInfos() throws Exception { - User mockedUserA = mock(User.class); - UserGenerationHistory mockedHistoryA = mock(UserGenerationHistory.class); - - given(mockedUserA.getId()).willReturn(1L); - given(mockedUserA.getName()).willReturn("TestUserA"); - given(mockedUserA.getPhone()).willReturn("01012345678"); - given(mockedUserA.getProfileImage()).willReturn("TestImageUrlA"); - given(mockedHistoryA.getId()).willReturn(1L); - given(mockedHistoryA.getPart()).willReturn(Part.SERVER); - given(mockedHistoryA.getGeneration()).willReturn(32); - given(mockedHistoryA.getTeam()).willReturn(Team.OPERATION); - given(mockedHistoryA.getPosition()).willReturn(Position.MEMBER); - - User mockedUserB = mock(User.class); - UserGenerationHistory mockedHistoryB = mock(UserGenerationHistory.class); - given(mockedUserB.getId()).willReturn(2L); - given(mockedUserB.getName()).willReturn("TestUserB"); - given(mockedUserB.getPhone()).willReturn("01056789012"); - given(mockedUserB.getProfileImage()).willReturn("TestImageUrlB"); - given(mockedHistoryB.getId()).willReturn(2L); - given(mockedHistoryB.getPart()).willReturn(Part.PLAN); - given(mockedHistoryB.getGeneration()).willReturn(32); - given(mockedHistoryB.getTeam()).willReturn(Team.MEDIA); - given(mockedHistoryB.getPosition()).willReturn(Position.TEAM_LEADER); - - Principal mockPrincipal = mock(Principal.class); - given(mockPrincipal.getName()).willReturn("1"); - - UserInfoResponse expectServiceResultOfA = UserInfoResponse.of(mockedUserA, List.of(mockedHistoryA)); - UserInfoResponse expectServiceResultOfB = UserInfoResponse.of(mockedUserB, List.of(mockedHistoryB)); - UserInfosResponse expected = UserInfosResponse.of(List.of(expectServiceResultOfA, expectServiceResultOfB)); - - given(userService.getUserInfos(anyList())).willReturn(expected); - - mockMvc.perform( - get(userInfosUri) - .contentType(MediaType.APPLICATION_JSON) - .principal(mockPrincipal) - .queryParam("userIds","1%2C2")) - .andDo(print()) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.success").value("true")) - .andExpect(jsonPath("$.message").value("전체 μœ μ € 정보 쑰회 성곡")) - - .andExpect(jsonPath("$.data.users[0].id").value("1")) - .andExpect(jsonPath("$.data.users[0].name").value("TestUserA")) - .andExpect(jsonPath("$.data.users[0].phone").value("01012345678")) - .andExpect(jsonPath("$.data.users[0].profileImage").value("TestImageUrlA")) - - .andExpect(jsonPath("$.data.users[0].activities[0].id").value("1")) - .andExpect(jsonPath("$.data.users[0].activities[0].generation").value("32")) - .andExpect(jsonPath("$.data.users[0].activities[0].part").value("SERVER")) - .andExpect(jsonPath("$.data.users[0].activities[0].team").value("OPERATION")) - .andExpect(jsonPath("$.data.users[0].activities[0].position").value("MEMBER")) - - .andExpect(jsonPath("$.data.users[1].id").value("2")) - .andExpect(jsonPath("$.data.users[1].name").value("TestUserB")) - .andExpect(jsonPath("$.data.users[1].phone").value("01056789012")) - .andExpect(jsonPath("$.data.users[1].profileImage").value("TestImageUrlB")) - - .andExpect(jsonPath("$.data.users[1].activities[0].id").value("2")) - .andExpect(jsonPath("$.data.users[1].activities[0].generation").value("32")) - .andExpect(jsonPath("$.data.users[1].activities[0].part").value("PLAN")) - .andExpect(jsonPath("$.data.users[1].activities[0].team").value("MEDIA")) - .andExpect(jsonPath("$.data.users[1].activities[0].position").value("TEAM_LEADER")); - - } - - } - - @Nested - @DisplayName("[TEST] μ‹€νŒ¨ν•œ κ²½μš°μ— λŒ€ν•œ ν…ŒμŠ€νŠΈ") - class FailTest { - - @Test - @DisplayName("Case. 잘λͺ»λœ ν˜•μ‹μ˜ userIds Parameter κ°’ : Null - /internal/user?userIds=") - void failUserInfosCausedByNullParameter() throws Exception { - Principal mockPrincipal = mock(Principal.class); - given(mockPrincipal.getName()).willReturn("1"); - - mockMvc.perform( - get(userInfosUri) - .contentType(MediaType.APPLICATION_JSON) - .principal(mockPrincipal) - .param("userIds", "")) - .andDo(print()) - .andExpect(status().isBadRequest()) - .andDo(print()); - } - - @DisplayName("Case. 잘λͺ»λœ ν˜•μ‹μ˜ userIds Parameter κ°’ : Wrong Delimiter - /internal/user?userIds=") - @ParameterizedTest(name = "* {index}번째 μž…λ ₯κ°’ = {0}") - @ValueSource(strings = {"123/124", "123_124", "123:124", "123-124"}) - void failUserInfosCausedByWrongDelimiter(String wrongDelimiter) throws Exception { - Principal mockPrincipal = mock(Principal.class); - given(mockPrincipal.getName()).willReturn("1"); - - mockMvc.perform( - get(userInfosUri) - .contentType(MediaType.APPLICATION_JSON) - .principal(mockPrincipal) - .param("userIds", wrongDelimiter)) - .andDo(print()) - .andExpect(status().isBadRequest()) - .andDo(print()); - } - - @DisplayName("Case. 잘λͺ»λœ ν˜•μ‹μ˜ userIds Parameter κ°’ : Not Number - /internal/user?userIds=") - @ParameterizedTest(name = "* {index}번째 μž…λ ₯κ°’ = {0}") - @ValueSource(strings = {"abc,def", "γ„±γ„΄γ„·,ㄹㅁㅂ", "[][],.;.;"}) - void failUserInfosCausedByNotNumber(String notNumberValue) throws Exception { - Principal mockPrincipal = mock(Principal.class); - given(mockPrincipal.getName()).willReturn("1"); - - mockMvc.perform( - get(userInfosUri) - .contentType(MediaType.APPLICATION_JSON) - .principal(mockPrincipal) - .param("userIds", notNumberValue)) - .andDo(print()) - .andExpect(status().isBadRequest()) - .andDo(print()); - } - } -} \ No newline at end of file diff --git a/operation-api/src/test/java/org/sopt/makers/operation/user/service/UserServiceTest.java b/operation-api/src/test/java/org/sopt/makers/operation/user/service/UserServiceTest.java deleted file mode 100644 index c944fdf8..00000000 --- a/operation-api/src/test/java/org/sopt/makers/operation/user/service/UserServiceTest.java +++ /dev/null @@ -1,161 +0,0 @@ -package org.sopt.makers.operation.user.service; - -import java.util.Arrays; -import java.util.List; -import java.util.Collections; -import java.util.stream.Stream; - -import lombok.val; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.extension.ExtendWith; - -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; -import org.junit.jupiter.params.provider.ValueSource; -import org.mockito.Mock; -import org.mockito.InjectMocks; -import org.mockito.junit.jupiter.MockitoExtension; - -import org.sopt.makers.operation.code.failure.UserFailureCode; -import org.sopt.makers.operation.exception.UserException; -import org.sopt.makers.operation.user.domain.*; -import org.sopt.makers.operation.user.dto.request.UserActivityModifyRequest; -import org.sopt.makers.operation.user.dto.request.UserModifyRequest; -import org.sopt.makers.operation.user.dto.response.UserInfoResponse; -import org.sopt.makers.operation.user.repository.UserRepository; -import org.sopt.makers.operation.user.repository.history.UserGenerationHistoryRepository; - -import static org.mockito.Mockito.mock; -import static org.mockito.BDDMockito.given; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; - -@ExtendWith(MockitoExtension.class) -@DisplayName("[[ Unit Test ]] - UserService ") -class UserServiceTest { - - @Mock - UserRepository userRepository; - @Mock - UserGenerationHistoryRepository userGenerationHistoryRepository; - @InjectMocks - UserServiceImpl userService; - - @Nested - @DisplayName("[TEST] μ„±κ³΅ν•œ κ²½μš°μ— λŒ€ν•œ ν…ŒμŠ€νŠΈ") - class SuccessTest { - - @Test - @DisplayName("Case. μ˜λ„ν–ˆλ˜ λ°μ΄ν„°λ‘œ κ΅¬μ„±λœ μœ μ € 쑰회 κ²°κ³Ό Response 데이터가 λ°˜ν™˜λœλ‹€.") - void expectFindUserResponseReturnSuccess() { - // given - User mockedUser = mock(User.class); - UserGenerationHistory mockedHistory = mock(UserGenerationHistory.class); - given(mockedUser.getId()).willReturn(1L); - given(mockedUser.getName()).willReturn("TestUser"); - given(mockedUser.getPhone()).willReturn("01012345678"); - - given(mockedHistory.getId()).willReturn(1L); - given(mockedHistory.getGeneration()).willReturn(32); - given(mockedHistory.getTeam()).willReturn(Team.OPERATION); - given(mockedHistory.getPosition()).willReturn(Position.MEMBER); - - given(userRepository.findUserById(1L)).willReturn(mockedUser); - given(userGenerationHistoryRepository.findAllHistoryByUserId(1L)).willReturn(List.of(mockedHistory)); - - long targetUserId = 1L; - UserInfoResponse expected = UserInfoResponse.of(mockedUser, List.of(mockedHistory)); - - // when - UserInfoResponse response = userService.getUserInfo(targetUserId); - - // then - assertThat(response).usingRecursiveComparison().isEqualTo(expected); - } - - } - - @Nested - @DisplayName("[TEST] μ‹€νŒ¨ν•œ κ²½μš°μ— λŒ€ν•œ ν…ŒμŠ€νŠΈ") - class FailureTest { - - - @Test - @DisplayName("Case. 볡수 μœ μ € 쑰회 μ‹œμ— 빈 Id 리슀트λ₯Ό μ£Όμž…ν•  경우, μ˜ˆμ™Έ λ°˜ν™˜") - void throwException_Empty_Ids() { - // given - List invalidUserIds = Collections.emptyList(); - - // when & then - assertThatThrownBy(() -> userService.getUserInfos(invalidUserIds)) - .isInstanceOf(UserException.class) - .hasMessageContaining(UserFailureCode.INVALID_PARAMETER.getMessage()); - } - - @ParameterizedTest(name = "Invalid User ID ({index}) = {0}") - @DisplayName("Case. 단일 μœ μ € 쑰회 μ‹œμ— μœ νš¨ν•˜μ§€ μ•Šμ€ λ²”μœ„μ˜ Id 값일 경우, μ˜ˆμ™Έ λ°˜ν™˜") - @ValueSource(longs = {0L, -1L}) - void throwException_Invalid_Id(Long invalidUserId) { - // when & then - assertThatThrownBy(() -> userService.getUserInfo(invalidUserId)) - .isInstanceOf(UserException.class) - .hasMessageContaining(UserFailureCode.INVALID_USER_IN_USER_LIST_PARAMETER.getMessage()); - } - - @Test - @DisplayName("Case. 볡수 μœ μ € 쑰회 μ‹œμ— μœ νš¨ν•˜μ§€ μ•Šμ€ λ²”μœ„μ˜ Id 값이 ν¬ν•¨λ˜μ–΄ μžˆμ„ 경우, μ˜ˆμ™Έ λ°˜ν™˜") - void throwException_Include_Invalid_Id() { - // given - val invalidUserIds = Arrays.asList(0L, -1L, 1L); - - // when & then - assertThatThrownBy(() -> userService.getUserInfos(invalidUserIds)) - .isInstanceOf(UserException.class) - .hasMessageContaining(UserFailureCode.INVALID_USER_IN_USER_LIST_PARAMETER.getMessage()); - } - - @ParameterizedTest - @DisplayName("Case. μœ μ € ν™œλ™ 데이터 λ³€κ²½ μ‹œμ— μž„μ›μ§„μ΄λ©΄μ„œ κΈ°μ‘΄ μ €μž₯λ˜μ–΄ 있던 Teamκ³Ό λ‹€λ₯Ό 경우") - @MethodSource("ofActivityUpdateRequests") - void throwException_Update_Team_Data_Of_Executive_User( - // given - UserModifyRequest userModifyRequest - ) { - val mockedUser = mock(User.class); - val mockedExistHistory = mock(UserGenerationHistory.class); - - given(mockedUser.getId()).willReturn(1L); - given(mockedExistHistory.isExecutive()).willReturn(true); - given(mockedExistHistory.isBelongTeamTo(Team.OPERATION)).willReturn(false); - - given(userRepository.findUserById(1L)).willReturn(mockedUser); - given(userGenerationHistoryRepository.findHistoryById(1L)).willReturn(mockedExistHistory); - - // then - assertThatThrownBy(() -> userService.modifyUserInfo(mockedUser.getId(), userModifyRequest)) - .isInstanceOf(UserException.class) - .hasMessageContaining(UserFailureCode.INVALID_USER_MODIFY_ACTIVITY_INFO.getMessage()); - } - static Stream ofActivityUpdateRequests() { - return Stream.of( - Arguments.of( -// new UserPersonalInfoUpdateDao("TestUser", -// "01012345678", -// "TestProfileImage" -// ), - new UserModifyRequest( - "TestUser", - "01012345678", - "TestProfileImage", - List.of( - new UserActivityModifyRequest(1L, 34, Part.SERVER, Team.OPERATION, Position.TEAM_LEADER) - ) - ) - ) - ); - } - } -} \ No newline at end of file diff --git a/operation-common/src/main/java/org/sopt/makers/operation/code/failure/auth/AuthFailureCode.java b/operation-common/src/main/java/org/sopt/makers/operation/code/failure/auth/AuthFailureCode.java deleted file mode 100644 index d1cf4c1a..00000000 --- a/operation-common/src/main/java/org/sopt/makers/operation/code/failure/auth/AuthFailureCode.java +++ /dev/null @@ -1,35 +0,0 @@ -package org.sopt.makers.operation.code.failure.auth; - -import lombok.Getter; -import lombok.RequiredArgsConstructor; -import org.sopt.makers.operation.code.failure.FailureCode; -import org.springframework.http.HttpStatus; - -import static org.springframework.http.HttpStatus.BAD_REQUEST; -import static org.springframework.http.HttpStatus.NOT_FOUND; -import static org.springframework.http.HttpStatus.UNAUTHORIZED; - -@Getter -@RequiredArgsConstructor -public enum AuthFailureCode implements FailureCode { - // 400 - NOT_NULL_GRANT_TYPE(BAD_REQUEST, "grantType 데이터가 λ“€μ–΄μ˜€μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€."), - INVALID_SOCIAL_TYPE(BAD_REQUEST, "μœ νš¨ν•˜μ§€ μ•Šμ€ social type μž…λ‹ˆλ‹€."), - INVALID_ID_TOKEN(BAD_REQUEST, "μœ νš¨ν•˜μ§€ μ•Šμ€ id token μž…λ‹ˆλ‹€."), - INVALID_SOCIAL_CODE(BAD_REQUEST, "μœ νš¨ν•˜μ§€ μ•Šμ€ social code μž…λ‹ˆλ‹€."), - FAILURE_READ_PRIVATE_KEY(BAD_REQUEST, "Private key 읽기 μ‹€νŒ¨"), - INVALID_GRANT_TYPE(BAD_REQUEST, "μœ νš¨ν•˜μ§€ μ•Šμ€ grantType μž…λ‹ˆλ‹€."), - NOT_NULL_CODE(BAD_REQUEST, "ν”Œλž«νΌ μΈκ°€μ½”λ“œκ°€ λ“€μ–΄μ˜€μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€."), - USED_PLATFORM_CODE(BAD_REQUEST, "이미 μ‚¬μš©ν•œ ν”Œλž«νΌ μΈκ°€μ½”λ“œμž…λ‹ˆλ‹€."), - NOT_NULL_REFRESH_TOKEN(BAD_REQUEST, "λ¦¬ν”„λ ˆμ‰¬ 토큰이 λ“€μ–΄μ˜€μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€."), - // 401 - EXPIRED_PLATFORM_CODE(UNAUTHORIZED, "만료된 ν”Œλž«νΌ μΈκ°€μ½”λ“œμž…λ‹ˆλ‹€."), - EXPIRED_REFRESH_TOKEN(UNAUTHORIZED, "만료된 λ¦¬ν”„λ ˆμ‰¬ ν† ν°μž…λ‹ˆλ‹€."), - // 404 - NOT_FOUNT_REGISTERED_TEAM(NOT_FOUND, "λ“±λ‘λ˜μ§€ μ•Šμ€ νŒ€μž…λ‹ˆλ‹€."), - NOT_FOUND_USER_SOCIAL_IDENTITY_INFO(NOT_FOUND, "λ“±λ‘λœ μ†Œμ…œ 정보가 μ—†μŠ΅λ‹ˆλ‹€."), - ; - - private final HttpStatus status; - private final String message; -} diff --git a/operation-common/src/main/java/org/sopt/makers/operation/code/success/auth/AuthSuccessCode.java b/operation-common/src/main/java/org/sopt/makers/operation/code/success/auth/AuthSuccessCode.java deleted file mode 100644 index 0b9131f5..00000000 --- a/operation-common/src/main/java/org/sopt/makers/operation/code/success/auth/AuthSuccessCode.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.sopt.makers.operation.code.success.auth; - -import lombok.Getter; -import lombok.RequiredArgsConstructor; -import org.sopt.makers.operation.code.success.SuccessCode; -import org.springframework.http.HttpStatus; - -import static org.springframework.http.HttpStatus.OK; - -@Getter -@RequiredArgsConstructor -public enum AuthSuccessCode implements SuccessCode { - SUCCESS_RETURN_REDIRECT_URL_WITH_PLATFORM_CODE(OK, "ν”Œλž«νΌ μΈκ°€μ½”λ“œλ₯Ό ν¬ν•¨ν•œ redirect url λ°˜ν™˜ 성곡"), - SUCCESS_GENERATE_TOKEN(OK, "토큰 λ°œκΈ‰ 성곡"); - private final HttpStatus status; - private final String message; -} diff --git a/operation-common/src/main/java/org/sopt/makers/operation/config/ValueConfig.java b/operation-common/src/main/java/org/sopt/makers/operation/config/ValueConfig.java index 2cc35629..ee9948b5 100644 --- a/operation-common/src/main/java/org/sopt/makers/operation/config/ValueConfig.java +++ b/operation-common/src/main/java/org/sopt/makers/operation/config/ValueConfig.java @@ -42,22 +42,6 @@ public class ValueConfig { private String eventBridgeRoleArn; @Value("${cloud.aws.s3.banner.name}") private String bannerBucket; - @Value("${oauth.apple.key.id}") - private String appleKeyId; - @Value("${oauth.apple.key.path}") - private String appleKeyPath; - @Value("${oauth.apple.team.id}") - private String appleTeamId; - @Value("${oauth.apple.aud}") - private String appleAud; - @Value("${oauth.apple.sub}") - private String appleSub; - @Value("${oauth.google.client.id}") - private String googleClientId; - @Value("${oauth.google.client.secret}") - private String googleClientSecret; - @Value("${oauth.google.redirect.url}") - private String googleRedirectUrl; @Value("${spring.jwt.secretKey.platform_code}") private String platformCodeSecretKey; diff --git a/operation-common/src/main/java/org/sopt/makers/operation/exception/AuthException.java b/operation-common/src/main/java/org/sopt/makers/operation/exception/AuthException.java deleted file mode 100644 index a391e5ac..00000000 --- a/operation-common/src/main/java/org/sopt/makers/operation/exception/AuthException.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.sopt.makers.operation.exception; - -import lombok.Getter; -import org.sopt.makers.operation.code.failure.FailureCode; - -@Getter -public class AuthException extends RuntimeException{ - private final FailureCode failureCode; - - public AuthException(FailureCode failureCode) { - super("[AuthException] : " + failureCode.getMessage()); - this.failureCode = failureCode; - } -} diff --git a/operation-domain/src/main/java/org/sopt/makers/operation/auth/domain/Team.java b/operation-domain/src/main/java/org/sopt/makers/operation/auth/domain/Team.java deleted file mode 100644 index bd95112c..00000000 --- a/operation-domain/src/main/java/org/sopt/makers/operation/auth/domain/Team.java +++ /dev/null @@ -1,5 +0,0 @@ -package org.sopt.makers.operation.auth.domain; - -public enum Team { - PLAYGROUND, CREW, APP -} diff --git a/operation-domain/src/main/java/org/sopt/makers/operation/auth/domain/TeamOAuthInfo.java b/operation-domain/src/main/java/org/sopt/makers/operation/auth/domain/TeamOAuthInfo.java deleted file mode 100644 index 7a7d2d19..00000000 --- a/operation-domain/src/main/java/org/sopt/makers/operation/auth/domain/TeamOAuthInfo.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.sopt.makers.operation.auth.domain; - -import static jakarta.persistence.GenerationType.IDENTITY; - -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.EnumType; -import jakarta.persistence.Enumerated; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.Id; -import jakarta.persistence.Table; - -@Entity -@Table(name = "team_oauth_info") -public class TeamOAuthInfo { - - @Id - @GeneratedValue(strategy = IDENTITY) - private Long id; - - @Column(name = "client_id", nullable = false) - private String clientId; - - @Column(name = "redirect_uri", nullable = false) - private String redirectUri; - - @Column(name = "team", nullable = false) - @Enumerated(EnumType.STRING) - private Team team; -} diff --git a/operation-domain/src/main/java/org/sopt/makers/operation/auth/repository/TeamOAuthInfoRepository.java b/operation-domain/src/main/java/org/sopt/makers/operation/auth/repository/TeamOAuthInfoRepository.java deleted file mode 100644 index 586a652a..00000000 --- a/operation-domain/src/main/java/org/sopt/makers/operation/auth/repository/TeamOAuthInfoRepository.java +++ /dev/null @@ -1,8 +0,0 @@ -package org.sopt.makers.operation.auth.repository; - -import org.sopt.makers.operation.auth.domain.TeamOAuthInfo; -import org.springframework.data.jpa.repository.JpaRepository; - -public interface TeamOAuthInfoRepository extends JpaRepository { - boolean existsByClientIdAndRedirectUri(String clientId, String redirectUri); -} diff --git a/operation-domain/src/main/java/org/sopt/makers/operation/user/dao/UserActivityInfoUpdateDao.java b/operation-domain/src/main/java/org/sopt/makers/operation/user/dao/UserActivityInfoUpdateDao.java deleted file mode 100644 index b769f8b0..00000000 --- a/operation-domain/src/main/java/org/sopt/makers/operation/user/dao/UserActivityInfoUpdateDao.java +++ /dev/null @@ -1,8 +0,0 @@ -package org.sopt.makers.operation.user.dao; - -import org.sopt.makers.operation.user.domain.Team; - -public record UserActivityInfoUpdateDao( - Team team -) { -} diff --git a/operation-domain/src/main/java/org/sopt/makers/operation/user/dao/UserPersonalInfoUpdateDao.java b/operation-domain/src/main/java/org/sopt/makers/operation/user/dao/UserPersonalInfoUpdateDao.java deleted file mode 100644 index 2465b98f..00000000 --- a/operation-domain/src/main/java/org/sopt/makers/operation/user/dao/UserPersonalInfoUpdateDao.java +++ /dev/null @@ -1,8 +0,0 @@ -package org.sopt.makers.operation.user.dao; - -public record UserPersonalInfoUpdateDao( - String name, - String phone, - String profileImage -) { -} diff --git a/operation-domain/src/main/java/org/sopt/makers/operation/user/domain/Gender.java b/operation-domain/src/main/java/org/sopt/makers/operation/user/domain/Gender.java deleted file mode 100644 index dcff9387..00000000 --- a/operation-domain/src/main/java/org/sopt/makers/operation/user/domain/Gender.java +++ /dev/null @@ -1,6 +0,0 @@ -package org.sopt.makers.operation.user.domain; - -public enum Gender { - MALE, - FEMALE, -} diff --git a/operation-domain/src/main/java/org/sopt/makers/operation/user/domain/Part.java b/operation-domain/src/main/java/org/sopt/makers/operation/user/domain/Part.java deleted file mode 100644 index 7386d086..00000000 --- a/operation-domain/src/main/java/org/sopt/makers/operation/user/domain/Part.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.sopt.makers.operation.user.domain; - -public enum Part { - - PLAN, - DESIGN, - WEB, - ANDROID, - IOS, - SERVER, - INDEPENDENT, // 회μž₯단 λ¬΄μ†Œμ† 선택지 -} diff --git a/operation-domain/src/main/java/org/sopt/makers/operation/user/domain/Position.java b/operation-domain/src/main/java/org/sopt/makers/operation/user/domain/Position.java deleted file mode 100644 index da0d79c9..00000000 --- a/operation-domain/src/main/java/org/sopt/makers/operation/user/domain/Position.java +++ /dev/null @@ -1,10 +0,0 @@ -package org.sopt.makers.operation.user.domain; - -public enum Position { - PRESIDENT, // 회μž₯ - VICE_PRESIDENT, // λΆ€νšŒμž₯ - GENERAL_AFFAIRS, // 총무 - TEAM_LEADER, // νŒ€μž₯ - PART_LEADER, // 파트μž₯ - MEMBER // νšŒμ› -} diff --git a/operation-domain/src/main/java/org/sopt/makers/operation/user/domain/SocialType.java b/operation-domain/src/main/java/org/sopt/makers/operation/user/domain/SocialType.java deleted file mode 100644 index bfca14f9..00000000 --- a/operation-domain/src/main/java/org/sopt/makers/operation/user/domain/SocialType.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.sopt.makers.operation.user.domain; - -import java.util.Arrays; - -public enum SocialType { - GOOGLE, - APPLE; - - - public static boolean isContains(String type) { - return Arrays.stream(SocialType.values()) - .anyMatch(socialType -> socialType.name().equals(type)); - } -} diff --git a/operation-domain/src/main/java/org/sopt/makers/operation/user/domain/Team.java b/operation-domain/src/main/java/org/sopt/makers/operation/user/domain/Team.java deleted file mode 100644 index 02105639..00000000 --- a/operation-domain/src/main/java/org/sopt/makers/operation/user/domain/Team.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.sopt.makers.operation.user.domain; - -public enum Team { - OPERATION, - MEDIA, - MAKERS -} diff --git a/operation-domain/src/main/java/org/sopt/makers/operation/user/domain/User.java b/operation-domain/src/main/java/org/sopt/makers/operation/user/domain/User.java deleted file mode 100644 index 4050489d..00000000 --- a/operation-domain/src/main/java/org/sopt/makers/operation/user/domain/User.java +++ /dev/null @@ -1,68 +0,0 @@ -package org.sopt.makers.operation.user.domain; - -import jakarta.persistence.Id; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Entity; -import jakarta.persistence.Table; -import jakarta.persistence.Column; -import jakarta.persistence.Enumerated; -import jakarta.persistence.EnumType; - -import java.time.LocalDate; - -import lombok.Getter; -import lombok.Builder; -import lombok.NoArgsConstructor; -import lombok.AllArgsConstructor; -import lombok.AccessLevel; - -import org.sopt.makers.operation.common.domain.BaseEntity; -import org.sopt.makers.operation.user.dao.UserPersonalInfoUpdateDao; - -@Entity @Getter -@Table(name = "users") -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@AllArgsConstructor(access = AccessLevel.PRIVATE) -public class User extends BaseEntity { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @Column(name = "email", nullable = false) - private String email; - - @Column(name = "phone", nullable = false) - private String phone; - - @Column(name = "gender", nullable = false) - @Enumerated(EnumType.STRING) - private Gender gender; - - @Column(name = "name", nullable = false) - private String name; - - @Column(name = "profile_image") - private String profileImage; - - @Column(name = "birthday") - private LocalDate birthday; - - - @Builder - public User(String email, String phone, Gender gender, String name, String profileImage, LocalDate birthday) { - this.email = email; - this.phone = phone; - this.gender = gender; - this.name = name; - this.profileImage = profileImage; - this.birthday = birthday; - } - - public void updateUserInfo(UserPersonalInfoUpdateDao infoUpdateDao) { - this.name = infoUpdateDao.name(); - this.phone = infoUpdateDao.phone(); - this.profileImage = infoUpdateDao.profileImage(); - } -} diff --git a/operation-domain/src/main/java/org/sopt/makers/operation/user/domain/UserGenerationHistory.java b/operation-domain/src/main/java/org/sopt/makers/operation/user/domain/UserGenerationHistory.java deleted file mode 100644 index b57e19b9..00000000 --- a/operation-domain/src/main/java/org/sopt/makers/operation/user/domain/UserGenerationHistory.java +++ /dev/null @@ -1,67 +0,0 @@ -package org.sopt.makers.operation.user.domain; - -import jakarta.persistence.Id; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Entity; -import jakarta.persistence.Table; -import jakarta.persistence.Column; -import jakarta.persistence.Enumerated; -import jakarta.persistence.EnumType; - -import lombok.Getter; -import lombok.Builder; -import lombok.NoArgsConstructor; -import lombok.AllArgsConstructor; -import lombok.AccessLevel; -import org.sopt.makers.operation.user.dao.UserActivityInfoUpdateDao; - -@Entity @Getter -@Table(name = "user_generation_history") -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@AllArgsConstructor(access = AccessLevel.PRIVATE) -public class UserGenerationHistory { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @Column(name = "user_id", nullable = false) - private Long userId; - - @Column(name = "generation", nullable = false) - private int generation; - - @Column(name = "part") - @Enumerated(value = EnumType.STRING) - private Part part; - - @Column(name = "team") - @Enumerated(value = EnumType.STRING) - private Team team; - - @Column(name = "position", nullable = false) - @Enumerated(value = EnumType.STRING) - private Position position; - - @Builder - public UserGenerationHistory(Long userId, int generation, Part part, Team team, Position position) { - this.userId = userId; - this.generation = generation; - this.part = part; - this.team = team; - this.position = position; - } - - public boolean isExecutive() { - return !Position.MEMBER.equals(this.position); - } - - public boolean isBelongTeamTo(Team team) { - return this.team.equals(team); - } - - public void updateActivityInfo(UserActivityInfoUpdateDao activityInfoUpdateDao) { - this.team = activityInfoUpdateDao.team(); - } -} diff --git a/operation-domain/src/main/java/org/sopt/makers/operation/user/domain/UserIdentityInfo.java b/operation-domain/src/main/java/org/sopt/makers/operation/user/domain/UserIdentityInfo.java deleted file mode 100644 index bf96d34b..00000000 --- a/operation-domain/src/main/java/org/sopt/makers/operation/user/domain/UserIdentityInfo.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.sopt.makers.operation.user.domain; - -import jakarta.persistence.Id; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Entity; -import jakarta.persistence.Table; -import jakarta.persistence.Column; -import jakarta.persistence.Enumerated; -import jakarta.persistence.EnumType; - -import lombok.Getter; -import lombok.Builder; -import lombok.NoArgsConstructor; -import lombok.AllArgsConstructor; -import lombok.AccessLevel; - -@Entity @Getter -@Table(name = "user_identity_info") -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@AllArgsConstructor(access = AccessLevel.PRIVATE) -public class UserIdentityInfo { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @Column(name = "user_id", nullable = false) - private Long userId; - - @Column(name = "idp_type", nullable = false) - @Enumerated(value = EnumType.STRING) - private SocialType socialType; - - @Column(name = "auth_user_id", nullable = false) - private String socialId; - - @Builder - public UserIdentityInfo(Long userId, SocialType socialType, String socialId) { - this.userId = userId; - this.socialType = socialType; - this.socialId = socialId; - } -} diff --git a/operation-domain/src/main/java/org/sopt/makers/operation/user/domain/UserRegisterInfo.java b/operation-domain/src/main/java/org/sopt/makers/operation/user/domain/UserRegisterInfo.java deleted file mode 100644 index 82de5273..00000000 --- a/operation-domain/src/main/java/org/sopt/makers/operation/user/domain/UserRegisterInfo.java +++ /dev/null @@ -1,52 +0,0 @@ -package org.sopt.makers.operation.user.domain; - -import jakarta.persistence.Id; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Entity; -import jakarta.persistence.Table; -import jakarta.persistence.Column; -import jakarta.persistence.Enumerated; -import jakarta.persistence.EnumType; - -import lombok.Getter; -import lombok.Builder; -import lombok.NoArgsConstructor; -import lombok.AllArgsConstructor; -import lombok.AccessLevel; - -@Entity @Getter -@Table(name = "user_register_info") -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@AllArgsConstructor(access = AccessLevel.PRIVATE) -public class UserRegisterInfo { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @Column(name = "name") - private String name; - - @Column(name = "email") - private String email; - - @Column(name = "generation", nullable = false) - private int generation; - - @Column(name = "phone") - private String phone; - - @Column(name = "part") - @Enumerated(value = EnumType.STRING) - private Part part; - - @Builder - public UserRegisterInfo(String name, String email, String phone, Part part, Integer generation) { - this.name = name; - this.email = email; - this.phone = phone; - this.part = part; - this.generation = generation; - } -} diff --git a/operation-domain/src/main/java/org/sopt/makers/operation/user/repository/UserRepository.java b/operation-domain/src/main/java/org/sopt/makers/operation/user/repository/UserRepository.java deleted file mode 100644 index 1bd663cf..00000000 --- a/operation-domain/src/main/java/org/sopt/makers/operation/user/repository/UserRepository.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.sopt.makers.operation.user.repository; - -import lombok.val; -import org.sopt.makers.operation.code.failure.UserFailureCode; -import org.sopt.makers.operation.exception.UserException; -import org.sopt.makers.operation.user.domain.User; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.stereotype.Repository; - -import java.util.List; - -@Repository -public interface UserRepository extends JpaRepository { - - default User findUserById(Long userId) { - return findById(userId).orElseThrow(() -> new UserException(UserFailureCode.NOT_FOUND_USER)); - } - default List findAllUsersById(List userIds) { - val allUsers = findAllById(userIds); - if (allUsers.size() != userIds.size()) { - throw new UserException(UserFailureCode.NOT_FOUND_USER_IN_USER_LIST_PARAMETER); - } - return allUsers; - } - -} diff --git a/operation-domain/src/main/java/org/sopt/makers/operation/user/repository/history/UserGenerationHistoryRepository.java b/operation-domain/src/main/java/org/sopt/makers/operation/user/repository/history/UserGenerationHistoryRepository.java deleted file mode 100644 index 3060045f..00000000 --- a/operation-domain/src/main/java/org/sopt/makers/operation/user/repository/history/UserGenerationHistoryRepository.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.sopt.makers.operation.user.repository.history; - -import java.util.List; - -import lombok.val; -import org.sopt.makers.operation.exception.UserException; -import org.sopt.makers.operation.code.failure.UserFailureCode; -import org.sopt.makers.operation.user.domain.UserGenerationHistory; - -import org.springframework.stereotype.Repository; -import org.springframework.data.jpa.repository.JpaRepository; - -@Repository -public interface UserGenerationHistoryRepository extends JpaRepository { - - List findAllByUserId(Long userId); - - default UserGenerationHistory findHistoryById(Long historyId) { - return findById(historyId).orElseThrow(() -> new UserException(UserFailureCode.NOT_FOUND_HISTORY)); - } - - default List findAllHistoryByUserId(Long userId) { - val histories = findAllByUserId(userId); - if (histories.isEmpty()) { - throw new UserException(UserFailureCode.NOT_FOUND_HISTORY); - } - return histories; - } - -} diff --git a/operation-domain/src/main/java/org/sopt/makers/operation/user/repository/identityinfo/UserIdentityInfoRepository.java b/operation-domain/src/main/java/org/sopt/makers/operation/user/repository/identityinfo/UserIdentityInfoRepository.java deleted file mode 100644 index 96408c1b..00000000 --- a/operation-domain/src/main/java/org/sopt/makers/operation/user/repository/identityinfo/UserIdentityInfoRepository.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.sopt.makers.operation.user.repository.identityinfo; - -import org.sopt.makers.operation.user.domain.SocialType; -import org.sopt.makers.operation.user.domain.UserIdentityInfo; -import org.springframework.data.jpa.repository.JpaRepository; - -import java.util.Optional; - -public interface UserIdentityInfoRepository extends JpaRepository { - - Optional findBySocialTypeAndSocialId(SocialType socialType, String socialId); - -} diff --git a/operation-domain/src/test/java/org/sopt/makers/operation/user/repository/UserRepositoryTest.java b/operation-domain/src/test/java/org/sopt/makers/operation/user/repository/UserRepositoryTest.java deleted file mode 100644 index c9451457..00000000 --- a/operation-domain/src/test/java/org/sopt/makers/operation/user/repository/UserRepositoryTest.java +++ /dev/null @@ -1,283 +0,0 @@ -package org.sopt.makers.operation.user.repository; - -import lombok.val; - -import java.time.LocalDate; -import java.util.List; -import java.util.stream.Stream; - -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.TestMethodOrder; -import org.junit.jupiter.api.MethodOrderer; -import org.junit.jupiter.api.TestInstance; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; - -import org.sopt.makers.operation.user.domain.User; -import org.sopt.makers.operation.user.domain.Gender; -import org.sopt.makers.operation.user.repository.history.UserGenerationHistoryRepository; -import org.sopt.makers.operation.user.dao.UserPersonalInfoUpdateDao; -import org.sopt.makers.operation.DatabaseCleaner; -import org.sopt.makers.operation.exception.UserException; -import org.sopt.makers.operation.code.failure.UserFailureCode; - -import org.springframework.test.context.ActiveProfiles; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.annotation.Rollback; -import org.springframework.boot.autoconfigure.domain.EntityScan; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; -import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; -import org.springframework.beans.factory.annotation.Autowired; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.junit.jupiter.api.TestInstance.Lifecycle; - -@DataJpaTest -@DisplayName("[[ Unit Test ]] - UserRepository") -@EntityScan(basePackages = "org.sopt.makers.operation.user") -@ContextConfiguration(classes = { - UserRepository.class, UserGenerationHistoryRepository.class, - DatabaseCleaner.class -}) -@EnableAutoConfiguration -@ActiveProfiles("test") -@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) -class UserRepositoryTest { - - @Autowired - private UserRepository userRepository; - - @Autowired - private DatabaseCleaner cleaner; - - @Nested - @DisplayName("[TEST] 단일 μœ μ € λŒ€μƒ 단일 ID둜 μ‘°νšŒν•˜λŠ” μ‹œλ‚˜λ¦¬μ˜€") - @TestInstance(Lifecycle.PER_CLASS) - @TestMethodOrder(MethodOrderer.OrderAnnotation.class) - class SingleUserSelectTest { - - @BeforeAll - void setUpCleanerProperties() { - cleaner.execute(); - } - - private User user; - - @BeforeEach - void setUpSingleUser() { - User userEntity = User.builder() - .email("test@test.com") - .phone("010-0000-0000") - .gender(Gender.MALE) - .name("TestUser") - .profileImage("DummyImageUrl") - .birthday(LocalDate.of(1999, 12,4)) - .build(); - user = userRepository.save(userEntity); - } - - @Test - @DisplayName("Case1. 단일 μœ μ €μ— λŒ€ν•œ 쑰회 성곡") - void getSuccessTest() { - // given - val userId = user.getId(); - - // when - val result = userRepository.findUserById(userId); - - // then - assertThat(result.getId()).isEqualTo(userId); - assertThat(result.getName()).isEqualTo("TestUser"); - assertThat(result.getPhone()).isEqualTo("010-0000-0000"); - assertThat(result.getEmail()).isEqualTo("test@test.com"); - assertThat(result.getBirthday()).isEqualTo(LocalDate.of(1999, 12, 4)); - assertThat(result.getGender()).isEqualTo(Gender.MALE); - assertThat(result.getProfileImage()).isEqualTo("DummyImageUrl"); - } - - @Test - @DisplayName("Case2. μ‘΄μž¬ν•˜μ§€ μ•Šμ€ userId일 경우, μ˜ˆμ™Έ λ°˜ν™˜") - void getFailTest() { - // given - val invalidUserId = 0L; - - // when & then - assertThatThrownBy(() -> userRepository.findUserById(invalidUserId)) - .isInstanceOf(UserException.class) - .hasMessageContaining(UserFailureCode.NOT_FOUND_USER.getMessage()); - } - - } - - @Nested - @TestInstance(Lifecycle.PER_CLASS) - @DisplayName("[TEST] μ—¬λŸ¬ μœ μ €κ°€ μ €μž₯된 μƒνƒœμ—μ„œ 단일 ID둜 μ‘°νšŒν•˜λŠ” μ‹œλ‚˜λ¦¬μ˜€") - class MultiUserSelectTest { - - List users; - - @BeforeAll - void setUpMultiUser() { - cleaner.execute(); - User userA = User.builder() - .email("test1@test.com") - .phone("010-0000-0000") - .gender(Gender.MALE) - .name("TestUser1") - .profileImage("DummyImageUrl1") - .birthday(LocalDate.of(1999, 12,4)) - .build(); - User userB = User.builder() - .email("test2@test.com") - .phone("010-1234-0000") - .gender(Gender.FEMALE) - .name("TestUser2") - .profileImage("DummyImageUrl2") - .birthday(LocalDate.of(1999, 12,4)) - .build(); - User userC = User.builder() - .email("test3@test.com") - .phone("010-5678-0000") - .gender(Gender.MALE) - .name("TestUser3") - .profileImage("DummyImageUrl3") - .birthday(LocalDate.of(1999, 12,4)) - .build(); - users = userRepository.saveAll(List.of(userA, userB, userC)); - } - - @Test - @DisplayName("Case1. 볡수 μœ μ € 쑰회 성곡") - void getSuccessTest() { - // given - val ids = List.of(1L, 2L, 3L); - List allUser = userRepository.findAll(); - allUser.forEach(u -> System.out.println(u.getId())); - // when - val result = userRepository.findAllUsersById(ids); - - - // then - assertThat(users).usingRecursiveComparison() - .isEqualTo(result); - } - - @Test - @DisplayName("Case2. μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ” userIdλ₯Ό 가진 경우, μ˜ˆμ™Έ λ°˜ν™˜") - void getFailTest_Include_NotExist_Id() { - // given - val ids = List.of(1L, 2L, 3L, 999L); - - // when & then - assertThatThrownBy(() -> userRepository.findAllUsersById(ids)) - .isInstanceOf(UserException.class) - .hasMessageContaining(UserFailureCode.NOT_FOUND_USER_IN_USER_LIST_PARAMETER.getMessage()); - } - - } - - @Nested - @TestInstance(Lifecycle.PER_CLASS) - @DisplayName("[TEST] 단일 μœ μ € 정보 μˆ˜μ •ν•˜λŠ” μ‹œλ‚˜λ¦¬μ˜€") - class SingleUserUpdateTest { - - private static final long ABSOLUTE_USER_ID_VALUE = 1L; - - private User user; - - @BeforeEach - void setUpUser() { - cleaner.afterPropertiesSet(); - cleaner.execute(); - User userEntity = User.builder() - .email("test@test.com") - .gender(Gender.MALE) - .phone("010-0000-0000") - .name("TestUser") - .profileImage("DummyImageUrl") - .birthday(LocalDate.of(1999, 12,4)) - .build(); - user = userRepository.save(userEntity); - } - - @ParameterizedTest - @DisplayName("Case. 단일 μœ μ €μ— λŒ€ν•œ 전체 데이터 λ³€κ²½ 성곡") - @MethodSource("ofAllDataUpdate") - @Rollback(value = false) - void updateAllDataSuccess( - UserPersonalInfoUpdateDao infoUpdateDao, - String expectedName, - String expectedPhone, - String expectedProfileImageUrl - ) { - // given - User targetUser = userRepository.findUserById(ABSOLUTE_USER_ID_VALUE); - - // when - targetUser.updateUserInfo(infoUpdateDao); - User expectedUser = userRepository.findUserById(ABSOLUTE_USER_ID_VALUE); - - // then - assertThat(expectedUser.getName()).isEqualTo(expectedName); - assertThat(expectedUser.getPhone()).isEqualTo(expectedPhone); - assertThat(expectedUser.getProfileImage()).isEqualTo(expectedProfileImageUrl); - } - static Stream ofAllDataUpdate(){ - return Stream.of( - Arguments.of( - new UserPersonalInfoUpdateDao("κΉ€μ² μˆ˜", "01098765432", "changedProfileImageForCheolSu"), - "κΉ€μ² μˆ˜", "01098765432", "changedProfileImageForCheolSu" - ) - ); - } - - @ParameterizedTest - @DisplayName("Case. 단일 μœ μ €μ— λŒ€ν•œ λΆ€λΆ„ 데이터 λ³€κ²½ 성곡") - @MethodSource("ofPartialDataUpdate") - @Rollback(value = false) - void updatePartialDataSuccess( - UserPersonalInfoUpdateDao infoUpdateDao, - String expectedName, - String expectedPhone, - String expectedProfileImageUrl - ) { - // given - User targetUser = userRepository.findUserById(ABSOLUTE_USER_ID_VALUE); - - // when - targetUser.updateUserInfo(infoUpdateDao); - userRepository.save(targetUser); - User expectedUser = userRepository.findUserById(ABSOLUTE_USER_ID_VALUE); - - // then - assertThat(expectedUser.getName()).isEqualTo(expectedName); - assertThat(expectedUser.getPhone()).isEqualTo(expectedPhone); - assertThat(expectedUser.getProfileImage()).isEqualTo(expectedProfileImageUrl); - } - static Stream ofPartialDataUpdate(){ - return Stream.of( - Arguments.of( - new UserPersonalInfoUpdateDao("κΉ€μ² μˆ˜", "010-0000-0000", "DummyImageUrl"), - "κΉ€μ² μˆ˜", "010-0000-0000", "DummyImageUrl" - ), - Arguments.of( - new UserPersonalInfoUpdateDao("TestUser", "010-1324-5768", "DummyImageUrl"), - "TestUser", "010-1324-5768", "DummyImageUrl" - ), - Arguments.of( - new UserPersonalInfoUpdateDao("TestUser", "010-0000-0000", "changedProfileImage"), - "TestUser", "010-0000-0000", "changedProfileImage" - ) - ); - } - - } - -} \ No newline at end of file diff --git a/operation-external/build.gradle b/operation-external/build.gradle index 57d2903b..882089e5 100644 --- a/operation-external/build.gradle +++ b/operation-external/build.gradle @@ -17,15 +17,6 @@ dependencies { implementation 'software.amazon.awssdk:scheduler' implementation group: 'org.springframework.cloud', name: 'spring-cloud-starter-aws', version: '2.2.6.RELEASE' - implementation 'org.bouncycastle:bcprov-jdk18on:1.75' - implementation 'org.bouncycastle:bcpkix-jdk18on:1.75' - - // jwt builder library - implementation 'io.jsonwebtoken:jjwt-api:0.11.2' - runtimeOnly "io.jsonwebtoken:jjwt-impl:0.11.2" - runtimeOnly "io.jsonwebtoken:jjwt-jackson:0.11.2" - // jwt payload read library - implementation "com.nimbusds:nimbus-jose-jwt:7.8.1" } test { diff --git a/operation-external/src/main/java/org/sopt/makers/operation/client/social/AppleSocialLogin.java b/operation-external/src/main/java/org/sopt/makers/operation/client/social/AppleSocialLogin.java deleted file mode 100644 index 1d2b5a5a..00000000 --- a/operation-external/src/main/java/org/sopt/makers/operation/client/social/AppleSocialLogin.java +++ /dev/null @@ -1,96 +0,0 @@ -package org.sopt.makers.operation.client.social; - -import io.jsonwebtoken.Jwts; -import io.jsonwebtoken.SignatureAlgorithm; -import lombok.RequiredArgsConstructor; -import lombok.val; -import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; -import org.bouncycastle.openssl.PEMParser; -import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter; -import org.sopt.makers.operation.client.social.dto.IdTokenResponse; -import org.sopt.makers.operation.config.ValueConfig; -import org.sopt.makers.operation.exception.AuthException; -import org.springframework.core.io.ClassPathResource; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.http.MediaType; -import org.springframework.stereotype.Component; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.web.client.RestTemplate; - -import java.io.IOException; -import java.io.StringReader; -import java.nio.charset.StandardCharsets; -import java.security.PrivateKey; -import java.util.Collections; -import java.util.Date; -import java.util.Optional; - -import static org.sopt.makers.operation.code.failure.auth.AuthFailureCode.FAILURE_READ_PRIVATE_KEY; - -@Component -@RequiredArgsConstructor -public class AppleSocialLogin { - // 1μ‹œκ°„ - private static final int EXPIRATION_TIME_IN_MILLISECONDS = 3600 * 1000; - private static final String GRANT_TYPE = "authorization_code"; - private static final String HOST = "https://appleid.apple.com/auth/token"; - - private final RestTemplate restTemplate; - private final ValueConfig valueConfig; - - public IdTokenResponse getIdTokenByCode(String code) { - val tokenRequest = new LinkedMultiValueMap<>(); - val clientId = valueConfig.getAppleSub(); - val clientSecret = createClientSecret(); - - tokenRequest.add("client_id", clientId); - tokenRequest.add("client_secret", clientSecret); - tokenRequest.add("code", code); - tokenRequest.add("grant_type", GRANT_TYPE); - - val headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); - headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); - val entity = new HttpEntity<>(tokenRequest, headers); - - return restTemplate.postForObject(HOST, entity, IdTokenResponse.class); - } - - private String createClientSecret() { - val now = new Date(); - val privateKey = getPrivateKey() - .orElseThrow(() -> new AuthException(FAILURE_READ_PRIVATE_KEY)); - val kid = valueConfig.getAppleKeyId(); - val issuer = valueConfig.getAppleTeamId(); - val aud = valueConfig.getAppleAud(); - val sub = valueConfig.getAppleSub(); - - return Jwts.builder() - .setHeaderParam("kid", kid) - .setHeaderParam("alg", "ES256") - .setIssuedAt(now) - .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME_IN_MILLISECONDS)) - .setIssuer(issuer) - .setAudience(aud) - .setSubject(sub) - .signWith(privateKey, SignatureAlgorithm.ES256) - .compact(); - } - - private Optional getPrivateKey() { - val appleKeyPath = valueConfig.getAppleKeyPath(); - try { - val resource = new ClassPathResource(appleKeyPath); - val privateKey = new String(resource.getInputStream().readAllBytes(), StandardCharsets.UTF_8); - val pemReader = new StringReader(privateKey); - val pemParser = new PEMParser(pemReader); - val converter = new JcaPEMKeyConverter(); - val object = (PrivateKeyInfo) pemParser.readObject(); - return Optional.of(converter.getPrivateKey(object)); - } catch (IOException e) { - return Optional.empty(); - } - } - -} diff --git a/operation-external/src/main/java/org/sopt/makers/operation/client/social/GoogleSocialLogin.java b/operation-external/src/main/java/org/sopt/makers/operation/client/social/GoogleSocialLogin.java deleted file mode 100644 index c6860255..00000000 --- a/operation-external/src/main/java/org/sopt/makers/operation/client/social/GoogleSocialLogin.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.sopt.makers.operation.client.social; - -import lombok.RequiredArgsConstructor; -import lombok.val; -import org.sopt.makers.operation.client.social.dto.IdTokenResponse; -import org.sopt.makers.operation.config.ValueConfig; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.http.MediaType; -import org.springframework.stereotype.Component; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.web.client.RestTemplate; - -import java.util.Collections; - -@Component -@RequiredArgsConstructor -public class GoogleSocialLogin { - private static final String GRANT_TYPE = "authorization_code"; - private static final String HOST = "https://oauth2.googleapis.com/token"; - - private final RestTemplate restTemplate; - private final ValueConfig valueConfig; - - public IdTokenResponse getIdTokenByCode(String code) { - val params = new LinkedMultiValueMap<>(); - val clientId = valueConfig.getGoogleClientId(); - val clientSecret = valueConfig.getGoogleClientSecret(); - val redirectUri = valueConfig.getGoogleRedirectUrl(); - - params.add("client_id", clientId); - params.add("client_secret", clientSecret); - params.add("code", code); - params.add("grant_type", GRANT_TYPE); - params.add("redirect_uri", redirectUri); - - val headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); - headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); - val entity = new HttpEntity<>(params, headers); - - return restTemplate.postForObject(HOST, entity, IdTokenResponse.class); - } -} diff --git a/operation-external/src/main/java/org/sopt/makers/operation/client/social/SocialLoginManager.java b/operation-external/src/main/java/org/sopt/makers/operation/client/social/SocialLoginManager.java deleted file mode 100644 index cdd296fd..00000000 --- a/operation-external/src/main/java/org/sopt/makers/operation/client/social/SocialLoginManager.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.sopt.makers.operation.client.social; - -import com.nimbusds.jwt.SignedJWT; -import lombok.RequiredArgsConstructor; -import lombok.val; -import org.sopt.makers.operation.client.social.dto.IdTokenResponse; -import org.sopt.makers.operation.exception.AuthException; -import org.sopt.makers.operation.user.domain.SocialType; -import org.springframework.stereotype.Component; - -import java.text.ParseException; - -import static org.sopt.makers.operation.code.failure.auth.AuthFailureCode.INVALID_ID_TOKEN; - -@Component -@RequiredArgsConstructor -public class SocialLoginManager { - private final AppleSocialLogin appleSocialLogin; - private final GoogleSocialLogin googleSocialLogin; - - public IdTokenResponse getIdTokenByCode(SocialType type, String code) { - return switch (type) { - case APPLE -> appleSocialLogin.getIdTokenByCode(code); - case GOOGLE -> googleSocialLogin.getIdTokenByCode(code); - }; - } - - public String getUserInfo(IdTokenResponse tokenResponse) { - val idToken = tokenResponse.idToken(); - try { - val signedJWT = SignedJWT.parse(idToken); - val payload = signedJWT.getJWTClaimsSet(); - val userId = payload.getSubject(); - return userId; - } catch (ParseException e) { - throw new AuthException(INVALID_ID_TOKEN); - } - } -} diff --git a/operation-external/src/main/java/org/sopt/makers/operation/client/social/dto/IdTokenResponse.java b/operation-external/src/main/java/org/sopt/makers/operation/client/social/dto/IdTokenResponse.java deleted file mode 100644 index 2d92aa1c..00000000 --- a/operation-external/src/main/java/org/sopt/makers/operation/client/social/dto/IdTokenResponse.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.sopt.makers.operation.client.social.dto; - -import com.fasterxml.jackson.annotation.JsonProperty; - -public record IdTokenResponse( - @JsonProperty("id_token") - String idToken -) { -}