diff --git a/README.md b/README.md new file mode 100644 index 0000000..d4c8427 --- /dev/null +++ b/README.md @@ -0,0 +1,228 @@ +# πŸ“’ FlipNote β€” User Service + +**FlipNote μ„œλΉ„μŠ€μ˜ μœ μ € 도메인 λ°±μ—”λ“œ λ ˆν¬μ§€ν† λ¦¬μž…λ‹ˆλ‹€.** + +![Spring Boot](https://img.shields.io/badge/Spring_Boot-6DB33F?logo=springboot&logoColor=white) +![Java](https://img.shields.io/badge/Java_21-007396?logo=openjdk&logoColor=white) +![MySQL](https://img.shields.io/badge/MySQL-4479A1?logo=mysql&logoColor=white) +![Redis](https://img.shields.io/badge/Redis-FF4438?logo=redis&logoColor=white) +![Deploy](https://img.shields.io/badge/Deploy-GHCR%20%2B%20Docker-2496ED?logo=docker&logoColor=white) + +--- + +## πŸ“‘ λͺ©μ°¨ + +- [μ‹œμž‘ν•˜κΈ°](#-μ‹œμž‘ν•˜κΈ°) +- [ν™˜κ²½ λ³€μˆ˜](#-ν™˜κ²½-λ³€μˆ˜) +- [μ‹€ν–‰ 및 배포](#-μ‹€ν–‰-및-배포) +- [ν”„λ‘œμ νŠΈ ꡬ쑰](#-ν”„λ‘œμ νŠΈ-ꡬ쑰) + +--- + +## πŸš€ μ‹œμž‘ν•˜κΈ° + +### 사전 μš”κ΅¬μ‚¬ν•­ + +- **Java** 21 이상 +- **Gradle** 8 이상 +- **MySQL** 8 이상 +- **Redis** 6 이상 +- Google OAuth2 ν΄λΌμ΄μ–ΈνŠΈ 생성 및 API ν‚€ λ°œκΈ‰ +- Resend 계정 생성 및 API ν‚€ λ°œκΈ‰ + +### μ„€μΉ˜ + +```bash +# μ˜μ‘΄μ„± μ„€μΉ˜ 및 λΉŒλ“œ +./gradlew build -x test +``` + +--- + +## πŸ” ν™˜κ²½ λ³€μˆ˜ + +`application.yml`μ—μ„œ μ°Έμ‘°ν•˜λŠ” ν™˜κ²½ λ³€μˆ˜ λͺ©λ‘μž…λ‹ˆλ‹€. 둜컬 μ‹€ν–‰ μ‹œ `.env` λ˜λŠ” IDE μ‹€ν–‰ ꡬ성에 μ•„λž˜ λ³€μˆ˜λ₯Ό μ„€μ •ν•©λ‹ˆλ‹€. + +``` +# ─── Database ─────────────────────────────────────────── +DB_URL=jdbc:mysql://localhost:3306/flipnote_user +DB_USERNAME= +DB_PASSWORD= + +# ─── Redis ────────────────────────────────────────────── +REDIS_HOST=localhost +REDIS_PORT=6379 +REDIS_PASSWORD= + +# ─── JPA ──────────────────────────────────────────────── +# create | create-drop | update | validate | none +DDL_AUTO=update + +# ─── gRPC ─────────────────────────────────────────────── +GRPC_PORT=9092 + +# ─── JWT ──────────────────────────────────────────────── +JWT_SECRET= +# μ•‘μ„ΈμŠ€ 토큰 만료 μ‹œκ°„ (ms), κΈ°λ³Έκ°’ 900000 (15λΆ„) +JWT_ACCESS_EXPIRATION=900000 +# λ¦¬ν”„λ ˆμ‹œ 토큰 만료 μ‹œκ°„ (ms), κΈ°λ³Έκ°’ 604800000 (7일) +JWT_REFRESH_EXPIRATION=604800000 + +# ─── Email (Resend) ───────────────────────────────────── +APP_RESEND_API_KEY= + +# ─── Client ───────────────────────────────────────────── +# ν”„λ‘ νŠΈμ—”λ“œ URL (CORS, λ¦¬λ‹€μ΄λ ‰νŠΈμ— μ‚¬μš©) +APP_CLIENT_URL=http://localhost:3000 + +# ─── Google OAuth2 ────────────────────────────────────── +GOOGLE_CLIENT_ID= +GOOGLE_CLIENT_SECRET= +``` + +> **⚠️ 주의**: ν™˜κ²½ λ³€μˆ˜ νŒŒμΌμ€ μ ˆλŒ€ git에 μ»€λ°‹ν•˜μ§€ λ§ˆμ„Έμš”. `.gitignore`에 ν¬ν•¨λ˜μ–΄ μžˆλŠ”μ§€ λ°˜λ“œμ‹œ ν™•μΈν•˜μ„Έμš”. + +--- + +## πŸ–₯️ μ‹€ν–‰ 및 배포 + +### 둜컬 개발 μ„œλ²„ μ‹€ν–‰ + +```bash +./gradlew bootRun +``` + +기본적으둜 `http://localhost:8081`μ—μ„œ μ‹€ν–‰λ©λ‹ˆλ‹€. +Swagger UIλŠ” `http://localhost:8081/users/swagger-ui.html`μ—μ„œ 확인할 수 μžˆμŠ΅λ‹ˆλ‹€. + +### ν”„λ‘œλ•μ…˜ λΉŒλ“œ + +```bash +./gradlew bootJar +``` + +`build/libs/user-0.0.1-SNAPSHOT.jar` 파일이 μƒμ„±λ©λ‹ˆλ‹€. + +### ν…ŒμŠ€νŠΈ μ‹€ν–‰ + +```bash +./gradlew test +``` + +### Docker 이미지 λΉŒλ“œ 및 μ‹€ν–‰ + +```bash +# 이미지 λΉŒλ“œ +docker build -t flipnote-user . + +# μ»¨ν…Œμ΄λ„ˆ μ‹€ν–‰ +docker run -p 8081:8080 \ + -e DB_URL=... \ + -e JWT_SECRET=... \ + flipnote-user +``` + +### 배포 (GitHub Actions) + +`main` λΈŒλžœμΉ˜μ— push μ‹œ GitHub Actionsκ°€ μžλ™μœΌλ‘œ μ•„λž˜ 과정을 μ‹€ν–‰ν•©λ‹ˆλ‹€. + +**CI** (`push` / `pull_request` β†’ `main`) +1. JDK 21 μ„€μΉ˜ +2. `./gradlew build -x test` β€” λΉŒλ“œ 검증 +3. `./gradlew test` β€” ν…ŒμŠ€νŠΈ μ‹€ν–‰ +4. Dependency-Check β€” 취약점 뢄석 리포트 생성 + +**CD** (`push` β†’ `main`) +1. GitHub Container Registry(GHCR) 둜그인 +2. Docker 이미지 λΉŒλ“œ +3. `ghcr.io/dungbik/flipnote-user` 이미지 Push + +> 배포에 ν•„μš”ν•œ μ‹œν¬λ¦Ώ(`ORG_PAT`)은 GitHub Repository β†’ Settings β†’ Secrets and variables β†’ Actions에 등둝해야 ν•©λ‹ˆλ‹€. + +--- + +## πŸ“ ν”„λ‘œμ νŠΈ ꡬ쑰 + +- κ°„λž΅ν™” 버전 + + ``` + src/main/java/flipnote/user/ + β”œβ”€β”€ domain/ # 도메인 λ ˆμ΄μ–΄ (μ—”ν‹°ν‹°, λ ˆν¬μ§€ν† λ¦¬, μ—λŸ¬μ½”λ“œ, 이벀트) + β”œβ”€β”€ application/ # μ• ν”Œλ¦¬μΌ€μ΄μ…˜ λ ˆμ΄μ–΄ (μ„œλΉ„μŠ€) + β”œβ”€β”€ infrastructure/ # 인프라 λ ˆμ΄μ–΄ (JWT, Redis, 메일, OAuth, μ„€μ •) + └── interfaces/ # μΈν„°νŽ˜μ΄μŠ€ λ ˆμ΄μ–΄ (HTTP, gRPC μ§„μž…μ ) + ``` + +``` +FlipNote-User/ +β”œβ”€β”€ src/ +β”‚ β”œβ”€β”€ main/ +β”‚ β”‚ β”œβ”€β”€ java/flipnote/user/ +β”‚ β”‚ β”‚ β”œβ”€β”€ UserApplication.java +β”‚ β”‚ β”‚ β”‚ +β”‚ β”‚ β”‚ β”œβ”€β”€ domain/ # 도메인 λ ˆμ΄μ–΄ +β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ common/ # 도메인 곡톡 +β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ ErrorCode.java +β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ BizException.java +β”‚ β”‚ β”‚ β”‚ β”‚ └── EmailSendException.java +β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ entity/ # JPA μ—”ν‹°ν‹° +β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ User.java +β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ OAuthLink.java +β”‚ β”‚ β”‚ β”‚ β”‚ └── BaseEntity.java +β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ repository/ # λ ˆν¬μ§€ν† λ¦¬ μΈν„°νŽ˜μ΄μŠ€ +β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ UserRepository.java +β”‚ β”‚ β”‚ β”‚ β”‚ └── OAuthLinkRepository.java +β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ event/ # 도메인 이벀트 +β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ EmailVerificationSendEvent.java +β”‚ β”‚ β”‚ β”‚ β”‚ └── PasswordResetCreateEvent.java +β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ AuthErrorCode.java +β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ UserErrorCode.java +β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ ImageErrorCode.java +β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ TokenClaims.java +β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ TokenPair.java +β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ PasswordResetConstants.java +β”‚ β”‚ β”‚ β”‚ └── VerificationConstants.java +β”‚ β”‚ β”‚ β”‚ +β”‚ β”‚ β”‚ β”œβ”€β”€ application/ # μ• ν”Œλ¦¬μΌ€μ΄μ…˜ λ ˆμ΄μ–΄ +β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ AuthService.java +β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ OAuthService.java +β”‚ β”‚ β”‚ β”‚ └── UserService.java +β”‚ β”‚ β”‚ β”‚ +β”‚ β”‚ β”‚ β”œβ”€β”€ infrastructure/ # 인프라 λ ˆμ΄μ–΄ +β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ config/ # λ²”μš© μ„€μ • (App, JPA, Swagger, gRPC ν΄λΌμ΄μ–ΈνŠΈ) +β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ jwt/ # JWT λ°œκΈ‰/검증 + μ„€μ • +β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ mail/ # 메일 λ°œμ†‘ μ„œλΉ„μŠ€ + μ„€μ • +β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ oauth/ # Google OAuth2 ν΄λΌμ΄μ–ΈνŠΈ + μ„€μ • +β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ redis/ # Redis μ €μž₯μ†Œ (토큰, μΈμ¦μ½”λ“œ λ“±) +β”‚ β”‚ β”‚ β”‚ └── listener/ # 도메인 이벀트 λ¦¬μŠ€λ„ˆ +β”‚ β”‚ β”‚ β”‚ +β”‚ β”‚ β”‚ └── interfaces/ # μΈν„°νŽ˜μ΄μŠ€ λ ˆμ΄μ–΄ +β”‚ β”‚ β”‚ β”œβ”€β”€ http/ # HTTP μ§„μž…μ  +β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ AuthController.java # 인증 (νšŒμ›κ°€μž…, 둜그인, λΉ„λ°€λ²ˆν˜Έ λ“±) +β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ OAuthController.java # μ†Œμ…œ 둜그인 (Google OAuth2) +β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ UserController.java # μœ μ € 정보 쑰회/μˆ˜μ • +β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ dto/ +β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ request/ # Request DTO +β”‚ β”‚ β”‚ β”‚ β”‚ └── response/ # Response DTO +β”‚ β”‚ β”‚ β”‚ └── common/ # ApiResponse, μ˜ˆμ™Έ 처리, μΏ ν‚€ μœ ν‹Έ +β”‚ β”‚ β”‚ └── grpc/ # gRPC μ§„μž…μ  +β”‚ β”‚ β”‚ β”œβ”€β”€ GrpcUserQueryService.java # μœ μ € 쑰회 gRPC μ„œλΉ„μŠ€ +β”‚ β”‚ β”‚ └── GrpcExceptionHandlerImpl.java # gRPC μ „μ—­ μ˜ˆμ™Έ 처리 +β”‚ β”‚ β”‚ +β”‚ β”‚ β”œβ”€β”€ proto/ # gRPC proto 파일 +β”‚ β”‚ β”‚ β”œβ”€β”€ user_query.proto +β”‚ β”‚ β”‚ └── image.proto +β”‚ β”‚ β”‚ +β”‚ β”‚ └── resources/ +β”‚ β”‚ β”œβ”€β”€ application.yml +β”‚ β”‚ └── templates/email/ # 이메일 HTML ν…œν”Œλ¦Ώ (Thymeleaf) +β”‚ β”‚ β”œβ”€β”€ email-verification.html +β”‚ β”‚ └── password-reset.html +β”‚ β”‚ +β”‚ └── test/ +β”‚ └── java/flipnote/user/ +β”‚ +β”œβ”€β”€ Dockerfile +β”œβ”€β”€ build.gradle.kts +└── settings.gradle.kts +``` \ No newline at end of file diff --git a/src/main/java/flipnote/user/auth/application/AuthService.java b/src/main/java/flipnote/user/application/AuthService.java similarity index 84% rename from src/main/java/flipnote/user/auth/application/AuthService.java rename to src/main/java/flipnote/user/application/AuthService.java index 0b81523..4e3a8ba 100644 --- a/src/main/java/flipnote/user/auth/application/AuthService.java +++ b/src/main/java/flipnote/user/application/AuthService.java @@ -1,30 +1,30 @@ -package flipnote.user.auth.application; - -import flipnote.user.auth.domain.AuthErrorCode; -import flipnote.user.auth.domain.TokenClaims; -import flipnote.user.auth.domain.TokenPair; -import flipnote.user.auth.domain.event.EmailVerificationSendEvent; -import flipnote.user.auth.domain.event.PasswordResetCreateEvent; -import flipnote.user.auth.infrastructure.jwt.JwtProvider; -import flipnote.user.auth.infrastructure.redis.EmailVerificationRepository; -import flipnote.user.auth.infrastructure.redis.PasswordResetRepository; -import flipnote.user.auth.infrastructure.redis.PasswordResetTokenGenerator; -import flipnote.user.auth.infrastructure.redis.SessionInvalidationRepository; -import flipnote.user.auth.infrastructure.redis.TokenBlacklistRepository; -import flipnote.user.auth.infrastructure.redis.VerificationCodeGenerator; -import flipnote.user.auth.presentation.dto.request.ChangePasswordRequest; -import flipnote.user.auth.presentation.dto.request.LoginRequest; -import flipnote.user.auth.presentation.dto.request.SignupRequest; -import flipnote.user.auth.presentation.dto.response.SocialLinksResponse; -import flipnote.user.auth.presentation.dto.response.TokenValidateResponse; -import flipnote.user.auth.presentation.dto.response.UserResponse; -import flipnote.user.global.config.ClientProperties; -import flipnote.user.global.exception.BizException; -import flipnote.user.user.domain.OAuthLink; -import flipnote.user.user.domain.OAuthLinkRepository; -import flipnote.user.user.domain.User; -import flipnote.user.user.domain.UserErrorCode; -import flipnote.user.user.domain.UserRepository; +package flipnote.user.application; + +import flipnote.user.domain.AuthErrorCode; +import flipnote.user.domain.entity.OAuthLink; +import flipnote.user.domain.repository.OAuthLinkRepository; +import flipnote.user.domain.TokenClaims; +import flipnote.user.domain.TokenPair; +import flipnote.user.domain.entity.User; +import flipnote.user.domain.UserErrorCode; +import flipnote.user.domain.repository.UserRepository; +import flipnote.user.domain.common.BizException; +import flipnote.user.domain.event.EmailVerificationSendEvent; +import flipnote.user.domain.event.PasswordResetCreateEvent; +import flipnote.user.infrastructure.config.ClientProperties; +import flipnote.user.infrastructure.jwt.JwtProvider; +import flipnote.user.infrastructure.redis.EmailVerificationRepository; +import flipnote.user.infrastructure.redis.PasswordResetRepository; +import flipnote.user.infrastructure.redis.PasswordResetTokenGenerator; +import flipnote.user.infrastructure.redis.SessionInvalidationRepository; +import flipnote.user.infrastructure.redis.TokenBlacklistRepository; +import flipnote.user.infrastructure.redis.VerificationCodeGenerator; +import flipnote.user.interfaces.http.dto.request.ChangePasswordRequest; +import flipnote.user.interfaces.http.dto.request.LoginRequest; +import flipnote.user.interfaces.http.dto.request.SignupRequest; +import flipnote.user.interfaces.http.dto.response.SocialLinksResponse; +import flipnote.user.interfaces.http.dto.response.TokenValidateResponse; +import flipnote.user.interfaces.http.dto.response.UserResponse; import lombok.RequiredArgsConstructor; import org.springframework.context.ApplicationEventPublisher; import org.springframework.security.crypto.password.PasswordEncoder; diff --git a/src/main/java/flipnote/user/auth/application/OAuthService.java b/src/main/java/flipnote/user/application/OAuthService.java similarity index 75% rename from src/main/java/flipnote/user/auth/application/OAuthService.java rename to src/main/java/flipnote/user/application/OAuthService.java index fb5eb6c..927cabd 100644 --- a/src/main/java/flipnote/user/auth/application/OAuthService.java +++ b/src/main/java/flipnote/user/application/OAuthService.java @@ -1,21 +1,21 @@ -package flipnote.user.auth.application; - -import flipnote.user.auth.domain.AuthErrorCode; -import flipnote.user.auth.domain.TokenPair; -import flipnote.user.auth.infrastructure.jwt.JwtProvider; -import flipnote.user.auth.infrastructure.oauth.OAuthApiClient; -import flipnote.user.auth.infrastructure.oauth.OAuth2UserInfo; -import flipnote.user.auth.infrastructure.oauth.PkceUtil; -import flipnote.user.auth.infrastructure.redis.SocialLinkTokenRepository; -import flipnote.user.global.config.OAuthProperties; -import flipnote.user.global.constants.HttpConstants; -import flipnote.user.global.exception.BizException; -import flipnote.user.user.domain.OAuthLink; -import flipnote.user.user.domain.OAuthLinkRepository; -import flipnote.user.user.domain.User; -import flipnote.user.user.domain.UserErrorCode; -import flipnote.user.user.domain.UserRepository; - +package flipnote.user.application; + +import flipnote.user.domain.AuthErrorCode; +import flipnote.user.domain.entity.OAuthLink; +import flipnote.user.domain.repository.OAuthLinkRepository; +import flipnote.user.domain.TokenPair; +import flipnote.user.domain.entity.User; +import flipnote.user.domain.UserErrorCode; +import flipnote.user.domain.repository.UserRepository; +import flipnote.user.domain.common.BizException; +import flipnote.user.infrastructure.oauth.OAuthProperties; +import flipnote.user.infrastructure.jwt.JwtProvider; +import flipnote.user.infrastructure.oauth.OAuthApiClient; +import flipnote.user.infrastructure.oauth.OAuth2UserInfo; +import flipnote.user.infrastructure.oauth.PkceUtil; +import flipnote.user.infrastructure.redis.SocialLinkTokenRepository; +import flipnote.user.interfaces.http.common.HttpConstants; +import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.http.ResponseCookie; @@ -43,7 +43,8 @@ public record AuthorizationRedirect(String authorizeUri, ResponseCookie verifier private static final int VERIFIER_COOKIE_MAX_AGE = 180; - public AuthorizationRedirect getAuthorizationUri(String providerName, Long userId) { + public AuthorizationRedirect getAuthorizationUri(String providerName, HttpServletRequest request, + Long userId) { OAuthProperties.Provider provider = resolveProvider(providerName); String codeVerifier = pkceUtil.generateCodeVerifier(); @@ -55,7 +56,7 @@ public AuthorizationRedirect getAuthorizationUri(String providerName, Long userI socialLinkTokenRepository.save(userId, state); } - String authorizeUri = oAuthApiClient.buildAuthorizeUri(provider, codeChallenge, state); + String authorizeUri = oAuthApiClient.buildAuthorizeUri(request, provider, codeChallenge, state); ResponseCookie verifierCookie = ResponseCookie.from(HttpConstants.OAUTH_VERIFIER_COOKIE, codeVerifier) .httpOnly(true) @@ -68,8 +69,9 @@ public AuthorizationRedirect getAuthorizationUri(String providerName, Long userI return new AuthorizationRedirect(authorizeUri, verifierCookie); } - public TokenPair socialLogin(String providerName, String code, String codeVerifier) { - OAuth2UserInfo userInfo = getOAuth2UserInfo(providerName, code, codeVerifier); + public TokenPair socialLogin(String providerName, String code, String codeVerifier, + HttpServletRequest request) { + OAuth2UserInfo userInfo = getOAuth2UserInfo(providerName, code, codeVerifier, request); OAuthLink oAuthLink = oAuthLinkRepository .findByProviderAndProviderIdWithUser(userInfo.getProvider(), userInfo.getProviderId()) @@ -80,13 +82,13 @@ public TokenPair socialLogin(String providerName, String code, String codeVerifi @Transactional public void linkSocialAccount(String providerName, String code, String state, - String codeVerifier) { + String codeVerifier, HttpServletRequest request) { Long userId = socialLinkTokenRepository.findUserIdByState(state) .orElseThrow(() -> new BizException(AuthErrorCode.INVALID_SOCIAL_LINK_TOKEN)); socialLinkTokenRepository.delete(state); - OAuth2UserInfo userInfo = getOAuth2UserInfo(providerName, code, codeVerifier); + OAuth2UserInfo userInfo = getOAuth2UserInfo(providerName, code, codeVerifier, request); if (oAuthLinkRepository.existsByUser_IdAndProviderAndProviderId( userId, userInfo.getProvider(), userInfo.getProviderId())) { @@ -105,9 +107,9 @@ public void linkSocialAccount(String providerName, String code, String state, } private OAuth2UserInfo getOAuth2UserInfo(String providerName, String code, - String codeVerifier) { + String codeVerifier, HttpServletRequest request) { OAuthProperties.Provider provider = resolveProvider(providerName); - String accessToken = oAuthApiClient.requestAccessToken(provider, code, codeVerifier); + String accessToken = oAuthApiClient.requestAccessToken(provider, code, codeVerifier, request); Map attributes = oAuthApiClient.requestUserInfo(provider, accessToken); return oAuthApiClient.createUserInfo(providerName, attributes); } diff --git a/src/main/java/flipnote/user/user/application/UserService.java b/src/main/java/flipnote/user/application/UserService.java similarity index 74% rename from src/main/java/flipnote/user/user/application/UserService.java rename to src/main/java/flipnote/user/application/UserService.java index 220bb07..5d50448 100644 --- a/src/main/java/flipnote/user/user/application/UserService.java +++ b/src/main/java/flipnote/user/application/UserService.java @@ -1,4 +1,7 @@ -package flipnote.user.user.application; +package flipnote.user.application; + +import java.util.List; +import java.util.Optional; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -9,17 +12,17 @@ import flipnote.image.grpc.v1.ChangeImageResponse; import flipnote.image.grpc.v1.ImageCommandServiceGrpc; import flipnote.image.grpc.v1.Type; -import flipnote.user.auth.infrastructure.jwt.JwtProvider; -import flipnote.user.auth.infrastructure.redis.SessionInvalidationRepository; -import flipnote.user.global.error.ImageErrorCode; -import flipnote.user.global.exception.BizException; -import flipnote.user.user.domain.User; -import flipnote.user.user.domain.UserErrorCode; -import flipnote.user.user.domain.UserRepository; -import flipnote.user.user.presentation.dto.request.UpdateProfileRequest; -import flipnote.user.user.presentation.dto.response.MyInfoResponse; -import flipnote.user.user.presentation.dto.response.UserInfoResponse; -import flipnote.user.user.presentation.dto.response.UserUpdateResponse; +import flipnote.user.domain.ImageErrorCode; +import flipnote.user.domain.entity.User; +import flipnote.user.domain.UserErrorCode; +import flipnote.user.domain.repository.UserRepository; +import flipnote.user.domain.common.BizException; +import flipnote.user.infrastructure.jwt.JwtProvider; +import flipnote.user.infrastructure.redis.SessionInvalidationRepository; +import flipnote.user.interfaces.http.dto.request.UpdateProfileRequest; +import flipnote.user.interfaces.http.dto.response.MyInfoResponse; +import flipnote.user.interfaces.http.dto.response.UserInfoResponse; +import flipnote.user.interfaces.http.dto.response.UserUpdateResponse; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -88,6 +91,14 @@ public void withdraw(Long userId) { sessionInvalidationRepository.invalidate(userId, jwtProvider.getRefreshTokenExpiration()); } + public Optional findActiveUserById(Long userId) { + return userRepository.findByIdAndStatus(userId, User.Status.ACTIVE); + } + + public List findActiveUsersByIds(List userIds) { + return userRepository.findByIdInAndStatus(userIds, User.Status.ACTIVE); + } + private User findActiveUser(Long userId) { return userRepository.findByIdAndStatus(userId, User.Status.ACTIVE) .orElseThrow(() -> new BizException(UserErrorCode.USER_NOT_FOUND)); diff --git a/src/main/java/flipnote/user/auth/domain/AuthErrorCode.java b/src/main/java/flipnote/user/domain/AuthErrorCode.java similarity index 96% rename from src/main/java/flipnote/user/auth/domain/AuthErrorCode.java rename to src/main/java/flipnote/user/domain/AuthErrorCode.java index 6ff29e5..b93c236 100644 --- a/src/main/java/flipnote/user/auth/domain/AuthErrorCode.java +++ b/src/main/java/flipnote/user/domain/AuthErrorCode.java @@ -1,9 +1,10 @@ -package flipnote.user.auth.domain; +package flipnote.user.domain; -import flipnote.user.global.error.ErrorCode; +import org.springframework.http.HttpStatus; + +import flipnote.user.domain.common.ErrorCode; import lombok.Getter; import lombok.RequiredArgsConstructor; -import org.springframework.http.HttpStatus; @Getter @RequiredArgsConstructor diff --git a/src/main/java/flipnote/user/global/error/ImageErrorCode.java b/src/main/java/flipnote/user/domain/ImageErrorCode.java similarity index 86% rename from src/main/java/flipnote/user/global/error/ImageErrorCode.java rename to src/main/java/flipnote/user/domain/ImageErrorCode.java index 16fc7b1..57670dd 100644 --- a/src/main/java/flipnote/user/global/error/ImageErrorCode.java +++ b/src/main/java/flipnote/user/domain/ImageErrorCode.java @@ -1,8 +1,10 @@ -package flipnote.user.global.error; +package flipnote.user.domain; +import org.springframework.http.HttpStatus; + +import flipnote.user.domain.common.ErrorCode; import lombok.Getter; import lombok.RequiredArgsConstructor; -import org.springframework.http.HttpStatus; @Getter @RequiredArgsConstructor diff --git a/src/main/java/flipnote/user/auth/domain/PasswordResetConstants.java b/src/main/java/flipnote/user/domain/PasswordResetConstants.java similarity index 85% rename from src/main/java/flipnote/user/auth/domain/PasswordResetConstants.java rename to src/main/java/flipnote/user/domain/PasswordResetConstants.java index 94878de..9767a83 100644 --- a/src/main/java/flipnote/user/auth/domain/PasswordResetConstants.java +++ b/src/main/java/flipnote/user/domain/PasswordResetConstants.java @@ -1,4 +1,4 @@ -package flipnote.user.auth.domain; +package flipnote.user.domain; import lombok.AccessLevel; import lombok.NoArgsConstructor; diff --git a/src/main/java/flipnote/user/auth/domain/TokenClaims.java b/src/main/java/flipnote/user/domain/TokenClaims.java similarity index 73% rename from src/main/java/flipnote/user/auth/domain/TokenClaims.java rename to src/main/java/flipnote/user/domain/TokenClaims.java index 52bc265..44a252a 100644 --- a/src/main/java/flipnote/user/auth/domain/TokenClaims.java +++ b/src/main/java/flipnote/user/domain/TokenClaims.java @@ -1,4 +1,4 @@ -package flipnote.user.auth.domain; +package flipnote.user.domain; public record TokenClaims( Long userId, diff --git a/src/main/java/flipnote/user/auth/domain/TokenPair.java b/src/main/java/flipnote/user/domain/TokenPair.java similarity index 66% rename from src/main/java/flipnote/user/auth/domain/TokenPair.java rename to src/main/java/flipnote/user/domain/TokenPair.java index 81cb9d4..48ec06a 100644 --- a/src/main/java/flipnote/user/auth/domain/TokenPair.java +++ b/src/main/java/flipnote/user/domain/TokenPair.java @@ -1,4 +1,4 @@ -package flipnote.user.auth.domain; +package flipnote.user.domain; public record TokenPair(String accessToken, String refreshToken) { } diff --git a/src/main/java/flipnote/user/user/domain/UserErrorCode.java b/src/main/java/flipnote/user/domain/UserErrorCode.java similarity index 85% rename from src/main/java/flipnote/user/user/domain/UserErrorCode.java rename to src/main/java/flipnote/user/domain/UserErrorCode.java index d98aa0c..dd4a612 100644 --- a/src/main/java/flipnote/user/user/domain/UserErrorCode.java +++ b/src/main/java/flipnote/user/domain/UserErrorCode.java @@ -1,9 +1,10 @@ -package flipnote.user.user.domain; +package flipnote.user.domain; -import flipnote.user.global.error.ErrorCode; +import org.springframework.http.HttpStatus; + +import flipnote.user.domain.common.ErrorCode; import lombok.Getter; import lombok.RequiredArgsConstructor; -import org.springframework.http.HttpStatus; @Getter @RequiredArgsConstructor diff --git a/src/main/java/flipnote/user/auth/domain/VerificationConstants.java b/src/main/java/flipnote/user/domain/VerificationConstants.java similarity index 85% rename from src/main/java/flipnote/user/auth/domain/VerificationConstants.java rename to src/main/java/flipnote/user/domain/VerificationConstants.java index d92bc97..31c09db 100644 --- a/src/main/java/flipnote/user/auth/domain/VerificationConstants.java +++ b/src/main/java/flipnote/user/domain/VerificationConstants.java @@ -1,4 +1,4 @@ -package flipnote.user.auth.domain; +package flipnote.user.domain; import lombok.AccessLevel; import lombok.NoArgsConstructor; diff --git a/src/main/java/flipnote/user/global/exception/BizException.java b/src/main/java/flipnote/user/domain/common/BizException.java similarity index 66% rename from src/main/java/flipnote/user/global/exception/BizException.java rename to src/main/java/flipnote/user/domain/common/BizException.java index f31adef..cfed271 100644 --- a/src/main/java/flipnote/user/global/exception/BizException.java +++ b/src/main/java/flipnote/user/domain/common/BizException.java @@ -1,6 +1,6 @@ -package flipnote.user.global.exception; +package flipnote.user.domain.common; -import flipnote.user.global.error.ErrorCode; +import flipnote.user.domain.common.ErrorCode; import lombok.AllArgsConstructor; import lombok.Getter; diff --git a/src/main/java/flipnote/user/global/exception/EmailSendException.java b/src/main/java/flipnote/user/domain/common/EmailSendException.java similarity index 77% rename from src/main/java/flipnote/user/global/exception/EmailSendException.java rename to src/main/java/flipnote/user/domain/common/EmailSendException.java index e8a11b5..dfe342f 100644 --- a/src/main/java/flipnote/user/global/exception/EmailSendException.java +++ b/src/main/java/flipnote/user/domain/common/EmailSendException.java @@ -1,4 +1,4 @@ -package flipnote.user.global.exception; +package flipnote.user.domain.common; public class EmailSendException extends RuntimeException { diff --git a/src/main/java/flipnote/user/global/error/ErrorCode.java b/src/main/java/flipnote/user/domain/common/ErrorCode.java similarity index 73% rename from src/main/java/flipnote/user/global/error/ErrorCode.java rename to src/main/java/flipnote/user/domain/common/ErrorCode.java index d043924..a12fbc6 100644 --- a/src/main/java/flipnote/user/global/error/ErrorCode.java +++ b/src/main/java/flipnote/user/domain/common/ErrorCode.java @@ -1,4 +1,4 @@ -package flipnote.user.global.error; +package flipnote.user.domain.common; public interface ErrorCode { diff --git a/src/main/java/flipnote/user/global/entity/BaseEntity.java b/src/main/java/flipnote/user/domain/entity/BaseEntity.java similarity index 94% rename from src/main/java/flipnote/user/global/entity/BaseEntity.java rename to src/main/java/flipnote/user/domain/entity/BaseEntity.java index 61b9181..1c1ca7e 100644 --- a/src/main/java/flipnote/user/global/entity/BaseEntity.java +++ b/src/main/java/flipnote/user/domain/entity/BaseEntity.java @@ -1,4 +1,4 @@ -package flipnote.user.global.entity; +package flipnote.user.domain.entity; import jakarta.persistence.Column; import jakarta.persistence.EntityListeners; diff --git a/src/main/java/flipnote/user/user/domain/OAuthLink.java b/src/main/java/flipnote/user/domain/entity/OAuthLink.java similarity index 96% rename from src/main/java/flipnote/user/user/domain/OAuthLink.java rename to src/main/java/flipnote/user/domain/entity/OAuthLink.java index 893b542..07abe1c 100644 --- a/src/main/java/flipnote/user/user/domain/OAuthLink.java +++ b/src/main/java/flipnote/user/domain/entity/OAuthLink.java @@ -1,4 +1,4 @@ -package flipnote.user.user.domain; +package flipnote.user.domain.entity; import jakarta.persistence.*; import lombok.AccessLevel; diff --git a/src/main/java/flipnote/user/user/domain/User.java b/src/main/java/flipnote/user/domain/entity/User.java similarity index 96% rename from src/main/java/flipnote/user/user/domain/User.java rename to src/main/java/flipnote/user/domain/entity/User.java index d09f98e..01546d7 100644 --- a/src/main/java/flipnote/user/user/domain/User.java +++ b/src/main/java/flipnote/user/domain/entity/User.java @@ -1,6 +1,5 @@ -package flipnote.user.user.domain; +package flipnote.user.domain.entity; -import flipnote.user.global.entity.BaseEntity; import jakarta.persistence.*; import lombok.AccessLevel; import lombok.Builder; diff --git a/src/main/java/flipnote/user/auth/domain/event/EmailVerificationSendEvent.java b/src/main/java/flipnote/user/domain/event/EmailVerificationSendEvent.java similarity index 68% rename from src/main/java/flipnote/user/auth/domain/event/EmailVerificationSendEvent.java rename to src/main/java/flipnote/user/domain/event/EmailVerificationSendEvent.java index 0373988..399867a 100644 --- a/src/main/java/flipnote/user/auth/domain/event/EmailVerificationSendEvent.java +++ b/src/main/java/flipnote/user/domain/event/EmailVerificationSendEvent.java @@ -1,4 +1,4 @@ -package flipnote.user.auth.domain.event; +package flipnote.user.domain.event; public record EmailVerificationSendEvent( String to, diff --git a/src/main/java/flipnote/user/auth/domain/event/PasswordResetCreateEvent.java b/src/main/java/flipnote/user/domain/event/PasswordResetCreateEvent.java similarity index 67% rename from src/main/java/flipnote/user/auth/domain/event/PasswordResetCreateEvent.java rename to src/main/java/flipnote/user/domain/event/PasswordResetCreateEvent.java index b1c6daf..d0c415a 100644 --- a/src/main/java/flipnote/user/auth/domain/event/PasswordResetCreateEvent.java +++ b/src/main/java/flipnote/user/domain/event/PasswordResetCreateEvent.java @@ -1,4 +1,4 @@ -package flipnote.user.auth.domain.event; +package flipnote.user.domain.event; public record PasswordResetCreateEvent( String to, diff --git a/src/main/java/flipnote/user/user/domain/OAuthLinkRepository.java b/src/main/java/flipnote/user/domain/repository/OAuthLinkRepository.java similarity index 90% rename from src/main/java/flipnote/user/user/domain/OAuthLinkRepository.java rename to src/main/java/flipnote/user/domain/repository/OAuthLinkRepository.java index fbc55c8..62ffd6a 100644 --- a/src/main/java/flipnote/user/user/domain/OAuthLinkRepository.java +++ b/src/main/java/flipnote/user/domain/repository/OAuthLinkRepository.java @@ -1,4 +1,4 @@ -package flipnote.user.user.domain; +package flipnote.user.domain.repository; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; @@ -7,6 +7,8 @@ import java.util.List; import java.util.Optional; +import flipnote.user.domain.entity.OAuthLink; + public interface OAuthLinkRepository extends JpaRepository { @Query(""" diff --git a/src/main/java/flipnote/user/user/domain/UserRepository.java b/src/main/java/flipnote/user/domain/repository/UserRepository.java similarity index 85% rename from src/main/java/flipnote/user/user/domain/UserRepository.java rename to src/main/java/flipnote/user/domain/repository/UserRepository.java index e59c10d..384e675 100644 --- a/src/main/java/flipnote/user/user/domain/UserRepository.java +++ b/src/main/java/flipnote/user/domain/repository/UserRepository.java @@ -1,10 +1,12 @@ -package flipnote.user.user.domain; +package flipnote.user.domain.repository; import org.springframework.data.jpa.repository.JpaRepository; import java.util.List; import java.util.Optional; +import flipnote.user.domain.entity.User; + public interface UserRepository extends JpaRepository { Optional findByEmail(String email); diff --git a/src/main/java/flipnote/user/global/config/AppConfig.java b/src/main/java/flipnote/user/infrastructure/config/AppConfig.java similarity index 95% rename from src/main/java/flipnote/user/global/config/AppConfig.java rename to src/main/java/flipnote/user/infrastructure/config/AppConfig.java index c8b5cfe..90b7f0d 100644 --- a/src/main/java/flipnote/user/global/config/AppConfig.java +++ b/src/main/java/flipnote/user/infrastructure/config/AppConfig.java @@ -1,4 +1,4 @@ -package flipnote.user.global.config; +package flipnote.user.infrastructure.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; diff --git a/src/main/java/flipnote/user/global/config/ClientProperties.java b/src/main/java/flipnote/user/infrastructure/config/ClientProperties.java similarity index 93% rename from src/main/java/flipnote/user/global/config/ClientProperties.java rename to src/main/java/flipnote/user/infrastructure/config/ClientProperties.java index 5334472..3edf7d5 100644 --- a/src/main/java/flipnote/user/global/config/ClientProperties.java +++ b/src/main/java/flipnote/user/infrastructure/config/ClientProperties.java @@ -1,4 +1,4 @@ -package flipnote.user.global.config; +package flipnote.user.infrastructure.config; import lombok.Getter; import lombok.RequiredArgsConstructor; diff --git a/src/main/java/flipnote/user/global/config/GrpcClientConfig.java b/src/main/java/flipnote/user/infrastructure/config/GrpcClientConfig.java similarity index 92% rename from src/main/java/flipnote/user/global/config/GrpcClientConfig.java rename to src/main/java/flipnote/user/infrastructure/config/GrpcClientConfig.java index 2b5eed3..c7bc08d 100644 --- a/src/main/java/flipnote/user/global/config/GrpcClientConfig.java +++ b/src/main/java/flipnote/user/infrastructure/config/GrpcClientConfig.java @@ -1,4 +1,4 @@ -package flipnote.user.global.config; +package flipnote.user.infrastructure.config; import flipnote.image.grpc.v1.ImageCommandServiceGrpc; import org.springframework.context.annotation.Bean; diff --git a/src/main/java/flipnote/user/global/config/JpaAuditingConfig.java b/src/main/java/flipnote/user/infrastructure/config/JpaAuditingConfig.java similarity index 82% rename from src/main/java/flipnote/user/global/config/JpaAuditingConfig.java rename to src/main/java/flipnote/user/infrastructure/config/JpaAuditingConfig.java index 6e3060c..d55f976 100644 --- a/src/main/java/flipnote/user/global/config/JpaAuditingConfig.java +++ b/src/main/java/flipnote/user/infrastructure/config/JpaAuditingConfig.java @@ -1,4 +1,4 @@ -package flipnote.user.global.config; +package flipnote.user.infrastructure.config; import org.springframework.context.annotation.Configuration; import org.springframework.data.jpa.repository.config.EnableJpaAuditing; diff --git a/src/main/java/flipnote/user/global/config/SwaggerConfig.java b/src/main/java/flipnote/user/infrastructure/config/SwaggerConfig.java similarity index 92% rename from src/main/java/flipnote/user/global/config/SwaggerConfig.java rename to src/main/java/flipnote/user/infrastructure/config/SwaggerConfig.java index 186cc42..4bf33fe 100644 --- a/src/main/java/flipnote/user/global/config/SwaggerConfig.java +++ b/src/main/java/flipnote/user/infrastructure/config/SwaggerConfig.java @@ -1,6 +1,6 @@ -package flipnote.user.global.config; +package flipnote.user.infrastructure.config; -import flipnote.user.global.constants.HttpConstants; +import flipnote.user.interfaces.http.common.HttpConstants; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.info.Info; import io.swagger.v3.oas.models.servers.Server; diff --git a/src/main/java/flipnote/user/global/config/JwtProperties.java b/src/main/java/flipnote/user/infrastructure/jwt/JwtProperties.java similarity index 89% rename from src/main/java/flipnote/user/global/config/JwtProperties.java rename to src/main/java/flipnote/user/infrastructure/jwt/JwtProperties.java index 6feaa72..a7d6f34 100644 --- a/src/main/java/flipnote/user/global/config/JwtProperties.java +++ b/src/main/java/flipnote/user/infrastructure/jwt/JwtProperties.java @@ -1,4 +1,4 @@ -package flipnote.user.global.config; +package flipnote.user.infrastructure.jwt; import lombok.Getter; import lombok.RequiredArgsConstructor; diff --git a/src/main/java/flipnote/user/auth/infrastructure/jwt/JwtProvider.java b/src/main/java/flipnote/user/infrastructure/jwt/JwtProvider.java similarity index 93% rename from src/main/java/flipnote/user/auth/infrastructure/jwt/JwtProvider.java rename to src/main/java/flipnote/user/infrastructure/jwt/JwtProvider.java index 9cd7a6e..276ca0e 100644 --- a/src/main/java/flipnote/user/auth/infrastructure/jwt/JwtProvider.java +++ b/src/main/java/flipnote/user/infrastructure/jwt/JwtProvider.java @@ -1,9 +1,9 @@ -package flipnote.user.auth.infrastructure.jwt; +package flipnote.user.infrastructure.jwt; -import flipnote.user.auth.domain.TokenClaims; -import flipnote.user.auth.domain.TokenPair; -import flipnote.user.user.domain.User; -import flipnote.user.global.config.JwtProperties; +import flipnote.user.domain.TokenClaims; +import flipnote.user.domain.TokenPair; +import flipnote.user.domain.entity.User; +import flipnote.user.infrastructure.jwt.JwtProperties; import io.jsonwebtoken.Claims; import io.jsonwebtoken.ExpiredJwtException; import io.jsonwebtoken.JwtException; diff --git a/src/main/java/flipnote/user/auth/infrastructure/listener/EmailVerificationEventListener.java b/src/main/java/flipnote/user/infrastructure/listener/EmailVerificationEventListener.java similarity index 70% rename from src/main/java/flipnote/user/auth/infrastructure/listener/EmailVerificationEventListener.java rename to src/main/java/flipnote/user/infrastructure/listener/EmailVerificationEventListener.java index d16fdd6..4dcbefe 100644 --- a/src/main/java/flipnote/user/auth/infrastructure/listener/EmailVerificationEventListener.java +++ b/src/main/java/flipnote/user/infrastructure/listener/EmailVerificationEventListener.java @@ -1,14 +1,14 @@ -package flipnote.user.auth.infrastructure.listener; +package flipnote.user.infrastructure.listener; import org.springframework.context.event.EventListener; import org.springframework.resilience.annotation.Retryable; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; -import flipnote.user.auth.domain.VerificationConstants; -import flipnote.user.auth.domain.event.EmailVerificationSendEvent; -import flipnote.user.auth.infrastructure.mail.MailService; -import flipnote.user.global.exception.EmailSendException; +import flipnote.user.domain.VerificationConstants; +import flipnote.user.domain.common.EmailSendException; +import flipnote.user.domain.event.EmailVerificationSendEvent; +import flipnote.user.infrastructure.mail.MailService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; diff --git a/src/main/java/flipnote/user/auth/infrastructure/listener/PasswordResetEventListener.java b/src/main/java/flipnote/user/infrastructure/listener/PasswordResetEventListener.java similarity index 70% rename from src/main/java/flipnote/user/auth/infrastructure/listener/PasswordResetEventListener.java rename to src/main/java/flipnote/user/infrastructure/listener/PasswordResetEventListener.java index 2518e79..4257c89 100644 --- a/src/main/java/flipnote/user/auth/infrastructure/listener/PasswordResetEventListener.java +++ b/src/main/java/flipnote/user/infrastructure/listener/PasswordResetEventListener.java @@ -1,14 +1,14 @@ -package flipnote.user.auth.infrastructure.listener; +package flipnote.user.infrastructure.listener; import org.springframework.context.event.EventListener; import org.springframework.resilience.annotation.Retryable; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; -import flipnote.user.auth.domain.PasswordResetConstants; -import flipnote.user.auth.domain.event.PasswordResetCreateEvent; -import flipnote.user.auth.infrastructure.mail.MailService; -import flipnote.user.global.exception.EmailSendException; +import flipnote.user.domain.PasswordResetConstants; +import flipnote.user.domain.common.EmailSendException; +import flipnote.user.domain.event.PasswordResetCreateEvent; +import flipnote.user.infrastructure.mail.MailService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; diff --git a/src/main/java/flipnote/user/auth/infrastructure/mail/MailService.java b/src/main/java/flipnote/user/infrastructure/mail/MailService.java similarity index 77% rename from src/main/java/flipnote/user/auth/infrastructure/mail/MailService.java rename to src/main/java/flipnote/user/infrastructure/mail/MailService.java index da8c47c..15df452 100644 --- a/src/main/java/flipnote/user/auth/infrastructure/mail/MailService.java +++ b/src/main/java/flipnote/user/infrastructure/mail/MailService.java @@ -1,4 +1,4 @@ -package flipnote.user.auth.infrastructure.mail; +package flipnote.user.infrastructure.mail; public interface MailService { diff --git a/src/main/java/flipnote/user/global/config/ResendConfig.java b/src/main/java/flipnote/user/infrastructure/mail/ResendConfig.java similarity index 90% rename from src/main/java/flipnote/user/global/config/ResendConfig.java rename to src/main/java/flipnote/user/infrastructure/mail/ResendConfig.java index ed0b74e..c52409f 100644 --- a/src/main/java/flipnote/user/global/config/ResendConfig.java +++ b/src/main/java/flipnote/user/infrastructure/mail/ResendConfig.java @@ -1,4 +1,4 @@ -package flipnote.user.global.config; +package flipnote.user.infrastructure.mail; import com.resend.Resend; import lombok.RequiredArgsConstructor; diff --git a/src/main/java/flipnote/user/auth/infrastructure/mail/ResendMailService.java b/src/main/java/flipnote/user/infrastructure/mail/ResendMailService.java similarity index 93% rename from src/main/java/flipnote/user/auth/infrastructure/mail/ResendMailService.java rename to src/main/java/flipnote/user/infrastructure/mail/ResendMailService.java index 4e57af1..4d44bc6 100644 --- a/src/main/java/flipnote/user/auth/infrastructure/mail/ResendMailService.java +++ b/src/main/java/flipnote/user/infrastructure/mail/ResendMailService.java @@ -1,10 +1,10 @@ -package flipnote.user.auth.infrastructure.mail; +package flipnote.user.infrastructure.mail; import com.resend.Resend; import com.resend.core.exception.ResendException; import com.resend.services.emails.model.CreateEmailOptions; -import flipnote.user.global.config.ResendProperties; -import flipnote.user.global.exception.EmailSendException; +import flipnote.user.domain.common.EmailSendException; +import flipnote.user.infrastructure.mail.ResendProperties; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; diff --git a/src/main/java/flipnote/user/global/config/ResendProperties.java b/src/main/java/flipnote/user/infrastructure/mail/ResendProperties.java similarity index 91% rename from src/main/java/flipnote/user/global/config/ResendProperties.java rename to src/main/java/flipnote/user/infrastructure/mail/ResendProperties.java index b1f28c6..7ab8b09 100644 --- a/src/main/java/flipnote/user/global/config/ResendProperties.java +++ b/src/main/java/flipnote/user/infrastructure/mail/ResendProperties.java @@ -1,4 +1,4 @@ -package flipnote.user.global.config; +package flipnote.user.infrastructure.mail; import jakarta.validation.constraints.NotEmpty; import lombok.Getter; diff --git a/src/main/java/flipnote/user/auth/infrastructure/oauth/GoogleUserInfo.java b/src/main/java/flipnote/user/infrastructure/oauth/GoogleUserInfo.java similarity index 92% rename from src/main/java/flipnote/user/auth/infrastructure/oauth/GoogleUserInfo.java rename to src/main/java/flipnote/user/infrastructure/oauth/GoogleUserInfo.java index b9e5b01..a1e282e 100644 --- a/src/main/java/flipnote/user/auth/infrastructure/oauth/GoogleUserInfo.java +++ b/src/main/java/flipnote/user/infrastructure/oauth/GoogleUserInfo.java @@ -1,4 +1,4 @@ -package flipnote.user.auth.infrastructure.oauth; +package flipnote.user.infrastructure.oauth; import java.util.Map; diff --git a/src/main/java/flipnote/user/auth/infrastructure/oauth/OAuth2UserInfo.java b/src/main/java/flipnote/user/infrastructure/oauth/OAuth2UserInfo.java similarity index 74% rename from src/main/java/flipnote/user/auth/infrastructure/oauth/OAuth2UserInfo.java rename to src/main/java/flipnote/user/infrastructure/oauth/OAuth2UserInfo.java index 5a394a5..339581e 100644 --- a/src/main/java/flipnote/user/auth/infrastructure/oauth/OAuth2UserInfo.java +++ b/src/main/java/flipnote/user/infrastructure/oauth/OAuth2UserInfo.java @@ -1,4 +1,4 @@ -package flipnote.user.auth.infrastructure.oauth; +package flipnote.user.infrastructure.oauth; public interface OAuth2UserInfo { diff --git a/src/main/java/flipnote/user/auth/infrastructure/oauth/OAuthApiClient.java b/src/main/java/flipnote/user/infrastructure/oauth/OAuthApiClient.java similarity index 80% rename from src/main/java/flipnote/user/auth/infrastructure/oauth/OAuthApiClient.java rename to src/main/java/flipnote/user/infrastructure/oauth/OAuthApiClient.java index 4417b43..cc8d7e0 100644 --- a/src/main/java/flipnote/user/auth/infrastructure/oauth/OAuthApiClient.java +++ b/src/main/java/flipnote/user/infrastructure/oauth/OAuthApiClient.java @@ -1,4 +1,4 @@ -package flipnote.user.auth.infrastructure.oauth; +package flipnote.user.infrastructure.oauth; import java.util.Map; @@ -8,10 +8,11 @@ import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.client.RestClient; +import org.springframework.web.servlet.support.ServletUriComponentsBuilder; import org.springframework.web.util.UriComponentsBuilder; -import flipnote.user.global.config.OAuthProperties; - +import flipnote.user.infrastructure.oauth.OAuthProperties; +import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import tools.jackson.core.type.TypeReference; import tools.jackson.databind.ObjectMapper; @@ -22,15 +23,14 @@ public class OAuthApiClient { private final RestClient restClient; private final ObjectMapper objectMapper; - private final OAuthProperties oAuthProperties; public String requestAccessToken(OAuthProperties.Provider provider, String code, - String codeVerifier) { + String codeVerifier, HttpServletRequest request) { MultiValueMap params = new LinkedMultiValueMap<>(); params.add("grant_type", "authorization_code"); params.add("client_id", provider.getClientId()); params.add("client_secret", provider.getClientSecret()); - params.add("redirect_uri", buildRedirectUri(provider.getRedirectUri())); + params.add("redirect_uri", buildRedirectUri(request, provider.getRedirectUri())); params.add("code", code); params.add("code_verifier", codeVerifier); @@ -70,11 +70,11 @@ public OAuth2UserInfo createUserInfo(String providerName, Map at }; } - public String buildAuthorizeUri(OAuthProperties.Provider provider, + public String buildAuthorizeUri(HttpServletRequest request, OAuthProperties.Provider provider, String codeChallenge, String state) { UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(provider.getAuthorizationUri()) .queryParam("client_id", provider.getClientId()) - .queryParam("redirect_uri", buildRedirectUri(provider.getRedirectUri())) + .queryParam("redirect_uri", buildRedirectUri(request, provider.getRedirectUri())) .queryParam("response_type", "code") .queryParam("scope", String.join(" ", provider.getScope())) .queryParam("code_challenge", codeChallenge) @@ -87,9 +87,9 @@ public String buildAuthorizeUri(OAuthProperties.Provider provider, return builder.toUriString(); } - private String buildRedirectUri(String path) { - return UriComponentsBuilder.fromUriString(oAuthProperties.getBaseUrl()) - .path(path) + private String buildRedirectUri(HttpServletRequest request, String path) { + return ServletUriComponentsBuilder.fromRequestUri(request) + .replacePath(path) .build() .toUriString(); } diff --git a/src/main/java/flipnote/user/global/config/OAuthProperties.java b/src/main/java/flipnote/user/infrastructure/oauth/OAuthProperties.java similarity index 90% rename from src/main/java/flipnote/user/global/config/OAuthProperties.java rename to src/main/java/flipnote/user/infrastructure/oauth/OAuthProperties.java index 8024ce6..bde860d 100644 --- a/src/main/java/flipnote/user/global/config/OAuthProperties.java +++ b/src/main/java/flipnote/user/infrastructure/oauth/OAuthProperties.java @@ -1,4 +1,4 @@ -package flipnote.user.global.config; +package flipnote.user.infrastructure.oauth; import lombok.Getter; import lombok.RequiredArgsConstructor; @@ -13,7 +13,6 @@ @ConfigurationProperties(prefix = "app.oauth2") public class OAuthProperties { - private final String baseUrl; private final Map providers; @Getter diff --git a/src/main/java/flipnote/user/auth/infrastructure/oauth/PkceUtil.java b/src/main/java/flipnote/user/infrastructure/oauth/PkceUtil.java similarity index 95% rename from src/main/java/flipnote/user/auth/infrastructure/oauth/PkceUtil.java rename to src/main/java/flipnote/user/infrastructure/oauth/PkceUtil.java index 544266c..cf4fe6e 100644 --- a/src/main/java/flipnote/user/auth/infrastructure/oauth/PkceUtil.java +++ b/src/main/java/flipnote/user/infrastructure/oauth/PkceUtil.java @@ -1,4 +1,4 @@ -package flipnote.user.auth.infrastructure.oauth; +package flipnote.user.infrastructure.oauth; import org.springframework.stereotype.Component; diff --git a/src/main/java/flipnote/user/auth/infrastructure/redis/EmailVerificationRepository.java b/src/main/java/flipnote/user/infrastructure/redis/EmailVerificationRepository.java similarity index 97% rename from src/main/java/flipnote/user/auth/infrastructure/redis/EmailVerificationRepository.java rename to src/main/java/flipnote/user/infrastructure/redis/EmailVerificationRepository.java index 6218947..656bc7f 100644 --- a/src/main/java/flipnote/user/auth/infrastructure/redis/EmailVerificationRepository.java +++ b/src/main/java/flipnote/user/infrastructure/redis/EmailVerificationRepository.java @@ -1,4 +1,4 @@ -package flipnote.user.auth.infrastructure.redis; +package flipnote.user.infrastructure.redis; import lombok.RequiredArgsConstructor; import org.springframework.data.redis.core.StringRedisTemplate; diff --git a/src/main/java/flipnote/user/auth/infrastructure/redis/PasswordResetRepository.java b/src/main/java/flipnote/user/infrastructure/redis/PasswordResetRepository.java similarity index 96% rename from src/main/java/flipnote/user/auth/infrastructure/redis/PasswordResetRepository.java rename to src/main/java/flipnote/user/infrastructure/redis/PasswordResetRepository.java index c821d5d..547b880 100644 --- a/src/main/java/flipnote/user/auth/infrastructure/redis/PasswordResetRepository.java +++ b/src/main/java/flipnote/user/infrastructure/redis/PasswordResetRepository.java @@ -1,4 +1,4 @@ -package flipnote.user.auth.infrastructure.redis; +package flipnote.user.infrastructure.redis; import lombok.RequiredArgsConstructor; import org.springframework.data.redis.core.StringRedisTemplate; diff --git a/src/main/java/flipnote/user/auth/infrastructure/redis/PasswordResetTokenGenerator.java b/src/main/java/flipnote/user/infrastructure/redis/PasswordResetTokenGenerator.java similarity index 81% rename from src/main/java/flipnote/user/auth/infrastructure/redis/PasswordResetTokenGenerator.java rename to src/main/java/flipnote/user/infrastructure/redis/PasswordResetTokenGenerator.java index 1e8797f..8d578d8 100644 --- a/src/main/java/flipnote/user/auth/infrastructure/redis/PasswordResetTokenGenerator.java +++ b/src/main/java/flipnote/user/infrastructure/redis/PasswordResetTokenGenerator.java @@ -1,4 +1,4 @@ -package flipnote.user.auth.infrastructure.redis; +package flipnote.user.infrastructure.redis; import org.springframework.stereotype.Component; diff --git a/src/main/java/flipnote/user/auth/infrastructure/redis/SessionInvalidationRepository.java b/src/main/java/flipnote/user/infrastructure/redis/SessionInvalidationRepository.java similarity index 95% rename from src/main/java/flipnote/user/auth/infrastructure/redis/SessionInvalidationRepository.java rename to src/main/java/flipnote/user/infrastructure/redis/SessionInvalidationRepository.java index e494496..887147e 100644 --- a/src/main/java/flipnote/user/auth/infrastructure/redis/SessionInvalidationRepository.java +++ b/src/main/java/flipnote/user/infrastructure/redis/SessionInvalidationRepository.java @@ -1,4 +1,4 @@ -package flipnote.user.auth.infrastructure.redis; +package flipnote.user.infrastructure.redis; import lombok.RequiredArgsConstructor; import org.springframework.data.redis.core.StringRedisTemplate; diff --git a/src/main/java/flipnote/user/auth/infrastructure/redis/SocialLinkTokenRepository.java b/src/main/java/flipnote/user/infrastructure/redis/SocialLinkTokenRepository.java similarity index 95% rename from src/main/java/flipnote/user/auth/infrastructure/redis/SocialLinkTokenRepository.java rename to src/main/java/flipnote/user/infrastructure/redis/SocialLinkTokenRepository.java index 1c4222b..4fb47cd 100644 --- a/src/main/java/flipnote/user/auth/infrastructure/redis/SocialLinkTokenRepository.java +++ b/src/main/java/flipnote/user/infrastructure/redis/SocialLinkTokenRepository.java @@ -1,4 +1,4 @@ -package flipnote.user.auth.infrastructure.redis; +package flipnote.user.infrastructure.redis; import lombok.RequiredArgsConstructor; import org.springframework.data.redis.core.StringRedisTemplate; diff --git a/src/main/java/flipnote/user/auth/infrastructure/redis/TokenBlacklistRepository.java b/src/main/java/flipnote/user/infrastructure/redis/TokenBlacklistRepository.java similarity index 94% rename from src/main/java/flipnote/user/auth/infrastructure/redis/TokenBlacklistRepository.java rename to src/main/java/flipnote/user/infrastructure/redis/TokenBlacklistRepository.java index 9a1d899..210f8ab 100644 --- a/src/main/java/flipnote/user/auth/infrastructure/redis/TokenBlacklistRepository.java +++ b/src/main/java/flipnote/user/infrastructure/redis/TokenBlacklistRepository.java @@ -1,4 +1,4 @@ -package flipnote.user.auth.infrastructure.redis; +package flipnote.user.infrastructure.redis; import lombok.RequiredArgsConstructor; import org.springframework.data.redis.core.StringRedisTemplate; diff --git a/src/main/java/flipnote/user/auth/infrastructure/redis/VerificationCodeGenerator.java b/src/main/java/flipnote/user/infrastructure/redis/VerificationCodeGenerator.java similarity index 87% rename from src/main/java/flipnote/user/auth/infrastructure/redis/VerificationCodeGenerator.java rename to src/main/java/flipnote/user/infrastructure/redis/VerificationCodeGenerator.java index 301156d..20b71d3 100644 --- a/src/main/java/flipnote/user/auth/infrastructure/redis/VerificationCodeGenerator.java +++ b/src/main/java/flipnote/user/infrastructure/redis/VerificationCodeGenerator.java @@ -1,4 +1,4 @@ -package flipnote.user.auth.infrastructure.redis; +package flipnote.user.infrastructure.redis; import org.springframework.stereotype.Component; diff --git a/src/main/java/flipnote/user/interfaces/grpc/GrpcExceptionHandlerImpl.java b/src/main/java/flipnote/user/interfaces/grpc/GrpcExceptionHandlerImpl.java new file mode 100644 index 0000000..073d90b --- /dev/null +++ b/src/main/java/flipnote/user/interfaces/grpc/GrpcExceptionHandlerImpl.java @@ -0,0 +1,46 @@ +package flipnote.user.interfaces.grpc; + +import flipnote.user.domain.common.BizException; +import flipnote.user.domain.common.ErrorCode; +import io.grpc.Status; +import io.grpc.StatusException; +import io.grpc.StatusRuntimeException; +import lombok.extern.slf4j.Slf4j; +import org.springframework.grpc.server.exception.GrpcExceptionHandler; +import org.springframework.stereotype.Component; + +@Slf4j +@Component +public class GrpcExceptionHandlerImpl implements GrpcExceptionHandler { + + @Override + public StatusException handleException(Throwable t) { + if (t instanceof BizException e) { + ErrorCode errorCode = e.getErrorCode(); + log.warn("gRPC BizException: code={}, status={}, message={}", + errorCode.getCode(), errorCode.getStatus(), errorCode.getMessage()); + return toGrpcStatus(errorCode) + .withDescription(errorCode.getMessage()) + .asException(); + } + if (t instanceof StatusRuntimeException e) { + log.warn("gRPC StatusRuntimeException: status={}, description={}", + e.getStatus().getCode(), e.getStatus().getDescription()); + return e.getStatus().asException(); + } + log.error("gRPC Unhandled exception", t); + return Status.INTERNAL.withDescription("Internal server error").asException(); + } + + private Status toGrpcStatus(ErrorCode errorCode) { + return switch (errorCode.getStatus()) { + case 400 -> Status.INVALID_ARGUMENT; + case 401 -> Status.UNAUTHENTICATED; + case 403 -> Status.PERMISSION_DENIED; + case 404 -> Status.NOT_FOUND; + case 409 -> Status.ALREADY_EXISTS; + case 429 -> Status.RESOURCE_EXHAUSTED; + default -> Status.INTERNAL; + }; + } +} diff --git a/src/main/java/flipnote/user/interfaces/grpc/GrpcUserQueryService.java b/src/main/java/flipnote/user/interfaces/grpc/GrpcUserQueryService.java new file mode 100644 index 0000000..2baa39b --- /dev/null +++ b/src/main/java/flipnote/user/interfaces/grpc/GrpcUserQueryService.java @@ -0,0 +1,55 @@ +package flipnote.user.interfaces.grpc; + +import flipnote.user.application.UserService; +import flipnote.user.domain.entity.User; +import flipnote.user.grpc.GetUserRequest; +import flipnote.user.grpc.GetUserResponse; +import flipnote.user.grpc.GetUsersRequest; +import flipnote.user.grpc.GetUsersResponse; +import flipnote.user.grpc.UserQueryServiceGrpc; +import io.grpc.Status; +import io.grpc.stub.StreamObserver; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +@RequiredArgsConstructor +public class GrpcUserQueryService extends UserQueryServiceGrpc.UserQueryServiceImplBase { + + private final UserService userService; + + @Override + public void getUser(GetUserRequest request, StreamObserver responseObserver) { + User user = userService.findActiveUserById(request.getUserId()) + .orElseThrow(() -> Status.NOT_FOUND + .withDescription("μ‚¬μš©μžλ₯Ό 찾을 수 μ—†μŠ΅λ‹ˆλ‹€.") + .asRuntimeException()); + + responseObserver.onNext(toResponse(user)); + responseObserver.onCompleted(); + } + + @Override + public void getUsers(GetUsersRequest request, StreamObserver responseObserver) { + List userIds = request.getUserIdsList(); + List users = userService.findActiveUsersByIds(userIds); + + GetUsersResponse response = GetUsersResponse.newBuilder() + .addAllUsers(users.stream().map(this::toResponse).toList()) + .build(); + + responseObserver.onNext(response); + responseObserver.onCompleted(); + } + + private GetUserResponse toResponse(User user) { + return GetUserResponse.newBuilder() + .setId(user.getId()) + .setEmail(user.getEmail()) + .setNickname(user.getNickname()) + .setProfileImageUrl(user.getProfileImageUrl() != null ? user.getProfileImageUrl() : "") + .build(); + } +} diff --git a/src/main/java/flipnote/user/auth/presentation/AuthController.java b/src/main/java/flipnote/user/interfaces/http/AuthController.java similarity index 82% rename from src/main/java/flipnote/user/auth/presentation/AuthController.java rename to src/main/java/flipnote/user/interfaces/http/AuthController.java index 060f8d6..62ff975 100644 --- a/src/main/java/flipnote/user/auth/presentation/AuthController.java +++ b/src/main/java/flipnote/user/interfaces/http/AuthController.java @@ -1,21 +1,21 @@ -package flipnote.user.auth.presentation; - -import flipnote.user.auth.application.AuthService; -import flipnote.user.auth.infrastructure.jwt.JwtProvider; -import flipnote.user.auth.domain.TokenPair; -import flipnote.user.auth.presentation.dto.request.ChangePasswordRequest; -import flipnote.user.auth.presentation.dto.request.EmailVerificationRequest; -import flipnote.user.auth.presentation.dto.request.EmailVerifyRequest; -import flipnote.user.auth.presentation.dto.request.LoginRequest; -import flipnote.user.auth.presentation.dto.request.PasswordResetCreateRequest; -import flipnote.user.auth.presentation.dto.request.PasswordResetRequest; -import flipnote.user.auth.presentation.dto.request.SignupRequest; -import flipnote.user.auth.presentation.dto.request.TokenValidateRequest; -import flipnote.user.auth.presentation.dto.response.SocialLinksResponse; -import flipnote.user.auth.presentation.dto.response.TokenValidateResponse; -import flipnote.user.auth.presentation.dto.response.UserResponse; -import flipnote.user.global.constants.HttpConstants; -import flipnote.user.global.util.CookieUtil; +package flipnote.user.interfaces; + +import flipnote.user.application.AuthService; +import flipnote.user.domain.TokenPair; +import flipnote.user.infrastructure.jwt.JwtProvider; +import flipnote.user.interfaces.http.common.CookieUtil; +import flipnote.user.interfaces.http.common.HttpConstants; +import flipnote.user.interfaces.http.dto.request.ChangePasswordRequest; +import flipnote.user.interfaces.http.dto.request.EmailVerificationRequest; +import flipnote.user.interfaces.http.dto.request.EmailVerifyRequest; +import flipnote.user.interfaces.http.dto.request.LoginRequest; +import flipnote.user.interfaces.http.dto.request.PasswordResetCreateRequest; +import flipnote.user.interfaces.http.dto.request.PasswordResetRequest; +import flipnote.user.interfaces.http.dto.request.SignupRequest; +import flipnote.user.interfaces.http.dto.request.TokenValidateRequest; +import flipnote.user.interfaces.http.dto.response.SocialLinksResponse; +import flipnote.user.interfaces.http.dto.response.TokenValidateResponse; +import flipnote.user.interfaces.http.dto.response.UserResponse; import jakarta.servlet.http.HttpServletResponse; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; diff --git a/src/main/java/flipnote/user/auth/presentation/OAuthController.java b/src/main/java/flipnote/user/interfaces/http/OAuthController.java similarity index 82% rename from src/main/java/flipnote/user/auth/presentation/OAuthController.java rename to src/main/java/flipnote/user/interfaces/http/OAuthController.java index e34b016..ceb9758 100644 --- a/src/main/java/flipnote/user/auth/presentation/OAuthController.java +++ b/src/main/java/flipnote/user/interfaces/http/OAuthController.java @@ -1,13 +1,14 @@ -package flipnote.user.auth.presentation; +package flipnote.user.interfaces; -import flipnote.user.auth.application.OAuthService; -import flipnote.user.auth.domain.AuthErrorCode; -import flipnote.user.global.exception.BizException; -import flipnote.user.auth.domain.TokenPair; -import flipnote.user.global.config.ClientProperties; -import flipnote.user.global.constants.HttpConstants; -import flipnote.user.global.util.CookieUtil; -import flipnote.user.auth.infrastructure.jwt.JwtProvider; +import flipnote.user.application.OAuthService; +import flipnote.user.domain.AuthErrorCode; +import flipnote.user.domain.TokenPair; +import flipnote.user.domain.common.BizException; +import flipnote.user.infrastructure.config.ClientProperties; +import flipnote.user.infrastructure.jwt.JwtProvider; +import flipnote.user.interfaces.http.common.CookieUtil; +import flipnote.user.interfaces.http.common.HttpConstants; +import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -31,8 +32,9 @@ public class OAuthController { @GetMapping("/oauth2/authorization/{provider}") public ResponseEntity redirectToProvider( @PathVariable String provider, - @RequestHeader(value = HttpConstants.USER_ID_HEADER, required = false) Long userId) { - OAuthService.AuthorizationRedirect redirect = oAuthService.getAuthorizationUri(provider, userId); + @RequestHeader(value = HttpConstants.USER_ID_HEADER, required = false) Long userId, + HttpServletRequest request) { + OAuthService.AuthorizationRedirect redirect = oAuthService.getAuthorizationUri(provider, request, userId); return ResponseEntity.status(HttpStatus.FOUND) .header(HttpHeaders.SET_COOKIE, redirect.verifierCookie().toString()) @@ -46,21 +48,22 @@ public ResponseEntity handleCallback( @RequestParam String code, @RequestParam(required = false) String state, @CookieValue(HttpConstants.OAUTH_VERIFIER_COOKIE) String codeVerifier, + HttpServletRequest request, HttpServletResponse response) { CookieUtil.deleteCookie(response, HttpConstants.OAUTH_VERIFIER_COOKIE); boolean isSocialLinkRequest = StringUtils.hasText(state); if (isSocialLinkRequest) { - return handleSocialLink(provider, code, state, codeVerifier); + return handleSocialLink(provider, code, state, codeVerifier, request); } - return handleSocialLogin(provider, code, codeVerifier, response); + return handleSocialLogin(provider, code, codeVerifier, request, response); } private ResponseEntity handleSocialLogin(String provider, String code, String codeVerifier, - HttpServletResponse response) { + HttpServletRequest request, HttpServletResponse response) { try { - TokenPair tokenPair = oAuthService.socialLogin(provider, code, codeVerifier); + TokenPair tokenPair = oAuthService.socialLogin(provider, code, codeVerifier, request); CookieUtil.addCookie(response, HttpConstants.ACCESS_TOKEN_COOKIE, tokenPair.accessToken(), jwtProvider.getAccessTokenExpiration() / 1000); CookieUtil.addCookie(response, HttpConstants.REFRESH_TOKEN_COOKIE, tokenPair.refreshToken(), @@ -77,9 +80,9 @@ private ResponseEntity handleSocialLogin(String provider, String code, Str } private ResponseEntity handleSocialLink(String provider, String code, String state, - String codeVerifier) { + String codeVerifier, HttpServletRequest request) { try { - oAuthService.linkSocialAccount(provider, code, state, codeVerifier); + oAuthService.linkSocialAccount(provider, code, state, codeVerifier, request); return ResponseEntity.status(HttpStatus.FOUND) .location(URI.create(clientProperties.getUrl() + clientProperties.getPaths().getSocialLinkSuccess())) .build(); diff --git a/src/main/java/flipnote/user/user/presentation/UserController.java b/src/main/java/flipnote/user/interfaces/http/UserController.java similarity index 76% rename from src/main/java/flipnote/user/user/presentation/UserController.java rename to src/main/java/flipnote/user/interfaces/http/UserController.java index fc53b14..4da91bf 100644 --- a/src/main/java/flipnote/user/user/presentation/UserController.java +++ b/src/main/java/flipnote/user/interfaces/http/UserController.java @@ -1,11 +1,11 @@ -package flipnote.user.user.presentation; +package flipnote.user.interfaces; -import flipnote.user.user.application.UserService; -import flipnote.user.user.presentation.dto.request.UpdateProfileRequest; -import flipnote.user.user.presentation.dto.response.MyInfoResponse; -import flipnote.user.user.presentation.dto.response.UserInfoResponse; -import flipnote.user.user.presentation.dto.response.UserUpdateResponse; -import flipnote.user.global.constants.HttpConstants; +import flipnote.user.application.UserService; +import flipnote.user.interfaces.http.common.HttpConstants; +import flipnote.user.interfaces.http.dto.request.UpdateProfileRequest; +import flipnote.user.interfaces.http.dto.response.MyInfoResponse; +import flipnote.user.interfaces.http.dto.response.UserInfoResponse; +import flipnote.user.interfaces.http.dto.response.UserUpdateResponse; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; diff --git a/src/main/java/flipnote/user/global/error/ApiResponse.java b/src/main/java/flipnote/user/interfaces/http/common/ApiResponse.java similarity index 95% rename from src/main/java/flipnote/user/global/error/ApiResponse.java rename to src/main/java/flipnote/user/interfaces/http/common/ApiResponse.java index 39f2442..968d8db 100644 --- a/src/main/java/flipnote/user/global/error/ApiResponse.java +++ b/src/main/java/flipnote/user/interfaces/http/common/ApiResponse.java @@ -1,5 +1,6 @@ -package flipnote.user.global.error; +package flipnote.user.interfaces.http.common; +import flipnote.user.domain.common.ErrorCode; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; diff --git a/src/main/java/flipnote/user/global/error/ApiResponseAdvice.java b/src/main/java/flipnote/user/interfaces/http/common/ApiResponseAdvice.java similarity index 96% rename from src/main/java/flipnote/user/global/error/ApiResponseAdvice.java rename to src/main/java/flipnote/user/interfaces/http/common/ApiResponseAdvice.java index eddabf1..b2bdb3a 100644 --- a/src/main/java/flipnote/user/global/error/ApiResponseAdvice.java +++ b/src/main/java/flipnote/user/interfaces/http/common/ApiResponseAdvice.java @@ -1,4 +1,4 @@ -package flipnote.user.global.error; +package flipnote.user.interfaces.http.common; import org.springframework.core.MethodParameter; import org.springframework.http.MediaType; diff --git a/src/main/java/flipnote/user/global/util/CookieUtil.java b/src/main/java/flipnote/user/interfaces/http/common/CookieUtil.java similarity index 95% rename from src/main/java/flipnote/user/global/util/CookieUtil.java rename to src/main/java/flipnote/user/interfaces/http/common/CookieUtil.java index bfeda9b..6df476e 100644 --- a/src/main/java/flipnote/user/global/util/CookieUtil.java +++ b/src/main/java/flipnote/user/interfaces/http/common/CookieUtil.java @@ -1,4 +1,4 @@ -package flipnote.user.global.util; +package flipnote.user.interfaces.http.common; import jakarta.servlet.http.HttpServletResponse; import org.springframework.http.ResponseCookie; diff --git a/src/main/java/flipnote/user/global/error/GlobalExceptionHandler.java b/src/main/java/flipnote/user/interfaces/http/common/GlobalExceptionHandler.java similarity index 95% rename from src/main/java/flipnote/user/global/error/GlobalExceptionHandler.java rename to src/main/java/flipnote/user/interfaces/http/common/GlobalExceptionHandler.java index 5d4d142..e50545d 100644 --- a/src/main/java/flipnote/user/global/error/GlobalExceptionHandler.java +++ b/src/main/java/flipnote/user/interfaces/http/common/GlobalExceptionHandler.java @@ -1,6 +1,6 @@ -package flipnote.user.global.error; +package flipnote.user.interfaces.http.common; -import flipnote.user.global.exception.BizException; +import flipnote.user.domain.common.BizException; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; diff --git a/src/main/java/flipnote/user/global/constants/HttpConstants.java b/src/main/java/flipnote/user/interfaces/http/common/HttpConstants.java similarity index 89% rename from src/main/java/flipnote/user/global/constants/HttpConstants.java rename to src/main/java/flipnote/user/interfaces/http/common/HttpConstants.java index dd85905..ef64b99 100644 --- a/src/main/java/flipnote/user/global/constants/HttpConstants.java +++ b/src/main/java/flipnote/user/interfaces/http/common/HttpConstants.java @@ -1,4 +1,4 @@ -package flipnote.user.global.constants; +package flipnote.user.interfaces.http.common; import lombok.NoArgsConstructor; diff --git a/src/main/java/flipnote/user/auth/presentation/dto/request/ChangePasswordRequest.java b/src/main/java/flipnote/user/interfaces/http/dto/request/ChangePasswordRequest.java similarity index 90% rename from src/main/java/flipnote/user/auth/presentation/dto/request/ChangePasswordRequest.java rename to src/main/java/flipnote/user/interfaces/http/dto/request/ChangePasswordRequest.java index 68fca89..1a9e6d3 100644 --- a/src/main/java/flipnote/user/auth/presentation/dto/request/ChangePasswordRequest.java +++ b/src/main/java/flipnote/user/interfaces/http/dto/request/ChangePasswordRequest.java @@ -1,4 +1,4 @@ -package flipnote.user.auth.presentation.dto.request; +package flipnote.user.interfaces.http.dto.request; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.Size; diff --git a/src/main/java/flipnote/user/auth/presentation/dto/request/EmailVerificationRequest.java b/src/main/java/flipnote/user/interfaces/http/dto/request/EmailVerificationRequest.java similarity index 87% rename from src/main/java/flipnote/user/auth/presentation/dto/request/EmailVerificationRequest.java rename to src/main/java/flipnote/user/interfaces/http/dto/request/EmailVerificationRequest.java index 9914235..a16898a 100644 --- a/src/main/java/flipnote/user/auth/presentation/dto/request/EmailVerificationRequest.java +++ b/src/main/java/flipnote/user/interfaces/http/dto/request/EmailVerificationRequest.java @@ -1,4 +1,4 @@ -package flipnote.user.auth.presentation.dto.request; +package flipnote.user.interfaces.http.dto.request; import jakarta.validation.constraints.Email; import jakarta.validation.constraints.NotBlank; diff --git a/src/main/java/flipnote/user/auth/presentation/dto/request/EmailVerifyRequest.java b/src/main/java/flipnote/user/interfaces/http/dto/request/EmailVerifyRequest.java similarity index 91% rename from src/main/java/flipnote/user/auth/presentation/dto/request/EmailVerifyRequest.java rename to src/main/java/flipnote/user/interfaces/http/dto/request/EmailVerifyRequest.java index add0490..0e2033d 100644 --- a/src/main/java/flipnote/user/auth/presentation/dto/request/EmailVerifyRequest.java +++ b/src/main/java/flipnote/user/interfaces/http/dto/request/EmailVerifyRequest.java @@ -1,4 +1,4 @@ -package flipnote.user.auth.presentation.dto.request; +package flipnote.user.interfaces.http.dto.request; import jakarta.validation.constraints.Email; import jakarta.validation.constraints.NotBlank; diff --git a/src/main/java/flipnote/user/auth/presentation/dto/request/LoginRequest.java b/src/main/java/flipnote/user/interfaces/http/dto/request/LoginRequest.java similarity index 89% rename from src/main/java/flipnote/user/auth/presentation/dto/request/LoginRequest.java rename to src/main/java/flipnote/user/interfaces/http/dto/request/LoginRequest.java index e84a68e..fd4e8d1 100644 --- a/src/main/java/flipnote/user/auth/presentation/dto/request/LoginRequest.java +++ b/src/main/java/flipnote/user/interfaces/http/dto/request/LoginRequest.java @@ -1,4 +1,4 @@ -package flipnote.user.auth.presentation.dto.request; +package flipnote.user.interfaces.http.dto.request; import jakarta.validation.constraints.Email; import jakarta.validation.constraints.NotBlank; diff --git a/src/main/java/flipnote/user/auth/presentation/dto/request/PasswordResetCreateRequest.java b/src/main/java/flipnote/user/interfaces/http/dto/request/PasswordResetCreateRequest.java similarity index 87% rename from src/main/java/flipnote/user/auth/presentation/dto/request/PasswordResetCreateRequest.java rename to src/main/java/flipnote/user/interfaces/http/dto/request/PasswordResetCreateRequest.java index 805ec9e..d166b03 100644 --- a/src/main/java/flipnote/user/auth/presentation/dto/request/PasswordResetCreateRequest.java +++ b/src/main/java/flipnote/user/interfaces/http/dto/request/PasswordResetCreateRequest.java @@ -1,4 +1,4 @@ -package flipnote.user.auth.presentation.dto.request; +package flipnote.user.interfaces.http.dto.request; import jakarta.validation.constraints.Email; import jakarta.validation.constraints.NotBlank; diff --git a/src/main/java/flipnote/user/auth/presentation/dto/request/PasswordResetRequest.java b/src/main/java/flipnote/user/interfaces/http/dto/request/PasswordResetRequest.java similarity index 90% rename from src/main/java/flipnote/user/auth/presentation/dto/request/PasswordResetRequest.java rename to src/main/java/flipnote/user/interfaces/http/dto/request/PasswordResetRequest.java index 5bf5a9f..fd57bd8 100644 --- a/src/main/java/flipnote/user/auth/presentation/dto/request/PasswordResetRequest.java +++ b/src/main/java/flipnote/user/interfaces/http/dto/request/PasswordResetRequest.java @@ -1,4 +1,4 @@ -package flipnote.user.auth.presentation.dto.request; +package flipnote.user.interfaces.http.dto.request; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.Size; diff --git a/src/main/java/flipnote/user/auth/presentation/dto/request/SignupRequest.java b/src/main/java/flipnote/user/interfaces/http/dto/request/SignupRequest.java similarity index 95% rename from src/main/java/flipnote/user/auth/presentation/dto/request/SignupRequest.java rename to src/main/java/flipnote/user/interfaces/http/dto/request/SignupRequest.java index a59af8e..8bea746 100644 --- a/src/main/java/flipnote/user/auth/presentation/dto/request/SignupRequest.java +++ b/src/main/java/flipnote/user/interfaces/http/dto/request/SignupRequest.java @@ -1,4 +1,4 @@ -package flipnote.user.auth.presentation.dto.request; +package flipnote.user.interfaces.http.dto.request; import jakarta.validation.constraints.Email; import jakarta.validation.constraints.NotBlank; diff --git a/src/main/java/flipnote/user/auth/presentation/dto/request/TokenValidateRequest.java b/src/main/java/flipnote/user/interfaces/http/dto/request/TokenValidateRequest.java similarity index 82% rename from src/main/java/flipnote/user/auth/presentation/dto/request/TokenValidateRequest.java rename to src/main/java/flipnote/user/interfaces/http/dto/request/TokenValidateRequest.java index 45055ce..3586ecb 100644 --- a/src/main/java/flipnote/user/auth/presentation/dto/request/TokenValidateRequest.java +++ b/src/main/java/flipnote/user/interfaces/http/dto/request/TokenValidateRequest.java @@ -1,4 +1,4 @@ -package flipnote.user.auth.presentation.dto.request; +package flipnote.user.interfaces.http.dto.request; import jakarta.validation.constraints.NotBlank; import lombok.Getter; diff --git a/src/main/java/flipnote/user/user/presentation/dto/request/UpdateProfileRequest.java b/src/main/java/flipnote/user/interfaces/http/dto/request/UpdateProfileRequest.java similarity index 91% rename from src/main/java/flipnote/user/user/presentation/dto/request/UpdateProfileRequest.java rename to src/main/java/flipnote/user/interfaces/http/dto/request/UpdateProfileRequest.java index 2bcbff3..29f23f5 100644 --- a/src/main/java/flipnote/user/user/presentation/dto/request/UpdateProfileRequest.java +++ b/src/main/java/flipnote/user/interfaces/http/dto/request/UpdateProfileRequest.java @@ -1,4 +1,4 @@ -package flipnote.user.user.presentation.dto.request; +package flipnote.user.interfaces.http.dto.request; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; diff --git a/src/main/java/flipnote/user/user/presentation/dto/response/MyInfoResponse.java b/src/main/java/flipnote/user/interfaces/http/dto/response/MyInfoResponse.java similarity index 91% rename from src/main/java/flipnote/user/user/presentation/dto/response/MyInfoResponse.java rename to src/main/java/flipnote/user/interfaces/http/dto/response/MyInfoResponse.java index 0798946..9a99532 100644 --- a/src/main/java/flipnote/user/user/presentation/dto/response/MyInfoResponse.java +++ b/src/main/java/flipnote/user/interfaces/http/dto/response/MyInfoResponse.java @@ -1,7 +1,7 @@ -package flipnote.user.user.presentation.dto.response; +package flipnote.user.interfaces.http.dto.response; import com.fasterxml.jackson.annotation.JsonFormat; -import flipnote.user.user.domain.User; +import flipnote.user.domain.entity.User; import lombok.AllArgsConstructor; import lombok.Getter; diff --git a/src/main/java/flipnote/user/auth/presentation/dto/response/SocialLinkResponse.java b/src/main/java/flipnote/user/interfaces/http/dto/response/SocialLinkResponse.java similarity index 83% rename from src/main/java/flipnote/user/auth/presentation/dto/response/SocialLinkResponse.java rename to src/main/java/flipnote/user/interfaces/http/dto/response/SocialLinkResponse.java index 1c7f250..bc68198 100644 --- a/src/main/java/flipnote/user/auth/presentation/dto/response/SocialLinkResponse.java +++ b/src/main/java/flipnote/user/interfaces/http/dto/response/SocialLinkResponse.java @@ -1,7 +1,7 @@ -package flipnote.user.auth.presentation.dto.response; +package flipnote.user.interfaces.http.dto.response; import com.fasterxml.jackson.annotation.JsonFormat; -import flipnote.user.user.domain.OAuthLink; +import flipnote.user.domain.entity.OAuthLink; import lombok.AllArgsConstructor; import lombok.Getter; diff --git a/src/main/java/flipnote/user/auth/presentation/dto/response/SocialLinksResponse.java b/src/main/java/flipnote/user/interfaces/http/dto/response/SocialLinksResponse.java similarity index 82% rename from src/main/java/flipnote/user/auth/presentation/dto/response/SocialLinksResponse.java rename to src/main/java/flipnote/user/interfaces/http/dto/response/SocialLinksResponse.java index d5f3bbd..2297b90 100644 --- a/src/main/java/flipnote/user/auth/presentation/dto/response/SocialLinksResponse.java +++ b/src/main/java/flipnote/user/interfaces/http/dto/response/SocialLinksResponse.java @@ -1,6 +1,6 @@ -package flipnote.user.auth.presentation.dto.response; +package flipnote.user.interfaces.http.dto.response; -import flipnote.user.user.domain.OAuthLink; +import flipnote.user.domain.entity.OAuthLink; import lombok.AllArgsConstructor; import lombok.Getter; diff --git a/src/main/java/flipnote/user/auth/presentation/dto/response/TokenValidateResponse.java b/src/main/java/flipnote/user/interfaces/http/dto/response/TokenValidateResponse.java similarity index 78% rename from src/main/java/flipnote/user/auth/presentation/dto/response/TokenValidateResponse.java rename to src/main/java/flipnote/user/interfaces/http/dto/response/TokenValidateResponse.java index 6b799b5..933306f 100644 --- a/src/main/java/flipnote/user/auth/presentation/dto/response/TokenValidateResponse.java +++ b/src/main/java/flipnote/user/interfaces/http/dto/response/TokenValidateResponse.java @@ -1,4 +1,4 @@ -package flipnote.user.auth.presentation.dto.response; +package flipnote.user.interfaces.http.dto.response; import lombok.AllArgsConstructor; import lombok.Getter; diff --git a/src/main/java/flipnote/user/user/presentation/dto/response/UserInfoResponse.java b/src/main/java/flipnote/user/interfaces/http/dto/response/UserInfoResponse.java similarity index 81% rename from src/main/java/flipnote/user/user/presentation/dto/response/UserInfoResponse.java rename to src/main/java/flipnote/user/interfaces/http/dto/response/UserInfoResponse.java index fd08f81..d739b6f 100644 --- a/src/main/java/flipnote/user/user/presentation/dto/response/UserInfoResponse.java +++ b/src/main/java/flipnote/user/interfaces/http/dto/response/UserInfoResponse.java @@ -1,6 +1,6 @@ -package flipnote.user.user.presentation.dto.response; +package flipnote.user.interfaces.http.dto.response; -import flipnote.user.user.domain.User; +import flipnote.user.domain.entity.User; import lombok.AllArgsConstructor; import lombok.Getter; diff --git a/src/main/java/flipnote/user/auth/presentation/dto/response/UserResponse.java b/src/main/java/flipnote/user/interfaces/http/dto/response/UserResponse.java similarity index 72% rename from src/main/java/flipnote/user/auth/presentation/dto/response/UserResponse.java rename to src/main/java/flipnote/user/interfaces/http/dto/response/UserResponse.java index 66a9541..77b88ac 100644 --- a/src/main/java/flipnote/user/auth/presentation/dto/response/UserResponse.java +++ b/src/main/java/flipnote/user/interfaces/http/dto/response/UserResponse.java @@ -1,6 +1,6 @@ -package flipnote.user.auth.presentation.dto.response; +package flipnote.user.interfaces.http.dto.response; -import flipnote.user.user.domain.User; +import flipnote.user.domain.entity.User; import lombok.AllArgsConstructor; import lombok.Getter; diff --git a/src/main/java/flipnote/user/user/presentation/dto/response/UserUpdateResponse.java b/src/main/java/flipnote/user/interfaces/http/dto/response/UserUpdateResponse.java similarity index 86% rename from src/main/java/flipnote/user/user/presentation/dto/response/UserUpdateResponse.java rename to src/main/java/flipnote/user/interfaces/http/dto/response/UserUpdateResponse.java index 1880087..6296af8 100644 --- a/src/main/java/flipnote/user/user/presentation/dto/response/UserUpdateResponse.java +++ b/src/main/java/flipnote/user/interfaces/http/dto/response/UserUpdateResponse.java @@ -1,6 +1,6 @@ -package flipnote.user.user.presentation.dto.response; +package flipnote.user.interfaces.http.dto.response; -import flipnote.user.user.domain.User; +import flipnote.user.domain.entity.User; import lombok.AllArgsConstructor; import lombok.Getter; diff --git a/src/main/java/flipnote/user/user/presentation/grpc/GrpcUserQueryService.java b/src/main/java/flipnote/user/user/presentation/grpc/GrpcUserQueryService.java deleted file mode 100644 index e38d3e6..0000000 --- a/src/main/java/flipnote/user/user/presentation/grpc/GrpcUserQueryService.java +++ /dev/null @@ -1,135 +0,0 @@ -package flipnote.user.user.presentation.grpc; - -import flipnote.user.auth.domain.TokenClaims; -import flipnote.user.auth.infrastructure.jwt.JwtProvider; -import flipnote.user.user.domain.User; -import flipnote.user.user.domain.UserRepository; -import flipnote.user.grpc.GetUserByEmailRequest; -import flipnote.user.grpc.GetUserByEmailResponse; -import flipnote.user.grpc.GetUserByTokenRequest; -import flipnote.user.grpc.GetUserByTokenResponse; -import flipnote.user.grpc.GetUserRequest; -import flipnote.user.grpc.GetUserResponse; -import flipnote.user.grpc.GetUsersRequest; -import flipnote.user.grpc.GetUsersResponse; -import flipnote.user.grpc.UserQueryServiceGrpc; -import io.grpc.Status; -import io.grpc.stub.StreamObserver; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; - -import java.util.List; - -@Slf4j -@Service -@RequiredArgsConstructor -public class GrpcUserQueryService extends UserQueryServiceGrpc.UserQueryServiceImplBase { - - private final UserRepository userRepository; - private final JwtProvider jwtProvider; - - @Override - public void getUser(GetUserRequest request, StreamObserver responseObserver) { - try { - User user = userRepository.findByIdAndStatus(request.getUserId(), User.Status.ACTIVE) - .orElse(null); - - if (user == null) { - responseObserver.onError( - Status.NOT_FOUND.withDescription("μ‚¬μš©μžλ₯Ό 찾을 수 μ—†μŠ΅λ‹ˆλ‹€.").asRuntimeException() - ); - return; - } - - responseObserver.onNext(toResponse(user)); - responseObserver.onCompleted(); - } catch (Exception e) { - log.error("gRPC getUser error. userId: {}", request.getUserId(), e); - responseObserver.onError(Status.INTERNAL.withDescription("Internal error").asRuntimeException()); - } - } - - @Override - public void getUsers(GetUsersRequest request, StreamObserver responseObserver) { - try { - List userIds = request.getUserIdsList(); - List users = userRepository.findByIdInAndStatus(userIds, User.Status.ACTIVE); - - GetUsersResponse response = GetUsersResponse.newBuilder() - .addAllUsers(users.stream().map(this::toResponse).toList()) - .build(); - - responseObserver.onNext(response); - responseObserver.onCompleted(); - } catch (Exception e) { - log.error("gRPC getUsers error. userIds: {}", request.getUserIdsList(), e); - responseObserver.onError(Status.INTERNAL.withDescription("Internal error").asRuntimeException()); - } - } - - @Override - public void getUserByEmail(GetUserByEmailRequest request, StreamObserver responseObserver) { - try { - User user = userRepository.findByEmailAndStatus(request.getEmail(), User.Status.ACTIVE) - .orElse(null); - - GetUserByEmailResponse.Builder responseBuilder = GetUserByEmailResponse.newBuilder(); - - if (user != null) { - responseBuilder.setExists(true).setUser(toResponse(user)); - } else { - responseBuilder.setExists(false); - } - - responseObserver.onNext(responseBuilder.build()); - responseObserver.onCompleted(); - } catch (Exception e) { - log.error("gRPC getUserByEmail error. email: {}", request.getEmail(), e); - responseObserver.onError(Status.INTERNAL.withDescription("Internal error").asRuntimeException()); - } - } - - @Override - public void getUserByToken(GetUserByTokenRequest request, StreamObserver responseObserver) { - try { - if (!jwtProvider.isTokenValid(request.getAccessToken())) { - responseObserver.onError( - Status.UNAUTHENTICATED.withDescription("μœ νš¨ν•˜μ§€ μ•Šμ€ ν† ν°μž…λ‹ˆλ‹€.").asRuntimeException() - ); - return; - } - - TokenClaims claims = jwtProvider.extractClaims(request.getAccessToken()); - User user = userRepository.findByIdAndStatus(claims.userId(), User.Status.ACTIVE) - .orElse(null); - - if (user == null) { - responseObserver.onError( - Status.NOT_FOUND.withDescription("μ‚¬μš©μžλ₯Ό 찾을 수 μ—†μŠ΅λ‹ˆλ‹€.").asRuntimeException() - ); - return; - } - - GetUserByTokenResponse response = GetUserByTokenResponse.newBuilder() - .setUserId(user.getId()) - .setNickname(user.getNickname()) - .build(); - - responseObserver.onNext(response); - responseObserver.onCompleted(); - } catch (Exception e) { - log.error("gRPC getUserByToken error", e); - responseObserver.onError(Status.INTERNAL.withDescription("Internal error").asRuntimeException()); - } - } - - private GetUserResponse toResponse(User user) { - return GetUserResponse.newBuilder() - .setId(user.getId()) - .setEmail(user.getEmail()) - .setNickname(user.getNickname()) - .setProfileImageUrl(user.getProfileImageUrl() != null ? user.getProfileImageUrl() : "") - .build(); - } -}