Skip to content

Commit dba4deb

Browse files
CCM-9872: Copy file to download bucket (#457)
1 parent 141816e commit dba4deb

File tree

18 files changed

+157
-32
lines changed

18 files changed

+157
-32
lines changed

infrastructure/terraform/components/sandbox/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ No requirements.
3131
| <a name="output_api_base_url"></a> [api\_base\_url](#output\_api\_base\_url) | n/a |
3232
| <a name="output_cognito_user_pool_client_id"></a> [cognito\_user\_pool\_client\_id](#output\_cognito\_user\_pool\_client\_id) | n/a |
3333
| <a name="output_cognito_user_pool_id"></a> [cognito\_user\_pool\_id](#output\_cognito\_user\_pool\_id) | n/a |
34+
| <a name="output_download_bucket_name"></a> [download\_bucket\_name](#output\_download\_bucket\_name) | n/a |
3435
| <a name="output_internal_bucket_name"></a> [internal\_bucket\_name](#output\_internal\_bucket\_name) | n/a |
3536
| <a name="output_quarantine_bucket_name"></a> [quarantine\_bucket\_name](#output\_quarantine\_bucket\_name) | n/a |
3637
| <a name="output_send_proof_queue_url"></a> [send\_proof\_queue\_url](#output\_send\_proof\_queue\_url) | n/a |

infrastructure/terraform/components/sandbox/outputs.tf

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ output "quarantine_bucket_name" {
3434
value = module.backend_api.quarantine_bucket_name
3535
}
3636

37+
output "download_bucket_name" {
38+
value = module.backend_api.download_bucket_name
39+
}
40+
3741
output "sftp_poll_lambda_name" {
3842
value = module.backend_api.sftp_poll_lambda_name
3943
}

infrastructure/terraform/modules/backend-api/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ No requirements.
6464
| Name | Description |
6565
|------|-------------|
6666
| <a name="output_api_base_url"></a> [api\_base\_url](#output\_api\_base\_url) | n/a |
67+
| <a name="output_download_bucket_name"></a> [download\_bucket\_name](#output\_download\_bucket\_name) | n/a |
6768
| <a name="output_internal_bucket_name"></a> [internal\_bucket\_name](#output\_internal\_bucket\_name) | n/a |
6869
| <a name="output_quarantine_bucket_name"></a> [quarantine\_bucket\_name](#output\_quarantine\_bucket\_name) | n/a |
6970
| <a name="output_send_proof_queue_url"></a> [send\_proof\_queue\_url](#output\_send\_proof\_queue\_url) | n/a |

infrastructure/terraform/modules/backend-api/locals.tf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ locals {
4747
TEMPLATES_EVENT_SOURCE = local.event_source
4848
TEMPLATES_INTERNAL_BUCKET_NAME = module.s3bucket_internal.id
4949
TEMPLATES_QUARANTINE_BUCKET_NAME = module.s3bucket_quarantine.id
50+
TEMPLATES_DOWNLOAD_BUCKET_NAME = module.s3bucket_download.id
5051
TEMPLATES_TABLE_NAME = aws_dynamodb_table.templates.name
5152
ENABLE_PROOFING = var.enable_proofing
5253
}

infrastructure/terraform/modules/backend-api/module_lambda_process_proof.tf

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,4 +114,18 @@ data "aws_iam_policy_document" "process_proof" {
114114

115115
resources = ["${module.s3bucket_internal.arn}/*"]
116116
}
117+
118+
statement {
119+
sid = "AllowS3DownloadWrite"
120+
effect = "Allow"
121+
122+
actions = [
123+
"s3:PutObject",
124+
"s3:PutObjectVersion",
125+
"s3:PutObjectTagging",
126+
"s3:PutObjectVersionTagging",
127+
]
128+
129+
resources = ["${module.s3bucket_download.arn}/*"]
130+
}
117131
}

infrastructure/terraform/modules/backend-api/outputs.tf

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ output "quarantine_bucket_name" {
2626
value = module.s3bucket_quarantine.id
2727
}
2828

29+
output "download_bucket_name" {
30+
value = module.s3bucket_download.id
31+
}
32+
2933
output "sftp_poll_lambda_name" {
3034
value = module.lambda_sftp_poll.function_name
3135
}

lambdas/backend-api/src/__tests__/templates/api/process-proof.test.ts

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,34 @@ test.each([
88
[
99
'NO_THREATS_FOUND',
1010
'PASSED',
11-
(letterFileRepository: LetterFileRepository) =>
11+
(letterFileRepository: LetterFileRepository) => {
1212
expect(
1313
letterFileRepository.copyFromQuarantineToInternal
1414
).toHaveBeenCalledWith(
1515
'proofs/template-id/proof.pdf',
1616
'version-id',
1717
'proofs/template-owner/template-id/proof.pdf'
18-
),
18+
);
19+
expect(
20+
letterFileRepository.copyFromQuarantineToDownload
21+
).toHaveBeenCalledWith(
22+
'proofs/template-id/proof.pdf',
23+
'version-id',
24+
'template-owner/proofs/template-id/proof.pdf'
25+
);
26+
},
1927
],
2028
[
2129
'THREATS_FOUND',
2230
'FAILED',
23-
(letterFileRepository) =>
31+
(letterFileRepository) => {
2432
expect(
2533
letterFileRepository.copyFromQuarantineToInternal
26-
).not.toHaveBeenCalled(),
34+
).not.toHaveBeenCalled();
35+
expect(
36+
letterFileRepository.copyFromQuarantineToDownload
37+
).not.toHaveBeenCalled();
38+
},
2739
],
2840
])(
2941
'calls dependencies as expected for a %s virus scan',

lambdas/backend-api/src/__tests__/templates/infra/letter-file-repository.test.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ const setup = () => {
1212

1313
const letterFileRepository = new LetterFileRepository(
1414
'quarantine-bucket',
15-
'internal-bucket'
15+
'internal-bucket',
16+
'download-bucket'
1617
);
1718

1819
return { letterFileRepository, mocks: { s3Client } };
@@ -39,6 +40,27 @@ describe('LetterUploadRepository', () => {
3940
});
4041
});
4142

43+
describe('copyFromQuarantineToDownload', () => {
44+
it('copies pdf template files from quarantine to download', async () => {
45+
const { letterFileRepository, mocks } = setup();
46+
47+
await letterFileRepository.copyFromQuarantineToDownload(
48+
's3/object/key',
49+
's3-object-version',
50+
's3/download/key'
51+
);
52+
53+
expect(mocks.s3Client).toHaveReceivedCommandWith(CopyObjectCommand, {
54+
Bucket: 'download-bucket',
55+
CopySource:
56+
'/quarantine-bucket/s3/object/key?versionId=s3-object-version',
57+
Key: 's3/download/key',
58+
MetadataDirective: 'COPY',
59+
TaggingDirective: 'COPY',
60+
});
61+
});
62+
});
63+
4264
describe('deleteFromQuarantine', () => {
4365
it('deletes files from quarantine', async () => {
4466
const { letterFileRepository, mocks } = setup();

lambdas/backend-api/src/__tests__/templates/infra/letter-upload-repository.test.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ const setup = () => {
1818

1919
const letterUploadRepository = new LetterUploadRepository(
2020
quarantineBucketName,
21-
internalBucketName
21+
internalBucketName,
22+
'download-bucket'
2223
);
2324

2425
return { letterUploadRepository, mocks: { s3Client } };

lambdas/backend-api/src/templates/api/process-proof.ts

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,24 @@ export const createHandler =
3636
scanResultStatus === 'NO_THREATS_FOUND' ? 'PASSED' : 'FAILED';
3737

3838
if (virusScanResult === 'PASSED') {
39-
await letterFileRepository.copyFromQuarantineToInternal(
40-
objectKey,
41-
versionId,
42-
internalKey
39+
const downloadKey = LetterProofRepository.getDownloadKey(
40+
owner,
41+
templateId,
42+
fileName
4343
);
44+
45+
await Promise.all([
46+
letterFileRepository.copyFromQuarantineToInternal(
47+
objectKey,
48+
versionId,
49+
internalKey
50+
),
51+
letterFileRepository.copyFromQuarantineToDownload(
52+
objectKey,
53+
versionId,
54+
downloadKey
55+
),
56+
]);
4457
} else {
4558
logger.error({
4659
description: 'File found that did not pass virus scan',

0 commit comments

Comments
 (0)