diff --git a/pom.xml b/pom.xml index 998b18a3..135e1196 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ io.securecodebox defectdojo-client - 2.0.1-SNAPSHOT + 3.0.0-SNAPSHOT jar DefectDojo Client Java diff --git a/src/main/java/io/securecodebox/persistence/defectdojo/ScanType.java b/src/main/java/io/securecodebox/persistence/defectdojo/ScanType.java index 5f6dd6c1..0803fde1 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/ScanType.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/ScanType.java @@ -7,202 +7,202 @@ import lombok.Getter; public enum ScanType { - ACUNETIX_SCAN("Acunetix Scan"), - ACUNETIX360_SCAN("Acunetix360 Scan"), - ANCHORE_ENGINE_SCAN("Anchore Engine Scan"), - ANCHORE_ENTERPRISE_POLICY_CHECK("Anchore Enterprise Policy Check"), - ANCHORE_GRYPE("anchore_grype"), - ANCHORECTL_POLICIES_REPORT("AnchoreCTL Policies Report"), - ANCHORECTL_VULN_REPORT("AnchoreCTL Vuln Report"), - API_TEST("API Test"), - APP_SPIDER_SCAN("AppSpider Scan"), - AQUA_SCAN("Aqua Scan"), - ARACHNI_SCAN("Arachni Scan"), - AUDIT_JS_SCAN("AuditJS Scan"), - AWS_PROWLER_SCAN("AWS Prowler Scan"), - AWS_PROWLER_SCANNER("AWS Prowler Scanner"), - AWS_PROWLER_V3("AWS Prowler V3"), - AWS_SCOUT2_SCAN("AWS Scout2 Scan"), - AWS_SCOUT2_SCANNER("AWS Scout2 Scanner"), - AWS_SECURITY_FINDING_FORMAT_ASFF_SCAN("AWS Security Finding Format (ASFF) Scan"), - AWS_SECURITY_HUB_SCAN("AWS Security Hub Scan"), - AZURE_SECURITY_CENTER_RECOMMENDATIONS_SCAN("Azure Security Center Recommendations Scan"), - BANDIT_SCAN("Bandit Scan"), - BLACKDUCK_API("BlackDuck API"), - BLACKDUCK_COMPONENT_RISK("Blackduck Component Risk"), - BLACKDUCK_HUB_SCAN("Blackduck Hub Scan"), - BRAKEMAN_SCAN("Brakeman Scan"), - BUG_CROWD_SCAN("BugCrowd Scan"), - BUG_CROWD("BugCrowd "), - BUGCROWD_API_IMPORT("Bugcrowd API Import"), - BUNDLER_AUDIT_SCAN("Bundler-Audit Scan"), - BURP_ENTERPRISE_SCAN("Burp Enterprise Scan"), - BURP_GRAPHQL_API("Burp GraphQL API"), - BURP_REST_API("Burp REST API"), - BURP_SCAN("Burp Scan"), - BURP_SUITE_ENTERPRISE("Burp Suite Enterprise"), - CARGO_AUDIT_SCAN("CargoAudit Scan"), - CCVS_REPORT("CCVS Report"), - CHECKMARX_OSA("Checkmarx OSA"), - CHECKMARX_SCAN_DETAILED("Checkmarx Scan detailed"), - CHECKMARX_SCAN("Checkmarx Scan"), - CHECKOV_SCAN("Checkov Scan"), - CHOCTAW_HOG_SCAN("Choctaw Hog Scan"), - CLAIR_KLAR_SCAN("Clair Klar Scan"), - CLAIR_SCAN("Clair Scan"), - CLOUDSPLOIT_SCAN("Cloudsploit Scan"), - COBALT_IO_SCAN("Cobalt.io Scan"), - CODECHECKER_REPORT_NATIVE("Codechecker Report native"), - CONTRAST_SCAN("Contrast Scan"), - COVERITY_API("Coverity API"), - CRASHTEST_SECURITY_JSON_FILE("Crashtest Security JSON File"), - CRASHTEST_SECURITY_SCAN("Crashtest Security Scan"), - CRASHTEST_SECURITY_XML_FILE("Crashtest Security XML File"), - CRED_SCAN_SCAN("CredScan Scan"), - CYCLONE_DX_SCAN("CycloneDX Scan"), - DAWN_SCANNER_SCAN("DawnScanner Scan"), - DEPENDENCY_CHECK_SCAN("Dependency Check Scan"), - DEPENDENCY_TRACK_FINDING_PACKAGING_FORMAT_FPF_EXPORT("Dependency Track Finding Packaging Format (FPF) Export"), - DETECT_SECRETS_SCAN("Detect-secrets Scan"), - DOCKER_BENCH_SECURITY_SCAN("docker-bench-security Scan"), - DOCKLE_SCAN("Dockle Scan"), - DR_HEADER_JSON_IMPORTER("DrHeader JSON Importer"), - DSOP_SCAN("DSOP Scan"), - EDGESCAN_SCAN("Edgescan Scan"), - ES_LINT_SCAN("ESLint Scan"), - FORTIFY_SCAN("Fortify Scan"), - FORTIFY("Fortify"), - GENERIC_FINDINGS_IMPORT("Generic Findings Import"), - GGSHIELD_SCAN("Ggshield Scan"), - GIT_LAB_API_FUZZING_REPORT_SCAN("GitLab API Fuzzing Report Scan"), - GIT_LAB_CONTAINER_SCAN("GitLab Container Scan"), - GIT_LAB_DAST_REPORT("GitLab DAST Report"), - GIT_LAB_DEPENDENCY_SCANNING_REPORT("GitLab Dependency Scanning Report"), - GIT_LAB_SAST_REPORT("GitLab SAST Report"), - GIT_LAB_SECRET_DETECTION_REPORT("GitLab Secret Detection Report"), - GITHUB_VULNERABILITY_SCAN("Github Vulnerability Scan"), - GITLEAKS_SCAN("Gitleaks Scan"), - GOSEC_SCANNER("Gosec Scanner"), - GOVULNCHECK_SCANNER("Govulncheck Scanner"), - HACKER_ONE_CASES("HackerOne Cases"), - HADOLINT_DOCKERFILE_CHECK("Hadolint Dockerfile check"), - HARBOR_VULNERABILITY_SCAN("Harbor Vulnerability Scan"), - HCLAPPSCAN_XML("HCLAppScan XML"), - HORUSEC_SCAN("Horusec Scan"), - HUMBLE_JSON_IMPORTER("Humble Json Importer"), - HUSKY_CI_REPORT("HuskyCI Report"), - HYDRA_SCAN("Hydra Scan"), - IBM_APP_SCAN_DAST("IBM AppScan DAST"), - IMMUNIWEB_SCAN("Immuniweb Scan"), - INT_SIGHTS_REPORT("IntSights Report"), - J_FROG_XRAY_SCAN("JFrog Xray Scan"), - J_FROG_XRAY_UNIFIED_SCAN("JFrog Xray Unified Scan"), - JFROG_XRAY_API_SUMMARY_ARTIFACT_SCAN("JFrog Xray API Summary Artifact Scan"), - JFROG_XRAY_ON_DEMAND_BINARY_SCAN("JFrog Xray On Demand Binary Scan"), - KICS_SCAN("KICS Scan"), - KIUWAN_SCAN("Kiuwan Scan"), - KUBE_BENCH_SCAN("kube-bench Scan"), - KUBEHUNTER_SCAN("KubeHunter Scan"), - MANUAL_CODE_REVIEW("Manual Code Review"), - METERIAN_SCAN("Meterian Scan"), - MICROFOCUS_WEBINSPECT_SCAN("Microfocus Webinspect Scan"), - MOB_SF_SCAN("MobSF Scan"), - MOB_SF_SCANNER("MobSF Scanner"), - MOBSFSCAN_SCAN("Mobsfscan Scan"), - MOZILLA_OBSERVATORY_SCAN("Mozilla Observatory Scan"), - NESSUS_SCAN("Nessus Scan"), - NESSUS_WAS_SCAN("Nessus WAS Scan"), - NETSPARKER_SCAN("Netsparker Scan"), - NEUVECTOR_COMPLIANCE("NeuVector (compliance)"), - NEUVECTOR_REST("NeuVector (REST)"), - NEXPOSE_SCAN("Nexpose Scan"), - NIKTO_SCAN("Nikto Scan"), - NMAP_XML_SCAN("Nmap Scan"), - NODE_SECURITY_PLATFORM_SCAN("Node Security Platform Scan"), - NPM_AUDIT_SCAN("NPM Audit Scan"), - NUCLEI_SCAN("Nuclei Scan"), - OPEN_VAS_CSV("OpenVAS CSV"), - OPENSCAP_VULNERABILITY_SCAN("Openscap Vulnerability Scan"), - OPENVAS_XML("OpenVAS XML"), - ORT_EVALUATED_MODEL_IMPORTER("ORT evaluated model Importer"), - OSS_INDEX_DEVAUDIT_SCA_SCAN_IMPORTER("OssIndex Devaudit SCA Scan Importer"), - OUTPOST24_SCAN("Outpost24 Scan"), - PEN_TEST("Pen Test"), - PHP_SECURITY_AUDIT_V2("PHP Security Audit v2"), - PHP_SYMFONY_SECURITY_CHECK("PHP Symfony Security Check"), - PHP_SYMFONY_SECURITY_CHECKER("PHP Symfony Security Checker"), - PIP_AUDIT_SCAN("pip-audit Scan"), - PMD_SCAN("PMD Scan"), - POPEYE_SCAN("Popeye Scan"), - PWN_SAST("PWN SAST"), - QUALYS_INFRASTRUCTURE_SCAN_WEB_GUI_XML("Qualys Infrastructure Scan (WebGUI XML)"), - QUALYS_SCAN("Qualys Scan"), - QUALYS_WEBAPP_SCAN("Qualys Webapp Scan"), - RETIRE_JS_SCAN("Retire.js Scan"), - RISK_RECON_API_IMPORTER("Risk Recon API Importer"), - RUBOCOP_SCAN("Rubocop Scan"), - RUSTY_HOG_SCAN("Rusty Hog Scan"), - SAFETY_SCAN("Safety Scan"), - SARIF("SARIF"), - SCANTIST_SCAN("Scantist Scan"), - SCOUT_SUITE_MULTI_CLOUD_SECURITY_AUDITING_TOOL("ScoutSuite Multi-Cloud Security Auditing Tool"), - SCOUT_SUITE_SCAN("Scout Suite Scan"), - SECURITY_RESEARCH("Security Research"), - SEMGREP_JSON_REPORT("Semgrep JSON Report"), - SKF_SCAN("SKF Scan"), - SNYK_SCAN("Snyk Scan"), - SOLAR_APPSCREENER_SCAN("Solar Appscreener Scan"), - SONAR_QUBE_API_IMPORT("SonarQube API Import"), - SONAR_QUBE_SCAN_DETAILED("SonarQube Scan detailed"), - SONAR_QUBE_SCAN("SonarQube Scan"), - SONAR_QUBE("SonarQube"), - SONATYPE_APPLICATION_SCAN("Sonatype Application Scan"), - SPOT_BUGS_SCAN("SpotBugs Scan"), - SPOT_BUGS("SpotBugs"), - SSH_AUDIT_IMPORTER("SSH Audit Importer"), - SSL_LABS_SCAN("SSL Labs Scan"), - SSLSCAN("Sslscan"), - SSLYZE_JSON_SCAN("SSLyze Scan (JSON)"), - SSLYZE_SCAN("Sslyze Scan"), - STACKHAWK_HAWKSCAN("StackHawk HawkScan"), - STATIC_CHECK("Static Check"), - SYSDIG_VULNERABILITY_REPORT_PIPELINE_REGISTRY_RUNTIME_CSV("Sysdig Vulnerability Report - Pipeline, Registry and Runtime (CSV)"), - TALISMAN_SCAN("Talisman Scan"), - TENABLE_SCAN("Tenable Scan"), - TERRASCAN_SCAN("Terrascan Scan"), - TESTSSL_SCAN("Testssl Scan"), - TF_SEC_SCAN("TFSec Scan"), - THREAGILE_RISKS_REPORT("Threagile risks report"), - THREAT_MODELING("Threat Modeling"), - TRIVY_OPERATOR_SCAN("Trivy Operator Scan"), - TRIVY_SCAN("Trivy Scan"), - TRUFFLEHOG_SCAN("Trufflehog Scan"), - TRUFFLEHOG("Trufflehog"), - TRUFFLEHOG3_SCAN("Trufflehog3 Scan"), - TRUSTWAVE_FUSION_API_SCAN("Trustwave Fusion API Scan"), - TRUSTWAVE_SCAN_CSV("Trustwave Scan (CSV)"), - TRUSTWAVE("Trustwave"), - TWISTLOCK_IMAGE_SCAN("Twistlock Image Scan"), - VCG_SCAN("VCG Scan"), - VERACODE_SCAN("Veracode Scan"), - VERACODE_SOURCECLEAR_SCAN("Veracode SourceClear Scan"), - VULNERS("Vulners"), - W_FUZZ_JSON_REPORT("WFuzz JSON report"), - WAPITI_SCAN("Wapiti Scan"), - WAZUH("Wazuh"), - WEB_APPLICATION_TEST("Web Application Test"), - WHISPERS_SCAN("Whispers Scan"), - WHITE_HAT_SENTINEL("WhiteHat Sentinel"), - WHITESOURCE_SCAN("Whitesource Scan"), - WPSCAN("Wpscan"), - XANITIZER_SCAN("Xanitizer Scan"), - YARN_AUDIT_SCAN("Yarn Audit Scan"), - ZAP_SCAN("ZAP Scan"); + ACUNETIX_SCAN("Acunetix Scan"), + ACUNETIX360_SCAN("Acunetix360 Scan"), + ANCHORE_ENGINE_SCAN("Anchore Engine Scan"), + ANCHORE_ENTERPRISE_POLICY_CHECK("Anchore Enterprise Policy Check"), + ANCHORE_GRYPE("anchore_grype"), + ANCHORECTL_POLICIES_REPORT("AnchoreCTL Policies Report"), + ANCHORECTL_VULN_REPORT("AnchoreCTL Vuln Report"), + API_TEST("API Test"), + APP_SPIDER_SCAN("AppSpider Scan"), + AQUA_SCAN("Aqua Scan"), + ARACHNI_SCAN("Arachni Scan"), + AUDIT_JS_SCAN("AuditJS Scan"), + AWS_PROWLER_SCAN("AWS Prowler Scan"), + AWS_PROWLER_SCANNER("AWS Prowler Scanner"), + AWS_PROWLER_V3("AWS Prowler V3"), + AWS_SCOUT2_SCAN("AWS Scout2 Scan"), + AWS_SCOUT2_SCANNER("AWS Scout2 Scanner"), + AWS_SECURITY_FINDING_FORMAT_ASFF_SCAN("AWS Security Finding Format (ASFF) Scan"), + AWS_SECURITY_HUB_SCAN("AWS Security Hub Scan"), + AZURE_SECURITY_CENTER_RECOMMENDATIONS_SCAN("Azure Security Center Recommendations Scan"), + BANDIT_SCAN("Bandit Scan"), + BLACKDUCK_API("BlackDuck API"), + BLACKDUCK_COMPONENT_RISK("Blackduck Component Risk"), + BLACKDUCK_HUB_SCAN("Blackduck Hub Scan"), + BRAKEMAN_SCAN("Brakeman Scan"), + BUG_CROWD_SCAN("BugCrowd Scan"), + BUG_CROWD("BugCrowd "), + BUGCROWD_API_IMPORT("Bugcrowd API Import"), + BUNDLER_AUDIT_SCAN("Bundler-Audit Scan"), + BURP_ENTERPRISE_SCAN("Burp Enterprise Scan"), + BURP_GRAPHQL_API("Burp GraphQL API"), + BURP_REST_API("Burp REST API"), + BURP_SCAN("Burp Scan"), + BURP_SUITE_ENTERPRISE("Burp Suite Enterprise"), + CARGO_AUDIT_SCAN("CargoAudit Scan"), + CCVS_REPORT("CCVS Report"), + CHECKMARX_OSA("Checkmarx OSA"), + CHECKMARX_SCAN_DETAILED("Checkmarx Scan detailed"), + CHECKMARX_SCAN("Checkmarx Scan"), + CHECKOV_SCAN("Checkov Scan"), + CHOCTAW_HOG_SCAN("Choctaw Hog Scan"), + CLAIR_KLAR_SCAN("Clair Klar Scan"), + CLAIR_SCAN("Clair Scan"), + CLOUDSPLOIT_SCAN("Cloudsploit Scan"), + COBALT_IO_SCAN("Cobalt.io Scan"), + CODECHECKER_REPORT_NATIVE("Codechecker Report native"), + CONTRAST_SCAN("Contrast Scan"), + COVERITY_API("Coverity API"), + CRASHTEST_SECURITY_JSON_FILE("Crashtest Security JSON File"), + CRASHTEST_SECURITY_SCAN("Crashtest Security Scan"), + CRASHTEST_SECURITY_XML_FILE("Crashtest Security XML File"), + CRED_SCAN_SCAN("CredScan Scan"), + CYCLONE_DX_SCAN("CycloneDX Scan"), + DAWN_SCANNER_SCAN("DawnScanner Scan"), + DEPENDENCY_CHECK_SCAN("Dependency Check Scan"), + DEPENDENCY_TRACK_FINDING_PACKAGING_FORMAT_FPF_EXPORT("Dependency Track Finding Packaging Format (FPF) Export"), + DETECT_SECRETS_SCAN("Detect-secrets Scan"), + DOCKER_BENCH_SECURITY_SCAN("docker-bench-security Scan"), + DOCKLE_SCAN("Dockle Scan"), + DR_HEADER_JSON_IMPORTER("DrHeader JSON Importer"), + DSOP_SCAN("DSOP Scan"), + EDGESCAN_SCAN("Edgescan Scan"), + ES_LINT_SCAN("ESLint Scan"), + FORTIFY_SCAN("Fortify Scan"), + FORTIFY("Fortify"), + GENERIC_FINDINGS_IMPORT("Generic Findings Import"), + GGSHIELD_SCAN("Ggshield Scan"), + GIT_LAB_API_FUZZING_REPORT_SCAN("GitLab API Fuzzing Report Scan"), + GIT_LAB_CONTAINER_SCAN("GitLab Container Scan"), + GIT_LAB_DAST_REPORT("GitLab DAST Report"), + GIT_LAB_DEPENDENCY_SCANNING_REPORT("GitLab Dependency Scanning Report"), + GIT_LAB_SAST_REPORT("GitLab SAST Report"), + GIT_LAB_SECRET_DETECTION_REPORT("GitLab Secret Detection Report"), + GITHUB_VULNERABILITY_SCAN("Github Vulnerability Scan"), + GITLEAKS_SCAN("Gitleaks Scan"), + GOSEC_SCANNER("Gosec Scanner"), + GOVULNCHECK_SCANNER("Govulncheck Scanner"), + HACKER_ONE_CASES("HackerOne Cases"), + HADOLINT_DOCKERFILE_CHECK("Hadolint Dockerfile check"), + HARBOR_VULNERABILITY_SCAN("Harbor Vulnerability Scan"), + HCLAPPSCAN_XML("HCLAppScan XML"), + HORUSEC_SCAN("Horusec Scan"), + HUMBLE_JSON_IMPORTER("Humble Json Importer"), + HUSKY_CI_REPORT("HuskyCI Report"), + HYDRA_SCAN("Hydra Scan"), + IBM_APP_SCAN_DAST("IBM AppScan DAST"), + IMMUNIWEB_SCAN("Immuniweb Scan"), + INT_SIGHTS_REPORT("IntSights Report"), + J_FROG_XRAY_SCAN("JFrog Xray Scan"), + J_FROG_XRAY_UNIFIED_SCAN("JFrog Xray Unified Scan"), + JFROG_XRAY_API_SUMMARY_ARTIFACT_SCAN("JFrog Xray API Summary Artifact Scan"), + JFROG_XRAY_ON_DEMAND_BINARY_SCAN("JFrog Xray On Demand Binary Scan"), + KICS_SCAN("KICS Scan"), + KIUWAN_SCAN("Kiuwan Scan"), + KUBE_BENCH_SCAN("kube-bench Scan"), + KUBEHUNTER_SCAN("KubeHunter Scan"), + MANUAL_CODE_REVIEW("Manual Code Review"), + METERIAN_SCAN("Meterian Scan"), + MICROFOCUS_WEBINSPECT_SCAN("Microfocus Webinspect Scan"), + MOB_SF_SCAN("MobSF Scan"), + MOB_SF_SCANNER("MobSF Scanner"), + MOBSFSCAN_SCAN("Mobsfscan Scan"), + MOZILLA_OBSERVATORY_SCAN("Mozilla Observatory Scan"), + NESSUS_SCAN("Nessus Scan"), + NESSUS_WAS_SCAN("Nessus WAS Scan"), + NETSPARKER_SCAN("Netsparker Scan"), + NEUVECTOR_COMPLIANCE("NeuVector (compliance)"), + NEUVECTOR_REST("NeuVector (REST)"), + NEXPOSE_SCAN("Nexpose Scan"), + NIKTO_SCAN("Nikto Scan"), + NMAP_XML_SCAN("Nmap Scan"), + NODE_SECURITY_PLATFORM_SCAN("Node Security Platform Scan"), + NPM_AUDIT_SCAN("NPM Audit Scan"), + NUCLEI_SCAN("Nuclei Scan"), + OPEN_VAS_CSV("OpenVAS CSV"), + OPENSCAP_VULNERABILITY_SCAN("Openscap Vulnerability Scan"), + OPENVAS_XML("OpenVAS XML"), + ORT_EVALUATED_MODEL_IMPORTER("ORT evaluated model Importer"), + OSS_INDEX_DEVAUDIT_SCA_SCAN_IMPORTER("OssIndex Devaudit SCA Scan Importer"), + OUTPOST24_SCAN("Outpost24 Scan"), + PEN_TEST("Pen Test"), + PHP_SECURITY_AUDIT_V2("PHP Security Audit v2"), + PHP_SYMFONY_SECURITY_CHECK("PHP Symfony Security Check"), + PHP_SYMFONY_SECURITY_CHECKER("PHP Symfony Security Checker"), + PIP_AUDIT_SCAN("pip-audit Scan"), + PMD_SCAN("PMD Scan"), + POPEYE_SCAN("Popeye Scan"), + PWN_SAST("PWN SAST"), + QUALYS_INFRASTRUCTURE_SCAN_WEB_GUI_XML("Qualys Infrastructure Scan (WebGUI XML)"), + QUALYS_SCAN("Qualys Scan"), + QUALYS_WEBAPP_SCAN("Qualys Webapp Scan"), + RETIRE_JS_SCAN("Retire.js Scan"), + RISK_RECON_API_IMPORTER("Risk Recon API Importer"), + RUBOCOP_SCAN("Rubocop Scan"), + RUSTY_HOG_SCAN("Rusty Hog Scan"), + SAFETY_SCAN("Safety Scan"), + SARIF("SARIF"), + SCANTIST_SCAN("Scantist Scan"), + SCOUT_SUITE_MULTI_CLOUD_SECURITY_AUDITING_TOOL("ScoutSuite Multi-Cloud Security Auditing Tool"), + SCOUT_SUITE_SCAN("Scout Suite Scan"), + SECURITY_RESEARCH("Security Research"), + SEMGREP_JSON_REPORT("Semgrep JSON Report"), + SKF_SCAN("SKF Scan"), + SNYK_SCAN("Snyk Scan"), + SOLAR_APPSCREENER_SCAN("Solar Appscreener Scan"), + SONAR_QUBE_API_IMPORT("SonarQube API Import"), + SONAR_QUBE_SCAN_DETAILED("SonarQube Scan detailed"), + SONAR_QUBE_SCAN("SonarQube Scan"), + SONAR_QUBE("SonarQube"), + SONATYPE_APPLICATION_SCAN("Sonatype Application Scan"), + SPOT_BUGS_SCAN("SpotBugs Scan"), + SPOT_BUGS("SpotBugs"), + SSH_AUDIT_IMPORTER("SSH Audit Importer"), + SSL_LABS_SCAN("SSL Labs Scan"), + SSLSCAN("Sslscan"), + SSLYZE_JSON_SCAN("SSLyze Scan (JSON)"), + SSLYZE_SCAN("Sslyze Scan"), + STACKHAWK_HAWKSCAN("StackHawk HawkScan"), + STATIC_CHECK("Static Check"), + SYSDIG_VULNERABILITY_REPORT_PIPELINE_REGISTRY_RUNTIME_CSV("Sysdig Vulnerability Report - Pipeline, Registry and Runtime (CSV)"), + TALISMAN_SCAN("Talisman Scan"), + TENABLE_SCAN("Tenable Scan"), + TERRASCAN_SCAN("Terrascan Scan"), + TESTSSL_SCAN("Testssl Scan"), + TF_SEC_SCAN("TFSec Scan"), + THREAGILE_RISKS_REPORT("Threagile risks report"), + THREAT_MODELING("Threat Modeling"), + TRIVY_OPERATOR_SCAN("Trivy Operator Scan"), + TRIVY_SCAN("Trivy Scan"), + TRUFFLEHOG_SCAN("Trufflehog Scan"), + TRUFFLEHOG("Trufflehog"), + TRUFFLEHOG3_SCAN("Trufflehog3 Scan"), + TRUSTWAVE_FUSION_API_SCAN("Trustwave Fusion API Scan"), + TRUSTWAVE_SCAN_CSV("Trustwave Scan (CSV)"), + TRUSTWAVE("Trustwave"), + TWISTLOCK_IMAGE_SCAN("Twistlock Image Scan"), + VCG_SCAN("VCG Scan"), + VERACODE_SCAN("Veracode Scan"), + VERACODE_SOURCECLEAR_SCAN("Veracode SourceClear Scan"), + VULNERS("Vulners"), + W_FUZZ_JSON_REPORT("WFuzz JSON report"), + WAPITI_SCAN("Wapiti Scan"), + WAZUH("Wazuh"), + WEB_APPLICATION_TEST("Web Application Test"), + WHISPERS_SCAN("Whispers Scan"), + WHITE_HAT_SENTINEL("WhiteHat Sentinel"), + WHITESOURCE_SCAN("Whitesource Scan"), + WPSCAN("Wpscan"), + XANITIZER_SCAN("Xanitizer Scan"), + YARN_AUDIT_SCAN("Yarn Audit Scan"), + ZAP_SCAN("ZAP Scan"); - @Getter - private final String testType; + @Getter + private final String testType; - ScanType(String testType) { - this.testType = testType; - } + ScanType(String testType) { + this.testType = testType; + } } 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 2d840d5c..8f1b20dc 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/config/Config.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/config/Config.java @@ -5,7 +5,10 @@ package io.securecodebox.persistence.defectdojo.config; import io.securecodebox.persistence.defectdojo.exception.ConfigException; -import lombok.*; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.NonNull; +import lombok.ToString; /** * Configures the DefectDojo client @@ -14,133 +17,133 @@ @ToString @EqualsAndHashCode public final class Config { - /** - * Default for {@link #maxPageCountForGets} - */ - static final int DEFAULT_MAX_PAGE_COUNT_FOR_GETS = 100; - /** - * Null pattern object. - */ - public static final Config NULL = new Config("", "", DEFAULT_MAX_PAGE_COUNT_FOR_GETS); - - /** - * URL of the host which serves the DefectDojo API. - *

- * It is only allowed to configure the base URL (e.g. {@literal "https://defectdojo.securecodebox.io/"} without - * any path. The path to the concrete API endpoints are maintained by this client library itself. - *

- */ - @NonNull - private final String url; - - /** - * API key to authorize against the DefectDojo API. - */ - @NonNull - private final String apiKey; - - /** - * How many pages of objects are fetched from the DefectDojo API - *

- * This setting is to avoid out of memory scenarios. - *

- *

- * Defaults to {@link #DEFAULT_MAX_PAGE_COUNT_FOR_GETS}. - *

- */ - private final int maxPageCountForGets; - - /** - * Convenience constructor which sets {@link #DEFAULT_MAX_PAGE_COUNT_FOR_GETS} - * - * @param url not {@code null} - * @param apiKey not {@code null} - */ - public Config(final @NonNull String url, final @NonNull String apiKey) { - this(url, apiKey, DEFAULT_MAX_PAGE_COUNT_FOR_GETS); + /** + * Default for {@link #maxPageCountForGets} + */ + static final int DEFAULT_MAX_PAGE_COUNT_FOR_GETS = 100; + /** + * Null pattern object. + */ + public static final Config NULL = new Config("", "", DEFAULT_MAX_PAGE_COUNT_FOR_GETS); + + /** + * URL of the host which serves the DefectDojo API. + *

+ * It is only allowed to configure the base URL (e.g. {@literal "https://defectdojo.securecodebox.io/"} without + * any path. The path to the concrete API endpoints are maintained by this client library itself. + *

+ */ + @NonNull + private final String url; + + /** + * API key to authorize against the DefectDojo API. + */ + @NonNull + private final String apiKey; + + /** + * How many pages of objects are fetched from the DefectDojo API + *

+ * This setting is to avoid out of memory scenarios. + *

+ *

+ * Defaults to {@link #DEFAULT_MAX_PAGE_COUNT_FOR_GETS}. + *

+ */ + private final int maxPageCountForGets; + + /** + * Convenience constructor which sets {@link #DEFAULT_MAX_PAGE_COUNT_FOR_GETS} + * + * @param url not {@code null} + * @param apiKey not {@code null} + */ + public Config(final @NonNull String url, final @NonNull String apiKey) { + this(url, apiKey, DEFAULT_MAX_PAGE_COUNT_FOR_GETS); + } + + /** + * Dedicated constructor + * + * @param url not {@code null} + * @param apiKey not {@code null} + * @param maxPageCountForGets not less than 1 + */ + public Config(final @NonNull String url, final @NonNull String apiKey, final int maxPageCountForGets) { + super(); + this.url = url; + this.apiKey = apiKey; + this.maxPageCountForGets = validateIsGreaterZero(maxPageCountForGets, "maxPageCountForGets"); + } + + private static int validateIsGreaterZero(final int number, final String name) { + if (number < 1) { + throw new IllegalArgumentException(String.format("%s must be greater than 0!", name)); } - /** - * Dedicated constructor - * - * @param url not {@code null} - * @param apiKey not {@code null} - * @param maxPageCountForGets not less than 1 - */ - public Config(final @NonNull String url, final @NonNull String apiKey, final int maxPageCountForGets) { - super(); - this.url = url; - this.apiKey = apiKey; - this.maxPageCountForGets = validateIsGreaterZero(maxPageCountForGets, "maxPageCountForGets"); - } - - private static int validateIsGreaterZero(final int number, final String name) { - if (number < 1) { - throw new IllegalArgumentException(String.format("%s must be greater than 0!", name)); - } - - return number; + return number; + } + + /** + * Creates config from environment variables + * + * @return never {@code null} + */ + public static Config fromEnv() { + final var url = findRequiredEnvVar(EnvVars.DEFECTDOJO_URL); + final var apiKey = findRequiredEnvVar(EnvVars.DEFECTDOJO_APIKEY); + final int maxPageCountForGets; + + if (hasEnvVar(EnvVars.DEFECTDOJO_MAX_PAGE_COUNT_FOR_GETS)) { + try { + maxPageCountForGets = Integer.parseInt(findEnvVar(EnvVars.DEFECTDOJO_MAX_PAGE_COUNT_FOR_GETS)); + } catch (final NumberFormatException e) { + throw new ConfigException(String.format("Given value for environment variable '%s' is not a valid number! Given was '%s'.", EnvVars.DEFECTDOJO_MAX_PAGE_COUNT_FOR_GETS.literal, findEnvVar(EnvVars.DEFECTDOJO_MAX_PAGE_COUNT_FOR_GETS)), + e); + } + } else { + maxPageCountForGets = DEFAULT_MAX_PAGE_COUNT_FOR_GETS; } - /** - * Creates config from environment variables - * - * @return never {@code null} - */ - public static Config fromEnv() { - final var url = findRequiredEnvVar(EnvVars.DEFECTDOJO_URL); - final var apiKey = findRequiredEnvVar(EnvVars.DEFECTDOJO_APIKEY); - final int maxPageCountForGets; - - if (hasEnvVar(EnvVars.DEFECTDOJO_MAX_PAGE_COUNT_FOR_GETS)) { - try { - maxPageCountForGets = Integer.parseInt(findEnvVar(EnvVars.DEFECTDOJO_MAX_PAGE_COUNT_FOR_GETS)); - } catch (final NumberFormatException e) { - throw new ConfigException(String.format("Given value for environment variable '%s' is not a valid number! Given was '%s'.", EnvVars.DEFECTDOJO_MAX_PAGE_COUNT_FOR_GETS.literal, findEnvVar(EnvVars.DEFECTDOJO_MAX_PAGE_COUNT_FOR_GETS)), - e); - } - } else { - maxPageCountForGets = DEFAULT_MAX_PAGE_COUNT_FOR_GETS; - } - - return new Config(url, apiKey, maxPageCountForGets); - } + return new Config(url, apiKey, maxPageCountForGets); + } - private static boolean hasEnvVar(final @NonNull EnvVars name) { - return findEnvVar(name) != null; - } + private static boolean hasEnvVar(final @NonNull EnvVars name) { + return findEnvVar(name) != null; + } - private static String findEnvVar(final @NonNull EnvVars name) { - return System.getenv(name.literal); - } + private static String findEnvVar(final @NonNull EnvVars name) { + return System.getenv(name.literal); + } - private static String findRequiredEnvVar(final @NonNull EnvVars name) { - final var envVar = System.getenv(name.literal); + private static String findRequiredEnvVar(final @NonNull EnvVars name) { + final var envVar = System.getenv(name.literal); - if (envVar == null) { - throw new ConfigException(String.format("Missing environment variable '%s'!", name.literal)); - } - return envVar; + if (envVar == null) { + throw new ConfigException(String.format("Missing environment variable '%s'!", name.literal)); } - + return envVar; + } + + /** + * Enumerates the available environment variables to configure the client + */ + public enum EnvVars { + DEFECTDOJO_URL("DEFECTDOJO_URL"), + DEFECTDOJO_APIKEY("DEFECTDOJO_APIKEY"), + DEFECTDOJO_MAX_PAGE_COUNT_FOR_GETS("DEFECTDOJO_MAX_PAGE_COUNT_FOR_GETS"); /** - * Enumerates the available environment variables to configure the client + * Literal name of configuration environment name + *

+ * We use an own value to hold the actual value, so that refactoring the enum name does + * not break the published API of env var names. + *

*/ - public enum EnvVars { - DEFECTDOJO_URL("DEFECTDOJO_URL"), - DEFECTDOJO_APIKEY("DEFECTDOJO_APIKEY"), - DEFECTDOJO_MAX_PAGE_COUNT_FOR_GETS("DEFECTDOJO_MAX_PAGE_COUNT_FOR_GETS"); - /** - * Literal name of configuration environment name - *

- * We use an own value to hold the actual value, so that refactoring the enum name does - * not break the published API of env var names. - *

- */ - private final String literal; - - EnvVars(final String literal) { - this.literal = literal; - } + private final String literal; + + EnvVars(final String literal) { + this.literal = literal; } + } } diff --git a/src/main/java/io/securecodebox/persistence/defectdojo/exception/ConfigException.java b/src/main/java/io/securecodebox/persistence/defectdojo/exception/ConfigException.java index 67cd6366..38b159ba 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/exception/ConfigException.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/exception/ConfigException.java @@ -9,10 +9,11 @@ * Indicates a missing {@link io.securecodebox.persistence.defectdojo.config.Config config property} */ public final class ConfigException extends RuntimeException { - public ConfigException(final String message) { - super(message); - } - public ConfigException(final String message, final Throwable cause) { - super(message, cause); - } + public ConfigException(final String message) { + super(message); + } + + public ConfigException(final String message, final Throwable cause) { + super(message, cause); + } } diff --git a/src/main/java/io/securecodebox/persistence/defectdojo/exception/PersistenceException.java b/src/main/java/io/securecodebox/persistence/defectdojo/exception/PersistenceException.java index 96c80e5e..b480c094 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/exception/PersistenceException.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/exception/PersistenceException.java @@ -5,11 +5,11 @@ package io.securecodebox.persistence.defectdojo.exception; public final class PersistenceException extends RuntimeException { - public PersistenceException(String message) { - super(message); - } + public PersistenceException(String message) { + super(message); + } - public PersistenceException(String message, Throwable cause) { - super(message, cause); - } + public PersistenceException(String message, Throwable cause) { + super(message, cause); + } } 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 34338634..7f5a25f9 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/http/Foo.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/http/Foo.java @@ -25,71 +25,71 @@ * Placeholder to move duplicated code, will be named better later */ public final class Foo { - private final Config config; - private final ProxyConfig proxyConfig; - - public Foo(@NonNull final Config config, @NonNull final ProxyConfig proxyConfig) { - super(); - this.config = config; - this.proxyConfig = proxyConfig; + private final Config config; + private final ProxyConfig proxyConfig; + + public Foo(@NonNull final Config config, @NonNull final ProxyConfig proxyConfig) { + super(); + this.config = config; + this.proxyConfig = proxyConfig; + } + + /** + * This method generates appropriate authorization headers + * + * @return never {@code null} + */ + public HttpHeaders generateAuthorizationHeaders() { + HttpHeaders headers = new HttpHeaders(); + headers.set(HttpHeaders.AUTHORIZATION, "Token " + this.config.getApiKey()); + + if (proxyConfig.isComplete()) { + // FIXME: System.out logging is a real bad code smell. Standard loging should be used. + System.out.println("Setting Proxy Auth Header..."); + headers.set(HttpHeaders.PROXY_AUTHORIZATION, "Basic " + encodeProxyCredentials(proxyConfig)); } - /** - * This method generates appropriate authorization headers - * - * @return never {@code null} - */ - public HttpHeaders generateAuthorizationHeaders() { - HttpHeaders headers = new HttpHeaders(); - headers.set(HttpHeaders.AUTHORIZATION, "Token " + this.config.getApiKey()); - - if (proxyConfig.isComplete()) { - // FIXME: System.out logging is a real bad code smell. Standard loging should be used. - System.out.println("Setting Proxy Auth Header..."); - headers.set(HttpHeaders.PROXY_AUTHORIZATION, "Basic " + encodeProxyCredentials(proxyConfig)); - } - - return headers; - } + return headers; + } - static String encodeProxyCredentials(@NonNull final ProxyConfig cfg) { - final var credential = String.format("%s:%s", cfg.getUser(), cfg.getPassword()); - return Base64.getEncoder().encodeToString(credential.getBytes(StandardCharsets.UTF_8)); - } + static String encodeProxyCredentials(@NonNull final ProxyConfig cfg) { + final var credential = String.format("%s:%s", cfg.getUser(), cfg.getPassword()); + return Base64.getEncoder().encodeToString(credential.getBytes(StandardCharsets.UTF_8)); + } - public RestTemplate createRestTemplate() { - if (proxyConfig.isComplete()) { - // Configuring Proxy Authentication explicitly as it isn't done by default for spring rest templates :( - final var builder = HttpClientBuilder.create() - .useSystemProperties() - .setProxy(createHttpHost()) - .setDefaultCredentialsProvider(createCredentialsProvider()) - .setProxyAuthenticationStrategy(new ProxyAuthenticationStrategy()); + public RestTemplate createRestTemplate() { + if (proxyConfig.isComplete()) { + // Configuring Proxy Authentication explicitly as it isn't done by default for spring rest templates :( + final var builder = HttpClientBuilder.create() + .useSystemProperties() + .setProxy(createHttpHost()) + .setDefaultCredentialsProvider(createCredentialsProvider()) + .setProxyAuthenticationStrategy(new ProxyAuthenticationStrategy()); - final var factory = new HttpComponentsClientHttpRequestFactory(); - factory.setHttpClient(builder.build()); + final var factory = new HttpComponentsClientHttpRequestFactory(); + factory.setHttpClient(builder.build()); - return new RestTemplate(factory); - } - - return new RestTemplate(); + return new RestTemplate(factory); } - CredentialsProvider createCredentialsProvider() { - final var provider = new BasicCredentialsProvider(); - provider.setCredentials(createAuthScope(), createCredentials()); - return provider; - } + return new RestTemplate(); + } - AuthScope createAuthScope() { - return new AuthScope(proxyConfig.getHost(), proxyConfig.getPort()); - } + CredentialsProvider createCredentialsProvider() { + final var provider = new BasicCredentialsProvider(); + provider.setCredentials(createAuthScope(), createCredentials()); + return provider; + } - Credentials createCredentials() { - return new UsernamePasswordCredentials(proxyConfig.getUser(), proxyConfig.getPassword()); - } + AuthScope createAuthScope() { + return new AuthScope(proxyConfig.getHost(), proxyConfig.getPort()); + } - HttpHost createHttpHost() { - return new HttpHost(proxyConfig.getHost(), proxyConfig.getPort()); - } + Credentials createCredentials() { + return new UsernamePasswordCredentials(proxyConfig.getUser(), proxyConfig.getPassword()); + } + + HttpHost createHttpHost() { + return new HttpHost(proxyConfig.getHost(), proxyConfig.getPort()); + } } diff --git a/src/main/java/io/securecodebox/persistence/defectdojo/http/MissingProxyConfigValue.java b/src/main/java/io/securecodebox/persistence/defectdojo/http/MissingProxyConfigValue.java index 2324bc69..b9dbdbf4 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/http/MissingProxyConfigValue.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/http/MissingProxyConfigValue.java @@ -10,7 +10,7 @@ * This exception indicates a missing proxy config value */ public final class MissingProxyConfigValue extends RuntimeException { - MissingProxyConfigValue(@NonNull final ProxyConfigNames name) { - super(String.format("Expected system property '%s' not set!", name.getLiterat())); - } + MissingProxyConfigValue(@NonNull final ProxyConfigNames name) { + super(String.format("Expected system property '%s' not set!", name.getLiterat())); + } } diff --git a/src/main/java/io/securecodebox/persistence/defectdojo/http/ProxyConfig.java b/src/main/java/io/securecodebox/persistence/defectdojo/http/ProxyConfig.java index 9729f675..8a13e1ac 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/http/ProxyConfig.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/http/ProxyConfig.java @@ -18,71 +18,71 @@ @Value @Builder public class ProxyConfig { - /** - * Null pattern object. - */ - public static final ProxyConfig NULL = ProxyConfig.builder().build(); - private static final String DEFAULT_STRING = ""; - private static final int DEFAULT_INT = 0; + /** + * Null pattern object. + */ + public static final ProxyConfig NULL = ProxyConfig.builder().build(); + private static final String DEFAULT_STRING = ""; + private static final int DEFAULT_INT = 0; - /** - * Username to authenticate on a proxy. - *

- * Defaults to empty string. - *

- */ - @Builder.Default - String user = DEFAULT_STRING; + /** + * Username to authenticate on a proxy. + *

+ * Defaults to empty string. + *

+ */ + @Builder.Default + String user = DEFAULT_STRING; - /** - * Password to authenticate on a proxy. - *

- * Defaults to empty string. - *

- */ - @Builder.Default - String password = DEFAULT_STRING; + /** + * Password to authenticate on a proxy. + *

+ * Defaults to empty string. + *

+ */ + @Builder.Default + String password = DEFAULT_STRING; - /** - * Host name of the proxy. - *

- * Defaults to empty string. - *

- */ - @Builder.Default - String host = DEFAULT_STRING; + /** + * Host name of the proxy. + *

+ * Defaults to empty string. + *

+ */ + @Builder.Default + String host = DEFAULT_STRING; - /** - * Port of the proxy. - *

- * Defaults to 0 (zero). - *

- */ - @Builder.Default - int port = DEFAULT_INT; + /** + * Port of the proxy. + *

+ * Defaults to 0 (zero). + *

+ */ + @Builder.Default + int port = DEFAULT_INT; - /** - * configuration is considered complete if all values are not default values - * - * @return {@code true} if all values are set else {@code false} - */ - public boolean isComplete() { - if (getUser().equals(DEFAULT_STRING)) { - return false; - } - - if (getPassword().equals(DEFAULT_STRING)) { - return false; - } + /** + * configuration is considered complete if all values are not default values + * + * @return {@code true} if all values are set else {@code false} + */ + public boolean isComplete() { + if (getUser().equals(DEFAULT_STRING)) { + return false; + } - if (getHost().equals(DEFAULT_STRING)) { - return false; - } + if (getPassword().equals(DEFAULT_STRING)) { + return false; + } - if (getPort() == DEFAULT_INT) { - return false; - } + if (getHost().equals(DEFAULT_STRING)) { + return false; + } - return true; + if (getPort() == DEFAULT_INT) { + return false; } + + return true; + } } diff --git a/src/main/java/io/securecodebox/persistence/defectdojo/http/ProxyConfigFactory.java b/src/main/java/io/securecodebox/persistence/defectdojo/http/ProxyConfigFactory.java index ce2a12d6..7cf8dcfc 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/http/ProxyConfigFactory.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/http/ProxyConfigFactory.java @@ -18,75 +18,75 @@ *

*/ public final class ProxyConfigFactory { - static final ProxyConfig DEFAULT_CONFIG = ProxyConfig.NULL; - private final SystemPropertyFinder properties = new SystemPropertyFinder(); - - /** - * Creates a configuration based on {@link ProxyConfigNames environment variables} - *

- * We assume a complete proxy configuration only if {@link ProxyConfigNames#HTTP_PROXY_USER user} and - * {@link ProxyConfigNames#HTTP_PROXY_PASSWORD password} is configured. Unless an - * {@link #DEFAULT_CONFIG} configuration will be returned. - *

- *

- * Throws {@link MissingProxyConfigValue}, if not all configuration values are present. - *

- * - * @return never {@code null} - */ - public ProxyConfig create() { - if (shouldCreateFromProperties()) { - return createFromProperties(); - } - - return DEFAULT_CONFIG; + static final ProxyConfig DEFAULT_CONFIG = ProxyConfig.NULL; + private final SystemPropertyFinder properties = new SystemPropertyFinder(); + + /** + * Creates a configuration based on {@link ProxyConfigNames environment variables} + *

+ * We assume a complete proxy configuration only if {@link ProxyConfigNames#HTTP_PROXY_USER user} and + * {@link ProxyConfigNames#HTTP_PROXY_PASSWORD password} is configured. Unless an + * {@link #DEFAULT_CONFIG} configuration will be returned. + *

+ *

+ * Throws {@link MissingProxyConfigValue}, if not all configuration values are present. + *

+ * + * @return never {@code null} + */ + public ProxyConfig create() { + if (shouldCreateFromProperties()) { + return createFromProperties(); } - private boolean shouldCreateFromProperties() { - return properties.hasProperty(ProxyConfigNames.HTTP_PROXY_USER) && - properties.hasProperty(ProxyConfigNames.HTTP_PROXY_PASSWORD); - } + return DEFAULT_CONFIG; + } - private ProxyConfig createFromProperties() { - final var builder = ProxyConfig.builder() - .user(properties.getProperty(ProxyConfigNames.HTTP_PROXY_USER)) - .password(properties.getProperty(ProxyConfigNames.HTTP_PROXY_PASSWORD)); + private boolean shouldCreateFromProperties() { + return properties.hasProperty(ProxyConfigNames.HTTP_PROXY_USER) && + properties.hasProperty(ProxyConfigNames.HTTP_PROXY_PASSWORD); + } - if (properties.notHasProperty(ProxyConfigNames.HTTP_PROXY_HOST)) { - throw new MissingProxyConfigValue(ProxyConfigNames.HTTP_PROXY_HOST); - } + private ProxyConfig createFromProperties() { + final var builder = ProxyConfig.builder() + .user(properties.getProperty(ProxyConfigNames.HTTP_PROXY_USER)) + .password(properties.getProperty(ProxyConfigNames.HTTP_PROXY_PASSWORD)); - builder.host(properties.getProperty(ProxyConfigNames.HTTP_PROXY_HOST)); + if (properties.notHasProperty(ProxyConfigNames.HTTP_PROXY_HOST)) { + throw new MissingProxyConfigValue(ProxyConfigNames.HTTP_PROXY_HOST); + } - if (properties.notHasProperty(ProxyConfigNames.HTTP_PROXY_PORT)) { - throw new MissingProxyConfigValue(ProxyConfigNames.HTTP_PROXY_PORT); - } + builder.host(properties.getProperty(ProxyConfigNames.HTTP_PROXY_HOST)); - try { - builder.port(Integer.parseInt(properties.getProperty(ProxyConfigNames.HTTP_PROXY_PORT))); - } catch (final NumberFormatException e) { - throw new IllegalArgumentException( - String.format("Given port for proxy authentication configuration (property '%s') is not a valid number! Given value wa '%s'.", - ProxyConfigNames.HTTP_PROXY_PORT.getLiterat(), - System.getProperty("http.proxyPort")), - e); - } + if (properties.notHasProperty(ProxyConfigNames.HTTP_PROXY_PORT)) { + throw new MissingProxyConfigValue(ProxyConfigNames.HTTP_PROXY_PORT); + } - return builder.build(); + try { + builder.port(Integer.parseInt(properties.getProperty(ProxyConfigNames.HTTP_PROXY_PORT))); + } catch (final NumberFormatException e) { + throw new IllegalArgumentException( + String.format("Given port for proxy authentication configuration (property '%s') is not a valid number! Given value wa '%s'.", + ProxyConfigNames.HTTP_PROXY_PORT.getLiterat(), + System.getProperty("http.proxyPort")), + e); } - private static class SystemPropertyFinder { - private boolean hasProperty(@NonNull final ProxyConfigNames name) { - return System.getProperty(name.getLiterat()) != null; - } + return builder.build(); + } - private boolean notHasProperty(@NonNull final ProxyConfigNames name) { - return !hasProperty(name); - } + private static class SystemPropertyFinder { + private boolean hasProperty(@NonNull final ProxyConfigNames name) { + return System.getProperty(name.getLiterat()) != null; + } + + private boolean notHasProperty(@NonNull final ProxyConfigNames name) { + return !hasProperty(name); + } - private String getProperty(@NonNull final ProxyConfigNames name) { - return System.getProperty(name.getLiterat()); - } + private String getProperty(@NonNull final ProxyConfigNames name) { + return System.getProperty(name.getLiterat()); } + } } diff --git a/src/main/java/io/securecodebox/persistence/defectdojo/http/ProxyConfigNames.java b/src/main/java/io/securecodebox/persistence/defectdojo/http/ProxyConfigNames.java index 85dd2f35..3a11d23f 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/http/ProxyConfigNames.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/http/ProxyConfigNames.java @@ -18,26 +18,26 @@ */ @Getter public enum ProxyConfigNames { - /** - * System property name for the proxy username - */ - HTTP_PROXY_USER("http.proxyUser"), - /** - * System property name for the proxy user's password - */ - HTTP_PROXY_PASSWORD("http.proxyPassword"), - /** - * System property name for the proxy's hostname - */ - HTTP_PROXY_HOST("http.proxyHost"), - /** - * System property for the proxy's port number - */ - HTTP_PROXY_PORT("http.proxyPort"); + /** + * System property name for the proxy username + */ + HTTP_PROXY_USER("http.proxyUser"), + /** + * System property name for the proxy user's password + */ + HTTP_PROXY_PASSWORD("http.proxyPassword"), + /** + * System property name for the proxy's hostname + */ + HTTP_PROXY_HOST("http.proxyHost"), + /** + * System property for the proxy's port number + */ + HTTP_PROXY_PORT("http.proxyPort"); - private final String literat; + private final String literat; - ProxyConfigNames(String literat) { - this.literat = literat; - } + ProxyConfigNames(String literat) { + this.literat = literat; + } } diff --git a/src/main/java/io/securecodebox/persistence/defectdojo/model/BaseModel.java b/src/main/java/io/securecodebox/persistence/defectdojo/model/BaseModel.java deleted file mode 100644 index 047b51d3..00000000 --- a/src/main/java/io/securecodebox/persistence/defectdojo/model/BaseModel.java +++ /dev/null @@ -1,12 +0,0 @@ -// SPDX-FileCopyrightText: the secureCodeBox authors -// -// SPDX-License-Identifier: Apache-2.0 - -package io.securecodebox.persistence.defectdojo.model; - -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) -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 0845b93f..d1b31085 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/model/Endpoint.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/model/Endpoint.java @@ -14,41 +14,46 @@ @Builder @NoArgsConstructor @AllArgsConstructor -@EqualsAndHashCode(callSuper = true) +@EqualsAndHashCode @JsonInclude(JsonInclude.Include.NON_NULL) -public class Endpoint extends BaseModel { +public final class Endpoint implements Model, HasId { @JsonProperty - Long id; + private long id; @JsonProperty - String protocol; + private String protocol; @JsonProperty - String host; + private String host; @JsonProperty("fqdm") - String fullyQualifiedDomainName; + private String fullyQualifiedDomainName; @JsonProperty - Long port; + private long port; @JsonProperty - String path; + private String path; @JsonProperty - String query; + private String query; @JsonProperty - String fragment; + private String fragment; @JsonProperty - Long product; + private long product; @JsonProperty - Boolean mitigated; + private boolean mitigated; @Override public boolean equalsQueryString(Map queryParams) { - return queryParams.containsKey("id") && queryParams.get("id").equals(this.id); + if (QueryParamsComparator.isNull(queryParams)) { + return false; + } + + return QueryParamsComparator.isIdEqual(this, queryParams); } + } diff --git a/src/main/java/io/securecodebox/persistence/defectdojo/model/Engagement.java b/src/main/java/io/securecodebox/persistence/defectdojo/model/Engagement.java index 452b7c79..16a7d80a 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/model/Engagement.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/model/Engagement.java @@ -15,96 +15,94 @@ @Builder @NoArgsConstructor @AllArgsConstructor -@EqualsAndHashCode(callSuper = true) +@EqualsAndHashCode @JsonInclude(JsonInclude.Include.NON_NULL) -public class Engagement extends BaseModel { +public final class Engagement implements Model, HasId, HasName { @JsonProperty("branch_tag") - public String branch; + private String branch; @JsonProperty - protected Long id; + private long id; @JsonProperty - protected String name; + private String name; @JsonProperty - protected Long product; + private long product; @JsonProperty("target_start") - protected String targetStart; + private String targetStart; @JsonProperty("target_end") - protected String targetEnd; + private String targetEnd; @JsonProperty - protected Long lead; + private long lead; @JsonProperty("engagement_type") @Builder.Default - protected String engagementType = "CI/CD"; + private String engagementType = "CI/CD"; @JsonProperty @Builder.Default - protected Status status = Status.IN_PROGRESS; + private Status status = Status.IN_PROGRESS; @JsonProperty - protected List tags; + private List tags; @JsonProperty - protected String tracker; + private String tracker; @JsonProperty("build_id") - protected String buildID; + private String buildID; @JsonProperty("commit_hash") - protected String commitHash; + private String commitHash; @JsonProperty("source_code_management_uri") - protected String repo; + private String repo; @JsonProperty("build_server") - protected Long buildServer; + private long buildServer; @JsonProperty("source_code_management_server") - protected Long scmServer; + private long scmServer; @JsonProperty("orchestration_engine") - protected Long orchestrationEngine; + private long orchestrationEngine; @JsonProperty - protected String description; + private String description; @JsonProperty("deduplication_on_engagement") - protected boolean deduplicationOnEngagement; + private boolean deduplicationOnEngagement; @JsonProperty("threat_model") - @Builder.Default - protected Boolean threatModel = false; + private boolean threatModel; @JsonProperty("api_test") - @Builder.Default - protected Boolean apiTest = false; + private boolean apiTest; @JsonProperty("pen_test") - @Builder.Default - protected Boolean penTest = false; + private boolean penTest; @JsonProperty("check_list") - @Builder.Default - protected Boolean checkList = false; + private boolean checkList; @JsonProperty - protected String version; + private String version; @Override public boolean equalsQueryString(Map queryParams) { - if (queryParams == null) { + if (QueryParamsComparator.isNull(queryParams)) { return false; } - if (queryParams.containsKey("id") && queryParams.get("id") != null && queryParams.get("id").equals(this.id)) { + + if (QueryParamsComparator.isIdEqual(this, queryParams)) { return true; } - if (queryParams.containsKey("name") && queryParams.get("name") != null && queryParams.get("name").equals(this.name)) { + + if (QueryParamsComparator.isNameEqual(this, queryParams)) { return true; } 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 7fdc2a72..1e3677eb 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/model/Finding.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/model/Finding.java @@ -19,141 +19,138 @@ @Builder @NoArgsConstructor @AllArgsConstructor -@EqualsAndHashCode(callSuper = true) +@EqualsAndHashCode @JsonInclude(JsonInclude.Include.NON_NULL) -public class Finding extends BaseModel { - @JsonProperty - Long id; - - @JsonProperty - @NonNull - String title; - - @JsonProperty - @NonNull - String description; - - @JsonProperty("found_by") - @NonNull - List foundBy; - - @JsonProperty - @NonNull - Severity severity; - - @JsonProperty - @NonNull - Long test; - - @JsonProperty - String mitigation; - - @JsonProperty - String impact; - - @JsonProperty - @NonNull - @Builder.Default - Boolean active = true; - - @JsonProperty - @NonNull - @Builder.Default - Boolean verified = true; - - @JsonProperty("risk_accepted") - @NonNull - @Builder.Default - Boolean riskAccepted = false; - - @JsonProperty("out_of_scope") - @NonNull - @Builder.Default - Boolean outOfScope = false; - - @JsonProperty - @NonNull - @Builder.Default - Boolean duplicate = false; - - @JsonProperty("duplicate_finding") - @Builder.Default - Long duplicateFinding = null; - - @JsonProperty("false_p") - @NonNull - @Builder.Default - Boolean falsePositive = false; - - @JsonProperty("component_name") - String componentName; - - @JsonProperty("component_version") - String componentVersion; - - @JsonProperty("file_path") - String filePath; - - @JsonProperty - @NonNull - @Builder.Default - List endpoints = new LinkedList<>(); - - @JsonProperty("created") - OffsetDateTime createdAt; - - @JsonProperty("mitigated") - OffsetDateTime mitigatedAt; - - @JsonProperty("accepted_risks") - List acceptedRisks; - - @JsonProperty("numerical_severity") - public String getNumericalSeverity() { - switch (this.severity) { - case CRITICAL: - return "S0"; - case HIGH: - return "S1"; - case MEDIUM: - return "S2"; - case LOW: - return "S3"; - case INFORMATIONAL: - return "S4"; - default: - throw new PersistenceException("Unknown severity: '" + this.severity + "'"); - } +public final class Finding implements Model, HasId { + @JsonProperty + private long id; + + @JsonProperty + @NonNull + private String title; + + @JsonProperty + @NonNull + private String description; + + @JsonProperty("found_by") + @NonNull + private List foundBy; + + @JsonProperty + @NonNull + private Severity severity; + + @JsonProperty + @NonNull + private long test; + + @JsonProperty + private String mitigation; + + @JsonProperty + private String impact; + + @JsonProperty + @NonNull + private boolean active; + + @JsonProperty + @NonNull + private boolean verified; + + @JsonProperty("risk_accepted") + @NonNull + private boolean riskAccepted; + + @JsonProperty("out_of_scope") + @NonNull + private boolean outOfScope; + + @JsonProperty + @NonNull + private boolean duplicate; + + @JsonProperty("duplicate_finding") + private long duplicateFinding; + + @JsonProperty("false_p") + @NonNull + private boolean falsePositive; + + @JsonProperty("component_name") + private String componentName; + + @JsonProperty("component_version") + private String componentVersion; + + @JsonProperty("file_path") + private String filePath; + + @JsonProperty + @NonNull + @Builder.Default + private List endpoints = new LinkedList<>(); + + @JsonProperty("created") + private OffsetDateTime createdAt; + + @JsonProperty("mitigated") + private OffsetDateTime mitigatedAt; + + @JsonProperty("accepted_risks") + private List acceptedRisks; + + @JsonProperty("numerical_severity") + public String getNumericalSeverity() { + switch (this.severity) { + case CRITICAL: + return "S0"; + case HIGH: + return "S1"; + case MEDIUM: + return "S2"; + case LOW: + return "S3"; + case INFORMATIONAL: + return "S4"; + default: + throw new PersistenceException("Unknown severity: '" + this.severity + "'"); } + } - @Override - public boolean equalsQueryString(Map queryParams) { - return queryParams.containsKey("id") && queryParams.get("id").equals(this.id); + @Override + public boolean equalsQueryString(Map queryParams) { + if (QueryParamsComparator.isNull(queryParams)) { + return false; } - public enum Severity { - @JsonProperty("Critical") - CRITICAL(5), - @JsonProperty("High") - HIGH(4), - @JsonProperty("Medium") - MEDIUM(3), - @JsonProperty("Low") - 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); - - final long severity; - - Severity(long severity) { - this.severity = severity; - } - - public long getNumericRepresentation() { - return severity; - } + return QueryParamsComparator.isIdEqual(this, queryParams); + } + + public enum Severity { + @JsonProperty("Critical") + CRITICAL(5), + @JsonProperty("High") + HIGH(4), + @JsonProperty("Medium") + MEDIUM(3), + @JsonProperty("Low") + 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); + + final long severity; + + Severity(long severity) { + this.severity = severity; } + + public long getNumericRepresentation() { + return severity; + } + } } diff --git a/src/main/java/io/securecodebox/persistence/defectdojo/model/Group.java b/src/main/java/io/securecodebox/persistence/defectdojo/model/Group.java index 46e3342b..3d7e0f5c 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/model/Group.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/model/Group.java @@ -15,33 +15,39 @@ @Builder @NoArgsConstructor @AllArgsConstructor -@EqualsAndHashCode(callSuper = true) +@EqualsAndHashCode @JsonInclude(JsonInclude.Include.NON_NULL) -public class Group extends BaseModel { - @JsonProperty - Long id; - - @JsonProperty - @NonNull - String name; - - @JsonProperty - String description; - - @JsonProperty - List users; - - @JsonProperty("social_provider") - String socialProvider; - - @Override - public boolean equalsQueryString(Map queryParams) { - if (queryParams.containsKey("id") && queryParams.get("id").equals(this.id)) { - return true; - } - if (queryParams.containsKey("name") && queryParams.get("name").equals(this.name)) { - return true; - } - return false; +public final class Group implements Model, HasId, HasName { + @JsonProperty + private long id; + + @JsonProperty + @NonNull + private String name; + + @JsonProperty + private String description; + + @JsonProperty + private List users; + + @JsonProperty("social_provider") + private String socialProvider; + + @Override + public boolean equalsQueryString(Map queryParams) { + if (QueryParamsComparator.isNull(queryParams)) { + return false; } + + if (QueryParamsComparator.isIdEqual(this, queryParams)) { + return true; + } + + if (QueryParamsComparator.isNameEqual(this, queryParams)) { + return true; + } + + return false; + } } diff --git a/src/main/java/io/securecodebox/persistence/defectdojo/model/GroupMember.java b/src/main/java/io/securecodebox/persistence/defectdojo/model/GroupMember.java index 4a830db6..b8041861 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/model/GroupMember.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/model/GroupMember.java @@ -14,29 +14,29 @@ @Builder @NoArgsConstructor @AllArgsConstructor -@EqualsAndHashCode(callSuper = true) +@EqualsAndHashCode @JsonInclude(JsonInclude.Include.NON_NULL) -public class GroupMember extends BaseModel { - @JsonProperty - Long id; - - @JsonProperty("group_id") - Long group; - - @JsonProperty("user_id") - Long user; - - @JsonProperty - Long role; - - @Override - public boolean equalsQueryString(Map queryParams) { - if (queryParams.containsKey("id") && queryParams.get("id").equals(this.id)) { - return true; - } - if (queryParams.containsKey("group") && queryParams.get("group").equals(this.group)) { - return true; - } - return false; +public final class GroupMember implements Model { + @JsonProperty + private long id; + + @JsonProperty("group_id") + private long group; + + @JsonProperty("user_id") + private long user; + + @JsonProperty + private long role; + + @Override + public boolean equalsQueryString(Map queryParams) { + if (queryParams.containsKey("id") && queryParams.get("id").equals(this.id)) { + return true; + } + if (queryParams.containsKey("group") && queryParams.get("group").equals(this.group)) { + return true; } + return false; + } } diff --git a/src/main/java/io/securecodebox/persistence/defectdojo/model/HasId.java b/src/main/java/io/securecodebox/persistence/defectdojo/model/HasId.java new file mode 100644 index 00000000..8c8e1092 --- /dev/null +++ b/src/main/java/io/securecodebox/persistence/defectdojo/model/HasId.java @@ -0,0 +1,18 @@ +// SPDX-FileCopyrightText: the secureCodeBox authors +// +// SPDX-License-Identifier: Apache-2.0 + +package io.securecodebox.persistence.defectdojo.model; + +/** + * Interface to mark {@link Model models} which have an id + *

+ * This type is package private because it is an implementation detail of the models and + * z should not be used outside of this package. + *

+ */ +interface HasId { + long getId(); + + void setId(long id); +} diff --git a/src/main/java/io/securecodebox/persistence/defectdojo/model/HasName.java b/src/main/java/io/securecodebox/persistence/defectdojo/model/HasName.java new file mode 100644 index 00000000..6d5b9a3a --- /dev/null +++ b/src/main/java/io/securecodebox/persistence/defectdojo/model/HasName.java @@ -0,0 +1,18 @@ +// SPDX-FileCopyrightText: the secureCodeBox authors +// +// SPDX-License-Identifier: Apache-2.0 + +package io.securecodebox.persistence.defectdojo.model; + +/** + * Interface to mark {@link Model models} which have a name + *

+ * This type is package private because it is an implementation detail of the models and + * z should not be used outside of this package. + *

+ */ +interface HasName { + String getName(); + + void setName(String id); +} diff --git a/src/main/java/io/securecodebox/persistence/defectdojo/model/PaginatedResult.java b/src/main/java/io/securecodebox/persistence/defectdojo/model/PaginatedResult.java new file mode 100644 index 00000000..92c05bf8 --- /dev/null +++ b/src/main/java/io/securecodebox/persistence/defectdojo/model/PaginatedResult.java @@ -0,0 +1,52 @@ +// SPDX-FileCopyrightText: the secureCodeBox authors +// +// SPDX-License-Identifier: Apache-2.0 + +package io.securecodebox.persistence.defectdojo.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +import java.util.ArrayList; +import java.util.List; + +/** + * This class wraps the paginated results from DefectDojo + * + * @param type of results + */ +@Data +public final class PaginatedResult { + /** + * Total number of results + */ + @JsonProperty + private int count; + + /** + * URL to the result's next page + *

+ * This is {@code null} if there is no next page. + *

+ */ + @JsonProperty + private String next; + + /** + * URL to the result's previous page + *

+ * This is {@code null} if there is no previous page. + *

+ */ + @JsonProperty + private String previous; + + /** + * Result for current page + *

+ * Never {@code null}. + *

+ */ + @JsonProperty + private List results = new ArrayList<>(); +} diff --git a/src/main/java/io/securecodebox/persistence/defectdojo/model/Product.java b/src/main/java/io/securecodebox/persistence/defectdojo/model/Product.java index 6e94f983..f5cb2824 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/model/Product.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/model/Product.java @@ -15,48 +15,53 @@ @Builder @NoArgsConstructor @AllArgsConstructor -@EqualsAndHashCode(callSuper = true) +@EqualsAndHashCode @JsonInclude(JsonInclude.Include.NON_NULL) -public class Product extends BaseModel { +public final class Product implements Model, HasId, HasName { @JsonProperty - Long id; + private long id; @JsonProperty - String name; + private String name; @JsonProperty - List tags; + private List tags; @JsonProperty - String description; + private String description; @JsonProperty("findings_count") - Long findingsCount; + private long findingsCount; @JsonProperty("authorized_users") - List authorizedUsers; + private List authorizedUsers; @JsonProperty("prod_type") - Long productType; - + private long productType; + @JsonProperty("enable_simple_risk_acceptance") - Boolean enableSimpleRiskAcceptance; - + private boolean enableSimpleRiskAcceptance; + @JsonProperty("enable_full_risk_acceptance") - Boolean enableFullRiskAcceptance; + private boolean enableFullRiskAcceptance; @JsonProperty("authorization_groups") - List authorizationGroups; - + private List authorizationGroups; + @JsonProperty - String lifecycle; + private String lifecycle; @Override public boolean equalsQueryString(Map queryParams) { - if (queryParams.containsKey("id") && queryParams.get("id").equals(this.id)) { + if (QueryParamsComparator.isNull(queryParams)) { + return false; + } + + if (QueryParamsComparator.isIdEqual(this, queryParams)) { return true; } - if (queryParams.containsKey("name") && queryParams.get("name").equals(this.name)) { + + if (QueryParamsComparator.isNameEqual(this, queryParams)) { return true; } diff --git a/src/main/java/io/securecodebox/persistence/defectdojo/model/ProductGroup.java b/src/main/java/io/securecodebox/persistence/defectdojo/model/ProductGroup.java index 20c4448b..109212af 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/model/ProductGroup.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/model/ProductGroup.java @@ -14,29 +14,29 @@ @Builder @NoArgsConstructor @AllArgsConstructor -@EqualsAndHashCode(callSuper = true) +@EqualsAndHashCode @JsonInclude(JsonInclude.Include.NON_NULL) -public class ProductGroup extends BaseModel { - @JsonProperty - Long id; - - @JsonProperty - Long product; - - @JsonProperty - Long group; - - @JsonProperty - Long role; - - @Override - public boolean equalsQueryString(Map queryParams) { - if (queryParams.containsKey("id") && queryParams.get("id").equals(this.id)) { - return true; - } - if (queryParams.containsKey("product") && queryParams.get("product").equals(this.product) && queryParams.containsKey("group") && queryParams.get("group").equals(this.group)) { - return true; - } - return false; +public final class ProductGroup implements Model { + @JsonProperty + private long id; + + @JsonProperty + private long product; + + @JsonProperty + private long group; + + @JsonProperty + private long role; + + @Override + public boolean equalsQueryString(Map queryParams) { + if (queryParams.containsKey("id") && queryParams.get("id").equals(this.id)) { + return true; + } + if (queryParams.containsKey("product") && queryParams.get("product").equals(this.product) && queryParams.containsKey("group") && queryParams.get("group").equals(this.group)) { + return true; } + return false; + } } diff --git a/src/main/java/io/securecodebox/persistence/defectdojo/model/ProductType.java b/src/main/java/io/securecodebox/persistence/defectdojo/model/ProductType.java index d767ada5..6aac466e 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/model/ProductType.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/model/ProductType.java @@ -14,28 +14,33 @@ @Builder @NoArgsConstructor @AllArgsConstructor -@EqualsAndHashCode(callSuper = true) +@EqualsAndHashCode @JsonInclude(JsonInclude.Include.NON_NULL) -public class ProductType extends BaseModel { +public final class ProductType implements Model, HasId, HasName { @JsonProperty - Long id; + private long id; @JsonProperty @NonNull - String name; + private String name; @JsonProperty("critical_product") - Boolean criticalProduct; + private boolean criticalProduct; @JsonProperty("key_product") - Boolean keyProduct; + private boolean keyProduct; @Override public boolean equalsQueryString(Map queryParams) { - if (queryParams.containsKey("id") && queryParams.get("id").equals(this.id)) { + if (QueryParamsComparator.isNull(queryParams)) { + return false; + } + + if (QueryParamsComparator.isIdEqual(this, queryParams)) { return true; } - if (queryParams.containsKey("name") && queryParams.get("name").equals(this.name)) { + + if (QueryParamsComparator.isNameEqual(this, queryParams)) { return true; } diff --git a/src/main/java/io/securecodebox/persistence/defectdojo/model/QueryParamsComparator.java b/src/main/java/io/securecodebox/persistence/defectdojo/model/QueryParamsComparator.java new file mode 100644 index 00000000..9715aae5 --- /dev/null +++ b/src/main/java/io/securecodebox/persistence/defectdojo/model/QueryParamsComparator.java @@ -0,0 +1,68 @@ +// SPDX-FileCopyrightText: the secureCodeBox authors +// +// SPDX-License-Identifier: Apache-2.0 + +package io.securecodebox.persistence.defectdojo.model; + +import java.util.Map; + +/** + * Pure static helper class + *

+ * This type is package private because it is an implementation detail of the models and + * should not be used outside of this package. + *

+ */ +final class QueryParamsComparator { + + static final String QUERY_PARAM_KEY_FOR_ID = "id"; + static final String QUERY_PARAM_KEY_FOR_NAME = "name"; + + private QueryParamsComparator() { + super(); + } + + static boolean isNull(Object o) { + return o == null; + } + + static boolean isIdEqual(HasId model, Map queryParams) { + if (isNull(model)) { + return false; + } + + if (isNull(queryParams)) { + return false; + } + + if (!queryParams.containsKey(QUERY_PARAM_KEY_FOR_ID)) { + return false; + } + + if (isNull(queryParams.get(QUERY_PARAM_KEY_FOR_ID))) { + return false; + } + + return queryParams.get(QUERY_PARAM_KEY_FOR_ID).equals(model.getId()); + } + + static boolean isNameEqual(HasName model, Map queryParams) { + if (isNull(model)) { + return false; + } + + if (isNull(queryParams)) { + return false; + } + + if (!queryParams.containsKey(QUERY_PARAM_KEY_FOR_NAME)) { + return false; + } + + if (isNull(queryParams.get(QUERY_PARAM_KEY_FOR_NAME))) { + return false; + } + + return queryParams.get(QUERY_PARAM_KEY_FOR_NAME).equals(model.getName()); + } +} diff --git a/src/main/java/io/securecodebox/persistence/defectdojo/model/Response.java b/src/main/java/io/securecodebox/persistence/defectdojo/model/Response.java deleted file mode 100644 index 92e7a5a4..00000000 --- a/src/main/java/io/securecodebox/persistence/defectdojo/model/Response.java +++ /dev/null @@ -1,25 +0,0 @@ -// SPDX-FileCopyrightText: the secureCodeBox authors -// -// SPDX-License-Identifier: Apache-2.0 - -package io.securecodebox.persistence.defectdojo.model; - -import com.fasterxml.jackson.annotation.JsonProperty; -import lombok.Data; - -import java.util.List; - -@Data -public class Response { - @JsonProperty - int count; - - @JsonProperty - String next; - - @JsonProperty - String previous; - - @JsonProperty - List results; -} 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 cc203673..fe6bc08f 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/model/RiskAcceptance.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/model/RiskAcceptance.java @@ -15,49 +15,53 @@ @Builder @NoArgsConstructor @AllArgsConstructor -@EqualsAndHashCode(callSuper = true) +@EqualsAndHashCode @JsonInclude(JsonInclude.Include.NON_NULL) -public class RiskAcceptance extends BaseModel { +public final class RiskAcceptance implements Model, HasId { @JsonProperty - Long id; + private long id; @JsonProperty - String recommendation; + private String recommendation; @JsonProperty("recommendation_details") - String recommendationDetails; + private String recommendationDetails; - String decision; + private String decision; @JsonProperty("decision_details") - String decisionDetails; + private String decisionDetails; @JsonProperty - String path; + private String path; @JsonProperty("accepted_by") - String acceptedBy; + private String acceptedBy; @JsonProperty("expiration_date") - OffsetDateTime expirationDate; + private OffsetDateTime expirationDate; @JsonProperty("expiration_date_warned") - OffsetDateTime expirationDateWarned; + private OffsetDateTime expirationDateWarned; @JsonProperty("expiration_date_handled") - OffsetDateTime expirationDateHandled; + private OffsetDateTime expirationDateHandled; @JsonProperty("created") - OffsetDateTime createdAt; + private OffsetDateTime createdAt; @JsonProperty("updated") - OffsetDateTime updatedAt; + private OffsetDateTime updatedAt; @JsonProperty - Long owner; + private long owner; @Override public boolean equalsQueryString(Map queryParams) { - return queryParams.containsKey("id") && queryParams.get("id").equals(this.id); + if (QueryParamsComparator.isNull(queryParams)) { + return false; + } + + return QueryParamsComparator.isIdEqual(this, queryParams); } } diff --git a/src/main/java/io/securecodebox/persistence/defectdojo/model/ScanFile.java b/src/main/java/io/securecodebox/persistence/defectdojo/model/ScanFile.java index 6eb8b511..c4c5ebb6 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/model/ScanFile.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/model/ScanFile.java @@ -6,28 +6,44 @@ import lombok.Data; +/** + * DTO to upload a secureCodeBox scan file + *

+ * This is not a JSON model – thus not implementing the Model interface – because it is only used as DTO for the + * multi-part form upload. + *

+ */ @Data -public class ScanFile { - /** - * A default name must be set - *

- * It does not matter however unless the parser pays attention to file endings like json or xml. - *

- */ - static final String DEFAULT_NAME = "default-name.txt"; - - String content; - - String name; - - public ScanFile(String content) { - this(content, DEFAULT_NAME); - } - - public ScanFile(String content, String name) { - super(); - this.content = content; - this.name = name; - } +public final class ScanFile { + /** + * A default name must be set + *

+ * It does not matter however unless the parser pays attention to file endings like json or xml. + *

+ */ + private static final String DEFAULT_NAME = "default-name.txt"; + + /** + * The file content. + */ + private String content; + + /** + * Name of file. + *

+ * Defaults to {@link #DEFAULT_NAME}. + *

+ */ + private String name; + + public ScanFile(String content) { + this(content, DEFAULT_NAME); + } + + public ScanFile(String content, String name) { + super(); + this.content = content; + this.name = name; + } } diff --git a/src/main/java/io/securecodebox/persistence/defectdojo/model/Test.java b/src/main/java/io/securecodebox/persistence/defectdojo/model/Test.java index 8ed5cdd1..002d9756 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/model/Test.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/model/Test.java @@ -16,42 +16,42 @@ @Builder @NoArgsConstructor @AllArgsConstructor -@EqualsAndHashCode(callSuper = true) +@EqualsAndHashCode @JsonInclude(JsonInclude.Include.NON_NULL) -public class Test extends BaseModel { +public final class Test implements Model, HasId { @JsonProperty - Long id; + private long id; @JsonProperty - String title; + private String title; @JsonProperty - String description; + private String description; @JsonProperty("target_start") - String targetStart; + private String targetStart; @JsonProperty("target_end") - String targetEnd; + private String targetEnd; @JsonProperty @Builder.Default - List tags = new LinkedList<>(); + private List tags = new LinkedList<>(); @JsonProperty("test_type") - Long testType; + private long testType; @JsonProperty - Long lead; + private long lead; @JsonProperty("percent_complete") - Long percentComplete; + private long percentComplete; @JsonProperty - Long engagement; + private long engagement; @JsonProperty - String version; + private String version; /** * 1 Development @@ -59,16 +59,22 @@ public class Test extends BaseModel { */ @JsonProperty @Builder.Default - Long environment = 1L; + private long environment = 1L; @Override public boolean equalsQueryString(Map queryParams) { - if (queryParams.containsKey("id") && queryParams.get("id").equals(this.id)) { + if (QueryParamsComparator.isNull(queryParams)) { + return false; + } + + if (QueryParamsComparator.isIdEqual(this, queryParams)) { return true; } + if (queryParams.containsKey("title") && queryParams.get("title").equals(this.title)) { return true; } + if (queryParams.containsKey("engagement") && queryParams.get("engagement").equals(this.engagement)) { return true; } diff --git a/src/main/java/io/securecodebox/persistence/defectdojo/model/TestType.java b/src/main/java/io/securecodebox/persistence/defectdojo/model/TestType.java index 9b8e94ea..a1cff33a 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/model/TestType.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/model/TestType.java @@ -14,29 +14,34 @@ @Builder @NoArgsConstructor @AllArgsConstructor -@EqualsAndHashCode(callSuper = true) +@EqualsAndHashCode @JsonInclude(JsonInclude.Include.NON_NULL) -public class TestType extends BaseModel { +public final class TestType implements Model, HasId, HasName { @JsonProperty - Long id; + private long id; @JsonProperty @NonNull - String name; + private String name; @JsonProperty("static_tool") - Boolean staticTool; + private boolean staticTool; @JsonProperty("dynamic_tool") - Boolean dynamicTool; + private boolean dynamicTool; @Override public boolean equalsQueryString(Map queryParams) { - if (queryParams.containsKey("id") && queryParams.get("id").equals(this.id)) { + if (QueryParamsComparator.isNull(queryParams)) { + return false; + } + + if (QueryParamsComparator.isIdEqual(this, queryParams)) { return true; } - if (queryParams.containsKey("name") && queryParams.get("name").equals(this.name)) { + + if (QueryParamsComparator.isNameEqual(this, queryParams)) { return true; } diff --git a/src/main/java/io/securecodebox/persistence/defectdojo/model/ToolConfig.java b/src/main/java/io/securecodebox/persistence/defectdojo/model/ToolConfig.java index 89ab56c5..9992ae36 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/model/ToolConfig.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/model/ToolConfig.java @@ -14,11 +14,11 @@ @Builder @NoArgsConstructor @AllArgsConstructor -@EqualsAndHashCode(callSuper = true) +@EqualsAndHashCode @JsonInclude(JsonInclude.Include.NON_NULL) -public class ToolConfig extends BaseModel { +public final class ToolConfig implements Model, HasId, HasName { @JsonProperty - Long id; + private long id; @JsonProperty String url; @@ -28,7 +28,7 @@ public class ToolConfig extends BaseModel { String name; @JsonProperty("tool_type") - Long toolType; + private long toolType; @JsonProperty("configuration_url") String configUrl; @@ -38,12 +38,18 @@ public class ToolConfig extends BaseModel { @Override public boolean equalsQueryString(Map queryParams) { - if (queryParams.containsKey("id") && queryParams.get("id").equals(this.id)) { + if (QueryParamsComparator.isNull(queryParams)) { + return false; + } + + if (QueryParamsComparator.isIdEqual(this, queryParams)) { return true; } - if (queryParams.containsKey("name") && queryParams.get("name").equals(this.name)) { + + if (QueryParamsComparator.isNameEqual(this, queryParams)) { return true; } + if (queryParams.containsKey("configuration_url") && queryParams.get("configuration_url").equals(this.configUrl)) { return true; } diff --git a/src/main/java/io/securecodebox/persistence/defectdojo/model/ToolType.java b/src/main/java/io/securecodebox/persistence/defectdojo/model/ToolType.java index 8722a148..e4e14213 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/model/ToolType.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/model/ToolType.java @@ -14,25 +14,30 @@ @Builder @NoArgsConstructor @AllArgsConstructor -@EqualsAndHashCode(callSuper = true) +@EqualsAndHashCode @JsonInclude(JsonInclude.Include.NON_NULL) -public class ToolType extends BaseModel { +public final class ToolType implements Model, HasId, HasName { @JsonProperty - Long id; + private long id; @JsonProperty @NonNull - String name; + private String name; @JsonProperty - String description; + private String description; @Override public boolean equalsQueryString(Map queryParams) { - if (queryParams.containsKey("id") && queryParams.get("id").equals(this.id)) { + if (QueryParamsComparator.isNull(queryParams)) { + return false; + } + + if (QueryParamsComparator.isIdEqual(this, queryParams)) { return true; } - if (queryParams.containsKey("name") && queryParams.get("name").equals(this.name)) { + + if (QueryParamsComparator.isNameEqual(this, queryParams)) { return true; } diff --git a/src/main/java/io/securecodebox/persistence/defectdojo/model/User.java b/src/main/java/io/securecodebox/persistence/defectdojo/model/User.java index e3027b25..737be18d 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/model/User.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/model/User.java @@ -14,27 +14,32 @@ @Builder @NoArgsConstructor @AllArgsConstructor -@EqualsAndHashCode(callSuper = true) +@EqualsAndHashCode @JsonInclude(JsonInclude.Include.NON_NULL) -public class User extends BaseModel { +public final class User implements Model, HasId { @JsonProperty - Long id; + private long id; @JsonProperty @NonNull - String username; + private String username; @JsonProperty("first_name") - String firstName; + private String firstName; @JsonProperty("last_name") - String lastName; + private String lastName; @Override public boolean equalsQueryString(Map queryParams) { - if (queryParams.containsKey("id") && queryParams.get("id").equals(this.id)) { + if (QueryParamsComparator.isNull(queryParams)) { + return false; + } + + if (QueryParamsComparator.isIdEqual(this, queryParams)) { return true; } + if (queryParams.containsKey("username") && queryParams.get("username").equals(this.username)) { return true; } diff --git a/src/main/java/io/securecodebox/persistence/defectdojo/model/UserProfile.java b/src/main/java/io/securecodebox/persistence/defectdojo/model/UserProfile.java index 8d2d044c..279c9783 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/model/UserProfile.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/model/UserProfile.java @@ -14,18 +14,22 @@ @Builder @NoArgsConstructor @AllArgsConstructor -@EqualsAndHashCode(callSuper = true) +@EqualsAndHashCode @JsonInclude(JsonInclude.Include.NON_NULL) +public final class UserProfile implements Model { -public class UserProfile extends BaseModel { + @JsonProperty + private User user; - @JsonProperty - User user; - - @Override - public boolean equalsQueryString(Map queryParams) { - // The user_profile endpoint does not have query parameters thats why this function will just return true - return true; + @Override + public boolean equalsQueryString(Map queryParams) { + if (QueryParamsComparator.isNull(queryParams)) { + return false; } - + + // The user_profile endpoint does not have query parameters that's + // why this function will just return true. + return true; + } + } diff --git a/src/main/java/io/securecodebox/persistence/defectdojo/service/DefaultImportScanService.java b/src/main/java/io/securecodebox/persistence/defectdojo/service/DefaultImportScanService.java index bea38469..e082a5ef 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/service/DefaultImportScanService.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/service/DefaultImportScanService.java @@ -41,166 +41,166 @@ * https://defectdojo.security.iteratec.dev/api/v2/oa3/swagger-ui/#operations-tag-import-scan */ class DefaultImportScanService implements ImportScanService { - private static final List> HTTP_MESSAGE_CONVERTERS = List.of( - new FormHttpMessageConverter(), - new ResourceHttpMessageConverter(), - new MappingJackson2HttpMessageConverter()); - @Getter - private final String defectDojoUrl; - @Getter - private final String defectDojoApiKey; - private final ProxyConfig proxyConfig; - - /** - * Dedicated constructor. - * - * @param config not {@code null} - * @param proxyConfig not {@code null} - */ - DefaultImportScanService(final @NonNull Config config, @NonNull ProxyConfig proxyConfig) { - super(); - this.defectDojoUrl = config.getUrl(); - this.defectDojoApiKey = config.getApiKey(); - this.proxyConfig = proxyConfig; + private static final List> HTTP_MESSAGE_CONVERTERS = List.of( + new FormHttpMessageConverter(), + new ResourceHttpMessageConverter(), + new MappingJackson2HttpMessageConverter()); + @Getter + private final String defectDojoUrl; + @Getter + private final String defectDojoApiKey; + private final ProxyConfig proxyConfig; + + /** + * Dedicated constructor. + * + * @param config not {@code null} + * @param proxyConfig not {@code null} + */ + DefaultImportScanService(final @NonNull Config config, @NonNull ProxyConfig proxyConfig) { + super(); + this.defectDojoUrl = config.getUrl(); + this.defectDojoApiKey = config.getApiKey(); + this.proxyConfig = proxyConfig; + } + + @Override + public ImportScanResponse importScan(ScanFile scanFile, long engagementId, long lead, String currentDate, ScanType scanType, long testType, Map options) { + options.put("engagement", Long.toString(engagementId)); + + return this.createFindings(scanFile, "import-scan", lead, currentDate, scanType, testType, options); + } + + @Override + public ImportScanResponse reimportScan(ScanFile scanFile, long testId, long lead, String currentDate, ScanType scanType, long testType, Map options) { + options.put("test", Long.toString(testId)); + + return this.createFindings(scanFile, "reimport-scan", lead, currentDate, scanType, testType, options); + } + + /* + * Before version 1.5.4. testName (in DefectDojo _test_type_) must be defectDojoScanName, afterward, you can have something else. + */ + private ImportScanResponse createFindings(ScanFile scanFile, String endpoint, long lead, String currentDate, ScanType scanType, long testType, Map options) { + final var headers = createDefectDojoAuthorizationHeaders(); + // We use multipart because we send two "parts" in the request body: + // 1. generic info as key=value&key=value... + // 2. the raw scan result as file + headers.setContentType(MediaType.MULTIPART_FORM_DATA); + + // FIXME: #36 Why do we use a multi value map here? Do we need multiple values for any given key? + final var body = new LinkedMultiValueMap(); + + body.add("lead", Long.toString(lead)); + body.add("scan_date", currentDate); + body.add("scan_type", scanType.getTestType()); + body.add("close_old_findings", "true"); + body.add("skip_duplicates", "false"); + body.add("test_type", String.valueOf(testType)); + + // Avoid duplicate entries: + for (final var optionName : options.keySet()) { + body.remove(optionName); } - @Override - public ImportScanResponse importScan(ScanFile scanFile, long engagementId, long lead, String currentDate, ScanType scanType, long testType, Map options) { - options.put("engagement", Long.toString(engagementId)); - - return this.createFindings(scanFile, "import-scan", lead, currentDate, scanType, testType, options); - } - - @Override - public ImportScanResponse reimportScan(ScanFile scanFile, long testId, long lead, String currentDate, ScanType scanType, long testType, Map options) { - options.put("test", Long.toString(testId)); - - return this.createFindings(scanFile, "reimport-scan", lead, currentDate, scanType, testType, options); - } - - /* - * Before version 1.5.4. testName (in DefectDojo _test_type_) must be defectDojoScanName, afterward, you can have something else. - */ - private ImportScanResponse createFindings(ScanFile scanFile, String endpoint, long lead, String currentDate, ScanType scanType, long testType, Map options) { - final var headers = createDefectDojoAuthorizationHeaders(); - // We use multipart because we send two "parts" in the request body: - // 1. generic info as key=value&key=value... - // 2. the raw scan result as file - headers.setContentType(MediaType.MULTIPART_FORM_DATA); - - // FIXME: #36 Why do we use a multi value map here? Do we need multiple values for any given key? - final var body = new LinkedMultiValueMap(); - - body.add("lead", Long.toString(lead)); - body.add("scan_date", currentDate); - body.add("scan_type", scanType.getTestType()); - body.add("close_old_findings", "true"); - body.add("skip_duplicates", "false"); - body.add("test_type", String.valueOf(testType)); - - // Avoid duplicate entries: - for (final var optionName : options.keySet()) { - body.remove(optionName); - } - - // FIXME: #36 Workaround due to type incompatibility of MultiValueMap and MultiValueMap. - for (final var option : options.entrySet()) { - body.add(option.getKey(), option.getValue()); - } - - try { - // scanFile is the raw result from lurker. - final var contentsAsResource = new ByteArrayResource(scanFile.getContent().getBytes(StandardCharsets.UTF_8)) { - @Override - public String getFilename() { - return scanFile.getName(); - } - }; - - // We send the whole file content, so DefectDojo can parse the finding by itself. - body.add("file", contentsAsResource); - - final var payload = new HttpEntity>(body, headers); - return exchangeRequest(endpoint, payload); - } catch (HttpClientErrorException e) { - throw new PersistenceException("Failed to attach findings to engagement."); - } - } - - ImportScanResponse exchangeRequest(String endpoint, HttpEntity payload) { - final var restTemplate = this.createRestTemplate(); - return restTemplate.exchange( - generateApiUrl(endpoint), - HttpMethod.POST, - payload, - ImportScanResponse.class) - .getBody(); - } - - String generateApiUrl(final String endpoint) { - return String.format("%s/api/v2/%s/", getDefectDojoUrl(), endpoint); + // FIXME: #36 Workaround due to type incompatibility of MultiValueMap and MultiValueMap. + for (final var option : options.entrySet()) { + body.add(option.getKey(), option.getValue()); } - /** - * The DefectDojo Authentication Header - * - * @return never {@code null} - */ - HttpHeaders createDefectDojoAuthorizationHeaders() { - final var authorizationHeader = new HttpHeaders(); - authorizationHeader.set(HttpHeaders.AUTHORIZATION, String.format("Token %s", defectDojoApiKey)); - return authorizationHeader; - } - - private RestTemplate createRestTemplate() { - final var template = new RestTemplate(); - - if (shouldConfigureProxySettings()) { - template.setRequestFactory(createRequestFactoryWithProxyAuthConfig()); + try { + // scanFile is the raw result from lurker. + final var contentsAsResource = new ByteArrayResource(scanFile.getContent().getBytes(StandardCharsets.UTF_8)) { + @Override + public String getFilename() { + return scanFile.getName(); } + }; - template.setMessageConverters(HTTP_MESSAGE_CONVERTERS); + // We send the whole file content, so DefectDojo can parse the finding by itself. + body.add("file", contentsAsResource); - return template; + final var payload = new HttpEntity>(body, headers); + return exchangeRequest(endpoint, payload); + } catch (HttpClientErrorException e) { + throw new PersistenceException("Failed to attach findings to engagement."); } - - boolean shouldConfigureProxySettings() { - return proxyConfig.isComplete(); + } + + ImportScanResponse exchangeRequest(String endpoint, HttpEntity payload) { + final var restTemplate = this.createRestTemplate(); + return restTemplate.exchange( + generateApiUrl(endpoint), + HttpMethod.POST, + payload, + ImportScanResponse.class) + .getBody(); + } + + String generateApiUrl(final String endpoint) { + return String.format("%s/api/v2/%s/", getDefectDojoUrl(), endpoint); + } + + /** + * The DefectDojo Authentication Header + * + * @return never {@code null} + */ + HttpHeaders createDefectDojoAuthorizationHeaders() { + final var authorizationHeader = new HttpHeaders(); + authorizationHeader.set(HttpHeaders.AUTHORIZATION, String.format("Token %s", defectDojoApiKey)); + return authorizationHeader; + } + + private RestTemplate createRestTemplate() { + final var template = new RestTemplate(); + + if (shouldConfigureProxySettings()) { + template.setRequestFactory(createRequestFactoryWithProxyAuthConfig()); } - /** - * Configuring proxy authentication explicitly - * - *

- * This isn't done by default for spring rest templates.This method expects these four system properties (Java flag - * {@literal -DpropertyName}) to be set: - *

- *
    - *
  • http.proxyUser
  • - *
  • http.proxyPassword
  • - *
  • http.proxyHost
  • - *
  • http.proxyPort
  • - *
- * - * @return never {@code null} - */ - ClientHttpRequestFactory createRequestFactoryWithProxyAuthConfig() { - final var credentials = new BasicCredentialsProvider(); - credentials.setCredentials( - new AuthScope(proxyConfig.getHost(), proxyConfig.getPort()), - new UsernamePasswordCredentials( - proxyConfig.getUser(), - proxyConfig.getPassword()) - ); - - final var clientBuilder = HttpClientBuilder.create(); - clientBuilder.useSystemProperties(); - clientBuilder.setProxy(new HttpHost(proxyConfig.getHost(), proxyConfig.getPort())); - clientBuilder.setDefaultCredentialsProvider(credentials); - clientBuilder.setProxyAuthenticationStrategy(new ProxyAuthenticationStrategy()); - - final var factory = new HttpComponentsClientHttpRequestFactory(); - factory.setHttpClient(clientBuilder.build()); - return factory; - } + template.setMessageConverters(HTTP_MESSAGE_CONVERTERS); + + return template; + } + + boolean shouldConfigureProxySettings() { + return proxyConfig.isComplete(); + } + + /** + * Configuring proxy authentication explicitly + * + *

+ * This isn't done by default for spring rest templates.This method expects these four system properties (Java flag + * {@literal -DpropertyName}) to be set: + *

+ *
    + *
  • http.proxyUser
  • + *
  • http.proxyPassword
  • + *
  • http.proxyHost
  • + *
  • http.proxyPort
  • + *
+ * + * @return never {@code null} + */ + ClientHttpRequestFactory createRequestFactoryWithProxyAuthConfig() { + final var credentials = new BasicCredentialsProvider(); + credentials.setCredentials( + new AuthScope(proxyConfig.getHost(), proxyConfig.getPort()), + new UsernamePasswordCredentials( + proxyConfig.getUser(), + proxyConfig.getPassword()) + ); + + final var clientBuilder = HttpClientBuilder.create(); + clientBuilder.useSystemProperties(); + clientBuilder.setProxy(new HttpHost(proxyConfig.getHost(), proxyConfig.getPort())); + clientBuilder.setDefaultCredentialsProvider(credentials); + clientBuilder.setProxyAuthenticationStrategy(new ProxyAuthenticationStrategy()); + + final var factory = new HttpComponentsClientHttpRequestFactory(); + factory.setHttpClient(clientBuilder.build()); + return factory; + } } diff --git a/src/main/java/io/securecodebox/persistence/defectdojo/service/EndpointService.java b/src/main/java/io/securecodebox/persistence/defectdojo/service/EndpointService.java index c3db474e..eef68497 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/service/EndpointService.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/service/EndpointService.java @@ -7,8 +7,8 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import io.securecodebox.persistence.defectdojo.config.Config; -import io.securecodebox.persistence.defectdojo.model.Response; import io.securecodebox.persistence.defectdojo.model.Endpoint; +import io.securecodebox.persistence.defectdojo.model.PaginatedResult; public class EndpointService extends GenericDefectDojoService { public EndpointService(Config config) { @@ -26,7 +26,7 @@ protected Class getModelClass() { } @Override - protected Response deserializeList(String response) throws JsonProcessingException { + protected PaginatedResult deserializeList(String response) throws JsonProcessingException { return this.objectMapper.readValue(response, new TypeReference<>() { }); } diff --git a/src/main/java/io/securecodebox/persistence/defectdojo/service/EngagementService.java b/src/main/java/io/securecodebox/persistence/defectdojo/service/EngagementService.java index d1f8a2ed..07976423 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/service/EngagementService.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/service/EngagementService.java @@ -7,8 +7,8 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import io.securecodebox.persistence.defectdojo.config.Config; -import io.securecodebox.persistence.defectdojo.model.Response; import io.securecodebox.persistence.defectdojo.model.Engagement; +import io.securecodebox.persistence.defectdojo.model.PaginatedResult; public class EngagementService extends GenericDefectDojoService { public EngagementService(Config config) { @@ -26,7 +26,7 @@ protected Class getModelClass() { } @Override - protected Response deserializeList(String response) throws JsonProcessingException { + protected PaginatedResult deserializeList(String response) throws JsonProcessingException { return this.objectMapper.readValue(response, new TypeReference<>() { }); } 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 607b2e68..7a339a4f 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/service/FindingService.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/service/FindingService.java @@ -7,8 +7,8 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import io.securecodebox.persistence.defectdojo.config.Config; -import io.securecodebox.persistence.defectdojo.model.Response; import io.securecodebox.persistence.defectdojo.model.Finding; +import io.securecodebox.persistence.defectdojo.model.PaginatedResult; import java.net.URISyntaxException; import java.util.List; @@ -30,7 +30,7 @@ protected Class getModelClass() { } @Override - protected Response deserializeList(String response) throws JsonProcessingException { + protected PaginatedResult deserializeList(String response) throws JsonProcessingException { return this.objectMapper.readValue(response, new TypeReference<>() { }); } 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 ea32ff7a..1dca8eb2 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/service/GenericDefectDojoService.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/service/GenericDefectDojoService.java @@ -16,7 +16,7 @@ import io.securecodebox.persistence.defectdojo.http.ProxyConfigFactory; import io.securecodebox.persistence.defectdojo.model.Engagement; import io.securecodebox.persistence.defectdojo.model.Model; -import io.securecodebox.persistence.defectdojo.model.Response; +import io.securecodebox.persistence.defectdojo.model.PaginatedResult; import lombok.Getter; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; @@ -35,6 +35,7 @@ import java.util.*; // FIXME: Should be package private bc implementation detail. +// TODO: Remove JsonProcessingException, URISyntaxException from public API and use a own runtime exception type bc these checked exceptions clutter the client coe. public abstract class GenericDefectDojoService { private static final String API_PREFIX = "/api/v2/"; private static final long DEFECT_DOJO_OBJET_LIMIT = 100L; @@ -63,7 +64,6 @@ public GenericDefectDojoService(Config config) { } - /** * @return The DefectDojo Authentication Header */ @@ -88,7 +88,7 @@ private RestTemplate setupRestTemplate() { protected abstract Class getModelClass(); - protected abstract Response deserializeList(String response) throws JsonProcessingException; + protected abstract PaginatedResult deserializeList(String response) throws JsonProcessingException; public T get(long id) { var restTemplate = this.getRestTemplate(); @@ -104,11 +104,11 @@ public T get(long id) { return response.getBody(); } - protected Response internalSearch(Map queryParams, long limit, long offset) throws JsonProcessingException, URISyntaxException { + protected PaginatedResult 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)); @@ -134,7 +134,7 @@ protected Response internalSearch(Map queryParams, long limit public List search(Map queryParams) throws URISyntaxException, JsonProcessingException { List objects = new LinkedList<>(); - boolean hasNext = false; + boolean hasNext; long page = 0; do { var response = internalSearch(queryParams, DEFECT_DOJO_OBJET_LIMIT, DEFECT_DOJO_OBJET_LIMIT * page++); diff --git a/src/main/java/io/securecodebox/persistence/defectdojo/service/GroupMemberService.java b/src/main/java/io/securecodebox/persistence/defectdojo/service/GroupMemberService.java index 05bf6aa3..10ba6495 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/service/GroupMemberService.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/service/GroupMemberService.java @@ -7,8 +7,8 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import io.securecodebox.persistence.defectdojo.config.Config; -import io.securecodebox.persistence.defectdojo.model.Response; import io.securecodebox.persistence.defectdojo.model.GroupMember; +import io.securecodebox.persistence.defectdojo.model.PaginatedResult; public class GroupMemberService extends GenericDefectDojoService { public GroupMemberService(Config config) { @@ -26,7 +26,7 @@ protected Class getModelClass() { } @Override - protected Response deserializeList(String response) throws JsonProcessingException { + protected PaginatedResult deserializeList(String response) throws JsonProcessingException { return this.objectMapper.readValue(response, new TypeReference<>() { }); } diff --git a/src/main/java/io/securecodebox/persistence/defectdojo/service/GroupService.java b/src/main/java/io/securecodebox/persistence/defectdojo/service/GroupService.java index 15d15dc9..ca5fa92e 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/service/GroupService.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/service/GroupService.java @@ -7,8 +7,8 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import io.securecodebox.persistence.defectdojo.config.Config; -import io.securecodebox.persistence.defectdojo.model.Response; import io.securecodebox.persistence.defectdojo.model.Group; +import io.securecodebox.persistence.defectdojo.model.PaginatedResult; public class GroupService extends GenericDefectDojoService { public GroupService(Config config) { @@ -26,7 +26,7 @@ protected Class getModelClass() { } @Override - protected Response deserializeList(String response) throws JsonProcessingException { + protected PaginatedResult deserializeList(String response) throws JsonProcessingException { return this.objectMapper.readValue(response, new TypeReference<>() { }); } diff --git a/src/main/java/io/securecodebox/persistence/defectdojo/service/ImportScanService.java b/src/main/java/io/securecodebox/persistence/defectdojo/service/ImportScanService.java index 808c2995..32ca3e5c 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/service/ImportScanService.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/service/ImportScanService.java @@ -20,48 +20,48 @@ * Service to re/import findings into DefectDojo */ public interface ImportScanService { - /** - * Factory method to create new instance of service default implementation - * - * @param config must not be {@code null} - * @return never {@code null} - */ - static ImportScanService createDefault(final Config config) { - return createDefault(config, new ProxyConfigFactory().create()); - } + /** + * Factory method to create new instance of service default implementation + * + * @param config must not be {@code null} + * @return never {@code null} + */ + static ImportScanService createDefault(final Config config) { + return createDefault(config, new ProxyConfigFactory().create()); + } - /** - * Factory method to create new instance of service default implementation - * - * @param config must not be {@code null} - * @param proxyConfig must not be {@code null} - * @return never {@code null} - */ - static ImportScanService createDefault(@NonNull final Config config, @NonNull final ProxyConfig proxyConfig) { - return new DefaultImportScanService(config, proxyConfig); - } + /** + * Factory method to create new instance of service default implementation + * + * @param config must not be {@code null} + * @param proxyConfig must not be {@code null} + * @return never {@code null} + */ + static ImportScanService createDefault(@NonNull final Config config, @NonNull final ProxyConfig proxyConfig) { + return new DefaultImportScanService(config, proxyConfig); + } - default ImportScanResponse importScan(ScanFile scanFile, long engagementId, long lead, String currentDate, ScanType scanType, long testType) { - return this.importScan(scanFile, engagementId, lead, currentDate, scanType, testType, new HashMap<>()); - } + default ImportScanResponse importScan(ScanFile scanFile, long engagementId, long lead, String currentDate, ScanType scanType, long testType) { + return this.importScan(scanFile, engagementId, lead, currentDate, scanType, testType, new HashMap<>()); + } - ImportScanResponse importScan(ScanFile scanFile, long engagementId, long lead, String currentDate, ScanType scanType, long testType, Map options); + ImportScanResponse importScan(ScanFile scanFile, long engagementId, long lead, String currentDate, ScanType scanType, long testType, Map options); - default ImportScanResponse reimportScan(ScanFile scanFile, long testId, long lead, String currentDate, ScanType scanType, long testType) { - return this.reimportScan(scanFile, testId, lead, currentDate, scanType, testType, new HashMap<>()); - } + default ImportScanResponse reimportScan(ScanFile scanFile, long testId, long lead, String currentDate, ScanType scanType, long testType) { + return this.reimportScan(scanFile, testId, lead, currentDate, scanType, testType, new HashMap<>()); + } - ImportScanResponse reimportScan(ScanFile scanFile, long testId, long lead, String currentDate, ScanType scanType, long testType, Map options); + ImportScanResponse reimportScan(ScanFile scanFile, long testId, long lead, String currentDate, ScanType scanType, long testType, Map options); - @Data - class ImportScanResponse { - @JsonProperty - protected Boolean verified; + @Data + 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/main/java/io/securecodebox/persistence/defectdojo/service/ProductGroupService.java b/src/main/java/io/securecodebox/persistence/defectdojo/service/ProductGroupService.java index 38bc5b58..9dcb9b69 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/service/ProductGroupService.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/service/ProductGroupService.java @@ -7,8 +7,8 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import io.securecodebox.persistence.defectdojo.config.Config; -import io.securecodebox.persistence.defectdojo.model.Response; import io.securecodebox.persistence.defectdojo.model.ProductGroup; +import io.securecodebox.persistence.defectdojo.model.PaginatedResult; public class ProductGroupService extends GenericDefectDojoService { public ProductGroupService(Config config) { @@ -26,7 +26,7 @@ protected Class getModelClass() { } @Override - protected Response deserializeList(String response) throws JsonProcessingException { + protected PaginatedResult deserializeList(String response) throws JsonProcessingException { return this.objectMapper.readValue(response, new TypeReference<>() { }); } diff --git a/src/main/java/io/securecodebox/persistence/defectdojo/service/ProductService.java b/src/main/java/io/securecodebox/persistence/defectdojo/service/ProductService.java index 2a7b420a..6be654a8 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/service/ProductService.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/service/ProductService.java @@ -7,8 +7,8 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import io.securecodebox.persistence.defectdojo.config.Config; -import io.securecodebox.persistence.defectdojo.model.Response; import io.securecodebox.persistence.defectdojo.model.Product; +import io.securecodebox.persistence.defectdojo.model.PaginatedResult; public class ProductService extends GenericDefectDojoService { @@ -27,7 +27,7 @@ protected Class getModelClass() { } @Override - protected Response deserializeList(String response) throws JsonProcessingException { + protected PaginatedResult deserializeList(String response) throws JsonProcessingException { return this.objectMapper.readValue(response, new TypeReference<>() { }); } diff --git a/src/main/java/io/securecodebox/persistence/defectdojo/service/ProductTypeService.java b/src/main/java/io/securecodebox/persistence/defectdojo/service/ProductTypeService.java index ad21be46..55da6c47 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/service/ProductTypeService.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/service/ProductTypeService.java @@ -7,8 +7,8 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import io.securecodebox.persistence.defectdojo.config.Config; -import io.securecodebox.persistence.defectdojo.model.Response; import io.securecodebox.persistence.defectdojo.model.ProductType; +import io.securecodebox.persistence.defectdojo.model.PaginatedResult; public class ProductTypeService extends GenericDefectDojoService { @@ -27,7 +27,7 @@ protected Class getModelClass() { } @Override - protected Response deserializeList(String response) throws JsonProcessingException { + protected PaginatedResult deserializeList(String response) throws JsonProcessingException { return this.objectMapper.readValue(response, new TypeReference<>() { }); } diff --git a/src/main/java/io/securecodebox/persistence/defectdojo/service/TestService.java b/src/main/java/io/securecodebox/persistence/defectdojo/service/TestService.java index 86bf89bc..d2ca576d 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/service/TestService.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/service/TestService.java @@ -7,7 +7,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import io.securecodebox.persistence.defectdojo.config.Config; -import io.securecodebox.persistence.defectdojo.model.Response; +import io.securecodebox.persistence.defectdojo.model.PaginatedResult; import io.securecodebox.persistence.defectdojo.model.Test; public class TestService extends GenericDefectDojoService { @@ -26,7 +26,7 @@ protected Class getModelClass() { } @Override - protected Response deserializeList(String response) throws JsonProcessingException { + protected PaginatedResult deserializeList(String response) throws JsonProcessingException { return this.objectMapper.readValue(response, new TypeReference<>() { }); } diff --git a/src/main/java/io/securecodebox/persistence/defectdojo/service/TestTypeService.java b/src/main/java/io/securecodebox/persistence/defectdojo/service/TestTypeService.java index 758faa4a..ec2b1c4a 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/service/TestTypeService.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/service/TestTypeService.java @@ -7,7 +7,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import io.securecodebox.persistence.defectdojo.config.Config; -import io.securecodebox.persistence.defectdojo.model.Response; +import io.securecodebox.persistence.defectdojo.model.PaginatedResult; import io.securecodebox.persistence.defectdojo.model.TestType; public class TestTypeService extends GenericDefectDojoService { @@ -26,7 +26,7 @@ protected Class getModelClass() { } @Override - protected Response deserializeList(String response) throws JsonProcessingException { + protected PaginatedResult deserializeList(String response) throws JsonProcessingException { return this.objectMapper.readValue(response, new TypeReference<>() { }); } diff --git a/src/main/java/io/securecodebox/persistence/defectdojo/service/ToolConfigService.java b/src/main/java/io/securecodebox/persistence/defectdojo/service/ToolConfigService.java index 77139aac..27894660 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/service/ToolConfigService.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/service/ToolConfigService.java @@ -7,7 +7,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import io.securecodebox.persistence.defectdojo.config.Config; -import io.securecodebox.persistence.defectdojo.model.Response; +import io.securecodebox.persistence.defectdojo.model.PaginatedResult; import io.securecodebox.persistence.defectdojo.model.ToolConfig; public class ToolConfigService extends GenericDefectDojoService { @@ -26,7 +26,7 @@ protected Class getModelClass() { } @Override - protected Response deserializeList(String response) throws JsonProcessingException { + protected PaginatedResult deserializeList(String response) throws JsonProcessingException { return this.objectMapper.readValue(response, new TypeReference<>() { }); } diff --git a/src/main/java/io/securecodebox/persistence/defectdojo/service/ToolTypeService.java b/src/main/java/io/securecodebox/persistence/defectdojo/service/ToolTypeService.java index 25b2824d..24ff54a2 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/service/ToolTypeService.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/service/ToolTypeService.java @@ -7,7 +7,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import io.securecodebox.persistence.defectdojo.config.Config; -import io.securecodebox.persistence.defectdojo.model.Response; +import io.securecodebox.persistence.defectdojo.model.PaginatedResult; import io.securecodebox.persistence.defectdojo.model.ToolType; public class ToolTypeService extends GenericDefectDojoService { @@ -31,7 +31,7 @@ protected Class getModelClass() { } @Override - protected Response deserializeList(String response) throws JsonProcessingException { + protected PaginatedResult deserializeList(String response) throws JsonProcessingException { return this.objectMapper.readValue(response, new TypeReference<>() { }); } diff --git a/src/main/java/io/securecodebox/persistence/defectdojo/service/UserProfileService.java b/src/main/java/io/securecodebox/persistence/defectdojo/service/UserProfileService.java index 835d414b..2db18d77 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/service/UserProfileService.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/service/UserProfileService.java @@ -4,43 +4,42 @@ package io.securecodebox.persistence.defectdojo.service; -import java.util.ArrayList; -import java.util.List; - import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; - import io.securecodebox.persistence.defectdojo.config.Config; -import io.securecodebox.persistence.defectdojo.model.Response; +import io.securecodebox.persistence.defectdojo.model.PaginatedResult; import io.securecodebox.persistence.defectdojo.model.UserProfile; -public class UserProfileService extends GenericDefectDojoService{ - - public UserProfileService(Config config) { - super(config); - } - - @Override - protected String getUrlPath() { - return "user_profile"; - } - - @Override - protected Class getModelClass() { - return UserProfile.class; - } - - @Override - protected Response deserializeList(String response) throws JsonProcessingException { - // GenericDefectDojoService expects that the response from the defectdojo api is a list - // This endpoint returns a single object though, to not break the code this response gets converted to a defectdojo response - UserProfile userProfile = this.objectMapper.readValue(response, new TypeReference<>() {}); - List userProfileList = new ArrayList<>(); - userProfileList.add(userProfile); - - Response fakeResult = new Response<>(); - fakeResult.setResults(userProfileList); - fakeResult.setCount(1); - return fakeResult; - } +import java.util.ArrayList; +import java.util.List; + +public final class UserProfileService extends GenericDefectDojoService { + + public UserProfileService(Config config) { + super(config); + } + + @Override + protected String getUrlPath() { + return "user_profile"; + } + + @Override + protected Class getModelClass() { + return UserProfile.class; + } + + @Override + protected PaginatedResult deserializeList(String response) throws JsonProcessingException { + /* GenericDefectDojoService expects that the response from the defectdojo api is a list. + * This endpoint returns a single object though, to not break the code this response + * gets converted to a defectdojo response. + */ + final var userProfile = this.objectMapper.readValue(response, new TypeReference() { + }); + final var result = new PaginatedResult(); + result.setResults(List.of(userProfile)); + result.setCount(1); + return result; + } } diff --git a/src/main/java/io/securecodebox/persistence/defectdojo/service/UserService.java b/src/main/java/io/securecodebox/persistence/defectdojo/service/UserService.java index 385d2f7a..d9c619e7 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/service/UserService.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/service/UserService.java @@ -7,7 +7,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import io.securecodebox.persistence.defectdojo.config.Config; -import io.securecodebox.persistence.defectdojo.model.Response; +import io.securecodebox.persistence.defectdojo.model.PaginatedResult; import io.securecodebox.persistence.defectdojo.model.User; public class UserService extends GenericDefectDojoService { @@ -26,7 +26,7 @@ protected Class getModelClass() { } @Override - protected Response deserializeList(String response) throws JsonProcessingException { + protected PaginatedResult deserializeList(String response) throws JsonProcessingException { return this.objectMapper.readValue(response, new TypeReference<>() { }); } diff --git a/src/test/java/io/securecodebox/persistence/defectdojo/config/ConfigTest.java b/src/test/java/io/securecodebox/persistence/defectdojo/config/ConfigTest.java index 81f0d6b9..8ffa3de0 100644 --- a/src/test/java/io/securecodebox/persistence/defectdojo/config/ConfigTest.java +++ b/src/test/java/io/securecodebox/persistence/defectdojo/config/ConfigTest.java @@ -5,7 +5,6 @@ package io.securecodebox.persistence.defectdojo.config; import io.securecodebox.persistence.defectdojo.exception.ConfigException; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.params.ParameterizedTest; @@ -14,9 +13,11 @@ import uk.org.webcompere.systemstubs.jupiter.SystemStub; import uk.org.webcompere.systemstubs.jupiter.SystemStubsExtension; -import static org.junit.jupiter.api.Assertions.*; import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.startsWith; +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertThrows; /** * Tests for {@link Config} @@ -24,92 +25,92 @@ @ExtendWith(SystemStubsExtension.class) class ConfigTest { - @SystemStub - private EnvironmentVariables environmentVariables; - - @Test - void constructor_urlMustNotBeNull() { - final var thrown = assertThrows(NullPointerException.class, () -> { - new Config(null, "apiKey", 1); - }); - - assertThat(thrown.getMessage(), startsWith("url ")); - } - - @Test - void constructor_apiKeyMustNotBeNull() { - final var thrown = assertThrows(NullPointerException.class, () -> { - new Config("url", null, 1); - }); - - assertThat(thrown.getMessage(), startsWith("apiKey ")); - } - - @ParameterizedTest - @ValueSource(ints = {0, -1, -2, -23, -42, Integer.MIN_VALUE}) - void constructor_maxPageCountForGetsMustNotBeLessThanOne(final int number) { - final var thrown = assertThrows(IllegalArgumentException.class, () -> { - new Config("url", "apiKey", number); - }); - - assertThat(thrown.getMessage(), startsWith("maxPageCountForGets ")); - } - - @Test - void fromEnv() { - environmentVariables - .set("DEFECTDOJO_URL", "url") - .set("DEFECTDOJO_APIKEY", "apikey") - .set("DEFECTDOJO_MAX_PAGE_COUNT_FOR_GETS", "23"); - - final var sut = Config.fromEnv(); - - assertAll( - () -> assertThat(sut.getUrl(), is("url")), - () -> assertThat(sut.getApiKey(), is("apikey")), - () -> assertThat(sut.getMaxPageCountForGets(), is(23)) - ); - } - - @Test - void fromEnv_throwsExceptionIfNoUrlSet() { - environmentVariables - .set("DEFECTDOJO_APIKEY", "apikey"); - - final var thrown = assertThrows(ConfigException.class, Config::fromEnv); - - assertThat(thrown.getMessage(), is("Missing environment variable 'DEFECTDOJO_URL'!")); - } - - @Test - void fromEnv_throwsExceptionIfNoApiKeySet() { - environmentVariables - .set("DEFECTDOJO_URL", "url"); - - final var thrown = assertThrows(ConfigException.class, Config::fromEnv); - - assertThat(thrown.getMessage(), is("Missing environment variable 'DEFECTDOJO_APIKEY'!")); - } - - @Test - void fromEnv_usesDefaultIfNoMaxPageCountForGetSet() { - environmentVariables - .set("DEFECTDOJO_URL", "url") - .set("DEFECTDOJO_APIKEY", "apikey"); - - final var sut = Config.fromEnv(); - assertThat(sut.getMaxPageCountForGets(), is(Config.DEFAULT_MAX_PAGE_COUNT_FOR_GETS)); - } - - @Test - void fromEnv_throwsExceptionIfMaxPageCountForGetIsNotParseableToInteger() { - environmentVariables - .set("DEFECTDOJO_URL", "url") - .set("DEFECTDOJO_APIKEY", "apikey") - .set("DEFECTDOJO_MAX_PAGE_COUNT_FOR_GETS", "foo"); - - final var thrown = assertThrows(ConfigException.class, Config::fromEnv); - - assertThat(thrown.getMessage(), is("Given value for environment variable 'DEFECTDOJO_MAX_PAGE_COUNT_FOR_GETS' is not a valid number! Given was 'foo'.")); - } + @SystemStub + private EnvironmentVariables environmentVariables; + + @Test + void constructor_urlMustNotBeNull() { + final var thrown = assertThrows(NullPointerException.class, () -> { + new Config(null, "apiKey", 1); + }); + + assertThat(thrown.getMessage(), startsWith("url ")); + } + + @Test + void constructor_apiKeyMustNotBeNull() { + final var thrown = assertThrows(NullPointerException.class, () -> { + new Config("url", null, 1); + }); + + assertThat(thrown.getMessage(), startsWith("apiKey ")); + } + + @ParameterizedTest + @ValueSource(ints = {0, -1, -2, -23, -42, Integer.MIN_VALUE}) + void constructor_maxPageCountForGetsMustNotBeLessThanOne(final int number) { + final var thrown = assertThrows(IllegalArgumentException.class, () -> { + new Config("url", "apiKey", number); + }); + + assertThat(thrown.getMessage(), startsWith("maxPageCountForGets ")); + } + + @Test + void fromEnv() { + environmentVariables + .set("DEFECTDOJO_URL", "url") + .set("DEFECTDOJO_APIKEY", "apikey") + .set("DEFECTDOJO_MAX_PAGE_COUNT_FOR_GETS", "23"); + + final var sut = Config.fromEnv(); + + assertAll( + () -> assertThat(sut.getUrl(), is("url")), + () -> assertThat(sut.getApiKey(), is("apikey")), + () -> assertThat(sut.getMaxPageCountForGets(), is(23)) + ); + } + + @Test + void fromEnv_throwsExceptionIfNoUrlSet() { + environmentVariables + .set("DEFECTDOJO_APIKEY", "apikey"); + + final var thrown = assertThrows(ConfigException.class, Config::fromEnv); + + assertThat(thrown.getMessage(), is("Missing environment variable 'DEFECTDOJO_URL'!")); + } + + @Test + void fromEnv_throwsExceptionIfNoApiKeySet() { + environmentVariables + .set("DEFECTDOJO_URL", "url"); + + final var thrown = assertThrows(ConfigException.class, Config::fromEnv); + + assertThat(thrown.getMessage(), is("Missing environment variable 'DEFECTDOJO_APIKEY'!")); + } + + @Test + void fromEnv_usesDefaultIfNoMaxPageCountForGetSet() { + environmentVariables + .set("DEFECTDOJO_URL", "url") + .set("DEFECTDOJO_APIKEY", "apikey"); + + final var sut = Config.fromEnv(); + assertThat(sut.getMaxPageCountForGets(), is(Config.DEFAULT_MAX_PAGE_COUNT_FOR_GETS)); + } + + @Test + void fromEnv_throwsExceptionIfMaxPageCountForGetIsNotParseableToInteger() { + environmentVariables + .set("DEFECTDOJO_URL", "url") + .set("DEFECTDOJO_APIKEY", "apikey") + .set("DEFECTDOJO_MAX_PAGE_COUNT_FOR_GETS", "foo"); + + final var thrown = assertThrows(ConfigException.class, Config::fromEnv); + + assertThat(thrown.getMessage(), is("Given value for environment variable 'DEFECTDOJO_MAX_PAGE_COUNT_FOR_GETS' is not a valid number! Given was 'foo'.")); + } } diff --git a/src/test/java/io/securecodebox/persistence/defectdojo/http/FooTest.java b/src/test/java/io/securecodebox/persistence/defectdojo/http/FooTest.java index 46f48250..58f6e287 100644 --- a/src/test/java/io/securecodebox/persistence/defectdojo/http/FooTest.java +++ b/src/test/java/io/securecodebox/persistence/defectdojo/http/FooTest.java @@ -5,107 +5,102 @@ package io.securecodebox.persistence.defectdojo.http; import io.securecodebox.persistence.defectdojo.config.Config; -import lombok.NonNull; -import org.apache.http.HttpHost; -import org.apache.http.auth.AuthScope; -import org.apache.http.auth.Credentials; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.springframework.http.HttpHeaders; -import static org.junit.jupiter.api.Assertions.*; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*; +import static org.junit.jupiter.api.Assertions.assertAll; /** * Tests for {@link Foo} */ class FooTest { - private final Config config = new Config("url", "apikey"); - private final ProxyConfig proxyConfig = ProxyConfig.builder() - .user("user") - .password("pw") - .host("host") - .port(42) - .build(); - private final Foo sut = new Foo(config, proxyConfig); - - @Test - void generateAuthorizationHeaders_withoutProxyAuth() { - final var innerSut = new Foo(config, ProxyConfig.NULL); - - assertAll( - () -> assertThat( - innerSut.generateAuthorizationHeaders().get(HttpHeaders.AUTHORIZATION), - contains("Token apikey")), - () -> assertThat( - innerSut.generateAuthorizationHeaders().get(HttpHeaders.PROXY_AUTHORIZATION), - not(contains("Basic dXNlcjpwdw=="))) - ); - } - - @Test - void generateAuthorizationHeaders_withProxyAuth() { - final var innerSut = new Foo(config, proxyConfig); - - assertAll( - () -> assertThat( - innerSut.generateAuthorizationHeaders().get(HttpHeaders.AUTHORIZATION), - contains("Token apikey")), - () -> assertThat( - innerSut.generateAuthorizationHeaders().get(HttpHeaders.PROXY_AUTHORIZATION), - contains("Basic dXNlcjpwdw==")) - ); - } - - @Test - void encodeProxyCredentials() { - final var proxyConfig = ProxyConfig.builder() - .user("bärtram") - .password("gohze8Ae") - .build(); - - assertThat(Foo.encodeProxyCredentials(proxyConfig), is("YsOkcnRyYW06Z29oemU4QWU=")); - } - - @Test - void createCredentialsProvider() { - final var result = sut.createCredentialsProvider(); - final var credentials = result.getCredentials(sut.createAuthScope()); - - assertAll( - () -> assertThat(credentials.getUserPrincipal().getName(), is(proxyConfig.getUser())), - () -> assertThat(credentials.getPassword(), is(proxyConfig.getPassword())) - ); - } - - @Test - void createAuthScope() { - final var result = sut.createAuthScope(); - - assertAll( - () -> assertThat(result.getHost(), is(proxyConfig.getHost())), - () -> assertThat(result.getPort(), is(proxyConfig.getPort())) - ); - } - - @Test - void createCredentials() { - final var result = sut.createCredentials(); - - assertAll( - () -> assertThat(result.getUserPrincipal().getName(), is(proxyConfig.getUser())), - () -> assertThat(result.getPassword(), is(proxyConfig.getPassword())) - ); - } - - @Test - void createHttpHost() { - final var result = sut.createHttpHost(); - - assertAll( - () -> assertThat(result.getHostName(), is(proxyConfig.getHost())), - () -> assertThat(result.getPort(), is(proxyConfig.getPort())) - ); - } + private final Config config = new Config("url", "apikey"); + private final ProxyConfig proxyConfig = ProxyConfig.builder() + .user("user") + .password("pw") + .host("host") + .port(42) + .build(); + private final Foo sut = new Foo(config, proxyConfig); + + @Test + void generateAuthorizationHeaders_withoutProxyAuth() { + final var innerSut = new Foo(config, ProxyConfig.NULL); + + assertAll( + () -> assertThat( + innerSut.generateAuthorizationHeaders().get(HttpHeaders.AUTHORIZATION), + contains("Token apikey")), + () -> assertThat( + innerSut.generateAuthorizationHeaders().get(HttpHeaders.PROXY_AUTHORIZATION), + not(contains("Basic dXNlcjpwdw=="))) + ); + } + + @Test + void generateAuthorizationHeaders_withProxyAuth() { + final var innerSut = new Foo(config, proxyConfig); + + assertAll( + () -> assertThat( + innerSut.generateAuthorizationHeaders().get(HttpHeaders.AUTHORIZATION), + contains("Token apikey")), + () -> assertThat( + innerSut.generateAuthorizationHeaders().get(HttpHeaders.PROXY_AUTHORIZATION), + contains("Basic dXNlcjpwdw==")) + ); + } + + @Test + void encodeProxyCredentials() { + final var proxyConfig = ProxyConfig.builder() + .user("bärtram") + .password("gohze8Ae") + .build(); + + assertThat(Foo.encodeProxyCredentials(proxyConfig), is("YsOkcnRyYW06Z29oemU4QWU=")); + } + + @Test + void createCredentialsProvider() { + final var result = sut.createCredentialsProvider(); + final var credentials = result.getCredentials(sut.createAuthScope()); + + assertAll( + () -> assertThat(credentials.getUserPrincipal().getName(), is(proxyConfig.getUser())), + () -> assertThat(credentials.getPassword(), is(proxyConfig.getPassword())) + ); + } + + @Test + void createAuthScope() { + final var result = sut.createAuthScope(); + + assertAll( + () -> assertThat(result.getHost(), is(proxyConfig.getHost())), + () -> assertThat(result.getPort(), is(proxyConfig.getPort())) + ); + } + + @Test + void createCredentials() { + final var result = sut.createCredentials(); + + assertAll( + () -> assertThat(result.getUserPrincipal().getName(), is(proxyConfig.getUser())), + () -> assertThat(result.getPassword(), is(proxyConfig.getPassword())) + ); + } + + @Test + void createHttpHost() { + final var result = sut.createHttpHost(); + + assertAll( + () -> assertThat(result.getHostName(), is(proxyConfig.getHost())), + () -> assertThat(result.getPort(), is(proxyConfig.getPort())) + ); + } } diff --git a/src/test/java/io/securecodebox/persistence/defectdojo/http/MissingProxyConfigValueTest.java b/src/test/java/io/securecodebox/persistence/defectdojo/http/MissingProxyConfigValueTest.java index 75613bc5..c76909ac 100644 --- a/src/test/java/io/securecodebox/persistence/defectdojo/http/MissingProxyConfigValueTest.java +++ b/src/test/java/io/securecodebox/persistence/defectdojo/http/MissingProxyConfigValueTest.java @@ -6,18 +6,17 @@ import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.is; /** * Tests for {@link MissingProxyConfigValue} */ class MissingProxyConfigValueTest { - @Test - void rendersMessageFromProxyConfigName() { - final var sut = new MissingProxyConfigValue(ProxyConfigNames.HTTP_PROXY_HOST); + @Test + void rendersMessageFromProxyConfigName() { + final var sut = new MissingProxyConfigValue(ProxyConfigNames.HTTP_PROXY_HOST); - assertThat(sut.getMessage(), is("Expected system property 'http.proxyHost' not set!")); - } + assertThat(sut.getMessage(), is("Expected system property 'http.proxyHost' not set!")); + } } diff --git a/src/test/java/io/securecodebox/persistence/defectdojo/http/ProxyConfigFactoryTest.java b/src/test/java/io/securecodebox/persistence/defectdojo/http/ProxyConfigFactoryTest.java index 63e6fb42..37a1b970 100644 --- a/src/test/java/io/securecodebox/persistence/defectdojo/http/ProxyConfigFactoryTest.java +++ b/src/test/java/io/securecodebox/persistence/defectdojo/http/ProxyConfigFactoryTest.java @@ -11,7 +11,8 @@ import uk.org.webcompere.systemstubs.properties.SystemProperties; import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.is; import static org.junit.jupiter.api.Assertions.assertThrows; /** @@ -19,87 +20,87 @@ */ @ExtendWith(SystemStubsExtension.class) class ProxyConfigFactoryTest { - @SystemStub - private SystemProperties restoreSystemProperties; - private final ProxyConfigFactory sut = new ProxyConfigFactory(); - - @Test - void create_returnsDefaultIfUserAndPasswordNotPresent() { - assertThat(sut.create(), is(ProxyConfigFactory.DEFAULT_CONFIG)); - } - - @Test - void create_returnsDefaultIfUserNotPresent() { - System.setProperty(ProxyConfigNames.HTTP_PROXY_USER.getLiterat(), "user"); - - assertThat(sut.create(), is(ProxyConfigFactory.DEFAULT_CONFIG)); - } - - @Test - void create_returnsDefaultIfPasswordNotPresent() { - System.setProperty(ProxyConfigNames.HTTP_PROXY_PASSWORD.getLiterat(), "password"); - - assertThat(sut.create(), is(ProxyConfigFactory.DEFAULT_CONFIG)); - } - - @Test - void create_returnsCompleteConfigIfAllPropertiesArePresent() { - System.setProperty(ProxyConfigNames.HTTP_PROXY_USER.getLiterat(), "user"); - System.setProperty(ProxyConfigNames.HTTP_PROXY_PASSWORD.getLiterat(), "password"); - System.setProperty(ProxyConfigNames.HTTP_PROXY_HOST.getLiterat(), "host"); - System.setProperty(ProxyConfigNames.HTTP_PROXY_PORT.getLiterat(), "4242"); - - final var expected = ProxyConfig.builder() - .user("user") - .password("password") - .host("host") - .port(4242) - .build(); - - assertThat(sut.create(), is(expected)); - } - - @Test - void create_throwsExceptionIfHostNotSet() { - System.setProperty(ProxyConfigNames.HTTP_PROXY_USER.getLiterat(), "user"); - System.setProperty(ProxyConfigNames.HTTP_PROXY_PASSWORD.getLiterat(), "password"); - System.clearProperty(ProxyConfigNames.HTTP_PROXY_HOST.getLiterat()); - System.setProperty(ProxyConfigNames.HTTP_PROXY_PORT.getLiterat(), "4242"); - - final var thrown = assertThrows( - MissingProxyConfigValue.class, - sut::create); - - assertThat(thrown.getMessage(), containsString("'http.proxyHost'")); - } - - @Test - void create_throwsExceptionIfPortNotSet() { - System.setProperty(ProxyConfigNames.HTTP_PROXY_USER.getLiterat(), "user"); - System.setProperty(ProxyConfigNames.HTTP_PROXY_PASSWORD.getLiterat(), "password"); - System.setProperty(ProxyConfigNames.HTTP_PROXY_HOST.getLiterat(), "host"); - System.clearProperty(ProxyConfigNames.HTTP_PROXY_PORT.getLiterat()); - - final var thrown = assertThrows( - MissingProxyConfigValue.class, - sut::create); - - assertThat(thrown.getMessage(), containsString("'http.proxyPort'")); - } - - @Test - void create_throwsExceptionIfPortIsNotInteger() { - System.setProperty(ProxyConfigNames.HTTP_PROXY_USER.getLiterat(), "user"); - System.setProperty(ProxyConfigNames.HTTP_PROXY_PASSWORD.getLiterat(), "password"); - System.setProperty(ProxyConfigNames.HTTP_PROXY_HOST.getLiterat(), "host"); - System.setProperty(ProxyConfigNames.HTTP_PROXY_PORT.getLiterat(), "FUBAR"); - - final var thrown = assertThrows( - IllegalArgumentException.class, - sut::create); - - assertThat( - thrown.getMessage(), - is("Given port for proxy authentication configuration (property 'http.proxyPort') is not a valid number! Given value wa 'FUBAR'.")); - } + @SystemStub + private SystemProperties restoreSystemProperties; + private final ProxyConfigFactory sut = new ProxyConfigFactory(); + + @Test + void create_returnsDefaultIfUserAndPasswordNotPresent() { + assertThat(sut.create(), is(ProxyConfigFactory.DEFAULT_CONFIG)); + } + + @Test + void create_returnsDefaultIfUserNotPresent() { + System.setProperty(ProxyConfigNames.HTTP_PROXY_USER.getLiterat(), "user"); + + assertThat(sut.create(), is(ProxyConfigFactory.DEFAULT_CONFIG)); + } + + @Test + void create_returnsDefaultIfPasswordNotPresent() { + System.setProperty(ProxyConfigNames.HTTP_PROXY_PASSWORD.getLiterat(), "password"); + + assertThat(sut.create(), is(ProxyConfigFactory.DEFAULT_CONFIG)); + } + + @Test + void create_returnsCompleteConfigIfAllPropertiesArePresent() { + System.setProperty(ProxyConfigNames.HTTP_PROXY_USER.getLiterat(), "user"); + System.setProperty(ProxyConfigNames.HTTP_PROXY_PASSWORD.getLiterat(), "password"); + System.setProperty(ProxyConfigNames.HTTP_PROXY_HOST.getLiterat(), "host"); + System.setProperty(ProxyConfigNames.HTTP_PROXY_PORT.getLiterat(), "4242"); + + final var expected = ProxyConfig.builder() + .user("user") + .password("password") + .host("host") + .port(4242) + .build(); + + assertThat(sut.create(), is(expected)); + } + + @Test + void create_throwsExceptionIfHostNotSet() { + System.setProperty(ProxyConfigNames.HTTP_PROXY_USER.getLiterat(), "user"); + System.setProperty(ProxyConfigNames.HTTP_PROXY_PASSWORD.getLiterat(), "password"); + System.clearProperty(ProxyConfigNames.HTTP_PROXY_HOST.getLiterat()); + System.setProperty(ProxyConfigNames.HTTP_PROXY_PORT.getLiterat(), "4242"); + + final var thrown = assertThrows( + MissingProxyConfigValue.class, + sut::create); + + assertThat(thrown.getMessage(), containsString("'http.proxyHost'")); + } + + @Test + void create_throwsExceptionIfPortNotSet() { + System.setProperty(ProxyConfigNames.HTTP_PROXY_USER.getLiterat(), "user"); + System.setProperty(ProxyConfigNames.HTTP_PROXY_PASSWORD.getLiterat(), "password"); + System.setProperty(ProxyConfigNames.HTTP_PROXY_HOST.getLiterat(), "host"); + System.clearProperty(ProxyConfigNames.HTTP_PROXY_PORT.getLiterat()); + + final var thrown = assertThrows( + MissingProxyConfigValue.class, + sut::create); + + assertThat(thrown.getMessage(), containsString("'http.proxyPort'")); + } + + @Test + void create_throwsExceptionIfPortIsNotInteger() { + System.setProperty(ProxyConfigNames.HTTP_PROXY_USER.getLiterat(), "user"); + System.setProperty(ProxyConfigNames.HTTP_PROXY_PASSWORD.getLiterat(), "password"); + System.setProperty(ProxyConfigNames.HTTP_PROXY_HOST.getLiterat(), "host"); + System.setProperty(ProxyConfigNames.HTTP_PROXY_PORT.getLiterat(), "FUBAR"); + + final var thrown = assertThrows( + IllegalArgumentException.class, + sut::create); + + assertThat( + thrown.getMessage(), + is("Given port for proxy authentication configuration (property 'http.proxyPort') is not a valid number! Given value wa 'FUBAR'.")); + } } diff --git a/src/test/java/io/securecodebox/persistence/defectdojo/http/ProxyConfigTest.java b/src/test/java/io/securecodebox/persistence/defectdojo/http/ProxyConfigTest.java index bb93248f..0dd4bf2a 100644 --- a/src/test/java/io/securecodebox/persistence/defectdojo/http/ProxyConfigTest.java +++ b/src/test/java/io/securecodebox/persistence/defectdojo/http/ProxyConfigTest.java @@ -12,76 +12,77 @@ import java.util.stream.Stream; -import static org.junit.jupiter.api.Assertions.*; import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.emptyString; +import static org.hamcrest.Matchers.is; +import static org.junit.jupiter.api.Assertions.assertAll; /** * Tests for {@link ProxyConfig} */ class ProxyConfigTest { - @Test - void equalsAndHashCode() { - EqualsVerifier.forClass(ProxyConfig.class).verify(); - } + @Test + void equalsAndHashCode() { + EqualsVerifier.forClass(ProxyConfig.class).verify(); + } - @Test - void builderCreatesDefault() { - final var sut = ProxyConfig.builder().build(); + @Test + void builderCreatesDefault() { + final var sut = ProxyConfig.builder().build(); - assertAll( - () -> assertThat(sut.getUser(), is(emptyString())), - () -> assertThat(sut.getPassword(), is(emptyString())), - () -> assertThat(sut.getHost(), is(emptyString())), - () -> assertThat(sut.getPort(), is(0)) - ); - } + assertAll( + () -> assertThat(sut.getUser(), is(emptyString())), + () -> assertThat(sut.getPassword(), is(emptyString())), + () -> assertThat(sut.getHost(), is(emptyString())), + () -> assertThat(sut.getPort(), is(0)) + ); + } - @Test - void buildersDefaultIsEqualToNullObject() { - assertThat(ProxyConfig.builder().build(), is(ProxyConfig.NULL)); - } + @Test + void buildersDefaultIsEqualToNullObject() { + assertThat(ProxyConfig.builder().build(), is(ProxyConfig.NULL)); + } - @Test - void isComplete_falseForNullObject() { - assertThat(ProxyConfig.NULL.isComplete(), is(false)); - } + @Test + void isComplete_falseForNullObject() { + assertThat(ProxyConfig.NULL.isComplete(), is(false)); + } - @Test - void isComplete_falseForDefault() { - assertThat(ProxyConfig.builder().build().isComplete(), is(false)); - } + @Test + void isComplete_falseForDefault() { + assertThat(ProxyConfig.builder().build().isComplete(), is(false)); + } - @ParameterizedTest - @MethodSource("incompleteConfigs") - void isComplete_falseUnlessAllFieldsAreSet(final ProxyConfig sut) { + @ParameterizedTest + @MethodSource("incompleteConfigs") + void isComplete_falseUnlessAllFieldsAreSet(final ProxyConfig sut) { - } + } - private static Stream incompleteConfigs() { - return Stream.of( - // Only one is set: - Arguments.of(ProxyConfig.builder().user("user").build()), - Arguments.of(ProxyConfig.builder().password("pw").build()), - Arguments.of(ProxyConfig.builder().host("host").build()), - Arguments.of(ProxyConfig.builder().port(42).build()), - // All but one is set: - Arguments.of(ProxyConfig.builder().password("pwd").host("host").port(42).build()), - Arguments.of(ProxyConfig.builder().user("user").host("host").port(42).build()), - Arguments.of(ProxyConfig.builder().user("user").password("pwd").port(42).build()), - Arguments.of(ProxyConfig.builder().user("user").password("pwd").host("host").build()) - ); - } + private static Stream incompleteConfigs() { + return Stream.of( + // Only one is set: + Arguments.of(ProxyConfig.builder().user("user").build()), + Arguments.of(ProxyConfig.builder().password("pw").build()), + Arguments.of(ProxyConfig.builder().host("host").build()), + Arguments.of(ProxyConfig.builder().port(42).build()), + // All but one is set: + Arguments.of(ProxyConfig.builder().password("pwd").host("host").port(42).build()), + Arguments.of(ProxyConfig.builder().user("user").host("host").port(42).build()), + Arguments.of(ProxyConfig.builder().user("user").password("pwd").port(42).build()), + Arguments.of(ProxyConfig.builder().user("user").password("pwd").host("host").build()) + ); + } - @Test - void isComplete_trueIfAllFieldsAreNonDefaults() { - final var sut = ProxyConfig.builder() - .user("user") - .password("pw") - .host("host") - .port(42) - .build(); + @Test + void isComplete_trueIfAllFieldsAreNonDefaults() { + final var sut = ProxyConfig.builder() + .user("user") + .password("pw") + .host("host") + .port(42) + .build(); - assertThat(sut.isComplete(), is(true)); - } + assertThat(sut.isComplete(), is(true)); + } } diff --git a/src/test/java/io/securecodebox/persistence/defectdojo/model/EndpointTest.java b/src/test/java/io/securecodebox/persistence/defectdojo/model/EndpointTest.java index 8f4445b4..e93348cc 100644 --- a/src/test/java/io/securecodebox/persistence/defectdojo/model/EndpointTest.java +++ b/src/test/java/io/securecodebox/persistence/defectdojo/model/EndpointTest.java @@ -1,20 +1,40 @@ package io.securecodebox.persistence.defectdojo.model; import nl.jqno.equalsverifier.EqualsVerifier; -import org.junit.jupiter.api.Disabled; +import nl.jqno.equalsverifier.Warning; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; +import java.util.HashMap; + import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.is; /** * Tests for {@link Endpoint} */ class EndpointTest { - @Test - @Disabled("#23 Fails due to wrong equals implementation") - void equalsAndHashCode() { - EqualsVerifier.forClass(Endpoint.class).verify(); - } + @Test + void equalsAndHashCode() { + EqualsVerifier.forClass(Endpoint.class) + .suppress(Warning.NONFINAL_FIELDS) + .verify(); + } + + @Test + void equalsQueryString_id() { + final var sut = Endpoint.builder().build(); + assertThat(sut.equalsQueryString(null), is(false)); + + final var params = new HashMap(); + assertThat(sut.equalsQueryString(params), is(false)); + + params.put("id", 42L); + assertThat(sut.equalsQueryString(params), is(false)); + + sut.setId(23L); + assertThat(sut.equalsQueryString(params), is(false)); + + sut.setId(42L); + assertThat(sut.equalsQueryString(params), is(true)); + } } diff --git a/src/test/java/io/securecodebox/persistence/defectdojo/model/EngagementTest.java b/src/test/java/io/securecodebox/persistence/defectdojo/model/EngagementTest.java index bf2210cd..e5973790 100644 --- a/src/test/java/io/securecodebox/persistence/defectdojo/model/EngagementTest.java +++ b/src/test/java/io/securecodebox/persistence/defectdojo/model/EngagementTest.java @@ -1,20 +1,58 @@ package io.securecodebox.persistence.defectdojo.model; import nl.jqno.equalsverifier.EqualsVerifier; -import org.junit.jupiter.api.Disabled; +import nl.jqno.equalsverifier.Warning; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; +import java.util.HashMap; + import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.is; /** * Tests for {@link Engagement} */ class EngagementTest { - @Test - @Disabled("#23 Fails due to wrong equals implementation") - void equalsAndHashCode() { - EqualsVerifier.forClass(Engagement.class).verify(); - } + @Test + void equalsAndHashCode() { + EqualsVerifier.forClass(Engagement.class) + .suppress(Warning.NONFINAL_FIELDS) + .verify(); + } + + @Test + void equalsQueryString_id() { + final var sut = Engagement.builder().build(); + assertThat(sut.equalsQueryString(null), is(false)); + + final var params = new HashMap(); + assertThat(sut.equalsQueryString(params), is(false)); + + params.put("id", 42L); + assertThat(sut.equalsQueryString(params), is(false)); + + sut.setId(23L); + assertThat(sut.equalsQueryString(params), is(false)); + + sut.setId(42L); + assertThat(sut.equalsQueryString(params), is(true)); + } + + @Test + void equalsQueryString_name() { + final var sut = Engagement.builder().build(); + assertThat(sut.equalsQueryString(null), is(false)); + + final var params = new HashMap(); + assertThat(sut.equalsQueryString(params), is(false)); + + params.put("name", "foobar"); + assertThat(sut.equalsQueryString(params), is(false)); + + sut.setName("snafu"); + assertThat(sut.equalsQueryString(params), is(false)); + + sut.setName("foobar"); + assertThat(sut.equalsQueryString(params), is(true)); + } } diff --git a/src/test/java/io/securecodebox/persistence/defectdojo/model/FindingTest.java b/src/test/java/io/securecodebox/persistence/defectdojo/model/FindingTest.java index 766a8063..db173323 100644 --- a/src/test/java/io/securecodebox/persistence/defectdojo/model/FindingTest.java +++ b/src/test/java/io/securecodebox/persistence/defectdojo/model/FindingTest.java @@ -1,20 +1,46 @@ package io.securecodebox.persistence.defectdojo.model; import nl.jqno.equalsverifier.EqualsVerifier; -import org.junit.jupiter.api.Disabled; +import nl.jqno.equalsverifier.Warning; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; +import java.util.Collections; +import java.util.HashMap; + import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.is; /** * Tests for {@link Finding} */ class FindingTest { - @Test - @Disabled("#23 Fails due to wrong equals implementation") - void equalsAndHashCode() { - EqualsVerifier.forClass(Finding.class).verify(); - } + @Test + void equalsAndHashCode() { + EqualsVerifier.forClass(Finding.class) + .suppress(Warning.NONFINAL_FIELDS) + .verify(); + } + + @Test + void equalsQueryString_id() { + final var sut = Finding.builder() + .title("title") + .description("description") + .foundBy(Collections.emptyList()) + .severity(Finding.Severity.INFORMATIONAL) + .build(); + assertThat(sut.equalsQueryString(null), is(false)); + + final var params = new HashMap(); + assertThat(sut.equalsQueryString(params), is(false)); + + params.put("id", 42L); + assertThat(sut.equalsQueryString(params), is(false)); + + sut.setId(23L); + assertThat(sut.equalsQueryString(params), is(false)); + + sut.setId(42L); + assertThat(sut.equalsQueryString(params), is(true)); + } } diff --git a/src/test/java/io/securecodebox/persistence/defectdojo/model/GroupMemberTest.java b/src/test/java/io/securecodebox/persistence/defectdojo/model/GroupMemberTest.java index b6819a80..0fc280d5 100644 --- a/src/test/java/io/securecodebox/persistence/defectdojo/model/GroupMemberTest.java +++ b/src/test/java/io/securecodebox/persistence/defectdojo/model/GroupMemberTest.java @@ -1,20 +1,17 @@ package io.securecodebox.persistence.defectdojo.model; import nl.jqno.equalsverifier.EqualsVerifier; -import org.junit.jupiter.api.Disabled; +import nl.jqno.equalsverifier.Warning; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.*; - /** * Tests for {@link GroupMember} */ class GroupMemberTest { - @Test - @Disabled("#23 Fails due to wrong equals implementation") - void equalsAndHashCode() { - EqualsVerifier.forClass(GroupMember.class).verify(); - } + @Test + void equalsAndHashCode() { + EqualsVerifier.forClass(GroupMember.class) + .suppress(Warning.NONFINAL_FIELDS) + .verify(); + } } diff --git a/src/test/java/io/securecodebox/persistence/defectdojo/model/GroupTest.java b/src/test/java/io/securecodebox/persistence/defectdojo/model/GroupTest.java index cbf1ccfd..725c0c97 100644 --- a/src/test/java/io/securecodebox/persistence/defectdojo/model/GroupTest.java +++ b/src/test/java/io/securecodebox/persistence/defectdojo/model/GroupTest.java @@ -1,20 +1,62 @@ package io.securecodebox.persistence.defectdojo.model; import nl.jqno.equalsverifier.EqualsVerifier; -import org.junit.jupiter.api.Disabled; +import nl.jqno.equalsverifier.Warning; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; +import java.util.HashMap; + import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.is; /** * Tests for {@link Group} */ class GroupTest { - @Test - @Disabled("#23 Fails due to wrong equals implementation") - void equalsAndHashCode() { - EqualsVerifier.forClass(Group.class).verify(); - } + @Test + void equalsAndHashCode() { + EqualsVerifier.forClass(Group.class) + .suppress(Warning.NONFINAL_FIELDS) + .verify(); + } + + @Test + void equalsQueryString_id() { + final var sut = Group.builder() + .name("") + .build(); + assertThat(sut.equalsQueryString(null), is(false)); + + final var params = new HashMap(); + assertThat(sut.equalsQueryString(params), is(false)); + + params.put("id", 42L); + assertThat(sut.equalsQueryString(params), is(false)); + + sut.setId(23L); + assertThat(sut.equalsQueryString(params), is(false)); + + sut.setId(42L); + assertThat(sut.equalsQueryString(params), is(true)); + } + + @Test + void equalsQueryString_name() { + final var sut = Group.builder() + .name("") + .build(); + assertThat(sut.equalsQueryString(null), is(false)); + + final var params = new HashMap(); + assertThat(sut.equalsQueryString(params), is(false)); + + params.put("name", "foobar"); + assertThat(sut.equalsQueryString(params), is(false)); + + sut.setName("snafu"); + assertThat(sut.equalsQueryString(params), is(false)); + + sut.setName("foobar"); + assertThat(sut.equalsQueryString(params), is(true)); + } } diff --git a/src/test/java/io/securecodebox/persistence/defectdojo/model/PaginatedResultTest.java b/src/test/java/io/securecodebox/persistence/defectdojo/model/PaginatedResultTest.java new file mode 100644 index 00000000..8c2d661c --- /dev/null +++ b/src/test/java/io/securecodebox/persistence/defectdojo/model/PaginatedResultTest.java @@ -0,0 +1,17 @@ +package io.securecodebox.persistence.defectdojo.model; + +import nl.jqno.equalsverifier.EqualsVerifier; +import nl.jqno.equalsverifier.Warning; +import org.junit.jupiter.api.Test; + +/** + * Tests for {@link PaginatedResult} + */ +class PaginatedResultTest { + @Test + void equalsAndHashCode() { + EqualsVerifier.forClass(PaginatedResult.class) + .suppress(Warning.NONFINAL_FIELDS) + .verify(); + } +} diff --git a/src/test/java/io/securecodebox/persistence/defectdojo/model/ProductGroupTest.java b/src/test/java/io/securecodebox/persistence/defectdojo/model/ProductGroupTest.java index bddce658..81bec777 100644 --- a/src/test/java/io/securecodebox/persistence/defectdojo/model/ProductGroupTest.java +++ b/src/test/java/io/securecodebox/persistence/defectdojo/model/ProductGroupTest.java @@ -1,20 +1,17 @@ package io.securecodebox.persistence.defectdojo.model; import nl.jqno.equalsverifier.EqualsVerifier; -import org.junit.jupiter.api.Disabled; +import nl.jqno.equalsverifier.Warning; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.*; - /** * Tests for {@link ProductGroup} */ class ProductGroupTest { - @Test - @Disabled("#23 Fails due to wrong equals implementation") - void equalsAndHashCode() { - EqualsVerifier.forClass(ProductGroup.class).verify(); - } + @Test + void equalsAndHashCode() { + EqualsVerifier.forClass(ProductGroup.class) + .suppress(Warning.NONFINAL_FIELDS) + .verify(); + } } diff --git a/src/test/java/io/securecodebox/persistence/defectdojo/model/ProductTest.java b/src/test/java/io/securecodebox/persistence/defectdojo/model/ProductTest.java index d1ba9918..7bf448b0 100644 --- a/src/test/java/io/securecodebox/persistence/defectdojo/model/ProductTest.java +++ b/src/test/java/io/securecodebox/persistence/defectdojo/model/ProductTest.java @@ -1,20 +1,62 @@ package io.securecodebox.persistence.defectdojo.model; import nl.jqno.equalsverifier.EqualsVerifier; -import org.junit.jupiter.api.Disabled; +import nl.jqno.equalsverifier.Warning; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; +import java.util.HashMap; + import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.is; /** * Tests for {@link Product} */ class ProductTest { - @Test - @Disabled("#23 Fails due to wrong equals implementation") - void equalsAndHashCode() { - EqualsVerifier.forClass(Product.class).verify(); - } + @Test + void equalsAndHashCode() { + EqualsVerifier.forClass(Product.class) + .suppress(Warning.NONFINAL_FIELDS) + .verify(); + } + + @Test + void equalsQueryString_id() { + final var sut = Product.builder() + .name("") + .build(); + assertThat(sut.equalsQueryString(null), is(false)); + + final var params = new HashMap(); + assertThat(sut.equalsQueryString(params), is(false)); + + params.put("id", 42L); + assertThat(sut.equalsQueryString(params), is(false)); + + sut.setId(23L); + assertThat(sut.equalsQueryString(params), is(false)); + + sut.setId(42L); + assertThat(sut.equalsQueryString(params), is(true)); + } + + @Test + void equalsQueryString_name() { + final var sut = Product.builder() + .name("") + .build(); + assertThat(sut.equalsQueryString(null), is(false)); + + final var params = new HashMap(); + assertThat(sut.equalsQueryString(params), is(false)); + + params.put("name", "foobar"); + assertThat(sut.equalsQueryString(params), is(false)); + + sut.setName("snafu"); + assertThat(sut.equalsQueryString(params), is(false)); + + sut.setName("foobar"); + assertThat(sut.equalsQueryString(params), is(true)); + } } diff --git a/src/test/java/io/securecodebox/persistence/defectdojo/model/ProductTypeTest.java b/src/test/java/io/securecodebox/persistence/defectdojo/model/ProductTypeTest.java index ff703735..f301599a 100644 --- a/src/test/java/io/securecodebox/persistence/defectdojo/model/ProductTypeTest.java +++ b/src/test/java/io/securecodebox/persistence/defectdojo/model/ProductTypeTest.java @@ -1,20 +1,62 @@ package io.securecodebox.persistence.defectdojo.model; import nl.jqno.equalsverifier.EqualsVerifier; -import org.junit.jupiter.api.Disabled; +import nl.jqno.equalsverifier.Warning; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; +import java.util.HashMap; + import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.is; /** * Tests for {@link ProductType} */ class ProductTypeTest { - @Test - @Disabled("#23 Fails due to wrong equals implementation") - void equalsAndHashCode() { - EqualsVerifier.forClass(ProductType.class).verify(); - } + @Test + void equalsAndHashCode() { + EqualsVerifier.forClass(ProductType.class) + .suppress(Warning.NONFINAL_FIELDS) + .verify(); + } + + @Test + void equalsQueryString_id() { + final var sut = ProductType.builder() + .name("") + .build(); + assertThat(sut.equalsQueryString(null), is(false)); + + final var params = new HashMap(); + assertThat(sut.equalsQueryString(params), is(false)); + + params.put("id", 42L); + assertThat(sut.equalsQueryString(params), is(false)); + + sut.setId(23L); + assertThat(sut.equalsQueryString(params), is(false)); + + sut.setId(42L); + assertThat(sut.equalsQueryString(params), is(true)); + } + + @Test + void equalsQueryString_name() { + final var sut = ProductType.builder() + .name("") + .build(); + assertThat(sut.equalsQueryString(null), is(false)); + + final var params = new HashMap(); + assertThat(sut.equalsQueryString(params), is(false)); + + params.put("name", "foobar"); + assertThat(sut.equalsQueryString(params), is(false)); + + sut.setName("snafu"); + assertThat(sut.equalsQueryString(params), is(false)); + + sut.setName("foobar"); + assertThat(sut.equalsQueryString(params), is(true)); + } } diff --git a/src/test/java/io/securecodebox/persistence/defectdojo/model/QueryParamsComparatorTest.java b/src/test/java/io/securecodebox/persistence/defectdojo/model/QueryParamsComparatorTest.java new file mode 100644 index 00000000..9a6ebad8 --- /dev/null +++ b/src/test/java/io/securecodebox/persistence/defectdojo/model/QueryParamsComparatorTest.java @@ -0,0 +1,144 @@ +// SPDX-FileCopyrightText: the secureCodeBox authors +// +// SPDX-License-Identifier: Apache-2.0 + +package io.securecodebox.persistence.defectdojo.model; + +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +import java.util.Collections; +import java.util.HashMap; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +/** + * Tests for {@link QueryParamsComparator} + */ +class QueryParamsComparatorTest { + @Test + void isNull() { + assertAll( + () -> assertThat(QueryParamsComparator.isNull(null), is(true)), + () -> assertThat(QueryParamsComparator.isNull(Collections.emptyMap()), is(false)) + ); + } + + @Test + void isIdEqual_falseIfModelIsNull() { + assertThat( + QueryParamsComparator.isIdEqual(null, Collections.emptyMap()), + is(false)); + } + + @Test + void isIdEqual_falseIfQueryParamsIsNull() { + assertThat( + QueryParamsComparator.isIdEqual(mock(HasId.class), null), + is(false)); + } + + @Test + void isIdEqual_falseIfQueryParamsDoesNotContainId() { + assertThat( + QueryParamsComparator.isIdEqual(mock(HasId.class), Collections.emptyMap()), + is(false)); + } + + @Test + void isIdEqual_falseIfQueryParamValueIsNull() { + final var queryParams = new HashMap(); + queryParams.put(QueryParamsComparator.QUERY_PARAM_KEY_FOR_ID, null); + + assertThat( + QueryParamsComparator.isIdEqual(mock(HasId.class), queryParams), + is(false)); + } + + @Test + void isIdEqual_trueForSameNumbers() { + final var model = mock(HasId.class); + when(model.getId()).thenReturn(42L); + + final var queryParams = new HashMap(); + queryParams.put(QueryParamsComparator.QUERY_PARAM_KEY_FOR_ID, 42L); + + assertThat( + QueryParamsComparator.isIdEqual(model, queryParams), + is(true)); + } + + @Test + void isIdEqual_falseForDifferentNumbers() { + final var model = mock(HasId.class); + when(model.getId()).thenReturn(42L); + + final var queryParams = new HashMap(); + queryParams.put(QueryParamsComparator.QUERY_PARAM_KEY_FOR_ID, 23L); + + assertThat( + QueryParamsComparator.isIdEqual(mock(HasId.class), queryParams), + is(false)); + } + + @Test + void isNameEqual_falseIfModelIsNull() { + assertThat( + QueryParamsComparator.isNameEqual(null, Collections.emptyMap()), + is(false)); + } + + @Test + void isNameEqual_falseIfQueryParamsIsNull() { + assertThat( + QueryParamsComparator.isNameEqual(mock(HasName.class), null), + is(false)); + } + + @Test + void isNameEqual_falseIfQueryParamsDoesNotContainId() { + assertThat( + QueryParamsComparator.isNameEqual(mock(HasName.class), Collections.emptyMap()), + is(false)); + } + + @Test + void isNameEqual_falseIfQueryParamValueIsNull() { + final var queryParams = new HashMap(); + queryParams.put(QueryParamsComparator.QUERY_PARAM_KEY_FOR_NAME, null); + + assertThat( + QueryParamsComparator.isNameEqual(mock(HasName.class), queryParams), + is(false)); + } + + @Test + void isNameEqual_trueForSameValues() { + final var model = mock(HasName.class); + when(model.getName()).thenReturn("foobar"); + + final var queryParams = new HashMap(); + queryParams.put(QueryParamsComparator.QUERY_PARAM_KEY_FOR_NAME, "foobar"); + + assertThat( + QueryParamsComparator.isNameEqual(model, queryParams), + is(true)); + } + + @Test + void isNameEqual_falseForDifferentValues() { + final var model = mock(HasName.class); + when(model.getName()).thenReturn("foobar"); + + final var queryParams = new HashMap(); + queryParams.put(QueryParamsComparator.QUERY_PARAM_KEY_FOR_NAME, "snafu"); + + assertThat( + QueryParamsComparator.isNameEqual(model, queryParams), + is(false)); + } +} diff --git a/src/test/java/io/securecodebox/persistence/defectdojo/model/ResponseTest.java b/src/test/java/io/securecodebox/persistence/defectdojo/model/ResponseTest.java deleted file mode 100644 index 0c49794d..00000000 --- a/src/test/java/io/securecodebox/persistence/defectdojo/model/ResponseTest.java +++ /dev/null @@ -1,20 +0,0 @@ -package io.securecodebox.persistence.defectdojo.model; - -import nl.jqno.equalsverifier.EqualsVerifier; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.*; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.*; - -/** - * Tests for {@link Response} - */ -class ResponseTest { - @Test - @Disabled("#23 Fails due to wrong equals implementation") - void equalsAndHashCode() { - EqualsVerifier.forClass(Response.class).verify(); - } -} diff --git a/src/test/java/io/securecodebox/persistence/defectdojo/model/RiskAcceptanceTest.java b/src/test/java/io/securecodebox/persistence/defectdojo/model/RiskAcceptanceTest.java index 56943606..bdb22538 100644 --- a/src/test/java/io/securecodebox/persistence/defectdojo/model/RiskAcceptanceTest.java +++ b/src/test/java/io/securecodebox/persistence/defectdojo/model/RiskAcceptanceTest.java @@ -1,20 +1,41 @@ package io.securecodebox.persistence.defectdojo.model; import nl.jqno.equalsverifier.EqualsVerifier; -import org.junit.jupiter.api.Disabled; +import nl.jqno.equalsverifier.Warning; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; +import java.util.HashMap; + import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.is; /** * Tests for {@link RiskAcceptance} */ class RiskAcceptanceTest { - @Test - @Disabled("#23 Fails due to wrong equals implementation") - void equalsAndHashCode() { - EqualsVerifier.forClass(RiskAcceptance.class).verify(); - } + @Test + void equalsAndHashCode() { + EqualsVerifier.forClass(RiskAcceptance.class) + .suppress(Warning.NONFINAL_FIELDS) + .verify(); + } + + @Test + void equalsQueryString_id() { + final var sut = RiskAcceptance.builder() + .build(); + assertThat(sut.equalsQueryString(null), is(false)); + + final var params = new HashMap(); + assertThat(sut.equalsQueryString(params), is(false)); + + params.put("id", 42L); + assertThat(sut.equalsQueryString(params), is(false)); + + sut.setId(23L); + assertThat(sut.equalsQueryString(params), is(false)); + + sut.setId(42L); + assertThat(sut.equalsQueryString(params), is(true)); + } } diff --git a/src/test/java/io/securecodebox/persistence/defectdojo/model/ScanFileTest.java b/src/test/java/io/securecodebox/persistence/defectdojo/model/ScanFileTest.java index 8f37fe03..cbfccc15 100644 --- a/src/test/java/io/securecodebox/persistence/defectdojo/model/ScanFileTest.java +++ b/src/test/java/io/securecodebox/persistence/defectdojo/model/ScanFileTest.java @@ -1,20 +1,17 @@ package io.securecodebox.persistence.defectdojo.model; import nl.jqno.equalsverifier.EqualsVerifier; -import org.junit.jupiter.api.Disabled; +import nl.jqno.equalsverifier.Warning; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.*; - /** * Tests for {@link ScanFile} */ class ScanFileTest { - @Test - @Disabled("#23 Fails due to wrong equals implementation") - void equalsAndHashCode() { - EqualsVerifier.forClass(ScanFile.class).verify(); - } + @Test + void equalsAndHashCode() { + EqualsVerifier.forClass(ScanFile.class) + .suppress(Warning.NONFINAL_FIELDS) + .verify(); + } } diff --git a/src/test/java/io/securecodebox/persistence/defectdojo/model/TestTest.java b/src/test/java/io/securecodebox/persistence/defectdojo/model/TestTest.java index 08b54b4d..33de9b65 100644 --- a/src/test/java/io/securecodebox/persistence/defectdojo/model/TestTest.java +++ b/src/test/java/io/securecodebox/persistence/defectdojo/model/TestTest.java @@ -1,20 +1,79 @@ package io.securecodebox.persistence.defectdojo.model; import nl.jqno.equalsverifier.EqualsVerifier; -import org.junit.jupiter.api.Disabled; +import nl.jqno.equalsverifier.Warning; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; +import java.util.HashMap; + import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.is; /** * Tests for {@link Test} */ class TestTest { - @Test - @Disabled("#23 Fails due to wrong equals implementation") - void equalsAndHashCode() { - EqualsVerifier.forClass(Test.class).verify(); - } + @Test + void equalsAndHashCode() { + EqualsVerifier.forClass(Test.class) + .suppress(Warning.NONFINAL_FIELDS) + .verify(); + } + + @Test + void equalsQueryString_id() { + final var sut = io.securecodebox.persistence.defectdojo.model.Test.builder() + .build(); + assertThat(sut.equalsQueryString(null), is(false)); + + final var params = new HashMap(); + assertThat(sut.equalsQueryString(params), is(false)); + + params.put("id", 42L); + assertThat(sut.equalsQueryString(params), is(false)); + + sut.setId(23L); + assertThat(sut.equalsQueryString(params), is(false)); + + sut.setId(42L); + assertThat(sut.equalsQueryString(params), is(true)); + } + + @Test + void equalsQueryString_title() { + final var sut = io.securecodebox.persistence.defectdojo.model.Test.builder() + .build(); + assertThat(sut.equalsQueryString(null), is(false)); + + final var params = new HashMap(); + assertThat(sut.equalsQueryString(params), is(false)); + + params.put("title", "foobar"); + assertThat(sut.equalsQueryString(params), is(false)); + + sut.setTitle("snafu"); + assertThat(sut.equalsQueryString(params), is(false)); + + sut.setTitle("foobar"); + assertThat(sut.equalsQueryString(params), is(true)); + } + + @Test + void equalsQueryString_engagement() { + final var sut = io.securecodebox.persistence.defectdojo.model.Test.builder() + .build(); + assertThat(sut.equalsQueryString(null), is(false)); + + final var params = new HashMap(); + assertThat(sut.equalsQueryString(params), is(false)); + + params.put("engagement", 42L); + assertThat(sut.equalsQueryString(params), is(false)); + + sut.setEngagement(23L); + assertThat(sut.equalsQueryString(params), is(false)); + + sut.setEngagement(42L); + assertThat(sut.equalsQueryString(params), is(true)); + } } diff --git a/src/test/java/io/securecodebox/persistence/defectdojo/model/TestTypeTest.java b/src/test/java/io/securecodebox/persistence/defectdojo/model/TestTypeTest.java index b9d97440..a35fa193 100644 --- a/src/test/java/io/securecodebox/persistence/defectdojo/model/TestTypeTest.java +++ b/src/test/java/io/securecodebox/persistence/defectdojo/model/TestTypeTest.java @@ -1,20 +1,62 @@ package io.securecodebox.persistence.defectdojo.model; import nl.jqno.equalsverifier.EqualsVerifier; -import org.junit.jupiter.api.Disabled; +import nl.jqno.equalsverifier.Warning; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; +import java.util.HashMap; + import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.is; /** * Tests for {@link TestType} */ class TestTypeTest { - @Test - @Disabled("#23 Fails due to wrong equals implementation") - void equalsAndHashCode() { - EqualsVerifier.forClass(TestType.class).verify(); - } + @Test + void equalsAndHashCode() { + EqualsVerifier.forClass(TestType.class) + .suppress(Warning.NONFINAL_FIELDS) + .verify(); + } + + @Test + void equalsQueryString_id() { + final var sut = ProductType.builder() + .name("") + .build(); + assertThat(sut.equalsQueryString(null), is(false)); + + final var params = new HashMap(); + assertThat(sut.equalsQueryString(params), is(false)); + + params.put("id", 42L); + assertThat(sut.equalsQueryString(params), is(false)); + + sut.setId(23L); + assertThat(sut.equalsQueryString(params), is(false)); + + sut.setId(42L); + assertThat(sut.equalsQueryString(params), is(true)); + } + + @Test + void equalsQueryString_name() { + final var sut = ProductType.builder() + .name("") + .build(); + assertThat(sut.equalsQueryString(null), is(false)); + + final var params = new HashMap(); + assertThat(sut.equalsQueryString(params), is(false)); + + params.put("name", "foobar"); + assertThat(sut.equalsQueryString(params), is(false)); + + sut.setName("snafu"); + assertThat(sut.equalsQueryString(params), is(false)); + + sut.setName("foobar"); + assertThat(sut.equalsQueryString(params), is(true)); + } } diff --git a/src/test/java/io/securecodebox/persistence/defectdojo/model/ToolConfigTest.java b/src/test/java/io/securecodebox/persistence/defectdojo/model/ToolConfigTest.java index 65ac5557..f0da84dc 100644 --- a/src/test/java/io/securecodebox/persistence/defectdojo/model/ToolConfigTest.java +++ b/src/test/java/io/securecodebox/persistence/defectdojo/model/ToolConfigTest.java @@ -1,20 +1,82 @@ package io.securecodebox.persistence.defectdojo.model; import nl.jqno.equalsverifier.EqualsVerifier; -import org.junit.jupiter.api.Disabled; +import nl.jqno.equalsverifier.Warning; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; +import java.util.HashMap; + import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.is; /** * Tests for {@link ToolConfig} */ class ToolConfigTest { - @Test - @Disabled("#23 Fails due to wrong equals implementation") - void equalsAndHashCode() { - EqualsVerifier.forClass(ToolConfig.class).verify(); - } + @Test + void equalsAndHashCode() { + EqualsVerifier.forClass(ToolConfig.class) + .suppress(Warning.NONFINAL_FIELDS) + .verify(); + } + + @Test + void equalsQueryString_id() { + final var sut = ToolConfig.builder() + .name("") + .build(); + assertThat(sut.equalsQueryString(null), is(false)); + + final var params = new HashMap(); + assertThat(sut.equalsQueryString(params), is(false)); + + params.put("id", 42L); + assertThat(sut.equalsQueryString(params), is(false)); + + sut.setId(23L); + assertThat(sut.equalsQueryString(params), is(false)); + + sut.setId(42L); + assertThat(sut.equalsQueryString(params), is(true)); + } + + @Test + void equalsQueryString_name() { + final var sut = ToolConfig.builder() + .name("") + .build(); + assertThat(sut.equalsQueryString(null), is(false)); + + final var params = new HashMap(); + assertThat(sut.equalsQueryString(params), is(false)); + + params.put("name", "foobar"); + assertThat(sut.equalsQueryString(params), is(false)); + + sut.setName("snafu"); + assertThat(sut.equalsQueryString(params), is(false)); + + sut.setName("foobar"); + assertThat(sut.equalsQueryString(params), is(true)); + } + + @Test + void equalsQueryString_configUrl() { + final var sut = ToolConfig.builder() + .name("") + .build(); + assertThat(sut.equalsQueryString(null), is(false)); + + final var params = new HashMap(); + assertThat(sut.equalsQueryString(params), is(false)); + + params.put("configuration_url", "foobar"); + assertThat(sut.equalsQueryString(params), is(false)); + + sut.setConfigUrl("snafu"); + assertThat(sut.equalsQueryString(params), is(false)); + + sut.setConfigUrl("foobar"); + assertThat(sut.equalsQueryString(params), is(true)); + } } diff --git a/src/test/java/io/securecodebox/persistence/defectdojo/model/ToolTypeTest.java b/src/test/java/io/securecodebox/persistence/defectdojo/model/ToolTypeTest.java index 7861122c..a81ad535 100644 --- a/src/test/java/io/securecodebox/persistence/defectdojo/model/ToolTypeTest.java +++ b/src/test/java/io/securecodebox/persistence/defectdojo/model/ToolTypeTest.java @@ -1,20 +1,62 @@ package io.securecodebox.persistence.defectdojo.model; import nl.jqno.equalsverifier.EqualsVerifier; -import org.junit.jupiter.api.Disabled; +import nl.jqno.equalsverifier.Warning; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; +import java.util.HashMap; + import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.is; /** * Tests for {@link ToolType} */ class ToolTypeTest { - @Test - @Disabled("#23 Fails due to wrong equals implementation") - void equalsAndHashCode() { - EqualsVerifier.forClass(ToolType.class).verify(); - } + @Test + void equalsAndHashCode() { + EqualsVerifier.forClass(ToolType.class) + .suppress(Warning.NONFINAL_FIELDS) + .verify(); + } + + @Test + void equalsQueryString_id() { + final var sut = ToolType.builder() + .name("") + .build(); + assertThat(sut.equalsQueryString(null), is(false)); + + final var params = new HashMap(); + assertThat(sut.equalsQueryString(params), is(false)); + + params.put("id", 42L); + assertThat(sut.equalsQueryString(params), is(false)); + + sut.setId(23L); + assertThat(sut.equalsQueryString(params), is(false)); + + sut.setId(42L); + assertThat(sut.equalsQueryString(params), is(true)); + } + + @Test + void equalsQueryString_name() { + final var sut = ToolType.builder() + .name("") + .build(); + assertThat(sut.equalsQueryString(null), is(false)); + + final var params = new HashMap(); + assertThat(sut.equalsQueryString(params), is(false)); + + params.put("name", "foobar"); + assertThat(sut.equalsQueryString(params), is(false)); + + sut.setName("snafu"); + assertThat(sut.equalsQueryString(params), is(false)); + + sut.setName("foobar"); + assertThat(sut.equalsQueryString(params), is(true)); + } } diff --git a/src/test/java/io/securecodebox/persistence/defectdojo/model/UserProfileTest.java b/src/test/java/io/securecodebox/persistence/defectdojo/model/UserProfileTest.java index 7cfa20ad..d3060209 100644 --- a/src/test/java/io/securecodebox/persistence/defectdojo/model/UserProfileTest.java +++ b/src/test/java/io/securecodebox/persistence/defectdojo/model/UserProfileTest.java @@ -1,16 +1,39 @@ package io.securecodebox.persistence.defectdojo.model; import nl.jqno.equalsverifier.EqualsVerifier; -import org.junit.jupiter.api.Disabled; +import nl.jqno.equalsverifier.Warning; import org.junit.jupiter.api.Test; +import java.util.Collections; +import java.util.HashMap; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; + /** * Tests for {@link UserProfile} */ class UserProfileTest { - @Test - @Disabled("#23 Fails due to wrong equals implementation") - void equalsAndHashCode() { - EqualsVerifier.forClass(UserProfile.class).verify(); - } + @Test + void equalsAndHashCode() { + EqualsVerifier.forClass(UserProfile.class) + .suppress(Warning.NONFINAL_FIELDS) + .verify(); + } + + @Test + void equalsQueryString_alwaysTrueIfNotNullGiven() { + final var sut = UserProfile.builder() + .build(); + + assertThat(sut.equalsQueryString(Collections.emptyMap()), is(true)); + } + + @Test + void equalsQueryString_alwaysFalseIfNull() { + final var sut = UserProfile.builder() + .build(); + + assertThat(sut.equalsQueryString(null), is(false)); + } } diff --git a/src/test/java/io/securecodebox/persistence/defectdojo/model/UserTest.java b/src/test/java/io/securecodebox/persistence/defectdojo/model/UserTest.java index 64001c3a..9e02cbfd 100644 --- a/src/test/java/io/securecodebox/persistence/defectdojo/model/UserTest.java +++ b/src/test/java/io/securecodebox/persistence/defectdojo/model/UserTest.java @@ -1,20 +1,62 @@ package io.securecodebox.persistence.defectdojo.model; import nl.jqno.equalsverifier.EqualsVerifier; -import org.junit.jupiter.api.Disabled; +import nl.jqno.equalsverifier.Warning; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; +import java.util.HashMap; + import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.is; /** * Tests for {@link User} */ class UserTest { - @Test - @Disabled("#23 Fails due to wrong equals implementation") - void equalsAndHashCode() { - EqualsVerifier.forClass(User.class).verify(); - } + @Test + void equalsAndHashCode() { + EqualsVerifier.forClass(User.class) + .suppress(Warning.NONFINAL_FIELDS) + .verify(); + } + + @Test + void equalsQueryString_id() { + final var sut = User.builder() + .username("") + .build(); + assertThat(sut.equalsQueryString(null), is(false)); + + final var params = new HashMap(); + assertThat(sut.equalsQueryString(params), is(false)); + + params.put("id", 42L); + assertThat(sut.equalsQueryString(params), is(false)); + + sut.setId(23L); + assertThat(sut.equalsQueryString(params), is(false)); + + sut.setId(42L); + assertThat(sut.equalsQueryString(params), is(true)); + } + + @Test + void equalsQueryString_username() { + final var sut = User.builder() + .username("") + .build(); + assertThat(sut.equalsQueryString(null), is(false)); + + final var params = new HashMap(); + assertThat(sut.equalsQueryString(params), is(false)); + + params.put("username", "foobar"); + assertThat(sut.equalsQueryString(params), is(false)); + + sut.setUsername("snafu"); + assertThat(sut.equalsQueryString(params), is(false)); + + sut.setUsername("foobar"); + assertThat(sut.equalsQueryString(params), is(true)); + } } diff --git a/src/test/java/io/securecodebox/persistence/defectdojo/service/DefaultImportScanServiceTest.java b/src/test/java/io/securecodebox/persistence/defectdojo/service/DefaultImportScanServiceTest.java index 902e4d22..8a4cd3e6 100644 --- a/src/test/java/io/securecodebox/persistence/defectdojo/service/DefaultImportScanServiceTest.java +++ b/src/test/java/io/securecodebox/persistence/defectdojo/service/DefaultImportScanServiceTest.java @@ -19,80 +19,80 @@ * Tests for {@link DefaultImportScanService} */ class DefaultImportScanServiceTest { - private final Config config = new Config( - "http://localhost", - "apiKey", - 23 + private final Config config = new Config( + "http://localhost", + "apiKey", + 23 + ); + private final DefaultImportScanService sut = new DefaultImportScanService(config, ProxyConfig.NULL); + + @Test + void constructorShouldThrowExceptionOnNullConfig() { + assertThrows(NullPointerException.class, () -> { + new DefaultImportScanService(null, ProxyConfig.NULL); + }); + } + + @Test + void constructorShouldThrowExceptionOnNullProxyConfig() { + assertThrows(NullPointerException.class, () -> { + new DefaultImportScanService(Config.NULL, null); + }); + } + + @Test + void createDefectDojoAuthorizationHeaders_apiKeyFromConfigShouldBePresentAsAuthHEader() { + final var authorizationHeaders = sut.createDefectDojoAuthorizationHeaders(); + assertAll( + () -> assertThat(authorizationHeaders.size(), is(1)), + () -> assertThat(authorizationHeaders.get(HttpHeaders.AUTHORIZATION).get(0), is("Token apiKey")) ); - private final DefaultImportScanService sut = new DefaultImportScanService(config, ProxyConfig.NULL); - - @Test - void constructorShouldThrowExceptionOnNullConfig() { - assertThrows(NullPointerException.class, () -> { - new DefaultImportScanService(null, ProxyConfig.NULL); - }); - } - - @Test - void constructorShouldThrowExceptionOnNullProxyConfig() { - assertThrows(NullPointerException.class, () -> { - new DefaultImportScanService(Config.NULL, null); - }); - } - - @Test - void createDefectDojoAuthorizationHeaders_apiKeyFromConfigShouldBePresentAsAuthHEader() { - final var authorizationHeaders = sut.createDefectDojoAuthorizationHeaders(); - assertAll( - () -> assertThat(authorizationHeaders.size(), is(1)), - () -> assertThat(authorizationHeaders.get(HttpHeaders.AUTHORIZATION).get(0), is("Token apiKey")) - ); - } - - @Test - void shouldConfigureProxySettings_trueIfProxyConfigIsComplete() { - final var proxyConfig = ProxyConfig.builder() - .user("user") - .password("pw") - .host("host") - .port(42) - .build(); - final var innerSut = new DefaultImportScanService(config, proxyConfig); - - assertThat(innerSut.shouldConfigureProxySettings(), is(true)); - } - - @Test - void shouldConfigureProxySettings_falseIfProxyConfigIsIncomplete() { - final var proxyConfig = ProxyConfig.builder() - .build(); - final var innerSut = new DefaultImportScanService(config, proxyConfig); - - assertThat(innerSut.shouldConfigureProxySettings(), is(false)); - } - - @Test - void generateApiUrl() { - assertThat(sut.generateApiUrl("foo"), is("http://localhost/api/v2/foo/")); - } - - @Test - @Disabled("Not implemented yet") - void importScan_shouldPassImportScanAsEndpoint() { - } - - @Test - @Disabled("Not implemented yet") - void importScan_shouldPassEngagementIdAsEngagement() { - } - - @Test - @Disabled("Not implemented yet") - void reimportScan_shouldPassReimportScanAsEndpoint() { - } - - @Test - @Disabled("Not implemented yet") - void reimportScan_shouldPassEngagementIdAsTest() { - } + } + + @Test + void shouldConfigureProxySettings_trueIfProxyConfigIsComplete() { + final var proxyConfig = ProxyConfig.builder() + .user("user") + .password("pw") + .host("host") + .port(42) + .build(); + final var innerSut = new DefaultImportScanService(config, proxyConfig); + + assertThat(innerSut.shouldConfigureProxySettings(), is(true)); + } + + @Test + void shouldConfigureProxySettings_falseIfProxyConfigIsIncomplete() { + final var proxyConfig = ProxyConfig.builder() + .build(); + final var innerSut = new DefaultImportScanService(config, proxyConfig); + + assertThat(innerSut.shouldConfigureProxySettings(), is(false)); + } + + @Test + void generateApiUrl() { + assertThat(sut.generateApiUrl("foo"), is("http://localhost/api/v2/foo/")); + } + + @Test + @Disabled("Not implemented yet") + void importScan_shouldPassImportScanAsEndpoint() { + } + + @Test + @Disabled("Not implemented yet") + void importScan_shouldPassEngagementIdAsEngagement() { + } + + @Test + @Disabled("Not implemented yet") + void reimportScan_shouldPassReimportScanAsEndpoint() { + } + + @Test + @Disabled("Not implemented yet") + void reimportScan_shouldPassEngagementIdAsTest() { + } } diff --git a/src/test/java/io/securecodebox/persistence/defectdojo/service/FindingServiceTest.java b/src/test/java/io/securecodebox/persistence/defectdojo/service/FindingServiceTest.java index db049097..7b717d50 100644 --- a/src/test/java/io/securecodebox/persistence/defectdojo/service/FindingServiceTest.java +++ b/src/test/java/io/securecodebox/persistence/defectdojo/service/FindingServiceTest.java @@ -6,154 +6,140 @@ import com.fasterxml.jackson.core.JsonProcessingException; import io.securecodebox.persistence.defectdojo.config.Config; - -import java.net.URISyntaxException; - -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.springframework.http.MediaType; import org.springframework.test.web.client.MockRestServiceServer; -import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess; - - -import static org.junit.jupiter.api.Assertions.*; - -import org.springframework.http.MediaType; +import java.net.URISyntaxException; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertIterableEquals; import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo; +import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess; // This test is sufficient for all services (except user profile) as all the code is generic class FindingServiceTest { - - Config config; - FindingService underTest; - MockRestServiceServer mockServer; - - String findingResponse = """ - { - "count": 1, - "next": null, - "previous": null, - "results": - [ - { - "id": 42, - "tags": [], - "request_response": { - "req_resp": [] - }, - "accepted_risks": [], - "push_to_jira": false, - "age": 145, - "sla_days_remaining": null, - "finding_meta": [], - "related_fields": null, - "jira_creation": null, - "jira_change": null, - "display_status": "Active, Verified", - "finding_groups": [], - "title": "Open Port: 9929/TCP", - "date": "2021-03-18", - "sla_start_date": null, - "cwe": 0, - "cve": null, - "cvssv3": null, - "cvssv3_score": null, - "url": null, - "severity": "Info", - "description": "### Host\\n\\n**IP Address:** 198.51.100.0\\n**FQDN:** scanme.nmap.org\\n\\n\\n**Port/Protocol:** 9929/tcp\\n\\n\\n\\n\\n", - "mitigation": "N/A", - "impact": "No impact provided", - "steps_to_reproduce": null, - "severity_justification": null, - "references": null, - "is_template": false, - "active": true, - "verified": true, - "false_p": false, - "duplicate": false, - "out_of_scope": false, - "risk_accepted": false, - "under_review": false, - "last_status_update": "2021-07-21T12:43:36.628994Z", - "under_defect_review": false, - "is_mitigated": false, - "thread_id": 0, - "mitigated": null, - "numerical_severity": "S4", - "last_reviewed": "2021-07-21T12:43:36.545348Z", - "line_number": null, - "sourcefilepath": null, - "sourcefile": null, - "param": null, - "payload": null, - "hash_code": "8dbaad23d4056f0a97bb8f487795fe392b4124f28d4049d16430e43415f1c219", - "line": null, - "file_path": null, - "component_name": null, - "component_version": null, - "static_finding": false, - "dynamic_finding": true, - "created": "2021-07-21T12:43:36.549669Z", - "scanner_confidence": null, - "unique_id_from_tool": null, - "vuln_id_from_tool": null, - "sast_source_object": null, - "sast_sink_object": null, - "sast_source_line": null, - "sast_source_file_path": null, - "nb_occurences": null, - "publish_date": null, - "test": 222, - "duplicate_finding": null, - "review_requested_by": null, - "defect_review_requested_by": null, - "mitigated_by": null, - "reporter": 5, - "last_reviewed_by": 5, - "sonarqube_issue": null, - "endpoints": [ - 875 - ], - "endpoint_status": [ - 8640 - ], - "reviewers": [], - "notes": [], - "files": [], - "found_by": [ - 132 - ] - } - ], - "prefetch": {} - } - """; - - @BeforeEach - void setup() { - config = new Config("https://defectdojo.example.com", "abc", 42); - underTest = new FindingService(config); - mockServer = MockRestServiceServer.createServer(underTest.getRestTemplate()); - } - - @Test - void deserializeList() throws JsonProcessingException { - var foo = underTest.deserializeList(findingResponse); - - assertEquals(1, foo.getCount()); - } - - @Test - void testSearch() throws JsonProcessingException, URISyntaxException { - var url = config.getUrl() + "/api/v2/" + underTest.getUrlPath() + "/?offset=0&limit=100"; - mockServer.expect(requestTo(url)).andRespond(withSuccess(findingResponse, MediaType.APPLICATION_JSON)); - - var expected = underTest.deserializeList(findingResponse).getResults(); - var actual = underTest.search(); - - mockServer.verify(); - assertIterableEquals(expected, actual); - } + private static final String FINDING_RESPONSE = """ + { + "count": 1, + "next": null, + "previous": null, + "results": + [ + { + "id": 42, + "tags": [], + "request_response": { + "req_resp": [] + }, + "accepted_risks": [], + "push_to_jira": false, + "age": 145, + "sla_days_remaining": null, + "finding_meta": [], + "related_fields": null, + "jira_creation": null, + "jira_change": null, + "display_status": "Active, Verified", + "finding_groups": [], + "title": "Open Port: 9929/TCP", + "date": "2021-03-18", + "sla_start_date": null, + "cwe": 0, + "cve": null, + "cvssv3": null, + "cvssv3_score": null, + "url": null, + "severity": "Info", + "description": "### Host\\n\\n**IP Address:** 198.51.100.0\\n**FQDN:** scanme.nmap.org\\n\\n\\n**Port/Protocol:** 9929/tcp\\n\\n\\n\\n\\n", + "mitigation": "N/A", + "impact": "No impact provided", + "steps_to_reproduce": null, + "severity_justification": null, + "references": null, + "is_template": false, + "active": true, + "verified": true, + "false_p": false, + "duplicate": false, + "out_of_scope": false, + "risk_accepted": false, + "under_review": false, + "last_status_update": "2021-07-21T12:43:36.628994Z", + "under_defect_review": false, + "is_mitigated": false, + "thread_id": 0, + "mitigated": null, + "numerical_severity": "S4", + "last_reviewed": "2021-07-21T12:43:36.545348Z", + "line_number": null, + "sourcefilepath": null, + "sourcefile": null, + "param": null, + "payload": null, + "hash_code": "8dbaad23d4056f0a97bb8f487795fe392b4124f28d4049d16430e43415f1c219", + "line": null, + "file_path": null, + "component_name": null, + "component_version": null, + "static_finding": false, + "dynamic_finding": true, + "created": "2021-07-21T12:43:36.549669Z", + "scanner_confidence": null, + "unique_id_from_tool": null, + "vuln_id_from_tool": null, + "sast_source_object": null, + "sast_sink_object": null, + "sast_source_line": null, + "sast_source_file_path": null, + "nb_occurences": null, + "publish_date": null, + "test": 222, + "duplicate_finding": null, + "review_requested_by": null, + "defect_review_requested_by": null, + "mitigated_by": null, + "reporter": 5, + "last_reviewed_by": 5, + "sonarqube_issue": null, + "endpoints": [ + 875 + ], + "endpoint_status": [ + 8640 + ], + "reviewers": [], + "notes": [], + "files": [], + "found_by": [ + 132 + ] + } + ], + "prefetch": {} + } + """; + + private final Config config = new Config("https://defectdojo.example.com", "abc", 42); + private final FindingService sut = new FindingService(config); + private final MockRestServiceServer server = MockRestServiceServer.createServer(sut.getRestTemplate()); + + + @Test + void deserializeList_shouldResultExactlyOneResult() throws JsonProcessingException { + var result = sut.deserializeList(FINDING_RESPONSE); + + assertEquals(1, result.getCount()); + } + + @Test + void search() throws JsonProcessingException, URISyntaxException { + final var url = String.format("%s/api/v2/%s/?offset=0&limit=100", config.getUrl(), sut.getUrlPath()); + server.expect(requestTo(url)) + .andRespond(withSuccess(FINDING_RESPONSE, MediaType.APPLICATION_JSON)); + + assertIterableEquals(sut.deserializeList(FINDING_RESPONSE).getResults(), sut.search()); + server.verify(); + } } diff --git a/src/test/java/io/securecodebox/persistence/defectdojo/service/ImportScanServiceTest.java b/src/test/java/io/securecodebox/persistence/defectdojo/service/ImportScanServiceTest.java index d49f1ce6..9a5a8aae 100644 --- a/src/test/java/io/securecodebox/persistence/defectdojo/service/ImportScanServiceTest.java +++ b/src/test/java/io/securecodebox/persistence/defectdojo/service/ImportScanServiceTest.java @@ -14,99 +14,100 @@ import java.util.Collections; import java.util.Map; -import static org.junit.jupiter.api.Assertions.*; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*; +import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertThrows; /** * Tests for {@link ImportScanService}. */ class ImportScanServiceTest { - private final ImportScanServiceStub sut = new ImportScanServiceStub(); + private final ImportScanServiceStub sut = new ImportScanServiceStub(); - @Test - void createDefault_throwsExceptionIfNullPassedInAsConfig() { - assertThrows(NullPointerException.class, () -> { - ImportScanService.createDefault(null, ProxyConfig.NULL); - }); - } + @Test + void createDefault_throwsExceptionIfNullPassedInAsConfig() { + assertThrows(NullPointerException.class, () -> { + ImportScanService.createDefault(null, ProxyConfig.NULL); + }); + } - @Test - void createDefault_throwsExceptionIfNullPassedInAsProxyConfig() { - assertThrows(NullPointerException.class, () -> { - ImportScanService.createDefault(Config.NULL, null); - }); - } + @Test + void createDefault_throwsExceptionIfNullPassedInAsProxyConfig() { + assertThrows(NullPointerException.class, () -> { + ImportScanService.createDefault(Config.NULL, null); + }); + } - @Test - void createDefault_passesConfig() { - final var config = new Config( - "url", - "apiKey", - 23 - ); + @Test + void createDefault_passesConfig() { + final var config = new Config( + "url", + "apiKey", + 23 + ); - final var sut = (DefaultImportScanService) ImportScanService.createDefault(config, ProxyConfig.NULL); + final var sut = (DefaultImportScanService) ImportScanService.createDefault(config, ProxyConfig.NULL); - assertAll( - () -> assertThat(sut.getDefectDojoUrl(), is(config.getUrl())), - () -> assertThat(sut.getDefectDojoApiKey(), is(config.getApiKey()))); - } + assertAll( + () -> assertThat(sut.getDefectDojoUrl(), is(config.getUrl())), + () -> assertThat(sut.getDefectDojoApiKey(), is(config.getApiKey()))); + } - @Test - void importScan_withoutOptionsShouldPassEmptyMap() { - assertThat(sut.getOptions(), is(nullValue())); + @Test + void importScan_withoutOptionsShouldPassEmptyMap() { + assertThat(sut.getOptions(), is(nullValue())); - sut.importScan(new ScanFile("content"), 42L, 43L, "1.1.2023", ScanType.AUDIT_JS_SCAN, 23L); + sut.importScan(new ScanFile("content"), 42L, 43L, "1.1.2023", ScanType.AUDIT_JS_SCAN, 23L); - assertThat(sut.getOptions(), equalTo(Collections.EMPTY_MAP)); - } + assertThat(sut.getOptions(), equalTo(Collections.EMPTY_MAP)); + } - @Test - void importScan_withoutOptionsShouldPassModifiableMap() { - assertThat(sut.getOptions(), is(nullValue())); + @Test + void importScan_withoutOptionsShouldPassModifiableMap() { + assertThat(sut.getOptions(), is(nullValue())); - sut.importScan(new ScanFile("content"), 42L, 43L, "1.1.2023", ScanType.AUDIT_JS_SCAN, 23L); - sut.getOptions().put("foo", "bar"); + sut.importScan(new ScanFile("content"), 42L, 43L, "1.1.2023", ScanType.AUDIT_JS_SCAN, 23L); + sut.getOptions().put("foo", "bar"); - assertThat(sut.getOptions(), hasEntry("foo", "bar")); - } + assertThat(sut.getOptions(), hasEntry("foo", "bar")); + } - @Test - void reimportScan_withoutOptionsShouldPassEmptyMap() { - assertThat(sut.getOptions(), is(nullValue())); + @Test + void reimportScan_withoutOptionsShouldPassEmptyMap() { + assertThat(sut.getOptions(), is(nullValue())); - sut.reimportScan(new ScanFile("content"), 42L, 43L, "1.1.2023", ScanType.AUDIT_JS_SCAN, 23L); + sut.reimportScan(new ScanFile("content"), 42L, 43L, "1.1.2023", ScanType.AUDIT_JS_SCAN, 23L); - assertThat(sut.getOptions(), equalTo(Collections.EMPTY_MAP)); - } + assertThat(sut.getOptions(), equalTo(Collections.EMPTY_MAP)); + } - @Test - void reimportScan_withoutOptionsShouldPassModifiableMap() { - assertThat(sut.getOptions(), is(nullValue())); + @Test + void reimportScan_withoutOptionsShouldPassModifiableMap() { + assertThat(sut.getOptions(), is(nullValue())); - sut.reimportScan(new ScanFile("content"), 42L, 43L, "1.1.2023", ScanType.AUDIT_JS_SCAN, 23L); - sut.getOptions().put("foo", "bar"); + sut.reimportScan(new ScanFile("content"), 42L, 43L, "1.1.2023", ScanType.AUDIT_JS_SCAN, 23L); + sut.getOptions().put("foo", "bar"); - assertThat(sut.getOptions(), hasEntry("foo", "bar")); - } + assertThat(sut.getOptions(), hasEntry("foo", "bar")); + } - private static final class ImportScanServiceStub implements ImportScanService { + private static final class ImportScanServiceStub implements ImportScanService { - @Getter - private Map options; + @Getter + private Map options; - @Override - public ImportScanResponse importScan(ScanFile scanFile, long engagementId, long lead, String currentDate, ScanType scanType, long testType, Map options) { - this.options = options; - return null; - } + @Override + public ImportScanResponse importScan(ScanFile scanFile, long engagementId, long lead, String currentDate, ScanType scanType, long testType, Map options) { + this.options = options; + return null; + } - @Override - public ImportScanResponse reimportScan(ScanFile scanFile, long testId, long lead, String currentDate, ScanType scanType, long testType, Map options) { - this.options = options; - return null; - } + @Override + public ImportScanResponse reimportScan(ScanFile scanFile, long testId, long lead, String currentDate, ScanType scanType, long testType, Map options) { + this.options = options; + return null; } + } } 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 75347c5e..1a12fd6a 100644 --- a/src/test/java/io/securecodebox/persistence/defectdojo/service/UserProfileServiceTest.java +++ b/src/test/java/io/securecodebox/persistence/defectdojo/service/UserProfileServiceTest.java @@ -8,37 +8,37 @@ import io.securecodebox.persistence.defectdojo.config.Config; import io.securecodebox.persistence.defectdojo.model.User; import io.securecodebox.persistence.defectdojo.model.UserProfile; +import org.junit.jupiter.api.Test; +import org.springframework.http.MediaType; +import org.springframework.test.web.client.MockRestServiceServer; import java.net.URISyntaxException; import java.util.Arrays; +import java.util.List; import static org.junit.jupiter.api.Assertions.assertIterableEquals; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.springframework.http.MediaType; -import org.springframework.test.web.client.MockRestServiceServer; - import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo; import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess; -// This test is special because the defectdojo api does not return a list, -// but the generic code assumes every endpoint returns a list +/** + * Tests for UserProfileService + *

+ * This test is special because the defectdojo api does not return a list, but the generic code assumes every endpoint + * returns a list. + *

+ */ class UserProfileServiceTest { - - 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 - private String apiResponse = """ + /** + * This string does not contain every field of the api response as those are not implemented + */ + private static final String API_RESPONSE = """ { "user": { "id": 0, - "username": "GdqmXprK.j7R+OYE49SzL3mM2U6I0DyLRHnDg87i9It0AfP-kxvswW3qOI2i+31-@0", - "first_name": "string", - "last_name": "string", + "username": "username", + "first_name": "first_name", + "last_name": "last_name", "email": "user@example.com", "last_login": "2022-11-01T16:20:19.373Z", "is_active": true, @@ -48,24 +48,18 @@ class UserProfileServiceTest { } """; - @BeforeEach - void setup() { - config = new Config("https://defectdojo.example.com", "abc", 42); - underTest = new UserProfileService(config); - mockServer = MockRestServiceServer.createServer(underTest.getRestTemplate()); - } + private final Config config = new Config("https://defectdojo.example.com", "abc", 42); + private final UserProfileService sut = new UserProfileService(config); + private final MockRestServiceServer server = MockRestServiceServer.createServer(sut.getRestTemplate()); @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)); + void search() throws JsonProcessingException, URISyntaxException { + final var url = String.format("%s/api/v2/%s/?offset=0&limit=100", config.getUrl(), sut.getUrlPath()); + server.expect(requestTo(url)).andRespond(withSuccess(API_RESPONSE, MediaType.APPLICATION_JSON)); - 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(); + final var expected = new UserProfile(new User(0L, "username", "first_name", "last_name")); - mockServer.verify(); - assertIterableEquals(expected, actual); + assertIterableEquals(List.of(expected), sut.search()); + server.verify(); } }