From 56363d6210365faa9a9b8c8d3f7a1ee2a7c8349a Mon Sep 17 00:00:00 2001 From: GaBaljaintheroom Date: Wed, 5 Jun 2024 17:36:38 +0900 Subject: [PATCH 01/23] feat : redis setting --- app/api/build.gradle | 1 + .../java/org/example/config/ApiConfig.java | 2 +- .../security/token/RefreshTokenProcessor.java | 3 ++ app/infrastructure/build.gradle | 10 ++++++ .../example/config/InfraStructureConfig.java | 13 ++++++++ .../java/org/example/config/RedisConfig.java | 31 +++++++++++++++++++ .../org/example/property/RedisProperty.java | 11 +++++++ .../example/repository/RedisRepository.java | 18 +++++++++++ app/src/main/resources/application-local.yml | 6 ++++ docker-compose.yml | 10 ++++-- settings.gradle | 2 ++ 11 files changed, 104 insertions(+), 3 deletions(-) create mode 100644 app/infrastructure/build.gradle create mode 100644 app/infrastructure/src/main/java/org/example/config/InfraStructureConfig.java create mode 100644 app/infrastructure/src/main/java/org/example/config/RedisConfig.java create mode 100644 app/infrastructure/src/main/java/org/example/property/RedisProperty.java create mode 100644 app/infrastructure/src/main/java/org/example/repository/RedisRepository.java diff --git a/app/api/build.gradle b/app/api/build.gradle index 5b7dff4d..c489a44d 100644 --- a/app/api/build.gradle +++ b/app/api/build.gradle @@ -14,6 +14,7 @@ allprojects { dependencies { implementation project(":app:api:user-api") + implementation project(":app:infrastructure") // spring-security implementation 'org.springframework.boot:spring-boot-starter-security' diff --git a/app/api/src/main/java/org/example/config/ApiConfig.java b/app/api/src/main/java/org/example/config/ApiConfig.java index 08a676b4..c470212c 100644 --- a/app/api/src/main/java/org/example/config/ApiConfig.java +++ b/app/api/src/main/java/org/example/config/ApiConfig.java @@ -7,7 +7,7 @@ import org.springframework.context.annotation.Import; @Configuration -@Import(UserApiConfig.class) +@Import({UserApiConfig.class, InfraStructureConfig.class}) @EnableConfigurationProperties(TokenProperty.class) @ComponentScan(basePackages = "org.example") public class ApiConfig { diff --git a/app/api/src/main/java/org/example/security/token/RefreshTokenProcessor.java b/app/api/src/main/java/org/example/security/token/RefreshTokenProcessor.java index e725066f..38eb3119 100644 --- a/app/api/src/main/java/org/example/security/token/RefreshTokenProcessor.java +++ b/app/api/src/main/java/org/example/security/token/RefreshTokenProcessor.java @@ -2,6 +2,7 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; +import java.util.UUID; import lombok.RequiredArgsConstructor; import org.example.security.dto.TokenParam; import org.springframework.stereotype.Component; @@ -17,6 +18,8 @@ public TokenParam process(HttpServletRequest request, HttpServletResponse respon String accessToken = jwtHandler.extractAccessToken(request); String refreshToken = jwtHandler.extractRefreshToken(request); + UUID userIdFromExpiredToken = jwtHandler.getUserIdFromExpiredToken(refreshToken); + return new TokenParam(accessToken, refreshToken); } } diff --git a/app/infrastructure/build.gradle b/app/infrastructure/build.gradle new file mode 100644 index 00000000..349cd938 --- /dev/null +++ b/app/infrastructure/build.gradle @@ -0,0 +1,10 @@ +bootJar.enabled = false; +jar.enabled = true; + +dependencies { + implementation "org.springframework.boot:spring-boot-starter-web" + + //redis + implementation 'org.springframework.data:spring-data-redis' + implementation 'io.lettuce:lettuce-core:6.3.0.RELEASE' +} diff --git a/app/infrastructure/src/main/java/org/example/config/InfraStructureConfig.java b/app/infrastructure/src/main/java/org/example/config/InfraStructureConfig.java new file mode 100644 index 00000000..fba83877 --- /dev/null +++ b/app/infrastructure/src/main/java/org/example/config/InfraStructureConfig.java @@ -0,0 +1,13 @@ +package org.example.config; + +import org.example.property.RedisProperty; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +@Configuration +@EnableConfigurationProperties(RedisProperty.class) +@ComponentScan(basePackages = "org.example") +public class InfraStructureConfig { + +} diff --git a/app/infrastructure/src/main/java/org/example/config/RedisConfig.java b/app/infrastructure/src/main/java/org/example/config/RedisConfig.java new file mode 100644 index 00000000..207a8903 --- /dev/null +++ b/app/infrastructure/src/main/java/org/example/config/RedisConfig.java @@ -0,0 +1,31 @@ +package org.example.config; + +import lombok.RequiredArgsConstructor; +import org.example.property.RedisProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.data.redis.serializer.GenericToStringSerializer; + +@Configuration +@RequiredArgsConstructor +public class RedisConfig { + + private final RedisProperty redisProperty; + + @Bean + public RedisConnectionFactory redisConnectionFactory() { + return new LettuceConnectionFactory(redisProperty.host(), redisProperty.port()); + } + + @Bean + StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) { + final StringRedisTemplate template = new StringRedisTemplate(); + template.setConnectionFactory(redisConnectionFactory); + template.setHashKeySerializer(new GenericToStringSerializer<>(Object.class)); + + return template; + } +} diff --git a/app/infrastructure/src/main/java/org/example/property/RedisProperty.java b/app/infrastructure/src/main/java/org/example/property/RedisProperty.java new file mode 100644 index 00000000..e7a903b8 --- /dev/null +++ b/app/infrastructure/src/main/java/org/example/property/RedisProperty.java @@ -0,0 +1,11 @@ +package org.example.property; + +import org.springframework.boot.context.properties.ConfigurationProperties; + +@ConfigurationProperties(prefix = "spring.data.redis") +public record RedisProperty( + String host, + int port +) { + +} diff --git a/app/infrastructure/src/main/java/org/example/repository/RedisRepository.java b/app/infrastructure/src/main/java/org/example/repository/RedisRepository.java new file mode 100644 index 00000000..06a0cbb1 --- /dev/null +++ b/app/infrastructure/src/main/java/org/example/repository/RedisRepository.java @@ -0,0 +1,18 @@ +package org.example.repository; + +import java.util.concurrent.TimeUnit; +import lombok.RequiredArgsConstructor; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Repository; + +@Repository +@RequiredArgsConstructor +public class RedisRepository { + + private final RedisTemplate redisTemplate; + + public final void save(String userId, String refreshToken) { + redisTemplate.opsForValue().set("memberId:" + userId, refreshToken, 14, TimeUnit.DAYS); + } + +} diff --git a/app/src/main/resources/application-local.yml b/app/src/main/resources/application-local.yml index d588e9ad..cdb87b71 100644 --- a/app/src/main/resources/application-local.yml +++ b/app/src/main/resources/application-local.yml @@ -6,11 +6,17 @@ spring: stop: command: down timeout: 1m + security: user: name: user password: password + data: + redis: + host: localhost + port: 6379 + token: secret-key: ahRhwlglftmrkwkfehlaussksmsdjraksrmadmfqjfrjtdlrhdkwnwlflsmswlqdptjgodqhrgkrptkftndlTDmfrjtdlek access-token-expiration-seconds: 3600000 # 1hour = 1000(=1s) * 60 * 60 diff --git a/docker-compose.yml b/docker-compose.yml index 5fcff832..3c687d38 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,8 +1,8 @@ version: '3' services: - poastgresql: - container_name: postgresql + postgresql: + container_name: yapp_postgresql image: postgres:14 environment: - 'POSTGRES_DATABASE=yapp' @@ -11,3 +11,9 @@ services: ports: - '5432' restart: always + + redis: + container_name: yapp_redis + image: redis:alpine + ports: + - "6379:6379" \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index 6652a3e0..7886b341 100644 --- a/settings.gradle +++ b/settings.gradle @@ -9,3 +9,5 @@ include(":app:domain:user-domain") include(":app:api") include(":app:api:user-api") + +include (":app:infrastructure") From 67e951a4833b23b4a514264b4799d0efac6c0444 Mon Sep 17 00:00:00 2001 From: GaBaljaintheroom Date: Wed, 5 Jun 2024 17:51:04 +0900 Subject: [PATCH 02/23] =?UTF-8?q?feat=20:=20accessToken=20=EB=A7=8C?= =?UTF-8?q?=EB=A3=8C=20=EC=8B=9C=20=ED=86=A0=ED=81=B0=20=EC=9E=AC=EB=B0=9C?= =?UTF-8?q?=EA=B8=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/org/example/filter/JWTFilter.java | 2 +- .../security/token/RefreshTokenProcessor.java | 16 +++++++++------- .../org/example/repository/RedisRepository.java | 2 +- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/app/api/src/main/java/org/example/filter/JWTFilter.java b/app/api/src/main/java/org/example/filter/JWTFilter.java index a90c9beb..97432faa 100644 --- a/app/api/src/main/java/org/example/filter/JWTFilter.java +++ b/app/api/src/main/java/org/example/filter/JWTFilter.java @@ -33,7 +33,7 @@ protected void doFilterInternal( FilterChain filterChain ) throws ServletException, IOException { if (request.getHeader("Refresh") != null) { - TokenParam token = refreshTokenProcessor.process(request, response); + TokenParam token = refreshTokenProcessor.reissueToken(request); response.getWriter().write(new ObjectMapper().writeValueAsString(token)); return; } diff --git a/app/api/src/main/java/org/example/security/token/RefreshTokenProcessor.java b/app/api/src/main/java/org/example/security/token/RefreshTokenProcessor.java index 38eb3119..6e7fff8d 100644 --- a/app/api/src/main/java/org/example/security/token/RefreshTokenProcessor.java +++ b/app/api/src/main/java/org/example/security/token/RefreshTokenProcessor.java @@ -1,10 +1,11 @@ package org.example.security.token; import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import java.util.UUID; +import java.util.Date; import lombok.RequiredArgsConstructor; +import org.example.repository.RedisRepository; import org.example.security.dto.TokenParam; +import org.example.security.dto.UserParam; import org.springframework.stereotype.Component; @Component @@ -13,13 +14,14 @@ public class RefreshTokenProcessor { private final JWTHandler jwtHandler; private final JWTGenerator jwtGenerator; + private final RedisRepository redisRepository; - public TokenParam process(HttpServletRequest request, HttpServletResponse response) { - String accessToken = jwtHandler.extractAccessToken(request); + public TokenParam reissueToken(HttpServletRequest request) { String refreshToken = jwtHandler.extractRefreshToken(request); + UserParam userParam = jwtHandler.extractUserFrom(refreshToken); + TokenParam newTokenParam = jwtGenerator.generate(userParam, new Date()); - UUID userIdFromExpiredToken = jwtHandler.getUserIdFromExpiredToken(refreshToken); - - return new TokenParam(accessToken, refreshToken); + redisRepository.save(userParam.userId().toString(), newTokenParam.refreshToken()); + return newTokenParam; } } diff --git a/app/infrastructure/src/main/java/org/example/repository/RedisRepository.java b/app/infrastructure/src/main/java/org/example/repository/RedisRepository.java index 06a0cbb1..54e939c4 100644 --- a/app/infrastructure/src/main/java/org/example/repository/RedisRepository.java +++ b/app/infrastructure/src/main/java/org/example/repository/RedisRepository.java @@ -12,7 +12,7 @@ public class RedisRepository { private final RedisTemplate redisTemplate; public final void save(String userId, String refreshToken) { - redisTemplate.opsForValue().set("memberId:" + userId, refreshToken, 14, TimeUnit.DAYS); + redisTemplate.opsForValue().set("userId:" + userId, refreshToken, 14, TimeUnit.DAYS); } } From 1b4b902ed34de90588f30caf8ff91c8a5f3953ef Mon Sep 17 00:00:00 2001 From: GaBaljaintheroom Date: Wed, 5 Jun 2024 23:32:00 +0900 Subject: [PATCH 03/23] =?UTF-8?q?feat=20:=20user=20entity=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/domain/user-domain/build.gradle | 2 ++ .../main/java/org/example/entity/User.java | 32 ++++++++++++++++++- .../main/java/org/example/vo/SocialType.java | 5 +++ .../main/java/org/example/vo/UserGender.java | 5 +++ 4 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 app/domain/user-domain/src/main/java/org/example/vo/SocialType.java create mode 100644 app/domain/user-domain/src/main/java/org/example/vo/UserGender.java diff --git a/app/domain/user-domain/build.gradle b/app/domain/user-domain/build.gradle index 8e7c951d..17585d57 100644 --- a/app/domain/user-domain/build.gradle +++ b/app/domain/user-domain/build.gradle @@ -2,5 +2,7 @@ bootJar.enabled = false jar.enabled = true dependencies { + // hypersistence utils + implementation 'io.hypersistence:hypersistence-utils-hibernate-63:3.7.6' implementation project(":app:domain") } diff --git a/app/domain/user-domain/src/main/java/org/example/entity/User.java b/app/domain/user-domain/src/main/java/org/example/entity/User.java index e53302ed..6d5b9caf 100644 --- a/app/domain/user-domain/src/main/java/org/example/entity/User.java +++ b/app/domain/user-domain/src/main/java/org/example/entity/User.java @@ -1,11 +1,22 @@ package org.example.entity; +import io.hypersistence.utils.hibernate.type.json.JsonType; import jakarta.persistence.Column; import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; import jakarta.persistence.Table; +import java.time.LocalDate; +import java.util.HashMap; +import java.util.Map; import lombok.AccessLevel; +import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; +import org.example.vo.SocialType; +import org.example.vo.UserGender; +import org.example.vo.UserRole; +import org.hibernate.annotations.Type; @Entity @Getter @@ -16,7 +27,26 @@ public class User extends BaseEntity { @Column(name = "nickname", nullable = false) private String nickname; - public User(String nickname) { + @Column(name = "birth") + private LocalDate birth; + + @Column(name = "fcm_token") + private String fcmToken; + @Type(JsonType.class) + @Column(name = "social_type", columnDefinition = "jsonb") + private Map socialCredentials = new HashMap<>(); + + @Column(name = "gender") + @Enumerated(value = EnumType.STRING) + private UserGender userGender; + + @Column(name = "role", nullable = false) + @Enumerated(value = EnumType.STRING) + private UserRole userRole; + + @Builder + private User(String nickname, SocialType socialType, String socialIdentifier) { this.nickname = nickname; + this.socialCredentials.put(socialType, socialIdentifier); } } \ No newline at end of file diff --git a/app/domain/user-domain/src/main/java/org/example/vo/SocialType.java b/app/domain/user-domain/src/main/java/org/example/vo/SocialType.java new file mode 100644 index 00000000..cd3a3c53 --- /dev/null +++ b/app/domain/user-domain/src/main/java/org/example/vo/SocialType.java @@ -0,0 +1,5 @@ +package org.example.vo; + +public enum SocialType { + GOOGLE, KAKAO, APPLE +} diff --git a/app/domain/user-domain/src/main/java/org/example/vo/UserGender.java b/app/domain/user-domain/src/main/java/org/example/vo/UserGender.java new file mode 100644 index 00000000..9d7fe2be --- /dev/null +++ b/app/domain/user-domain/src/main/java/org/example/vo/UserGender.java @@ -0,0 +1,5 @@ +package org.example.vo; + +public enum UserGender { + MAN, WOMAN +} From 4df94b2b52ecd09d96c83624a23848e40998547e Mon Sep 17 00:00:00 2001 From: GaBaljaintheroom Date: Wed, 5 Jun 2024 23:47:57 +0900 Subject: [PATCH 04/23] =?UTF-8?q?feat=20:=20jwt=20=EA=B4=80=EB=A0=A8=20?= =?UTF-8?q?=EC=9D=98=EC=A1=B4=EC=84=B1=20=EB=B0=8F=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?user-api=20=EB=AA=A8=EB=93=88=EB=A1=9C=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/api/build.gradle | 6 ------ app/api/src/main/java/org/example/config/ApiConfig.java | 5 +---- app/api/user-api/build.gradle | 7 +++++++ .../src/main/java/org/example/config/UserApiConfig.java | 5 ++++- .../src/main/java/org/example/property/TokenProperty.java | 0 .../java/org/example/security/dto/AuthenticatedUser.java | 0 .../src/main/java/org/example/security/dto/TokenParam.java | 0 .../src/main/java/org/example/security/dto/UserParam.java | 0 .../main/java/org/example/security/token/JWTGenerator.java | 0 .../main/java/org/example/security/token/JWTHandler.java | 0 .../org/example/security/token/RefreshTokenProcessor.java | 0 .../src/main/java/org/example/security/vo/TokenError.java | 0 .../src/main/java/org/example/vo/UserRoleApiType.java | 0 .../java/org/example/security/token/JWTGeneratorTest.java | 0 .../java/org/example/security/token/JWTHandlerTest.java | 0 15 files changed, 12 insertions(+), 11 deletions(-) rename app/api/{ => user-api}/src/main/java/org/example/property/TokenProperty.java (100%) rename app/api/{ => user-api}/src/main/java/org/example/security/dto/AuthenticatedUser.java (100%) rename app/api/{ => user-api}/src/main/java/org/example/security/dto/TokenParam.java (100%) rename app/api/{ => user-api}/src/main/java/org/example/security/dto/UserParam.java (100%) rename app/api/{ => user-api}/src/main/java/org/example/security/token/JWTGenerator.java (100%) rename app/api/{ => user-api}/src/main/java/org/example/security/token/JWTHandler.java (100%) rename app/api/{ => user-api}/src/main/java/org/example/security/token/RefreshTokenProcessor.java (100%) rename app/api/{ => user-api}/src/main/java/org/example/security/vo/TokenError.java (100%) rename app/api/{ => user-api}/src/main/java/org/example/vo/UserRoleApiType.java (100%) rename app/api/{ => user-api}/src/test/java/org/example/security/token/JWTGeneratorTest.java (100%) rename app/api/{ => user-api}/src/test/java/org/example/security/token/JWTHandlerTest.java (100%) diff --git a/app/api/build.gradle b/app/api/build.gradle index c489a44d..3c18fdc5 100644 --- a/app/api/build.gradle +++ b/app/api/build.gradle @@ -14,13 +14,7 @@ allprojects { dependencies { implementation project(":app:api:user-api") - implementation project(":app:infrastructure") // spring-security implementation 'org.springframework.boot:spring-boot-starter-security' - - // jwt - implementation 'io.jsonwebtoken:jjwt-api:0.12.5' - runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.12.5' - runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.12.5' } \ No newline at end of file diff --git a/app/api/src/main/java/org/example/config/ApiConfig.java b/app/api/src/main/java/org/example/config/ApiConfig.java index c470212c..60cdde5f 100644 --- a/app/api/src/main/java/org/example/config/ApiConfig.java +++ b/app/api/src/main/java/org/example/config/ApiConfig.java @@ -1,14 +1,11 @@ package org.example.config; -import org.example.property.TokenProperty; -import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; @Configuration -@Import({UserApiConfig.class, InfraStructureConfig.class}) -@EnableConfigurationProperties(TokenProperty.class) +@Import(UserApiConfig.class) @ComponentScan(basePackages = "org.example") public class ApiConfig { diff --git a/app/api/user-api/build.gradle b/app/api/user-api/build.gradle index 8d463376..b5f8474a 100644 --- a/app/api/user-api/build.gradle +++ b/app/api/user-api/build.gradle @@ -4,4 +4,11 @@ jar.enabled = true dependencies { implementation project(":app:domain") implementation project(":app:domain:user-domain") + + implementation project(":app:infrastructure") + + // jwt + implementation 'io.jsonwebtoken:jjwt-api:0.12.5' + runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.12.5' + runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.12.5' } \ No newline at end of file diff --git a/app/api/user-api/src/main/java/org/example/config/UserApiConfig.java b/app/api/user-api/src/main/java/org/example/config/UserApiConfig.java index 0d709c9d..9b02a7a4 100644 --- a/app/api/user-api/src/main/java/org/example/config/UserApiConfig.java +++ b/app/api/user-api/src/main/java/org/example/config/UserApiConfig.java @@ -1,11 +1,14 @@ package org.example.config; +import org.example.property.TokenProperty; +import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; @Configuration -@Import(UserDomainConfig.class) +@Import({UserDomainConfig.class, InfraStructureConfig.class}) +@EnableConfigurationProperties(TokenProperty.class) @ComponentScan(basePackages = "org.example") public class UserApiConfig { diff --git a/app/api/src/main/java/org/example/property/TokenProperty.java b/app/api/user-api/src/main/java/org/example/property/TokenProperty.java similarity index 100% rename from app/api/src/main/java/org/example/property/TokenProperty.java rename to app/api/user-api/src/main/java/org/example/property/TokenProperty.java diff --git a/app/api/src/main/java/org/example/security/dto/AuthenticatedUser.java b/app/api/user-api/src/main/java/org/example/security/dto/AuthenticatedUser.java similarity index 100% rename from app/api/src/main/java/org/example/security/dto/AuthenticatedUser.java rename to app/api/user-api/src/main/java/org/example/security/dto/AuthenticatedUser.java diff --git a/app/api/src/main/java/org/example/security/dto/TokenParam.java b/app/api/user-api/src/main/java/org/example/security/dto/TokenParam.java similarity index 100% rename from app/api/src/main/java/org/example/security/dto/TokenParam.java rename to app/api/user-api/src/main/java/org/example/security/dto/TokenParam.java diff --git a/app/api/src/main/java/org/example/security/dto/UserParam.java b/app/api/user-api/src/main/java/org/example/security/dto/UserParam.java similarity index 100% rename from app/api/src/main/java/org/example/security/dto/UserParam.java rename to app/api/user-api/src/main/java/org/example/security/dto/UserParam.java diff --git a/app/api/src/main/java/org/example/security/token/JWTGenerator.java b/app/api/user-api/src/main/java/org/example/security/token/JWTGenerator.java similarity index 100% rename from app/api/src/main/java/org/example/security/token/JWTGenerator.java rename to app/api/user-api/src/main/java/org/example/security/token/JWTGenerator.java diff --git a/app/api/src/main/java/org/example/security/token/JWTHandler.java b/app/api/user-api/src/main/java/org/example/security/token/JWTHandler.java similarity index 100% rename from app/api/src/main/java/org/example/security/token/JWTHandler.java rename to app/api/user-api/src/main/java/org/example/security/token/JWTHandler.java diff --git a/app/api/src/main/java/org/example/security/token/RefreshTokenProcessor.java b/app/api/user-api/src/main/java/org/example/security/token/RefreshTokenProcessor.java similarity index 100% rename from app/api/src/main/java/org/example/security/token/RefreshTokenProcessor.java rename to app/api/user-api/src/main/java/org/example/security/token/RefreshTokenProcessor.java diff --git a/app/api/src/main/java/org/example/security/vo/TokenError.java b/app/api/user-api/src/main/java/org/example/security/vo/TokenError.java similarity index 100% rename from app/api/src/main/java/org/example/security/vo/TokenError.java rename to app/api/user-api/src/main/java/org/example/security/vo/TokenError.java diff --git a/app/api/src/main/java/org/example/vo/UserRoleApiType.java b/app/api/user-api/src/main/java/org/example/vo/UserRoleApiType.java similarity index 100% rename from app/api/src/main/java/org/example/vo/UserRoleApiType.java rename to app/api/user-api/src/main/java/org/example/vo/UserRoleApiType.java diff --git a/app/api/src/test/java/org/example/security/token/JWTGeneratorTest.java b/app/api/user-api/src/test/java/org/example/security/token/JWTGeneratorTest.java similarity index 100% rename from app/api/src/test/java/org/example/security/token/JWTGeneratorTest.java rename to app/api/user-api/src/test/java/org/example/security/token/JWTGeneratorTest.java diff --git a/app/api/src/test/java/org/example/security/token/JWTHandlerTest.java b/app/api/user-api/src/test/java/org/example/security/token/JWTHandlerTest.java similarity index 100% rename from app/api/src/test/java/org/example/security/token/JWTHandlerTest.java rename to app/api/user-api/src/test/java/org/example/security/token/JWTHandlerTest.java From 569689b2a49557bd90828c09e46c946305329080 Mon Sep 17 00:00:00 2001 From: GaBaljaintheroom Date: Thu, 6 Jun 2024 01:09:38 +0900 Subject: [PATCH 05/23] =?UTF-8?q?feat=20:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20?= =?UTF-8?q?=ED=9B=84=20=ED=86=A0=ED=81=B0=20=EB=B0=9C=EA=B8=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/org/example/config/UserApiConfig.java | 2 +- .../org/example/controller/UserController.java | 10 +++++----- .../org/example/dto/request/SignUpRequest.java | 15 +++++++++++++-- .../org/example/security/dto/UserParam.java | 5 +++++ .../java/org/example/service/UserService.java | 17 +++++++++++++++-- app/build.gradle | 1 + .../src/main/java/org/example/entity/User.java | 1 + .../java/org/example/usecase/UserUseCase.java | 2 ++ .../org/example/repository/RedisRepository.java | 6 +++--- docker-compose.yml | 2 +- 10 files changed, 47 insertions(+), 14 deletions(-) diff --git a/app/api/user-api/src/main/java/org/example/config/UserApiConfig.java b/app/api/user-api/src/main/java/org/example/config/UserApiConfig.java index 9b02a7a4..6a171aa5 100644 --- a/app/api/user-api/src/main/java/org/example/config/UserApiConfig.java +++ b/app/api/user-api/src/main/java/org/example/config/UserApiConfig.java @@ -7,7 +7,7 @@ import org.springframework.context.annotation.Import; @Configuration -@Import({UserDomainConfig.class, InfraStructureConfig.class}) +@Import(UserDomainConfig.class) @EnableConfigurationProperties(TokenProperty.class) @ComponentScan(basePackages = "org.example") public class UserApiConfig { diff --git a/app/api/user-api/src/main/java/org/example/controller/UserController.java b/app/api/user-api/src/main/java/org/example/controller/UserController.java index 41d80d58..1d08e276 100644 --- a/app/api/user-api/src/main/java/org/example/controller/UserController.java +++ b/app/api/user-api/src/main/java/org/example/controller/UserController.java @@ -5,6 +5,7 @@ import lombok.RequiredArgsConstructor; import org.example.dto.request.SignUpRequest; import org.example.entity.User; +import org.example.security.dto.TokenParam; import org.example.service.UserService; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PostMapping; @@ -20,13 +21,12 @@ public class UserController { private final UserService userService; @PostMapping("/sign-up") - @Operation(summary = "유저 회원가입", description = "사용자는 회원가입을 할 수 있다.", tags = {"user"}) - public ResponseEntity signUp(@Valid @RequestBody SignUpRequest request) { + @Operation(summary = "유저 로그인", description = "사용자는 소셜 로그인을 할 수 있다.", tags = {"user"}) + public ResponseEntity signUp(@Valid @RequestBody SignUpRequest request) { final User createdUser = request.toUser(); - final User user = userService.signUp(createdUser); - final String nickName = userService.findNickname(user); + TokenParam tokenParam = userService.signUp(createdUser); - return ResponseEntity.ok(nickName + "사용자 생성 성공!"); + return ResponseEntity.ok(tokenParam); } } diff --git a/app/api/user-api/src/main/java/org/example/dto/request/SignUpRequest.java b/app/api/user-api/src/main/java/org/example/dto/request/SignUpRequest.java index 06f97172..79e037dc 100644 --- a/app/api/user-api/src/main/java/org/example/dto/request/SignUpRequest.java +++ b/app/api/user-api/src/main/java/org/example/dto/request/SignUpRequest.java @@ -2,14 +2,25 @@ import jakarta.validation.constraints.NotNull; import org.example.entity.User; +import org.example.vo.SocialType; public record SignUpRequest( @NotNull(message = "닉네임은 필수 입력값입니다.") - String nickname + String nickname, + + @NotNull(message = "소셜 타입은 필수 입력값입니다.") + SocialType socialType, + + @NotNull(message = "소셜 식별자는 필수 입력값입니다.") + String socialIdentifier ) { public User toUser() { - return new User(nickname); + return User.builder() + .nickname(nickname) + .socialType(socialType) + .socialIdentifier(socialIdentifier) + .build(); } } diff --git a/app/api/user-api/src/main/java/org/example/security/dto/UserParam.java b/app/api/user-api/src/main/java/org/example/security/dto/UserParam.java index d0bd12d3..f9c7c653 100644 --- a/app/api/user-api/src/main/java/org/example/security/dto/UserParam.java +++ b/app/api/user-api/src/main/java/org/example/security/dto/UserParam.java @@ -3,6 +3,7 @@ import java.util.Map; import java.util.UUID; import lombok.Builder; +import org.example.vo.UserRole; import org.example.vo.UserRoleApiType; @Builder @@ -26,4 +27,8 @@ public static UserParam fromPayload(Object payload) { .role(UserRoleApiType.valueOf(claim.get("role"))) .build(); } + + public static UserParam as(UUID userId, UserRole userRole) { + return new UserParam(userId, UserRoleApiType.valueOf(userRole.name())); + } } diff --git a/app/api/user-api/src/main/java/org/example/service/UserService.java b/app/api/user-api/src/main/java/org/example/service/UserService.java index 20dc3565..bfca0737 100644 --- a/app/api/user-api/src/main/java/org/example/service/UserService.java +++ b/app/api/user-api/src/main/java/org/example/service/UserService.java @@ -1,7 +1,12 @@ package org.example.service; +import java.util.Date; import lombok.RequiredArgsConstructor; import org.example.entity.User; +import org.example.repository.RedisRepository; +import org.example.security.dto.TokenParam; +import org.example.security.dto.UserParam; +import org.example.security.token.JWTGenerator; import org.example.usecase.UserUseCase; import org.springframework.stereotype.Service; @@ -10,9 +15,17 @@ public class UserService { private final UserUseCase userUseCase; + private final JWTGenerator jwtGenerator; + private final RedisRepository redisRepository; - public User signUp(final User user) { - return userUseCase.save(user); + public TokenParam signUp(final User user) { + User createdUser = userUseCase.save(user); + UserParam userParam = UserParam.as(createdUser.getId(), createdUser.getUserRole()); + TokenParam tokenParam = jwtGenerator.generate(userParam, new Date()); + + redisRepository.save(userParam.userId().toString(), tokenParam.refreshToken()); + + return tokenParam; } public String findNickname(final User user) { diff --git a/app/build.gradle b/app/build.gradle index 24935494..b289b4f5 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -18,6 +18,7 @@ allprojects { dependencies { implementation "org.springframework.boot:spring-boot-starter-web" implementation project(":app:api") + implementation project(":app:infrastructure") // docker-compose developmentOnly 'org.springframework.boot:spring-boot-docker-compose' diff --git a/app/domain/user-domain/src/main/java/org/example/entity/User.java b/app/domain/user-domain/src/main/java/org/example/entity/User.java index 6d5b9caf..465f5a08 100644 --- a/app/domain/user-domain/src/main/java/org/example/entity/User.java +++ b/app/domain/user-domain/src/main/java/org/example/entity/User.java @@ -48,5 +48,6 @@ public class User extends BaseEntity { private User(String nickname, SocialType socialType, String socialIdentifier) { this.nickname = nickname; this.socialCredentials.put(socialType, socialIdentifier); + this.userRole = UserRole.USER; } } \ No newline at end of file diff --git a/app/domain/user-domain/src/main/java/org/example/usecase/UserUseCase.java b/app/domain/user-domain/src/main/java/org/example/usecase/UserUseCase.java index 331c3b2f..82d98121 100644 --- a/app/domain/user-domain/src/main/java/org/example/usecase/UserUseCase.java +++ b/app/domain/user-domain/src/main/java/org/example/usecase/UserUseCase.java @@ -4,6 +4,7 @@ import org.example.entity.User; import org.example.repository.UserRepository; import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; @Component @RequiredArgsConstructor @@ -11,6 +12,7 @@ public class UserUseCase { private final UserRepository userRepository; + @Transactional public User save(final User user) { return userRepository.save(user); } diff --git a/app/infrastructure/src/main/java/org/example/repository/RedisRepository.java b/app/infrastructure/src/main/java/org/example/repository/RedisRepository.java index 54e939c4..39095a03 100644 --- a/app/infrastructure/src/main/java/org/example/repository/RedisRepository.java +++ b/app/infrastructure/src/main/java/org/example/repository/RedisRepository.java @@ -2,17 +2,17 @@ import java.util.concurrent.TimeUnit; import lombok.RequiredArgsConstructor; -import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Repository; @Repository @RequiredArgsConstructor public class RedisRepository { - private final RedisTemplate redisTemplate; + private final StringRedisTemplate stringRedisTemplate; public final void save(String userId, String refreshToken) { - redisTemplate.opsForValue().set("userId:" + userId, refreshToken, 14, TimeUnit.DAYS); + stringRedisTemplate.opsForValue().set("userId:" + userId, refreshToken, 14, TimeUnit.DAYS); } } diff --git a/docker-compose.yml b/docker-compose.yml index 3c687d38..005bf304 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -16,4 +16,4 @@ services: container_name: yapp_redis image: redis:alpine ports: - - "6379:6379" \ No newline at end of file + - '6379:6379' \ No newline at end of file From 8b85938468bd3179e72b26256a1c7503cf0543c3 Mon Sep 17 00:00:00 2001 From: GaBaljaintheroom Date: Thu, 6 Jun 2024 01:34:10 +0900 Subject: [PATCH 06/23] =?UTF-8?q?refactor=20:=20redis=20=EC=97=B0=EA=B2=B0?= =?UTF-8?q?=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/org/example/repository/RedisRepository.java | 4 ++-- app/src/main/java/org/example/YappBackendApplication.java | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/app/infrastructure/src/main/java/org/example/repository/RedisRepository.java b/app/infrastructure/src/main/java/org/example/repository/RedisRepository.java index 39095a03..1f81fa2a 100644 --- a/app/infrastructure/src/main/java/org/example/repository/RedisRepository.java +++ b/app/infrastructure/src/main/java/org/example/repository/RedisRepository.java @@ -3,9 +3,9 @@ import java.util.concurrent.TimeUnit; import lombok.RequiredArgsConstructor; import org.springframework.data.redis.core.StringRedisTemplate; -import org.springframework.stereotype.Repository; +import org.springframework.stereotype.Component; -@Repository +@Component @RequiredArgsConstructor public class RedisRepository { diff --git a/app/src/main/java/org/example/YappBackendApplication.java b/app/src/main/java/org/example/YappBackendApplication.java index c8e2d838..b406a91f 100644 --- a/app/src/main/java/org/example/YappBackendApplication.java +++ b/app/src/main/java/org/example/YappBackendApplication.java @@ -1,12 +1,13 @@ package org.example; import org.example.config.ApiConfig; +import org.example.config.InfraStructureConfig; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Import; @SpringBootApplication -@Import(value = ApiConfig.class) +@Import(value = {ApiConfig.class, InfraStructureConfig.class}) public class YappBackendApplication { public static void main(String[] args) { From 8ea3bbded36aab4a424d5ca3128d89a37dc7509a Mon Sep 17 00:00:00 2001 From: GaBaljaintheroom Date: Fri, 7 Jun 2024 13:25:36 +0900 Subject: [PATCH 07/23] =?UTF-8?q?refactor=20:=20pr=20=EB=A6=AC=EB=B7=B0=20?= =?UTF-8?q?=ED=9B=84=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../example/controller/UserController.java | 4 +++- .../example/dto/request/SignUpRequest.java | 6 +++--- .../main/java/org/example/entity/User.java | 18 ++++++++--------- .../org/example/vo/SocialCredentials.java | 20 +++++++++++++++++++ .../{SocialType.java => SocialLoginType.java} | 2 +- app/src/main/resources/application-local.yml | 2 -- 6 files changed, 35 insertions(+), 17 deletions(-) create mode 100644 app/domain/user-domain/src/main/java/org/example/vo/SocialCredentials.java rename app/domain/user-domain/src/main/java/org/example/vo/{SocialType.java => SocialLoginType.java} (63%) diff --git a/app/api/user-api/src/main/java/org/example/controller/UserController.java b/app/api/user-api/src/main/java/org/example/controller/UserController.java index 1d08e276..f6ad63ef 100644 --- a/app/api/user-api/src/main/java/org/example/controller/UserController.java +++ b/app/api/user-api/src/main/java/org/example/controller/UserController.java @@ -1,6 +1,7 @@ package org.example.controller; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.example.dto.request.SignUpRequest; @@ -21,7 +22,8 @@ public class UserController { private final UserService userService; @PostMapping("/sign-up") - @Operation(summary = "유저 로그인", description = "사용자는 소셜 로그인을 할 수 있다.", tags = {"user"}) + @Tag(name = "user") + @Operation(summary = "유저 로그인", description = "사용자는 소셜 로그인을 할 수 있다.") public ResponseEntity signUp(@Valid @RequestBody SignUpRequest request) { final User createdUser = request.toUser(); TokenParam tokenParam = userService.signUp(createdUser); diff --git a/app/api/user-api/src/main/java/org/example/dto/request/SignUpRequest.java b/app/api/user-api/src/main/java/org/example/dto/request/SignUpRequest.java index 79e037dc..3bf2128f 100644 --- a/app/api/user-api/src/main/java/org/example/dto/request/SignUpRequest.java +++ b/app/api/user-api/src/main/java/org/example/dto/request/SignUpRequest.java @@ -2,7 +2,7 @@ import jakarta.validation.constraints.NotNull; import org.example.entity.User; -import org.example.vo.SocialType; +import org.example.vo.SocialLoginType; public record SignUpRequest( @@ -10,7 +10,7 @@ public record SignUpRequest( String nickname, @NotNull(message = "소셜 타입은 필수 입력값입니다.") - SocialType socialType, + SocialLoginType socialLoginType, @NotNull(message = "소셜 식별자는 필수 입력값입니다.") String socialIdentifier @@ -19,7 +19,7 @@ public record SignUpRequest( public User toUser() { return User.builder() .nickname(nickname) - .socialType(socialType) + .socialLoginType(socialLoginType) .socialIdentifier(socialIdentifier) .build(); } diff --git a/app/domain/user-domain/src/main/java/org/example/entity/User.java b/app/domain/user-domain/src/main/java/org/example/entity/User.java index 465f5a08..edc72914 100644 --- a/app/domain/user-domain/src/main/java/org/example/entity/User.java +++ b/app/domain/user-domain/src/main/java/org/example/entity/User.java @@ -1,22 +1,20 @@ package org.example.entity; -import io.hypersistence.utils.hibernate.type.json.JsonType; import jakarta.persistence.Column; +import jakarta.persistence.Embedded; import jakarta.persistence.Entity; import jakarta.persistence.EnumType; import jakarta.persistence.Enumerated; import jakarta.persistence.Table; import java.time.LocalDate; -import java.util.HashMap; -import java.util.Map; import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; -import org.example.vo.SocialType; +import org.example.vo.SocialCredentials; +import org.example.vo.SocialLoginType; import org.example.vo.UserGender; import org.example.vo.UserRole; -import org.hibernate.annotations.Type; @Entity @Getter @@ -32,9 +30,9 @@ public class User extends BaseEntity { @Column(name = "fcm_token") private String fcmToken; - @Type(JsonType.class) - @Column(name = "social_type", columnDefinition = "jsonb") - private Map socialCredentials = new HashMap<>(); + + @Embedded + private SocialCredentials socialCredentials = new SocialCredentials(); @Column(name = "gender") @Enumerated(value = EnumType.STRING) @@ -45,9 +43,9 @@ public class User extends BaseEntity { private UserRole userRole; @Builder - private User(String nickname, SocialType socialType, String socialIdentifier) { + private User(String nickname, SocialLoginType socialLoginType, String socialIdentifier) { this.nickname = nickname; - this.socialCredentials.put(socialType, socialIdentifier); + this.socialCredentials.put(socialLoginType, socialIdentifier); this.userRole = UserRole.USER; } } \ No newline at end of file diff --git a/app/domain/user-domain/src/main/java/org/example/vo/SocialCredentials.java b/app/domain/user-domain/src/main/java/org/example/vo/SocialCredentials.java new file mode 100644 index 00000000..c5c526b8 --- /dev/null +++ b/app/domain/user-domain/src/main/java/org/example/vo/SocialCredentials.java @@ -0,0 +1,20 @@ +package org.example.vo; + +import io.hypersistence.utils.hibernate.type.json.JsonType; +import jakarta.persistence.Column; +import jakarta.persistence.Embeddable; +import java.util.HashMap; +import java.util.Map; +import org.hibernate.annotations.Type; + +@Embeddable +public final class SocialCredentials { + + @Type(JsonType.class) + @Column(name = "social_credentials", columnDefinition = "jsonb", nullable = false) + private final Map socialCredentials = new HashMap<>(); + + public void put(SocialLoginType socialLoginType, String socialIdentifier) { + socialCredentials.put(socialLoginType, socialIdentifier); + } +} diff --git a/app/domain/user-domain/src/main/java/org/example/vo/SocialType.java b/app/domain/user-domain/src/main/java/org/example/vo/SocialLoginType.java similarity index 63% rename from app/domain/user-domain/src/main/java/org/example/vo/SocialType.java rename to app/domain/user-domain/src/main/java/org/example/vo/SocialLoginType.java index cd3a3c53..4c17827f 100644 --- a/app/domain/user-domain/src/main/java/org/example/vo/SocialType.java +++ b/app/domain/user-domain/src/main/java/org/example/vo/SocialLoginType.java @@ -1,5 +1,5 @@ package org.example.vo; -public enum SocialType { +public enum SocialLoginType { GOOGLE, KAKAO, APPLE } diff --git a/app/src/main/resources/application-local.yml b/app/src/main/resources/application-local.yml index cdb87b71..ecd45656 100644 --- a/app/src/main/resources/application-local.yml +++ b/app/src/main/resources/application-local.yml @@ -6,12 +6,10 @@ spring: stop: command: down timeout: 1m - security: user: name: user password: password - data: redis: host: localhost From 7bb9e275da2898e6a67496066608c0a246ad57ce Mon Sep 17 00:00:00 2001 From: GaBaljaintheroom Date: Sun, 9 Jun 2024 11:57:57 +0900 Subject: [PATCH 08/23] =?UTF-8?q?refactor=20:=20SocialCredentials=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 --- app/domain/user-domain/build.gradle | 1 + .../credential/AppleSocialCredential.java | 37 ++++++++++++++++++ .../credential/GoogleSocialCredential.java | 37 ++++++++++++++++++ .../credential/KakaoSocialCredential.java | 37 ++++++++++++++++++ .../entity/credential/SocialCredential.java | 18 +++++++++ .../entity/credential/SocialCredentials.java | 38 +++++++++++++++++++ .../org/example/vo/SocialCredentials.java | 20 ---------- 7 files changed, 168 insertions(+), 20 deletions(-) create mode 100644 app/domain/user-domain/src/main/java/org/example/entity/credential/AppleSocialCredential.java create mode 100644 app/domain/user-domain/src/main/java/org/example/entity/credential/GoogleSocialCredential.java create mode 100644 app/domain/user-domain/src/main/java/org/example/entity/credential/KakaoSocialCredential.java create mode 100644 app/domain/user-domain/src/main/java/org/example/entity/credential/SocialCredential.java create mode 100644 app/domain/user-domain/src/main/java/org/example/entity/credential/SocialCredentials.java delete mode 100644 app/domain/user-domain/src/main/java/org/example/vo/SocialCredentials.java diff --git a/app/domain/user-domain/build.gradle b/app/domain/user-domain/build.gradle index 17585d57..e9c84c6c 100644 --- a/app/domain/user-domain/build.gradle +++ b/app/domain/user-domain/build.gradle @@ -4,5 +4,6 @@ jar.enabled = true dependencies { // hypersistence utils implementation 'io.hypersistence:hypersistence-utils-hibernate-63:3.7.6' + implementation 'com.fasterxml.jackson.core:jackson-databind:2.15.4' implementation project(":app:domain") } diff --git a/app/domain/user-domain/src/main/java/org/example/entity/credential/AppleSocialCredential.java b/app/domain/user-domain/src/main/java/org/example/entity/credential/AppleSocialCredential.java new file mode 100644 index 00000000..71fb15ae --- /dev/null +++ b/app/domain/user-domain/src/main/java/org/example/entity/credential/AppleSocialCredential.java @@ -0,0 +1,37 @@ +package org.example.entity.credential; + +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +public final class AppleSocialCredential implements SocialCredential { + + private final Map credentialMap = new HashMap<>(); + + @Override + public void put(Object socialLoginType, String socialIdentifier) { + credentialMap.put(socialLoginType, socialIdentifier); + } + + @Override + public Map getCredentialMap() { + return credentialMap; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + AppleSocialCredential that = (AppleSocialCredential) o; + return Objects.equals(getCredentialMap(), that.getCredentialMap()); + } + + @Override + public int hashCode() { + return Objects.hash(getCredentialMap()); + } +} diff --git a/app/domain/user-domain/src/main/java/org/example/entity/credential/GoogleSocialCredential.java b/app/domain/user-domain/src/main/java/org/example/entity/credential/GoogleSocialCredential.java new file mode 100644 index 00000000..23dc9655 --- /dev/null +++ b/app/domain/user-domain/src/main/java/org/example/entity/credential/GoogleSocialCredential.java @@ -0,0 +1,37 @@ +package org.example.entity.credential; + +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +public final class GoogleSocialCredential implements SocialCredential { + + private final Map credentialMap = new HashMap<>(); + + @Override + public void put(Object socialLoginType, String socialIdentifier) { + credentialMap.put(socialLoginType, socialIdentifier); + } + + @Override + public Map getCredentialMap() { + return credentialMap; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + GoogleSocialCredential that = (GoogleSocialCredential) o; + return Objects.equals(getCredentialMap(), that.getCredentialMap()); + } + + @Override + public int hashCode() { + return Objects.hash(getCredentialMap()); + } +} diff --git a/app/domain/user-domain/src/main/java/org/example/entity/credential/KakaoSocialCredential.java b/app/domain/user-domain/src/main/java/org/example/entity/credential/KakaoSocialCredential.java new file mode 100644 index 00000000..4ba1ecee --- /dev/null +++ b/app/domain/user-domain/src/main/java/org/example/entity/credential/KakaoSocialCredential.java @@ -0,0 +1,37 @@ +package org.example.entity.credential; + +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +public final class KakaoSocialCredential implements SocialCredential { + + private final Map credentialMap = new HashMap<>(); + + @Override + public void put(Object socialLoginType, String socialIdentifier) { + credentialMap.put(socialLoginType, socialIdentifier); + } + + @Override + public Map getCredentialMap() { + return credentialMap; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + KakaoSocialCredential that = (KakaoSocialCredential) o; + return Objects.equals(getCredentialMap(), that.getCredentialMap()); + } + + @Override + public int hashCode() { + return Objects.hash(getCredentialMap()); + } +} diff --git a/app/domain/user-domain/src/main/java/org/example/entity/credential/SocialCredential.java b/app/domain/user-domain/src/main/java/org/example/entity/credential/SocialCredential.java new file mode 100644 index 00000000..e50dbe76 --- /dev/null +++ b/app/domain/user-domain/src/main/java/org/example/entity/credential/SocialCredential.java @@ -0,0 +1,18 @@ +package org.example.entity.credential; + +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import java.util.Map; + +public sealed interface SocialCredential permits AppleSocialCredential, GoogleSocialCredential, + KakaoSocialCredential { + + + @JsonAnySetter + void put(Object socialLoginType, String socialIdentifier); + + @JsonAnyGetter + Map getCredentialMap(); + + +} diff --git a/app/domain/user-domain/src/main/java/org/example/entity/credential/SocialCredentials.java b/app/domain/user-domain/src/main/java/org/example/entity/credential/SocialCredentials.java new file mode 100644 index 00000000..f2ff2e62 --- /dev/null +++ b/app/domain/user-domain/src/main/java/org/example/entity/credential/SocialCredentials.java @@ -0,0 +1,38 @@ +package org.example.entity.credential; + +import io.hypersistence.utils.hibernate.type.json.JsonType; +import jakarta.persistence.Column; +import jakarta.persistence.Embeddable; +import java.util.ArrayList; +import java.util.List; +import org.example.vo.SocialLoginType; +import org.hibernate.annotations.Type; + +@Embeddable +public final class SocialCredentials { + + @Type(JsonType.class) + @Column(name = "social_credentials", columnDefinition = "jsonb", nullable = false) + private final List socialCredentials = new ArrayList<>(); + + public void put(SocialLoginType socialLoginType, String socialIdentifier) { + SocialCredential socialCredential = getSocialCredential(socialLoginType, socialIdentifier); + socialCredentials.add(socialCredential); + } + + private SocialCredential getSocialCredential( + SocialLoginType socialLoginType, + String socialIdentifier + ) { + SocialCredential socialCredential; + switch (socialLoginType) { + case GOOGLE -> socialCredential = new GoogleSocialCredential(); + case KAKAO -> socialCredential = new KakaoSocialCredential(); + case APPLE -> socialCredential = new AppleSocialCredential(); + default -> socialCredential = null; + } + socialCredential.put(socialLoginType, socialIdentifier); + return socialCredential; + } + +} \ No newline at end of file diff --git a/app/domain/user-domain/src/main/java/org/example/vo/SocialCredentials.java b/app/domain/user-domain/src/main/java/org/example/vo/SocialCredentials.java deleted file mode 100644 index c5c526b8..00000000 --- a/app/domain/user-domain/src/main/java/org/example/vo/SocialCredentials.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.example.vo; - -import io.hypersistence.utils.hibernate.type.json.JsonType; -import jakarta.persistence.Column; -import jakarta.persistence.Embeddable; -import java.util.HashMap; -import java.util.Map; -import org.hibernate.annotations.Type; - -@Embeddable -public final class SocialCredentials { - - @Type(JsonType.class) - @Column(name = "social_credentials", columnDefinition = "jsonb", nullable = false) - private final Map socialCredentials = new HashMap<>(); - - public void put(SocialLoginType socialLoginType, String socialIdentifier) { - socialCredentials.put(socialLoginType, socialIdentifier); - } -} From d9314ad7396dfa094044248281376dd52d720af1 Mon Sep 17 00:00:00 2001 From: GaBaljaintheroom Date: Sun, 9 Jun 2024 12:45:31 +0900 Subject: [PATCH 09/23] =?UTF-8?q?refactor=20:=20BaseEntity=20persistable?= =?UTF-8?q?=20=EC=B6=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/api/build.gradle | 3 +++ .../src/main/java/org/example/entity/BaseEntity.java | 8 +++++++- .../src/main/java/org/example/entity/User.java | 2 +- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/app/api/build.gradle b/app/api/build.gradle index 3c18fdc5..7365f964 100644 --- a/app/api/build.gradle +++ b/app/api/build.gradle @@ -6,6 +6,9 @@ allprojects { //swagger implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.5.0' + implementation 'org.springframework.data:spring-data-commons:3.3.0' + + implementation "org.springframework.boot:spring-boot-starter-web" implementation 'org.springframework.boot:spring-boot-starter-validation' testImplementation "org.springframework.boot:spring-boot-starter-test" diff --git a/app/domain/src/main/java/org/example/entity/BaseEntity.java b/app/domain/src/main/java/org/example/entity/BaseEntity.java index ae5cd0d3..5dc362bf 100644 --- a/app/domain/src/main/java/org/example/entity/BaseEntity.java +++ b/app/domain/src/main/java/org/example/entity/BaseEntity.java @@ -10,12 +10,13 @@ import lombok.Getter; import org.springframework.data.annotation.CreatedDate; import org.springframework.data.annotation.LastModifiedDate; +import org.springframework.data.domain.Persistable; import org.springframework.data.jpa.domain.support.AuditingEntityListener; @Getter @EntityListeners(value = {AuditingEntityListener.class}) @MappedSuperclass -public abstract class BaseEntity { +public abstract class BaseEntity implements Persistable { @Id @Column(name = "id") @@ -28,4 +29,9 @@ public abstract class BaseEntity { @LastModifiedDate @Column(name = "updated_at", nullable = false) private LocalDateTime updatedAt; + + @Override + public boolean isNew() { + return id != null; + } } \ No newline at end of file diff --git a/app/domain/user-domain/src/main/java/org/example/entity/User.java b/app/domain/user-domain/src/main/java/org/example/entity/User.java index edc72914..0938f2a3 100644 --- a/app/domain/user-domain/src/main/java/org/example/entity/User.java +++ b/app/domain/user-domain/src/main/java/org/example/entity/User.java @@ -11,7 +11,7 @@ import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; -import org.example.vo.SocialCredentials; +import org.example.entity.credential.SocialCredentials; import org.example.vo.SocialLoginType; import org.example.vo.UserGender; import org.example.vo.UserRole; From f0cc8893f4ae031da2f84b5271ce873723e9bd84 Mon Sep 17 00:00:00 2001 From: GaBaljaintheroom Date: Sun, 9 Jun 2024 13:05:04 +0900 Subject: [PATCH 10/23] =?UTF-8?q?refactor=20:=20common-api=20=EB=AA=A8?= =?UTF-8?q?=EB=93=88=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/api/build.gradle | 4 +--- app/api/common-api/build.gradle | 15 +++++++++++++++ .../java/org/example/config/CommonApiConfig.java | 10 ++++++++++ .../java/org/example/config/SecurityConfig.java | 0 .../java/org/example/config/SwaggerConfig.java | 0 .../org/example/error/GlobalExceptionHandler.java | 0 .../example/filter/ExceptionHandlerFilter.java | 0 .../main/java/org/example/filter/JWTFilter.java | 0 .../java/org/example/property/TokenProperty.java | 0 .../example/security/dto/AuthenticatedUser.java | 0 .../java/org/example/security/dto/TokenParam.java | 0 .../java/org/example/security/dto/UserParam.java | 0 .../org/example/security/token/JWTGenerator.java | 0 .../org/example/security/token/JWTHandler.java | 0 .../security/token/RefreshTokenProcessor.java | 0 .../java/org/example/security/vo/TokenError.java | 0 .../main/java/org/example/vo/UserRoleApiType.java | 0 .../example/security/token/JWTGeneratorTest.java | 0 .../example/security/token/JWTHandlerTest.java | 0 .../main/java/org/example/config/ApiConfig.java | 4 +--- app/api/user-api/build.gradle | 7 ++----- settings.gradle | 1 + 22 files changed, 30 insertions(+), 11 deletions(-) create mode 100644 app/api/common-api/build.gradle create mode 100644 app/api/common-api/src/main/java/org/example/config/CommonApiConfig.java rename app/api/{ => common-api}/src/main/java/org/example/config/SecurityConfig.java (100%) rename app/api/{ => common-api}/src/main/java/org/example/config/SwaggerConfig.java (100%) rename app/api/{ => common-api}/src/main/java/org/example/error/GlobalExceptionHandler.java (100%) rename app/api/{ => common-api}/src/main/java/org/example/filter/ExceptionHandlerFilter.java (100%) rename app/api/{ => common-api}/src/main/java/org/example/filter/JWTFilter.java (100%) rename app/api/{user-api => common-api}/src/main/java/org/example/property/TokenProperty.java (100%) rename app/api/{user-api => common-api}/src/main/java/org/example/security/dto/AuthenticatedUser.java (100%) rename app/api/{user-api => common-api}/src/main/java/org/example/security/dto/TokenParam.java (100%) rename app/api/{user-api => common-api}/src/main/java/org/example/security/dto/UserParam.java (100%) rename app/api/{user-api => common-api}/src/main/java/org/example/security/token/JWTGenerator.java (100%) rename app/api/{user-api => common-api}/src/main/java/org/example/security/token/JWTHandler.java (100%) rename app/api/{user-api => common-api}/src/main/java/org/example/security/token/RefreshTokenProcessor.java (100%) rename app/api/{user-api => common-api}/src/main/java/org/example/security/vo/TokenError.java (100%) rename app/api/{user-api => common-api}/src/main/java/org/example/vo/UserRoleApiType.java (100%) rename app/api/{user-api => common-api}/src/test/java/org/example/security/token/JWTGeneratorTest.java (100%) rename app/api/{user-api => common-api}/src/test/java/org/example/security/token/JWTHandlerTest.java (100%) diff --git a/app/api/build.gradle b/app/api/build.gradle index 7365f964..9c8880d7 100644 --- a/app/api/build.gradle +++ b/app/api/build.gradle @@ -17,7 +17,5 @@ allprojects { dependencies { implementation project(":app:api:user-api") - - // spring-security - implementation 'org.springframework.boot:spring-boot-starter-security' + implementation project(":app:api:common-api") } \ No newline at end of file diff --git a/app/api/common-api/build.gradle b/app/api/common-api/build.gradle new file mode 100644 index 00000000..117e9bee --- /dev/null +++ b/app/api/common-api/build.gradle @@ -0,0 +1,15 @@ +bootJar.enabled = false +jar.enabled = true + +dependencies { + implementation project(":app:domain:user-domain") + implementation project(":app:infrastructure") + + // spring-security + implementation 'org.springframework.boot:spring-boot-starter-security' + + // jwt + implementation 'io.jsonwebtoken:jjwt-api:0.12.5' + runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.12.5' + runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.12.5' +} \ No newline at end of file diff --git a/app/api/common-api/src/main/java/org/example/config/CommonApiConfig.java b/app/api/common-api/src/main/java/org/example/config/CommonApiConfig.java new file mode 100644 index 00000000..2b344e0f --- /dev/null +++ b/app/api/common-api/src/main/java/org/example/config/CommonApiConfig.java @@ -0,0 +1,10 @@ +package org.example.config; + +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +@Configuration +@ComponentScan(basePackages = "org.example") +public class CommonApiConfig { + +} diff --git a/app/api/src/main/java/org/example/config/SecurityConfig.java b/app/api/common-api/src/main/java/org/example/config/SecurityConfig.java similarity index 100% rename from app/api/src/main/java/org/example/config/SecurityConfig.java rename to app/api/common-api/src/main/java/org/example/config/SecurityConfig.java diff --git a/app/api/src/main/java/org/example/config/SwaggerConfig.java b/app/api/common-api/src/main/java/org/example/config/SwaggerConfig.java similarity index 100% rename from app/api/src/main/java/org/example/config/SwaggerConfig.java rename to app/api/common-api/src/main/java/org/example/config/SwaggerConfig.java diff --git a/app/api/src/main/java/org/example/error/GlobalExceptionHandler.java b/app/api/common-api/src/main/java/org/example/error/GlobalExceptionHandler.java similarity index 100% rename from app/api/src/main/java/org/example/error/GlobalExceptionHandler.java rename to app/api/common-api/src/main/java/org/example/error/GlobalExceptionHandler.java diff --git a/app/api/src/main/java/org/example/filter/ExceptionHandlerFilter.java b/app/api/common-api/src/main/java/org/example/filter/ExceptionHandlerFilter.java similarity index 100% rename from app/api/src/main/java/org/example/filter/ExceptionHandlerFilter.java rename to app/api/common-api/src/main/java/org/example/filter/ExceptionHandlerFilter.java diff --git a/app/api/src/main/java/org/example/filter/JWTFilter.java b/app/api/common-api/src/main/java/org/example/filter/JWTFilter.java similarity index 100% rename from app/api/src/main/java/org/example/filter/JWTFilter.java rename to app/api/common-api/src/main/java/org/example/filter/JWTFilter.java diff --git a/app/api/user-api/src/main/java/org/example/property/TokenProperty.java b/app/api/common-api/src/main/java/org/example/property/TokenProperty.java similarity index 100% rename from app/api/user-api/src/main/java/org/example/property/TokenProperty.java rename to app/api/common-api/src/main/java/org/example/property/TokenProperty.java diff --git a/app/api/user-api/src/main/java/org/example/security/dto/AuthenticatedUser.java b/app/api/common-api/src/main/java/org/example/security/dto/AuthenticatedUser.java similarity index 100% rename from app/api/user-api/src/main/java/org/example/security/dto/AuthenticatedUser.java rename to app/api/common-api/src/main/java/org/example/security/dto/AuthenticatedUser.java diff --git a/app/api/user-api/src/main/java/org/example/security/dto/TokenParam.java b/app/api/common-api/src/main/java/org/example/security/dto/TokenParam.java similarity index 100% rename from app/api/user-api/src/main/java/org/example/security/dto/TokenParam.java rename to app/api/common-api/src/main/java/org/example/security/dto/TokenParam.java diff --git a/app/api/user-api/src/main/java/org/example/security/dto/UserParam.java b/app/api/common-api/src/main/java/org/example/security/dto/UserParam.java similarity index 100% rename from app/api/user-api/src/main/java/org/example/security/dto/UserParam.java rename to app/api/common-api/src/main/java/org/example/security/dto/UserParam.java diff --git a/app/api/user-api/src/main/java/org/example/security/token/JWTGenerator.java b/app/api/common-api/src/main/java/org/example/security/token/JWTGenerator.java similarity index 100% rename from app/api/user-api/src/main/java/org/example/security/token/JWTGenerator.java rename to app/api/common-api/src/main/java/org/example/security/token/JWTGenerator.java diff --git a/app/api/user-api/src/main/java/org/example/security/token/JWTHandler.java b/app/api/common-api/src/main/java/org/example/security/token/JWTHandler.java similarity index 100% rename from app/api/user-api/src/main/java/org/example/security/token/JWTHandler.java rename to app/api/common-api/src/main/java/org/example/security/token/JWTHandler.java diff --git a/app/api/user-api/src/main/java/org/example/security/token/RefreshTokenProcessor.java b/app/api/common-api/src/main/java/org/example/security/token/RefreshTokenProcessor.java similarity index 100% rename from app/api/user-api/src/main/java/org/example/security/token/RefreshTokenProcessor.java rename to app/api/common-api/src/main/java/org/example/security/token/RefreshTokenProcessor.java diff --git a/app/api/user-api/src/main/java/org/example/security/vo/TokenError.java b/app/api/common-api/src/main/java/org/example/security/vo/TokenError.java similarity index 100% rename from app/api/user-api/src/main/java/org/example/security/vo/TokenError.java rename to app/api/common-api/src/main/java/org/example/security/vo/TokenError.java diff --git a/app/api/user-api/src/main/java/org/example/vo/UserRoleApiType.java b/app/api/common-api/src/main/java/org/example/vo/UserRoleApiType.java similarity index 100% rename from app/api/user-api/src/main/java/org/example/vo/UserRoleApiType.java rename to app/api/common-api/src/main/java/org/example/vo/UserRoleApiType.java diff --git a/app/api/user-api/src/test/java/org/example/security/token/JWTGeneratorTest.java b/app/api/common-api/src/test/java/org/example/security/token/JWTGeneratorTest.java similarity index 100% rename from app/api/user-api/src/test/java/org/example/security/token/JWTGeneratorTest.java rename to app/api/common-api/src/test/java/org/example/security/token/JWTGeneratorTest.java diff --git a/app/api/user-api/src/test/java/org/example/security/token/JWTHandlerTest.java b/app/api/common-api/src/test/java/org/example/security/token/JWTHandlerTest.java similarity index 100% rename from app/api/user-api/src/test/java/org/example/security/token/JWTHandlerTest.java rename to app/api/common-api/src/test/java/org/example/security/token/JWTHandlerTest.java diff --git a/app/api/src/main/java/org/example/config/ApiConfig.java b/app/api/src/main/java/org/example/config/ApiConfig.java index 60cdde5f..f7c59525 100644 --- a/app/api/src/main/java/org/example/config/ApiConfig.java +++ b/app/api/src/main/java/org/example/config/ApiConfig.java @@ -1,12 +1,10 @@ package org.example.config; -import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; @Configuration -@Import(UserApiConfig.class) -@ComponentScan(basePackages = "org.example") +@Import({UserApiConfig.class, CommonApiConfig.class}) public class ApiConfig { } diff --git a/app/api/user-api/build.gradle b/app/api/user-api/build.gradle index b5f8474a..d2099be0 100644 --- a/app/api/user-api/build.gradle +++ b/app/api/user-api/build.gradle @@ -5,10 +5,7 @@ dependencies { implementation project(":app:domain") implementation project(":app:domain:user-domain") - implementation project(":app:infrastructure") + implementation project(":app:api:common-api") - // jwt - implementation 'io.jsonwebtoken:jjwt-api:0.12.5' - runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.12.5' - runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.12.5' + implementation project(":app:infrastructure") } \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index 7886b341..e8971820 100644 --- a/settings.gradle +++ b/settings.gradle @@ -8,6 +8,7 @@ include(":app:domain") include(":app:domain:user-domain") include(":app:api") +include (":app:api:common-api") include(":app:api:user-api") include (":app:infrastructure") From 754672e071c11106c63b88f10b9418c3fe62157f Mon Sep 17 00:00:00 2001 From: GaBaljaintheroom Date: Sun, 9 Jun 2024 22:18:18 +0900 Subject: [PATCH 11/23] =?UTF-8?q?refactor=20:=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=EB=AA=A8=EB=93=88=20import=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle | 1 + .../src/main/java/org/example/config/DomainConfig.java | 10 ++++++++++ .../src/main/java/org/example/entity/BaseEntity.java | 2 +- .../main/java/org/example/YappBackendApplication.java | 3 ++- 4 files changed, 14 insertions(+), 2 deletions(-) create mode 100644 app/domain/src/main/java/org/example/config/DomainConfig.java diff --git a/app/build.gradle b/app/build.gradle index b289b4f5..ef8549a7 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -18,6 +18,7 @@ allprojects { dependencies { implementation "org.springframework.boot:spring-boot-starter-web" implementation project(":app:api") + implementation project(":app:domain") implementation project(":app:infrastructure") // docker-compose diff --git a/app/domain/src/main/java/org/example/config/DomainConfig.java b/app/domain/src/main/java/org/example/config/DomainConfig.java new file mode 100644 index 00000000..00d2b26f --- /dev/null +++ b/app/domain/src/main/java/org/example/config/DomainConfig.java @@ -0,0 +1,10 @@ +package org.example.config; + +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +@Configuration +@ComponentScan(basePackages = "org.example") +public class DomainConfig { + +} \ No newline at end of file diff --git a/app/domain/src/main/java/org/example/entity/BaseEntity.java b/app/domain/src/main/java/org/example/entity/BaseEntity.java index 5dc362bf..79965457 100644 --- a/app/domain/src/main/java/org/example/entity/BaseEntity.java +++ b/app/domain/src/main/java/org/example/entity/BaseEntity.java @@ -19,7 +19,7 @@ public abstract class BaseEntity implements Persistable { @Id - @Column(name = "id") + @Column(name = "id", updatable = false, nullable = false) private UUID id = UlidCreator.getMonotonicUlid().toUuid(); @CreatedDate diff --git a/app/src/main/java/org/example/YappBackendApplication.java b/app/src/main/java/org/example/YappBackendApplication.java index b406a91f..57c69cd5 100644 --- a/app/src/main/java/org/example/YappBackendApplication.java +++ b/app/src/main/java/org/example/YappBackendApplication.java @@ -1,13 +1,14 @@ package org.example; import org.example.config.ApiConfig; +import org.example.config.DomainConfig; import org.example.config.InfraStructureConfig; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Import; @SpringBootApplication -@Import(value = {ApiConfig.class, InfraStructureConfig.class}) +@Import(value = {ApiConfig.class, DomainConfig.class, InfraStructureConfig.class}) public class YappBackendApplication { public static void main(String[] args) { From 5c515393ad3959e8475ce9b1987cd24e884b59aa Mon Sep 17 00:00:00 2001 From: GaBaljaintheroom Date: Sun, 9 Jun 2024 22:30:05 +0900 Subject: [PATCH 12/23] =?UTF-8?q?refactor=20:=20Infrastructure=20=EC=9D=98?= =?UTF-8?q?=EC=A1=B4=EC=84=B1=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/api/common-api/build.gradle | 1 - .../main/java/org/example/config/CommonApiConfig.java | 3 +++ .../java/org/example/repository/RedisRepository.java | 9 +++++++++ app/api/user-api/build.gradle | 2 -- .../src/main/java/org/example/config/UserApiConfig.java | 3 --- .../java/org/example/repository/RedisRepository.java | 9 +++++++++ app/infrastructure/build.gradle | 7 +++++-- ...{RedisRepository.java => LettuceRedisRepository.java} | 4 ++-- 8 files changed, 28 insertions(+), 10 deletions(-) create mode 100644 app/api/common-api/src/main/java/org/example/repository/RedisRepository.java create mode 100644 app/api/user-api/src/main/java/org/example/repository/RedisRepository.java rename app/infrastructure/src/main/java/org/example/repository/{RedisRepository.java => LettuceRedisRepository.java} (77%) diff --git a/app/api/common-api/build.gradle b/app/api/common-api/build.gradle index 117e9bee..851f64ac 100644 --- a/app/api/common-api/build.gradle +++ b/app/api/common-api/build.gradle @@ -3,7 +3,6 @@ jar.enabled = true dependencies { implementation project(":app:domain:user-domain") - implementation project(":app:infrastructure") // spring-security implementation 'org.springframework.boot:spring-boot-starter-security' diff --git a/app/api/common-api/src/main/java/org/example/config/CommonApiConfig.java b/app/api/common-api/src/main/java/org/example/config/CommonApiConfig.java index 2b344e0f..22e13e2b 100644 --- a/app/api/common-api/src/main/java/org/example/config/CommonApiConfig.java +++ b/app/api/common-api/src/main/java/org/example/config/CommonApiConfig.java @@ -1,9 +1,12 @@ package org.example.config; +import org.example.property.TokenProperty; +import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; @Configuration +@EnableConfigurationProperties(TokenProperty.class) @ComponentScan(basePackages = "org.example") public class CommonApiConfig { diff --git a/app/api/common-api/src/main/java/org/example/repository/RedisRepository.java b/app/api/common-api/src/main/java/org/example/repository/RedisRepository.java new file mode 100644 index 00000000..d7d1782b --- /dev/null +++ b/app/api/common-api/src/main/java/org/example/repository/RedisRepository.java @@ -0,0 +1,9 @@ +package org.example.repository; + +import org.springframework.stereotype.Component; + +@Component +public interface RedisRepository { + + void save(String userId, String refreshToken); +} diff --git a/app/api/user-api/build.gradle b/app/api/user-api/build.gradle index d2099be0..336ab82b 100644 --- a/app/api/user-api/build.gradle +++ b/app/api/user-api/build.gradle @@ -6,6 +6,4 @@ dependencies { implementation project(":app:domain:user-domain") implementation project(":app:api:common-api") - - implementation project(":app:infrastructure") } \ No newline at end of file diff --git a/app/api/user-api/src/main/java/org/example/config/UserApiConfig.java b/app/api/user-api/src/main/java/org/example/config/UserApiConfig.java index 6a171aa5..0d709c9d 100644 --- a/app/api/user-api/src/main/java/org/example/config/UserApiConfig.java +++ b/app/api/user-api/src/main/java/org/example/config/UserApiConfig.java @@ -1,14 +1,11 @@ package org.example.config; -import org.example.property.TokenProperty; -import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; @Configuration @Import(UserDomainConfig.class) -@EnableConfigurationProperties(TokenProperty.class) @ComponentScan(basePackages = "org.example") public class UserApiConfig { diff --git a/app/api/user-api/src/main/java/org/example/repository/RedisRepository.java b/app/api/user-api/src/main/java/org/example/repository/RedisRepository.java new file mode 100644 index 00000000..d7d1782b --- /dev/null +++ b/app/api/user-api/src/main/java/org/example/repository/RedisRepository.java @@ -0,0 +1,9 @@ +package org.example.repository; + +import org.springframework.stereotype.Component; + +@Component +public interface RedisRepository { + + void save(String userId, String refreshToken); +} diff --git a/app/infrastructure/build.gradle b/app/infrastructure/build.gradle index 349cd938..0057522c 100644 --- a/app/infrastructure/build.gradle +++ b/app/infrastructure/build.gradle @@ -1,7 +1,10 @@ -bootJar.enabled = false; -jar.enabled = true; +bootJar.enabled = false +jar.enabled = true dependencies { + implementation project(":app:api:user-api") + implementation project(":app:api:common-api") + implementation "org.springframework.boot:spring-boot-starter-web" //redis diff --git a/app/infrastructure/src/main/java/org/example/repository/RedisRepository.java b/app/infrastructure/src/main/java/org/example/repository/LettuceRedisRepository.java similarity index 77% rename from app/infrastructure/src/main/java/org/example/repository/RedisRepository.java rename to app/infrastructure/src/main/java/org/example/repository/LettuceRedisRepository.java index 1f81fa2a..5d22c252 100644 --- a/app/infrastructure/src/main/java/org/example/repository/RedisRepository.java +++ b/app/infrastructure/src/main/java/org/example/repository/LettuceRedisRepository.java @@ -7,11 +7,11 @@ @Component @RequiredArgsConstructor -public class RedisRepository { +public class LettuceRedisRepository implements RedisRepository { private final StringRedisTemplate stringRedisTemplate; - public final void save(String userId, String refreshToken) { + public void save(String userId, String refreshToken) { stringRedisTemplate.opsForValue().set("userId:" + userId, refreshToken, 14, TimeUnit.DAYS); } From b644a49e94665319953688d8c81f3063f7240326 Mon Sep 17 00:00:00 2001 From: GaBaljaintheroom Date: Tue, 11 Jun 2024 20:52:49 +0900 Subject: [PATCH 13/23] =?UTF-8?q?refactor=20:=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EB=A6=AC=EB=B7=B0=20=ED=9B=84=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/api/build.gradle | 1 - app/api/common-api/build.gradle | 2 - .../org/example/security/dto/UserParam.java | 5 --- .../example/controller/UserController.java | 10 ++--- .../java/org/example/dto/LoginApiDto.java | 17 ++++++++ .../example/dto/request/LoginApiRequest.java | 17 ++++++++ .../example/dto/request/SignUpRequest.java | 26 ------------ .../java/org/example/service/UserService.java | 11 +++-- app/build.gradle | 1 - app/domain/user-domain/build.gradle | 5 ++- .../main/java/org/example/entity/User.java | 20 +++++----- .../credential/AppleSocialCredential.java | 38 ++++-------------- .../credential/GoogleSocialCredential.java | 40 +++++-------------- .../credential/KakaoSocialCredential.java | 39 ++++-------------- .../entity/credential/SocialCredential.java | 21 +++++----- .../entity/credential/SocialCredentials.java | 38 ------------------ ...eConfig.java => InfrastructureConfig.java} | 2 +- .../org/example/YappBackendApplication.java | 5 +-- 18 files changed, 99 insertions(+), 199 deletions(-) create mode 100644 app/api/user-api/src/main/java/org/example/dto/LoginApiDto.java create mode 100644 app/api/user-api/src/main/java/org/example/dto/request/LoginApiRequest.java delete mode 100644 app/api/user-api/src/main/java/org/example/dto/request/SignUpRequest.java delete mode 100644 app/domain/user-domain/src/main/java/org/example/entity/credential/SocialCredentials.java rename app/infrastructure/src/main/java/org/example/config/{InfraStructureConfig.java => InfrastructureConfig.java} (91%) diff --git a/app/api/build.gradle b/app/api/build.gradle index 9c8880d7..4faf9f94 100644 --- a/app/api/build.gradle +++ b/app/api/build.gradle @@ -8,7 +8,6 @@ allprojects { implementation 'org.springframework.data:spring-data-commons:3.3.0' - implementation "org.springframework.boot:spring-boot-starter-web" implementation 'org.springframework.boot:spring-boot-starter-validation' testImplementation "org.springframework.boot:spring-boot-starter-test" diff --git a/app/api/common-api/build.gradle b/app/api/common-api/build.gradle index 851f64ac..681b65f9 100644 --- a/app/api/common-api/build.gradle +++ b/app/api/common-api/build.gradle @@ -2,8 +2,6 @@ bootJar.enabled = false jar.enabled = true dependencies { - implementation project(":app:domain:user-domain") - // spring-security implementation 'org.springframework.boot:spring-boot-starter-security' diff --git a/app/api/common-api/src/main/java/org/example/security/dto/UserParam.java b/app/api/common-api/src/main/java/org/example/security/dto/UserParam.java index f9c7c653..d0bd12d3 100644 --- a/app/api/common-api/src/main/java/org/example/security/dto/UserParam.java +++ b/app/api/common-api/src/main/java/org/example/security/dto/UserParam.java @@ -3,7 +3,6 @@ import java.util.Map; import java.util.UUID; import lombok.Builder; -import org.example.vo.UserRole; import org.example.vo.UserRoleApiType; @Builder @@ -27,8 +26,4 @@ public static UserParam fromPayload(Object payload) { .role(UserRoleApiType.valueOf(claim.get("role"))) .build(); } - - public static UserParam as(UUID userId, UserRole userRole) { - return new UserParam(userId, UserRoleApiType.valueOf(userRole.name())); - } } diff --git a/app/api/user-api/src/main/java/org/example/controller/UserController.java b/app/api/user-api/src/main/java/org/example/controller/UserController.java index f6ad63ef..0a71dadc 100644 --- a/app/api/user-api/src/main/java/org/example/controller/UserController.java +++ b/app/api/user-api/src/main/java/org/example/controller/UserController.java @@ -4,8 +4,8 @@ import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; -import org.example.dto.request.SignUpRequest; -import org.example.entity.User; +import org.example.dto.LoginApiDto; +import org.example.dto.request.LoginApiRequest; import org.example.security.dto.TokenParam; import org.example.service.UserService; import org.springframework.http.ResponseEntity; @@ -24,9 +24,9 @@ public class UserController { @PostMapping("/sign-up") @Tag(name = "user") @Operation(summary = "유저 로그인", description = "사용자는 소셜 로그인을 할 수 있다.") - public ResponseEntity signUp(@Valid @RequestBody SignUpRequest request) { - final User createdUser = request.toUser(); - TokenParam tokenParam = userService.signUp(createdUser); + public ResponseEntity signUp(@Valid @RequestBody LoginApiRequest request) { + final LoginApiDto loginApiDto = request.toLoginApiDto(); + TokenParam tokenParam = userService.login(loginApiDto); return ResponseEntity.ok(tokenParam); } diff --git a/app/api/user-api/src/main/java/org/example/dto/LoginApiDto.java b/app/api/user-api/src/main/java/org/example/dto/LoginApiDto.java new file mode 100644 index 00000000..f566be1b --- /dev/null +++ b/app/api/user-api/src/main/java/org/example/dto/LoginApiDto.java @@ -0,0 +1,17 @@ +package org.example.dto; + +import lombok.Builder; +import org.example.entity.User; +import org.example.entity.credential.SocialCredential; + +@Builder +public record LoginApiDto( + SocialCredential socialCredential +) { + + public User toUser() { + return User.builder() + .socialCredential(socialCredential) + .build(); + } +} diff --git a/app/api/user-api/src/main/java/org/example/dto/request/LoginApiRequest.java b/app/api/user-api/src/main/java/org/example/dto/request/LoginApiRequest.java new file mode 100644 index 00000000..991b27ae --- /dev/null +++ b/app/api/user-api/src/main/java/org/example/dto/request/LoginApiRequest.java @@ -0,0 +1,17 @@ +package org.example.dto.request; + +import jakarta.validation.constraints.NotNull; +import org.example.dto.LoginApiDto; +import org.example.entity.credential.SocialCredential; + +public record LoginApiRequest( + @NotNull(message = "소셜 식별자는 필수 입력값입니다.") + SocialCredential socialCredential +) { + + public LoginApiDto toLoginApiDto() { + return LoginApiDto.builder() + .socialCredential(socialCredential) + .build(); + } +} diff --git a/app/api/user-api/src/main/java/org/example/dto/request/SignUpRequest.java b/app/api/user-api/src/main/java/org/example/dto/request/SignUpRequest.java deleted file mode 100644 index 3bf2128f..00000000 --- a/app/api/user-api/src/main/java/org/example/dto/request/SignUpRequest.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.example.dto.request; - -import jakarta.validation.constraints.NotNull; -import org.example.entity.User; -import org.example.vo.SocialLoginType; - -public record SignUpRequest( - - @NotNull(message = "닉네임은 필수 입력값입니다.") - String nickname, - - @NotNull(message = "소셜 타입은 필수 입력값입니다.") - SocialLoginType socialLoginType, - - @NotNull(message = "소셜 식별자는 필수 입력값입니다.") - String socialIdentifier -) { - - public User toUser() { - return User.builder() - .nickname(nickname) - .socialLoginType(socialLoginType) - .socialIdentifier(socialIdentifier) - .build(); - } -} diff --git a/app/api/user-api/src/main/java/org/example/service/UserService.java b/app/api/user-api/src/main/java/org/example/service/UserService.java index bfca0737..c18612b5 100644 --- a/app/api/user-api/src/main/java/org/example/service/UserService.java +++ b/app/api/user-api/src/main/java/org/example/service/UserService.java @@ -2,12 +2,14 @@ import java.util.Date; import lombok.RequiredArgsConstructor; +import org.example.dto.LoginApiDto; import org.example.entity.User; import org.example.repository.RedisRepository; import org.example.security.dto.TokenParam; import org.example.security.dto.UserParam; import org.example.security.token.JWTGenerator; import org.example.usecase.UserUseCase; +import org.example.vo.UserRoleApiType; import org.springframework.stereotype.Service; @Service @@ -18,9 +20,12 @@ public class UserService { private final JWTGenerator jwtGenerator; private final RedisRepository redisRepository; - public TokenParam signUp(final User user) { - User createdUser = userUseCase.save(user); - UserParam userParam = UserParam.as(createdUser.getId(), createdUser.getUserRole()); + public TokenParam login(final LoginApiDto loginApiDto) { + User createdUser = userUseCase.save(loginApiDto.toUser()); + UserParam userParam = UserParam.builder() + .userId(createdUser.getId()) + .role(UserRoleApiType.valueOf(createdUser.getUserRole().name())) + .build(); TokenParam tokenParam = jwtGenerator.generate(userParam, new Date()); redisRepository.save(userParam.userId().toString(), tokenParam.refreshToken()); diff --git a/app/build.gradle b/app/build.gradle index ef8549a7..b289b4f5 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -18,7 +18,6 @@ allprojects { dependencies { implementation "org.springframework.boot:spring-boot-starter-web" implementation project(":app:api") - implementation project(":app:domain") implementation project(":app:infrastructure") // docker-compose diff --git a/app/domain/user-domain/build.gradle b/app/domain/user-domain/build.gradle index e9c84c6c..7dc8a3ce 100644 --- a/app/domain/user-domain/build.gradle +++ b/app/domain/user-domain/build.gradle @@ -2,8 +2,9 @@ bootJar.enabled = false jar.enabled = true dependencies { + implementation project(":app:domain") + // hypersistence utils implementation 'io.hypersistence:hypersistence-utils-hibernate-63:3.7.6' - implementation 'com.fasterxml.jackson.core:jackson-databind:2.15.4' - implementation project(":app:domain") + } diff --git a/app/domain/user-domain/src/main/java/org/example/entity/User.java b/app/domain/user-domain/src/main/java/org/example/entity/User.java index 0938f2a3..39fa6e53 100644 --- a/app/domain/user-domain/src/main/java/org/example/entity/User.java +++ b/app/domain/user-domain/src/main/java/org/example/entity/User.java @@ -1,7 +1,7 @@ package org.example.entity; +import io.hypersistence.utils.hibernate.type.json.JsonType; import jakarta.persistence.Column; -import jakarta.persistence.Embedded; import jakarta.persistence.Entity; import jakarta.persistence.EnumType; import jakarta.persistence.Enumerated; @@ -11,10 +11,10 @@ import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; -import org.example.entity.credential.SocialCredentials; -import org.example.vo.SocialLoginType; +import org.example.entity.credential.SocialCredential; import org.example.vo.UserGender; import org.example.vo.UserRole; +import org.hibernate.annotations.Type; @Entity @Getter @@ -22,7 +22,7 @@ @Table(name = "app_user") public class User extends BaseEntity { - @Column(name = "nickname", nullable = false) + @Column(name = "nickname") private String nickname; @Column(name = "birth") @@ -31,8 +31,9 @@ public class User extends BaseEntity { @Column(name = "fcm_token") private String fcmToken; - @Embedded - private SocialCredentials socialCredentials = new SocialCredentials(); + @Type(JsonType.class) + @Column(name = "social_credentials", columnDefinition = "jsonb", nullable = false) + private SocialCredential socialCredential; @Column(name = "gender") @Enumerated(value = EnumType.STRING) @@ -43,9 +44,10 @@ public class User extends BaseEntity { private UserRole userRole; @Builder - private User(String nickname, SocialLoginType socialLoginType, String socialIdentifier) { - this.nickname = nickname; - this.socialCredentials.put(socialLoginType, socialIdentifier); + private User( + SocialCredential socialCredential + ) { + this.socialCredential = socialCredential; this.userRole = UserRole.USER; } } \ No newline at end of file diff --git a/app/domain/user-domain/src/main/java/org/example/entity/credential/AppleSocialCredential.java b/app/domain/user-domain/src/main/java/org/example/entity/credential/AppleSocialCredential.java index 71fb15ae..2dde615f 100644 --- a/app/domain/user-domain/src/main/java/org/example/entity/credential/AppleSocialCredential.java +++ b/app/domain/user-domain/src/main/java/org/example/entity/credential/AppleSocialCredential.java @@ -1,37 +1,15 @@ package org.example.entity.credential; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.example.vo.SocialLoginType; -public final class AppleSocialCredential implements SocialCredential { +@Getter +@NoArgsConstructor +public final class AppleSocialCredential extends SocialCredential { - private final Map credentialMap = new HashMap<>(); - - @Override - public void put(Object socialLoginType, String socialIdentifier) { - credentialMap.put(socialLoginType, socialIdentifier); - } - - @Override - public Map getCredentialMap() { - return credentialMap; + public AppleSocialCredential(SocialLoginType socialLoginType, String basicIdentifier) { + super(socialLoginType, basicIdentifier); } - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - AppleSocialCredential that = (AppleSocialCredential) o; - return Objects.equals(getCredentialMap(), that.getCredentialMap()); - } - - @Override - public int hashCode() { - return Objects.hash(getCredentialMap()); - } } diff --git a/app/domain/user-domain/src/main/java/org/example/entity/credential/GoogleSocialCredential.java b/app/domain/user-domain/src/main/java/org/example/entity/credential/GoogleSocialCredential.java index 23dc9655..b6706efe 100644 --- a/app/domain/user-domain/src/main/java/org/example/entity/credential/GoogleSocialCredential.java +++ b/app/domain/user-domain/src/main/java/org/example/entity/credential/GoogleSocialCredential.java @@ -1,37 +1,15 @@ package org.example.entity.credential; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.example.vo.SocialLoginType; -public final class GoogleSocialCredential implements SocialCredential { +@Getter +@NoArgsConstructor +public final class GoogleSocialCredential extends SocialCredential { - private final Map credentialMap = new HashMap<>(); - - @Override - public void put(Object socialLoginType, String socialIdentifier) { - credentialMap.put(socialLoginType, socialIdentifier); - } - - @Override - public Map getCredentialMap() { - return credentialMap; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - GoogleSocialCredential that = (GoogleSocialCredential) o; - return Objects.equals(getCredentialMap(), that.getCredentialMap()); - } - - @Override - public int hashCode() { - return Objects.hash(getCredentialMap()); + public GoogleSocialCredential(SocialLoginType socialLoginType, String basicIdentifier) { + super(socialLoginType, basicIdentifier); } } + diff --git a/app/domain/user-domain/src/main/java/org/example/entity/credential/KakaoSocialCredential.java b/app/domain/user-domain/src/main/java/org/example/entity/credential/KakaoSocialCredential.java index 4ba1ecee..98ef9db0 100644 --- a/app/domain/user-domain/src/main/java/org/example/entity/credential/KakaoSocialCredential.java +++ b/app/domain/user-domain/src/main/java/org/example/entity/credential/KakaoSocialCredential.java @@ -1,37 +1,14 @@ package org.example.entity.credential; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.example.vo.SocialLoginType; -public final class KakaoSocialCredential implements SocialCredential { +@Getter +@NoArgsConstructor +public final class KakaoSocialCredential extends SocialCredential { - private final Map credentialMap = new HashMap<>(); - - @Override - public void put(Object socialLoginType, String socialIdentifier) { - credentialMap.put(socialLoginType, socialIdentifier); - } - - @Override - public Map getCredentialMap() { - return credentialMap; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - KakaoSocialCredential that = (KakaoSocialCredential) o; - return Objects.equals(getCredentialMap(), that.getCredentialMap()); - } - - @Override - public int hashCode() { - return Objects.hash(getCredentialMap()); + public KakaoSocialCredential(SocialLoginType socialLoginType, String basicIdentifier) { + super(socialLoginType, basicIdentifier); } } diff --git a/app/domain/user-domain/src/main/java/org/example/entity/credential/SocialCredential.java b/app/domain/user-domain/src/main/java/org/example/entity/credential/SocialCredential.java index e50dbe76..1d770a67 100644 --- a/app/domain/user-domain/src/main/java/org/example/entity/credential/SocialCredential.java +++ b/app/domain/user-domain/src/main/java/org/example/entity/credential/SocialCredential.java @@ -1,18 +1,17 @@ package org.example.entity.credential; -import com.fasterxml.jackson.annotation.JsonAnyGetter; -import com.fasterxml.jackson.annotation.JsonAnySetter; -import java.util.Map; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.example.vo.SocialLoginType; -public sealed interface SocialCredential permits AppleSocialCredential, GoogleSocialCredential, +@Getter +@NoArgsConstructor +@AllArgsConstructor +public sealed class SocialCredential permits AppleSocialCredential, GoogleSocialCredential, KakaoSocialCredential { - - @JsonAnySetter - void put(Object socialLoginType, String socialIdentifier); - - @JsonAnyGetter - Map getCredentialMap(); - + private SocialLoginType socialLoginType; + private String basicIdentifier; } diff --git a/app/domain/user-domain/src/main/java/org/example/entity/credential/SocialCredentials.java b/app/domain/user-domain/src/main/java/org/example/entity/credential/SocialCredentials.java deleted file mode 100644 index f2ff2e62..00000000 --- a/app/domain/user-domain/src/main/java/org/example/entity/credential/SocialCredentials.java +++ /dev/null @@ -1,38 +0,0 @@ -package org.example.entity.credential; - -import io.hypersistence.utils.hibernate.type.json.JsonType; -import jakarta.persistence.Column; -import jakarta.persistence.Embeddable; -import java.util.ArrayList; -import java.util.List; -import org.example.vo.SocialLoginType; -import org.hibernate.annotations.Type; - -@Embeddable -public final class SocialCredentials { - - @Type(JsonType.class) - @Column(name = "social_credentials", columnDefinition = "jsonb", nullable = false) - private final List socialCredentials = new ArrayList<>(); - - public void put(SocialLoginType socialLoginType, String socialIdentifier) { - SocialCredential socialCredential = getSocialCredential(socialLoginType, socialIdentifier); - socialCredentials.add(socialCredential); - } - - private SocialCredential getSocialCredential( - SocialLoginType socialLoginType, - String socialIdentifier - ) { - SocialCredential socialCredential; - switch (socialLoginType) { - case GOOGLE -> socialCredential = new GoogleSocialCredential(); - case KAKAO -> socialCredential = new KakaoSocialCredential(); - case APPLE -> socialCredential = new AppleSocialCredential(); - default -> socialCredential = null; - } - socialCredential.put(socialLoginType, socialIdentifier); - return socialCredential; - } - -} \ No newline at end of file diff --git a/app/infrastructure/src/main/java/org/example/config/InfraStructureConfig.java b/app/infrastructure/src/main/java/org/example/config/InfrastructureConfig.java similarity index 91% rename from app/infrastructure/src/main/java/org/example/config/InfraStructureConfig.java rename to app/infrastructure/src/main/java/org/example/config/InfrastructureConfig.java index fba83877..6450145e 100644 --- a/app/infrastructure/src/main/java/org/example/config/InfraStructureConfig.java +++ b/app/infrastructure/src/main/java/org/example/config/InfrastructureConfig.java @@ -8,6 +8,6 @@ @Configuration @EnableConfigurationProperties(RedisProperty.class) @ComponentScan(basePackages = "org.example") -public class InfraStructureConfig { +public class InfrastructureConfig { } diff --git a/app/src/main/java/org/example/YappBackendApplication.java b/app/src/main/java/org/example/YappBackendApplication.java index 57c69cd5..9ad6069d 100644 --- a/app/src/main/java/org/example/YappBackendApplication.java +++ b/app/src/main/java/org/example/YappBackendApplication.java @@ -1,14 +1,13 @@ package org.example; import org.example.config.ApiConfig; -import org.example.config.DomainConfig; -import org.example.config.InfraStructureConfig; +import org.example.config.InfrastructureConfig; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Import; @SpringBootApplication -@Import(value = {ApiConfig.class, DomainConfig.class, InfraStructureConfig.class}) +@Import(value = {ApiConfig.class, InfrastructureConfig.class}) public class YappBackendApplication { public static void main(String[] args) { From 684290e8e724fc5b2bb72a35e12ed18d47b91188 Mon Sep 17 00:00:00 2001 From: GaBaljaintheroom Date: Fri, 14 Jun 2024 12:03:26 +0900 Subject: [PATCH 14/23] =?UTF-8?q?refactor=20:=20BaseEntity=20isDeleted=20?= =?UTF-8?q?=ED=95=84=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/org/example/entity/BaseEntity.java | 3 +++ 1 file changed, 3 insertions(+) rename app/domain/{ => common-domain}/src/main/java/org/example/entity/BaseEntity.java (92%) diff --git a/app/domain/src/main/java/org/example/entity/BaseEntity.java b/app/domain/common-domain/src/main/java/org/example/entity/BaseEntity.java similarity index 92% rename from app/domain/src/main/java/org/example/entity/BaseEntity.java rename to app/domain/common-domain/src/main/java/org/example/entity/BaseEntity.java index 79965457..99c2536f 100644 --- a/app/domain/src/main/java/org/example/entity/BaseEntity.java +++ b/app/domain/common-domain/src/main/java/org/example/entity/BaseEntity.java @@ -30,6 +30,9 @@ public abstract class BaseEntity implements Persistable { @Column(name = "updated_at", nullable = false) private LocalDateTime updatedAt; + @Column(name = "is_deleted", nullable = false) + private Boolean isDeleted = false; + @Override public boolean isNew() { return id != null; From 07e7ce4c7702661b8c84723f66917c5399e05bf3 Mon Sep 17 00:00:00 2001 From: GaBaljaintheroom Date: Fri, 14 Jun 2024 12:04:07 +0900 Subject: [PATCH 15/23] =?UTF-8?q?refactor=20:=20User=20=EC=97=94=ED=8B=B0?= =?UTF-8?q?=ED=8B=B0=20=EA=B8=B0=EB=B3=B8=EA=B0=92=20=EB=B6=80=EC=97=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/org/example/entity/User.java | 8 ++++---- .../src/main/java/org/example/vo/UserGender.java | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/domain/user-domain/src/main/java/org/example/entity/User.java b/app/domain/user-domain/src/main/java/org/example/entity/User.java index 39fa6e53..12e2cbd3 100644 --- a/app/domain/user-domain/src/main/java/org/example/entity/User.java +++ b/app/domain/user-domain/src/main/java/org/example/entity/User.java @@ -25,8 +25,8 @@ public class User extends BaseEntity { @Column(name = "nickname") private String nickname; - @Column(name = "birth") - private LocalDate birth; + @Column(name = "birth", nullable = false) + private LocalDate birth = LocalDate.of(0, 1, 1); @Column(name = "fcm_token") private String fcmToken; @@ -35,9 +35,9 @@ public class User extends BaseEntity { @Column(name = "social_credentials", columnDefinition = "jsonb", nullable = false) private SocialCredential socialCredential; - @Column(name = "gender") + @Column(name = "gender", nullable = false) @Enumerated(value = EnumType.STRING) - private UserGender userGender; + private UserGender userGender = UserGender.NONE; @Column(name = "role", nullable = false) @Enumerated(value = EnumType.STRING) diff --git a/app/domain/user-domain/src/main/java/org/example/vo/UserGender.java b/app/domain/user-domain/src/main/java/org/example/vo/UserGender.java index 9d7fe2be..d99edc20 100644 --- a/app/domain/user-domain/src/main/java/org/example/vo/UserGender.java +++ b/app/domain/user-domain/src/main/java/org/example/vo/UserGender.java @@ -1,5 +1,5 @@ package org.example.vo; public enum UserGender { - MAN, WOMAN + MAN, WOMAN, NONE } From 04a3461ce10fe9af2950534c6f52443ba92ccc96 Mon Sep 17 00:00:00 2001 From: GaBaljaintheroom Date: Fri, 14 Jun 2024 12:09:12 +0900 Subject: [PATCH 16/23] =?UTF-8?q?refactor=20:=20Infrastructure=20=EB=AA=A8?= =?UTF-8?q?=EB=93=88=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/api/build.gradle | 2 ++ .../security/token/RefreshTokenProcessor.java | 3 +++ app/api/user-api/build.gradle | 1 - app/domain/build.gradle | 7 +------ app/domain/common-domain/build.gradle | 7 +++++++ .../org/example/config/CommonDomainConfig.java} | 2 +- .../org/example/config/JpaAuditingConfig.java | 0 .../java/org/example/config/QuerydslConfig.java | 0 .../main/resources/application-domain-dev.yml | 0 .../main/resources/application-domain-local.yml | 0 .../main/resources/application-domain-prod.yml | 0 app/domain/user-domain/build.gradle | 3 +-- app/infrastructure/build.gradle | 17 ++++++++--------- app/infrastructure/redis/build.gradle | 11 +++++++++++ .../org/example/config/RedisBeanConfig.java | 13 +++++++++++++ .../java/org/example/config/RedisConfig.java | 0 .../org/example/property/RedisProperty.java | 0 .../repository/LettuceRedisRepository.java | 0 .../example/config/InfrastructureConfig.java | 7 ++----- settings.gradle | 2 ++ 20 files changed, 51 insertions(+), 24 deletions(-) create mode 100644 app/domain/common-domain/build.gradle rename app/domain/{src/main/java/org/example/config/DomainConfig.java => common-domain/src/main/java/org/example/config/CommonDomainConfig.java} (86%) rename app/domain/{ => common-domain}/src/main/java/org/example/config/JpaAuditingConfig.java (100%) rename app/domain/{ => common-domain}/src/main/java/org/example/config/QuerydslConfig.java (100%) rename app/domain/{ => common-domain}/src/main/resources/application-domain-dev.yml (100%) rename app/domain/{ => common-domain}/src/main/resources/application-domain-local.yml (100%) rename app/domain/{ => common-domain}/src/main/resources/application-domain-prod.yml (100%) create mode 100644 app/infrastructure/redis/build.gradle create mode 100644 app/infrastructure/redis/src/main/java/org/example/config/RedisBeanConfig.java rename app/infrastructure/{ => redis}/src/main/java/org/example/config/RedisConfig.java (100%) rename app/infrastructure/{ => redis}/src/main/java/org/example/property/RedisProperty.java (100%) rename app/infrastructure/{ => redis}/src/main/java/org/example/repository/LettuceRedisRepository.java (100%) diff --git a/app/api/build.gradle b/app/api/build.gradle index 4faf9f94..d974bc19 100644 --- a/app/api/build.gradle +++ b/app/api/build.gradle @@ -3,6 +3,8 @@ jar.enabled = true allprojects { dependencies { + implementation project(":app:domain:common-domain") + //swagger implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.5.0' diff --git a/app/api/common-api/src/main/java/org/example/security/token/RefreshTokenProcessor.java b/app/api/common-api/src/main/java/org/example/security/token/RefreshTokenProcessor.java index 6e7fff8d..1f275367 100644 --- a/app/api/common-api/src/main/java/org/example/security/token/RefreshTokenProcessor.java +++ b/app/api/common-api/src/main/java/org/example/security/token/RefreshTokenProcessor.java @@ -19,6 +19,9 @@ public class RefreshTokenProcessor { public TokenParam reissueToken(HttpServletRequest request) { String refreshToken = jwtHandler.extractRefreshToken(request); UserParam userParam = jwtHandler.extractUserFrom(refreshToken); + + // 기존 redis의 Refresh토큰과 비교해서 맞는 refresh인지 확인 해야함 + TokenParam newTokenParam = jwtGenerator.generate(userParam, new Date()); redisRepository.save(userParam.userId().toString(), newTokenParam.refreshToken()); diff --git a/app/api/user-api/build.gradle b/app/api/user-api/build.gradle index 336ab82b..05eae81a 100644 --- a/app/api/user-api/build.gradle +++ b/app/api/user-api/build.gradle @@ -2,7 +2,6 @@ bootJar.enabled = false jar.enabled = true dependencies { - implementation project(":app:domain") implementation project(":app:domain:user-domain") implementation project(":app:api:common-api") diff --git a/app/domain/build.gradle b/app/domain/build.gradle index a19f7a1e..d0c68379 100644 --- a/app/domain/build.gradle +++ b/app/domain/build.gradle @@ -21,9 +21,4 @@ subprojects { dependencies { runtimeOnly 'org.postgresql:postgresql' } -} - -dependencies { - //ulid - implementation 'com.github.f4b6a3:ulid-creator:5.2.3' -} +} \ No newline at end of file diff --git a/app/domain/common-domain/build.gradle b/app/domain/common-domain/build.gradle new file mode 100644 index 00000000..ef210a87 --- /dev/null +++ b/app/domain/common-domain/build.gradle @@ -0,0 +1,7 @@ +bootJar.enabled = false +jar.enabled = true + +dependencies { + //ulid + implementation 'com.github.f4b6a3:ulid-creator:5.2.3' +} diff --git a/app/domain/src/main/java/org/example/config/DomainConfig.java b/app/domain/common-domain/src/main/java/org/example/config/CommonDomainConfig.java similarity index 86% rename from app/domain/src/main/java/org/example/config/DomainConfig.java rename to app/domain/common-domain/src/main/java/org/example/config/CommonDomainConfig.java index 00d2b26f..b541bb74 100644 --- a/app/domain/src/main/java/org/example/config/DomainConfig.java +++ b/app/domain/common-domain/src/main/java/org/example/config/CommonDomainConfig.java @@ -5,6 +5,6 @@ @Configuration @ComponentScan(basePackages = "org.example") -public class DomainConfig { +public class CommonDomainConfig { } \ No newline at end of file diff --git a/app/domain/src/main/java/org/example/config/JpaAuditingConfig.java b/app/domain/common-domain/src/main/java/org/example/config/JpaAuditingConfig.java similarity index 100% rename from app/domain/src/main/java/org/example/config/JpaAuditingConfig.java rename to app/domain/common-domain/src/main/java/org/example/config/JpaAuditingConfig.java diff --git a/app/domain/src/main/java/org/example/config/QuerydslConfig.java b/app/domain/common-domain/src/main/java/org/example/config/QuerydslConfig.java similarity index 100% rename from app/domain/src/main/java/org/example/config/QuerydslConfig.java rename to app/domain/common-domain/src/main/java/org/example/config/QuerydslConfig.java diff --git a/app/domain/src/main/resources/application-domain-dev.yml b/app/domain/common-domain/src/main/resources/application-domain-dev.yml similarity index 100% rename from app/domain/src/main/resources/application-domain-dev.yml rename to app/domain/common-domain/src/main/resources/application-domain-dev.yml diff --git a/app/domain/src/main/resources/application-domain-local.yml b/app/domain/common-domain/src/main/resources/application-domain-local.yml similarity index 100% rename from app/domain/src/main/resources/application-domain-local.yml rename to app/domain/common-domain/src/main/resources/application-domain-local.yml diff --git a/app/domain/src/main/resources/application-domain-prod.yml b/app/domain/common-domain/src/main/resources/application-domain-prod.yml similarity index 100% rename from app/domain/src/main/resources/application-domain-prod.yml rename to app/domain/common-domain/src/main/resources/application-domain-prod.yml diff --git a/app/domain/user-domain/build.gradle b/app/domain/user-domain/build.gradle index 7dc8a3ce..113bb5b1 100644 --- a/app/domain/user-domain/build.gradle +++ b/app/domain/user-domain/build.gradle @@ -2,9 +2,8 @@ bootJar.enabled = false jar.enabled = true dependencies { - implementation project(":app:domain") + implementation project(":app:domain:common-domain") // hypersistence utils implementation 'io.hypersistence:hypersistence-utils-hibernate-63:3.7.6' - } diff --git a/app/infrastructure/build.gradle b/app/infrastructure/build.gradle index 0057522c..b3b62f26 100644 --- a/app/infrastructure/build.gradle +++ b/app/infrastructure/build.gradle @@ -1,13 +1,12 @@ bootJar.enabled = false jar.enabled = true -dependencies { - implementation project(":app:api:user-api") - implementation project(":app:api:common-api") - - implementation "org.springframework.boot:spring-boot-starter-web" - - //redis - implementation 'org.springframework.data:spring-data-redis' - implementation 'io.lettuce:lettuce-core:6.3.0.RELEASE' +allprojects { + dependencies { + implementation "org.springframework.boot:spring-boot-starter-web" + } } + +dependencies { + implementation project(":app:infrastructure:redis") +} \ No newline at end of file diff --git a/app/infrastructure/redis/build.gradle b/app/infrastructure/redis/build.gradle new file mode 100644 index 00000000..cc56c6b0 --- /dev/null +++ b/app/infrastructure/redis/build.gradle @@ -0,0 +1,11 @@ +bootJar.enabled = false +jar.enabled = true + +dependencies { + implementation project(":app:api:user-api") + implementation project(":app:api:common-api") + + //redis + implementation 'org.springframework.data:spring-data-redis' + implementation 'io.lettuce:lettuce-core:6.3.0.RELEASE' +} diff --git a/app/infrastructure/redis/src/main/java/org/example/config/RedisBeanConfig.java b/app/infrastructure/redis/src/main/java/org/example/config/RedisBeanConfig.java new file mode 100644 index 00000000..d6bd380a --- /dev/null +++ b/app/infrastructure/redis/src/main/java/org/example/config/RedisBeanConfig.java @@ -0,0 +1,13 @@ +package org.example.config; + +import org.example.property.RedisProperty; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +@Configuration +@EnableConfigurationProperties(RedisProperty.class) +@ComponentScan(basePackages = "org.example") +public class RedisBeanConfig { + +} diff --git a/app/infrastructure/src/main/java/org/example/config/RedisConfig.java b/app/infrastructure/redis/src/main/java/org/example/config/RedisConfig.java similarity index 100% rename from app/infrastructure/src/main/java/org/example/config/RedisConfig.java rename to app/infrastructure/redis/src/main/java/org/example/config/RedisConfig.java diff --git a/app/infrastructure/src/main/java/org/example/property/RedisProperty.java b/app/infrastructure/redis/src/main/java/org/example/property/RedisProperty.java similarity index 100% rename from app/infrastructure/src/main/java/org/example/property/RedisProperty.java rename to app/infrastructure/redis/src/main/java/org/example/property/RedisProperty.java diff --git a/app/infrastructure/src/main/java/org/example/repository/LettuceRedisRepository.java b/app/infrastructure/redis/src/main/java/org/example/repository/LettuceRedisRepository.java similarity index 100% rename from app/infrastructure/src/main/java/org/example/repository/LettuceRedisRepository.java rename to app/infrastructure/redis/src/main/java/org/example/repository/LettuceRedisRepository.java diff --git a/app/infrastructure/src/main/java/org/example/config/InfrastructureConfig.java b/app/infrastructure/src/main/java/org/example/config/InfrastructureConfig.java index 6450145e..3e92ad50 100644 --- a/app/infrastructure/src/main/java/org/example/config/InfrastructureConfig.java +++ b/app/infrastructure/src/main/java/org/example/config/InfrastructureConfig.java @@ -1,13 +1,10 @@ package org.example.config; -import org.example.property.RedisProperty; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; @Configuration -@EnableConfigurationProperties(RedisProperty.class) -@ComponentScan(basePackages = "org.example") +@Import(RedisBeanConfig.class) public class InfrastructureConfig { } diff --git a/settings.gradle b/settings.gradle index e8971820..cf1fdd70 100644 --- a/settings.gradle +++ b/settings.gradle @@ -5,6 +5,7 @@ include(":common") include(":app") include(":app:domain") +include (":app:domain:common-domain") include(":app:domain:user-domain") include(":app:api") @@ -12,3 +13,4 @@ include (":app:api:common-api") include(":app:api:user-api") include (":app:infrastructure") +include (":app:infrastructure:redis") \ No newline at end of file From b9776e113b4b419edefe4f7c3e8f6448954113eb Mon Sep 17 00:00:00 2001 From: GaBaljaintheroom Date: Fri, 14 Jun 2024 13:08:54 +0900 Subject: [PATCH 17/23] =?UTF-8?q?refactor=20:=20login=20dto=20=EB=B6=84?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../example/controller/UserController.java | 11 +++--- .../example/controller/dto/LoginApiDto.java | 17 ++++++++ .../dto/request/LoginApiRequest.java | 39 +++++++++++++++++++ .../java/org/example/dto/LoginApiDto.java | 17 -------- .../example/dto/request/LoginApiRequest.java | 17 -------- .../java/org/example/service/UserService.java | 6 +-- .../example/service/dto/LoginServiceDto.java | 18 +++++++++ .../dto/request/LoginServiceRequest.java | 17 ++++++++ .../main/java/org/example/entity/User.java | 14 +++---- .../credential/AppleSocialCredential.java | 6 +-- .../credential/GoogleSocialCredential.java | 5 +-- .../credential/KakaoSocialCredential.java | 5 +-- .../entity/credential/SocialCredential.java | 5 +-- .../entity/credential/SocialCredentials.java | 21 ++++++++++ 14 files changed, 134 insertions(+), 64 deletions(-) create mode 100644 app/api/user-api/src/main/java/org/example/controller/dto/LoginApiDto.java create mode 100644 app/api/user-api/src/main/java/org/example/controller/dto/request/LoginApiRequest.java delete mode 100644 app/api/user-api/src/main/java/org/example/dto/LoginApiDto.java delete mode 100644 app/api/user-api/src/main/java/org/example/dto/request/LoginApiRequest.java create mode 100644 app/api/user-api/src/main/java/org/example/service/dto/LoginServiceDto.java create mode 100644 app/api/user-api/src/main/java/org/example/service/dto/request/LoginServiceRequest.java create mode 100644 app/domain/user-domain/src/main/java/org/example/entity/credential/SocialCredentials.java diff --git a/app/api/user-api/src/main/java/org/example/controller/UserController.java b/app/api/user-api/src/main/java/org/example/controller/UserController.java index 0a71dadc..28dafb64 100644 --- a/app/api/user-api/src/main/java/org/example/controller/UserController.java +++ b/app/api/user-api/src/main/java/org/example/controller/UserController.java @@ -4,10 +4,10 @@ import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; -import org.example.dto.LoginApiDto; -import org.example.dto.request.LoginApiRequest; +import org.example.controller.dto.request.LoginApiRequest; import org.example.security.dto.TokenParam; import org.example.service.UserService; +import org.example.service.dto.request.LoginServiceRequest; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; @@ -21,12 +21,13 @@ public class UserController { private final UserService userService; - @PostMapping("/sign-up") + @PostMapping("/login") @Tag(name = "user") @Operation(summary = "유저 로그인", description = "사용자는 소셜 로그인을 할 수 있다.") public ResponseEntity signUp(@Valid @RequestBody LoginApiRequest request) { - final LoginApiDto loginApiDto = request.toLoginApiDto(); - TokenParam tokenParam = userService.login(loginApiDto); + final LoginServiceRequest loginServiceRequest = request.toLoginApiDto() + .toLoginServiceRequest(); + TokenParam tokenParam = userService.login(loginServiceRequest); return ResponseEntity.ok(tokenParam); } diff --git a/app/api/user-api/src/main/java/org/example/controller/dto/LoginApiDto.java b/app/api/user-api/src/main/java/org/example/controller/dto/LoginApiDto.java new file mode 100644 index 00000000..7f213a45 --- /dev/null +++ b/app/api/user-api/src/main/java/org/example/controller/dto/LoginApiDto.java @@ -0,0 +1,17 @@ +package org.example.controller.dto; + +import lombok.Builder; +import org.example.entity.credential.SocialCredentials; +import org.example.service.dto.request.LoginServiceRequest; + +@Builder +public record LoginApiDto( + SocialCredentials socialCredentials +) { + + public LoginServiceRequest toLoginServiceRequest() { + return LoginServiceRequest.builder() + .socialCredentials(socialCredentials) + .build(); + } +} diff --git a/app/api/user-api/src/main/java/org/example/controller/dto/request/LoginApiRequest.java b/app/api/user-api/src/main/java/org/example/controller/dto/request/LoginApiRequest.java new file mode 100644 index 00000000..08939577 --- /dev/null +++ b/app/api/user-api/src/main/java/org/example/controller/dto/request/LoginApiRequest.java @@ -0,0 +1,39 @@ +package org.example.controller.dto.request; + +import jakarta.validation.constraints.NotNull; +import org.example.controller.dto.LoginApiDto; +import org.example.entity.credential.AppleSocialCredential; +import org.example.entity.credential.GoogleSocialCredential; +import org.example.entity.credential.KakaoSocialCredential; +import org.example.entity.credential.SocialCredential; +import org.example.entity.credential.SocialCredentials; +import org.example.vo.SocialLoginType; + +public record LoginApiRequest( + @NotNull(message = "소셜 로그인 타입은 필수 입력값입니다.") + SocialLoginType socialLoginType, + + @NotNull(message = "소셜 로그인 식별값은 필수 입력값입니다.") + String socialLoginIdentifier +) { + + public LoginApiDto toLoginApiDto() { + return LoginApiDto.builder() + .socialCredentials(socialCredentials()) + .build(); + } + + private SocialCredentials socialCredentials() { + SocialCredentials socialCredentials = new SocialCredentials(); + socialCredentials.saveCredentials(socialLoginType, socialCredential()); + return socialCredentials; + } + + private SocialCredential socialCredential() { + return switch (socialLoginType) { + case GOOGLE -> new GoogleSocialCredential(socialLoginIdentifier); + case KAKAO -> new KakaoSocialCredential(socialLoginIdentifier); + case APPLE -> new AppleSocialCredential(socialLoginIdentifier); + }; + } +} diff --git a/app/api/user-api/src/main/java/org/example/dto/LoginApiDto.java b/app/api/user-api/src/main/java/org/example/dto/LoginApiDto.java deleted file mode 100644 index f566be1b..00000000 --- a/app/api/user-api/src/main/java/org/example/dto/LoginApiDto.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.example.dto; - -import lombok.Builder; -import org.example.entity.User; -import org.example.entity.credential.SocialCredential; - -@Builder -public record LoginApiDto( - SocialCredential socialCredential -) { - - public User toUser() { - return User.builder() - .socialCredential(socialCredential) - .build(); - } -} diff --git a/app/api/user-api/src/main/java/org/example/dto/request/LoginApiRequest.java b/app/api/user-api/src/main/java/org/example/dto/request/LoginApiRequest.java deleted file mode 100644 index 991b27ae..00000000 --- a/app/api/user-api/src/main/java/org/example/dto/request/LoginApiRequest.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.example.dto.request; - -import jakarta.validation.constraints.NotNull; -import org.example.dto.LoginApiDto; -import org.example.entity.credential.SocialCredential; - -public record LoginApiRequest( - @NotNull(message = "소셜 식별자는 필수 입력값입니다.") - SocialCredential socialCredential -) { - - public LoginApiDto toLoginApiDto() { - return LoginApiDto.builder() - .socialCredential(socialCredential) - .build(); - } -} diff --git a/app/api/user-api/src/main/java/org/example/service/UserService.java b/app/api/user-api/src/main/java/org/example/service/UserService.java index c18612b5..abeaef16 100644 --- a/app/api/user-api/src/main/java/org/example/service/UserService.java +++ b/app/api/user-api/src/main/java/org/example/service/UserService.java @@ -2,12 +2,12 @@ import java.util.Date; import lombok.RequiredArgsConstructor; -import org.example.dto.LoginApiDto; import org.example.entity.User; import org.example.repository.RedisRepository; import org.example.security.dto.TokenParam; import org.example.security.dto.UserParam; import org.example.security.token.JWTGenerator; +import org.example.service.dto.request.LoginServiceRequest; import org.example.usecase.UserUseCase; import org.example.vo.UserRoleApiType; import org.springframework.stereotype.Service; @@ -20,8 +20,8 @@ public class UserService { private final JWTGenerator jwtGenerator; private final RedisRepository redisRepository; - public TokenParam login(final LoginApiDto loginApiDto) { - User createdUser = userUseCase.save(loginApiDto.toUser()); + public TokenParam login(final LoginServiceRequest loginServiceRequest) { + User createdUser = userUseCase.save(loginServiceRequest.toLoginServiceDto().toUser()); UserParam userParam = UserParam.builder() .userId(createdUser.getId()) .role(UserRoleApiType.valueOf(createdUser.getUserRole().name())) diff --git a/app/api/user-api/src/main/java/org/example/service/dto/LoginServiceDto.java b/app/api/user-api/src/main/java/org/example/service/dto/LoginServiceDto.java new file mode 100644 index 00000000..0dbe0c32 --- /dev/null +++ b/app/api/user-api/src/main/java/org/example/service/dto/LoginServiceDto.java @@ -0,0 +1,18 @@ +package org.example.service.dto; + +import lombok.Builder; +import org.example.entity.User; +import org.example.entity.credential.SocialCredentials; + +@Builder +public record LoginServiceDto( + SocialCredentials socialCredentials + +) { + + public User toUser() { + return User.builder() + .socialCredentials(socialCredentials) + .build(); + } +} diff --git a/app/api/user-api/src/main/java/org/example/service/dto/request/LoginServiceRequest.java b/app/api/user-api/src/main/java/org/example/service/dto/request/LoginServiceRequest.java new file mode 100644 index 00000000..78e05fc8 --- /dev/null +++ b/app/api/user-api/src/main/java/org/example/service/dto/request/LoginServiceRequest.java @@ -0,0 +1,17 @@ +package org.example.service.dto.request; + +import lombok.Builder; +import org.example.entity.credential.SocialCredentials; +import org.example.service.dto.LoginServiceDto; + +@Builder +public record LoginServiceRequest( + SocialCredentials socialCredentials +) { + + public LoginServiceDto toLoginServiceDto() { + return LoginServiceDto.builder() + .socialCredentials(socialCredentials) + .build(); + } +} diff --git a/app/domain/user-domain/src/main/java/org/example/entity/User.java b/app/domain/user-domain/src/main/java/org/example/entity/User.java index 12e2cbd3..ac4ed9a0 100644 --- a/app/domain/user-domain/src/main/java/org/example/entity/User.java +++ b/app/domain/user-domain/src/main/java/org/example/entity/User.java @@ -1,7 +1,7 @@ package org.example.entity; -import io.hypersistence.utils.hibernate.type.json.JsonType; import jakarta.persistence.Column; +import jakarta.persistence.Embedded; import jakarta.persistence.Entity; import jakarta.persistence.EnumType; import jakarta.persistence.Enumerated; @@ -11,10 +11,9 @@ import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; -import org.example.entity.credential.SocialCredential; +import org.example.entity.credential.SocialCredentials; import org.example.vo.UserGender; import org.example.vo.UserRole; -import org.hibernate.annotations.Type; @Entity @Getter @@ -31,9 +30,8 @@ public class User extends BaseEntity { @Column(name = "fcm_token") private String fcmToken; - @Type(JsonType.class) - @Column(name = "social_credentials", columnDefinition = "jsonb", nullable = false) - private SocialCredential socialCredential; + @Embedded + private SocialCredentials socialCredentials; @Column(name = "gender", nullable = false) @Enumerated(value = EnumType.STRING) @@ -45,9 +43,9 @@ public class User extends BaseEntity { @Builder private User( - SocialCredential socialCredential + SocialCredentials socialCredentials ) { - this.socialCredential = socialCredential; + this.socialCredentials = socialCredentials; this.userRole = UserRole.USER; } } \ No newline at end of file diff --git a/app/domain/user-domain/src/main/java/org/example/entity/credential/AppleSocialCredential.java b/app/domain/user-domain/src/main/java/org/example/entity/credential/AppleSocialCredential.java index 2dde615f..3e112c99 100644 --- a/app/domain/user-domain/src/main/java/org/example/entity/credential/AppleSocialCredential.java +++ b/app/domain/user-domain/src/main/java/org/example/entity/credential/AppleSocialCredential.java @@ -2,14 +2,12 @@ import lombok.Getter; import lombok.NoArgsConstructor; -import org.example.vo.SocialLoginType; @Getter @NoArgsConstructor public final class AppleSocialCredential extends SocialCredential { - public AppleSocialCredential(SocialLoginType socialLoginType, String basicIdentifier) { - super(socialLoginType, basicIdentifier); + public AppleSocialCredential(String basicIdentifier) { + super(basicIdentifier); } - } diff --git a/app/domain/user-domain/src/main/java/org/example/entity/credential/GoogleSocialCredential.java b/app/domain/user-domain/src/main/java/org/example/entity/credential/GoogleSocialCredential.java index b6706efe..3d3f2ae3 100644 --- a/app/domain/user-domain/src/main/java/org/example/entity/credential/GoogleSocialCredential.java +++ b/app/domain/user-domain/src/main/java/org/example/entity/credential/GoogleSocialCredential.java @@ -2,14 +2,13 @@ import lombok.Getter; import lombok.NoArgsConstructor; -import org.example.vo.SocialLoginType; @Getter @NoArgsConstructor public final class GoogleSocialCredential extends SocialCredential { - public GoogleSocialCredential(SocialLoginType socialLoginType, String basicIdentifier) { - super(socialLoginType, basicIdentifier); + public GoogleSocialCredential(String basicIdentifier) { + super(basicIdentifier); } } diff --git a/app/domain/user-domain/src/main/java/org/example/entity/credential/KakaoSocialCredential.java b/app/domain/user-domain/src/main/java/org/example/entity/credential/KakaoSocialCredential.java index 98ef9db0..7fcb560b 100644 --- a/app/domain/user-domain/src/main/java/org/example/entity/credential/KakaoSocialCredential.java +++ b/app/domain/user-domain/src/main/java/org/example/entity/credential/KakaoSocialCredential.java @@ -2,13 +2,12 @@ import lombok.Getter; import lombok.NoArgsConstructor; -import org.example.vo.SocialLoginType; @Getter @NoArgsConstructor public final class KakaoSocialCredential extends SocialCredential { - public KakaoSocialCredential(SocialLoginType socialLoginType, String basicIdentifier) { - super(socialLoginType, basicIdentifier); + public KakaoSocialCredential(String basicIdentifier) { + super(basicIdentifier); } } diff --git a/app/domain/user-domain/src/main/java/org/example/entity/credential/SocialCredential.java b/app/domain/user-domain/src/main/java/org/example/entity/credential/SocialCredential.java index 1d770a67..59e8eb9a 100644 --- a/app/domain/user-domain/src/main/java/org/example/entity/credential/SocialCredential.java +++ b/app/domain/user-domain/src/main/java/org/example/entity/credential/SocialCredential.java @@ -3,15 +3,12 @@ import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; -import org.example.vo.SocialLoginType; @Getter @NoArgsConstructor @AllArgsConstructor -public sealed class SocialCredential permits AppleSocialCredential, GoogleSocialCredential, +public abstract sealed class SocialCredential permits AppleSocialCredential, GoogleSocialCredential, KakaoSocialCredential { - private SocialLoginType socialLoginType; private String basicIdentifier; - } diff --git a/app/domain/user-domain/src/main/java/org/example/entity/credential/SocialCredentials.java b/app/domain/user-domain/src/main/java/org/example/entity/credential/SocialCredentials.java new file mode 100644 index 00000000..8a045bcc --- /dev/null +++ b/app/domain/user-domain/src/main/java/org/example/entity/credential/SocialCredentials.java @@ -0,0 +1,21 @@ +package org.example.entity.credential; + +import io.hypersistence.utils.hibernate.type.json.JsonType; +import jakarta.persistence.Column; +import jakarta.persistence.Embeddable; +import java.util.HashMap; +import java.util.Map; +import org.example.vo.SocialLoginType; +import org.hibernate.annotations.Type; + +@Embeddable +public class SocialCredentials { + + @Type(JsonType.class) + @Column(name = "social_credentials", columnDefinition = "jsonb", nullable = false) + private Map socialLoginTypeCredentials = new HashMap<>(); + + public void saveCredentials(SocialLoginType socialLoginType, SocialCredential socialCredential) { + socialLoginTypeCredentials.put(socialLoginType, socialCredential); + } +} From bf45cff9395937c028b9846b8e22ebb2ca73c3f7 Mon Sep 17 00:00:00 2001 From: GaBaljaintheroom Date: Fri, 14 Jun 2024 13:24:17 +0900 Subject: [PATCH 18/23] =?UTF-8?q?refactor=20:=20refreshToken=20=EB=B9=84?= =?UTF-8?q?=EA=B5=90=20=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../{RedisRepository.java => TokenRepository.java} | 4 +++- .../org/example/security/token/JWTGenerator.java | 7 ++++++- .../security/token/RefreshTokenProcessor.java | 13 +++++++++---- .../example/security/token/JWTGeneratorTest.java | 7 +++++-- .../org/example/security/token/JWTHandlerTest.java | 5 ++++- .../org/example/repository/RedisRepository.java | 9 --------- .../main/java/org/example/service/UserService.java | 8 ++------ app/infrastructure/redis/build.gradle | 1 - .../example/repository/LettuceRedisRepository.java | 8 +++++++- 9 files changed, 36 insertions(+), 26 deletions(-) rename app/api/common-api/src/main/java/org/example/repository/{RedisRepository.java => TokenRepository.java} (64%) delete mode 100644 app/api/user-api/src/main/java/org/example/repository/RedisRepository.java diff --git a/app/api/common-api/src/main/java/org/example/repository/RedisRepository.java b/app/api/common-api/src/main/java/org/example/repository/TokenRepository.java similarity index 64% rename from app/api/common-api/src/main/java/org/example/repository/RedisRepository.java rename to app/api/common-api/src/main/java/org/example/repository/TokenRepository.java index d7d1782b..f98cc5d5 100644 --- a/app/api/common-api/src/main/java/org/example/repository/RedisRepository.java +++ b/app/api/common-api/src/main/java/org/example/repository/TokenRepository.java @@ -3,7 +3,9 @@ import org.springframework.stereotype.Component; @Component -public interface RedisRepository { +public interface TokenRepository { void save(String userId, String refreshToken); + + String getOldRefreshToken(String userId); } diff --git a/app/api/common-api/src/main/java/org/example/security/token/JWTGenerator.java b/app/api/common-api/src/main/java/org/example/security/token/JWTGenerator.java index 0568f166..af6181a1 100644 --- a/app/api/common-api/src/main/java/org/example/security/token/JWTGenerator.java +++ b/app/api/common-api/src/main/java/org/example/security/token/JWTGenerator.java @@ -4,6 +4,7 @@ import java.util.Date; import lombok.RequiredArgsConstructor; import org.example.property.TokenProperty; +import org.example.repository.TokenRepository; import org.example.security.dto.TokenParam; import org.example.security.dto.UserParam; import org.springframework.stereotype.Component; @@ -13,12 +14,16 @@ public class JWTGenerator { private final TokenProperty tokenProperty; + private final TokenRepository tokenRepository; public TokenParam generate(UserParam userParam, Date from) { - return TokenParam.builder() + TokenParam tokenParam = TokenParam.builder() .accessToken(createAccessToken(userParam, from)) .refreshToken(createRefreshToken(userParam, from)) .build(); + + tokenRepository.save(userParam.userId().toString(), tokenParam.refreshToken()); + return tokenParam; } private String createAccessToken(UserParam userParam, Date from) { diff --git a/app/api/common-api/src/main/java/org/example/security/token/RefreshTokenProcessor.java b/app/api/common-api/src/main/java/org/example/security/token/RefreshTokenProcessor.java index 1f275367..8dddca1c 100644 --- a/app/api/common-api/src/main/java/org/example/security/token/RefreshTokenProcessor.java +++ b/app/api/common-api/src/main/java/org/example/security/token/RefreshTokenProcessor.java @@ -3,9 +3,11 @@ import jakarta.servlet.http.HttpServletRequest; import java.util.Date; import lombok.RequiredArgsConstructor; -import org.example.repository.RedisRepository; +import org.example.exception.BusinessException; +import org.example.repository.TokenRepository; import org.example.security.dto.TokenParam; import org.example.security.dto.UserParam; +import org.example.security.vo.TokenError; import org.springframework.stereotype.Component; @Component @@ -14,17 +16,20 @@ public class RefreshTokenProcessor { private final JWTHandler jwtHandler; private final JWTGenerator jwtGenerator; - private final RedisRepository redisRepository; + private final TokenRepository tokenRepository; public TokenParam reissueToken(HttpServletRequest request) { String refreshToken = jwtHandler.extractRefreshToken(request); UserParam userParam = jwtHandler.extractUserFrom(refreshToken); - // 기존 redis의 Refresh토큰과 비교해서 맞는 refresh인지 확인 해야함 + String oldRefreshToken = tokenRepository.getOldRefreshToken(userParam.userId().toString()); + if (!refreshToken.equals(oldRefreshToken)) { + throw new BusinessException(TokenError.INVALID_TOKEN); + } TokenParam newTokenParam = jwtGenerator.generate(userParam, new Date()); - redisRepository.save(userParam.userId().toString(), newTokenParam.refreshToken()); + tokenRepository.save(userParam.userId().toString(), newTokenParam.refreshToken()); return newTokenParam; } } diff --git a/app/api/common-api/src/test/java/org/example/security/token/JWTGeneratorTest.java b/app/api/common-api/src/test/java/org/example/security/token/JWTGeneratorTest.java index f5e1d5b1..7449e925 100644 --- a/app/api/common-api/src/test/java/org/example/security/token/JWTGeneratorTest.java +++ b/app/api/common-api/src/test/java/org/example/security/token/JWTGeneratorTest.java @@ -1,10 +1,13 @@ package org.example.security.token; +import static org.mockito.Mockito.mock; + import io.jsonwebtoken.ExpiredJwtException; import io.jsonwebtoken.Jwts; import java.util.Date; import java.util.UUID; import org.example.property.TokenProperty; +import org.example.repository.TokenRepository; import org.example.security.dto.TokenParam; import org.example.security.dto.UserParam; import org.example.vo.UserRoleApiType; @@ -23,8 +26,8 @@ class JWTGeneratorTest { hour, twoWeeks ); - - JWTGenerator tokenGenerator = new JWTGenerator(tokenProperty); + TokenRepository tokenRepository = mock(TokenRepository.class); + JWTGenerator tokenGenerator = new JWTGenerator(tokenProperty, tokenRepository); UserParam userParam = new UserParam( UUID.randomUUID(), UserRoleApiType.USER diff --git a/app/api/common-api/src/test/java/org/example/security/token/JWTHandlerTest.java b/app/api/common-api/src/test/java/org/example/security/token/JWTHandlerTest.java index 7227d068..2e43fbe5 100644 --- a/app/api/common-api/src/test/java/org/example/security/token/JWTHandlerTest.java +++ b/app/api/common-api/src/test/java/org/example/security/token/JWTHandlerTest.java @@ -2,11 +2,13 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.Mockito.mock; import java.util.Date; import java.util.UUID; import org.example.exception.BusinessException; import org.example.property.TokenProperty; +import org.example.repository.TokenRepository; import org.example.security.dto.TokenParam; import org.example.security.dto.UserParam; import org.example.security.vo.TokenError; @@ -22,8 +24,9 @@ class JWTHandlerTest { 3600000L, 1209600000L ); + TokenRepository tokenRepository = mock(TokenRepository.class); JWTHandler jwtHandler = new JWTHandler(tokenProperty); - JWTGenerator jwtGenerator = new JWTGenerator(tokenProperty); + JWTGenerator jwtGenerator = new JWTGenerator(tokenProperty, tokenRepository); UserParam userParam = new UserParam( UUID.randomUUID(), UserRoleApiType.USER diff --git a/app/api/user-api/src/main/java/org/example/repository/RedisRepository.java b/app/api/user-api/src/main/java/org/example/repository/RedisRepository.java deleted file mode 100644 index d7d1782b..00000000 --- a/app/api/user-api/src/main/java/org/example/repository/RedisRepository.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.example.repository; - -import org.springframework.stereotype.Component; - -@Component -public interface RedisRepository { - - void save(String userId, String refreshToken); -} diff --git a/app/api/user-api/src/main/java/org/example/service/UserService.java b/app/api/user-api/src/main/java/org/example/service/UserService.java index abeaef16..9b6ec699 100644 --- a/app/api/user-api/src/main/java/org/example/service/UserService.java +++ b/app/api/user-api/src/main/java/org/example/service/UserService.java @@ -3,7 +3,6 @@ import java.util.Date; import lombok.RequiredArgsConstructor; import org.example.entity.User; -import org.example.repository.RedisRepository; import org.example.security.dto.TokenParam; import org.example.security.dto.UserParam; import org.example.security.token.JWTGenerator; @@ -18,7 +17,7 @@ public class UserService { private final UserUseCase userUseCase; private final JWTGenerator jwtGenerator; - private final RedisRepository redisRepository; + public TokenParam login(final LoginServiceRequest loginServiceRequest) { User createdUser = userUseCase.save(loginServiceRequest.toLoginServiceDto().toUser()); @@ -26,11 +25,8 @@ public TokenParam login(final LoginServiceRequest loginServiceRequest) { .userId(createdUser.getId()) .role(UserRoleApiType.valueOf(createdUser.getUserRole().name())) .build(); - TokenParam tokenParam = jwtGenerator.generate(userParam, new Date()); - - redisRepository.save(userParam.userId().toString(), tokenParam.refreshToken()); - return tokenParam; + return jwtGenerator.generate(userParam, new Date()); } public String findNickname(final User user) { diff --git a/app/infrastructure/redis/build.gradle b/app/infrastructure/redis/build.gradle index cc56c6b0..f901e61e 100644 --- a/app/infrastructure/redis/build.gradle +++ b/app/infrastructure/redis/build.gradle @@ -2,7 +2,6 @@ bootJar.enabled = false jar.enabled = true dependencies { - implementation project(":app:api:user-api") implementation project(":app:api:common-api") //redis diff --git a/app/infrastructure/redis/src/main/java/org/example/repository/LettuceRedisRepository.java b/app/infrastructure/redis/src/main/java/org/example/repository/LettuceRedisRepository.java index 5d22c252..d861b84d 100644 --- a/app/infrastructure/redis/src/main/java/org/example/repository/LettuceRedisRepository.java +++ b/app/infrastructure/redis/src/main/java/org/example/repository/LettuceRedisRepository.java @@ -7,12 +7,18 @@ @Component @RequiredArgsConstructor -public class LettuceRedisRepository implements RedisRepository { +public class LettuceRedisRepository implements TokenRepository { private final StringRedisTemplate stringRedisTemplate; + @Override public void save(String userId, String refreshToken) { stringRedisTemplate.opsForValue().set("userId:" + userId, refreshToken, 14, TimeUnit.DAYS); } + @Override + public String getOldRefreshToken(String userId) { + return stringRedisTemplate.opsForValue().get("userId:" + userId); + } + } From 9bae61739cbf0464041057a00ce177549b38c2f8 Mon Sep 17 00:00:00 2001 From: GaBaljaintheroom Date: Fri, 14 Jun 2024 13:36:48 +0900 Subject: [PATCH 19/23] =?UTF-8?q?refactor=20:=20common-api=20=EB=AA=A8?= =?UTF-8?q?=EB=93=88=20=EC=9D=98=EC=A1=B4=EC=84=B1=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/api/build.gradle | 1 - app/api/src/main/java/org/example/config/ApiConfig.java | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/app/api/build.gradle b/app/api/build.gradle index d974bc19..379bd9ba 100644 --- a/app/api/build.gradle +++ b/app/api/build.gradle @@ -18,5 +18,4 @@ allprojects { dependencies { implementation project(":app:api:user-api") - implementation project(":app:api:common-api") } \ No newline at end of file diff --git a/app/api/src/main/java/org/example/config/ApiConfig.java b/app/api/src/main/java/org/example/config/ApiConfig.java index f7c59525..d205a94a 100644 --- a/app/api/src/main/java/org/example/config/ApiConfig.java +++ b/app/api/src/main/java/org/example/config/ApiConfig.java @@ -4,7 +4,7 @@ import org.springframework.context.annotation.Import; @Configuration -@Import({UserApiConfig.class, CommonApiConfig.class}) +@Import(UserApiConfig.class) public class ApiConfig { } From 0942e58c93fe7e13b5c0a2cbdc0bca793536a031 Mon Sep 17 00:00:00 2001 From: GaBaljaintheroom Date: Fri, 14 Jun 2024 14:34:38 +0900 Subject: [PATCH 20/23] =?UTF-8?q?refactor=20:=20jwtfilter=20=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=EC=95=84=EC=9B=83=20=EB=90=9C=20=ED=86=A0=ED=81=B0?= =?UTF-8?q?=EC=9D=B8=EC=A7=80=20=EA=B2=80=EC=A6=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/org/example/filter/JWTFilter.java | 5 +++++ .../org/example/repository/TokenRepository.java | 5 ++++- .../org/example/security/token/JWTGenerator.java | 13 +++++++++++++ .../security/token/RefreshTokenProcessor.java | 9 ++------- .../example/repository/LettuceRedisRepository.java | 12 +++++++++--- 5 files changed, 33 insertions(+), 11 deletions(-) diff --git a/app/api/common-api/src/main/java/org/example/filter/JWTFilter.java b/app/api/common-api/src/main/java/org/example/filter/JWTFilter.java index 97432faa..08394df0 100644 --- a/app/api/common-api/src/main/java/org/example/filter/JWTFilter.java +++ b/app/api/common-api/src/main/java/org/example/filter/JWTFilter.java @@ -11,6 +11,7 @@ import org.example.security.dto.AuthenticatedUser; import org.example.security.dto.TokenParam; import org.example.security.dto.UserParam; +import org.example.security.token.JWTGenerator; import org.example.security.token.JWTHandler; import org.example.security.token.RefreshTokenProcessor; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; @@ -24,6 +25,7 @@ public class JWTFilter extends OncePerRequestFilter { private final JWTHandler jwtHandler; + private final JWTGenerator jwtGenerator; private final RefreshTokenProcessor refreshTokenProcessor; @Override @@ -48,6 +50,9 @@ protected void doFilterInternal( private void handleAccessToken(HttpServletRequest request) { String accessToken = jwtHandler.extractAccessToken(request); UserParam userParam = jwtHandler.extractUserFrom(accessToken); + + jwtGenerator.verifyLogoutAccessToken(userParam); + saveOnSecurityContextHolder(userParam); } diff --git a/app/api/common-api/src/main/java/org/example/repository/TokenRepository.java b/app/api/common-api/src/main/java/org/example/repository/TokenRepository.java index f98cc5d5..d2020457 100644 --- a/app/api/common-api/src/main/java/org/example/repository/TokenRepository.java +++ b/app/api/common-api/src/main/java/org/example/repository/TokenRepository.java @@ -1,5 +1,6 @@ package org.example.repository; +import java.util.Optional; import org.springframework.stereotype.Component; @Component @@ -7,5 +8,7 @@ public interface TokenRepository { void save(String userId, String refreshToken); - String getOldRefreshToken(String userId); + Optional getOldRefreshToken(String userId); + + boolean existAccessToken(String userId); } diff --git a/app/api/common-api/src/main/java/org/example/security/token/JWTGenerator.java b/app/api/common-api/src/main/java/org/example/security/token/JWTGenerator.java index af6181a1..f41d9b25 100644 --- a/app/api/common-api/src/main/java/org/example/security/token/JWTGenerator.java +++ b/app/api/common-api/src/main/java/org/example/security/token/JWTGenerator.java @@ -3,10 +3,12 @@ import io.jsonwebtoken.Jwts; import java.util.Date; import lombok.RequiredArgsConstructor; +import org.example.exception.BusinessException; import org.example.property.TokenProperty; import org.example.repository.TokenRepository; import org.example.security.dto.TokenParam; import org.example.security.dto.UserParam; +import org.example.security.vo.TokenError; import org.springframework.stereotype.Component; @Component @@ -47,4 +49,15 @@ private String createRefreshToken(UserParam userParam, Date from) { .signWith(tokenProperty.getBase64URLSecretKey()) .compact(); } + + public String getOldRefreshToken(UserParam userParam) { + return tokenRepository.getOldRefreshToken(userParam.userId().toString()) + .orElseThrow(() -> new BusinessException(TokenError.WRONG_HEADER)); + } + + public void verifyLogoutAccessToken(UserParam userParam) { + if (tokenRepository.existAccessToken(userParam.userId().toString())) { + throw new BusinessException(TokenError.INVALID_TOKEN); + } + } } diff --git a/app/api/common-api/src/main/java/org/example/security/token/RefreshTokenProcessor.java b/app/api/common-api/src/main/java/org/example/security/token/RefreshTokenProcessor.java index 8dddca1c..c994988c 100644 --- a/app/api/common-api/src/main/java/org/example/security/token/RefreshTokenProcessor.java +++ b/app/api/common-api/src/main/java/org/example/security/token/RefreshTokenProcessor.java @@ -4,7 +4,6 @@ import java.util.Date; import lombok.RequiredArgsConstructor; import org.example.exception.BusinessException; -import org.example.repository.TokenRepository; import org.example.security.dto.TokenParam; import org.example.security.dto.UserParam; import org.example.security.vo.TokenError; @@ -16,20 +15,16 @@ public class RefreshTokenProcessor { private final JWTHandler jwtHandler; private final JWTGenerator jwtGenerator; - private final TokenRepository tokenRepository; public TokenParam reissueToken(HttpServletRequest request) { String refreshToken = jwtHandler.extractRefreshToken(request); UserParam userParam = jwtHandler.extractUserFrom(refreshToken); - String oldRefreshToken = tokenRepository.getOldRefreshToken(userParam.userId().toString()); + String oldRefreshToken = jwtGenerator.getOldRefreshToken(userParam); if (!refreshToken.equals(oldRefreshToken)) { throw new BusinessException(TokenError.INVALID_TOKEN); } - TokenParam newTokenParam = jwtGenerator.generate(userParam, new Date()); - - tokenRepository.save(userParam.userId().toString(), newTokenParam.refreshToken()); - return newTokenParam; + return jwtGenerator.generate(userParam, new Date()); } } diff --git a/app/infrastructure/redis/src/main/java/org/example/repository/LettuceRedisRepository.java b/app/infrastructure/redis/src/main/java/org/example/repository/LettuceRedisRepository.java index d861b84d..fe87c2dc 100644 --- a/app/infrastructure/redis/src/main/java/org/example/repository/LettuceRedisRepository.java +++ b/app/infrastructure/redis/src/main/java/org/example/repository/LettuceRedisRepository.java @@ -1,5 +1,6 @@ package org.example.repository; +import java.util.Optional; import java.util.concurrent.TimeUnit; import lombok.RequiredArgsConstructor; import org.springframework.data.redis.core.StringRedisTemplate; @@ -13,12 +14,17 @@ public class LettuceRedisRepository implements TokenRepository { @Override public void save(String userId, String refreshToken) { - stringRedisTemplate.opsForValue().set("userId:" + userId, refreshToken, 14, TimeUnit.DAYS); + stringRedisTemplate.opsForValue().set("RT:" + userId, refreshToken, 14, TimeUnit.DAYS); } @Override - public String getOldRefreshToken(String userId) { - return stringRedisTemplate.opsForValue().get("userId:" + userId); + public Optional getOldRefreshToken(String userId) { + return Optional.ofNullable(stringRedisTemplate.opsForValue().get("RT:" + userId)); + } + + @Override + public boolean existAccessToken(String userId) { + return Boolean.TRUE.equals(stringRedisTemplate.hasKey("AT:" + userId)); } } From 708cb42c0b87d75894ccecc5bc904ca6a050ef17 Mon Sep 17 00:00:00 2001 From: GaBaljaintheroom Date: Fri, 14 Jun 2024 14:48:10 +0900 Subject: [PATCH 21/23] =?UTF-8?q?refactor=20:=20existAccessToken=20?= =?UTF-8?q?=EB=A9=94=EC=84=9C=EB=93=9C=20=ED=83=80=EC=9E=85=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/org/example/repository/TokenRepository.java | 2 +- .../java/org/example/repository/LettuceRedisRepository.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/api/common-api/src/main/java/org/example/repository/TokenRepository.java b/app/api/common-api/src/main/java/org/example/repository/TokenRepository.java index d2020457..f53da2b6 100644 --- a/app/api/common-api/src/main/java/org/example/repository/TokenRepository.java +++ b/app/api/common-api/src/main/java/org/example/repository/TokenRepository.java @@ -10,5 +10,5 @@ public interface TokenRepository { Optional getOldRefreshToken(String userId); - boolean existAccessToken(String userId); + Boolean existAccessToken(String userId); } diff --git a/app/infrastructure/redis/src/main/java/org/example/repository/LettuceRedisRepository.java b/app/infrastructure/redis/src/main/java/org/example/repository/LettuceRedisRepository.java index fe87c2dc..96f9d032 100644 --- a/app/infrastructure/redis/src/main/java/org/example/repository/LettuceRedisRepository.java +++ b/app/infrastructure/redis/src/main/java/org/example/repository/LettuceRedisRepository.java @@ -23,8 +23,8 @@ public Optional getOldRefreshToken(String userId) { } @Override - public boolean existAccessToken(String userId) { - return Boolean.TRUE.equals(stringRedisTemplate.hasKey("AT:" + userId)); + public Boolean existAccessToken(String userId) { + return stringRedisTemplate.hasKey("AT:" + userId); } } From ff5a1913b17237de31798cf590561a596db2c429 Mon Sep 17 00:00:00 2001 From: GaBaljaintheroom Date: Sat, 15 Jun 2024 11:38:43 +0900 Subject: [PATCH 22/23] =?UTF-8?q?refactor=20:=20PR=20=EB=A6=AC=EB=B7=B0=20?= =?UTF-8?q?=ED=9B=84=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/api/common-api/build.gradle | 2 ++ .../java/org/example/filter/JWTFilter.java | 14 +++++++++++--- .../example/repository/TokenRepository.java | 2 +- .../example/security/token/JWTGenerator.java | 9 ++------- .../security/token/RefreshTokenProcessor.java | 2 +- .../java/org/example/vo/UserRoleApiType.java | 5 +++++ .../org/example/controller/UserController.java | 3 +-- .../example/controller/dto/LoginApiDto.java | 17 ----------------- .../dto/request/LoginApiRequest.java | 6 +++--- .../java/org/example/service/UserService.java | 4 ++-- .../example/service/dto/LoginServiceDto.java | 18 ------------------ .../dto/request/LoginServiceRequest.java | 6 +++--- .../src/main/java/org/example/entity/User.java | 2 +- .../main/java/org/example/vo/UserGender.java | 2 +- .../repository/LettuceRedisRepository.java | 2 +- 15 files changed, 34 insertions(+), 60 deletions(-) delete mode 100644 app/api/user-api/src/main/java/org/example/controller/dto/LoginApiDto.java delete mode 100644 app/api/user-api/src/main/java/org/example/service/dto/LoginServiceDto.java diff --git a/app/api/common-api/build.gradle b/app/api/common-api/build.gradle index 681b65f9..851f64ac 100644 --- a/app/api/common-api/build.gradle +++ b/app/api/common-api/build.gradle @@ -2,6 +2,8 @@ bootJar.enabled = false jar.enabled = true dependencies { + implementation project(":app:domain:user-domain") + // spring-security implementation 'org.springframework.boot:spring-boot-starter-security' diff --git a/app/api/common-api/src/main/java/org/example/filter/JWTFilter.java b/app/api/common-api/src/main/java/org/example/filter/JWTFilter.java index 08394df0..a6a65152 100644 --- a/app/api/common-api/src/main/java/org/example/filter/JWTFilter.java +++ b/app/api/common-api/src/main/java/org/example/filter/JWTFilter.java @@ -8,12 +8,15 @@ import java.io.IOException; import java.util.List; import lombok.RequiredArgsConstructor; +import org.example.exception.BusinessException; +import org.example.repository.TokenRepository; import org.example.security.dto.AuthenticatedUser; import org.example.security.dto.TokenParam; import org.example.security.dto.UserParam; import org.example.security.token.JWTGenerator; import org.example.security.token.JWTHandler; import org.example.security.token.RefreshTokenProcessor; +import org.example.security.vo.TokenError; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.context.SecurityContextHolder; @@ -27,6 +30,7 @@ public class JWTFilter extends OncePerRequestFilter { private final JWTHandler jwtHandler; private final JWTGenerator jwtGenerator; private final RefreshTokenProcessor refreshTokenProcessor; + private final TokenRepository tokenRepository; @Override protected void doFilterInternal( @@ -50,12 +54,16 @@ protected void doFilterInternal( private void handleAccessToken(HttpServletRequest request) { String accessToken = jwtHandler.extractAccessToken(request); UserParam userParam = jwtHandler.extractUserFrom(accessToken); - - jwtGenerator.verifyLogoutAccessToken(userParam); - + verifyLogoutAccessToken(userParam); saveOnSecurityContextHolder(userParam); } + public void verifyLogoutAccessToken(UserParam userParam) { + if (tokenRepository.existAccessToken(userParam.userId().toString())) { + throw new BusinessException(TokenError.INVALID_TOKEN); + } + } + private void saveOnSecurityContextHolder(UserParam userParam) { AuthenticatedUser authenticatedUser = AuthenticatedUser.builder() .userId(userParam.userId()) diff --git a/app/api/common-api/src/main/java/org/example/repository/TokenRepository.java b/app/api/common-api/src/main/java/org/example/repository/TokenRepository.java index f53da2b6..d54eb616 100644 --- a/app/api/common-api/src/main/java/org/example/repository/TokenRepository.java +++ b/app/api/common-api/src/main/java/org/example/repository/TokenRepository.java @@ -8,7 +8,7 @@ public interface TokenRepository { void save(String userId, String refreshToken); - Optional getOldRefreshToken(String userId); + Optional getExistRefreshToken(String userId); Boolean existAccessToken(String userId); } diff --git a/app/api/common-api/src/main/java/org/example/security/token/JWTGenerator.java b/app/api/common-api/src/main/java/org/example/security/token/JWTGenerator.java index f41d9b25..35828989 100644 --- a/app/api/common-api/src/main/java/org/example/security/token/JWTGenerator.java +++ b/app/api/common-api/src/main/java/org/example/security/token/JWTGenerator.java @@ -50,14 +50,9 @@ private String createRefreshToken(UserParam userParam, Date from) { .compact(); } - public String getOldRefreshToken(UserParam userParam) { - return tokenRepository.getOldRefreshToken(userParam.userId().toString()) + public String getExistRefreshToken(UserParam userParam) { + return tokenRepository.getExistRefreshToken(userParam.userId().toString()) .orElseThrow(() -> new BusinessException(TokenError.WRONG_HEADER)); } - public void verifyLogoutAccessToken(UserParam userParam) { - if (tokenRepository.existAccessToken(userParam.userId().toString())) { - throw new BusinessException(TokenError.INVALID_TOKEN); - } - } } diff --git a/app/api/common-api/src/main/java/org/example/security/token/RefreshTokenProcessor.java b/app/api/common-api/src/main/java/org/example/security/token/RefreshTokenProcessor.java index c994988c..666537c2 100644 --- a/app/api/common-api/src/main/java/org/example/security/token/RefreshTokenProcessor.java +++ b/app/api/common-api/src/main/java/org/example/security/token/RefreshTokenProcessor.java @@ -20,7 +20,7 @@ public TokenParam reissueToken(HttpServletRequest request) { String refreshToken = jwtHandler.extractRefreshToken(request); UserParam userParam = jwtHandler.extractUserFrom(refreshToken); - String oldRefreshToken = jwtGenerator.getOldRefreshToken(userParam); + String oldRefreshToken = jwtGenerator.getExistRefreshToken(userParam); if (!refreshToken.equals(oldRefreshToken)) { throw new BusinessException(TokenError.INVALID_TOKEN); } diff --git a/app/api/common-api/src/main/java/org/example/vo/UserRoleApiType.java b/app/api/common-api/src/main/java/org/example/vo/UserRoleApiType.java index 6e88d9ea..05e24e6e 100644 --- a/app/api/common-api/src/main/java/org/example/vo/UserRoleApiType.java +++ b/app/api/common-api/src/main/java/org/example/vo/UserRoleApiType.java @@ -1,6 +1,7 @@ package org.example.vo; import lombok.Getter; +import org.example.entity.User; @Getter public enum UserRoleApiType { @@ -13,4 +14,8 @@ public enum UserRoleApiType { UserRoleApiType(String authority) { this.authority = authority; } + + public static UserRoleApiType from(User user) { + return UserRoleApiType.valueOf(user.getUserRole().name()); + } } diff --git a/app/api/user-api/src/main/java/org/example/controller/UserController.java b/app/api/user-api/src/main/java/org/example/controller/UserController.java index 28dafb64..10254cc3 100644 --- a/app/api/user-api/src/main/java/org/example/controller/UserController.java +++ b/app/api/user-api/src/main/java/org/example/controller/UserController.java @@ -25,8 +25,7 @@ public class UserController { @Tag(name = "user") @Operation(summary = "유저 로그인", description = "사용자는 소셜 로그인을 할 수 있다.") public ResponseEntity signUp(@Valid @RequestBody LoginApiRequest request) { - final LoginServiceRequest loginServiceRequest = request.toLoginApiDto() - .toLoginServiceRequest(); + LoginServiceRequest loginServiceRequest = request.toLoginServiceRequest(); TokenParam tokenParam = userService.login(loginServiceRequest); return ResponseEntity.ok(tokenParam); diff --git a/app/api/user-api/src/main/java/org/example/controller/dto/LoginApiDto.java b/app/api/user-api/src/main/java/org/example/controller/dto/LoginApiDto.java deleted file mode 100644 index 7f213a45..00000000 --- a/app/api/user-api/src/main/java/org/example/controller/dto/LoginApiDto.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.example.controller.dto; - -import lombok.Builder; -import org.example.entity.credential.SocialCredentials; -import org.example.service.dto.request.LoginServiceRequest; - -@Builder -public record LoginApiDto( - SocialCredentials socialCredentials -) { - - public LoginServiceRequest toLoginServiceRequest() { - return LoginServiceRequest.builder() - .socialCredentials(socialCredentials) - .build(); - } -} diff --git a/app/api/user-api/src/main/java/org/example/controller/dto/request/LoginApiRequest.java b/app/api/user-api/src/main/java/org/example/controller/dto/request/LoginApiRequest.java index 08939577..5397e520 100644 --- a/app/api/user-api/src/main/java/org/example/controller/dto/request/LoginApiRequest.java +++ b/app/api/user-api/src/main/java/org/example/controller/dto/request/LoginApiRequest.java @@ -1,12 +1,12 @@ package org.example.controller.dto.request; import jakarta.validation.constraints.NotNull; -import org.example.controller.dto.LoginApiDto; import org.example.entity.credential.AppleSocialCredential; import org.example.entity.credential.GoogleSocialCredential; import org.example.entity.credential.KakaoSocialCredential; import org.example.entity.credential.SocialCredential; import org.example.entity.credential.SocialCredentials; +import org.example.service.dto.request.LoginServiceRequest; import org.example.vo.SocialLoginType; public record LoginApiRequest( @@ -17,8 +17,8 @@ public record LoginApiRequest( String socialLoginIdentifier ) { - public LoginApiDto toLoginApiDto() { - return LoginApiDto.builder() + public LoginServiceRequest toLoginServiceRequest() { + return LoginServiceRequest.builder() .socialCredentials(socialCredentials()) .build(); } diff --git a/app/api/user-api/src/main/java/org/example/service/UserService.java b/app/api/user-api/src/main/java/org/example/service/UserService.java index 9b6ec699..fa8663ca 100644 --- a/app/api/user-api/src/main/java/org/example/service/UserService.java +++ b/app/api/user-api/src/main/java/org/example/service/UserService.java @@ -20,10 +20,10 @@ public class UserService { public TokenParam login(final LoginServiceRequest loginServiceRequest) { - User createdUser = userUseCase.save(loginServiceRequest.toLoginServiceDto().toUser()); + User createdUser = userUseCase.save(loginServiceRequest.toUser()); UserParam userParam = UserParam.builder() .userId(createdUser.getId()) - .role(UserRoleApiType.valueOf(createdUser.getUserRole().name())) + .role(UserRoleApiType.from(createdUser)) .build(); return jwtGenerator.generate(userParam, new Date()); diff --git a/app/api/user-api/src/main/java/org/example/service/dto/LoginServiceDto.java b/app/api/user-api/src/main/java/org/example/service/dto/LoginServiceDto.java deleted file mode 100644 index 0dbe0c32..00000000 --- a/app/api/user-api/src/main/java/org/example/service/dto/LoginServiceDto.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.example.service.dto; - -import lombok.Builder; -import org.example.entity.User; -import org.example.entity.credential.SocialCredentials; - -@Builder -public record LoginServiceDto( - SocialCredentials socialCredentials - -) { - - public User toUser() { - return User.builder() - .socialCredentials(socialCredentials) - .build(); - } -} diff --git a/app/api/user-api/src/main/java/org/example/service/dto/request/LoginServiceRequest.java b/app/api/user-api/src/main/java/org/example/service/dto/request/LoginServiceRequest.java index 78e05fc8..c6731401 100644 --- a/app/api/user-api/src/main/java/org/example/service/dto/request/LoginServiceRequest.java +++ b/app/api/user-api/src/main/java/org/example/service/dto/request/LoginServiceRequest.java @@ -1,16 +1,16 @@ package org.example.service.dto.request; import lombok.Builder; +import org.example.entity.User; import org.example.entity.credential.SocialCredentials; -import org.example.service.dto.LoginServiceDto; @Builder public record LoginServiceRequest( SocialCredentials socialCredentials ) { - public LoginServiceDto toLoginServiceDto() { - return LoginServiceDto.builder() + public User toUser() { + return User.builder() .socialCredentials(socialCredentials) .build(); } diff --git a/app/domain/user-domain/src/main/java/org/example/entity/User.java b/app/domain/user-domain/src/main/java/org/example/entity/User.java index ac4ed9a0..872788b5 100644 --- a/app/domain/user-domain/src/main/java/org/example/entity/User.java +++ b/app/domain/user-domain/src/main/java/org/example/entity/User.java @@ -35,7 +35,7 @@ public class User extends BaseEntity { @Column(name = "gender", nullable = false) @Enumerated(value = EnumType.STRING) - private UserGender userGender = UserGender.NONE; + private UserGender userGender = UserGender.NOT_CHOSEN; @Column(name = "role", nullable = false) @Enumerated(value = EnumType.STRING) diff --git a/app/domain/user-domain/src/main/java/org/example/vo/UserGender.java b/app/domain/user-domain/src/main/java/org/example/vo/UserGender.java index d99edc20..dbde773b 100644 --- a/app/domain/user-domain/src/main/java/org/example/vo/UserGender.java +++ b/app/domain/user-domain/src/main/java/org/example/vo/UserGender.java @@ -1,5 +1,5 @@ package org.example.vo; public enum UserGender { - MAN, WOMAN, NONE + MAN, WOMAN, NOT_CHOSEN } diff --git a/app/infrastructure/redis/src/main/java/org/example/repository/LettuceRedisRepository.java b/app/infrastructure/redis/src/main/java/org/example/repository/LettuceRedisRepository.java index 96f9d032..ebe53742 100644 --- a/app/infrastructure/redis/src/main/java/org/example/repository/LettuceRedisRepository.java +++ b/app/infrastructure/redis/src/main/java/org/example/repository/LettuceRedisRepository.java @@ -18,7 +18,7 @@ public void save(String userId, String refreshToken) { } @Override - public Optional getOldRefreshToken(String userId) { + public Optional getExistRefreshToken(String userId) { return Optional.ofNullable(stringRedisTemplate.opsForValue().get("RT:" + userId)); } From 63655948649e897dccc8c65c392213a6ebe7ddf3 Mon Sep 17 00:00:00 2001 From: GaBaljaintheroom Date: Sat, 15 Jun 2024 11:52:43 +0900 Subject: [PATCH 23/23] =?UTF-8?q?refactor=20:=20UserRoleApiType=20?= =?UTF-8?q?=EB=A7=A4=EA=B2=8C=EB=B3=80=EC=88=98=20=ED=83=80=EC=9E=85=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 --- .../src/main/java/org/example/vo/UserRoleApiType.java | 5 ++--- .../src/main/java/org/example/service/UserService.java | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/app/api/common-api/src/main/java/org/example/vo/UserRoleApiType.java b/app/api/common-api/src/main/java/org/example/vo/UserRoleApiType.java index 05e24e6e..2c214fbe 100644 --- a/app/api/common-api/src/main/java/org/example/vo/UserRoleApiType.java +++ b/app/api/common-api/src/main/java/org/example/vo/UserRoleApiType.java @@ -1,7 +1,6 @@ package org.example.vo; import lombok.Getter; -import org.example.entity.User; @Getter public enum UserRoleApiType { @@ -15,7 +14,7 @@ public enum UserRoleApiType { this.authority = authority; } - public static UserRoleApiType from(User user) { - return UserRoleApiType.valueOf(user.getUserRole().name()); + public static UserRoleApiType from(UserRole userRole) { + return UserRoleApiType.valueOf(userRole.name()); } } diff --git a/app/api/user-api/src/main/java/org/example/service/UserService.java b/app/api/user-api/src/main/java/org/example/service/UserService.java index fa8663ca..024ded50 100644 --- a/app/api/user-api/src/main/java/org/example/service/UserService.java +++ b/app/api/user-api/src/main/java/org/example/service/UserService.java @@ -23,7 +23,7 @@ public TokenParam login(final LoginServiceRequest loginServiceRequest) { User createdUser = userUseCase.save(loginServiceRequest.toUser()); UserParam userParam = UserParam.builder() .userId(createdUser.getId()) - .role(UserRoleApiType.from(createdUser)) + .role(UserRoleApiType.from(createdUser.getUserRole())) .build(); return jwtGenerator.generate(userParam, new Date());