Skip to content

Commit 255ea6a

Browse files
authored
JCL-380: Add issuedAt getter to credentials (#529)
1 parent b910e2a commit 255ea6a

File tree

3 files changed

+40
-1
lines changed

3 files changed

+40
-1
lines changed

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

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ public class AccessCredential {
5252
private final URI recipient;
5353
private final URI creator;
5454
private final Instant expiration;
55+
private final Instant issuedAt;
5556
private final Status status;
5657

5758
/**
@@ -78,6 +79,7 @@ protected AccessCredential(final URI identifier, final String credential,
7879
this.types = metadata.getTypes();
7980
this.status = metadata.getStatus();
8081
this.expiration = metadata.getExpiration();
82+
this.issuedAt = metadata.getIssuedAt();
8183
}
8284

8385
/**
@@ -116,6 +118,10 @@ public Instant getExpiration() {
116118
return expiration != null ? expiration : Instant.MAX;
117119
}
118120

121+
public Instant getIssuedAt() {
122+
return issuedAt;
123+
}
124+
119125
/**
120126
* Get the issuer of the access credential.
121127
*
@@ -188,6 +194,7 @@ public static class CredentialMetadata {
188194
private final Set<String> types;
189195
private final Status status;
190196
private final Instant expiration;
197+
private final Instant issuedAt;
191198

192199
/**
193200
* A collection of server-managed credential metadata.
@@ -197,12 +204,30 @@ public static class CredentialMetadata {
197204
* @param types the credential types
198205
* @param expiration the credential expiration
199206
* @param status the credential status
207+
* @deprecated as of Beta4, please use the 6-parameter constructor
200208
*/
209+
@Deprecated
201210
public CredentialMetadata(final URI issuer, final URI creator, final Set<String> types,
202211
final Instant expiration, final Status status) {
212+
this(issuer, creator, types, Instant.now(), expiration, status);
213+
}
214+
215+
/**
216+
* A collection of server-managed credential metadata.
217+
*
218+
* @param issuer the issuer
219+
* @param creator the agent who created the credential
220+
* @param types the credential types
221+
* @param issuedAt the credential issuance date
222+
* @param expiration the credential expiration date
223+
* @param status the credential status
224+
*/
225+
public CredentialMetadata(final URI issuer, final URI creator, final Set<String> types,
226+
final Instant issuedAt, final Instant expiration, final Status status) {
203227
this.issuer = Objects.requireNonNull(issuer, "issuer may not be null!");
204228
this.creator = Objects.requireNonNull(creator, "creator may not be null!");
205229
this.types = Objects.requireNonNull(types, "types may not be null!");
230+
this.issuedAt = Objects.requireNonNull(issuedAt, "issuedAt may not be null!");
206231
this.expiration = expiration;
207232
this.status = status;
208233
}
@@ -251,6 +276,15 @@ public Instant getExpiration() {
251276
public Status getStatus() {
252277
return status;
253278
}
279+
280+
/**
281+
* Get the instant when the credential was issued.
282+
*
283+
* @return the time at which the access credentials was issued
284+
*/
285+
public Instant getIssuedAt() {
286+
return issuedAt;
287+
}
254288
}
255289

256290
/** User-managed credential data. */
@@ -318,6 +352,7 @@ static CredentialMetadata extractMetadata(final Map<String, Object> data) {
318352
new IllegalArgumentException("Missing or invalid issuer field"));
319353
final Set<String> types = asSet(data.get(TYPE)).orElseGet(Collections::emptySet);
320354
final Instant expiration = asInstant(data.get("expirationDate")).orElse(Instant.MAX);
355+
final Instant issuedAt = asInstant(data.get("issuanceDate")).orElse(Instant.EPOCH);
321356
final Status status = asMap(data.get("credentialStatus")).flatMap(credentialStatus ->
322357
asSet(credentialStatus.get(TYPE)).filter(statusTypes ->
323358
statusTypes.contains(REVOCATION_LIST_2020_STATUS)).map(x ->
@@ -329,7 +364,7 @@ static CredentialMetadata extractMetadata(final Map<String, Object> data) {
329364
final URI creator = asUri(subject.get("id")).orElseThrow(() ->
330365
new IllegalArgumentException("Missing or invalid credentialSubject.id field"));
331366

332-
return new CredentialMetadata(issuer, creator, types, expiration, status);
367+
return new CredentialMetadata(issuer, creator, types, issuedAt, expiration, status);
333368
}
334369

335370
static Map<String, Object> extractConsent(final Map<String, Object> data, final String property) {

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ void testReadAccessGrant() throws IOException {
5555
expectedTypes.add("SolidAccessGrant");
5656
assertEquals(expectedTypes, grant.getTypes());
5757
assertEquals(Instant.parse("2022-08-27T12:00:00Z"), grant.getExpiration());
58+
assertEquals(Instant.parse("2022-08-25T20:34:05.153Z"), grant.getIssuedAt());
5859
assertEquals(URI.create("https://accessgrant.example/credential/5c6060ad-2f16-4bc1-b022-dffb46bff626"),
5960
grant.getIdentifier());
6061
assertEquals(Collections.singleton("https://purpose.example/Purpose1"), grant.getPurpose());
@@ -88,6 +89,7 @@ void testReadAccessGrantSingletons() throws IOException {
8889
expectedTypes.add("SolidAccessGrant");
8990
assertEquals(expectedTypes, grant.getTypes());
9091
assertEquals(Instant.parse("2022-08-27T12:00:00Z"), grant.getExpiration());
92+
assertEquals(Instant.parse("2022-08-25T20:34:05.153Z"), grant.getIssuedAt());
9193
assertEquals(URI.create("https://accessgrant.example/credential/5c6060ad-2f16-4bc1-b022-dffb46bff626"),
9294
grant.getIdentifier());
9395
assertEquals(Collections.singleton("https://purpose.example/Purpose1"), grant.getPurpose());

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ void testReadAccessRequest() throws IOException {
5353
expectedTypes.add("SolidAccessRequest");
5454
assertEquals(expectedTypes, request.getTypes());
5555
assertEquals(Instant.parse("2022-08-27T12:00:00Z"), request.getExpiration());
56+
assertEquals(Instant.parse("2022-08-25T20:34:05.153Z"), request.getIssuedAt());
5657
assertEquals(URI.create("https://accessgrant.test/credential/d604c858-209a-4bb6-a7f8-2f52c9617cab"),
5758
request.getIdentifier());
5859
assertEquals(Collections.singleton(URI.create("https://purpose.test/Purpose1")), request.getPurposes());
@@ -83,6 +84,7 @@ void testReadAccessRequestSingletons() throws IOException {
8384
expectedTypes.add("SolidAccessRequest");
8485
assertEquals(expectedTypes, request.getTypes());
8586
assertEquals(Instant.parse("2022-08-27T12:00:00Z"), request.getExpiration());
87+
assertEquals(Instant.parse("2022-08-25T20:34:05.153Z"), request.getIssuedAt());
8688
assertEquals(URI.create("https://accessgrant.test/credential/d604c858-209a-4bb6-a7f8-2f52c9617cab"),
8789
request.getIdentifier());
8890
assertEquals(Collections.singleton(URI.create("https://purpose.test/Purpose1")), request.getPurposes());

0 commit comments

Comments
 (0)