From 781ab9211dbfd0917ff391255cddbd74d8354cf5 Mon Sep 17 00:00:00 2001 From: ivyxjc Date: Wed, 30 Apr 2025 16:29:22 +0800 Subject: [PATCH 1/2] feat(): dynamodb support --- build.gradle.kts | 3 + .../entity/UserRefreshTokenMapping.java | 3 +- .../authforge/repository/UserRepository.java | 12 +- .../repository/dynamodb/DynamodbUser.java | 184 ++++++++++++++++++ .../dynamodb/DynamodbUserRepositoryImpl.java | 166 ++++++++++++++++ .../repository/dynamodb/DynamodbUserUtil.java | 88 +++++++++ 6 files changed, 449 insertions(+), 7 deletions(-) create mode 100644 src/main/java/org/clevercastle/authforge/repository/dynamodb/DynamodbUser.java create mode 100644 src/main/java/org/clevercastle/authforge/repository/dynamodb/DynamodbUserRepositoryImpl.java create mode 100644 src/main/java/org/clevercastle/authforge/repository/dynamodb/DynamodbUserUtil.java diff --git a/build.gradle.kts b/build.gradle.kts index 6d03d58..8153b80 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -24,6 +24,9 @@ dependencies { implementation("com.nimbusds:oauth2-oidc-sdk:11.23.1") + implementation("software.amazon.awssdk:dynamodb:2.31.31") + implementation("software.amazon.awssdk:dynamodb-enhanced:2.31.31") + compileOnly("org.springframework.boot:spring-boot-starter-data-jpa:2.7.18") implementation("org.apache.commons:commons-lang3:3.17.0") diff --git a/src/main/java/org/clevercastle/authforge/entity/UserRefreshTokenMapping.java b/src/main/java/org/clevercastle/authforge/entity/UserRefreshTokenMapping.java index 80098d3..68be72e 100644 --- a/src/main/java/org/clevercastle/authforge/entity/UserRefreshTokenMapping.java +++ b/src/main/java/org/clevercastle/authforge/entity/UserRefreshTokenMapping.java @@ -22,9 +22,10 @@ public class UserRefreshTokenMapping { @Id private String refreshToken; - private OffsetDateTime createdAt; private OffsetDateTime expiredAt; + private OffsetDateTime createdAt; + public String getUserId() { return userId; diff --git a/src/main/java/org/clevercastle/authforge/repository/UserRepository.java b/src/main/java/org/clevercastle/authforge/repository/UserRepository.java index d2870ec..166e3a6 100644 --- a/src/main/java/org/clevercastle/authforge/repository/UserRepository.java +++ b/src/main/java/org/clevercastle/authforge/repository/UserRepository.java @@ -2,25 +2,25 @@ import jakarta.annotation.Nonnull; import org.apache.commons.lang3.tuple.Pair; -import org.clevercastle.authforge.exception.CastleException; import org.clevercastle.authforge.entity.User; import org.clevercastle.authforge.entity.UserLoginItem; import org.clevercastle.authforge.entity.UserRefreshTokenMapping; +import org.clevercastle.authforge.exception.CastleException; import java.time.OffsetDateTime; public interface UserRepository { - void save(User user, UserLoginItem userLoginItem); + void save(User user, UserLoginItem userLoginItem) throws CastleException; @Nonnull - Pair getByLoginIdentifier(String loginIdentifier); + Pair getByLoginIdentifier(String loginIdentifier) throws CastleException; @Nonnull - Pair getByUserSub(String userSUb); + Pair getByUserSub(String userSUb) throws CastleException; - void confirmLoginItem(String loginIdentifier); + void confirmLoginItem(String loginIdentifier) throws CastleException; - UserRefreshTokenMapping addRefreshToken(User user, String refreshToken, OffsetDateTime expiredAt); + UserRefreshTokenMapping addRefreshToken(User user, String refreshToken, OffsetDateTime expiredAt) throws CastleException; boolean verifyRefreshToken(User user, String refreshToken) throws CastleException; } \ No newline at end of file diff --git a/src/main/java/org/clevercastle/authforge/repository/dynamodb/DynamodbUser.java b/src/main/java/org/clevercastle/authforge/repository/dynamodb/DynamodbUser.java new file mode 100644 index 0000000..57fcb60 --- /dev/null +++ b/src/main/java/org/clevercastle/authforge/repository/dynamodb/DynamodbUser.java @@ -0,0 +1,184 @@ +package org.clevercastle.authforge.repository.dynamodb; + +import org.clevercastle.authforge.UserState; +import org.clevercastle.authforge.entity.UserLoginItem; +import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbBean; +import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbPartitionKey; +import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSecondaryPartitionKey; +import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSortKey; + +import java.time.OffsetDateTime; + +// single table design +@DynamoDbBean +public class DynamodbUser { + public enum Type { + user, + loginItem, + refreshToken + } + + public static final String TABLE_NAME = "auth-forge"; + + public static final String UserLoginItem_UserSub_index = "UserLoginItem_UserSub_index"; + + + // for user: pk = userId, sk = "user" + // for user login item: pk = loginIdentifier, sk = "loginItem" + // for user refresh token: pk = userId, sk="refreshToken#"+ refreshToken + private String pk; + private String sk; + + // region from user table + private UserState userState; + private String userHashedPassword; + private String userResetPasswordCode; + private OffsetDateTime userResetPasswordCodeExpiredAt; + // endregion + + // region from user login item table + private String userLoginItemLoginIdentifierPrefix; + private UserLoginItem.Type userLoginItemType; + private String userLoginItemUserSub; + private String userLoginItemUserId; + private UserLoginItem.State userLoginItemState; + private String userLoginItemVerificationCode; + private OffsetDateTime userLoginItemVerificationCodeExpiredAt; + // endregion + + private OffsetDateTime userRefreshTokenExpiredAt; + + private OffsetDateTime createdAt; + private OffsetDateTime updatedAt; + + @DynamoDbPartitionKey + public String getPk() { + return pk; + } + + public void setPk(String pk) { + this.pk = pk; + } + + @DynamoDbSortKey + public String getSk() { + return sk; + } + + public void setSk(String sk) { + this.sk = sk; + } + + public UserState getUserState() { + return userState; + } + + public void setUserState(UserState userState) { + this.userState = userState; + } + + public String getUserHashedPassword() { + return userHashedPassword; + } + + public void setUserHashedPassword(String userHashedPassword) { + this.userHashedPassword = userHashedPassword; + } + + public String getUserResetPasswordCode() { + return userResetPasswordCode; + } + + public void setUserResetPasswordCode(String userResetPasswordCode) { + this.userResetPasswordCode = userResetPasswordCode; + } + + public OffsetDateTime getUserResetPasswordCodeExpiredAt() { + return userResetPasswordCodeExpiredAt; + } + + public void setUserResetPasswordCodeExpiredAt(OffsetDateTime userResetPasswordCodeExpiredAt) { + this.userResetPasswordCodeExpiredAt = userResetPasswordCodeExpiredAt; + } + + public String getUserLoginItemLoginIdentifierPrefix() { + return userLoginItemLoginIdentifierPrefix; + } + + public void setUserLoginItemLoginIdentifierPrefix(String userLoginItemLoginIdentifierPrefix) { + this.userLoginItemLoginIdentifierPrefix = userLoginItemLoginIdentifierPrefix; + } + + public UserLoginItem.Type getUserLoginItemType() { + return userLoginItemType; + } + + public void setUserLoginItemType(UserLoginItem.Type userLoginItemType) { + this.userLoginItemType = userLoginItemType; + } + + @DynamoDbSecondaryPartitionKey(indexNames = UserLoginItem_UserSub_index) + public String getUserLoginItemUserSub() { + return userLoginItemUserSub; + } + + public void setUserLoginItemUserSub(String userLoginItemUserSub) { + this.userLoginItemUserSub = userLoginItemUserSub; + } + + public String getUserLoginItemUserId() { + return userLoginItemUserId; + } + + public void setUserLoginItemUserId(String userLoginItemUserId) { + this.userLoginItemUserId = userLoginItemUserId; + } + + public UserLoginItem.State getUserLoginItemState() { + return userLoginItemState; + } + + public void setUserLoginItemState(UserLoginItem.State userLoginItemState) { + this.userLoginItemState = userLoginItemState; + } + + public String getUserLoginItemVerificationCode() { + return userLoginItemVerificationCode; + } + + public void setUserLoginItemVerificationCode(String userLoginItemVerificationCode) { + this.userLoginItemVerificationCode = userLoginItemVerificationCode; + } + + public OffsetDateTime getUserLoginItemVerificationCodeExpiredAt() { + return userLoginItemVerificationCodeExpiredAt; + } + + public void setUserLoginItemVerificationCodeExpiredAt(OffsetDateTime userLoginItemVerificationCodeExpiredAt) { + this.userLoginItemVerificationCodeExpiredAt = userLoginItemVerificationCodeExpiredAt; + } + + public OffsetDateTime getUserRefreshTokenExpiredAt() { + return userRefreshTokenExpiredAt; + } + + public void setUserRefreshTokenExpiredAt(OffsetDateTime userRefreshTokenExpiredAt) { + this.userRefreshTokenExpiredAt = userRefreshTokenExpiredAt; + } + + public OffsetDateTime getCreatedAt() { + return createdAt; + } + + public void setCreatedAt(OffsetDateTime createdAt) { + this.createdAt = createdAt; + } + + public OffsetDateTime getUpdatedAt() { + return updatedAt; + } + + public void setUpdatedAt(OffsetDateTime updatedAt) { + this.updatedAt = updatedAt; + } +} diff --git a/src/main/java/org/clevercastle/authforge/repository/dynamodb/DynamodbUserRepositoryImpl.java b/src/main/java/org/clevercastle/authforge/repository/dynamodb/DynamodbUserRepositoryImpl.java new file mode 100644 index 0000000..192ee42 --- /dev/null +++ b/src/main/java/org/clevercastle/authforge/repository/dynamodb/DynamodbUserRepositoryImpl.java @@ -0,0 +1,166 @@ +package org.clevercastle.authforge.repository.dynamodb; + +import jakarta.annotation.Nonnull; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.tuple.Pair; +import org.clevercastle.authforge.entity.User; +import org.clevercastle.authforge.entity.UserLoginItem; +import org.clevercastle.authforge.entity.UserRefreshTokenMapping; +import org.clevercastle.authforge.exception.CastleException; +import org.clevercastle.authforge.repository.UserRepository; +import org.clevercastle.authforge.util.TimeUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClient; +import software.amazon.awssdk.enhanced.dynamodb.DynamoDbTable; +import software.amazon.awssdk.enhanced.dynamodb.Key; +import software.amazon.awssdk.enhanced.dynamodb.TableSchema; +import software.amazon.awssdk.enhanced.dynamodb.model.QueryConditional; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; +import software.amazon.awssdk.services.dynamodb.model.DynamoDbException; +import software.amazon.awssdk.services.dynamodb.model.Put; +import software.amazon.awssdk.services.dynamodb.model.TransactWriteItem; +import software.amazon.awssdk.services.dynamodb.model.TransactWriteItemsRequest; +import software.amazon.awssdk.services.dynamodb.model.UpdateItemRequest; + +import java.time.OffsetDateTime; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +public class DynamodbUserRepositoryImpl implements UserRepository { + private static final Logger logger = LoggerFactory.getLogger(DynamodbUserRepositoryImpl.class); + private final DynamoDbEnhancedClient enhancedClient; + private final DynamoDbClient lowClient; + + + private volatile DynamoDbTable table; + private volatile DynamoDbTable userLoginItemTable; + + public DynamodbUserRepositoryImpl(DynamoDbEnhancedClient enhancedClient, DynamoDbClient lowClient) { + this.enhancedClient = enhancedClient; + this.lowClient = lowClient; + } + + + @Override + public void save(User user, UserLoginItem userLoginItem) throws CastleException { + TransactWriteItem userWrite = TransactWriteItem.builder() + .put(Put.builder() + .tableName(DynamodbUser.TABLE_NAME) + .item(getTable().tableSchema().itemToMap(DynamodbUserUtil.fromUser(user), true)) + .build()) + .build(); + TransactWriteItem userLoginItemWrite = TransactWriteItem.builder() + .put(Put.builder() + .tableName(DynamodbUser.TABLE_NAME) + .item(getTable().tableSchema().itemToMap(DynamodbUserUtil.fromUserLogItem(userLoginItem), true)) + .build()) + .build(); + + TransactWriteItemsRequest transactWriteItemsRequest = TransactWriteItemsRequest.builder() + .transactItems(Arrays.asList(userWrite, userLoginItemWrite)) + .build(); + try { + lowClient.transactWriteItems(transactWriteItemsRequest); + } catch (DynamoDbException e) { + logger.error("Fail to save user", e); + throw new CastleException(); + } + } + + @Nonnull + @Override + public Pair getByLoginIdentifier(String loginIdentifier) { + DynamodbUser dynamodbUser = getTable().getItem(Key.builder().partitionValue(loginIdentifier).sortValue(DynamodbUser.Type.loginItem.name()).build()); + if (dynamodbUser == null) { + return Pair.of(null, null); + } + UserLoginItem userLoginItem = DynamodbUserUtil.toUserLogItem(dynamodbUser); + dynamodbUser = getTable().getItem(Key.builder().partitionValue(userLoginItem.getUserId()).sortValue(DynamodbUser.Type.user.name()).build()); + if (dynamodbUser == null) { + logger.error(""); + return Pair.of(null, null); + } + return Pair.of(DynamodbUserUtil.toUser(dynamodbUser), userLoginItem); + } + + @Nonnull + @Override + public Pair getByUserSub(String userSub) { + List dynamodbUsers = getTable().index(DynamodbUser.UserLoginItem_UserSub_index) + .query(QueryConditional.keyEqualTo(Key.builder().partitionValue(userSub).build())) + .stream().flatMap(it -> it.items().stream()).collect(Collectors.toList()); + if (dynamodbUsers.isEmpty()) { + return Pair.of(null, null); + } + if (dynamodbUsers.size() > 1) { + logger.error("More than one user found for user sub {}", userSub); + + } + DynamodbUser dynamodbUser = dynamodbUsers.get(0); + UserLoginItem userLoginItem = DynamodbUserUtil.toUserLogItem(dynamodbUser); + dynamodbUser = getTable().getItem(Key.builder().partitionValue(userLoginItem.getUserId()).sortValue(DynamodbUser.Type.user.name()).build()); + if (dynamodbUser == null) { + logger.error(""); + return Pair.of(null, null); + } + return Pair.of(DynamodbUserUtil.toUser(dynamodbUser), userLoginItem); + } + + @Override + public void confirmLoginItem(String loginIdentifier) { + UpdateItemRequest updateItemRequest = UpdateItemRequest.builder() + .tableName(DynamodbUser.TABLE_NAME) + .key(Map.of("pk", AttributeValue.fromS(loginIdentifier), "sk", AttributeValue.fromS(DynamodbUser.Type.loginItem.name()))) + .updateExpression("Set userLoginItemState = :state Remove userLoginItemVerificationCode, userLoginItemVerificationCodeExpiredAt") + .expressionAttributeValues(Map.of(":state", AttributeValue.fromS(UserLoginItem.State.ACTIVE.name()))) + .build(); + this.lowClient.updateItem(updateItemRequest); + } + + @Override + public UserRefreshTokenMapping addRefreshToken(User user, String refreshToken, OffsetDateTime expiredAt) { + UserRefreshTokenMapping mapping = new UserRefreshTokenMapping(); + mapping.setUserId(user.getUserId()); + mapping.setRefreshToken(DynamodbUser.Type.refreshToken + "#" + refreshToken); + OffsetDateTime now = OffsetDateTime.now(); + mapping.setCreatedAt(now); + mapping.setExpiredAt(expiredAt); + getTable().putItem(DynamodbUserUtil.fromUserRefreshTokenMapping(mapping)); + return mapping; + } + + @Override + public boolean verifyRefreshToken(User user, String refreshToken) throws CastleException { + if (StringUtils.isBlank(refreshToken)) { + return false; + } + Key key = Key.builder().partitionValue(user.getUserId()).sortValue(DynamodbUser.Type.refreshToken + "#" + refreshToken).build(); + DynamodbUser dynamodbUser = getTable() + .getItem(key); + if (dynamodbUser == null) { + return false; + } + UserRefreshTokenMapping userRefreshTokenMapping = DynamodbUserUtil.toUserRefreshTokenMapping(dynamodbUser); + if (userRefreshTokenMapping.getExpiredAt() != null && userRefreshTokenMapping.getExpiredAt().isAfter(TimeUtils.now())) { + getTable().deleteItem(key); + return true; + } + return false; + } + + private DynamoDbTable getTable() { + if (table == null) { + synchronized (this) { + if (table == null) { + TableSchema schema = TableSchema.fromBean(DynamodbUser.class); + table = enhancedClient.table(DynamodbUser.TABLE_NAME, schema); + } + } + } + return table; + } +} diff --git a/src/main/java/org/clevercastle/authforge/repository/dynamodb/DynamodbUserUtil.java b/src/main/java/org/clevercastle/authforge/repository/dynamodb/DynamodbUserUtil.java new file mode 100644 index 0000000..37c6e8f --- /dev/null +++ b/src/main/java/org/clevercastle/authforge/repository/dynamodb/DynamodbUserUtil.java @@ -0,0 +1,88 @@ +package org.clevercastle.authforge.repository.dynamodb; + +import org.clevercastle.authforge.entity.User; +import org.clevercastle.authforge.entity.UserLoginItem; +import org.clevercastle.authforge.entity.UserRefreshTokenMapping; + +public class DynamodbUserUtil { + + public static DynamodbUser fromUser(User user) { + DynamodbUser dynamodbUser = new DynamodbUser(); + dynamodbUser.setPk(user.getUserId()); + dynamodbUser.setSk(DynamodbUser.Type.user.name()); + + dynamodbUser.setUserState(user.getUserState()); + dynamodbUser.setUserHashedPassword(user.getHashedPassword()); + dynamodbUser.setUserResetPasswordCode(user.getResetPasswordCode()); + dynamodbUser.setUserResetPasswordCodeExpiredAt(user.getResetPasswordCodeExpiredAt()); + + dynamodbUser.setCreatedAt(user.getCreatedAt()); + dynamodbUser.setUpdatedAt(user.getUpdatedAt()); + return dynamodbUser; + } + + public static DynamodbUser fromUserLogItem(UserLoginItem userLoginItem) { + DynamodbUser dynamodbUser = new DynamodbUser(); + dynamodbUser.setPk(userLoginItem.getLoginIdentifier()); + dynamodbUser.setSk(DynamodbUser.Type.loginItem.name()); + + dynamodbUser.setUserLoginItemLoginIdentifierPrefix(userLoginItem.getLoginIdentifierPrefix()); + dynamodbUser.setUserLoginItemType(userLoginItem.getType()); + dynamodbUser.setUserLoginItemUserSub(userLoginItem.getUserSub()); + dynamodbUser.setUserLoginItemUserId(userLoginItem.getUserId()); + dynamodbUser.setUserLoginItemState(userLoginItem.getState()); + dynamodbUser.setUserLoginItemVerificationCode(userLoginItem.getVerificationCode()); + dynamodbUser.setUserLoginItemVerificationCodeExpiredAt(userLoginItem.getVerificationCodeExpiredAt()); + + dynamodbUser.setCreatedAt(userLoginItem.getCreatedAt()); + dynamodbUser.setUpdatedAt(userLoginItem.getUpdatedAt()); + return dynamodbUser; + } + + public static DynamodbUser fromUserRefreshTokenMapping(UserRefreshTokenMapping userRefreshTokenMapping) { + DynamodbUser dynamodbUser = new DynamodbUser(); + dynamodbUser.setPk(userRefreshTokenMapping.getUserId()); + dynamodbUser.setSk(userRefreshTokenMapping.getRefreshToken()); + dynamodbUser.setUserRefreshTokenExpiredAt(userRefreshTokenMapping.getExpiredAt()); + + dynamodbUser.setCreatedAt(userRefreshTokenMapping.getCreatedAt()); + return dynamodbUser; + } + + public static User toUser(DynamodbUser dynamodbUser) { + User user = new User(); + user.setUserId(dynamodbUser.getPk()); + user.setUserState(dynamodbUser.getUserState()); + user.setHashedPassword(dynamodbUser.getUserHashedPassword()); + user.setResetPasswordCode(dynamodbUser.getUserResetPasswordCode()); + user.setResetPasswordCodeExpiredAt(dynamodbUser.getUserResetPasswordCodeExpiredAt()); + user.setCreatedAt(dynamodbUser.getCreatedAt()); + user.setUpdatedAt(dynamodbUser.getUpdatedAt()); + return user; + } + + public static UserLoginItem toUserLogItem(DynamodbUser dynamodbUser) { + UserLoginItem userLoginItem = new UserLoginItem(); + userLoginItem.setLoginIdentifier(dynamodbUser.getPk()); + userLoginItem.setLoginIdentifierPrefix(dynamodbUser.getUserLoginItemLoginIdentifierPrefix()); + userLoginItem.setType(dynamodbUser.getUserLoginItemType()); + userLoginItem.setUserSub(dynamodbUser.getUserLoginItemUserSub()); + userLoginItem.setUserId(dynamodbUser.getUserLoginItemUserId()); + userLoginItem.setState(dynamodbUser.getUserLoginItemState()); + userLoginItem.setVerificationCode(dynamodbUser.getUserLoginItemVerificationCode()); + userLoginItem.setVerificationCodeExpiredAt(dynamodbUser.getUserLoginItemVerificationCodeExpiredAt()); + userLoginItem.setCreatedAt(dynamodbUser.getCreatedAt()); + userLoginItem.setUpdatedAt(dynamodbUser.getUpdatedAt()); + return userLoginItem; + } + + public static UserRefreshTokenMapping toUserRefreshTokenMapping(DynamodbUser dynamodbUser) { + UserRefreshTokenMapping userRefreshTokenMapping = new UserRefreshTokenMapping(); + userRefreshTokenMapping.setUserId(dynamodbUser.getPk()); + userRefreshTokenMapping.setRefreshToken(dynamodbUser.getSk()); + userRefreshTokenMapping.setExpiredAt(dynamodbUser.getUserRefreshTokenExpiredAt()); + + userRefreshTokenMapping.setCreatedAt(dynamodbUser.getCreatedAt()); + return userRefreshTokenMapping; + } +} From 37f6113d0a78574e16b65d24a50f33aabdd99f90 Mon Sep 17 00:00:00 2001 From: ivyxjc Date: Wed, 30 Apr 2025 16:29:34 +0800 Subject: [PATCH 2/2] feat(example): dynamodb support --- examples/spring-boot-example/build.gradle.kts | 5 +++- .../springbootexample/AuthController.java | 1 - .../springboot/springbootexample/Beans.java | 25 +++++++++++++++++-- 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/examples/spring-boot-example/build.gradle.kts b/examples/spring-boot-example/build.gradle.kts index c3556a0..9128b2d 100644 --- a/examples/spring-boot-example/build.gradle.kts +++ b/examples/spring-boot-example/build.gradle.kts @@ -23,11 +23,14 @@ dependencies { implementation("org.apache.httpcomponents.client5:httpclient5:5.4.2") implementation("org.apache.httpcomponents.core5:httpcore5:5.3.4") + implementation("software.amazon.awssdk:dynamodb:2.31.31") + implementation("software.amazon.awssdk:dynamodb-enhanced:2.31.31") + implementation("org.apache.commons:commons-lang3:3.17.0") implementation("com.auth0:java-jwt:4.5.0") implementation("org.springframework.boot:spring-boot-starter-web") implementation("org.springframework.boot:spring-boot-starter-data-jpa") - developmentOnly("org.springframework.boot:spring-boot-devtools") +// developmentOnly("org.springframework.boot:spring-boot-devtools") runtimeOnly("org.postgresql:postgresql:42.7.5") testImplementation("org.springframework.boot:spring-boot-starter-test") testRuntimeOnly("org.junit.platform:junit-platform-launcher") diff --git a/examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/AuthController.java b/examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/AuthController.java index d57b238..ffa9351 100644 --- a/examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/AuthController.java +++ b/examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/AuthController.java @@ -111,7 +111,6 @@ public UserWithToken login(@RequestHeader String authorization, @RequestBody Ref if (StringUtils.isBlank(userSub)) { throw new CastleException(""); } - userService.getByLoginIdentifier(userSub); Pair pair = userService.getByUserSub(userSub); if (pair.getLeft() == null || pair.getRight() == null) { throw new CastleException(""); diff --git a/examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/Beans.java b/examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/Beans.java index fbc0325..5aa8f63 100644 --- a/examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/Beans.java +++ b/examples/spring-boot-example/src/main/java/org/clevercastle/authforge/examples/springboot/springbootexample/Beans.java @@ -5,6 +5,8 @@ import org.clevercastle.authforge.UserService; import org.clevercastle.authforge.UserServiceImpl; import org.clevercastle.authforge.repository.UserRepository; +import org.clevercastle.authforge.repository.dynamodb.DynamodbUser; +import org.clevercastle.authforge.repository.dynamodb.DynamodbUserRepositoryImpl; import org.clevercastle.authforge.repository.rdsjpa.RdsJpaUserLoginItemRepository; import org.clevercastle.authforge.repository.rdsjpa.RdsJpaUserModelRepository; import org.clevercastle.authforge.repository.rdsjpa.RdsJpaUserRefreshTokenMappingRepository; @@ -16,6 +18,8 @@ import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClient; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import java.security.KeyFactory; import java.security.NoSuchAlgorithmException; @@ -37,6 +41,23 @@ public UserRepository userRepository(RdsJpaUserModelRepository userModelReposito return new RdsJpaUserRepositoryImpl(userModelRepository, userLoginItemRepository, userRefreshTokenMappingRepository); } + + @Bean + public UserRepository dynamodbUserRepository(DynamoDbEnhancedClient dynamodbEnhancedClient, DynamoDbClient dynamodbClient) { + return new DynamodbUserRepositoryImpl(dynamodbEnhancedClient, dynamodbClient); + } + + @Bean + public DynamoDbClient dynamoDbClient() { + return DynamoDbClient.builder().build(); + } + + @Bean + public DynamoDbEnhancedClient dynamoDbEnhancedClient(DynamoDbClient dynamoDbClient) { + return DynamoDbEnhancedClient.builder().dynamoDbClient(dynamoDbClient).build(); + } + + @Bean public TokenService tokenService() throws NoSuchAlgorithmException, InvalidKeySpecException { String privateKeyBase64 = "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg9dIFmLwqXyr9fLX8XYOL5tiS63YJP0NGo9+7wqm3gdahRANCAATcI/NjILO7b1x7CQwHkB2+CGsrIKqI94fh8aEtaWTIzGYn1vct9u2/AvORtn6qBpi4/rJH4XxFekFigifbXors"; @@ -56,8 +77,8 @@ public TokenService tokenService() throws NoSuchAlgorithmException, InvalidKeySp } @Bean - public UserService userService(UserRepository userRepository, TokenService tokenService) { - return new UserServiceImpl(Config.builder().build(), userRepository, tokenService, new DummyVerificationService(userRepository)); + public UserService userService(UserRepository dynamodbUserRepository, TokenService tokenService) { + return new UserServiceImpl(Config.builder().build(), dynamodbUserRepository, tokenService, new DummyVerificationService(dynamodbUserRepository)); }