From 041d271e0878bad0d609110d7acb586ae23e6878 Mon Sep 17 00:00:00 2001 From: cbolles Date: Tue, 7 May 2024 10:20:47 -0400 Subject: [PATCH 1/3] Add in fetch request to webhook --- .../dataset-download-request.resolver.ts | 3 ++- packages/zipper/src/commands/zip/index.ts | 17 +++++++++++++---- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/packages/server/src/download-request/resolvers/dataset-download-request.resolver.ts b/packages/server/src/download-request/resolvers/dataset-download-request.resolver.ts index 354905f..55e1029 100644 --- a/packages/server/src/download-request/resolvers/dataset-download-request.resolver.ts +++ b/packages/server/src/download-request/resolvers/dataset-download-request.resolver.ts @@ -12,7 +12,6 @@ import { Dataset } from '../../dataset/dataset.model'; import { DatasetPipe } from '../../dataset/pipes/dataset.pipe'; import { DatasetDownloadRequestPipe } from '../pipes/dataset-download-request.pipe'; -@UseGuards(JwtAuthGuard, OrganizationGuard) @Resolver(() => DatasetDownloadRequest) export class DatasetDownloadRequestResolver { constructor( @@ -21,6 +20,7 @@ export class DatasetDownloadRequestResolver { ) {} @Mutation(() => DatasetDownloadRequest) + @UseGuards(JwtAuthGuard, OrganizationGuard) async createDatasetDownload( @Args('downloadRequest', CreateDatasetDownloadPipe) downloadRequest: CreateDatasetDownloadRequest, @OrganizationContext() organization: Organization @@ -29,6 +29,7 @@ export class DatasetDownloadRequestResolver { } @Query(() => [DatasetDownloadRequest]) + @UseGuards(JwtAuthGuard, OrganizationGuard) async getDatasetDownloads( @Args('dataset', { type: () => ID }, DatasetPipe) dataset: Dataset ): Promise { diff --git a/packages/zipper/src/commands/zip/index.ts b/packages/zipper/src/commands/zip/index.ts index 6e95d19..480a98a 100644 --- a/packages/zipper/src/commands/zip/index.ts +++ b/packages/zipper/src/commands/zip/index.ts @@ -32,7 +32,7 @@ export default class ZipHander extends Command { const entries: string[] = JSON.parse(await readFile(flags.target_entries, 'utf8'))['entries']; // Load the webhook payload (before taking too long with zipping) - // const payload = await readFile(flags.webhook_payload, 'utf8'); + const payload = await readFile(flags.webhook_payload, 'utf8'); // Add the enties to the zip for (const entry of entries) { @@ -43,11 +43,20 @@ export default class ZipHander extends Command { await zip.writeZipPromise(flags.output_zip); // Post to the webhook to notify of completion - /* - await fetch(flags.notification_webhook, { + const result = await fetch(flags.notification_webhook, { method: 'POST', + headers: { + 'content-type': 'application/json' + }, body: payload }); - */ + + if (result.status != 200) { + console.error(await result.text()); + throw new Error('Failed to call webhook'); + } + + // Left for easier debugging + console.log(await result.json()); } } From 73a0354354bf978713822e83a048665c2032b520 Mon Sep 17 00:00:00 2001 From: cbolles Date: Tue, 7 May 2024 14:13:45 -0400 Subject: [PATCH 2/3] Add handlers for webhooks --- packages/server/src/config/configuration.ts | 3 ++ .../study-download-request.resolver.ts | 3 +- .../dataset-download-request.service.ts | 19 ++++++++++-- .../study-download-request.service.ts | 30 ++++++++++++++++--- packages/zipper/src/commands/zip/index.ts | 1 + 5 files changed, 49 insertions(+), 7 deletions(-) diff --git a/packages/server/src/config/configuration.ts b/packages/server/src/config/configuration.ts index 09f6782..4d4ea48 100644 --- a/packages/server/src/config/configuration.ts +++ b/packages/server/src/config/configuration.ts @@ -43,5 +43,8 @@ export default () => ({ downloads: { bucketPrefix: 'downloads', jobName: process.env.ZIP_JOB_NAME + }, + endpoints: { + gateway: process.env.GATEWAY_ENDPOINT || 'http://localhost:3002/graphql' } }); diff --git a/packages/server/src/download-request/resolvers/study-download-request.resolver.ts b/packages/server/src/download-request/resolvers/study-download-request.resolver.ts index 32a3dc6..e620ca7 100644 --- a/packages/server/src/download-request/resolvers/study-download-request.resolver.ts +++ b/packages/server/src/download-request/resolvers/study-download-request.resolver.ts @@ -12,12 +12,12 @@ import { StudyPipe } from '../../study/pipes/study.pipe'; import { Study } from '../../study/study.model'; import { StudyDownloadRequestPipe } from '../pipes/study-download-request.pipe'; -@UseGuards(JwtAuthGuard, OrganizationGuard) @Resolver(() => StudyDownloadRequest) export class StudyDownloadRequestResolver { constructor(private readonly studyDownloadService: StudyDownloadService, private readonly studyPipe: StudyPipe) {} @Mutation(() => StudyDownloadRequest) + @UseGuards(JwtAuthGuard, OrganizationGuard) async createStudyDownload( @Args('downloadRequest', CreateStudyDownloadPipe) downloadRequest: CreateStudyDownloadRequest, @OrganizationContext() organization: Organization @@ -26,6 +26,7 @@ export class StudyDownloadRequestResolver { } @Query(() => [StudyDownloadRequest]) + @UseGuards(JwtAuthGuard, OrganizationGuard) async getStudyDownloads(@Args('study', { type: () => ID }, StudyPipe) study: Study): Promise { return this.studyDownloadService.getStudyDownloads(study); } diff --git a/packages/server/src/download-request/services/dataset-download-request.service.ts b/packages/server/src/download-request/services/dataset-download-request.service.ts index 4240b94..3bca8cd 100644 --- a/packages/server/src/download-request/services/dataset-download-request.service.ts +++ b/packages/server/src/download-request/services/dataset-download-request.service.ts @@ -16,6 +16,14 @@ import { randomUUID } from 'crypto'; @Injectable() export class DatasetDownloadService { private readonly expiration = this.configService.getOrThrow('entry.signedURLExpiration'); + private readonly gatewayEndpoint = this.configService.getOrThrow('endpoints.gateway'); + + /** The mutation to execute for marking a field as complete */ + private readonly markCompleteMutation = ` + mutation markDatasetFieldComplete($downloadRequest: ID!, $datasetField: DatasetDownloadField!, $code: String!) { + markDatasetFieldComplete(downloadRequest: $downloadRequest, datasetField: $datasetField, code: $code) + } + `; constructor( @InjectModel(DatasetDownloadRequest.name) @@ -64,8 +72,15 @@ export class DatasetDownloadService { entryJSONLocation: request.entryJSONLocation!, entryZIPLocation: request.entryZIPLocation!, webhookPayloadLocation: request.webhookPayloadLocation!, - webhookPayload: JSON.stringify({ test: 'hello' }), - webhook: 'http://localhost:3000/', + webhookPayload: JSON.stringify({ + query: this.markCompleteMutation, + variables: { + downloadRequest: request._id, + datasetField: DatasetDownloadField.ENTRY_ZIP.toString(), + code: request.verificationCode + } + }), + webhook: this.gatewayEndpoint, entries: await this.entryService.findForDataset(request.dataset), bucket: (await this.bucketFactory.getBucket(request.organization))!, organization: request.organization diff --git a/packages/server/src/download-request/services/study-download-request.service.ts b/packages/server/src/download-request/services/study-download-request.service.ts index ed86318..55efa7b 100644 --- a/packages/server/src/download-request/services/study-download-request.service.ts +++ b/packages/server/src/download-request/services/study-download-request.service.ts @@ -20,6 +20,14 @@ import { randomUUID } from 'crypto'; @Injectable() export class StudyDownloadService { private readonly expiration = this.configService.getOrThrow('entry.signedURLExpiration'); + private readonly gatewayEndpoint = this.configService.getOrThrow('endpoints.gateway'); + + /** The mutation to execute for marking a field as complete */ + private readonly markCompleteMutation = ` + mutation markStudyFieldComplete($downloadRequest: ID!, $studyField: StudyDownloadField!, $code: String!) { + markStudyFieldComplete(downloadRequest: $downloadRequest, studyField: $studyField, code: $code) + } + `; constructor( @InjectModel(StudyDownloadRequest.name) @@ -79,8 +87,15 @@ export class StudyDownloadService { entryJSONLocation: request.entryJSONLocation!, entryZIPLocation: request.entryZIPLocation!, webhookPayloadLocation: request.webhookPayloadLocation!, - webhookPayload: JSON.stringify({ test: 'hello' }), - webhook: 'http://localhost:3000', + webhookPayload: JSON.stringify({ + query: this.markCompleteMutation, + variables: { + downloadRequest: request._id, + studyField: StudyDownloadField.ENTRY_ZIP.toString(), + code: request.verificationCode + } + }), + webhook: this.gatewayEndpoint, entries: await this.entryService.getEntriesForStudy(request.study), bucket: (await this.bucketFactory.getBucket(request.organization))!, organization: request.organization @@ -92,8 +107,15 @@ export class StudyDownloadService { entryJSONLocation: request.taggedEntriesJSONLocation!, entryZIPLocation: request.taggedEntriesZipLocation!, webhookPayloadLocation: request.taggedEntryWebhookPayloadLocation!, - webhookPayload: JSON.stringify({ test: 'hello' }), - webhook: 'http://localhost:3000', + webhookPayload: JSON.stringify({ + query: this.markCompleteMutation, + variables: { + downloadRequest: request._id, + studyField: StudyDownloadField.TAGGED_ENTRIES_ZIP.toString(), + code: request.verificationCode + } + }), + webhook: this.gatewayEndpoint, entries: await this.getLabeledEntries(request), bucket: (await this.bucketFactory.getBucket(request.organization))!, organization: request.organization diff --git a/packages/zipper/src/commands/zip/index.ts b/packages/zipper/src/commands/zip/index.ts index 480a98a..4464b9a 100644 --- a/packages/zipper/src/commands/zip/index.ts +++ b/packages/zipper/src/commands/zip/index.ts @@ -51,6 +51,7 @@ export default class ZipHander extends Command { body: payload }); + // Check to make sure the request went through successfully if (result.status != 200) { console.error(await result.text()); throw new Error('Failed to call webhook'); From 6bfd367147d01a967a035b94dbcb22d218105653 Mon Sep 17 00:00:00 2001 From: cbolles Date: Tue, 7 May 2024 16:05:50 -0400 Subject: [PATCH 3/3] Add missing webhook url --- .../src/download-request/services/download-request.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/server/src/download-request/services/download-request.service.ts b/packages/server/src/download-request/services/download-request.service.ts index 890be9a..de26016 100644 --- a/packages/server/src/download-request/services/download-request.service.ts +++ b/packages/server/src/download-request/services/download-request.service.ts @@ -78,7 +78,7 @@ export class DownloadRequestService { args: [ `--target_entries=${mountPoint}/${request.entryJSONLocation}`, `--output_zip=${mountPoint}/${request.entryZIPLocation}`, - `--notification_webhook=http://localhost:3000`, + `--notification_webhook=${request.webhook}`, `--webhook_payload=${mountPoint}/${request.webhookPayloadLocation}` ] }