Compare commits
7 Commits
a9e4a187b6
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 1e41b75502 | |||
| acf9ec8a2c | |||
| 004ea4eca4 | |||
| a56d995d0f | |||
| a3ad34d094 | |||
| b7a3103837 | |||
| c54d0214f3 |
@ -21,10 +21,16 @@ services:
|
||||
KEYCLOAK_ADMIN: admin
|
||||
KEYCLOAK_ADMIN_PASSWORD: admin
|
||||
# Make issuer consistent & reachable from other containers
|
||||
KC_HOSTNAME: keycloak
|
||||
# KC_HOSTNAME: keycloak
|
||||
KC_HTTP_ENABLED: "true"
|
||||
KC_HOSTNAME_STRICT: "false"
|
||||
KC_PROXY: edge
|
||||
KC_HOSTNAME_URL: "http://localhost:8081/"
|
||||
KC_HOSTNAME_ADMIN_URL: "http://localhost:8081/"
|
||||
KC_HOSTNAME_STRICT_HTTPS: "false"
|
||||
extra_hosts:
|
||||
- "host.docker.internal:host-gateway"
|
||||
|
||||
ports:
|
||||
- "8081:8081"
|
||||
volumes:
|
||||
@ -40,6 +46,9 @@ services:
|
||||
depends_on:
|
||||
postgres: { condition: service_healthy }
|
||||
environment:
|
||||
# Aktivera Spring-profilen "dev"
|
||||
SPRING_PROFILES_ACTIVE: dev
|
||||
|
||||
SPRING_DATASOURCE_URL: jdbc:postgresql://postgres:5432/hemhub
|
||||
SPRING_DATASOURCE_USERNAME: hemhub
|
||||
SPRING_DATASOURCE_PASSWORD: hemhub
|
||||
|
||||
@ -2,11 +2,18 @@ package se.urmo.hemhub.config;
|
||||
|
||||
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.method.configuration.EnableMethodSecurity;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter;
|
||||
import org.springframework.web.cors.CorsConfiguration;
|
||||
import org.springframework.web.cors.CorsConfigurationSource;
|
||||
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Configuration
|
||||
@EnableMethodSecurity
|
||||
@ -16,18 +23,37 @@ public class SecurityConfig {
|
||||
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.csrf(AbstractHttpConfigurer::disable)
|
||||
.cors(Customizer.withDefaults())
|
||||
.authorizeHttpRequests(auth -> auth
|
||||
.requestMatchers(
|
||||
"/public/**",
|
||||
"/actuator/health", "/actuator/info",
|
||||
"/v3/api-docs/**", "/swagger-ui/**", "/swagger-ui.html"
|
||||
).permitAll()
|
||||
.requestMatchers(HttpMethod.OPTIONS, "/**").permitAll()
|
||||
.anyRequest().authenticated()
|
||||
)
|
||||
.oauth2ResourceServer(oauth -> oauth.jwt(jwt -> jwt.jwtAuthenticationConverter(jwtConverter())));
|
||||
return http.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
CorsConfigurationSource corsConfigurationSource() {
|
||||
var config = new CorsConfiguration();
|
||||
config.setAllowedOrigins(List.of(
|
||||
"http://localhost:5173", // dev-SPA
|
||||
"https://rubble.se" // prod-origin (SPA ligger under subpath men origin är domen)
|
||||
));
|
||||
config.setAllowedMethods(List.of("GET","POST","PATCH","DELETE","OPTIONS"));
|
||||
config.setAllowedHeaders(List.of("Authorization","Content-Type","Accept"));
|
||||
config.setAllowCredentials(false); // Bearer, inga cookies
|
||||
config.setMaxAge(3600L);
|
||||
|
||||
var source = new UrlBasedCorsConfigurationSource();
|
||||
source.registerCorsConfiguration("/**", config);
|
||||
return source;
|
||||
}
|
||||
|
||||
@Bean
|
||||
JwtAuthenticationConverter jwtConverter() {
|
||||
var converter = new JwtAuthenticationConverter();
|
||||
@ -35,4 +61,3 @@ public class SecurityConfig {
|
||||
return converter;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -19,7 +19,6 @@ public class MeController {
|
||||
|
||||
// ---- Läs roller på ett säkert sätt ----
|
||||
List<String> roles = extractRealmRoles(jwt);
|
||||
log.info("Jwt: {}", jwt);
|
||||
// ---- Bygg svar ----
|
||||
Map<String, Object> response = new LinkedHashMap<>();
|
||||
response.put("sub", jwt.getSubject());
|
||||
|
||||
27
src/main/resources/application-dev.yml
Normal file
27
src/main/resources/application-dev.yml
Normal file
@ -0,0 +1,27 @@
|
||||
server:
|
||||
port: 8080
|
||||
|
||||
spring:
|
||||
datasource:
|
||||
url: jdbc:postgresql://postgres:5432/hemhub
|
||||
username: hemhub
|
||||
password: hemhub
|
||||
jpa:
|
||||
hibernate:
|
||||
ddl-auto: none
|
||||
flyway:
|
||||
enabled: true
|
||||
security:
|
||||
oauth2:
|
||||
resourceserver:
|
||||
jwt:
|
||||
jwk-set-uri: http://host.docker.internal:8081/realms/hemhub/protocol/openid-connect/certs
|
||||
springdoc:
|
||||
swagger-ui: # (valfritt, behåll om du redan har)
|
||||
url: /v3/api-docs
|
||||
|
||||
logging:
|
||||
level:
|
||||
org.springframework.security: DEBUG
|
||||
org.springframework.security.oauth2: DEBUG
|
||||
|
||||
@ -11,12 +11,10 @@ spring:
|
||||
ddl-auto: none
|
||||
flyway:
|
||||
enabled: true
|
||||
security:
|
||||
oauth2:
|
||||
resourceserver:
|
||||
jwt:
|
||||
jwk-set-uri: http://keycloak:8080/realms/hemhub/protocol/openid-connect/certs
|
||||
issuer-uri: https://rubbel.se/hemhub/auth/realms/hemhub
|
||||
springdoc:
|
||||
swagger-ui: # (valfritt, behåll om du redan har)
|
||||
url: /v3/api-docs
|
||||
|
||||
hemhub:
|
||||
schedule:
|
||||
reminders:
|
||||
|
||||
7
src/main/resources/applications-prod.yml
Normal file
7
src/main/resources/applications-prod.yml
Normal file
@ -0,0 +1,7 @@
|
||||
spring:
|
||||
security:
|
||||
oauth2:
|
||||
resourceserver:
|
||||
jwt:
|
||||
#jwk-set-uri: http://keycloak:8080/realms/hemhub/protocol/openid-connect/certs
|
||||
issuer-uri: https://rubble.se/hemhub/auth/realms/hemhub
|
||||
@ -4,8 +4,10 @@ import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import se.urmo.hemhub.support.TestSecurityConfig;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -19,6 +21,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||
@SpringBootTest
|
||||
@AutoConfigureMockMvc
|
||||
@ActiveProfiles("test")
|
||||
@Import(TestSecurityConfig.class)
|
||||
class HouseholdControllerIT {
|
||||
|
||||
@Autowired
|
||||
|
||||
@ -4,8 +4,10 @@ import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import se.urmo.hemhub.support.TestSecurityConfig;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@ -17,6 +19,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||
@SpringBootTest
|
||||
@AutoConfigureMockMvc
|
||||
@ActiveProfiles("test")
|
||||
@Import(TestSecurityConfig.class)
|
||||
class MeControllerBranchesIT {
|
||||
|
||||
@Autowired
|
||||
|
||||
@ -4,8 +4,10 @@ import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import se.urmo.hemhub.support.TestSecurityConfig;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -18,6 +20,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||
@SpringBootTest
|
||||
@AutoConfigureMockMvc
|
||||
@ActiveProfiles("test")
|
||||
@Import(TestSecurityConfig.class)
|
||||
class MeControllerIT {
|
||||
|
||||
@Autowired
|
||||
|
||||
@ -5,9 +5,11 @@ import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import se.urmo.hemhub.support.TestSecurityConfig;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
@ -19,6 +21,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||
@SpringBootTest
|
||||
@AutoConfigureMockMvc
|
||||
@ActiveProfiles("test")
|
||||
@Import(TestSecurityConfig.class)
|
||||
class PagingAndFilteringIT {
|
||||
|
||||
@Autowired MockMvc mvc;
|
||||
|
||||
@ -5,8 +5,10 @@ import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import se.urmo.hemhub.support.TestSecurityConfig;
|
||||
|
||||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.jwt;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
|
||||
@ -15,6 +17,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||
@SpringBootTest
|
||||
@AutoConfigureMockMvc
|
||||
@ActiveProfiles("test")
|
||||
@Import(TestSecurityConfig.class)
|
||||
class ProjectTaskControllerIT {
|
||||
|
||||
@Autowired MockMvc mvc;
|
||||
|
||||
@ -4,8 +4,10 @@ import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import se.urmo.hemhub.support.TestSecurityConfig;
|
||||
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
@ -14,6 +16,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||
@SpringBootTest
|
||||
@AutoConfigureMockMvc
|
||||
@ActiveProfiles("test")
|
||||
@Import(TestSecurityConfig.class)
|
||||
class PublicControllerIT {
|
||||
|
||||
@Autowired
|
||||
|
||||
@ -5,8 +5,10 @@ import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import se.urmo.hemhub.support.TestSecurityConfig;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
@ -19,6 +21,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||
@SpringBootTest
|
||||
@AutoConfigureMockMvc
|
||||
@ActiveProfiles("test")
|
||||
@Import(TestSecurityConfig.class)
|
||||
class TaskDueControllerIT {
|
||||
|
||||
@Autowired
|
||||
|
||||
@ -5,9 +5,11 @@ import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import se.urmo.hemhub.support.TestSecurityConfig;
|
||||
|
||||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.jwt;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
|
||||
@ -16,6 +18,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||
@SpringBootTest
|
||||
@AutoConfigureMockMvc
|
||||
@ActiveProfiles("test")
|
||||
@Import(TestSecurityConfig.class)
|
||||
class ValidationAndErrorHandlingIT {
|
||||
|
||||
@Autowired MockMvc mvc;
|
||||
|
||||
22
src/test/java/se/urmo/hemhub/support/TestSecurityConfig.java
Normal file
22
src/test/java/se/urmo/hemhub/support/TestSecurityConfig.java
Normal file
@ -0,0 +1,22 @@
|
||||
package se.urmo.hemhub.support;
|
||||
|
||||
import java.time.Instant;
|
||||
import org.springframework.boot.test.context.TestConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.security.oauth2.jwt.Jwt;
|
||||
import org.springframework.security.oauth2.jwt.JwtDecoder;
|
||||
|
||||
@TestConfiguration
|
||||
public class TestSecurityConfig {
|
||||
|
||||
@Bean
|
||||
JwtDecoder jwtDecoder() {
|
||||
return token -> Jwt.withTokenValue(token)
|
||||
.header("alg", "none")
|
||||
.claim("sub", "test-user")
|
||||
.claim("preferred_username", "test")
|
||||
.issuedAt(Instant.now())
|
||||
.expiresAt(Instant.now().plusSeconds(300))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@ -6,7 +6,7 @@ spring:
|
||||
password:
|
||||
jpa:
|
||||
hibernate:
|
||||
ddl-auto: none # 👈 turn off Hibernate's validate/ddl in tests
|
||||
ddl-auto: none
|
||||
properties:
|
||||
hibernate.hbm2ddl.auto: none
|
||||
flyway:
|
||||
|
||||
Reference in New Issue
Block a user