From 9b4fc5e3d8099854b084f02f770edf4899bf7b36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Tue, 22 Jan 2019 17:22:59 +0100 Subject: [PATCH] Persist permissions in repository --- .../java/sonia/scm/repository/Repository.java | 31 +++++++++++++++++-- .../scm/repository/RepositoryPermission.java | 25 ++++++++------- .../RepositoryCollectionResource.java | 7 +++-- .../RepositoryPermissionRootResourceTest.java | 19 ++++++------ ...onToRepositoryPermissionDtoMapperTest.java | 5 +-- .../DefaultAuthorizationCollectorTest.java | 3 +- 6 files changed, 63 insertions(+), 27 deletions(-) diff --git a/scm-core/src/main/java/sonia/scm/repository/Repository.java b/scm-core/src/main/java/sonia/scm/repository/Repository.java index 310a0f0556..3adb215d27 100644 --- a/scm-core/src/main/java/sonia/scm/repository/Repository.java +++ b/scm-core/src/main/java/sonia/scm/repository/Repository.java @@ -80,6 +80,7 @@ public class Repository extends BasicPropertiesAware implements ModelObject, Per private Long lastModified; private String namespace; private String name; + private final Set permissions = new HashSet<>(); @XmlElement(name = "public") private boolean publicReadable = false; private boolean archived = false; @@ -117,14 +118,20 @@ public class Repository extends BasicPropertiesAware implements ModelObject, Per * @param contact email address of a person who is responsible for * this repository. * @param description a short description of the repository + * @param permissions permissions for specific users and groups. */ - public Repository(String id, String type, String namespace, String name, String contact, String description) { + public Repository(String id, String type, String namespace, String name, String contact, + String description, RepositoryPermission... permissions) { this.id = id; this.type = type; this.namespace = namespace; this.name = name; this.contact = contact; this.description = description; + + if (Util.isNotEmpty(permissions)) { + this.permissions.addAll(Arrays.asList(permissions)); + } } /** @@ -193,6 +200,10 @@ public class Repository extends BasicPropertiesAware implements ModelObject, Per return new NamespaceAndName(getNamespace(), getName()); } + public Collection getPermissions() { + return Collections.unmodifiableCollection(permissions); + } + /** * Returns the type (hg, git, svn ...) of the {@link Repository}. * @@ -285,6 +296,19 @@ public class Repository extends BasicPropertiesAware implements ModelObject, Per this.name = name; } + public void setPermissions(Collection permissions) { + this.permissions.clear(); + this.permissions.addAll(permissions); + } + + public void addPermission(RepositoryPermission newPermission) { + this.permissions.add(newPermission); + } + + public void removePermission(RepositoryPermission permission) { + this.permissions.remove(permission); + } + public void setPublicReadable(boolean publicReadable) { this.publicReadable = publicReadable; } @@ -322,6 +346,7 @@ public class Repository extends BasicPropertiesAware implements ModelObject, Per repository.setCreationDate(creationDate); repository.setLastModified(lastModified); repository.setDescription(description); + repository.setPermissions(permissions); repository.setPublicReadable(publicReadable); repository.setArchived(archived); @@ -353,6 +378,7 @@ public class Repository extends BasicPropertiesAware implements ModelObject, Per && Objects.equal(description, other.description) && Objects.equal(publicReadable, other.publicReadable) && Objects.equal(archived, other.archived) + && Objects.equal(permissions, other.permissions) && Objects.equal(type, other.type) && Objects.equal(creationDate, other.creationDate) && Objects.equal(lastModified, other.lastModified) @@ -363,7 +389,7 @@ public class Repository extends BasicPropertiesAware implements ModelObject, Per @Override public int hashCode() { return Objects.hashCode(id, namespace, name, contact, description, publicReadable, - archived, type, creationDate, lastModified, properties, + archived, permissions, type, creationDate, lastModified, properties, healthCheckFailures); } @@ -377,6 +403,7 @@ public class Repository extends BasicPropertiesAware implements ModelObject, Per .add("description", description) .add("publicReadable", publicReadable) .add("archived", archived) + .add("permissions", permissions) .add("type", type) .add("lastModified", lastModified) .add("creationDate", creationDate) 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 492142674d..70d0c8491e 100644 --- a/scm-core/src/main/java/sonia/scm/repository/RepositoryPermission.java +++ b/scm-core/src/main/java/sonia/scm/repository/RepositoryPermission.java @@ -41,8 +41,10 @@ import sonia.scm.security.PermissionObject; 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.Serializable; +import java.util.Collection; //~--- JDK imports ------------------------------------------------------------ @@ -60,7 +62,8 @@ public class RepositoryPermission implements PermissionObject, Serializable private boolean groupPermission = false; private String name; - private String verb; + @XmlElement(name = "verb") + private Collection verbs; /** * Constructs a new {@link RepositoryPermission}. @@ -68,10 +71,10 @@ public class RepositoryPermission implements PermissionObject, Serializable */ public RepositoryPermission() {} - public RepositoryPermission(String name, String verb, boolean groupPermission) + public RepositoryPermission(String name, Collection verbs, boolean groupPermission) { this.name = name; - this.verb = verb; + this.verbs = verbs; this.groupPermission = groupPermission; } @@ -101,7 +104,7 @@ public class RepositoryPermission implements PermissionObject, Serializable final RepositoryPermission other = (RepositoryPermission) obj; return Objects.equal(name, other.name) - && Objects.equal(verb, other.verb) + && Objects.equal(verbs, other.verbs) && Objects.equal(groupPermission, other.groupPermission); } @@ -114,7 +117,7 @@ public class RepositoryPermission implements PermissionObject, Serializable @Override public int hashCode() { - return Objects.hashCode(name, verb, groupPermission); + return Objects.hashCode(name, verbs, groupPermission); } @@ -124,7 +127,7 @@ public class RepositoryPermission implements PermissionObject, Serializable //J- return MoreObjects.toStringHelper(this) .add("name", name) - .add("verb", verb) + .add("verbs", verbs) .add("groupPermission", groupPermission) .toString(); //J+ @@ -150,9 +153,9 @@ public class RepositoryPermission implements PermissionObject, Serializable * * @return verb of the permission */ - public String getVerb() + public Collection getVerbs() { - return verb; + return verbs; } /** @@ -195,10 +198,10 @@ public class RepositoryPermission implements PermissionObject, Serializable * Sets the verb of the permission. * * - * @param verb verb of the permission + * @param verbs verbs of the permission */ - public void setVerb(String verb) + public void setVerbs(Collection verbs) { - this.verb = verb; + this.verbs = verbs; } } diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryCollectionResource.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryCollectionResource.java index cfcd279692..a9bd5c2424 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryCollectionResource.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryCollectionResource.java @@ -8,6 +8,7 @@ import com.webcohesion.enunciate.metadata.rs.TypeHint; import org.apache.shiro.SecurityUtils; import sonia.scm.repository.Repository; import sonia.scm.repository.RepositoryManager; +import sonia.scm.repository.RepositoryPermission; import sonia.scm.user.User; import sonia.scm.web.VndMediaType; @@ -22,6 +23,9 @@ import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.Response; +import static java.util.Arrays.asList; +import static java.util.Collections.singletonList; + public class RepositoryCollectionResource { private static final int DEFAULT_PAGE_SIZE = 10; @@ -96,8 +100,7 @@ public class RepositoryCollectionResource { private Repository createModelObjectFromDto(@Valid RepositoryDto repositoryDto) { Repository repository = dtoToRepositoryMapper.map(repositoryDto, null); - // TODO RP -// repository.setPermissions(singletonList(new RepositoryPermission(currentUser(), PermissionType.OWNER))); + repository.setPermissions(singletonList(new RepositoryPermission(currentUser(), singletonList("*"), false))); return repository; } diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryPermissionRootResourceTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryPermissionRootResourceTest.java index b66a274f0d..9fe13a71d8 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryPermissionRootResourceTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryPermissionRootResourceTest.java @@ -46,6 +46,7 @@ import java.util.stream.Stream; import static de.otto.edison.hal.Link.link; import static de.otto.edison.hal.Links.linkingTo; +import static java.util.Arrays.asList; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; @@ -78,12 +79,12 @@ public class RepositoryPermissionRootResourceTest extends RepositoryTestBase { private static final String PERMISSION_TEST_PAYLOAD = "{ \"name\" : \"permission_name\", \"type\" : \"READ\" }"; private static final ArrayList TEST_PERMISSIONS = Lists .newArrayList( - new RepositoryPermission("user_write", "read,modify", false), - new RepositoryPermission("user_read", "read", false), - new RepositoryPermission("user_owner", "read,modify,delete", false), - new RepositoryPermission("group_read", "read", true), - new RepositoryPermission("group_write", "read,modify", true), - new RepositoryPermission("group_owner", "read,modify,delete", true) + new RepositoryPermission("user_write", asList("read","modify"), false), + new RepositoryPermission("user_read", asList("read"), false), + new RepositoryPermission("user_owner", asList("*"), false), + new RepositoryPermission("group_read", asList("read"), true), + new RepositoryPermission("group_write", asList("read","modify"), true), + new RepositoryPermission("group_owner", asList("*"), true) ); private final ExpectedRequest requestGETAllPermissions = new ExpectedRequest() .description("GET all permissions") @@ -258,7 +259,7 @@ public class RepositoryPermissionRootResourceTest extends RepositoryTestBase { @Test public void shouldGetCreatedPermissions() throws URISyntaxException { createUserWithRepositoryAndPermissions(TEST_PERMISSIONS, PERMISSION_WRITE); - RepositoryPermission newPermission = new RepositoryPermission("new_group_perm", "read,modify", true); + RepositoryPermission newPermission = new RepositoryPermission("new_group_perm", asList("read","modify"), true); ArrayList permissions = Lists.newArrayList(TEST_PERMISSIONS); permissions.add(newPermission); ImmutableList expectedPermissions = ImmutableList.copyOf(permissions); @@ -287,7 +288,7 @@ public class RepositoryPermissionRootResourceTest extends RepositoryTestBase { createUserWithRepositoryAndPermissions(TEST_PERMISSIONS, PERMISSION_WRITE); RepositoryPermission modifiedPermission = TEST_PERMISSIONS.get(0); // modify the type to owner - modifiedPermission.setVerb("read,modify,delete"); + modifiedPermission.setVerbs(asList("read", "modify", "delete")); ImmutableList expectedPermissions = ImmutableList.copyOf(TEST_PERMISSIONS); assertExpectedRequest(requestPUTPermission .content("{\"name\" : \"" + modifiedPermission.getName() + "\" , \"type\" : \"OWNER\" , \"groupPermission\" : false}") @@ -381,7 +382,7 @@ public class RepositoryPermissionRootResourceTest extends RepositoryTestBase { RepositoryPermissionDto result = new RepositoryPermissionDto(); result.setName(permission.getName()); result.setGroupPermission(permission.isGroupPermission()); - result.setType(permission.getVerb()); +// result.setType(permission.getVerbs()); TODO RP String permissionName = Optional.of(permission.getName()) .filter(p -> !permission.isGroupPermission()) .orElse(GROUP_PREFIX + permission.getName()); diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryPermissionToRepositoryPermissionDtoMapperTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryPermissionToRepositoryPermissionDtoMapperTest.java index 09a3ab4855..97146e67ff 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryPermissionToRepositoryPermissionDtoMapperTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryPermissionToRepositoryPermissionDtoMapperTest.java @@ -12,6 +12,7 @@ import sonia.scm.repository.Repository; import java.net.URI; +import static java.util.Arrays.asList; import static org.assertj.core.api.Assertions.assertThat; @RunWith(MockitoJUnitRunner.Silent.class) @@ -35,7 +36,7 @@ public class RepositoryPermissionToRepositoryPermissionDtoMapperTest { @SubjectAware(username = "trillian", password = "secret") public void shouldMapGroupPermissionCorrectly() { Repository repository = getDummyRepository(); - RepositoryPermission permission = new RepositoryPermission("42", "read,modify,delete", true); + RepositoryPermission permission = new RepositoryPermission("42", asList("read","modify","delete"), true); RepositoryPermissionDto repositoryPermissionDto = mapper.map(permission, repository); @@ -47,7 +48,7 @@ public class RepositoryPermissionToRepositoryPermissionDtoMapperTest { @SubjectAware(username = "trillian", password = "secret") public void shouldMapNonGroupPermissionCorrectly() { Repository repository = getDummyRepository(); - RepositoryPermission permission = new RepositoryPermission("42", "read,modify,delete", false); + RepositoryPermission permission = new RepositoryPermission("42", asList("read","modify","delete"), false); RepositoryPermissionDto repositoryPermissionDto = mapper.map(permission, repository); diff --git a/scm-webapp/src/test/java/sonia/scm/security/DefaultAuthorizationCollectorTest.java b/scm-webapp/src/test/java/sonia/scm/security/DefaultAuthorizationCollectorTest.java index bfb97d0b40..d04c35686f 100644 --- a/scm-webapp/src/test/java/sonia/scm/security/DefaultAuthorizationCollectorTest.java +++ b/scm-webapp/src/test/java/sonia/scm/security/DefaultAuthorizationCollectorTest.java @@ -58,6 +58,7 @@ import sonia.scm.repository.RepositoryTestData; import sonia.scm.user.User; import sonia.scm.user.UserTestData; +import static java.util.Arrays.asList; import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.nullValue; @@ -228,7 +229,7 @@ public class DefaultAuthorizationCollectorTest { // heartOfGold.setPermissions(Lists.newArrayList(new RepositoryPermission("trillian"))); Repository puzzle42 = RepositoryTestData.create42Puzzle(); puzzle42.setId("two"); - RepositoryPermission permission = new RepositoryPermission(group, "read,modify", true); + RepositoryPermission permission = new RepositoryPermission(group, asList("read","modify"), true); // puzzle42.setPermissions(Lists.newArrayList(permission)); when(repositoryDAO.getAll()).thenReturn(Lists.newArrayList(heartOfGold, puzzle42));