Login should work now, tests are missing
Build, Test & Push Auth Service / quality-check (push) Failing after 37s
Build, Test & Push Auth Service / docker (push) Has been skipped

This commit is contained in:
lobo committed 2026-03-31 19:48:23 +02:00
1 parent 8dd17f84f6
commit 7e8a04d83c
13 files changed
+392 -17

No files matched your search

@@ -5,9 +5,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class AuthServiceApplication {
public static void main(String[] args) {
SpringApplication.run(AuthServiceApplication.class, args);
}
}
static void main(String[] args) {
SpringApplication.run(AuthServiceApplication.class, args);
}
}
@@ -0,0 +1,24 @@
package auth_service.configuration;
import io.micrometer.core.aop.TimedAspect;
import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Configuration for application observability and metrics.
*/
@Configuration
public class ObservabilityConfig {
/**
* Registers the TimedAspect bean to enable @Timed annotations.
* * @param registry The Micrometer MeterRegistry
*
* @return A new TimedAspect instance
*/
@Bean
public TimedAspect timedAspect(MeterRegistry registry) {
return new TimedAspect(registry);
}
}
@@ -0,0 +1,85 @@
package auth_service.configuration;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import java.util.Arrays;
import java.util.List;
/**
* Global security configuration for the Authentication Service.
* Implements whitelist routing and environment-specific CORS.
*/
@Configuration
@EnableWebSecurity
public class SecurityConfig {
/**
* The Whitelist: Endpoints that do NOT require authentication.
*/
private static final String[] WHITE_LIST_URLS = {
"/api/auth/**", // Allow login, registration, etc.
"/actuator/health", // Allow health checks (e.g., for Docker/Traefik)
"/actuator/prometheus", // Allow Prometheus to scrape metrics
"/error" // Default Spring Boot error page routing
};
/**
* Injects the allowed CORS origins from the active application.yml profile.
*/
@Value("${app.cors.allowed-origins}")
private String[] allowedOrigins;
/**
* Defines the password encoder used for hashing passwords.
*/
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
/**
* Defines the global CORS configuration.
* Using a dedicated Bean ensures it's properly registered in the filter chain.
*/
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
// Use OriginPatterns instead of AllowedOrigins to safely support "*" wildcards
configuration.setAllowedOriginPatterns(Arrays.asList(allowedOrigins));
configuration.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "OPTIONS"));
configuration.setAllowedHeaders(List.of("*"));
configuration.setAllowCredentials(false); // Set to true later if we use cookies
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
// Apply this CORS config to all endpoints
source.registerCorsConfiguration("/**", configuration);
return source;
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) {
http
.csrf(AbstractHttpConfigurer::disable)
// Tell Spring Security to use the CorsConfigurationSource bean defined above
.cors(cors -> cors.configurationSource(corsConfigurationSource()))
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authorizeHttpRequests(auth -> auth
.requestMatchers(WHITE_LIST_URLS).permitAll()
.anyRequest().authenticated()
);
return http.build();
}
}
@@ -0,0 +1,46 @@
package auth_service.domain.login.controller;
import auth_service.domain.login.controller.dtos.LoginRequest;
import auth_service.domain.login.controller.dtos.LoginResponse;
import auth_service.domain.login.repository.UserRepository;
import io.micrometer.core.annotation.Timed;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* Controller handling authentication requests.
*/
@RestController
@RequestMapping("/api/auth")
@RequiredArgsConstructor
public class LoginController {
private final UserRepository userRepository;
private final PasswordEncoder passwordEncoder;
/**
* Authenticates a user based on email and password.
* * @param request The login credentials
*
* @return HTTP 200 on success, HTTP 401 on failure
*/
@PostMapping("/login")
@Timed(value = "auth.login.requests.time", description = "Time taken to process login requests")
public ResponseEntity<LoginResponse> login(@RequestBody LoginRequest request) {
return userRepository.findByEmail(request.email())
.filter(user -> passwordEncoder.matches(request.password(), user.getPassword()))
.map(user -> ResponseEntity.ok(
new LoginResponse("Login successful", user.getEmail())
))
.orElseGet(() -> ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(
new LoginResponse("Invalid credentials", null)
));
}
}
@@ -0,0 +1,7 @@
package auth_service.domain.login.controller.dtos;
/**
* DTO (Data Transfer Object) representing the incoming login request.
*/
public record LoginRequest(String email, String password) {
}
@@ -0,0 +1,8 @@
package auth_service.domain.login.controller.dtos;
/**
* DTO representing the outgoing login response.
* The email will be null if the login fails.
*/
public record LoginResponse(String message, String email) {
}
@@ -0,0 +1,30 @@
package auth_service.domain.login.model;
import jakarta.persistence.*;
import lombok.*;
/**
* Represents a user entity mapped to the 'users' table in PostgreSQL.
*/
@Entity
@Table(name = "users")
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class UserEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true, nullable = false)
private String email;
@Column(nullable = false)
private String password;
@Column(nullable = false)
private boolean enabled;
}
@@ -0,0 +1,22 @@
package auth_service.domain.login.repository;
import auth_service.domain.login.model.UserEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.Optional;
/**
* Repository for database operations regarding the User entity.
*/
@Repository
public interface UserRepository extends JpaRepository<UserEntity, Long> {
/**
* Finds a user by their email address.
* * @param email The email to search for
*
* @return An Optional containing the user if found
*/
Optional<UserEntity> findByEmail(String email);
}
+14
View File
@@ -0,0 +1,14 @@
# ─────────────────────────────────────────────
# DEVELOPMENT CONFIGURATION
# ─────────────────────────────────────────────
# Overrides properties from application.yml when the 'dev' profile is active
app:
cors:
# Local development: allow all origins to prevent CORS issues
allowed-origins: "*"
# Optional: Make SQL logs visible for debugging
spring:
jpa:
show-sql: true
+33 -2
View File
@@ -1,5 +1,36 @@
# ─────────────────────────────────────────────
# BASE CONFIGURATION (Production Defaults)
# ─────────────────────────────────────────────
spring:
application:
name: auth-service
name: tbp-auth-service
profiles:
active: dev # Default profile for local startup
flyway:
# Force Flyway to be enabled
enabled: true
# Create the schema history table if it does not exist
baseline-on-migrate: true
# Explicitly state where to look for scripts
locations: classpath:db/migration
# Actuator & Micrometer Settings
management:
endpoints:
web:
exposure:
# Expose health and metrics to the web
include: health, prometheus, metrics
endpoint:
health:
show-details: always
prometheus:
metrics:
export:
enabled: true
# Custom properties for CORS
app:
version: '@project.version@'
cors:
# Production default: strictly allow only the frontend domain
allowed-origins: "https://tbp.andreas-dahm.eu"