diff --git a/src/main/java/com/backend/allreva/auth/application/AuthService.java b/src/main/java/com/backend/allreva/auth/application/AuthService.java new file mode 100644 index 00000000..982afd86 --- /dev/null +++ b/src/main/java/com/backend/allreva/auth/application/AuthService.java @@ -0,0 +1,107 @@ +package com.backend.allreva.auth.application; + +import com.backend.allreva.auth.application.dto.LoginResponse; +import com.backend.allreva.auth.application.dto.ReissueRequest; +import com.backend.allreva.auth.application.dto.ReissueResponse; +import com.backend.allreva.auth.application.dto.UserInfo; +import com.backend.allreva.auth.exception.code.InvalidJwtTokenException; +import com.backend.allreva.auth.exception.code.TokenNotFoundException; +import com.backend.allreva.common.model.Email; +import com.backend.allreva.member.command.domain.Member; +import com.backend.allreva.member.command.domain.MemberRepository; +import com.backend.allreva.member.command.domain.value.LoginProvider; +import java.util.Optional; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@Transactional +@RequiredArgsConstructor +public class AuthService { + + private final OAuth2LoginService oAuth2LoginService; + private final JwtService jwtService; + private final MemberRepository memberRepository; + + /** + * 카카오 로그인을 검증합니다. + * @param authorizationCode 인가 코드 + * @return 로그인 응답 + */ + public LoginResponse kakaoLogin(final String authorizationCode) { + UserInfo userInfo = oAuth2LoginService.getUserInfo(authorizationCode); + + // 회원 존재 확인 + Email emailVO = Email.builder() + .email(userInfo.email()) + .build(); + LoginProvider loginProvider = userInfo.loginProvider(); + Optional memberOptional = memberRepository.findByEmailAndLoginProvider(emailVO, loginProvider); + + if (memberOptional.isPresent()) { + return getMemberInfo(memberOptional.get()); + } + return getTemporaryMemberInfo(userInfo); + + } + + private LoginResponse getTemporaryMemberInfo(final UserInfo userInfo) { + return LoginResponse.builder() + .isUser(false) + .email(userInfo.email()) + .nickname(userInfo.nickname()) + .profileImageUrl(userInfo.profileImageUrl()) + .build(); + } + + private LoginResponse getMemberInfo(final Member member) { + // token 생성 + Long memberId = member.getId(); + String accessToken = jwtService.generateAccessToken(String.valueOf(memberId)); + String refreshToken = jwtService.generateRefreshToken(String.valueOf(memberId)); + + // redis에 RefreshToken 저장 + jwtService.updateRefreshToken(refreshToken, memberId); + + return LoginResponse.builder() + .isUser(true) + .accessToken(accessToken) + .refreshToken(refreshToken) + .email(member.getEmail().getEmail()) + .nickname(member.getMemberInfo().getNickname()) + .profileImageUrl(member.getMemberInfo().getProfileImageUrl()) + .build(); + } + + /** + * Access Token을 재발급합니다. + * @param reissueRequest Refresh Token + * @Return 재발급된 Access Token 및 Refresh Token + */ + public ReissueResponse reissueAccessToken(final ReissueRequest reissueRequest) { + String refreshToken = reissueRequest.refreshToken(); + + // refresh token 검증 + boolean isRefreshTokenValid = jwtService.validateToken(refreshToken); + if (!isRefreshTokenValid) { + throw new InvalidJwtTokenException(); + } + if (!jwtService.isRefreshTokenExist(refreshToken)) { + throw new TokenNotFoundException(); + } + + // access token 재발급 + String memberId = jwtService.extractMemberId(refreshToken); + String generatedAccessToken = jwtService.generateAccessToken(memberId); + + // token rotate + String generateRefreshToken = jwtService.generateRefreshToken(memberId); + jwtService.updateRefreshToken(generateRefreshToken, Long.valueOf(memberId)); + + return ReissueResponse.builder() + .accessToken(generatedAccessToken) + .refreshToken(generateRefreshToken) + .build(); + } +} diff --git a/src/main/java/com/backend/allreva/auth/application/CookieService.java b/src/main/java/com/backend/allreva/auth/application/CookieService.java new file mode 100644 index 00000000..6b3356ca --- /dev/null +++ b/src/main/java/com/backend/allreva/auth/application/CookieService.java @@ -0,0 +1,28 @@ +package com.backend.allreva.auth.application; + +import com.backend.allreva.common.util.CookieUtils; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +@Service +public class CookieService { + + @Value("${jwt.refresh.expiration}") + private int refreshTime; + @Value("${url.name}") + private String domainName; + + public void addRefreshTokenCookie( + final HttpServletResponse response, + final String refreshToken + ) { + CookieUtils.addCookie( + response, + domainName, + "refreshToken", + refreshToken, + refreshTime + ); + } +} diff --git a/src/main/java/com/backend/allreva/auth/application/JwtService.java b/src/main/java/com/backend/allreva/auth/application/JwtService.java index a6c9d6b9..6d84817f 100644 --- a/src/main/java/com/backend/allreva/auth/application/JwtService.java +++ b/src/main/java/com/backend/allreva/auth/application/JwtService.java @@ -24,20 +24,20 @@ public class JwtService { private final SecretKey secretKey; - private final int ACCESS_TIME; - private final int REFRESH_TIME; + private final int accessTime; + private final int refreshTime; private final RefreshTokenRepository refreshTokenRepository; public JwtService( @Value("${jwt.secret-key}") final String secretKey, - @Value("${jwt.access.expiration}") final int ACCESS_TIME, - @Value("${jwt.refresh.expiration}") final int REFRESH_TIME, + @Value("${jwt.access.expiration}") final int accessTime, + @Value("${jwt.refresh.expiration}") final int refreshTime, final RefreshTokenRepository refreshTokenRepository ) { this.secretKey = Keys.hmacShaKeyFor(Decoders.BASE64URL.decode(secretKey)); - this.ACCESS_TIME = ACCESS_TIME; - this.REFRESH_TIME = REFRESH_TIME; + this.accessTime = accessTime; + this.refreshTime = refreshTime; this.refreshTokenRepository = refreshTokenRepository; } @@ -130,7 +130,7 @@ public boolean validateToken(final String token) { */ public String generateAccessToken(final String subject) { Date currentDate = new Date(); - Date expireDate = new Date(currentDate.getTime() + ACCESS_TIME); + Date expireDate = new Date(currentDate.getTime() + accessTime); return Jwts.builder() .subject(subject) @@ -147,7 +147,7 @@ public String generateAccessToken(final String subject) { */ public String generateRefreshToken(final String subject) { Date currentDate = new Date(); - Date expireDate = new Date(currentDate.getTime() + REFRESH_TIME); + Date expireDate = new Date(currentDate.getTime() + refreshTime); return Jwts.builder() .subject(subject) @@ -164,15 +164,24 @@ public String generateRefreshToken(final String subject) { */ public void updateRefreshToken( final String generatedRefreshToken, - final String memberId + final Long memberId ) { - refreshTokenRepository.findRefreshTokenByMemberId(Long.valueOf(memberId)) + refreshTokenRepository.findRefreshTokenByMemberId(memberId) .ifPresent(refreshTokenRepository::delete); RefreshToken refreshTokenEntity = RefreshToken.builder() .token(generatedRefreshToken) - .memberId(Long.valueOf(memberId)) + .memberId(memberId) .build(); refreshTokenRepository.save(refreshTokenEntity); } + + /** + * Refresh Token이 Redis에 존재하는지 확인합니다. + * @param refreshToken Cookie에 저장되있던 Refresh Token + * @return Refresh Token이 존재하면 true, 그렇지 않으면 false + */ + public boolean isRefreshTokenExist(final String refreshToken) { + return refreshTokenRepository.existsRefreshTokenByToken(refreshToken); + } } diff --git a/src/main/java/com/backend/allreva/auth/application/OAuth2LoginService.java b/src/main/java/com/backend/allreva/auth/application/OAuth2LoginService.java new file mode 100644 index 00000000..3d7ea426 --- /dev/null +++ b/src/main/java/com/backend/allreva/auth/application/OAuth2LoginService.java @@ -0,0 +1,8 @@ +package com.backend.allreva.auth.application; + +import com.backend.allreva.auth.application.dto.UserInfo; + +public interface OAuth2LoginService { + + UserInfo getUserInfo(String authorizationCode); +} diff --git a/src/main/java/com/backend/allreva/auth/application/dto/LoginResponse.java b/src/main/java/com/backend/allreva/auth/application/dto/LoginResponse.java new file mode 100644 index 00000000..338411e2 --- /dev/null +++ b/src/main/java/com/backend/allreva/auth/application/dto/LoginResponse.java @@ -0,0 +1,15 @@ +package com.backend.allreva.auth.application.dto; + +import lombok.Builder; + +@Builder +public record LoginResponse( + boolean isUser, + String email, + String nickname, + String profileImageUrl, + String accessToken, + String refreshToken +) { + +} diff --git a/src/main/java/com/backend/allreva/auth/application/dto/LoginSuccessResponse.java b/src/main/java/com/backend/allreva/auth/application/dto/LoginSuccessResponse.java deleted file mode 100644 index 399d23ae..00000000 --- a/src/main/java/com/backend/allreva/auth/application/dto/LoginSuccessResponse.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.backend.allreva.auth.application.dto; - -import lombok.Builder; - -@Builder -public record LoginSuccessResponse( - String accessToken, - String refreshToken, - Long refreshTokenExpirationTime, - String email, - String profileImageUrl -) { - - public static LoginSuccessResponse of( - final String accessToken, - final String refreshToken, - final Long refreshTokenExpirationTime, - final String email, - final String profileImageUrl - ) { - return LoginSuccessResponse.builder() - .accessToken(accessToken) - .refreshToken(refreshToken) - .refreshTokenExpirationTime(refreshTokenExpirationTime) - .email(email) - .profileImageUrl(profileImageUrl) - .build(); - } -} - diff --git a/src/main/java/com/backend/allreva/auth/application/dto/ReissueRequest.java b/src/main/java/com/backend/allreva/auth/application/dto/ReissueRequest.java new file mode 100644 index 00000000..ee45c030 --- /dev/null +++ b/src/main/java/com/backend/allreva/auth/application/dto/ReissueRequest.java @@ -0,0 +1,10 @@ +package com.backend.allreva.auth.application.dto; + +import lombok.Builder; + +@Builder +public record ReissueRequest( + String refreshToken +) { + +} diff --git a/src/main/java/com/backend/allreva/auth/application/dto/ReissueResponse.java b/src/main/java/com/backend/allreva/auth/application/dto/ReissueResponse.java new file mode 100644 index 00000000..a185e0cd --- /dev/null +++ b/src/main/java/com/backend/allreva/auth/application/dto/ReissueResponse.java @@ -0,0 +1,11 @@ +package com.backend.allreva.auth.application.dto; + +import lombok.Builder; + +@Builder +public record ReissueResponse( + String accessToken, + String refreshToken +) { + +} diff --git a/src/main/java/com/backend/allreva/auth/application/dto/UserInfo.java b/src/main/java/com/backend/allreva/auth/application/dto/UserInfo.java new file mode 100644 index 00000000..fc05322b --- /dev/null +++ b/src/main/java/com/backend/allreva/auth/application/dto/UserInfo.java @@ -0,0 +1,15 @@ +package com.backend.allreva.auth.application.dto; + +import com.backend.allreva.member.command.domain.value.LoginProvider; +import lombok.Builder; + +@Builder +public record UserInfo( + LoginProvider loginProvider, + String providerId, + String nickname, + String email, + String profileImageUrl +) { + +} diff --git a/src/main/java/com/backend/allreva/auth/domain/RefreshTokenRepository.java b/src/main/java/com/backend/allreva/auth/domain/RefreshTokenRepository.java index 988a9767..5e2156d9 100644 --- a/src/main/java/com/backend/allreva/auth/domain/RefreshTokenRepository.java +++ b/src/main/java/com/backend/allreva/auth/domain/RefreshTokenRepository.java @@ -5,4 +5,5 @@ public interface RefreshTokenRepository extends CrudRepository { Optional findRefreshTokenByMemberId(Long memberId); + boolean existsRefreshTokenByToken(String token); } \ No newline at end of file diff --git a/src/main/java/com/backend/allreva/auth/exception/code/JwtErrorCode.java b/src/main/java/com/backend/allreva/auth/exception/code/JwtErrorCode.java index 94866a3f..ae4a4892 100644 --- a/src/main/java/com/backend/allreva/auth/exception/code/JwtErrorCode.java +++ b/src/main/java/com/backend/allreva/auth/exception/code/JwtErrorCode.java @@ -13,7 +13,7 @@ public enum JwtErrorCode implements ErrorCodeInterface { INVALID_JWT_TOKEN(HttpStatus.UNAUTHORIZED.value(), "INVALID_JWT_TOKEN", "유효하지 않은 토큰입니다."), INVALID_JWT_SIGNATURE(HttpStatus.UNAUTHORIZED.value(), "INVALID_JWT_SIGNATURE", "유효하지 않은 서명입니다."), EXPIRED_JWT_TOKEN(HttpStatus.UNAUTHORIZED.value(), "EXPIRED_JWT_TOKEN", "토큰이 만료되었습니다."), - JWT_TOKEN_NOT_FOUND(HttpStatus.UNAUTHORIZED.value(), "JWT_TOKEN_NOT_FOUND", "토큰이 존재하지 않습니다."), + JWT_TOKEN_NOT_FOUND(HttpStatus.UNAUTHORIZED.value(), "TOKEN_NOT_FOUND", "토큰이 존재하지 않습니다."), ; private final Integer status; diff --git a/src/main/java/com/backend/allreva/auth/oauth2/exception/OAuth2ErrorCode.java b/src/main/java/com/backend/allreva/auth/exception/code/OAuth2ErrorCode.java similarity index 84% rename from src/main/java/com/backend/allreva/auth/oauth2/exception/OAuth2ErrorCode.java rename to src/main/java/com/backend/allreva/auth/exception/code/OAuth2ErrorCode.java index bc11f790..6df2be45 100644 --- a/src/main/java/com/backend/allreva/auth/oauth2/exception/OAuth2ErrorCode.java +++ b/src/main/java/com/backend/allreva/auth/exception/code/OAuth2ErrorCode.java @@ -1,4 +1,4 @@ -package com.backend.allreva.auth.oauth2.exception; +package com.backend.allreva.auth.exception.code; import org.springframework.http.HttpStatus; @@ -10,7 +10,7 @@ @RequiredArgsConstructor public enum OAuth2ErrorCode implements ErrorCodeInterface { - UNSUPPORTED_PROVIDER(HttpStatus.BAD_REQUEST.value(), "UNSUPPORTED_PROVIDER", "지원하지 않는 provider 입니다.") + UNSUPPORTED_PROVIDER(HttpStatus.BAD_REQUEST.value(), "UNSUPPORTED_PROVIDER", "지원하지 않는 provider 입니다."), ; private final Integer status; diff --git a/src/main/java/com/backend/allreva/auth/exception/code/JwtTokenNotFoundException.java b/src/main/java/com/backend/allreva/auth/exception/code/TokenNotFoundException.java similarity index 61% rename from src/main/java/com/backend/allreva/auth/exception/code/JwtTokenNotFoundException.java rename to src/main/java/com/backend/allreva/auth/exception/code/TokenNotFoundException.java index fb610b60..dac91391 100644 --- a/src/main/java/com/backend/allreva/auth/exception/code/JwtTokenNotFoundException.java +++ b/src/main/java/com/backend/allreva/auth/exception/code/TokenNotFoundException.java @@ -2,9 +2,9 @@ import com.backend.allreva.common.exception.CustomException; -public class JwtTokenNotFoundException extends CustomException { +public class TokenNotFoundException extends CustomException { - public JwtTokenNotFoundException() { + public TokenNotFoundException() { super(JwtErrorCode.JWT_TOKEN_NOT_FOUND); } } diff --git a/src/main/java/com/backend/allreva/auth/oauth2/exception/UnsupportedProviderException.java b/src/main/java/com/backend/allreva/auth/exception/code/UnsupportedProviderException.java similarity index 82% rename from src/main/java/com/backend/allreva/auth/oauth2/exception/UnsupportedProviderException.java rename to src/main/java/com/backend/allreva/auth/exception/code/UnsupportedProviderException.java index 3113d912..bc25ab80 100644 --- a/src/main/java/com/backend/allreva/auth/oauth2/exception/UnsupportedProviderException.java +++ b/src/main/java/com/backend/allreva/auth/exception/code/UnsupportedProviderException.java @@ -1,4 +1,4 @@ -package com.backend.allreva.auth.oauth2.exception; +package com.backend.allreva.auth.exception.code; import com.backend.allreva.common.exception.CustomException; diff --git a/src/main/java/com/backend/allreva/auth/oauth2/KakaoAuthClient.java b/src/main/java/com/backend/allreva/auth/oauth2/KakaoAuthClient.java new file mode 100644 index 00000000..210d10b8 --- /dev/null +++ b/src/main/java/com/backend/allreva/auth/oauth2/KakaoAuthClient.java @@ -0,0 +1,19 @@ +package com.backend.allreva.auth.oauth2; + +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestParam; + +@FeignClient(name = "kakaoAuthClient", url = "${oauth2.kakao.auth-url}") +public interface KakaoAuthClient { + + @PostMapping(value = "/oauth/token", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE) + KakaoToken getToken( + @RequestParam("client_id") String clientId, + @RequestParam("redirect_uri") String redirectUri, + @RequestParam("code") String code, + @RequestParam("grant_type") String grantType, + @RequestParam("client_secret") String clientSecret + ); +} diff --git a/src/main/java/com/backend/allreva/auth/oauth2/KakaoOAuth2LoginService.java b/src/main/java/com/backend/allreva/auth/oauth2/KakaoOAuth2LoginService.java new file mode 100644 index 00000000..8c9fe089 --- /dev/null +++ b/src/main/java/com/backend/allreva/auth/oauth2/KakaoOAuth2LoginService.java @@ -0,0 +1,51 @@ +package com.backend.allreva.auth.oauth2; + +import com.backend.allreva.auth.application.OAuth2LoginService; +import com.backend.allreva.auth.application.dto.UserInfo; +import com.backend.allreva.member.command.domain.value.LoginProvider; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class KakaoOAuth2LoginService implements OAuth2LoginService { + + private final KakaoAuthClient kakaoAuthClient; + private final KakaoUserInfoClient kakaoUserInfoClient; + + @Value("${oauth2.kakao.redirect-uri}") + private String kakaoRedirectUri; + @Value("${oauth2.kakao.client-id}") + private String kakaoClientId; + @Value("${oauth2.kakao.client-secret}") + private String kakaoClientSecret; + + /** + * 카카오 로그인 시 사용자 정보를 가져옵니다. + * @param authorizationCode 인가 코드 + * @return 사용자 정보 + */ + @Override + public UserInfo getUserInfo(final String authorizationCode) { + KakaoToken token = kakaoAuthClient.getToken( + kakaoClientId, + kakaoRedirectUri, + authorizationCode, + "authorization_code", + kakaoClientSecret + ); + + KakaoUserInfo kakaoUserInfo = kakaoUserInfoClient.getUserInfo( + "Bearer " + token.accessToken() + ); + + return UserInfo.builder() + .loginProvider(LoginProvider.KAKAO) + .providerId(kakaoUserInfo.id()) + .email(kakaoUserInfo.kakaoAccount().email()) + .nickname(kakaoUserInfo.kakaoAccount().profile().nickname()) + .profileImageUrl(kakaoUserInfo.kakaoAccount().profile().profileImageUrl()) + .build(); + } +} diff --git a/src/main/java/com/backend/allreva/auth/oauth2/KakaoToken.java b/src/main/java/com/backend/allreva/auth/oauth2/KakaoToken.java new file mode 100644 index 00000000..659ebb30 --- /dev/null +++ b/src/main/java/com/backend/allreva/auth/oauth2/KakaoToken.java @@ -0,0 +1,15 @@ +package com.backend.allreva.auth.oauth2; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public record KakaoToken( + @JsonProperty("access_token") String accessToken, + @JsonProperty("refresh_token") String refreshToken, + @JsonProperty("token_type") String tokenType, + @JsonProperty("expires_in") int expiresIn, + @JsonProperty("refresh_token_expires_in") int refreshTokenExpiresIn +) { + +} diff --git a/src/main/java/com/backend/allreva/auth/oauth2/KakaoUserInfo.java b/src/main/java/com/backend/allreva/auth/oauth2/KakaoUserInfo.java new file mode 100644 index 00000000..84cf3632 --- /dev/null +++ b/src/main/java/com/backend/allreva/auth/oauth2/KakaoUserInfo.java @@ -0,0 +1,26 @@ +package com.backend.allreva.auth.oauth2; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public record KakaoUserInfo( + @JsonProperty("id") String id, + @JsonProperty("kakao_account") KakaoAccount kakaoAccount +) { + + @JsonIgnoreProperties(ignoreUnknown = true) + public record KakaoAccount( + @JsonProperty("email") String email, + @JsonProperty("profile") Profile profile + ) { + + @JsonIgnoreProperties(ignoreUnknown = true) + public record Profile( + @JsonProperty("nickname") String nickname, + @JsonProperty("profile_image_url") String profileImageUrl + ) { + + } + } +} diff --git a/src/main/java/com/backend/allreva/auth/oauth2/KakaoUserInfoClient.java b/src/main/java/com/backend/allreva/auth/oauth2/KakaoUserInfoClient.java new file mode 100644 index 00000000..436bb6c5 --- /dev/null +++ b/src/main/java/com/backend/allreva/auth/oauth2/KakaoUserInfoClient.java @@ -0,0 +1,12 @@ +package com.backend.allreva.auth.oauth2; + +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestHeader; + +@FeignClient(name = "kakaoUserInfoClient", url = "${oauth2.kakao.api-url}") +public interface KakaoUserInfoClient { + + @GetMapping("/v2/user/me") + KakaoUserInfo getUserInfo(@RequestHeader("Authorization") String accessToken); +} diff --git a/src/main/java/com/backend/allreva/auth/oauth2/application/CustomOAuth2UserService.java b/src/main/java/com/backend/allreva/auth/oauth2/application/CustomOAuth2UserService.java deleted file mode 100644 index 64e20a73..00000000 --- a/src/main/java/com/backend/allreva/auth/oauth2/application/CustomOAuth2UserService.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.backend.allreva.auth.oauth2.application; - -import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService; -import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest; -import org.springframework.security.oauth2.core.OAuth2AuthenticationException; -import org.springframework.security.oauth2.core.user.OAuth2User; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import com.backend.allreva.auth.application.dto.PrincipalDetails; -import com.backend.allreva.auth.oauth2.application.dto.OAuth2UserInfo; -import com.backend.allreva.auth.oauth2.exception.UnsupportedProviderException; -import com.backend.allreva.common.model.Email; -import com.backend.allreva.member.command.domain.MemberRepository; -import com.backend.allreva.member.command.domain.value.LoginProvider; -import com.backend.allreva.member.command.domain.Member; - -import lombok.RequiredArgsConstructor; - -@Service -@RequiredArgsConstructor -public class CustomOAuth2UserService extends DefaultOAuth2UserService { - - private final MemberRepository memberRepository; - - @Transactional - @Override - public OAuth2User loadUser(final OAuth2UserRequest userRequest) throws OAuth2AuthenticationException { - // 1 - OAuth2 Client를 사용하여 Auth Server로부터 유저 정보 가져오기 - OAuth2User oAuth2User = super.loadUser(userRequest); - - // 2 - socialType 가져오기(third-party id) - String socialType = userRequest.getClientRegistration().getRegistrationId(); - - // 3 - 유저 정보 dto 생성(Auth Server로부터 받은 attributes들을 토대로 유저 정보 DTO를 만듬) - OAuth2UserInfo oAuth2UserInfo = switch (socialType) { - case "google" -> OAuth2UserInfo.ofGoogle(oAuth2User.getAttributes()); - case "kakao" -> OAuth2UserInfo.ofKakao(oAuth2User.getAttributes()); - default -> throw new UnsupportedProviderException(); // ISSUE: 해당 정보 가져오기 전에 이미 Filter단에서 미리 구현된 다른 예외가 잡힘 - }; - - // 4 - 회원 존재 확인, 없다면 임시 회원 정보 생성 - Email emailVO = Email.builder() - .email(oAuth2UserInfo.email()) - .build(); - LoginProvider loginProvider = oAuth2UserInfo.loginProvider(); - Member member = memberRepository.findByEmailAndLoginProvider(emailVO, loginProvider) - .orElseGet(() -> registerTemporaryMember(oAuth2UserInfo)); - - // 5 - OAuth2User로 반환 - return new PrincipalDetails(member, oAuth2User.getAttributes()); - } - - private Member registerTemporaryMember(final OAuth2UserInfo oAuth2UserInfo) { - Member temporaryMember = Member.createTemporary( - oAuth2UserInfo.email(), - oAuth2UserInfo.nickname(), - oAuth2UserInfo.loginProvider(), - oAuth2UserInfo.profile()); - return memberRepository.save(temporaryMember); - } -} diff --git a/src/main/java/com/backend/allreva/auth/oauth2/application/dto/OAuth2UserInfo.java b/src/main/java/com/backend/allreva/auth/oauth2/application/dto/OAuth2UserInfo.java deleted file mode 100644 index 3a19c0c0..00000000 --- a/src/main/java/com/backend/allreva/auth/oauth2/application/dto/OAuth2UserInfo.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.backend.allreva.auth.oauth2.application.dto; - -import java.util.Map; - -import com.backend.allreva.member.command.domain.value.LoginProvider; - -import lombok.Builder; - -@Builder -public record OAuth2UserInfo( - LoginProvider loginProvider, - String providerId, - String nickname, - String email, - String profile) { - - public static OAuth2UserInfo ofGoogle(final Map attributes) { - return OAuth2UserInfo.builder() - .loginProvider(LoginProvider.GOOGLE) - .providerId((String) attributes.get("sub")) - .nickname((String) attributes.get("name")) - .email((String) attributes.get("email")) - .profile((String) attributes.get("picture")) - .build(); - } - - public static OAuth2UserInfo ofKakao(final Map attributes) { - @SuppressWarnings("unchecked") - Map account = (Map) attributes.get("kakao_account"); - @SuppressWarnings("unchecked") - Map profile = (Map) account.get("profile"); - Long providerId = (Long) attributes.get("id"); - - return OAuth2UserInfo.builder() - .loginProvider(LoginProvider.KAKAO) - .providerId(String.valueOf(providerId)) - .nickname((String) profile.get("nickname")) - .email((String) account.get("email")) - .profile((String) profile.get("profile_image_url")) - .build(); - } -} diff --git a/src/main/java/com/backend/allreva/auth/oauth2/handler/OAuth2LoginFailureHandler.java b/src/main/java/com/backend/allreva/auth/oauth2/handler/OAuth2LoginFailureHandler.java deleted file mode 100644 index f4a3c927..00000000 --- a/src/main/java/com/backend/allreva/auth/oauth2/handler/OAuth2LoginFailureHandler.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.backend.allreva.auth.oauth2.handler; - -import com.backend.allreva.auth.exception.code.UnauthorizedException; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import java.io.IOException; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.security.core.AuthenticationException; -import org.springframework.security.web.authentication.AuthenticationFailureHandler; -import org.springframework.stereotype.Component; -import org.springframework.web.servlet.HandlerExceptionResolver; - -@Slf4j -@Component -public class OAuth2LoginFailureHandler implements AuthenticationFailureHandler { - - private final HandlerExceptionResolver resolver; - - public OAuth2LoginFailureHandler( - @Qualifier("handlerExceptionResolver") final HandlerExceptionResolver resolver - ) { - this.resolver = resolver; - } - - @Override - public void onAuthenticationFailure( - final HttpServletRequest request, - final HttpServletResponse response, - final AuthenticationException exception - ) throws IOException, ServletException { - UnauthorizedException unauthorizedException = new UnauthorizedException(exception.getLocalizedMessage()); - resolver.resolveException(request, response, null, unauthorizedException); - } -} diff --git a/src/main/java/com/backend/allreva/auth/oauth2/handler/OAuth2LoginSuccessHandler.java b/src/main/java/com/backend/allreva/auth/oauth2/handler/OAuth2LoginSuccessHandler.java deleted file mode 100644 index eb759896..00000000 --- a/src/main/java/com/backend/allreva/auth/oauth2/handler/OAuth2LoginSuccessHandler.java +++ /dev/null @@ -1,83 +0,0 @@ -package com.backend.allreva.auth.oauth2.handler; - -import com.backend.allreva.auth.application.JwtService; -import com.backend.allreva.auth.application.dto.PrincipalDetails; -import com.backend.allreva.auth.domain.RefreshToken; -import com.backend.allreva.auth.domain.RefreshTokenRepository; -import com.backend.allreva.common.util.CookieUtils; -import com.backend.allreva.member.command.domain.Member; -import com.backend.allreva.member.command.domain.value.MemberRole; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.net.URLEncoder; -import java.nio.charset.StandardCharsets; -import lombok.RequiredArgsConstructor; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.security.core.Authentication; -import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler; -import org.springframework.stereotype.Component; - -@Component -@RequiredArgsConstructor -public class OAuth2LoginSuccessHandler extends SimpleUrlAuthenticationSuccessHandler { - - private static final String FRONT_BASE_URL = "https://allreva.shop"; //http://localhost:3000 - private static final String FRONT_SIGNUP_URL = "/signup"; - - private final JwtService jwtService; - private final RefreshTokenRepository refreshTokenRepository; - @Value("${jwt.refresh.expiration}") - private int REFRESH_TIME; - @Value("${jwt.access.expiration}") - private int ACCESS_TIME; - - /** - * OAuth2 인증 success시 JWT 반환하는 메서드 - * - * OAuth2는 OAuth2UserService에서 이미 인증되기 때문에 별도의 인증 filter가 필요없다. - */ - @Override - public void onAuthenticationSuccess( - final HttpServletRequest request, - final HttpServletResponse response, - final Authentication authentication - ) throws IOException, ServletException { - // OAuth2 인증된 사용자 정보 가져오기 - PrincipalDetails oAuth2User = (PrincipalDetails) authentication.getPrincipal(); - Member member = oAuth2User.member(); - - // token 생성 - Long memberId = member.getId(); - String accessToken = jwtService.generateAccessToken(String.valueOf(memberId)); - String refreshToken = jwtService.generateRefreshToken(String.valueOf(memberId)); - - // redis에 RefreshToken 저장 - refreshTokenRepository.findRefreshTokenByMemberId(memberId) - .ifPresent(refreshTokenRepository::delete); - RefreshToken refreshTokenEntity = RefreshToken.builder() - .token(refreshToken) - .memberId(memberId) - .build(); - refreshTokenRepository.save(refreshTokenEntity); - - // refreshToken 쿠키 등록 - CookieUtils.addCookie(response, "accessToken", accessToken, ACCESS_TIME); - CookieUtils.addCookie(response, "refreshToken", refreshToken, REFRESH_TIME); - - sendRedirect(response, member, accessToken); - } - - private void sendRedirect( - final HttpServletResponse response, - final Member member, - final String accessToken - ) throws IOException { - if (member.getMemberRole().equals(MemberRole.USER)) { - response.sendRedirect(FRONT_BASE_URL + "/auth-success?accessToken=" + URLEncoder.encode(accessToken, StandardCharsets.UTF_8)); - } else { - response.sendRedirect(FRONT_BASE_URL + FRONT_SIGNUP_URL + "/auth-success?accessToken=" + URLEncoder.encode(accessToken, StandardCharsets.UTF_8)); - } - } -} \ No newline at end of file diff --git a/src/main/java/com/backend/allreva/auth/application/AuthMember.java b/src/main/java/com/backend/allreva/auth/security/AuthMember.java similarity index 90% rename from src/main/java/com/backend/allreva/auth/application/AuthMember.java rename to src/main/java/com/backend/allreva/auth/security/AuthMember.java index 4fc0e6fa..de06eaed 100644 --- a/src/main/java/com/backend/allreva/auth/application/AuthMember.java +++ b/src/main/java/com/backend/allreva/auth/security/AuthMember.java @@ -1,4 +1,4 @@ -package com.backend.allreva.auth.application; +package com.backend.allreva.auth.security; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/src/main/java/com/backend/allreva/auth/exception/CustomAccessDeniedHandler.java b/src/main/java/com/backend/allreva/auth/security/CustomAccessDeniedHandler.java similarity index 97% rename from src/main/java/com/backend/allreva/auth/exception/CustomAccessDeniedHandler.java rename to src/main/java/com/backend/allreva/auth/security/CustomAccessDeniedHandler.java index a1bb100f..704e6fbe 100644 --- a/src/main/java/com/backend/allreva/auth/exception/CustomAccessDeniedHandler.java +++ b/src/main/java/com/backend/allreva/auth/security/CustomAccessDeniedHandler.java @@ -1,4 +1,4 @@ -package com.backend.allreva.auth.exception; +package com.backend.allreva.auth.security; import com.backend.allreva.auth.exception.code.CustomAccessDeniedException; import java.io.IOException; diff --git a/src/main/java/com/backend/allreva/auth/exception/CustomAuthenticationEntryPoint.java b/src/main/java/com/backend/allreva/auth/security/CustomAuthenticationEntryPoint.java similarity index 97% rename from src/main/java/com/backend/allreva/auth/exception/CustomAuthenticationEntryPoint.java rename to src/main/java/com/backend/allreva/auth/security/CustomAuthenticationEntryPoint.java index ed6d4fec..4c96127b 100644 --- a/src/main/java/com/backend/allreva/auth/exception/CustomAuthenticationEntryPoint.java +++ b/src/main/java/com/backend/allreva/auth/security/CustomAuthenticationEntryPoint.java @@ -1,4 +1,4 @@ -package com.backend.allreva.auth.exception; +package com.backend.allreva.auth.security; import com.backend.allreva.auth.exception.code.UnauthorizedException; import jakarta.servlet.ServletException; diff --git a/src/main/java/com/backend/allreva/auth/application/CustomUserDetailsService.java b/src/main/java/com/backend/allreva/auth/security/CustomUserDetailsService.java similarity index 84% rename from src/main/java/com/backend/allreva/auth/application/CustomUserDetailsService.java rename to src/main/java/com/backend/allreva/auth/security/CustomUserDetailsService.java index 545b4bb4..e65cd0c8 100644 --- a/src/main/java/com/backend/allreva/auth/application/CustomUserDetailsService.java +++ b/src/main/java/com/backend/allreva/auth/security/CustomUserDetailsService.java @@ -1,11 +1,10 @@ -package com.backend.allreva.auth.application; +package com.backend.allreva.auth.security; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.stereotype.Component; -import com.backend.allreva.auth.application.dto.PrincipalDetails; import com.backend.allreva.member.command.domain.MemberRepository; import com.backend.allreva.member.command.domain.Member; import com.backend.allreva.member.exception.MemberNotFoundException; @@ -23,6 +22,6 @@ public UserDetails loadUserByUsername(final String memberId) throws UsernameNotF Member member = memberRepository.findById(Long.valueOf(memberId)) .orElseThrow(MemberNotFoundException::new); - return new PrincipalDetails(member, null); + return new PrincipalDetails(member); } } \ No newline at end of file diff --git a/src/main/java/com/backend/allreva/auth/filter/JwtAuthenticationFilter.java b/src/main/java/com/backend/allreva/auth/security/JwtAuthenticationFilter.java similarity index 75% rename from src/main/java/com/backend/allreva/auth/filter/JwtAuthenticationFilter.java rename to src/main/java/com/backend/allreva/auth/security/JwtAuthenticationFilter.java index 41946a64..e9fdaadc 100644 --- a/src/main/java/com/backend/allreva/auth/filter/JwtAuthenticationFilter.java +++ b/src/main/java/com/backend/allreva/auth/security/JwtAuthenticationFilter.java @@ -1,4 +1,4 @@ -package com.backend.allreva.auth.filter; +package com.backend.allreva.auth.security; import com.backend.allreva.auth.application.JwtService; import com.backend.allreva.auth.exception.code.InvalidJwtTokenException; @@ -25,20 +25,20 @@ @Profile("!local") public class JwtAuthenticationFilter extends OncePerRequestFilter { - private final int ACCESS_TIME; - private final int REFRESH_TIME; + private final int refreshTime; + private final String domainName; private final JwtService jwtService; private final UserDetailsService userDetailsService; public JwtAuthenticationFilter( - @Value("${jwt.access.expiration}") final int ACCESS_TIME, - @Value("${jwt.refresh.expiration}") final int REFRESH_TIME, + @Value("${jwt.refresh.expiration}") final int refreshTime, + @Value("${url.name}") final String domainName, final JwtService jwtService, final UserDetailsService userDetailsService ) { - this.ACCESS_TIME = ACCESS_TIME; - this.REFRESH_TIME = REFRESH_TIME; + this.refreshTime = refreshTime; + this.domainName = domainName; this.jwtService = jwtService; this.userDetailsService = userDetailsService; } @@ -56,42 +56,34 @@ protected void doFilterInternal( String accessToken = jwtService.extractAccessToken(request); String refreshToken = jwtService.extractRefreshToken(request); + // ANONYMOUS 요청 처리 if (accessToken == null && refreshToken == null) { filterChain.doFilter(request, response); return; } - // 토큰 검증 결과 boolean 변수로 분리 - boolean isAccessTokenValid = jwtService.validateToken(accessToken); + // Refresh Token 검증 boolean isRefreshTokenValid = jwtService.validateToken(refreshToken); - - String memberId = ""; - - // Access도 Refresh도 둘 다 유효하지 않으면 예외 발생 - if (!isAccessTokenValid && !isRefreshTokenValid) { + if (!isRefreshTokenValid) { throw new InvalidJwtTokenException(); } - // Access Token이 유효하지 않으나, Refresh Token은 유효한 경우 => Access Token 및 Refresh Token 재발급 + // Access Token 검증 + boolean isAccessTokenValid = jwtService.validateToken(accessToken); + String memberId; + + // Access Token X, Refresh Token O => Access Token 및 Refresh Token 재발급 if (!isAccessTokenValid) { memberId = jwtService.extractMemberId(refreshToken); reissueAccessToken(memberId, response); - reissueRefreshToken(memberId, response); + reissueRefreshToken(memberId, response); // token rotate } - - // Access Token이 유효하고, Refresh Token이 유효하지 않은 경우 => Refresh Token 재발급 - if (isAccessTokenValid && !isRefreshTokenValid) { + // Access Token O, Refresh Token O + else { memberId = jwtService.extractMemberId(accessToken); - reissueRefreshToken(memberId, response); } - if (isAccessTokenValid && isRefreshTokenValid) { - memberId = jwtService.extractMemberId(accessToken); - } - - // Authentication Security Holder에 저장 setAuthenication(memberId, request); - filterChain.doFilter(request, response); } @@ -105,8 +97,8 @@ private void reissueRefreshToken( final HttpServletResponse response ) { String generatedRefreshToken = jwtService.generateRefreshToken(memberId); - CookieUtils.addCookie(response, "refreshToken", generatedRefreshToken, REFRESH_TIME); - jwtService.updateRefreshToken(generatedRefreshToken, memberId); + CookieUtils.addCookie(response, "refreshToken", domainName, generatedRefreshToken, refreshTime); + jwtService.updateRefreshToken(generatedRefreshToken, Long.valueOf(memberId)); } /** @@ -119,7 +111,7 @@ private void reissueAccessToken( final HttpServletResponse response ) { String generatedAccessToken = jwtService.generateAccessToken(memberId); - CookieUtils.addCookie(response, "accessToken", generatedAccessToken, ACCESS_TIME); + response.addHeader("Authorization", "Bearer " + generatedAccessToken); } /** diff --git a/src/main/java/com/backend/allreva/auth/exception/JwtExceptionFilter.java b/src/main/java/com/backend/allreva/auth/security/JwtExceptionFilter.java similarity index 97% rename from src/main/java/com/backend/allreva/auth/exception/JwtExceptionFilter.java rename to src/main/java/com/backend/allreva/auth/security/JwtExceptionFilter.java index 26a8cef4..c6851758 100644 --- a/src/main/java/com/backend/allreva/auth/exception/JwtExceptionFilter.java +++ b/src/main/java/com/backend/allreva/auth/security/JwtExceptionFilter.java @@ -1,4 +1,4 @@ -package com.backend.allreva.auth.exception; +package com.backend.allreva.auth.security; import com.backend.allreva.common.exception.CustomException; import jakarta.servlet.FilterChain; diff --git a/src/main/java/com/backend/allreva/auth/application/dto/PrincipalDetails.java b/src/main/java/com/backend/allreva/auth/security/PrincipalDetails.java similarity index 57% rename from src/main/java/com/backend/allreva/auth/application/dto/PrincipalDetails.java rename to src/main/java/com/backend/allreva/auth/security/PrincipalDetails.java index 00e1083d..db9c02ef 100644 --- a/src/main/java/com/backend/allreva/auth/application/dto/PrincipalDetails.java +++ b/src/main/java/com/backend/allreva/auth/security/PrincipalDetails.java @@ -1,30 +1,19 @@ -package com.backend.allreva.auth.application.dto; +package com.backend.allreva.auth.security; +import com.backend.allreva.member.command.domain.Member; import java.util.Collection; import java.util.Collections; -import java.util.Map; - +import lombok.Getter; +import lombok.RequiredArgsConstructor; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.oauth2.core.user.OAuth2User; -import com.backend.allreva.member.command.domain.Member; +@Getter +@RequiredArgsConstructor +public class PrincipalDetails implements UserDetails { -public record PrincipalDetails( - Member member, - Map attributes -) implements OAuth2User, UserDetails { - - @Override - public Map getAttributes() { - return attributes != null ? attributes : Collections.emptyMap(); - } - - @Override - public String getName() { - return member.getMemberInfo().getNickname(); - } + private final Member member; @Override public Collection getAuthorities() { diff --git a/src/main/java/com/backend/allreva/auth/filter/TestAuthenticationFilter.java b/src/main/java/com/backend/allreva/auth/security/TestAuthenticationFilter.java similarity index 94% rename from src/main/java/com/backend/allreva/auth/filter/TestAuthenticationFilter.java rename to src/main/java/com/backend/allreva/auth/security/TestAuthenticationFilter.java index 5bd22d03..51059b74 100644 --- a/src/main/java/com/backend/allreva/auth/filter/TestAuthenticationFilter.java +++ b/src/main/java/com/backend/allreva/auth/security/TestAuthenticationFilter.java @@ -1,6 +1,5 @@ -package com.backend.allreva.auth.filter; +package com.backend.allreva.auth.security; -import com.backend.allreva.auth.application.dto.PrincipalDetails; import com.backend.allreva.member.command.domain.Member; import com.backend.allreva.member.command.domain.MemberRepository; import com.backend.allreva.member.command.domain.value.MemberRole; @@ -41,7 +40,7 @@ protected void doFilterInternal( } public void setAuthentication(final Member member) { - PrincipalDetails principalDetails = new PrincipalDetails(member, null); + PrincipalDetails principalDetails = new PrincipalDetails(member); Authentication authentication = new UsernamePasswordAuthenticationToken( principalDetails, null, List.of(new SimpleGrantedAuthority("ROLE_DEVELOPER")) ); diff --git a/src/main/java/com/backend/allreva/auth/ui/AuthController.java b/src/main/java/com/backend/allreva/auth/ui/AuthController.java new file mode 100644 index 00000000..9aadcf28 --- /dev/null +++ b/src/main/java/com/backend/allreva/auth/ui/AuthController.java @@ -0,0 +1,47 @@ +package com.backend.allreva.auth.ui; + +import com.backend.allreva.auth.application.AuthService; +import com.backend.allreva.auth.application.CookieService; +import com.backend.allreva.auth.application.dto.LoginResponse; +import com.backend.allreva.auth.application.dto.ReissueRequest; +import com.backend.allreva.auth.application.dto.ReissueResponse; +import com.backend.allreva.common.dto.Response; +import jakarta.servlet.http.HttpServletResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +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 AuthController implements AuthControllerSwagger { + + private final AuthService authService; + private final CookieService cookieService; + + @GetMapping("/token/kakao") + public Response authKakaoLogin( + @RequestParam("code") final String authorizationCode, + final HttpServletResponse response + ) { + LoginResponse loginResponse = authService.kakaoLogin(authorizationCode); + if (loginResponse.isUser()) { + cookieService.addRefreshTokenCookie(response, loginResponse.refreshToken()); + } + return Response.onSuccess(loginResponse); + } + + @PostMapping("/token/reissue") + public Response reissueToken( + @RequestBody final ReissueRequest reissueRequest, + final HttpServletResponse response + ) { + ReissueResponse reissueResponse = authService.reissueAccessToken(reissueRequest); + cookieService.addRefreshTokenCookie(response, reissueResponse.refreshToken()); + return Response.onSuccess(reissueResponse); + } +} diff --git a/src/main/java/com/backend/allreva/auth/ui/AuthControllerSwagger.java b/src/main/java/com/backend/allreva/auth/ui/AuthControllerSwagger.java new file mode 100644 index 00000000..798e6c3b --- /dev/null +++ b/src/main/java/com/backend/allreva/auth/ui/AuthControllerSwagger.java @@ -0,0 +1,26 @@ +package com.backend.allreva.auth.ui; + +import com.backend.allreva.auth.application.dto.LoginResponse; +import com.backend.allreva.auth.application.dto.ReissueRequest; +import com.backend.allreva.auth.application.dto.ReissueResponse; +import com.backend.allreva.common.dto.Response; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.http.HttpServletResponse; + +@Tag(name = "회원 인증 및 인가 API", description = "인증 및 인가를 처리합니다") +public interface AuthControllerSwagger { + + @Operation(summary = "kakao oauth2 인가코드 요청", description = "인가코드를 바탕으로 사용자를 인증합니다.\n" + + "먼저 카카오 로그인을 한 후에 authorization code를 받아서 이를 파라미터로 넘겨야 합니다.") + Response authKakaoLogin( + String authorizationCode, + HttpServletResponse response + ); + + @Operation(summary = "access token 재발급 요청", description = "refresh token을 이용하여 access token을 재발급합니다.") + Response reissueToken( + ReissueRequest reissueRequest, + HttpServletResponse response + ); +} diff --git a/src/main/java/com/backend/allreva/auth/ui/OAuth2Controller.java b/src/main/java/com/backend/allreva/auth/ui/OAuth2Controller.java deleted file mode 100644 index 20852758..00000000 --- a/src/main/java/com/backend/allreva/auth/ui/OAuth2Controller.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.backend.allreva.auth.ui; - -import com.backend.allreva.auth.application.AuthMember; -import com.backend.allreva.member.command.application.MemberCommandFacade; -import com.backend.allreva.member.command.application.request.MemberInfoRequest; -import com.backend.allreva.member.command.domain.Member; -import lombok.RequiredArgsConstructor; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -@RestController -@RequiredArgsConstructor -@RequestMapping("/api/v1/oauth2") -public class OAuth2Controller implements OAuth2ControllerSwagger{ - - @GetMapping("/login") - public ResponseEntity login() { - return null; - } -} diff --git a/src/main/java/com/backend/allreva/auth/ui/OAuth2ControllerSwagger.java b/src/main/java/com/backend/allreva/auth/ui/OAuth2ControllerSwagger.java deleted file mode 100644 index 3c65d8ac..00000000 --- a/src/main/java/com/backend/allreva/auth/ui/OAuth2ControllerSwagger.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.backend.allreva.auth.ui; - -import com.backend.allreva.auth.application.AuthMember; -import com.backend.allreva.member.command.application.request.MemberInfoRequest; -import com.backend.allreva.member.command.domain.Member; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; -import org.springframework.http.ResponseEntity; - -@Tag(name = "회원 OAuth2 로그인 API") -public interface OAuth2ControllerSwagger { - - @Operation( - summary = "oauth2 로그인", - description = """ - oauth2 로그인 API - - 먼저 로그인을 다음 주소로 login한 후 token 주소를 얻습니다. - - ex) `/api/v1/oauth2/login/kakao` - - 이후 token을 이용하여 회원가입 절차를 진행합니다. - - 두 절차를 모두 거치면 USER 권한을 가진 Member로 등록됩니다. - - ⚠️ 주의: 테스트 환경에서는 oauth2 API가 유효하지 않습니다. 로컬 테스트일 경우 /test-developer로 개발자 모드를 활성화하세요. - """ - ) - ResponseEntity login(); -} diff --git a/src/main/java/com/backend/allreva/common/config/SecurityConfig.java b/src/main/java/com/backend/allreva/common/config/SecurityConfig.java index fea38ab5..1b578c80 100644 --- a/src/main/java/com/backend/allreva/common/config/SecurityConfig.java +++ b/src/main/java/com/backend/allreva/common/config/SecurityConfig.java @@ -1,14 +1,15 @@ package com.backend.allreva.common.config; -import static com.backend.allreva.common.config.SecurityEndpointPaths.*; +import static com.backend.allreva.common.config.SecurityEndpointPaths.ADMIN_LIST; +import static com.backend.allreva.common.config.SecurityEndpointPaths.ANONYMOUS_LIST; +import static com.backend.allreva.common.config.SecurityEndpointPaths.ANONYMOUS_LIST_GET; +import static com.backend.allreva.common.config.SecurityEndpointPaths.USER_LIST_GET; +import static com.backend.allreva.common.config.SecurityEndpointPaths.WHITE_LIST; -import com.backend.allreva.auth.exception.CustomAccessDeniedHandler; -import com.backend.allreva.auth.exception.CustomAuthenticationEntryPoint; -import com.backend.allreva.auth.exception.JwtExceptionFilter; -import com.backend.allreva.auth.filter.JwtAuthenticationFilter; -import com.backend.allreva.auth.oauth2.application.CustomOAuth2UserService; -import com.backend.allreva.auth.oauth2.handler.OAuth2LoginFailureHandler; -import com.backend.allreva.auth.oauth2.handler.OAuth2LoginSuccessHandler; +import com.backend.allreva.auth.security.CustomAccessDeniedHandler; +import com.backend.allreva.auth.security.CustomAuthenticationEntryPoint; +import com.backend.allreva.auth.security.JwtAuthenticationFilter; +import com.backend.allreva.auth.security.JwtExceptionFilter; import lombok.RequiredArgsConstructor; import org.springframework.boot.autoconfigure.security.servlet.PathRequest; import org.springframework.context.annotation.Bean; @@ -19,7 +20,6 @@ import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; import org.springframework.security.config.annotation.web.configurers.CsrfConfigurer; import org.springframework.security.config.annotation.web.configurers.FormLoginConfigurer; import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer; @@ -39,10 +39,6 @@ public class SecurityConfig { private final CustomAccessDeniedHandler customAccessDeniedHandler; private final JwtAuthenticationFilter jwtAuthenticationFilter; private final JwtExceptionFilter jwtExceptionFilter; - // OAuth2 - private final CustomOAuth2UserService customOAuth2UserService; - private final OAuth2LoginSuccessHandler oAuth2LoginSuccessHandler; - private final OAuth2LoginFailureHandler oAuth2LoginFailureHandler; @Bean public SecurityFilterChain filterChain(final HttpSecurity http) throws Exception { @@ -58,20 +54,9 @@ public SecurityFilterChain filterChain(final HttpSecurity http) throws Exception .requestMatchers(WHITE_LIST).permitAll() .requestMatchers(ADMIN_LIST).hasRole("ADMIN") .requestMatchers(HttpMethod.GET, USER_LIST_GET).hasRole("USER") - .requestMatchers(GUEST_LIST).hasRole("GUEST") .requestMatchers(ANONYMOUS_LIST).permitAll() .requestMatchers(HttpMethod.GET, ANONYMOUS_LIST_GET).permitAll() - .anyRequest().authenticated()) - .httpBasic(AbstractHttpConfigurer::disable); - - // OAuth2 인증 필터 - http - .oauth2Login(customConfigurer -> customConfigurer - .authorizationEndpoint(end -> end.baseUri("/api/v1/oauth2/login")) - .userInfoEndpoint(endPointConfig -> endPointConfig - .userService(customOAuth2UserService)) - .successHandler(oAuth2LoginSuccessHandler) - .failureHandler(oAuth2LoginFailureHandler)); + .anyRequest().authenticated()); // jwt 인증 필터 http diff --git a/src/main/java/com/backend/allreva/common/config/SecurityEndpointPaths.java b/src/main/java/com/backend/allreva/common/config/SecurityEndpointPaths.java index 38ae1f81..f6bcdd39 100644 --- a/src/main/java/com/backend/allreva/common/config/SecurityEndpointPaths.java +++ b/src/main/java/com/backend/allreva/common/config/SecurityEndpointPaths.java @@ -18,7 +18,7 @@ public final class SecurityEndpointPaths { public static final String[] ANONYMOUS_LIST = { "/api/v1/search/**", "/api/v1/concerts/**", - + "/api/v1/members/register" }; public static final String[] USER_LIST_GET = { @@ -31,14 +31,12 @@ public final class SecurityEndpointPaths { }; public static final String[] ANONYMOUS_LIST_GET = { - "/api/v1/surveys/**", "/api/v1/rents/**" + "/api/v1/surveys/**", + "/api/v1/rents/**", + "/api/v1/auth/**" }; public static final String[] ADMIN_LIST = { "/api/v1/admin/**" }; - - public static final String[] GUEST_LIST = { - "/api/v1/members/register" - }; } diff --git a/src/main/java/com/backend/allreva/common/config/SecurityTestConfig.java b/src/main/java/com/backend/allreva/common/config/SecurityTestConfig.java index 39202f97..6b0090d5 100644 --- a/src/main/java/com/backend/allreva/common/config/SecurityTestConfig.java +++ b/src/main/java/com/backend/allreva/common/config/SecurityTestConfig.java @@ -2,9 +2,9 @@ import static org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl.fromHierarchy; -import com.backend.allreva.auth.exception.CustomAccessDeniedHandler; -import com.backend.allreva.auth.exception.CustomAuthenticationEntryPoint; -import com.backend.allreva.auth.filter.TestAuthenticationFilter; +import com.backend.allreva.auth.security.CustomAccessDeniedHandler; +import com.backend.allreva.auth.security.CustomAuthenticationEntryPoint; +import com.backend.allreva.auth.security.TestAuthenticationFilter; import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; diff --git a/src/main/java/com/backend/allreva/common/util/CookieUtils.java b/src/main/java/com/backend/allreva/common/util/CookieUtils.java index 1b89935d..b2616118 100644 --- a/src/main/java/com/backend/allreva/common/util/CookieUtils.java +++ b/src/main/java/com/backend/allreva/common/util/CookieUtils.java @@ -9,17 +9,16 @@ @NoArgsConstructor(access = AccessLevel.PRIVATE) public final class CookieUtils { - private static final String COOKIE_DOMAIN = "localhost"; - // refreshToken 쿠키 생성 public static void addCookie( final HttpServletResponse response, + final String cookieDomain, final String name, final String value, final int maxAge ) { ResponseCookie cookie = ResponseCookie.from(name, value) - .domain(COOKIE_DOMAIN) + .domain(cookieDomain) .path("/") .maxAge(maxAge) .httpOnly(true) diff --git a/src/main/java/com/backend/allreva/diary/ui/DiaryController.java b/src/main/java/com/backend/allreva/diary/ui/DiaryController.java index 347fefde..5dad6fcf 100644 --- a/src/main/java/com/backend/allreva/diary/ui/DiaryController.java +++ b/src/main/java/com/backend/allreva/diary/ui/DiaryController.java @@ -1,6 +1,6 @@ package com.backend.allreva.diary.ui; -import com.backend.allreva.auth.application.AuthMember; +import com.backend.allreva.auth.security.AuthMember; import com.backend.allreva.common.dto.Response; import com.backend.allreva.diary.command.application.DiaryCommandService; import com.backend.allreva.diary.command.application.request.AddDiaryRequest; diff --git a/src/main/java/com/backend/allreva/member/command/application/MemberCommandFacade.java b/src/main/java/com/backend/allreva/member/command/application/MemberCommandFacade.java index 42523ac6..87d73248 100644 --- a/src/main/java/com/backend/allreva/member/command/application/MemberCommandFacade.java +++ b/src/main/java/com/backend/allreva/member/command/application/MemberCommandFacade.java @@ -2,7 +2,7 @@ import com.backend.allreva.common.application.S3ImageService; import com.backend.allreva.common.model.Image; -import com.backend.allreva.member.command.application.request.MemberInfoRequest; +import com.backend.allreva.member.command.application.request.MemberRegisterRequest; import com.backend.allreva.member.command.application.request.RefundAccountRequest; import com.backend.allreva.member.command.domain.Member; import lombok.RequiredArgsConstructor; @@ -21,24 +21,23 @@ public class MemberCommandFacade { @Transactional public void registerMember( - final MemberInfoRequest memberInfoRequest, - final Member member, + final MemberRegisterRequest memberRegisterRequest, final MultipartFile image ) { Image uploadedImage = s3ImageService.upload(image); - memberInfoCommandService.registerMember(memberInfoRequest, member, uploadedImage); - memberArtistCommandService.updateMemberArtist(memberInfoRequest.memberArtistRequests(), member); + Member registeredMember = memberInfoCommandService.registerMember(memberRegisterRequest, uploadedImage); + memberArtistCommandService.updateMemberArtist(memberRegisterRequest.memberArtistRequests(), registeredMember); } @Transactional public void updateMemberInfo( - final MemberInfoRequest memberInfoRequest, + final MemberRegisterRequest memberRegisterRequest, final Member member, final MultipartFile image ) { Image uploadedImage = s3ImageService.upload(image); - memberInfoCommandService.updateMemberInfo(memberInfoRequest, member, uploadedImage); - memberArtistCommandService.updateMemberArtist(memberInfoRequest.memberArtistRequests(), member); + memberInfoCommandService.updateMemberInfo(memberRegisterRequest, member, uploadedImage); + memberArtistCommandService.updateMemberArtist(memberRegisterRequest.memberArtistRequests(), member); } @Transactional diff --git a/src/main/java/com/backend/allreva/member/command/application/MemberInfoCommandService.java b/src/main/java/com/backend/allreva/member/command/application/MemberInfoCommandService.java index ece26492..2eec3f0c 100644 --- a/src/main/java/com/backend/allreva/member/command/application/MemberInfoCommandService.java +++ b/src/main/java/com/backend/allreva/member/command/application/MemberInfoCommandService.java @@ -1,7 +1,7 @@ package com.backend.allreva.member.command.application; import com.backend.allreva.common.model.Image; -import com.backend.allreva.member.command.application.request.MemberInfoRequest; +import com.backend.allreva.member.command.application.request.MemberRegisterRequest; import com.backend.allreva.member.command.application.request.RefundAccountRequest; import com.backend.allreva.member.command.domain.Member; import com.backend.allreva.member.command.domain.MemberRepository; @@ -15,19 +15,13 @@ public class MemberInfoCommandService { private final MemberRepository memberRepository; /** - * 회원 가입 시 유저정보 입력 회원 성공적으로 가입 시 GUEST에서 USER로 Role 변경 + * 회원 정보 등록 */ public Member registerMember( - final MemberInfoRequest memberInfoRequest, - final Member member, + final MemberRegisterRequest memberRegisterRequest, final Image image ) { - member.setMemberInfo( - memberInfoRequest.nickname(), - memberInfoRequest.introduce(), - image.getUrl() - ); - member.upgradeToUser(); // USER 권한으로 변경 + Member member = memberRegisterRequest.toEntity(image); return memberRepository.save(member); } @@ -35,13 +29,13 @@ public Member registerMember( * 회원 정보 수정 */ public Member updateMemberInfo( - final MemberInfoRequest memberInfoRequest, + final MemberRegisterRequest memberRegisterRequest, final Member member, final Image image ) { member.setMemberInfo( - memberInfoRequest.nickname(), - memberInfoRequest.introduce(), + memberRegisterRequest.nickname(), + memberRegisterRequest.introduce(), image.getUrl() ); return memberRepository.save(member); diff --git a/src/main/java/com/backend/allreva/member/command/application/request/MemberInfoRequest.java b/src/main/java/com/backend/allreva/member/command/application/request/MemberInfoRequest.java deleted file mode 100644 index 71c176cf..00000000 --- a/src/main/java/com/backend/allreva/member/command/application/request/MemberInfoRequest.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.backend.allreva.member.command.application.request; - -import java.util.List; - -public record MemberInfoRequest( - String nickname, - String introduce, - List memberArtistRequests -) { - -} diff --git a/src/main/java/com/backend/allreva/member/command/application/request/MemberRegisterRequest.java b/src/main/java/com/backend/allreva/member/command/application/request/MemberRegisterRequest.java new file mode 100644 index 00000000..5a2296e8 --- /dev/null +++ b/src/main/java/com/backend/allreva/member/command/application/request/MemberRegisterRequest.java @@ -0,0 +1,32 @@ +package com.backend.allreva.member.command.application.request; + +import com.backend.allreva.common.model.Email; +import com.backend.allreva.common.model.Image; +import com.backend.allreva.member.command.domain.Member; +import com.backend.allreva.member.command.domain.value.LoginProvider; +import com.backend.allreva.member.command.domain.value.MemberRole; +import java.util.List; +import lombok.Builder; + +@Builder +public record MemberRegisterRequest( + String email, + String nickname, + String introduce, + LoginProvider loginProvider, + List memberArtistRequests +) { + + public Member toEntity(final Image image) { + return Member.builder() + .email(Email.builder() + .email(email) + .build()) + .nickname(nickname) + .memberRole(MemberRole.USER) + .introduce(introduce) + .profileImageUrl(image.getUrl()) + .loginProvider(loginProvider) + .build(); + } +} diff --git a/src/main/java/com/backend/allreva/member/command/application/request/RefundAccountRequest.java b/src/main/java/com/backend/allreva/member/command/application/request/RefundAccountRequest.java index eb8e6d16..959d0afd 100644 --- a/src/main/java/com/backend/allreva/member/command/application/request/RefundAccountRequest.java +++ b/src/main/java/com/backend/allreva/member/command/application/request/RefundAccountRequest.java @@ -1,5 +1,8 @@ package com.backend.allreva.member.command.application.request; +import lombok.Builder; + +@Builder public record RefundAccountRequest( String bank, String number diff --git a/src/main/java/com/backend/allreva/member/command/domain/Member.java b/src/main/java/com/backend/allreva/member/command/domain/Member.java index ac7aba43..9da0adfa 100644 --- a/src/main/java/com/backend/allreva/member/command/domain/Member.java +++ b/src/main/java/com/backend/allreva/member/command/domain/Member.java @@ -55,15 +55,15 @@ public class Member extends BaseEntity { @Builder private Member( final Email email, - final MemberRole memberRole, final LoginProvider loginProvider, + final MemberRole memberRole, final String nickname, final String introduce, final String profileImageUrl ) { this.email = email; - this.memberRole = memberRole; this.loginProvider = loginProvider; + this.memberRole = memberRole; this.memberInfo = MemberInfo.builder() .nickname(nickname) .introduce(introduce) @@ -71,28 +71,6 @@ private Member( .build(); } - /** - * 임시 GUEST 생성 메서드 - *

- * 아직 회원가입이 완전히 이루어진 상태가 아니기 때문에 GUEST 권한으로 등록되어 있습니다. 회원가입에 필요한 정보들을 모두 기입할 시 USER 권한으로 승격됩니다. - password 없음 - */ - public static Member createTemporary( - final String email, - final String nickname, - final LoginProvider loginProvider, - final String profileImageUrl - ) { - return Member.builder() - .email(Email.builder() - .email(email) - .build()) - .nickname(nickname) - .loginProvider(loginProvider) - .memberRole(MemberRole.GUEST) - .profileImageUrl(profileImageUrl) - .build(); - } - public void setMemberInfo( final String nickname, final String introduce, @@ -121,10 +99,4 @@ public void setDefaultRefundAccount() { .number("") .build(); } - - public void upgradeToUser() { - if (this.memberRole.equals(MemberRole.GUEST)) { - this.memberRole = MemberRole.USER; - } - } } diff --git a/src/main/java/com/backend/allreva/member/command/domain/value/MemberRole.java b/src/main/java/com/backend/allreva/member/command/domain/value/MemberRole.java index b273408e..85e7537a 100644 --- a/src/main/java/com/backend/allreva/member/command/domain/value/MemberRole.java +++ b/src/main/java/com/backend/allreva/member/command/domain/value/MemberRole.java @@ -7,7 +7,6 @@ @RequiredArgsConstructor public enum MemberRole { - GUEST("ROLE_GUEST"), USER("ROLE_USER"), ADMIN("ROLE_ADMIN"), DEVELOPER("ROLE_DEVELOPER"); diff --git a/src/main/java/com/backend/allreva/member/ui/MemberController.java b/src/main/java/com/backend/allreva/member/ui/MemberController.java index 7ba69f8f..28414df8 100644 --- a/src/main/java/com/backend/allreva/member/ui/MemberController.java +++ b/src/main/java/com/backend/allreva/member/ui/MemberController.java @@ -1,14 +1,13 @@ package com.backend.allreva.member.ui; -import com.backend.allreva.auth.application.AuthMember; +import com.backend.allreva.auth.security.AuthMember; import com.backend.allreva.common.dto.Response; import com.backend.allreva.member.command.application.MemberCommandFacade; -import com.backend.allreva.member.command.application.request.MemberInfoRequest; +import com.backend.allreva.member.command.application.request.MemberRegisterRequest; import com.backend.allreva.member.command.application.request.RefundAccountRequest; import com.backend.allreva.member.command.domain.Member; import com.backend.allreva.member.query.application.MemberQueryService; import com.backend.allreva.member.query.application.response.MemberDetailResponse; -import io.swagger.v3.oas.annotations.Operation; import lombok.RequiredArgsConstructor; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.*; @@ -24,7 +23,7 @@ public class MemberController implements MemberControllerSwagger { @GetMapping public Response getMemberDetail( - final @AuthMember Member member + @AuthMember final Member member ) { return Response.onSuccess(memberQueryService.getById(member.getId())); } @@ -38,21 +37,20 @@ public Response isDuplicatedNickname( @PostMapping(path = "/register", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) public Response registerMember( - @AuthMember final Member member, - @RequestPart final MemberInfoRequest memberInfoRequest, + @RequestPart final MemberRegisterRequest memberRegisterRequest, @RequestPart(value = "image", required = false) final MultipartFile image ) { - memberCommandFacade.registerMember(memberInfoRequest, member, image); + memberCommandFacade.registerMember(memberRegisterRequest, image); return Response.onSuccess(); } @PatchMapping(path = "/info", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) public Response updateMemberInfo( @AuthMember final Member member, - @RequestPart final MemberInfoRequest memberInfoRequest, + @RequestPart final MemberRegisterRequest memberRegisterRequest, @RequestPart(value = "image", required = false) final MultipartFile image ) { - memberCommandFacade.updateMemberInfo(memberInfoRequest, member, image); + memberCommandFacade.updateMemberInfo(memberRegisterRequest, member, image); return Response.onSuccess(); } diff --git a/src/main/java/com/backend/allreva/member/ui/MemberControllerSwagger.java b/src/main/java/com/backend/allreva/member/ui/MemberControllerSwagger.java index 473c6cba..97ef1a4e 100644 --- a/src/main/java/com/backend/allreva/member/ui/MemberControllerSwagger.java +++ b/src/main/java/com/backend/allreva/member/ui/MemberControllerSwagger.java @@ -1,8 +1,8 @@ package com.backend.allreva.member.ui; -import com.backend.allreva.auth.application.AuthMember; +import com.backend.allreva.auth.security.AuthMember; import com.backend.allreva.common.dto.Response; -import com.backend.allreva.member.command.application.request.MemberInfoRequest; +import com.backend.allreva.member.command.application.request.MemberRegisterRequest; import com.backend.allreva.member.command.application.request.RefundAccountRequest; import com.backend.allreva.member.command.domain.Member; import com.backend.allreva.member.query.application.response.MemberDetailResponse; @@ -18,45 +18,44 @@ @Tag(name = "회원 API", description = "회원 정보를 관리하는 API") public interface MemberControllerSwagger { - @Operation(summary = "회원 정보 조회", description = "회원 정보를 조회합니다.") + @Operation(summary = "회원 정보 조회 API", description = "회원 정보를 조회합니다.") Response getMemberDetail( @AuthMember Member member ); - @Operation(summary = "닉네임 중복 확인", description = "닉네임 중복을 확인합니다.") + @Operation(summary = "닉네임 중복 확인 API", description = "닉네임 중복을 확인합니다.") Response isDuplicatedNickname( - final String nickname + String nickname ); - @Operation(summary = "oauth2 회원가입", description = "oauth2 회원가입 시 USER 권한으로 승격됩니다.") + @Operation(summary = "회원 가입 API", description = "회원을 등록합니다.") @RequestBody( content = @Content( encoding = @Encoding( - name = "memberInfoRequest", contentType = MediaType.APPLICATION_JSON_VALUE))) + name = "memberRegisterRequest", contentType = MediaType.APPLICATION_JSON_VALUE))) Response registerMember( - @AuthMember Member member, - @RequestPart MemberInfoRequest memberInfoRequest, + @RequestPart MemberRegisterRequest memberRegisterRequest, @RequestPart(value = "image", required = false) MultipartFile image ); - @Operation(summary = "회원 프로필 수정", description = "회원 프로필 수정 API, USER 권한일 때만 사용 가능합니다.") + @Operation(summary = "회원 프로필 수정 API", description = "회원 프로필을 수정합니다.") @RequestBody( content = @Content( encoding = @Encoding( - name = "memberInfoRequest", contentType = MediaType.APPLICATION_JSON_VALUE))) + name = "memberRegisterRequest", contentType = MediaType.APPLICATION_JSON_VALUE))) Response updateMemberInfo( @AuthMember Member member, - @RequestPart MemberInfoRequest memberInfoRequest, + @RequestPart MemberRegisterRequest memberRegisterRequest, @RequestPart(value = "image", required = false) MultipartFile image ); - @Operation(summary = "회원 환불 계좌 등록", description = "회원 환불 계좌 등록 API") + @Operation(summary = "회원 환불 계좌 등록 API", description = "회원 환불 계좌를 등록합니다.") Response registerRefundAccount( @AuthMember Member member, @RequestBody RefundAccountRequest refundAccountRequest ); - @Operation(summary = "회원 환불 계좌 삭제", description = "회원 환불 계좌 삭제 API") + @Operation(summary = "회원 환불 계좌 삭제 API", description = "회원 환불 계좌를 삭제합니다.") Response deleteRefundAccount( @AuthMember Member member ); diff --git a/src/main/java/com/backend/allreva/rent/ui/RentController.java b/src/main/java/com/backend/allreva/rent/ui/RentController.java index bd39a31e..35a022dd 100644 --- a/src/main/java/com/backend/allreva/rent/ui/RentController.java +++ b/src/main/java/com/backend/allreva/rent/ui/RentController.java @@ -1,6 +1,6 @@ package com.backend.allreva.rent.ui; -import com.backend.allreva.auth.application.AuthMember; +import com.backend.allreva.auth.security.AuthMember; import com.backend.allreva.common.dto.Response; import com.backend.allreva.member.command.domain.Member; import com.backend.allreva.rent.command.application.RentCommandService; diff --git a/src/main/java/com/backend/allreva/rent/ui/RentControllerSwagger.java b/src/main/java/com/backend/allreva/rent/ui/RentControllerSwagger.java index 76e3535a..063fda07 100644 --- a/src/main/java/com/backend/allreva/rent/ui/RentControllerSwagger.java +++ b/src/main/java/com/backend/allreva/rent/ui/RentControllerSwagger.java @@ -1,6 +1,6 @@ package com.backend.allreva.rent.ui; -import com.backend.allreva.auth.application.AuthMember; +import com.backend.allreva.auth.security.AuthMember; import com.backend.allreva.common.dto.Response; import com.backend.allreva.member.command.domain.Member; import com.backend.allreva.rent.command.application.request.RentIdRequest; diff --git a/src/main/java/com/backend/allreva/rent/ui/RentViewController.java b/src/main/java/com/backend/allreva/rent/ui/RentViewController.java index 667d5015..b7e40b23 100644 --- a/src/main/java/com/backend/allreva/rent/ui/RentViewController.java +++ b/src/main/java/com/backend/allreva/rent/ui/RentViewController.java @@ -1,6 +1,6 @@ package com.backend.allreva.rent.ui; -import com.backend.allreva.auth.application.AuthMember; +import com.backend.allreva.auth.security.AuthMember; import com.backend.allreva.common.dto.Response; import com.backend.allreva.member.command.domain.Member; import com.backend.allreva.rent.command.domain.value.Region; diff --git a/src/main/java/com/backend/allreva/rent_join/ui/RentJoinController.java b/src/main/java/com/backend/allreva/rent_join/ui/RentJoinController.java index 547a3166..034b1009 100644 --- a/src/main/java/com/backend/allreva/rent_join/ui/RentJoinController.java +++ b/src/main/java/com/backend/allreva/rent_join/ui/RentJoinController.java @@ -1,6 +1,6 @@ package com.backend.allreva.rent_join.ui; -import com.backend.allreva.auth.application.AuthMember; +import com.backend.allreva.auth.security.AuthMember; import com.backend.allreva.common.dto.Response; import com.backend.allreva.member.command.domain.Member; import com.backend.allreva.rent_join.command.application.RentJoinCommandService; diff --git a/src/main/java/com/backend/allreva/rent_join/ui/RentJoinControllerSwagger.java b/src/main/java/com/backend/allreva/rent_join/ui/RentJoinControllerSwagger.java index 9cb60b02..93ade937 100644 --- a/src/main/java/com/backend/allreva/rent_join/ui/RentJoinControllerSwagger.java +++ b/src/main/java/com/backend/allreva/rent_join/ui/RentJoinControllerSwagger.java @@ -1,6 +1,6 @@ package com.backend.allreva.rent_join.ui; -import com.backend.allreva.auth.application.AuthMember; +import com.backend.allreva.auth.security.AuthMember; import com.backend.allreva.common.dto.Response; import com.backend.allreva.member.command.domain.Member; import com.backend.allreva.rent_join.command.application.request.RentJoinApplyRequest; diff --git a/src/main/java/com/backend/allreva/survey/ui/SurveyController.java b/src/main/java/com/backend/allreva/survey/ui/SurveyController.java index 12cbb551..c3451921 100644 --- a/src/main/java/com/backend/allreva/survey/ui/SurveyController.java +++ b/src/main/java/com/backend/allreva/survey/ui/SurveyController.java @@ -1,6 +1,6 @@ package com.backend.allreva.survey.ui; -import com.backend.allreva.auth.application.AuthMember; +import com.backend.allreva.auth.security.AuthMember; import com.backend.allreva.common.dto.Response; import com.backend.allreva.member.command.domain.Member; import com.backend.allreva.survey.command.application.SurveyCommandService; diff --git a/src/main/java/com/backend/allreva/survey_join/ui/SurveyJoinController.java b/src/main/java/com/backend/allreva/survey_join/ui/SurveyJoinController.java index edfd6ad4..d471c3a5 100644 --- a/src/main/java/com/backend/allreva/survey_join/ui/SurveyJoinController.java +++ b/src/main/java/com/backend/allreva/survey_join/ui/SurveyJoinController.java @@ -1,6 +1,6 @@ package com.backend.allreva.survey_join.ui; -import com.backend.allreva.auth.application.AuthMember; +import com.backend.allreva.auth.security.AuthMember; import com.backend.allreva.common.dto.Response; import com.backend.allreva.member.command.domain.Member; import com.backend.allreva.survey.query.application.response.CreatedSurveyResponse; diff --git a/src/test/java/com/backend/allreva/member/fixture/MemberFixture.java b/src/test/java/com/backend/allreva/member/fixture/MemberFixture.java index e285faf9..ecd2be06 100644 --- a/src/test/java/com/backend/allreva/member/fixture/MemberFixture.java +++ b/src/test/java/com/backend/allreva/member/fixture/MemberFixture.java @@ -4,8 +4,10 @@ import com.backend.allreva.member.command.domain.Member; import com.backend.allreva.member.command.domain.value.LoginProvider; import com.backend.allreva.member.command.domain.value.MemberRole; +import lombok.NoArgsConstructor; import org.springframework.test.util.ReflectionTestUtils; +@NoArgsConstructor(access = lombok.AccessLevel.PRIVATE) public final class MemberFixture { public static Member createMemberFixture( diff --git a/src/test/java/com/backend/allreva/member/fixture/MemberRequestFixture.java b/src/test/java/com/backend/allreva/member/fixture/MemberRequestFixture.java new file mode 100644 index 00000000..700b37b6 --- /dev/null +++ b/src/test/java/com/backend/allreva/member/fixture/MemberRequestFixture.java @@ -0,0 +1,26 @@ +package com.backend.allreva.member.fixture; + +import com.backend.allreva.member.command.application.request.MemberArtistRequest; +import com.backend.allreva.member.command.application.request.MemberRegisterRequest; +import com.backend.allreva.member.command.application.request.RefundAccountRequest; +import com.backend.allreva.member.command.domain.value.LoginProvider; +import java.util.List; +import lombok.NoArgsConstructor; + +@NoArgsConstructor(access = lombok.AccessLevel.PRIVATE) +public final class MemberRequestFixture { + + public static MemberRegisterRequest createMemberRegisterRequest() { + return MemberRegisterRequest.builder() + .email("my@email") + .nickname("nickname") + .loginProvider(LoginProvider.GOOGLE) + .introduce("introduce") + .memberArtistRequests(List.of(new MemberArtistRequest("spotify_1L","name1"))) + .build(); + } + + public static RefundAccountRequest createRefundAccountRequest() { + return new RefundAccountRequest("땡땡은행", "123456789"); + } +} diff --git a/src/test/java/com/backend/allreva/member/integration/OAuth2RegisterIntegrationTest.java b/src/test/java/com/backend/allreva/member/integration/OAuth2RegisterIntegrationTest.java index cc9ac3e5..083e2f6c 100644 --- a/src/test/java/com/backend/allreva/member/integration/OAuth2RegisterIntegrationTest.java +++ b/src/test/java/com/backend/allreva/member/integration/OAuth2RegisterIntegrationTest.java @@ -5,17 +5,15 @@ import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import com.backend.allreva.artist.command.domain.ArtistRepository; import com.backend.allreva.artist.command.domain.Artist; -import com.backend.allreva.member.command.application.request.MemberArtistRequest; -import com.backend.allreva.member.command.application.request.MemberInfoRequest; +import com.backend.allreva.artist.command.domain.ArtistRepository; import com.backend.allreva.member.command.domain.Member; import com.backend.allreva.member.command.domain.MemberRepository; import com.backend.allreva.member.command.domain.value.MemberRole; import com.backend.allreva.member.fixture.MemberFixture; +import com.backend.allreva.member.fixture.MemberRequestFixture; import com.backend.allreva.support.ContextHolderTestUtil; import com.backend.allreva.support.IntegrationTestSupport; -import java.util.List; import java.util.Optional; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; @@ -43,7 +41,7 @@ class OAuth2RegisterIntegrationTest extends IntegrationTestSupport { @BeforeEach void setUp() { - member = MemberFixture.createMemberFixture(1L, MemberRole.GUEST); + member = MemberFixture.createMemberFixture(1L, MemberRole.USER); ContextHolderTestUtil.setContextHolder(member); } @@ -61,17 +59,13 @@ void cleanUp() { .name("Spotify").build(); artistRepository.save(artist); - var memberInfoRequest = new MemberInfoRequest( - "updated nickname", - "test introduce", - List.of(new MemberArtistRequest("spotify_1L","name1")) - ); + var memberRegisterRequest = MemberRequestFixture.createMemberRegisterRequest(); var uploadedImage = new MockMultipartFile("image", "test.jpg", "image/jpeg", "test".getBytes()); // when var resultActions = mockMvc.perform(multipart(HttpMethod.POST, "/api/v1/members/register") .file(uploadedImage) - .part(new MockPart("memberInfoRequest", "application/json", objectMapper.writeValueAsBytes(memberInfoRequest))) + .part(new MockPart("memberRegisterRequest", "application/json", objectMapper.writeValueAsBytes(memberRegisterRequest))) .contentType(MediaType.MULTIPART_FORM_DATA) ); @@ -83,7 +77,7 @@ void cleanUp() { registeredMember.ifPresent(registered -> assertSoftly(softly -> { softly.assertThat(registered.getMemberRole()).isEqualTo(MemberRole.USER); - softly.assertThat(registered.getMemberInfo().getIntroduce()).isEqualTo("test introduce"); + softly.assertThat(registered.getMemberInfo().getIntroduce()).isEqualTo(memberRegisterRequest.introduce()); })); } } diff --git a/src/test/java/com/backend/allreva/member/service/MemberArtistCommandTest.java b/src/test/java/com/backend/allreva/member/service/MemberArtistCommandTest.java index 0bfc57e9..d1bd7467 100644 --- a/src/test/java/com/backend/allreva/member/service/MemberArtistCommandTest.java +++ b/src/test/java/com/backend/allreva/member/service/MemberArtistCommandTest.java @@ -13,7 +13,8 @@ import com.backend.allreva.member.command.domain.Member; import com.backend.allreva.member.command.domain.MemberArtistRepository; import com.backend.allreva.member.command.domain.MemberArtistService; -import com.backend.allreva.member.command.domain.value.LoginProvider; +import com.backend.allreva.member.command.domain.value.MemberRole; +import com.backend.allreva.member.fixture.MemberFixture; import java.util.List; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -21,7 +22,6 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import org.springframework.test.util.ReflectionTestUtils; @ExtendWith(MockitoExtension.class) @SuppressWarnings("NonAsciiCharacters") @@ -46,12 +46,7 @@ class MemberArtistCommandTest { @BeforeEach void setUp() { - member = Member.createTemporary( - "my@email", - "nickname", - LoginProvider.GOOGLE, - "https://my_picture"); - ReflectionTestUtils.setField(member, "id", 1L); + member = MemberFixture.createMemberFixture(1L, MemberRole.USER); } @Test diff --git a/src/test/java/com/backend/allreva/member/service/MemberInfoCommandTest.java b/src/test/java/com/backend/allreva/member/service/MemberInfoCommandTest.java index 3366e2cc..34e1d0aa 100644 --- a/src/test/java/com/backend/allreva/member/service/MemberInfoCommandTest.java +++ b/src/test/java/com/backend/allreva/member/service/MemberInfoCommandTest.java @@ -8,19 +8,17 @@ import com.backend.allreva.common.application.S3ImageService; import com.backend.allreva.common.model.Image; import com.backend.allreva.member.command.application.MemberInfoCommandService; -import com.backend.allreva.member.command.application.request.MemberInfoRequest; import com.backend.allreva.member.command.domain.Member; import com.backend.allreva.member.command.domain.MemberRepository; -import com.backend.allreva.member.command.domain.value.LoginProvider; import com.backend.allreva.member.command.domain.value.MemberRole; -import java.util.List; +import com.backend.allreva.member.fixture.MemberFixture; +import com.backend.allreva.member.fixture.MemberRequestFixture; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import org.springframework.test.util.ReflectionTestUtils; @ExtendWith(MockitoExtension.class) @SuppressWarnings("NonAsciiCharacters") @@ -37,31 +35,22 @@ class MemberInfoCommandTest { @BeforeEach void setUp() { - member = Member.createTemporary( - "my@email", - "nickname", - LoginProvider.GOOGLE, - "https://my_picture"); - ReflectionTestUtils.setField(member, "id", 1L); + member = MemberFixture.createMemberFixture(1L, MemberRole.USER); } @Test void 회원_가입_시_회원_정보를_성공적으로_등록한다() { // given var uploadedImage = new Image("https://my_picture"); - var memberInfoRequest = new MemberInfoRequest( - "updated nickname", - "test introduce", - List.of() - ); + var memberRegisterRequest = MemberRequestFixture.createMemberRegisterRequest(); given(memberRepository.save(any(Member.class))).willReturn(member); // when - var updatedMember = memberInfoCommandService.registerMember(memberInfoRequest, member, uploadedImage); + var updatedMember = memberInfoCommandService.registerMember(memberRegisterRequest, uploadedImage); // then assertSoftly(softly -> { - softly.assertThat(updatedMember.getMemberInfo().getIntroduce()).isEqualTo("test introduce"); + softly.assertThat(updatedMember.getMemberInfo().getIntroduce()).isEqualTo(memberRegisterRequest.introduce()); softly.assertThat(updatedMember.getMemberRole()).isEqualTo(MemberRole.USER); }); } @@ -70,17 +59,13 @@ void setUp() { void 회원_정보를_성공적으로_수정한다() { // given var uploadedImage = new Image("https://my_picture"); - var memberInfoRequest = new MemberInfoRequest( - "updated nickname", - "test introduce", - List.of() - ); + var memberRegisterRequest = MemberRequestFixture.createMemberRegisterRequest(); given(memberRepository.save(any(Member.class))).willReturn(member); // when - Member updatedMember = memberInfoCommandService.updateMemberInfo(memberInfoRequest, member, uploadedImage); + Member updatedMember = memberInfoCommandService.updateMemberInfo(memberRegisterRequest, member, uploadedImage); // then - assertThat(updatedMember.getMemberInfo().getIntroduce()).isEqualTo("test introduce"); + assertThat(updatedMember.getMemberInfo().getIntroduce()).isEqualTo(memberRegisterRequest.introduce()); } } diff --git a/src/test/java/com/backend/allreva/member/service/RefundAccountCommandTest.java b/src/test/java/com/backend/allreva/member/service/RefundAccountCommandTest.java index 5a363ba4..0dd4b0a3 100644 --- a/src/test/java/com/backend/allreva/member/service/RefundAccountCommandTest.java +++ b/src/test/java/com/backend/allreva/member/service/RefundAccountCommandTest.java @@ -5,21 +5,21 @@ import static org.mockito.BDDMockito.given; import com.backend.allreva.member.command.application.MemberInfoCommandService; -import com.backend.allreva.member.command.domain.MemberRepository; -import com.backend.allreva.member.command.application.request.RefundAccountRequest; import com.backend.allreva.member.command.domain.Member; -import com.backend.allreva.member.command.domain.value.LoginProvider; +import com.backend.allreva.member.command.domain.MemberRepository; +import com.backend.allreva.member.command.domain.value.MemberRole; +import com.backend.allreva.member.fixture.MemberFixture; +import com.backend.allreva.member.fixture.MemberRequestFixture; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import org.springframework.test.util.ReflectionTestUtils; @ExtendWith(MockitoExtension.class) @SuppressWarnings("NonAsciiCharacters") -public class RefundAccountCommandTest { +class RefundAccountCommandTest { @InjectMocks private MemberInfoCommandService memberInfoCommandService; @@ -31,19 +31,13 @@ public class RefundAccountCommandTest { @BeforeEach void setUp() { - member = Member.createTemporary( - "my@email", - "nickname", - LoginProvider.GOOGLE, - "https://my_picture"); - ReflectionTestUtils.setField(member, "id", 1L); - member.upgradeToUser(); + member = MemberFixture.createMemberFixture(1L, MemberRole.USER); } @Test void 환불_계좌_정보를_성공적으로_등록한다() { // given - var refundAccountRequest = new RefundAccountRequest("땡땡은행", "123456789"); + var refundAccountRequest = MemberRequestFixture.createRefundAccountRequest(); given(memberRepository.save(any(Member.class))).willReturn(member); // when @@ -62,6 +56,6 @@ void setUp() { var deletedMember = memberInfoCommandService.deleteRefundAccount(member); // then - assertThat(deletedMember.getRefundAccount().getBank()).isEqualTo(""); + assertThat(deletedMember.getRefundAccount().getBank()).isEmpty(); } } diff --git a/src/test/java/com/backend/allreva/support/ApiTestSupport.java b/src/test/java/com/backend/allreva/support/ApiTestSupport.java index e10e3d25..76ff4dde 100644 --- a/src/test/java/com/backend/allreva/support/ApiTestSupport.java +++ b/src/test/java/com/backend/allreva/support/ApiTestSupport.java @@ -1,11 +1,12 @@ package com.backend.allreva.support; -import com.backend.allreva.auth.filter.JwtAuthenticationFilter; +import com.backend.allreva.auth.security.JwtAuthenticationFilter; +import com.backend.allreva.auth.ui.AuthController; import com.backend.allreva.common.config.SecurityConfig; import com.backend.allreva.member.command.application.MemberCommandFacade; import com.backend.allreva.member.command.domain.Member; -import com.backend.allreva.member.command.domain.value.LoginProvider; -import com.backend.allreva.auth.ui.OAuth2Controller; +import com.backend.allreva.member.command.domain.value.MemberRole; +import com.backend.allreva.member.fixture.MemberFixture; import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; @@ -17,11 +18,10 @@ import org.springframework.context.annotation.FilterType; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.test.context.ActiveProfiles; -import org.springframework.test.util.ReflectionTestUtils; import org.springframework.test.web.servlet.MockMvc; @WebMvcTest( - controllers = {OAuth2Controller.class}, + controllers = {AuthController.class}, excludeFilters = @ComponentScan.Filter( type = FilterType.ASSIGNABLE_TYPE, classes = {JwtAuthenticationFilter.class, SecurityConfig.class} @@ -44,12 +44,7 @@ public abstract class ApiTestSupport { @BeforeEach void setUp() { - member = Member.createTemporary( - "my@email", - "nickname", - LoginProvider.GOOGLE, - "https://my_picture"); - ReflectionTestUtils.setField(member, "id", 1L); + member = MemberFixture.createMemberFixture(1L, MemberRole.USER); } @AfterEach diff --git a/src/test/java/com/backend/allreva/support/ContextHolderTestUtil.java b/src/test/java/com/backend/allreva/support/ContextHolderTestUtil.java index 6df8a5a8..575056ba 100644 --- a/src/test/java/com/backend/allreva/support/ContextHolderTestUtil.java +++ b/src/test/java/com/backend/allreva/support/ContextHolderTestUtil.java @@ -1,6 +1,6 @@ package com.backend.allreva.support; -import com.backend.allreva.auth.application.dto.PrincipalDetails; +import com.backend.allreva.auth.security.PrincipalDetails; import com.backend.allreva.member.command.domain.Member; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.context.SecurityContextHolder; @@ -8,7 +8,7 @@ public final class ContextHolderTestUtil { public static void setContextHolder(Member member) { - var principalDetails = new PrincipalDetails(member, null); + var principalDetails = new PrincipalDetails(member); var authentication = new UsernamePasswordAuthenticationToken( principalDetails, null, diff --git a/src/test/java/com/backend/allreva/support/WithCustomMockUserSecurityContextFactory.java b/src/test/java/com/backend/allreva/support/WithCustomMockUserSecurityContextFactory.java index a8e27d67..c3f4ab47 100644 --- a/src/test/java/com/backend/allreva/support/WithCustomMockUserSecurityContextFactory.java +++ b/src/test/java/com/backend/allreva/support/WithCustomMockUserSecurityContextFactory.java @@ -1,32 +1,24 @@ package com.backend.allreva.support; -import com.backend.allreva.auth.application.dto.PrincipalDetails; +import com.backend.allreva.auth.security.PrincipalDetails; import com.backend.allreva.member.command.domain.Member; -import com.backend.allreva.member.command.domain.value.LoginProvider; -import com.backend.allreva.support.WithCustomMockUser; +import com.backend.allreva.member.command.domain.value.MemberRole; +import com.backend.allreva.member.fixture.MemberFixture; +import java.util.List; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.test.context.support.WithSecurityContextFactory; -import org.springframework.test.util.ReflectionTestUtils; - -import java.util.List; public class WithCustomMockUserSecurityContextFactory implements WithSecurityContextFactory { @Override public SecurityContext createSecurityContext(WithCustomMockUser annotation) { - - - Member member = Member.createTemporary("allreva@gmail.com", "닉네임", LoginProvider.KAKAO, ".jpg"); - ReflectionTestUtils.setField(member, "id", 1L); - member.setMemberInfo("닉네임", "소개", ".jpg"); - + Member member = MemberFixture.createMemberFixture(1L, MemberRole.USER); List authorities = List.of(new SimpleGrantedAuthority("ROLE_USER")); - PrincipalDetails principalDetails = new PrincipalDetails(member, null); - + PrincipalDetails principalDetails = new PrincipalDetails(member); UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(principalDetails, null, authorities); diff --git a/src/test/java/com/backend/allreva/survey/ui/SurveyUITest.java b/src/test/java/com/backend/allreva/survey/ui/SurveyUITest.java index 6a6fe362..2ddd2d9d 100644 --- a/src/test/java/com/backend/allreva/survey/ui/SurveyUITest.java +++ b/src/test/java/com/backend/allreva/survey/ui/SurveyUITest.java @@ -1,6 +1,18 @@ package com.backend.allreva.survey.ui; -import com.backend.allreva.auth.filter.JwtAuthenticationFilter; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doReturn; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import com.backend.allreva.auth.security.JwtAuthenticationFilter; import com.backend.allreva.common.config.SecurityConfig; import com.backend.allreva.support.ApiTestSupport; import com.backend.allreva.support.WithCustomMockUser; @@ -10,13 +22,22 @@ import com.backend.allreva.survey.command.application.request.UpdateSurveyRequest; import com.backend.allreva.survey.command.domain.value.Region; import com.backend.allreva.survey.query.application.SurveyQueryService; -import com.backend.allreva.survey.query.application.response.*; +import com.backend.allreva.survey.query.application.response.CreatedSurveyResponse; +import com.backend.allreva.survey.query.application.response.SortType; +import com.backend.allreva.survey.query.application.response.SurveyBoardingDateResponse; +import com.backend.allreva.survey.query.application.response.SurveyDetailResponse; +import com.backend.allreva.survey.query.application.response.SurveyResponse; +import com.backend.allreva.survey.query.application.response.SurveySummaryResponse; import com.backend.allreva.survey_join.command.application.SurveyJoinCommandService; import com.backend.allreva.survey_join.command.application.request.JoinSurveyRequest; import com.backend.allreva.survey_join.command.domain.value.BoardingType; import com.backend.allreva.survey_join.query.application.SurveyJoinQueryService; import com.backend.allreva.survey_join.query.application.response.JoinSurveyResponse; import com.backend.allreva.survey_join.ui.SurveyJoinController; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; @@ -26,20 +47,6 @@ import org.springframework.context.annotation.FilterType; import org.springframework.http.MediaType; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.doReturn; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; -import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - @WebMvcTest( controllers = {SurveyController.class, SurveyJoinController.class}, excludeFilters = @ComponentScan.Filter( @@ -222,7 +229,7 @@ void findSurveyList() throws Exception { @Test @WithCustomMockUser @DisplayName("내가 개설한 수요조사 목록 조회에 성공한다.") - public void getCreatedSurveyList() throws Exception { + void getCreatedSurveyList() throws Exception { // Given List responseList = new ArrayList<>(); SurveyResponse surveyResponse = new SurveyResponse(1L, @@ -259,7 +266,7 @@ public void getCreatedSurveyList() throws Exception { @Test @WithCustomMockUser @DisplayName("내가 참여한 수요조사 목록 조회에 성공한다.") - public void getJoinSurveyList() throws Exception { + void getJoinSurveyList() throws Exception { // Given List responseList = new ArrayList<>(); SurveyResponse surveyResponse = new SurveyResponse(1L,