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

Commit fb1bb7a

Browse files
author
Philipp Etschel
authored
Merge pull request #682 from boschresearch/feature/register-ld-schema-be
API Endpoint to post a json-ld schema config
2 parents 71bc759 + d831c81 commit fb1bb7a

File tree

53 files changed

+1058
-264
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+1058
-264
lines changed

.github/workflows/build.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@ on:
88
branches:
99
- main
1010
tags:
11-
- '**'
11+
- '**'
12+
release:
13+
types:
14+
- created
1215

1316
jobs:
1417
build:

backend/business-partner-agent/pom.xml

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@
107107
<dependency><!-- Overwrite for jakarta-annotations-api -->
108108
<groupId>org.apache.tomcat</groupId>
109109
<artifactId>tomcat-annotations-api</artifactId>
110-
<version>10.1.0-M7</version>
110+
<version>10.1.0-M8</version>
111111
</dependency>
112112

113113
<!-- Logging -->
@@ -128,7 +128,7 @@
128128
<dependency>
129129
<groupId>network.idu.acapy</groupId>
130130
<artifactId>aries-client-python</artifactId>
131-
<version>0.7.14</version>
131+
<version>0.7.17</version>
132132
</dependency>
133133
<dependency>
134134
<groupId>org.hyperledger.business-partner-agent</groupId>
@@ -150,7 +150,7 @@
150150
<dependency>
151151
<groupId>com.squareup.okhttp3</groupId>
152152
<artifactId>okhttp</artifactId>
153-
<version>4.9.2</version>
153+
<version>${okhttp.version}</version>
154154
</dependency>
155155
<dependency>
156156
<groupId>org.springframework.security</groupId>
@@ -219,6 +219,12 @@
219219
<artifactId>mockito-junit-jupiter</artifactId>
220220
<scope>test</scope>
221221
</dependency>
222+
<dependency>
223+
<groupId>com.squareup.okhttp3</groupId>
224+
<artifactId>mockwebserver</artifactId>
225+
<version>${okhttp.version}</version>
226+
<scope>test</scope>
227+
</dependency>
222228
</dependencies>
223229

224230
<build>

backend/business-partner-agent/src/main/java/org/hyperledger/bpa/api/ApiConstants.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,20 @@ public class ApiConstants {
2525

2626
public static final String DEFAULT_VERIFICATION_KEY_TYPE = "Ed25519VerificationKey2018";
2727

28-
public static final String CREDENTIALS_V1 = "https://www.w3.org/2018/credentials/v1";
28+
public static final String VERIFIABLE_CREDENTIAL_NAME = "VerifiableCredential";
29+
30+
public static final String LABELED_CREDENTIAL_NAME = "LabeledCredential";
31+
32+
public static final String ORG_PROFILE_NAME = "OrganizationalProfileCredential";
33+
34+
// Schema Links
35+
public static final String CREDENTIALS_V1_SCHEMA = "https://www.w3.org/2018/credentials/v1";
36+
37+
public static final String BBS_V1_SCHEMA = "https://w3id.org/security/bbs/v1";
2938

3039
public static final String INDY_CREDENTIAL_SCHEMA = "https://raw.githubusercontent.com/iil-network/contexts/master/indycredential.jsonld";
40+
41+
public static final String LABELED_CREDENTIAL_SCHEMA = "https://raw.githubusercontent.com/iil-network/contexts/master/labeled-credential.jsonld";
42+
43+
public static final String MASTER_DATA_SCHEMA = "https://raw.githubusercontent.com/iil-network/contexts/master/masterdata.jsonld";
3144
}

backend/business-partner-agent/src/main/java/org/hyperledger/bpa/api/CredentialType.java

Lines changed: 37 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919

2020
import lombok.AllArgsConstructor;
2121
import lombok.Getter;
22+
import lombok.NonNull;
23+
import org.hyperledger.aries.api.jsonld.VerifiableCredential;
2224

2325
import java.util.List;
2426

@@ -30,42 +32,58 @@
3032
public enum CredentialType {
3133

3234
/**
33-
* A document that can never be a credential and that is not linked to a schema.
35+
* A document that can never be a credential, and is not linked to a schema.
3436
* Typed documents use a static context, like it is defined here.
3537
*/
3638
ORGANIZATIONAL_PROFILE_CREDENTIAL(
3739
List.of(
38-
ApiConstants.CREDENTIALS_V1,
39-
"https://raw.githubusercontent.com/iil-network/contexts/master/masterdata.jsonld",
40-
"https://raw.githubusercontent.com/iil-network/contexts/master/labeled-credential.jsonld"),
40+
ApiConstants.CREDENTIALS_V1_SCHEMA,
41+
ApiConstants.LABELED_CREDENTIAL_SCHEMA,
42+
ApiConstants.MASTER_DATA_SCHEMA),
4143
List.of(
42-
"VerifiableCredential",
43-
"LabeledCredential",
44-
"OrganizationalProfileCredential")),
44+
ApiConstants.VERIFIABLE_CREDENTIAL_NAME,
45+
ApiConstants.LABELED_CREDENTIAL_NAME,
46+
ApiConstants.ORG_PROFILE_NAME)),
4547
/**
46-
* A document or indy credential that is linked to a schema and uses an ad hoc
47-
* context
48+
* A document or indy credential that is linked to a ledger schema and uses an
49+
* embedded context
4850
*/
4951
INDY(
50-
List.of(ApiConstants.CREDENTIALS_V1),
51-
List.of("VerifiableCredential"));
52+
List.of(
53+
ApiConstants.CREDENTIALS_V1_SCHEMA,
54+
ApiConstants.LABELED_CREDENTIAL_SCHEMA),
55+
List.of(
56+
ApiConstants.VERIFIABLE_CREDENTIAL_NAME,
57+
ApiConstants.LABELED_CREDENTIAL_NAME)),
5258

53-
// json-ld
59+
/**
60+
* A document or json-ld credential that is not linked to any ledger and uses an
61+
* external or embedded context
62+
*/
63+
JSON_LD(
64+
List.of(
65+
ApiConstants.CREDENTIALS_V1_SCHEMA,
66+
ApiConstants.LABELED_CREDENTIAL_SCHEMA,
67+
ApiConstants.BBS_V1_SCHEMA),
68+
List.of(
69+
ApiConstants.VERIFIABLE_CREDENTIAL_NAME,
70+
ApiConstants.LABELED_CREDENTIAL_NAME));
5471

5572
private final List<Object> context;
5673
private final List<String> type;
5774

5875
/**
59-
* Tries to get the type from the type list
76+
* Tries to determine the credential type from the VC
6077
*
61-
* @param type the list of credential types
78+
* @param c {@link VerifiableCredential.VerifiableIndyCredential}
6279
* @return {@link CredentialType} or null when no match was found
6380
*/
64-
public static CredentialType fromType(List<String> type) {
65-
for (String t : type) {
66-
if ("OrganizationalProfileCredential".equals(t)) {
67-
return CredentialType.ORGANIZATIONAL_PROFILE_CREDENTIAL;
68-
}
81+
public static CredentialType fromCredential(@NonNull VerifiableCredential.VerifiableIndyCredential c) {
82+
if (c.getType().stream().anyMatch(ApiConstants.ORG_PROFILE_NAME::equals)) {
83+
return CredentialType.ORGANIZATIONAL_PROFILE_CREDENTIAL;
84+
}
85+
if (c.getContext().stream().anyMatch(ApiConstants.BBS_V1_SCHEMA::equals)) {
86+
return CredentialType.JSON_LD;
6987
}
7088
return CredentialType.INDY;
7189
}

backend/business-partner-agent/src/main/java/org/hyperledger/bpa/api/aries/SchemaAPI.java

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import lombok.Builder;
2323
import lombok.Data;
2424
import lombok.NoArgsConstructor;
25+
import org.hyperledger.bpa.api.CredentialType;
2526
import org.hyperledger.bpa.controller.api.admin.TrustedIssuer;
2627
import org.hyperledger.bpa.controller.api.issuer.CredDef;
2728
import org.hyperledger.bpa.impl.activity.Identity;
@@ -41,19 +42,27 @@ public class SchemaAPI {
4142

4243
private UUID id;
4344

45+
private CredentialType type;
46+
4447
private String label;
4548

4649
private String schemaId;
4750

48-
private String version;
51+
private Boolean isMine;
4952

5053
private Set<String> schemaAttributeNames;
5154

5255
private List<TrustedIssuer> trustedIssuer;
5356

54-
private List<CredDef> credentialDefinitions;
57+
// ld only
5558

56-
private Boolean isMine;
59+
private String ldType;
60+
61+
// indy only
62+
63+
private String version;
64+
65+
private List<CredDef> credentialDefinitions;
5766

5867
public static SchemaAPI from(BPASchema s) {
5968
return from(s, true, true, null);
@@ -74,20 +83,25 @@ public static SchemaAPI from(BPASchema s, boolean includeRestrictions, boolean i
7483
s.getRestrictions().forEach(r -> ti.add(TrustedIssuer.from(r)));
7584
builder.trustedIssuer(ti);
7685
}
77-
if (includeCredDefs && CollectionUtils.isNotEmpty(s.getCredentialDefinitions())) {
78-
List<CredDef> cd = new ArrayList<>();
79-
s.getCredentialDefinitions().forEach(r -> cd.add(CredDef.from(r)));
80-
builder.credentialDefinitions(cd);
81-
}
82-
if (identity != null) {
83-
builder.isMine(identity.isMySchema(s.getSchemaId()));
86+
if (s.typeIsIndy()) {
87+
if (includeCredDefs && CollectionUtils.isNotEmpty(s.getCredentialDefinitions())) {
88+
List<CredDef> cd = new ArrayList<>();
89+
s.getCredentialDefinitions().forEach(r -> cd.add(CredDef.from(r)));
90+
builder.credentialDefinitions(cd);
91+
}
92+
if (identity != null) {
93+
builder.isMine(identity.isMySchema(s.getSchemaId()));
94+
}
95+
builder.version(s.getSchemaId() == null ? "" : AriesStringUtil.schemaGetVersion(s.getSchemaId()));
96+
} else {
97+
builder.isMine(Boolean.TRUE);
8498
}
85-
String version = s.getSchemaId() == null ? "" : AriesStringUtil.schemaGetVersion(s.getSchemaId());
8699
return builder
87100
.id(s.getId())
101+
.type(s.getType())
102+
.ldType(s.getLdType())
88103
.label(s.getLabel())
89104
.schemaId(s.getSchemaId())
90-
.version(version)
91105
.schemaAttributeNames(s.getSchemaAttributeNames() != null ? s.getSchemaAttributeNames() : Set.of())
92106
.build();
93107
}

backend/business-partner-agent/src/main/java/org/hyperledger/bpa/controller/AdminController.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,15 @@ public HttpResponse<SchemaAPI> getSchema(@PathVariable UUID id) {
9696
*/
9797
@Post("/schema")
9898
public HttpResponse<SchemaAPI> addSchema(@Body AddSchemaRequest req) {
99-
return HttpResponse.ok(schemaService.addSchema(req.getSchemaId(), req.getLabel(),
100-
req.getDefaultAttributeName(), req.getTrustedIssuer()));
99+
if (req instanceof AddSchemaRequest.AddIndySchema) {
100+
return HttpResponse.ok(schemaService.addIndySchema(req.getSchemaId(), req.getLabel(),
101+
req.getDefaultAttributeName(), ((AddSchemaRequest.AddIndySchema) req).getTrustedIssuer()));
102+
} else if (req instanceof AddSchemaRequest.AddJsonLDSchema) {
103+
AddSchemaRequest.AddJsonLDSchema addSchema = (AddSchemaRequest.AddJsonLDSchema) req;
104+
return HttpResponse.ok(schemaService.addJsonLDSchema(req.getSchemaId(), req.getLabel(),
105+
req.getDefaultAttributeName(), addSchema.getLdType(), addSchema.getAttributes()));
106+
}
107+
return HttpResponse.badRequest();
101108
}
102109

103110
/**

backend/business-partner-agent/src/main/java/org/hyperledger/bpa/controller/IssuerController.java

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,36 +19,46 @@
1919

2020
import io.micronaut.core.annotation.Nullable;
2121
import io.micronaut.http.HttpResponse;
22+
import io.micronaut.http.HttpStatus;
2223
import io.micronaut.http.annotation.*;
2324
import io.micronaut.scheduling.TaskExecutors;
2425
import io.micronaut.scheduling.annotation.ExecuteOn;
2526
import io.micronaut.security.annotation.Secured;
2627
import io.micronaut.security.rules.SecurityRule;
2728
import io.micronaut.validation.Validated;
2829
import io.swagger.v3.oas.annotations.Parameter;
30+
import io.swagger.v3.oas.annotations.responses.ApiResponse;
2931
import io.swagger.v3.oas.annotations.tags.Tag;
3032
import jakarta.inject.Inject;
3133
import org.hyperledger.aries.api.issue_credential_v1.CredentialExchangeRole;
3234
import org.hyperledger.bpa.api.aries.SchemaAPI;
3335
import org.hyperledger.bpa.controller.api.issuer.*;
3436
import org.hyperledger.bpa.impl.IssuerCredentialManager;
37+
import org.hyperledger.bpa.impl.aries.ConnectionLessCredential;
3538
import org.hyperledger.bpa.impl.aries.config.SchemaService;
3639

3740
import javax.validation.Valid;
3841
import java.util.List;
3942
import java.util.Optional;
4043
import java.util.UUID;
4144

42-
@Controller("/api/issuer")
45+
import static org.hyperledger.bpa.controller.IssuerController.ISSUER_CONTROLLER_BASE_URL;
46+
47+
@Controller(ISSUER_CONTROLLER_BASE_URL)
4348
@Tag(name = "Credential Issuance Management")
4449
@Validated
4550
@Secured(SecurityRule.IS_AUTHENTICATED)
4651
@ExecuteOn(TaskExecutors.IO)
4752
public class IssuerController {
4853

54+
public static final String ISSUER_CONTROLLER_BASE_URL = "/api/issuer";
55+
4956
@Inject
5057
IssuerCredentialManager im;
5158

59+
@Inject
60+
ConnectionLessCredential connectionLess;
61+
5262
@Inject
5363
SchemaService schemaService;
5464

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

150+
/**
151+
* Issue connection-less credential step 1 - prepares credential offer and
152+
* returns URL for use within the barcode
153+
*
154+
* @param req {@link IssueConnectionLessRequest}
155+
* @return {@link IssueConnectionLessResponse}
156+
*/
157+
@Post("/issue-credential/connection-less")
158+
public HttpResponse<IssueConnectionLessResponse> issueCredentialConnectionLess(
159+
@Valid @Body IssueConnectionLessRequest req) {
160+
return HttpResponse.ok(new IssueConnectionLessResponse(connectionLess.issueConnectionLess(req).toString()));
161+
}
162+
163+
/**
164+
* Issue connection-less credential step 2 - redirect with encoded offer
165+
*
166+
* @param id {@link UUID}
167+
* @return Redirect with encoded credential offer in the location header
168+
*/
169+
@ApiResponse(responseCode = "307", description = "Redirect with encoded credential offer in the location header")
170+
@Get("/issue-credential/connection-less/{id}")
171+
public HttpResponse<Object> handleConnectionLess(@PathVariable UUID id) {
172+
return HttpResponse.status(HttpStatus.TEMPORARY_REDIRECT).header("location",
173+
connectionLess.handleConnectionLess(id));
174+
}
175+
140176
/**
141177
* List issued credentials
142178
*

0 commit comments

Comments
 (0)