Skip to content
This repository has been archived by the owner on Feb 13, 2024. It is now read-only.

Commit

Permalink
Merge pull request #682 from boschresearch/feature/register-ld-schema-be
Browse files Browse the repository at this point in the history
API Endpoint to post a json-ld schema config
  • Loading branch information
etschelp authored Dec 14, 2021
2 parents 71bc759 + d831c81 commit fb1bb7a
Show file tree
Hide file tree
Showing 53 changed files with 1,058 additions and 264 deletions.
5 changes: 4 additions & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ on:
branches:
- main
tags:
- '**'
- '**'
release:
types:
- created

jobs:
build:
Expand Down
12 changes: 9 additions & 3 deletions backend/business-partner-agent/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@
<dependency><!-- Overwrite for jakarta-annotations-api -->
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-annotations-api</artifactId>
<version>10.1.0-M7</version>
<version>10.1.0-M8</version>
</dependency>

<!-- Logging -->
Expand All @@ -128,7 +128,7 @@
<dependency>
<groupId>network.idu.acapy</groupId>
<artifactId>aries-client-python</artifactId>
<version>0.7.14</version>
<version>0.7.17</version>
</dependency>
<dependency>
<groupId>org.hyperledger.business-partner-agent</groupId>
Expand All @@ -150,7 +150,7 @@
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.9.2</version>
<version>${okhttp.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
Expand Down Expand Up @@ -219,6 +219,12 @@
<artifactId>mockito-junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>mockwebserver</artifactId>
<version>${okhttp.version}</version>
<scope>test</scope>
</dependency>
</dependencies>

<build>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,20 @@ public class ApiConstants {

public static final String DEFAULT_VERIFICATION_KEY_TYPE = "Ed25519VerificationKey2018";

public static final String CREDENTIALS_V1 = "https://www.w3.org/2018/credentials/v1";
public static final String VERIFIABLE_CREDENTIAL_NAME = "VerifiableCredential";

public static final String LABELED_CREDENTIAL_NAME = "LabeledCredential";

public static final String ORG_PROFILE_NAME = "OrganizationalProfileCredential";

// Schema Links
public static final String CREDENTIALS_V1_SCHEMA = "https://www.w3.org/2018/credentials/v1";

public static final String BBS_V1_SCHEMA = "https://w3id.org/security/bbs/v1";

public static final String INDY_CREDENTIAL_SCHEMA = "https://raw.githubusercontent.com/iil-network/contexts/master/indycredential.jsonld";

public static final String LABELED_CREDENTIAL_SCHEMA = "https://raw.githubusercontent.com/iil-network/contexts/master/labeled-credential.jsonld";

public static final String MASTER_DATA_SCHEMA = "https://raw.githubusercontent.com/iil-network/contexts/master/masterdata.jsonld";
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NonNull;
import org.hyperledger.aries.api.jsonld.VerifiableCredential;

import java.util.List;

Expand All @@ -30,42 +32,58 @@
public enum CredentialType {

/**
* A document that can never be a credential and that is not linked to a schema.
* A document that can never be a credential, and is not linked to a schema.
* Typed documents use a static context, like it is defined here.
*/
ORGANIZATIONAL_PROFILE_CREDENTIAL(
List.of(
ApiConstants.CREDENTIALS_V1,
"https://raw.githubusercontent.com/iil-network/contexts/master/masterdata.jsonld",
"https://raw.githubusercontent.com/iil-network/contexts/master/labeled-credential.jsonld"),
ApiConstants.CREDENTIALS_V1_SCHEMA,
ApiConstants.LABELED_CREDENTIAL_SCHEMA,
ApiConstants.MASTER_DATA_SCHEMA),
List.of(
"VerifiableCredential",
"LabeledCredential",
"OrganizationalProfileCredential")),
ApiConstants.VERIFIABLE_CREDENTIAL_NAME,
ApiConstants.LABELED_CREDENTIAL_NAME,
ApiConstants.ORG_PROFILE_NAME)),
/**
* A document or indy credential that is linked to a schema and uses an ad hoc
* context
* A document or indy credential that is linked to a ledger schema and uses an
* embedded context
*/
INDY(
List.of(ApiConstants.CREDENTIALS_V1),
List.of("VerifiableCredential"));
List.of(
ApiConstants.CREDENTIALS_V1_SCHEMA,
ApiConstants.LABELED_CREDENTIAL_SCHEMA),
List.of(
ApiConstants.VERIFIABLE_CREDENTIAL_NAME,
ApiConstants.LABELED_CREDENTIAL_NAME)),

// json-ld
/**
* A document or json-ld credential that is not linked to any ledger and uses an
* external or embedded context
*/
JSON_LD(
List.of(
ApiConstants.CREDENTIALS_V1_SCHEMA,
ApiConstants.LABELED_CREDENTIAL_SCHEMA,
ApiConstants.BBS_V1_SCHEMA),
List.of(
ApiConstants.VERIFIABLE_CREDENTIAL_NAME,
ApiConstants.LABELED_CREDENTIAL_NAME));

private final List<Object> context;
private final List<String> type;

/**
* Tries to get the type from the type list
* Tries to determine the credential type from the VC
*
* @param type the list of credential types
* @param c {@link VerifiableCredential.VerifiableIndyCredential}
* @return {@link CredentialType} or null when no match was found
*/
public static CredentialType fromType(List<String> type) {
for (String t : type) {
if ("OrganizationalProfileCredential".equals(t)) {
return CredentialType.ORGANIZATIONAL_PROFILE_CREDENTIAL;
}
public static CredentialType fromCredential(@NonNull VerifiableCredential.VerifiableIndyCredential c) {
if (c.getType().stream().anyMatch(ApiConstants.ORG_PROFILE_NAME::equals)) {
return CredentialType.ORGANIZATIONAL_PROFILE_CREDENTIAL;
}
if (c.getContext().stream().anyMatch(ApiConstants.BBS_V1_SCHEMA::equals)) {
return CredentialType.JSON_LD;
}
return CredentialType.INDY;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hyperledger.bpa.api.CredentialType;
import org.hyperledger.bpa.controller.api.admin.TrustedIssuer;
import org.hyperledger.bpa.controller.api.issuer.CredDef;
import org.hyperledger.bpa.impl.activity.Identity;
Expand All @@ -41,19 +42,27 @@ public class SchemaAPI {

private UUID id;

private CredentialType type;

private String label;

private String schemaId;

private String version;
private Boolean isMine;

private Set<String> schemaAttributeNames;

private List<TrustedIssuer> trustedIssuer;

private List<CredDef> credentialDefinitions;
// ld only

private Boolean isMine;
private String ldType;

// indy only

private String version;

private List<CredDef> credentialDefinitions;

public static SchemaAPI from(BPASchema s) {
return from(s, true, true, null);
Expand All @@ -74,20 +83,25 @@ public static SchemaAPI from(BPASchema s, boolean includeRestrictions, boolean i
s.getRestrictions().forEach(r -> ti.add(TrustedIssuer.from(r)));
builder.trustedIssuer(ti);
}
if (includeCredDefs && CollectionUtils.isNotEmpty(s.getCredentialDefinitions())) {
List<CredDef> cd = new ArrayList<>();
s.getCredentialDefinitions().forEach(r -> cd.add(CredDef.from(r)));
builder.credentialDefinitions(cd);
}
if (identity != null) {
builder.isMine(identity.isMySchema(s.getSchemaId()));
if (s.typeIsIndy()) {
if (includeCredDefs && CollectionUtils.isNotEmpty(s.getCredentialDefinitions())) {
List<CredDef> cd = new ArrayList<>();
s.getCredentialDefinitions().forEach(r -> cd.add(CredDef.from(r)));
builder.credentialDefinitions(cd);
}
if (identity != null) {
builder.isMine(identity.isMySchema(s.getSchemaId()));
}
builder.version(s.getSchemaId() == null ? "" : AriesStringUtil.schemaGetVersion(s.getSchemaId()));
} else {
builder.isMine(Boolean.TRUE);
}
String version = s.getSchemaId() == null ? "" : AriesStringUtil.schemaGetVersion(s.getSchemaId());
return builder
.id(s.getId())
.type(s.getType())
.ldType(s.getLdType())
.label(s.getLabel())
.schemaId(s.getSchemaId())
.version(version)
.schemaAttributeNames(s.getSchemaAttributeNames() != null ? s.getSchemaAttributeNames() : Set.of())
.build();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,15 @@ public HttpResponse<SchemaAPI> getSchema(@PathVariable UUID id) {
*/
@Post("/schema")
public HttpResponse<SchemaAPI> addSchema(@Body AddSchemaRequest req) {
return HttpResponse.ok(schemaService.addSchema(req.getSchemaId(), req.getLabel(),
req.getDefaultAttributeName(), req.getTrustedIssuer()));
if (req instanceof AddSchemaRequest.AddIndySchema) {
return HttpResponse.ok(schemaService.addIndySchema(req.getSchemaId(), req.getLabel(),
req.getDefaultAttributeName(), ((AddSchemaRequest.AddIndySchema) req).getTrustedIssuer()));
} else if (req instanceof AddSchemaRequest.AddJsonLDSchema) {
AddSchemaRequest.AddJsonLDSchema addSchema = (AddSchemaRequest.AddJsonLDSchema) req;
return HttpResponse.ok(schemaService.addJsonLDSchema(req.getSchemaId(), req.getLabel(),
req.getDefaultAttributeName(), addSchema.getLdType(), addSchema.getAttributes()));
}
return HttpResponse.badRequest();
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,36 +19,46 @@

import io.micronaut.core.annotation.Nullable;
import io.micronaut.http.HttpResponse;
import io.micronaut.http.HttpStatus;
import io.micronaut.http.annotation.*;
import io.micronaut.scheduling.TaskExecutors;
import io.micronaut.scheduling.annotation.ExecuteOn;
import io.micronaut.security.annotation.Secured;
import io.micronaut.security.rules.SecurityRule;
import io.micronaut.validation.Validated;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.inject.Inject;
import org.hyperledger.aries.api.issue_credential_v1.CredentialExchangeRole;
import org.hyperledger.bpa.api.aries.SchemaAPI;
import org.hyperledger.bpa.controller.api.issuer.*;
import org.hyperledger.bpa.impl.IssuerCredentialManager;
import org.hyperledger.bpa.impl.aries.ConnectionLessCredential;
import org.hyperledger.bpa.impl.aries.config.SchemaService;

import javax.validation.Valid;
import java.util.List;
import java.util.Optional;
import java.util.UUID;

@Controller("/api/issuer")
import static org.hyperledger.bpa.controller.IssuerController.ISSUER_CONTROLLER_BASE_URL;

@Controller(ISSUER_CONTROLLER_BASE_URL)
@Tag(name = "Credential Issuance Management")
@Validated
@Secured(SecurityRule.IS_AUTHENTICATED)
@ExecuteOn(TaskExecutors.IO)
public class IssuerController {

public static final String ISSUER_CONTROLLER_BASE_URL = "/api/issuer";

@Inject
IssuerCredentialManager im;

@Inject
ConnectionLessCredential connectionLess;

@Inject
SchemaService schemaService;

Expand Down Expand Up @@ -137,6 +147,32 @@ public HttpResponse<String> issueCredentialSend(@Valid @Body IssueCredentialSend
return HttpResponse.ok(exchange);
}

/**
* Issue connection-less credential step 1 - prepares credential offer and
* returns URL for use within the barcode
*
* @param req {@link IssueConnectionLessRequest}
* @return {@link IssueConnectionLessResponse}
*/
@Post("/issue-credential/connection-less")
public HttpResponse<IssueConnectionLessResponse> issueCredentialConnectionLess(
@Valid @Body IssueConnectionLessRequest req) {
return HttpResponse.ok(new IssueConnectionLessResponse(connectionLess.issueConnectionLess(req).toString()));
}

/**
* Issue connection-less credential step 2 - redirect with encoded offer
*
* @param id {@link UUID}
* @return Redirect with encoded credential offer in the location header
*/
@ApiResponse(responseCode = "307", description = "Redirect with encoded credential offer in the location header")
@Get("/issue-credential/connection-less/{id}")
public HttpResponse<Object> handleConnectionLess(@PathVariable UUID id) {
return HttpResponse.status(HttpStatus.TEMPORARY_REDIRECT).header("location",
connectionLess.handleConnectionLess(id));
}

/**
* List issued credentials
*
Expand Down
Loading

0 comments on commit fb1bb7a

Please sign in to comment.