Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Added encrypted StatusList APIs + enhanced type safety #350

Merged
merged 39 commits into from
Aug 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
a4ea92b
Added base frame + major validation opts
Eengineer1 Aug 18, 2023
b90076d
Merge branch 'develop' into encrypted-status-list
Eengineer1 Aug 18, 2023
29765b7
Removed unsafe
Eengineer1 Aug 18, 2023
5acd82b
Removed redundant
Eengineer1 Aug 18, 2023
0031eb0
Added read ops + various type safety fixes
Eengineer1 Aug 21, 2023
f217c57
Added deep imports, enriched documentation + monkey patch json sortify
Eengineer1 Aug 21, 2023
58c9f4c
Merge branch 'develop' into encrypted-status-list
Eengineer1 Aug 21, 2023
081b3e7
Added ref + bump where relevant
Eengineer1 Aug 21, 2023
50d420a
Overall format
Eengineer1 Aug 21, 2023
6667055
Enhanced error handling
Eengineer1 Aug 21, 2023
fced224
Switch to enhanced type
Eengineer1 Aug 22, 2023
cc4c6d5
Swagger nits
Eengineer1 Aug 23, 2023
731ae3c
Merge branch 'develop' into encrypted-status-list
Eengineer1 Aug 23, 2023
0a9c306
bump
ankurdotb Aug 24, 2023
66cb1b8
npm run format
ankurdotb Aug 24, 2023
0d463df
Create unencrypted Swagger
ankurdotb Aug 24, 2023
26d1dab
Move AlsoKnownAs to own schema
ankurdotb Aug 24, 2023
9b393c9
CredentialStatusCreateEncryptedFormRequest
ankurdotb Aug 24, 2023
bba355d
CredentialStatusCreateEncryptedJsonRequest
ankurdotb Aug 24, 2023
72a64bf
Cosmetic fix
ankurdotb Aug 24, 2023
be73008
CredentialStatusUpdateUnencryptedRequest
ankurdotb Aug 24, 2023
4e699a4
Update swagger-types.ts
ankurdotb Aug 24, 2023
cb2de7c
CredentialStatusUpdateEncryptedFormRequest
ankurdotb Aug 25, 2023
eaf5b1d
CredentialStatusUpdateEncryptedJsonRequest
ankurdotb Aug 25, 2023
392f8db
integer
ankurdotb Aug 25, 2023
2d0c6ff
Update revocation.ts
ankurdotb Aug 25, 2023
13d7de5
Update shared.ts
ankurdotb Aug 25, 2023
5cbf86a
Update swagger-types.ts
ankurdotb Aug 25, 2023
4a64ef3
Update swagger-types.ts
ankurdotb Aug 25, 2023
97574a6
Update swagger-types.ts
ankurdotb Aug 25, 2023
727de63
CredentialStatusCreateUnencryptedResult
ankurdotb Aug 25, 2023
8b78e2e
CredentialStatusUpdateUnencryptedResult
ankurdotb Aug 25, 2023
9a2321b
CredentialStatusListSearchResult
ankurdotb Aug 25, 2023
3572952
CredentialStatusCreateEncryptedResult
ankurdotb Aug 25, 2023
93a5081
CredentialStatusUpdateEncryptedResult
ankurdotb Aug 25, 2023
6f012f6
CredentialStatusListSearchResult
ankurdotb Aug 25, 2023
4adcc97
npm update
ankurdotb Aug 25, 2023
da91947
Added runtime redundancy construct
Eengineer1 Aug 25, 2023
8040c63
bump
ankurdotb Aug 25, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2,341 changes: 1,118 additions & 1,223 deletions package-lock.json

Large diffs are not rendered by default.

26 changes: 14 additions & 12 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"build:app": "tsc",
"build:swagger": "swagger-jsdoc --definition src/static/swagger-options.json -o src/static/swagger.json ./src/controllers/*.ts ./src/types/swagger-types.ts",
"start": "node dist/index.js",
"start:local": "npm run build:app && npm run start",
"format": "prettier --write src/**/*.{js,ts,cjs,mjs}",
"lint": "eslint --max-warnings=0 src && prettier --check '*.{json,js}' 'src/**/*.{js,ts}' 'test/**/*.{js,ts}'",
"test": "jest --config jestconfig.json --verbose",
Expand All @@ -45,11 +46,12 @@
"README.md"
],
"dependencies": {
"@cheqd/did-provider-cheqd": "^3.6.4",
"@cheqd/did-provider-cheqd": "^3.6.6",
"@cheqd/sdk": "^3.6.1",
"@cosmjs/amino": "^0.31.0",
"@cosmjs/encoding": "^0.31.0",
"@logto/express": "^2.0.2",
"@cheqd/ts-proto": "^3.3.1",
"@cosmjs/amino": "^0.31.1",
"@cosmjs/encoding": "^0.31.1",
"@logto/express": "^2.1.0",
"@types/jsonwebtoken": "^9.0.2",
"@veramo/core": "^5.4.1",
"@veramo/credential-ld": "^5.4.1",
Expand All @@ -59,10 +61,10 @@
"@veramo/did-resolver": "^5.4.1",
"@veramo/key-manager": "^5.4.1",
"@veramo/kms-local": "^5.4.1",
"@verida/account-node": "^2.3.6",
"@verida/client-ts": "^2.3.6",
"@verida/account-node": "^2.3.7",
"@verida/client-ts": "^2.3.7",
"@verida/types": "^2.3.1",
"@verida/vda-did-resolver": "^2.3.6",
"@verida/vda-did-resolver": "^2.3.7",
"cookie-parser": "^1.4.6",
"copyfiles": "^2.4.1",
"cors": "^2.8.5",
Expand All @@ -89,7 +91,7 @@
"@semantic-release/commit-analyzer": "^10.0.1",
"@semantic-release/git": "^10.0.1",
"@semantic-release/github": "^9.0.4",
"@semantic-release/npm": "^10.0.4",
"@semantic-release/npm": "^10.0.5",
"@semantic-release/release-notes-generator": "^11.0.4",
"@types/cookie-parser": "^1.4.3",
"@types/cors": "^2.8.13",
Expand All @@ -98,7 +100,7 @@
"@types/express-session": "^1.17.7",
"@types/helmet": "^4.0.0",
"@types/json-stringify-safe": "^5.0.0",
"@types/node": "^20.5.0",
"@types/node": "^20.5.6",
"@types/secp256k1": "^4.0.3",
"@types/swagger-jsdoc": "^6.0.1",
"@types/swagger-ui-express": "^4.1.3",
Expand All @@ -110,14 +112,14 @@
"eslint": "^8.47.0",
"eslint-config-prettier": "^9.0.0",
"eslint-config-typescript": "^3.0.0",
"jest": "^29.6.2",
"jest": "^29.6.4",
"prettier": "^3.0.2",
"semantic-release": "^21.0.7",
"semantic-release": "^21.1.1",
"swagger-jsdoc": "^6.2.8",
"ts-jest": "^29.1.1",
"ts-loader": "^9.4.4",
"ts-node": "^10.9.1",
"typescript": "^5.1.6",
"typescript": "^5.2.2",
"uint8arrays": "^4.0.6"
},
"publishConfig": {
Expand Down
46 changes: 33 additions & 13 deletions src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,27 @@ import { RevocationController } from './controllers/revocation.js';
import { CORS_ALLOWED_ORIGINS, CORS_ERROR_MSG, configLogToExpress } from './types/constants.js';
import { LogToWebHook } from './middleware/hook.js';
import { Middleware } from './middleware/middleware.js';
import { JSONStringify } from './monkey-patch.js';

import * as dotenv from 'dotenv';
dotenv.config();

// monkey patch JSON.stringify to use native-like implementation
// TODO: remove this when @verida/encryption-utils,
// TODO: switches json.sortify to its own implementation
// TODO: e.g. replace JSON.stringify = require('json.sortify')
// TODO: with JSON.sortify = require('json.sortify')
// see: https://github.com/verida/verida-js/blob/c94b95de687c64cc776652602665bb45a327dfb6/packages/encryption-utils/src/index.ts#L10
// eslint-disable-next-line @typescript-eslint/no-unused-vars
JSON.stringify = function (value, _replacer, _space) {
return (
JSONStringify(value) ||
(function () {
throw new Error('JSON.stringify failed');
})()
);
};

// Define Swagger file
import swaggerDocument from './static/swagger.json' assert { type: 'json' };
import { handleAuthRoutes, withLogto } from '@logto/express';
Expand Down Expand Up @@ -116,30 +133,33 @@ class App {

// revocation
app.post(
'/credential-status/create',
RevocationController.commonValidator,
RevocationController.createValidator,
new RevocationController().createStatusList
'/credential-status/create/unencrypted',
RevocationController.createUnencryptedValidator,
new RevocationController().createUnencryptedStatusList
);
app.post(
'/credential-status/create/encrypted',
RevocationController.createEncryptedValidator,
new RevocationController().createEncryptedStatusList
);
app.post(
'/credential-status/update',
RevocationController.updateValidator,
new RevocationController().updateStatusList
'/credential-status/update/unencrypted',
RevocationController.updateUnencryptedValidator,
new RevocationController().updateUnencryptedStatusList
);
app.post(
'/credential-status/publish',
RevocationController.commonValidator,
new RevocationController().publishStatusList
'/credential-status/update/encrypted',
RevocationController.updateEncryptedValidator,
new RevocationController().updateEncryptedStatusList
);
app.post(
'/credential-status/check',
RevocationController.commonValidator,
RevocationController.checkValidator,
new RevocationController().checkStatusList
);
app.get(
'/credential-status/search',
RevocationController.commonValidator,
RevocationController.searchValidator,
new RevocationController().searchStatusList
);

Expand All @@ -156,7 +176,7 @@ class App {

// Resource API
app.post('/resource/create/:did', IssuerController.resourceValidator, new IssuerController().createResource);
app.get('/resource/search/:did', new IssuerController().getResource);
app.get('/resource/search/:did', new IssuerController().getResource);

// Account API
app.post('/account', new AccountController().create);
Expand Down
14 changes: 7 additions & 7 deletions src/controllers/credentials.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { StatusCodes } from 'http-status-codes';
import { check, query, validationResult } from 'express-validator';

import { Credentials } from '../services/credentials.js';
import { IdentityStrategySetup } from '../services/identity/index.js';
import { IdentityServiceStrategySetup } from '../services/identity/index.js';

export class CredentialController {
public static issueValidator = [
Expand Down Expand Up @@ -167,7 +167,7 @@ export class CredentialController {
const { credential, policies } = request.body;
const verifyStatus = request.query.verifyStatus === 'true' ? true : false;
try {
const result = await new IdentityStrategySetup(response.locals.customerId).agent.verifyCredential(
const result = await new IdentityServiceStrategySetup(response.locals.customerId).agent.verifyCredential(
credential,
{
verifyStatus,
Expand Down Expand Up @@ -239,7 +239,7 @@ export class CredentialController {
return response
.status(StatusCodes.OK)
.json(
await new IdentityStrategySetup(response.locals.customerId).agent.revokeCredentials(
await new IdentityServiceStrategySetup(response.locals.customerId).agent.revokeCredentials(
request.body.credential,
publish,
response.locals.customerId
Expand Down Expand Up @@ -299,7 +299,7 @@ export class CredentialController {
return response
.status(StatusCodes.OK)
.json(
await new IdentityStrategySetup(response.locals.customerId).agent.suspendCredentials(
await new IdentityServiceStrategySetup(response.locals.customerId).agent.suspendCredentials(
request.body.credential,
request.body.publish,
response.locals.customerId
Expand Down Expand Up @@ -341,7 +341,7 @@ export class CredentialController {
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/UnSuspensionResult'
* $ref: '#/components/schemas/UnsuspensionResult'
* 400:
* $ref: '#/components/schemas/InvalidRequest'
* 401:
Expand All @@ -359,7 +359,7 @@ export class CredentialController {
return response
.status(StatusCodes.OK)
.json(
await new IdentityStrategySetup(response.locals.customerId).agent.reinstateCredentials(
await new IdentityServiceStrategySetup(response.locals.customerId).agent.reinstateCredentials(
request.body.credential,
request.body.publish,
response.locals.customerId
Expand Down Expand Up @@ -425,7 +425,7 @@ export class CredentialController {
const { presentation, verifierDid, policies } = request.body;
const verifyStatus = request.query.verifyStatus === 'true' ? true : false;
try {
const result = await new IdentityStrategySetup(response.locals.customerId).agent.verifyPresentation(
const result = await new IdentityServiceStrategySetup(response.locals.customerId).agent.verifyPresentation(
presentation,
{
verifyStatus,
Expand Down
42 changes: 24 additions & 18 deletions src/controllers/issuer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { MethodSpecificIdAlgo, VerificationMethods, CheqdNetwork } from '@cheqd/
import type { MsgCreateResourcePayload } from '@cheqd/ts-proto/cheqd/resource/v2/index.js';
import { StatusCodes } from 'http-status-codes';

import { IdentityStrategySetup } from '../services/identity/index.js';
import { IdentityServiceStrategySetup } from '../services/identity/index.js';
import { generateDidDoc, getQueryParams, validateSpecCompliantPayload } from '../helpers/helpers.js';

export class IssuerController {
Expand Down Expand Up @@ -107,7 +107,7 @@ export class IssuerController {
*/
public async createKey(request: Request, response: Response) {
try {
const key = await new IdentityStrategySetup(response.locals.customerId).agent.createKey(
const key = await new IdentityServiceStrategySetup(response.locals.customerId).agent.createKey(
'Ed25519',
response.locals.customerId
);
Expand Down Expand Up @@ -162,7 +162,7 @@ export class IssuerController {
*/
public async getKey(request: Request, response: Response) {
try {
const key = await new IdentityStrategySetup(response.locals.customerId).agent.getKey(
const key = await new IdentityServiceStrategySetup(response.locals.customerId).agent.getKey(
request.params.kid,
response.locals.customerId
);
Expand Down Expand Up @@ -236,7 +236,7 @@ export class IssuerController {
if (request.body.didDocument) {
didDocument = request.body.didDocument;
} else if (verificationMethodType) {
const key = await new IdentityStrategySetup(response.locals.customerId).agent.createKey(
const key = await new IdentityServiceStrategySetup(response.locals.customerId).agent.createKey(
'Ed25519',
response.locals.customerId
);
Expand Down Expand Up @@ -267,7 +267,7 @@ export class IssuerController {
});
}

const did = await new IdentityStrategySetup(response.locals.customerId).agent.createDid(
const did = await new IdentityServiceStrategySetup(response.locals.customerId).agent.createDid(
network || didDocument.id.split(':')[2],
didDocument,
response.locals.customerId
Expand Down Expand Up @@ -329,7 +329,9 @@ export class IssuerController {
if (request.body.didDocument) {
updatedDocument = request.body.didDocument;
} else if (did && (service || verificationMethod || authentication)) {
const resolvedResult = await new IdentityStrategySetup(response.locals.customerId).agent.resolveDid(did);
const resolvedResult = await new IdentityServiceStrategySetup(
response.locals.customerId
).agent.resolveDid(did);
if (!resolvedResult?.didDocument || resolvedResult.didDocumentMetadata.deactivated) {
return response.status(StatusCodes.BAD_REQUEST).send({
error: `${did} is either Deactivated or Not found`,
Expand All @@ -355,7 +357,7 @@ export class IssuerController {
});
}

const result = await new IdentityStrategySetup(response.locals.customerId).agent.updateDid(
const result = await new IdentityServiceStrategySetup(response.locals.customerId).agent.updateDid(
updatedDocument,
response.locals.customerId
);
Expand Down Expand Up @@ -405,7 +407,7 @@ export class IssuerController {
}

try {
const did = await new IdentityStrategySetup(response.locals.customerId).agent.deactivateDid(
const did = await new IdentityServiceStrategySetup(response.locals.customerId).agent.deactivateDid(
request.params.did,
response.locals.customerId
);
Expand Down Expand Up @@ -464,7 +466,7 @@ export class IssuerController {
let resourcePayload: Partial<MsgCreateResourcePayload> = {};
try {
// check if did is registered on the ledger
const { didDocument, didDocumentMetadata } = await new IdentityStrategySetup(
const { didDocument, didDocumentMetadata } = await new IdentityServiceStrategySetup(
response.locals.customerId
).agent.resolveDid(did);
if (!didDocument || !didDocumentMetadata || didDocumentMetadata.deactivated) {
Expand All @@ -482,7 +484,7 @@ export class IssuerController {
version,
alsoKnownAs,
};
const result = await new IdentityStrategySetup(response.locals.customerId).agent.createResource(
const result = await new IdentityServiceStrategySetup(response.locals.customerId).agent.createResource(
network || did.split(':')[2],
resourcePayload,
response.locals.customerId
Expand Down Expand Up @@ -580,14 +582,14 @@ export class IssuerController {
try {
let res: globalThis.Response;
if (request.params.did) {
res = await new IdentityStrategySetup(response.locals.customerId).agent.resolve(
res = await new IdentityServiceStrategySetup(response.locals.customerId).agent.resolve(
request.params.did + getQueryParams(request.query)
);

const contentType = res.headers.get('Content-Type');
const contentType = res.headers.get('Content-Type') || 'application/octet-stream';
const body = new TextDecoder().decode(await res.arrayBuffer());

return response.setHeader('Content-Type', contentType!).status(res.status).send(body);
return response.setHeader('Content-Type', contentType).status(res.status).send(body);
} else {
return response.status(StatusCodes.BAD_REQUEST).json({
error: 'The DID parameter is empty.',
Expand Down Expand Up @@ -627,8 +629,12 @@ export class IssuerController {
public async getDids(request: Request, response: Response) {
try {
const did = request.params.did
? await new IdentityStrategySetup(response.locals.customerId).agent.resolveDid(request.params.did)
: await new IdentityStrategySetup(response.locals.customerId).agent.listDids(response.locals.customerId);
? await new IdentityServiceStrategySetup(response.locals.customerId).agent.resolveDid(
request.params.did
)
: await new IdentityServiceStrategySetup(response.locals.customerId).agent.listDids(
response.locals.customerId
);

return response.status(StatusCodes.OK).json(did);
} catch (error) {
Expand Down Expand Up @@ -712,14 +718,14 @@ export class IssuerController {
try {
let res: globalThis.Response;
if (request.params.did) {
res = await new IdentityStrategySetup(response.locals.customerId).agent.resolve(
res = await new IdentityServiceStrategySetup(response.locals.customerId).agent.resolve(
request.params.did + getQueryParams(request.query)
);

const contentType = res.headers.get('Content-Type');
const contentType = res.headers.get('Content-Type') || 'application/octet-stream';
const body = new TextDecoder().decode(await res.arrayBuffer());

return response.setHeader('Content-Type', contentType!).status(res.status).send(body);
return response.setHeader('Content-Type', contentType).status(res.status).send(body);
} else {
return response.status(StatusCodes.BAD_REQUEST).json({
error: 'The DIDUrl parameter is empty.',
Expand Down
Loading