From 80e0ffdc61640e731029ecc1e046b133dd919b46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maren=20S=C3=BCwer?= Date: Mon, 28 Jan 2019 15:12:26 +0100 Subject: [PATCH 1/5] disable add admin group/user button when entry is empty --- .../packages/ui-components/src/forms/AddEntryToTableField.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scm-ui-components/packages/ui-components/src/forms/AddEntryToTableField.js b/scm-ui-components/packages/ui-components/src/forms/AddEntryToTableField.js index e5c04eb613..013014cd98 100644 --- a/scm-ui-components/packages/ui-components/src/forms/AddEntryToTableField.js +++ b/scm-ui-components/packages/ui-components/src/forms/AddEntryToTableField.js @@ -48,7 +48,7 @@ class AddEntryToTableField extends React.Component { ); From 225fb0a705fdfb92c601e7db70d1b07ff41b31dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Thu, 31 Jan 2019 11:39:16 +0100 Subject: [PATCH 2/5] Validate groups and users in backend, too --- .../sonia/scm/api/v2/resources/ConfigDto.java | 2 ++ .../scm/api/v2/resources/ConfigResource.java | 3 ++- .../scm/api/v2/resources/NoBlankStrings.java | 26 +++++++++++++++++++ .../v2/resources/NoBlankStringsValidator.java | 23 ++++++++++++++++ 4 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 scm-webapp/src/main/java/sonia/scm/api/v2/resources/NoBlankStrings.java create mode 100644 scm-webapp/src/main/java/sonia/scm/api/v2/resources/NoBlankStringsValidator.java diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/ConfigDto.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/ConfigDto.java index 4c9620564b..f77823eaac 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/ConfigDto.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/ConfigDto.java @@ -23,7 +23,9 @@ public class ConfigDto extends HalRepresentation { private boolean disableGroupingGrid; private String dateFormat; private boolean anonymousAccessEnabled; + @NoBlankStrings private Set adminGroups; + @NoBlankStrings private Set adminUsers; private String baseUrl; private boolean forceBaseUrl; diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/ConfigResource.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/ConfigResource.java index bf3a11fb9c..c646dceab4 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/ConfigResource.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/ConfigResource.java @@ -9,6 +9,7 @@ import sonia.scm.util.ScmConfigurationUtil; import sonia.scm.web.VndMediaType; import javax.inject.Inject; +import javax.validation.Valid; import javax.ws.rs.Consumes; import javax.ws.rs.GET; import javax.ws.rs.PUT; @@ -71,7 +72,7 @@ public class ConfigResource { @ResponseCode(code = 500, condition = "internal server error") }) @TypeHint(TypeHint.NO_CONTENT.class) - public Response update(ConfigDto configDto) { + public Response update(@Valid ConfigDto configDto) { // This *could* be moved to ScmConfiguration or ScmConfigurationUtil classes. // But to where to check? load() or store()? Leave it for now, SCMv1 legacy that can be cleaned up later. diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/NoBlankStrings.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/NoBlankStrings.java new file mode 100644 index 0000000000..ba5e20ffbd --- /dev/null +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/NoBlankStrings.java @@ -0,0 +1,26 @@ +package sonia.scm.api.v2.resources; + +import javax.validation.Constraint; +import javax.validation.Payload; +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.ANNOTATION_TYPE; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +@Target({FIELD, METHOD, PARAMETER, ANNOTATION_TYPE}) +@Retention(RUNTIME) +@Constraint(validatedBy = NoBlankStringsValidator.class) +@Documented +public @interface NoBlankStrings { + + String message() default "collection must not contain empty strings"; + + Class[] groups() default {}; + + Class[] payload() default {}; +} diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/NoBlankStringsValidator.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/NoBlankStringsValidator.java new file mode 100644 index 0000000000..6bae44164e --- /dev/null +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/NoBlankStringsValidator.java @@ -0,0 +1,23 @@ +package sonia.scm.api.v2.resources; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; +import java.util.Collection; + +public class NoBlankStringsValidator implements ConstraintValidator { + + @Override + public void initialize(NoBlankStrings constraintAnnotation) { + } + + @Override + public boolean isValid(Collection object, ConstraintValidatorContext constraintContext) { + if ( object == null || object.isEmpty()) { + return true; + } + return object.stream() + .map(x -> x.toString()) + .map(s -> ((String) s).trim()) + .noneMatch(s -> ((String) s).isEmpty()); + } +} From bd91036f725ee0bbe25da89d4e69209c77db47fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Thu, 31 Jan 2019 11:56:27 +0100 Subject: [PATCH 3/5] Add unit test --- .../api/v2/resources/ConfigResourceTest.java | 42 ++++++++++++++----- .../api/v2/config-test-empty-admin-group.json | 3 ++ .../api/v2/config-test-empty-admin-user.json | 3 ++ 3 files changed, 38 insertions(+), 10 deletions(-) create mode 100644 scm-webapp/src/test/resources/sonia/scm/api/v2/config-test-empty-admin-group.json create mode 100644 scm-webapp/src/test/resources/sonia/scm/api/v2/config-test-empty-admin-user.json diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/ConfigResourceTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/ConfigResourceTest.java index 033824cbea..4fb25d2371 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/ConfigResourceTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/ConfigResourceTest.java @@ -92,11 +92,7 @@ public class ConfigResourceTest { @Test @SubjectAware(username = "readWrite") public void shouldUpdateConfig() throws URISyntaxException, IOException { - URL url = Resources.getResource("sonia/scm/api/v2/config-test-update.json"); - byte[] configJson = Resources.toByteArray(url); - MockHttpRequest request = MockHttpRequest.put("/" + ConfigResource.CONFIG_PATH_V2) - .contentType(VndMediaType.CONFIG) - .content(configJson); + MockHttpRequest request = post("sonia/scm/api/v2/config-test-update.json"); MockHttpResponse response = new MockHttpResponse(); dispatcher.invoke(request, response); @@ -113,11 +109,7 @@ public class ConfigResourceTest { @Test @SubjectAware(username = "readOnly") public void shouldNotUpdateConfigWhenNotAuthorized() throws URISyntaxException, IOException { - URL url = Resources.getResource("sonia/scm/api/v2/config-test-update.json"); - byte[] configJson = Resources.toByteArray(url); - MockHttpRequest request = MockHttpRequest.put("/" + ConfigResource.CONFIG_PATH_V2) - .contentType(VndMediaType.CONFIG) - .content(configJson); + MockHttpRequest request = post("sonia/scm/api/v2/config-test-update.json"); MockHttpResponse response = new MockHttpResponse(); thrown.expectMessage("Subject does not have permission [configuration:write:global]"); @@ -125,6 +117,36 @@ public class ConfigResourceTest { dispatcher.invoke(request, response); } + @Test + @SubjectAware(username = "readWrite") + public void shouldFailForEmptyAdminUsers() throws URISyntaxException, IOException { + MockHttpRequest request = post("sonia/scm/api/v2/config-test-empty-admin-user.json"); + + MockHttpResponse response = new MockHttpResponse(); + dispatcher.invoke(request, response); + + assertEquals(HttpServletResponse.SC_BAD_REQUEST, response.getStatus()); + } + + @Test + @SubjectAware(username = "readWrite") + public void shouldFailForEmptyAdminGroups() throws URISyntaxException, IOException { + MockHttpRequest request = post("sonia/scm/api/v2/config-test-empty-admin-group.json"); + + MockHttpResponse response = new MockHttpResponse(); + dispatcher.invoke(request, response); + + assertEquals(HttpServletResponse.SC_BAD_REQUEST, response.getStatus()); + } + + private MockHttpRequest post(String resourceName) throws IOException, URISyntaxException { + URL url = Resources.getResource(resourceName); + byte[] configJson = Resources.toByteArray(url); + return MockHttpRequest.put("/" + ConfigResource.CONFIG_PATH_V2) + .contentType(VndMediaType.CONFIG) + .content(configJson); + } + private static ScmConfiguration createConfiguration() { ScmConfiguration scmConfiguration = new ScmConfiguration(); scmConfiguration.setProxyPassword("heartOfGold"); diff --git a/scm-webapp/src/test/resources/sonia/scm/api/v2/config-test-empty-admin-group.json b/scm-webapp/src/test/resources/sonia/scm/api/v2/config-test-empty-admin-group.json new file mode 100644 index 0000000000..f665c29ee7 --- /dev/null +++ b/scm-webapp/src/test/resources/sonia/scm/api/v2/config-test-empty-admin-group.json @@ -0,0 +1,3 @@ +{ + "adminGroups": [""] +} diff --git a/scm-webapp/src/test/resources/sonia/scm/api/v2/config-test-empty-admin-user.json b/scm-webapp/src/test/resources/sonia/scm/api/v2/config-test-empty-admin-user.json new file mode 100644 index 0000000000..61efcb1609 --- /dev/null +++ b/scm-webapp/src/test/resources/sonia/scm/api/v2/config-test-empty-admin-user.json @@ -0,0 +1,3 @@ +{ + "adminUsers": [""] +} From ed57450dc3971b3f22476ced3ebdcb4736bbd043 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Thu, 31 Jan 2019 12:00:40 +0100 Subject: [PATCH 4/5] Add unit test --- .../NoBlankStringsValidatorTest.java | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 scm-webapp/src/test/java/sonia/scm/api/v2/resources/NoBlankStringsValidatorTest.java diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/NoBlankStringsValidatorTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/NoBlankStringsValidatorTest.java new file mode 100644 index 0000000000..1929b0bb06 --- /dev/null +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/NoBlankStringsValidatorTest.java @@ -0,0 +1,28 @@ +package sonia.scm.api.v2.resources; + +import org.junit.jupiter.api.Test; + +import java.util.Arrays; +import java.util.Collections; + +import static java.util.Collections.emptySet; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class NoBlankStringsValidatorTest { + + @Test + void shouldAcceptNonEmptyElements() { + assertTrue(new NoBlankStringsValidator().isValid(Arrays.asList("not", "empty"), null)); + } + + @Test + void shouldFailForEmptyElements() { + assertFalse(new NoBlankStringsValidator().isValid(Arrays.asList("one", "", "three"), null)); + } + + @Test + void shouldAcceptEmptyList() { + assertTrue(new NoBlankStringsValidator().isValid(emptySet(), null)); + } +} From 82aff173372c79496564c347d9109bb8b704797f Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Fri, 1 Feb 2019 07:30:31 +0000 Subject: [PATCH 5/5] Close branch bugfix/forbid_empty_groups_users_at_global_permission