Skip to content

Commit 5a3d616

Browse files
committed
Additional tests
1 parent a1e6150 commit 5a3d616

4 files changed

Lines changed: 206 additions & 2 deletions

File tree

access-grant/src/main/java/com/inrupt/client/accessgrant/AccessGrantClient.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,7 @@ public CompletionStage<AccessGrant> grantAccess(final AccessRequest request,
333333
LOGGER.atWarn()
334334
.setMessage("No data URLs supplied: {} resource URLs and {} mapped templates")
335335
.addArgument(() -> request.getResources().size())
336-
.addArgument(() -> templated.size())
336+
.addArgument(templated::size)
337337
.log();
338338
}
339339
return v1Metadata().thenCompose(metadata -> {

access-grant/src/test/java/com/inrupt/client/accessgrant/AccessGrantClientTest.java

Lines changed: 148 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
import java.util.UUID;
4343
import java.util.concurrent.CompletableFuture;
4444
import java.util.concurrent.CompletionException;
45+
import java.util.stream.Collectors;
4546

4647
import org.apache.commons.io.IOUtils;
4748
import org.jose4j.jwk.PublicJsonWebKey;
@@ -174,7 +175,6 @@ void testFetch5() {
174175
assertInstanceOf(AccessGrantException.class, err1.getCause());
175176
}
176177

177-
178178
@Test
179179
void testFetch6() {
180180
final Map<String, Object> claims = new HashMap<>();
@@ -215,6 +215,27 @@ void testNotAccessGrant() {
215215
client.fetch(uri, AccessGrant.class).toCompletableFuture()::join);
216216
}
217217

218+
@Test
219+
void testFetchTemplate() {
220+
final Map<String, Object> claims = new HashMap<>();
221+
claims.put("webid", WEBID);
222+
claims.put("sub", SUB);
223+
claims.put("iss", ISS);
224+
claims.put("azp", AZP);
225+
final String token = generateIdToken(claims);
226+
final URI uri = URIBuilder.newBuilder(baseUri).path("access-request-6").build();
227+
final AccessGrantClient client = agClient.session(OpenIdSession.ofIdToken(token));
228+
final AccessRequest request = client.fetch(uri, AccessRequest.class).toCompletableFuture().join();
229+
230+
assertEquals(uri, request.getIdentifier());
231+
assertEquals(baseUri, request.getIssuer());
232+
233+
// Revoke
234+
final CompletableFuture<Void> future = client.revoke(request).toCompletableFuture();
235+
final CompletionException err1 = assertThrows(CompletionException.class, future::join);
236+
assertInstanceOf(AccessGrantException.class, err1.getCause());
237+
}
238+
218239
@Test
219240
void testFetchInvalid() {
220241
final URI uri = URIBuilder.newBuilder(baseUri).path(".well-known/vc-configuration").build();
@@ -286,6 +307,33 @@ void testIssueRequestBuilder() {
286307
assertEquals(resources, request.getResources());
287308
}
288309

310+
@Test
311+
void testGrantFromTemplate() {
312+
final Map<String, Object> claims = new HashMap<>();
313+
claims.put("webid", WEBID);
314+
claims.put("sub", SUB);
315+
claims.put("iss", ISS);
316+
claims.put("azp", AZP);
317+
final String token = generateIdToken(claims);
318+
final URI uri = URIBuilder.newBuilder(baseUri).path("access-request-6").build();
319+
final AccessGrantClient client = agClient.session(OpenIdSession.ofIdToken(token));
320+
final AccessRequest request = client.fetch(uri, AccessRequest.class).toCompletableFuture().join();
321+
322+
final AccessGrant grant = client.grantAccess(request).toCompletableFuture().join();
323+
324+
final Instant expiration = Instant.parse("2022-08-27T12:00:00Z");
325+
final Set<String> modes = Set.of("Read", "Append");
326+
final Set<URI> purposes = Collections.singleton(URI.create("https://purpose.test/Purpose1"));
327+
328+
assertTrue(grant.getTypes().contains("SolidAccessGrant"));
329+
assertEquals(Optional.of(URI.create("https://id.test/agent")), grant.getRecipient());
330+
assertEquals(modes, grant.getModes());
331+
assertEquals(expiration, grant.getExpiration());
332+
assertEquals(baseUri, grant.getIssuer());
333+
assertEquals(purposes, grant.getPurposes());
334+
assertNotNull(grant.getAccessRequest());
335+
}
336+
289337
@Test
290338
void testRequestAccessNoAuth() {
291339
final URI recipient = URI.create("https://id.test/agent");
@@ -335,6 +383,53 @@ void testGrantAccess(final boolean verifyRequest) {
335383
assertNotNull(grant.getAccessRequest());
336384
}
337385

386+
@ParameterizedTest
387+
@ValueSource(booleans = {true, false})
388+
void testGrantTemplatedAccess(final boolean verifyRequest) {
389+
final Map<String, Object> claims = new HashMap<>();
390+
claims.put("webid", WEBID);
391+
claims.put("sub", SUB);
392+
claims.put("iss", ISS);
393+
claims.put("azp", AZP);
394+
final String token = generateIdToken(claims);
395+
final AccessGrantClient client = agClient.session(OpenIdSession.ofIdToken(token));
396+
397+
final URI recipient = URI.create("https://id.test/agent");
398+
final Instant expiration = Instant.parse("2022-08-27T12:00:00Z");
399+
final Set<String> modes = Set.of("Read", "Append");
400+
final Set<URI> purposes = Collections.singleton(URI.create("https://purpose.test/Purpose1"));
401+
final Set<URI> resources = Collections.singleton(URI.create("https://storage.test/data/"));
402+
403+
final var req = AccessRequest.RequestParameters.newBuilder()
404+
.recipient(recipient)
405+
.templates(Collections.singleton("http://{storage}/path"))
406+
.templates(null)
407+
.template(AccessRequest.template("data"))
408+
.modes(modes)
409+
.purposes(purposes)
410+
.expiration(expiration)
411+
.build();
412+
413+
final AccessRequest request = client.requestAccess(req)
414+
.toCompletableFuture().join();
415+
416+
final AccessGrant grant = client.grantAccess(request, templates ->
417+
templates.stream()
418+
.map(t -> t.replace("{domain}", "storage.test").replace("{+path}/", ""))
419+
.map(URI::create)
420+
.collect(Collectors.toSet()), verifyRequest)
421+
.toCompletableFuture().join();
422+
423+
assertTrue(grant.getTypes().contains("SolidAccessGrant"));
424+
assertEquals(Optional.of(recipient), grant.getRecipient());
425+
assertEquals(modes, grant.getModes());
426+
assertEquals(expiration, grant.getExpiration());
427+
assertEquals(baseUri, grant.getIssuer());
428+
assertEquals(purposes, grant.getPurposes());
429+
assertEquals(resources, grant.getResources());
430+
assertNotNull(grant.getAccessRequest());
431+
}
432+
338433
@ParameterizedTest
339434
@ValueSource(booleans = {true, false})
340435
void testDenyAccess(final boolean verifyRequest) {
@@ -371,6 +466,58 @@ void testDenyAccess(final boolean verifyRequest) {
371466
assertInstanceOf(AccessGrantException.class, err.getCause());
372467
}
373468

469+
@Test
470+
void testNoTemplatesResources() {
471+
final Map<String, Object> claims = new HashMap<>();
472+
claims.put("webid", WEBID);
473+
claims.put("sub", SUB);
474+
claims.put("iss", ISS);
475+
claims.put("azp", AZP);
476+
final String token = generateIdToken(claims);
477+
final AccessGrantClient client = agClient.session(OpenIdSession.ofIdToken(token));
478+
479+
final URI recipient = URI.create("https://id.test/agent");
480+
final Instant expiration = Instant.parse("2022-08-27T12:00:00Z");
481+
final Set<String> modes = Set.of("Read", "Append");
482+
final Set<URI> purposes = Collections.singleton(URI.create("https://purpose.test/Purpose1"));
483+
484+
final var req = AccessRequest.RequestParameters.newBuilder()
485+
.recipient(recipient)
486+
.modes(modes)
487+
.purposes(purposes)
488+
.expiration(expiration)
489+
.build();
490+
491+
assertDoesNotThrow(client.requestAccess(req).toCompletableFuture()::join);
492+
}
493+
494+
@Test
495+
void testBothTemplatesResources() {
496+
final Map<String, Object> claims = new HashMap<>();
497+
claims.put("webid", WEBID);
498+
claims.put("sub", SUB);
499+
claims.put("iss", ISS);
500+
claims.put("azp", AZP);
501+
final String token = generateIdToken(claims);
502+
final AccessGrantClient client = agClient.session(OpenIdSession.ofIdToken(token));
503+
504+
final URI recipient = URI.create("https://id.test/agent");
505+
final Instant expiration = Instant.parse("2022-08-27T12:00:00Z");
506+
final Set<String> modes = Set.of("Read", "Append");
507+
final Set<URI> purposes = Collections.singleton(URI.create("https://purpose.test/Purpose1"));
508+
509+
final var req = AccessRequest.RequestParameters.newBuilder()
510+
.recipient(recipient)
511+
.modes(modes)
512+
.purposes(purposes)
513+
.expiration(expiration)
514+
.template(AccessRequest.template("data"))
515+
.resource(URI.create("https://storage.test/path/data/"))
516+
.build();
517+
518+
assertDoesNotThrow(client.requestAccess(req).toCompletableFuture()::join);
519+
}
520+
374521
@Test
375522
void testGrantAccessNoAuth() {
376523
final Map<String, Object> claims = new HashMap<>();

access-grant/src/test/java/com/inrupt/client/accessgrant/MockAccessGrantServer.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,32 @@ private void setupMocks() {
139139
.withStatus(401)
140140
.withHeader("WWW-Authenticate", "Bearer,DPoP algs=\"ES256\"")));
141141

142+
wireMockServer.stubFor(get(urlEqualTo("/access-request-6"))
143+
.atPriority(1)
144+
.withHeader("Authorization", containing("Bearer eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9."))
145+
.willReturn(aResponse()
146+
.withStatus(200)
147+
.withHeader(CONTENT_TYPE, APPLICATION_JSON)
148+
.withBody(getResource("/template-6.json", wireMockServer.baseUrl()))));
149+
150+
wireMockServer.stubFor(get(urlEqualTo("/access-request-6"))
151+
.atPriority(2)
152+
.willReturn(aResponse()
153+
.withStatus(401)
154+
.withHeader("WWW-Authenticate", "Bearer,DPoP algs=\"ES256\"")));
155+
156+
wireMockServer.stubFor(delete(urlEqualTo("/access-request-6"))
157+
.atPriority(1)
158+
.withHeader("Authorization", containing("Bearer eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9."))
159+
.willReturn(aResponse()
160+
.withStatus(204)));
161+
162+
wireMockServer.stubFor(delete(urlEqualTo("/access-request-6"))
163+
.atPriority(2)
164+
.willReturn(aResponse()
165+
.withStatus(401)
166+
.withHeader("WWW-Authenticate", "Bearer,DPoP algs=\"ES256\"")));
167+
142168
wireMockServer.stubFor(get(urlEqualTo("/access-grant-6"))
143169
.atPriority(1)
144170
.withHeader("Authorization", containing("Bearer eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9."))
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{
2+
"@context":[
3+
"https://www.w3.org/2018/credentials/v1",
4+
"https://w3id.org/security/suites/ed25519-2020/v1",
5+
"https://w3id.org/vc-revocation-list-2020/v1",
6+
"https://schema.inrupt.com/credentials/v2.jsonld"],
7+
"id":"{{baseUrl}}/access-request-6",
8+
"type":["VerifiableCredential","SolidAccessRequest"],
9+
"issuer":"{{baseUrl}}",
10+
"expirationDate":"2022-08-27T12:00:00Z",
11+
"issuanceDate":"2022-08-25T20:34:05.153Z",
12+
"credentialStatus":{
13+
"id":"https://accessgrant.example/status/CVAM#2832",
14+
"revocationListCredential":"https://accessgrant.example/status/CVAM",
15+
"revocationListIndex":"2832",
16+
"type":"RevocationList2020Status"},
17+
"credentialSubject":{
18+
"id":"https://id.test/username",
19+
"hasConsent":{
20+
"mode":["Read","Append"],
21+
"hasStatus":"https://w3id.org/GConsent#ConsentStatusRequested",
22+
"forPurpose":["https://purpose.test/Purpose1"],
23+
"template":["https://{domain}/{+path}/data/"]}},
24+
"proof":{
25+
"created":"2022-08-25T20:34:05.236Z",
26+
"proofPurpose":"assertionMethod",
27+
"proofValue":"nIeQF44XVik7onnAbdkbp8xxJ2C8JoTw6-VtCkAzxuWYRFsSfYpft5MuAJaivyeKDmaK82Lj_YsME2xgL2WIBQ",
28+
"type":"Ed25519Signature2020",
29+
"verificationMethod":"https://accessgrant.example/key/1e332728-4af5-46e4-a5db-4f7b89e3f378"}
30+
}
31+

0 commit comments

Comments
 (0)