diff --git a/scm-core/src/main/java/sonia/scm/repository/RepositoryPermission.java b/scm-core/src/main/java/sonia/scm/repository/RepositoryPermission.java index 6bd95c9f3d..3099c1f74b 100644 --- a/scm-core/src/main/java/sonia/scm/repository/RepositoryPermission.java +++ b/scm-core/src/main/java/sonia/scm/repository/RepositoryPermission.java @@ -144,7 +144,7 @@ public class RepositoryPermission implements PermissionObject, Serializable { // Normally we do not have a log of repository permissions having the same size of verbs, but different content. // Therefore we do not use the verbs themselves for the hash code but only the number of verbs. - return Objects.hashCode(name, verbs.size(), role, groupPermission); + return Objects.hashCode(name, verbs == null? -1: verbs.size(), role, groupPermission); } diff --git a/scm-dao-xml/src/main/java/sonia/scm/repository/xml/XmlRepositoryRoleDAO.java b/scm-dao-xml/src/main/java/sonia/scm/repository/xml/XmlRepositoryRoleDAO.java index c913d57ee4..0eb860a134 100644 --- a/scm-dao-xml/src/main/java/sonia/scm/repository/xml/XmlRepositoryRoleDAO.java +++ b/scm-dao-xml/src/main/java/sonia/scm/repository/xml/XmlRepositoryRoleDAO.java @@ -6,8 +6,10 @@ import sonia.scm.repository.RepositoryRoleDAO; import sonia.scm.store.ConfigurationStoreFactory; import sonia.scm.xml.AbstractXmlDAO; +import javax.inject.Singleton; import java.util.List; +@Singleton public class XmlRepositoryRoleDAO extends AbstractXmlDAO implements RepositoryRoleDAO { diff --git a/scm-dao-xml/src/main/java/sonia/scm/repository/xml/XmlRepositoryRoleDatabase.java b/scm-dao-xml/src/main/java/sonia/scm/repository/xml/XmlRepositoryRoleDatabase.java index 8219d32a67..c7665316e2 100644 --- a/scm-dao-xml/src/main/java/sonia/scm/repository/xml/XmlRepositoryRoleDatabase.java +++ b/scm-dao-xml/src/main/java/sonia/scm/repository/xml/XmlRepositoryRoleDatabase.java @@ -21,7 +21,7 @@ public class XmlRepositoryRoleDatabase implements XmlDatabase { @XmlJavaTypeAdapter(XmlRepositoryRoleMapAdapter.class) @XmlElement(name = "roles") - private Map roleMap = new LinkedHashMap(); + private Map roleMap = new LinkedHashMap<>(); public XmlRepositoryRoleDatabase() { long c = System.currentTimeMillis(); diff --git a/scm-it/src/test/java/sonia/scm/it/RoleITCase.java b/scm-it/src/test/java/sonia/scm/it/RoleITCase.java new file mode 100644 index 0000000000..998c4e315e --- /dev/null +++ b/scm-it/src/test/java/sonia/scm/it/RoleITCase.java @@ -0,0 +1,71 @@ +package sonia.scm.it; + +import org.apache.http.HttpStatus; +import org.junit.Before; +import org.junit.Test; +import sonia.scm.it.utils.RestUtil; +import sonia.scm.it.utils.TestData; +import sonia.scm.web.VndMediaType; + +import static org.junit.Assert.assertNotNull; +import static sonia.scm.it.PermissionsITCase.USER_PASS; +import static sonia.scm.it.utils.RestUtil.given; +import static sonia.scm.it.utils.TestData.USER_SCM_ADMIN; +import static sonia.scm.it.utils.TestData.callRepository; + +public class RoleITCase { + + private static final String USER = "user"; + public static final String ROLE_NAME = "permission-role"; + + @Before + public void init() { + TestData.createDefault(); + TestData.createNotAdminUser(USER, USER_PASS); + } + + @Test + public void userShouldSeePermissionsAfterAddingRoleToUser() { + callRepository(USER, USER_PASS, "git", HttpStatus.SC_FORBIDDEN); + + given() + .when() + .delete(RestUtil.createResourceUrl("repository-roles/" + ROLE_NAME)) + .then() + .statusCode(HttpStatus.SC_NO_CONTENT); + + given(VndMediaType.REPOSITORY_ROLE) + .when() + .content("{" + + "\"name\": \"" + ROLE_NAME + "\"," + + "\"verbs\": [\"read\",\"permissionRead\"]" + + "}") + .post(RestUtil.createResourceUrl("repository-roles/")) + .then() + .statusCode(HttpStatus.SC_CREATED); + + String permissionUrl = given(VndMediaType.REPOSITORY, USER_SCM_ADMIN, USER_SCM_ADMIN) + .when() + .get(TestData.getDefaultRepositoryUrl("git")) + .then() + .statusCode(HttpStatus.SC_OK) + .extract() + .body().jsonPath().getString("_links.permissions.href"); + + given(VndMediaType.REPOSITORY_PERMISSION) + .when() + .content("{\n" + + "\t\"role\": \"" + ROLE_NAME + "\",\n" + + "\t\"name\": \"" + USER + "\",\n" + + "\t\"groupPermission\": false\n" + + "\t\n" + + "}") + .post(permissionUrl) + .then() + .statusCode(HttpStatus.SC_CREATED); + + assertNotNull(callRepository(USER, USER_PASS, "git", HttpStatus.SC_OK) + .extract() + .body().jsonPath().getString("_links.permissions.href")); + } +} diff --git a/scm-it/src/test/java/sonia/scm/it/utils/TestData.java b/scm-it/src/test/java/sonia/scm/it/utils/TestData.java index 23228d686b..20de47ffa4 100644 --- a/scm-it/src/test/java/sonia/scm/it/utils/TestData.java +++ b/scm-it/src/test/java/sonia/scm/it/utils/TestData.java @@ -106,14 +106,31 @@ public class TestData { ; } - public static void createUserPermission(String name, Collection permissionType, String repositoryType) { + public static void createUserPermission(String username, Collection verbs, String repositoryType) { String defaultPermissionUrl = TestData.getDefaultPermissionUrl(USER_SCM_ADMIN, USER_SCM_ADMIN, repositoryType); - LOG.info("create permission with name {} and type: {} using the endpoint: {}", name, permissionType, defaultPermissionUrl); + LOG.info("create permission with name {} and verbs {} using the endpoint: {}", username, verbs, defaultPermissionUrl); given(VndMediaType.REPOSITORY_PERMISSION) .when() .content("{\n" + - "\t\"verbs\": " + permissionType.stream().collect(Collectors.joining("\",\"", "[\"", "\"]")) + ",\n" + - "\t\"name\": \"" + name + "\",\n" + + "\t\"verbs\": " + verbs.stream().collect(Collectors.joining("\",\"", "[\"", "\"]")) + ",\n" + + "\t\"name\": \"" + username + "\",\n" + + "\t\"groupPermission\": false\n" + + "\t\n" + + "}") + .post(defaultPermissionUrl) + .then() + .statusCode(HttpStatus.SC_CREATED) + ; + } + + public static void createUserPermission(String username, String roleName, String repositoryType) { + String defaultPermissionUrl = TestData.getDefaultPermissionUrl(USER_SCM_ADMIN, USER_SCM_ADMIN, repositoryType); + LOG.info("create permission with name {} and role {} using the endpoint: {}", username, roleName, defaultPermissionUrl); + given(VndMediaType.REPOSITORY_PERMISSION) + .when() + .content("{\n" + + "\t\"role\": " + roleName + ",\n" + + "\t\"name\": \"" + username + "\",\n" + "\t\"groupPermission\": false\n" + "\t\n" + "}") 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 292feee7c1..bacd9fb637 100644 --- a/scm-webapp/src/main/java/sonia/scm/security/RepositoryPermissionProvider.java +++ b/scm-webapp/src/main/java/sonia/scm/security/RepositoryPermissionProvider.java @@ -1,30 +1,12 @@ package sonia.scm.security; import com.google.inject.Inject; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import sonia.scm.plugin.PluginLoader; import sonia.scm.repository.RepositoryRole; import sonia.scm.repository.RepositoryRoleDAO; -import javax.xml.bind.JAXBContext; -import javax.xml.bind.JAXBException; -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlRootElement; -import java.io.IOException; -import java.net.URL; import java.util.AbstractList; -import java.util.ArrayList; import java.util.Collection; -import java.util.Enumeration; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Optional; -import java.util.Set; - -import static java.util.Collections.unmodifiableCollection; +import java.util.List ; public class RepositoryPermissionProvider { @@ -42,8 +24,8 @@ public class RepositoryPermissionProvider { } public Collection availableRoles() { - List customRoles = repositoryRoleDAO.getAll(); List availableSystemRoles = systemRepositoryPermissionProvider.availableRoles(); + List customRoles = repositoryRoleDAO.getAll(); return new AbstractList() { @Override