diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index fa17b278..6cd434a2 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -28,3 +28,4 @@ Committing with `git commit -s` will add the sign-off at the end of the commit m - Simon Hülkenberg - Sven Strittmatter - Timo Pagel +- Maximilian Dorner \ No newline at end of file diff --git a/src/main/java/io/securecodebox/persistence/defectdojo/config/Config.java b/src/main/java/io/securecodebox/persistence/defectdojo/config/Config.java index ac66a519..704f6492 100644 --- a/src/main/java/io/securecodebox/persistence/defectdojo/config/Config.java +++ b/src/main/java/io/securecodebox/persistence/defectdojo/config/Config.java @@ -20,10 +20,16 @@ public final class Config { * Default for {@link #maxPageCountForGets} */ static final int DEFAULT_MAX_PAGE_COUNT_FOR_GETS = 100; + + /** + * Default for {@link #refetchWaitSeconds} + */ + static final int DEFAULT_REFETCH_WAIT_SECONDS = 0; + /** * Null pattern object. */ - public static final Config NULL = new Config("", "", DEFAULT_MAX_PAGE_COUNT_FOR_GETS); + public static final Config NULL = new Config("", "", DEFAULT_MAX_PAGE_COUNT_FOR_GETS, DEFAULT_REFETCH_WAIT_SECONDS); /** * URL of the host which serves the DefectDojo API. @@ -41,6 +47,15 @@ public final class Config { @NonNull private final String apiKey; + /** + * Number of seconds to wait before refetching results from the DefectDojo API. + *

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

+ */ + @NonNull + private final int refetchWaitSeconds; + /** * How many pages of objects are fetched from the DefectDojo API *

@@ -53,13 +68,13 @@ public final class Config { private final int maxPageCountForGets; /** - * Convenience constructor which sets {@link #DEFAULT_MAX_PAGE_COUNT_FOR_GETS} + * Convenience constructor which sets {@link #DEFAULT_MAX_PAGE_COUNT_FOR_GETS} and {@link #DEFAULT_REFETCH_WAIT_SECONDS} * * @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); + this(url, apiKey, DEFAULT_MAX_PAGE_COUNT_FOR_GETS, DEFAULT_REFETCH_WAIT_SECONDS); } /** @@ -68,12 +83,22 @@ public Config(final @NonNull String url, final @NonNull String apiKey) { * @param url not {@code null} * @param apiKey not {@code null} * @param maxPageCountForGets not less than 1 + * @param refetchWaitSeconds not less than 0 */ - public Config(final @NonNull String url, final @NonNull String apiKey, final int maxPageCountForGets) { + public Config(final @NonNull String url, final @NonNull String apiKey, final int maxPageCountForGets, final int refetchWaitSeconds) { super(); this.url = url; this.apiKey = apiKey; this.maxPageCountForGets = validateIsGreaterZero(maxPageCountForGets, "maxPageCountForGets"); + this.refetchWaitSeconds = validateIsNotNegative(refetchWaitSeconds, "refetchWaitSeconds"); + } + + private static int validateIsNotNegative(final int number, final String name) { + if (number < 0) { + throw new IllegalArgumentException(String.format("%s must not be negative!", name)); + } + + return number; } private static int validateIsGreaterZero(final int number, final String name) { @@ -93,6 +118,7 @@ public static Config fromEnv() { final var url = findRequiredEnvVar(EnvVars.DEFECTDOJO_URL); final var apiKey = findRequiredEnvVar(EnvVars.DEFECTDOJO_APIKEY); final int maxPageCountForGets; + final int refetchWaitSeconds; if (hasEnvVar(EnvVars.DEFECTDOJO_MAX_PAGE_COUNT_FOR_GETS)) { try { @@ -105,7 +131,18 @@ public static Config fromEnv() { maxPageCountForGets = DEFAULT_MAX_PAGE_COUNT_FOR_GETS; } - return new Config(url, apiKey, maxPageCountForGets); + if (hasEnvVar(EnvVars.DEFECTDOJO_REFETCH_WAIT_SECONDS)) { + try { + refetchWaitSeconds = Integer.parseInt(findEnvVar(EnvVars.DEFECTDOJO_REFETCH_WAIT_SECONDS)); + } 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_REFETCH_WAIT_SECONDS.literal, findEnvVar(EnvVars.DEFECTDOJO_REFETCH_WAIT_SECONDS)), + e); + } + } else { + refetchWaitSeconds = DEFAULT_REFETCH_WAIT_SECONDS; + } + + return new Config(url, apiKey, maxPageCountForGets, refetchWaitSeconds); } private static boolean hasEnvVar(final @NonNull EnvVars name) { @@ -131,7 +168,8 @@ private static String findRequiredEnvVar(final @NonNull EnvVars name) { public enum EnvVars { DEFECTDOJO_URL("DEFECTDOJO_URL"), DEFECTDOJO_APIKEY("DEFECTDOJO_APIKEY"), - DEFECTDOJO_MAX_PAGE_COUNT_FOR_GETS("DEFECTDOJO_MAX_PAGE_COUNT_FOR_GETS"); + DEFECTDOJO_MAX_PAGE_COUNT_FOR_GETS("DEFECTDOJO_MAX_PAGE_COUNT_FOR_GETS"), + DEFECTDOJO_REFETCH_WAIT_SECONDS("DEFECTDOJO_REFETCH_WAIT_SECONDS"); /** * Literal name of configuration environment name *

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..c96bd0c3 100644 --- a/src/test/java/io/securecodebox/persistence/defectdojo/config/ConfigTest.java +++ b/src/test/java/io/securecodebox/persistence/defectdojo/config/ConfigTest.java @@ -30,7 +30,7 @@ class ConfigTest { @Test void constructor_urlMustNotBeNull() { final var thrown = assertThrows(NullPointerException.class, () -> { - new Config(null, "apiKey", 1); + new Config(null, "apiKey", 1, 1); }); assertThat(thrown.getMessage(), startsWith("url ")); @@ -39,17 +39,27 @@ void constructor_urlMustNotBeNull() { @Test void constructor_apiKeyMustNotBeNull() { final var thrown = assertThrows(NullPointerException.class, () -> { - new Config("url", null, 1); + new Config("url", null, 1, 1); }); assertThat(thrown.getMessage(), startsWith("apiKey ")); } + @ParameterizedTest + @ValueSource(ints = {-1, -2, -23, -42, Integer.MIN_VALUE}) + void constructor_refetchWaitSecondsMustNotBeLessThanZero(final int number) { + final var thrown = assertThrows(IllegalArgumentException.class, () -> { + new Config("url", "apiKey", 1, number); + }); + + assertThat(thrown.getMessage(), startsWith("refetchWaitSeconds ")); + } + @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); + new Config("url", "apiKey", number, 60 ); }); assertThat(thrown.getMessage(), startsWith("maxPageCountForGets ")); @@ -60,14 +70,16 @@ void fromEnv() { environmentVariables .set("DEFECTDOJO_URL", "url") .set("DEFECTDOJO_APIKEY", "apikey") - .set("DEFECTDOJO_MAX_PAGE_COUNT_FOR_GETS", "23"); + .set("DEFECTDOJO_MAX_PAGE_COUNT_FOR_GETS", "23") + .set("DEFECTDOJO_REFETCH_WAIT_SECONDS", "60"); final var sut = Config.fromEnv(); assertAll( () -> assertThat(sut.getUrl(), is("url")), () -> assertThat(sut.getApiKey(), is("apikey")), - () -> assertThat(sut.getMaxPageCountForGets(), is(23)) + () -> assertThat(sut.getMaxPageCountForGets(), is(23)), + () -> assertThat(sut.getRefetchWaitSeconds(), is(60)) ); } @@ -91,6 +103,29 @@ void fromEnv_throwsExceptionIfNoApiKeySet() { assertThat(thrown.getMessage(), is("Missing environment variable 'DEFECTDOJO_APIKEY'!")); } + @Test + void fromEnv_usesDefaultIfNoRefetchWaitSecondsSet() { + environmentVariables + .set("DEFECTDOJO_URL", "url") + .set("DEFECTDOJO_APIKEY", "apikey") + .set("DEFECTDOJO_MAX_PAGE_COUNT_FOR_GETS", 1); + + final var sut = Config.fromEnv(); + assertThat(sut.getRefetchWaitSeconds(), is(Config.DEFAULT_REFETCH_WAIT_SECONDS)); + } + + @Test + void fromEnv_throwsExceptionIfRefetchWaitSecondsIsNotParseableToInteger() { + environmentVariables + .set("DEFECTDOJO_URL", "url") + .set("DEFECTDOJO_APIKEY", "apikey") + .set("DEFECTDOJO_REFETCH_WAIT_SECONDS", "foo"); + + final var thrown = assertThrows(ConfigException.class, Config::fromEnv); + + assertThat(thrown.getMessage(), is("Given value for environment variable 'DEFECTDOJO_REFETCH_WAIT_SECONDS' is not a valid number! Given was 'foo'.")); + } + @Test void fromEnv_usesDefaultIfNoMaxPageCountForGetSet() { environmentVariables 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..02afcdb5 100644 --- a/src/test/java/io/securecodebox/persistence/defectdojo/service/DefaultImportScanServiceTest.java +++ b/src/test/java/io/securecodebox/persistence/defectdojo/service/DefaultImportScanServiceTest.java @@ -22,7 +22,8 @@ class DefaultImportScanServiceTest { private final Config config = new Config( "http://localhost", "apiKey", - 23 + 23, + 60 ); private final DefaultImportScanService sut = new DefaultImportScanService(config, ProxyConfig.NULL); 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..5171a741 100644 --- a/src/test/java/io/securecodebox/persistence/defectdojo/service/FindingServiceTest.java +++ b/src/test/java/io/securecodebox/persistence/defectdojo/service/FindingServiceTest.java @@ -133,7 +133,7 @@ class FindingServiceTest { @BeforeEach void setup() { - config = new Config("https://defectdojo.example.com", "abc", 42); + config = new Config("https://defectdojo.example.com", "abc", 42, 60); underTest = new FindingService(config); mockServer = MockRestServiceServer.createServer(underTest.getRestTemplate()); } 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..8d3cd8ac 100644 --- a/src/test/java/io/securecodebox/persistence/defectdojo/service/ImportScanServiceTest.java +++ b/src/test/java/io/securecodebox/persistence/defectdojo/service/ImportScanServiceTest.java @@ -44,7 +44,8 @@ void createDefault_passesConfig() { final var config = new Config( "url", "apiKey", - 23 + 23, + 60 ); final var sut = (DefaultImportScanService) ImportScanService.createDefault(config, ProxyConfig.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 4fc42699..3db877b3 100644 --- a/src/test/java/io/securecodebox/persistence/defectdojo/service/UserProfileServiceTest.java +++ b/src/test/java/io/securecodebox/persistence/defectdojo/service/UserProfileServiceTest.java @@ -50,7 +50,7 @@ public class UserProfileServiceTest { @BeforeEach void setup() { - config = new Config("https://defectdojo.example.com", "abc", 42); + config = new Config("https://defectdojo.example.com", "abc", 42, 60); underTest = new UserProfileService(config); mockServer = MockRestServiceServer.createServer(underTest.getRestTemplate()); }