Skip to content

Commit

Permalink
- Add resource tracking
Browse files Browse the repository at this point in the history
- Fix credential actions for encrypted statusList
  • Loading branch information
Andrew Nikitin committed Nov 8, 2023
1 parent ece69e9 commit ac90c44
Show file tree
Hide file tree
Showing 14 changed files with 443 additions and 60 deletions.
13 changes: 9 additions & 4 deletions src/controllers/credentials.ts
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ export class CredentialController {
if (result.error) {
return response.status(StatusCodes.BAD_REQUEST).json({
verified: result.verified,
error: result.error,
error: result.error.message,
});
}
return response.status(StatusCodes.OK).json(result);
Expand Down Expand Up @@ -302,14 +302,16 @@ export class CredentialController {
}

const publish = request.query.publish === 'false' ? false : true;
const symmetricKey = request.body.symmetricKey as string;
try {
return response
.status(StatusCodes.OK)
.json(
await new IdentityServiceStrategySetup(response.locals.customer.customerId).agent.revokeCredentials(
request.body.credential,
publish,
response.locals.customer
response.locals.customer,
symmetricKey
)
);
} catch (error) {
Expand Down Expand Up @@ -364,12 +366,13 @@ export class CredentialController {

try {
const publish = request.query.publish === 'false' ? false : true;
const symmetricKey = request.body.symmetricKey as string;
return response
.status(StatusCodes.OK)
.json(
await new IdentityServiceStrategySetup(
response.locals.customer.customerId
).agent.suspendCredentials(request.body.credential, publish, response.locals.customer)
).agent.suspendCredentials(request.body.credential, publish, response.locals.customer, symmetricKey)
);
} catch (error) {
return response.status(StatusCodes.INTERNAL_SERVER_ERROR).json({
Expand Down Expand Up @@ -423,6 +426,7 @@ export class CredentialController {

try {
const publish = request.query.publish === 'false' ? false : true;
const symmetricKey = request.body.symmetricKey as string;
return response
.status(StatusCodes.OK)
.json(
Expand All @@ -431,7 +435,8 @@ export class CredentialController {
).agent.reinstateCredentials(
request.body.credential,
publish,
response.locals.customer
response.locals.customer,
symmetricKey
)
);
} catch (error) {
Expand Down
29 changes: 22 additions & 7 deletions src/controllers/issuer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -543,13 +543,12 @@ export class IssuerController {

const { did } = request.params;
const { data, encoding, name, type, alsoKnownAs, version, network } = request.body;
const identityServiceStrategySetup = new IdentityServiceStrategySetup(response.locals.customer.customerId);

let resourcePayload: Partial<MsgCreateResourcePayload> = {};
try {
// check if did is registered on the ledger
const { didDocument, didDocumentMetadata } = await new IdentityServiceStrategySetup(
response.locals.customer.customerId
).agent.resolveDid(did);
const { didDocument, didDocumentMetadata } = await identityServiceStrategySetup.agent.resolveDid(did);
if (!didDocument || !didDocumentMetadata || didDocumentMetadata.deactivated) {
return response.status(StatusCodes.BAD_REQUEST).send({
error: `${did} is a either Deactivated or Not found`,
Expand All @@ -565,18 +564,34 @@ export class IssuerController {
version,
alsoKnownAs,
};
const result = await new IdentityServiceStrategySetup(
response.locals.customer.customerId
).agent.createResource(network || did.split(':')[2], resourcePayload, response.locals.customer);
const result = await identityServiceStrategySetup.agent.createResource(
network || did.split(':')[2], resourcePayload, response.locals.customer);

if (result) {
const url = new URL(
`${process.env.RESOLVER_URL || DefaultResolverUrl}${did}?` +
`resourceId=${resourcePayload.id}&resourceMetadata=true`
);
const didDereferencing = (await (await fetch(url)).json()) as DIDMetadataDereferencingResult;
const resource = didDereferencing.contentStream.linkedResourceMetadata[0];

// track resource creation
const trackResourceInfo= {
customer: response.locals.customer,
did,
resource: resource,
encrypted: false,
symmetricKey: '',
}
const trackResult = await identityServiceStrategySetup.agent.trackResourceCreation(trackResourceInfo)
if (trackResult.error) {
return response.status(StatusCodes.INTERNAL_SERVER_ERROR).json({
error: `${trackResult.error}`,
})
}

return response.status(StatusCodes.CREATED).json({
resource: didDereferencing.contentStream.linkedResourceMetadata[0],
resource
});
} else {
return response.status(StatusCodes.INTERNAL_SERVER_ERROR).json({
Expand Down
82 changes: 73 additions & 9 deletions src/controllers/revocation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -551,12 +551,13 @@ export class RevocationController {
// define broadcast mode
const data = encodedList ? fromString(encodedList, encoding) : undefined;

// create agent
const identityServiceStrategySetup = new IdentityServiceStrategySetup(response.locals.customer.customerId);

try {
// broadcast, if applicable
if (data) {
const result = await new IdentityServiceStrategySetup(
response.locals.customer.customerId
).agent.broadcastStatusList2021(
const result = await identityServiceStrategySetup.agent.broadcastStatusList2021(
did,
{ data, name: statusListName, alsoKnownAs, version: statusListVersion },
{ encoding, statusPurpose },
Expand All @@ -566,9 +567,7 @@ export class RevocationController {
}

// create unencrypted status list
const result = (await new IdentityServiceStrategySetup(
response.locals.customer.customerId
).agent.createUnencryptedStatusList2021(
const result = (await identityServiceStrategySetup.agent.createUnencryptedStatusList2021(
did,
{
name: statusListName,
Expand All @@ -591,6 +590,20 @@ export class RevocationController {
} as CreateUnencryptedStatusListUnsuccessfulResponseBody);
}

// Keep track of resources
const trackResourceInfo= {
customer: response.locals.customer,
did,
resource: result.resourceMetadata,
encrypted: result.resource?.metadata?.encrypted,
symmetricKey: '',
}
const trackResult = await identityServiceStrategySetup.agent.trackResourceCreation(trackResourceInfo)
if (trackResult.error) {
return response.status(StatusCodes.INTERNAL_SERVER_ERROR).json(
trackResult as CreateEncryptedStatusListUnsuccessfulResponseBody);
}

// return result
return response.status(StatusCodes.OK).json({ ...result, encrypted: undefined });
} catch (error) {
Expand Down Expand Up @@ -667,12 +680,11 @@ export class RevocationController {

// collect request parameters - case: query
const { statusPurpose } = request.query as CreateEncryptedStatusListRequestQuery;
const identityServiceStrategySetup = new IdentityServiceStrategySetup(response.locals.customer.customerId);

try {
// create encrypted status list
const result = (await new IdentityServiceStrategySetup(
response.locals.customer.customerId
).agent.createEncryptedStatusList2021(
const result = (await identityServiceStrategySetup.agent.createEncryptedStatusList2021(
did,
{
name: statusListName,
Expand All @@ -698,6 +710,20 @@ export class RevocationController {
error: result.error?.message || result.error.toString(),
} as CreateEncryptedStatusListUnsuccessfulResponseBody);
}
// Keep track of resources
// For now we decided not to store symmetricKey yet
const trackResourceInfo= {
customer: response.locals.customer,
did,
resource: result.resourceMetadata,
encrypted: result.resource?.metadata?.encrypted,
symmetricKey: '',
}
const trackResult = await identityServiceStrategySetup.agent.trackResourceCreation(trackResourceInfo)
if (trackResult.error) {
return response.status(StatusCodes.INTERNAL_SERVER_ERROR).json(
trackResult as CreateEncryptedStatusListUnsuccessfulResponseBody);
}

// return result
return response.status(StatusCodes.OK).json({ ...result, encrypted: undefined });
Expand Down Expand Up @@ -855,6 +881,25 @@ export class RevocationController {
resourceMetadata: result.resourceMetadata,
} satisfies UpdateUnencryptedStatusListSuccessfulResponseBody;

// track resource creation
if (result.resourceMetadata) {
const trackResourceInfo= {
customer: response.locals.customer,
did,
resource: result.resourceMetadata,
encrypted: false,
symmetricKey: '',
}
const trackResult = await identityServiceStrategySetup.agent.trackResourceCreation(trackResourceInfo)
if (trackResult.error) {
return response.status(StatusCodes.INTERNAL_SERVER_ERROR).json(
{
updated: false,
error: trackResult.error
} as UpdateUnencryptedStatusListUnsuccessfulResponseBody);
}
}

return response.status(StatusCodes.OK).json(formatted);
} catch (error) {
// return catch-all error
Expand Down Expand Up @@ -1026,6 +1071,25 @@ export class RevocationController {
symmetricKey: result.symmetricKey,
} satisfies UpdateEncryptedStatusListSuccessfulResponseBody;

// track resource creation
if (result.resourceMetadata) {
const trackResourceInfo= {
customer: response.locals.customer,
did,
resource: result.resourceMetadata,
encrypted: true,
symmetricKey: '',
}
const trackResult = await identityServiceStrategySetup.agent.trackResourceCreation(trackResourceInfo)
if (trackResult.error) {
return response.status(StatusCodes.INTERNAL_SERVER_ERROR).json(
{
updated: false,
error: trackResult.error
} as UpdateUnencryptedStatusListUnsuccessfulResponseBody);
}
}

return response.status(StatusCodes.OK).json(formatted);
} catch (error) {
// return catch-all error
Expand Down
27 changes: 20 additions & 7 deletions src/database/entities/resource.entity.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { BeforeInsert, Column, Entity, JoinColumn, ManyToOne, PrimaryGeneratedColumn } from 'typeorm';
import { BeforeInsert, Column, Entity, JoinColumn, ManyToOne, PrimaryColumn } from 'typeorm';

import * as dotenv from 'dotenv';
import { Identifier, Key } from '@veramo/data-store';
Expand All @@ -9,7 +9,10 @@ dotenv.config();

@Entity('resource')
export class ResourceEntity {
@PrimaryGeneratedColumn('uuid')
@PrimaryColumn({
type: 'uuid',
nullable: false,
})
resourceId!: string;

@Column({
Expand Down Expand Up @@ -80,18 +83,28 @@ export class ResourceEntity {
customer!: CustomerEntity;

constructor(
identifier: IdentifierEntity,
key: KeyEntity,
resourceId: string,
resourceName: string,
resourceType: string,
mediaType: string,
customer: CustomerEntity
previousVersionId: string | null,
nextVersionId: string | null,
customer: CustomerEntity,
identifier: IdentifierEntity,
key: KeyEntity,
encrypted: boolean,
symmetricKey: string
) {
this.identifier = identifier;
this.key = key;
this.resourceId = resourceId;
this.resourceName = resourceName;
this.resourceType = resourceType;
this.mediaType = mediaType;
this.previousVersionId = previousVersionId || '';
this.nextVersionId = nextVersionId || '';
this.customer = customer;
this.identifier = identifier;
this.key = key;
this.encrypted = encrypted;
this.symmetricKey = symmetricKey;
}
}
2 changes: 1 addition & 1 deletion src/database/migrations/CreateResourceTable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export class CreateResourceTable1695740345977 implements MigrationInterface {
{ name: 'symmetricKey', type: 'text', isNullable: true },

{ name: 'createdAt', type: 'timestamptz', isNullable: false },
{ name: 'updatedAt', type: 'timestamptz', isNullable: false },
{ name: 'updatedAt', type: 'timestamptz', isNullable: true },
],
});
await queryRunner.createTable(table, true);
Expand Down
16 changes: 13 additions & 3 deletions src/services/identity/abstract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ import type {
CreateUnencryptedStatusListOptions,
CredentialRequest,
FeePaymentOptions,
IResourceTrack,
StatusOptions,
TrackResult,
UpdateEncryptedStatusListOptions,
UpdateUnencryptedStatusListOptions,
VeramoAgent,
Expand Down Expand Up @@ -142,24 +144,32 @@ export abstract class AbstractIdentityService implements IIdentityService {
): Promise<boolean> {
throw new Error(`Not supported`);
}
trackResourceCreation(
trackResource: IResourceTrack
): Promise<TrackResult> {
throw new Error(`Not supported`);
}
revokeCredentials(
credential: VerifiableCredential | VerifiableCredential[],
publish: boolean,
customer: CustomerEntity
customer: CustomerEntity,
symmetricKey: string
): Promise<RevocationResult | BulkRevocationResult> {
throw new Error(`Not supported`);
}
suspendCredentials(
credential: VerifiableCredential | VerifiableCredential[],
publish: boolean,
customer: CustomerEntity
customer: CustomerEntity,
symmetricKey: string
): Promise<SuspensionResult | BulkSuspensionResult> {
throw new Error(`Not supported`);
}
reinstateCredentials(
credential: VerifiableCredential | VerifiableCredential[],
publish: boolean,
customer: CustomerEntity
customer: CustomerEntity,
symmetricKey: string
): Promise<UnsuspensionResult | BulkUnsuspensionResult> {
throw new Error(`Not supported`);
}
Expand Down
Loading

0 comments on commit ac90c44

Please sign in to comment.