Skip to content

Commit c18bf61

Browse files
committed
Additional tests
1 parent 3348ae8 commit c18bf61

File tree

5 files changed

+86
-39
lines changed

5 files changed

+86
-39
lines changed

acp/src/main/java/com/inrupt/client/acp/AccessControlResource.java

Lines changed: 30 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@
2929
import com.inrupt.rdf.wrapping.commons.WrapperIRI;
3030

3131
import java.net.URI;
32+
import java.util.Collections;
33+
import java.util.List;
34+
import java.util.Map;
3235
import java.util.Set;
3336
import java.util.UUID;
3437
import java.util.function.Consumer;
@@ -54,6 +57,17 @@ public class AccessControlResource extends RDFSource {
5457

5558
public static final URI SOLID_ACCESS_GRANT = URI.create("http://www.w3.org/ns/solid/vc#SolidAccessGrant");
5659

60+
private static final Map<URI, IRI> EXPANSION_MAPPINGS = Map.of(
61+
ACP.accessControl, asIRI(ACP.AccessControl),
62+
ACP.memberAccessControl, asIRI(ACP.AccessControl),
63+
ACP.apply, asIRI(ACP.Policy),
64+
ACP.allOf, asIRI(ACP.Matcher),
65+
ACP.anyOf, asIRI(ACP.Matcher),
66+
ACP.noneOf, asIRI(ACP.Matcher));
67+
68+
private static final List<URI> EXPANSION_PROPERTIES = List.of(ACP.accessControl, ACP.memberAccessControl,
69+
ACP.apply, ACP.allOf, ACP.anyOf, ACP.noneOf);
70+
5771
/**
5872
* Definitions for different matcher types, for use with {@link #find}.
5973
*/
@@ -127,23 +141,13 @@ public Set<AccessControl> memberAccessControl() {
127141
public AccessControlResource expand(final SolidSyncClient client) {
128142
// Copy the data from the existing ACR into a new dataset
129143
final var dataset = rdf.createDataset();
130-
final var matcherType = asIRI(ACP.Matcher);
131-
final var accessControlType = asIRI(ACP.AccessControl);
132144
stream().forEach(dataset::add);
133145

134146
try (final var cache = rdf.createDataset()) {
135-
expandType(dataset, cache, asIRI(ACP.accessControl), accessControlType,
136-
uri -> populateCache(client, uri, cache));
137-
expandType(dataset, cache, asIRI(ACP.memberAccessControl), accessControlType,
138-
uri -> populateCache(client, uri, cache));
139-
expandType(dataset, cache, asIRI(ACP.apply), asIRI(ACP.Policy),
140-
uri -> populateCache(client, uri, cache));
141-
expandType(dataset, cache, asIRI(ACP.allOf), matcherType,
142-
uri -> populateCache(client, uri, cache));
143-
expandType(dataset, cache, asIRI(ACP.anyOf), matcherType,
144-
uri -> populateCache(client, uri, cache));
145-
expandType(dataset, cache, asIRI(ACP.noneOf), matcherType,
147+
for (final var property : EXPANSION_PROPERTIES) {
148+
expandType(dataset, cache, asIRI(property), EXPANSION_MAPPINGS.get(property),
146149
uri -> populateCache(client, uri, cache));
150+
}
147151
} catch (final Exception ex) {
148152
LOGGER.atDebug().setMessage("Unable to close dataset: {}").addArgument(ex::getMessage).log();
149153
}
@@ -162,21 +166,11 @@ public AccessControlResource expand(final SolidClient client) {
162166
final var dataset = rdf.createDataset();
163167
stream().forEach(dataset::add);
164168

165-
final var matcherType = asIRI(ACP.Matcher);
166-
final var accessControlType = asIRI(ACP.AccessControl);
167169
try (final var cache = rdf.createDataset()) {
168-
expandType(dataset, cache, asIRI(ACP.accessControl), accessControlType,
169-
uri -> populateCacheAsync(client, uri, cache));
170-
expandType(dataset, cache, asIRI(ACP.memberAccessControl), accessControlType,
171-
uri -> populateCacheAsync(client, uri, cache));
172-
expandType(dataset, cache, asIRI(ACP.apply), asIRI(ACP.Policy),
173-
uri -> populateCacheAsync(client, uri, cache));
174-
expandType(dataset, cache, asIRI(ACP.allOf), matcherType,
175-
uri -> populateCacheAsync(client, uri, cache));
176-
expandType(dataset, cache, asIRI(ACP.anyOf), matcherType,
177-
uri -> populateCacheAsync(client, uri, cache));
178-
expandType(dataset, cache, asIRI(ACP.noneOf), matcherType,
179-
uri -> populateCacheAsync(client, uri, cache));
170+
for (final var property : EXPANSION_PROPERTIES) {
171+
expandType(dataset, cache, asIRI(property), EXPANSION_MAPPINGS.get(property),
172+
uri -> populateCacheAsync(client, uri, cache));
173+
}
180174
} catch (final Exception ex) {
181175
LOGGER.atDebug().setMessage("Unable to close dataset: {}").addArgument(ex::getMessage).log();
182176
}
@@ -208,37 +202,41 @@ public void compact() {
208202
/**
209203
* Merge two or more policies into a single policies with combined matchers.
210204
*
205+
* @param allow the modes to allow
211206
* @param policies the policies to merge
212207
* @return the merged policy
213208
*/
214-
public Policy merge(final Policy... policies) {
209+
public Policy merge(final Set<URI> allow, final Policy... policies) {
215210
final var baseUri = getIdentifier().getScheme() + ":" + getIdentifier().getSchemeSpecificPart();
216211
final var policy = new Policy(asIRI(baseUri + "#" + UUID.randomUUID()), getGraph());
217212
for (final var p : policies) {
218213
policy.allOf().addAll(p.allOf());
219214
policy.anyOf().addAll(p.anyOf());
220215
policy.noneOf().addAll(p.noneOf());
221216
}
217+
policy.allow().addAll(allow);
222218
return policy;
223219
}
224220

225221
/**
226222
* Find a policy, given a type, value and set of modes.
227223
*
228224
* @param type the matcher type
229-
* @param value the matcher value
230-
* @param modes the expected modes of the enclosing policy
225+
* @param value the matcher value, may be {@null}
226+
* @param modes the expected modes of the enclosing policy, may be {@null}
231227
* @return the matched policies
232228
*/
233229
public Set<Policy> find(final MatcherType type, final URI value, final Set<URI> modes) {
234-
return stream(null, null, type.asIRI(), asIRI(value))
230+
final IRI matcherValue = value != null ? asIRI(value) : null;
231+
final Set<URI> matcherModes = modes != null ? modes : Collections.emptySet();
232+
return stream(null, null, type.asIRI(), matcherValue)
235233
.map(Quad::getSubject)
236234
.flatMap(matcher -> stream(null, null, null, matcher))
237235
.map(Quad::getSubject)
238236
.filter(policy -> contains(null, policy, asIRI(RDF.type), asIRI(ACP.Policy)))
239237
.filter(policy -> stream(null, policy, asIRI(ACP.allow), null)
240238
.map(Quad::getObject).filter(IRI.class::isInstance).map(IRI.class::cast)
241-
.map(IRI::getIRIString).map(URI::create).toList().containsAll(modes))
239+
.map(IRI::getIRIString).map(URI::create).toList().containsAll(matcherModes))
242240
.map(policy -> new Policy(policy, getGraph()))
243241
.collect(Collectors.toSet());
244242
}

acp/src/main/java/com/inrupt/client/acp/Policy.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,10 @@ static IRI asResource(final Policy policy, final Graph graph) {
104104
graph.add(policy, asIRI(ACP.anyOf), matcher);
105105
Matcher.asResource(matcher, graph);
106106
});
107+
policy.noneOf().forEach(matcher -> {
108+
graph.add(policy, asIRI(ACP.noneOf), matcher);
109+
Matcher.asResource(matcher, graph);
110+
});
107111
policy.allow().forEach(allow ->
108112
graph.add(policy, asIRI(ACP.allow), asIRI(allow)));
109113
return policy;

acp/src/test/java/com/inrupt/client/acp/AccessControlResourceTest.java

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -186,16 +186,22 @@ void testAcrFindPolicies() {
186186
final var uri = mockHttpServer.acr2();
187187
try (final AccessControlResource acr = client.read(uri, AccessControlResource.class)) {
188188
assertEquals(1, acr.find(AccessControlResource.MatcherType.VC,
189-
AccessControlResource.SOLID_ACCESS_GRANT, Set.of(ACL.Read)).size());
189+
AccessControlResource.SOLID_ACCESS_GRANT, Set.of(ACL.Read)).size());
190190

191191
assertEquals(0, acr.find(AccessControlResource.MatcherType.VC,
192-
AccessControlResource.SOLID_ACCESS_GRANT, Set.of(ACL.Read, ACL.Write)).size());
192+
AccessControlResource.SOLID_ACCESS_GRANT, Set.of(ACL.Read, ACL.Write)).size());
193193

194194
assertEquals(0, acr.find(AccessControlResource.MatcherType.AGENT,
195-
URI.create("https://bot.example/id"), Set.of(ACL.Read, ACL.Write)).size());
195+
URI.create("https://bot.example/id"), Set.of(ACL.Read, ACL.Write)).size());
196196

197197
assertEquals(1, acr.find(AccessControlResource.MatcherType.AGENT,
198-
URI.create("https://bot.example/id"), Set.of(ACL.Read)).size());
198+
URI.create("https://bot.example/id"), Set.of(ACL.Read)).size());
199+
200+
assertEquals(2, acr.find(AccessControlResource.MatcherType.AGENT,
201+
null, Set.of(ACL.Read)).size());
202+
203+
assertEquals(1, acr.find(AccessControlResource.MatcherType.AGENT,
204+
URI.create("https://bot.example/id"), null).size());
199205
}
200206
}
201207

@@ -335,4 +341,44 @@ void expandAcr4Sync() {
335341
assertEquals(20, acr.size());
336342
}
337343
}
344+
345+
@Test
346+
void expandAcr4Async() {
347+
final var uri = mockHttpServer.acr4();
348+
final var asyncClient = SolidClient.getClient();
349+
asyncClient.read(uri, AccessControlResource.class).thenAccept(res -> {
350+
try (final var acr = res) {
351+
assertEquals(2, acr.accessControl().size());
352+
assertEquals(3, acr.memberAccessControl().size());
353+
354+
// Check dataset size
355+
assertEquals(20, acr.size());
356+
357+
final var expanded = acr.expand(asyncClient);
358+
assertEquals(22, expanded.size());
359+
assertEquals(20, acr.size());
360+
}
361+
}).toCompletableFuture().join();
362+
}
363+
364+
@Test
365+
void testMerge() {
366+
final var identifier = "https://data.example/resource";
367+
final var agent = URI.create("https://id.example/agent");
368+
final var app = URI.create("https://app.example/id");
369+
370+
final var acr = new AccessControlResource(URI.create(identifier), rdf.createDataset());
371+
final var policy = acr.merge(Set.of(ACL.Read, ACL.Write), acr.agentPolicy(agent), acr.clientPolicy(app));
372+
373+
assertEquals(2, policy.allow().size());
374+
assertTrue(policy.allow().contains(ACL.Read));
375+
assertTrue(policy.allow().contains(ACL.Write));
376+
377+
assertEquals(2, policy.allOf().size());
378+
assertEquals(0, policy.anyOf().size());
379+
assertEquals(0, policy.noneOf().size());
380+
381+
assertTrue(policy.allOf().stream().anyMatch(matcher -> matcher.client().contains(app)));
382+
assertTrue(policy.allOf().stream().anyMatch(matcher -> matcher.agent().contains(agent)));
383+
}
338384
}

acp/src/test/resources/__files/acr-4.ttl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,15 @@
1616
acp:apply <#indexer-policy> .
1717
<#indexer-policy>
1818
a acp:Policy ;
19-
acp:allOf </also-not-an-acr> ;
19+
acp:noneOf </also-not-an-acr> ;
2020
acp:allow acl:Read .
2121

2222
<#vc-access-control>
2323
a acp:AccessControl ;
2424
acp:apply <#vc-policy> .
2525
<#vc-policy>
2626
a acp:Policy ;
27-
acp:allOf <#vc-matcher> ;
27+
acp:anyOf <#vc-matcher> ;
2828
acp:allow acl:Read .
2929
<#vc-matcher>
3030
a acp:Matcher ;

pom.xml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,6 @@
206206
<link>https://jena.apache.org/documentation/javadoc/arq/</link>
207207
<link>https://www.antlr.org/api/Java/</link>
208208
<link>https://rdf4j.org/javadoc/5.1.0/</link>
209-
<link>http://www.javadoc.io/doc/com.fasterxml.jackson.core/jackson-databind/latest/</link>
210209
</links>
211210
<header>
212211
<![CDATA[

0 commit comments

Comments
 (0)