Skip to content

Commit

Permalink
CMDCT-4190: Backend form validation for create banner endpoint (#85)
Browse files Browse the repository at this point in the history
Co-authored-by: benmartin-coforma <[email protected]>
  • Loading branch information
angelaco11 and benmartin-coforma authored Jan 6, 2025
1 parent 62e3059 commit 8a6957f
Show file tree
Hide file tree
Showing 7 changed files with 116 additions and 7 deletions.
12 changes: 12 additions & 0 deletions services/app-api/handlers/banners/create.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,13 @@ const testEvent: APIGatewayProxyEvent = {
headers: { "cognito-identity-id": "test" },
};

const testEventWithInvalidData: APIGatewayProxyEvent = {
...proxyEvent,
body: `{"description":"test description","link":"test link","startDate":"1000","endDate":2000}`,
pathParameters: { bannerId: "testKey" },
headers: { "cognito-identity-id": "test" },
};

describe("Test createBanner API method", () => {
beforeEach(() => {
jest.clearAllMocks();
Expand Down Expand Up @@ -74,4 +81,9 @@ describe("Test createBanner API method", () => {
expect(res.statusCode).toBe(StatusCodes.BadRequest);
expect(res.body).toContain(error.MISSING_DATA);
});

test("Test invalid data causes internal server error", async () => {
const res = await createBanner(testEventWithInvalidData);
expect(res.statusCode).toBe(StatusCodes.BadRequest);
});
});
14 changes: 8 additions & 6 deletions services/app-api/handlers/banners/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import {
} from "../../libs/response-lib";
import { canWriteBanner } from "../../utils/authorization";
import { parseBannerId } from "../../libs/param-lib";
import { validateBannerPayload } from "../../utils/validation";
import { logger } from "../../libs/debug-lib";
import { BannerData } from "../../types/banner";

export const createBanner = handler(parseBannerId, async (request) => {
Expand All @@ -19,15 +21,15 @@ export const createBanner = handler(parseBannerId, async (request) => {
return forbidden(error.UNAUTHORIZED);
}

if (!request?.body) {
let validatedPayload: BannerData | undefined;
try {
validatedPayload = await validateBannerPayload(request.body);
} catch (err) {
logger.error(err);
return badRequest("Invalid request");
}

const unvalidatedPayload = request.body;

//TO DO: add validation & validation test back
const { title, description, link, startDate, endDate } =
unvalidatedPayload as BannerData;
const { title, description, link, startDate, endDate } = validatedPayload;

const currentTime = Date.now();

Expand Down
9 changes: 9 additions & 0 deletions services/app-api/handlers/reports/create.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,12 @@ describe("Test create report handler", () => {
expect(res.statusCode).toBe(StatusCodes.Ok);
});
});

test("Test invalid report type", async () => {
const invalidDataEvent = {
...proxyEvent,
pathParameters: { reportType: "BM", state: "NM" },
} as APIGatewayProxyEvent;
const res = await createReport(invalidDataEvent);
expect(res.statusCode).toBe(StatusCodes.BadRequest);
});
3 changes: 2 additions & 1 deletion services/app-api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@
"jsdom": "20.0.0",
"jwt-decode": "3.1.2",
"ksuid": "^3.0.0",
"util": "^0.12.5"
"util": "^0.12.5",
"yup": "^1.6.1"
},
"jest": {
"verbose": true,
Expand Down
31 changes: 31 additions & 0 deletions services/app-api/utils/tests/validation.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { validateBannerPayload } from "../validation";

const validObject = {
key: "1023",
title: "this is a title",
description: "this is a description",
link: "https://www.google.com",
startDate: 11022933,
endDate: 103444405,
};

const invalidObject = {
// missing key
title: "this is a title",
description: "this is a description",
link: "https://www.google.com",
startDate: 11022933,
endDate: 103444405,
};

describe("Test validateBannerPayload function", () => {
it("successfully validates a valid object", async () => {
const validatedData = await validateBannerPayload(validObject);
expect(validatedData).toEqual(validObject);
});
it("throws an error when validating an invalid object", () => {
expect(async () => {
await validateBannerPayload(invalidObject);
}).rejects.toThrow();
});
});
24 changes: 24 additions & 0 deletions services/app-api/utils/validation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { number, object, string } from "yup";
import { BannerData } from "../types/banner";
import { error } from "./constants";

const bannerValidateSchema = object().shape({
key: string().required(),
title: string().required(),
description: string().required(),
link: string().url().notRequired(),
startDate: number().notRequired(),
endDate: number().notRequired(),
});

export const validateBannerPayload = async (payload: object | undefined) => {
if (!payload) {
throw new Error(error.MISSING_DATA);
}

const validatedPayload = await bannerValidateSchema.validate(payload, {
stripUnknown: true,
});

return validatedPayload as BannerData;
};
30 changes: 30 additions & 0 deletions services/app-api/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3536,6 +3536,11 @@ prompts@^2.0.1:
kleur "^3.0.3"
sisteransi "^1.0.5"

property-expr@^2.0.5:
version "2.0.6"
resolved "https://registry.yarnpkg.com/property-expr/-/property-expr-2.0.6.tgz#f77bc00d5928a6c748414ad12882e83f24aec1e8"
integrity sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA==

psl@^1.1.33:
version "1.9.0"
resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7"
Expand Down Expand Up @@ -3817,6 +3822,11 @@ test-exclude@^6.0.0:
glob "^7.1.4"
minimatch "^3.0.4"

tiny-case@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/tiny-case/-/tiny-case-1.0.3.tgz#d980d66bc72b5d5a9ca86fb7c9ffdb9c898ddd03"
integrity sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q==

[email protected]:
version "1.0.5"
resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc"
Expand All @@ -3834,6 +3844,11 @@ to-regex-range@^5.0.1:
dependencies:
is-number "^7.0.0"

toposort@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/toposort/-/toposort-2.0.2.tgz#ae21768175d1559d48bef35420b2f4962f09c330"
integrity sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==

tough-cookie@^4.0.0:
version "4.1.4"
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.4.tgz#945f1461b45b5a8c76821c33ea49c3ac192c1b36"
Expand Down Expand Up @@ -3905,6 +3920,11 @@ type-fest@^0.21.3:
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37"
integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==

type-fest@^2.19.0:
version "2.19.0"
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.19.0.tgz#88068015bb33036a598b952e55e9311a60fd3a9b"
integrity sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==

undici-types@~6.19.2:
version "6.19.8"
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02"
Expand Down Expand Up @@ -4104,3 +4124,13 @@ yocto-queue@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==

yup@^1.6.1:
version "1.6.1"
resolved "https://registry.yarnpkg.com/yup/-/yup-1.6.1.tgz#8defcff9daaf9feac178029c0e13b616563ada4b"
integrity sha512-JED8pB50qbA4FOkDol0bYF/p60qSEDQqBD0/qeIrUCG1KbPBIQ776fCUNb9ldbPcSTxA69g/47XTo4TqWiuXOA==
dependencies:
property-expr "^2.0.5"
tiny-case "^1.0.3"
toposort "^2.0.2"
type-fest "^2.19.0"

0 comments on commit 8a6957f

Please sign in to comment.