Skip to content

Commit

Permalink
feat: Add verify presentation API and update StatusList APIs [DEV-281…
Browse files Browse the repository at this point in the history
…1] & [DEV-2669] (#265)

* feat: Init presentation

* feat: Add did:key resolver

* feat: Add uniresolver && update policies

* feat: Add broadcast statusList api

* feat: Update swagger

* feat: Add did update && deactivate operations

* feat: Update swagger

* fix: External db bug && api paths

* feat: Support urlencoded request body

* feat: Update swagger

* feat: Refactor inputs

* fix: Array issues with urlencoded

* feat: Add credential-status update api

* fix: DID update in chunks

* bump deps

* feat: Update credential-status and verify api's

* fix: credential verify

* feat: Update indices mandatory in statusUpdate

* Update package-lock.json

* fix: Presentation api example

* fix: Minor issues

* Update package-lock.json

---------

Co-authored-by: Ankur Banerjee <ankurdotb@users.noreply.github.com>
  • Loading branch information
DaevMithran and ankurdotb authored Jul 7, 2023
1 parent 99eac3b commit 4e43430
Show file tree
Hide file tree
Showing 17 changed files with 2,061 additions and 546 deletions.
552 changes: 443 additions & 109 deletions package-lock.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
"README.md"
],
"dependencies": {
"@cheqd/did-provider-cheqd": "3.3.1",
"@cheqd/did-provider-cheqd": "^3.4.1",
"@cosmjs/amino": "^0.31.0",
"@cosmjs/encoding": "^0.30.1",
"@logto/express": "^2.0.2",
Expand All @@ -52,13 +52,13 @@
"@veramo/credential-w3c": "^5.2.0",
"@veramo/data-store": "^5.2.0",
"@veramo/did-manager": "^5.1.2",
"@veramo/did-provider-key": "^5.2.0",
"@veramo/did-resolver": "^5.2.0",
"@veramo/key-manager": "^5.1.2",
"@veramo/kms-local": "^5.1.2",
"@verida/account-node": "^2.3.5",
"@verida/client-ts": "^2.3.5",
"@verida/types": "^2.3.1",
"@verida/vda-did-resolver": "^2.3.5",
"cookie-parser": "^1.4.6",
"copyfiles": "^2.4.1",
"cors": "^2.8.5",
Expand Down
30 changes: 21 additions & 9 deletions src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import cors from 'cors'
import swaggerUi from 'swagger-ui-express'
import session from 'express-session'
import cookieParser from 'cookie-parser'
import {withLogto, handleAuthRoutes } from '@logto/express'

import { CredentialController } from './controllers/credentials.js'
import { StoreController } from './controllers/store.js'
Expand All @@ -13,7 +12,7 @@ import { CustomerController } from './controllers/customer.js'
import { Authentication } from './middleware/authentication.js'
import { Connection } from './database/connection/connection.js'
import { RevocationController } from './controllers/revocation.js'
import { CORS_ERROR_MSG, configLogToExpress } from './types/constants.js'
import { CORS_ERROR_MSG } from './types/constants.js'

import swaggerJSONDoc from './static/swagger.json' assert { type: "json" }

Expand All @@ -22,6 +21,8 @@ dotenv.config()

import { UserInfo } from './controllers/user_info.js'
import path from 'path'
import e from 'express'
import { Middleware } from './middleware/middleware.js'

let swagger_options = {}
if (process.env.ENABLE_AUTHENTICATION === 'true') {
Expand All @@ -42,7 +43,8 @@ class App {

private middleware() {
this.express.use(express.json({ limit: '50mb' }))
this.express.use(express.urlencoded({ extended: false }))
this.express.use(express.urlencoded({ extended: true }))
this.express.use(Middleware.parseUrlEncodedJson)
this.express.use(Helmet())
this.express.use(cors({
origin: function(origin, callback){
Expand All @@ -61,7 +63,9 @@ class App {
// Authentication funcitons/methods
this.express.use(Authentication.wrapperHandleAuthRoutes)
this.express.use(Authentication.withLogtoWrapper)
this.express.use(Authentication.guard)
}
if (process.env.ENABLE_EXTERNAL_DB === 'true') {
this.express.use(Authentication.guard)
}
this.express.use(express.text())

Expand Down Expand Up @@ -89,20 +93,28 @@ class App {
app.post('/credential/suspend', new CredentialController().suspend)
app.post('/credential/reinstate', new CredentialController().reinstate)

//credential-status
app.post('/credential-status/statusList2021/create', RevocationController.didValidator, RevocationController.statusListValidator, new RevocationController().createStatusList)
app.get('/credential-status/statusList2021/list', RevocationController.didValidator, new RevocationController().fetchStatusList)
// presentation
app.post(`/presentation/verify`, CredentialController.presentationValidator, new CredentialController().verifyPresentation)

//revocation
app.post('/credential-status/create', RevocationController.queryValidator, RevocationController.statusListValidator, new RevocationController().createStatusList)
app.post('/credential-status/update', RevocationController.updateValidator, new RevocationController().updateStatusList)
app.post('/credential-status/publish', RevocationController.queryValidator, new RevocationController().createStatusList)
app.get('/credential-status/search', RevocationController.queryValidator, new RevocationController().fetchStatusList)

// store
app.post(`/store`, new StoreController().set)
app.get(`/store/:id`, new StoreController().get)

// issuer
app.post(`/key/create`, new IssuerController().createKey)
app.get(`/key/:kid`, new IssuerController().getKey)
app.post(`/did/create`, IssuerController.didValidator, new IssuerController().createDid)
app.post(`/did/create`, IssuerController.createValidator, new IssuerController().createDid)
app.post(`/did/update`, IssuerController.updateValidator, new IssuerController().updateDid)
app.post(`/did/deactivate/:did`, IssuerController.deactivateValidator, new IssuerController().deactivateDid)
app.get(`/did/list`, new IssuerController().getDids)
app.get(`/did/:did`, new IssuerController().getDids)
app.post(`/:did/create-resource`, IssuerController.resourceValidator, new IssuerController().createResource)
app.post(`/resource/create/:did`, IssuerController.resourceValidator, new IssuerController().createResource)

// customer
app.post(`/account`, new CustomerController().create)
Expand Down
62 changes: 55 additions & 7 deletions src/controllers/credentials.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { Request, Response } from 'express'
import type { VerifiableCredential } from '@veramo/core'

import { check, validationResult } from 'express-validator'
import { check, query, validationResult } from 'express-validator'

import { Credentials } from '../services/credentials.js'
import { Identity } from '../services/identity/index.js'
Expand All @@ -16,8 +16,6 @@ export class CredentialController {
check('attributes')
.exists().withMessage('attributes are required')
.isObject().withMessage('attributes should be an object'),
check('type').optional().isArray().withMessage('type should be a string array'),
check('@context').optional().isArray().withMessage('@context should be a string array'),
check('expirationDate').optional().isDate().withMessage('Invalid expiration date'),
check('format').optional().isString().withMessage('Invalid credential format')
]
Expand All @@ -31,14 +29,34 @@ export class CredentialController {
return false
})
.withMessage('Entry must be a jwt string or an credential'),
check('publish').optional().isBoolean().withMessage('publish should be a boolean value')
query('publish').optional().isBoolean().withMessage('publish should be a boolean value')
]

public static presentationValidator = [
check('presentation').exists().withMessage('W3c verifiable presentation was not provided')
.custom((value) => {
if (typeof value === 'string' || typeof value === 'object') {
return true
}
return false
})
.withMessage('Entry must be a jwt string or a presentation'),
]

public async issue(request: Request, response: Response) {
const result = validationResult(request)
if (!result.isEmpty()) {
return response.status(400).json({ error: result.array()[0].msg })
}

// Handles string input instead of an array
if(typeof request.body.type === 'string') {
request.body.type = [request.body.type]
}
if(typeof request.body['@context'] === 'string') {
request.body['@context'] = [request.body['@context']]
}

try {
const credential: VerifiableCredential = await Credentials.instance.issue_credential(request.body, response.locals.customerId)
response.status(200).json(credential)
Expand All @@ -59,7 +77,14 @@ export class CredentialController {
return response.status(400).json({ error: result.array()[0].msg })
}
try {
return response.status(200).json(await Credentials.instance.verify_credentials(request.body.credential, request.body.statusOptions, response.locals.customerId))
const result = await Credentials.instance.verify_credentials(request.body.credential, request.body.statusOptions, response.locals.customerId)
if (result.error) {
return response.status(400).json({
verified: result.verified,
error: result.error
})
}
return response.status(200).json(result)
} catch (error) {
return response.status(500).json({
error: `${error}`
Expand All @@ -72,9 +97,10 @@ export class CredentialController {
if (!result.isEmpty()) {
return response.status(400).json({ error: result.array()[0].msg })
}


const publish = request.query.publish === 'false' ? false : true
try {
return response.status(200).json(await Identity.instance.revokeCredentials(request.body.credential, request.body.publish, response.locals.customerId))
return response.status(200).json(await Identity.instance.revokeCredentials(request.body.credential, publish, response.locals.customerId))
} catch (error) {
return response.status(500).json({
error: `${error}`
Expand Down Expand Up @@ -111,4 +137,26 @@ export class CredentialController {
})
}
}

public async verifyPresentation(request: Request, response: Response) {
const result = validationResult(request)
if (!result.isEmpty()) {
return response.status(400).json({ error: result.array()[0].msg })
}

try {
const result = await Identity.instance.verifyPresentation(request.body.presentation, request.body.statusOptions, response.locals.customerId)
if (result.error) {
return response.status(400).json({
verified: result.verified,
error: result.error
})
}
return response.status(200).json(result)
} catch (error) {
return response.status(500).json({
error: `${error}`
})
}
}
}
Loading

0 comments on commit 4e43430

Please sign in to comment.