Skip to content

Commit a7c13bf

Browse files
authored
Support qualified type names in the Access Grant client (#1409)
1 parent 067d124 commit a7c13bf

File tree

12 files changed

+346
-7
lines changed

12 files changed

+346
-7
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ public static AccessDenial of(final InputStream serialization) {
9393
static Set<String> getSupportedTypes() {
9494
final Set<String> types = new HashSet<>();
9595
types.add("SolidAccessDenial");
96+
types.add("vc:SolidAccessDenial");
9697
types.add("http://www.w3.org/ns/solid/vc#SolidAccessDenial");
9798
return Collections.unmodifiableSet(types);
9899
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ public static AccessGrant of(final InputStream serialization) {
9393
static Set<String> getSupportedTypes() {
9494
final Set<String> types = new HashSet<>();
9595
types.add("SolidAccessGrant");
96+
types.add("vc:SolidAccessGrant");
9697
types.add("http://www.w3.org/ns/solid/vc#SolidAccessGrant");
9798
return Collections.unmodifiableSet(types);
9899
}

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

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ public class AccessGrantClient {
9494
private static final String INRUPT_CONTEXT_URI = "https://schema.inrupt.com/credentials/v1.jsonld";
9595
private static final String VERIFIABLE_CREDENTIAL = "verifiableCredential";
9696
private static final String SOLID_VC_NAMESPACE = "http://www.w3.org/ns/solid/vc#";
97+
private static final String SOLID_VC_QN = "vc:";
9798
private static final String TYPE = "type";
9899
private static final String APPLICATION_JSON = "application/json";
99100
private static final String CONTENT_TYPE = "Content-Type";
@@ -114,6 +115,9 @@ public class AccessGrantClient {
114115
private static final URI FQ_ACCESS_GRANT = URI.create(SOLID_VC_NAMESPACE + SOLID_ACCESS_GRANT);
115116
private static final URI FQ_ACCESS_REQUEST = URI.create(SOLID_VC_NAMESPACE + SOLID_ACCESS_REQUEST);
116117
private static final URI FQ_ACCESS_DENIAL = URI.create(SOLID_VC_NAMESPACE + SOLID_ACCESS_DENIAL);
118+
private static final URI QN_ACCESS_GRANT = URI.create(SOLID_VC_QN + SOLID_ACCESS_GRANT);
119+
private static final URI QN_ACCESS_REQUEST = URI.create(SOLID_VC_QN + SOLID_ACCESS_REQUEST);
120+
private static final URI QN_ACCESS_DENIAL = URI.create(SOLID_VC_QN + SOLID_ACCESS_DENIAL);
117121
private static final Set<String> ACCESS_GRANT_TYPES = getAccessGrantTypes();
118122
private static final Set<String> ACCESS_REQUEST_TYPES = getAccessRequestTypes();
119123
private static final Set<String> ACCESS_DENIAL_TYPES = getAccessDenialTypes();
@@ -785,33 +789,39 @@ static boolean isSuccess(final int statusCode) {
785789
static Set<String> getAccessRequestTypes() {
786790
final Set<String> types = new HashSet<>();
787791
types.add(SOLID_ACCESS_REQUEST);
792+
types.add(QN_ACCESS_REQUEST.toString());
788793
types.add(FQ_ACCESS_REQUEST.toString());
789794
return Collections.unmodifiableSet(types);
790795
}
791796

792797
static Set<String> getAccessGrantTypes() {
793798
final Set<String> types = new HashSet<>();
794799
types.add(SOLID_ACCESS_GRANT);
800+
types.add(QN_ACCESS_GRANT.toString());
795801
types.add(FQ_ACCESS_GRANT.toString());
796802
return Collections.unmodifiableSet(types);
797803
}
798804

799805
static Set<String> getAccessDenialTypes() {
800806
final Set<String> types = new HashSet<>();
801807
types.add(SOLID_ACCESS_DENIAL);
808+
types.add(QN_ACCESS_DENIAL.toString());
802809
types.add(FQ_ACCESS_DENIAL.toString());
803810
return Collections.unmodifiableSet(types);
804811
}
805812

806813
static boolean isAccessGrant(final URI type) {
807-
return SOLID_ACCESS_GRANT.equals(type.toString()) || FQ_ACCESS_GRANT.equals(type);
814+
return SOLID_ACCESS_GRANT.equals(type.toString()) || QN_ACCESS_GRANT.equals(type)
815+
|| FQ_ACCESS_GRANT.equals(type);
808816
}
809817

810818
static boolean isAccessRequest(final URI type) {
811-
return SOLID_ACCESS_REQUEST.equals(type.toString()) || FQ_ACCESS_REQUEST.equals(type);
819+
return SOLID_ACCESS_REQUEST.equals(type.toString()) || QN_ACCESS_REQUEST.equals(type)
820+
|| FQ_ACCESS_REQUEST.equals(type);
812821
}
813822

814823
static boolean isAccessDenial(final URI type) {
815-
return SOLID_ACCESS_DENIAL.equals(type.toString()) || FQ_ACCESS_DENIAL.equals(type);
824+
return SOLID_ACCESS_DENIAL.equals(type.toString()) || QN_ACCESS_DENIAL.equals(type)
825+
|| FQ_ACCESS_DENIAL.equals(type);
816826
}
817827
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ public static AccessRequest of(final InputStream serialization) {
9494
static Set<String> getSupportedTypes() {
9595
final Set<String> types = new HashSet<>();
9696
types.add("SolidAccessRequest");
97+
types.add("vc:SolidAccessRequest");
9798
types.add("http://www.w3.org/ns/solid/vc#SolidAccessRequest");
9899
return Collections.unmodifiableSet(types);
99100
}
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
/*
2+
* Copyright Inrupt Inc.
3+
*
4+
* Permission is hereby granted, free of charge, to any person obtaining a copy
5+
* of this software and associated documentation files (the "Software"), to deal in
6+
* the Software without restriction, including without limitation the rights to use,
7+
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
8+
* Software, and to permit persons to whom the Software is furnished to do so,
9+
* subject to the following conditions:
10+
*
11+
* The above copyright notice and this permission notice shall be included in
12+
* all copies or substantial portions of the Software.
13+
*
14+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
15+
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
16+
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
17+
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
18+
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
19+
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20+
*/
21+
package com.inrupt.client.accessgrant;
22+
23+
import static org.junit.jupiter.api.Assertions.*;
24+
25+
import com.inrupt.client.spi.JsonService;
26+
import com.inrupt.client.spi.ServiceProvider;
27+
28+
import java.io.IOException;
29+
import java.io.InputStream;
30+
import java.net.URI;
31+
import java.time.Instant;
32+
import java.util.Collections;
33+
import java.util.HashSet;
34+
import java.util.Optional;
35+
import java.util.Set;
36+
37+
import org.junit.jupiter.api.Test;
38+
39+
class AccessDenialTest {
40+
41+
private static final JsonService jsonService = ServiceProvider.getJsonService();
42+
43+
@Test
44+
void testReadAccessDenial() throws IOException {
45+
try (final InputStream resource = AccessDenialTest.class.getResourceAsStream("/access_denial1.json")) {
46+
final AccessDenial denial = AccessDenial.of(resource);
47+
assertEquals(Collections.singleton("Read"), denial.getModes());
48+
assertEquals(URI.create("https://accessgrant.test"), denial.getIssuer());
49+
final Set<String> expectedTypes = new HashSet<>();
50+
expectedTypes.add("VerifiableCredential");
51+
expectedTypes.add("SolidAccessDenial");
52+
assertEquals(expectedTypes, denial.getTypes());
53+
assertEquals(Instant.parse("2022-08-27T12:00:00Z"), denial.getExpiration());
54+
assertEquals(Instant.parse("2022-08-25T20:34:05.153Z"), denial.getIssuedAt());
55+
assertEquals(URI.create("https://accessgrant.test/credential/fc2dbcd9-81d4-4fa4-8fd4-239e16dd83ab"),
56+
denial.getIdentifier());
57+
assertEquals(Collections.singleton(URI.create("https://purpose.test/Purpose1")), denial.getPurposes());
58+
assertEquals(Collections.singleton(
59+
URI.create("https://storage.test/e973cc3d-5c28-4a10-98c5-e40079289358/")),
60+
denial.getResources());
61+
assertEquals(URI.create("https://id.test/grantor"), denial.getCreator());
62+
assertEquals(Optional.of(URI.create("https://id.test/grantee")), denial.getRecipient());
63+
final Optional<Status> status = denial.getStatus();
64+
assertTrue(status.isPresent());
65+
status.ifPresent(s -> {
66+
assertEquals(URI.create("https://accessgrant.test/status/CVAM#2832"), s.getIdentifier());
67+
assertEquals(URI.create("https://accessgrant.test/status/CVAM"), s.getCredential());
68+
assertEquals(2832, s.getIndex());
69+
assertEquals("RevocationList2020Status", s.getType());
70+
});
71+
}
72+
}
73+
74+
@Test
75+
void testReadAccessDenialQualifiedName() throws IOException {
76+
try (final InputStream resource = AccessDenialTest.class.getResourceAsStream("/access_denial2.json")) {
77+
final AccessDenial denial = AccessDenial.of(resource);
78+
assertEquals(Collections.singleton("Read"), denial.getModes());
79+
assertEquals(URI.create("https://accessgrant.test"), denial.getIssuer());
80+
final Set<String> expectedTypes = new HashSet<>();
81+
expectedTypes.add("VerifiableCredential");
82+
expectedTypes.add("vc:SolidAccessDenial");
83+
assertEquals(expectedTypes, denial.getTypes());
84+
assertEquals(Instant.parse("2022-08-27T12:00:00Z"), denial.getExpiration());
85+
assertEquals(Instant.parse("2022-08-25T20:34:05.153Z"), denial.getIssuedAt());
86+
assertEquals(URI.create("https://accessgrant.test/credential/39a4fdd4-44b0-48a5-a9b5-7a9b648e9a67"),
87+
denial.getIdentifier());
88+
assertEquals(Collections.singleton(URI.create("https://purpose.test/Purpose1")), denial.getPurposes());
89+
assertEquals(Collections.singleton(
90+
URI.create("https://storage.test/d5ef4173-4f12-40b2-9a0e-18fa7cc0dd38/")),
91+
denial.getResources());
92+
assertEquals(URI.create("https://id.test/grantor"), denial.getCreator());
93+
assertEquals(Optional.of(URI.create("https://id.test/grantee")), denial.getRecipient());
94+
final Optional<Status> status = denial.getStatus();
95+
assertTrue(status.isPresent());
96+
status.ifPresent(s -> {
97+
assertEquals(URI.create("https://accessgrant.test/status/CVAM#2832"), s.getIdentifier());
98+
assertEquals(URI.create("https://accessgrant.test/status/CVAM"), s.getCredential());
99+
assertEquals(2832, s.getIndex());
100+
assertEquals("RevocationList2020Status", s.getType());
101+
});
102+
}
103+
}
104+
}

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

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,37 @@ void testReadAccessGrant() throws IOException {
7373
}
7474
}
7575

76+
@Test
77+
void testReadAccessGrantQualifiedName() throws IOException {
78+
try (final InputStream resource = AccessGrantTest.class.getResourceAsStream("/access_grant4.json")) {
79+
final AccessGrant grant = AccessGrant.of(resource);
80+
assertEquals(Collections.singleton("Read"), grant.getModes());
81+
assertEquals(URI.create("https://accessgrant.example"), grant.getIssuer());
82+
final Set<String> expectedTypes = new HashSet<>();
83+
expectedTypes.add("VerifiableCredential");
84+
expectedTypes.add("vc:SolidAccessGrant");
85+
assertEquals(expectedTypes, grant.getTypes());
86+
assertEquals(Instant.parse("2022-08-27T12:00:00Z"), grant.getExpiration());
87+
assertEquals(Instant.parse("2022-08-25T20:34:05.153Z"), grant.getIssuedAt());
88+
assertEquals(URI.create("https://accessgrant.example/credential/5c6060ad-2f16-4bc1-b022-dffb46bff626"),
89+
grant.getIdentifier());
90+
assertEquals(Collections.singleton(URI.create("https://purpose.example/Purpose1")), grant.getPurposes());
91+
assertEquals(Collections.singleton(
92+
URI.create("https://storage.example/e973cc3d-5c28-4a10-98c5-e40079289358/")),
93+
grant.getResources());
94+
assertEquals(URI.create("https://id.example/grantor"), grant.getCreator());
95+
assertEquals(Optional.of(URI.create("https://id.example/grantee")), grant.getRecipient());
96+
final Optional<Status> status = grant.getStatus();
97+
assertTrue(status.isPresent());
98+
status.ifPresent(s -> {
99+
assertEquals(URI.create("https://accessgrant.example/status/CVAM#2832"), s.getIdentifier());
100+
assertEquals(URI.create("https://accessgrant.example/status/CVAM"), s.getCredential());
101+
assertEquals(2832, s.getIndex());
102+
assertEquals("RevocationList2020Status", s.getType());
103+
});
104+
}
105+
}
106+
76107
@Test
77108
void testReadAccessGrantSingletons() throws IOException {
78109
try (final InputStream resource = AccessGrantTest.class.getResourceAsStream("/access_grant2.json")) {

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

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,6 @@ void testBuilderWithCollections() {
100100
assertNull(params.getIssuedAt());
101101
}
102102

103-
104103
@Test
105104
void testReadAccessRequest() throws IOException {
106105
try (final InputStream resource = AccessRequestTest.class.getResourceAsStream("/access_request1.json")) {
@@ -132,6 +131,37 @@ void testReadAccessRequest() throws IOException {
132131
}
133132
}
134133

134+
@Test
135+
void testReadAccessRequestQualifiedName() throws IOException {
136+
try (final InputStream resource = AccessRequestTest.class.getResourceAsStream("/access_request3.json")) {
137+
final AccessRequest request = AccessRequest.of(resource);
138+
assertEquals(Collections.singleton("Read"), request.getModes());
139+
assertEquals(URI.create("https://accessgrant.test"), request.getIssuer());
140+
final Set<String> expectedTypes = new HashSet<>();
141+
expectedTypes.add("VerifiableCredential");
142+
expectedTypes.add("vc:SolidAccessRequest");
143+
assertEquals(expectedTypes, request.getTypes());
144+
assertEquals(Instant.parse("2022-08-27T12:00:00Z"), request.getExpiration());
145+
assertEquals(Instant.parse("2022-08-25T20:34:05.153Z"), request.getIssuedAt());
146+
assertEquals(URI.create("https://accessgrant.test/credential/d604c858-209a-4bb6-a7f8-2f52c9617cab"),
147+
request.getIdentifier());
148+
assertEquals(Collections.singleton(URI.create("https://purpose.test/Purpose1")), request.getPurposes());
149+
assertEquals(Collections.singleton(
150+
URI.create("https://storage.test/data/")),
151+
request.getResources());
152+
assertEquals(URI.create("https://id.test/username"), request.getCreator());
153+
assertEquals(Optional.of(URI.create("https://id.test/agent")), request.getRecipient());
154+
final Optional<Status> status = request.getStatus();
155+
assertTrue(status.isPresent());
156+
status.ifPresent(s -> {
157+
assertEquals(URI.create("https://accessgrant.test/status/CVAM#2832"), s.getIdentifier());
158+
assertEquals(URI.create("https://accessgrant.test/status/CVAM"), s.getCredential());
159+
assertEquals(2832, s.getIndex());
160+
assertEquals("RevocationList2020Status", s.getType());
161+
});
162+
}
163+
}
164+
135165
@Test
136166
void testReadAccessRequestSingletons() throws IOException {
137167
try (final InputStream resource = AccessRequestTest.class.getResourceAsStream("/access_request2.json")) {
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
{
2+
"@context": ["https://www.w3.org/2018/credentials/v1"],
3+
"type": ["VerifiablePresentation"],
4+
"verifiableCredential": [{
5+
"@context":[
6+
"https://www.w3.org/2018/credentials/v1",
7+
"https://w3id.org/security/suites/ed25519-2020/v1",
8+
"https://w3id.org/vc-revocation-list-2020/v1",
9+
"https://schema.inrupt.com/credentials/v1.jsonld"],
10+
"id":"https://accessgrant.test/credential/fc2dbcd9-81d4-4fa4-8fd4-239e16dd83ab",
11+
"type":["VerifiableCredential","SolidAccessDenial"],
12+
"issuer":"https://accessgrant.test",
13+
"expirationDate":"2022-08-27T12:00:00Z",
14+
"issuanceDate":"2022-08-25T20:34:05.153Z",
15+
"credentialStatus":{
16+
"id":"https://accessgrant.test/status/CVAM#2832",
17+
"revocationListCredential":"https://accessgrant.test/status/CVAM",
18+
"revocationListIndex":"2832",
19+
"type":"RevocationList2020Status"},
20+
"credentialSubject":{
21+
"id":"https://id.test/grantor",
22+
"providedConsent":{
23+
"mode":["Read"],
24+
"hasStatus":"https://w3id.org/GConsent#ConsentStatusRefused",
25+
"isProvidedTo":"https://id.test/grantee",
26+
"forPurpose":["https://purpose.test/Purpose1"],
27+
"forPersonalData":["https://storage.test/e973cc3d-5c28-4a10-98c5-e40079289358/"]}},
28+
"proof":{
29+
"created":"2022-08-25T20:34:05.236Z",
30+
"proofPurpose":"assertionMethod",
31+
"proofValue":"nIeQF44XVik7onnAbdkbp8xxJ2C8JoTw6-VtCkAzxuWYRFsSfYpft5MuAJaivyeKDmaK82Lj_YsME2xgL2WIBQ",
32+
"type":"Ed25519Signature2020",
33+
"verificationMethod":"https://accessgrant.test/key/1e332728-4af5-46e4-a5db-4f7b89e3f378"}
34+
}]
35+
}
36+
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
{
2+
"@context": ["https://www.w3.org/2018/credentials/v1"],
3+
"type": ["VerifiablePresentation"],
4+
"verifiableCredential": [{
5+
"@context":[
6+
"https://www.w3.org/2018/credentials/v1",
7+
"https://w3id.org/security/suites/ed25519-2020/v1",
8+
"https://w3id.org/vc-revocation-list-2020/v1",
9+
"https://schema.inrupt.com/credentials/v1.jsonld"],
10+
"id":"https://accessgrant.test/credential/39a4fdd4-44b0-48a5-a9b5-7a9b648e9a67",
11+
"type":["VerifiableCredential","vc:SolidAccessDenial"],
12+
"issuer":"https://accessgrant.test",
13+
"expirationDate":"2022-08-27T12:00:00Z",
14+
"issuanceDate":"2022-08-25T20:34:05.153Z",
15+
"credentialStatus":{
16+
"id":"https://accessgrant.test/status/CVAM#2832",
17+
"revocationListCredential":"https://accessgrant.test/status/CVAM",
18+
"revocationListIndex":"2832",
19+
"type":"RevocationList2020Status"},
20+
"credentialSubject":{
21+
"id":"https://id.test/grantor",
22+
"providedConsent":{
23+
"mode":["Read"],
24+
"hasStatus":"https://w3id.org/GConsent#ConsentStatusRefused",
25+
"isProvidedTo":"https://id.test/grantee",
26+
"forPurpose":["https://purpose.test/Purpose1"],
27+
"forPersonalData":["https://storage.test/d5ef4173-4f12-40b2-9a0e-18fa7cc0dd38/"]}},
28+
"proof":{
29+
"created":"2022-08-25T20:34:05.236Z",
30+
"proofPurpose":"assertionMethod",
31+
"proofValue":"nIeQF44XVik7onnAbdkbp8xxJ2C8JoTw6-VtCkAzxuWYRFsSfYpft5MuAJaivyeKDmaK82Lj_YsME2xgL2WIBQ",
32+
"type":"Ed25519Signature2020",
33+
"verificationMethod":"https://accessgrant.test/key/1e332728-4af5-46e4-a5db-4f7b89e3f378"}
34+
}]
35+
}
36+

0 commit comments

Comments
 (0)