@cheqd/studio 3.3.0 → 3.4.0-develop.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +7 -0
- package/dist/app.js.map +1 -1
- package/dist/controllers/api/accreditation.d.ts +227 -0
- package/dist/controllers/api/accreditation.d.ts.map +1 -0
- package/dist/controllers/api/accreditation.js +667 -0
- package/dist/controllers/api/accreditation.js.map +1 -0
- package/dist/controllers/validator/index.d.ts +1 -1
- package/dist/controllers/validator/index.d.ts.map +1 -1
- package/dist/controllers/validator/index.js +1 -1
- package/dist/controllers/validator/index.js.map +1 -1
- package/dist/helpers/helpers.d.ts +3 -0
- package/dist/helpers/helpers.d.ts.map +1 -1
- package/dist/helpers/helpers.js +17 -0
- package/dist/helpers/helpers.js.map +1 -1
- package/dist/middleware/auth/routes/api/accreditation-auth.d.ts +5 -0
- package/dist/middleware/auth/routes/api/accreditation-auth.d.ts.map +1 -0
- package/dist/middleware/auth/routes/api/accreditation-auth.js +21 -0
- package/dist/middleware/auth/routes/api/accreditation-auth.js.map +1 -0
- package/dist/middleware/authentication.d.ts.map +1 -1
- package/dist/middleware/authentication.js +2 -0
- package/dist/middleware/authentication.js.map +1 -1
- package/dist/services/api/accreditation.d.ts +11 -0
- package/dist/services/api/accreditation.d.ts.map +1 -0
- package/dist/services/api/accreditation.js +116 -0
- package/dist/services/api/accreditation.js.map +1 -0
- package/dist/services/api/credentials.d.ts +1 -1
- package/dist/services/api/credentials.d.ts.map +1 -1
- package/dist/services/api/credentials.js +10 -2
- package/dist/services/api/credentials.js.map +1 -1
- package/dist/services/connectors/resource.d.ts +22 -0
- package/dist/services/connectors/resource.d.ts.map +1 -0
- package/dist/services/connectors/resource.js +38 -0
- package/dist/services/connectors/resource.js.map +1 -0
- package/dist/services/w3c-credential.d.ts +1 -0
- package/dist/services/w3c-credential.d.ts.map +1 -1
- package/dist/services/w3c-credential.js +2 -0
- package/dist/services/w3c-credential.js.map +1 -1
- package/dist/static/swagger-api.json +616 -0
- package/dist/types/accreditation.d.ts +84 -0
- package/dist/types/accreditation.d.ts.map +1 -0
- package/dist/types/accreditation.js +23 -0
- package/dist/types/accreditation.js.map +1 -0
- package/dist/types/constants.d.ts.map +1 -1
- package/dist/types/constants.js +1 -1
- package/dist/types/constants.js.map +1 -1
- package/dist/types/credential.d.ts +10 -4
- package/dist/types/credential.d.ts.map +1 -1
- package/dist/types/credential.js +5 -1
- package/dist/types/credential.js.map +1 -1
- package/dist/types/swagger-api-types.d.ts +233 -0
- package/dist/types/swagger-api-types.d.ts.map +1 -1
- package/dist/types/swagger-api-types.js +233 -0
- package/dist/types/swagger-api-types.js.map +1 -1
- package/package.json +21 -21
|
@@ -0,0 +1,667 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import { StatusCodes } from 'http-status-codes';
|
|
8
|
+
import { v4 } from 'uuid';
|
|
9
|
+
import { AccreditationRequestType, DIDAccreditationTypes } from '../../types/accreditation.js';
|
|
10
|
+
import { CredentialConnectors } from '../../types/credential.js';
|
|
11
|
+
import { OperationCategoryNameEnum, OperationNameEnum } from '../../types/constants.js';
|
|
12
|
+
import { IdentityServiceStrategySetup } from '../../services/identity/index.js';
|
|
13
|
+
import { AccreditationService } from '../../services/api/accreditation.js';
|
|
14
|
+
import { Credentials } from '../../services/api/credentials.js';
|
|
15
|
+
import { eventTracker } from '../../services/track/tracker.js';
|
|
16
|
+
import { body, query } from '../validator/index.js';
|
|
17
|
+
import { validate } from '../validator/decorator.js';
|
|
18
|
+
import { constructDidUrl, parseDidFromDidUrl } from '../../helpers/helpers.js';
|
|
19
|
+
export class AccreditationController {
|
|
20
|
+
static issueValidator = [
|
|
21
|
+
query('accreditationType')
|
|
22
|
+
.exists()
|
|
23
|
+
.isIn([
|
|
24
|
+
AccreditationRequestType.authorize,
|
|
25
|
+
AccreditationRequestType.accredit,
|
|
26
|
+
AccreditationRequestType.attest,
|
|
27
|
+
])
|
|
28
|
+
.bail(),
|
|
29
|
+
body('accreditationName').exists().isString().withMessage('accreditationName is required').bail(),
|
|
30
|
+
body('issuerDid').exists().isDID().bail(),
|
|
31
|
+
body('subjectDid').exists().isDID().bail(),
|
|
32
|
+
body('schemas').exists().isArray().withMessage('schemas must be a array').bail(),
|
|
33
|
+
body('schemas.*.url').isString().withMessage('schema urls must be a string').bail(),
|
|
34
|
+
body('schemas.*.type')
|
|
35
|
+
.custom((value) => typeof value === 'string' || (Array.isArray(value) && typeof value[0] === 'string'))
|
|
36
|
+
.withMessage('schema type must be a string'),
|
|
37
|
+
body('parentAccreditation').optional().isString().withMessage('parentAccreditation must be a string').bail(),
|
|
38
|
+
body('rootAuthorization').optional().isString().withMessage('rootAuthorization must be a string').bail(),
|
|
39
|
+
body('trustFramework').optional().isString().withMessage('trustFramework must be a string').bail(),
|
|
40
|
+
body('trustFrameworkId').optional().isString().withMessage('trustFrameworkId must be a string').bail(),
|
|
41
|
+
query('accreditationType')
|
|
42
|
+
.custom((value, { req }) => {
|
|
43
|
+
const { parentAccreditation, rootAuthorization, trustFramework, trustFrameworkId } = req.body;
|
|
44
|
+
const hasParentOrRoot = parentAccreditation || rootAuthorization;
|
|
45
|
+
if (!hasParentOrRoot &&
|
|
46
|
+
(value === AccreditationRequestType.accredit || value === AccreditationRequestType.attest)) {
|
|
47
|
+
throw new Error('parentAccreditation or rootAuthorization is required');
|
|
48
|
+
}
|
|
49
|
+
if (hasParentOrRoot && value === AccreditationRequestType.authorize) {
|
|
50
|
+
throw new Error('parentAccreditation or rootAuthorization is not required for an authorize operation');
|
|
51
|
+
}
|
|
52
|
+
const hasTrustFramework = trustFramework && trustFrameworkId;
|
|
53
|
+
if (!hasTrustFramework && value === AccreditationRequestType.authorize) {
|
|
54
|
+
throw new Error('trustFramework and trustFrameworkId are required for an authorize operation');
|
|
55
|
+
}
|
|
56
|
+
return true;
|
|
57
|
+
})
|
|
58
|
+
.bail(),
|
|
59
|
+
body('accreditationName').exists().isString(),
|
|
60
|
+
];
|
|
61
|
+
static verifyValidator = [
|
|
62
|
+
body('did').optional().isDID().bail(),
|
|
63
|
+
body('didUrl')
|
|
64
|
+
.optional()
|
|
65
|
+
.isString()
|
|
66
|
+
.custom((value) => value.includes('/resources/') || value.includes('?resourceName'))
|
|
67
|
+
.withMessage('didUrls should point to a unique DID Linked Resource')
|
|
68
|
+
.bail(),
|
|
69
|
+
body('resourceId').optional().isUUID().withMessage('resourceId should be a string').bail(),
|
|
70
|
+
body('resourceName').optional().isString().withMessage('resourceName should be a string').bail(),
|
|
71
|
+
body('resourceType').optional().isString().withMessage('resourceType should be a string').bail(),
|
|
72
|
+
body('schemas').optional().isArray().withMessage('schemas must be a array').bail(),
|
|
73
|
+
body('schemas.*.url').isString().withMessage('schema urls must be a string').bail(),
|
|
74
|
+
body('schemas.*.type')
|
|
75
|
+
.custom((value) => typeof value === 'string' || (Array.isArray(value) && typeof value[0] === 'string'))
|
|
76
|
+
.withMessage('schema type must be a string'),
|
|
77
|
+
body('did')
|
|
78
|
+
.custom((value, { req }) => {
|
|
79
|
+
const { didUrl, resourceId, resourceName, resourceType } = req.body;
|
|
80
|
+
if (!value && !didUrl) {
|
|
81
|
+
throw new Error('Either "did" or "didUrl" is required');
|
|
82
|
+
}
|
|
83
|
+
// If did is provided, ensure either resourceId or both resourceName and resourceType are provided
|
|
84
|
+
if (value && !(resourceId || (resourceName && resourceType))) {
|
|
85
|
+
throw new Error('Either "resourceId" or both "resourceName" and "resourceType" are required');
|
|
86
|
+
}
|
|
87
|
+
return true;
|
|
88
|
+
})
|
|
89
|
+
.bail(),
|
|
90
|
+
body('subjectDid').exists().isDID().bail(),
|
|
91
|
+
query('verifyStatus')
|
|
92
|
+
.optional()
|
|
93
|
+
.isBoolean()
|
|
94
|
+
.withMessage('verifyStatus should be a boolean value')
|
|
95
|
+
.toBoolean()
|
|
96
|
+
.bail(),
|
|
97
|
+
query('allowDeactivatedDid')
|
|
98
|
+
.optional()
|
|
99
|
+
.isBoolean()
|
|
100
|
+
.withMessage('allowDeactivatedDid should be a boolean value')
|
|
101
|
+
.toBoolean()
|
|
102
|
+
.bail(),
|
|
103
|
+
query('policies').optional().isObject().withMessage('Verification policies should be an object').bail(),
|
|
104
|
+
];
|
|
105
|
+
static publishValidator = [
|
|
106
|
+
query('publish').optional().isBoolean().withMessage('publish should be a boolean value').toBoolean().bail(),
|
|
107
|
+
];
|
|
108
|
+
/**
|
|
109
|
+
* @openapi
|
|
110
|
+
*
|
|
111
|
+
* /trust-registry/accreditation/issue:
|
|
112
|
+
* post:
|
|
113
|
+
* tags: [ Trust Registry ]
|
|
114
|
+
* summary: Publish a verifiable accreditation for a DID.
|
|
115
|
+
* description: Generate and publish a Verifiable Accreditation for a subject DID as a DID Linked resource.
|
|
116
|
+
* operationId: accredit-issue
|
|
117
|
+
* parameters:
|
|
118
|
+
* - in: query
|
|
119
|
+
* name: accreditationType
|
|
120
|
+
* description: Select the type of accreditation to be issued.
|
|
121
|
+
* schema:
|
|
122
|
+
* type: string
|
|
123
|
+
* enum:
|
|
124
|
+
* - authorize
|
|
125
|
+
* - accredit
|
|
126
|
+
* - attest
|
|
127
|
+
* required: true
|
|
128
|
+
* requestBody:
|
|
129
|
+
* content:
|
|
130
|
+
* application/x-www-form-urlencoded:
|
|
131
|
+
* schema:
|
|
132
|
+
* $ref: '#/components/schemas/AccreditationIssueRequest'
|
|
133
|
+
* application/json:
|
|
134
|
+
* schema:
|
|
135
|
+
* $ref: '#/components/schemas/AccreditationIssueRequest'
|
|
136
|
+
* responses:
|
|
137
|
+
* 200:
|
|
138
|
+
* description: The request was successful.
|
|
139
|
+
* content:
|
|
140
|
+
* application/json:
|
|
141
|
+
* schema:
|
|
142
|
+
* $ref: '#/components/schemas/Credential'
|
|
143
|
+
* 400:
|
|
144
|
+
* $ref: '#/components/schemas/InvalidRequest'
|
|
145
|
+
* 401:
|
|
146
|
+
* $ref: '#/components/schemas/UnauthorizedError'
|
|
147
|
+
* 500:
|
|
148
|
+
* $ref: '#/components/schemas/InternalError'
|
|
149
|
+
*/
|
|
150
|
+
async issue(request, response) {
|
|
151
|
+
// Get strategy e.g. postgres or local
|
|
152
|
+
const identityServiceStrategySetup = new IdentityServiceStrategySetup();
|
|
153
|
+
// Extract did from params
|
|
154
|
+
const { accreditationType } = request.query;
|
|
155
|
+
// Handles string input instead of an array
|
|
156
|
+
if (typeof request.body.type === 'string') {
|
|
157
|
+
request.body.type = [request.body.type];
|
|
158
|
+
}
|
|
159
|
+
if (typeof request.body['@context'] === 'string') {
|
|
160
|
+
request.body['@context'] = [request.body['@context']];
|
|
161
|
+
}
|
|
162
|
+
const { issuerDid, subjectDid, schemas, type, parentAccreditation, rootAuthorization, trustFramework, trustFrameworkId, attributes, accreditationName, format, credentialStatus, } = request.body;
|
|
163
|
+
try {
|
|
164
|
+
// Validate issuer DID
|
|
165
|
+
const resolvedResult = await identityServiceStrategySetup.agent.resolve(issuerDid);
|
|
166
|
+
// check if DID-Document is resolved
|
|
167
|
+
const body = await resolvedResult.json();
|
|
168
|
+
if (!body?.didDocument) {
|
|
169
|
+
return response.status(StatusCodes.BAD_REQUEST).send({
|
|
170
|
+
error: `DID ${issuerDid} is not resolved because of error from resolver: ${body.didResolutionMetadata.error}.`,
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
if (body.didDocumentMetadata.deactivated) {
|
|
174
|
+
return response.status(StatusCodes.BAD_REQUEST).send({
|
|
175
|
+
error: `${issuerDid} is deactivated`,
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
// Validate subject DID
|
|
179
|
+
const res = await identityServiceStrategySetup.agent.resolve(subjectDid);
|
|
180
|
+
const subjectDidRes = await res.json();
|
|
181
|
+
if (!subjectDidRes?.didDocument) {
|
|
182
|
+
return response.status(StatusCodes.BAD_REQUEST).send({
|
|
183
|
+
error: `DID ${subjectDid} is not resolved because of error from resolver: ${body.didResolutionMetadata.error}.`,
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
if (subjectDidRes.didDocumentMetadata.deactivated) {
|
|
187
|
+
return response.status(StatusCodes.BAD_REQUEST).send({
|
|
188
|
+
error: `${subjectDid} is deactivated`,
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
const resourceId = v4();
|
|
192
|
+
const accreditedFor = schemas.map(({ url, type }) => ({
|
|
193
|
+
schemaId: url,
|
|
194
|
+
type,
|
|
195
|
+
}));
|
|
196
|
+
// construct credential request
|
|
197
|
+
const credentialRequest = {
|
|
198
|
+
subjectDid,
|
|
199
|
+
attributes: {
|
|
200
|
+
...attributes,
|
|
201
|
+
accreditedFor,
|
|
202
|
+
id: subjectDid,
|
|
203
|
+
},
|
|
204
|
+
issuerDid,
|
|
205
|
+
format: format || 'jwt',
|
|
206
|
+
connector: CredentialConnectors.Resource, // resource connector
|
|
207
|
+
credentialId: resourceId,
|
|
208
|
+
credentialName: accreditationName,
|
|
209
|
+
credentialStatus,
|
|
210
|
+
};
|
|
211
|
+
let resourceType;
|
|
212
|
+
switch (accreditationType) {
|
|
213
|
+
case AccreditationRequestType.authorize:
|
|
214
|
+
resourceType = DIDAccreditationTypes.VerifiableAuthorisationForTrustChain;
|
|
215
|
+
credentialRequest.type = [...(type || []), resourceType];
|
|
216
|
+
credentialRequest.termsOfUse = {
|
|
217
|
+
type: resourceType,
|
|
218
|
+
trustFramework,
|
|
219
|
+
trustFrameworkId,
|
|
220
|
+
};
|
|
221
|
+
break;
|
|
222
|
+
case AccreditationRequestType.accredit:
|
|
223
|
+
resourceType = DIDAccreditationTypes.VerifiableAccreditationToAccredit;
|
|
224
|
+
credentialRequest.type = [...(type || []), resourceType];
|
|
225
|
+
credentialRequest.termsOfUse = {
|
|
226
|
+
type: resourceType,
|
|
227
|
+
parentAccreditation,
|
|
228
|
+
rootAuthorization,
|
|
229
|
+
};
|
|
230
|
+
break;
|
|
231
|
+
case AccreditationRequestType.attest:
|
|
232
|
+
resourceType = DIDAccreditationTypes.VerifiableAccreditationToAttest;
|
|
233
|
+
credentialRequest.type = [...(type || []), resourceType];
|
|
234
|
+
credentialRequest.termsOfUse = {
|
|
235
|
+
type: resourceType,
|
|
236
|
+
parentAccreditation,
|
|
237
|
+
rootAuthorization,
|
|
238
|
+
};
|
|
239
|
+
break;
|
|
240
|
+
}
|
|
241
|
+
// validate parent and root accreditations
|
|
242
|
+
if (accreditationType === AccreditationRequestType.accredit ||
|
|
243
|
+
accreditationType === AccreditationRequestType.attest) {
|
|
244
|
+
const result = await AccreditationService.instance.verify_accreditation(issuerDid, parentAccreditation, accreditedFor, true, false, response.locals.customer, rootAuthorization);
|
|
245
|
+
if (result.success === false) {
|
|
246
|
+
return response.status(result.status).send({
|
|
247
|
+
error: `Invalid Request: Root Authorization or parent Accreditation is not valid: ${result.error}`,
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
// issue accreditation
|
|
252
|
+
const accreditation = await Credentials.instance.issue_credential(credentialRequest, response.locals.customer);
|
|
253
|
+
// Track operation
|
|
254
|
+
const trackInfo = {
|
|
255
|
+
category: OperationCategoryNameEnum.CREDENTIAL,
|
|
256
|
+
name: OperationNameEnum.CREDENTIAL_ISSUE,
|
|
257
|
+
customer: response.locals.customer,
|
|
258
|
+
user: response.locals.user,
|
|
259
|
+
data: {
|
|
260
|
+
did: issuerDid,
|
|
261
|
+
},
|
|
262
|
+
};
|
|
263
|
+
eventTracker.emit('track', trackInfo);
|
|
264
|
+
return response.status(StatusCodes.OK).json({
|
|
265
|
+
didUrls: [
|
|
266
|
+
`${issuerDid}/resources/${resourceId}`,
|
|
267
|
+
`${issuerDid}?resourceName=${accreditationName}&resourceType=${credentialRequest.type}`,
|
|
268
|
+
],
|
|
269
|
+
accreditation,
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
catch (error) {
|
|
273
|
+
return response.status(StatusCodes.INTERNAL_SERVER_ERROR).json({
|
|
274
|
+
error: `Internal error: ${error?.message || error}`,
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* @openapi
|
|
280
|
+
*
|
|
281
|
+
* /trust-registry/accreditation/verify:
|
|
282
|
+
* post:
|
|
283
|
+
* tags: [ Trust Registry ]
|
|
284
|
+
* summary: Verify a verifiable accreditation for a DID.
|
|
285
|
+
* description: Generate and publish a Verifiable Accreditation for a subject DID as a DID Linked resource.
|
|
286
|
+
* operationId: accredit-verify
|
|
287
|
+
* parameters:
|
|
288
|
+
* - in: query
|
|
289
|
+
* name: verifyStatus
|
|
290
|
+
* description: If set to `true` the verification will also check the status of the accreditation. Requires the VC to have a `credentialStatus` property.
|
|
291
|
+
* schema:
|
|
292
|
+
* type: boolean
|
|
293
|
+
* default: false
|
|
294
|
+
* - in: query
|
|
295
|
+
* name: allowDeactivatedDid
|
|
296
|
+
* description: If set to `true` allow to verify accreditation which based on deactivated DID.
|
|
297
|
+
* schema:
|
|
298
|
+
* type: boolean
|
|
299
|
+
* default: false
|
|
300
|
+
* requestBody:
|
|
301
|
+
* content:
|
|
302
|
+
* application/x-www-form-urlencoded:
|
|
303
|
+
* schema:
|
|
304
|
+
* $ref: '#/components/schemas/AccreditationVerifyRequest'
|
|
305
|
+
* application/json:
|
|
306
|
+
* schema:
|
|
307
|
+
* $ref: '#/components/schemas/AccreditationVerifyRequest'
|
|
308
|
+
* responses:
|
|
309
|
+
* 200:
|
|
310
|
+
* description: The request was successful.
|
|
311
|
+
* content:
|
|
312
|
+
* application/json:
|
|
313
|
+
* schema:
|
|
314
|
+
* $ref: '#/components/schemas/Credential'
|
|
315
|
+
* 400:
|
|
316
|
+
* $ref: '#/components/schemas/InvalidRequest'
|
|
317
|
+
* 401:
|
|
318
|
+
* $ref: '#/components/schemas/UnauthorizedError'
|
|
319
|
+
* 500:
|
|
320
|
+
* $ref: '#/components/schemas/InternalError'
|
|
321
|
+
*/
|
|
322
|
+
async verify(request, response) {
|
|
323
|
+
// Extract did from params
|
|
324
|
+
let { verifyStatus = false, allowDeactivatedDid = false } = request.query;
|
|
325
|
+
const { policies, subjectDid, schemas } = request.body;
|
|
326
|
+
// construct didUrl
|
|
327
|
+
const didUrl = constructDidUrl(request.body);
|
|
328
|
+
if (!didUrl) {
|
|
329
|
+
return response.status(400).json({
|
|
330
|
+
error: `Invalid Request: Either didUrl or did with resource attributes are required`,
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
try {
|
|
334
|
+
const accreditedFor = schemas?.map(({ url, type }) => ({
|
|
335
|
+
schemaId: url,
|
|
336
|
+
type,
|
|
337
|
+
}));
|
|
338
|
+
const result = await AccreditationService.instance.verify_accreditation(subjectDid, didUrl, accreditedFor, verifyStatus, allowDeactivatedDid, response.locals.customer, undefined, policies);
|
|
339
|
+
// Track operation
|
|
340
|
+
const trackInfo = {
|
|
341
|
+
category: OperationCategoryNameEnum.CREDENTIAL,
|
|
342
|
+
name: OperationNameEnum.CREDENTIAL_VERIFY,
|
|
343
|
+
customer: response.locals.customer,
|
|
344
|
+
user: response.locals.user,
|
|
345
|
+
data: {
|
|
346
|
+
did: parseDidFromDidUrl(didUrl),
|
|
347
|
+
},
|
|
348
|
+
};
|
|
349
|
+
eventTracker.emit('track', trackInfo);
|
|
350
|
+
if (result.success) {
|
|
351
|
+
return response.status(StatusCodes.OK).json(result.data);
|
|
352
|
+
}
|
|
353
|
+
else {
|
|
354
|
+
return response.status(result.status).json({ verified: false, error: result.error });
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
catch (error) {
|
|
358
|
+
return response.status(StatusCodes.INTERNAL_SERVER_ERROR).json({
|
|
359
|
+
error: `Internal error: ${error?.message || error}`,
|
|
360
|
+
});
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
/**
|
|
364
|
+
* @openapi
|
|
365
|
+
*
|
|
366
|
+
* /trust-registry/accreditation/revoke:
|
|
367
|
+
* post:
|
|
368
|
+
* tags: [ Trust Registry ]
|
|
369
|
+
* summary: Revoke a Verifiable Accreditation.
|
|
370
|
+
* description: This endpoint revokes a given Verifiable Accreditation. As input, it can take the didUrl as a string. The StatusList2021 resource should already be setup in the VC and `credentialStatus` property present in the VC.
|
|
371
|
+
* operationId: accredit-revoke
|
|
372
|
+
* parameters:
|
|
373
|
+
* - in: query
|
|
374
|
+
* name: publish
|
|
375
|
+
* description: Set whether the StatusList2021 resource should be published to the ledger or not. If set to `false`, the StatusList2021 publisher should manually publish the resource.
|
|
376
|
+
* required: true
|
|
377
|
+
* schema:
|
|
378
|
+
* type: boolean
|
|
379
|
+
* default: true
|
|
380
|
+
* requestBody:
|
|
381
|
+
* content:
|
|
382
|
+
* application/x-www-form-urlencoded:
|
|
383
|
+
* schema:
|
|
384
|
+
* $ref: '#/components/schemas/AccreditationRevokeRequest'
|
|
385
|
+
* application/json:
|
|
386
|
+
* schema:
|
|
387
|
+
* $ref: '#/components/schemas/AccreditationRevokeRequest'
|
|
388
|
+
* responses:
|
|
389
|
+
* 200:
|
|
390
|
+
* description: The request was successful.
|
|
391
|
+
* content:
|
|
392
|
+
* application/json:
|
|
393
|
+
* schema:
|
|
394
|
+
* $ref: '#/components/schemas/RevocationResult'
|
|
395
|
+
* 400:
|
|
396
|
+
* $ref: '#/components/schemas/InvalidRequest'
|
|
397
|
+
* 401:
|
|
398
|
+
* $ref: '#/components/schemas/UnauthorizedError'
|
|
399
|
+
* 500:
|
|
400
|
+
* $ref: '#/components/schemas/InternalError'
|
|
401
|
+
*/
|
|
402
|
+
async revoke(request, response) {
|
|
403
|
+
// Get publish flag
|
|
404
|
+
const { publish } = request.query;
|
|
405
|
+
// Get symmetric key
|
|
406
|
+
const { symmetricKey, ...didUrlParams } = request.body;
|
|
407
|
+
// Get strategy e.g. postgres or local
|
|
408
|
+
const identityServiceStrategySetup = new IdentityServiceStrategySetup(response.locals.customer.customerId);
|
|
409
|
+
const didUrl = constructDidUrl(didUrlParams);
|
|
410
|
+
if (!didUrl) {
|
|
411
|
+
return response.status(400).json({
|
|
412
|
+
error: `Invalid Request: Either didUrl or did with resource attributes are required`,
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
try {
|
|
416
|
+
const res = await identityServiceStrategySetup.agent.resolve(didUrl);
|
|
417
|
+
const resource = await res.json();
|
|
418
|
+
if (resource.dereferencingMetadata) {
|
|
419
|
+
return {
|
|
420
|
+
success: false,
|
|
421
|
+
status: 404,
|
|
422
|
+
error: `DID URL ${didUrl} is not found`,
|
|
423
|
+
};
|
|
424
|
+
}
|
|
425
|
+
const accreditation = resource;
|
|
426
|
+
const result = await identityServiceStrategySetup.agent.revokeCredentials(accreditation, publish, response.locals.customer, symmetricKey);
|
|
427
|
+
// Track operation if revocation was successful and publish is true
|
|
428
|
+
// Otherwise the StatusList2021 publisher should manually publish the resource
|
|
429
|
+
// and it will be tracked there
|
|
430
|
+
if (!result.error && result.resourceMetadata && publish) {
|
|
431
|
+
// get issuer did
|
|
432
|
+
const issuerDid = typeof accreditation.issuer === 'string'
|
|
433
|
+
? accreditation.issuer
|
|
434
|
+
: accreditation.issuer.id;
|
|
435
|
+
const trackInfo = {
|
|
436
|
+
category: OperationCategoryNameEnum.CREDENTIAL,
|
|
437
|
+
name: OperationNameEnum.CREDENTIAL_REVOKE,
|
|
438
|
+
customer: response.locals.customer,
|
|
439
|
+
user: response.locals.user,
|
|
440
|
+
data: {
|
|
441
|
+
did: issuerDid,
|
|
442
|
+
encrypted: result.statusList?.metadata?.encrypted,
|
|
443
|
+
resource: result.resourceMetadata,
|
|
444
|
+
symmetricKey: '',
|
|
445
|
+
},
|
|
446
|
+
};
|
|
447
|
+
// Track operation
|
|
448
|
+
eventTracker.emit('track', trackInfo);
|
|
449
|
+
}
|
|
450
|
+
// Return Ok response
|
|
451
|
+
return response.status(StatusCodes.OK).json(result);
|
|
452
|
+
}
|
|
453
|
+
catch (error) {
|
|
454
|
+
return response.status(StatusCodes.INTERNAL_SERVER_ERROR).json({
|
|
455
|
+
error: `Internal error: ${error?.message || error}`,
|
|
456
|
+
});
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
/**
|
|
460
|
+
* @openapi
|
|
461
|
+
*
|
|
462
|
+
* /trust-registry/accreditation/suspend:
|
|
463
|
+
* post:
|
|
464
|
+
* tags: [ Trust Registry ]
|
|
465
|
+
* summary: Suspend a Verifiable Accreditation.
|
|
466
|
+
* description: This endpoint suspends a given Verifiable Accreditation. As input, it can take the didUrl as a string. The StatusList2021 resource should already be setup in the VC and `credentialStatus` property present in the VC.
|
|
467
|
+
* operationId: accredit-suspend
|
|
468
|
+
* parameters:
|
|
469
|
+
* - in: query
|
|
470
|
+
* name: publish
|
|
471
|
+
* description: Set whether the StatusList2021 resource should be published to the ledger or not. If set to `false`, the StatusList2021 publisher should manually publish the resource.
|
|
472
|
+
* required: true
|
|
473
|
+
* schema:
|
|
474
|
+
* type: boolean
|
|
475
|
+
* default: true
|
|
476
|
+
* requestBody:
|
|
477
|
+
* content:
|
|
478
|
+
* application/x-www-form-urlencoded:
|
|
479
|
+
* schema:
|
|
480
|
+
* $ref: '#/components/schemas/AccreditationRevokeRequest'
|
|
481
|
+
* application/json:
|
|
482
|
+
* schema:
|
|
483
|
+
* $ref: '#/components/schemas/AccreditationRevokeRequest'
|
|
484
|
+
* responses:
|
|
485
|
+
* 200:
|
|
486
|
+
* description: The request was successful.
|
|
487
|
+
* content:
|
|
488
|
+
* application/json:
|
|
489
|
+
* schema:
|
|
490
|
+
* $ref: '#/components/schemas/RevocationResult'
|
|
491
|
+
* 400:
|
|
492
|
+
* $ref: '#/components/schemas/InvalidRequest'
|
|
493
|
+
* 401:
|
|
494
|
+
* $ref: '#/components/schemas/UnauthorizedError'
|
|
495
|
+
* 500:
|
|
496
|
+
* $ref: '#/components/schemas/InternalError'
|
|
497
|
+
*/
|
|
498
|
+
async suspend(request, response) {
|
|
499
|
+
// Get publish flag
|
|
500
|
+
const { publish } = request.query;
|
|
501
|
+
// Get symmetric key
|
|
502
|
+
const { symmetricKey, ...didUrlParams } = request.body;
|
|
503
|
+
// Get strategy e.g. postgres or local
|
|
504
|
+
const identityServiceStrategySetup = new IdentityServiceStrategySetup(response.locals.customer.customerId);
|
|
505
|
+
const didUrl = constructDidUrl(didUrlParams);
|
|
506
|
+
if (!didUrl) {
|
|
507
|
+
return response.status(400).json({
|
|
508
|
+
error: `Invalid Request: Either didUrl or did with resource attributes are required`,
|
|
509
|
+
});
|
|
510
|
+
}
|
|
511
|
+
try {
|
|
512
|
+
const res = await identityServiceStrategySetup.agent.resolve(didUrl);
|
|
513
|
+
const resource = await res.json();
|
|
514
|
+
if (resource.dereferencingMetadata) {
|
|
515
|
+
return {
|
|
516
|
+
success: false,
|
|
517
|
+
status: 404,
|
|
518
|
+
error: `DID URL ${didUrl} is not found`,
|
|
519
|
+
};
|
|
520
|
+
}
|
|
521
|
+
const accreditation = resource;
|
|
522
|
+
const result = await identityServiceStrategySetup.agent.suspendCredentials(accreditation, publish, response.locals.customer, symmetricKey);
|
|
523
|
+
// Track operation if revocation was successful and publish is true
|
|
524
|
+
// Otherwise the StatusList2021 publisher should manually publish the resource
|
|
525
|
+
// and it will be tracked there
|
|
526
|
+
if (!result.error && result.resourceMetadata && publish) {
|
|
527
|
+
// get issuer did
|
|
528
|
+
const issuerDid = typeof accreditation.issuer === 'string'
|
|
529
|
+
? accreditation.issuer
|
|
530
|
+
: accreditation.issuer.id;
|
|
531
|
+
const trackInfo = {
|
|
532
|
+
category: OperationCategoryNameEnum.CREDENTIAL,
|
|
533
|
+
name: OperationNameEnum.CREDENTIAL_SUSPEND,
|
|
534
|
+
customer: response.locals.customer,
|
|
535
|
+
user: response.locals.user,
|
|
536
|
+
data: {
|
|
537
|
+
did: issuerDid,
|
|
538
|
+
encrypted: result.statusList?.metadata?.encrypted,
|
|
539
|
+
resource: result.resourceMetadata,
|
|
540
|
+
symmetricKey: '',
|
|
541
|
+
},
|
|
542
|
+
};
|
|
543
|
+
// Track operation
|
|
544
|
+
eventTracker.emit('track', trackInfo);
|
|
545
|
+
}
|
|
546
|
+
// Return Ok response
|
|
547
|
+
return response.status(StatusCodes.OK).json(result);
|
|
548
|
+
}
|
|
549
|
+
catch (error) {
|
|
550
|
+
return response.status(StatusCodes.INTERNAL_SERVER_ERROR).json({
|
|
551
|
+
error: `Internal error: ${error?.message || error}`,
|
|
552
|
+
});
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
/**
|
|
556
|
+
* @openapi
|
|
557
|
+
*
|
|
558
|
+
* /trust-registry/accreditation/reinstate:
|
|
559
|
+
* post:
|
|
560
|
+
* tags: [ Trust Registry ]
|
|
561
|
+
* summary: Reinstate a Verifiable Accreditation.
|
|
562
|
+
* description: This endpoint reinstates a given Verifiable Accreditation. As input, it can take the didUrl as a string. The StatusList2021 resource should already be setup in the VC and `credentialStatus` property present in the VC.
|
|
563
|
+
* operationId: accredit-reinstate
|
|
564
|
+
* parameters:
|
|
565
|
+
* - in: query
|
|
566
|
+
* name: publish
|
|
567
|
+
* description: Set whether the StatusList2021 resource should be published to the ledger or not. If set to `false`, the StatusList2021 publisher should manually publish the resource.
|
|
568
|
+
* required: true
|
|
569
|
+
* schema:
|
|
570
|
+
* type: boolean
|
|
571
|
+
* default: true
|
|
572
|
+
* requestBody:
|
|
573
|
+
* content:
|
|
574
|
+
* application/x-www-form-urlencoded:
|
|
575
|
+
* schema:
|
|
576
|
+
* $ref: '#/components/schemas/AccreditationRevokeRequest'
|
|
577
|
+
* application/json:
|
|
578
|
+
* schema:
|
|
579
|
+
* $ref: '#/components/schemas/AccreditationRevokeRequest'
|
|
580
|
+
* responses:
|
|
581
|
+
* 200:
|
|
582
|
+
* description: The request was successful.
|
|
583
|
+
* content:
|
|
584
|
+
* application/json:
|
|
585
|
+
* schema:
|
|
586
|
+
* $ref: '#/components/schemas/RevocationResult'
|
|
587
|
+
* 400:
|
|
588
|
+
* $ref: '#/components/schemas/InvalidRequest'
|
|
589
|
+
* 401:
|
|
590
|
+
* $ref: '#/components/schemas/UnauthorizedError'
|
|
591
|
+
* 500:
|
|
592
|
+
* $ref: '#/components/schemas/InternalError'
|
|
593
|
+
*/
|
|
594
|
+
async reinstate(request, response) {
|
|
595
|
+
// Get publish flag
|
|
596
|
+
const { publish } = request.query;
|
|
597
|
+
// Get symmetric key
|
|
598
|
+
const { symmetricKey, ...didUrlParams } = request.body;
|
|
599
|
+
// Get strategy e.g. postgres or local
|
|
600
|
+
const identityServiceStrategySetup = new IdentityServiceStrategySetup(response.locals.customer.customerId);
|
|
601
|
+
const didUrl = constructDidUrl(didUrlParams);
|
|
602
|
+
if (!didUrl) {
|
|
603
|
+
return response.status(400).json({
|
|
604
|
+
error: `Invalid Request: Either didUrl or did with resource attributes are required`,
|
|
605
|
+
});
|
|
606
|
+
}
|
|
607
|
+
try {
|
|
608
|
+
const res = await identityServiceStrategySetup.agent.resolve(didUrl);
|
|
609
|
+
const resource = await res.json();
|
|
610
|
+
if (resource.dereferencingMetadata) {
|
|
611
|
+
return {
|
|
612
|
+
success: false,
|
|
613
|
+
status: 404,
|
|
614
|
+
error: `DID URL ${didUrl} is not found`,
|
|
615
|
+
};
|
|
616
|
+
}
|
|
617
|
+
const accreditation = resource;
|
|
618
|
+
const result = await identityServiceStrategySetup.agent.reinstateCredentials(accreditation, publish, response.locals.customer, symmetricKey);
|
|
619
|
+
// Track operation if revocation was successful and publish is true
|
|
620
|
+
// Otherwise the StatusList2021 publisher should manually publish the resource
|
|
621
|
+
// and it will be tracked there
|
|
622
|
+
if (!result.error && result.resourceMetadata && publish) {
|
|
623
|
+
// get issuer did
|
|
624
|
+
const issuerDid = typeof accreditation.issuer === 'string'
|
|
625
|
+
? accreditation.issuer
|
|
626
|
+
: accreditation.issuer.id;
|
|
627
|
+
const trackInfo = {
|
|
628
|
+
category: OperationCategoryNameEnum.CREDENTIAL,
|
|
629
|
+
name: OperationNameEnum.CREDENTIAL_UNSUSPEND,
|
|
630
|
+
customer: response.locals.customer,
|
|
631
|
+
user: response.locals.user,
|
|
632
|
+
data: {
|
|
633
|
+
did: issuerDid,
|
|
634
|
+
encrypted: result.statusList?.metadata?.encrypted || false,
|
|
635
|
+
resource: result.resourceMetadata,
|
|
636
|
+
symmetricKey: '',
|
|
637
|
+
},
|
|
638
|
+
};
|
|
639
|
+
// Track operation
|
|
640
|
+
eventTracker.emit('track', trackInfo);
|
|
641
|
+
}
|
|
642
|
+
// Return Ok response
|
|
643
|
+
return response.status(StatusCodes.OK).json(result);
|
|
644
|
+
}
|
|
645
|
+
catch (error) {
|
|
646
|
+
return response.status(StatusCodes.INTERNAL_SERVER_ERROR).json({
|
|
647
|
+
error: `Internal error: ${error?.message || error}`,
|
|
648
|
+
});
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
__decorate([
|
|
653
|
+
validate
|
|
654
|
+
], AccreditationController.prototype, "issue", null);
|
|
655
|
+
__decorate([
|
|
656
|
+
validate
|
|
657
|
+
], AccreditationController.prototype, "verify", null);
|
|
658
|
+
__decorate([
|
|
659
|
+
validate
|
|
660
|
+
], AccreditationController.prototype, "revoke", null);
|
|
661
|
+
__decorate([
|
|
662
|
+
validate
|
|
663
|
+
], AccreditationController.prototype, "suspend", null);
|
|
664
|
+
__decorate([
|
|
665
|
+
validate
|
|
666
|
+
], AccreditationController.prototype, "reinstate", null);
|
|
667
|
+
//# sourceMappingURL=accreditation.js.map
|