diff --git a/pom.xml b/pom.xml index 9079a2e..ece58b6 100644 --- a/pom.xml +++ b/pom.xml @@ -1,518 +1,348 @@ + xmlns="http://maven.apache.org/POM/4.0.0" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> - 4.0.0 + 4.0.0 - tng.trustnetwork.keydistribution - tng-key-distribution - latest - jar + + org.springframework.cloud + spring-cloud-starter-parent + 2023.0.0 + + + tng.trustnetwork.keydistribution + tng-key-distribution + latest + jar - tng-key-distribution - GDHCN Key Distribution Service project. - - T-Systems International GmbH - + tng-key-distribution + GDHCN Key Distribution Service project. + + T-Systems International GmbH + - - - 17 - 17 - 17 - - UTF-8 - UTF-8 - - 8.3.1 - 3.0.9 - 2022.0.3 - 2.1.0 - 5.3.23 - 6.1.2 - 1.18.28 - 4.22.0 - 2.1.0 - 2.4.2 - 1.5.5.Final - 5.0.0-alpha.11 - 5.4.0 - 2.2.220 - 1.5 - - 3.3.0 - 3.9.1.2184 - 0.8.10 - 1.7.0 - 3.1.2 - - Key Distribution Service / tng-key-distribution - 2021 - apache_v2 - - WorldHealthOrganization - tng-key-distribution - - WorldHealthOrganization - ${sonar.organization}_${project.artifactId} - https://sonarcloud.io - - **/KeyDistributionServiceApplication.java, - **/model/*, - **/mapper/*, - **/entity/*, - **/DgcKeyStore.java, - **/ErrorHandler.java - - + + + 17 + 17 + 17 + + UTF-8 + UTF-8 + + 8.3.1 + 2.1.0 + 1.5.5.Final + 5.12.0 + + 3.3.0 + 0.8.10 + 2.4.0 + + Key Distribution Service / tng-key-distribution + 2021 + apache_v2 + + WorldHealthOrganization + tng-key-distribution + + WorldHealthOrganization + ${sonar.organization}_${project.artifactId} + https://sonarcloud.io + + **/KeyDistributionServiceApplication.java, + **/model/*, + **/mapper/*, + **/entity/*, + **/DgcKeyStore.java, + **/ErrorHandler.java + + - https://github.com/WorldHealthOrganization/tng-key-distribution - - https://github.com/WorldHealthOrganization/tng-key-distribution/actions - - - https://github.com/WorldHealthOrganization/tng-key-distribution/issues - - https://github.com/WorldHealthOrganization/tng-key-distribution - + + https://github.com/WorldHealthOrganization/tng-key-distribution/actions + + + https://github.com/WorldHealthOrganization/tng-key-distribution/issues + + + https://github.com/WorldHealthOrganization/tng-key-distribution + - - - docker - - docker - jar - - - - - org.springframework.boot - spring-boot-maven-plugin - - ${project.build.directory}/docker - ddccg - - - - maven-assembly-plugin - - - make-zip-ACC - none - - - make-zip-test - none - - - make-zip-PRD - none - - - - - - - + + + docker + + docker + jar + + + + + org.springframework.boot + spring-boot-maven-plugin + + ${project.build.directory}/docker + ddccg + + + + maven-assembly-plugin + + + make-zip-ACC + none + + + make-zip-test + none + + + make-zip-PRD + none + + + + + + + - - - who-github - https://maven.pkg.github.com/${github.organization}/* - - + + + who-github + https://maven.pkg.github.com/${github.organization}/* + + - - - who-github - https://maven.pkg.github.com/${github.organization}/${github.project} - - + + + who-github + https://maven.pkg.github.com/${github.organization}/${github.project} + + - - - - - org.yaml - snakeyaml - 2.0 - - - com.fasterxml.jackson.core - jackson-databind - 2.15.2 - - - com.fasterxml.jackson.core - jackson-core - 2.15.2 - - - com.fasterxml.jackson.datatype - jackson-datatype-jsr310 - 2.15.2 - - - com.fasterxml.jackson.core - jackson-annotations - 2.15.2 - - - com.fasterxml.jackson.jr - jackson-jr-objects - 2.15.2 - - - com.fasterxml.jackson.datatype - jackson-datatype-jdk8 - 2.15.2 - - - com.fasterxml.jackson.module - jackson-module-parameter-names - 2.15.2 - - - com.fasterxml.jackson.dataformat - jackson-dataformat-yaml - 2.15.2 - - - org.json - json - 20230618 - - - com.google.guava - guava - 32.0.1-jre - - - org.springframework.boot - spring-boot-dependencies - ${spring.boot.version} - pom - import - - - org.springframework.cloud - spring-cloud-dependencies - ${spring.cloud.version} - pom - import - - - org.projectlombok - lombok - ${lombok.version} - - - org.springdoc - springdoc-openapi-starter-webmvc-ui - ${springdoc.version} - - - org.liquibase - liquibase-core - ${liquibase.version} - - - + + eu.europa.ec.dgc + ddcc-gateway-lib + 2.0.1 + - - - eu.europa.ec.dgc - ddcc-gateway-lib - 2.0.1 - - - org.springframework.boot - spring-boot-starter - - - org.springframework.boot - spring-boot-starter-data-jpa - - - org.springframework.boot - spring-boot-starter-validation - - - org.springframework.boot - spring-boot-starter-web - - - org.springframework.boot - spring-boot-starter-actuator - - - org.liquibase - liquibase-core - - - org.springframework.boot - spring-boot-starter-test - test - - - org.projectlombok - lombok - provided - - - org.springdoc - springdoc-openapi-starter-webmvc-ui - ${springdoc.version} - - - com.h2database - h2 - ${h2.version} - runtime - - - org.postgresql - postgresql - runtime - - - org.mapstruct - mapstruct - ${mapstruct.version} - - - org.springframework.security - spring-security-web - ${spring.security.version} - - - com.squareup.okhttp3 - okhttp - ${okhttp.version} - test - - - net.javacrumbs.shedlock - shedlock-provider-jdbc-template - ${shedlock.version} - - - net.javacrumbs.shedlock - shedlock-spring - ${shedlock.version} - - - io.pivotal.cfenv - java-cfenv-boot - ${pivotal.cfenv.version} - - - org.springframework.boot - spring-boot - - - - - - com.google.code.bean-matchers - bean-matchers - 0.14 - test - - - commons-fileupload - commons-fileupload - ${commons-fileupload.version} - - - org.springframework.cloud - spring-cloud-starter-feign - 1.4.7.RELEASE - - + + + org.springframework + spring-web + 6.1.5 + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + org.springframework.boot + spring-boot-starter-validation + + + org.springframework.boot + spring-boot-starter-actuator + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springdoc + springdoc-openapi-starter-webmvc-ui + ${springdoc.version} + + + org.springframework.cloud + spring-cloud-starter-openfeign + + + + + org.liquibase + liquibase-core + + + com.h2database + h2 + runtime + + + org.postgresql + postgresql + runtime + 42.7.3 + - - - - - org.springframework.boot - spring-boot-maven-plugin - ${spring.boot.version} - - - org.apache.maven.plugins - maven-checkstyle-plugin - ${plugin.checkstyle.version} - - - com.puppycrawl.tools - checkstyle - 8.41.1 - - - - - org.sonarsource.scanner.maven - sonar-maven-plugin - ${plugin.sonar.version} - - - org.jacoco - jacoco-maven-plugin - ${plugin.jacoco.version} - - - org.apache.maven.plugins - maven-surefire-plugin - ${plugin.surefire.version} - - - org.apache.maven.plugins - maven-compiler-plugin - 3.8.1 - - - org.codehaus.mojo - license-maven-plugin - 2.0.0 - - - org.apache.maven.plugins - maven-resources-plugin - 3.2.0 - - UTF-8 - - - - - - - org.owasp - dependency-check-maven - ${owasp.version} - - ./owasp/suppressions.xml - 8 - false - - - - org.apache.maven.plugins - maven-surefire-plugin - - - org.springframework.boot - spring-boot-maven-plugin - - - - repackage - build-info - - - - - - org.apache.maven.plugins - maven-checkstyle-plugin - - ./codestyle/checkstyle.xml - ./target/**/* - true - true - warning - true - false - - - - check - validate - - check - - - - - - org.jacoco - jacoco-maven-plugin - ${plugin.jacoco.version} - - - - prepare-agent - - - - report - - report - - - - - - org.apache.maven.plugins - maven-compiler-plugin - - - - org.projectlombok - lombok - ${lombok.version} - - - org.mapstruct - mapstruct-processor - ${mapstruct.version} - - - - - - org.codehaus.mojo - license-maven-plugin - - **/*.java - ${project.organization.name} and all other contributors - ---license-start - ---license-end - --- - false - true - true - - - - download-licenses - validate - - download-licenses - - - - - - org.springdoc - springdoc-openapi-maven-plugin - 1.3 - - http://localhost:8080/api/docs - - - - integration-test - - generate - - - - - - + + + org.projectlombok + lombok + + + org.mapstruct + mapstruct + ${mapstruct.version} + + + net.javacrumbs.shedlock + shedlock-provider-jdbc-template + ${shedlock.version} + + + net.javacrumbs.shedlock + shedlock-spring + ${shedlock.version} + + + + + + + org.owasp + dependency-check-maven + ${owasp.version} + + ./owasp/suppressions.xml + 8 + false + + + + org.apache.maven.plugins + maven-surefire-plugin + + + org.springframework.boot + spring-boot-maven-plugin + + + + repackage + build-info + + + + + + org.apache.maven.plugins + maven-checkstyle-plugin + ${plugin.checkstyle.version} + + ./codestyle/checkstyle.xml + ./target/**/* + true + true + warning + true + false + + + + check + validate + + check + + + + + + com.puppycrawl.tools + checkstyle + 8.41.1 + + + + + org.jacoco + jacoco-maven-plugin + ${plugin.jacoco.version} + + + + prepare-agent + + + + report + + report + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + + org.projectlombok + lombok + ${lombok.version} + + + org.mapstruct + mapstruct-processor + ${mapstruct.version} + + + + + + org.codehaus.mojo + license-maven-plugin + ${plugin.license.version} + + **/*.java + ${project.organization.name} and all other contributors + ---license-start + ---license-end + --- + false + true + true + + + + download-licenses + validate + + download-licenses + + + + + + org.springdoc + springdoc-openapi-maven-plugin + 1.3 + + http://localhost:8080/api/docs + + + + integration-test + + generate + + + + + + diff --git a/src/main/java/tng/trustnetwork/keydistribution/clients/UniversalResolverClient.java b/src/main/java/tng/trustnetwork/keydistribution/clients/UniversalResolverClient.java index afa781f..f1a1822 100644 --- a/src/main/java/tng/trustnetwork/keydistribution/clients/UniversalResolverClient.java +++ b/src/main/java/tng/trustnetwork/keydistribution/clients/UniversalResolverClient.java @@ -3,13 +3,12 @@ import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; -import tng.trustnetwork.keydistribution.model.DidDocument; @FeignClient(value = "universalresolver", url = "${universal.resolver}", configuration = UniversalResolverClientConfig.class) public interface UniversalResolverClient { @GetMapping(value = "/{didKey}", produces = "application/json") - DidDocument getDidDocument(@PathVariable("didKey") String didKey); + String getDidDocument(@PathVariable("didKey") String didKey); } diff --git a/src/main/java/tng/trustnetwork/keydistribution/config/KdsConfigProperties.java b/src/main/java/tng/trustnetwork/keydistribution/config/KdsConfigProperties.java index 9a60f1c..ef26918 100644 --- a/src/main/java/tng/trustnetwork/keydistribution/config/KdsConfigProperties.java +++ b/src/main/java/tng/trustnetwork/keydistribution/config/KdsConfigProperties.java @@ -20,6 +20,9 @@ package tng.trustnetwork.keydistribution.config; +import eu.europa.ec.dgc.gateway.connector.model.TrustedIssuer; +import java.util.ArrayList; +import java.util.List; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.Setter; @@ -30,6 +33,8 @@ @ConfigurationProperties("dgc") //TODO separate kds and dgc-lib properties public class KdsConfigProperties { + private List staticTrustedIssuer = new ArrayList<>(); + private final CertificatesDownloader certificatesDownloader = new CertificatesDownloader(); private final TrustedIssuerDownloader trustedIssuerDownloader = new TrustedIssuerDownloader(); diff --git a/src/main/java/tng/trustnetwork/keydistribution/entity/DecentralizedIdentifierEntity.java b/src/main/java/tng/trustnetwork/keydistribution/entity/DecentralizedIdentifierEntity.java new file mode 100644 index 0000000..a52b2de --- /dev/null +++ b/src/main/java/tng/trustnetwork/keydistribution/entity/DecentralizedIdentifierEntity.java @@ -0,0 +1,46 @@ +package tng.trustnetwork.keydistribution.entity; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.OneToMany; +import jakarta.persistence.Table; +import java.time.ZonedDateTime; +import java.util.List; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + + +@Data +@Getter +@Setter +@Entity +@Table(name = "decentralized_identifier") +@AllArgsConstructor +@NoArgsConstructor +public class DecentralizedIdentifierEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id", columnDefinition = "BIGINT") + private Long id; + + @Column(name = "created_at", nullable = false) + private ZonedDateTime createdAt = ZonedDateTime.now(); + + @Column(name = "did_id", length = 100) + private String didId; + + @OneToMany(mappedBy = "parentDocument", fetch = FetchType.EAGER) + private List verificationMethods; + + @Column(name = "raw", length = 10_000_000) + private String raw; + +} diff --git a/src/main/java/tng/trustnetwork/keydistribution/entity/EcPublicKeyJwkEntity.java b/src/main/java/tng/trustnetwork/keydistribution/entity/EcPublicKeyJwkEntity.java new file mode 100644 index 0000000..b5b99d3 --- /dev/null +++ b/src/main/java/tng/trustnetwork/keydistribution/entity/EcPublicKeyJwkEntity.java @@ -0,0 +1,28 @@ +package tng.trustnetwork.keydistribution.entity; + +import jakarta.persistence.Column; +import jakarta.persistence.DiscriminatorValue; +import jakarta.persistence.Entity; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@AllArgsConstructor +@NoArgsConstructor +@Entity +@DiscriminatorValue("EC") +public class EcPublicKeyJwkEntity extends PublicKeyJwkEntity { + + @Column(name = "crv", length = 100) + private String crv; + + @Column(name = "x", length = 100) + private String xvalue; + + @Column(name = "y", length = 100) + private String yvalue; + +} diff --git a/src/main/java/tng/trustnetwork/keydistribution/entity/PublicKeyJwkEntity.java b/src/main/java/tng/trustnetwork/keydistribution/entity/PublicKeyJwkEntity.java new file mode 100644 index 0000000..74ad49e --- /dev/null +++ b/src/main/java/tng/trustnetwork/keydistribution/entity/PublicKeyJwkEntity.java @@ -0,0 +1,39 @@ +package tng.trustnetwork.keydistribution.entity; + +import jakarta.persistence.Column; +import jakarta.persistence.DiscriminatorColumn; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.Inheritance; +import jakarta.persistence.InheritanceType; +import jakarta.persistence.Table; +import java.time.ZonedDateTime; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@AllArgsConstructor +@NoArgsConstructor +@Entity +@Table(name = "public_key_jwk") +@Inheritance(strategy = InheritanceType.SINGLE_TABLE) +@DiscriminatorColumn(name = "kty", columnDefinition = "varchar(10)") +public abstract class PublicKeyJwkEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id") + private Long id; + + @Column(name = "created_at", nullable = false) + private ZonedDateTime createdAt = ZonedDateTime.now(); + + @Column(name = "x5c", length = 7000) + private String x5c; + +} diff --git a/src/main/java/tng/trustnetwork/keydistribution/entity/RsaPublicKeyJwkEntity.java b/src/main/java/tng/trustnetwork/keydistribution/entity/RsaPublicKeyJwkEntity.java new file mode 100644 index 0000000..89da47e --- /dev/null +++ b/src/main/java/tng/trustnetwork/keydistribution/entity/RsaPublicKeyJwkEntity.java @@ -0,0 +1,25 @@ +package tng.trustnetwork.keydistribution.entity; + +import jakarta.persistence.Column; +import jakarta.persistence.DiscriminatorValue; +import jakarta.persistence.Entity; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@AllArgsConstructor +@NoArgsConstructor +@Entity +@DiscriminatorValue("RSA") +public class RsaPublicKeyJwkEntity extends PublicKeyJwkEntity { + + @Column(name = "n", length = 1000) + private String nvalue; + + @Column(name = "e", length = 1000) + private String evalue; + +} diff --git a/src/main/java/tng/trustnetwork/keydistribution/entity/VerificationMethodEntity.java b/src/main/java/tng/trustnetwork/keydistribution/entity/VerificationMethodEntity.java new file mode 100644 index 0000000..5f11c73 --- /dev/null +++ b/src/main/java/tng/trustnetwork/keydistribution/entity/VerificationMethodEntity.java @@ -0,0 +1,54 @@ +package tng.trustnetwork.keydistribution.entity; + +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToOne; +import jakarta.persistence.Table; +import java.time.ZonedDateTime; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Data +@Getter +@Setter +@Entity +@Table(name = "verification_method") +@AllArgsConstructor +@NoArgsConstructor +public class VerificationMethodEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id", columnDefinition = "BIGINT") + private Long id; + + @Column(name = "vm_id", length = 100) + private String vmId; + + @Column(name = "type", length = 100) + private String type; + + @Column(name = "controller", length = 100) + private String controller; + + @OneToOne(cascade = CascadeType.ALL) + @JoinColumn(name = "public_key_jwk_id") + private PublicKeyJwkEntity publicKeyJwk; + + @ManyToOne + @JoinColumn(name = "parent_document_id") + private DecentralizedIdentifierEntity parentDocument; + + @Column(name = "created_at", nullable = false) + private ZonedDateTime createdAt = ZonedDateTime.now(); + +} diff --git a/src/main/java/tng/trustnetwork/keydistribution/mapper/DidMapper.java b/src/main/java/tng/trustnetwork/keydistribution/mapper/DidMapper.java new file mode 100644 index 0000000..1a62634 --- /dev/null +++ b/src/main/java/tng/trustnetwork/keydistribution/mapper/DidMapper.java @@ -0,0 +1,67 @@ +package tng.trustnetwork.keydistribution.mapper; + +import java.util.List; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.SubclassExhaustiveStrategy; +import org.mapstruct.SubclassMapping; +import tng.trustnetwork.keydistribution.entity.DecentralizedIdentifierEntity; +import tng.trustnetwork.keydistribution.entity.EcPublicKeyJwkEntity; +import tng.trustnetwork.keydistribution.entity.PublicKeyJwkEntity; +import tng.trustnetwork.keydistribution.entity.RsaPublicKeyJwkEntity; +import tng.trustnetwork.keydistribution.entity.VerificationMethodEntity; +import tng.trustnetwork.keydistribution.model.DidDocument; +import tng.trustnetwork.keydistribution.model.EcPublicKeyJwk; +import tng.trustnetwork.keydistribution.model.JwkVerificationMethod; +import tng.trustnetwork.keydistribution.model.PublicKeyJwk; +import tng.trustnetwork.keydistribution.model.RsaPublicKeyJwk; +import tng.trustnetwork.keydistribution.model.StringOrObject; +import tng.trustnetwork.keydistribution.model.VerificationMethod; + +@Mapper(componentModel = "spring", subclassExhaustiveStrategy = SubclassExhaustiveStrategy.RUNTIME_EXCEPTION) +public interface DidMapper { + + @Mapping(target = "didId", source = "didDocument.id") + @Mapping(target = "verificationMethods", source = "didDocument.verificationMethod") + @Mapping(target = "id", ignore = true) + @Mapping(target = "createdAt", ignore = true) + DecentralizedIdentifierEntity toEntity(DidDocument didDocument, String raw); + + @SubclassMapping(target = RsaPublicKeyJwkEntity.class, source = RsaPublicKeyJwk.class) + @SubclassMapping(target = EcPublicKeyJwkEntity.class, source = EcPublicKeyJwk.class) + @Mapping(target = "id", ignore = true) + @Mapping(target = "createdAt", ignore = true) + PublicKeyJwkEntity toEntity(PublicKeyJwk publicKeyJwk); + + @Mapping(target = "id", ignore = true) + @Mapping(target = "createdAt", ignore = true) + EcPublicKeyJwkEntity toEntity(EcPublicKeyJwk model); + + @Mapping(target = "id", ignore = true) + @Mapping(target = "createdAt", ignore = true) + RsaPublicKeyJwkEntity toEntity(RsaPublicKeyJwk model); + + @SubclassMapping(target = VerificationMethodEntity.class, source = JwkVerificationMethod.class) + @Mapping(target = "vmId", source = "verificationMethod.id") + @Mapping(target = "id", ignore = true) + @Mapping(target = "createdAt", ignore = true) + @Mapping(target = "parentDocument", ignore = true) + @Mapping(target = "publicKeyJwk", ignore = true) + VerificationMethodEntity toEntity(VerificationMethod verificationMethod); + + @Mapping(target = "type", constant = "JsonWebKey2020") + @Mapping(target = "vmId", source = "verificationMethod.id") + @Mapping(target = "id", ignore = true) + @Mapping(target = "parentDocument", ignore = true) + @Mapping(target = "createdAt", ignore = true) + VerificationMethodEntity toEntity(JwkVerificationMethod verificationMethod); + + default T unwrap(StringOrObject wrapped) { + return wrapped.getObjectValue(); + } + + default String toSingleString(List list) { + + return list == null ? null : String.join(",", list); + } +} diff --git a/src/main/java/tng/trustnetwork/keydistribution/mapper/IssuerMapper.java b/src/main/java/tng/trustnetwork/keydistribution/mapper/IssuerMapper.java index b37b94a..0091ec5 100644 --- a/src/main/java/tng/trustnetwork/keydistribution/mapper/IssuerMapper.java +++ b/src/main/java/tng/trustnetwork/keydistribution/mapper/IssuerMapper.java @@ -31,6 +31,9 @@ public interface IssuerMapper { @Mapping(source = "type", target = "urlType") + @Mapping(target = "id", ignore = true) + @Mapping(target = "etag", ignore = true) + @Mapping(target = "createdAt", ignore = true) TrustedIssuerEntity trustedIssuerToTrustedIssuerEntity(TrustedIssuer trustedIssuer); diff --git a/src/main/java/tng/trustnetwork/keydistribution/model/DidContext.java b/src/main/java/tng/trustnetwork/keydistribution/model/DidContext.java new file mode 100644 index 0000000..7082b49 --- /dev/null +++ b/src/main/java/tng/trustnetwork/keydistribution/model/DidContext.java @@ -0,0 +1,23 @@ +package tng.trustnetwork.keydistribution.model; + +import com.fasterxml.jackson.annotation.JsonInclude; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@JsonInclude(JsonInclude.Include.NON_NULL) +public class DidContext { + + private String base; + + private String rating; + + private String publicAccess; + + private String additionalType; +} diff --git a/src/main/java/tng/trustnetwork/keydistribution/model/DidDocument.java b/src/main/java/tng/trustnetwork/keydistribution/model/DidDocument.java index e578968..e6ba7a7 100644 --- a/src/main/java/tng/trustnetwork/keydistribution/model/DidDocument.java +++ b/src/main/java/tng/trustnetwork/keydistribution/model/DidDocument.java @@ -1,6 +1,7 @@ package tng.trustnetwork.keydistribution.model; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import java.util.List; import lombok.Getter; @@ -8,18 +9,20 @@ @Getter @Setter +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) public class DidDocument { @JsonProperty("@context") - @JsonIgnoreProperties(ignoreUnknown = true) - private List context; - @JsonIgnoreProperties(ignoreUnknown = true) + private List> context; + private String id; - @JsonIgnoreProperties(ignoreUnknown = true) + private String controller; - @JsonIgnoreProperties(ignoreUnknown = true) - private Object verificationMethod; - @JsonIgnoreProperties(ignoreUnknown = true) + + + private List> verificationMethod; + private Proof proof; } diff --git a/src/main/java/tng/trustnetwork/keydistribution/model/DidDocumentUnmarshal.java b/src/main/java/tng/trustnetwork/keydistribution/model/DidDocumentUnmarshal.java deleted file mode 100644 index a3afc04..0000000 --- a/src/main/java/tng/trustnetwork/keydistribution/model/DidDocumentUnmarshal.java +++ /dev/null @@ -1,24 +0,0 @@ -package tng.trustnetwork.keydistribution.model; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import java.util.List; -import lombok.Getter; -import lombok.Setter; - - -@Getter -@Setter -public class DidDocumentUnmarshal { - - @JsonIgnoreProperties(ignoreUnknown = true) - private List context; - @JsonIgnoreProperties(ignoreUnknown = true) - private String id; - @JsonIgnoreProperties(ignoreUnknown = true) - private String controller; - @JsonIgnoreProperties(ignoreUnknown = true) - private VerificationMethod verificationMethod; - @JsonIgnoreProperties(ignoreUnknown = true) - private Proof proof; - -} diff --git a/src/main/java/tng/trustnetwork/keydistribution/model/EcPublicKeyJwk.java b/src/main/java/tng/trustnetwork/keydistribution/model/EcPublicKeyJwk.java new file mode 100644 index 0000000..ddb5481 --- /dev/null +++ b/src/main/java/tng/trustnetwork/keydistribution/model/EcPublicKeyJwk.java @@ -0,0 +1,37 @@ +package tng.trustnetwork.keydistribution.model; + +import com.fasterxml.jackson.annotation.JsonEnumDefaultValue; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@JsonInclude(JsonInclude.Include.NON_NULL) +public class EcPublicKeyJwk extends PublicKeyJwk { + + private Curve crv; + + @JsonProperty("x") + private String xvalue; + + @JsonProperty("y") + private String yvalue; + + public enum Curve { + @JsonEnumDefaultValue + UNKNOWN, + + @JsonProperty("P-256") + P256, + + @JsonProperty("P-384") + P384, + + @JsonProperty("P-521") + P521 + + } + +} diff --git a/src/main/java/tng/trustnetwork/keydistribution/model/JwkVerificationMethod.java b/src/main/java/tng/trustnetwork/keydistribution/model/JwkVerificationMethod.java new file mode 100644 index 0000000..3a67394 --- /dev/null +++ b/src/main/java/tng/trustnetwork/keydistribution/model/JwkVerificationMethod.java @@ -0,0 +1,14 @@ +package tng.trustnetwork.keydistribution.model; + +import com.fasterxml.jackson.annotation.JsonInclude; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@JsonInclude(JsonInclude.Include.NON_NULL) +public class JwkVerificationMethod extends VerificationMethod { + + private PublicKeyJwk publicKeyJwk; + +} diff --git a/src/main/java/tng/trustnetwork/keydistribution/model/Proof.java b/src/main/java/tng/trustnetwork/keydistribution/model/Proof.java index 556f7da..c959b1e 100644 --- a/src/main/java/tng/trustnetwork/keydistribution/model/Proof.java +++ b/src/main/java/tng/trustnetwork/keydistribution/model/Proof.java @@ -1,24 +1,24 @@ package tng.trustnetwork.keydistribution.model; -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; import lombok.Getter; import lombok.Setter; @Getter @Setter +@JsonInclude(JsonInclude.Include.NON_NULL) public class Proof { - @JsonIgnoreProperties(ignoreUnknown = true) private String type; - @JsonIgnoreProperties(ignoreUnknown = true) + private String created; - @JsonIgnoreProperties(ignoreUnknown = true) + private String nonce; - @JsonIgnoreProperties(ignoreUnknown = true) + private String proofPurpose; - @JsonIgnoreProperties(ignoreUnknown = true) + private String verificationMethod; - @JsonIgnoreProperties(ignoreUnknown = true) + private String jws; } diff --git a/src/main/java/tng/trustnetwork/keydistribution/model/PublicKeyJwk.java b/src/main/java/tng/trustnetwork/keydistribution/model/PublicKeyJwk.java index 45b0438..74aaf20 100644 --- a/src/main/java/tng/trustnetwork/keydistribution/model/PublicKeyJwk.java +++ b/src/main/java/tng/trustnetwork/keydistribution/model/PublicKeyJwk.java @@ -1,26 +1,74 @@ package tng.trustnetwork.keydistribution.model; -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonSubTypes; +import com.fasterxml.jackson.annotation.JsonTypeInfo; import java.util.List; import lombok.Getter; import lombok.Setter; @Getter @Setter -public class PublicKeyJwk { +@JsonTypeInfo(property = "kty", use = JsonTypeInfo.Id.NAME) +@JsonSubTypes({ + @JsonSubTypes.Type(name = "EC", value = EcPublicKeyJwk.class), + @JsonSubTypes.Type(name = "RSA", value = RsaPublicKeyJwk.class), +}) +@JsonInclude(JsonInclude.Include.NON_NULL) +public abstract class PublicKeyJwk { - @JsonIgnoreProperties(ignoreUnknown = true) private String kty; - @JsonIgnoreProperties(ignoreUnknown = true) - private String crv; - @JsonProperty("x") - @JsonIgnoreProperties(ignoreUnknown = true) - private String xvalue; - @JsonProperty("y") - @JsonIgnoreProperties(ignoreUnknown = true) - private String yvalue; - @JsonIgnoreProperties(ignoreUnknown = true) + + private String kid; + + private String x5u; + private List x5c; + private String x5t; + + @JsonProperty("x5t#S256") + private String x5tS256; + + private Use use; + + @JsonProperty("key_ops") + private List keyOps; + + public enum KeyOps { + @JsonProperty("sign") + SIGN, + + @JsonProperty("verify") + VERIFY, + + @JsonProperty("encrypt") + ENCRYPT, + + @JsonProperty("decrypt") + DECRYPT, + + @JsonProperty("wrapKey") + WRAP_KEY, + + @JsonProperty("unwrapKey") + UNWRAP_KEY, + + @JsonProperty("deriveKey") + DERIVE_KEY, + + @JsonProperty("deriveBits") + DERIVE_BITS + + } + + public enum Use { + @JsonProperty("sig") + SIGNATURE, + + @JsonProperty("enc") + ENCRYPTION + } + } diff --git a/src/main/java/tng/trustnetwork/keydistribution/model/ResolvedKey.java b/src/main/java/tng/trustnetwork/keydistribution/model/ResolvedKey.java deleted file mode 100644 index 8143924..0000000 --- a/src/main/java/tng/trustnetwork/keydistribution/model/ResolvedKey.java +++ /dev/null @@ -1,21 +0,0 @@ -package tng.trustnetwork.keydistribution.model; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import lombok.Getter; -import lombok.Setter; - - -@Getter -@Setter -public class ResolvedKey { - - @JsonIgnoreProperties(ignoreUnknown = true) - private String type; - @JsonIgnoreProperties(ignoreUnknown = true) - private String id; - @JsonIgnoreProperties(ignoreUnknown = true) - private String controller; - @JsonIgnoreProperties(ignoreUnknown = true) - private PublicKeyJwk publicKeyJwk; - -} diff --git a/src/main/java/tng/trustnetwork/keydistribution/model/RsaPublicKeyJwk.java b/src/main/java/tng/trustnetwork/keydistribution/model/RsaPublicKeyJwk.java new file mode 100644 index 0000000..1b80591 --- /dev/null +++ b/src/main/java/tng/trustnetwork/keydistribution/model/RsaPublicKeyJwk.java @@ -0,0 +1,19 @@ +package tng.trustnetwork.keydistribution.model; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@JsonInclude(JsonInclude.Include.NON_NULL) +public class RsaPublicKeyJwk extends PublicKeyJwk { + + @JsonProperty("n") + private String nvalue; + + @JsonProperty("e") + private String evalue; + +} diff --git a/src/main/java/tng/trustnetwork/keydistribution/model/StringOrObject.java b/src/main/java/tng/trustnetwork/keydistribution/model/StringOrObject.java new file mode 100644 index 0000000..59b90fc --- /dev/null +++ b/src/main/java/tng/trustnetwork/keydistribution/model/StringOrObject.java @@ -0,0 +1,17 @@ +package tng.trustnetwork.keydistribution.model; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@AllArgsConstructor +@JsonDeserialize(using = StringOrObjectDeserializer.class) +public class StringOrObject { + + private T objectValue; + + private String stringValue; +} diff --git a/src/main/java/tng/trustnetwork/keydistribution/model/StringOrObjectDeserializer.java b/src/main/java/tng/trustnetwork/keydistribution/model/StringOrObjectDeserializer.java new file mode 100644 index 0000000..b5775ab --- /dev/null +++ b/src/main/java/tng/trustnetwork/keydistribution/model/StringOrObjectDeserializer.java @@ -0,0 +1,44 @@ +package tng.trustnetwork.keydistribution.model; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.BeanProperty; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JavaType; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.deser.ContextualDeserializer; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.fasterxml.jackson.databind.node.TextNode; +import java.io.IOException; + +//@RequiredArgsConstructor +public class StringOrObjectDeserializer extends JsonDeserializer> implements ContextualDeserializer { + + private JavaType type; + + //private final ObjectMapper objectMapper; + + @Override + public JsonDeserializer createContextual(DeserializationContext context, BeanProperty property) { + + this.type = property.getType().containedType(0).containedType(0); + return this; + } + + @Override + public StringOrObject deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) + throws IOException { + + JsonNode jsonNode = jsonParser.getCodec().readTree(jsonParser); + + if (jsonNode instanceof TextNode textNode) { + + return new StringOrObject<>(null, textNode.textValue()); + } else if (jsonNode instanceof ObjectNode objectNode) { + + return new StringOrObject<>(deserializationContext.readTreeAsValue(objectNode, type), null); + } else { + return null; + } + } +} diff --git a/src/main/java/tng/trustnetwork/keydistribution/model/VerificationMethod.java b/src/main/java/tng/trustnetwork/keydistribution/model/VerificationMethod.java index 9f72641..e5590e9 100644 --- a/src/main/java/tng/trustnetwork/keydistribution/model/VerificationMethod.java +++ b/src/main/java/tng/trustnetwork/keydistribution/model/VerificationMethod.java @@ -1,20 +1,27 @@ package tng.trustnetwork.keydistribution.model; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonSubTypes; +import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import java.util.List; import lombok.Getter; import lombok.Setter; +@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type") +@JsonSubTypes({ + @JsonSubTypes.Type(value = JwkVerificationMethod.class, name = "JsonWebKey2020") +}) @Getter @Setter -@JsonDeserialize(using = VerificationMethodDeserializer.class) -public class VerificationMethod { +@JsonInclude(JsonInclude.Include.NON_NULL) +public abstract class VerificationMethod { - private List resolvedKeys; - private List unResolvedKeys; + private String id; - public VerificationMethod() { + private String controller; + + private String type; - } } diff --git a/src/main/java/tng/trustnetwork/keydistribution/model/VerificationMethodDeserializer.java b/src/main/java/tng/trustnetwork/keydistribution/model/VerificationMethodDeserializer.java deleted file mode 100644 index 364f875..0000000 --- a/src/main/java/tng/trustnetwork/keydistribution/model/VerificationMethodDeserializer.java +++ /dev/null @@ -1,55 +0,0 @@ -package tng.trustnetwork.keydistribution.model; - -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.databind.DeserializationContext; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.deser.std.StdDeserializer; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -public class VerificationMethodDeserializer extends StdDeserializer { - - public VerificationMethodDeserializer() { - - this(null); - } - - protected VerificationMethodDeserializer(Class vc) { - - super(vc); - } - - @Override - public VerificationMethod deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { - - JsonNode node = p.getCodec().readTree(p); - - ObjectMapper mapper = new ObjectMapper(); - - VerificationMethod verificationMethod = new VerificationMethod(); - List resolvedKeys = new ArrayList<>(); - List unResolvedKeys = new ArrayList<>(); - - if (node.isArray()) { - for (int i = 0; i <= node.size() - 1; i++) { - JsonNode chileNode = node.get(i); - Iterator> fields = chileNode.fields(); - - if (fields.hasNext()) { - ResolvedKey resolvedKey = mapper.readValue(chileNode.toString(), ResolvedKey.class); - resolvedKeys.add(resolvedKey); - } else { - unResolvedKeys.add(chileNode.toString()); - } - } - verificationMethod.setResolvedKeys(resolvedKeys); - verificationMethod.setUnResolvedKeys(unResolvedKeys); - } - return verificationMethod; - } - -} diff --git a/src/main/java/tng/trustnetwork/keydistribution/model/VerificationMethodModel.java b/src/main/java/tng/trustnetwork/keydistribution/model/VerificationMethodModel.java new file mode 100644 index 0000000..d7ad453 --- /dev/null +++ b/src/main/java/tng/trustnetwork/keydistribution/model/VerificationMethodModel.java @@ -0,0 +1,25 @@ +package tng.trustnetwork.keydistribution.model; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonSubTypes; +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import lombok.Getter; +import lombok.Setter; + + +@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type") +@JsonSubTypes({ + @JsonSubTypes.Type(value = JwkVerificationMethod.class, name = "JsonWebKey2020") +}) +@Getter +@Setter +@JsonInclude(JsonInclude.Include.NON_NULL) +public abstract class VerificationMethodModel { + + private String id; + + private String controller; + + private String type; + +} diff --git a/src/main/java/tng/trustnetwork/keydistribution/model/VerificationMethodReference.java b/src/main/java/tng/trustnetwork/keydistribution/model/VerificationMethodReference.java new file mode 100644 index 0000000..5783ead --- /dev/null +++ b/src/main/java/tng/trustnetwork/keydistribution/model/VerificationMethodReference.java @@ -0,0 +1,16 @@ +package tng.trustnetwork.keydistribution.model; + +import com.fasterxml.jackson.annotation.JsonInclude; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@AllArgsConstructor +@JsonInclude(JsonInclude.Include.NON_NULL) +public class VerificationMethodReference extends DidContext { + + private String reference; + +} diff --git a/src/main/java/tng/trustnetwork/keydistribution/repository/DecentralizedIdentifierRepository.java b/src/main/java/tng/trustnetwork/keydistribution/repository/DecentralizedIdentifierRepository.java new file mode 100644 index 0000000..ca9d120 --- /dev/null +++ b/src/main/java/tng/trustnetwork/keydistribution/repository/DecentralizedIdentifierRepository.java @@ -0,0 +1,7 @@ +package tng.trustnetwork.keydistribution.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import tng.trustnetwork.keydistribution.entity.DecentralizedIdentifierEntity; + +public interface DecentralizedIdentifierRepository extends JpaRepository { +} diff --git a/src/main/java/tng/trustnetwork/keydistribution/repository/PublicKeyJwkRepository.java b/src/main/java/tng/trustnetwork/keydistribution/repository/PublicKeyJwkRepository.java new file mode 100644 index 0000000..b2240f7 --- /dev/null +++ b/src/main/java/tng/trustnetwork/keydistribution/repository/PublicKeyJwkRepository.java @@ -0,0 +1,7 @@ +package tng.trustnetwork.keydistribution.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import tng.trustnetwork.keydistribution.entity.PublicKeyJwkEntity; + +public interface PublicKeyJwkRepository extends JpaRepository { +} diff --git a/src/main/java/tng/trustnetwork/keydistribution/repository/TrustedIssuerRepository.java b/src/main/java/tng/trustnetwork/keydistribution/repository/TrustedIssuerRepository.java index c8e76a5..a612b98 100644 --- a/src/main/java/tng/trustnetwork/keydistribution/repository/TrustedIssuerRepository.java +++ b/src/main/java/tng/trustnetwork/keydistribution/repository/TrustedIssuerRepository.java @@ -24,7 +24,7 @@ import org.springframework.data.jpa.repository.JpaRepository; import tng.trustnetwork.keydistribution.entity.TrustedIssuerEntity; -public interface TrustedIssuerRepository extends JpaRepository { +public interface TrustedIssuerRepository extends JpaRepository { void deleteAllByEtag(String etag); diff --git a/src/main/java/tng/trustnetwork/keydistribution/repository/VerificationMethodRepository.java b/src/main/java/tng/trustnetwork/keydistribution/repository/VerificationMethodRepository.java new file mode 100644 index 0000000..9aa01fe --- /dev/null +++ b/src/main/java/tng/trustnetwork/keydistribution/repository/VerificationMethodRepository.java @@ -0,0 +1,7 @@ +package tng.trustnetwork.keydistribution.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import tng.trustnetwork.keydistribution.entity.VerificationMethodEntity; + +public interface VerificationMethodRepository extends JpaRepository { +} diff --git a/src/main/java/tng/trustnetwork/keydistribution/restapi/controller/UniversalResolverController.java b/src/main/java/tng/trustnetwork/keydistribution/restapi/controller/UniversalResolverController.java deleted file mode 100644 index 4c1e241..0000000 --- a/src/main/java/tng/trustnetwork/keydistribution/restapi/controller/UniversalResolverController.java +++ /dev/null @@ -1,34 +0,0 @@ -package tng.trustnetwork.keydistribution.restapi.controller; - -import io.swagger.v3.oas.annotations.tags.Tag; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RestController; -import tng.trustnetwork.keydistribution.model.DidDocumentUnmarshal; -import tng.trustnetwork.keydistribution.service.UniversalResolverService; - -@RestController -public class UniversalResolverController { - - @Autowired - private UniversalResolverService urService; - - /** - * Fetches DID document. - * - * @param didKey key id of the did document - * @return ResponseEntity as http response - */ - @GetMapping(path = "/getDID/{didKey}", produces = MediaType.APPLICATION_JSON_VALUE) - @Tag(name = "Temporary Testing API") - public ResponseEntity getDidDocument(@PathVariable String didKey) { - - DidDocumentUnmarshal didDocumentUnmarshal = urService.universalResolverApiCall(didKey); - return ResponseEntity.ok(didDocumentUnmarshal); - - } - -} diff --git a/src/main/java/tng/trustnetwork/keydistribution/service/DecentralizedIdentifierService.java b/src/main/java/tng/trustnetwork/keydistribution/service/DecentralizedIdentifierService.java new file mode 100644 index 0000000..f595304 --- /dev/null +++ b/src/main/java/tng/trustnetwork/keydistribution/service/DecentralizedIdentifierService.java @@ -0,0 +1,51 @@ +package tng.trustnetwork.keydistribution.service; + +import java.util.Objects; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import tng.trustnetwork.keydistribution.entity.DecentralizedIdentifierEntity; +import tng.trustnetwork.keydistribution.mapper.DidMapper; +import tng.trustnetwork.keydistribution.model.DidDocument; +import tng.trustnetwork.keydistribution.repository.DecentralizedIdentifierRepository; +import tng.trustnetwork.keydistribution.repository.PublicKeyJwkRepository; +import tng.trustnetwork.keydistribution.repository.VerificationMethodRepository; + +@Slf4j +@Service +@RequiredArgsConstructor +public class DecentralizedIdentifierService { + + private final DecentralizedIdentifierRepository decentralizedIdentifierRepository; + + private final VerificationMethodRepository verificationMethodRepository; + + private final PublicKeyJwkRepository publicKeyJwkRepository; + + private final DidMapper didMapper; + + /** + * Update list of stored DID with given Document. + * + * @param didDocument Parsed DIDDocument + * @param raw RAW-JSON-Value of the DID Document. This will be stored to allow validation of LD-Proof later. + */ + @Transactional + public void updateDecentralizedIdentifierList(DidDocument didDocument, String raw) { + + DecentralizedIdentifierEntity didEntity = didMapper.toEntity(didDocument, raw); + decentralizedIdentifierRepository.save(didEntity); + + didEntity.getVerificationMethods() + .stream() + .filter(Objects::nonNull) + .forEach(verificationMethod -> { + + verificationMethod.setParentDocument(didEntity); + publicKeyJwkRepository.save(verificationMethod.getPublicKeyJwk()); + verificationMethodRepository.save(verificationMethod); + }); + } + +} diff --git a/src/main/java/tng/trustnetwork/keydistribution/service/SignerCertificateDownloadService.java b/src/main/java/tng/trustnetwork/keydistribution/service/SignerCertificateDownloadService.java index 650c9c8..8cd1792 100644 --- a/src/main/java/tng/trustnetwork/keydistribution/service/SignerCertificateDownloadService.java +++ b/src/main/java/tng/trustnetwork/keydistribution/service/SignerCertificateDownloadService.java @@ -20,10 +20,40 @@ package tng.trustnetwork.keydistribution.service; -public interface SignerCertificateDownloadService { +import eu.europa.ec.dgc.gateway.connector.DgcGatewayDownloadConnector; +import eu.europa.ec.dgc.gateway.connector.model.TrustListItem; +import java.util.List; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import net.javacrumbs.shedlock.spring.annotation.SchedulerLock; +import org.springframework.context.annotation.Profile; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +/** + * A service to download the signer certificates from the digital green certificate gateway. + */ +@Slf4j +@RequiredArgsConstructor +@Component +public class SignerCertificateDownloadService { + + private final DgcGatewayDownloadConnector dgcGatewayConnector; + private final SignerInformationService signerInformationService; /** - * Synchronises the signer certificates with the gateway. + * Download TrustedCertificates from Gateway. */ - void downloadCertificates(); + @Scheduled(fixedDelayString = "${dgc.certificatesDownloader.timeInterval}") + @SchedulerLock(name = "SignerCertificateDownloadService_downloadCertificates", lockAtLeastFor = "PT0S", + lockAtMostFor = "${dgc.certificatesDownloader.lockLimit}") + public void downloadCertificates() { + log.info("Certificates download started"); + + List trustedCerts = dgcGatewayConnector.getTrustedCertificates(); + + signerInformationService.updateTrustedCertsList(trustedCerts); + + log.info("Certificates download finished"); + } } diff --git a/src/main/java/tng/trustnetwork/keydistribution/service/SignerCertificateDownloadServiceImpl.java b/src/main/java/tng/trustnetwork/keydistribution/service/SignerCertificateDownloadServiceImpl.java deleted file mode 100644 index e885f28..0000000 --- a/src/main/java/tng/trustnetwork/keydistribution/service/SignerCertificateDownloadServiceImpl.java +++ /dev/null @@ -1,60 +0,0 @@ -/*- - * ---license-start - * WorldHealthOrganization / tng-key-distribution - * --- - * Copyright (C) 2021 T-Systems International GmbH and all other contributors - * --- - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ---license-end - */ - -package tng.trustnetwork.keydistribution.service; - -import eu.europa.ec.dgc.gateway.connector.DgcGatewayDownloadConnector; -import eu.europa.ec.dgc.gateway.connector.model.TrustListItem; -import java.util.List; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import net.javacrumbs.shedlock.spring.annotation.SchedulerLock; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.context.annotation.Profile; -import org.springframework.scheduling.annotation.Scheduled; -import org.springframework.stereotype.Component; - -/** - * A service to download the signer certificates from the digital green certificate gateway. - */ -@Slf4j -@RequiredArgsConstructor -@Component -@Profile("!btp") -//@ConditionalOnProperty("dgc.gateway.connector.enabled") -public class SignerCertificateDownloadServiceImpl implements SignerCertificateDownloadService { - - private final DgcGatewayDownloadConnector dgcGatewayConnector; - private final SignerInformationService signerInformationService; - - @Override - @Scheduled(fixedDelayString = "${dgc.certificatesDownloader.timeInterval}") - @SchedulerLock(name = "SignerCertificateDownloadService_downloadCertificates", lockAtLeastFor = "PT0S", - lockAtMostFor = "${dgc.certificatesDownloader.lockLimit}") - public void downloadCertificates() { - log.info("Certificates download started"); - - List trustedCerts = dgcGatewayConnector.getTrustedCertificates(); - - signerInformationService.updateTrustedCertsList(trustedCerts); - - log.info("Certificates download finished"); - } -} diff --git a/src/main/java/tng/trustnetwork/keydistribution/service/TrustedIssuerDownloadService.java b/src/main/java/tng/trustnetwork/keydistribution/service/TrustedIssuerDownloadService.java index 507636c..c40ead7 100644 --- a/src/main/java/tng/trustnetwork/keydistribution/service/TrustedIssuerDownloadService.java +++ b/src/main/java/tng/trustnetwork/keydistribution/service/TrustedIssuerDownloadService.java @@ -1,10 +1,67 @@ +/*- + * ---license-start + * WorldHealthOrganization / tng-key-distribution + * --- + * Copyright (C) 2021 T-Systems International GmbH and all other contributors + * --- + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ---license-end + */ + package tng.trustnetwork.keydistribution.service; +import eu.europa.ec.dgc.gateway.connector.DgcGatewayTrustedIssuerDownloadConnector; +import eu.europa.ec.dgc.gateway.connector.model.TrustedIssuer; +import java.util.ArrayList; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import net.javacrumbs.shedlock.spring.annotation.SchedulerLock; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; +import tng.trustnetwork.keydistribution.config.KdsConfigProperties; + +/** + * A service to download the signer certificates from the digital green certificate gateway. + */ +@Slf4j +@RequiredArgsConstructor +@Component +@ConditionalOnProperty("dgc.trustedIssuerDownloader.enabled") +public class TrustedIssuerDownloadService { + + private final DgcGatewayTrustedIssuerDownloadConnector downloadConnector; + + private final TrustedIssuerService trustedIssuerService; -public interface TrustedIssuerDownloadService { + private final KdsConfigProperties configProperties; /** - * Synchronises the trusted issuers with the gateway. + * Download TrustedIssuers and Resolve DID Documents. */ - void downloadTrustedIssuers(); + @Scheduled(fixedDelayString = "${dgc.trustedIssuerDownloader.timeInterval}") + @SchedulerLock(name = "TrustedIssuerDownloadService_downloadTrustedIssuers", lockAtLeastFor = "PT0S", + lockAtMostFor = "${dgc.trustedIssuerDownloader.lockLimit}") + public void downloadTrustedIssuers() { + + log.info("Trusted issuers download started"); + + ArrayList trustedIssuers = new ArrayList<>(); + trustedIssuers.addAll(configProperties.getStaticTrustedIssuer()); + trustedIssuers.addAll(downloadConnector.getTrustedIssuers()); + + trustedIssuerService.updateTrustedIssuersList(trustedIssuers); + + log.info("Trusted issuers download finished. {} issuers downloaded.", trustedIssuers.size()); + } } diff --git a/src/main/java/tng/trustnetwork/keydistribution/service/TrustedIssuerDownloadServiceImpl.java b/src/main/java/tng/trustnetwork/keydistribution/service/TrustedIssuerDownloadServiceImpl.java deleted file mode 100644 index 07f187b..0000000 --- a/src/main/java/tng/trustnetwork/keydistribution/service/TrustedIssuerDownloadServiceImpl.java +++ /dev/null @@ -1,60 +0,0 @@ -/*- - * ---license-start - * WorldHealthOrganization / tng-key-distribution - * --- - * Copyright (C) 2021 T-Systems International GmbH and all other contributors - * --- - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ---license-end - */ - -package tng.trustnetwork.keydistribution.service; - -import eu.europa.ec.dgc.gateway.connector.DgcGatewayTrustedIssuerDownloadConnector; -import eu.europa.ec.dgc.gateway.connector.model.TrustedIssuer; -import java.util.List; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import net.javacrumbs.shedlock.spring.annotation.SchedulerLock; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.context.annotation.Profile; -import org.springframework.scheduling.annotation.Scheduled; -import org.springframework.stereotype.Component; - -/** - * A service to download the signer certificates from the digital green certificate gateway. - */ -@Slf4j -@RequiredArgsConstructor -@Component -@Profile("!btp") -@ConditionalOnProperty("dgc.trustedIssuerDownloader.enabled") -public class TrustedIssuerDownloadServiceImpl implements TrustedIssuerDownloadService { - - private final DgcGatewayTrustedIssuerDownloadConnector downloadConnector; - private final TrustedIssuerService trustedIssuerService; - - @Override - @Scheduled(fixedDelayString = "${dgc.trustedIssuerDownloader.timeInterval}") - @SchedulerLock(name = "TrustedIssuerDownloadService_downloadTrustedIssuers", lockAtLeastFor = "PT0S", - lockAtMostFor = "${dgc.trustedIssuerDownloader.lockLimit}") - public void downloadTrustedIssuers() { - log.info("Trusted issuers download started"); - - List trustedIssuers = downloadConnector.getTrustedIssuers(); - - trustedIssuerService.updateTrustedIssuersList(trustedIssuers); - - log.info("Trusted issuers download finished. {} issuers downloaded.", trustedIssuers.size()); - } -} diff --git a/src/main/java/tng/trustnetwork/keydistribution/service/TrustedIssuerService.java b/src/main/java/tng/trustnetwork/keydistribution/service/TrustedIssuerService.java index 797e1aa..9c61a28 100644 --- a/src/main/java/tng/trustnetwork/keydistribution/service/TrustedIssuerService.java +++ b/src/main/java/tng/trustnetwork/keydistribution/service/TrustedIssuerService.java @@ -20,6 +20,7 @@ package tng.trustnetwork.keydistribution.service; +import com.fasterxml.jackson.core.JsonProcessingException; import eu.europa.ec.dgc.gateway.connector.model.TrustedIssuer; import java.util.ArrayList; import java.util.List; @@ -43,12 +44,18 @@ public class TrustedIssuerService { private final TrustedIssuerRepository trustedIssuerRepository; + private final UniversalResolverService urService; + + private final DecentralizedIdentifierService decentralizedIdentifierService; + /** * Get the current etag. + * * @return the current etag */ public String getEtag() { + String etag = infoService.getValueForKey(InfoService.CURRENT_ETAG); if (etag == null) { etag = ""; @@ -62,6 +69,7 @@ public String getEtag() { * @return List holding the found trusted issuers. */ public List getAllIssuers(String etag) { + return trustedIssuerRepository.findAllByEtag(etag); } @@ -69,17 +77,29 @@ public List getAllIssuers(String etag) { * Method to synchronise the issuers in the db with the given List of trusted issuers. * * @param trustedIssuers defines the list of trusted issuers. - * */ @Transactional public void updateTrustedIssuersList(List trustedIssuers) { + String newEtag = UUID.randomUUID().toString(); List trustedIssuerEntities = new ArrayList<>(); - for (TrustedIssuer trustedIssuer : trustedIssuers) { + trustedIssuerEntities.add(getTrustedIssuerEntity(newEtag, trustedIssuer)); + + if (TrustedIssuer.UrlType.DID == trustedIssuer.getType()) { + try { + UniversalResolverService.DidDocumentWithRawResponse didDocument = + urService.universalResolverApiCall(trustedIssuer.getUrl()); + + decentralizedIdentifierService.updateDecentralizedIdentifierList(didDocument.didDocument(), + didDocument.raw()); + } catch (JsonProcessingException e) { + log.error("Failed to download/parse DID {}", trustedIssuer.getUrl()); + } + } } trustedIssuerRepository.saveAll(trustedIssuerEntities); @@ -92,12 +112,14 @@ public void updateTrustedIssuersList(List trustedIssuers) { } private TrustedIssuerEntity getTrustedIssuerEntity(String etag, TrustedIssuer trustedIssuer) { + TrustedIssuerEntity entity = issuerMapper.trustedIssuerToTrustedIssuerEntity(trustedIssuer); entity.setEtag(etag); return entity; } private void cleanupData(String etag) { + trustedIssuerRepository.deleteAllByEtag(etag); } diff --git a/src/main/java/tng/trustnetwork/keydistribution/service/UniversalResolverService.java b/src/main/java/tng/trustnetwork/keydistribution/service/UniversalResolverService.java index fbbcc4e..59e1ede 100644 --- a/src/main/java/tng/trustnetwork/keydistribution/service/UniversalResolverService.java +++ b/src/main/java/tng/trustnetwork/keydistribution/service/UniversalResolverService.java @@ -1,9 +1,42 @@ package tng.trustnetwork.keydistribution.service; -import tng.trustnetwork.keydistribution.model.DidDocumentUnmarshal; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import tng.trustnetwork.keydistribution.clients.UniversalResolverClient; +import tng.trustnetwork.keydistribution.model.DidDocument; -public interface UniversalResolverService { - public DidDocumentUnmarshal universalResolverApiCall(String didKey); +@Slf4j +@Service +@RequiredArgsConstructor +public class UniversalResolverService { + + private final UniversalResolverClient universalResolverClient; + + private final ObjectMapper objectMapper; + + /** + * Try to resolve DID Document by ID at UniversalResolverService. + * + * @param didId Identifier of document to resolve + * @return Parsed and RAW DID Document + * @throws JsonProcessingException when parsing of downloaded document failed. + */ + public DidDocumentWithRawResponse universalResolverApiCall(String didId) throws JsonProcessingException { + + String rawResponse = universalResolverClient.getDidDocument(didId); + DidDocument didDocument = objectMapper.readValue(rawResponse, DidDocument.class); + + return new DidDocumentWithRawResponse(didDocument, rawResponse); + } + + public record DidDocumentWithRawResponse( + DidDocument didDocument, + + String raw) { + } } diff --git a/src/main/java/tng/trustnetwork/keydistribution/service/UniversalResolverServiceImpl.java b/src/main/java/tng/trustnetwork/keydistribution/service/UniversalResolverServiceImpl.java deleted file mode 100644 index 820a9e6..0000000 --- a/src/main/java/tng/trustnetwork/keydistribution/service/UniversalResolverServiceImpl.java +++ /dev/null @@ -1,51 +0,0 @@ -package tng.trustnetwork.keydistribution.service; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import tng.trustnetwork.keydistribution.clients.UniversalResolverClient; -import tng.trustnetwork.keydistribution.model.DidDocument; -import tng.trustnetwork.keydistribution.model.DidDocumentUnmarshal; -import tng.trustnetwork.keydistribution.model.VerificationMethod; - - -@Slf4j -@Service -public class UniversalResolverServiceImpl implements UniversalResolverService { - - @Autowired - private UniversalResolverClient universalResolverClient; - - @Override - public DidDocumentUnmarshal universalResolverApiCall(String didKey) { - - DidDocument did = universalResolverClient.getDidDocument(didKey); - - if (null != did) { - ObjectMapper mapper = new ObjectMapper(); - - try { - - String verificationMethodStr = mapper.writeValueAsString(did.getVerificationMethod()); - VerificationMethod verificationMethod = - mapper.readValue(verificationMethodStr, VerificationMethod.class); - - DidDocumentUnmarshal didDocumentUnmarshal = new DidDocumentUnmarshal(); - didDocumentUnmarshal.setContext(did.getContext()); - didDocumentUnmarshal.setController(did.getController()); - didDocumentUnmarshal.setId(did.getId()); - didDocumentUnmarshal.setProof(did.getProof()); - didDocumentUnmarshal.setVerificationMethod(verificationMethod); - return didDocumentUnmarshal; - - } catch (JsonProcessingException ex) { - log.error("Issue parsing DID document", ex); - } - } - - return null; - } - -} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 1f6352e..87b4c73 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -8,6 +8,10 @@ spring: url: jdbc:h2:mem:dgc;DB_CLOSE_ON_EXIT=FALSE;DB_CLOSE_DELAY=-1; username: sa password: '' + jackson: + deserialization: + read-unknown-enum-values-using-default-value: true + jpa: database-platform: org.hibernate.dialect.H2Dialect hibernate: @@ -77,3 +81,9 @@ dgc: alias: ${DGC_GATEWAY_CONNECTOR_TRUSTANCHOR_ALIAS} password: ${DGC_GATEWAY_CONNECTOR_TRUSTANCHOR_PASSWORD} path: ${DGC_GATEWAY_CONNECTOR_TRUSTANCHOR_PATH} + static-trusted-issuer: + - name: WHO Trustlist (DEV) + country: WH + type: did + url: did:web:tng-cdn-dev.who.int:trustlist + signature: No-Signature # required because of DB restrictions diff --git a/src/main/resources/db/changelog.yaml b/src/main/resources/db/changelog.yaml index c002dee..5268236 100644 --- a/src/main/resources/db/changelog.yaml +++ b/src/main/resources/db/changelog.yaml @@ -7,3 +7,9 @@ databaseChangeLog: file: db/changelog/create-info-table.yaml - include: file: db/changelog/create-trusted-issuer-table.yaml + - include: + file: db/changelog/create-decentralized-identifier-table.yaml + - include: + file: db/changelog/create-public-key-jwk-table.yaml + - include: + file: db/changelog/create-verification-method-table.yaml diff --git a/src/main/resources/db/changelog/create-decentralized-identifier-table.yaml b/src/main/resources/db/changelog/create-decentralized-identifier-table.yaml new file mode 100644 index 0000000..987c95a --- /dev/null +++ b/src/main/resources/db/changelog/create-decentralized-identifier-table.yaml @@ -0,0 +1,30 @@ +databaseChangeLog: + - changeSet: + id: create-decentralized-identifier-table + author: f11h + changes: + - createTable: + tableName: decentralized_identifier + columns: + - column: + autoIncrement: true + name: id + type: bigint + constraints: + primaryKey: true + primaryKeyName: decentralized_identifier_id + nullable: false + - column: + name: created_at + type: datetime + constraints: + nullable: false + - column: + name: did_id + type: varchar(255) + constraints: + nullable: true + - column: + name: raw + type: clob + diff --git a/src/main/resources/db/changelog/create-public-key-jwk-table.yaml b/src/main/resources/db/changelog/create-public-key-jwk-table.yaml new file mode 100644 index 0000000..8be08ad --- /dev/null +++ b/src/main/resources/db/changelog/create-public-key-jwk-table.yaml @@ -0,0 +1,57 @@ +databaseChangeLog: + - changeSet: + id: create-public-key-jwk-table + author: f11h + changes: + - createTable: + tableName: public_key_jwk + columns: + - column: + autoIncrement: true + name: id + type: bigint + constraints: + primaryKey: true + primaryKeyName: public_key_jwk_id + nullable: true + - column: + name: created_at + type: datetime + constraints: + nullable: false + - column: + name: kty + type: varchar(50) + constraints: + nullable: false + - column: + name: crv + type: varchar(50) + constraints: + nullable: true + - column: + name: x + type: varchar(100) + constraints: + nullable: true + - column: + name: y + type: varchar(100) + constraints: + nullable: true + - column: + name: e + type: varchar(5000) + constraints: + nullable: true + - column: + name: n + type: varchar(5000) + constraints: + nullable: true + - column: + name: x5c + type: varchar(10000) + constraints: + nullable: true + diff --git a/src/main/resources/db/changelog/create-verification-method-table.yaml b/src/main/resources/db/changelog/create-verification-method-table.yaml new file mode 100644 index 0000000..db0d66a --- /dev/null +++ b/src/main/resources/db/changelog/create-verification-method-table.yaml @@ -0,0 +1,58 @@ +databaseChangeLog: + - changeSet: + id: create-verification-method-table + author: f11h + changes: + - createTable: + tableName: verification_method + columns: + - column: + autoIncrement: true + name: id + type: bigint + constraints: + primaryKey: true + primaryKeyName: verification_method_id + nullable: false + - column: + name: created_at + type: datetime + constraints: + nullable: false + - column: + name: vm_id + type: varchar(255) + constraints: + nullable: true + - column: + name: type + type: varchar(100) + constraints: + nullable: true + - column: + name: controller + type: varchar(255) + constraints: + nullable: true + - column: + name: parent_document_id + type: bigint + constraints: + nullable: false + - column: + name: public_key_jwk_id + type: bigint + constraints: + nullable: false + - addForeignKeyConstraint: + constraintName: fk_did_vm + referencedTableName: decentralized_identifier + referencedColumnNames: id + baseTableName: verification_method + baseColumnNames: parent_document_id + - addForeignKeyConstraint: + constraintName: fk_pk_vm + referencedTableName: public_key_jwk + referencedColumnNames: id + baseTableName: verification_method + baseColumnNames: public_key_jwk_id diff --git a/src/test/java/tng/trustnetwork/keydistribution/service/DecentralizedIdentifierServiceTest.java b/src/test/java/tng/trustnetwork/keydistribution/service/DecentralizedIdentifierServiceTest.java new file mode 100644 index 0000000..aa2d4a7 --- /dev/null +++ b/src/test/java/tng/trustnetwork/keydistribution/service/DecentralizedIdentifierServiceTest.java @@ -0,0 +1,101 @@ +package tng.trustnetwork.keydistribution.service; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import eu.europa.ec.dgc.gateway.connector.DgcGatewayDownloadConnector; +import java.util.List; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import tng.trustnetwork.keydistribution.entity.DecentralizedIdentifierEntity; +import tng.trustnetwork.keydistribution.entity.EcPublicKeyJwkEntity; +import tng.trustnetwork.keydistribution.model.DidDocument; +import tng.trustnetwork.keydistribution.repository.DecentralizedIdentifierRepository; + +@SpringBootTest +public class DecentralizedIdentifierServiceTest { + + @MockBean + DgcGatewayDownloadConnector dgcGatewayDownloadConnector; + + @Autowired + DecentralizedIdentifierRepository decentralizedIdentifierRepository; + + @Autowired + DecentralizedIdentifierService decentralizedIdentifierService; + + @Autowired + ObjectMapper objectMapper; + + private static final String testDidId = "did:web:did.actor:mike"; + + private static final String testDid = """ + { + "@context": [ + "https://www.w3.org/ns/did/v1", + { + "@base": "did:web:did.actor:mike", + "rating": "https://schema.org/Rating", + "publicAccess": "https://schema.org/publicAccess", + "additionalType": "https://schema.org/additionalType" + } + ], + "id": "did:web:did.actor:mike", + "rating": 4.5, + "publicAccess": true, + "additionalType": null, + "verificationMethod": [ + { + "id": "#g1", + "controller": "did:web:did.actor:mike", + "type": "JsonWebKey2020", + "publicKeyJwk": { + "kty": "EC", + "crv": "P-256", + "x": "xValue" + } + } + ], + "authentication": [ + "did:web:did.actor:mike#g1" + ], + "assertionMethod": [ + "did:web:did.actor:mike#g1" + ] + } + """; + + @Test + void itShouldPersistDIDsInDb() throws JsonProcessingException { + + DidDocument didDocument = objectMapper.readValue(testDid, DidDocument.class); + + decentralizedIdentifierService.updateDecentralizedIdentifierList(didDocument, testDid); + + List allDids = decentralizedIdentifierRepository.findAll(); + + Assertions.assertEquals(1, allDids.size()); + + DecentralizedIdentifierEntity storedDid = allDids.get(0); + + Assertions.assertEquals(testDidId, storedDid.getDidId()); + Assertions.assertEquals(testDid, storedDid.getRaw()); + Assertions.assertNotNull(storedDid.getCreatedAt()); + Assertions.assertEquals(1, storedDid.getVerificationMethods().size()); + Assertions.assertEquals("#g1", storedDid.getVerificationMethods().get(0).getVmId()); + Assertions.assertEquals("JsonWebKey2020", storedDid.getVerificationMethods().get(0).getType()); + Assertions.assertEquals(testDidId, storedDid.getVerificationMethods().get(0).getController()); + + Assertions.assertInstanceOf(EcPublicKeyJwkEntity.class, storedDid.getVerificationMethods().get(0).getPublicKeyJwk()); + EcPublicKeyJwkEntity ecPublicKeyJwk = + (EcPublicKeyJwkEntity) storedDid.getVerificationMethods().get(0).getPublicKeyJwk(); + Assertions.assertEquals("P256", ecPublicKeyJwk.getCrv()); + Assertions.assertEquals("xValue", ecPublicKeyJwk.getXvalue()); + + Assertions.assertEquals(storedDid, storedDid.getVerificationMethods().get(0).getParentDocument()); + + } + +} diff --git a/src/test/java/tng/trustnetwork/keydistribution/service/SignerCertificateDownloadServiceImplTest.java b/src/test/java/tng/trustnetwork/keydistribution/service/SignerCertificateDownloadServiceTest.java similarity index 94% rename from src/test/java/tng/trustnetwork/keydistribution/service/SignerCertificateDownloadServiceImplTest.java rename to src/test/java/tng/trustnetwork/keydistribution/service/SignerCertificateDownloadServiceTest.java index 5c02ebf..97ee85c 100644 --- a/src/test/java/tng/trustnetwork/keydistribution/service/SignerCertificateDownloadServiceImplTest.java +++ b/src/test/java/tng/trustnetwork/keydistribution/service/SignerCertificateDownloadServiceTest.java @@ -15,13 +15,13 @@ import org.springframework.boot.test.mock.mockito.MockBean; @SpringBootTest -class SignerCertificateDownloadServiceImplTest { +class SignerCertificateDownloadServiceTest { @MockBean DgcGatewayDownloadConnector dgcGatewayDownloadConnector; @Autowired - SignerCertificateDownloadServiceImpl signerCertificateDownloadService; + SignerCertificateDownloadService signerCertificateDownloadService; @Autowired SignerInformationRepository signerInformationRepository; diff --git a/src/test/java/tng/trustnetwork/keydistribution/service/SignerInformationServiceTest.java b/src/test/java/tng/trustnetwork/keydistribution/service/SignerInformationServiceTest.java index 1ea033a..dcaab27 100644 --- a/src/test/java/tng/trustnetwork/keydistribution/service/SignerInformationServiceTest.java +++ b/src/test/java/tng/trustnetwork/keydistribution/service/SignerInformationServiceTest.java @@ -20,14 +20,8 @@ package tng.trustnetwork.keydistribution.service; -import com.google.code.beanmatchers.BeanMatchers; import eu.europa.ec.dgc.gateway.connector.DgcGatewayDownloadConnector; import eu.europa.ec.dgc.gateway.connector.model.TrustListItem; -import tng.trustnetwork.keydistribution.dto.TrustedIssuerDto; -import tng.trustnetwork.keydistribution.entity.SignerInformationEntity; -import tng.trustnetwork.keydistribution.repository.SignerInformationRepository; -import tng.trustnetwork.keydistribution.restapi.dto.DeltaListDto; -import tng.trustnetwork.keydistribution.testdata.SignerInformationTestHelper; import java.time.ZonedDateTime; import java.util.ArrayList; import java.util.List; @@ -37,13 +31,11 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; -import static com.google.code.beanmatchers.BeanMatchers.hasValidBeanConstructor; -import static com.google.code.beanmatchers.BeanMatchers.hasValidBeanEquals; -import static com.google.code.beanmatchers.BeanMatchers.hasValidBeanHashCode; -import static com.google.code.beanmatchers.BeanMatchers.hasValidBeanToString; -import static com.google.code.beanmatchers.BeanMatchers.hasValidGettersAndSetters; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.allOf; +import tng.trustnetwork.keydistribution.dto.TrustedIssuerDto; +import tng.trustnetwork.keydistribution.entity.SignerInformationEntity; +import tng.trustnetwork.keydistribution.repository.SignerInformationRepository; +import tng.trustnetwork.keydistribution.restapi.dto.DeltaListDto; +import tng.trustnetwork.keydistribution.testdata.SignerInformationTestHelper; @SpringBootTest class SignerInformationServiceTest { @@ -197,8 +189,6 @@ void updateRepositoryWithEmptyCertList() { @Test void dataTypeTests() { - assertThat(DeltaListDto.class, allOf(hasValidBeanConstructor(), hasValidBeanEquals(), - hasValidGettersAndSetters(), hasValidBeanHashCode(), hasValidBeanToString())); List updated = new ArrayList<>(); updated.add("updated"); List deleted = new ArrayList<>(); @@ -218,12 +208,6 @@ void dataTypeTests() { Assertions.assertEquals("url",issuer.getUrl()); issuer.setUrl("newUrl"); Assertions.assertEquals("newUrl",issuer.getUrl()); - - BeanMatchers.registerValueGenerator(ZonedDateTime::now, ZonedDateTime.class); - - assertThat(TrustedIssuerDto.class, allOf(hasValidBeanConstructor(), hasValidBeanEquals(), - hasValidGettersAndSetters(), hasValidBeanHashCode(), hasValidBeanToString())); - } } diff --git a/src/test/java/tng/trustnetwork/keydistribution/service/TrustedIssuerDownloadServiceImplTest.java b/src/test/java/tng/trustnetwork/keydistribution/service/TrustedIssuerDownloadServiceTest.java similarity index 96% rename from src/test/java/tng/trustnetwork/keydistribution/service/TrustedIssuerDownloadServiceImplTest.java rename to src/test/java/tng/trustnetwork/keydistribution/service/TrustedIssuerDownloadServiceTest.java index cc1c449..74c3242 100644 --- a/src/test/java/tng/trustnetwork/keydistribution/service/TrustedIssuerDownloadServiceImplTest.java +++ b/src/test/java/tng/trustnetwork/keydistribution/service/TrustedIssuerDownloadServiceTest.java @@ -18,7 +18,7 @@ @SpringBootTest @TestPropertySource(properties = {"dgc.trustedIssuerDownloader.enabled=true"}) -class TrustedIssuerDownloadServiceImplTest { +class TrustedIssuerDownloadServiceTest { @MockBean DgcGatewayDownloadConnector dgcGatewayDownloadConnectorMock; @@ -28,7 +28,7 @@ class TrustedIssuerDownloadServiceImplTest { @Autowired - TrustedIssuerDownloadServiceImpl trustedIssuerDownloadService; + TrustedIssuerDownloadService trustedIssuerDownloadService; @Autowired TrustedIssuerRepository trustedIssuerRepository; diff --git a/src/test/java/tng/trustnetwork/keydistribution/service/UniversalResolverServiceImplTest.java b/src/test/java/tng/trustnetwork/keydistribution/service/UniversalResolverServiceImplTest.java deleted file mode 100644 index 6218f91..0000000 --- a/src/test/java/tng/trustnetwork/keydistribution/service/UniversalResolverServiceImplTest.java +++ /dev/null @@ -1,51 +0,0 @@ -package tng.trustnetwork.keydistribution.service; - -import eu.europa.ec.dgc.gateway.connector.DgcGatewayDownloadConnector; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.mockito.Mockito; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import tng.trustnetwork.keydistribution.clients.UniversalResolverClient; -import tng.trustnetwork.keydistribution.model.DidDocument; -import tng.trustnetwork.keydistribution.model.DidDocumentUnmarshal; - -@SpringBootTest -class UniversalResolverServiceImplTest { - - @MockBean - private UniversalResolverClient universalResolverClient; - - @Autowired - private UniversalResolverService universalResolverService; - - @MockBean - DgcGatewayDownloadConnector dgcGatewayDownloadConnector; - - @Autowired - SignerCertificateDownloadServiceImpl signerCertificateDownloadService; - - @Test - void resolveDIDDocumentNotNull() { - - DidDocument didDocument = new DidDocument(); - Mockito.when(universalResolverClient.getDidDocument("did:web:tng-cdn-dev.who.int:trustlist")) - .thenReturn(didDocument); - DidDocumentUnmarshal didDocumentUnmarshal = - universalResolverService.universalResolverApiCall("did:web:tng-cdn-dev.who.int:trustlist"); - Assertions.assertNotNull(didDocumentUnmarshal); - - } - - @Test - void resolveDIDDocumentNull() { - - DidDocument didDocument = new DidDocument(); - Mockito.when(universalResolverClient.getDidDocument("test")).thenReturn(null); - DidDocumentUnmarshal didDocumentUnmarshal = universalResolverService.universalResolverApiCall("test"); - Assertions.assertNull(didDocumentUnmarshal); - - } - -} diff --git a/src/test/java/tng/trustnetwork/keydistribution/service/UniversalResolverServiceTest.java b/src/test/java/tng/trustnetwork/keydistribution/service/UniversalResolverServiceTest.java new file mode 100644 index 0000000..32552ee --- /dev/null +++ b/src/test/java/tng/trustnetwork/keydistribution/service/UniversalResolverServiceTest.java @@ -0,0 +1,101 @@ +package tng.trustnetwork.keydistribution.service; + +import static org.mockito.Mockito.when; + +import com.fasterxml.jackson.core.JsonProcessingException; +import eu.europa.ec.dgc.gateway.connector.DgcGatewayDownloadConnector; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import tng.trustnetwork.keydistribution.clients.UniversalResolverClient; +import tng.trustnetwork.keydistribution.model.EcPublicKeyJwk; +import tng.trustnetwork.keydistribution.model.JwkVerificationMethod; + +@SpringBootTest +class UniversalResolverServiceTest { + + @MockBean + DgcGatewayDownloadConnector dgcGatewayDownloadConnector; + + @MockBean + UniversalResolverClient universalResolverClientMock; + + @Autowired + UniversalResolverService universalResolverService; + + private static final String testDidId = "did:web:did.actor:mike"; + + private static final String testDid = """ + { + "@context": [ + "https://www.w3.org/ns/did/v1", + { + "@base": "did:web:did.actor:mike", + "rating": "https://schema.org/Rating", + "publicAccess": "https://schema.org/publicAccess", + "additionalType": "https://schema.org/additionalType" + } + ], + "id": "did:web:did.actor:mike", + "rating": 4.5, + "publicAccess": true, + "additionalType": null, + "verificationMethod": [ + { + "id": "#g1", + "controller": "did:web:did.actor:mike", + "type": "JsonWebKey2020", + "publicKeyJwk": { + "kty": "EC", + "crv": "P-256", + "x": "xValue" + } + } + ], + "authentication": [ + "did:web:did.actor:mike#g1" + ], + "assertionMethod": [ + "did:web:did.actor:mike#g1" + ] + } + """; + + @Test + void itShouldReturnParsedDidDocument() throws JsonProcessingException { + + when(universalResolverClientMock.getDidDocument(testDidId)) + .thenReturn(testDid); + + UniversalResolverService.DidDocumentWithRawResponse response = + universalResolverService.universalResolverApiCall(testDidId); + + Assertions.assertEquals(testDid, response.raw()); + Assertions.assertEquals(testDidId, response.didDocument().getId()); + Assertions.assertEquals(1, response.didDocument().getVerificationMethod().size()); + Assertions.assertEquals(testDidId, response.didDocument().getVerificationMethod().get(0).getObjectValue().getController()); + Assertions.assertEquals("#g1", response.didDocument().getVerificationMethod().get(0).getObjectValue().getId()); + + Assertions.assertInstanceOf(JwkVerificationMethod.class, response.didDocument().getVerificationMethod().get(0).getObjectValue()); + JwkVerificationMethod jwkVerificationMethod = + (JwkVerificationMethod) response.didDocument().getVerificationMethod().get(0).getObjectValue(); + + Assertions.assertInstanceOf(EcPublicKeyJwk.class, jwkVerificationMethod.getPublicKeyJwk()); + EcPublicKeyJwk ecPublicKeyJwk = (EcPublicKeyJwk) jwkVerificationMethod.getPublicKeyJwk(); + + Assertions.assertEquals(EcPublicKeyJwk.Curve.P256 , ecPublicKeyJwk.getCrv()); + Assertions.assertEquals("xValue", ecPublicKeyJwk.getXvalue()); + } + + @Test + void itShouldThrowAnExceptionIfJsonIsInvalid() { + + when(universalResolverClientMock.getDidDocument(testDidId)) + .thenReturn("noValidJson"); + + Assertions.assertThrows(JsonProcessingException.class, () -> + universalResolverService.universalResolverApiCall(testDidId)); + } +} diff --git a/src/test/resources/application.yml b/src/test/resources/application.yml index 579964a..c37e32f 100644 --- a/src/test/resources/application.yml +++ b/src/test/resources/application.yml @@ -9,6 +9,9 @@ spring: url: jdbc:h2:mem:dgc;DB_CLOSE_ON_EXIT=FALSE;DB_CLOSE_DELAY=-1; username: sa password: '' + jackson: + deserialization: + read-unknown-enum-values-using-default-value: true jpa: database-platform: org.hibernate.dialect.H2Dialect hibernate: