Persist permissions in repository

This commit is contained in:
René Pfeuffer
2019-01-22 17:22:59 +01:00
parent 101b21e914
commit 9b4fc5e3d8
6 changed files with 63 additions and 27 deletions

View File

@@ -80,6 +80,7 @@ public class Repository extends BasicPropertiesAware implements ModelObject, Per
private Long lastModified; private Long lastModified;
private String namespace; private String namespace;
private String name; private String name;
private final Set<RepositoryPermission> permissions = new HashSet<>();
@XmlElement(name = "public") @XmlElement(name = "public")
private boolean publicReadable = false; private boolean publicReadable = false;
private boolean archived = 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 * @param contact email address of a person who is responsible for
* this repository. * this repository.
* @param description a short description of the 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.id = id;
this.type = type; this.type = type;
this.namespace = namespace; this.namespace = namespace;
this.name = name; this.name = name;
this.contact = contact; this.contact = contact;
this.description = description; 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()); return new NamespaceAndName(getNamespace(), getName());
} }
public Collection<RepositoryPermission> getPermissions() {
return Collections.unmodifiableCollection(permissions);
}
/** /**
* Returns the type (hg, git, svn ...) of the {@link Repository}. * 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; this.name = name;
} }
public void setPermissions(Collection<RepositoryPermission> 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) { public void setPublicReadable(boolean publicReadable) {
this.publicReadable = publicReadable; this.publicReadable = publicReadable;
} }
@@ -322,6 +346,7 @@ public class Repository extends BasicPropertiesAware implements ModelObject, Per
repository.setCreationDate(creationDate); repository.setCreationDate(creationDate);
repository.setLastModified(lastModified); repository.setLastModified(lastModified);
repository.setDescription(description); repository.setDescription(description);
repository.setPermissions(permissions);
repository.setPublicReadable(publicReadable); repository.setPublicReadable(publicReadable);
repository.setArchived(archived); repository.setArchived(archived);
@@ -353,6 +378,7 @@ public class Repository extends BasicPropertiesAware implements ModelObject, Per
&& Objects.equal(description, other.description) && Objects.equal(description, other.description)
&& Objects.equal(publicReadable, other.publicReadable) && Objects.equal(publicReadable, other.publicReadable)
&& Objects.equal(archived, other.archived) && Objects.equal(archived, other.archived)
&& Objects.equal(permissions, other.permissions)
&& Objects.equal(type, other.type) && Objects.equal(type, other.type)
&& Objects.equal(creationDate, other.creationDate) && Objects.equal(creationDate, other.creationDate)
&& Objects.equal(lastModified, other.lastModified) && Objects.equal(lastModified, other.lastModified)
@@ -363,7 +389,7 @@ public class Repository extends BasicPropertiesAware implements ModelObject, Per
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hashCode(id, namespace, name, contact, description, publicReadable, return Objects.hashCode(id, namespace, name, contact, description, publicReadable,
archived, type, creationDate, lastModified, properties, archived, permissions, type, creationDate, lastModified, properties,
healthCheckFailures); healthCheckFailures);
} }
@@ -377,6 +403,7 @@ public class Repository extends BasicPropertiesAware implements ModelObject, Per
.add("description", description) .add("description", description)
.add("publicReadable", publicReadable) .add("publicReadable", publicReadable)
.add("archived", archived) .add("archived", archived)
.add("permissions", permissions)
.add("type", type) .add("type", type)
.add("lastModified", lastModified) .add("lastModified", lastModified)
.add("creationDate", creationDate) .add("creationDate", creationDate)

View File

@@ -41,8 +41,10 @@ import sonia.scm.security.PermissionObject;
import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlRootElement;
import java.io.Serializable; import java.io.Serializable;
import java.util.Collection;
//~--- JDK imports ------------------------------------------------------------ //~--- JDK imports ------------------------------------------------------------
@@ -60,7 +62,8 @@ public class RepositoryPermission implements PermissionObject, Serializable
private boolean groupPermission = false; private boolean groupPermission = false;
private String name; private String name;
private String verb; @XmlElement(name = "verb")
private Collection<String> verbs;
/** /**
* Constructs a new {@link RepositoryPermission}. * Constructs a new {@link RepositoryPermission}.
@@ -68,10 +71,10 @@ public class RepositoryPermission implements PermissionObject, Serializable
*/ */
public RepositoryPermission() {} public RepositoryPermission() {}
public RepositoryPermission(String name, String verb, boolean groupPermission) public RepositoryPermission(String name, Collection<String> verbs, boolean groupPermission)
{ {
this.name = name; this.name = name;
this.verb = verb; this.verbs = verbs;
this.groupPermission = groupPermission; this.groupPermission = groupPermission;
} }
@@ -101,7 +104,7 @@ public class RepositoryPermission implements PermissionObject, Serializable
final RepositoryPermission other = (RepositoryPermission) obj; final RepositoryPermission other = (RepositoryPermission) obj;
return Objects.equal(name, other.name) return Objects.equal(name, other.name)
&& Objects.equal(verb, other.verb) && Objects.equal(verbs, other.verbs)
&& Objects.equal(groupPermission, other.groupPermission); && Objects.equal(groupPermission, other.groupPermission);
} }
@@ -114,7 +117,7 @@ public class RepositoryPermission implements PermissionObject, Serializable
@Override @Override
public int hashCode() 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- //J-
return MoreObjects.toStringHelper(this) return MoreObjects.toStringHelper(this)
.add("name", name) .add("name", name)
.add("verb", verb) .add("verbs", verbs)
.add("groupPermission", groupPermission) .add("groupPermission", groupPermission)
.toString(); .toString();
//J+ //J+
@@ -150,9 +153,9 @@ public class RepositoryPermission implements PermissionObject, Serializable
* *
* @return verb of the permission * @return verb of the permission
*/ */
public String getVerb() public Collection<String> getVerbs()
{ {
return verb; return verbs;
} }
/** /**
@@ -195,10 +198,10 @@ public class RepositoryPermission implements PermissionObject, Serializable
* Sets the verb of the permission. * 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<String> verbs)
{ {
this.verb = verb; this.verbs = verbs;
} }
} }

View File

@@ -8,6 +8,7 @@ import com.webcohesion.enunciate.metadata.rs.TypeHint;
import org.apache.shiro.SecurityUtils; import org.apache.shiro.SecurityUtils;
import sonia.scm.repository.Repository; import sonia.scm.repository.Repository;
import sonia.scm.repository.RepositoryManager; import sonia.scm.repository.RepositoryManager;
import sonia.scm.repository.RepositoryPermission;
import sonia.scm.user.User; import sonia.scm.user.User;
import sonia.scm.web.VndMediaType; import sonia.scm.web.VndMediaType;
@@ -22,6 +23,9 @@ import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam; import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
import static java.util.Arrays.asList;
import static java.util.Collections.singletonList;
public class RepositoryCollectionResource { public class RepositoryCollectionResource {
private static final int DEFAULT_PAGE_SIZE = 10; private static final int DEFAULT_PAGE_SIZE = 10;
@@ -96,8 +100,7 @@ public class RepositoryCollectionResource {
private Repository createModelObjectFromDto(@Valid RepositoryDto repositoryDto) { private Repository createModelObjectFromDto(@Valid RepositoryDto repositoryDto) {
Repository repository = dtoToRepositoryMapper.map(repositoryDto, null); Repository repository = dtoToRepositoryMapper.map(repositoryDto, null);
// TODO RP repository.setPermissions(singletonList(new RepositoryPermission(currentUser(), singletonList("*"), false)));
// repository.setPermissions(singletonList(new RepositoryPermission(currentUser(), PermissionType.OWNER)));
return repository; return repository;
} }

View File

@@ -46,6 +46,7 @@ import java.util.stream.Stream;
import static de.otto.edison.hal.Link.link; import static de.otto.edison.hal.Link.link;
import static de.otto.edison.hal.Links.linkingTo; 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.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail; 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 String PERMISSION_TEST_PAYLOAD = "{ \"name\" : \"permission_name\", \"type\" : \"READ\" }";
private static final ArrayList<RepositoryPermission> TEST_PERMISSIONS = Lists private static final ArrayList<RepositoryPermission> TEST_PERMISSIONS = Lists
.newArrayList( .newArrayList(
new RepositoryPermission("user_write", "read,modify", false), new RepositoryPermission("user_write", asList("read","modify"), false),
new RepositoryPermission("user_read", "read", false), new RepositoryPermission("user_read", asList("read"), false),
new RepositoryPermission("user_owner", "read,modify,delete", false), new RepositoryPermission("user_owner", asList("*"), false),
new RepositoryPermission("group_read", "read", true), new RepositoryPermission("group_read", asList("read"), true),
new RepositoryPermission("group_write", "read,modify", true), new RepositoryPermission("group_write", asList("read","modify"), true),
new RepositoryPermission("group_owner", "read,modify,delete", true) new RepositoryPermission("group_owner", asList("*"), true)
); );
private final ExpectedRequest requestGETAllPermissions = new ExpectedRequest() private final ExpectedRequest requestGETAllPermissions = new ExpectedRequest()
.description("GET all permissions") .description("GET all permissions")
@@ -258,7 +259,7 @@ public class RepositoryPermissionRootResourceTest extends RepositoryTestBase {
@Test @Test
public void shouldGetCreatedPermissions() throws URISyntaxException { public void shouldGetCreatedPermissions() throws URISyntaxException {
createUserWithRepositoryAndPermissions(TEST_PERMISSIONS, PERMISSION_WRITE); 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<RepositoryPermission> permissions = Lists.newArrayList(TEST_PERMISSIONS); ArrayList<RepositoryPermission> permissions = Lists.newArrayList(TEST_PERMISSIONS);
permissions.add(newPermission); permissions.add(newPermission);
ImmutableList<RepositoryPermission> expectedPermissions = ImmutableList.copyOf(permissions); ImmutableList<RepositoryPermission> expectedPermissions = ImmutableList.copyOf(permissions);
@@ -287,7 +288,7 @@ public class RepositoryPermissionRootResourceTest extends RepositoryTestBase {
createUserWithRepositoryAndPermissions(TEST_PERMISSIONS, PERMISSION_WRITE); createUserWithRepositoryAndPermissions(TEST_PERMISSIONS, PERMISSION_WRITE);
RepositoryPermission modifiedPermission = TEST_PERMISSIONS.get(0); RepositoryPermission modifiedPermission = TEST_PERMISSIONS.get(0);
// modify the type to owner // modify the type to owner
modifiedPermission.setVerb("read,modify,delete"); modifiedPermission.setVerbs(asList("read", "modify", "delete"));
ImmutableList<RepositoryPermission> expectedPermissions = ImmutableList.copyOf(TEST_PERMISSIONS); ImmutableList<RepositoryPermission> expectedPermissions = ImmutableList.copyOf(TEST_PERMISSIONS);
assertExpectedRequest(requestPUTPermission assertExpectedRequest(requestPUTPermission
.content("{\"name\" : \"" + modifiedPermission.getName() + "\" , \"type\" : \"OWNER\" , \"groupPermission\" : false}") .content("{\"name\" : \"" + modifiedPermission.getName() + "\" , \"type\" : \"OWNER\" , \"groupPermission\" : false}")
@@ -381,7 +382,7 @@ public class RepositoryPermissionRootResourceTest extends RepositoryTestBase {
RepositoryPermissionDto result = new RepositoryPermissionDto(); RepositoryPermissionDto result = new RepositoryPermissionDto();
result.setName(permission.getName()); result.setName(permission.getName());
result.setGroupPermission(permission.isGroupPermission()); result.setGroupPermission(permission.isGroupPermission());
result.setType(permission.getVerb()); // result.setType(permission.getVerbs()); TODO RP
String permissionName = Optional.of(permission.getName()) String permissionName = Optional.of(permission.getName())
.filter(p -> !permission.isGroupPermission()) .filter(p -> !permission.isGroupPermission())
.orElse(GROUP_PREFIX + permission.getName()); .orElse(GROUP_PREFIX + permission.getName());

View File

@@ -12,6 +12,7 @@ import sonia.scm.repository.Repository;
import java.net.URI; import java.net.URI;
import static java.util.Arrays.asList;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
@RunWith(MockitoJUnitRunner.Silent.class) @RunWith(MockitoJUnitRunner.Silent.class)
@@ -35,7 +36,7 @@ public class RepositoryPermissionToRepositoryPermissionDtoMapperTest {
@SubjectAware(username = "trillian", password = "secret") @SubjectAware(username = "trillian", password = "secret")
public void shouldMapGroupPermissionCorrectly() { public void shouldMapGroupPermissionCorrectly() {
Repository repository = getDummyRepository(); 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); RepositoryPermissionDto repositoryPermissionDto = mapper.map(permission, repository);
@@ -47,7 +48,7 @@ public class RepositoryPermissionToRepositoryPermissionDtoMapperTest {
@SubjectAware(username = "trillian", password = "secret") @SubjectAware(username = "trillian", password = "secret")
public void shouldMapNonGroupPermissionCorrectly() { public void shouldMapNonGroupPermissionCorrectly() {
Repository repository = getDummyRepository(); 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); RepositoryPermissionDto repositoryPermissionDto = mapper.map(permission, repository);

View File

@@ -58,6 +58,7 @@ import sonia.scm.repository.RepositoryTestData;
import sonia.scm.user.User; import sonia.scm.user.User;
import sonia.scm.user.UserTestData; import sonia.scm.user.UserTestData;
import static java.util.Arrays.asList;
import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.nullValue; import static org.hamcrest.Matchers.nullValue;
@@ -228,7 +229,7 @@ public class DefaultAuthorizationCollectorTest {
// heartOfGold.setPermissions(Lists.newArrayList(new RepositoryPermission("trillian"))); // heartOfGold.setPermissions(Lists.newArrayList(new RepositoryPermission("trillian")));
Repository puzzle42 = RepositoryTestData.create42Puzzle(); Repository puzzle42 = RepositoryTestData.create42Puzzle();
puzzle42.setId("two"); 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)); // puzzle42.setPermissions(Lists.newArrayList(permission));
when(repositoryDAO.getAll()).thenReturn(Lists.newArrayList(heartOfGold, puzzle42)); when(repositoryDAO.getAll()).thenReturn(Lists.newArrayList(heartOfGold, puzzle42));