diff --git a/src/main/java/io/securecodebox/persistence/defectdojo/config/Config.java b/src/main/java/io/securecodebox/persistence/defectdojo/config/Config.java index ac66a519..2d840d5c 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/config/Config.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/config/Config.java @@ -7,8 +7,6 @@ import io.securecodebox.persistence.defectdojo.exception.ConfigException; import lombok.*; -import java.util.Optional; - /** * Configures the DefectDojo client */ diff --git a/src/main/java/io/securecodebox/persistence/defectdojo/http/Foo.java b/src/main/java/io/securecodebox/persistence/defectdojo/http/Foo.java index 3430eb42..34338634 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/http/Foo.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/http/Foo.java @@ -12,7 +12,6 @@ import org.apache.http.auth.UsernamePasswordCredentials; import org.apache.http.client.CredentialsProvider; import org.apache.http.impl.client.BasicCredentialsProvider; -import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.client.ProxyAuthenticationStrategy; import org.springframework.http.HttpHeaders; diff --git a/src/main/java/io/securecodebox/persistence/defectdojo/model/BaseModel.java b/src/main/java/io/securecodebox/persistence/defectdojo/model/BaseModel.java index 90216f00..047b51d3 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/model/BaseModel.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/model/BaseModel.java @@ -4,11 +4,9 @@ package io.securecodebox.persistence.defectdojo.model; -import java.util.Map; import lombok.EqualsAndHashCode; @EqualsAndHashCode // FIXME: Implement hashCode/equals in inheritance is problematic https://www.artima.com/articles/how-to-write-an-equality-method-in-java (see https://github.com/secureCodeBox/defectdojo-client-java/issues/23) -// FIXME: Class should be package private because implementation detail -abstract public class BaseModel { - public abstract boolean equalsQueryString(Map queryParams); +abstract class BaseModel implements Model { + // Class can be removed we remove @EqualsAndHashCode. } diff --git a/src/main/java/io/securecodebox/persistence/defectdojo/model/Endpoint.java b/src/main/java/io/securecodebox/persistence/defectdojo/model/Endpoint.java index 5daf9ea8..0845b93f 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/model/Endpoint.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/model/Endpoint.java @@ -49,9 +49,6 @@ public class Endpoint extends BaseModel { @Override public boolean equalsQueryString(Map queryParams) { - if (queryParams.containsKey("id") && queryParams.get("id").equals(this.id)) { - return true; - } - return false; + return queryParams.containsKey("id") && queryParams.get("id").equals(this.id); } } diff --git a/src/main/java/io/securecodebox/persistence/defectdojo/model/Finding.java b/src/main/java/io/securecodebox/persistence/defectdojo/model/Finding.java index 669eef70..7fdc2a72 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/model/Finding.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/model/Finding.java @@ -111,15 +111,15 @@ public class Finding extends BaseModel { @JsonProperty("numerical_severity") public String getNumericalSeverity() { switch (this.severity) { - case Critical: + case CRITICAL: return "S0"; - case High: + case HIGH: return "S1"; - case Medium: + case MEDIUM: return "S2"; - case Low: + case LOW: return "S3"; - case Informational: + case INFORMATIONAL: return "S4"; default: throw new PersistenceException("Unknown severity: '" + this.severity + "'"); @@ -133,21 +133,20 @@ public boolean equalsQueryString(Map queryParams) { public enum Severity { @JsonProperty("Critical") - Critical(5), + CRITICAL(5), @JsonProperty("High") - High(4), + HIGH(4), @JsonProperty("Medium") - Medium(3), + MEDIUM(3), @JsonProperty("Low") - Low(2), + LOW(2), // Depending on the Scanner DefectDojo uses either Info or Informational // E.g. Nmap uses Info, Zap uses Informational @JsonProperty("Info") @JsonAlias("Informational") - Informational(1), - ; + INFORMATIONAL(1); - long severity; + final long severity; Severity(long severity) { this.severity = severity; diff --git a/src/main/java/io/securecodebox/persistence/defectdojo/model/Model.java b/src/main/java/io/securecodebox/persistence/defectdojo/model/Model.java new file mode 100644 index 00000000..1b5af800 --- /dev/null +++ b/src/main/java/io/securecodebox/persistence/defectdojo/model/Model.java @@ -0,0 +1,10 @@ +package io.securecodebox.persistence.defectdojo.model; + +import java.util.Map; + +/** + * Interface for all models + */ +public interface Model { + boolean equalsQueryString(Map queryParams); +} diff --git a/src/main/java/io/securecodebox/persistence/defectdojo/model/RiskAcceptance.java b/src/main/java/io/securecodebox/persistence/defectdojo/model/RiskAcceptance.java index 04bd6a2d..cc203673 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/model/RiskAcceptance.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/model/RiskAcceptance.java @@ -58,9 +58,6 @@ public class RiskAcceptance extends BaseModel { @Override public boolean equalsQueryString(Map queryParams) { - if (queryParams.containsKey("id") && queryParams.get("id").equals(this.id)) { - return true; - } - return false; + return queryParams.containsKey("id") && queryParams.get("id").equals(this.id); } } diff --git a/src/main/java/io/securecodebox/persistence/defectdojo/service/FindingService.java b/src/main/java/io/securecodebox/persistence/defectdojo/service/FindingService.java index 959be637..607b2e68 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/service/FindingService.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/service/FindingService.java @@ -13,7 +13,6 @@ import java.net.URISyntaxException; import java.util.List; import java.util.Map; -import java.util.stream.Collectors; public class FindingService extends GenericDefectDojoService { public FindingService(Config config) { @@ -37,14 +36,24 @@ protected Response deserializeList(String response) throws JsonProcessi } public List getUnhandledFindingsForProduct(long productId, Finding.Severity minimumSeverity) throws URISyntaxException, JsonProcessingException { - return this.search(Map.of("test__engagement__product", Long.toString(productId), "active", Boolean.toString(true))).stream().filter((finding -> { - return finding.getSeverity().getNumericRepresentation() >= minimumSeverity.getNumericRepresentation(); - })).collect(Collectors.toList()); + final Map queryParams = Map.of( + "test__engagement__product", Long.toString(productId), + "active", Boolean.toString(true)); + + return this.search(queryParams) + .stream() + .filter((finding -> finding.getSeverity().getNumericRepresentation() >= minimumSeverity.getNumericRepresentation())) + .toList(); } public List getUnhandledFindingsForEngagement(long engagementId, Finding.Severity minimumSeverity) throws URISyntaxException, JsonProcessingException { - return this.search(Map.of("test__engagement", Long.toString(engagementId), "active", Boolean.toString(true))).stream().filter((finding -> { - return finding.getSeverity().getNumericRepresentation() >= minimumSeverity.getNumericRepresentation(); - })).collect(Collectors.toList()); + final Map queryParams = Map.of( + "test__engagement", Long.toString(engagementId), + "active", Boolean.toString(true)); + + return this.search(queryParams) + .stream() + .filter((finding -> finding.getSeverity().getNumericRepresentation() >= minimumSeverity.getNumericRepresentation())) + .toList(); } } diff --git a/src/main/java/io/securecodebox/persistence/defectdojo/service/GenericDefectDojoService.java b/src/main/java/io/securecodebox/persistence/defectdojo/service/GenericDefectDojoService.java index 85c0f7c6..ea32ff7a 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/service/GenericDefectDojoService.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/service/GenericDefectDojoService.java @@ -14,8 +14,8 @@ import io.securecodebox.persistence.defectdojo.exception.LoopException; import io.securecodebox.persistence.defectdojo.http.Foo; import io.securecodebox.persistence.defectdojo.http.ProxyConfigFactory; -import io.securecodebox.persistence.defectdojo.model.BaseModel; import io.securecodebox.persistence.defectdojo.model.Engagement; +import io.securecodebox.persistence.defectdojo.model.Model; import io.securecodebox.persistence.defectdojo.model.Response; import lombok.Getter; import org.springframework.http.HttpEntity; @@ -35,162 +35,163 @@ import java.util.*; // FIXME: Should be package private bc implementation detail. -abstract public class GenericDefectDojoService { - protected Config config; +public abstract class GenericDefectDojoService { + private static final String API_PREFIX = "/api/v2/"; + private static final long DEFECT_DOJO_OBJET_LIMIT = 100L; + protected Config config; - protected ObjectMapper objectMapper; - protected ObjectMapper searchStringMapper; + protected ObjectMapper objectMapper; + protected ObjectMapper searchStringMapper; - @Getter - protected RestTemplate restTemplate; + @Getter + protected RestTemplate restTemplate; - public GenericDefectDojoService(Config config) { - this.config = config; + public GenericDefectDojoService(Config config) { + this.config = config; - this.objectMapper = new ObjectMapper(); - this.objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); - this.objectMapper.coercionConfigFor(Engagement.Status.class).setCoercion(CoercionInputShape.EmptyString, CoercionAction.AsNull); - this.objectMapper.findAndRegisterModules(); + this.objectMapper = new ObjectMapper(); + this.objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + this.objectMapper.coercionConfigFor(Engagement.Status.class).setCoercion(CoercionInputShape.EmptyString, CoercionAction.AsNull); + this.objectMapper.findAndRegisterModules(); - this.searchStringMapper = new ObjectMapper(); - this.searchStringMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); - this.searchStringMapper.coercionConfigFor(Engagement.Status.class).setCoercion(CoercionInputShape.EmptyString, CoercionAction.AsNull); - this.searchStringMapper.setSerializationInclusion(JsonInclude.Include.NON_DEFAULT); + this.searchStringMapper = new ObjectMapper(); + this.searchStringMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + this.searchStringMapper.coercionConfigFor(Engagement.Status.class).setCoercion(CoercionInputShape.EmptyString, CoercionAction.AsNull); + this.searchStringMapper.setSerializationInclusion(JsonInclude.Include.NON_DEFAULT); - this.restTemplate = this.setupRestTemplate(); - } + this.restTemplate = this.setupRestTemplate(); + } - protected long DEFECT_DOJO_OBJET_LIMIT = 100L; - /** - * @return The DefectDojo Authentication Header - */ - private HttpHeaders getDefectDojoAuthorizationHeaders() { - return new Foo(config, new ProxyConfigFactory().create()).generateAuthorizationHeaders(); - } + /** + * @return The DefectDojo Authentication Header + */ + private HttpHeaders getDefectDojoAuthorizationHeaders() { + return new Foo(config, new ProxyConfigFactory().create()).generateAuthorizationHeaders(); + } - private RestTemplate setupRestTemplate() { - RestTemplate restTemplate = new Foo(config, new ProxyConfigFactory().create()).createRestTemplate(); - MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(); - converter.setObjectMapper(this.objectMapper); - restTemplate.setMessageConverters(List.of( - new FormHttpMessageConverter(), - new ResourceHttpMessageConverter(), - new StringHttpMessageConverter(), - converter - )); - return restTemplate; - } + private RestTemplate setupRestTemplate() { + RestTemplate restTemplate = new Foo(config, new ProxyConfigFactory().create()).createRestTemplate(); + MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(); + converter.setObjectMapper(this.objectMapper); + restTemplate.setMessageConverters(List.of( + new FormHttpMessageConverter(), + new ResourceHttpMessageConverter(), + new StringHttpMessageConverter(), + converter + )); + return restTemplate; + } - protected abstract String getUrlPath(); + protected abstract String getUrlPath(); - protected abstract Class getModelClass(); + protected abstract Class getModelClass(); - protected abstract Response deserializeList(String response) throws JsonProcessingException; + protected abstract Response deserializeList(String response) throws JsonProcessingException; - public T get(long id) { - var restTemplate = this.getRestTemplate(); - HttpEntity payload = new HttpEntity<>(getDefectDojoAuthorizationHeaders()); + public T get(long id) { + var restTemplate = this.getRestTemplate(); + HttpEntity payload = new HttpEntity<>(getDefectDojoAuthorizationHeaders()); - ResponseEntity response = restTemplate.exchange( - this.config.getUrl() + "/api/v2/" + this.getUrlPath() + "/" + id, - HttpMethod.GET, - payload, - getModelClass() - ); + ResponseEntity response = restTemplate.exchange( + this.config.getUrl() + API_PREFIX + this.getUrlPath() + "/" + id, + HttpMethod.GET, + payload, + getModelClass() + ); - return response.getBody(); - } + return response.getBody(); + } - protected Response internalSearch(Map queryParams, long limit, long offset) throws JsonProcessingException, URISyntaxException { - var restTemplate = this.getRestTemplate(); - HttpEntity payload = new HttpEntity<>(getDefectDojoAuthorizationHeaders()); + protected Response internalSearch(Map queryParams, long limit, long offset) throws JsonProcessingException, URISyntaxException { + var restTemplate = this.getRestTemplate(); + HttpEntity payload = new HttpEntity<>(getDefectDojoAuthorizationHeaders()); - var mutableQueryParams = new HashMap(queryParams); + var mutableQueryParams = new HashMap(queryParams); - mutableQueryParams.put("limit", String.valueOf(limit)); - mutableQueryParams.put("offset", String.valueOf(offset)); + mutableQueryParams.put("limit", String.valueOf(limit)); + mutableQueryParams.put("offset", String.valueOf(offset)); - var multiValueMap = new LinkedMultiValueMap(); - for (var entry : mutableQueryParams.entrySet()) { - multiValueMap.set(entry.getKey(), String.valueOf(entry.getValue())); - } + var multiValueMap = new LinkedMultiValueMap(); + for (var entry : mutableQueryParams.entrySet()) { + multiValueMap.set(entry.getKey(), String.valueOf(entry.getValue())); + } - var url = new URI(this.config.getUrl() + "/api/v2/" + this.getUrlPath() + "/"); - var uriBuilder = UriComponentsBuilder.fromUri(url).queryParams(multiValueMap); + var url = new URI(this.config.getUrl() + API_PREFIX + this.getUrlPath() + "/"); + var uriBuilder = UriComponentsBuilder.fromUri(url).queryParams(multiValueMap); - ResponseEntity responseString = restTemplate.exchange( - uriBuilder.build(mutableQueryParams), - HttpMethod.GET, - payload, - String.class - ); + ResponseEntity responseString = restTemplate.exchange( + uriBuilder.build(mutableQueryParams), + HttpMethod.GET, + payload, + String.class + ); - return deserializeList(responseString.getBody()); - } + return deserializeList(responseString.getBody()); + } - public List search(Map queryParams) throws URISyntaxException, JsonProcessingException { - List objects = new LinkedList<>(); + public List search(Map queryParams) throws URISyntaxException, JsonProcessingException { + List objects = new LinkedList<>(); - boolean hasNext = false; - long page = 0; - do { - var response = internalSearch(queryParams, DEFECT_DOJO_OBJET_LIMIT, DEFECT_DOJO_OBJET_LIMIT * page++); - objects.addAll(response.getResults()); + boolean hasNext = false; + long page = 0; + do { + var response = internalSearch(queryParams, DEFECT_DOJO_OBJET_LIMIT, DEFECT_DOJO_OBJET_LIMIT * page++); + objects.addAll(response.getResults()); - hasNext = response.getNext() != null; - if (page > this.config.getMaxPageCountForGets()) { - throw new LoopException("Found too many response object. Quitting after " + (page - 1) + " paginated API pages of " + DEFECT_DOJO_OBJET_LIMIT + " each."); - } - } while (hasNext); + hasNext = response.getNext() != null; + if (page > this.config.getMaxPageCountForGets()) { + throw new LoopException("Found too many response object. Quitting after " + (page - 1) + " paginated API pages of " + DEFECT_DOJO_OBJET_LIMIT + " each."); + } + } while (hasNext); - return objects; - } + return objects; + } - public List search() throws URISyntaxException, JsonProcessingException { - return search(new LinkedHashMap<>()); - } + public List search() throws URISyntaxException, JsonProcessingException { + return search(new LinkedHashMap<>()); + } - @SuppressWarnings("unchecked") - public Optional searchUnique(T searchObject) throws URISyntaxException, JsonProcessingException { - Map queryParams = searchStringMapper.convertValue(searchObject, Map.class); + @SuppressWarnings("unchecked") + public Optional searchUnique(T searchObject) throws URISyntaxException, JsonProcessingException { + Map queryParams = searchStringMapper.convertValue(searchObject, Map.class); - var objects = search(queryParams); + var objects = search(queryParams); - return objects.stream() - .filter((object) -> object != null && object.equalsQueryString(queryParams)) - .findFirst(); - } + return objects.stream() + .filter(object -> object != null && object.equalsQueryString(queryParams)) + .findFirst(); + } - public Optional searchUnique(Map queryParams) throws URISyntaxException, JsonProcessingException { - var objects = search(queryParams); + public Optional searchUnique(Map queryParams) throws URISyntaxException, JsonProcessingException { + var objects = search(queryParams); - return objects.stream() - .filter((object) -> object.equalsQueryString(queryParams)) - .findFirst(); - } + return objects.stream() + .filter(object -> object.equalsQueryString(queryParams)) + .findFirst(); + } - public T create(T object) { - var restTemplate = this.getRestTemplate(); - HttpEntity payload = new HttpEntity(object, getDefectDojoAuthorizationHeaders()); + public T create(T object) { + var restTemplate = this.getRestTemplate(); + HttpEntity payload = new HttpEntity<>(object, getDefectDojoAuthorizationHeaders()); - ResponseEntity response = restTemplate.exchange(this.config.getUrl() + "/api/v2/" + getUrlPath() + "/", HttpMethod.POST, payload, getModelClass()); - return response.getBody(); - } + ResponseEntity response = restTemplate.exchange(this.config.getUrl() + API_PREFIX + getUrlPath() + "/", HttpMethod.POST, payload, getModelClass()); + return response.getBody(); + } - public void delete(long id) { - var restTemplate = this.getRestTemplate(); - HttpEntity payload = new HttpEntity<>(getDefectDojoAuthorizationHeaders()); + public void delete(long id) { + var restTemplate = this.getRestTemplate(); + HttpEntity payload = new HttpEntity<>(getDefectDojoAuthorizationHeaders()); - restTemplate.exchange(this.config.getUrl() + "/api/v2/" + getUrlPath() + "/" + id + "/", HttpMethod.DELETE, payload, String.class); - } + restTemplate.exchange(this.config.getUrl() + API_PREFIX + getUrlPath() + "/" + id + "/", HttpMethod.DELETE, payload, String.class); + } - public T update(T object, long objectId) { - var restTemplate = this.getRestTemplate(); - HttpEntity payload = new HttpEntity(object, getDefectDojoAuthorizationHeaders()); + public T update(T object, long objectId) { + var restTemplate = this.getRestTemplate(); + HttpEntity payload = new HttpEntity<>(object, getDefectDojoAuthorizationHeaders()); - ResponseEntity response = restTemplate.exchange(this.config.getUrl() + "/api/v2/" + getUrlPath() + "/" + objectId + "/", HttpMethod.PUT, payload, getModelClass()); - return response.getBody(); - } + ResponseEntity response = restTemplate.exchange(this.config.getUrl() + API_PREFIX + getUrlPath() + "/" + objectId + "/", HttpMethod.PUT, payload, getModelClass()); + return response.getBody(); + } } diff --git a/src/main/java/io/securecodebox/persistence/defectdojo/service/ImportScanService2.java b/src/main/java/io/securecodebox/persistence/defectdojo/service/ImportScanService2.java index b9622f15..e87b7451 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/service/ImportScanService2.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/service/ImportScanService2.java @@ -33,112 +33,106 @@ */ public class ImportScanService2 { - private final Config config; - @Deprecated - protected String defectDojoUrl; - @Deprecated - protected String defectDojoApiKey; - - public ImportScanService2(Config config) { - super(); - this.config = config; - this.defectDojoUrl = config.getUrl(); - this.defectDojoApiKey = config.getApiKey(); + private final Config config; + + public ImportScanService2(Config config) { + super(); + this.config = config; + } + + /** + * @return The DefectDojo Authentication Header + */ + private HttpHeaders getDefectDojoAuthorizationHeaders() { + return new Foo(config, new ProxyConfigFactory().create()).generateAuthorizationHeaders(); + } + + protected RestTemplate setupRestTemplate() { + return new Foo(config, new ProxyConfigFactory().create()).createRestTemplate(); + } + + /** + * Before version 1.5.4. testName (in DefectDojo _test_type_) must be defectDojoScanName, afterwards, you can have somethings else + */ + protected ImportScanResponse createFindings(ScanFile scanFile, String endpoint, long lead, String currentDate, ScanType scanType, long testType, MultiValueMap options) { + var restTemplate = this.setupRestTemplate(); + HttpHeaders headers = getDefectDojoAuthorizationHeaders(); + headers.setContentType(MediaType.MULTIPART_FORM_DATA); + restTemplate.setMessageConverters(List.of( + new FormHttpMessageConverter(), + new ResourceHttpMessageConverter(), + new MappingJackson2HttpMessageConverter()) + ); + + MultiValueMap mvn = new LinkedMultiValueMap<>(); + + mvn.add("lead", Long.toString(lead)); + mvn.add("scan_date", currentDate); + mvn.add("scan_type", scanType.getTestType()); + mvn.add("close_old_findings", "true"); + mvn.add("skip_duplicates", "false"); + mvn.add("test_type", String.valueOf(testType)); + + for (String theKey : options.keySet()) { + mvn.remove(theKey); } + mvn.addAll(options); - /** - * @return The DefectDojo Authentication Header - */ - private HttpHeaders getDefectDojoAuthorizationHeaders() { - return new Foo(config, new ProxyConfigFactory().create()).generateAuthorizationHeaders(); - } - - protected RestTemplate setupRestTemplate() { - return new Foo(config, new ProxyConfigFactory().create()).createRestTemplate(); - } - - /** - * Before version 1.5.4. testName (in DefectDojo _test_type_) must be defectDojoScanName, afterwards, you can have somethings else - */ - protected ImportScanResponse createFindings(ScanFile scanFile, String endpoint, long lead, String currentDate, ScanType scanType, long testType, MultiValueMap options) { - var restTemplate = this.setupRestTemplate(); - HttpHeaders headers = getDefectDojoAuthorizationHeaders(); - headers.setContentType(MediaType.MULTIPART_FORM_DATA); - restTemplate.setMessageConverters(List.of( - new FormHttpMessageConverter(), - new ResourceHttpMessageConverter(), - new MappingJackson2HttpMessageConverter()) - ); - - MultiValueMap mvn = new LinkedMultiValueMap<>(); - - mvn.add("lead", Long.toString(lead)); - mvn.add("scan_date", currentDate); - mvn.add("scan_type", scanType.getTestType()); - mvn.add("close_old_findings", "true"); - mvn.add("skip_duplicates", "false"); - mvn.add("test_type", String.valueOf(testType)); - - for (String theKey : options.keySet()) { - mvn.remove(theKey); + try { + ByteArrayResource contentsAsResource = new ByteArrayResource(scanFile.getContent().getBytes(StandardCharsets.UTF_8)) { + @Override + public String getFilename() { + return scanFile.getName(); } - mvn.addAll(options); - - try { - ByteArrayResource contentsAsResource = new ByteArrayResource(scanFile.getContent().getBytes(StandardCharsets.UTF_8)) { - @Override - public String getFilename() { - return scanFile.getName(); - } - }; + }; - mvn.add("file", contentsAsResource); + mvn.add("file", contentsAsResource); - var payload = new HttpEntity<>(mvn, headers); + var payload = new HttpEntity<>(mvn, headers); - return restTemplate.exchange(defectDojoUrl + "/api/v2/" + endpoint + "/", HttpMethod.POST, payload, ImportScanResponse.class).getBody(); - } catch (HttpClientErrorException e) { - throw new PersistenceException("Failed to attach findings to engagement."); - } + return restTemplate.exchange(config.getUrl() + "/api/v2/" + endpoint + "/", HttpMethod.POST, payload, ImportScanResponse.class).getBody(); + } catch (HttpClientErrorException e) { + throw new PersistenceException("Failed to attach findings to engagement."); } + } - public ImportScanResponse importScan(ScanFile scanFile, long engagementId, long lead, String currentDate, ScanType scanType, long testType) { - var additionalValues = new LinkedMultiValueMap(); - additionalValues.add("engagement", Long.toString(engagementId)); + public ImportScanResponse importScan(ScanFile scanFile, long engagementId, long lead, String currentDate, ScanType scanType, long testType) { + var additionalValues = new LinkedMultiValueMap(); + additionalValues.add("engagement", Long.toString(engagementId)); - return this.importScan(scanFile, engagementId, lead, currentDate, scanType, testType, additionalValues); - } + return this.importScan(scanFile, engagementId, lead, currentDate, scanType, testType, additionalValues); + } - public ImportScanResponse reimportScan(ScanFile scanFile, long testId, long lead, String currentDate, ScanType scanType, long testType) { - var additionalValues = new LinkedMultiValueMap(); - additionalValues.add("test", Long.toString(testId)); + public ImportScanResponse reimportScan(ScanFile scanFile, long testId, long lead, String currentDate, ScanType scanType, long testType) { + var additionalValues = new LinkedMultiValueMap(); + additionalValues.add("test", Long.toString(testId)); - return this.reimportScan(scanFile, testId, lead, currentDate, scanType, testType, additionalValues); - } + return this.reimportScan(scanFile, testId, lead, currentDate, scanType, testType, additionalValues); + } - //overloading with optional parameter - public ImportScanResponse importScan(ScanFile scanFile, long engagementId, long lead, String currentDate, ScanType scanType, long testType, LinkedMultiValueMap additionalValues) { - additionalValues.add("engagement", Long.toString(engagementId)); + //overloading with optional parameter + public ImportScanResponse importScan(ScanFile scanFile, long engagementId, long lead, String currentDate, ScanType scanType, long testType, LinkedMultiValueMap additionalValues) { + additionalValues.add("engagement", Long.toString(engagementId)); - return this.createFindings(scanFile, "import-scan", lead, currentDate, scanType, testType, additionalValues); - } + return this.createFindings(scanFile, "import-scan", lead, currentDate, scanType, testType, additionalValues); + } - public ImportScanResponse reimportScan(ScanFile scanFile, long testId, long lead, String currentDate, ScanType scanType, long testType, LinkedMultiValueMap additionalValues) { - additionalValues.add("test", Long.toString(testId)); + public ImportScanResponse reimportScan(ScanFile scanFile, long testId, long lead, String currentDate, ScanType scanType, long testType, LinkedMultiValueMap additionalValues) { + additionalValues.add("test", Long.toString(testId)); - return this.createFindings(scanFile, "reimport-scan", lead, currentDate, scanType, testType, additionalValues); - } + return this.createFindings(scanFile, "reimport-scan", lead, currentDate, scanType, testType, additionalValues); + } - @Data - public static class ImportScanResponse { - @JsonProperty - protected Boolean verified; + @Data + public static class ImportScanResponse { + @JsonProperty + protected Boolean verified; - @JsonProperty - protected Boolean active; + @JsonProperty + protected Boolean active; - @JsonProperty("test") - protected long testId; - } + @JsonProperty("test") + protected long testId; + } } diff --git a/src/test/java/io/securecodebox/persistence/defectdojo/service/UserProfileServiceTest.java b/src/test/java/io/securecodebox/persistence/defectdojo/service/UserProfileServiceTest.java index 4fc42699..75347c5e 100644 --- a/src/test/java/io/securecodebox/persistence/defectdojo/service/UserProfileServiceTest.java +++ b/src/test/java/io/securecodebox/persistence/defectdojo/service/UserProfileServiceTest.java @@ -25,47 +25,47 @@ // This test is special because the defectdojo api does not return a list, // but the generic code assumes every endpoint returns a list -public class UserProfileServiceTest { +class UserProfileServiceTest { - Config config; - UserProfileService underTest; - MockRestServiceServer mockServer; + private Config config; + private UserProfileService underTest; + private MockRestServiceServer mockServer; - // This string does not contain every field of the api response as those are not implemented - String apiResponse = """ - { - "user": { - "id": 0, - "username": "GdqmXprK.j7R+OYE49SzL3mM2U6I0DyLRHnDg87i9It0AfP-kxvswW3qOI2i+31-@0", - "first_name": "string", - "last_name": "string", - "email": "user@example.com", - "last_login": "2022-11-01T16:20:19.373Z", - "is_active": true, - "is_superuser": true, - "configuration_permissions": [0] - } - } - """; - - @BeforeEach - void setup() { - config = new Config("https://defectdojo.example.com", "abc", 42); - underTest = new UserProfileService(config); - mockServer = MockRestServiceServer.createServer(underTest.getRestTemplate()); + // This string does not contain every field of the api response as those are not implemented + private String apiResponse = """ + { + "user": { + "id": 0, + "username": "GdqmXprK.j7R+OYE49SzL3mM2U6I0DyLRHnDg87i9It0AfP-kxvswW3qOI2i+31-@0", + "first_name": "string", + "last_name": "string", + "email": "user@example.com", + "last_login": "2022-11-01T16:20:19.373Z", + "is_active": true, + "is_superuser": true, + "configuration_permissions": [0] + } } + """; - @Test - void testSearch() throws JsonProcessingException, URISyntaxException { - var url = config.getUrl() + "/api/v2/" + underTest.getUrlPath() + "/?offset=0&limit=100"; - mockServer.expect(requestTo(url)).andRespond(withSuccess(apiResponse, MediaType.APPLICATION_JSON)); + @BeforeEach + void setup() { + config = new Config("https://defectdojo.example.com", "abc", 42); + underTest = new UserProfileService(config); + mockServer = MockRestServiceServer.createServer(underTest.getRestTemplate()); + } - var user = new User(0L, "GdqmXprK.j7R+OYE49SzL3mM2U6I0DyLRHnDg87i9It0AfP-kxvswW3qOI2i+31-@0", "string", "string"); - var userProfile = new UserProfile(user); - var expected = Arrays.asList(userProfile); - var actual = underTest.search(); + @Test + void testSearch() throws JsonProcessingException, URISyntaxException { + var url = config.getUrl() + "/api/v2/" + underTest.getUrlPath() + "/?offset=0&limit=100"; + mockServer.expect(requestTo(url)).andRespond(withSuccess(apiResponse, MediaType.APPLICATION_JSON)); - mockServer.verify(); - assertIterableEquals(expected, actual); - } + var user = new User(0L, "GdqmXprK.j7R+OYE49SzL3mM2U6I0DyLRHnDg87i9It0AfP-kxvswW3qOI2i+31-@0", "string", "string"); + var userProfile = new UserProfile(user); + var expected = Arrays.asList(userProfile); + var actual = underTest.search(); + + mockServer.verify(); + assertIterableEquals(expected, actual); + } }