diff --git a/src/controllers/credentials.ts b/src/controllers/credentials.ts index a636e9e8..8f19c5e9 100644 --- a/src/controllers/credentials.ts +++ b/src/controllers/credentials.ts @@ -6,6 +6,204 @@ import { check, query, validationResult } from 'express-validator' import { Credentials } from '../services/credentials.js' import { Identity } from '../services/identity/index.js' +/** + * @openapi + * + * components: + * schemas: + * CredentialRequest: + * description: Input fields for the create operation. + * type: object + * additionalProperties: false + * properties: + * issuerDid: + * description: This input field is the Issuer's DID. + * type: string + * example: did:cheqd:testnet:7bf81a20-633c-4cc7-bc4a-5a45801005e0 + * subjectDid: + * description: This input field is the holder's DID. + * type: string + * example: did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK + * attributes: + * description: Json input of the attributes. + * type: object + * example: + * gender: male + * name: bob + * '@context': + * description: Additional contexts to be included in the credential. + * type: array + * items: + * type: string + * example: + * - https://schema.org + * type: + * description: Additional type property to be included in the credential. + * type: array + * items: + * type: string + * example: + * - Person + * expirationDate: + * description: Optional expiration date according to the https://www.w3.org/TR/vc-data-model/#expiration specification. + * format: + * description: Select one of the supported credential formats, jwt by default. + * type: string + * enum: + * - jwt + * - lds + * example: jwt + * credentialStatus: + * description: Optional field to support revocation or suspension, which takes statusListName and statusListPurpose as inputs. + * type: object + * required: + * - statusPurpose + * - statusListName + * properties: + * statusPurpose: + * type: string + * enum: + * - revocation + * - suspension + * example: revocation + * statusListName: + * type: string + * example: employee-credentials + * statusListIndex: + * type: number + * example: 10 + * statusListVersion: + * type: string + * statusListRangeStart: + * type: number + * statusListRangeEnd: + * type: number + * indexNotIn: + * type: number + * required: [issuerDid, subjectDid, attributes] + * Credential: + * description: Input fields for the update operation. + * type: object + * additionalProperties: false + * properties: + * '@context': + * type: array + * items: + * type: string + * example: + * - https://www.w3.org/2018/credentials/v1 + * - https://schema.org + * - https://veramo.io/contexts/profile/v1 + * type: + * type: array + * items: + * type: string + * example: + * - VerifiableCredential + * - Person + * expirationDate: + * type: string + * issuer: + * type: object + * properties: + * id: + * type: string + * example: did:cheqd:testnet:7bf81a20-633c-4cc7-bc4a-5a45801005e0 + * credentialSubject: + * type: object + * properties: + * id: + * type: string + * example: + * gender: male + * id: did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK + * name: Bob + * credentialStatus: + * type: object + * properties: + * id: + * type: string + * example: https://resolver.cheqd.net/1.0/identifiers/did:cheqd:testnet:7c2b990c-3d05-4ebf-91af-f4f4d0091d2e?resourceName=cheqd-suspension-1&resourceType=StatusList2021Suspension#20 + * statusListIndex: + * type: string + * example: 20 + * statusPurpose: + * type: string + * enum: + * - revocation + * - suspension + * example: suspension + * type: + * type: string + * enum: + * - StatusList2021Entry + * example: StatusList2021Entry + * issuanceDate: + * type: string + * example: 2023-06-08T13:49:28.000Z + * proof: + * type: object + * properties: + * type: + * type: string + * example: JwtProof2020 + * jwt: + * type: string + * example: eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJkaWQ6Y2hlcWQ6dGVzdG5ldDo3YmY4MWEyMC02MzNjLTRjYzctYmM0YS01YTQ1ODAxMDA1ZTAiLCJuYmYiOjE2ODYyMzIxNjgsInN1YiI6ImRpZDprZXk6ejZNa2hhWGdCWkR2b3REa0w1MjU3ZmFpenRpR2lDMlF0S0xHcGJubkVHdGEyZG9LIiwidmMiOnsiQGNvbnRleHQiOlsiaHR0cHM6Ly93d3cudzMub3JnLzIwMTgvY3JlZGVudGlhbHMvdjEiLCJodHRwczovL3NjaGVtYS5vcmciLCJodHRwczovL3ZlcmFtby5pby9jb250ZXh0cy9wcm9maWxlL3YxIl0sImNyZWRlbnRpYWxTdWJqZWN0Ijp7ImdlbmRlciI6Im1hbGUiLCJuYW1lIjoiQm9iIn0sInR5cGUiOlsiVmVyaWZpYWJsZUNyZWRlbnRpYWwiLCJQZXJzb24iXX19.wMfdR6RtyAZA4eoWya5Aw97wwER2Cm5Guk780Xw8H9fA3sfudIJeLRLboqixpTchqSbYeA7KbuCTAnLgXTD_Cg + * CredentialRevokeRequest: + * type: object + * properties: + * credential: + * description: This input field takes the credential object or the JWT string + * oneOf: + * - type: object + * - type: string + * RevocationResult: + * properties: + * revoked: + * type: boolean + * SuspensionResult: + * properties: + * suspended: + * type: boolean + * statusList: + * type: string + * UnSuspensionResult: + * properties: + * unsuspended: + * type: boolean + * statusList: + * type: string + * CredentialVerifyRequest: + * type: object + * properties: + * credential: + * description: This input field takes the credential object or the JWT string.\ + * allOf: + * - type: object + * - type: string + * IVerifyResult: + * type: object + * properties: + * verified: + * type: boolean + * example: true + * issuer: + * type: string + * example: did:cheqd:testnet:7bf81a20-633c-4cc7-bc4a-5a45801005e0 + * signer: + * type: object + * example: + * controller: did:cheqd:testnet:7bf81a20-633c-4cc7-bc4a-5a45801005e0 + * id: did:cheqd:testnet:7bf81a20-633c-4cc7-bc4a-5a45801005e0#key-1 + * publicKeyBase58: BTJiso1S4iSiReP6wGksSneGfiKHxz9SYcm2KknpqBJt + * type: Ed25519VerificationKey2018 + * jwt: + * type: string + * verifiableCredential: + * type: object + */ + export class CredentialController { public static issueValidator = [ @@ -43,6 +241,49 @@ export class CredentialController { .withMessage('Entry must be a jwt string or a presentation'), ] + /** + * @openapi + * + * /credential/issue: + * post: + * tags: [ Credential ] + * summary: Issue a credential. + * description: This endpoint issues a credential. As input it takes the list of attributes, subjectDid, context and expiration date of the credential to be issued. + * security: [ bearerAuth: [] ] + * requestBody: + * content: + * application/x-www-form-urlencoded: + * schema: + * $ref: '#/components/schemas/CredentialRequest' + * application/json: + * schema: + * $ref: '#/components/schemas/CredentialRequest' + * responses: + * 200: + * description: The request was successful. + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/Credential' + * 400: + * description: A problem with the input fields has occurred. Additional state information plus metadata may be available in the response body. + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/InvalidRequest' + * example: + * error: Invalid Request + * 401: + * $ref: '#/components/schemas/UnauthorizedError' + * 500: + * description: An internal error has occurred. Additional state information plus metadata may be available in the response body. + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/InvalidRequest' + * example: + * error: Internal Error + */ public async issue(request: Request, response: Response) { const result = validationResult(request) if (!result.isEmpty()) { @@ -92,6 +333,57 @@ export class CredentialController { } } + /** + * @openapi + * + * /credential/revoke: + * post: + * tags: [ Credential ] + * summary: Revoke a credential. + * description: This endpoint verifies the credential. As input it takes the entire credential itself or just the JWT string. + * operationId: revoke + * security: [ bearerAuth: [] ] + * parameters: + * - in: query + * name: publish + * required: true + * schema: + * type: boolean + * default: true + * requestBody: + * content: + * application/x-www-form-urlencoded: + * schema: + * $ref: '#/components/schemas/CredentialRevokeRequest' + * application/json: + * schema: + * $ref: '#/components/schemas/CredentialRevokeRequest' + * responses: + * 200: + * description: The request was successful. + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/RevocationResult' + * 400: + * description: A problem with the input fields has occurred. Additional state information plus metadata may be available in the response body. + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/InvalidRequest' + * example: + * error: Invalid Request + * 401: + * $ref: '#/components/schemas/UnauthorizedError' + * 500: + * description: An internal error has occurred. Additional state information plus metadata may be available in the response body. + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/InvalidRequest' + * example: + * error: Internal Error + */ public async revoke(request: Request, response: Response) { const result = validationResult(request) if (!result.isEmpty()) { @@ -108,6 +400,55 @@ export class CredentialController { } } + /** + * @openapi + * + * /credential/suspend: + * post: + * tags: [ Credential ] + * summary: Suspend a credential. + * description: This endpoint suspends the credential. As input it takes the entire credential itself. + * operationId: suspend + * security: [ bearerAuth: [] ] + * parameters: + * - in: query + * name: publish + * schema: + * type: boolean + * requestBody: + * content: + * application/x-www-form-urlencoded: + * schema: + * $ref: '#/components/schemas/CredentialRevokeRequest' + * application/json: + * schema: + * $ref: '#/components/schemas/CredentialRevokeRequest' + * responses: + * 200: + * description: The request was successful. + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/SuspensionResult' + * 400: + * description: A problem with the input fields has occurred. Additional state information plus metadata may be available in the response body. + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/InvalidRequest' + * example: + * error: Invalid Request + * 401: + * $ref: '#/components/schemas/UnauthorizedError' + * 500: + * description: An internal error has occurred. Additional state information plus metadata may be available in the response body. + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/InvalidRequest' + * example: + * error: Internal Error + */ public async suspend(request: Request, response: Response) { const result = validationResult(request) if (!result.isEmpty()) { @@ -123,6 +464,55 @@ export class CredentialController { } } + /** + * @openapi + * + * /credential/reinstate: + * post: + * tags: [ Credential ] + * summary: Reinstate a credential. + * description: This endpoint reinstates the credential. As input it takes the entire credential itself. + * operationId: reinstate + * security: [ bearerAuth: [] ] + * parameters: + * - in: query + * name: publish + * schema: + * type: boolean + * requestBody: + * content: + * application/x-www-form-urlencoded: + * schema: + * $ref: '#/components/schemas/CredentialRevokeRequest' + * application/json: + * schema: + * $ref: '#/components/schemas/CredentialRevokeRequest' + * responses: + * 200: + * description: The request was successful. + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/UnSuspensionResult' + * 400: + * description: A problem with the input fields has occurred. Additional state information plus metadata may be available in the response body. + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/InvalidRequest' + * example: + * error: Invalid Request + * 401: + * $ref: '#/components/schemas/UnauthorizedError' + * 500: + * description: An internal error has occurred. Additional state information plus metadata may be available in the response body. + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/InvalidRequest' + * example: + * error: Internal Error + */ public async reinstate(request: Request, response: Response) { const result = validationResult(request) if (!result.isEmpty()) { @@ -137,7 +527,50 @@ export class CredentialController { }) } } - + /** + * @openapi + * + * /credential/verify: + * post: + * tags: [ Credential ] + * summary: Verify a credential. + * description: This endpoint verifies the credential. As input it takes the entire credential itself or just the JWT string. + * operationId: verify + * security: [ bearerAuth: [] ] + * requestBody: + * content: + * application/x-www-form-urlencoded: + * schema: + * $ref: '#/components/schemas/CredentialVerifyRequest' + * application/json: + * schema: + * $ref: '#/components/schemas/CredentialVerifyRequest' + * responses: + * 200: + * description: The request was successful. + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/IVerifyResult' + * 400: + * description: A problem with the input fields has occurred. Additional state information plus metadata may be available in the response body. + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/InvalidRequest' + * example: + * error: Invalid Request + * 401: + * $ref: '#/components/schemas/UnauthorizedError' + * 500: + * description: An internal error has occurred. Additional state information plus metadata may be available in the response body. + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/InvalidRequest' + * example: + * error: Internal Error + */ public async verifyPresentation(request: Request, response: Response) { const result = validationResult(request) if (!result.isEmpty()) { diff --git a/src/controllers/issuer.ts b/src/controllers/issuer.ts index 12c1066a..e1509b1b 100644 --- a/src/controllers/issuer.ts +++ b/src/controllers/issuer.ts @@ -143,157 +143,6 @@ import { generateDidDoc, isValidService, isValidVerificationMethod, validateSpec * type: string * didDocument: * $ref: '#/components/schemas/DidDocument' - * CredentialRequest: - * description: Input fields for the create operation. - * type: object - * additionalProperties: false - * properties: - * issuerDid: - * description: This input field is the Issuer's DID. - * type: string - * subjectDid: - * description: This input field is the holder's DID. - * type: string - * attributes: - * description: Json input of the attributes. - * type: object - * @context: - * description: Additional contexts to be included in the credential. - * type: array - * items: - * type: string - * type: - * description: Additional type property to be included in the credential. - * type: array - * items: - * type: string - * expirationDate: - * description: Optional expiration date according to the https://www.w3.org/TR/vc-data-model/#expiration specification. - * format: - * description: Select one of the supported credential formats, jwt by default. - * type: string - * enum: - * - jwt - * - lds - * credentialStatus: - * description: Optional field to support revocation or suspension, which takes statusListName and statusListPurpose as inputs. - * type: object - * required: - * - statusPurpose - * - statusListName - * properties: - * statusPurpose: - * type: string - * enum: - * - revocation - * - suspension - * statusListName: - * type: string - * statusListIndex: - * type: number - * statusListVersion: - * type: string - * statusListRangeStart: - * type: number - * statusListRangeEnd: - * type: number - * indexNotIn: - * type: number - * example: - * statusPurpose: revocation - * statusListName: employee-credentials - * required: - * - issuerDid - * - subjectDid - * - attributes - * example: - * issuerDid: did:cheqd:testnet:7bf81a20-633c-4cc7-bc4a-5a45801005e0 - * subjectDid: did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK - * attributes: - * gender: male - * name: Bob - * @context: - * https://schema.org - * type: - * - Person - * format: jwt - * credentialStatus: - * statusPurpose: revocation - * statusListName: employee-credentials - * statusListIndex: 10 - * Credential: - * description: Input fields for the update operation. - * type: object - * additionalProperties: false - * properties: - * @context: - * type: array - * items: - * type: string - * type: - * type: array - * items: - * type: string - * expirationDate: - * type: string - * issuer: - * type: object - * properties: - * id: - * type: string - * credentialSubject: - * type: object - * properties: - * id: - * type: string - * credentialStatus: - * type: object - * properties: - * id: - * type: string - * statusListIndex: - * type: string - * statusPurpose: - * type: string - * enum: - * - revocation - * - suspension - * type: - * type: string - * enum: - * - StatusList2021Entry - * issuanceDate: - * type: string - * proof: - * type: object - * properties: - * type: - * type: string - * jwt: - * type: string - * example: - * @context: - * - https://www.w3.org/2018/credentials/v1 - * - https://schema.org - * - https://veramo.io/contexts/profile/v1 - * credentialSubject: - * gender: male - * id: did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK - * name: Bob - * credentialStatus: - * id: https://resolver.cheqd.net/1.0/identifiers/did:cheqd:testnet:7c2b990c-3d05-4ebf-91af-f4f4d0091d2e?resourceName=cheqd-suspension-1&resourceType=StatusList2021Suspension#20 - * statusListIndex: 20 - * statusPurpose: suspension - * type: StatusList2021Entry - * issuanceDate: 2023-06-08T13:49:28.000Z - * issuer: - * id: did:cheqd:testnet:7bf81a20-633c-4cc7-bc4a-5a45801005e0 - * proof: - * jwt: eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJkaWQ6Y2hlcWQ6dGVzdG5ldDo3YmY4MWEyMC02MzNjLTRjYzctYmM0YS01YTQ1ODAxMDA1ZTAiLCJuYmYiOjE2ODYyMzIxNjgsInN1YiI6ImRpZDprZXk6ejZNa2hhWGdCWkR2b3REa0w1MjU3ZmFpenRpR2lDMlF0S0xHcGJubkVHdGEyZG9LIiwidmMiOnsiQGNvbnRleHQiOlsiaHR0cHM6Ly93d3cudzMub3JnLzIwMTgvY3JlZGVudGlhbHMvdjEiLCJodHRwczovL3NjaGVtYS5vcmciLCJodHRwczovL3ZlcmFtby5pby9jb250ZXh0cy9wcm9maWxlL3YxIl0sImNyZWRlbnRpYWxTdWJqZWN0Ijp7ImdlbmRlciI6Im1hbGUiLCJuYW1lIjoiQm9iIn0sInR5cGUiOlsiVmVyaWZpYWJsZUNyZWRlbnRpYWwiLCJQZXJzb24iXX19.wMfdR6RtyAZA4eoWya5Aw97wwER2Cm5Guk780Xw8H9fA3sfudIJeLRLboqixpTchqSbYeA7KbuCTAnLgXTD_Cg - * type: JwtProof2020 - * type: - * - VerifiableCredential - * - Person */ /**