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