@Override public boolean hasAcl() { return mutable.hasAcl(); } }
@Override public boolean hasAcl() { return mutable.hasAcl(); } }
private Stream<Authorization> getAllAuthorizationsFor(final Resource resource, final boolean inherited) { LOGGER.debug("Checking ACL for: {}", resource.getIdentifier()); if (resource.hasAcl()) { try (final WrappedGraph graph = wrap(resource.stream(Trellis.PreferAccessControl).collect(toGraph()))) { final List<Authorization> authorizations = getAuthorizationFromGraph(graph.getGraph()); // Check for any acl:default statements if checking for inheritance if (inherited && authorizations.stream().anyMatch(getInheritedAuth(resource.getIdentifier()))) { return authorizations.stream().filter(getInheritedAuth(resource.getIdentifier())); // If not inheriting, just return the relevant Authorizations in the ACL } else if (!inherited) { return authorizations.stream().filter(getAccessToAuth(resource.getIdentifier())); } } } // Nothing here, check the parent LOGGER.debug("No ACL for {}; looking up parent resource", resource.getIdentifier()); return getContainer(resource.getIdentifier()).map(resourceService::get) .map(CompletionStage::toCompletableFuture).map(CompletableFuture::join) .map(res -> getAllAuthorizationsFor(res, true)).orElseGet(Stream::empty); }
/** * Check a Trellis Resource. * @param res the Resource * @param identifier the identifier * @param ldpType the LDP type * @param time an instant before which the resource shouldn't exist * @param dataset a dataset to compare against * @return a stream of testable assertions */ default Stream<Executable> checkResource(final Resource res, final IRI identifier, final IRI ldpType, final Instant time, final Dataset dataset) { return Stream.of( () -> assertEquals(ldpType, res.getInteractionModel(), "Check the interaction model"), () -> assertEquals(identifier, res.getIdentifier(), "Check the identifier"), () -> assertFalse(res.getModified().isBefore(time), "Check the modification time (1)"), () -> assertFalse(res.getModified().isAfter(now()), "Check the modification time (2)"), () -> assertFalse(res.hasAcl(), "Check for an ACL"), () -> assertEquals(LDP.NonRDFSource.equals(ldpType), res.getBinaryMetadata().isPresent(), "Check Binary"), () -> assertEquals(asList(LDP.DirectContainer, LDP.IndirectContainer).contains(ldpType), res.getMembershipResource().isPresent(), "Check ldp:membershipResource"), () -> assertEquals(asList(LDP.DirectContainer, LDP.IndirectContainer).contains(ldpType), res.getMemberRelation().isPresent() || res.getMemberOfRelation().isPresent(), "Check ldp:hasMemberRelation or ldp:isMemberOfRelation"), () -> assertEquals(asList(LDP.DirectContainer, LDP.IndirectContainer).contains(ldpType), res.getInsertedContentRelation().isPresent(), "Check ldp:insertedContentRelation"), () -> res.stream(Trellis.PreferUserManaged).forEach(t -> assertTrue(dataset.contains(of(Trellis.PreferUserManaged), t.getSubject(), t.getPredicate(), t.getObject())))); }
@Test public void testInitializeExistingLdpResourceWithNoACL() throws Exception { final ResourceService mockService = mock(ResourceService.class); when(mockBundler.getResourceService()).thenReturn(mockService); when(mockService.get(eq(root))).thenAnswer(inv -> completedFuture(mockRootResource)); when(mockRootResource.hasAcl()).thenReturn(false); when(mockService.replace(any(Metadata.class), any(Dataset.class))).thenReturn(completedFuture(null)); final TrellisHttpResource matcher = new TrellisHttpResource(mockBundler); matcher.initialize(); verify(mockService, never().description("When re-initializing the root ACL, create should not be called")) .create(any(Metadata.class), any(Dataset.class)); verify(mockService, description("Use replace when re-initializing the root ACL")) .replace(any(Metadata.class), any(Dataset.class)); verify(mockService, description("Verify that the root resource is fetched only once")).get(root); }
private CompletionStage<Void> initialize(final IRI id, final Resource res, final TrellisDataset dataset) { if (MISSING_RESOURCE.equals(res) || DELETED_RESOURCE.equals(res)) { LOGGER.info("Initializing root container: {}", id); return trellis.getResourceService().create(Metadata.builder(id).interactionModel(LDP.BasicContainer) .build(), dataset.asDataset()); } else if (!res.hasAcl()) { LOGGER.info("Initializeing root ACL: {}", id); try (final Stream<Triple> triples = res.stream(Trellis.PreferUserManaged)) { triples.map(toQuad(Trellis.PreferUserManaged)).forEach(dataset::add); } return trellis.getResourceService().replace(Metadata.builder(res).build(), dataset.asDataset()); } return completedFuture(null); }
@Test public void testGetBinaryAcl() { when(mockBinaryResource.hasAcl()).thenReturn(true); final Response res = target(BINARY_PATH).queryParam("ext", "acl").request().get(); assertEquals(SC_OK, res.getStatus(), "Unexpected response code!"); assertFalse(getLinks(res).stream().anyMatch(l -> l.getRel().equals("describes")), "Unexpected rel=describes"); assertFalse(getLinks(res).stream().anyMatch(l -> l.getRel().equals("describedby")), "Unexpected rel=describedby"); assertFalse(getLinks(res).stream().anyMatch(l -> l.getRel().equals("canonical")), "Unexpected rel=canonical"); assertFalse(getLinks(res).stream().anyMatch(l -> l.getRel().equals("alternate")), "Unexpected rel=alternate"); }
@Test public void testGetAcl() { when(mockResource.getInteractionModel()).thenReturn(LDP.Container); when(mockResource.hasAcl()).thenReturn(true); when(mockTrellisRequest.getExt()).thenReturn("acl"); final GetHandler handler = new GetHandler(mockTrellisRequest, mockBundler, false, true, true, null, baseUrl); final Response res = handler.getRepresentation(handler.standardHeaders(handler.initialize(mockResource))) .toCompletableFuture().join().build(); assertEquals(OK, res.getStatusInfo(), "Incorrect response code!"); assertAll("Check LDP type link headers", checkLdpType(res, LDP.RDFSource)); assertAll("Check Allow headers", checkAllowHeader(res, asList(GET, HEAD, OPTIONS, PATCH))); }
@BeforeEach @SuppressWarnings("unchecked") public void setUp() { initMocks(this); testService = new WebACService(mockResourceService); when(mockCache.get(anyString(), any(Function.class))).thenAnswer(inv -> { final String key = inv.getArgument(0); final Function<String, String> mapper = inv.getArgument(1); return mapper.apply(key); }); setUpResourceService(); setUpChildResource(); setUpRootResource(); setUpMemberResource(); when(mockResource.hasAcl()).thenReturn(false); when(mockResource.getIdentifier()).thenReturn(resourceIRI); when(mockResource.getInteractionModel()).thenReturn(LDP.RDFSource); when(mockResource.getMembershipResource()).thenReturn(empty()); when(mockParentResource.hasAcl()).thenReturn(false); when(mockParentResource.getIdentifier()).thenReturn(parentIRI); when(mockParentResource.getInteractionModel()).thenReturn(LDP.Container); when(mockParentResource.getMembershipResource()).thenReturn(empty()); when(mockSession.getAgent()).thenReturn(agentIRI); when(mockSession.getDelegatedBy()).thenReturn(empty()); }
/** * Initialize the get handler. * @param resource the Trellis resource * @return the response builder */ public ResponseBuilder initialize(final Resource resource) { if (MISSING_RESOURCE.equals(resource)) { throw new NotFoundException(); } else if (DELETED_RESOURCE.equals(resource)) { throw new ClientErrorException(GONE); } LOGGER.debug("Acceptable media types: {}", getRequest().getAcceptableMediaTypes()); this.syntax = getSyntax(getServices().getIOService(), getRequest().getAcceptableMediaTypes(), resource.getBinaryMetadata() .filter(b -> !DESCRIPTION.equals(getRequest().getExt())) .map(b -> b.getMimeType().orElse(APPLICATION_OCTET_STREAM))).orElse(null); if (ACL.equals(getRequest().getExt()) && !resource.hasAcl()) { throw new NotFoundException(); } setResource(resource); return ok(); }
@Test public void testRetrievableResource() { final Instant time = now(); final Quad quad = createQuad(testResourceId2, testResourceId2, testResourceId1, badId); final Resource mockMutable = mock(Resource.class); when(mockMutable.getInteractionModel()).thenReturn(LDP.RDFSource); when(mockMutable.getModified()).thenReturn(time); when(mockMutable.hasAcl()).thenReturn(true); when(mockMutable.getContainer()).thenReturn(empty()); when(mockMutable.stream()).thenAnswer(inv -> Stream.of(quad)); final Resource res = new RetrievableResource(mockMutable, null); assertEquals(LDP.RDFSource, res.getInteractionModel(), "Resource retrieved with wrong interaction model!"); assertEquals(time, res.getModified(), "Resource has wrong modified date!"); assertTrue(res.hasAcl(), "Resource is missing ACL!"); assertFalse(res.getContainer().isPresent(), "Unexpected parent resource!"); assertTrue(res.stream().anyMatch(quad::equals), "Expected quad not present in resource stream!"); }
@BeforeEach public void setUp() { initMocks(this); doCallRealMethod().when(mockResource).getMembershipResource(); doCallRealMethod().when(mockResource).getMemberRelation(); doCallRealMethod().when(mockResource).getMemberOfRelation(); doCallRealMethod().when(mockResource).getInsertedContentRelation(); doCallRealMethod().when(mockResource).stream(any(IRI.class)); doCallRealMethod().when(mockResource).stream(anyCollection()); doCallRealMethod().when(mockResource).getBinaryMetadata(); doCallRealMethod().when(mockResource).hasAcl(); doCallRealMethod().when(mockResource).getExtraLinkRelations(); when(mockResource.stream()).thenAnswer((x) -> empty()); }
@Test public void testResource() { assertEquals(0L, mockResource.stream(prefer).count(), "Resource stream has extra triples!"); assertEquals(0L, mockResource.stream(singleton(prefer)).count(), "Resource stream has extra triples!"); assertFalse(mockResource.getMembershipResource().isPresent(), "Membership resource unexpectedly present!"); assertFalse(mockResource.getMemberRelation().isPresent(), "Member relation unexpectedly present!"); assertFalse(mockResource.getMemberOfRelation().isPresent(), "Member of relation unexpectedly present!"); assertFalse(mockResource.getInsertedContentRelation().isPresent(), "Inserted content relation is present!"); assertFalse(mockResource.getBinaryMetadata().isPresent(), "Binary is unexpectedly present!"); assertFalse(mockResource.getExtraLinkRelations().findFirst().isPresent(), "Extra links unexpectedly present!"); assertFalse(mockResource.hasAcl(), "ACL unexpectedly present!"); }
private static Stream<Executable> checkResource(final Resource res, final IRI identifier, final IRI ldpType, final boolean hasBinary, final boolean hasAcl, final boolean hasParent) { return Stream.of( () -> assertEquals(identifier, res.getIdentifier(), "Incorrect identifier!"), () -> assertEquals(ldpType, res.getInteractionModel(), "Incorrect interaction model!"), () -> assertEquals(parse(time), res.getModified(), "Incorrect modified date!"), () -> assertEquals(hasBinary, res.getBinaryMetadata().isPresent(), "Unexpected binary presence!"), () -> assertEquals(hasParent, res.getContainer().isPresent(), "Unexpected parent resource!"), () -> assertEquals(hasAcl, res.hasAcl(), "Unexpected ACL presence!")); }
private void setUpRootResource() { when(mockRootResource.hasAcl()).thenReturn(true); when(mockRootResource.getIdentifier()).thenReturn(rootIRI); when(mockRootResource.getInteractionModel()).thenReturn(LDP.BasicContainer); when(mockRootResource.getMembershipResource()).thenReturn(empty()); when(mockRootResource.stream(eq(Trellis.PreferAccessControl))).thenAnswer(inv -> Stream.of( rdf.createTriple(authIRI5, ACL.accessTo, rootIRI), rdf.createTriple(authIRI5, ACL.agent, addisonIRI), rdf.createTriple(authIRI5, ACL.mode, ACL.Read), rdf.createTriple(authIRI5, ACL.mode, ACL.Append), rdf.createTriple(authIRI6, type, ACL.Authorization), rdf.createTriple(authIRI6, ACL.agent, acoburnIRI), rdf.createTriple(authIRI6, ACL.accessTo, rootIRI), rdf.createTriple(authIRI6, ACL.mode, ACL.Append), rdf.createTriple(authIRI8, type, ACL.Authorization), rdf.createTriple(authIRI8, ACL.agent, agentIRI), rdf.createTriple(authIRI8, ACL.accessTo, rootIRI), rdf.createTriple(authIRI8, ACL.mode, ACL.Read), rdf.createTriple(authIRI8, ACL.mode, ACL.Write))); }
private void setUpMemberResource() { when(mockMemberResource.hasAcl()).thenReturn(true); when(mockMemberResource.getIdentifier()).thenReturn(memberIRI); when(mockMemberResource.getInteractionModel()).thenReturn(LDP.RDFSource); when(mockMemberResource.getMembershipResource()).thenReturn(empty()); when(mockMemberResource.stream(eq(Trellis.PreferAccessControl))).thenAnswer(inv -> Stream.of( rdf.createTriple(authIRI5, ACL.accessTo, memberIRI), rdf.createTriple(authIRI5, ACL.agent, addisonIRI), rdf.createTriple(authIRI5, ACL.mode, ACL.Read), rdf.createTriple(authIRI5, ACL.mode, ACL.Append), rdf.createTriple(authIRI6, type, ACL.Authorization), rdf.createTriple(authIRI6, ACL.agent, acoburnIRI), rdf.createTriple(authIRI6, ACL.accessTo, memberIRI), rdf.createTriple(authIRI6, ACL.mode, ACL.Write), rdf.createTriple(authIRI8, type, ACL.Authorization), rdf.createTriple(authIRI8, ACL.agent, agentIRI), rdf.createTriple(authIRI8, ACL.accessTo, memberIRI), rdf.createTriple(authIRI8, ACL.mode, ACL.Read), rdf.createTriple(authIRI8, ACL.mode, ACL.Write))); }
@Test public void testNotInherited() { when(mockParentResource.hasAcl()).thenReturn(true); when(mockParentResource.stream(eq(Trellis.PreferAccessControl))).thenAnswer(inv -> Stream.of( rdf.createTriple(authIRI5, type, ACL.Authorization), rdf.createTriple(authIRI5, ACL.accessTo, parentIRI), rdf.createTriple(authIRI5, ACL.agent, agentIRI), rdf.createTriple(authIRI5, ACL.mode, ACL.Read))); when(mockRootResource.stream(eq(Trellis.PreferAccessControl))).thenAnswer(inv -> Stream.of( rdf.createTriple(authIRI8, type, ACL.Authorization), rdf.createTriple(authIRI8, ACL.mode, ACL.Write), rdf.createTriple(authIRI8, ACL.mode, ACL.Read), rdf.createTriple(authIRI8, ACL.agent, agentIRI), rdf.createTriple(authIRI8, ACL.accessTo, rootIRI))); when(mockSession.getAgent()).thenReturn(agentIRI); assertAll("Test non-inheritance writability", checkCanWrite(resourceIRI), checkCanWrite(childIRI), checkCannotWrite(parentIRI), checkCanWrite(rootIRI)); }
@Test public void testGetAclJsonCompact() throws IOException { when(mockResource.hasAcl()).thenReturn(true); final Response res = target(RESOURCE_PATH).queryParam("ext", "acl").request() .accept("application/ld+json; profile=\"http://www.w3.org/ns/json-ld#compacted\"").get(); assertEquals(SC_OK, res.getStatus(), "Unexpected response code!"); assertEquals(APPLICATION_SPARQL_UPDATE, res.getHeaderString(ACCEPT_PATCH), "Incorrect Accept-Patch header"); assertEquals(from(time), res.getLastModified(), "Incorrect last-modified header!"); assertFalse(hasTimeGateLink(res, RESOURCE_PATH), "Unexpected rel=timegate link"); assertFalse(hasOriginalLink(res, RESOURCE_PATH), "Unexpected rel=original link"); assertTrue(res.hasEntity(), "Missing entity!"); final String entity = IOUtils.toString((InputStream) res.getEntity(), UTF_8); final Map<String, Object> obj = MAPPER.readValue(entity, new TypeReference<Map<String, Object>>(){}); assertEquals(ACL.Control.getIRIString(), (String) obj.get("mode"), "Incorrect ACL mode property!"); assertAll("Check Simple JSON-LD", checkSimpleJsonLdResponse(res, LDP.RDFSource)); assertAll("Check allowed methods", checkAllowedMethods(res, asList(PATCH, GET, HEAD, OPTIONS))); assertAll("Check Vary headers", checkVary(res, asList(ACCEPT_DATETIME))); assertAll("Check null headers", checkNullHeaders(res, asList(ACCEPT_POST, ACCEPT_RANGES))); assertAll("Check JSON-LD structure", checkJsonStructure(obj, asList("@context", "mode"), asList("title"))); }
@Test public void testBinary() { final IRI identifier = rdf.createIRI(TRELLIS_DATA_PREFIX + "binary"); final File file = new File(getClass().getResource("/binary.nq").getFile()); assertTrue(file.exists(), "Resource file doesn't exist!"); final Resource res = new FileResource(identifier, file); assertEquals(identifier, res.getIdentifier(), "Incorrect identifier!"); assertEquals(parse("2017-02-16T11:17:00Z"), res.getModified(), "Incorrect modification date!"); assertEquals(LDP.NonRDFSource, res.getInteractionModel(), "Incorrect interaction model!"); assertFalse(res.getMembershipResource().isPresent(), "Unexpected ldp:membershipResource value!"); assertFalse(res.getMemberRelation().isPresent(), "Unexpected ldp:memberRelation value!"); assertFalse(res.getMemberOfRelation().isPresent(), "Unexpected ldp:isMemberOfRelation value!"); assertFalse(res.getInsertedContentRelation().isPresent(), "Unexpected ldp:insertedContentRelation value!"); assertTrue(res.getBinaryMetadata().isPresent(), "Missing binary metadata!"); res.getBinaryMetadata().ifPresent(binary -> { assertEquals(of("text/plain"), binary.getMimeType(), "Incorrect binary mime type!"); assertEquals(rdf.createIRI("file:///path/to/binary"), binary.getIdentifier(), "Incorrect binary id!"); }); assertFalse(res.getContainer().isPresent(), "Unexpected parent resource!"); assertFalse(res.hasAcl(), "Unexpected ACL present!"); assertEquals(0L, res.stream(LDP.PreferContainment).count(), "Incorrect containment triple count!"); assertEquals(2L, res.stream(Trellis.PreferUserManaged).count(), "Incorrect user triple count!"); assertEquals(6L, res.stream(Trellis.PreferServerManaged).count(), "Incorrect server managed count!"); assertEquals(8L, res.stream().count(), "Incorrect total triple count!"); }
@Test public void testResource() { final IRI identifier = rdf.createIRI(TRELLIS_DATA_PREFIX + "resource"); final File file = new File(getClass().getResource("/resource.nq").getFile()); assertTrue(file.exists(), "Resource file doesn't exist!"); final Resource res = new FileResource(identifier, file); assertEquals(identifier, res.getIdentifier(), "Incorrect identifier!"); assertEquals(parse("2017-02-16T11:15:01Z"), res.getModified(), "Incorrect modification date!"); assertEquals(LDP.BasicContainer, res.getInteractionModel(), "Incorrect interaction model!"); assertFalse(res.getMembershipResource().isPresent(), "Unexpected ldp:membershipResource value!"); assertFalse(res.getMemberRelation().isPresent(), "Unexpected ldp:memberRelation value!"); assertFalse(res.getMemberOfRelation().isPresent(), "Unexpected ldp:isMemberOfRelation value!"); assertFalse(res.getInsertedContentRelation().isPresent(), "Unexpected ldp:insertedContentRelation value!"); assertFalse(res.getBinaryMetadata().isPresent(), "Unexpected binary present!"); assertFalse(res.hasAcl(), "Unexpected ACL present!"); assertFalse(res.getContainer().isPresent(), "Unexpected parent resource!"); assertEquals(3L, res.stream(LDP.PreferContainment).count(), "Incorrect containment count!"); assertEquals(3L, res.stream(Trellis.PreferUserManaged).count(), "Incorrect user triple count!"); assertEquals(2L, res.stream(Trellis.PreferServerManaged).count(), "Incorrect server managed count!"); assertEquals(8L, res.stream().count(), "Incorrect total triple count!"); }