diff --git a/pom.xml b/pom.xml
index 7936024..dc5dd00 100644
--- a/pom.xml
+++ b/pom.xml
@@ -15,6 +15,7 @@
21
21
21
+ 6.0.0
@@ -54,6 +55,11 @@
sportshub-infrastructure
${project.version}
+
+ jakarta.servlet
+ jakarta.servlet-api
+ ${jakarta.servlet-api.version}
+
diff --git a/sportshub-application/pom.xml b/sportshub-application/pom.xml
index 1fb543c..63fa59d 100644
--- a/sportshub-application/pom.xml
+++ b/sportshub-application/pom.xml
@@ -25,5 +25,13 @@
org.springframework
spring-context
+
+ org.springframework.boot
+ spring-boot-starter-security
+
+
+ jakarta.servlet
+ jakarta.servlet-api
+
diff --git a/sportshub-application/src/main/java/org/sportshub/application/configuration/SecurityConfiguration.java b/sportshub-application/src/main/java/org/sportshub/application/configuration/SecurityConfiguration.java
new file mode 100644
index 0000000..8281378
--- /dev/null
+++ b/sportshub-application/src/main/java/org/sportshub/application/configuration/SecurityConfiguration.java
@@ -0,0 +1,57 @@
+package org.sportshub.application.configuration;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.HttpMethod;
+import org.springframework.security.config.Customizer;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.security.web.SecurityFilterChain;
+import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
+
+import jakarta.servlet.DispatcherType;
+import jakarta.servlet.http.HttpServletResponse;
+
+@Configuration
+@EnableWebSecurity
+public class SecurityConfiguration {
+ @Bean
+ public SecurityFilterChain securityFilterChain(
+ HttpSecurity httpSecurity
+ ) throws Exception {
+ httpSecurity
+ .csrf(AbstractHttpConfigurer::disable)
+ .httpBasic(Customizer.withDefaults())
+ .authorizeHttpRequests(requests -> requests
+ .dispatcherTypeMatchers(DispatcherType.FORWARD).permitAll()
+ .requestMatchers(
+ HttpMethod.GET,
+ "/api/health/check"
+ ).permitAll()
+ .requestMatchers(
+ HttpMethod.POST,
+ "/api/users/login"
+ ).permitAll()
+ .anyRequest().authenticated()
+ )
+ .exceptionHandling(configurer -> configurer
+ .defaultAuthenticationEntryPointFor(
+ (request, response, authException) -> response.sendError(HttpServletResponse.SC_UNAUTHORIZED),
+ new AntPathRequestMatcher("/api/**")
+ ).defaultAccessDeniedHandlerFor(
+ (request, response, accessDeniedException) -> response.sendError(HttpServletResponse.SC_FORBIDDEN),
+ new AntPathRequestMatcher("/api/**")
+ )
+ );
+
+ return httpSecurity.build();
+ }
+
+ @Bean
+ public PasswordEncoder passwordEncoder() {
+ return new BCryptPasswordEncoder();
+ }
+}
diff --git a/sportshub-application/src/main/java/org/sportshub/application/user/CustomUserDetails.java b/sportshub-application/src/main/java/org/sportshub/application/user/CustomUserDetails.java
new file mode 100644
index 0000000..d91ac08
--- /dev/null
+++ b/sportshub-application/src/main/java/org/sportshub/application/user/CustomUserDetails.java
@@ -0,0 +1,51 @@
+package org.sportshub.application.user;
+
+import static java.util.Collections.emptyList;
+import java.util.Collection;
+
+import org.sportshub.domain.user.model.User;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.userdetails.UserDetails;
+
+public class CustomUserDetails implements UserDetails {
+ private final User user;
+
+ public CustomUserDetails(final User user) {
+ this.user = user;
+ }
+
+ @Override
+ public Collection extends GrantedAuthority> getAuthorities() {
+ return emptyList();
+ }
+
+ @Override
+ public String getUsername() {
+ return user.id().toString();
+ }
+
+ @Override
+ public String getPassword() {
+ return user.password();
+ }
+
+ @Override
+ public boolean isAccountNonExpired() {
+ return true;
+ }
+
+ @Override
+ public boolean isAccountNonLocked() {
+ return true;
+ }
+
+ @Override
+ public boolean isCredentialsNonExpired() {
+ return true;
+ }
+
+ @Override
+ public boolean isEnabled() {
+ return true;
+ }
+}
diff --git a/sportshub-application/src/main/java/org/sportshub/application/user/CustomUserDetailsService.java b/sportshub-application/src/main/java/org/sportshub/application/user/CustomUserDetailsService.java
new file mode 100644
index 0000000..5eec933
--- /dev/null
+++ b/sportshub-application/src/main/java/org/sportshub/application/user/CustomUserDetailsService.java
@@ -0,0 +1,33 @@
+package org.sportshub.application.user;
+
+import java.util.UUID;
+
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.stereotype.Service;
+
+@Service
+public class CustomUserDetailsService implements UserDetailsService {
+ private final UserUseCases userUseCases;
+
+ public CustomUserDetailsService(final UserUseCases userUseCases) {
+ this.userUseCases = userUseCases;
+ }
+
+ @Override
+ public UserDetails loadUserByUsername(final String userIdAsString) throws UsernameNotFoundException {
+ UUID userId = parseUserId(userIdAsString);
+ return userUseCases.findById(userId)
+ .map(CustomUserDetails::new)
+ .orElseThrow(() -> new UsernameNotFoundException(userIdAsString));
+ }
+
+ private UUID parseUserId(final String userIdAsString) {
+ try {
+ return UUID.fromString(userIdAsString);
+ } catch (IllegalArgumentException exception) {
+ throw new UsernameNotFoundException(userIdAsString);
+ }
+ }
+}
diff --git a/sportshub-application/src/main/java/org/sportshub/application/user/UserUseCases.java b/sportshub-application/src/main/java/org/sportshub/application/user/UserUseCases.java
index 34ded03..60eaa63 100644
--- a/sportshub-application/src/main/java/org/sportshub/application/user/UserUseCases.java
+++ b/sportshub-application/src/main/java/org/sportshub/application/user/UserUseCases.java
@@ -1,5 +1,6 @@
package org.sportshub.application.user;
+import java.util.List;
import java.util.Optional;
import java.util.UUID;
@@ -18,4 +19,8 @@ public class UserUseCases {
public Optional findById(UUID userId) {
return userPort.findById(userId);
}
+
+ public List findAll() {
+ return userPort.findAll();
+ }
}
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 b1d9872..15f948a 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
@@ -1,5 +1,6 @@
package org.sportshub.domain.user.port;
+import java.util.List;
import java.util.Optional;
import java.util.UUID;
@@ -7,4 +8,6 @@ import org.sportshub.domain.user.model.User;
public interface UserPort {
Optional findById(UUID userId);
+
+ List findAll();
}
diff --git a/sportshub-exposition/pom.xml b/sportshub-exposition/pom.xml
index eee73dc..4240100 100644
--- a/sportshub-exposition/pom.xml
+++ b/sportshub-exposition/pom.xml
@@ -17,6 +17,14 @@
jar
+
+ org.sportshub
+ sportshub-application
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
@@ -25,11 +33,6 @@
-
- org.springframework.boot
- spring-boot-starter-web
-
-
diff --git a/sportshub-exposition/src/main/java/org/sportshub/exposition/user/UserController.java b/sportshub-exposition/src/main/java/org/sportshub/exposition/user/UserController.java
index 7bc917d..f39ad2d 100644
--- a/sportshub-exposition/src/main/java/org/sportshub/exposition/user/UserController.java
+++ b/sportshub-exposition/src/main/java/org/sportshub/exposition/user/UserController.java
@@ -1,8 +1,10 @@
package org.sportshub.exposition.user;
-import java.util.UUID;
+import java.util.List;
import org.sportshub.application.user.UserUseCases;
+import org.sportshub.domain.user.model.User;
+import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@@ -16,8 +18,13 @@ public class UserController {
this.userUseCases = userUseCases;
}
- @PostMapping
+ @PostMapping("/login")
public String login() {
return "";
}
+
+ @GetMapping
+ public List findAll() {
+ return userUseCases.findAll();
+ }
}
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 ae8047a..8302c5a 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
@@ -11,9 +11,9 @@ import org.springframework.stereotype.Component;
@Component
public class UserInMemoryAdapter implements UserPort {
private static final List users = List.of(
- new User(UUID.fromString("c1a0805f-c618-47dc-bae7-bee70503644e"), "password"),
- new User(UUID.fromString("4eff194d-dd8e-463e-974f-034bfd509f84"), "password"),
- new User(UUID.fromString("c78d7d7c-0386-415d-86dc-98a470591e07"), "password")
+ new User(UUID.fromString("c1a0805f-c618-47dc-bae7-bee70503644e"), "$2a$10$WPuLOKpvaQnMotNo5ijPwegBPwmMF1C04XkTNCBpeBFo4r2YJWy.2"),
+ new User(UUID.fromString("4eff194d-dd8e-463e-974f-034bfd509f84"), "$2a$10$WPuLOKpvaQnMotNo5ijPwegBPwmMF1C04XkTNCBpeBFo4r2YJWy.2"),
+ new User(UUID.fromString("c78d7d7c-0386-415d-86dc-98a470591e07"), "$2a$10$WPuLOKpvaQnMotNo5ijPwegBPwmMF1C04XkTNCBpeBFo4r2YJWy.2")
);
@Override
@@ -22,4 +22,9 @@ public class UserInMemoryAdapter implements UserPort {
.filter(user -> userId.equals(user.id()))
.findFirst();
}
+
+ @Override
+ public List findAll() {
+ return users;
+ }
}
diff --git a/sportshub-launcher/src/main/resources/application.yml b/sportshub-launcher/src/main/resources/application.yml
new file mode 100644
index 0000000..fd51fb8
--- /dev/null
+++ b/sportshub-launcher/src/main/resources/application.yml
@@ -0,0 +1,3 @@
+logging:
+ level:
+ org.springframework.security: DEBUG
\ No newline at end of file