diff --git a/src/main/java/com/project/bumawiki/domain/auth/service/implementation/AuthReader.java b/src/main/java/com/project/bumawiki/domain/auth/implementation/AuthReader.java similarity index 91% rename from src/main/java/com/project/bumawiki/domain/auth/service/implementation/AuthReader.java rename to src/main/java/com/project/bumawiki/domain/auth/implementation/AuthReader.java index a1cbc8d2..d01dc07f 100644 --- a/src/main/java/com/project/bumawiki/domain/auth/service/implementation/AuthReader.java +++ b/src/main/java/com/project/bumawiki/domain/auth/implementation/AuthReader.java @@ -1,4 +1,4 @@ -package com.project.bumawiki.domain.auth.service.implementation; +package com.project.bumawiki.domain.auth.implementation; import org.springframework.stereotype.Service; diff --git a/src/main/java/com/project/bumawiki/domain/auth/service/implementation/AuthUpdater.java b/src/main/java/com/project/bumawiki/domain/auth/implementation/AuthUpdater.java similarity index 86% rename from src/main/java/com/project/bumawiki/domain/auth/service/implementation/AuthUpdater.java rename to src/main/java/com/project/bumawiki/domain/auth/implementation/AuthUpdater.java index 49db9935..37720866 100644 --- a/src/main/java/com/project/bumawiki/domain/auth/service/implementation/AuthUpdater.java +++ b/src/main/java/com/project/bumawiki/domain/auth/implementation/AuthUpdater.java @@ -1,4 +1,4 @@ -package com.project.bumawiki.domain.auth.service.implementation; +package com.project.bumawiki.domain.auth.implementation; import org.springframework.stereotype.Service; diff --git a/src/main/java/com/project/bumawiki/domain/auth/service/implementation/AuthValidator.java b/src/main/java/com/project/bumawiki/domain/auth/implementation/AuthValidator.java similarity index 92% rename from src/main/java/com/project/bumawiki/domain/auth/service/implementation/AuthValidator.java rename to src/main/java/com/project/bumawiki/domain/auth/implementation/AuthValidator.java index 5839d313..4750545d 100644 --- a/src/main/java/com/project/bumawiki/domain/auth/service/implementation/AuthValidator.java +++ b/src/main/java/com/project/bumawiki/domain/auth/implementation/AuthValidator.java @@ -1,4 +1,4 @@ -package com.project.bumawiki.domain.auth.service.implementation; +package com.project.bumawiki.domain.auth.implementation; import org.springframework.stereotype.Service; diff --git a/src/main/java/com/project/bumawiki/domain/auth/service/implementation/TokenProvider.java b/src/main/java/com/project/bumawiki/domain/auth/implementation/TokenProvider.java similarity index 94% rename from src/main/java/com/project/bumawiki/domain/auth/service/implementation/TokenProvider.java rename to src/main/java/com/project/bumawiki/domain/auth/implementation/TokenProvider.java index c17e57a4..bef4bab3 100644 --- a/src/main/java/com/project/bumawiki/domain/auth/service/implementation/TokenProvider.java +++ b/src/main/java/com/project/bumawiki/domain/auth/implementation/TokenProvider.java @@ -1,4 +1,4 @@ -package com.project.bumawiki.domain.auth.service.implementation; +package com.project.bumawiki.domain.auth.implementation; import java.util.Date; diff --git a/src/main/java/com/project/bumawiki/domain/auth/infra/BsmLoginHandler.java b/src/main/java/com/project/bumawiki/domain/auth/infra/BsmLoginHandler.java new file mode 100644 index 00000000..b583da06 --- /dev/null +++ b/src/main/java/com/project/bumawiki/domain/auth/infra/BsmLoginHandler.java @@ -0,0 +1,46 @@ +package com.project.bumawiki.domain.auth.infra; + +import java.io.IOException; + +import com.project.bumawiki.domain.user.domain.User; +import com.project.bumawiki.domain.user.domain.authority.Authority; +import com.project.bumawiki.global.annotation.Implementation; +import com.project.bumawiki.global.error.exception.BumawikiException; +import com.project.bumawiki.global.error.exception.ErrorCode; + +import leehj050211.bsmOauth.BsmOauth; +import leehj050211.bsmOauth.dto.response.BsmResourceResponse; +import leehj050211.bsmOauth.exceptions.BsmAuthCodeNotFoundException; +import leehj050211.bsmOauth.exceptions.BsmAuthInvalidClientException; +import leehj050211.bsmOauth.exceptions.BsmAuthTokenNotFoundException; +import lombok.RequiredArgsConstructor; + +@Implementation +@RequiredArgsConstructor +public class BsmLoginHandler { + private final BsmOauth bsmOauth; + + public User getUserByAuthId(String authId) { + try { + String token = bsmOauth.getToken(authId); + BsmResourceResponse response = bsmOauth.getResource(token); + return createUnknownUser(response); + } catch (BsmAuthCodeNotFoundException | BsmAuthTokenNotFoundException e) { + throw new BumawikiException(ErrorCode.INVALID_AUTHID); + } catch (BsmAuthInvalidClientException e) { + throw new BumawikiException(ErrorCode.INVALID_BSM_CLIENT); + } catch (IOException e) { + throw new BumawikiException(ErrorCode.INTERNAL_SERVER_ERROR); + } + } + + private User createUnknownUser(BsmResourceResponse resource) { + return User.builder() + .email(resource.getEmail()) + .nickName(resource.getNickname()) + .authority(Authority.USER) + .enroll(resource.getStudent().getEnrolledAt()) + .name(resource.getStudent().getName()) + .build(); + } +} diff --git a/src/main/java/com/project/bumawiki/domain/auth/interceptor/AuthInterceptor.java b/src/main/java/com/project/bumawiki/domain/auth/interceptor/AuthInterceptor.java index 881929f9..5e929300 100644 --- a/src/main/java/com/project/bumawiki/domain/auth/interceptor/AuthInterceptor.java +++ b/src/main/java/com/project/bumawiki/domain/auth/interceptor/AuthInterceptor.java @@ -9,13 +9,13 @@ import com.project.bumawiki.domain.auth.annotation.AdminOnly; import com.project.bumawiki.domain.auth.annotation.LoginOrNot; import com.project.bumawiki.domain.auth.annotation.LoginRequired; -import com.project.bumawiki.domain.auth.service.implementation.AuthReader; -import com.project.bumawiki.domain.auth.service.implementation.AuthUpdater; +import com.project.bumawiki.domain.auth.implementation.AuthReader; +import com.project.bumawiki.domain.auth.implementation.AuthUpdater; import com.project.bumawiki.domain.auth.util.BearerTokenExtractor; import com.project.bumawiki.domain.auth.util.JwtParser; import com.project.bumawiki.domain.user.domain.User; import com.project.bumawiki.domain.user.domain.authority.Authority; -import com.project.bumawiki.domain.user.domain.repository.UserRepository; +import com.project.bumawiki.domain.user.implementation.UserReader; import com.project.bumawiki.global.error.exception.BumawikiException; import com.project.bumawiki.global.error.exception.ErrorCode; @@ -30,8 +30,7 @@ public class AuthInterceptor implements HandlerInterceptor { private final JwtParser jwtParser; private final AuthUpdater authUpdater; private final AuthReader authReader; - //TODO UserReader로 변경 - private final UserRepository userRepository; + private final UserReader userReader; private static void shouldUserAdmin(User currentUser) { if (currentUser.getAuthority() != Authority.ADMIN) { @@ -55,7 +54,7 @@ public boolean preHandle( String jwt = BearerTokenExtractor.extract(bearer); Long userId = jwtParser.getIdFromJwt(jwt); - User user = userRepository.getById(userId); + User user = userReader.getById(userId); authUpdater.updateCurrentUser(user); } diff --git a/src/main/java/com/project/bumawiki/domain/auth/presentation/AuthController.java b/src/main/java/com/project/bumawiki/domain/auth/presentation/AuthController.java index ce5a3216..77bff943 100644 --- a/src/main/java/com/project/bumawiki/domain/auth/presentation/AuthController.java +++ b/src/main/java/com/project/bumawiki/domain/auth/presentation/AuthController.java @@ -5,13 +5,14 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PutMapping; -import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import com.project.bumawiki.domain.auth.presentation.dto.LoginReqestDto; +import com.project.bumawiki.domain.auth.presentation.dto.RefreshTokenRequestDto; import com.project.bumawiki.domain.auth.presentation.dto.TokenResponseDto; -import com.project.bumawiki.domain.auth.service.AccessTokenRefreshService; -import com.project.bumawiki.domain.auth.service.UserSignUpOrUpdateService; +import com.project.bumawiki.domain.auth.service.CommandAuthService; import lombok.RequiredArgsConstructor; @@ -20,16 +21,15 @@ @RestController @RequestMapping("/api/auth") public class AuthController { - private final UserSignUpOrUpdateService userSignUpOrUpdateService; - private final AccessTokenRefreshService accessTokenRefreshService; + private final CommandAuthService commandAuthService; @PostMapping("/oauth/bsm") - public TokenResponseDto userSignup(@RequestHeader("authCode") String authCode) throws IOException { - return TokenResponseDto.from(userSignUpOrUpdateService.execute(authCode)); + public TokenResponseDto userSignup(@RequestBody LoginReqestDto loginReqestDto) throws IOException { + return TokenResponseDto.from(commandAuthService.login(loginReqestDto.accessToken())); } @PutMapping("/refresh/access") - public TokenResponseDto refreshAccessToken(@RequestHeader("refreshToken") String refreshToken) { - return TokenResponseDto.from(accessTokenRefreshService.execute(refreshToken)); + public TokenResponseDto refreshAccessToken(@RequestBody RefreshTokenRequestDto refreshTokenRequestDto) { + return TokenResponseDto.from(commandAuthService.refresh(refreshTokenRequestDto.refreshToken())); } } diff --git a/src/main/java/com/project/bumawiki/domain/auth/presentation/dto/AccessTokenRequestDto.java b/src/main/java/com/project/bumawiki/domain/auth/presentation/dto/LoginReqestDto.java similarity index 69% rename from src/main/java/com/project/bumawiki/domain/auth/presentation/dto/AccessTokenRequestDto.java rename to src/main/java/com/project/bumawiki/domain/auth/presentation/dto/LoginReqestDto.java index b1037656..6b6079e7 100644 --- a/src/main/java/com/project/bumawiki/domain/auth/presentation/dto/AccessTokenRequestDto.java +++ b/src/main/java/com/project/bumawiki/domain/auth/presentation/dto/LoginReqestDto.java @@ -1,6 +1,6 @@ package com.project.bumawiki.domain.auth.presentation.dto; -public record AccessTokenRequestDto( +public record LoginReqestDto( String accessToken ) { } diff --git a/src/main/java/com/project/bumawiki/domain/auth/service/AccessTokenRefreshService.java b/src/main/java/com/project/bumawiki/domain/auth/service/AccessTokenRefreshService.java deleted file mode 100644 index fd045967..00000000 --- a/src/main/java/com/project/bumawiki/domain/auth/service/AccessTokenRefreshService.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.project.bumawiki.domain.auth.service; - -import org.springframework.stereotype.Service; - -import com.project.bumawiki.domain.auth.domain.Token; -import com.project.bumawiki.domain.auth.service.implementation.AuthReader; -import com.project.bumawiki.domain.auth.service.implementation.AuthValidator; -import com.project.bumawiki.domain.auth.service.implementation.TokenProvider; -import com.project.bumawiki.domain.auth.util.BearerTokenExtractor; -import com.project.bumawiki.domain.user.domain.repository.UserRepository; - -import lombok.RequiredArgsConstructor; - -@SuppressWarnings("checkstyle:RegexpSinglelineJava") -@RequiredArgsConstructor -@Service -public class AccessTokenRefreshService { - private final TokenProvider tokenProvider; - private final AuthValidator authValidator; - private final AuthReader authReader; - //TODO UserReader로 변경 - private final UserRepository userRepository; - - public Token execute(String bearer) { - String refreshToken = BearerTokenExtractor.extract(bearer); - authValidator.shouldRefreshTokenValid(refreshToken); - - Long userId = authReader.getIdFromJwt(refreshToken); - String accessToken = tokenProvider.createAccessToken(userRepository.getById(userId)); - - return new Token(accessToken, refreshToken); - } -} diff --git a/src/main/java/com/project/bumawiki/domain/auth/service/CommandAuthService.java b/src/main/java/com/project/bumawiki/domain/auth/service/CommandAuthService.java new file mode 100644 index 00000000..b9a9d7e1 --- /dev/null +++ b/src/main/java/com/project/bumawiki/domain/auth/service/CommandAuthService.java @@ -0,0 +1,51 @@ +package com.project.bumawiki.domain.auth.service; + +import org.springframework.stereotype.Service; + +import com.project.bumawiki.domain.auth.domain.Token; +import com.project.bumawiki.domain.auth.implementation.AuthReader; +import com.project.bumawiki.domain.auth.implementation.AuthValidator; +import com.project.bumawiki.domain.auth.implementation.TokenProvider; +import com.project.bumawiki.domain.auth.infra.BsmLoginHandler; +import com.project.bumawiki.domain.auth.util.BearerTokenExtractor; +import com.project.bumawiki.domain.user.domain.User; +import com.project.bumawiki.domain.user.implementation.UserCreator; +import com.project.bumawiki.domain.user.implementation.UserReader; +import com.project.bumawiki.domain.user.implementation.UserUpdater; + +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class CommandAuthService { + private final AuthValidator authValidator; + private final AuthReader authReader; + private final BsmLoginHandler bsmLoginHandler; + private final TokenProvider tokenProvider; + private final UserReader userReader; + private final UserCreator userCreator; + private final UserUpdater userUpdater; + + public Token login(String authId) { + User unknownUser = bsmLoginHandler.getUserByAuthId(authId); + User user = userReader.getByEmail(unknownUser.getEmail()); + + if (user == null) { + userCreator.create(unknownUser); + } else { + userUpdater.update(user, unknownUser); + } + + return tokenProvider.createNewTokens(user); + } + + public Token refresh(String bearer) { + String refreshToken = BearerTokenExtractor.extract(bearer); + authValidator.shouldRefreshTokenValid(refreshToken); + + Long userId = authReader.getIdFromJwt(refreshToken); + String accessToken = tokenProvider.createAccessToken(userReader.getById(userId)); + + return new Token(accessToken, refreshToken); + } +} diff --git a/src/main/java/com/project/bumawiki/domain/auth/service/UserSignUpOrUpdateService.java b/src/main/java/com/project/bumawiki/domain/auth/service/UserSignUpOrUpdateService.java deleted file mode 100644 index 92bdeea4..00000000 --- a/src/main/java/com/project/bumawiki/domain/auth/service/UserSignUpOrUpdateService.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.project.bumawiki.domain.auth.service; - -import java.io.IOException; -import java.util.Optional; - -import org.springframework.transaction.annotation.Transactional; - -import com.project.bumawiki.domain.auth.domain.Token; -import com.project.bumawiki.domain.auth.service.implementation.TokenProvider; -import com.project.bumawiki.domain.user.domain.User; -import com.project.bumawiki.domain.user.domain.authority.Authority; -import com.project.bumawiki.domain.user.domain.repository.UserRepository; -import com.project.bumawiki.global.annotation.ServiceWithTransactionalReadOnly; -import com.project.bumawiki.global.error.exception.BumawikiException; -import com.project.bumawiki.global.error.exception.ErrorCode; - -import leehj050211.bsmOauth.BsmOauth; -import leehj050211.bsmOauth.dto.response.BsmResourceResponse; -import leehj050211.bsmOauth.exceptions.BsmAuthCodeNotFoundException; -import leehj050211.bsmOauth.exceptions.BsmAuthInvalidClientException; -import leehj050211.bsmOauth.exceptions.BsmAuthTokenNotFoundException; -import lombok.RequiredArgsConstructor; - -@RequiredArgsConstructor -@ServiceWithTransactionalReadOnly -public class UserSignUpOrUpdateService { - private final BsmOauth bsmOauth; - private final UserRepository userRepository; - private final TokenProvider tokenProvider; - - @Transactional - public Token execute(String authId) throws IOException { - String token; - BsmResourceResponse resource; - try { - token = bsmOauth.getToken(authId); - resource = bsmOauth.getResource(token); - } catch (BsmAuthCodeNotFoundException | BsmAuthTokenNotFoundException | BsmAuthInvalidClientException e) { - throw new BumawikiException(ErrorCode.USER_NOT_LOGIN); - } - User user = updateOrSignUp(resource); - - return tokenProvider.createNewTokens(user); - } - - protected User updateOrSignUp(BsmResourceResponse resource) { - Optional user = userRepository.findByEmail(resource.getEmail()); - if (user.isEmpty()) { - return saveUser(resource); - } - User updateUser = user.get(); - return updateUser.update(resource); - } - - protected User saveUser(final BsmResourceResponse resource) { - return userRepository.save( - User.builder() - .email(resource.getEmail()) - .nickName(resource.getNickname()) - .authority(Authority.USER) - .enroll(resource.getStudent().getEnrolledAt()) - .name(resource.getStudent().getName()) - .build() - ); - } -} diff --git a/src/main/java/com/project/bumawiki/domain/auth/util/BearerTokenExtractor.java b/src/main/java/com/project/bumawiki/domain/auth/util/BearerTokenExtractor.java index 01a1f1c2..2c115516 100644 --- a/src/main/java/com/project/bumawiki/domain/auth/util/BearerTokenExtractor.java +++ b/src/main/java/com/project/bumawiki/domain/auth/util/BearerTokenExtractor.java @@ -9,19 +9,19 @@ @NoArgsConstructor(access = AccessLevel.PRIVATE) public class BearerTokenExtractor { - private static final String BEARER_TYPE = "Bearer "; + private static final String PREFIX = "Bearer"; private static final String BEARER_JWT_REGEX = "^Bearer [A-Za-z0-9-_=]+\\.[A-Za-z0-9-_=]+\\.?[A-Za-z0-9-_.+/=]*$"; public static String extract(String bearer) { validate(bearer); - return bearer.replace(BEARER_TYPE, "").trim(); + return bearer.replace(PREFIX, "").trim(); } - private static void validate(String authorization) { - if (authorization == null) { + private static void validate(String bearer) { + if (bearer == null) { throw new BumawikiException(ErrorCode.TOKEN_MISSING); } - if (!authorization.matches(BEARER_JWT_REGEX)) { + if (!bearer.matches(BEARER_JWT_REGEX)) { throw new BumawikiException(ErrorCode.INVALID_JWT); } } diff --git a/src/main/java/com/project/bumawiki/domain/user/domain/User.java b/src/main/java/com/project/bumawiki/domain/user/domain/User.java index 786b780c..4e6ce8ad 100644 --- a/src/main/java/com/project/bumawiki/domain/user/domain/User.java +++ b/src/main/java/com/project/bumawiki/domain/user/domain/User.java @@ -19,7 +19,6 @@ import jakarta.persistence.GenerationType; import jakarta.persistence.Id; import jakarta.persistence.OneToMany; -import leehj050211.bsmOauth.dto.response.BsmResourceResponse; import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Builder; @@ -83,12 +82,11 @@ public List getList() { .toList(); } - public User update(BsmResourceResponse resource) { - this.email = resource.getEmail(); - this.name = resource.getStudent().getName(); - this.enroll = resource.getStudent().getEnrolledAt(); - this.nickName = resource.getNickname(); - return this; + public void update(User user) { + this.email = user.getEmail(); + this.name = user.getName(); + this.enroll = user.getEnroll(); + this.nickName = user.getNickName(); } public void changeUserAuthority(Authority authority) { diff --git a/src/main/java/com/project/bumawiki/domain/user/domain/repository/UserRepository.java b/src/main/java/com/project/bumawiki/domain/user/domain/repository/UserRepository.java index a19a00bf..7451681d 100644 --- a/src/main/java/com/project/bumawiki/domain/user/domain/repository/UserRepository.java +++ b/src/main/java/com/project/bumawiki/domain/user/domain/repository/UserRepository.java @@ -5,12 +5,7 @@ import org.springframework.data.jpa.repository.JpaRepository; import com.project.bumawiki.domain.user.domain.User; -import com.project.bumawiki.domain.user.exception.UserNotFoundException; public interface UserRepository extends JpaRepository { Optional findByEmail(String email); - - default User getById(Long id) { - return findById(id).orElseThrow(() -> UserNotFoundException.EXCEPTION); - } } diff --git a/src/main/java/com/project/bumawiki/domain/user/implementation/UserCreator.java b/src/main/java/com/project/bumawiki/domain/user/implementation/UserCreator.java new file mode 100644 index 00000000..f2c9db7d --- /dev/null +++ b/src/main/java/com/project/bumawiki/domain/user/implementation/UserCreator.java @@ -0,0 +1,17 @@ +package com.project.bumawiki.domain.user.implementation; + +import com.project.bumawiki.domain.user.domain.User; +import com.project.bumawiki.domain.user.domain.repository.UserRepository; +import com.project.bumawiki.global.annotation.Implementation; + +import lombok.RequiredArgsConstructor; + +@Implementation +@RequiredArgsConstructor +public class UserCreator { + private final UserRepository userRepository; + + public void create(User user) { + userRepository.save(user); + } +} diff --git a/src/main/java/com/project/bumawiki/domain/user/implementation/UserReader.java b/src/main/java/com/project/bumawiki/domain/user/implementation/UserReader.java new file mode 100644 index 00000000..e3be722e --- /dev/null +++ b/src/main/java/com/project/bumawiki/domain/user/implementation/UserReader.java @@ -0,0 +1,23 @@ +package com.project.bumawiki.domain.user.implementation; + +import com.project.bumawiki.domain.user.domain.User; +import com.project.bumawiki.domain.user.domain.repository.UserRepository; +import com.project.bumawiki.global.annotation.Implementation; +import com.project.bumawiki.global.error.exception.BumawikiException; +import com.project.bumawiki.global.error.exception.ErrorCode; + +import lombok.RequiredArgsConstructor; + +@Implementation +@RequiredArgsConstructor +public class UserReader { + private final UserRepository userRepository; + + public User getById(Long id) { + return userRepository.findById(id).orElseThrow(() -> new BumawikiException(ErrorCode.USER_NOT_FOUND)); + } + + public User getByEmail(String email) { + return userRepository.findByEmail(email).orElseThrow(() -> new BumawikiException(ErrorCode.USER_NOT_FOUND)); + } +} diff --git a/src/main/java/com/project/bumawiki/domain/user/implementation/UserUpdater.java b/src/main/java/com/project/bumawiki/domain/user/implementation/UserUpdater.java new file mode 100644 index 00000000..6bd81384 --- /dev/null +++ b/src/main/java/com/project/bumawiki/domain/user/implementation/UserUpdater.java @@ -0,0 +1,11 @@ +package com.project.bumawiki.domain.user.implementation; + +import com.project.bumawiki.domain.user.domain.User; +import com.project.bumawiki.global.annotation.Implementation; + +@Implementation +public class UserUpdater { + public void update(User user, User newUserInfo) { + user.update(newUserInfo); + } +} diff --git a/src/main/java/com/project/bumawiki/global/error/exception/ErrorCode.java b/src/main/java/com/project/bumawiki/global/error/exception/ErrorCode.java index 505e969d..5095289e 100644 --- a/src/main/java/com/project/bumawiki/global/error/exception/ErrorCode.java +++ b/src/main/java/com/project/bumawiki/global/error/exception/ErrorCode.java @@ -39,9 +39,12 @@ public enum ErrorCode { REFRESH_TOKEN_EXPIRED(403, "TOKEN-403-3", "리프레시 토큰이 만료되었습니다."), TOKEN_MISSING(403, "TOKEN-403-4", "토큰이 없습니다."), + //BSM + INVALID_AUTHID(400, "BSM-400-1", "AuthId가 유효하지 않습니다."), + INVALID_BSM_CLIENT(500, "BSM-500-1", "Bsm Client Is Invalid"), + //ServerError, INVALID_ARGUMENT(400, "ARG-400-1", "Arg Is Not Valid"), - BSM_AUTH_INVALID_CLIENT(500, "BSM-500-1", "Bsm Client Is Invalid"), INTERNAL_SERVER_ERROR(500, "SERVER-500-1", "Internal Server Error"), //Image,