Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,13 @@
import lt.satsyuk.repository.ClientRepository;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cache.CacheManager;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import lt.satsyuk.config.KeycloakProperties;
import lt.satsyuk.security.RateLimitingFilter;

import java.math.BigDecimal;

Expand All @@ -26,11 +29,18 @@
)
class AccountIntegrationIT extends KeycloakIntegrationTest {

@Autowired
private AccountRepository accountRepository;

@Autowired
private ClientRepository clientRepository;
private final AccountRepository accountRepository;
private final ClientRepository clientRepository;

AccountIntegrationIT(@Qualifier("keycloakProperties") KeycloakProperties props,
CacheManager cacheManager,
RateLimitingFilter rateLimitingFilter,
AccountRepository accountRepository,
ClientRepository clientRepository) {
super(props, cacheManager, rateLimitingFilter);
this.accountRepository = accountRepository;
this.clientRepository = clientRepository;
}

@BeforeEach
void setUp() {
Expand Down
10 changes: 10 additions & 0 deletions src/test/java/lt/satsyuk/api/integrationtest/AuthValidationIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,26 @@
import lt.satsyuk.MainApplication;
import lt.satsyuk.dto.AppResponse;
import lt.satsyuk.api.util.AbstractIntegrationTest;
import lt.satsyuk.config.KeycloakProperties;
import lt.satsyuk.dto.KeycloakTokenResponse;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cache.CacheManager;
import org.springframework.http.*;
import lt.satsyuk.security.RateLimitingFilter;

import java.util.Set;

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = MainApplication.class)
class AuthValidationIT extends AbstractIntegrationTest {

AuthValidationIT(@Qualifier("keycloakProperties") KeycloakProperties props,
CacheManager cacheManager,
RateLimitingFilter rateLimitingFilter) {
super(props, cacheManager, rateLimitingFilter);
}

@Test
void login_emptyFields_badRequest() {
ResponseEntity<AppResponse<KeycloakTokenResponse>> response = loginRequest(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,12 @@
import lt.satsyuk.service.ClientService;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cache.CacheManager;
import org.springframework.http.*;
import lt.satsyuk.config.KeycloakProperties;
import lt.satsyuk.security.RateLimitingFilter;

import java.util.Set;
import java.util.UUID;
Expand All @@ -39,12 +42,21 @@ class ClientIntegrationIT extends KeycloakIntegrationTest {
public static final String ALICE = "Alice";
public static final String SMITH = "Smith";
public static final String PHONE = "+37061234567";
@Autowired
ClientRepository repo;
@Autowired
AccountRepository accountRepository;
@Autowired
RequestRepository requestRepository;
private final ClientRepository repo;
private final AccountRepository accountRepository;
private final RequestRepository requestRepository;

ClientIntegrationIT(@Qualifier("keycloakProperties") KeycloakProperties props,
CacheManager cacheManager,
RateLimitingFilter rateLimitingFilter,
ClientRepository repo,
AccountRepository accountRepository,
RequestRepository requestRepository) {
super(props, cacheManager, rateLimitingFilter);
this.repo = repo;
this.accountRepository = accountRepository;
this.requestRepository = requestRepository;
}

@BeforeEach
void setUp() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,14 @@
import lt.satsyuk.model.Client;
import lt.satsyuk.repository.ClientRepository;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.cache.CacheManager;
import lt.satsyuk.config.KeycloakProperties;
import lt.satsyuk.security.RateLimitingFilter;

import java.security.KeyPair;
import java.security.KeyPairGenerator;
Expand All @@ -38,8 +41,15 @@
)
class DpopIntegrationIT extends WireMockIntegrationTest {

@Autowired
private ClientRepository clientRepository;
private final ClientRepository clientRepository;

DpopIntegrationIT(@Qualifier("keycloakProperties") KeycloakProperties props,
CacheManager cacheManager,
RateLimitingFilter rateLimitingFilter,
ClientRepository clientRepository) {
super(props, cacheManager, rateLimitingFilter);
this.clientRepository = clientRepository;
}

@Test
void login_forwardsDpopHeaderToKeycloak() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,14 @@
import lt.satsyuk.MainApplication;
import lt.satsyuk.dto.AppResponse;
import lt.satsyuk.api.util.KeycloakIntegrationTest;
import lt.satsyuk.config.KeycloakProperties;
import lt.satsyuk.dto.KeycloakTokenResponse;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cache.CacheManager;
import org.springframework.http.*;
import lt.satsyuk.security.RateLimitingFilter;

import static org.assertj.core.api.Assertions.assertThat;

Expand All @@ -16,6 +20,12 @@
)
class KeycloakIntegrationIT extends KeycloakIntegrationTest {

KeycloakIntegrationIT(@Qualifier("keycloakProperties") KeycloakProperties props,
CacheManager cacheManager,
RateLimitingFilter rateLimitingFilter) {
super(props, cacheManager, rateLimitingFilter);
}

// ------------------------------------------------------------
// LOGIN TESTS
// ------------------------------------------------------------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,14 @@
import lt.satsyuk.MainApplication;
import lt.satsyuk.dto.AppResponse;
import lt.satsyuk.api.util.WireMockIntegrationTest;
import lt.satsyuk.config.KeycloakProperties;
import lt.satsyuk.dto.KeycloakTokenResponse;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cache.CacheManager;
import org.springframework.http.*;
import lt.satsyuk.security.RateLimitingFilter;

import static com.github.tomakehurst.wiremock.client.WireMock.*;
import static org.springframework.http.HttpHeaders.CONTENT_TYPE;
Expand All @@ -18,6 +22,12 @@
)
class KeycloakNegativeIT extends WireMockIntegrationTest {

KeycloakNegativeIT(@Qualifier("keycloakProperties") KeycloakProperties props,
CacheManager cacheManager,
RateLimitingFilter rateLimitingFilter) {
super(props, cacheManager, rateLimitingFilter);
}

// ------------------------------------------------------------
// KEYCLOAK CONNECTION FAILURES
// ------------------------------------------------------------
Expand Down
10 changes: 10 additions & 0 deletions src/test/java/lt/satsyuk/api/integrationtest/RateLimitingIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,14 @@
import lt.satsyuk.MainApplication;
import lt.satsyuk.dto.AppResponse;
import lt.satsyuk.api.util.WireMockIntegrationTest;
import lt.satsyuk.config.KeycloakProperties;
import lt.satsyuk.dto.KeycloakTokenResponse;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cache.CacheManager;
import org.springframework.http.*;
import lt.satsyuk.security.RateLimitingFilter;

import java.util.ArrayList;
import java.util.List;
Expand All @@ -22,6 +26,12 @@
)
class RateLimitingIT extends WireMockIntegrationTest {

RateLimitingIT(@Qualifier("keycloakProperties") KeycloakProperties props,
CacheManager cacheManager,
RateLimitingFilter rateLimitingFilter) {
super(props, cacheManager, rateLimitingFilter);
}

// ------------------------------------------------------------
// LOGIN RATE LIMIT TESTS (5 requests per minute)
// ------------------------------------------------------------
Expand Down
20 changes: 13 additions & 7 deletions src/test/java/lt/satsyuk/api/util/AbstractIntegrationTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@
import org.junit.jupiter.api.BeforeEach;
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;
import org.springframework.test.context.TestConstructor;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.boot.test.web.server.LocalServerPort;
Expand All @@ -40,6 +40,7 @@
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
@ActiveProfiles("test")
@Testcontainers
@TestConstructor(autowireMode = TestConstructor.AutowireMode.ALL)
public abstract class AbstractIntegrationTest {

// Testcontainers-managed shared containers for integration tests
Expand Down Expand Up @@ -82,16 +83,21 @@ static void checkDocker() {
assumeTrue(pg != null && pg.isRunning(), "Postgres container must be running");
}

@Autowired
protected KeycloakProperties props;
protected final KeycloakProperties props;

protected RestTemplate restTemplate;

@Autowired
protected CacheManager cacheManager;
protected final CacheManager cacheManager;

@Autowired
protected RateLimitingFilter rateLimitingFilter;
protected final RateLimitingFilter rateLimitingFilter;

protected AbstractIntegrationTest(KeycloakProperties props,
CacheManager cacheManager,
RateLimitingFilter rateLimitingFilter) {
this.props = props;
this.cacheManager = cacheManager;
this.rateLimitingFilter = rateLimitingFilter;
}

// Use a local ObjectMapper in Boot 4 PoC so integration tests do not depend on a Spring-managed bean.
protected final ObjectMapper objectMapper = new ObjectMapper().findAndRegisterModules();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package lt.satsyuk.api.util;

import dasniko.testcontainers.keycloak.KeycloakContainer;
import lt.satsyuk.config.KeycloakProperties;
import lt.satsyuk.security.RateLimitingFilter;
import org.junit.jupiter.api.BeforeAll;
import org.springframework.cache.CacheManager;
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;
import org.testcontainers.junit.jupiter.Container;
Expand All @@ -10,6 +13,12 @@

public abstract class KeycloakIntegrationTest extends AbstractIntegrationTest {

protected KeycloakIntegrationTest(KeycloakProperties props,
CacheManager cacheManager,
RateLimitingFilter rateLimitingFilter) {
super(props, cacheManager, rateLimitingFilter);
}

@Container
protected static KeycloakContainer keycloak = new KeycloakContainer("quay.io/keycloak/keycloak:26.0.0")
.withRealmImportFile("keycloak/realm-export.json")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,12 @@
import com.nimbusds.jose.jwk.RSAKey;
import com.nimbusds.jwt.JWTClaimsSet;
import com.nimbusds.jwt.SignedJWT;
import lt.satsyuk.config.KeycloakProperties;
import lt.satsyuk.security.RateLimitingFilter;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.springframework.cache.CacheManager;
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;
import org.springframework.test.annotation.DirtiesContext;
Expand All @@ -33,6 +36,12 @@
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
public abstract class WireMockIntegrationTest extends AbstractIntegrationTest {

protected WireMockIntegrationTest(KeycloakProperties props,
CacheManager cacheManager,
RateLimitingFilter rateLimitingFilter) {
super(props, cacheManager, rateLimitingFilter);
}

protected static final String REALMS_PROTOCOL_OPENID_CONNECT_TOKEN = "/realms/.*/protocol/openid-connect/token";
protected static final String REALMS_PROTOCOL_OPENID_CONNECT_LOGOUT = "/realms/.*/protocol/openid-connect/logout";
protected static final String REALMS_PROTOCOL_OPENID_CONNECT_INTROSPECT = "/realms/.*/protocol/openid-connect/token/introspect";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@
import org.junit.jupiter.api.extension.ExtendWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.system.CapturedOutput;
import org.springframework.boot.test.system.OutputCaptureExtension;
import org.springframework.test.context.TestConstructor;

import static org.assertj.core.api.Assertions.assertThat;

Expand All @@ -28,12 +28,16 @@
}
)
@ExtendWith(OutputCaptureExtension.class)
@TestConstructor(autowireMode = TestConstructor.AutowireMode.ALL)
class LoggingCorrelationTest {

private static final Logger log = LoggerFactory.getLogger(LoggingCorrelationTest.class);

@Autowired
private Tracer tracer;
private final Tracer tracer;

LoggingCorrelationTest(Tracer tracer) {
this.tracer = tracer;
}

@Test
void logLineContainsTraceIdAndSpanIdWhenSpanIsActive(CapturedOutput output) {
Expand Down