diff --git a/pom.xml b/pom.xml index 11904b5..e06aea0 100644 --- a/pom.xml +++ b/pom.xml @@ -17,6 +17,7 @@ 21 6.0.0 4.4.0 + 42.7.0 @@ -66,6 +67,11 @@ java-jwt ${java-jwt.version} + + org.postgresql + postgresql + ${postgresql.version} + diff --git a/sportshub-domain/src/main/java/org/sportshub/domain/user/port/UserPort.java b/sportshub-domain/src/main/java/org/sportshub/domain/user/port/UserPort.java index 15f948a..8f8f84f 100644 --- a/sportshub-domain/src/main/java/org/sportshub/domain/user/port/UserPort.java +++ b/sportshub-domain/src/main/java/org/sportshub/domain/user/port/UserPort.java @@ -10,4 +10,6 @@ public interface UserPort { Optional findById(UUID userId); List findAll(); + + void save(User user); } diff --git a/sportshub-infrastructure/pom.xml b/sportshub-infrastructure/pom.xml index d2ee38e..64d544b 100644 --- a/sportshub-infrastructure/pom.xml +++ b/sportshub-infrastructure/pom.xml @@ -25,5 +25,17 @@ org.springframework spring-context + + org.springframework.boot + spring-boot-starter-data-jpa + + + org.projectlombok + lombok + + + org.postgresql + postgresql + diff --git a/sportshub-infrastructure/src/main/java/org/sportshub/infrastructure/configuration/JpaConfiguration.java b/sportshub-infrastructure/src/main/java/org/sportshub/infrastructure/configuration/JpaConfiguration.java new file mode 100644 index 0000000..8e18150 --- /dev/null +++ b/sportshub-infrastructure/src/main/java/org/sportshub/infrastructure/configuration/JpaConfiguration.java @@ -0,0 +1,11 @@ +package org.sportshub.infrastructure.configuration; + +import org.springframework.boot.autoconfigure.domain.EntityScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; + +@Configuration +@EnableJpaRepositories("org.sportshub.infrastructure") +@EntityScan("org.sportshub.infrastructure") +public class JpaConfiguration { +} diff --git a/sportshub-infrastructure/src/main/java/org/sportshub/infrastructure/user/adapter/UserInMemoryAdapter.java b/sportshub-infrastructure/src/main/java/org/sportshub/infrastructure/user/adapter/UserInMemoryAdapter.java index c275a17..f64ad21 100644 --- a/sportshub-infrastructure/src/main/java/org/sportshub/infrastructure/user/adapter/UserInMemoryAdapter.java +++ b/sportshub-infrastructure/src/main/java/org/sportshub/infrastructure/user/adapter/UserInMemoryAdapter.java @@ -10,7 +10,7 @@ import org.sportshub.domain.user.model.User; import org.sportshub.domain.user.port.UserPort; import org.springframework.stereotype.Component; -@Component +//@Component public class UserInMemoryAdapter implements UserPort { private static final List users = List.of( new User( @@ -41,4 +41,9 @@ public class UserInMemoryAdapter implements UserPort { public List findAll() { return users; } + + @Override + public void save(final User user) { + // Do nothing. + } } diff --git a/sportshub-infrastructure/src/main/java/org/sportshub/infrastructure/user/adapter/UserJpaAdapter.java b/sportshub-infrastructure/src/main/java/org/sportshub/infrastructure/user/adapter/UserJpaAdapter.java new file mode 100644 index 0000000..93ed200 --- /dev/null +++ b/sportshub-infrastructure/src/main/java/org/sportshub/infrastructure/user/adapter/UserJpaAdapter.java @@ -0,0 +1,46 @@ +package org.sportshub.infrastructure.user.adapter; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +import org.sportshub.domain.user.model.User; +import org.sportshub.domain.user.port.UserPort; +import org.sportshub.infrastructure.user.mapper.UserMapper; +import org.sportshub.infrastructure.user.model.UserEntity; +import org.sportshub.infrastructure.user.repository.UserJpaRepository; +import org.springframework.stereotype.Component; + +@Component +public class UserJpaAdapter implements UserPort { + private final UserJpaRepository userJpaRepository; + private final UserMapper userMapper; + + public UserJpaAdapter( + UserJpaRepository userJpaRepository, + UserMapper userMapper + ) { + this.userJpaRepository = userJpaRepository; + this.userMapper = userMapper; + } + + @Override + public Optional findById(final UUID userId) { + return userJpaRepository.findById(userId) + .map(userMapper::mapFrom); + } + + @Override + public List findAll() { + return userJpaRepository.findAll() + .stream() + .map(userMapper::mapFrom) + .toList(); + } + + @Override + public void save(User user) { + UserEntity userEntity = userMapper.mapTo(user); + userJpaRepository.save(userEntity); + } +} diff --git a/sportshub-infrastructure/src/main/java/org/sportshub/infrastructure/user/mapper/UserMapper.java b/sportshub-infrastructure/src/main/java/org/sportshub/infrastructure/user/mapper/UserMapper.java new file mode 100644 index 0000000..288b3b2 --- /dev/null +++ b/sportshub-infrastructure/src/main/java/org/sportshub/infrastructure/user/mapper/UserMapper.java @@ -0,0 +1,20 @@ +package org.sportshub.infrastructure.user.mapper; + +import org.sportshub.domain.user.model.User; +import org.sportshub.infrastructure.user.model.UserEntity; +import org.springframework.stereotype.Component; + +@Component +public class UserMapper { + public User mapFrom(UserEntity userEntity) { + return new User(userEntity.getId(), userEntity.getPassword(), userEntity.getRoles()); + } + + public UserEntity mapTo(User user) { + return new UserEntity( + user.id(), + user.password(), + user.roles() + ); + } +} diff --git a/sportshub-infrastructure/src/main/java/org/sportshub/infrastructure/user/model/UserEntity.java b/sportshub-infrastructure/src/main/java/org/sportshub/infrastructure/user/model/UserEntity.java new file mode 100644 index 0000000..2c94d62 --- /dev/null +++ b/sportshub-infrastructure/src/main/java/org/sportshub/infrastructure/user/model/UserEntity.java @@ -0,0 +1,40 @@ +package org.sportshub.infrastructure.user.model; + +import java.util.List; +import java.util.UUID; + +import org.sportshub.domain.user.model.UserRole; + +import jakarta.persistence.CollectionTable; +import jakarta.persistence.Column; +import jakarta.persistence.ElementCollection; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.Table; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Entity +@Table(name = "`user`") +@AllArgsConstructor +@NoArgsConstructor +@Getter +@Setter +public class UserEntity { + @Id + private UUID id; + + @Column(nullable = false) + private String password; + + @ElementCollection(targetClass = UserRole.class) + @CollectionTable( + name = "user_role", + joinColumns = @JoinColumn(name = "user_id") + ) + @Column(name = "role") + private List roles; +} diff --git a/sportshub-infrastructure/src/main/java/org/sportshub/infrastructure/user/repository/UserJpaRepository.java b/sportshub-infrastructure/src/main/java/org/sportshub/infrastructure/user/repository/UserJpaRepository.java new file mode 100644 index 0000000..574236b --- /dev/null +++ b/sportshub-infrastructure/src/main/java/org/sportshub/infrastructure/user/repository/UserJpaRepository.java @@ -0,0 +1,20 @@ +package org.sportshub.infrastructure.user.repository; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +import org.sportshub.infrastructure.user.model.UserEntity; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Service; + +@Service +public interface UserJpaRepository extends JpaRepository { + @Query("SELECT u FROM UserEntity u JOIN FETCH u.roles WHERE u.id = :userId") + Optional findById(@Param("userId") UUID userId); + + @Query("SELECT u FROM UserEntity u JOIN FETCH u.roles") + List findAll(); +} diff --git a/sportshub-infrastructure/src/main/resources/sql/000-database-creation.sql b/sportshub-infrastructure/src/main/resources/sql/000-database-creation.sql index 682131d..4faabea 100644 --- a/sportshub-infrastructure/src/main/resources/sql/000-database-creation.sql +++ b/sportshub-infrastructure/src/main/resources/sql/000-database-creation.sql @@ -1 +1,12 @@ -CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; \ No newline at end of file +\c sportshub_db + +CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; + +CREATE USER sportshub_user + WITH PASSWORD 'password' + NOCREATEDB; + +GRANT SELECT, INSERT, UPDATE, DELETE + ON ALL TABLES + IN SCHEMA public + TO sportshub_user; \ No newline at end of file diff --git a/sportshub-launcher/src/main/resources/application.yml b/sportshub-launcher/src/main/resources/application.yml index 9672836..2b01a2e 100644 --- a/sportshub-launcher/src/main/resources/application.yml +++ b/sportshub-launcher/src/main/resources/application.yml @@ -11,4 +11,11 @@ server: error: whitelabel: enabled: false # Disable html error responses. - include-stacktrace: never \ No newline at end of file + include-stacktrace: never + +spring: + datasource: + driverClassName: org.postgresql.Driver + url: jdbc:postgresql://localhost:50001/sportshub_db + username: sportshub_user + password: password