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

766 store circuit inputs translation schema #783

Merged
merged 18 commits into from
Jun 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
8def4ff
Tell vscode to use workspace typescript version
ognjenkurtic Jan 21, 2024
7386e11
Add circuitInputsTranslationSchema field to workstep + migration
ognjenkurtic Jan 21, 2024
ffaa8f9
Add extremely basic validateCircuitInputTranslationSchema method to c…
ognjenkurtic Jan 21, 2024
6699c25
Implement first version of AddCircuitInputsSchemaCommand with a handler
ognjenkurtic Jan 21, 2024
52dcf72
Implement endpoint for setting circuit input schema on a workstep; ad…
ognjenkurtic Jan 21, 2024
cfb5f85
Run prettier
ognjenkurtic Jan 21, 2024
b577957
Extend validateCircuitInputTranslationSchema method and add first bat…
ognjenkurtic Jan 22, 2024
a0c5287
Add dummy circuit input schema creation step to e2e test
ognjenkurtic Jan 22, 2024
0d90443
validateCircuitInputTranslationSchema - Parse validation reuslt and t…
ognjenkurtic Jan 22, 2024
999feda
Rename output param for validateCircuitInputTranslationSchema for bet…
ognjenkurtic Apr 11, 2024
fc2b672
Rename setCircuitInputsSchema command to updateCircuitInputsSchema
ognjenkurtic Apr 11, 2024
f869d30
Add circuitInputsTranslationSchema as JSON column to workstep
ognjenkurtic Apr 11, 2024
410ab21
Update postman collection with example schema
ognjenkurtic Apr 12, 2024
6c30aa3
Finish rename of SetCircuitInputSchema to UpdateCircuitInputSchema
ognjenkurtic Apr 12, 2024
05ee92f
Cleanup from local testing
ognjenkurtic Apr 12, 2024
af581fc
Fix validateCircuitInputTranslationSchema return type to be a single …
ognjenkurtic Jun 19, 2024
3c9230d
Fix failing unit tests related to circuit input parsers
ognjenkurtic Jun 20, 2024
0dc2cf3
Fix assert for invalid JSON schema test in ciruit parser service
ognjenkurtic Jun 20, 2024
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
3 changes: 3 additions & 0 deletions examples/bri-3/.vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"typescript.tsdk": "node_modules/typescript/lib"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE "Workstep" ADD COLUMN "circuitInputsTranslationSchema" JSONB;
1 change: 1 addition & 0 deletions examples/bri-3/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ model Workstep {
workgroupId String
securityPolicy String
privacyPolicy String
circuitInputsTranslationSchema Json?
workflow Workflow[]
workgroup Workgroup @relation(fields: [workgroupId], references: [id])
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,12 @@
const rawMessage = 'test';

// Act
const [resultDto, validationErrors] =

Check warning on line 34 in examples/bri-3/src/bri/communication/agents/messaging.agent.spec.ts

View workflow job for this annotation

GitHub Actions / ci (ubuntu-latest, 17.0.0)

'resultDto' is assigned a value but never used
messagingAgent.tryDeserializeToBpiMessageCandidate(rawMessage);

// Assert
expect(validationErrors.length).toBe(1);
expect(validationErrors[0]).toEqual(
'test is not valid JSON. Error: SyntaxError: Unexpected token e in JSON at position 1',
);
expect(validationErrors[0]).toMatch(/^test is not valid JSON./);
});

it('Should return error when validating correct JSON raw message with invalid UUID in id field', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
import { Injectable, NotFoundException } from '@nestjs/common';
import {
BadRequestException,
Injectable,
NotFoundException,
} from '@nestjs/common';
import { Workstep } from '../models/workstep';

import { v4 } from 'uuid';
import { CircuitInputsParserService } from '../../../zeroKnowledgeProof/services/circuit/circuitInputsParser/circuitInputParser.service';
import { NOT_FOUND_ERR_MESSAGE } from '../api/err.messages';
import { WorkstepStorageAgent } from './workstepsStorage.agent';

@Injectable()
export class WorkstepAgent {
constructor(private storageAgent: WorkstepStorageAgent) {}
constructor(
private storageAgent: WorkstepStorageAgent,
private cips: CircuitInputsParserService,
) {}

public createNewWorkstep(
name: string,
Expand Down Expand Up @@ -57,6 +65,20 @@ export class WorkstepAgent {
workstepToUpdate.updatePrivacyPolicy(privacyPolicy);
}

public throwIfCircuitInputTranslationSchemaInvalid(schema): void {
const error = this.cips.validateCircuitInputTranslationSchema(schema);
if (error) {
throw new BadRequestException(error);
}
}

public updateCircuitInputTranslationSchema(
workstepToUpdate: Workstep,
schema: string,
): void {
workstepToUpdate.updateCircuitInputTranslationSchema(schema);
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can error occur here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not really, asigning string value


public async fetchDeleteCandidateAndThrowIfDeleteValidationFails(
id: string,
): Promise<Workstep> {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { plainToInstance } from 'class-transformer';
import { validate } from 'class-validator';
import { SHOULD_NOT_BE_EMPTY_VALIDATION_MESSAGE } from '../../../../../shared/constants';
import { UpdateCircuitInputsSchemaDto } from './updateCircuitInputsSchema.dto';

describe('UpdateCircuitInputsSchemaDto', () => {
it('should return error in case schema not provided.', async () => {
// Arrange
const dto = { wrong: '1' };
const setCircuitInputsSchemaDto = plainToInstance(
UpdateCircuitInputsSchemaDto,
dto,
);

// Act
const errors = await validate(setCircuitInputsSchemaDto);

// Assert
expect(errors.length).toBe(1);
expect(errors[0].property).toEqual('schema');
expect(errors[0].constraints?.isNotEmpty).toContain(
'schema ' + SHOULD_NOT_BE_EMPTY_VALIDATION_MESSAGE,
);
});

it('should return no error if all required properties provided.', async () => {
// Arrange
const dto = { schema: 'test' };
const setCircuitInputsSchemaDto = plainToInstance(
UpdateCircuitInputsSchemaDto,
dto,
);

// Act
const errors = await validate(setCircuitInputsSchemaDto);

// Assert
expect(errors.length).toBe(0);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { IsNotEmpty } from 'class-validator';

export class UpdateCircuitInputsSchemaDto {
@IsNotEmpty()
schema: string;
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,7 @@ export class WorkstepDto {

@AutoMap()
privacyPolicy: string;

@AutoMap()
circuitInputsTranslationSchema: string;
}
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
import { classes } from '@automapper/classes';
import { AutomapperModule } from '@automapper/nestjs';
import { NotFoundException } from '@nestjs/common';
import { CqrsModule } from '@nestjs/cqrs';
import { Test, TestingModule } from '@nestjs/testing';
import { DeepMockProxy, mockDeep } from 'jest-mock-extended';
import { validate as uuidValidate, version as uuidVersion } from 'uuid';
import { uuid } from 'uuidv4';
import { LoggingService } from '../../../../shared/logging/logging.service';
import { CircuitInputsParserService } from '../../../zeroKnowledgeProof/services/circuit/circuitInputsParser/circuitInputParser.service';
import { WorkstepAgent } from '../agents/worksteps.agent';
import { WorkstepStorageAgent } from '../agents/workstepsStorage.agent';
import { CreateWorkstepCommandHandler } from '../capabilities/createWorkstep/createWorkstepCommand.handler';
import { DeleteWorkstepCommandHandler } from '../capabilities/deleteWorkstep/deleteWorkstepCommand.handler';
import { GetAllWorkstepsQueryHandler } from '../capabilities/getAllWorksteps/getAllWorkstepsQuery.handler';
import { GetWorkstepByIdQueryHandler } from '../capabilities/getWorkstepById/getWorkstepByIdQuery.handler';
import { UpdateWorkstepCommandHandler } from '../capabilities/updateWorkstep/updateWorkstep.command.handler';
import { WorkstepStorageAgent } from '../agents/workstepsStorage.agent';
import { Workstep } from '../models/workstep';
import { WorkstepProfile } from '../workstep.profile';
import { CreateWorkstepDto } from './dtos/request/createWorkstep.dto';
import { UpdateWorkstepDto } from './dtos/request/updateWorkstep.dto';
import { NOT_FOUND_ERR_MESSAGE } from './err.messages';
import { WorkstepController } from './worksteps.controller';
import { validate as uuidValidate, version as uuidVersion } from 'uuid';
import { WorkstepProfile } from '../workstep.profile';
import { classes } from '@automapper/classes';
import { AutomapperModule } from '@automapper/nestjs';
import { mockDeep, DeepMockProxy } from 'jest-mock-extended';
import { Workstep } from '../models/workstep';
import { uuid } from 'uuidv4';

describe('WorkstepController', () => {
let wController: WorkstepController;
Expand Down Expand Up @@ -47,6 +49,8 @@ describe('WorkstepController', () => {
controllers: [WorkstepController],
providers: [
WorkstepAgent,
CircuitInputsParserService,
LoggingService,
CreateWorkstepCommandHandler,
UpdateWorkstepCommandHandler,
DeleteWorkstepCommandHandler,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@ import {
} from '@nestjs/common';
import { CommandBus, QueryBus } from '@nestjs/cqrs';
import { CheckAuthz } from '../../../authz/guards/authz.decorator';
import { UpdateCircuitInputsSchemaCommand } from '../capabilities/updateCircuitInputsSchema/updateCircuitInputsSchema.command';
import { CreateWorkstepCommand } from '../capabilities/createWorkstep/createWorkstep.command';
import { DeleteWorkstepCommand } from '../capabilities/deleteWorkstep/deleteWorkstep.command';
import { GetAllWorkstepsQuery } from '../capabilities/getAllWorksteps/getAllWorksteps.query';
import { GetWorkstepByIdQuery } from '../capabilities/getWorkstepById/getWorkstepById.query';
import { UpdateWorkstepCommand } from '../capabilities/updateWorkstep/updateWorkstep.command';
import { UpdateCircuitInputsSchemaDto } from './dtos/request/updateCircuitInputsSchema.dto';
import { CreateWorkstepDto } from './dtos/request/createWorkstep.dto';
import { UpdateWorkstepDto } from './dtos/request/updateWorkstep.dto';
import { WorkstepDto } from './dtos/response/workstep.dto';
Expand Down Expand Up @@ -71,6 +73,17 @@ export class WorkstepController {
);
}

@Put('/:id/circuitinputsschema')
@CheckAuthz({ action: 'update', type: 'Workstep' })
async updateCircuitInputsSchemaCommand(
@Param('id') id: string,
@Body() requestDto: UpdateCircuitInputsSchemaDto,
): Promise<WorkstepDto> {
return await this.commandBus.execute(
new UpdateCircuitInputsSchemaCommand(id, requestDto.schema),
);
}

@Delete('/:id')
@CheckAuthz({ action: 'delete', type: 'Workstep' })
async deleteWorkstep(@Param('id') id: string): Promise<void> {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { CommandHandler, ICommandHandler } from '@nestjs/cqrs';
import { WorkstepAgent } from '../../agents/worksteps.agent';
import { WorkstepStorageAgent } from '../../agents/workstepsStorage.agent';
import { UpdateCircuitInputsSchemaCommand } from './updateCircuitInputsSchema.command';
import { InjectMapper } from '@automapper/nestjs';
import { Mapper } from '@automapper/core';
import { Workstep } from '../../models/workstep';
import { WorkstepDto } from '../../api/dtos/response/workstep.dto';

@CommandHandler(UpdateCircuitInputsSchemaCommand)
export class UpdateCircuitInputsSchemaCommandHandler
implements ICommandHandler<UpdateCircuitInputsSchemaCommand>
{
constructor(
@InjectMapper() private readonly mapper: Mapper,
private agent: WorkstepAgent,
private storageAgent: WorkstepStorageAgent,
) {}

async execute(command: UpdateCircuitInputsSchemaCommand) {
const workstepToUpdate =
await this.agent.fetchUpdateCandidateAndThrowIfUpdateValidationFails(
command.workstepId,
);

this.agent.throwIfCircuitInputTranslationSchemaInvalid(command.schema);

this.agent.updateCircuitInputTranslationSchema(
workstepToUpdate,
command.schema,
);

const updatedWorkstep = await this.storageAgent.updateWorkstep(
workstepToUpdate,
);

return this.mapper.map(updatedWorkstep, Workstep, WorkstepDto);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export class UpdateCircuitInputsSchemaCommand {
constructor(
public readonly workstepId: string,
public readonly schema: string,
) {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ export class Workstep {
@AutoMap()
privacyPolicy: string; // TODO Implement simple privacy policy inhereted from workgroup #487

@AutoMap()
circuitInputsTranslationSchema: string;
Therecanbeonlyone1969 marked this conversation as resolved.
Show resolved Hide resolved

constructor(
id: string,
name: string,
Expand Down Expand Up @@ -63,4 +66,8 @@ export class Workstep {
public updatePrivacyPolicy(newPrivacyPolicy: string): void {
this.privacyPolicy = newPrivacyPolicy;
}

public updateCircuitInputTranslationSchema(schema): void {
this.circuitInputsTranslationSchema = schema;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,23 @@ import { Module } from '@nestjs/common';
import { CqrsModule } from '@nestjs/cqrs';
import { LoggingModule } from '../../../../src/shared/logging/logging.module';
import { PrismaModule } from '../../../shared/prisma/prisma.module';
import { ZeroKnowledgeProofModule } from '../../zeroKnowledgeProof/zeroKnowledgeProof.module';
import { WorkstepAgent } from './agents/worksteps.agent';
import { WorkstepStorageAgent } from './agents/workstepsStorage.agent';
import { WorkstepController } from './api/worksteps.controller';
import { CreateWorkstepCommandHandler } from './capabilities/createWorkstep/createWorkstepCommand.handler';
import { DeleteWorkstepCommandHandler } from './capabilities/deleteWorkstep/deleteWorkstepCommand.handler';
import { GetAllWorkstepsQueryHandler } from './capabilities/getAllWorksteps/getAllWorkstepsQuery.handler';
import { GetWorkstepByIdQueryHandler } from './capabilities/getWorkstepById/getWorkstepByIdQuery.handler';
import { UpdateCircuitInputsSchemaCommandHandler } from './capabilities/updateCircuitInputsSchema/updateCircuitInputsSchema.command.handler';
import { UpdateWorkstepCommandHandler } from './capabilities/updateWorkstep/updateWorkstep.command.handler';
import { WorkstepProfile } from './workstep.profile';

export const CommandHandlers = [
CreateWorkstepCommandHandler,
UpdateWorkstepCommandHandler,
DeleteWorkstepCommandHandler,
UpdateCircuitInputsSchemaCommandHandler,
];

export const QueryHandlers = [
Expand All @@ -24,7 +27,7 @@ export const QueryHandlers = [
];

@Module({
imports: [CqrsModule, LoggingModule, PrismaModule],
imports: [CqrsModule, LoggingModule, PrismaModule, ZeroKnowledgeProofModule],
controllers: [WorkstepController],
providers: [
...CommandHandlers,
Expand Down
Loading
Loading