From c3d7e07522b788fe9302ecfe4dfbffa01758d68b Mon Sep 17 00:00:00 2001 From: Aaron Coburn Date: Mon, 22 May 2023 12:16:48 -0400 Subject: [PATCH] JCL-360: Add acl property to Metadata class in solid module --- .../com/inrupt/client/solid/Metadata.java | 38 ++++++++++++++++++- .../client/solid/SolidResourceHandlers.java | 2 + .../client/solid/SolidMockHttpService.java | 7 ++++ .../client/solid/SolidRDFSourceTest.java | 6 +++ 4 files changed, 52 insertions(+), 1 deletion(-) diff --git a/solid/src/main/java/com/inrupt/client/solid/Metadata.java b/solid/src/main/java/com/inrupt/client/solid/Metadata.java index 385be973852..c24c82f134c 100644 --- a/solid/src/main/java/com/inrupt/client/solid/Metadata.java +++ b/solid/src/main/java/com/inrupt/client/solid/Metadata.java @@ -32,6 +32,7 @@ */ public class Metadata { + private final URI acl; private final URI storage; private final Set type = new HashSet<>(); private final Map> wacAllow = new HashMap<>(); @@ -71,6 +72,15 @@ public Map> getWacAllow() { return wacAllow; } + /** + * The access control resource location. + * + * @return the access control resource location, if present + */ + public Optional getAcl() { + return Optional.ofNullable(acl); + } + /** * The supported HTTP methods for the associated resource. * @@ -133,9 +143,23 @@ public String getContentType() { * * @param storage the Solid storage in which this resource is managed * @param contentType the content type of the respective Solid resource + * @deprecated as of Beta3, please use the 3-parameter constructor */ + @Deprecated protected Metadata(final URI storage, final String contentType) { + this(storage, null, contentType); + } + + /** + * Create a new Metadata object. + * + * @param storage the Solid storage in which this resource is managed + * @param acl the ACL location for this resource + * @param contentType the content type of the respective Solid resource + */ + protected Metadata(final URI storage, final URI acl, final String contentType) { this.storage = storage; + this.acl = acl; this.contentType = contentType; } @@ -153,6 +177,7 @@ public static Builder newBuilder() { */ public static final class Builder { + private URI builderAcl; private URI builderStorage; private Set builderType = new HashSet<>(); private Map> builderWacAllow = new HashMap<>(); @@ -195,6 +220,17 @@ public Builder wacAllow(final Map.Entry> accessParam) { return this; } + /** + * Add an acl property. + * + * @param acl the acl location + * @return this builder + */ + public Builder acl(final URI acl) { + builderAcl = acl; + return this; + } + /** * Add an allowedMethod property. * @@ -256,7 +292,7 @@ public Builder contentType(final String type) { * @return the resource Metadata object */ public Metadata build() { - final Metadata metadata = new Metadata(builderStorage, builderContentType); + final Metadata metadata = new Metadata(builderStorage, builderAcl, builderContentType); metadata.wacAllow.putAll(builderWacAllow); metadata.type.addAll(builderType); metadata.allowedMethods.addAll(builderAllowedMethods); diff --git a/solid/src/main/java/com/inrupt/client/solid/SolidResourceHandlers.java b/solid/src/main/java/com/inrupt/client/solid/SolidResourceHandlers.java index cc5f1f83eb1..5c93e70eaaa 100644 --- a/solid/src/main/java/com/inrupt/client/solid/SolidResourceHandlers.java +++ b/solid/src/main/java/com/inrupt/client/solid/SolidResourceHandlers.java @@ -101,6 +101,8 @@ static Metadata buildMetadata(final URI uri, final Headers headers) { metadata.storage(uri); } metadata.type(link.getUri()); + } else if (link.getParameter("rel").contains("acl")) { + metadata.acl(link.getUri()); } else if (link.getParameter("rel").contains(PIM.storage.toString())) { metadata.storage(link.getUri()); } diff --git a/solid/src/test/java/com/inrupt/client/solid/SolidMockHttpService.java b/solid/src/test/java/com/inrupt/client/solid/SolidMockHttpService.java index d1f015e5443..2e128dcefc7 100644 --- a/solid/src/test/java/com/inrupt/client/solid/SolidMockHttpService.java +++ b/solid/src/test/java/com/inrupt/client/solid/SolidMockHttpService.java @@ -54,6 +54,7 @@ private void setupMocks() { .withStatus(200) .withHeader("Content-Type", "text/turtle") .withHeader("Link", Link.of(LDP.BasicContainer, "type").toString()) + .withHeader("Link", Link.of(URI.create("http://acl.example/"), "acl").toString()) .withHeader("Link", Link.of( URI.create(PIM.getNamespace() + "Storage"), "type").toString()) @@ -66,6 +67,7 @@ private void setupMocks() { .withStatus(200) .withHeader("Content-Type", "text/turtle") .withHeader("Link", Link.of(LDP.BasicContainer, "type").toString()) + .withHeader("Link", Link.of(URI.create("http://acl.example/solid/"), "acl").toString()) .withHeader("Link", Link.of(URI.create("http://storage.example/"), PIM.storage).toString()) .withHeader("Link", Link.of(URI.create("https://history.test/"), "timegate").toString()) @@ -84,6 +86,7 @@ private void setupMocks() { .withStatus(200) .withHeader("Content-Type", "text/turtle") .withHeader("Link", Link.of(LDP.RDFSource, "type").toString()) + .withHeader("Link", Link.of(URI.create("http://acl.example/recipe"), "acl").toString()) .withHeader("Link", Link.of(URI.create("http://storage.example/"), PIM.storage).toString()) .withHeader("Link", Link.of(URI.create("https://history.test/"), "timegate").toString()) @@ -103,6 +106,7 @@ private void setupMocks() { .withHeader("Content-Type", "text/turtle") .withHeader("Link", Link.of(LDP.RDFSource, "type").toString()) .withHeader("Link", Link.of(URI.create("http://storage.example/"), PIM.storage).toString()) + .withHeader("Link", Link.of(URI.create("http://acl.example/custom-agent"), "acl").toString()) .withHeader("Link", Link.of(URI.create("https://history.test/"), "timegate").toString()) .withHeader("WAC-Allow", "user=\"read write\",public=\"read\"") .withHeader("Allow", "POST, PUT, PATCH") @@ -136,6 +140,7 @@ private void setupMocks() { .withHeader("Link", Link.of(URI.create("http://storage.example/"), PIM.storage).toString()) .withHeader("Link", Link.of(URI.create("https://history.test/"), "timegate").toString()) + .withHeader("Link", Link.of(URI.create("http://acl.example/playlist"), "acl").toString()) .withHeader("WAC-Allow", "user=\"read write\",public=\"read\"") .withHeader("Allow", "POST, PUT, PATCH") .withHeader("Accept-Post", "application/ld+json, text/turtle") @@ -171,6 +176,7 @@ private void setupMocks() { .willReturn(aResponse() .withStatus(200) .withHeader("Content-Type", "text/plain") + .withHeader("Link", Link.of(URI.create("http://acl.example/binary"), "acl").toString()) .withBody("This is a plain text document."))); wireMockServer.stubFor(put(urlEqualTo("/binary")) @@ -191,6 +197,7 @@ private void setupMocks() { .willReturn(aResponse() .withStatus(200) .withHeader("Content-Type", "text/turtle") + .withHeader("Link", Link.of(URI.create("http://acl.example/nonRDF"), "acl").toString()) .withBody("This isn't valid turtle."))); wireMockServer.stubFor(get(urlEqualTo("/missing")) diff --git a/solid/src/test/java/com/inrupt/client/solid/SolidRDFSourceTest.java b/solid/src/test/java/com/inrupt/client/solid/SolidRDFSourceTest.java index 13ddf2b3c59..b40b875e5ee 100644 --- a/solid/src/test/java/com/inrupt/client/solid/SolidRDFSourceTest.java +++ b/solid/src/test/java/com/inrupt/client/solid/SolidRDFSourceTest.java @@ -76,6 +76,8 @@ void testGetOfSolidRDFSource() throws IOException, InterruptedException { try (final SolidRDFSource resource = response.body()) { assertEquals(uri, resource.getIdentifier()); assertTrue(resource.getMetadata().getType().contains(LDP.BasicContainer)); + assertEquals(Optional.of(URI.create("http://acl.example/solid/")), + resource.getMetadata().getAcl()); assertEquals(Optional.of(URI.create("http://storage.example/")), resource.getMetadata().getStorage()); assertTrue(resource.getMetadata().getWacAllow().get("user") @@ -114,6 +116,8 @@ void testCheckRootOfSolidRDFSource() throws IOException, InterruptedException { try (final SolidRDFSource resource = response.body()) { assertEquals(uri, resource.getIdentifier()); assertTrue(resource.getMetadata().getType().contains(LDP.BasicContainer)); + assertEquals(Optional.of(URI.create("http://acl.example/")), + resource.getMetadata().getAcl()); assertEquals(Optional.of(uri), resource.getMetadata().getStorage()); } } @@ -157,6 +161,7 @@ void testEmptyResourceBuilder() { final URI id = URI.create("https://resource.example/"); try (final SolidRDFSource res = new SolidRDFSource(id, null, null)) { assertFalse(res.getMetadata().getStorage().isPresent()); + assertFalse(res.getMetadata().getAcl().isPresent()); assertTrue(res.getMetadata().getAllowedPatchSyntaxes().isEmpty()); assertEquals(0, res.size()); assertEquals(id, res.getIdentifier()); @@ -168,6 +173,7 @@ void testEmptyContainerBuilder() { final URI id = URI.create("https://resource.example/"); try (final SolidContainer res = new SolidContainer(id, null, null)) { assertFalse(res.getMetadata().getStorage().isPresent()); + assertFalse(res.getMetadata().getAcl().isPresent()); assertTrue(res.getMetadata().getAllowedPatchSyntaxes().isEmpty()); assertEquals(0, res.size()); assertEquals(id, res.getIdentifier());