Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/feat/child-storage' into uat
Browse files Browse the repository at this point in the history
  • Loading branch information
KenLSM committed Dec 12, 2024
2 parents 4b38cc6 + 1156f7a commit dfe920d
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -244,8 +244,7 @@ export const MyInfoFieldPanel = ({ searchValue }: { searchValue: string }) => {
</Box>
)}
</Droppable>
{user?.betaFlags?.children &&
form?.responseMode === FormResponseMode.Email ? (
{user?.betaFlags?.children ? (
<Droppable isDropDisabled droppableId={CREATE_MYINFO_CHILDREN_DROP_ID}>
{(provided) => (
<Box ref={provided.innerRef} {...provided.droppableProps}>
Expand Down
2 changes: 1 addition & 1 deletion src/app/modules/myinfo/myinfo.util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -521,7 +521,7 @@ export const handleMyInfoChildHashResponse = (
// Validate each answer (child)
childAnswer.forEach((attrAnswer, subFieldIndex) => {
const key = getMyInfoChildHashKey(
field._id as string,
field._id,
subFields[subFieldIndex],
childIndex,
childName,
Expand Down
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
12 changes: 3 additions & 9 deletions src/app/modules/submission/submission.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@ import {
MyInfoMissingLoginCookieError,
} from '../myinfo/myinfo.errors'
import { MyInfoKey } from '../myinfo/myinfo.types'
import { getMyInfoChildHashKey } from '../myinfo/myinfo.util'
import {
InvalidPaymentProductsError,
PaymentNotFoundError,
Expand Down Expand Up @@ -752,17 +751,12 @@ export const getAnswersForChild = (
return []
}
return response.answerArray.flatMap((arr, childIdx) => {
// First array element is always child name
const childName = arr[0]
return arr.map((answer, idx) => {
const subfield = subFields[idx]
return {
_id: getMyInfoChildHashKey(
response._id,
subFields[idx],
childIdx,
childName,
),
// Recreates the individual _id of the child field based on the parent field's _id and the subfield
// e.g., childrenbirthrecords.67585515e1ced6d790a91e14.childname.0
_id: `${MyInfoAttribute.ChildrenBirthRecords}.${response._id}.${subFields[idx]}.${childIdx}`,
fieldType: response.fieldType,
// qnChildIdx represents the index of the MyInfo field
// childIdx represents the index of the child in this MyInfo field
Expand Down

0 comments on commit dfe920d

Please sign in to comment.