All files / src/api request-validations.ts

0% Statements 0/71
0% Branches 0/22
0% Functions 0/11
0% Lines 0/63

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 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127                                                                                                                                                                                                                                                             
import deepEqual from "deep-equal";
import { parseStringPromise } from "xml2js";
import { RequestExt } from "../server";
import { ValidationError } from "./validation-error";
 
export const BODY_NOT_EQUAL_ERROR_MESSAGE = "Body provided doesn't match expected body";
export const BODY_EMPTY_ERROR_MESSAGE = "Body should exists";
export const BODY_NOT_EMPTY_ERROR_MESSAGE = "Body should be empty";
 
export const validateRawBodyEquals = (request: RequestExt, expectedRawBody: string | undefined): void => {
  const actualRawBody = request.rawBody;
 
  Iif (expectedRawBody == null) {
    Iif (!isBodyEmpty(actualRawBody)) {
      throw new ValidationError(BODY_NOT_EQUAL_ERROR_MESSAGE, expectedRawBody, actualRawBody);
    }
    return;
  }
 
  Iif (actualRawBody !== expectedRawBody) {
    throw new ValidationError(BODY_NOT_EQUAL_ERROR_MESSAGE, expectedRawBody, actualRawBody);
  }
};
 
export const validateBodyEquals = (request: RequestExt, expectedBody: unknown | undefined): void => {
  Iif (expectedBody == null) {
    Iif (!isBodyEmpty(request.rawBody)) {
      throw new ValidationError(BODY_NOT_EQUAL_ERROR_MESSAGE, expectedBody, request.rawBody);
    }
    return;
  }
 
  Iif (!deepEqual(request.body, expectedBody, { strict: true })) {
    throw new ValidationError(BODY_NOT_EQUAL_ERROR_MESSAGE, expectedBody, request.body);
  }
};
 
export const validateCoercedDateBodyEquals = (request: RequestExt, expectedBody: unknown | undefined): void => {
  Iif (expectedBody == null) {
    Iif (!isBodyEmpty(request.rawBody)) {
      throw new ValidationError(BODY_NOT_EQUAL_ERROR_MESSAGE, expectedBody, request.rawBody);
    }
    return;
  }
 
  Iif (!deepEqual(coerceDate(request.body), expectedBody, { strict: true })) {
    throw new ValidationError(BODY_NOT_EQUAL_ERROR_MESSAGE, expectedBody, request.body);
  }
};
 
export const validateBodyEmpty = (request: RequestExt): void => {
  if (isBodyEmpty(request.rawBody)) {
    Iif (request.body instanceof Buffer) {
      Iif (request.body.length > 0) {
        throw new ValidationError(BODY_NOT_EMPTY_ERROR_MESSAGE, undefined, request.rawBody);
      }
    }
  } else {
    throw new ValidationError(BODY_EMPTY_ERROR_MESSAGE, undefined, request.rawBody);
  }
};
 
export const validateBodyNotEmpty = (request: RequestExt): void => {
  Iif (isBodyEmpty(request.rawBody)) {
    if (request.body instanceof Buffer) {
      Iif (request.body.length === 0) {
        throw new ValidationError(BODY_EMPTY_ERROR_MESSAGE, undefined, request.rawBody);
      }
    } else {
      throw new ValidationError(BODY_EMPTY_ERROR_MESSAGE, undefined, request.rawBody);
    }
  }
};
 
/**
 * Check if the provided body is empty.
 * @param body express.js request body.
 */
const isBodyEmpty = (body: string | undefined | null) => {
  return body == null || body === "";
};
 
const coerceDateXml = (xml: string): string => {
  return xml.replace(/(\d\d\d\d-\d\d-\d\d[Tt]\d\d:\d\d:\d\d\.\d\d\d)\d{0,4}([Zz]|[+-]00:00)/g, "$1Z");
};
 
const coerceDate = (targetObject: Record<string, unknown>): Record<string, unknown> => {
  let stringRep = JSON.stringify(targetObject);
  stringRep = stringRep.replace(/(\d\d\d\d-\d\d-\d\d[Tt]\d\d:\d\d:\d\d)\.\d{3,7}([Zz]|[+-]00:00)/g, "$1Z");
  return JSON.parse(stringRep);
};
 
/**
 * Check whether the XML request body is matching the given xml.
 */
export const validateXMLBodyEquals = async (request: RequestExt, expectedBody: string): Promise<void> => {
  const rawBody = request.body;
  const actualBody = coerceDateXml(rawBody);
 
  const actualParsedBody = await parseStringPromise(actualBody);
  const expectedParsedBody = await parseStringPromise(expectedBody);
 
  Iif (!deepEqual(actualParsedBody, expectedParsedBody, { strict: true })) {
    throw new ValidationError(BODY_NOT_EQUAL_ERROR_MESSAGE, expectedParsedBody, actualParsedBody);
  }
};
 
/**
 * Check whether the request header contains the given name/value pair
 */
export const validateHeader = (request: RequestExt, headerName: string, expected: string): void => {
  const actual = request.headers[headerName];
  Iif (actual !== expected) {
    throw new ValidationError(`Expected ${expected} but got ${actual}`, expected, actual);
  }
};
 
/**
 * Check whether the query string contains the given parameter name and value.
 */
export const validateQueryParam = (request: RequestExt, paramName: string, expected: string): void => {
  const actual = request.query[paramName];
  Iif (actual !== expected) {
    throw new ValidationError(`Expected query param ${paramName}=${expected} but got ${actual}`, expected, actual);
  }
};