diff --git a/scm-webapp/src/main/java/sonia/scm/security/RepositoryPermissionProvider.java b/scm-webapp/src/main/java/sonia/scm/security/RepositoryPermissionProvider.java index 0a508753bd..ca0d6d40fa 100644 --- a/scm-webapp/src/main/java/sonia/scm/security/RepositoryPermissionProvider.java +++ b/scm-webapp/src/main/java/sonia/scm/security/RepositoryPermissionProvider.java @@ -18,6 +18,7 @@ import java.util.Collection; import java.util.Enumeration; import java.util.LinkedHashSet; import java.util.List; +import java.util.Optional; import java.util.stream.Collectors; import static java.util.Collections.unmodifiableCollection; @@ -63,7 +64,7 @@ public class RepositoryPermissionProvider { RepositoryPermissionsRoot repositoryPermissionsRoot = parsePermissionDescriptor(context, descriptorUrl); availableVerbs.addAll(repositoryPermissionsRoot.verbs.verbs); - availableRoles.addAll(repositoryPermissionsRoot.roles.roles); + mergeRolesInto(availableRoles, repositoryPermissionsRoot.roles.roles); } } catch (IOException ex) { logger.error("could not read permission descriptors", ex); @@ -75,7 +76,22 @@ public class RepositoryPermissionProvider { return new AvailableRepositoryPermissions(availableVerbs, availableRoles); } - @SuppressWarnings("unchecked") + private static void mergeRolesInto(Collection targetRoles, List additionalRoles) { + additionalRoles.forEach(r -> addOrMergeInto(targetRoles, r)); + } + + private static void addOrMergeInto(Collection targetRoles, RoleDescriptor additionalRole) { + Optional existingRole = targetRoles + .stream() + .filter(r -> r.name.equals(additionalRole.name)) + .findFirst(); + if (existingRole.isPresent()) { + existingRole.get().verbs.verbs.addAll(additionalRole.verbs.verbs); + } else { + targetRoles.add(additionalRole); + } + } + private static RepositoryPermissionsRoot parsePermissionDescriptor(JAXBContext context, URL descriptorUrl) { try { RepositoryPermissionsRoot descriptorWrapper = diff --git a/scm-webapp/src/test/java/sonia/scm/security/RepositoryPermissionProviderTest.java b/scm-webapp/src/test/java/sonia/scm/security/RepositoryPermissionProviderTest.java index 9a7277ddb5..8a8d85fdb2 100644 --- a/scm-webapp/src/test/java/sonia/scm/security/RepositoryPermissionProviderTest.java +++ b/scm-webapp/src/test/java/sonia/scm/security/RepositoryPermissionProviderTest.java @@ -8,6 +8,7 @@ import sonia.scm.util.ClassLoaders; import java.lang.reflect.Field; import java.util.Arrays; +import java.util.Collection; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.fail; @@ -48,6 +49,18 @@ class RepositoryPermissionProviderTest { assertThat(repositoryPermissionProvider.availableVerbs()).contains(allVerbsFromRepositoryClass); } + @Test + void shouldMergeRepositoryRoles() { + Collection verbsInMergedRole = repositoryPermissionProvider + .availableRoles() + .stream() + .filter(r -> "READ".equals(r.getName())) + .findFirst() + .get() + .getVerbs(); + assertThat(verbsInMergedRole).contains("read", "pull", "test"); + } + private String getString(Field field) { try { return (String) field.get(null); diff --git a/scm-webapp/src/test/resources/META-INF/scm/repository-permissions.xml b/scm-webapp/src/test/resources/META-INF/scm/repository-permissions.xml new file mode 100644 index 0000000000..7da12934e5 --- /dev/null +++ b/scm-webapp/src/test/resources/META-INF/scm/repository-permissions.xml @@ -0,0 +1,13 @@ + + + test + + + + READ + + test + + + +