From 85845f7600bc38f75ff28c95173bc83cb72f6016 Mon Sep 17 00:00:00 2001 From: Junhyeok Lee Date: Wed, 5 Nov 2025 22:56:29 +0900 Subject: [PATCH 1/6] =?UTF-8?q?refactor:=20=EB=B9=84=EB=B0=80=EB=B2=88?= =?UTF-8?q?=ED=98=B8=20=EC=B4=88=EA=B8=B0=ED=99=94=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 임시 토큰 검증에 대한 책임은 인증 모듈로 이동 - 인증 모듈과 회원 모듈 간 순환 의존 제거 --- .../{ => common}/config/WebConfiguration.java | 0 .../event/CompleteQuestEvent.java | 0 .../event/CreateQuestPoolEvent.java | 0 .../core/auth/SpringModulithPackageInfo.java | 22 ++++++++++ .../app/core/auth/adapter/in/api/AuthApi.java | 10 +++++ .../in/api/request/ResetPasswordRequest.java | 21 +++++++++ .../auth/adapter/out/client/MemberClient.java | 18 +++++--- .../port/in/PasswordResetProcessor.java | 17 ++++++++ .../port/in/SpringModulithPackageInfo.java | 9 ++++ .../port/out/PrincipalPasswordResetter.java | 6 +++ .../auth/application/service/AuthService.java | 15 ++++++- .../FilterRegistrationConfiguration.java | 2 +- .../auth/domain/exception/AuthErrorCode.java | 1 - .../member/SpringModulithPackageInfo.java | 24 +++++++++++ .../member/adapter/in/api/PasswordApi.java | 9 ---- .../adapter/out/client/EmailTokenClient.java | 24 ----------- .../command/SpringModulithPackageInfo.java | 9 ++++ .../port/dto/SpringModulithPackageInfo.java | 9 ++++ .../application/port/in/PasswordResetter.java | 6 +-- .../port/in/SpringModulithPackageInfo.java | 9 ++++ .../port/out/EmailTokenVerifier.java | 14 ------ .../application/service/PasswordService.java | 6 +-- .../exception/code/MemberErrorCode.java | 3 +- .../app/core/member/domain/model/Member.java | 6 +-- .../model/SpringModulithPackageInfo.java | 9 ++++ .../LogSimulator.java | 0 .../api/ResetPasswordDocumentationTest.java | 8 ++-- .../in/api/snippet/ResetPasswordSnippet.java | 0 .../out/client/TemporaryTokenClientTest.java | 43 ------------------- 29 files changed, 185 insertions(+), 115 deletions(-) rename src/main/java/com/gomo/app/{ => common}/config/WebConfiguration.java (100%) rename src/main/java/com/gomo/app/{core/quest/domain => common}/event/CompleteQuestEvent.java (100%) rename src/main/java/com/gomo/app/{core/quest/domain => common}/event/CreateQuestPoolEvent.java (100%) create mode 100644 src/main/java/com/gomo/app/core/auth/SpringModulithPackageInfo.java create mode 100644 src/main/java/com/gomo/app/core/auth/adapter/in/api/request/ResetPasswordRequest.java create mode 100644 src/main/java/com/gomo/app/core/auth/application/port/in/PasswordResetProcessor.java create mode 100644 src/main/java/com/gomo/app/core/auth/application/port/in/SpringModulithPackageInfo.java create mode 100644 src/main/java/com/gomo/app/core/auth/application/port/out/PrincipalPasswordResetter.java rename src/main/java/com/gomo/app/{ => core/auth}/config/FilterRegistrationConfiguration.java (98%) create mode 100644 src/main/java/com/gomo/app/core/member/SpringModulithPackageInfo.java delete mode 100644 src/main/java/com/gomo/app/core/member/adapter/out/client/EmailTokenClient.java create mode 100644 src/main/java/com/gomo/app/core/member/application/port/command/SpringModulithPackageInfo.java create mode 100644 src/main/java/com/gomo/app/core/member/application/port/dto/SpringModulithPackageInfo.java create mode 100644 src/main/java/com/gomo/app/core/member/application/port/in/SpringModulithPackageInfo.java delete mode 100644 src/main/java/com/gomo/app/core/member/application/port/out/EmailTokenVerifier.java create mode 100644 src/main/java/com/gomo/app/core/member/domain/model/SpringModulithPackageInfo.java rename src/main/java/com/gomo/app/support/{diagnositc => diagnostic}/LogSimulator.java (100%) rename src/test/java/com/gomo/app/core/{member => auth}/adapter/in/api/ResetPasswordDocumentationTest.java (88%) rename src/test/java/com/gomo/app/core/{member => auth}/adapter/in/api/snippet/ResetPasswordSnippet.java (100%) delete mode 100644 src/test/java/com/gomo/app/core/member/adapter/out/client/TemporaryTokenClientTest.java diff --git a/src/main/java/com/gomo/app/config/WebConfiguration.java b/src/main/java/com/gomo/app/common/config/WebConfiguration.java similarity index 100% rename from src/main/java/com/gomo/app/config/WebConfiguration.java rename to src/main/java/com/gomo/app/common/config/WebConfiguration.java diff --git a/src/main/java/com/gomo/app/core/quest/domain/event/CompleteQuestEvent.java b/src/main/java/com/gomo/app/common/event/CompleteQuestEvent.java similarity index 100% rename from src/main/java/com/gomo/app/core/quest/domain/event/CompleteQuestEvent.java rename to src/main/java/com/gomo/app/common/event/CompleteQuestEvent.java diff --git a/src/main/java/com/gomo/app/core/quest/domain/event/CreateQuestPoolEvent.java b/src/main/java/com/gomo/app/common/event/CreateQuestPoolEvent.java similarity index 100% rename from src/main/java/com/gomo/app/core/quest/domain/event/CreateQuestPoolEvent.java rename to src/main/java/com/gomo/app/common/event/CreateQuestPoolEvent.java diff --git a/src/main/java/com/gomo/app/core/auth/SpringModulithPackageInfo.java b/src/main/java/com/gomo/app/core/auth/SpringModulithPackageInfo.java new file mode 100644 index 00000000..0928c382 --- /dev/null +++ b/src/main/java/com/gomo/app/core/auth/SpringModulithPackageInfo.java @@ -0,0 +1,22 @@ +package com.gomo.app.core.auth; + +import org.springframework.modulith.ApplicationModule; +import org.springframework.modulith.PackageInfo; + +@ApplicationModule( + id = "core-auth", + displayName = "core-auth", + allowedDependencies = { + "common-arch", + "common-exception", + "common-logging", + "common-session", + "core-member::in", + "core-member::model", + "core-member::command", + "support-logging" + } +) +@PackageInfo +class SpringModulithPackageInfo { +} diff --git a/src/main/java/com/gomo/app/core/auth/adapter/in/api/AuthApi.java b/src/main/java/com/gomo/app/core/auth/adapter/in/api/AuthApi.java index 235ad35d..6b408103 100644 --- a/src/main/java/com/gomo/app/core/auth/adapter/in/api/AuthApi.java +++ b/src/main/java/com/gomo/app/core/auth/adapter/in/api/AuthApi.java @@ -12,6 +12,7 @@ import org.springframework.web.bind.annotation.CookieValue; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; @@ -20,10 +21,12 @@ import com.gomo.app.common.session.SessionInfo; import com.gomo.app.core.auth.adapter.in.api.request.CreatePrincipalRequest; import com.gomo.app.core.auth.adapter.in.api.request.LoginRequest; +import com.gomo.app.core.auth.adapter.in.api.request.ResetPasswordRequest; import com.gomo.app.core.auth.adapter.in.api.response.AccessTokenResponse; import com.gomo.app.core.auth.adapter.in.api.response.CreatePrincipalResponse; import com.gomo.app.core.auth.application.port.dto.AuthTokenDto; import com.gomo.app.core.auth.application.port.in.LoginProcessor; +import com.gomo.app.core.auth.application.port.in.PasswordResetProcessor; import com.gomo.app.core.auth.application.port.in.RefreshTokenDeleter; import com.gomo.app.core.auth.application.port.in.RefreshTokenUpdater; import com.gomo.app.core.auth.application.port.in.SignupProcessor; @@ -36,6 +39,7 @@ public class AuthApi { private final SignupProcessor signupProcessor; + private final PasswordResetProcessor passwordResetProcessor; private final LoginProcessor loginProcessor; private final RefreshTokenUpdater refreshTokenUpdater; private final RefreshTokenDeleter refreshTokenDeleter; @@ -46,6 +50,12 @@ public ResponseEntity signup(@RequestBody CreatePrincip return ResponseEntity.status(HttpStatus.CREATED).body(CreatePrincipalResponse.of(principalId)); } + @PutMapping("/passwords/reset") + public ResponseEntity reset(@RequestBody ResetPasswordRequest request) { + passwordResetProcessor.reset(request.getEmail(), request.getNewPassword(), request.getTemporaryToken()); + return ResponseEntity.noContent().build(); + } + @PostMapping("/login") public ResponseEntity login(@RequestBody LoginRequest request) { AuthTokenDto authTokenDto = loginProcessor.login(request.getEmail(), request.getPassword()); diff --git a/src/main/java/com/gomo/app/core/auth/adapter/in/api/request/ResetPasswordRequest.java b/src/main/java/com/gomo/app/core/auth/adapter/in/api/request/ResetPasswordRequest.java new file mode 100644 index 00000000..e0262e5e --- /dev/null +++ b/src/main/java/com/gomo/app/core/auth/adapter/in/api/request/ResetPasswordRequest.java @@ -0,0 +1,21 @@ +package com.gomo.app.core.auth.adapter.in.api.request; + +import lombok.Getter; + +@Getter +public class ResetPasswordRequest { + + private final String email; + private final String newPassword; + private final String temporaryToken; + + private ResetPasswordRequest(String email, String newPassword, String temporaryToken) { + this.email = email; + this.newPassword = newPassword; + this.temporaryToken = temporaryToken; + } + + public static ResetPasswordRequest of(String email, String newPassword, String temporaryToken) { + return new ResetPasswordRequest(email, newPassword, temporaryToken); + } +} diff --git a/src/main/java/com/gomo/app/core/auth/adapter/out/client/MemberClient.java b/src/main/java/com/gomo/app/core/auth/adapter/out/client/MemberClient.java index 85f614e4..8e237441 100644 --- a/src/main/java/com/gomo/app/core/auth/adapter/out/client/MemberClient.java +++ b/src/main/java/com/gomo/app/core/auth/adapter/out/client/MemberClient.java @@ -4,26 +4,29 @@ import java.util.UUID; import com.gomo.app.common.arch.Adapter; -import com.gomo.app.core.member.application.port.in.EmailChecker; -import com.gomo.app.core.member.application.port.in.MemberCreator; -import com.gomo.app.core.member.application.port.in.MemberLoginProcessor; -import com.gomo.app.core.member.application.port.in.MemberOAuthLoginProcessor; import com.gomo.app.core.auth.application.port.command.CreatePrincipalCommand; import com.gomo.app.core.auth.application.port.out.PrincipalCreator; import com.gomo.app.core.auth.application.port.out.PrincipalEmailChecker; import com.gomo.app.core.auth.application.port.out.PrincipalLoginProcessor; import com.gomo.app.core.auth.application.port.out.PrincipalOAuthLoginProcessor; +import com.gomo.app.core.auth.application.port.out.PrincipalPasswordResetter; +import com.gomo.app.core.member.application.port.in.EmailChecker; +import com.gomo.app.core.member.application.port.in.MemberCreator; +import com.gomo.app.core.member.application.port.in.MemberLoginProcessor; +import com.gomo.app.core.member.application.port.in.MemberOAuthLoginProcessor; +import com.gomo.app.core.member.application.port.in.PasswordResetter; import lombok.RequiredArgsConstructor; @RequiredArgsConstructor @Adapter -class MemberClient implements PrincipalCreator, PrincipalEmailChecker, PrincipalLoginProcessor, PrincipalOAuthLoginProcessor { +class MemberClient implements PrincipalCreator, PrincipalEmailChecker, PrincipalLoginProcessor, PrincipalOAuthLoginProcessor, PrincipalPasswordResetter { private final MemberCreator memberCreator; private final EmailChecker emailChecker; private final MemberLoginProcessor memberLoginProcessor; private final MemberOAuthLoginProcessor memberOAuthLoginProcessor; + private final PasswordResetter passwordResetter; @Override public UUID create(CreatePrincipalCommand command) { @@ -44,4 +47,9 @@ public UUID login(String email, String password) { public Optional login(String email) { return memberOAuthLoginProcessor.login(email); } + + @Override + public void reset(String email, String newPassword) { + passwordResetter.reset(email, newPassword); + } } diff --git a/src/main/java/com/gomo/app/core/auth/application/port/in/PasswordResetProcessor.java b/src/main/java/com/gomo/app/core/auth/application/port/in/PasswordResetProcessor.java new file mode 100644 index 00000000..d175b401 --- /dev/null +++ b/src/main/java/com/gomo/app/core/auth/application/port/in/PasswordResetProcessor.java @@ -0,0 +1,17 @@ +package com.gomo.app.core.auth.application.port.in; + +import com.gomo.app.core.member.domain.exception.MemberNotFoundException; + +public interface PasswordResetProcessor { + + /** + * Resets the password for a member after validating a temporary token. + * + * @param email The email address of the member for whom the password reset is being performed. + * @param newPassword The new raw password to be set. + * @param temporaryToken The verification token required to authorize the password change. + * @throws MemberNotFoundException if no member is found with the specified email address. + * @throws IllegalArgumentException if the provided temporary token is invalid. + */ + void reset(String email, String newPassword, String temporaryToken); +} diff --git a/src/main/java/com/gomo/app/core/auth/application/port/in/SpringModulithPackageInfo.java b/src/main/java/com/gomo/app/core/auth/application/port/in/SpringModulithPackageInfo.java new file mode 100644 index 00000000..c835079f --- /dev/null +++ b/src/main/java/com/gomo/app/core/auth/application/port/in/SpringModulithPackageInfo.java @@ -0,0 +1,9 @@ +package com.gomo.app.core.auth.application.port.in; + +import org.springframework.modulith.NamedInterface; +import org.springframework.modulith.PackageInfo; + +@NamedInterface("in") +@PackageInfo +class SpringModulithPackageInfo { +} diff --git a/src/main/java/com/gomo/app/core/auth/application/port/out/PrincipalPasswordResetter.java b/src/main/java/com/gomo/app/core/auth/application/port/out/PrincipalPasswordResetter.java new file mode 100644 index 00000000..8f062f2b --- /dev/null +++ b/src/main/java/com/gomo/app/core/auth/application/port/out/PrincipalPasswordResetter.java @@ -0,0 +1,6 @@ +package com.gomo.app.core.auth.application.port.out; + +public interface PrincipalPasswordResetter { + + void reset(String email, String newPassword); +} diff --git a/src/main/java/com/gomo/app/core/auth/application/service/AuthService.java b/src/main/java/com/gomo/app/core/auth/application/service/AuthService.java index 517a3371..70865882 100644 --- a/src/main/java/com/gomo/app/core/auth/application/service/AuthService.java +++ b/src/main/java/com/gomo/app/core/auth/application/service/AuthService.java @@ -9,10 +9,12 @@ import com.gomo.app.core.auth.application.port.command.CreatePrincipalCommand; import com.gomo.app.core.auth.application.port.dto.AuthTokenDto; import com.gomo.app.core.auth.application.port.in.LoginProcessor; +import com.gomo.app.core.auth.application.port.in.PasswordResetProcessor; import com.gomo.app.core.auth.application.port.in.SignupProcessor; import com.gomo.app.core.auth.application.port.out.JwtVerifier; import com.gomo.app.core.auth.application.port.out.PrincipalCreator; import com.gomo.app.core.auth.application.port.out.PrincipalLoginProcessor; +import com.gomo.app.core.auth.application.port.out.PrincipalPasswordResetter; import com.gomo.app.core.auth.domain.exception.AuthenticationFailException; import com.gomo.app.core.auth.domain.model.AuthToken; import com.gomo.app.core.member.domain.model.LoginProvider; @@ -21,12 +23,13 @@ @RequiredArgsConstructor @ApplicationService -class AuthService implements SignupProcessor, LoginProcessor { +class AuthService implements SignupProcessor, LoginProcessor, PasswordResetProcessor { private final PrincipalCreator principalCreator; private final JwtVerifier jwtVerifier; private final PrincipalLoginProcessor principalLoginProcessor; private final AuthTokenService authTokenService; + private final PrincipalPasswordResetter principalPasswordResetter; @Override @AuditLog(action = "SIGNUP") @@ -46,4 +49,14 @@ public AuthTokenDto login(String email, String password) { long expirationTime = jwtVerifier.extractExpirationTime(authToken.getRefreshToken()); return AuthTokenDto.of(principalId, authToken.getAccessToken(), authToken.getRefreshToken(), expirationTime); } + + @Override + @AuditLog(action = "TOKEN_VERIFY_AND_PASSWORD_RESET") + public void reset(String email, String newPassword, String temporaryToken) { + // TODO [2025-11-04] jhl221123 : 토큰 내부 이메일이 동일한지 확인하는 jwt 기능이 추가되어야 합니다. + if (!jwtVerifier.verify(temporaryToken)) { + throw new AuthenticationFailException(INVALID_VERIFIED_EMAIL_TOKEN); + } + principalPasswordResetter.reset(email, newPassword); + } } diff --git a/src/main/java/com/gomo/app/config/FilterRegistrationConfiguration.java b/src/main/java/com/gomo/app/core/auth/config/FilterRegistrationConfiguration.java similarity index 98% rename from src/main/java/com/gomo/app/config/FilterRegistrationConfiguration.java rename to src/main/java/com/gomo/app/core/auth/config/FilterRegistrationConfiguration.java index 96de7988..2a2b4ea7 100644 --- a/src/main/java/com/gomo/app/config/FilterRegistrationConfiguration.java +++ b/src/main/java/com/gomo/app/core/auth/config/FilterRegistrationConfiguration.java @@ -1,4 +1,4 @@ -package com.gomo.app.config; +package com.gomo.app.core.auth.config; import java.util.Arrays; diff --git a/src/main/java/com/gomo/app/core/auth/domain/exception/AuthErrorCode.java b/src/main/java/com/gomo/app/core/auth/domain/exception/AuthErrorCode.java index 65ccc08e..c6f17c8b 100644 --- a/src/main/java/com/gomo/app/core/auth/domain/exception/AuthErrorCode.java +++ b/src/main/java/com/gomo/app/core/auth/domain/exception/AuthErrorCode.java @@ -8,7 +8,6 @@ public enum AuthErrorCode { INVALID_AUTH_CODE(401, "AUT-ROO-001", "Auth code is incorrect"), MISSING_REFRESH_TOKEN(401, "AUT-ROO-002", "Refresh token not found"), INVALID_REFRESH_TOKEN(401, "AUT-ROO-003", "Refresh token is incorrect"), - UNSUPPORTED_LOGIN_METHOD(401, "AUT-ROO-004", "OAuth member cannot login with password"), PRINCIPAL_DUPLICATED(409, "AUT-ROO-005", "Principal already exists"), PRINCIPAL_NOT_FOUND(404, "AUT-ROO-006", "Principal not found"), INVALID_VERIFIED_EMAIL_TOKEN(401, "AUT-ROO-007", "Verified email token is incorrect"); diff --git a/src/main/java/com/gomo/app/core/member/SpringModulithPackageInfo.java b/src/main/java/com/gomo/app/core/member/SpringModulithPackageInfo.java new file mode 100644 index 00000000..085373aa --- /dev/null +++ b/src/main/java/com/gomo/app/core/member/SpringModulithPackageInfo.java @@ -0,0 +1,24 @@ +package com.gomo.app.core.member; + +import org.springframework.modulith.ApplicationModule; +import org.springframework.modulith.PackageInfo; + +@ApplicationModule( + id = "core-member", + displayName = "core-member", + allowedDependencies = { + "common-arch", + "common-exception", + "common-jpa", + "common-logging", + "common-session", + "common-util", + "core-point::in", + "core-streak::in", + "support-logging", + "support-image::in" + } +) +@PackageInfo +class SpringModulithPackageInfo { +} diff --git a/src/main/java/com/gomo/app/core/member/adapter/in/api/PasswordApi.java b/src/main/java/com/gomo/app/core/member/adapter/in/api/PasswordApi.java index 31603d95..92b99574 100644 --- a/src/main/java/com/gomo/app/core/member/adapter/in/api/PasswordApi.java +++ b/src/main/java/com/gomo/app/core/member/adapter/in/api/PasswordApi.java @@ -8,9 +8,7 @@ import com.gomo.app.common.arch.CoreApi; import com.gomo.app.common.session.Session; import com.gomo.app.common.session.SessionInfo; -import com.gomo.app.core.member.adapter.in.api.request.ResetPasswordRequest; import com.gomo.app.core.member.adapter.in.api.request.UpdatePasswordRequest; -import com.gomo.app.core.member.application.port.in.PasswordResetter; import com.gomo.app.core.member.application.port.in.PasswordUpdater; import lombok.RequiredArgsConstructor; @@ -21,17 +19,10 @@ public class PasswordApi { private final PasswordUpdater passwordUpdater; - private final PasswordResetter passwordResetter; @PutMapping public ResponseEntity update(@Session SessionInfo sessionInfo, @RequestBody UpdatePasswordRequest request) { passwordUpdater.update(sessionInfo.getPrincipalId(), request.getOriginPassword(), request.getNewPassword()); return ResponseEntity.noContent().build(); } - - @PutMapping("/reset") - public ResponseEntity reset(@RequestBody ResetPasswordRequest request) { - passwordResetter.reset(request.getEmail(), request.getNewPassword(), request.getTemporaryToken()); - return ResponseEntity.noContent().build(); - } } diff --git a/src/main/java/com/gomo/app/core/member/adapter/out/client/EmailTokenClient.java b/src/main/java/com/gomo/app/core/member/adapter/out/client/EmailTokenClient.java deleted file mode 100644 index 39ddf001..00000000 --- a/src/main/java/com/gomo/app/core/member/adapter/out/client/EmailTokenClient.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.gomo.app.core.member.adapter.out.client; - -import com.gomo.app.common.arch.Adapter; -import com.gomo.app.core.member.application.port.out.EmailTokenVerifier; -import com.gomo.app.core.auth.application.port.out.JwtVerifier; - -import lombok.RequiredArgsConstructor; - -@RequiredArgsConstructor -@Adapter -class EmailTokenClient implements EmailTokenVerifier { - - private final JwtVerifier jwtVerifier; - - // TODO [2025-11-02] jhl221123 : 인증 모듈의 책임입니다. - @Override - public void verify(String temporaryToken) { - // TODO [2025-10-18] jhl221123 : jwt 형식 뿐 아니라 내부 이메일이 요청한 이메일과 같은지 검증이 필요합니다. - // TODO [2025-10-19] jhl221123 : 커스텀 예외를 반환하도록 수정해야합니다. - if (!jwtVerifier.verify(temporaryToken)) { - throw new IllegalArgumentException("Invalid temporary token"); - } - } -} diff --git a/src/main/java/com/gomo/app/core/member/application/port/command/SpringModulithPackageInfo.java b/src/main/java/com/gomo/app/core/member/application/port/command/SpringModulithPackageInfo.java new file mode 100644 index 00000000..4149cfd0 --- /dev/null +++ b/src/main/java/com/gomo/app/core/member/application/port/command/SpringModulithPackageInfo.java @@ -0,0 +1,9 @@ +package com.gomo.app.core.member.application.port.command; + +import org.springframework.modulith.NamedInterface; +import org.springframework.modulith.PackageInfo; + +@NamedInterface("command") +@PackageInfo +class SpringModulithPackageInfo { +} diff --git a/src/main/java/com/gomo/app/core/member/application/port/dto/SpringModulithPackageInfo.java b/src/main/java/com/gomo/app/core/member/application/port/dto/SpringModulithPackageInfo.java new file mode 100644 index 00000000..070ca5e7 --- /dev/null +++ b/src/main/java/com/gomo/app/core/member/application/port/dto/SpringModulithPackageInfo.java @@ -0,0 +1,9 @@ +package com.gomo.app.core.member.application.port.dto; + +import org.springframework.modulith.NamedInterface; +import org.springframework.modulith.PackageInfo; + +@NamedInterface("dto") +@PackageInfo +class SpringModulithPackageInfo { +} diff --git a/src/main/java/com/gomo/app/core/member/application/port/in/PasswordResetter.java b/src/main/java/com/gomo/app/core/member/application/port/in/PasswordResetter.java index f69e19b2..4b4253a0 100644 --- a/src/main/java/com/gomo/app/core/member/application/port/in/PasswordResetter.java +++ b/src/main/java/com/gomo/app/core/member/application/port/in/PasswordResetter.java @@ -5,13 +5,11 @@ public interface PasswordResetter { /** - * Resets the password for a member after validating a temporary token. + * Resets the password for a member. * * @param email The email address of the member for whom the password reset is being performed. * @param newPassword The new raw password to be set. - * @param temporaryToken The verification token required to authorize the password change. * @throws MemberNotFoundException if no member is found with the specified email address. - * @throws IllegalArgumentException if the provided temporary token is invalid. */ - void reset(String email, String newPassword, String temporaryToken); + void reset(String email, String newPassword); } diff --git a/src/main/java/com/gomo/app/core/member/application/port/in/SpringModulithPackageInfo.java b/src/main/java/com/gomo/app/core/member/application/port/in/SpringModulithPackageInfo.java new file mode 100644 index 00000000..8d155660 --- /dev/null +++ b/src/main/java/com/gomo/app/core/member/application/port/in/SpringModulithPackageInfo.java @@ -0,0 +1,9 @@ +package com.gomo.app.core.member.application.port.in; + +import org.springframework.modulith.NamedInterface; +import org.springframework.modulith.PackageInfo; + +@NamedInterface("in") +@PackageInfo +class SpringModulithPackageInfo { +} diff --git a/src/main/java/com/gomo/app/core/member/application/port/out/EmailTokenVerifier.java b/src/main/java/com/gomo/app/core/member/application/port/out/EmailTokenVerifier.java deleted file mode 100644 index d699a6db..00000000 --- a/src/main/java/com/gomo/app/core/member/application/port/out/EmailTokenVerifier.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.gomo.app.core.member.application.port.out; - -public interface EmailTokenVerifier { - - // TODO [2025-11-02] jhl221123 : 인증 모듈의 책임입니다. - - /** - * Verifies the validity of a temporary token, typically used for processes like email verification. - * - * @param temporaryToken The temporary token string to be validated. - * @throws IllegalArgumentException if the token is invalid, expired, or malformed. - */ - void verify(String temporaryToken); -} diff --git a/src/main/java/com/gomo/app/core/member/application/service/PasswordService.java b/src/main/java/com/gomo/app/core/member/application/service/PasswordService.java index 6a1fb59e..0ee8f9b1 100644 --- a/src/main/java/com/gomo/app/core/member/application/service/PasswordService.java +++ b/src/main/java/com/gomo/app/core/member/application/service/PasswordService.java @@ -8,7 +8,6 @@ import com.gomo.app.common.logging.AuditLog; import com.gomo.app.core.member.application.port.in.PasswordResetter; import com.gomo.app.core.member.application.port.in.PasswordUpdater; -import com.gomo.app.core.member.application.port.out.EmailTokenVerifier; import com.gomo.app.core.member.application.port.out.PasswordEncodeManager; import com.gomo.app.core.member.domain.exception.MemberAuthenticationFailedException; import com.gomo.app.core.member.domain.model.LoginProvider; @@ -23,15 +22,12 @@ @ApplicationService class PasswordService implements PasswordResetter, PasswordUpdater { - private final EmailTokenVerifier emailTokenVerifier; private final PasswordEncodeManager passwordEncodeManager; private final MemberService memberService; @Override @AuditLog(action = "PASSWORD_RESET") - public void reset(String email, String newPassword, String temporaryToken) { - emailTokenVerifier.verify(temporaryToken); - + public void reset(String email, String newPassword) { Member member = memberService.findByEmail(email); String encoded = passwordEncodeManager.encode(Password.ofRaw(newPassword).getPassword()); member.updatePassword(Password.ofEncoded(encoded)); diff --git a/src/main/java/com/gomo/app/core/member/domain/exception/code/MemberErrorCode.java b/src/main/java/com/gomo/app/core/member/domain/exception/code/MemberErrorCode.java index eedd4a67..ed3c6209 100644 --- a/src/main/java/com/gomo/app/core/member/domain/exception/code/MemberErrorCode.java +++ b/src/main/java/com/gomo/app/core/member/domain/exception/code/MemberErrorCode.java @@ -7,7 +7,8 @@ public enum MemberErrorCode { NOT_FOUND(404, "MEM-ROO-001", "Member not found"), ACCESS_DENIED(403, "MEM-ROO-002", "Access denied for the member"), - AUTHENTICATION_FAILED(401, "MEM-ROO-003", "Member Authentication fail"); + AUTHENTICATION_FAILED(401, "MEM-ROO-003", "Member Authentication fail"), + UNSUPPORTED_LOGIN(401, "MEM-ROO-004", "OAuth member cannot login with password"); private final int httpStatus; private final String errorCode; diff --git a/src/main/java/com/gomo/app/core/member/domain/model/Member.java b/src/main/java/com/gomo/app/core/member/domain/model/Member.java index 8cd6453e..e977b4f9 100644 --- a/src/main/java/com/gomo/app/core/member/domain/model/Member.java +++ b/src/main/java/com/gomo/app/core/member/domain/model/Member.java @@ -5,9 +5,9 @@ import com.gomo.app.common.jpa.LogicalDeleteBaseAudit; import com.gomo.app.core.member.domain.exception.ActivateStatusException; +import com.gomo.app.core.member.domain.exception.MemberAuthenticationFailedException; import com.gomo.app.core.member.domain.exception.code.ActivateStatusErrorCode; -import com.gomo.app.core.auth.domain.exception.AuthErrorCode; -import com.gomo.app.core.auth.domain.exception.AuthenticationFailException; +import com.gomo.app.core.member.domain.exception.code.MemberErrorCode; import jakarta.persistence.AttributeOverride; import jakarta.persistence.AttributeOverrides; @@ -193,7 +193,7 @@ public void validateActive() { public void validateLoginProviderIsEmail() { if (this.loginProvider != LoginProvider.EMAIL) { - throw new AuthenticationFailException(AuthErrorCode.UNSUPPORTED_LOGIN_METHOD); + throw new MemberAuthenticationFailedException(MemberErrorCode.UNSUPPORTED_LOGIN); } } diff --git a/src/main/java/com/gomo/app/core/member/domain/model/SpringModulithPackageInfo.java b/src/main/java/com/gomo/app/core/member/domain/model/SpringModulithPackageInfo.java new file mode 100644 index 00000000..63fce320 --- /dev/null +++ b/src/main/java/com/gomo/app/core/member/domain/model/SpringModulithPackageInfo.java @@ -0,0 +1,9 @@ +package com.gomo.app.core.member.domain.model; + +import org.springframework.modulith.NamedInterface; +import org.springframework.modulith.PackageInfo; + +@NamedInterface("model") +@PackageInfo +class SpringModulithPackageInfo { +} diff --git a/src/main/java/com/gomo/app/support/diagnositc/LogSimulator.java b/src/main/java/com/gomo/app/support/diagnostic/LogSimulator.java similarity index 100% rename from src/main/java/com/gomo/app/support/diagnositc/LogSimulator.java rename to src/main/java/com/gomo/app/support/diagnostic/LogSimulator.java diff --git a/src/test/java/com/gomo/app/core/member/adapter/in/api/ResetPasswordDocumentationTest.java b/src/test/java/com/gomo/app/core/auth/adapter/in/api/ResetPasswordDocumentationTest.java similarity index 88% rename from src/test/java/com/gomo/app/core/member/adapter/in/api/ResetPasswordDocumentationTest.java rename to src/test/java/com/gomo/app/core/auth/adapter/in/api/ResetPasswordDocumentationTest.java index 5094d2c7..f0374eae 100644 --- a/src/test/java/com/gomo/app/core/member/adapter/in/api/ResetPasswordDocumentationTest.java +++ b/src/test/java/com/gomo/app/core/auth/adapter/in/api/ResetPasswordDocumentationTest.java @@ -11,7 +11,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.restdocs.restassured.RestDocumentationFilter; -import com.gomo.app.core.member.adapter.in.api.request.ResetPasswordRequest; +import com.gomo.app.core.auth.adapter.in.api.request.ResetPasswordRequest; import com.gomo.app.core.member.adapter.in.api.snippet.ResetPasswordSnippet; import com.gomo.app.core.member.domain.repository.MemberRepository; import com.gomo.app.test.DocumentationTestBase; @@ -19,7 +19,7 @@ @DisplayName("[Presentation Documentation]: 비밀번호 초기화 테스트") public class ResetPasswordDocumentationTest extends DocumentationTestBase { - private static final String RESET_PASSWORD_URL = "/members/passwords/reset"; + private static final String URL = "/auth/passwords/reset"; private final RestDocumentationFilter filter = ResetPasswordSnippet.create(); private final RestDocumentationFilter errorFilter = ResetPasswordSnippet.createError(); @@ -34,14 +34,14 @@ void tearDown() { @DisplayName("비밀번호를 초기화 한다.") @Test - void update_password() { + void reset_password() { String email = "testmember@naver.com"; String temporaryToken = jwtCreator.createTemporaryToken(email, 300); given(this.specification).filter(filter) .header(CONTENT_TYPE, APPLICATION_JSON_VALUE) .body(ResetPasswordRequest.of(email, "Test1234!", temporaryToken)) .when() - .put(RESET_PASSWORD_URL) + .put(URL) .then() .statusCode(NO_CONTENT.value()); } diff --git a/src/test/java/com/gomo/app/core/member/adapter/in/api/snippet/ResetPasswordSnippet.java b/src/test/java/com/gomo/app/core/auth/adapter/in/api/snippet/ResetPasswordSnippet.java similarity index 100% rename from src/test/java/com/gomo/app/core/member/adapter/in/api/snippet/ResetPasswordSnippet.java rename to src/test/java/com/gomo/app/core/auth/adapter/in/api/snippet/ResetPasswordSnippet.java diff --git a/src/test/java/com/gomo/app/core/member/adapter/out/client/TemporaryTokenClientTest.java b/src/test/java/com/gomo/app/core/member/adapter/out/client/TemporaryTokenClientTest.java deleted file mode 100644 index 1922ee2b..00000000 --- a/src/test/java/com/gomo/app/core/member/adapter/out/client/TemporaryTokenClientTest.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.gomo.app.core.member.adapter.out.client; - -import static org.assertj.core.api.Assertions.*; -import static org.mockito.ArgumentMatchers.*; -import static org.mockito.Mockito.*; - -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -import com.gomo.app.core.auth.application.port.out.JwtVerifier; - -@DisplayName("[Adapter Unit]: 임시토큰 요청 테스트") -@ExtendWith(MockitoExtension.class) -class TemporaryTokenClientTest { - - @InjectMocks - private EmailTokenClient sut; - - @Mock - private JwtVerifier jwtVerifier; - - @DisplayName("임시토큰을 검증한다.") - @Test - void verify_temporary_token() { - doReturn(true).when(jwtVerifier).verify(any()); - - assertThatCode(() -> sut.verify("temporaryToken")).doesNotThrowAnyException(); - verify(jwtVerifier, times(1)).verify(any()); - } - - @DisplayName("유효하지 않은 임시토큰으로 검증한다.") - @Test - void verify_invalid_temporary_token() { - doReturn(false).when(jwtVerifier).verify(any()); - - assertThatThrownBy(() -> sut.verify("temporaryToken")).isExactlyInstanceOf(IllegalArgumentException.class); - verify(jwtVerifier, times(1)).verify(any()); - } -} From 64e9bc0ca214e50286c17d095fa68efd6ffe958d Mon Sep 17 00:00:00 2001 From: Junhyeok Lee Date: Wed, 5 Nov 2025 22:57:46 +0900 Subject: [PATCH 2/6] =?UTF-8?q?feat:=20=EC=8A=A4=ED=94=84=EB=A7=81=20?= =?UTF-8?q?=EB=AA=A8=EB=93=88=EB=A6=AC=EC=8A=A4=20=EB=8F=84=EC=9E=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 모듈간 순환 의존성 검증 자동화 - 모듈간 의존 방향 문서화 --- build.gradle | 17 ++- src/docs/asciidoc/apis/auth-api.adoc | 20 +++ src/docs/asciidoc/apis/member-api.adoc | 24 --- src/docs/asciidoc/index.adoc | 2 +- src/docs/asciidoc/modulith-index.adoc | 67 +++++++++ .../app/batch/MemberCleanupScheduler.java | 138 ++++++++---------- .../arch/SpringModulithPackageInfo.java | 12 ++ .../config/SpringModulithPackageInfo.java | 12 ++ .../app/common/config/WebConfiguration.java | 2 +- .../SpringModulithPackageInfo.java | 12 ++ .../app/common/event/CompleteQuestEvent.java | 4 +- .../common/event/CreateQuestPoolEvent.java | 4 +- .../event/SpringModulithPackageInfo.java | 12 ++ .../exception/SpringModulithPackageInfo.java | 12 ++ .../common/jpa/SpringModulithPackageInfo.java | 12 ++ .../logging/SpringModulithPackageInfo.java | 12 ++ .../session/SpringModulithPackageInfo.java | 12 ++ .../util/SpringModulithPackageInfo.java | 12 ++ .../common/web/SpringModulithPackageInfo.java | 12 ++ .../interest/SpringModulithPackageInfo.java | 26 ++++ .../CompleteQuestEventScoreConsumer.java | 2 +- .../port/dto/SpringModulithPackageInfo.java | 9 ++ .../port/in/SpringModulithPackageInfo.java | 9 ++ .../core/point/SpringModulithPackageInfo.java | 24 +++ .../CompleteQuestEventPointConsumer.java | 2 +- .../port/in/SpringModulithPackageInfo.java | 9 ++ .../core/quest/SpringModulithPackageInfo.java | 30 ++++ .../consumer/FillQuestPoolEventConsumer.java | 2 +- .../service/AssignQuestCompleteService.java | 2 +- .../service/QuestPoolEventService.java | 2 +- .../streak/SpringModulithPackageInfo.java | 24 +++ .../CompleteQuestEventStreakConsumer.java | 2 +- .../port/in/SpringModulithPackageInfo.java | 9 ++ .../survey/SpringModulithPackageInfo.java | 12 ++ .../app/support/diagnostic/LogSimulator.java | 2 +- .../diagnostic/SpringModulithPackageInfo.java | 12 ++ .../evententry/SpringModulithPackageInfo.java | 18 +++ .../port/SpringModulithPackageInfo.java | 9 ++ .../model/SpringModulithPackageInfo.java | 9 ++ .../image/SpringModulithPackageInfo.java | 16 ++ .../port/in/SpringModulithPackageInfo.java | 9 ++ .../llm/SpringModulithPackageInfo.java | 12 ++ .../SpringModulithPackageInfo.java | 9 ++ .../logging/SpringModulithPackageInfo.java | 13 ++ .../SpringModulithPackageInfo.java | 12 ++ .../port/in/SpringModulithPackageInfo.java | 9 ++ .../model/SpringModulithPackageInfo.java | 9 ++ .../api/ResetPasswordDocumentationTest.java | 4 +- .../in/api/snippet/ResetPasswordSnippet.java | 4 +- .../application/service/AuthServiceTest.java | 24 +++ .../CompleteQuestEventScoreConsumerTest.java | 2 +- .../in/api/DeleteMemberDocumentationTest.java | 6 + .../service/PasswordServiceTest.java | 7 +- .../CompleteQuestEventPointConsumerTest.java | 2 +- .../CompleteQuestEventStreakConsumerTest.java | 2 +- ...nnotationBasedModuleDetectionStrategy.java | 15 ++ .../gomo/app/modulith/ModularityTests.java | 31 ++++ src/test/resources/META-INF/spring.factories | 2 + 58 files changed, 666 insertions(+), 134 deletions(-) create mode 100644 src/docs/asciidoc/modulith-index.adoc create mode 100644 src/main/java/com/gomo/app/common/arch/SpringModulithPackageInfo.java create mode 100644 src/main/java/com/gomo/app/common/config/SpringModulithPackageInfo.java create mode 100644 src/main/java/com/gomo/app/common/displayorder/SpringModulithPackageInfo.java create mode 100644 src/main/java/com/gomo/app/common/event/SpringModulithPackageInfo.java create mode 100644 src/main/java/com/gomo/app/common/exception/SpringModulithPackageInfo.java create mode 100644 src/main/java/com/gomo/app/common/jpa/SpringModulithPackageInfo.java create mode 100644 src/main/java/com/gomo/app/common/logging/SpringModulithPackageInfo.java create mode 100644 src/main/java/com/gomo/app/common/session/SpringModulithPackageInfo.java create mode 100644 src/main/java/com/gomo/app/common/util/SpringModulithPackageInfo.java create mode 100644 src/main/java/com/gomo/app/common/web/SpringModulithPackageInfo.java create mode 100644 src/main/java/com/gomo/app/core/interest/SpringModulithPackageInfo.java create mode 100644 src/main/java/com/gomo/app/core/interest/application/port/dto/SpringModulithPackageInfo.java create mode 100644 src/main/java/com/gomo/app/core/interest/application/port/in/SpringModulithPackageInfo.java create mode 100644 src/main/java/com/gomo/app/core/point/SpringModulithPackageInfo.java create mode 100644 src/main/java/com/gomo/app/core/point/application/port/in/SpringModulithPackageInfo.java create mode 100644 src/main/java/com/gomo/app/core/quest/SpringModulithPackageInfo.java create mode 100644 src/main/java/com/gomo/app/core/streak/SpringModulithPackageInfo.java create mode 100644 src/main/java/com/gomo/app/core/streak/application/port/in/SpringModulithPackageInfo.java create mode 100644 src/main/java/com/gomo/app/core/survey/SpringModulithPackageInfo.java create mode 100644 src/main/java/com/gomo/app/support/diagnostic/SpringModulithPackageInfo.java create mode 100644 src/main/java/com/gomo/app/support/evententry/SpringModulithPackageInfo.java create mode 100644 src/main/java/com/gomo/app/support/evententry/application/port/SpringModulithPackageInfo.java create mode 100644 src/main/java/com/gomo/app/support/evententry/domain/model/SpringModulithPackageInfo.java create mode 100644 src/main/java/com/gomo/app/support/image/SpringModulithPackageInfo.java create mode 100644 src/main/java/com/gomo/app/support/image/application/port/in/SpringModulithPackageInfo.java create mode 100644 src/main/java/com/gomo/app/support/llm/SpringModulithPackageInfo.java create mode 100644 src/main/java/com/gomo/app/support/llm/application/SpringModulithPackageInfo.java create mode 100644 src/main/java/com/gomo/app/support/logging/SpringModulithPackageInfo.java create mode 100644 src/main/java/com/gomo/app/support/messagebroker/SpringModulithPackageInfo.java create mode 100644 src/main/java/com/gomo/app/support/messagebroker/application/port/in/SpringModulithPackageInfo.java create mode 100644 src/main/java/com/gomo/app/support/messagebroker/domain/model/SpringModulithPackageInfo.java create mode 100644 src/test/java/com/gomo/app/modulith/AnnotationBasedModuleDetectionStrategy.java create mode 100644 src/test/java/com/gomo/app/modulith/ModularityTests.java create mode 100644 src/test/resources/META-INF/spring.factories diff --git a/build.gradle b/build.gradle index c7854e63..307e2020 100644 --- a/build.gradle +++ b/build.gradle @@ -35,6 +35,11 @@ repositories { mavenCentral() } +ext { + set('springModulithVersion', "1.4.4") + snippetsDir = file('build/generated-snippets') +} + dependencies { // web implementation 'org.springframework.boot:spring-boot-starter-web' @@ -91,10 +96,14 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-actuator' runtimeOnly 'io.micrometer:micrometer-registry-prometheus' - // batch + // spring batch implementation("org.springframework.boot:spring-boot-starter-batch") implementation("org.springframework.boot:spring-boot-starter-quartz") + // spring modulith + implementation 'org.springframework.modulith:spring-modulith-starter-jpa' + testImplementation 'org.springframework.modulith:spring-modulith-starter-test' + // test testRuntimeOnly "org.junit.platform:junit-platform-launcher" testImplementation "org.springframework.boot:spring-boot-starter-test" @@ -110,8 +119,10 @@ dependencies { testImplementation "org.testcontainers:minio" } -ext { - snippetsDir = file('build/generated-snippets') +dependencyManagement { + imports { + mavenBom "org.springframework.modulith:spring-modulith-bom:${springModulithVersion}" + } } tasks.named('test') { diff --git a/src/docs/asciidoc/apis/auth-api.adoc b/src/docs/asciidoc/apis/auth-api.adoc index ba4fe7aa..8a4ac6af 100644 --- a/src/docs/asciidoc/apis/auth-api.adoc +++ b/src/docs/asciidoc/apis/auth-api.adoc @@ -18,6 +18,26 @@ operation::auth-signup[snippets='http-response,response-fields'] ''' +=== 비밀번호 초기화 (찾기) + +`PUT /auth/passwords/reset` + +이메일 인증 등을 통해 본인인증이 완료된 사용자가 비밀번호를 새로 설정합니다. + +==== 요청 헤더 + +operation::auth-password-reset[snippets='request-headers'] + +==== 요청 본문 (JSON) + +operation::auth-password-reset[snippets='http-request,request-fields'] + +==== 성공 응답 + +성공 시 `204 No Content` 상태 코드와 함께 빈 응답 본문을 반환합니다. + +''' + === 로그인 `POST /auth/login` diff --git a/src/docs/asciidoc/apis/member-api.adoc b/src/docs/asciidoc/apis/member-api.adoc index 0fb6cb74..41e4aea5 100644 --- a/src/docs/asciidoc/apis/member-api.adoc +++ b/src/docs/asciidoc/apis/member-api.adoc @@ -153,30 +153,6 @@ operation::member-quest-property-read-error[snippets='http-response,response-fie ''' -=== 비밀번호 초기화 (찾기) - -`PUT /members/passwords/reset` - -이메일 인증 등을 통해 본인인증이 완료된 사용자가 비밀번호를 새로 설정합니다. - -==== 요청 헤더 - -operation::member-password-reset[snippets='request-headers'] - -==== 요청 본문 (JSON) - -operation::member-password-reset[snippets='http-request,request-fields'] - -==== 성공 응답 - -성공 시 `204 No Content` 상태 코드와 함께 빈 응답 본문을 반환합니다. - -==== 에러 응답 - -operation::member-password-reset-error[snippets='http-response,response-fields'] - -''' - === 핸들 수정 `PUT /members/handles` diff --git a/src/docs/asciidoc/index.adoc b/src/docs/asciidoc/index.adoc index 0c6e1d1f..d78aa64b 100644 --- a/src/docs/asciidoc/index.adoc +++ b/src/docs/asciidoc/index.adoc @@ -15,7 +15,6 @@ include::apis/auth-api.adoc[] `AUT-ROO-001`: Auth code is incorrect + `AUT-ROO-002`: Refresh token not found + `AUT-ROO-003`: Refresh token is incorrect + -`AUT-ROO-004`: OAuth member cannot login with password + `AUT-ROO-005`: Principal already exists + `AUT-ROO-006`: Principal not found + `AUT-ROO-007`: Verified email token is incorrect + @@ -30,6 +29,7 @@ include::apis/member-api.adoc[] `MEM-ROO-001`: Member not found + `MEM-ROO-002`: Access denied for the member + `MEM-ROO-003`: Member Authentication fail + +`MEM-ROO-004`: OAuth member cannot login with password + `MEM-EMA-001`: Email must not be blank + `MEM-EMA-002`: Email must be at least 10 characters + diff --git a/src/docs/asciidoc/modulith-index.adoc b/src/docs/asciidoc/modulith-index.adoc new file mode 100644 index 00000000..2e7d4aad --- /dev/null +++ b/src/docs/asciidoc/modulith-index.adoc @@ -0,0 +1,67 @@ += Spring Modulith Example Documentation +:modulith-docs: ../../../build/spring-modulith-docs + +== core-auth + +plantuml::{modulith-docs}/module-core-auth.puml[format="svg"] +include::{modulith-docs}/module-core-auth.adoc[] + +== core-member + +plantuml::{modulith-docs}/module-core-member.puml[format="svg"] +include::{modulith-docs}/module-core-member.adoc[] + +== core-interest + +plantuml::{modulith-docs}/module-core-interest.puml[format="svg"] +include::{modulith-docs}/module-core-interest.adoc[] + +== core-quest + +plantuml::{modulith-docs}/module-core-quest.puml[format="svg"] +include::{modulith-docs}/module-core-quest.adoc[] + +== core-streak + +plantuml::{modulith-docs}/module-core-streak.puml[format="svg"] +include::{modulith-docs}/module-core-streak.adoc[] + +== core-point + +plantuml::{modulith-docs}/module-core-point.puml[format="svg"] +include::{modulith-docs}/module-core-point.adoc[] + +== core-survey + +plantuml::{modulith-docs}/module-core-survey.puml[format="svg"] +include::{modulith-docs}/module-core-survey.adoc[] + +== support-image + +plantuml::{modulith-docs}/module-support-image.puml[format="svg"] +include::{modulith-docs}/module-support-image.adoc[] + +== support-messagebroker + +plantuml::{modulith-docs}/module-support-messagebroker.puml[format="svg"] +include::{modulith-docs}/module-support-messagebroker.adoc[] + +== support-logging + +plantuml::{modulith-docs}/module-support-logging.puml[format="svg"] +include::{modulith-docs}/module-support-logging.adoc[] + +== support-evententry + +plantuml::{modulith-docs}/module-support-evententry.puml[format="svg"] +include::{modulith-docs}/module-support-evententry.adoc[] + +== support-llm + +plantuml::{modulith-docs}/module-support-llm.puml[format="svg"] +include::{modulith-docs}/module-support-llm.adoc[] + +== support-diagnostic + +plantuml::{modulith-docs}/module-support-diagnostic.puml[format="svg"] +include::{modulith-docs}/module-support-diagnostic.adoc[] diff --git a/src/main/java/com/gomo/app/batch/MemberCleanupScheduler.java b/src/main/java/com/gomo/app/batch/MemberCleanupScheduler.java index df267ac4..45e6c32a 100644 --- a/src/main/java/com/gomo/app/batch/MemberCleanupScheduler.java +++ b/src/main/java/com/gomo/app/batch/MemberCleanupScheduler.java @@ -1,90 +1,70 @@ package com.gomo.app.batch; -import java.time.LocalDateTime; -import java.util.List; -import java.util.concurrent.CompletableFuture; - -import org.springframework.beans.factory.annotation.Value; -import org.springframework.scheduling.annotation.Async; -import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; -import com.gomo.app.core.interest.domain.repository.InterestRelationRepository; -import com.gomo.app.core.interest.domain.repository.InterestRepository; -import com.gomo.app.core.interest.domain.repository.MajorInterestRepository; -import com.gomo.app.core.member.domain.model.Member; -import com.gomo.app.core.member.domain.repository.MemberRepository; -import com.gomo.app.core.point.domain.repository.PointRepository; -import com.gomo.app.core.point.domain.repository.PointWalletRepository; -import com.gomo.app.core.quest.domain.repository.AssignQuestRepository; -import com.gomo.app.core.quest.domain.repository.RepeatQuestRepository; -import com.gomo.app.core.streak.domain.repository.AchieverRepository; -import com.gomo.app.core.streak.domain.repository.StreakRepository; -import com.gomo.app.support.image.application.port.in.ImageDeleter; - import lombok.RequiredArgsConstructor; @Component @RequiredArgsConstructor public class MemberCleanupScheduler { - private final ImageDeleter imageDeleter; - private final PointRepository pointRepository; - private final PointWalletRepository pointWalletRepository; - private final AssignQuestRepository assignQuestRepository; - private final RepeatQuestRepository repeatQuestRepository; - private final InterestRelationRepository interestRelationRepository; - private final MajorInterestRepository majorInterestRepository; - private final InterestRepository interestRepository; - private final StreakRepository streakRepository; - private final AchieverRepository achieverRepository; - private final MemberRepository memberRepository; - - @Value("${app.members.retentionDays}") - private long retentionDays; - - @Scheduled(cron = "0 0 2 * * *") - public void memberDataCleanUp() { - List deletedMembers = memberRepository.findByDeletedAtBefore(LocalDateTime.now().minusDays(retentionDays)); - - for (Member member : deletedMembers) { - cleanupMemberDataAsync(member); - } - } - - @Async("memberCleanupExecutor") - public CompletableFuture cleanupMemberDataAsync(Member member) { - try { - deleteMemberAndRelatedData(member); - return CompletableFuture.completedFuture(null); - } catch (Exception e) { - return CompletableFuture.failedFuture(e); - } - } - - private void deleteMemberAndRelatedData(Member member) { - // Quest 관련 데이터 삭제 - assignQuestRepository.deleteAllByParticipantId(member.getId()); - repeatQuestRepository.deleteAllByParticipantId(member.getId()); - - // Interest 관련 데이터 삭제 - interestRelationRepository.deleteAllByRegistrantId(member.getId()); - majorInterestRepository.deleteAllByRegistrantId(member.getId()); - interestRepository.deleteAllByRegistrantId(member.getId()); - - // Point 관련 데이터 삭제 - pointRepository.deleteAllByTransactorId(member.getId()); - pointWalletRepository.deletePointWalletByTransactorId(member.getId()); - - // Streak 관련 데이터 삭제 - streakRepository.deleteAllByAchieverId(member.getId()); - achieverRepository.deleteByAchieverId(member.getId()); - - // 이미지 파일 삭제 - imageDeleter.delete(member.profileImageUrl()); - imageDeleter.delete(member.profileBannerUrl()); - - // member 최종 삭제 - memberRepository.deleteById(member.getId()); - } + // private final ImageDeleter imageDeleter; + // private final PointRepository pointRepository; + // private final PointWalletRepository pointWalletRepository; + // private final AssignQuestRepository assignQuestRepository; + // private final RepeatQuestRepository repeatQuestRepository; + // private final InterestRelationRepository interestRelationRepository; + // private final MajorInterestRepository majorInterestRepository; + // private final InterestRepository interestRepository; + // private final StreakRepository streakRepository; + // private final AchieverRepository achieverRepository; + // private final MemberRepository memberRepository; + // + // @Value("${app.members.retentionDays}") + // private long retentionDays; + // + // @Scheduled(cron = "0 0 2 * * *") + // public void memberDataCleanUp() { + // List deletedMembers = memberRepository.findByDeletedAtBefore(LocalDateTime.now().minusDays(retentionDays)); + // + // for (Member member : deletedMembers) { + // cleanupMemberDataAsync(member); + // } + // } + // + // @Async("memberCleanupExecutor") + // public CompletableFuture cleanupMemberDataAsync(Member member) { + // try { + // deleteMemberAndRelatedData(member); + // return CompletableFuture.completedFuture(null); + // } catch (Exception e) { + // return CompletableFuture.failedFuture(e); + // } + // } + // + // private void deleteMemberAndRelatedData(Member member) { + // // Quest 관련 데이터 삭제 + // assignQuestRepository.deleteAllByParticipantId(member.getId()); + // repeatQuestRepository.deleteAllByParticipantId(member.getId()); + // + // // Interest 관련 데이터 삭제 + // interestRelationRepository.deleteAllByRegistrantId(member.getId()); + // majorInterestRepository.deleteAllByRegistrantId(member.getId()); + // interestRepository.deleteAllByRegistrantId(member.getId()); + // + // // Point 관련 데이터 삭제 + // pointRepository.deleteAllByTransactorId(member.getId()); + // pointWalletRepository.deletePointWalletByTransactorId(member.getId()); + // + // // Streak 관련 데이터 삭제 + // streakRepository.deleteAllByAchieverId(member.getId()); + // achieverRepository.deleteByAchieverId(member.getId()); + // + // // 이미지 파일 삭제 + // imageDeleter.delete(member.profileImageUrl()); + // imageDeleter.delete(member.profileBannerUrl()); + // + // // member 최종 삭제 + // memberRepository.deleteById(member.getId()); + // } } diff --git a/src/main/java/com/gomo/app/common/arch/SpringModulithPackageInfo.java b/src/main/java/com/gomo/app/common/arch/SpringModulithPackageInfo.java new file mode 100644 index 00000000..81f0ddbf --- /dev/null +++ b/src/main/java/com/gomo/app/common/arch/SpringModulithPackageInfo.java @@ -0,0 +1,12 @@ +package com.gomo.app.common.arch; + +import org.springframework.modulith.ApplicationModule; +import org.springframework.modulith.PackageInfo; + +@ApplicationModule( + id = "common-arch", + displayName = "common-arch" +) +@PackageInfo +class SpringModulithPackageInfo { +} diff --git a/src/main/java/com/gomo/app/common/config/SpringModulithPackageInfo.java b/src/main/java/com/gomo/app/common/config/SpringModulithPackageInfo.java new file mode 100644 index 00000000..c727a026 --- /dev/null +++ b/src/main/java/com/gomo/app/common/config/SpringModulithPackageInfo.java @@ -0,0 +1,12 @@ +package com.gomo.app.common.config; + +import org.springframework.modulith.ApplicationModule; +import org.springframework.modulith.PackageInfo; + +@ApplicationModule( + id = "common-config", + displayName = "common-config" +) +@PackageInfo +class SpringModulithPackageInfo { +} diff --git a/src/main/java/com/gomo/app/common/config/WebConfiguration.java b/src/main/java/com/gomo/app/common/config/WebConfiguration.java index 41d36129..0aabf3d7 100644 --- a/src/main/java/com/gomo/app/common/config/WebConfiguration.java +++ b/src/main/java/com/gomo/app/common/config/WebConfiguration.java @@ -1,4 +1,4 @@ -package com.gomo.app.config; +package com.gomo.app.common.config; import java.util.List; diff --git a/src/main/java/com/gomo/app/common/displayorder/SpringModulithPackageInfo.java b/src/main/java/com/gomo/app/common/displayorder/SpringModulithPackageInfo.java new file mode 100644 index 00000000..dde4a767 --- /dev/null +++ b/src/main/java/com/gomo/app/common/displayorder/SpringModulithPackageInfo.java @@ -0,0 +1,12 @@ +package com.gomo.app.common.displayorder; + +import org.springframework.modulith.ApplicationModule; +import org.springframework.modulith.PackageInfo; + +@ApplicationModule( + id = "common-displayorder", + displayName = "common-displayorder" +) +@PackageInfo +class SpringModulithPackageInfo { +} diff --git a/src/main/java/com/gomo/app/common/event/CompleteQuestEvent.java b/src/main/java/com/gomo/app/common/event/CompleteQuestEvent.java index f664e21d..d9759722 100644 --- a/src/main/java/com/gomo/app/common/event/CompleteQuestEvent.java +++ b/src/main/java/com/gomo/app/common/event/CompleteQuestEvent.java @@ -1,10 +1,8 @@ -package com.gomo.app.core.quest.domain.event; +package com.gomo.app.common.event; import java.time.LocalDateTime; import java.util.UUID; -import com.gomo.app.common.event.Event; -import com.gomo.app.common.event.EventRouting; import com.gomo.app.core.quest.domain.model.quest.QuestType; import lombok.AccessLevel; diff --git a/src/main/java/com/gomo/app/common/event/CreateQuestPoolEvent.java b/src/main/java/com/gomo/app/common/event/CreateQuestPoolEvent.java index 9aedd81d..667a2184 100644 --- a/src/main/java/com/gomo/app/common/event/CreateQuestPoolEvent.java +++ b/src/main/java/com/gomo/app/common/event/CreateQuestPoolEvent.java @@ -1,10 +1,8 @@ -package com.gomo.app.core.quest.domain.event; +package com.gomo.app.common.event; import java.util.List; import java.util.UUID; -import com.gomo.app.common.event.Event; -import com.gomo.app.common.event.EventRouting; import com.gomo.app.core.quest.domain.model.quest.QuestType; import lombok.AccessLevel; diff --git a/src/main/java/com/gomo/app/common/event/SpringModulithPackageInfo.java b/src/main/java/com/gomo/app/common/event/SpringModulithPackageInfo.java new file mode 100644 index 00000000..43178487 --- /dev/null +++ b/src/main/java/com/gomo/app/common/event/SpringModulithPackageInfo.java @@ -0,0 +1,12 @@ +package com.gomo.app.common.event; + +import org.springframework.modulith.ApplicationModule; +import org.springframework.modulith.PackageInfo; + +@ApplicationModule( + id = "common-event", + displayName = "common-event" +) +@PackageInfo +class SpringModulithPackageInfo { +} diff --git a/src/main/java/com/gomo/app/common/exception/SpringModulithPackageInfo.java b/src/main/java/com/gomo/app/common/exception/SpringModulithPackageInfo.java new file mode 100644 index 00000000..e07b99d2 --- /dev/null +++ b/src/main/java/com/gomo/app/common/exception/SpringModulithPackageInfo.java @@ -0,0 +1,12 @@ +package com.gomo.app.common.exception; + +import org.springframework.modulith.ApplicationModule; +import org.springframework.modulith.PackageInfo; + +@ApplicationModule( + id = "common-exception", + displayName = "common-exception" +) +@PackageInfo +class SpringModulithPackageInfo { +} diff --git a/src/main/java/com/gomo/app/common/jpa/SpringModulithPackageInfo.java b/src/main/java/com/gomo/app/common/jpa/SpringModulithPackageInfo.java new file mode 100644 index 00000000..559106ce --- /dev/null +++ b/src/main/java/com/gomo/app/common/jpa/SpringModulithPackageInfo.java @@ -0,0 +1,12 @@ +package com.gomo.app.common.jpa; + +import org.springframework.modulith.ApplicationModule; +import org.springframework.modulith.PackageInfo; + +@ApplicationModule( + id = "common-jpa", + displayName = "common-jpa" +) +@PackageInfo +class SpringModulithPackageInfo { +} diff --git a/src/main/java/com/gomo/app/common/logging/SpringModulithPackageInfo.java b/src/main/java/com/gomo/app/common/logging/SpringModulithPackageInfo.java new file mode 100644 index 00000000..c3b2bfea --- /dev/null +++ b/src/main/java/com/gomo/app/common/logging/SpringModulithPackageInfo.java @@ -0,0 +1,12 @@ +package com.gomo.app.common.logging; + +import org.springframework.modulith.ApplicationModule; +import org.springframework.modulith.PackageInfo; + +@ApplicationModule( + id = "common-logging", + displayName = "common-logging" +) +@PackageInfo +class SpringModulithPackageInfo { +} diff --git a/src/main/java/com/gomo/app/common/session/SpringModulithPackageInfo.java b/src/main/java/com/gomo/app/common/session/SpringModulithPackageInfo.java new file mode 100644 index 00000000..2a5417a7 --- /dev/null +++ b/src/main/java/com/gomo/app/common/session/SpringModulithPackageInfo.java @@ -0,0 +1,12 @@ +package com.gomo.app.common.session; + +import org.springframework.modulith.ApplicationModule; +import org.springframework.modulith.PackageInfo; + +@ApplicationModule( + id = "common-session", + displayName = "common-session" +) +@PackageInfo +class SpringModulithPackageInfo { +} diff --git a/src/main/java/com/gomo/app/common/util/SpringModulithPackageInfo.java b/src/main/java/com/gomo/app/common/util/SpringModulithPackageInfo.java new file mode 100644 index 00000000..6ca019c8 --- /dev/null +++ b/src/main/java/com/gomo/app/common/util/SpringModulithPackageInfo.java @@ -0,0 +1,12 @@ +package com.gomo.app.common.util; + +import org.springframework.modulith.ApplicationModule; +import org.springframework.modulith.PackageInfo; + +@ApplicationModule( + id = "common-util", + displayName = "common-util" +) +@PackageInfo +class SpringModulithPackageInfo { +} diff --git a/src/main/java/com/gomo/app/common/web/SpringModulithPackageInfo.java b/src/main/java/com/gomo/app/common/web/SpringModulithPackageInfo.java new file mode 100644 index 00000000..c829b60b --- /dev/null +++ b/src/main/java/com/gomo/app/common/web/SpringModulithPackageInfo.java @@ -0,0 +1,12 @@ +package com.gomo.app.common.web; + +import org.springframework.modulith.ApplicationModule; +import org.springframework.modulith.PackageInfo; + +@ApplicationModule( + id = "common-web", + displayName = "common-web" +) +@PackageInfo +class SpringModulithPackageInfo { +} diff --git a/src/main/java/com/gomo/app/core/interest/SpringModulithPackageInfo.java b/src/main/java/com/gomo/app/core/interest/SpringModulithPackageInfo.java new file mode 100644 index 00000000..b93e6dc7 --- /dev/null +++ b/src/main/java/com/gomo/app/core/interest/SpringModulithPackageInfo.java @@ -0,0 +1,26 @@ +package com.gomo.app.core.interest; + +import org.springframework.modulith.ApplicationModule; + +@ApplicationModule( + id = "core-interest", + displayName = "core-interest", + allowedDependencies = { + "common-arch", + "common-displayorder", + "common-event", + "common-exception", + "common-jpa", + "common-logging", + "common-session", + "common-util", + "core-member::in", + "core-member::dto", + "support-evententry::in", + "support-evententry::model", + "support-image::in" + } +) +@org.springframework.modulith.PackageInfo +class SpringModulithPackageInfo { +} diff --git a/src/main/java/com/gomo/app/core/interest/adapter/in/consumer/CompleteQuestEventScoreConsumer.java b/src/main/java/com/gomo/app/core/interest/adapter/in/consumer/CompleteQuestEventScoreConsumer.java index 8cd7c5d3..a33acd72 100644 --- a/src/main/java/com/gomo/app/core/interest/adapter/in/consumer/CompleteQuestEventScoreConsumer.java +++ b/src/main/java/com/gomo/app/core/interest/adapter/in/consumer/CompleteQuestEventScoreConsumer.java @@ -3,9 +3,9 @@ import org.springframework.amqp.rabbit.annotation.RabbitListener; import com.gomo.app.common.arch.EventConsumer; +import com.gomo.app.common.event.CompleteQuestEvent; import com.gomo.app.common.util.JsonParser; import com.gomo.app.core.interest.application.port.in.ProficiencyPropagator; -import com.gomo.app.core.quest.domain.event.CompleteQuestEvent; import com.gomo.app.support.evententry.application.port.IdempotentEventEntryConsumer; import com.gomo.app.support.evententry.domain.model.EventEntry; diff --git a/src/main/java/com/gomo/app/core/interest/application/port/dto/SpringModulithPackageInfo.java b/src/main/java/com/gomo/app/core/interest/application/port/dto/SpringModulithPackageInfo.java new file mode 100644 index 00000000..90f60f6f --- /dev/null +++ b/src/main/java/com/gomo/app/core/interest/application/port/dto/SpringModulithPackageInfo.java @@ -0,0 +1,9 @@ +package com.gomo.app.core.interest.application.port.dto; + +import org.springframework.modulith.NamedInterface; +import org.springframework.modulith.PackageInfo; + +@NamedInterface("dto") +@PackageInfo +class SpringModulithPackageInfo { +} diff --git a/src/main/java/com/gomo/app/core/interest/application/port/in/SpringModulithPackageInfo.java b/src/main/java/com/gomo/app/core/interest/application/port/in/SpringModulithPackageInfo.java new file mode 100644 index 00000000..97f553cd --- /dev/null +++ b/src/main/java/com/gomo/app/core/interest/application/port/in/SpringModulithPackageInfo.java @@ -0,0 +1,9 @@ +package com.gomo.app.core.interest.application.port.in; + +import org.springframework.modulith.NamedInterface; +import org.springframework.modulith.PackageInfo; + +@NamedInterface("in") +@PackageInfo +class SpringModulithPackageInfo { +} diff --git a/src/main/java/com/gomo/app/core/point/SpringModulithPackageInfo.java b/src/main/java/com/gomo/app/core/point/SpringModulithPackageInfo.java new file mode 100644 index 00000000..48b7ed65 --- /dev/null +++ b/src/main/java/com/gomo/app/core/point/SpringModulithPackageInfo.java @@ -0,0 +1,24 @@ +package com.gomo.app.core.point; + +import org.springframework.modulith.ApplicationModule; +import org.springframework.modulith.PackageInfo; + +@ApplicationModule( + id = "core-point", + displayName = "core-point", + allowedDependencies = { + "common-arch", + "common-event", + "common-exception", + "common-jpa", + "common-logging", + "common-session", + "common-util", + "common-web", + "support-evententry::in", + "support-evententry::model", + } +) +@PackageInfo +class SpringModulithPackageInfo { +} diff --git a/src/main/java/com/gomo/app/core/point/adapter/in/consumer/CompleteQuestEventPointConsumer.java b/src/main/java/com/gomo/app/core/point/adapter/in/consumer/CompleteQuestEventPointConsumer.java index 5e6cd85e..854a4394 100644 --- a/src/main/java/com/gomo/app/core/point/adapter/in/consumer/CompleteQuestEventPointConsumer.java +++ b/src/main/java/com/gomo/app/core/point/adapter/in/consumer/CompleteQuestEventPointConsumer.java @@ -3,9 +3,9 @@ import org.springframework.amqp.rabbit.annotation.RabbitListener; import com.gomo.app.common.arch.EventConsumer; +import com.gomo.app.common.event.CompleteQuestEvent; import com.gomo.app.common.util.JsonParser; import com.gomo.app.core.point.application.port.in.PointCreator; -import com.gomo.app.core.quest.domain.event.CompleteQuestEvent; import com.gomo.app.support.evententry.application.port.IdempotentEventEntryConsumer; import com.gomo.app.support.evententry.domain.model.EventEntry; diff --git a/src/main/java/com/gomo/app/core/point/application/port/in/SpringModulithPackageInfo.java b/src/main/java/com/gomo/app/core/point/application/port/in/SpringModulithPackageInfo.java new file mode 100644 index 00000000..083fb1da --- /dev/null +++ b/src/main/java/com/gomo/app/core/point/application/port/in/SpringModulithPackageInfo.java @@ -0,0 +1,9 @@ +package com.gomo.app.core.point.application.port.in; + +import org.springframework.modulith.NamedInterface; +import org.springframework.modulith.PackageInfo; + +@NamedInterface("in") +@PackageInfo +class SpringModulithPackageInfo { +} diff --git a/src/main/java/com/gomo/app/core/quest/SpringModulithPackageInfo.java b/src/main/java/com/gomo/app/core/quest/SpringModulithPackageInfo.java new file mode 100644 index 00000000..104fc2e4 --- /dev/null +++ b/src/main/java/com/gomo/app/core/quest/SpringModulithPackageInfo.java @@ -0,0 +1,30 @@ +package com.gomo.app.core.quest; + +import org.springframework.modulith.ApplicationModule; +import org.springframework.modulith.PackageInfo; + +@ApplicationModule( + id = "core-quest", + displayName = "core-quest", + allowedDependencies = { + "common-arch", + "common-displayorder", + "common-event", + "common-exception", + "common-jpa", + "common-logging", + "common-session", + "common-util", + "core-member::in", + "core-member::dto", + "core-interest::in", + "core-interest::dto", + "support-llm::in", + "support-evententry::in", + "support-messagebroker::in", + "support-messagebroker::model", + } +) +@PackageInfo +class SpringModulithPackageInfo { +} diff --git a/src/main/java/com/gomo/app/core/quest/adapter/in/consumer/FillQuestPoolEventConsumer.java b/src/main/java/com/gomo/app/core/quest/adapter/in/consumer/FillQuestPoolEventConsumer.java index 6a6f0705..3e1ab3a7 100644 --- a/src/main/java/com/gomo/app/core/quest/adapter/in/consumer/FillQuestPoolEventConsumer.java +++ b/src/main/java/com/gomo/app/core/quest/adapter/in/consumer/FillQuestPoolEventConsumer.java @@ -3,10 +3,10 @@ import org.springframework.amqp.rabbit.annotation.RabbitListener; import com.gomo.app.common.arch.EventConsumer; +import com.gomo.app.common.event.CreateQuestPoolEvent; import com.gomo.app.common.util.JsonParser; import com.gomo.app.core.quest.application.port.command.CreateQuestPoolCommand; import com.gomo.app.core.quest.application.port.in.QuestPoolCreator; -import com.gomo.app.core.quest.domain.event.CreateQuestPoolEvent; import com.gomo.app.support.messagebroker.application.port.in.IdempotentDirectEventConsumer; import com.gomo.app.support.messagebroker.domain.model.DirectEvent; diff --git a/src/main/java/com/gomo/app/core/quest/application/service/AssignQuestCompleteService.java b/src/main/java/com/gomo/app/core/quest/application/service/AssignQuestCompleteService.java index 068fa2fd..16fb73ba 100644 --- a/src/main/java/com/gomo/app/core/quest/application/service/AssignQuestCompleteService.java +++ b/src/main/java/com/gomo/app/core/quest/application/service/AssignQuestCompleteService.java @@ -5,12 +5,12 @@ import org.springframework.transaction.annotation.Transactional; import com.gomo.app.common.arch.ApplicationService; +import com.gomo.app.common.event.CompleteQuestEvent; import com.gomo.app.common.logging.AuditLog; import com.gomo.app.common.util.JsonParser; import com.gomo.app.common.util.TimestampGenerator; import com.gomo.app.core.quest.application.port.command.CompleteAssignQuestCommand; import com.gomo.app.core.quest.application.port.in.AssignQuestCompleter; -import com.gomo.app.core.quest.domain.event.CompleteQuestEvent; import com.gomo.app.core.quest.domain.model.assign.AssignQuest; import com.gomo.app.core.quest.domain.model.assign.CompletionProof; import com.gomo.app.core.quest.domain.model.reward.QuestReward; diff --git a/src/main/java/com/gomo/app/core/quest/application/service/QuestPoolEventService.java b/src/main/java/com/gomo/app/core/quest/application/service/QuestPoolEventService.java index 5baa9aee..9daeb9e2 100644 --- a/src/main/java/com/gomo/app/core/quest/application/service/QuestPoolEventService.java +++ b/src/main/java/com/gomo/app/core/quest/application/service/QuestPoolEventService.java @@ -7,6 +7,7 @@ import java.util.stream.Collectors; import com.gomo.app.common.arch.ApplicationService; +import com.gomo.app.common.event.CreateQuestPoolEvent; import com.gomo.app.common.event.EventRouter; import com.gomo.app.common.logging.AuditLog; import com.gomo.app.common.util.JsonParser; @@ -16,7 +17,6 @@ import com.gomo.app.core.quest.application.port.dto.SubjectDto; import com.gomo.app.core.quest.application.port.in.QuestPoolEventPublisher; import com.gomo.app.core.quest.application.port.out.SubjectReader; -import com.gomo.app.core.quest.domain.event.CreateQuestPoolEvent; import com.gomo.app.core.quest.domain.model.participant.Participant; import com.gomo.app.support.messagebroker.application.port.in.MessagePublisher; import com.gomo.app.support.messagebroker.domain.model.DirectEvent; diff --git a/src/main/java/com/gomo/app/core/streak/SpringModulithPackageInfo.java b/src/main/java/com/gomo/app/core/streak/SpringModulithPackageInfo.java new file mode 100644 index 00000000..affae844 --- /dev/null +++ b/src/main/java/com/gomo/app/core/streak/SpringModulithPackageInfo.java @@ -0,0 +1,24 @@ +package com.gomo.app.core.streak; + +import org.springframework.modulith.ApplicationModule; +import org.springframework.modulith.PackageInfo; + +@ApplicationModule( + id = "core-streak", + displayName = "core-streak", + allowedDependencies = { + "common-arch", + "common-event", + "common-exception", + "common-jpa", + "common-logging", + "common-session", + "common-util", + "common-web", + "support-evententry::in", + "support-evententry::model", + } +) +@PackageInfo +class SpringModulithPackageInfo { +} diff --git a/src/main/java/com/gomo/app/core/streak/adapter/in/consumer/CompleteQuestEventStreakConsumer.java b/src/main/java/com/gomo/app/core/streak/adapter/in/consumer/CompleteQuestEventStreakConsumer.java index 286d1a30..b79f50fc 100644 --- a/src/main/java/com/gomo/app/core/streak/adapter/in/consumer/CompleteQuestEventStreakConsumer.java +++ b/src/main/java/com/gomo/app/core/streak/adapter/in/consumer/CompleteQuestEventStreakConsumer.java @@ -3,8 +3,8 @@ import org.springframework.amqp.rabbit.annotation.RabbitListener; import com.gomo.app.common.arch.EventConsumer; +import com.gomo.app.common.event.CompleteQuestEvent; import com.gomo.app.common.util.JsonParser; -import com.gomo.app.core.quest.domain.event.CompleteQuestEvent; import com.gomo.app.core.streak.application.port.in.StreakCreator; import com.gomo.app.support.evententry.application.port.IdempotentEventEntryConsumer; import com.gomo.app.support.evententry.domain.model.EventEntry; diff --git a/src/main/java/com/gomo/app/core/streak/application/port/in/SpringModulithPackageInfo.java b/src/main/java/com/gomo/app/core/streak/application/port/in/SpringModulithPackageInfo.java new file mode 100644 index 00000000..258e4650 --- /dev/null +++ b/src/main/java/com/gomo/app/core/streak/application/port/in/SpringModulithPackageInfo.java @@ -0,0 +1,9 @@ +package com.gomo.app.core.streak.application.port.in; + +import org.springframework.modulith.NamedInterface; +import org.springframework.modulith.PackageInfo; + +@NamedInterface("in") +@PackageInfo +class SpringModulithPackageInfo { +} diff --git a/src/main/java/com/gomo/app/core/survey/SpringModulithPackageInfo.java b/src/main/java/com/gomo/app/core/survey/SpringModulithPackageInfo.java new file mode 100644 index 00000000..3319ef3a --- /dev/null +++ b/src/main/java/com/gomo/app/core/survey/SpringModulithPackageInfo.java @@ -0,0 +1,12 @@ +package com.gomo.app.core.survey; + +import org.springframework.modulith.ApplicationModule; +import org.springframework.modulith.PackageInfo; + +@ApplicationModule( + id = "core-survey", + displayName = "core-survey" +) +@PackageInfo +class SpringModulithPackageInfo { +} diff --git a/src/main/java/com/gomo/app/support/diagnostic/LogSimulator.java b/src/main/java/com/gomo/app/support/diagnostic/LogSimulator.java index e4cbcfd7..0650cad8 100644 --- a/src/main/java/com/gomo/app/support/diagnostic/LogSimulator.java +++ b/src/main/java/com/gomo/app/support/diagnostic/LogSimulator.java @@ -1,4 +1,4 @@ -package com.gomo.app.support.diagnositc; +package com.gomo.app.support.diagnostic; import org.springframework.context.annotation.Profile; import org.springframework.web.bind.annotation.PostMapping; diff --git a/src/main/java/com/gomo/app/support/diagnostic/SpringModulithPackageInfo.java b/src/main/java/com/gomo/app/support/diagnostic/SpringModulithPackageInfo.java new file mode 100644 index 00000000..90a75a24 --- /dev/null +++ b/src/main/java/com/gomo/app/support/diagnostic/SpringModulithPackageInfo.java @@ -0,0 +1,12 @@ +package com.gomo.app.support.diagnostic; + +import org.springframework.modulith.ApplicationModule; +import org.springframework.modulith.PackageInfo; + +@ApplicationModule( + id = "support-diagnostic", + displayName = "support-diagnostic" +) +@PackageInfo +class SpringModulithPackageInfo { +} diff --git a/src/main/java/com/gomo/app/support/evententry/SpringModulithPackageInfo.java b/src/main/java/com/gomo/app/support/evententry/SpringModulithPackageInfo.java new file mode 100644 index 00000000..e86d4194 --- /dev/null +++ b/src/main/java/com/gomo/app/support/evententry/SpringModulithPackageInfo.java @@ -0,0 +1,18 @@ +package com.gomo.app.support.evententry; + +import org.springframework.modulith.ApplicationModule; +import org.springframework.modulith.PackageInfo; + +@ApplicationModule( + id = "support-evententry", + displayName = "support-evententry", + allowedDependencies = { + "common-arch", + "common-event", + "common-util", + "support-messagebroker::in" + } +) +@PackageInfo +class SpringModulithPackageInfo { +} diff --git a/src/main/java/com/gomo/app/support/evententry/application/port/SpringModulithPackageInfo.java b/src/main/java/com/gomo/app/support/evententry/application/port/SpringModulithPackageInfo.java new file mode 100644 index 00000000..bf913a16 --- /dev/null +++ b/src/main/java/com/gomo/app/support/evententry/application/port/SpringModulithPackageInfo.java @@ -0,0 +1,9 @@ +package com.gomo.app.support.evententry.application.port; + +import org.springframework.modulith.NamedInterface; +import org.springframework.modulith.PackageInfo; + +@NamedInterface("in") +@PackageInfo +class SpringModulithPackageInfo { +} diff --git a/src/main/java/com/gomo/app/support/evententry/domain/model/SpringModulithPackageInfo.java b/src/main/java/com/gomo/app/support/evententry/domain/model/SpringModulithPackageInfo.java new file mode 100644 index 00000000..a0a72881 --- /dev/null +++ b/src/main/java/com/gomo/app/support/evententry/domain/model/SpringModulithPackageInfo.java @@ -0,0 +1,9 @@ +package com.gomo.app.support.evententry.domain.model; + +import org.springframework.modulith.NamedInterface; +import org.springframework.modulith.PackageInfo; + +@NamedInterface("model") +@PackageInfo +class SpringModulithPackageInfo { +} diff --git a/src/main/java/com/gomo/app/support/image/SpringModulithPackageInfo.java b/src/main/java/com/gomo/app/support/image/SpringModulithPackageInfo.java new file mode 100644 index 00000000..d08f387b --- /dev/null +++ b/src/main/java/com/gomo/app/support/image/SpringModulithPackageInfo.java @@ -0,0 +1,16 @@ +package com.gomo.app.support.image; + +import org.springframework.modulith.ApplicationModule; +import org.springframework.modulith.PackageInfo; + +@ApplicationModule( + id = "support-image", + displayName = "support-image", + allowedDependencies = { + "common-arch", + "common-exception" + } +) +@PackageInfo +class SpringModulithPackageInfo { +} diff --git a/src/main/java/com/gomo/app/support/image/application/port/in/SpringModulithPackageInfo.java b/src/main/java/com/gomo/app/support/image/application/port/in/SpringModulithPackageInfo.java new file mode 100644 index 00000000..b5909842 --- /dev/null +++ b/src/main/java/com/gomo/app/support/image/application/port/in/SpringModulithPackageInfo.java @@ -0,0 +1,9 @@ +package com.gomo.app.support.image.application.port.in; + +import org.springframework.modulith.NamedInterface; +import org.springframework.modulith.PackageInfo; + +@NamedInterface("in") +@PackageInfo +class SpringModulithPackageInfo { +} diff --git a/src/main/java/com/gomo/app/support/llm/SpringModulithPackageInfo.java b/src/main/java/com/gomo/app/support/llm/SpringModulithPackageInfo.java new file mode 100644 index 00000000..3e477016 --- /dev/null +++ b/src/main/java/com/gomo/app/support/llm/SpringModulithPackageInfo.java @@ -0,0 +1,12 @@ +package com.gomo.app.support.llm; + +import org.springframework.modulith.ApplicationModule; +import org.springframework.modulith.PackageInfo; + +@ApplicationModule( + id = "support-llm", + displayName = "support-llm" +) +@PackageInfo +class SpringModulithPackageInfo { +} diff --git a/src/main/java/com/gomo/app/support/llm/application/SpringModulithPackageInfo.java b/src/main/java/com/gomo/app/support/llm/application/SpringModulithPackageInfo.java new file mode 100644 index 00000000..435f2af5 --- /dev/null +++ b/src/main/java/com/gomo/app/support/llm/application/SpringModulithPackageInfo.java @@ -0,0 +1,9 @@ +package com.gomo.app.support.llm.application; + +import org.springframework.modulith.NamedInterface; +import org.springframework.modulith.PackageInfo; + +@NamedInterface("in") +@PackageInfo +class SpringModulithPackageInfo { +} diff --git a/src/main/java/com/gomo/app/support/logging/SpringModulithPackageInfo.java b/src/main/java/com/gomo/app/support/logging/SpringModulithPackageInfo.java new file mode 100644 index 00000000..91702eee --- /dev/null +++ b/src/main/java/com/gomo/app/support/logging/SpringModulithPackageInfo.java @@ -0,0 +1,13 @@ +package com.gomo.app.support.logging; + +import org.springframework.modulith.ApplicationModule; +import org.springframework.modulith.PackageInfo; + +@ApplicationModule( + id = "support-logging", + displayName = "support-logging", + type = ApplicationModule.Type.OPEN +) +@PackageInfo +class SpringModulithPackageInfo { +} diff --git a/src/main/java/com/gomo/app/support/messagebroker/SpringModulithPackageInfo.java b/src/main/java/com/gomo/app/support/messagebroker/SpringModulithPackageInfo.java new file mode 100644 index 00000000..ec5d326a --- /dev/null +++ b/src/main/java/com/gomo/app/support/messagebroker/SpringModulithPackageInfo.java @@ -0,0 +1,12 @@ +package com.gomo.app.support.messagebroker; + +import org.springframework.modulith.ApplicationModule; +import org.springframework.modulith.PackageInfo; + +@ApplicationModule( + id = "support-messagebroker", + displayName = "support-messagebroker" +) +@PackageInfo +class SpringModulithPackageInfo { +} diff --git a/src/main/java/com/gomo/app/support/messagebroker/application/port/in/SpringModulithPackageInfo.java b/src/main/java/com/gomo/app/support/messagebroker/application/port/in/SpringModulithPackageInfo.java new file mode 100644 index 00000000..ac12084d --- /dev/null +++ b/src/main/java/com/gomo/app/support/messagebroker/application/port/in/SpringModulithPackageInfo.java @@ -0,0 +1,9 @@ +package com.gomo.app.support.messagebroker.application.port.in; + +import org.springframework.modulith.NamedInterface; +import org.springframework.modulith.PackageInfo; + +@NamedInterface("in") +@PackageInfo +class SpringModulithPackageInfo { +} diff --git a/src/main/java/com/gomo/app/support/messagebroker/domain/model/SpringModulithPackageInfo.java b/src/main/java/com/gomo/app/support/messagebroker/domain/model/SpringModulithPackageInfo.java new file mode 100644 index 00000000..55dd0a75 --- /dev/null +++ b/src/main/java/com/gomo/app/support/messagebroker/domain/model/SpringModulithPackageInfo.java @@ -0,0 +1,9 @@ +package com.gomo.app.support.messagebroker.domain.model; + +import org.springframework.modulith.NamedInterface; +import org.springframework.modulith.PackageInfo; + +@NamedInterface("model") +@PackageInfo +class SpringModulithPackageInfo { +} diff --git a/src/test/java/com/gomo/app/core/auth/adapter/in/api/ResetPasswordDocumentationTest.java b/src/test/java/com/gomo/app/core/auth/adapter/in/api/ResetPasswordDocumentationTest.java index f0374eae..1f08a24a 100644 --- a/src/test/java/com/gomo/app/core/auth/adapter/in/api/ResetPasswordDocumentationTest.java +++ b/src/test/java/com/gomo/app/core/auth/adapter/in/api/ResetPasswordDocumentationTest.java @@ -1,4 +1,4 @@ -package com.gomo.app.core.member.adapter.in.api; +package com.gomo.app.core.auth.adapter.in.api; import static io.restassured.RestAssured.*; import static org.springframework.http.HttpHeaders.*; @@ -12,7 +12,7 @@ import org.springframework.restdocs.restassured.RestDocumentationFilter; import com.gomo.app.core.auth.adapter.in.api.request.ResetPasswordRequest; -import com.gomo.app.core.member.adapter.in.api.snippet.ResetPasswordSnippet; +import com.gomo.app.core.auth.adapter.in.api.snippet.ResetPasswordSnippet; import com.gomo.app.core.member.domain.repository.MemberRepository; import com.gomo.app.test.DocumentationTestBase; diff --git a/src/test/java/com/gomo/app/core/auth/adapter/in/api/snippet/ResetPasswordSnippet.java b/src/test/java/com/gomo/app/core/auth/adapter/in/api/snippet/ResetPasswordSnippet.java index 16499bea..34b49331 100644 --- a/src/test/java/com/gomo/app/core/auth/adapter/in/api/snippet/ResetPasswordSnippet.java +++ b/src/test/java/com/gomo/app/core/auth/adapter/in/api/snippet/ResetPasswordSnippet.java @@ -1,4 +1,4 @@ -package com.gomo.app.core.member.adapter.in.api.snippet; +package com.gomo.app.core.auth.adapter.in.api.snippet; import static com.gomo.app.test.ErrorResponseFields.*; import static org.springframework.http.HttpHeaders.*; @@ -12,7 +12,7 @@ import org.springframework.restdocs.snippet.Snippet; public class ResetPasswordSnippet { - private static final String IDENTIFIER = "member-password-reset"; + private static final String IDENTIFIER = "auth-password-reset"; private static final Snippet REQUEST_HEADERS = requestHeaders( headerWithName(CONTENT_TYPE).description("Content-Type: `application/json`") diff --git a/src/test/java/com/gomo/app/core/auth/application/service/AuthServiceTest.java b/src/test/java/com/gomo/app/core/auth/application/service/AuthServiceTest.java index e48cf0d0..3963301e 100644 --- a/src/test/java/com/gomo/app/core/auth/application/service/AuthServiceTest.java +++ b/src/test/java/com/gomo/app/core/auth/application/service/AuthServiceTest.java @@ -21,6 +21,7 @@ import com.gomo.app.core.auth.application.port.out.JwtVerifier; import com.gomo.app.core.auth.application.port.out.PrincipalCreator; import com.gomo.app.core.auth.application.port.out.PrincipalLoginProcessor; +import com.gomo.app.core.auth.application.port.out.PrincipalPasswordResetter; import com.gomo.app.core.auth.domain.exception.AuthenticationFailException; import com.gomo.app.core.auth.domain.model.AuthToken; import com.gomo.app.core.member.domain.model.LoginProvider; @@ -44,6 +45,9 @@ public class AuthServiceTest { @Mock private AuthTokenService authTokenService; + @Mock + private PrincipalPasswordResetter principalPasswordResetter; + @DisplayName("이메일로 회원 가입한다.") @Test void email_signup() { @@ -95,4 +99,24 @@ void login() { assertThat(actual).usingRecursiveComparison().isEqualTo(expected); } + + @DisplayName("사용자 비밀번호 초기화 요청을 처리한다.") + @Test + void reset_password() { + doReturn(true).when(jwtVerifier).verify(anyString()); + + sut.reset("email@email.com", "Gomo123@", "token"); + + verify(principalPasswordResetter, times(1)).reset(anyString(), anyString()); + } + + @DisplayName("사용자 비밀번호 초기화 요청을 처리한다.") + @Test + void reset_password_with_invalid_token() { + doReturn(false).when(jwtVerifier).verify(anyString()); + + assertThatThrownBy(() -> sut.reset("email@email.com", "Gomo123@", "token")) + .isInstanceOf(AuthenticationFailException.class) + .hasMessageContaining(INVALID_VERIFIED_EMAIL_TOKEN.getMessage()); + } } diff --git a/src/test/java/com/gomo/app/core/interest/adapter/in/consumer/CompleteQuestEventScoreConsumerTest.java b/src/test/java/com/gomo/app/core/interest/adapter/in/consumer/CompleteQuestEventScoreConsumerTest.java index f651a000..bc662c25 100644 --- a/src/test/java/com/gomo/app/core/interest/adapter/in/consumer/CompleteQuestEventScoreConsumerTest.java +++ b/src/test/java/com/gomo/app/core/interest/adapter/in/consumer/CompleteQuestEventScoreConsumerTest.java @@ -15,9 +15,9 @@ import org.mockito.MockedStatic; import org.mockito.junit.jupiter.MockitoExtension; +import com.gomo.app.common.event.CompleteQuestEvent; import com.gomo.app.common.util.JsonParser; import com.gomo.app.core.interest.application.port.in.ProficiencyPropagator; -import com.gomo.app.core.quest.domain.event.CompleteQuestEvent; import com.gomo.app.support.evententry.domain.model.EventEntry; @DisplayName("[Consumer unit]: 퀘스트 완료(점수) 이벤트 처리 테스트") diff --git a/src/test/java/com/gomo/app/core/member/adapter/in/api/DeleteMemberDocumentationTest.java b/src/test/java/com/gomo/app/core/member/adapter/in/api/DeleteMemberDocumentationTest.java index 31b1c31d..cff1168c 100644 --- a/src/test/java/com/gomo/app/core/member/adapter/in/api/DeleteMemberDocumentationTest.java +++ b/src/test/java/com/gomo/app/core/member/adapter/in/api/DeleteMemberDocumentationTest.java @@ -9,9 +9,11 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.restdocs.restassured.RestDocumentationFilter; import com.gomo.app.core.member.adapter.in.api.snippet.DeleteMemberSnippet; +import com.gomo.app.core.member.domain.repository.MemberRepository; import com.gomo.app.test.DocumentationTestBase; @DisplayName("[Presentation documentation]: 회원 탈퇴 테스트") @@ -22,6 +24,9 @@ public class DeleteMemberDocumentationTest extends DocumentationTestBase { private final RestDocumentationFilter filter = DeleteMemberSnippet.create(); private final RestDocumentationFilter errorFilter = DeleteMemberSnippet.createError(); + @Autowired + private MemberRepository memberRepository; + @BeforeEach void setSessionToTestPrincipal() { String email = "test@naver.com"; @@ -33,6 +38,7 @@ void setSessionToTestPrincipal() { @AfterEach void setSessionToOriginalPrincipal() { sessionInit(login(sessionEmail, sessionPassword)); + memberRepository.deleteAllInBatch(); } @DisplayName("사용자가 회원 탈퇴를 요청한다.") diff --git a/src/test/java/com/gomo/app/core/member/application/service/PasswordServiceTest.java b/src/test/java/com/gomo/app/core/member/application/service/PasswordServiceTest.java index f837822b..35ae2c7b 100644 --- a/src/test/java/com/gomo/app/core/member/application/service/PasswordServiceTest.java +++ b/src/test/java/com/gomo/app/core/member/application/service/PasswordServiceTest.java @@ -14,7 +14,6 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import com.gomo.app.core.member.application.port.out.EmailTokenVerifier; import com.gomo.app.core.member.application.port.out.PasswordEncodeManager; import com.gomo.app.core.member.domain.exception.MemberAuthenticationFailedException; import com.gomo.app.core.member.domain.model.LoginProvider; @@ -29,9 +28,6 @@ class PasswordServiceTest { @InjectMocks private PasswordService sut; - @Mock - private EmailTokenVerifier emailTokenVerifier; - @Mock private PasswordEncodeManager passwordEncodeManager; @@ -46,10 +42,9 @@ void reset_password() { doReturn(member).when(memberService).findByEmail(any()); doReturn(encoded).when(passwordEncodeManager).encode(any()); - sut.reset(member.email(), "New1234@", "temporaryToken"); + sut.reset(member.email(), "New1234@"); assertThat(member.password()).isEqualTo(encoded); - verify(emailTokenVerifier, times(1)).verify(any()); } @DisplayName("비밀번호를 변경한다.") diff --git a/src/test/java/com/gomo/app/core/point/adapter/in/consumer/CompleteQuestEventPointConsumerTest.java b/src/test/java/com/gomo/app/core/point/adapter/in/consumer/CompleteQuestEventPointConsumerTest.java index 7ba92467..c58a02ff 100644 --- a/src/test/java/com/gomo/app/core/point/adapter/in/consumer/CompleteQuestEventPointConsumerTest.java +++ b/src/test/java/com/gomo/app/core/point/adapter/in/consumer/CompleteQuestEventPointConsumerTest.java @@ -15,9 +15,9 @@ import org.mockito.MockedStatic; import org.mockito.junit.jupiter.MockitoExtension; +import com.gomo.app.common.event.CompleteQuestEvent; import com.gomo.app.common.util.JsonParser; import com.gomo.app.core.point.application.port.in.PointCreator; -import com.gomo.app.core.quest.domain.event.CompleteQuestEvent; import com.gomo.app.support.evententry.domain.model.EventEntry; @DisplayName("[Consumer unit]: 퀘스트 완료(포인트) 이벤트 처리 테스트") diff --git a/src/test/java/com/gomo/app/core/streak/adapter/in/consumer/CompleteQuestEventStreakConsumerTest.java b/src/test/java/com/gomo/app/core/streak/adapter/in/consumer/CompleteQuestEventStreakConsumerTest.java index 6d90fc29..fb729755 100644 --- a/src/test/java/com/gomo/app/core/streak/adapter/in/consumer/CompleteQuestEventStreakConsumerTest.java +++ b/src/test/java/com/gomo/app/core/streak/adapter/in/consumer/CompleteQuestEventStreakConsumerTest.java @@ -15,8 +15,8 @@ import org.mockito.MockedStatic; import org.mockito.junit.jupiter.MockitoExtension; +import com.gomo.app.common.event.CompleteQuestEvent; import com.gomo.app.common.util.JsonParser; -import com.gomo.app.core.quest.domain.event.CompleteQuestEvent; import com.gomo.app.core.streak.application.port.in.StreakCreator; import com.gomo.app.support.evententry.domain.model.EventEntry; diff --git a/src/test/java/com/gomo/app/modulith/AnnotationBasedModuleDetectionStrategy.java b/src/test/java/com/gomo/app/modulith/AnnotationBasedModuleDetectionStrategy.java new file mode 100644 index 00000000..2326fecb --- /dev/null +++ b/src/test/java/com/gomo/app/modulith/AnnotationBasedModuleDetectionStrategy.java @@ -0,0 +1,15 @@ +package com.gomo.app.modulith; + +import java.util.stream.Stream; + +import org.springframework.modulith.ApplicationModule; +import org.springframework.modulith.core.ApplicationModuleDetectionStrategy; +import org.springframework.modulith.core.JavaPackage; + +public class AnnotationBasedModuleDetectionStrategy implements ApplicationModuleDetectionStrategy { + + @Override + public Stream getModuleBasePackages(JavaPackage basePackage) { + return basePackage.getSubPackagesAnnotatedWith(ApplicationModule.class); + } +} diff --git a/src/test/java/com/gomo/app/modulith/ModularityTests.java b/src/test/java/com/gomo/app/modulith/ModularityTests.java new file mode 100644 index 00000000..45ea7948 --- /dev/null +++ b/src/test/java/com/gomo/app/modulith/ModularityTests.java @@ -0,0 +1,31 @@ +package com.gomo.app.modulith; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.modulith.core.ApplicationModules; +import org.springframework.modulith.docs.Documenter; + +import com.gomo.app.GomoApplication; + +/** + * Tests to verify the modular structure and generate documentation for the modules. + */ +public class ModularityTests { + + ApplicationModules modules = ApplicationModules.of(GomoApplication.class); + + @DisplayName("모듈간 순환 의존성은 존재하지 않는다.") + @Test + void verifies_modular_structure() { + modules.verify(); + } + + @DisplayName("모듈 문서를 생성한다.") + @Test + void create_module_documentation() { + new Documenter(modules) + .writeModulesAsPlantUml() + .writeIndividualModulesAsPlantUml() + .writeModuleCanvases(); + } +} diff --git a/src/test/resources/META-INF/spring.factories b/src/test/resources/META-INF/spring.factories new file mode 100644 index 00000000..7f20010c --- /dev/null +++ b/src/test/resources/META-INF/spring.factories @@ -0,0 +1,2 @@ +org.springframework.modulith.core.ApplicationModuleDetectionStrategy=\ + com.gomo.app.modulith.AnnotationBasedModuleDetectionStrategy From 85c4d6fdb8c85ecceecc2952fff04559c255931b Mon Sep 17 00:00:00 2001 From: Junhyeok Lee Date: Wed, 5 Nov 2025 23:08:27 +0900 Subject: [PATCH 3/6] =?UTF-8?q?docs:=20=EB=AC=B8=EC=84=9C=20=EC=A0=9C?= =?UTF-8?q?=EB=AA=A9=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/modulith-index.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/docs/asciidoc/modulith-index.adoc b/src/docs/asciidoc/modulith-index.adoc index 2e7d4aad..f64b256a 100644 --- a/src/docs/asciidoc/modulith-index.adoc +++ b/src/docs/asciidoc/modulith-index.adoc @@ -1,4 +1,4 @@ -= Spring Modulith Example Documentation += Spring Modulith Documentation :modulith-docs: ../../../build/spring-modulith-docs == core-auth From aa8a2f05063b964e8e1526b8ea2b2a4d7dbc53d5 Mon Sep 17 00:00:00 2001 From: Junhyeok Lee Date: Wed, 5 Nov 2025 23:10:15 +0900 Subject: [PATCH 4/6] =?UTF-8?q?docs:=20=EB=AC=B8=EC=84=9C=20=EC=A0=9C?= =?UTF-8?q?=EB=AA=A9=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/modulith-index.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/docs/asciidoc/modulith-index.adoc b/src/docs/asciidoc/modulith-index.adoc index f64b256a..91207cc1 100644 --- a/src/docs/asciidoc/modulith-index.adoc +++ b/src/docs/asciidoc/modulith-index.adoc @@ -1,4 +1,4 @@ -= Spring Modulith Documentation += Module Docs :modulith-docs: ../../../build/spring-modulith-docs == core-auth From 57f6ebfdf17773af6ed9f1b1571b78a4d7e63a35 Mon Sep 17 00:00:00 2001 From: Junhyeok Lee Date: Wed, 5 Nov 2025 23:11:57 +0900 Subject: [PATCH 5/6] =?UTF-8?q?docs:=20=EB=AC=B8=EC=84=9C=20=EC=A0=9C?= =?UTF-8?q?=EB=AA=A9=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/docs/asciidoc/index.adoc | 2 +- src/docs/asciidoc/modulith-index.adoc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/docs/asciidoc/index.adoc b/src/docs/asciidoc/index.adoc index d78aa64b..f4919476 100644 --- a/src/docs/asciidoc/index.adoc +++ b/src/docs/asciidoc/index.adoc @@ -1,4 +1,4 @@ -= gomo api docs += GOMO Docs - API :doctype: book :source-highlighter: highlightjs :toc: left diff --git a/src/docs/asciidoc/modulith-index.adoc b/src/docs/asciidoc/modulith-index.adoc index 91207cc1..14f667af 100644 --- a/src/docs/asciidoc/modulith-index.adoc +++ b/src/docs/asciidoc/modulith-index.adoc @@ -1,4 +1,4 @@ -= Module Docs += GOMO Docs - Module :modulith-docs: ../../../build/spring-modulith-docs == core-auth From f58eeb03e0e372f3c2c967395a0add3340b93133 Mon Sep 17 00:00:00 2001 From: Junhyeok Lee Date: Wed, 5 Nov 2025 23:29:43 +0900 Subject: [PATCH 6/6] =?UTF-8?q?fix:=20support-logging=20=EB=AA=A8=EB=93=88?= =?UTF-8?q?=20=ED=8C=A8=ED=82=A4=EC=A7=80=20=EA=B3=B5=EA=B0=9C=20=ED=83=80?= =?UTF-8?q?=EC=9E=85=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../gomo/app/support/logging/SpringModulithPackageInfo.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/com/gomo/app/support/logging/SpringModulithPackageInfo.java b/src/main/java/com/gomo/app/support/logging/SpringModulithPackageInfo.java index 91702eee..63b45a4f 100644 --- a/src/main/java/com/gomo/app/support/logging/SpringModulithPackageInfo.java +++ b/src/main/java/com/gomo/app/support/logging/SpringModulithPackageInfo.java @@ -5,8 +5,7 @@ @ApplicationModule( id = "support-logging", - displayName = "support-logging", - type = ApplicationModule.Type.OPEN + displayName = "support-logging" ) @PackageInfo class SpringModulithPackageInfo {