Skip to content

Commit ee5b712

Browse files
authored
implement lear credential v2 model (#60)
* implement lear credential v2 model * add deserializer * fix constants * remove signer addition to tir this id should be added during the onboarding not during the issuance. * add tests * add json include non null * add description * resolve comment * add jsonValue
1 parent f4861e6 commit ee5b712

19 files changed

+595
-206
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file.
44
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
55
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

7+
## [v1.3.0](https://github.com/in2workspace/in2-issuer-api/releases/tag/v1.3.0)
8+
### Changed
9+
- The issuer now issues only LearCredentialEmployee v2.
10+
711
## [v1.2.5](https://github.com/in2workspace/in2-issuer-api/releases/tag/v1.2.5)
812
### Changed
913
- Changing environment variable for wallet knowledge redirection to email.

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ plugins {
1111
}
1212

1313
group = 'es.in2'
14-
version = '1.2.5'
14+
version = '1.3.0'
1515

1616
java {
1717
sourceCompatibility = '17'

src/main/java/es/in2/issuer/IssuerApiApplication.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package es.in2.issuer;
22

3+
import com.fasterxml.jackson.annotation.JsonInclude;
34
import com.fasterxml.jackson.databind.DeserializationFeature;
45
import com.fasterxml.jackson.databind.ObjectMapper;
56
import com.fasterxml.jackson.databind.json.JsonMapper;
@@ -17,6 +18,7 @@ public class IssuerApiApplication {
1718
private static final ObjectMapper OBJECT_MAPPER =
1819
JsonMapper.builder()
1920
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
21+
.serializationInclusion(JsonInclude.Include.NON_NULL)
2022
.build();
2123

2224
public static void main(String[] args) {

src/main/java/es/in2/issuer/application/workflow/impl/VerifiableCredentialIssuanceWorkflowImpl.java

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -221,30 +221,21 @@ private Mono<Void> processDecodedCredential(String processId, String decodedCred
221221

222222
LEARCredentialEmployeeJwtPayload learCredentialEmployeeJwtPayload = credentialEmployeeFactory.mapStringToLEARCredentialEmployeeJwtPayload(decodedCredential);
223223

224-
String signerOrgIdentifier = learCredentialEmployeeJwtPayload.learCredentialEmployee().credentialSubject().mandate().signer().organizationIdentifier();
225-
if (signerOrgIdentifier == null || signerOrgIdentifier.isBlank()) {
226-
log.error("ProcessID: {} Signer Organization Identifier connot be null or empty", processId);
227-
return Mono.error(new IllegalArgumentException("Organization Identifier not valid"));
228-
}
229-
230224
String mandatorOrgIdentifier = learCredentialEmployeeJwtPayload.learCredentialEmployee().credentialSubject().mandate().mandator().organizationIdentifier();
231225
if (mandatorOrgIdentifier == null || mandatorOrgIdentifier.isBlank()) {
232-
log.error("ProcessID: {} Mandator Organization Identifier connot be null or empty", processId);
226+
log.error("ProcessID: {} Mandator Organization Identifier cannot be null or empty", processId);
233227
return Mono.error(new IllegalArgumentException("Organization Identifier not valid"));
234228
}
235229

236-
return saveToTrustFramework(processId, signerOrgIdentifier, mandatorOrgIdentifier);
230+
return saveToTrustFramework(processId, mandatorOrgIdentifier);
237231
}
238232

239-
private Mono<Void> saveToTrustFramework(String processId, String signerOrgIdentifier, String mandatorOrgIdentifier) {
233+
private Mono<Void> saveToTrustFramework(String processId, String mandatorOrgIdentifier) {
240234

241-
String signerDid = DID_ELSI + signerOrgIdentifier;
242235
String mandatorDid = DID_ELSI + mandatorOrgIdentifier;
243236

244-
return trustFrameworkService.validateDidFormat(processId, signerDid)
245-
.flatMap(isValid -> registerDidIfValid(processId, signerDid, isValid))
246-
.then(trustFrameworkService.validateDidFormat(processId, mandatorDid)
247-
.flatMap(isValid -> registerDidIfValid(processId, mandatorDid, isValid)));
237+
return trustFrameworkService.validateDidFormat(processId, mandatorDid)
238+
.flatMap(isValid -> registerDidIfValid(processId, mandatorDid, isValid));
248239
}
249240

250241
private Mono<Void> registerDidIfValid(String processId, String did, boolean isValid) {
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package es.in2.issuer.domain.model.dto;
2+
3+
import com.fasterxml.jackson.annotation.JsonProperty;
4+
import lombok.Builder;
5+
6+
7+
@Builder
8+
public record DetailedIssuer(
9+
@JsonProperty("id") String id,
10+
@JsonProperty("organizationIdentifier") String organizationIdentifier,
11+
@JsonProperty("organization") String organization,
12+
@JsonProperty("country") String country,
13+
@JsonProperty("commonName") String commonName,
14+
@JsonProperty("emailAddress") String emailAddress,
15+
@JsonProperty("serialNumber") String serialNumber
16+
) implements Issuer {
17+
@Override
18+
public String getId() {
19+
return id;
20+
}
21+
}
22+
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package es.in2.issuer.domain.model.dto;
2+
3+
import com.fasterxml.jackson.annotation.JsonProperty;
4+
5+
public interface Issuer {
6+
7+
@JsonProperty("id")
8+
String getId();
9+
}
10+
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package es.in2.issuer.domain.model.dto;
2+
3+
import com.fasterxml.jackson.core.JsonParser;
4+
import com.fasterxml.jackson.databind.DeserializationContext;
5+
import com.fasterxml.jackson.databind.JsonDeserializer;
6+
import com.fasterxml.jackson.databind.JsonMappingException;
7+
import com.fasterxml.jackson.databind.JsonNode;
8+
9+
import java.io.IOException;
10+
11+
public class IssuerDeserializer extends JsonDeserializer<Issuer> {
12+
@Override
13+
public Issuer deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
14+
JsonNode node = p.getCodec().readTree(p);
15+
// If the node is a string, we convert it to SimpleIssuer.
16+
if (node.isTextual()) {
17+
return new SimpleIssuer(node.asText());
18+
}
19+
// If the node is an object, we convert it to DetailedIssuer.
20+
else if (node.isObject()) {
21+
return p.getCodec().treeToValue(node, DetailedIssuer.class);
22+
}
23+
throw new JsonMappingException(p, "Unexpected data type for Issuer");
24+
}
25+
}
26+
Lines changed: 64 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package es.in2.issuer.domain.model.dto;
22

3+
import com.fasterxml.jackson.annotation.JsonAlias;
34
import com.fasterxml.jackson.annotation.JsonProperty;
5+
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
46
import lombok.Builder;
57

68
import java.util.List;
@@ -10,15 +12,56 @@ public record LEARCredentialEmployee(
1012
@JsonProperty("@context") List<String> context,
1113
@JsonProperty("id") String id,
1214
@JsonProperty("type") List<String> type,
15+
@JsonProperty("description") String description,
1316
@JsonProperty("credentialSubject") CredentialSubject credentialSubject,
14-
@JsonProperty("issuer") String issuer,
17+
@JsonProperty("issuer") @JsonDeserialize(using = IssuerDeserializer.class) Issuer issuer,
1518
@JsonProperty("validFrom") String validFrom,
1619
@JsonProperty("validUntil") String validUntil
17-
) {
20+
) implements W3CVerifiableCredential<LEARCredentialEmployee.CredentialSubject> {
1821

19-
@Builder
20-
public record CredentialSubject(@JsonProperty("mandate") Mandate mandate) {
22+
@Override
23+
public List<String> getContext() {
24+
return context;
25+
}
26+
27+
@Override
28+
public String getId() {
29+
return id;
30+
}
31+
32+
@Override
33+
public List<String> getType() {
34+
return type;
35+
}
36+
37+
@Override
38+
public String getDescription() {
39+
return description;
40+
}
41+
@Override
42+
public Issuer getIssuer() {
43+
return issuer;
44+
}
45+
46+
@Override
47+
public String getValidFrom() {
48+
return validFrom;
49+
}
50+
51+
@Override
52+
public String getValidUntil() {
53+
return validUntil;
54+
}
55+
56+
@Override
57+
public CredentialSubject getCredentialSubject() {
58+
return credentialSubject;
59+
}
2160

61+
@Builder
62+
public record CredentialSubject(
63+
@JsonProperty("mandate") Mandate mandate
64+
) {
2265
@Builder
2366
public record Mandate(
2467
@JsonProperty("id") String id,
@@ -28,23 +71,23 @@ public record Mandate(
2871
@JsonProperty("power") List<Power> power,
2972
@JsonProperty("signer") Signer signer
3073
) {
31-
3274
@Builder
3375
public record LifeSpan(
3476
@JsonProperty("end_date_time") String endDateTime,
3577
@JsonProperty("start_date_time") String startDateTime
36-
) {
37-
}
78+
) { }
3879

3980
@Builder
4081
public record Mandatee(
4182
@JsonProperty("id") String id,
4283
@JsonProperty("email") String email,
43-
@JsonProperty("first_name") String firstName,
44-
@JsonProperty("last_name") String lastName,
45-
@JsonProperty("mobile_phone") String mobilePhone
46-
) {
47-
}
84+
// To keep compatibility with the v1 credential we keep the old name
85+
@JsonProperty("firstName") @JsonAlias("first_name") String firstName,
86+
// To keep compatibility with the v1 credential we keep the old name
87+
@JsonProperty("lastName") @JsonAlias("last_name") String lastName,
88+
@JsonProperty("mobile_phone") String mobilePhone,
89+
@JsonProperty("nationality") String nationality
90+
) { }
4891

4992
@Builder
5093
public record Mandator(
@@ -54,18 +97,16 @@ public record Mandator(
5497
@JsonProperty("organization") String organization,
5598
@JsonProperty("organizationIdentifier") String organizationIdentifier,
5699
@JsonProperty("serialNumber") String serialNumber
57-
) {
58-
}
100+
) { }
59101

60102
@Builder
61103
public record Power(
62104
@JsonProperty("id") String id,
63-
@JsonProperty("tmf_action") Object tmfAction,
64-
@JsonProperty("tmf_domain") String tmfDomain,
65-
@JsonProperty("tmf_function") String tmfFunction,
66-
@JsonProperty("tmf_type") String tmfType
67-
) {
68-
}
105+
@JsonProperty("action") @JsonAlias("tmf_action") Object action,
106+
@JsonProperty("domain") @JsonAlias("tmf_domain") String domain,
107+
@JsonProperty("function") @JsonAlias("tmf_function") String function,
108+
@JsonProperty("type") @JsonAlias("tmf_type") String type
109+
) { }
69110

70111
@Builder
71112
public record Signer(
@@ -75,9 +116,9 @@ public record Signer(
75116
@JsonProperty("organization") String organization,
76117
@JsonProperty("organizationIdentifier") String organizationIdentifier,
77118
@JsonProperty("serialNumber") String serialNumber
78-
) {
79-
}
80-
119+
) { }
81120
}
82121
}
83122
}
123+
124+
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package es.in2.issuer.domain.model.dto;
2+
3+
import com.fasterxml.jackson.annotation.JsonProperty;
4+
import com.fasterxml.jackson.annotation.JsonValue;
5+
import lombok.Builder;
6+
7+
@Builder
8+
public record SimpleIssuer(@JsonProperty("id") String id) implements Issuer {
9+
10+
@JsonValue
11+
public String toJson() {
12+
return id;
13+
}
14+
15+
@Override
16+
public String getId() {
17+
return id;
18+
}
19+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package es.in2.issuer.domain.model.dto;
2+
3+
import java.util.List;
4+
5+
public interface W3CVerifiableCredential<T> {
6+
List<String> getContext();
7+
String getId();
8+
List<String> getType();
9+
String getDescription();
10+
Issuer getIssuer();
11+
String getValidFrom();
12+
String getValidUntil();
13+
T getCredentialSubject();
14+
}

0 commit comments

Comments
 (0)