All files / lib/attachment-archive/worker failure-classification.ts

80% Statements 12/15
71.42% Branches 10/14
100% Functions 3/3
80% Lines 12/15

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75                          2x                 2x   2x 1x               1x                       5x       5x 5x 5x   5x 2x     3x                                  
import { isAttachmentAccessDeniedError } from "../attachment-errors";
import { buildAttachmentNotCleanArchiveFailure } from "../failure-state";
import { isNonCleanVirusScanStatus, VIRUS_SCAN_STATUS_TAG_KEY } from "../file-scan-status";
import { AttachmentArchiveCurrent, AttachmentArchiveSourceAttachment } from "../types";
 
type AttachmentArchiveFailureState = Pick<
  AttachmentArchiveCurrent,
  "errorMessage" | "failureCode" | "failureMessage" | "blockedAttachment"
>;
 
function isFailureStateCandidate(
  value: unknown,
): value is Omit<AttachmentArchiveFailureState, "errorMessage"> {
  return !!(
    value &&
    typeof value === "object" &&
    "failureCode" in value &&
    typeof (value as AttachmentArchiveFailureState).failureCode === "string"
  );
}
 
export function getAttachmentArchiveFailureState(error: unknown): AttachmentArchiveFailureState {
  const errorMessage = error instanceof Error ? error.message : String(error);
 
  if (isFailureStateCandidate(error)) {
    return {
      errorMessage,
      failureCode: error.failureCode,
      failureMessage: error.failureMessage,
      blockedAttachment: error.blockedAttachment,
    };
  }
 
  return { errorMessage };
}
 
export async function classifyAttachmentArchiveAccessFailure({
  attachment,
  error,
  getObjectTags,
}: {
  attachment: AttachmentArchiveSourceAttachment;
  error: unknown;
  getObjectTags: (bucket: string, key: string) => Promise<Record<string, string>>;
}) {
  Iif (!isAttachmentAccessDeniedError(error)) {
    return undefined;
  }
 
  try {
    const tags = await getObjectTags(attachment.bucket, attachment.key);
    const virusScanStatus = tags[VIRUS_SCAN_STATUS_TAG_KEY];
 
    if (!isNonCleanVirusScanStatus(virusScanStatus)) {
      return undefined;
    }
 
    return buildAttachmentNotCleanArchiveFailure({
      attachment,
      virusScanStatus,
    });
  } catch (taggingError) {
    console.warn(
      JSON.stringify({
        event: "attachment_archive_failure_tag_lookup_failed",
        bucket: attachment.bucket,
        key: attachment.key,
        filename: attachment.filename,
        message: taggingError instanceof Error ? taggingError.message : String(taggingError),
      }),
    );
    return undefined;
  }
}