Skip to content

Commit

Permalink
Merge pull request #7986 from opengovsg/release_v6.169.0
Browse files Browse the repository at this point in the history
build: release v6.169.0
  • Loading branch information
KenLSM authored Dec 11, 2024
2 parents 32916c4 + ae74833 commit e300ebf
Show file tree
Hide file tree
Showing 14 changed files with 206 additions and 109 deletions.
15 changes: 10 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,23 @@ All notable changes to this project will be documented in this file. Dates are d

Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).

#### [v6.168.0](https://github.com/opengovsg/FormSG/compare/v6.168.0...v6.168.0)
#### [v6.169.0](https://github.com/opengovsg/FormSG/compare/v6.168.0...v6.169.0)

- fix: search fields drag and drop mismatch [`#7972`](https://github.com/opengovsg/FormSG/pull/7972)
- feat: move to react email, update copy [`#7985`](https://github.com/opengovsg/FormSG/pull/7985)
- feat: add logs for uploads to s3 [`#7975`](https://github.com/opengovsg/FormSG/pull/7975)
- build: merge release v6.168.0 to develop [`#7973`](https://github.com/opengovsg/FormSG/pull/7973)
- build: release v6.168.0 [`#7971`](https://github.com/opengovsg/FormSG/pull/7971)

#### [v6.168.0](https://github.com/opengovsg/FormSG/compare/v6.167.0...v6.168.0)

> 3 December 2024

- fix: search fields drag and drop mismatch [`#7972`](https://github.com/opengovsg/FormSG/pull/7972)
- build: merge release v6.167.0 to develop [`#7964`](https://github.com/opengovsg/FormSG/pull/7964)
- feat: implement field search functionality [`#7958`](https://github.com/opengovsg/FormSG/pull/7958)
- feat(mrf be validation): enable mrf response validation hard block [`#7963`](https://github.com/opengovsg/FormSG/pull/7963)
- build: release v6.167.0 [`#7962`](https://github.com/opengovsg/FormSG/pull/7962)
- chore: bump version to v6.168.0 [`c69a28b`](https://github.com/opengovsg/FormSG/commit/c69a28b58d1e7f3f8faeb58624f408b830d115f7)
- chore: bump version to v6.168.0 [`49b9755`](https://github.com/opengovsg/FormSG/commit/49b9755b0312c66badef4f2a037c7fe35588a9a9)

#### [v6.167.0](https://github.com/opengovsg/FormSG/compare/v6.166.1...v6.167.0)

Expand All @@ -27,15 +31,16 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
- feat: update form create modal response options [`#7957`](https://github.com/opengovsg/FormSG/pull/7957)
- chore: include latest features in whats new page [`#7956`](https://github.com/opengovsg/FormSG/pull/7956)
- build: release v6.166.1 [`#7950`](https://github.com/opengovsg/FormSG/pull/7950)
- fix: trim previous text responses [`#7949`](https://github.com/opengovsg/FormSG/pull/7949)
- chore: bump version to v6.167.0 [`9f97c52`](https://github.com/opengovsg/FormSG/commit/9f97c52fa05aa990beb143139ef36b027e0b3874)
- chore: bump version to v6.166.1 [`844ee29`](https://github.com/opengovsg/FormSG/commit/844ee2912b45fd0d7dc3fedaab7b53adfa1375d8)

#### [v6.166.1](https://github.com/opengovsg/FormSG/compare/v6.166.0...v6.166.1)

> 27 November 2024

- fix: trim previous text responses [`#7949`](https://github.com/opengovsg/FormSG/pull/7949)
- build: release v6.166.0 [`#7945`](https://github.com/opengovsg/FormSG/pull/7945)
- chore: bump version to v6.166.1 [`844ee29`](https://github.com/opengovsg/FormSG/commit/844ee2912b45fd0d7dc3fedaab7b53adfa1375d8)
- chore: bump version to v6.166.1 [`18d9c74`](https://github.com/opengovsg/FormSG/commit/18d9c74cde8739bc96a0833f3764cb518e4e34aa)

#### [v6.166.0](https://github.com/opengovsg/FormSG/compare/v6.165.0...v6.166.0)

Expand Down
4 changes: 2 additions & 2 deletions frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "form-frontend",
"version": "6.168.0",
"version": "6.169.0",
"homepage": ".",
"type": "module",
"private": true,
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "FormSG",
"description": "Form Manager for Government",
"version": "6.168.0",
"version": "6.169.0",
"homepage": "https://form.gov.sg",
"authors": [
"FormSG <[email protected]>"
Expand Down
23 changes: 23 additions & 0 deletions react-email-preview/emails/EmailAddressVerificationOtp.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Meta, StoryFn } from '@storybook/react'

import EmailAddressVerificationOtp, {
type EmailAddressVerificationOtpHtmlData,
} from './EmailAddressVerificationOtp'

export default {
title: 'EmailPreview/EmailAddressVerificationOtp',
component: EmailAddressVerificationOtp,
decorators: [],
} as Meta

const Template: StoryFn<EmailAddressVerificationOtpHtmlData> = (args) => (
<EmailAddressVerificationOtp {...args} />
)

export const Default = Template.bind({})
Default.args = {
otpPrefix: 'ABC',
otp: '123456',
minutesToExpiry: 30,
appName: 'FormSG',
}
5 changes: 5 additions & 0 deletions react-email-preview/emails/EmailAddressVerificationOtp.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { EmailAddressVerificationOtp } from '../../src/app/views/templates/EmailAddressVerificationOtp'

export type { EmailAddressVerificationOtpHtmlData } from '../../src/app/views/templates/EmailAddressVerificationOtp'

export default EmailAddressVerificationOtp
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ export const validateStorageSubmissionParams = celebrate({
*/
const asyncVirusScanning = (
responses: ParsedClearFormFieldResponse[],
formId: string,
): ResultAsync<
ParsedClearFormFieldResponse,
| VirusScanFailedError
Expand All @@ -176,6 +177,7 @@ const asyncVirusScanning = (
if (isQuarantinedAttachmentResponse(response)) {
return SubmissionService.triggerVirusScanThenDownloadCleanFileChain(
response,
formId,
)
}

Expand All @@ -191,6 +193,7 @@ const asyncVirusScanning = (
*/
const devModeSyncVirusScanning = async (
responses: ParsedClearFormFieldResponse[],
formId: string,
): Promise<
Result<
ParsedClearFormFieldResponse,
Expand All @@ -209,6 +212,7 @@ const devModeSyncVirusScanning = async (
const attachmentResponse =
await SubmissionService.triggerVirusScanThenDownloadCleanFileChain(
response,
formId,
)
results.push(attachmentResponse)
if (attachmentResponse.isErr()) break
Expand Down Expand Up @@ -246,8 +250,18 @@ export const scanAndRetrieveAttachments = async (
// run the virus scanning asynchronously for better performance (lower latency).
// Note on .combine: if any scans or downloads error out, it will short circuit and return the first error.
isDev
? Result.combine(await devModeSyncVirusScanning(req.body.responses))
: await ResultAsync.combine(asyncVirusScanning(req.body.responses))
? Result.combine(
await devModeSyncVirusScanning(
req.body.responses,
req.formsg.formDef._id.toString(),
),
)
: await ResultAsync.combine(
asyncVirusScanning(
req.body.responses,
req.formsg.formDef._id.toString(),
),
)

if (scanAndRetrieveFilesResult.isErr()) {
logger.error({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,14 +184,15 @@ type IdTaggedParsedClearAttachmentResponseV3 =
*/
const asyncVirusScanning = (
responses: IdTaggedParsedClearAttachmentResponseV3[],
formId: string,
): ResultAsync<
IdTaggedParsedClearAttachmentResponseV3,
| VirusScanFailedError
| DownloadCleanFileFailedError
| MaliciousFileDetectedError
>[] =>
responses.map((response) =>
triggerVirusScanThenDownloadCleanFileChain(response.answer).map(
triggerVirusScanThenDownloadCleanFileChain(response.answer, formId).map(
(attachmentResponse) => ({ ...response, answer: attachmentResponse }),
),
)
Expand All @@ -203,6 +204,7 @@ const asyncVirusScanning = (
*/
const devModeSyncVirusScanning = async (
responses: IdTaggedParsedClearAttachmentResponseV3[],
formId: string,
): Promise<
Result<
IdTaggedParsedClearAttachmentResponseV3,
Expand All @@ -216,6 +218,7 @@ const devModeSyncVirusScanning = async (
// await to pause for...of loop until the virus scanning and downloading of clean file is completed.
const attachmentResponse = await triggerVirusScanThenDownloadCleanFileChain(
response.answer,
formId,
)
if (attachmentResponse.isErr()) {
results.push(err(attachmentResponse.error))
Expand Down Expand Up @@ -267,10 +270,16 @@ export const scanAndRetrieveAttachments = async (
// Note on .combine: if any scans or downloads error out, it will short circuit and return the first error.
isDev
? Result.combine(
await devModeSyncVirusScanning(attachmentResponsesToRetrieve),
await devModeSyncVirusScanning(
attachmentResponsesToRetrieve,
req.formsg.formDef._id.toString(),
),
)
: await ResultAsync.combine(
asyncVirusScanning(attachmentResponsesToRetrieve),
asyncVirusScanning(
attachmentResponsesToRetrieve,
req.formsg.formDef._id.toString(),
),
)

if (scanAndRetrieveFilesResult.isErr()) {
Expand Down
64 changes: 43 additions & 21 deletions src/app/modules/submission/submission.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -432,33 +432,55 @@ export const triggerVirusScanThenDownloadCleanFileChain = <
| ParsedClearAttachmentFieldResponseV3,
>(
response: T,
formId: string,
): ResultAsync<
T,
| VirusScanFailedError
| DownloadCleanFileFailedError
| MaliciousFileDetectedError
> =>
> => {
const logMeta = {
action: 'triggerVirusScanThenDownloadCleanFileChain',
formId,
quarantineFileKey: response.answer,
}
// Step 3: Trigger lambda to scan attachments.
triggerVirusScanning(response.answer)
.mapErr((error) => {
if (error instanceof MaliciousFileDetectedError)
return new MaliciousFileDetectedError(response.filename)
return error
})
.map((lambdaOutput) => lambdaOutput.body)
// Step 4: Retrieve attachments from the clean bucket.
.andThen((cleanAttachment) =>
// Retrieve attachment from clean bucket.
downloadCleanFile(
cleanAttachment.cleanFileKey,
cleanAttachment.destinationVersionId,
).map((attachmentBuffer) => ({
...response,
// Replace content with attachmentBuffer and answer with filename.
content: attachmentBuffer,
answer: response.filename,
})),
)
return (
triggerVirusScanning(response.answer)
.mapErr((error) => {
if (error instanceof MaliciousFileDetectedError) {
logger.error({
message: 'Malicious file detected during lambda virus scan',
meta: logMeta,
error,
})
return new MaliciousFileDetectedError(response.filename)
}
return error
})
.map((lambdaOutput) => {
logger.info({
message:
'Successfully retrieved clean file from virus scanning lambda',
meta: { ...logMeta, cleanFileKey: lambdaOutput.body.cleanFileKey },
})
return lambdaOutput.body
})
// Step 4: Retrieve attachments from the clean bucket.
.andThen((cleanAttachment) =>
// Retrieve attachment from clean bucket.
downloadCleanFile(
cleanAttachment.cleanFileKey,
cleanAttachment.destinationVersionId,
).map((attachmentBuffer) => ({
...response,
// Replace content with attachmentBuffer and answer with filename.
content: attachmentBuffer,
answer: response.filename,
})),
)
)
}

type AttachmentReducerData = {
attachmentMetadata: AttachmentMetadata // type alias for Map<string, string>
Expand Down
Loading

0 comments on commit e300ebf

Please sign in to comment.