Skip to content

Commit

Permalink
Add additional tests
Browse files Browse the repository at this point in the history
  • Loading branch information
DaevMithran committed Oct 7, 2024
1 parent 7b597e1 commit 9b34c7e
Show file tree
Hide file tree
Showing 7 changed files with 175 additions and 34 deletions.
14 changes: 13 additions & 1 deletion src/controllers/api/accreditation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,16 @@ export class AccreditationController {
];

public static verifyValidator = [
body('did').optional().isDID().bail(),
body('didUrl')
.optional()
.isDID()
.custom((value) => value.includes('/resources/') || value.includes('?resourceName'))
.withMessage('didUrls should point to a unique DID Linked Resource')
.bail(),
body('resourceId').optional().isUUID().withMessage('resourceId should be a string').bail(),
body('resourceName').optional().isString().withMessage('resourceName should be a string').bail(),
body('resourceType').optional().isString().withMessage('resourceType should be a string').bail(),
body('did')
.custom((value, { req }) => {
const { didUrl, resourceId, resourceName, resourceType } = req.body;
Expand Down Expand Up @@ -266,6 +276,7 @@ export class AccreditationController {
const result = await AccreditationService.instance.verify_accreditation(
issuerDid,
parentAccreditation!,
schemas,
true,
false,
response.locals.customer,
Expand Down Expand Up @@ -360,7 +371,7 @@ export class AccreditationController {
public async verify(request: Request, response: Response) {
// Extract did from params
let { verifyStatus = false, allowDeactivatedDid = false } = request.query as VerifyCredentialRequestQuery;
const { policies, subjectDid } = request.body as VerifyAccreditationRequestBody;
const { policies, subjectDid, schemas } = request.body as VerifyAccreditationRequestBody;

// construct didUrl
let didUrl: string;
Expand All @@ -384,6 +395,7 @@ export class AccreditationController {
const result = await AccreditationService.instance.verify_accreditation(
subjectDid,
didUrl,
schemas,
verifyStatus,
allowDeactivatedDid,
response.locals.customer,
Expand Down
20 changes: 16 additions & 4 deletions src/services/api/accreditation.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import type { CustomerEntity } from '../../database/entities/customer.entity.js';
import type { SafeAPIResponse } from '../../types/common.js';
import { DIDAccreditationTypes } from '../../types/accreditation.js';
import { AccreditationSchemaType, DIDAccreditationTypes, VerfifiableAccreditation } from '../../types/accreditation.js';
import { isCredentialIssuerDidDeactivated } from '../helpers.js';
import { IdentityServiceStrategySetup } from '../identity/index.js';
import type { VerifiableCredential, VerificationPolicies } from '@veramo/core';
import type { VerificationPolicies } from '@veramo/core';
import { CheqdW3CVerifiableCredential } from '../w3c-credential.js';

export class AccreditationService {
Expand All @@ -12,6 +12,7 @@ export class AccreditationService {
async verify_accreditation(
subjectDid: string,
didUrl: string,
schemas: AccreditationSchemaType[] = [],
verifyStatus: boolean,
allowDeactivatedDid: boolean,
customer: CustomerEntity,
Expand All @@ -37,11 +38,11 @@ export class AccreditationService {
}

// Create credential object
const accreditation: VerifiableCredential = result;
const accreditation: VerfifiableAccreditation = result;

if (
!allowDeactivatedDid &&
(await isCredentialIssuerDidDeactivated(accreditation as CheqdW3CVerifiableCredential))
(await isCredentialIssuerDidDeactivated(accreditation as unknown as CheqdW3CVerifiableCredential))
) {
return {
success: false,
Expand All @@ -50,6 +51,7 @@ export class AccreditationService {
};
}

// Check if the accreditation is provided for the subjectDid
if (accreditation.credentialSubject.id !== accreditedSubject) {
return {
success: false,
Expand All @@ -62,6 +64,15 @@ export class AccreditationService {
verifyStatus = false;
}

// Check if the accreditor has permission for the schema provided
if (!schemas.some((x) => accreditation.credentialSubject.accreditedFor.includes(x))) {
return {
success: false,
status: 401,
error: `Invalid Request: Accreditation does not have the permissions for the given schema`,
};
}

const verifyResult = await identityServiceStrategySetup.agent.verifyCredential(
accreditation,
{
Expand Down Expand Up @@ -116,6 +127,7 @@ export class AccreditationService {

accreditationUrl = termsOfUse.parentAccreditation;
accreditedSubject = accreditorDid;
schemas = accreditation.credentialSubject.accreditedFor;

if (rootAuthorization && rootAuthorization !== termsOfUse.rootAuthorization) {
return {
Expand Down
50 changes: 33 additions & 17 deletions src/static/swagger-api.json
Original file line number Diff line number Diff line change
Expand Up @@ -513,19 +513,19 @@
}
},
"AccreditationIssueRequest": {
"description": "Input fields for the creating a Verifiable Credential.",
"description": "Input fields for the creating a Verifiable Accreditation.",
"type": "object",
"additionalProperties": false,
"properties": {
"issuerDid": {
"description": "DID of the Verifiable Credential issuer. This needs to be a `did:cheqd` DID.",
"description": "DID of the Verifiable Accreditation issuer. This needs to be a `did:cheqd` DID.",
"type": "string",
"example": "did:cheqd:testnet:7bf81a20-633c-4cc7-bc4a-5a45801005e0"
},
"subjectDid": {
"description": "DID of the Verifiable Credential holder/subject. This needs to be a `did:key` DID.",
"description": "DID of the Verifiable Accreditation holder/subject. This needs to be a `did:cheqd` DID.",
"type": "string",
"example": "did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK"
"example": "did:cheqd:testnet:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK"
},
"schemas": {
"description": "The list of schemas the subject DID is accredited for.",
Expand All @@ -535,11 +535,11 @@
}
},
"attributes": {
"description": "JSON object containing the attributes to be included in the credential.",
"description": "JSON object containing the attributes to be included in the Accreditation.",
"type": "object"
},
"@context": {
"description": "Optional properties to be included in the `@context` property of the credential.",
"description": "Optional properties to be included in the `@context` property of the Accreditation.",
"type": "array",
"items": {
"type": "string"
Expand All @@ -558,7 +558,7 @@
"type": "string"
},
"type": {
"description": "Optional properties to be included in the `type` property of the credential.",
"description": "Optional properties to be included in the `type` property of the Accreditation.",
"type": "array",
"items": {
"type": "string"
Expand All @@ -574,7 +574,7 @@
"example": "2023-06-08T13:49:28.000Z"
},
"format": {
"description": "Format of the Verifiable Credential. Defaults to VC-JWT.",
"description": "Format of the Verifiable Accreditation. Defaults to VC-JWT.",
"type": "string",
"enum": [
"jwt",
Expand Down Expand Up @@ -688,7 +688,7 @@
],
"example": {
"issuerDid": "did:cheqd:testnet:7bf81a20-633c-4cc7-bc4a-5a45801005e0",
"subjectDid": "did:cheqd:testnet:cbe7ccf6-5937-44e6-8480-282b2d7ccc5b",
"subjectDid": "did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK",
"schemas": [
{
"type": "MuseumPassCredential",
Expand All @@ -713,16 +713,33 @@
"type": "object",
"properties": {
"subjectDid": {
"description": "DID of the Verifiable Accreditation holder/subject. This needs to be a `did:cheqd` DID.",
"description": "DID of the Verifiable Accreditation holder/subject. This needs to be a `did:key` DID.",
"type": "string",
"example": "did:cheqd:testnet:cbe7ccf6-5937-44e6-8480-282b2d7ccc5b"
"example": "did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK"
},
"didUrl": {
"description": "Verifiable Accreditation to be verified as a VC-JWT string or a JSON object.",
"type": "object"
"description": "Verifiable Accreditation to be verified as a VC-JWT string or a JSON object.",
"type": "string"
},
"example": "did:cheqd:testnet:7c2b990c-3d05-4ebf-91af-f4f4d0091d2e?resourceName=cheqd-issuer-logo&resourceType=CredentialArtwork",
"did": {
"type": "string",
"example": "did:cheqd:testnet:7c2b990c-3d05-4ebf-91af-f4f4d0091d2e"
},
"resourceId": {
"type": "string",
"example": "398cee0a-efac-4643-9f4c-74c48c72a14b"
},
"resourceName": {
"type": "string",
"example": "cheqd-issuer-logo"
},
"resourceType": {
"type": "string",
"example": "CredentialArtwork"
},
"policies": {
"description": "Custom verification policies to execute when verifying credential.",
"description": "Custom verification policies to execute when verifying Accreditation.",
"type": "object",
"properties": {
"issuanceDate": {
Expand All @@ -744,7 +761,6 @@
}
},
"required": [
"accreditation",
"subjectDid"
]
},
Expand Down Expand Up @@ -2439,7 +2455,7 @@
}
}
},
"/accreditation/issue": {
"/trust-registry/accreditation/issue": {
"post": {
"tags": [
"Trust Registry"
Expand Down Expand Up @@ -2500,7 +2516,7 @@
}
}
},
"/accreditation/verify": {
"/trust-registry/accreditation/verify": {
"post": {
"tags": [
"Trust Registry"
Expand Down
25 changes: 18 additions & 7 deletions src/types/accreditation.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { VerifiableCredential } from '@veramo/core';
import type { CredentialRequest, VerifyCredentialRequestBody } from './credential';

// Enums
Expand All @@ -13,14 +14,16 @@ export enum AccreditationRequestType {
attest = 'attest',
}

export type AccreditationSchemaType = {
type: string;
url: string;
};

export type DIDAccreditationRequestBody = Omit<
CredentialRequest,
'attributes' | 'credentialSummary' | 'credentialSchema' | 'credentialName'
> & {
schemas: {
type: string;
url: string;
}[];
schemas: AccreditationSchemaType[];
accreditationName: string;
attributes?: Record<string, unknown>;
type: string[] | undefined;
Expand All @@ -41,16 +44,17 @@ export interface VerifyAccreditationRequestBody extends Pick<VerifyCredentialReq
resourceName?: string;
resourceType?: string;
subjectDid: string;
schemas?: AccreditationSchemaType[];
}

type DidUrl = Pick<VerifyAccreditationRequestBody, 'policies' | 'subjectDid'> & {
type DidUrl = Pick<VerifyAccreditationRequestBody, 'policies' | 'subjectDid' | 'schemas'> & {
didUrl: string;
};
type DidAndResourceId = Pick<VerifyAccreditationRequestBody, 'policies' | 'subjectDid'> & {
type DidAndResourceId = Pick<VerifyAccreditationRequestBody, 'policies' | 'subjectDid' | 'schemas'> & {
did: string;
resourceId: string;
};
type DidResourceNameAndType = Pick<VerifyAccreditationRequestBody, 'policies' | 'subjectDid'> & {
type DidResourceNameAndType = Pick<VerifyAccreditationRequestBody, 'policies' | 'subjectDid' | 'schemas'> & {
did: string;
resourceName: string;
resourceType: string;
Expand All @@ -71,3 +75,10 @@ export function isDidAndResourceName(body: VerifyAccreditationRequestBody): body
typeof body.did === 'string' && typeof body.resourceName === 'string' && typeof body.resourceType === 'string'
);
}

export interface VerfifiableAccreditation extends VerifiableCredential {
credentialSubject: {
id: string;
accreditedFor: AccreditationSchemaType[];
};
}
14 changes: 14 additions & 0 deletions tests/e2e/payloads/accreditation/child-accredit-jwt.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"issuerDid": "did:cheqd:testnet:BjS4Nv8bVdxm2WW28MCfXA",
"subjectDid": "did:cheqd:testnet:MehB8hz2X4rHnAzvWG1y73",
"schemas": [
{
"url": "https://schema.org/Person",
"type": "Person"
}
],
"format": "jwt",
"accreditationName": "accreditAccreditation",
"parentAccreditation": "did:cheqd:testnet:15b74787-6e48-4fd5-8020-eab24e990578?resourceName=accreditAccreditation&resourceType=VerifiableAccreditationToAccredit",
"rootAuthorization": "did:cheqd:testnet:5RpEg66jhhbmASWPXJRWrA?resourceName=authorizeAccreditation&resourceType=VerifiableAuthorisationForTrustChain"
}
14 changes: 14 additions & 0 deletions tests/e2e/payloads/accreditation/invalid-schema-accredit.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"issuerDid": "did:cheqd:testnet:BjS4Nv8bVdxm2WW28MCfXA",
"subjectDid": "did:cheqd:testnet:MehB8hz2X4rHnAzvWG1y73",
"schemas": [
{
"url": "https://schema.org/Event",
"type": "Event"
}
],
"format": "jwt",
"accreditationName": "childAccreditAccreditation",
"parentAccreditation": "did:cheqd:testnet:15b74787-6e48-4fd5-8020-eab24e990578?resourceName=accreditAccreditation&resourceType=VerifiableAccreditationToAccredit",
"rootAuthorization": "did:cheqd:testnet:5RpEg66jhhbmASWPXJRWrA?resourceName=authorizeAccreditation&resourceType=VerifiableAuthorisationForTrustChain"
}
Loading

0 comments on commit 9b34c7e

Please sign in to comment.