diff --git a/src/main/java/org/codequistify/master/application/account/controller/AuthenticationController.java b/src/main/java/org/codequistify/master/application/account/controller/AuthenticationController.java index c7aac9d6..c28b6d25 100644 --- a/src/main/java/org/codequistify/master/application/account/controller/AuthenticationController.java +++ b/src/main/java/org/codequistify/master/application/account/controller/AuthenticationController.java @@ -47,14 +47,13 @@ public class AuthenticationController { private static final Logger logger = LoggerFactory.getLogger(AuthenticationController.class); - private final SocialSignHandlerMap handlerMap; private final AccountService accountService; private final EmailVerificationService emailVerificationService; + private final SocialSignHandlerMap handlerMap; private final PlayerQueryService playerQueryService; - - private final TokenProvider tokenProvider; private final TokenCookieProvider tokenCookieProvider; private final TokenGenerator tokenGenerator; + private final TokenProvider tokenProvider; @GetMapping("/{provider}/url") @Operation(summary = "소셜 로그인 URL 발급", description = "구글/카카오/네이버/깃허브 로그인 URL을 반환") diff --git a/src/main/java/org/codequistify/master/application/account/controller/EmailVerificationController.java b/src/main/java/org/codequistify/master/application/account/controller/EmailVerificationController.java index 5aa6700b..a0ca16e2 100644 --- a/src/main/java/org/codequistify/master/application/account/controller/EmailVerificationController.java +++ b/src/main/java/org/codequistify/master/application/account/controller/EmailVerificationController.java @@ -1,8 +1,8 @@ package org.codequistify.master.application.account.controller; import lombok.RequiredArgsConstructor; -import org.codequistify.master.core.domain.account.model.EmailVerificationType; import org.codequistify.master.application.account.service.EmailVerificationService; +import org.codequistify.master.core.domain.account.model.EmailVerificationType; import org.codequistify.master.global.aspect.LogMonitoring; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; @@ -16,9 +16,13 @@ @RequiredArgsConstructor public class EmailVerificationController { private final EmailVerificationService emailVerificationService; + @GetMapping("home/auth/email/verify") @LogMonitoring - public String verifyMail(@RequestParam String email, @RequestParam String code, @RequestParam EmailVerificationType type, Model model) { + public String verifyMail(@RequestParam String email, + @RequestParam String code, + @RequestParam EmailVerificationType type, + Model model) { if (email.isBlank() || code.isBlank() || type == null) { return "redirect:/home/failure"; } diff --git a/src/main/java/org/codequistify/master/application/account/service/AccountService.java b/src/main/java/org/codequistify/master/application/account/service/AccountService.java index dbf5b047..d6fab5aa 100644 --- a/src/main/java/org/codequistify/master/application/account/service/AccountService.java +++ b/src/main/java/org/codequistify/master/application/account/service/AccountService.java @@ -38,14 +38,13 @@ @Service @RequiredArgsConstructor public class AccountService { - private final PlayerQueryService playerQueryService; - private final PlayerProfileService playerProfileService; + private final Logger logger = LoggerFactory.getLogger(AccountService.class); + private final PlayerJpaRepository playerJpaRepository; private final PlayerPasswordManager playerPasswordManager; + private final PlayerProfileService playerProfileService; + private final PlayerQueryService playerQueryService; private final PlayerValidator playerValidator; private final TokenProvider tokenProvider; - private final PlayerJpaRepository playerJpaRepository; - - private final Logger logger = LoggerFactory.getLogger(AccountService.class); @Transactional @LogMonitoring diff --git a/src/main/java/org/codequistify/master/application/account/service/EmailVerificationService.java b/src/main/java/org/codequistify/master/application/account/service/EmailVerificationService.java index 6830acc7..1836a502 100644 --- a/src/main/java/org/codequistify/master/application/account/service/EmailVerificationService.java +++ b/src/main/java/org/codequistify/master/application/account/service/EmailVerificationService.java @@ -30,13 +30,12 @@ @RequiredArgsConstructor public class EmailVerificationService { - private final EmailVerificationRepository emailVerificationRepository; - private final EmailVerificationPolicyHandler policyHandler; + private final EmailVerificationCodeManager codeManager; private final EmailMessageFactory emailMessageFactory; private final EmailSender emailSender; - private final EmailVerificationCodeManager codeManager; + private final EmailVerificationRepository emailVerificationRepository; private final Logger logger = LoggerFactory.getLogger(EmailVerificationService.class); - + private final EmailVerificationPolicyHandler policyHandler; @Value("${mail.secret}") private String mailSecret; diff --git a/src/main/java/org/codequistify/master/application/account/service/GithubSocialSignService.java b/src/main/java/org/codequistify/master/application/account/service/GithubSocialSignService.java index e682333b..2102a269 100644 --- a/src/main/java/org/codequistify/master/application/account/service/GithubSocialSignService.java +++ b/src/main/java/org/codequistify/master/application/account/service/GithubSocialSignService.java @@ -1,7 +1,10 @@ package org.codequistify.master.application.account.service; import lombok.RequiredArgsConstructor; -import org.codequistify.master.application.account.vo.*; +import org.codequistify.master.application.account.vo.OAuthProfile; +import org.codequistify.master.application.account.vo.OAuthResource; +import org.codequistify.master.application.account.vo.OAuthToken; +import org.codequistify.master.application.account.vo.ResourceOfGithub; import org.codequistify.master.application.exception.ApplicationException; import org.codequistify.master.core.domain.player.model.OAuthType; import org.codequistify.master.core.domain.player.model.Player; @@ -28,10 +31,9 @@ public class GithubSocialSignService implements SocialSignService { private static final String LOGIN_URL_TEMPLATE = "https://github.com/login/oauth/authorize?client_id=%s&redirect_uri=%s&response_type=code&state=%s"; - - private final RestTemplate restTemplate; private final OAuthKey oAuthKey; private final PlayerRepository playerRepository; + private final RestTemplate restTemplate; @Override public String getSocialLogInURL() { diff --git a/src/main/java/org/codequistify/master/application/account/service/GoogleSocialSignService.java b/src/main/java/org/codequistify/master/application/account/service/GoogleSocialSignService.java index 89d8b7ca..b4993ea2 100644 --- a/src/main/java/org/codequistify/master/application/account/service/GoogleSocialSignService.java +++ b/src/main/java/org/codequistify/master/application/account/service/GoogleSocialSignService.java @@ -30,10 +30,9 @@ public class GoogleSocialSignService implements SocialSignService { private static final String LOGIN_URL_TEMPLATE = "https://accounts.google.com/o/oauth2/auth?client_id=%s&redirect_uri=%s&response_type=code&scope=email%%20profile"; - - private final RestTemplate restTemplate; private final OAuthKey oAuthKey; private final PlayerRepository playerRepository; + private final RestTemplate restTemplate; @Override public String getSocialLogInURL() { diff --git a/src/main/java/org/codequistify/master/application/account/service/KakaoSocialSignService.java b/src/main/java/org/codequistify/master/application/account/service/KakaoSocialSignService.java index b66b7414..5b146337 100644 --- a/src/main/java/org/codequistify/master/application/account/service/KakaoSocialSignService.java +++ b/src/main/java/org/codequistify/master/application/account/service/KakaoSocialSignService.java @@ -31,10 +31,9 @@ public class KakaoSocialSignService implements SocialSignService { private static final String LOGIN_URL_TEMPLATE = "https://kauth.kakao.com/oauth/authorize?response_type=code&client_id=%s&redirect_uri=%s"; - - private final RestTemplate restTemplate; private final OAuthKey oAuthKey; private final PlayerRepository playerRepository; + private final RestTemplate restTemplate; /** * 카카오 소셜 로그인 주소 반환 diff --git a/src/main/java/org/codequistify/master/application/account/service/NaverSocialSignService.java b/src/main/java/org/codequistify/master/application/account/service/NaverSocialSignService.java index 80dcbdfe..170573a2 100644 --- a/src/main/java/org/codequistify/master/application/account/service/NaverSocialSignService.java +++ b/src/main/java/org/codequistify/master/application/account/service/NaverSocialSignService.java @@ -1,7 +1,10 @@ package org.codequistify.master.application.account.service; import lombok.RequiredArgsConstructor; -import org.codequistify.master.application.account.vo.*; +import org.codequistify.master.application.account.vo.OAuthProfile; +import org.codequistify.master.application.account.vo.OAuthResource; +import org.codequistify.master.application.account.vo.OAuthToken; +import org.codequistify.master.application.account.vo.ResourceOfNaver; import org.codequistify.master.application.exception.ApplicationException; import org.codequistify.master.core.domain.player.model.OAuthType; import org.codequistify.master.core.domain.player.model.Player; @@ -28,10 +31,9 @@ public class NaverSocialSignService implements SocialSignService { private static final String LOGIN_URL_TEMPLATE = "https://nid.naver.com/oauth2.0/authorize?client_id=%s&redirect_uri=%s&response_type=code&state=%s"; - - private final RestTemplate restTemplate; - private final PlayerRepository playerRepository; private final OAuthKey oAuthKey; + private final PlayerRepository playerRepository; + private final RestTemplate restTemplate; /** * 네이버 소셜 로그인 URL 반환 diff --git a/src/main/java/org/codequistify/master/application/account/service/SocialSignService.java b/src/main/java/org/codequistify/master/application/account/service/SocialSignService.java index 5ca5531e..175eb395 100644 --- a/src/main/java/org/codequistify/master/application/account/service/SocialSignService.java +++ b/src/main/java/org/codequistify/master/application/account/service/SocialSignService.java @@ -5,7 +5,9 @@ public interface SocialSignService { String getSocialLogInURL(); + Player socialLogIn(OAuthProfile oAuthProfile); + Player socialSignUp(OAuthProfile oAuthProfile); OAuthProfile getOAuthProfile(String code); diff --git a/src/main/java/org/codequistify/master/application/account/strategy/EmailVerificationPolicy.java b/src/main/java/org/codequistify/master/application/account/strategy/EmailVerificationPolicy.java index 33a5bba2..05a3dfdf 100644 --- a/src/main/java/org/codequistify/master/application/account/strategy/EmailVerificationPolicy.java +++ b/src/main/java/org/codequistify/master/application/account/strategy/EmailVerificationPolicy.java @@ -4,5 +4,6 @@ public interface EmailVerificationPolicy { boolean supports(EmailVerificationType type); + void validate(String email); } \ No newline at end of file diff --git a/src/main/java/org/codequistify/master/application/account/support/TokenCookieProvider.java b/src/main/java/org/codequistify/master/application/account/support/TokenCookieProvider.java index 20ea7e05..67b5fbbb 100644 --- a/src/main/java/org/codequistify/master/application/account/support/TokenCookieProvider.java +++ b/src/main/java/org/codequistify/master/application/account/support/TokenCookieProvider.java @@ -8,16 +8,20 @@ @Component public class TokenCookieProvider { - private static final String PROD_DOMAIN = "pol.or.kr"; - private static final String DEV_DOMAIN = "localhost"; private static final int ACCESS_TOKEN_EXPIRATION_SECONDS = 60 * 60; // 1 hour + private static final String DEV_DOMAIN = "localhost"; + private static final String PROD_DOMAIN = "pol.or.kr"; private static final int REFRESH_TOKEN_EXPIRATION_SECONDS = 7 * 24 * 60 * 60; // 7 days public void addTokenCookies(HttpServletResponse response, TokenResponse token) { addCookie(response, "POL_ACCESS_TOKEN", token.accessToken(), PROD_DOMAIN, ACCESS_TOKEN_EXPIRATION_SECONDS); addCookie(response, "POL_REFRESH_TOKEN", token.refreshToken(), PROD_DOMAIN, REFRESH_TOKEN_EXPIRATION_SECONDS); addCookie(response, "POL_ACCESS_TOKEN_DEV", token.accessToken(), DEV_DOMAIN, ACCESS_TOKEN_EXPIRATION_SECONDS); - addCookie(response, "POL_REFRESH_TOKEN_DEV", token.refreshToken(), DEV_DOMAIN, REFRESH_TOKEN_EXPIRATION_SECONDS); + addCookie(response, + "POL_REFRESH_TOKEN_DEV", + token.refreshToken(), + DEV_DOMAIN, + REFRESH_TOKEN_EXPIRATION_SECONDS); } public void removeTokenCookies(HttpServletResponse response) { diff --git a/src/main/java/org/codequistify/master/application/account/support/TokenGenerator.java b/src/main/java/org/codequistify/master/application/account/support/TokenGenerator.java index f49a0471..edd4e1da 100644 --- a/src/main/java/org/codequistify/master/application/account/support/TokenGenerator.java +++ b/src/main/java/org/codequistify/master/application/account/support/TokenGenerator.java @@ -11,8 +11,8 @@ @RequiredArgsConstructor public class TokenGenerator { - private final TokenProvider tokenProvider; private final AccountService accountService; + private final TokenProvider tokenProvider; public TokenResponse generate(Player player) { String refreshToken = tokenProvider.generateRefreshToken(player); diff --git a/src/main/java/org/codequistify/master/application/account/vo/ResourceOfKakao.java b/src/main/java/org/codequistify/master/application/account/vo/ResourceOfKakao.java index 70ba6859..b7b6d1e8 100644 --- a/src/main/java/org/codequistify/master/application/account/vo/ResourceOfKakao.java +++ b/src/main/java/org/codequistify/master/application/account/vo/ResourceOfKakao.java @@ -5,12 +5,6 @@ public record ResourceOfKakao( @JsonProperty("properties") Properties properties ) { - public record Properties( - String id, - String email, - String nickname - ) {} - public OAuthResource toOAuthResource() { return new OAuthResource( properties.id(), @@ -18,4 +12,11 @@ public OAuthResource toOAuthResource() { properties.nickname() ); } + + public record Properties( + String id, + String email, + String nickname + ) { + } } diff --git a/src/main/java/org/codequistify/master/application/account/vo/ResourceOfNaver.java b/src/main/java/org/codequistify/master/application/account/vo/ResourceOfNaver.java index 30580ed2..27823893 100644 --- a/src/main/java/org/codequistify/master/application/account/vo/ResourceOfNaver.java +++ b/src/main/java/org/codequistify/master/application/account/vo/ResourceOfNaver.java @@ -5,12 +5,6 @@ public record ResourceOfNaver( @JsonProperty("response") Response response ) { - public record Response( - String id, - String email, - String name - ) {} - public OAuthResource toOAuthResource() { return new OAuthResource( response.id(), @@ -18,4 +12,11 @@ public OAuthResource toOAuthResource() { response.name() ); } + + public record Response( + String id, + String email, + String name + ) { + } } diff --git a/src/main/java/org/codequistify/master/application/exception/ApplicationException.java b/src/main/java/org/codequistify/master/application/exception/ApplicationException.java index 5910c64a..c564efea 100644 --- a/src/main/java/org/codequistify/master/application/exception/ApplicationException.java +++ b/src/main/java/org/codequistify/master/application/exception/ApplicationException.java @@ -5,9 +5,9 @@ import org.springframework.http.HttpStatus; public class ApplicationException extends RuntimeException { - private final HttpStatus httpStatus; - private final ErrorCode errorCode; private final String detail; + private final ErrorCode errorCode; + private final HttpStatus httpStatus; public ApplicationException(ErrorCode errorCode, HttpStatus httpStatus) { super(errorCode.getMessage()); @@ -43,7 +43,11 @@ public ApplicationException(BusinessException businessException, HttpStatus http this.detail = businessException.getDetail(); } - public ApplicationException(ErrorCode errorCode, HttpStatus httpStatus, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { + public ApplicationException(ErrorCode errorCode, + HttpStatus httpStatus, + Throwable cause, + boolean enableSuppression, + boolean writableStackTrace) { super(errorCode.getMessage(), cause, enableSuppression, writableStackTrace); this.httpStatus = httpStatus; this.errorCode = errorCode; diff --git a/src/main/java/org/codequistify/master/application/player/controller/PlayerCredentialController.java b/src/main/java/org/codequistify/master/application/player/controller/PlayerCredentialController.java index f8e0c131..4f95341e 100644 --- a/src/main/java/org/codequistify/master/application/player/controller/PlayerCredentialController.java +++ b/src/main/java/org/codequistify/master/application/player/controller/PlayerCredentialController.java @@ -4,8 +4,8 @@ import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import org.codequistify.master.application.exception.ApplicationException; -import org.codequistify.master.application.player.service.PlayerCredentialService; import org.codequistify.master.application.player.dto.UpdatePasswordRequest; +import org.codequistify.master.application.player.service.PlayerCredentialService; import org.codequistify.master.core.domain.player.model.Player; import org.codequistify.master.global.aspect.LogMonitoring; import org.codequistify.master.global.exception.ErrorCode; @@ -23,8 +23,8 @@ @RequestMapping("api/players") public class PlayerCredentialController { - private final PlayerCredentialService playerCredentialService; private final Logger logger = LoggerFactory.getLogger(PlayerCredentialController.class); + private final PlayerCredentialService playerCredentialService; @Operation( summary = "비밀번호 재설정", diff --git a/src/main/java/org/codequistify/master/application/player/service/PlayerCredentialService.java b/src/main/java/org/codequistify/master/application/player/service/PlayerCredentialService.java index 88a876a2..43eef925 100644 --- a/src/main/java/org/codequistify/master/application/player/service/PlayerCredentialService.java +++ b/src/main/java/org/codequistify/master/application/player/service/PlayerCredentialService.java @@ -20,23 +20,25 @@ @RequiredArgsConstructor public class PlayerCredentialService { + private final Logger logger = LoggerFactory.getLogger(PlayerCredentialService.class); private final PlayerJpaRepository playerJpaRepository; private final PlayerPasswordManager playerPasswordManager; - private final Logger logger = LoggerFactory.getLogger(PlayerCredentialService.class); - @Transactional @LogExecutionTime public void updatePassword(Player player, UpdatePasswordRequest request) { Player updated = playerJpaRepository.findByUid(player.getUid().getValue()) .map(PlayerConverter::toDomain) .map(current -> { - if (!playerPasswordManager.matches(current, request.rawPassword())) { - throw new ApplicationException(ErrorCode.INVALID_EMAIL_OR_PASSWORD, HttpStatus.BAD_REQUEST); - } - return playerPasswordManager.encodePassword(current, request.password()); - }) - .orElseThrow(() -> new ApplicationException(ErrorCode.PLAYER_NOT_FOUND, HttpStatus.NOT_FOUND)); + if (!playerPasswordManager.matches(current, request.rawPassword())) { + throw new ApplicationException(ErrorCode.INVALID_EMAIL_OR_PASSWORD, + HttpStatus.BAD_REQUEST); + } + return playerPasswordManager.encodePassword(current, + request.password()); + }) + .orElseThrow(() -> new ApplicationException(ErrorCode.PLAYER_NOT_FOUND, + HttpStatus.NOT_FOUND)); playerJpaRepository.save(PlayerConverter.toEntity(updated)); logger.info("[updatePassword] Player: {}, 비밀번호 변경 성공", updated.getUid()); diff --git a/src/main/java/org/codequistify/master/application/player/service/PlayerQueryService.java b/src/main/java/org/codequistify/master/application/player/service/PlayerQueryService.java index bdb97ae3..267f81ff 100644 --- a/src/main/java/org/codequistify/master/application/player/service/PlayerQueryService.java +++ b/src/main/java/org/codequistify/master/application/player/service/PlayerQueryService.java @@ -31,9 +31,9 @@ public Player findOneByUid(PolId uid) { return playerJpaRepository.findByUid(uid.getValue()) .map(PlayerConverter::toDomain) .orElseThrow(() -> { - logger.warn("[findOneByUid] 존재하지 않는 player. uid={}", uid); - return new ApplicationException(ErrorCode.PLAYER_NOT_FOUND, HttpStatus.NOT_FOUND); - }); + logger.warn("[findOneByUid] 존재하지 않는 player. uid={}", uid); + return new ApplicationException(ErrorCode.PLAYER_NOT_FOUND, HttpStatus.NOT_FOUND); + }); } /** @@ -44,9 +44,9 @@ public Player findOneByEmail(String email) { return playerJpaRepository.findByEmail(email) .map(PlayerConverter::toDomain) .orElseThrow(() -> { - logger.warn("[findOneByEmail] 존재하지 않는 email. email={}", email); - return new ApplicationException(ErrorCode.PLAYER_NOT_FOUND, HttpStatus.NOT_FOUND); - }); + logger.warn("[findOneByEmail] 존재하지 않는 email. email={}", email); + return new ApplicationException(ErrorCode.PLAYER_NOT_FOUND, HttpStatus.NOT_FOUND); + }); } /** @@ -56,9 +56,9 @@ public Player findOneByEmail(String email) { public OAuthType findOAuthTypeByEmail(String email) { return playerJpaRepository.getOAuthTypeByEmail(email) .orElseThrow(() -> { - logger.warn("[findOAtuhTypebyEmail] 존재하지 않는 email, email={}", email); - return new ApplicationException(ErrorCode.PLAYER_NOT_FOUND, HttpStatus.NOT_FOUND); - }); + logger.warn("[findOAtuhTypebyEmail] 존재하지 않는 email, email={}", email); + return new ApplicationException(ErrorCode.PLAYER_NOT_FOUND, HttpStatus.NOT_FOUND); + }); } /** diff --git a/src/main/java/org/codequistify/master/core/domain/HomeController.java b/src/main/java/org/codequistify/master/core/domain/HomeController.java index 797e3d2f..fe64fd5f 100644 --- a/src/main/java/org/codequistify/master/core/domain/HomeController.java +++ b/src/main/java/org/codequistify/master/core/domain/HomeController.java @@ -6,7 +6,7 @@ @Controller public class HomeController { @GetMapping(value = {"", "index", "home"}) - public String home(){ + public String home() { return "index"; } } diff --git a/src/main/java/org/codequistify/master/core/domain/account/model/EmailVerification.java b/src/main/java/org/codequistify/master/core/domain/account/model/EmailVerification.java index 84284d92..16b2399e 100644 --- a/src/main/java/org/codequistify/master/core/domain/account/model/EmailVerification.java +++ b/src/main/java/org/codequistify/master/core/domain/account/model/EmailVerification.java @@ -8,13 +8,22 @@ @ToString @Builder(toBuilder = true) public class EmailVerification { - private final Long id; - - private final String email; private final String code; - private final boolean verified; - private final boolean used; + private final String email; private final EmailVerificationType emailVerificationType; + private final Long id; + private final boolean used; + private final boolean verified; + + public static EmailVerification of(String email, String code, EmailVerificationType type) { + return EmailVerification.builder() + .email(email) + .code(code) + .verified(false) + .used(false) + .emailVerificationType(type) + .build(); + } public EmailVerification markAsVerified() { return this.toBuilder() @@ -27,14 +36,4 @@ public EmailVerification markAsUsed() { .used(true) .build(); } - - public static EmailVerification of(String email, String code, EmailVerificationType type) { - return EmailVerification.builder() - .email(email) - .code(code) - .verified(false) - .used(false) - .emailVerificationType(type) - .build(); - } } \ No newline at end of file diff --git a/src/main/java/org/codequistify/master/core/domain/lab/controller/LabController.java b/src/main/java/org/codequistify/master/core/domain/lab/controller/LabController.java index 5bd6a856..540138ab 100644 --- a/src/main/java/org/codequistify/master/core/domain/lab/controller/LabController.java +++ b/src/main/java/org/codequistify/master/core/domain/lab/controller/LabController.java @@ -28,13 +28,11 @@ @RequiredArgsConstructor @Tag(name = "Lab") public class LabController { - private final LabService labService; - private final StageSearchServiceImpl stageSearchService; - private final LockManager lockManager; - private final String LAB_HOST = "wss://lab.pol.or.kr"; - private final Logger LOGGER = LoggerFactory.getLogger(LabController.class); + private final LabService labService; + private final LockManager lockManager; + private final StageSearchServiceImpl stageSearchService; @Operation( summary = "가상 터미널 (PShell) 생성요청", diff --git a/src/main/java/org/codequistify/master/core/domain/lab/dto/PShellCreateResponse.java b/src/main/java/org/codequistify/master/core/domain/lab/dto/PShellCreateResponse.java index 71f748b2..4579985e 100644 --- a/src/main/java/org/codequistify/master/core/domain/lab/dto/PShellCreateResponse.java +++ b/src/main/java/org/codequistify/master/core/domain/lab/dto/PShellCreateResponse.java @@ -4,16 +4,17 @@ public record PShellCreateResponse( String url, String query ) { - public static PShellCreateResponse of (String url, String uid, String stageImageName) { + public static PShellCreateResponse of(String url, String uid, String stageImageName) { String query = "?uid=" + uid.toLowerCase() + "&stage=" + stageImageName; return new PShellCreateResponse( - url+query, + url + query, query ); } - public static record XHeader ( + public record XHeader( String key, String value - ){} + ) { + } } diff --git a/src/main/java/org/codequistify/master/core/domain/lab/factory/KubernetesPodFactory.java b/src/main/java/org/codequistify/master/core/domain/lab/factory/KubernetesPodFactory.java index 3054ec97..6c7cedbb 100644 --- a/src/main/java/org/codequistify/master/core/domain/lab/factory/KubernetesPodFactory.java +++ b/src/main/java/org/codequistify/master/core/domain/lab/factory/KubernetesPodFactory.java @@ -12,8 +12,8 @@ @Component public class KubernetesPodFactory implements PodFactory { - private final Logger LOGGER = LoggerFactory.getLogger(KubernetesPodFactory.class); private final static Long ACTIVE_DEADLINE = 10_800L; + private final Logger LOGGER = LoggerFactory.getLogger(KubernetesPodFactory.class); @Override public Pod create(Stage stage, int port, String uid) { @@ -22,29 +22,29 @@ public Pod create(Stage stage, int port, String uid) { return new PodBuilder() .withNewMetadata() - .withName(podName) - .addToLabels("app", "pol") - .addToLabels("tire", "term") - .addToLabels("player", uid) - .addToLabels("stage", stageImage.name().toLowerCase()) + .withName(podName) + .addToLabels("app", "pol") + .addToLabels("tire", "term") + .addToLabels("player", uid) + .addToLabels("stage", stageImage.name().toLowerCase()) .endMetadata() .withNewSpec() - .addNewContainer() - .withName(stageImage.name().toLowerCase()) - .withImage(stageImage.getImageName()) - .addNewPort() - .withContainerPort(port) - .endPort() - .withNewReadinessProbe()// agent 준비 확인 - .withNewHttpGet() - .withPath("/health") - .withPort(new IntOrString(8080)) - .endHttpGet() - .withInitialDelaySeconds(9) - .withPeriodSeconds(2) - .endReadinessProbe() - .endContainer() - .withActiveDeadlineSeconds(ACTIVE_DEADLINE) + .addNewContainer() + .withName(stageImage.name().toLowerCase()) + .withImage(stageImage.getImageName()) + .addNewPort() + .withContainerPort(port) + .endPort() + .withNewReadinessProbe()// agent 준비 확인 + .withNewHttpGet() + .withPath("/health") + .withPort(new IntOrString(8080)) + .endHttpGet() + .withInitialDelaySeconds(9) + .withPeriodSeconds(2) + .endReadinessProbe() + .endContainer() + .withActiveDeadlineSeconds(ACTIVE_DEADLINE) .endSpec().build(); } diff --git a/src/main/java/org/codequistify/master/core/domain/lab/factory/KubernetesServiceFactory.java b/src/main/java/org/codequistify/master/core/domain/lab/factory/KubernetesServiceFactory.java index d42a1446..330ce03d 100644 --- a/src/main/java/org/codequistify/master/core/domain/lab/factory/KubernetesServiceFactory.java +++ b/src/main/java/org/codequistify/master/core/domain/lab/factory/KubernetesServiceFactory.java @@ -9,8 +9,9 @@ import org.springframework.stereotype.Component; @Component -public class KubernetesServiceFactory implements ServiceFactory{ +public class KubernetesServiceFactory implements ServiceFactory { private final static Long ACTIVE_DEADLINE = 10_800L; + @Override public Service create(Stage stage, int port, String uid) { StageImageType stageImage = stage.getStageImage(); @@ -18,24 +19,24 @@ public Service create(Stage stage, int port, String uid) { return new ServiceBuilder() .withNewMetadata() - .withName(serviceName) - .addToLabels("app", "pol") - .addToLabels("tire", "term") - .addToLabels("player", uid) - .addToLabels("stage", stageImage.name().toLowerCase()) + .withName(serviceName) + .addToLabels("app", "pol") + .addToLabels("tire", "term") + .addToLabels("player", uid) + .addToLabels("stage", stageImage.name().toLowerCase()) .endMetadata() .withNewSpec() - .withType("ClusterIP") - .addNewPort() - .withName("http") - .withProtocol("TCP") - .withPort(port) - .withTargetPort(new IntOrString(port)) - .endPort() - .addToSelector("app", "pol") - .addToSelector("tire", "term") - .addToSelector("player", uid) - .addToSelector("stage", stageImage.name().toLowerCase()) + .withType("ClusterIP") + .addNewPort() + .withName("http") + .withProtocol("TCP") + .withPort(port) + .withTargetPort(new IntOrString(port)) + .endPort() + .addToSelector("app", "pol") + .addToSelector("tire", "term") + .addToSelector("player", uid) + .addToSelector("stage", stageImage.name().toLowerCase()) .endSpec().build(); } diff --git a/src/main/java/org/codequistify/master/core/domain/lab/service/KubernetesResourceCollector.java b/src/main/java/org/codequistify/master/core/domain/lab/service/KubernetesResourceCollector.java index 9b8313b8..4ad2df7f 100644 --- a/src/main/java/org/codequistify/master/core/domain/lab/service/KubernetesResourceCollector.java +++ b/src/main/java/org/codequistify/master/core/domain/lab/service/KubernetesResourceCollector.java @@ -13,8 +13,8 @@ @Service @RequiredArgsConstructor public class KubernetesResourceCollector { - private final KubernetesResourceManager kubernetesResourceManager; private final Logger LOGGER = LoggerFactory.getLogger(KubernetesResourceCollector.class); + private final KubernetesResourceManager kubernetesResourceManager; @Scheduled(cron = "0 0 * * * ?") public void resourceCollection() { @@ -24,7 +24,7 @@ public void resourceCollection() { kubernetesResourceManager.deleteAsyncService(timeoutPod); }); - LOGGER.info("[resourceCollection] PShell {}개 제거, List: {}", timeoutPods.size(), timeoutPods.toString()); + LOGGER.info("[resourceCollection] PShell {}개 제거, List: {}", timeoutPods.size(), timeoutPods); } private String getResourceName(Pod pod) { @@ -33,8 +33,8 @@ private String getResourceName(Pod pod) { private List extractPodNames(List pods) { return pods.stream() - .map(this::getResourceName) - .collect(Collectors.toList()); + .map(this::getResourceName) + .collect(Collectors.toList()); } } diff --git a/src/main/java/org/codequistify/master/core/domain/lab/service/KubernetesResourceManager.java b/src/main/java/org/codequistify/master/core/domain/lab/service/KubernetesResourceManager.java index 2f580400..f457f693 100644 --- a/src/main/java/org/codequistify/master/core/domain/lab/service/KubernetesResourceManager.java +++ b/src/main/java/org/codequistify/master/core/domain/lab/service/KubernetesResourceManager.java @@ -19,19 +19,17 @@ @RequiredArgsConstructor public class KubernetesResourceManager { private final Logger LOGGER = LoggerFactory.getLogger(KubernetesResourceManager.class); - + private final KubernetesClient kubernetesClient; private final PodFactory podFactory; private final ServiceFactory serviceFactory; - private final KubernetesClient kubernetesClient; - public Service createServiceOnKubernetes(Stage stage, String uid) { Service service = serviceFactory.create(stage, 8080, uid); service = kubernetesClient.services() - .inNamespace("default") - .resource(service) - .create(); + .inNamespace("default") + .resource(service) + .create(); LOGGER.debug("[createServiceOnKubernetes] service: {}", service.getMetadata().getName()); return service; @@ -41,9 +39,9 @@ public Pod createPodOnKubernetes(Stage stage, String uid) { Pod pod = podFactory.create(stage, 8080, uid); pod = kubernetesClient.pods() - .inNamespace("default") - .resource(pod) - .create(); + .inNamespace("default") + .resource(pod) + .create(); LOGGER.debug("[createPodOnKubernetes] pod: {}", pod.getMetadata().getName()); return pod; @@ -53,18 +51,18 @@ public void deleteAsyncService(Stage stage, String uid) { String svcName = KubernetesResourceNaming.getServiceName(stage.getStageImage().name(), uid); List result = kubernetesClient.services() - .inNamespace("default") - .withName(svcName) - .delete(); + .inNamespace("default") + .withName(svcName) + .delete(); LOGGER.debug("[deleteAsyncService] result {}", result); } public void deleteAsyncService(String svcName) { List result = kubernetesClient.services() - .inNamespace("default") - .withName(svcName) - .delete(); + .inNamespace("default") + .withName(svcName) + .delete(); LOGGER.debug("[deleteAsyncService] result {}", result); } @@ -73,18 +71,18 @@ public void deleteAsyncPod(Stage stage, String uid) { String podName = KubernetesResourceNaming.getPodName(stage.getStageImage().name(), uid); List result = kubernetesClient.pods() - .inNamespace("default") - .withName(podName) - .delete(); + .inNamespace("default") + .withName(podName) + .delete(); LOGGER.debug("[deleteAsyncPod] result {}", result); } public void deleteAsyncPod(String podName) { List result = kubernetesClient.pods() - .inNamespace("default") - .withName(podName) - .delete(); + .inNamespace("default") + .withName(podName) + .delete(); LOGGER.debug("[deleteAsyncPod] result {}", result); } @@ -93,9 +91,9 @@ public Service getService(Stage stage, String uid) { String svcName = KubernetesResourceNaming.getServiceName(stage.getStageImage().name(), uid); Service service = kubernetesClient.services() - .inNamespace("default") - .withName(svcName) - .get(); + .inNamespace("default") + .withName(svcName) + .get(); LOGGER.debug("[getService] name : {}", service.getMetadata().getName()); return service; @@ -105,9 +103,9 @@ public Pod getPod(Stage stage, String uid) { String podName = KubernetesResourceNaming.getPodName(stage.getStageImage().name(), uid); Pod pod = kubernetesClient.pods() - .inNamespace("default") - .withName(podName) - .get(); + .inNamespace("default") + .withName(podName) + .get(); LOGGER.debug("[getPod] name : {}", pod.getMetadata().getName()); return pod; @@ -117,9 +115,9 @@ public boolean existsService(Stage stage, String uid) { String svcName = KubernetesResourceNaming.getServiceName(stage.getStageImage().name(), uid); boolean exists = kubernetesClient.services() - .inNamespace("default") - .withName(svcName) - .get() != null; + .inNamespace("default") + .withName(svcName) + .get() != null; //LOGGER.info("[existsService] name: {}, exists: {}", svcName, exists); return exists; @@ -129,9 +127,9 @@ public boolean existsPod(Stage stage, String uid) { String podName = KubernetesResourceNaming.getPodName(stage.getStageImage().name(), uid); boolean exists = kubernetesClient.pods() - .inNamespace("default") - .withName(podName) - .get() != null; + .inNamespace("default") + .withName(podName) + .get() != null; //LOGGER.info("[existsPod] name: {}, exists: {}", podName, exists); return exists; @@ -141,10 +139,10 @@ public List getTimeOutPods() { PodList podList = kubernetesClient.pods().inNamespace("default").list(); return podList.getItems().stream() - .filter(this::isPhaseFailed) - .filter(this::isReasonDeadlineExceeded) - .filter(this::hasErrorStatus) - .toList(); + .filter(this::isPhaseFailed) + .filter(this::isReasonDeadlineExceeded) + .filter(this::hasErrorStatus) + .toList(); } private boolean isPhaseFailed(Pod pod) { @@ -157,8 +155,8 @@ private boolean isReasonDeadlineExceeded(Pod pod) { private boolean hasErrorStatus(Pod pod) { return pod.getStatus().getContainerStatuses().stream() - .anyMatch(status -> status.getState().getTerminated() != null && - "Error".equals(status.getState().getTerminated().getReason())); + .anyMatch(status -> status.getState().getTerminated() != null && + "Error".equals(status.getState().getTerminated().getReason())); } } diff --git a/src/main/java/org/codequistify/master/core/domain/lab/service/LabAssignmentService.java b/src/main/java/org/codequistify/master/core/domain/lab/service/LabAssignmentService.java index 03aa6bc6..f930aa17 100644 --- a/src/main/java/org/codequistify/master/core/domain/lab/service/LabAssignmentService.java +++ b/src/main/java/org/codequistify/master/core/domain/lab/service/LabAssignmentService.java @@ -20,22 +20,23 @@ @RequiredArgsConstructor @Service public class LabAssignmentService { - private final RestTemplate restTemplate; private final Logger LOGGER = LoggerFactory.getLogger(LabAssignmentService.class); private final String NAMESPACE = "default"; - + private final RestTemplate restTemplate; @Bean public void testA() { String stageCode = StageImageType.S1015.name(); String uid = "pol-bdbeej-gj5antzprz"; //String qUrl = KubernetesResourceNaming.getQuery(stageCode, uid); - System.out.println("https://lab.pol.or.kr/grade"+KubernetesResourceNaming.getQuery(stageCode, uid)); - System.out.println("https://lab.pol.or.kr/compose"+KubernetesResourceNaming.getQuery(stageCode, uid)); + System.out.println("https://lab.pol.or.kr/grade" + KubernetesResourceNaming.getQuery(stageCode, uid)); + System.out.println("https://lab.pol.or.kr/compose" + KubernetesResourceNaming.getQuery(stageCode, uid)); } @LogExecutionTime - public ResponseEntity sendGradingRequest(String stageCode, String uid, StageActionRequest request) { + public ResponseEntity sendGradingRequest(String stageCode, + String uid, + StageActionRequest request) { //String svcName = KubernetesResourceNaming.getServiceName(stageCode, uid); String url = "https://lab.pol.or.kr/grade" + KubernetesResourceNaming.getQuery(stageCode, uid); @@ -69,8 +70,10 @@ public ResponseEntity sendGradingRequest(String stageCode, Stri } @LogExecutionTime - public ResponseEntity sendComposeRequest(String stageCode, String uid, StageActionRequest request) { - String url = "https://lab.pol.or.kr/compose"+KubernetesResourceNaming.getQuery(stageCode, uid); + public ResponseEntity sendComposeRequest(String stageCode, + String uid, + StageActionRequest request) { + String url = "https://lab.pol.or.kr/compose" + KubernetesResourceNaming.getQuery(stageCode, uid); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); diff --git a/src/main/java/org/codequistify/master/core/domain/lab/service/LabService.java b/src/main/java/org/codequistify/master/core/domain/lab/service/LabService.java index 59f9ee2d..9b4f33af 100644 --- a/src/main/java/org/codequistify/master/core/domain/lab/service/LabService.java +++ b/src/main/java/org/codequistify/master/core/domain/lab/service/LabService.java @@ -15,13 +15,13 @@ @org.springframework.stereotype.Service @RequiredArgsConstructor public class LabService { - private final KubernetesResourceManager kubernetesResourceManager; - private final Logger LOGGER = LoggerFactory.getLogger(LabService.class); - private final static int THRESHOLD = 20; private final static int SLEEP_PERIOD = 5000; + private final static int THRESHOLD = 20; + private final Logger LOGGER = LoggerFactory.getLogger(LabService.class); + private final KubernetesResourceManager kubernetesResourceManager; @LogExecutionTime - public void createStageOnKubernetes(Player player, Stage stage){ + public void createStageOnKubernetes(Player player, Stage stage) { String uid = player.getUid().toLowerCase(); kubernetesResourceManager.createServiceOnKubernetes(stage, uid); @@ -60,7 +60,7 @@ public void deleteSyncStageOnKubernetes(Player player, Stage stage) { LOGGER.info("[deleteSyncStageOnKubernetes] Service 삭제 확인 {}번 시도", retryCount); } if (retryCount > THRESHOLD) { - LOGGER.error("[deleteSyncStageOnKubernetes] {}",ErrorCode.PSHELL_CREATE_FAILED.getMessage()); + LOGGER.error("[deleteSyncStageOnKubernetes] {}", ErrorCode.PSHELL_CREATE_FAILED.getMessage()); throw new BusinessException(ErrorCode.PSHELL_CREATE_FAILED, HttpStatus.INTERNAL_SERVER_ERROR); } try { @@ -92,14 +92,16 @@ public void waitForPodReadiness(Player player, Stage stage) { if (pod != null && pod.getStatus() != null && pod.getStatus().getConditions() != null) { for (PodCondition condition : pod.getStatus().getConditions()) { if ("Ready".equals(condition.getType()) && "True".equals(condition.getStatus())) { - LOGGER.info("[waitForPodReadiness] 네트워크 구성완료, pod: {}, time: {}ms", pod.getMetadata().getName(), retryCount * 2000); + LOGGER.info("[waitForPodReadiness] 네트워크 구성완료, pod: {}, time: {}ms", + pod.getMetadata().getName(), + retryCount * 2000); return; } } } if (retryCount > THRESHOLD) { - LOGGER.error("[checkPodReady] {}",ErrorCode.PSHELL_CREATE_FAILED.getMessage()); + LOGGER.error("[checkPodReady] {}", ErrorCode.PSHELL_CREATE_FAILED.getMessage()); throw new BusinessException(ErrorCode.PSHELL_CREATE_FAILED, HttpStatus.INTERNAL_SERVER_ERROR); } try { diff --git a/src/main/java/org/codequistify/master/core/domain/lab/utils/KubernetesResourceNaming.java b/src/main/java/org/codequistify/master/core/domain/lab/utils/KubernetesResourceNaming.java index 9430d720..83535fbd 100644 --- a/src/main/java/org/codequistify/master/core/domain/lab/utils/KubernetesResourceNaming.java +++ b/src/main/java/org/codequistify/master/core/domain/lab/utils/KubernetesResourceNaming.java @@ -3,11 +3,10 @@ public class KubernetesResourceNaming { //private static final String POD_NAME_FORMAT = "%s-pod-%s"; private static final String POD_NAME_FORMAT = "%s-%s"; + private static final String QUERY_URL_FORMAT = "?uid=%s&stage=%s"; + private static final String SERVICE_DNS_FORMAT = "%s.%s.svc.cluster.local"; //private static final String SERVICE_NAME_FORMAT = "%s-svc-%s"; private static final String SERVICE_NAME_FORMAT = "%s-%s"; - private static final String SERVICE_DNS_FORMAT = "%s.%s.svc.cluster.local"; - - private static final String QUERY_URL_FORMAT = "?uid=%s&stage=%s"; public static String getPodName(String stageCode, String uid) { return String.format(POD_NAME_FORMAT, stageCode.toLowerCase(), uid.toLowerCase()); diff --git a/src/main/java/org/codequistify/master/core/domain/player/converter/PlayerConverter.java b/src/main/java/org/codequistify/master/core/domain/player/converter/PlayerConverter.java index 1cfa1199..24b44e1f 100644 --- a/src/main/java/org/codequistify/master/core/domain/player/converter/PlayerConverter.java +++ b/src/main/java/org/codequistify/master/core/domain/player/converter/PlayerConverter.java @@ -1,9 +1,9 @@ package org.codequistify.master.core.domain.player.converter; import org.codequistify.master.application.account.dto.SignUpRequest; +import org.codequistify.master.application.player.dto.PlayerProfile; import org.codequistify.master.core.domain.player.model.OAuthType; import org.codequistify.master.core.domain.player.model.Player; -import org.codequistify.master.application.player.dto.PlayerProfile; import org.springframework.stereotype.Component; import java.util.List; @@ -22,13 +22,13 @@ public PlayerProfile convert(Player player) { public Player convert(SignUpRequest request) { return Player.builder() - .email(request.email()) - .name(request.name()) - .password(request.password()) - .oAuthType(OAuthType.POL) - .oAuthId("0") - .locked(false) - .exp(0) - .build(); + .email(request.email()) + .name(request.name()) + .password(request.password()) + .oAuthType(OAuthType.POL) + .oAuthId("0") + .locked(false) + .exp(0) + .build(); } } diff --git a/src/main/java/org/codequistify/master/core/domain/player/model/Player.java b/src/main/java/org/codequistify/master/core/domain/player/model/Player.java index 2275f745..30ebfd02 100644 --- a/src/main/java/org/codequistify/master/core/domain/player/model/Player.java +++ b/src/main/java/org/codequistify/master/core/domain/player/model/Player.java @@ -14,23 +14,26 @@ @AllArgsConstructor public class Player { - private final PolId uid; - private final String name; private final String email; - private final String password; - private final OAuthType oAuthType; - private final String oAuthId; - private final Set roles; + private final Integer exp; private final Boolean locked; + private final String name; private final String oAuthAccessToken; + private final String oAuthId; + private final OAuthType oAuthType; + private final String password; private final String refreshToken; - private final Integer exp; + private final Set roles; + private final PolId uid; + + public static PolId generateUID(String email) { + return UidGenerator.generate(email); + } public String getId() { return this.uid.getValue(); } - public Player withOAuthAccessToken(String token) { return this.toBuilder() .oAuthAccessToken(token) @@ -80,8 +83,4 @@ public Player dataClear() { .locked(true) .build(); } - - public static PolId generateUID(String email) { - return UidGenerator.generate(email); - } } diff --git a/src/main/java/org/codequistify/master/core/domain/player/model/PolId.java b/src/main/java/org/codequistify/master/core/domain/player/model/PolId.java index 6448b3ce..49fe2f06 100644 --- a/src/main/java/org/codequistify/master/core/domain/player/model/PolId.java +++ b/src/main/java/org/codequistify/master/core/domain/player/model/PolId.java @@ -15,11 +15,6 @@ private PolId(String value) { this.value = value; } - @JsonValue - public String getValue() { - return value; - } - @JsonCreator public static PolId of(String value) { if (value == null || value.isBlank()) { @@ -27,4 +22,9 @@ public static PolId of(String value) { } return new PolId(value); } + + @JsonValue + public String getValue() { + return value; + } } diff --git a/src/main/java/org/codequistify/master/core/domain/player/service/PlayerValidator.java b/src/main/java/org/codequistify/master/core/domain/player/service/PlayerValidator.java index 06e7f8c7..4423148a 100644 --- a/src/main/java/org/codequistify/master/core/domain/player/service/PlayerValidator.java +++ b/src/main/java/org/codequistify/master/core/domain/player/service/PlayerValidator.java @@ -6,12 +6,10 @@ @RequiredArgsConstructor public class PlayerValidator { - private static final Pattern PASSWORD_PATTERN = - Pattern.compile("^(?=.*[a-z])(?=.*\\d)(?=.*[@$!%*#?&])[a-z\\d@$!%*#?&]{8,}$"); - private static final Pattern NAME_PATTERN = Pattern.compile("^[a-zA-Z가-힣0-9]+$"); - + private static final Pattern PASSWORD_PATTERN = + Pattern.compile("^(?=.*[a-z])(?=.*\\d)(?=.*[@$!%*#?&])[a-z\\d@$!%*#?&]{8,}$"); private final ProfanityChecker profanityChecker; public boolean isValidName(String name) { diff --git a/src/main/java/org/codequistify/master/core/domain/stage/controller/StageManagementController.java b/src/main/java/org/codequistify/master/core/domain/stage/controller/StageManagementController.java index 20f89072..003d9b55 100644 --- a/src/main/java/org/codequistify/master/core/domain/stage/controller/StageManagementController.java +++ b/src/main/java/org/codequistify/master/core/domain/stage/controller/StageManagementController.java @@ -6,7 +6,6 @@ import lombok.RequiredArgsConstructor; import org.codequistify.master.core.domain.player.model.Player; import org.codequistify.master.core.domain.stage.dto.*; -import org.codequistify.master.domain.stage.dto.*; import org.codequistify.master.core.domain.stage.service.StageManagementService; import org.codequistify.master.global.aspect.LogMonitoring; import org.codequistify.master.global.exception.ErrorCode; @@ -25,8 +24,8 @@ @Tag(name = "Stage") @RequestMapping("api") public class StageManagementController { - private final StageManagementService stageManagementService; private final Logger LOGGER = LoggerFactory.getLogger(StageManagementController.class); + private final StageManagementService stageManagementService; // 스테이지 등록 @Operation(summary = "스테이지 신규 등록", description = "스테이지 신규 등록") @@ -46,7 +45,7 @@ public ResponseEntity registryStage(@RequestBody StageRegistryReq summary = "문항 채점 요청", description = """ 문항을 채점합니다. 문항 고유 Id와 순서에 대한 정보, 채점 받을 선택을 요청에 포함합니다. - + 마지막 문항인 경우 `nextIndex = -1`, `isLast = true`를 반환힙니다. 다음 문항(question)이 환경 구성 (compose)을 요구한다면, `isComposable = true` 입니다. @@ -107,7 +106,6 @@ public ResponseEntity completeStage(@AuthenticationPrin } - // 스테이지 수정 // 스테이지 문항 수정 diff --git a/src/main/java/org/codequistify/master/core/domain/stage/controller/StageSearchController.java b/src/main/java/org/codequistify/master/core/domain/stage/controller/StageSearchController.java index 4bf09c12..8e0be6e8 100644 --- a/src/main/java/org/codequistify/master/core/domain/stage/controller/StageSearchController.java +++ b/src/main/java/org/codequistify/master/core/domain/stage/controller/StageSearchController.java @@ -28,15 +28,16 @@ @Tag(name = "Stage") @RequestMapping("api") public class StageSearchController { + private final Logger LOGGER = LoggerFactory.getLogger(StageSearchController.class); private final StageManagementService stageManagementService; private final StageSearchService stageSearchService; - private final Logger LOGGER = LoggerFactory.getLogger(StageSearchController.class); + // 스테이지 목록 조회 @Operation( summary = "스테이지 목록 조회", description = """ - 스테이지 목록을 페이지 단위로 조회합니다. - + - 검색가능 조건은 다음과 같습니다. *'스테이지 분류', '세부 난이도', '풀이 여부', '검색 텍스트 포함'* *풀이여부* @@ -50,14 +51,14 @@ public class StageSearchController { - "BASIC_PROBLEMS" : 기본문제 - "ADVANCED_PROBLEMS" : 심화문제 - "MOCK_TESTS" : 모의고사 - + *세부난이도* - difficultLevels 배열안에 있는 난이도를 가지는 문제를 필터링합니다. - "L1", "L2", "L3", "L4", "L5" *텍스트 검색* - searchText 가 'title', 'description', 'stageCode' 중 일치하는 문제를 필터링합니다 - + """ ) @LogExecutionTime @@ -75,7 +76,7 @@ public ResponseEntity findAllStagesByCriteria(@Authentication ) @LogExecutionTime @GetMapping("stages/{stage_id}") - public ResponseEntity getStageInfoById(@PathVariable(value = "stage_id")Long stageId) { + public ResponseEntity getStageInfoById(@PathVariable(value = "stage_id") Long stageId) { StageResponse response = StageConverter.convert(stageSearchService.getStageById(stageId)); return ResponseEntity.status(HttpStatus.OK).body(response); @@ -102,7 +103,7 @@ public ResponseEntity HangulQuery(@RequestParam String s HangulExtractor hangulExtractor = new HangulExtractor(); HangulExtractor.ChoCho response = new HangulExtractor .ChoCho(hangulExtractor - .extractChoseongs(src)); + .extractChoseongs(src)); return ResponseEntity.status(HttpStatus.OK).body(response); } @@ -126,8 +127,7 @@ public ResponseEntity searchStagePreview(@RequestParam String que } response = stageSearchService.getStageBySearchText(query); return ResponseEntity.status(HttpStatus.OK).body(response); - } - catch (EntityNotFoundException exception) { + } catch (EntityNotFoundException exception) { LOGGER.info("[searchStagePreview] 조회된 stage가 존재하지 않습니다."); return ResponseEntity.status(HttpStatus.NO_CONTENT).body(null); } diff --git a/src/main/java/org/codequistify/master/core/domain/stage/convertoer/QuestionConverter.java b/src/main/java/org/codequistify/master/core/domain/stage/convertoer/QuestionConverter.java index f56803c1..4bb16b3a 100644 --- a/src/main/java/org/codequistify/master/core/domain/stage/convertoer/QuestionConverter.java +++ b/src/main/java/org/codequistify/master/core/domain/stage/convertoer/QuestionConverter.java @@ -9,12 +9,12 @@ public class QuestionConverter { public Question convert(QuestionRequest questionRequest) { return Question.builder() - .title(questionRequest.title()) - .description(questionRequest.description()) - .answerType(questionRequest.answerType()) - .correctAnswer(questionRequest.correctAnswer()) - .options(questionRequest.options()) - .build(); + .title(questionRequest.title()) + .description(questionRequest.description()) + .answerType(questionRequest.answerType()) + .correctAnswer(questionRequest.correctAnswer()) + .options(questionRequest.options()) + .build(); } public QuestionResponse convert(Question question) { diff --git a/src/main/java/org/codequistify/master/core/domain/stage/convertoer/StageConverter.java b/src/main/java/org/codequistify/master/core/domain/stage/convertoer/StageConverter.java index 3dfd8e8e..c3b4e8e0 100644 --- a/src/main/java/org/codequistify/master/core/domain/stage/convertoer/StageConverter.java +++ b/src/main/java/org/codequistify/master/core/domain/stage/convertoer/StageConverter.java @@ -19,26 +19,6 @@ public class StageConverter { private final QuestionConverter questionConverter; - public Stage convert(StageRegistryRequest request) { - return Stage.builder() - .title(request.title()) - .description(request.description()) - .stageGroup(request.groupType()) - .difficultyLevel(request.difficultyLevel()) - .questionCount(request.questions().size()) - .questions( - IntStream.range(0, request.questions().size()) - .mapToObj(index -> { - Question question = questionConverter.convert( - request.questions().get(index)); - question.setIndex(index+1); - return question; - }) - .collect(Collectors.toList()) - ) - .build(); - } - public static StageResponse convert(Stage stage) { return new StageResponse( stage.getId(), @@ -53,14 +33,14 @@ public static StageResponse convert(Stage stage) { public static List convert(List stages) { return stages.stream() - .map(StageConverter::convert).collect(Collectors.toList()); + .map(StageConverter::convert).collect(Collectors.toList()); } public static StagePageResponse convert(Page stages) { PageParameters pageParameters = new PageParameters( stages.getTotalPages(), stages.getSize(), - stages.getNumber()+1, + stages.getNumber() + 1, stages.getNumberOfElements(), (int) stages.getTotalElements() ); @@ -69,4 +49,24 @@ public static StagePageResponse convert(Page stages) { return new StagePageResponse(response, pageParameters); } + + public Stage convert(StageRegistryRequest request) { + return Stage.builder() + .title(request.title()) + .description(request.description()) + .stageGroup(request.groupType()) + .difficultyLevel(request.difficultyLevel()) + .questionCount(request.questions().size()) + .questions( + IntStream.range(0, request.questions().size()) + .mapToObj(index -> { + Question question = questionConverter.convert( + request.questions().get(index)); + question.setIndex(index + 1); + return question; + }) + .collect(Collectors.toList()) + ) + .build(); + } } diff --git a/src/main/java/org/codequistify/master/core/domain/stage/domain/CompletedStage.java b/src/main/java/org/codequistify/master/core/domain/stage/domain/CompletedStage.java index 9bb3bb13..96ba380d 100644 --- a/src/main/java/org/codequistify/master/core/domain/stage/domain/CompletedStage.java +++ b/src/main/java/org/codequistify/master/core/domain/stage/domain/CompletedStage.java @@ -33,6 +33,16 @@ public class CompletedStage extends BaseTimeEntity { @Column(name = "question_index", columnDefinition = "0") private Integer questionIndex = 0; + @Builder + public CompletedStage(Player player, Stage stage, CompletedStatus status) { + this.player = player; + this.stage = stage; + this.status = status; + } + + protected CompletedStage() { + } + public void updateQuestionIndex(Integer questionIndex) { this.questionIndex = questionIndex; } @@ -43,14 +53,4 @@ public void updateCompleted() { } this.status = CompletedStatus.COMPLETED; } - - @Builder - public CompletedStage(Player player, Stage stage, CompletedStatus status) { - this.player = player; - this.stage = stage; - this.status = status; - } - - protected CompletedStage() { - } } diff --git a/src/main/java/org/codequistify/master/core/domain/stage/domain/DifficultyLevelType.java b/src/main/java/org/codequistify/master/core/domain/stage/domain/DifficultyLevelType.java index f168f669..0c3723c0 100644 --- a/src/main/java/org/codequistify/master/core/domain/stage/domain/DifficultyLevelType.java +++ b/src/main/java/org/codequistify/master/core/domain/stage/domain/DifficultyLevelType.java @@ -10,8 +10,9 @@ public enum DifficultyLevelType { L4(4, 219), L5(5, 327); - private final int level; private final int exp; + private final int level; + DifficultyLevelType(int level, int exp) { this.level = level; this.exp = exp; diff --git a/src/main/java/org/codequistify/master/core/domain/stage/domain/Question.java b/src/main/java/org/codequistify/master/core/domain/stage/domain/Question.java index 763263ba..78ee08ef 100644 --- a/src/main/java/org/codequistify/master/core/domain/stage/domain/Question.java +++ b/src/main/java/org/codequistify/master/core/domain/stage/domain/Question.java @@ -24,7 +24,8 @@ @UniqueConstraint(name = "uc_stageid_questionindex", columnNames = {"stage_id", "question_index"}) }) public class Question extends BaseTimeEntity { - @Id @GeneratedValue(strategy = GenerationType.AUTO) + @Id + @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "question_id") private Long id; @@ -40,7 +41,8 @@ public class Question extends BaseTimeEntity { @NotNull private String description; - @Column(name = "answer_type") @ColumnDefault("SHORT_ANSWER") + @Column(name = "answer_type") + @ColumnDefault("SHORT_ANSWER") @Enumerated(EnumType.STRING) @NotNull private AnswerType answerType = AnswerType.SHORT_ANSWER; @@ -49,7 +51,8 @@ public class Question extends BaseTimeEntity { @NotNull private String correctAnswer = ""; - @Column(name = "is_composable") @ColumnDefault("false") + @Column(name = "is_composable") + @ColumnDefault("false") @NotNull private boolean isComposable = false; @@ -74,6 +77,7 @@ public void setQuestionId(Long id) { public void addStage(Stage stage) { this.stage = stage; } + public void setIndex(int index) { this.index = index; } diff --git a/src/main/java/org/codequistify/master/core/domain/stage/domain/Stage.java b/src/main/java/org/codequistify/master/core/domain/stage/domain/Stage.java index 0fc7ebf3..7eb2a717 100644 --- a/src/main/java/org/codequistify/master/core/domain/stage/domain/Stage.java +++ b/src/main/java/org/codequistify/master/core/domain/stage/domain/Stage.java @@ -14,7 +14,7 @@ import java.util.stream.Collectors; @Getter -@ToString(exclude = {"questions", "completedStages" }) +@ToString(exclude = {"questions", "completedStages"}) @NoArgsConstructor(access = AccessLevel.PROTECTED) @AllArgsConstructor @Builder @@ -44,7 +44,8 @@ public class Stage extends BaseTimeEntity { @NotNull private DifficultyLevelType difficultyLevel; - @Column(name = "count") @ColumnDefault("0") + @Column(name = "count") + @ColumnDefault("0") private Integer questionCount = 0; @OneToMany(mappedBy = "stage", cascade = CascadeType.ALL, orphanRemoval = true) @@ -56,7 +57,8 @@ public class Stage extends BaseTimeEntity { @NotNull private StageImageType stageImage; - @Column(name = "approved") @ColumnDefault("false") + @Column(name = "approved") + @ColumnDefault("false") private Boolean approved = false; @OneToMany(mappedBy = "stage") @@ -70,8 +72,8 @@ public void updateStageImage(StageImageType stageImageType) { protected void onPostPersist() { // question id 할당 this.questions = questions.stream() - .peek(question -> { - question.addStage(this); - }).collect(Collectors.toList()); + .peek(question -> { + question.addStage(this); + }).collect(Collectors.toList()); } } diff --git a/src/main/java/org/codequistify/master/core/domain/stage/domain/StageImageType.java b/src/main/java/org/codequistify/master/core/domain/stage/domain/StageImageType.java index d4ed99b5..f533a719 100644 --- a/src/main/java/org/codequistify/master/core/domain/stage/domain/StageImageType.java +++ b/src/main/java/org/codequistify/master/core/domain/stage/domain/StageImageType.java @@ -27,7 +27,6 @@ public enum StageImageType { S1021("polhub/s1021", "latest"), - Q1001("polhub/q1001", "latest"), S0000("polhub/s1001", "latest"); diff --git a/src/main/java/org/codequistify/master/core/domain/stage/dto/StageCodeDTO.java b/src/main/java/org/codequistify/master/core/domain/stage/dto/StageCodeDTO.java index 164ff1a3..bda9d18e 100644 --- a/src/main/java/org/codequistify/master/core/domain/stage/dto/StageCodeDTO.java +++ b/src/main/java/org/codequistify/master/core/domain/stage/dto/StageCodeDTO.java @@ -6,7 +6,7 @@ public record StageCodeDTO( StageImageType stageCode, String accessUri ) { - public static StageCodeDTO of (StageImageType stageImageType) { + public static StageCodeDTO of(StageImageType stageImageType) { return new StageCodeDTO(stageImageType, ""); } } diff --git a/src/main/java/org/codequistify/master/core/domain/stage/dto/StageCompletionRequest.java b/src/main/java/org/codequistify/master/core/domain/stage/dto/StageCompletionRequest.java index b5603530..b1b9feda 100644 --- a/src/main/java/org/codequistify/master/core/domain/stage/dto/StageCompletionRequest.java +++ b/src/main/java/org/codequistify/master/core/domain/stage/dto/StageCompletionRequest.java @@ -4,6 +4,5 @@ public record StageCompletionRequest( CompletedStatus status -) -{ +) { } diff --git a/src/main/java/org/codequistify/master/core/domain/stage/repository/StageRepository.java b/src/main/java/org/codequistify/master/core/domain/stage/repository/StageRepository.java index 331a0e89..98a5972c 100644 --- a/src/main/java/org/codequistify/master/core/domain/stage/repository/StageRepository.java +++ b/src/main/java/org/codequistify/master/core/domain/stage/repository/StageRepository.java @@ -19,5 +19,4 @@ public interface StageRepository extends JpaRepository { List findAllByPlayerIdWithCompleted(@Param("playerId") Long playerId);*/ - } diff --git a/src/main/java/org/codequistify/master/core/domain/stage/service/StageManagementService.java b/src/main/java/org/codequistify/master/core/domain/stage/service/StageManagementService.java index d3472dbb..8f3b5c84 100644 --- a/src/main/java/org/codequistify/master/core/domain/stage/service/StageManagementService.java +++ b/src/main/java/org/codequistify/master/core/domain/stage/service/StageManagementService.java @@ -24,7 +24,7 @@ public interface StageManagementService { void recordInProgressStageInit(Player player, GradingRequest request); // 문제 풀이 정보 기록 - public void updateInProgressStage(Player player, GradingRequest request); + void updateInProgressStage(Player player, GradingRequest request); // 스테이지 수정 @@ -32,5 +32,4 @@ public interface StageManagementService { // 스테이지 옵션 수정 - } diff --git a/src/main/java/org/codequistify/master/core/domain/stage/service/StageSearchService.java b/src/main/java/org/codequistify/master/core/domain/stage/service/StageSearchService.java index 6bec64a5..39898824 100644 --- a/src/main/java/org/codequistify/master/core/domain/stage/service/StageSearchService.java +++ b/src/main/java/org/codequistify/master/core/domain/stage/service/StageSearchService.java @@ -1,7 +1,7 @@ package org.codequistify.master.core.domain.stage.service; -import org.codequistify.master.core.domain.player.model.Player; import org.codequistify.master.application.player.dto.PlayerStageProgressResponse; +import org.codequistify.master.core.domain.player.model.Player; import org.codequistify.master.core.domain.player.model.PolId; import org.codequistify.master.core.domain.stage.domain.Stage; import org.codequistify.master.core.domain.stage.dto.*; @@ -23,10 +23,12 @@ public interface StageSearchService { // 진행중인 스테이지 목록 조회 PlayerStageProgressResponse getInProgressStagesByPlayerId(PolId playerId); + // 완료한 날짜/횟수 기록 조회 List getHeatMapDataPointsByModifiedDate(PolId playerId); //preview 메서드 StageResponse getStageByChoCho(String src); + StageResponse getStageBySearchText(String searchText); } diff --git a/src/main/java/org/codequistify/master/core/domain/stage/service/impl/StageManagementServiceImpl.java b/src/main/java/org/codequistify/master/core/domain/stage/service/impl/StageManagementServiceImpl.java index e85760dd..bffb69f6 100644 --- a/src/main/java/org/codequistify/master/core/domain/stage/service/impl/StageManagementServiceImpl.java +++ b/src/main/java/org/codequistify/master/core/domain/stage/service/impl/StageManagementServiceImpl.java @@ -1,14 +1,13 @@ package org.codequistify.master.core.domain.stage.service.impl; import lombok.RequiredArgsConstructor; +import org.codequistify.master.application.player.service.PlayerProfileService; import org.codequistify.master.core.domain.lab.service.LabAssignmentService; import org.codequistify.master.core.domain.player.model.Player; -import org.codequistify.master.application.player.service.PlayerProfileService; import org.codequistify.master.core.domain.stage.convertoer.QuestionConverter; import org.codequistify.master.core.domain.stage.convertoer.StageConverter; import org.codequistify.master.core.domain.stage.domain.*; import org.codequistify.master.core.domain.stage.dto.*; -import org.codequistify.master.domain.stage.dto.*; import org.codequistify.master.core.domain.stage.repository.CompletedStageRepository; import org.codequistify.master.core.domain.stage.repository.QuestionRepository; import org.codequistify.master.core.domain.stage.repository.StageRepository; @@ -25,17 +24,16 @@ @Service @RequiredArgsConstructor public class StageManagementServiceImpl implements StageManagementService { - private final StageRepository stageRepository; - private final QuestionRepository questionRepository; + private final static int LEVEL_STEP_SIZE = 500; + private final Logger LOGGER = LoggerFactory.getLogger(StageManagementServiceImpl.class); private final CompletedStageRepository completedStageRepository; private final LabAssignmentService labAssignmentService; private final PlayerProfileService playerProfileService; - - private final StageConverter stageConverter; private final QuestionConverter questionConverter; - private final Logger LOGGER = LoggerFactory.getLogger(StageManagementServiceImpl.class); - private final static int LEVEL_STEP_SIZE = 500; + private final QuestionRepository questionRepository; + private final StageConverter stageConverter; + private final StageRepository stageRepository; @Override @Transactional @@ -51,17 +49,19 @@ public void saveStage(StageRegistryRequest request) { public GradingResponse evaluateAnswer(Player player, GradingRequest request) { Question question = questionRepository.findByStageIdAndIndex(request.stageId(), request.questionIndex()) .orElseThrow(() -> { - LOGGER.info("[checkAnswerCorrectness] {}, id: {}, index: {}", - ErrorCode.QUESTION_NOT_FOUND.getMessage(), request.stageId(), request.questionIndex()); - return new BusinessException(ErrorCode.QUESTION_NOT_FOUND, HttpStatus.NOT_FOUND); - }); + LOGGER.info("[checkAnswerCorrectness] {}, id: {}, index: {}", + ErrorCode.QUESTION_NOT_FOUND.getMessage(), + request.stageId(), + request.questionIndex()); + return new BusinessException(ErrorCode.QUESTION_NOT_FOUND, + HttpStatus.NOT_FOUND); + }); boolean isCorrect; if (question.getAnswerType().equals(AnswerType.PRACTICAL)) { Stage stage = question.getStage(); isCorrect = this.evaluatePracticalAnswerCorrectness(player, stage, request); - } - else { + } else { isCorrect = this.evaluateStandardAnswerCorrectness(question, request); } @@ -70,7 +70,7 @@ public GradingResponse evaluateAnswer(Player player, GradingRequest request) { int nextIndex = isLast ? -1 : request.questionIndex() + 1; Boolean isComposable = questionRepository - .isComposableForStageAndIndex(request.stageId(), request.questionIndex()); + .isComposableForStageAndIndex(request.stageId(), request.questionIndex()); if (isComposable == null) { isComposable = false; } @@ -104,11 +104,14 @@ private boolean evaluatePracticalAnswerCorrectness(Player player, Stage stage, G @Transactional public SuccessResponse composePShell(Player player, GradingRequest request) { Question question = questionRepository.findByStageIdAndIndex(request.stageId(), request.questionIndex()) - .orElseThrow(() -> { - LOGGER.info("[checkAnswerCorrectness] {}, id: {}, index: {}", - ErrorCode.QUESTION_NOT_FOUND.getMessage(), request.stageId(), request.questionIndex()); - return new BusinessException(ErrorCode.QUESTION_NOT_FOUND, HttpStatus.NOT_FOUND); - }); + .orElseThrow(() -> { + LOGGER.info("[checkAnswerCorrectness] {}, id: {}, index: {}", + ErrorCode.QUESTION_NOT_FOUND.getMessage(), + request.stageId(), + request.questionIndex()); + return new BusinessException(ErrorCode.QUESTION_NOT_FOUND, + HttpStatus.NOT_FOUND); + }); Stage stage = question.getStage(); StageActionRequest stageActionRequest = new StageActionRequest( @@ -128,11 +131,11 @@ public SuccessResponse composePShell(Player player, GradingRequest request) { @Transactional public StageCompletionResponse recordStageComplete(Player player, Long stageId) { Stage stage = stageRepository.findById(stageId) - .orElseThrow(() -> { - LOGGER.info("[recordStageComplete] {}}, stage: {}", - ErrorCode.STAGE_NOT_FOUND.getMessage(), stageId); - return new BusinessException(ErrorCode.STAGE_NOT_FOUND, HttpStatus.NOT_FOUND); - }); + .orElseThrow(() -> { + LOGGER.info("[recordStageComplete] {}}, stage: {}", + ErrorCode.STAGE_NOT_FOUND.getMessage(), stageId); + return new BusinessException(ErrorCode.STAGE_NOT_FOUND, HttpStatus.NOT_FOUND); + }); CompletedStage completedStage; if (!completedStageRepository.existsByPlayerIdAndStageId(player.getId(), stageId)) { @@ -140,13 +143,12 @@ public StageCompletionResponse recordStageComplete(Player player, Long stageId) .player(player) .stage(stage) .status(CompletedStatus.COMPLETED).build(); - } - else { + } else { completedStage = completedStageRepository .findByPlayerIdAndStageId(player.getId(), stageId) .orElseThrow(() -> { LOGGER.info("[updateInProgressStage] {}, stage: {}", - ErrorCode.STAGE_PROGRESS_NOT_FOUND.getMessage(), stageId); + ErrorCode.STAGE_PROGRESS_NOT_FOUND.getMessage(), stageId); return new BusinessException(ErrorCode.STAGE_PROGRESS_NOT_FOUND, HttpStatus.NOT_FOUND); }); completedStage.updateCompleted(); @@ -176,38 +178,37 @@ public void recordInProgressStageInit(Player player, GradingRequest request) { } Stage stage = stageRepository.findById(request.stageId()) - .orElseThrow(() -> { - LOGGER.info("[recordStageComplete] {}, stage: {}", - ErrorCode.STAGE_NOT_FOUND.getMessage(), request.stageId()); - return new BusinessException(ErrorCode.STAGE_NOT_FOUND, HttpStatus.NOT_FOUND); - }); + .orElseThrow(() -> { + LOGGER.info("[recordStageComplete] {}, stage: {}", + ErrorCode.STAGE_NOT_FOUND.getMessage(), request.stageId()); + return new BusinessException(ErrorCode.STAGE_NOT_FOUND, HttpStatus.NOT_FOUND); + }); CompletedStage completedStage = CompletedStage.builder() - .player(player) - .stage(stage) - .status(CompletedStatus.IN_PROGRESS).build(); + .player(player) + .stage(stage) + .status(CompletedStatus.IN_PROGRESS).build(); completedStageRepository.save(completedStage); LOGGER.info("[recordInProgressStageInit] 풀이 시작 기록 stage: {}, index: {}", - request.stageId(), request.questionIndex()); + request.stageId(), request.questionIndex()); } @Transactional public void updateInProgressStage(Player player, GradingRequest request) { CompletedStage completedStage = completedStageRepository .findByPlayerIdAndStageId(player.getId(), request.stageId()) - .orElseThrow(()->{ + .orElseThrow(() -> { LOGGER.info("[updateInProgressStage] {}, stage: {}", - ErrorCode.STAGE_PROGRESS_NOT_FOUND.getMessage(), request.stageId()); + ErrorCode.STAGE_PROGRESS_NOT_FOUND.getMessage(), request.stageId()); return new BusinessException(ErrorCode.STAGE_PROGRESS_NOT_FOUND, HttpStatus.NOT_FOUND); }); completedStage.updateQuestionIndex(request.questionIndex()); completedStageRepository.save(completedStage); LOGGER.info("[updateInProgressStage] 진행정도 업데이트 stage: {}, index: {}", - request.stageId(), request.questionIndex()); + request.stageId(), request.questionIndex()); } - } diff --git a/src/main/java/org/codequistify/master/core/domain/stage/service/impl/StageSearchServiceImpl.java b/src/main/java/org/codequistify/master/core/domain/stage/service/impl/StageSearchServiceImpl.java index 35ff0333..f99db1d5 100644 --- a/src/main/java/org/codequistify/master/core/domain/stage/service/impl/StageSearchServiceImpl.java +++ b/src/main/java/org/codequistify/master/core/domain/stage/service/impl/StageSearchServiceImpl.java @@ -7,8 +7,8 @@ import com.querydsl.jpa.impl.JPAQueryFactory; import jakarta.persistence.EntityNotFoundException; import lombok.RequiredArgsConstructor; -import org.codequistify.master.core.domain.player.model.Player; import org.codequistify.master.application.player.dto.PlayerStageProgressResponse; +import org.codequistify.master.core.domain.player.model.Player; import org.codequistify.master.core.domain.player.model.PolId; import org.codequistify.master.core.domain.stage.convertoer.QuestionConverter; import org.codequistify.master.core.domain.stage.convertoer.StageConverter; @@ -16,13 +16,13 @@ import org.codequistify.master.core.domain.stage.domain.Question; import org.codequistify.master.core.domain.stage.domain.Stage; import org.codequistify.master.core.domain.stage.dto.*; -import org.codequistify.master.domain.stage.domain.*; -import org.codequistify.master.domain.stage.dto.*; import org.codequistify.master.core.domain.stage.repository.CompletedStageRepository; import org.codequistify.master.core.domain.stage.repository.QuestionRepository; import org.codequistify.master.core.domain.stage.repository.StageRepository; import org.codequistify.master.core.domain.stage.service.StageSearchService; import org.codequistify.master.core.domain.stage.utils.HangulExtractor; +import org.codequistify.master.domain.stage.domain.QCompletedStage; +import org.codequistify.master.domain.stage.domain.QStage; import org.codequistify.master.global.aspect.LogMonitoring; import org.codequistify.master.global.exception.ErrorCode; import org.codequistify.master.global.exception.domain.BusinessException; @@ -41,24 +41,22 @@ @Service public class StageSearchServiceImpl implements StageSearchService { - private final StageRepository stageRepository; - private final QuestionRepository questionRepository; + private final Logger LOGGER = LoggerFactory.getLogger(StageSearchServiceImpl.class); private final CompletedStageRepository completedStageRepository; private final JPAQueryFactory queryFactory; - - private final StageConverter stageConverter; private final QuestionConverter questionConverter; - private final Logger LOGGER = LoggerFactory.getLogger(StageSearchServiceImpl.class); - + private final QuestionRepository questionRepository; + private final StageConverter stageConverter; + private final StageRepository stageRepository; @Override // 스테이지 조회 @Transactional public Stage getStageById(Long stageId) { return stageRepository.findById(stageId) - .orElseThrow(() -> { - LOGGER.info("[findStageById] 등록되지 않은 스테이지 id: {}", stageId); - return new BusinessException(ErrorCode.STAGE_NOT_FOUND, HttpStatus.NOT_FOUND); - }); + .orElseThrow(() -> { + LOGGER.info("[findStageById] 등록되지 않은 스테이지 id: {}", stageId); + return new BusinessException(ErrorCode.STAGE_NOT_FOUND, HttpStatus.NOT_FOUND); + }); } @Override // 문항 조회 @@ -66,9 +64,13 @@ public Stage getStageById(Long stageId) { public QuestionResponse findQuestion(Long stageId, Integer questionIndex) { Question question = questionRepository.findByStageIdAndIndex(stageId, questionIndex) .orElseThrow(() -> { - LOGGER.info("[findQuestion] {}, id: {}, index: {}", ErrorCode.QUESTION_NOT_FOUND.getMessage(), stageId, questionIndex); - return new BusinessException(ErrorCode.QUESTION_NOT_FOUND, HttpStatus.NOT_FOUND); - }); + LOGGER.info("[findQuestion] {}, id: {}, index: {}", + ErrorCode.QUESTION_NOT_FOUND.getMessage(), + stageId, + questionIndex); + return new BusinessException(ErrorCode.QUESTION_NOT_FOUND, + HttpStatus.NOT_FOUND); + }); QuestionResponse response = questionConverter.convert(question); LOGGER.info("[findQuestion] 문항 조회, id: {}, index: {}", stageId, questionIndex); @@ -82,40 +84,34 @@ public StageResponse getStageByChoCho(String query) { //int index = 1; //PageRequest pageRequest = PageRequest.of(index, 10); - return stageConverter.convert( + return StageConverter.convert( stageRepository.findAll().stream().parallel() - .filter(stage -> { - if (hangulExtractor.containsByChoseong(stage.getTitle(), choSrc)) { - return true; - } - if (hangulExtractor.containsByChoseong(stage.getDescription(), choSrc)) { - return true; - } - return false; - }).findAny() - .orElseThrow(() -> new EntityNotFoundException()) + .filter(stage -> { + if (hangulExtractor.containsByChoseong(stage.getTitle(), choSrc)) { + return true; + } + return hangulExtractor.containsByChoseong(stage.getDescription(), choSrc); + }).findAny() + .orElseThrow(() -> new EntityNotFoundException()) ); } public StageResponse getStageBySearchText(String query) { - return stageConverter.convert( + return StageConverter.convert( stageRepository.findAll().stream().parallel() - .filter(stage -> { - if (stage.getTitle().toLowerCase() - .contains(query.toLowerCase())) { - return true; - } - if (stage.getDescription().toLowerCase() - .contains(query.toLowerCase())) { - return true; - } - if (stage.getStageImage().name().toLowerCase() - .contains(query.toLowerCase())) { - return true; - } - return false; - }).findAny() - .orElseThrow(() -> new EntityNotFoundException()) + .filter(stage -> { + if (stage.getTitle().toLowerCase() + .contains(query.toLowerCase())) { + return true; + } + if (stage.getDescription().toLowerCase() + .contains(query.toLowerCase())) { + return true; + } + return stage.getStageImage().name().toLowerCase() + .contains(query.toLowerCase()); + }).findAny() + .orElseThrow(() -> new EntityNotFoundException()) ); } @@ -165,7 +161,11 @@ public StagePageResponse findStagesByCriteria(SearchCriteria searchCriteria, Pla whereClause.and(qStage.approved.eq(true)); // 쿼리 결과 조회 - List results = fetchStageResponses(whereClause, qStage, qCompletedStage, pageRequest, player.getId()); + List results = fetchStageResponses(whereClause, + qStage, + qCompletedStage, + pageRequest, + player.getId()); // 전체 개수 조회 long total = fetchTotalCount(whereClause, qStage, qCompletedStage, player.getId()); @@ -196,14 +196,14 @@ private List fetchStageResponses( return queryFactory .select(Projections.constructor(StageResponse.class, - qStage.id, - Expressions.stringTemplate("cast({0} as string)", qStage.stageImage), - qStage.title, - qStage.description, - qStage.stageGroup, - qStage.difficultyLevel, - qStage.questionCount, - qCompletedStage.status.coalesce(CompletedStatus.NOT_COMPLETED))) + qStage.id, + Expressions.stringTemplate("cast({0} as string)", qStage.stageImage), + qStage.title, + qStage.description, + qStage.stageGroup, + qStage.difficultyLevel, + qStage.questionCount, + qCompletedStage.status.coalesce(CompletedStatus.NOT_COMPLETED))) .from(qStage) .leftJoin(qStage.completedStages, qCompletedStage) .on(qCompletedStage.player.id.eq(playerId)) @@ -225,21 +225,27 @@ private long fetchTotalCount(BooleanBuilder whereClause, .fetchCount(); } - private void addWhereConditionForStageGroupTypes(BooleanBuilder whereClause, SearchCriteria searchCriteria, QStage qStage) { + private void addWhereConditionForStageGroupTypes(BooleanBuilder whereClause, + SearchCriteria searchCriteria, + QStage qStage) { if (searchCriteria.getStageGroupTypes() == null || searchCriteria.getStageGroupTypes().isEmpty()) { return; } whereClause.and(qStage.stageGroup.in(searchCriteria.getStageGroupTypes())); } - private void addWhereConditionForDifficultLevels(BooleanBuilder whereClause, SearchCriteria searchCriteria, QStage qStage) { + private void addWhereConditionForDifficultLevels(BooleanBuilder whereClause, + SearchCriteria searchCriteria, + QStage qStage) { if (searchCriteria.getDifficultyLevels() == null || searchCriteria.getDifficultyLevels().isEmpty()) { return; } whereClause.and(qStage.difficultyLevel.in(searchCriteria.getDifficultyLevels())); } - private void addWhereConditionForSearchText(BooleanBuilder whereClause, SearchCriteria searchCriteria, QStage qStage) { + private void addWhereConditionForSearchText(BooleanBuilder whereClause, + SearchCriteria searchCriteria, + QStage qStage) { if (searchCriteria.getSearchText() == null || searchCriteria.getSearchText().isBlank()) { return; } @@ -256,14 +262,17 @@ private void addWhereConditionForSearchText(BooleanBuilder whereClause, SearchCr whereClause.and(descriptionContains.or(titleContains).or(stageImageContains)); } - private void addWhereConditionForCompletedStatus(BooleanBuilder whereClause, SearchCriteria searchCriteria, QCompletedStage qCompletedStage, Long playerId) { + private void addWhereConditionForCompletedStatus(BooleanBuilder whereClause, + SearchCriteria searchCriteria, + QCompletedStage qCompletedStage, + Long playerId) { if (searchCriteria.getCompleted() != null) { if (searchCriteria.getCompleted() == CompletedStatus.NOT_COMPLETED) { // NOT_COMPLETED 상태는 Completed 테이블에 기록되지 않은 상태임 whereClause.and(qCompletedStage.id.isNull()); } else { whereClause.and(qCompletedStage.status.eq(searchCriteria.getCompleted()) - .and(qCompletedStage.player.id.eq(playerId))); + .and(qCompletedStage.player.id.eq(playerId))); } } } diff --git a/src/main/java/org/codequistify/master/core/domain/stage/utils/HangulExtractor.java b/src/main/java/org/codequistify/master/core/domain/stage/utils/HangulExtractor.java index 5fcf1d57..128da323 100644 --- a/src/main/java/org/codequistify/master/core/domain/stage/utils/HangulExtractor.java +++ b/src/main/java/org/codequistify/master/core/domain/stage/utils/HangulExtractor.java @@ -5,8 +5,9 @@ public class HangulExtractor { public final static List choseongs = List .of('ㄱ', 'ㄲ', 'ㄴ', 'ㄷ', 'ㄸ', 'ㄹ', 'ㅁ', 'ㅂ', 'ㅃ', 'ㅅ', 'ㅆ', 'ㅇ', 'ㅈ', 'ㅉ', 'ㅊ', 'ㅋ', 'ㅌ', 'ㅍ', 'ㅎ'); - private final static int JUNGSEONGS_COUNT = 21; private final static int JONGSEONGS_COUNT = 28; + private final static int JUNGSEONGS_COUNT = 21; + public String extractChoseongs(String src) { StringBuilder sb = new StringBuilder(); @@ -21,7 +22,7 @@ public String extractChoseongs(String src) { sb.append(choseongs.get(idx)); } - System.out.println(sb.toString()); + System.out.println(sb); return sb.toString(); } @@ -45,7 +46,7 @@ private boolean isHangul(int unicode) { return 0xAC00 <= unicode && unicode <= 0xD7A3; // 한글이면 } - public static record ChoCho ( + public record ChoCho( String choseongs ) { diff --git a/src/main/java/org/codequistify/master/global/aspect/ExecutionTimeLoggingAspect.java b/src/main/java/org/codequistify/master/global/aspect/ExecutionTimeLoggingAspect.java index 214eb172..c74b1b60 100644 --- a/src/main/java/org/codequistify/master/global/aspect/ExecutionTimeLoggingAspect.java +++ b/src/main/java/org/codequistify/master/global/aspect/ExecutionTimeLoggingAspect.java @@ -14,6 +14,7 @@ @RequiredArgsConstructor public class ExecutionTimeLoggingAspect { private final Logger LOGGER = LoggerFactory.getLogger(MethodInvocationLoggingAspect.class); + @Around("@annotation(LogExecutionTime) || @annotation(LogMonitoring)") public Object logMethod(ProceedingJoinPoint joinPoint) throws Throwable { MethodSignature signature = (MethodSignature) joinPoint.getSignature(); diff --git a/src/main/java/org/codequistify/master/global/aspect/MethodInvocationLoggingAspect.java b/src/main/java/org/codequistify/master/global/aspect/MethodInvocationLoggingAspect.java index a7123401..5c4b64f8 100644 --- a/src/main/java/org/codequistify/master/global/aspect/MethodInvocationLoggingAspect.java +++ b/src/main/java/org/codequistify/master/global/aspect/MethodInvocationLoggingAspect.java @@ -20,6 +20,7 @@ @RequiredArgsConstructor public class MethodInvocationLoggingAspect { private final Logger LOGGER = LoggerFactory.getLogger(MethodInvocationLoggingAspect.class); + @Around("@annotation(LogMethodInvocation) || @annotation(LogMonitoring)") public Object logMethod(ProceedingJoinPoint joinPoint) throws Throwable { MethodSignature signature = (MethodSignature) joinPoint.getSignature(); @@ -28,7 +29,10 @@ public Object logMethod(ProceedingJoinPoint joinPoint) throws Throwable { HttpServletRequest request = attributes.getRequest(); String requestId = (String) request.getAttribute("RequestID"); - LOGGER.info("[{}] RequestID: {}, Parameter: {}", signature.getMethod().getName(), requestId, Arrays.toString(joinPoint.getArgs())); + LOGGER.info("[{}] RequestID: {}, Parameter: {}", + signature.getMethod().getName(), + requestId, + Arrays.toString(joinPoint.getArgs())); Object result = ErrorCode.FAIL_PROCEED; try { diff --git a/src/main/java/org/codequistify/master/global/config/BadWordFilteringConfig.java b/src/main/java/org/codequistify/master/global/config/BadWordFilteringConfig.java index 958b6365..8d8343d3 100644 --- a/src/main/java/org/codequistify/master/global/config/BadWordFilteringConfig.java +++ b/src/main/java/org/codequistify/master/global/config/BadWordFilteringConfig.java @@ -21,7 +21,7 @@ public class BadWordFilteringConfig { @Bean public BadWordFiltering badWordFiltering() throws IOException { BadWordFiltering badWordFiltering = new BadWordFiltering(); - List filteringWords = loadWordsAsList(); + List filteringWords = loadWordsAsList(); badWordFiltering.addAll(filteringWords); return badWordFiltering; diff --git a/src/main/java/org/codequistify/master/global/config/RestTemplateConfig.java b/src/main/java/org/codequistify/master/global/config/RestTemplateConfig.java index e23c0883..800bb105 100644 --- a/src/main/java/org/codequistify/master/global/config/RestTemplateConfig.java +++ b/src/main/java/org/codequistify/master/global/config/RestTemplateConfig.java @@ -15,13 +15,15 @@ public class RestTemplateConfig { @Bean public RestTemplate restTemplate() { PoolingHttpClientConnectionManager connectionManager = PoolingHttpClientConnectionManagerBuilder.create() - .setMaxConnTotal(100) - .setMaxConnPerRoute(60) - .build(); + .setMaxConnTotal( + 100) + .setMaxConnPerRoute( + 60) + .build(); CloseableHttpClient closeableHttpClient = HttpClients.custom() - .setConnectionManager(connectionManager) - .build(); + .setConnectionManager(connectionManager) + .build(); HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(closeableHttpClient); factory.setConnectTimeout(1000); diff --git a/src/main/java/org/codequistify/master/global/config/SecurityConfig.java b/src/main/java/org/codequistify/master/global/config/SecurityConfig.java index 36df8830..ab6a9495 100644 --- a/src/main/java/org/codequistify/master/global/config/SecurityConfig.java +++ b/src/main/java/org/codequistify/master/global/config/SecurityConfig.java @@ -20,9 +20,9 @@ @EnableWebSecurity @RequiredArgsConstructor public class SecurityConfig { - private final CustomCorsFilter customCorsFilter; private final AuthenticationTokenFilter authenticationTokenFilter; private final BusinessExceptionHandlerFilter businessExceptionHandlerFilter; + private final CustomCorsFilter customCorsFilter; private final ServletFilter servletFilter; @Bean @@ -39,7 +39,13 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { // 폼 로그인 비활성화 .formLogin(form -> form.disable()) .authorizeHttpRequests((authorize) -> authorize - .requestMatchers("/home/**", "/index/**", "/index.js", "/favicon.ico", "/swagger-ui/**", "/v3/**", "/api/todo-list/**").permitAll() + .requestMatchers("/home/**", + "/index/**", + "/index.js", + "/favicon.ico", + "/swagger-ui/**", + "/v3/**", + "/api/todo-list/**").permitAll() .requestMatchers("/api/auth/**").permitAll() .anyRequest().authenticated()) diff --git a/src/main/java/org/codequistify/master/global/config/WebConfig.java b/src/main/java/org/codequistify/master/global/config/WebConfig.java index a5216ed1..885e39ec 100644 --- a/src/main/java/org/codequistify/master/global/config/WebConfig.java +++ b/src/main/java/org/codequistify/master/global/config/WebConfig.java @@ -10,6 +10,7 @@ @RequiredArgsConstructor public class WebConfig implements WebMvcConfigurer { private final HttpLoggingInterceptor httpLoggingInterceptor; + @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(httpLoggingInterceptor) diff --git a/src/main/java/org/codequistify/master/global/exception/ErrorCode.java b/src/main/java/org/codequistify/master/global/exception/ErrorCode.java index fcd2c882..27e56e06 100644 --- a/src/main/java/org/codequistify/master/global/exception/ErrorCode.java +++ b/src/main/java/org/codequistify/master/global/exception/ErrorCode.java @@ -44,8 +44,8 @@ public enum ErrorCode { // 정상 SUCCESS("SUCCESS", "2000_SUCCESS_OK"); - private final String message; private final String code; + private final String message; ErrorCode(String message, String code) { this.message = message; diff --git a/src/main/java/org/codequistify/master/global/exception/RestExceptionHandler.java b/src/main/java/org/codequistify/master/global/exception/RestExceptionHandler.java index b3bfd297..aeec8250 100644 --- a/src/main/java/org/codequistify/master/global/exception/RestExceptionHandler.java +++ b/src/main/java/org/codequistify/master/global/exception/RestExceptionHandler.java @@ -13,6 +13,7 @@ @RestControllerAdvice public class RestExceptionHandler { private final Logger LOGGER = LoggerFactory.getLogger(RestExceptionHandler.class); + @ExceptionHandler(BusinessException.class) public ResponseEntity handleBusinessException(BusinessException exception) { LOGGER.info("[ExceptionHandler] Message: {}, Detail: {}", exception.getMessage(), exception.getDetail()); @@ -23,13 +24,15 @@ public ResponseEntity handleBusinessException(BusinessException e @ExceptionHandler(MethodArgumentNotValidException.class) public ResponseEntity handleMethodArgumentNotValidException(MethodArgumentNotValidException exception) { ErrorCode errorCode = exception.getBindingResult().getAllErrors().stream() - .findAny() - .map(error -> ErrorCode.findByCode( - error.getDefaultMessage())) - .orElse(ErrorCode.UNKNOWN); + .findAny() + .map(error -> ErrorCode.findByCode( + error.getDefaultMessage())) + .orElse(ErrorCode.UNKNOWN); BusinessException businessException = new BusinessException(errorCode, HttpStatus.BAD_REQUEST); - LOGGER.info("[ExceptionHandler] Message: {}, Detail: {}", businessException.getMessage(), businessException.getDetail()); + LOGGER.info("[ExceptionHandler] Message: {}, Detail: {}", + businessException.getMessage(), + businessException.getDetail()); return ResponseEntity .status(businessException.getHttpStatus()) @@ -44,7 +47,9 @@ public ResponseEntity handleRuntimeException(RuntimeException exc HttpStatus status = HttpStatus.INTERNAL_SERVER_ERROR; BusinessException businessException = new BusinessException(errorCode, status, "서버 내부 오류가 발생했습니다."); - LOGGER.error("[ExceptionHandler] Message: {}, Detail: {}", businessException.getMessage(), exception.getMessage()); + LOGGER.error("[ExceptionHandler] Message: {}, Detail: {}", + businessException.getMessage(), + exception.getMessage()); return ResponseEntity .status(status) diff --git a/src/main/java/org/codequistify/master/global/exception/domain/BusinessException.java b/src/main/java/org/codequistify/master/global/exception/domain/BusinessException.java index 5b67c011..cc9e869b 100644 --- a/src/main/java/org/codequistify/master/global/exception/domain/BusinessException.java +++ b/src/main/java/org/codequistify/master/global/exception/domain/BusinessException.java @@ -5,10 +5,10 @@ import org.springframework.http.HttpStatus; @Getter -public class BusinessException extends RuntimeException{ - private final HttpStatus httpStatus; - private final ErrorCode errorCode; +public class BusinessException extends RuntimeException { private final String detail; + private final ErrorCode errorCode; + private final HttpStatus httpStatus; public BusinessException(ErrorCode errorCode, HttpStatus httpStatus) { super(errorCode.getMessage()); @@ -44,7 +44,11 @@ public BusinessException(BusinessException businessException, HttpStatus httpSta this.detail = businessException.getDetail(); } - public BusinessException(ErrorCode errorCode, HttpStatus httpStatus, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { + public BusinessException(ErrorCode errorCode, + HttpStatus httpStatus, + Throwable cause, + boolean enableSuppression, + boolean writableStackTrace) { super(errorCode.getMessage(), cause, enableSuppression, writableStackTrace); this.httpStatus = httpStatus; this.errorCode = errorCode; diff --git a/src/main/java/org/codequistify/master/global/filter/AuthenticationTokenFilter.java b/src/main/java/org/codequistify/master/global/filter/AuthenticationTokenFilter.java index ebf863ac..7494ea9b 100644 --- a/src/main/java/org/codequistify/master/global/filter/AuthenticationTokenFilter.java +++ b/src/main/java/org/codequistify/master/global/filter/AuthenticationTokenFilter.java @@ -25,9 +25,8 @@ @Component @RequiredArgsConstructor public class AuthenticationTokenFilter extends OncePerRequestFilter { - private final TokenProvider tokenProvider; private final Logger logger = LoggerFactory.getLogger(AuthenticationTokenFilter.class); - + private final TokenProvider tokenProvider; @Value("${host.develop.api.ant-match.uri}") private List antMatchURIs = new ArrayList<>(); diff --git a/src/main/java/org/codequistify/master/global/filter/BusinessExceptionHandlerFilter.java b/src/main/java/org/codequistify/master/global/filter/BusinessExceptionHandlerFilter.java index 0512d66f..173bf8d9 100644 --- a/src/main/java/org/codequistify/master/global/filter/BusinessExceptionHandlerFilter.java +++ b/src/main/java/org/codequistify/master/global/filter/BusinessExceptionHandlerFilter.java @@ -15,16 +15,19 @@ @Component public class BusinessExceptionHandlerFilter extends OncePerRequestFilter { @Override - protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { + protected void doFilterInternal(HttpServletRequest request, + HttpServletResponse response, + FilterChain filterChain) throws ServletException, IOException { try { filterChain.doFilter(request, response); - } - catch (BusinessException exception) { + } catch (BusinessException exception) { writeErrorCode(request, response, exception); } } - private void writeErrorCode(HttpServletRequest request, HttpServletResponse response, BusinessException exception) throws IOException { + private void writeErrorCode(HttpServletRequest request, + HttpServletResponse response, + BusinessException exception) throws IOException { response.setContentType("application/json"); response.setCharacterEncoding("UTF-8"); response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); diff --git a/src/main/java/org/codequistify/master/global/filter/CustomCorsFilter.java b/src/main/java/org/codequistify/master/global/filter/CustomCorsFilter.java index b0e05911..6127bf94 100644 --- a/src/main/java/org/codequistify/master/global/filter/CustomCorsFilter.java +++ b/src/main/java/org/codequistify/master/global/filter/CustomCorsFilter.java @@ -16,9 +16,17 @@ public CustomCorsFilter() { private static CorsConfigurationSource corsConfigurationSource() { CorsConfiguration configuration = new CorsConfiguration(); - configuration.setAllowedOrigins(Arrays.asList("http://localhost:3000", "https://localhost:3000", "http://localhost:8080", "https://www.pol.or.kr", "https://test.www.pol.or.kr", "https://api.pol.or.kr")); // 허용할 출처 + configuration.setAllowedOrigins(Arrays.asList("http://localhost:3000", + "https://localhost:3000", + "http://localhost:8080", + "https://www.pol.or.kr", + "https://test.www.pol.or.kr", + "https://api.pol.or.kr")); // 허용할 출처 configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "PATCH")); // 허용할 HTTP 메소드 - configuration.setAllowedHeaders(Arrays.asList("Content-Type", "Accept", "Authorization", "X-Real-IP")); // 허용할 헤더 + configuration.setAllowedHeaders(Arrays.asList("Content-Type", + "Accept", + "Authorization", + "X-Real-IP")); // 허용할 헤더 configuration.setAllowCredentials(true); // 쿠키 및 인증 정보 허용 설정 configuration.setMaxAge(3600L); // 사전 요청 캐시 시간 diff --git a/src/main/java/org/codequistify/master/global/filter/ServletFilter.java b/src/main/java/org/codequistify/master/global/filter/ServletFilter.java index 8c821f03..7110cde0 100644 --- a/src/main/java/org/codequistify/master/global/filter/ServletFilter.java +++ b/src/main/java/org/codequistify/master/global/filter/ServletFilter.java @@ -15,15 +15,6 @@ public class ServletFilter extends OncePerRequestFilter { private final Logger LOGGER = LoggerFactory.getLogger(ServletFilter.class); - @Override - protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { - String requestURI = request.getRequestURI(); - String requestAddr = getOriginRemoteAddr(request); - - LOGGER.info("[LOGGER] RequestURI: {}, RequestHost: {}", requestURI, requestAddr); - filterChain.doFilter(request, response); - } - private static String getOriginRemoteAddr(HttpServletRequest request) { String originAddr = request.getHeader("X-Real-IP"); @@ -33,4 +24,15 @@ private static String getOriginRemoteAddr(HttpServletRequest request) { return originAddr; } + + @Override + protected void doFilterInternal(HttpServletRequest request, + HttpServletResponse response, + FilterChain filterChain) throws ServletException, IOException { + String requestURI = request.getRequestURI(); + String requestAddr = getOriginRemoteAddr(request); + + LOGGER.info("[LOGGER] RequestURI: {}, RequestHost: {}", requestURI, requestAddr); + filterChain.doFilter(request, response); + } } diff --git a/src/main/java/org/codequistify/master/global/interceptor/HttpLoggingInterceptor.java b/src/main/java/org/codequistify/master/global/interceptor/HttpLoggingInterceptor.java index 86753fd7..248a37dc 100644 --- a/src/main/java/org/codequistify/master/global/interceptor/HttpLoggingInterceptor.java +++ b/src/main/java/org/codequistify/master/global/interceptor/HttpLoggingInterceptor.java @@ -14,24 +14,41 @@ public class HttpLoggingInterceptor implements HandlerInterceptor { private final Logger LOGGER = LoggerFactory.getLogger(HttpLoggingInterceptor.class); + private static String getOriginRemoteAddr(HttpServletRequest request) { + String originAddr = request.getHeader("X-Real-IP"); + + if (originAddr == null || originAddr.isBlank()) { + originAddr = request.getRemoteAddr(); + } + + return originAddr; + } + @Override - public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws + Exception { String requestURI = request.getRequestURI(); String requestAddr = getOriginRemoteAddr(request); String requestID = UUID.randomUUID().toString(); request.setAttribute("RequestID", requestID); - if (handler instanceof HandlerMethod) { - HandlerMethod handlerMethod = (HandlerMethod) handler; + if (handler instanceof HandlerMethod handlerMethod) { } - LOGGER.info("[API Request] RequestID: {}, RequestURI: {}, RequestHost: {} Handler: {}", requestID, requestURI, requestAddr, handler); + LOGGER.info("[API Request] RequestID: {}, RequestURI: {}, RequestHost: {} Handler: {}", + requestID, + requestURI, + requestAddr, + handler); return true; } @Override - public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { + public void afterCompletion(HttpServletRequest request, + HttpServletResponse response, + Object handler, + Exception ex) throws Exception { String requestURI = request.getRequestURI(); String requestID = request.getAttribute("RequestID").toString(); @@ -41,14 +58,4 @@ public void afterCompletion(HttpServletRequest request, HttpServletResponse resp LOGGER.error("[API Response] Error: ", ex); } } - - private static String getOriginRemoteAddr(HttpServletRequest request) { - String originAddr = request.getHeader("X-Real-IP"); - - if (originAddr == null || originAddr.isBlank()) { - originAddr = request.getRemoteAddr(); - } - - return originAddr; - } } diff --git a/src/main/java/org/codequistify/master/global/jwt/TokenProvider.java b/src/main/java/org/codequistify/master/global/jwt/TokenProvider.java index 23b6dd32..37768578 100644 --- a/src/main/java/org/codequistify/master/global/jwt/TokenProvider.java +++ b/src/main/java/org/codequistify/master/global/jwt/TokenProvider.java @@ -29,8 +29,8 @@ @Component @RequiredArgsConstructor public class TokenProvider { - private final String ISS = "api.pol.or.kr"; private final Long ACCESS_VALIDITY_TIME = 60 * 60 * 1000L; + private final String ISS = "api.pol.or.kr"; private final Long REFRESH_VALIDITY_TIME = 7 * 24 * 60 * 60 * 1000L; private final Logger logger = LoggerFactory.getLogger(TokenProvider.class); @Value("${jwt.secret}") diff --git a/src/main/java/org/codequistify/master/global/jwt/TokenType.java b/src/main/java/org/codequistify/master/global/jwt/TokenType.java index f183822c..ce204a51 100644 --- a/src/main/java/org/codequistify/master/global/jwt/TokenType.java +++ b/src/main/java/org/codequistify/master/global/jwt/TokenType.java @@ -2,5 +2,5 @@ public enum TokenType { ACCESS_TOKEN, - REFRESH_TOKEN; + REFRESH_TOKEN } diff --git a/src/main/java/org/codequistify/master/infrastructure/account/entity/EmailVerificationEntity.java b/src/main/java/org/codequistify/master/infrastructure/account/entity/EmailVerificationEntity.java index 6203c42b..28aa9a43 100644 --- a/src/main/java/org/codequistify/master/infrastructure/account/entity/EmailVerificationEntity.java +++ b/src/main/java/org/codequistify/master/infrastructure/account/entity/EmailVerificationEntity.java @@ -1,11 +1,7 @@ package org.codequistify.master.infrastructure.account.entity; import jakarta.persistence.*; -import lombok.AccessLevel; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.ToString; +import lombok.*; import org.codequistify.master.core.domain.account.model.EmailVerificationType; import org.codequistify.master.global.util.BaseTimeEntity; import org.hibernate.annotations.ColumnDefault; diff --git a/src/main/java/org/codequistify/master/infrastructure/account/mail/EmailMessageFactory.java b/src/main/java/org/codequistify/master/infrastructure/account/mail/EmailMessageFactory.java index ef4a4338..a3c283bc 100644 --- a/src/main/java/org/codequistify/master/infrastructure/account/mail/EmailMessageFactory.java +++ b/src/main/java/org/codequistify/master/infrastructure/account/mail/EmailMessageFactory.java @@ -21,8 +21,8 @@ public class EmailMessageFactory { private final JavaMailSender javaMailSender; - private final TemplateEngine templateEngine; private final Logger logger = LoggerFactory.getLogger(EmailMessageFactory.class); + private final TemplateEngine templateEngine; public MimeMessage createVerificationMessage(String email, String code, EmailVerificationType type) throws MessagingException { diff --git a/src/main/java/org/codequistify/master/infrastructure/account/mail/EmailSender.java b/src/main/java/org/codequistify/master/infrastructure/account/mail/EmailSender.java index 0b0fddc9..ae6c5b53 100644 --- a/src/main/java/org/codequistify/master/infrastructure/account/mail/EmailSender.java +++ b/src/main/java/org/codequistify/master/infrastructure/account/mail/EmailSender.java @@ -13,8 +13,8 @@ @RequiredArgsConstructor public class EmailSender { - private final JavaMailSender javaMailSender; private static final Logger logger = LoggerFactory.getLogger(EmailSender.class); + private final JavaMailSender javaMailSender; public void send(MimeMessage message) throws MessagingException { try { diff --git a/src/main/java/org/codequistify/master/infrastructure/account/repository/EmailVerificationRepository.java b/src/main/java/org/codequistify/master/infrastructure/account/repository/EmailVerificationRepository.java index 445e63dc..886b6747 100644 --- a/src/main/java/org/codequistify/master/infrastructure/account/repository/EmailVerificationRepository.java +++ b/src/main/java/org/codequistify/master/infrastructure/account/repository/EmailVerificationRepository.java @@ -22,5 +22,7 @@ Optional findFirstByEmailAndUsedAndEmailVerificationTypeOrder ORDER BY e.createdDate DESC LIMIT 1 """) - Optional findLatestUnusedVerification(String email, Boolean used, EmailVerificationType type); + Optional findLatestUnusedVerification(String email, + Boolean used, + EmailVerificationType type); } diff --git a/src/main/java/org/codequistify/master/infrastructure/player/converter/PlayerConverter.java b/src/main/java/org/codequistify/master/infrastructure/player/converter/PlayerConverter.java index 066e4680..1d865a08 100644 --- a/src/main/java/org/codequistify/master/infrastructure/player/converter/PlayerConverter.java +++ b/src/main/java/org/codequistify/master/infrastructure/player/converter/PlayerConverter.java @@ -9,7 +9,9 @@ public class PlayerConverter { public static Player toDomain(PlayerEntity entity) { - if (entity == null) return null; + if (entity == null) { + return null; + } return Player.builder() .uid(PolId.of(entity.getUid())) @@ -27,7 +29,9 @@ public static Player toDomain(PlayerEntity entity) { } public static PlayerEntity toEntity(Player domain) { - if (domain == null) return null; + if (domain == null) { + return null; + } return PlayerEntity.builder() .uid(domain.getUid().getValue()) diff --git a/src/main/java/org/codequistify/master/infrastructure/player/entity/PlayerEntity.java b/src/main/java/org/codequistify/master/infrastructure/player/entity/PlayerEntity.java index 7eaef3fc..f19fe541 100644 --- a/src/main/java/org/codequistify/master/infrastructure/player/entity/PlayerEntity.java +++ b/src/main/java/org/codequistify/master/infrastructure/player/entity/PlayerEntity.java @@ -3,8 +3,8 @@ import jakarta.persistence.*; import lombok.*; import org.codequistify.master.core.domain.player.model.OAuthType; -import org.hibernate.annotations.ColumnDefault; import org.codequistify.master.global.util.BaseTimeEntity; +import org.hibernate.annotations.ColumnDefault; import java.util.ArrayList; import java.util.List; diff --git a/src/main/java/org/codequistify/master/infrastructure/security/TokenPlayer.java b/src/main/java/org/codequistify/master/infrastructure/security/TokenPlayer.java index 197501ac..7657ae1a 100644 --- a/src/main/java/org/codequistify/master/infrastructure/security/TokenPlayer.java +++ b/src/main/java/org/codequistify/master/infrastructure/security/TokenPlayer.java @@ -9,8 +9,8 @@ @Getter @Builder public class TokenPlayer { - private final PolId uid; - private final String name; private final String email; + private final String name; private final Set roles; + private final PolId uid; }