Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
2e3d219
feat(security): implement end-to-end security pillar
Arzu-N Jun 28, 2026
0b84f18
fix(test): fix method naming convention and checkstyle violations
Arzu-N Jun 28, 2026
2b59ea8
fix(test): resolve checkstyle violations and dependency injection errors
Arzu-N Jun 28, 2026
0ef3c0e
fix(worker): enable component scanning
Arzu-N Jun 28, 2026
796d6b5
fix(test): align worker and api tests with application context
Arzu-N Jun 28, 2026
e63e6e9
refactor(test): decouple SpringBootTest from AbstractIntegrationTest …
Arzu-N Jun 28, 2026
d16e765
fix(test): exclude data source auto-config in integration tests
Arzu-N Jun 28, 2026
b0167ac
fix(test): mock service dependencies in worker test
Arzu-N Jun 28, 2026
9705041
test: decouple SpringBootTest from the integration base and remove re…
Arzu-N Jun 29, 2026
b3728a5
test: refactor integration tests with active profiles and testcontainers
Arzu-N Jun 29, 2026
c37478c
test: isolate test context with application-test.yml and disable auto…
Arzu-N Jun 29, 2026
398edbe
test: add classes parameter to @SpringBootTest in worker module
Arzu-N Jun 29, 2026
c475c44
test: add @ComponentScan annotation to CleatWorkerApplicationTests
Arzu-N Jun 29, 2026
5280e5f
test: add @ComponentScan annotation to CleatApiApplicationTests
Arzu-N Jun 29, 2026
d68b7bd
test: clean integration test context and remove redundant mock beans
Arzu-N Jun 29, 2026
908757a
test: remove auto-configuration exclusion to allow Testcontainers to …
Arzu-N Jun 29, 2026
288381f
test: resolve NoUniqueBeanDefinitionException by providing primary da…
Arzu-N Jun 29, 2026
e447937
test: remove redundant application-test.properties configurations to …
Arzu-N Jun 29, 2026
6d6949b
test: add @EnableJpaRepository and @EntityScan to fix multi-module be…
Arzu-N Jun 29, 2026
1343001
test: remove @EntityScan and @EnableJpaRepositories from integration …
Arzu-N Jun 29, 2026
b71a4c5
test: add @EntityScan and @EnableJpaRepositories to CleatWorkerApllic…
Arzu-N Jun 29, 2026
31d74b2
test: add @EntityScan and @EnableJpaRepositories(basePackages=dev.cle…
Arzu-N Jun 29, 2026
3b0c901
fix(test): resolve Spring context wiring issues in multi-module build
Arzu-N Jun 29, 2026
2276feb
test: add properties parameter to @SpringBootTest
Arzu-N Jun 29, 2026
1ca2b28
test: add classes parameter to @SpringBootTest in CleatApiApplication
Arzu-N Jun 29, 2026
4fb6ea5
test: isolate test contexts via ComponentScan filters
Arzu-N Jun 29, 2026
b8d0b5d
test: isolate test contexts with dedicated TestConfigs
Arzu-N Jun 29, 2026
d8c1368
fix(tests): resolve bean conflicts with context isolation
Arzu-N Jun 29, 2026
3329cca
fix(tests): resolve context contamination with DirtiesContext
Arzu-N Jun 29, 2026
b826707
test: add webEnvironment parameter to @SpringBootTest
Arzu-N Jun 29, 2026
c6b1554
test: add static modifier to containers in AbstractIntegrationTest
Arzu-N Jun 29, 2026
f4b3ace
fix(spring-context): scope scanBasePackages in api and worker apps
Arzu-N Jun 29, 2026
77f1876
fix(spring-context): add dev.cleat.common package to @SpringBootAppli…
Arzu-N Jun 29, 2026
dfa2451
fix(spring-context): add @EntityScan and @EnableJpaRepositories to Cl…
Arzu-N Jun 29, 2026
09815e4
refactor(exception): improve security and logging in GlobalExceptionH…
Arzu-N Jun 29, 2026
6dcca83
refactor(dto): remove 'priority' field from VulnerabilityRequestDto t…
Arzu-N Jun 29, 2026
460951d
refactor(domain): add canonical contructor to Vulnerability record to…
Arzu-N Jun 29, 2026
5e05290
fix(test): update test data in VulnerabilityScannerTest to provide va…
Arzu-N Jun 29, 2026
a2cd900
fix(test): provide mandatory 'cvss','kev' and 'severity' values in te…
Arzu-N Jun 29, 2026
d348d02
fix(scanning): correct typo causing compilation error
Arzu-N Jun 29, 2026
11be14a
refactor(persistence): add @PrePersist to populate detectedAt automat…
Arzu-N Jun 29, 2026
dc21393
refactor(api): improve exception handling in GlobalExceptionHandler
Arzu-N Jun 29, 2026
e06aac2
refactor(migration): remove DEFAULT 'main' from code_scan_alerts.bran…
Arzu-N Jun 29, 2026
4c0de2d
fix(migartion): remove DEFAULT from code_scan_alerts.branch column
Arzu-N Jun 29, 2026
fced438
fix(scanning): delete verify() method from CodeScanAlertScannerTest t…
Arzu-N Jun 29, 2026
f584d6c
refactor(scanning): input validation moved out of try block to improv…
Arzu-N Jun 29, 2026
091ddf1
test(scanning): update unit test to verify persistence calls via veri…
Arzu-N Jun 29, 2026
fbe8608
test(scanning): refine unit test in VulnerabilityScannerTest
Arzu-N Jun 29, 2026
bf11293
feat(worker): implement comprehensive SecurityScanWorker for schedule…
Arzu-N Jun 30, 2026
530061c
refactor(worker): move security scan fixedDelay to application.yml
Arzu-N Jun 30, 2026
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 @@ -5,7 +5,14 @@
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;

@SpringBootApplication(scanBasePackages = {"dev.cleat.api", "dev.cleat.persistence", "dev.cleat.common"})
@SpringBootApplication(
scanBasePackages = {
"dev.cleat.api",
"dev.cleat.persistence",
"dev.cleat.domain",
"dev.cleat.common",
"dev.cleat.scanning"
})
@EnableJpaRepositories(basePackages = "dev.cleat.persistence.repository")
@EntityScan(basePackages = "dev.cleat.persistence.entity")
public class CleatApiApplication {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package dev.cleat.api.controller;

import dev.cleat.common.dto.request.CodeScanAlertRequestDto;
import dev.cleat.common.dto.response.CodeScanAlertResponseDto;
import dev.cleat.scanning.service.CodeScanAlertService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
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;

@RestController
@RequestMapping("/api/v1/alerts")
public class CodeScanAlertController {

private final CodeScanAlertService codeScanAlertService;

public CodeScanAlertController(CodeScanAlertService codeScanAlertService) {
this.codeScanAlertService = codeScanAlertService;
}

@PostMapping
public ResponseEntity<CodeScanAlertResponseDto> create(
@RequestBody CodeScanAlertRequestDto codeScanAlertRequestDto) {
return ResponseEntity.status(HttpStatus.CREATED).body(codeScanAlertService.create(codeScanAlertRequestDto));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package dev.cleat.api.controller;

import dev.cleat.common.dto.request.SecretFindingRequestDto;
import dev.cleat.common.dto.response.SecretFindingResponseDto;
import dev.cleat.scanning.service.SecretFindingService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
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;

@RestController
@RequestMapping("/api/v1/secrets")
public class SecretFindingController {

private final SecretFindingService secretFindingService;

public SecretFindingController(SecretFindingService secretFindingService) {
this.secretFindingService = secretFindingService;
}

@PostMapping
public ResponseEntity<SecretFindingResponseDto> createSecret(
@RequestBody SecretFindingRequestDto secretFindingRequestDto) {
return ResponseEntity.status(HttpStatus.CREATED).body(secretFindingService.create(secretFindingRequestDto));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package dev.cleat.api.controller;

import dev.cleat.common.dto.request.VulnerabilityRequestDto;
import dev.cleat.common.dto.response.VulnerabilityResponseDto;
import dev.cleat.scanning.service.VulnerabilityService;
import java.util.UUID;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
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;

@RestController
@RequestMapping("/api/v1/vulnerabilities")
public class VulnerabilityController {

private final VulnerabilityService vulnerabilityService;

public VulnerabilityController(VulnerabilityService vulnerabilityService) {
this.vulnerabilityService = vulnerabilityService;
}

@PostMapping
public ResponseEntity<VulnerabilityResponseDto> createVulnerability(
@RequestBody VulnerabilityRequestDto vulnerabilityRequestDto) {
return ResponseEntity.status(HttpStatus.CREATED).body(vulnerabilityService.create(vulnerabilityRequestDto));
}

@GetMapping("/{id}")
public ResponseEntity<VulnerabilityResponseDto> getVulnerability(@PathVariable UUID id) {
return ResponseEntity.ok(vulnerabilityService.findById(id));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package dev.cleat.api.exception;

import dev.cleat.common.exception.NotFoundException;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.server.ResponseStatusException;

@RestControllerAdvice
public class GlobalExceptionHandler {
private static final Logger LOG = LoggerFactory.getLogger(GlobalExceptionHandler.class);

@ExceptionHandler(NotFoundException.class)
public ResponseEntity<Map<String, String>> handleNotFound(NotFoundException ex) {
LOG.info("Resource not found: {}", ex.getMessage());
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(Map.of("error", ex.getMessage()));
}

@ExceptionHandler(Exception.class)
public ResponseEntity<Map<String, String>> handleGeneralException(Exception ex) {

if (ex instanceof ResponseStatusException) {
throw (ResponseStatusException) ex;
}
LOG.error("Unhandled exception occurred: ", ex);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(Map.of("error", "An unexpected error occurred"));
}
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
package dev.cleat.api;

import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.PostgreSQLContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;

@Testcontainers
@SpringBootTest
public abstract class AbstractIntegrationTest {

@Container
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.DirtiesContext;

@SpringBootTest
@SpringBootTest(classes = CleatApiApplication.class)
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
public class CleatApiTests extends AbstractIntegrationTest {

@Test
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package dev.cleat.api;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

import com.fasterxml.jackson.databind.ObjectMapper;
import dev.cleat.api.controller.CodeScanAlertController;
import dev.cleat.common.dto.request.CodeScanAlertRequestDto;
import dev.cleat.scanning.service.CodeScanAlertService;
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.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.bean.override.mockito.MockitoBean;
import org.springframework.test.web.servlet.MockMvc;

@WebMvcTest(CodeScanAlertController.class)
@AutoConfigureMockMvc(addFilters = false)
@ContextConfiguration(classes = CodeScanAlertController.class)
public class CodeScanAlertControllerTest {

@Autowired
private MockMvc mockMvc;

@Autowired
private ObjectMapper objectMapper;

@MockitoBean
private CodeScanAlertService codeScanAlertService;

@Test
void whenCreateCodeScanAlertThenShouldBeReturn201() throws Exception {

// given
CodeScanAlertRequestDto codeScanAlertRequestDto = new CodeScanAlertRequestDto();

// then
mockMvc.perform(post("/api/v1/alerts")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(codeScanAlertRequestDto)))
.andExpect(status().isCreated());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package dev.cleat.api;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

import com.fasterxml.jackson.databind.ObjectMapper;
import dev.cleat.api.controller.SecretFindingController;
import dev.cleat.common.dto.request.SecretFindingRequestDto;
import dev.cleat.scanning.service.SecretFindingService;
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.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.bean.override.mockito.MockitoBean;
import org.springframework.test.web.servlet.MockMvc;

@WebMvcTest(SecretFindingController.class)
@AutoConfigureMockMvc(addFilters = false)
@ContextConfiguration(classes = {SecretFindingController.class})
public class SecretFindingControllerTest {

@Autowired
private MockMvc mockMvc;

@Autowired
private ObjectMapper objectMapper;

@MockitoBean
private SecretFindingService secretFindingService;

@Test
void whenCreateSecretThenShouldReturn201() throws Exception {

// given
SecretFindingRequestDto secretFindingRequestDto = new SecretFindingRequestDto();

// then
mockMvc.perform(post("/api/v1/secrets")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(secretFindingRequestDto)))
.andExpect(status().isCreated());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package dev.cleat.api;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

import com.fasterxml.jackson.databind.ObjectMapper;
import dev.cleat.api.controller.VulnerabilityController;
import dev.cleat.common.dto.request.VulnerabilityRequestDto;
import dev.cleat.scanning.service.VulnerabilityService;
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.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.bean.override.mockito.MockitoBean;
import org.springframework.test.web.servlet.MockMvc;

@WebMvcTest(VulnerabilityController.class)
@AutoConfigureMockMvc(addFilters = false)
@ContextConfiguration(classes = {VulnerabilityController.class})
public class VulnerabilityControllerTest {

@Autowired
private MockMvc mockMvc;

@Autowired
private ObjectMapper objectMapper;

@MockitoBean
private VulnerabilityService vulnerabilityService;

@Test
void whenCreateVulnerabilityThenShouldReturn201() throws Exception {

// given
VulnerabilityRequestDto vulnerabilityRequestDto = new VulnerabilityRequestDto();

// then
mockMvc.perform(post("/api/v1/vulnerabilities")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(vulnerabilityRequestDto)))
.andExpect(status().isCreated());
}
}
9 changes: 5 additions & 4 deletions backend/apps/worker/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ dependencies {
implementation("org.springframework.boot:spring-boot-starter-actuator")

testImplementation("org.springframework.boot:spring-boot-starter-test")
testImplementation("org.testcontainers:junit-jupiter")
testImplementation("org.testcontainers:postgresql")
testImplementation("org.testcontainers:testcontainers")
testImplementation("org.springframework.boot:spring-boot-testcontainers")
testImplementation("org.testcontainers:junit-jupiter")
testImplementation("org.testcontainers:postgresql")
testImplementation("org.testcontainers:testcontainers")
testImplementation("org.springframework.boot:spring-boot-testcontainers")

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,20 @@

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.scheduling.annotation.EnableScheduling;

@SpringBootApplication
@SpringBootApplication(
scanBasePackages = {
"dev.cleat.persistence",
"dev.cleat.scanning",
"dev.cleat.worker",
"dev.cleat.domain",
"dev.cleat.common"
})
@EnableJpaRepositories(basePackages = "dev.cleat.persistence.repository")
@EntityScan(basePackages = "dev.cleat.persistence.entity")
@EnableScheduling
public class CleatWorkerApplication {

Expand Down
Loading
Loading