All files / src/storage/get-file get-file.ts

81.81% Statements 27/33
75% Branches 18/24
100% Functions 1/1
82.75% Lines 24/29

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 76 77 78 793x 3x 3x   3x 3x         3x 8x                   8x       8x               8x   8x     8x 8x 8x     8x 8x 3x   8x   3x   3x             3x         3x   2x 2x                        
import { DEFAULT_ZONEFILE_LOOKUP_URL } from '../common/constants';
import { handleSignedEncryptedContents } from './sign';
import { getFileContents, getFileSignedUnencrypted } from './getters';
 
import { decryptContent } from 'micro-stacks/crypto';
import { getGlobalObject } from 'micro-stacks/common';
 
import type { GaiaHubConfig } from '../gaia/types';
import type { GetFileOptions } from '../common/types';
 
export async function getFile(path: string, getFileOptions: GetFileOptions) {
  const options: GetFileOptions = {
    decrypt: true,
    verify: false,
    app: getGlobalObject('location', { returnEmptyObject: true })!.origin,
    zoneFileLookupURL: DEFAULT_ZONEFILE_LOOKUP_URL,
    ...getFileOptions,
  };
 
  // in the case of signature verification, but no
  //  encryption expected, need to fetch _two_ files.
  Iif (options.verify && !options.decrypt) {
    return getFileSignedUnencrypted(path, options);
  }
 
  const storedContents = await getFileContents({
    path,
    app: options.app!,
    username: options.username,
    zoneFileLookupURL: options.zoneFileLookupURL,
    forceText: !!options.decrypt,
    gaiaHubConfig: options.gaiaHubConfig,
  });
  Iif (storedContents === null) return storedContents;
 
  Iif (typeof storedContents !== 'string')
    throw new Error('[micro-stacks/storage] Expected to get back a string for the cipherText');
 
  let verify = !!options.verify;
  let decrypt = !!options.decrypt;
  const privateKey = typeof options.decrypt === 'string' ? options.decrypt : options.privateKey;
 
  // try to set options if provided incorrectly
  if (storedContents.includes('signature') && storedContents.includes('publicKey')) verify = true;
  if (storedContents.includes('cipherText') && storedContents.includes('ephemeralPK'))
    decrypt = true;
 
  if (!verify && !decrypt) return storedContents;
 
  const doesNotContainCypherText = !storedContents.includes('cipherText');
 
  Iif (decrypt && doesNotContainCypherText)
    throw new Error(
      `[micro-stacks/storage] Expected to get back a string that includes cipherText, is it encrypted? got back: ${JSON.stringify(
        storedContents
      )}`
    );
 
  Iif (!privateKey)
    throw new Error(
      '[micro-stacks/storage] No private key was passed to getFile, a private key needs to be passed if decrypt is set to true'
    );
 
  if (!verify) return decryptContent(storedContents, { privateKey });
 
  if (decrypt && verify)
    return handleSignedEncryptedContents({
      path,
      storedContents,
      app: options.app!,
      privateKey,
      username: options.username,
      zoneFileLookupURL: options.zoneFileLookupURL,
      gaiaHubConfig: options.gaiaHubConfig,
    });
 
  throw new Error('[micro-stacks/storage] Should be unreachable.');
}