From 08d69bd92842d9ea28fb404863ca6d1e8d3ef090 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 10 Feb 2022 17:42:15 +0000 Subject: [PATCH 01/10] chore(deps-dev): bump eslint-plugin-jest from 26.0.0 to 26.1.0 (#3419) Bumps [eslint-plugin-jest](https://github.com/jest-community/eslint-plugin-jest) from 26.0.0 to 26.1.0. - [Release notes](https://github.com/jest-community/eslint-plugin-jest/releases) - [Changelog](https://github.com/jest-community/eslint-plugin-jest/blob/main/CHANGELOG.md) - [Commits](https://github.com/jest-community/eslint-plugin-jest/compare/v26.0.0...v26.1.0) --- updated-dependencies: - dependency-name: eslint-plugin-jest dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 52 +++++++++++++++++++++++------------------------ package.json | 2 +- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1c1ecc75c7..a4d29221c4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6296,43 +6296,43 @@ } }, "@typescript-eslint/utils": { - "version": "5.10.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.10.2.tgz", - "integrity": "sha512-vuJaBeig1NnBRkf7q9tgMLREiYD7zsMrsN1DA3wcoMDvr3BTFiIpKjGiYZoKPllfEwN7spUjv7ZqD+JhbVjEPg==", + "version": "5.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.11.0.tgz", + "integrity": "sha512-g2I480tFE1iYRDyMhxPAtLQ9HAn0jjBtipgTCZmd9I9s11OV8CTsG+YfFciuNDcHqm4csbAgC2aVZCHzLxMSUw==", "dev": true, "requires": { "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.10.2", - "@typescript-eslint/types": "5.10.2", - "@typescript-eslint/typescript-estree": "5.10.2", + "@typescript-eslint/scope-manager": "5.11.0", + "@typescript-eslint/types": "5.11.0", + "@typescript-eslint/typescript-estree": "5.11.0", "eslint-scope": "^5.1.1", "eslint-utils": "^3.0.0" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "5.10.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.10.2.tgz", - "integrity": "sha512-39Tm6f4RoZoVUWBYr3ekS75TYgpr5Y+X0xLZxXqcZNDWZdJdYbKd3q2IR4V9y5NxxiPu/jxJ8XP7EgHiEQtFnw==", + "version": "5.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.11.0.tgz", + "integrity": "sha512-z+K4LlahDFVMww20t/0zcA7gq/NgOawaLuxgqGRVKS0PiZlCTIUtX0EJbC0BK1JtR4CelmkPK67zuCgpdlF4EA==", "dev": true, "requires": { - "@typescript-eslint/types": "5.10.2", - "@typescript-eslint/visitor-keys": "5.10.2" + "@typescript-eslint/types": "5.11.0", + "@typescript-eslint/visitor-keys": "5.11.0" } }, "@typescript-eslint/types": { - "version": "5.10.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.10.2.tgz", - "integrity": "sha512-Qfp0qk/5j2Rz3p3/WhWgu4S1JtMcPgFLnmAKAW061uXxKSa7VWKZsDXVaMXh2N60CX9h6YLaBoy9PJAfCOjk3w==", + "version": "5.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.11.0.tgz", + "integrity": "sha512-cxgBFGSRCoBEhvSVLkKw39+kMzUKHlJGVwwMbPcTZX3qEhuXhrjwaZXWMxVfxDgyMm+b5Q5b29Llo2yow8Y7xQ==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "5.10.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.10.2.tgz", - "integrity": "sha512-WHHw6a9vvZls6JkTgGljwCsMkv8wu8XU8WaYKeYhxhWXH/atZeiMW6uDFPLZOvzNOGmuSMvHtZKd6AuC8PrwKQ==", + "version": "5.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.11.0.tgz", + "integrity": "sha512-yVH9hKIv3ZN3lw8m/Jy5I4oXO4ZBMqijcXCdA4mY8ull6TPTAoQnKKrcZ0HDXg7Bsl0Unwwx7jcXMuNZc0m4lg==", "dev": true, "requires": { - "@typescript-eslint/types": "5.10.2", - "@typescript-eslint/visitor-keys": "5.10.2", + "@typescript-eslint/types": "5.11.0", + "@typescript-eslint/visitor-keys": "5.11.0", "debug": "^4.3.2", "globby": "^11.0.4", "is-glob": "^4.0.3", @@ -6341,12 +6341,12 @@ } }, "@typescript-eslint/visitor-keys": { - "version": "5.10.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.10.2.tgz", - "integrity": "sha512-zHIhYGGGrFJvvyfwHk5M08C5B5K4bewkm+rrvNTKk1/S15YHR+SA/QUF8ZWscXSfEaB8Nn2puZj+iHcoxVOD/Q==", + "version": "5.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.11.0.tgz", + "integrity": "sha512-E8w/vJReMGuloGxJDkpPlGwhxocxOpSVgSvjiLO5IxZPmxZF30weOeJYyPSEACwM+X4NziYS9q+WkN/2DHYQwA==", "dev": true, "requires": { - "@typescript-eslint/types": "5.10.2", + "@typescript-eslint/types": "5.11.0", "eslint-visitor-keys": "^3.0.0" } }, @@ -11028,9 +11028,9 @@ } }, "eslint-plugin-jest": { - "version": "26.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-26.0.0.tgz", - "integrity": "sha512-Fvs0YgJ/nw9FTrnqTuMGVrkozkd07jkQzWm0ajqyHlfcsdkxGfAuv30fgfWHOnHiCr9+1YQ365CcDX7vrNhqQg==", + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-26.1.0.tgz", + "integrity": "sha512-vjF6RvcKm4xZSJgCmXb9fXmhzTva+I9jtj9Qv5JeZQTRocU7WT1g3Kx0cZ+00SekPe2DtSWDawHtSj4RaxFhXQ==", "dev": true, "requires": { "@typescript-eslint/utils": "^5.10.0" diff --git a/package.json b/package.json index e01e8b2ffb..d78fe96590 100644 --- a/package.json +++ b/package.json @@ -211,7 +211,7 @@ "eslint-config-prettier": "^8.3.0", "eslint-plugin-angular": "^4.1.0", "eslint-plugin-import": "^2.25.4", - "eslint-plugin-jest": "^26.0.0", + "eslint-plugin-jest": "^26.1.0", "eslint-plugin-prettier": "^4.0.0", "eslint-plugin-simple-import-sort": "^7.0.0", "eslint-plugin-typesafe": "^0.5.2", From 45fbad276004de017863d47adf27b4d2abfe5942 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 13 Feb 2022 19:36:29 +0000 Subject: [PATCH 02/10] fix(deps): bump libphonenumber-js from 1.9.48 to 1.9.49 in /shared (#3423) Bumps [libphonenumber-js](https://gitlab.com/catamphetamine/libphonenumber-js) from 1.9.48 to 1.9.49. - [Release notes](https://gitlab.com/catamphetamine/libphonenumber-js/tags) - [Changelog](https://gitlab.com/catamphetamine/libphonenumber-js/blob/master/CHANGELOG.md) - [Commits](https://gitlab.com/catamphetamine/libphonenumber-js/compare/v1.9.48...v1.9.49) --- updated-dependencies: - dependency-name: libphonenumber-js dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- shared/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/shared/package-lock.json b/shared/package-lock.json index 8573c3cc1c..be957aa83f 100644 --- a/shared/package-lock.json +++ b/shared/package-lock.json @@ -349,9 +349,9 @@ } }, "libphonenumber-js": { - "version": "1.9.48", - "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.9.48.tgz", - "integrity": "sha512-2aiDGkr5Ty7LZRhKhnMeV9tfRbzd2zahgF12I0v11AFwEelSdiu5t8/Npf3UejKcuoO4anqTdjnIW3dEtj1xYQ==" + "version": "1.9.49", + "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.9.49.tgz", + "integrity": "sha512-/wEOIONcVboFky+lWlCaF7glm1FhBz11M5PHeCApA+xDdVfmhKjHktHS8KjyGxouV5CSXIr4f3GvLSpJa4qMSg==" }, "lie": { "version": "3.3.0", From 0956c9600ec5ccbf39899b9f3ba842a55f7482d4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Feb 2022 10:53:04 +0800 Subject: [PATCH 03/10] fix(deps): bump helmet from 5.0.1 to 5.0.2 (#3319) * fix(deps): bump helmet from 5.0.1 to 5.0.2 Bumps [helmet](https://github.com/helmetjs/helmet) from 5.0.1 to 5.0.2. - [Release notes](https://github.com/helmetjs/helmet/releases) - [Changelog](https://github.com/helmetjs/helmet/blob/main/CHANGELOG.md) - [Commits](https://github.com/helmetjs/helmet/compare/v5.0.1...v5.0.2) --- updated-dependencies: - dependency-name: helmet dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * fix: update ContentSecurityPolicyOptions import path Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Antariksh --- package-lock.json | 6 +++--- package.json | 2 +- src/app/loaders/express/helmet.ts | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index a4d29221c4..d108a23d4c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12885,9 +12885,9 @@ "dev": true }, "helmet": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/helmet/-/helmet-4.6.0.tgz", - "integrity": "sha512-HVqALKZlR95ROkrnesdhbbZJFi/rIVSoNq6f3jA/9u6MIbTsPh3xZwihjeI5+DO/2sOV6HMHooXcEOuwskHpTg==" + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/helmet/-/helmet-5.0.2.tgz", + "integrity": "sha512-QWlwUZZ8BtlvwYVTSDTBChGf8EOcQ2LkGMnQJxSzD1mUu8CCjXJZq/BXP8eWw4kikRnzlhtYo3lCk0ucmYA3Vg==" }, "hex-color-regex": { "version": "1.1.0", diff --git a/package.json b/package.json index d78fe96590..7b800af151 100644 --- a/package.json +++ b/package.json @@ -113,7 +113,7 @@ "file-saver": "^2.0.5", "font-awesome": "4.7.0", "fp-ts": "^2.11.7", - "helmet": "^4.6.0", + "helmet": "^5.0.2", "hot-shots": "^9.0.0", "http-status-codes": "^2.2.0", "intl-tel-input": "~12.4.0", diff --git a/src/app/loaders/express/helmet.ts b/src/app/loaders/express/helmet.ts index 88b0522197..639e154780 100644 --- a/src/app/loaders/express/helmet.ts +++ b/src/app/loaders/express/helmet.ts @@ -1,6 +1,6 @@ import { RequestHandler } from 'express' import helmet from 'helmet' -import { ContentSecurityPolicyOptions } from 'helmet/dist/middlewares/content-security-policy' +import { ContentSecurityPolicyOptions } from 'helmet/dist/types/middlewares/content-security-policy' import config from '../../config/config' import { sentryConfig } from '../../config/features/sentry.config' From b98295679d516ec7753b72e36347195c3f0e02c9 Mon Sep 17 00:00:00 2001 From: Timothee Groleau Date: Mon, 14 Feb 2022 14:27:27 +0800 Subject: [PATCH 04/10] fix(docs): Add missing characters for consistency (#3426) --- docs/DEPLOYMENT_SETUP.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/DEPLOYMENT_SETUP.md b/docs/DEPLOYMENT_SETUP.md index f76e420d07..03fb873fa3 100644 --- a/docs/DEPLOYMENT_SETUP.md +++ b/docs/DEPLOYMENT_SETUP.md @@ -66,9 +66,9 @@ Firstly, name the secret with a unique secret name and store the secret value in ```json { "accountSid": "", - "apiKey": "redacted>", - "apiSecret": "redacted>", - "messagingServiceSid": "redacted>" + "apiKey": "", + "apiSecret": "", + "messagingServiceSid": "" } ``` From c3c92460327d4f4adbf90c09bd6ac407f656d55e Mon Sep 17 00:00:00 2001 From: Snyk bot Date: Mon, 14 Feb 2022 08:47:25 +0200 Subject: [PATCH 05/10] chore: bump spcp-auth-client to 1.14.15 (#3341) Co-authored-by: Antariksh --- package-lock.json | 30 ++++++++++++++++++++---------- package.json | 2 +- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/package-lock.json b/package-lock.json index d108a23d4c..fd579669ce 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5390,17 +5390,17 @@ } }, "@opengovsg/spcp-auth-client": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@opengovsg/spcp-auth-client/-/spcp-auth-client-1.4.14.tgz", - "integrity": "sha512-fHm+DUfsUmPr59C3gsYLcnql+ZSIxTNQ31UIFJI0AVvNHKh0VBEaxPlniU6srOpZ9qNIjrH0sTYyirEqV7zCqg==", + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@opengovsg/spcp-auth-client/-/spcp-auth-client-1.4.15.tgz", + "integrity": "sha512-6FuILIQ6ZL6PrdUrosv2f5jK5px9enAYH7T8v7CX6X+cRKXj9+V18/Po4wCLFKCCnbxyF9JARyRgOslCscLX9g==", "requires": { "@xmldom/xmldom": "^0.8.0", - "axios": "^0.24.0", + "axios": "^0.25.0", "base-64": "^1.0.0", "jsonwebtoken": "^8.3.0", "lodash": "^4.17.21", "xml-crypto": "^2.1.3", - "xml-encryption": "^1.3.0", + "xml-encryption": "^2.0.0", "xml2json-light": "^1.0.6", "xpath": "0.0.32" }, @@ -5410,12 +5410,21 @@ "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.0.tgz", "integrity": "sha512-7wVnF+rKrVDEo1xjzkkidTG0grclaVnX0vKa0z9JSXcEdtftUJjvU33jLGg6SHyvs3eeqEsI7jZ6NxYfRypEEg==" }, - "axios": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.24.0.tgz", - "integrity": "sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==", + "xml-encryption": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/xml-encryption/-/xml-encryption-2.0.0.tgz", + "integrity": "sha512-4Av83DdvAgUQQMfi/w8G01aJshbEZP9ewjmZMpS9t3H+OCZBDvyK4GJPnHGfWiXlArnPbYvR58JB9qF2x9Ds+Q==", "requires": { - "follow-redirects": "^1.14.4" + "@xmldom/xmldom": "^0.7.0", + "escape-html": "^1.0.3", + "xpath": "0.0.32" + }, + "dependencies": { + "@xmldom/xmldom": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.7.5.tgz", + "integrity": "sha512-V3BIhmY36fXZ1OtVcI9W+FxQqxVLsPKcNjWigIaa81dLC9IolJl5Mt4Cvhmr0flUnjSpTdrbMTSbXqYqV5dT6A==" + } } } } @@ -25754,6 +25763,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/xml-encryption/-/xml-encryption-1.3.0.tgz", "integrity": "sha512-3P8C4egMMxSR1BmsRM+fG16a3WzOuUEQKS2U4c3AZ5v7OseIfdUeVkD8dwxIhuLryFZSRWUL5OP6oqkgU7hguA==", + "dev": true, "requires": { "@xmldom/xmldom": "^0.7.0", "escape-html": "^1.0.3", diff --git a/package.json b/package.json index 7b800af151..ca080a0c38 100644 --- a/package.json +++ b/package.json @@ -62,7 +62,7 @@ "@opengovsg/myinfo-gov-client": "^4.0.0", "@opengovsg/ng-file-upload": "^12.2.15", "@opengovsg/sgid-client": "0.0.12", - "@opengovsg/spcp-auth-client": "^1.4.14", + "@opengovsg/spcp-auth-client": "^1.4.15", "@sentry/browser": "^6.16.1", "@sentry/integrations": "^6.16.1", "@stablelib/base64": "^1.0.1", From e4e959408e492b0314ac847a81cc5d43b6878d7e Mon Sep 17 00:00:00 2001 From: tshuli <63710093+tshuli@users.noreply.github.com> Date: Mon, 14 Feb 2022 15:20:31 +0800 Subject: [PATCH 06/10] refactor: use combined route validators and handlers (#3428) * refactor(combine-validators-and-handlers): perform combination for contact verification OTP * refactor(combine-validators-and-handlers): remove additional validation and use Segments enum * refactor(combine-validators-and-handlers): apply for sendContactOtp * refactor(combine-validators-and-handlers): apply for auth module * refactor(combine-validators-and-handlers): apply for billing module * refactor(combine-validators-and-handlers): apply for admin-form module * refactor(combine-validators-and-handlers): apply for example route * refactor(combine-validators-and-handlers): apply for frontend module * docs: minor tense change * docs: run grammarly Co-authored-by: Jing Wei --- README.md | 12 ++--- .../auth/__tests__/auth.controller.spec.ts | 22 ++++----- src/app/modules/auth/auth.controller.ts | 46 +++++++++++++----- src/app/modules/auth/auth.middlewares.ts | 35 ++++++++++++++ src/app/modules/auth/auth.routes.ts | 42 +--------------- .../__tests__/billing.controller.spec.ts | 4 +- src/app/modules/billing/billing.controller.ts | 24 ++++++---- .../modules/billing/billing.middlewares.ts | 9 ++++ src/app/modules/billing/billing.routes.ts | 13 +---- .../__tests__/examples.controller.spec.ts | 4 +- .../modules/examples/examples.controller.ts | 8 +++- .../modules/examples/examples.middlewares.ts | 12 +++++ src/app/modules/examples/examples.routes.ts | 16 +------ .../__tests__/admin-form.controller.spec.ts | 18 +++---- .../form/admin-form/admin-form.controller.ts | 38 ++++++++------- .../form/admin-form/admin-form.middlewares.ts | 30 ++++++++++++ .../__tests__/frontend.controller.spec.ts | 4 +- .../modules/frontend/frontend.controller.ts | 9 +++- .../modules/frontend/frontend.middlewares.ts | 9 ++++ src/app/modules/frontend/frontend.routes.ts | 13 +---- .../user/__tests__/user.controller.spec.ts | 24 +++++----- src/app/modules/user/user.controller.ts | 48 ++++++++++++------- src/app/modules/user/user.middleware.ts | 24 ++++++++++ src/app/modules/user/user.routes.ts | 26 +--------- .../forms/admin-forms.settings.routes.ts | 31 +----------- src/app/routes/api/v3/auth/auth.routes.ts | 42 +--------------- .../routes/api/v3/billings/billings.routes.ts | 13 +---- src/app/routes/api/v3/client/client.routes.ts | 13 +---- src/app/routes/api/v3/user/user.routes.ts | 26 +--------- 29 files changed, 293 insertions(+), 322 deletions(-) create mode 100644 src/app/modules/billing/billing.middlewares.ts create mode 100644 src/app/modules/examples/examples.middlewares.ts create mode 100644 src/app/modules/form/admin-form/admin-form.middlewares.ts create mode 100644 src/app/modules/frontend/frontend.middlewares.ts create mode 100644 src/app/modules/user/user.middleware.ts diff --git a/README.md b/README.md index bd5efb8e73..6ac6e23c99 100755 --- a/README.md +++ b/README.md @@ -63,7 +63,7 @@ npm run dev After the Docker image has finished building, the application can be accessed at [localhost:5000](localhost:5000). -If there have been no dependency changes in `package.json` or changes in the +If there are no dependency changes in `package.json` or changes in the `src/app/server.ts` file, you can run ```bash @@ -75,7 +75,7 @@ only takes ~15 seconds to finish starting up the image. ### Accessing email locally -We use [MailDev](https://github.com/maildev/maildev) to access emails in the development environment. The MailDev UI can be accessed at [localhost:1080](localhost:1080) when the Docker container is running. +We use [MailDev](https://github.com/maildev/maildev) to access emails in the development environment. The MailDev UI can be accessed at [localhost:1080](localhost:1080) when the Docker container runs. ### Environment variables @@ -87,8 +87,8 @@ The following is the order of priority: - Environment file - Dockerfile -FormSG requires some environment variables in order to function. -More information about the required environment variables can be seen in +FormSG requires some environment variables to function. +More information about the required environment variables are in [DEPLOYMENT_SETUP.md](/docs/DEPLOYMENT_SETUP.md). We provide a [`.template-env`](./.template-env) file with the secrets blanked out. You can copy and @@ -159,7 +159,7 @@ npm run test-e2e-ci ## Architecture -An overview of the architecture can be found [here](docs/ARCHITECTURE.md). +The architecture overview is [here](docs/ARCHITECTURE.md). ## MongoDB Scripts @@ -167,7 +167,7 @@ Scripts for common tasks in MongoDB can be found [here](docs/MONGODB.md). ## Contributing -We welcome all contributions, bug reports, bug fixes, documentation improvements, enhancements, and ideas to code open sourced by the Government Technology Agency of Singapore. Contributors should read [CONTRIBUTING.md](CONTRIBUTING.md) and will also be asked to sign a Contributor License Agreement (CLA) in order to ensure that everybody is free to use their contributions. +We welcome all contributions, bug reports, bug fixes, documentation improvements, enhancements, and ideas to code open sourced by the Government Technology Agency of Singapore. Contributors should read [CONTRIBUTING.md](CONTRIBUTING.md) and will also be asked to sign a Contributor License Agreement (CLA) to ensure that everybody is free to use their contributions. ## Support diff --git a/src/app/modules/auth/__tests__/auth.controller.spec.ts b/src/app/modules/auth/__tests__/auth.controller.spec.ts index f5dd798968..a142751310 100644 --- a/src/app/modules/auth/__tests__/auth.controller.spec.ts +++ b/src/app/modules/auth/__tests__/auth.controller.spec.ts @@ -42,7 +42,7 @@ describe('auth.controller', () => { ) // Act - await AuthController.handleCheckUser(MOCK_REQ, mockRes, jest.fn()) + await AuthController._handleCheckUser(MOCK_REQ, mockRes, jest.fn()) // Assert expect(mockRes.sendStatus).toBeCalledWith(200) @@ -57,7 +57,7 @@ describe('auth.controller', () => { ) // Act - await AuthController.handleCheckUser(MOCK_REQ, mockRes, jest.fn()) + await AuthController._handleCheckUser(MOCK_REQ, mockRes, jest.fn()) // Assert expect(mockRes.status).toBeCalledWith(401) @@ -82,7 +82,7 @@ describe('auth.controller', () => { MockMailService.sendLoginOtp.mockReturnValueOnce(okAsync(true)) // Act - await AuthController.handleLoginSendOtp(MOCK_REQ, mockRes, jest.fn()) + await AuthController._handleLoginSendOtp(MOCK_REQ, mockRes, jest.fn()) // Assert expect(mockRes.status).toBeCalledWith(200) @@ -101,7 +101,7 @@ describe('auth.controller', () => { ) // Act - await AuthController.handleLoginSendOtp(MOCK_REQ, mockRes, jest.fn()) + await AuthController._handleLoginSendOtp(MOCK_REQ, mockRes, jest.fn()) // Assert expect(mockRes.status).toBeCalledWith(401) @@ -120,7 +120,7 @@ describe('auth.controller', () => { ) // Act - await AuthController.handleLoginSendOtp(MOCK_REQ, mockRes, jest.fn()) + await AuthController._handleLoginSendOtp(MOCK_REQ, mockRes, jest.fn()) // Assert expect(mockRes.status).toBeCalledWith(500) @@ -146,7 +146,7 @@ describe('auth.controller', () => { ) // Act - await AuthController.handleLoginSendOtp(MOCK_REQ, mockRes, jest.fn()) + await AuthController._handleLoginSendOtp(MOCK_REQ, mockRes, jest.fn()) // Assert expect(mockRes.status).toBeCalledWith(500) @@ -183,7 +183,7 @@ describe('auth.controller', () => { MockUserService.retrieveUser.mockReturnValueOnce(okAsync(mockUser)) // Act - await AuthController.handleLoginVerifyOtp(MOCK_REQ, mockRes, jest.fn()) + await AuthController._handleLoginVerifyOtp(MOCK_REQ, mockRes, jest.fn()) // Assert expect(mockRes.status).toBeCalledWith(200) @@ -199,7 +199,7 @@ describe('auth.controller', () => { ) // Act - await AuthController.handleLoginVerifyOtp(MOCK_REQ, mockRes, jest.fn()) + await AuthController._handleLoginVerifyOtp(MOCK_REQ, mockRes, jest.fn()) // Assert expect(mockRes.status).toBeCalledWith(401) @@ -219,7 +219,7 @@ describe('auth.controller', () => { ) // Act - await AuthController.handleLoginVerifyOtp(MOCK_REQ, mockRes, jest.fn()) + await AuthController._handleLoginVerifyOtp(MOCK_REQ, mockRes, jest.fn()) // Assert expect(mockRes.status).toBeCalledWith(422) @@ -241,7 +241,7 @@ describe('auth.controller', () => { ) // Act - await AuthController.handleLoginVerifyOtp(MOCK_REQ, mockRes, jest.fn()) + await AuthController._handleLoginVerifyOtp(MOCK_REQ, mockRes, jest.fn()) // Assert expect(mockRes.status).toBeCalledWith(500) @@ -265,7 +265,7 @@ describe('auth.controller', () => { ) // Act - await AuthController.handleLoginVerifyOtp(MOCK_REQ, mockRes, jest.fn()) + await AuthController._handleLoginVerifyOtp(MOCK_REQ, mockRes, jest.fn()) // Assert expect(mockRes.status).toBeCalledWith(500) diff --git a/src/app/modules/auth/auth.controller.ts b/src/app/modules/auth/auth.controller.ts index 5d280baeba..188c8f3524 100644 --- a/src/app/modules/auth/auth.controller.ts +++ b/src/app/modules/auth/auth.controller.ts @@ -8,19 +8,18 @@ import { createReqMeta, getRequestIp } from '../../utils/request' import { ControllerHandler } from '../core/core.types' import * as UserService from '../user/user.service' +import { + validateCheckUserParams, + validateLoginSendOtpParams, + validateVerifyOtpParams, +} from './auth.middlewares' import * as AuthService from './auth.service' import { SessionUser } from './auth.types' import { mapRouteError } from './auth.utils' const logger = createLoggerWithLabel(module) -/** - * Handler for GET /auth/checkuser endpoint. - * @returns 500 when there was an error validating body.email - * @returns 401 when domain of body.email is invalid - * @returns 200 if domain of body.email is valid - */ -export const handleCheckUser: ControllerHandler< +export const _handleCheckUser: ControllerHandler< unknown, string, { email: string } @@ -46,12 +45,17 @@ export const handleCheckUser: ControllerHandler< } /** - * Handler for POST /auth/sendotp endpoint. - * @return 200 when OTP has been been successfully sent - * @return 401 when email domain is invalid - * @return 500 when unknown errors occurs during generate OTP, or create/send the email that delivers the OTP to the user's email address + * Handler for GET /auth/checkuser endpoint. + * @returns 500 when there was an error validating body.email + * @returns 401 when domain of body.email is invalid + * @returns 200 if domain of body.email is valid */ -export const handleLoginSendOtp: ControllerHandler< +export const handleCheckUser = [ + validateCheckUserParams, + _handleCheckUser, +] as ControllerHandler[] + +export const _handleLoginSendOtp: ControllerHandler< unknown, { message: string } | string, { email: string } @@ -103,6 +107,17 @@ export const handleLoginSendOtp: ControllerHandler< ) } +/** + * Handler for POST /auth/sendotp endpoint. + * @return 200 when OTP has been been successfully sent + * @return 401 when email domain is invalid + * @return 500 when unknown errors occurs during generate OTP, or create/send the email that delivers the OTP to the user's email address + */ +export const handleLoginSendOtp = [ + validateLoginSendOtpParams, + _handleLoginSendOtp, +] as ControllerHandler[] + /** * Handler for POST /auth/verifyotp endpoint. * @returns 200 when user has successfully logged in, with session cookie set @@ -110,7 +125,7 @@ export const handleLoginSendOtp: ControllerHandler< * @returns 422 when the OTP is invalid * @returns 500 when error occurred whilst verifying the OTP */ -export const handleLoginVerifyOtp: ControllerHandler< +export const _handleLoginVerifyOtp: ControllerHandler< unknown, string | SessionUser, { email: string; otp: string } @@ -185,6 +200,11 @@ export const handleLoginVerifyOtp: ControllerHandler< ) } +export const handleLoginVerifyOtp = [ + validateVerifyOtpParams, + _handleLoginVerifyOtp, +] as ControllerHandler[] + export const handleSignout: ControllerHandler = async (req, res) => { if (!req.session || isEmpty(req.session)) { logger.error({ diff --git a/src/app/modules/auth/auth.middlewares.ts b/src/app/modules/auth/auth.middlewares.ts index d61ad462aa..af232735b1 100644 --- a/src/app/modules/auth/auth.middlewares.ts +++ b/src/app/modules/auth/auth.middlewares.ts @@ -1,3 +1,4 @@ +import { celebrate, Joi, Segments } from 'celebrate' import { AuthedSessionData } from 'express-session' import { StatusCodes } from 'http-status-codes' @@ -57,3 +58,37 @@ export const logAdminAction: ControllerHandler<{ formId: string }> = async ( return next() } + +export const validateCheckUserParams = celebrate({ + [Segments.BODY]: Joi.object().keys({ + email: Joi.string() + .required() + .email() + .message('Please enter a valid email') + .lowercase(), + }), +}) + +export const validateLoginSendOtpParams = celebrate({ + [Segments.BODY]: Joi.object().keys({ + email: Joi.string() + .required() + .email() + .message('Please enter a valid email') + .lowercase(), + }), +}) + +export const validateVerifyOtpParams = celebrate({ + [Segments.BODY]: Joi.object().keys({ + email: Joi.string() + .required() + .email() + .message('Please enter a valid email') + .lowercase(), + otp: Joi.string() + .required() + .regex(/^\d{6}$/) + .message('Please enter a valid OTP'), + }), +}) diff --git a/src/app/modules/auth/auth.routes.ts b/src/app/modules/auth/auth.routes.ts index b47a532017..ffa645bbc3 100644 --- a/src/app/modules/auth/auth.routes.ts +++ b/src/app/modules/auth/auth.routes.ts @@ -1,4 +1,3 @@ -import { celebrate, Joi, Segments } from 'celebrate' import { Router } from 'express' import { rateLimitConfig } from '../../config/config' @@ -16,19 +15,7 @@ export const AuthRouter = Router() * @return 200 when email domain is valid * @return 401 when email domain is invalid */ -AuthRouter.post( - '/checkuser', - celebrate({ - [Segments.BODY]: Joi.object().keys({ - email: Joi.string() - .required() - .email() - .message('Please enter a valid email') - .lowercase(), - }), - }), - AuthController.handleCheckUser, -) +AuthRouter.post('/checkuser', AuthController.handleCheckUser) /** * Send a one-time password (OTP) to the specified email address @@ -45,15 +32,6 @@ AuthRouter.post( AuthRouter.post( '/sendotp', limitRate({ max: rateLimitConfig.sendAuthOtp }), - celebrate({ - [Segments.BODY]: Joi.object().keys({ - email: Joi.string() - .required() - .email() - .message('Please enter a valid email') - .lowercase(), - }), - }), AuthController.handleLoginSendOtp, ) @@ -70,23 +48,7 @@ AuthRouter.post( * @returns 422 when the OTP is invalid * @returns 500 when error occurred whilst verifying the OTP */ -AuthRouter.post( - '/verifyotp', - celebrate({ - [Segments.BODY]: Joi.object().keys({ - email: Joi.string() - .required() - .email() - .message('Please enter a valid email') - .lowercase(), - otp: Joi.string() - .required() - .regex(/^\d{6}$/) - .message('Please enter a valid OTP'), - }), - }), - AuthController.handleLoginVerifyOtp, -) +AuthRouter.post('/verifyotp', AuthController.handleLoginVerifyOtp) /** * Sign the user out of the session by clearing the relevant session cookie diff --git a/src/app/modules/billing/__tests__/billing.controller.spec.ts b/src/app/modules/billing/__tests__/billing.controller.spec.ts index dd11890b61..4dc500bb57 100644 --- a/src/app/modules/billing/__tests__/billing.controller.spec.ts +++ b/src/app/modules/billing/__tests__/billing.controller.spec.ts @@ -68,7 +68,7 @@ describe('billing.controller', () => { ) // Act - await BillingController.handleGetBillInfo(MOCK_REQ, mockRes, jest.fn()) + await BillingController._handleGetBillInfo(MOCK_REQ, mockRes, jest.fn()) // Assert expect(MockBillingService.getSpLoginStats).toHaveBeenCalledWith( @@ -86,7 +86,7 @@ describe('billing.controller', () => { ) // Act - await BillingController.handleGetBillInfo(MOCK_REQ, mockRes, jest.fn()) + await BillingController._handleGetBillInfo(MOCK_REQ, mockRes, jest.fn()) // Assert expect(MockBillingService.getSpLoginStats).toHaveBeenCalledWith( diff --git a/src/app/modules/billing/billing.controller.ts b/src/app/modules/billing/billing.controller.ts index 71f4af4fea..ade5f6bdcf 100644 --- a/src/app/modules/billing/billing.controller.ts +++ b/src/app/modules/billing/billing.controller.ts @@ -11,19 +11,12 @@ import { createLoggerWithLabel } from '../../config/logger' import { createReqMeta } from '../../utils/request' import { ControllerHandler } from '../core/core.types' +import { validateGetBillingInfoParams } from './billing.middlewares' import * as BillingService from './billing.service' const logger = createLoggerWithLabel(module) -/** - * Handler for GET /billing endpoint. - * @security session - * - * @return 200 with login statistics when query is valid - * @return 401 when request does not contain a user session - * @return 500 when error occurs whilst querying database - */ -export const handleGetBillInfo: ControllerHandler< +export const _handleGetBillInfo: ControllerHandler< unknown, ErrorDto | BillingInfoDto, unknown, @@ -72,3 +65,16 @@ export const handleGetBillInfo: ControllerHandler< loginStats: loginStatsResult.value, }) } + +/** + * Handler for GET /billing endpoint. + * @security session + * + * @return 200 with login statistics when query is valid + * @return 401 when request does not contain a user session + * @return 500 when error occurs whilst querying database + */ +export const handleGetBillInfo = [ + validateGetBillingInfoParams, + _handleGetBillInfo, +] as ControllerHandler[] diff --git a/src/app/modules/billing/billing.middlewares.ts b/src/app/modules/billing/billing.middlewares.ts new file mode 100644 index 0000000000..76c1e742c0 --- /dev/null +++ b/src/app/modules/billing/billing.middlewares.ts @@ -0,0 +1,9 @@ +import { celebrate, Joi, Segments } from 'celebrate' + +export const validateGetBillingInfoParams = celebrate({ + [Segments.QUERY]: Joi.object({ + esrvcId: Joi.string().required(), + yr: Joi.number().integer().min(2019).required(), + mth: Joi.number().integer().min(0).max(11).required(), + }), +}) diff --git a/src/app/modules/billing/billing.routes.ts b/src/app/modules/billing/billing.routes.ts index ca53f8b546..afa71877c2 100644 --- a/src/app/modules/billing/billing.routes.ts +++ b/src/app/modules/billing/billing.routes.ts @@ -1,4 +1,3 @@ -import { celebrate, Joi, Segments } from 'celebrate' import { Router } from 'express' import { withUserAuthentication } from '../auth/auth.middlewares' @@ -22,14 +21,4 @@ BillingRouter.use(withUserAuthentication) * @return 401 when request does not contain a user session * @return 500 when error occurs whilst querying database */ -BillingRouter.get( - '/', - celebrate({ - [Segments.QUERY]: Joi.object({ - esrvcId: Joi.string().required(), - yr: Joi.number().integer().min(2019).required(), - mth: Joi.number().integer().min(0).max(11).required(), - }), - }), - BillingController.handleGetBillInfo, -) +BillingRouter.get('/', BillingController.handleGetBillInfo) diff --git a/src/app/modules/examples/__tests__/examples.controller.spec.ts b/src/app/modules/examples/__tests__/examples.controller.spec.ts index dba66283d4..e7ea870910 100644 --- a/src/app/modules/examples/__tests__/examples.controller.spec.ts +++ b/src/app/modules/examples/__tests__/examples.controller.spec.ts @@ -42,7 +42,7 @@ describe('examples.controller', () => { ) // Act - await ExamplesController.handleGetExamples(MOCK_REQ, mockRes, jest.fn()) + await ExamplesController._handleGetExamples(MOCK_REQ, mockRes, jest.fn()) // Assert expect(MockExamplesService.getExampleForms).toHaveBeenCalledWith( @@ -61,7 +61,7 @@ describe('examples.controller', () => { ) // Act - await ExamplesController.handleGetExamples(MOCK_REQ, mockRes, jest.fn()) + await ExamplesController._handleGetExamples(MOCK_REQ, mockRes, jest.fn()) // Assert expect(MockExamplesService.getExampleForms).toHaveBeenCalledWith( diff --git a/src/app/modules/examples/examples.controller.ts b/src/app/modules/examples/examples.controller.ts index 533b1cdceb..43407637bd 100644 --- a/src/app/modules/examples/examples.controller.ts +++ b/src/app/modules/examples/examples.controller.ts @@ -10,6 +10,7 @@ import { createLoggerWithLabel } from '../../config/logger' import { createReqMeta } from '../../utils/request' import { ControllerHandler } from '../core/core.types' +import { validateGetExamplesParams } from './examples.middlewares' import * as ExamplesService from './examples.service' import { mapRouteError } from './examples.utils' @@ -23,7 +24,7 @@ const logger = createLoggerWithLabel(module) * @returns 401 when user does not exist in session * @returns 500 when error occurs whilst querying the database */ -export const handleGetExamples: ControllerHandler< +export const _handleGetExamples: ControllerHandler< unknown, ErrorDto | ExampleFormsResult, unknown, @@ -46,6 +47,11 @@ export const handleGetExamples: ControllerHandler< }) } +export const handleGetExamples = [ + validateGetExamplesParams, + _handleGetExamples, +] as ControllerHandler[] + /** * Handler for GET /examples/:formId endpoint. * @security session diff --git a/src/app/modules/examples/examples.middlewares.ts b/src/app/modules/examples/examples.middlewares.ts new file mode 100644 index 0000000000..4df50b44fb --- /dev/null +++ b/src/app/modules/examples/examples.middlewares.ts @@ -0,0 +1,12 @@ +import { celebrate, Joi, Segments } from 'celebrate' + +export const validateGetExamplesParams = celebrate({ + [Segments.QUERY]: Joi.object().keys({ + pageNo: Joi.number().min(0).required(), + agency: Joi.string() + .regex(/^[0-9a-fA-F]{24}$/) + .allow(''), + searchTerm: Joi.string().allow(''), + shouldGetTotalNumResults: Joi.boolean().default(false), + }), +}) diff --git a/src/app/modules/examples/examples.routes.ts b/src/app/modules/examples/examples.routes.ts index 611a1547b9..313cff72e6 100644 --- a/src/app/modules/examples/examples.routes.ts +++ b/src/app/modules/examples/examples.routes.ts @@ -1,4 +1,3 @@ -import { celebrate, Joi, Segments } from 'celebrate' import { Router } from 'express' import { withUserAuthentication } from '../auth/auth.middlewares' @@ -22,20 +21,7 @@ ExamplesRouter.use(withUserAuthentication) * @returns 401 when user does not exist in session * @returns 500 when error occurs whilst querying the database */ -ExamplesRouter.get( - '/', - celebrate({ - [Segments.QUERY]: Joi.object().keys({ - pageNo: Joi.number().min(0).required(), - agency: Joi.string() - .regex(/^[0-9a-fA-F]{24}$/) - .allow(''), - searchTerm: Joi.string().allow(''), - shouldGetTotalNumResults: Joi.boolean().default(false), - }), - }), - ExamplesController.handleGetExamples, -) +ExamplesRouter.get('/', ExamplesController.handleGetExamples) /** * Returns example information for the form that is referenced by the given diff --git a/src/app/modules/form/admin-form/__tests__/admin-form.controller.spec.ts b/src/app/modules/form/admin-form/__tests__/admin-form.controller.spec.ts index e922e14019..6ba7072fe1 100644 --- a/src/app/modules/form/admin-form/__tests__/admin-form.controller.spec.ts +++ b/src/app/modules/form/admin-form/__tests__/admin-form.controller.spec.ts @@ -4525,7 +4525,7 @@ describe('admin-form.controller', () => { ) // Act - await AdminFormController.handleUpdateSettings( + await AdminFormController._handleUpdateSettings( MOCK_REQ, mockRes, jest.fn(), @@ -4564,7 +4564,7 @@ describe('admin-form.controller', () => { ) // Act - await AdminFormController.handleUpdateSettings( + await AdminFormController._handleUpdateSettings( MOCK_REQ, mockRes, jest.fn(), @@ -4598,7 +4598,7 @@ describe('admin-form.controller', () => { ) // Act - await AdminFormController.handleUpdateSettings( + await AdminFormController._handleUpdateSettings( MOCK_REQ, mockRes, jest.fn(), @@ -4636,7 +4636,7 @@ describe('admin-form.controller', () => { ) // Act - await AdminFormController.handleUpdateSettings( + await AdminFormController._handleUpdateSettings( MOCK_REQ, mockRes, jest.fn(), @@ -4673,7 +4673,7 @@ describe('admin-form.controller', () => { ) // Act - await AdminFormController.handleUpdateSettings( + await AdminFormController._handleUpdateSettings( MOCK_REQ, mockRes, jest.fn(), @@ -4711,7 +4711,7 @@ describe('admin-form.controller', () => { ) // Act - await AdminFormController.handleUpdateSettings( + await AdminFormController._handleUpdateSettings( MOCK_REQ, mockRes, jest.fn(), @@ -4752,7 +4752,7 @@ describe('admin-form.controller', () => { ) // Act - await AdminFormController.handleUpdateSettings( + await AdminFormController._handleUpdateSettings( MOCK_REQ, mockRes, jest.fn(), @@ -4786,7 +4786,7 @@ describe('admin-form.controller', () => { ) // Act - await AdminFormController.handleUpdateSettings( + await AdminFormController._handleUpdateSettings( MOCK_REQ, mockRes, jest.fn(), @@ -4820,7 +4820,7 @@ describe('admin-form.controller', () => { ) // Act - await AdminFormController.handleUpdateSettings( + await AdminFormController._handleUpdateSettings( MOCK_REQ, mockRes, jest.fn(), diff --git a/src/app/modules/form/admin-form/admin-form.controller.ts b/src/app/modules/form/admin-form/admin-form.controller.ts index 35222f0f19..024154f7c5 100644 --- a/src/app/modules/form/admin-form/admin-form.controller.ts +++ b/src/app/modules/form/admin-form/admin-form.controller.ts @@ -88,6 +88,7 @@ import { PREVIEW_SINGPASS_UINFIN, } from './admin-form.constants' import { EditFieldError } from './admin-form.errors' +import { updateSettingsValidator } from './admin-form.middlewares' import * as AdminFormService from './admin-form.service' import { PermissionLevel } from './admin-form.types' import { mapRouteError } from './admin-form.utils' @@ -1247,22 +1248,7 @@ export const handleDuplicateFormField: ControllerHandler< }) } -/** - * Handler for PATCH /forms/:formId/settings. - * @security session - * - * @returns 200 with updated form settings - * @returns 400 when body is malformed; can happen when email parameter is passed for encrypt-mode forms - * @returns 403 when current user does not have permissions to update form settings - * @returns 404 when form to update settings for cannot be found - * @returns 409 when saving form settings incurs a conflict in the database - * @returns 410 when updating settings for archived form - * @returns 413 when updating settings causes form to be too large to be saved in the database - * @returns 422 when an invalid settings update is attempted on the form - * @returns 422 when user in session cannot be retrieved from the database - * @returns 500 when database error occurs - */ -export const handleUpdateSettings: ControllerHandler< +export const _handleUpdateSettings: ControllerHandler< { formId: string }, FormSettings | ErrorDto, SettingsUpdateDto @@ -1302,6 +1288,26 @@ export const handleUpdateSettings: ControllerHandler< }) } +/** + * Handler for PATCH /forms/:formId/settings. + * @security session + * + * @returns 200 with updated form settings + * @returns 400 when body is malformed; can happen when email parameter is passed for encrypt-mode forms + * @returns 403 when current user does not have permissions to update form settings + * @returns 404 when form to update settings for cannot be found + * @returns 409 when saving form settings incurs a conflict in the database + * @returns 410 when updating settings for archived form + * @returns 413 when updating settings causes form to be too large to be saved in the database + * @returns 422 when an invalid settings update is attempted on the form + * @returns 422 when user in session cannot be retrieved from the database + * @returns 500 when database error occurs + */ +export const handleUpdateSettings = [ + updateSettingsValidator, + _handleUpdateSettings, +] as ControllerHandler[] + /** * NOTE: Exported for testing. * Private handler for PUT /forms/:formId/fields/:fieldId diff --git a/src/app/modules/form/admin-form/admin-form.middlewares.ts b/src/app/modules/form/admin-form/admin-form.middlewares.ts new file mode 100644 index 0000000000..320b73b76c --- /dev/null +++ b/src/app/modules/form/admin-form/admin-form.middlewares.ts @@ -0,0 +1,30 @@ +import { celebrate, Joi, Segments } from 'celebrate' + +import { + FormAuthType, + FormStatus, + SettingsUpdateDto, +} from '../../../../../shared/types' + +/** + * Joi validator for PATCH /forms/:formId/settings route. + */ +export const updateSettingsValidator = celebrate({ + [Segments.BODY]: Joi.object({ + authType: Joi.string().valid(...Object.values(FormAuthType)), + emails: Joi.alternatives().try( + Joi.array().items(Joi.string().email()), + Joi.string().email({ multiple: true }), + ), + esrvcId: Joi.string().allow(''), + hasCaptcha: Joi.boolean(), + inactiveMessage: Joi.string(), + status: Joi.string().valid(...Object.values(FormStatus)), + submissionLimit: Joi.number().allow(null), + title: Joi.string(), + webhook: Joi.object({ + url: Joi.string().uri().allow(''), + isRetryEnabled: Joi.boolean(), + }).min(1), + }).min(1), +}) diff --git a/src/app/modules/frontend/__tests__/frontend.controller.spec.ts b/src/app/modules/frontend/__tests__/frontend.controller.spec.ts index da32eb2d63..a80076dc32 100644 --- a/src/app/modules/frontend/__tests__/frontend.controller.spec.ts +++ b/src/app/modules/frontend/__tests__/frontend.controller.spec.ts @@ -77,7 +77,7 @@ describe('frontend.server.controller', () => { 'window.location.hash = "#!/formId?fieldId1=abc&fieldId2=<>'"' // Note this is different from mockReqModified.query.redirectPath as // there are html-encoded characters - FrontendServerController.generateRedirectUrl( + FrontendServerController._generateRedirectUrl( mockReqModified, mockRes, jest.fn(), @@ -89,7 +89,7 @@ describe('frontend.server.controller', () => { expect(mockRes.status).toHaveBeenCalledWith(StatusCodes.OK) }) it('should return BAD_REQUEST if the request is not valid', () => { - FrontendServerController.generateRedirectUrl( + FrontendServerController._generateRedirectUrl( // @ts-ignore mockBadReq, mockRes, diff --git a/src/app/modules/frontend/frontend.controller.ts b/src/app/modules/frontend/frontend.controller.ts index 3268e9552d..7af36f345c 100644 --- a/src/app/modules/frontend/frontend.controller.ts +++ b/src/app/modules/frontend/frontend.controller.ts @@ -5,6 +5,8 @@ import { createLoggerWithLabel } from '../../config/logger' import { createReqMeta } from '../../utils/request' import { ControllerHandler } from '../core/core.types' +import { validateGenerateRedirectParams } from './frontend.middlewares' + const logger = createLoggerWithLabel(module) /** @@ -81,7 +83,7 @@ export const addEnvVarData: ControllerHandler = ( * @param res - Express response object * @returns Templated Javascript code for the frontend that redirects to specific form url */ -export const generateRedirectUrl: ControllerHandler< +export const _generateRedirectUrl: ControllerHandler< unknown, string | { message: string }, unknown, @@ -115,6 +117,11 @@ export const generateRedirectUrl: ControllerHandler< } } +export const generateRedirectUrl = [ + validateGenerateRedirectParams, + _generateRedirectUrl, +] as ControllerHandler[] + // Duplicated here since the feature manager is being deprecated. // TODO (#2147): delete this. enum FeatureNames { diff --git a/src/app/modules/frontend/frontend.middlewares.ts b/src/app/modules/frontend/frontend.middlewares.ts new file mode 100644 index 0000000000..f1a7699724 --- /dev/null +++ b/src/app/modules/frontend/frontend.middlewares.ts @@ -0,0 +1,9 @@ +import { celebrate, Joi, Segments } from 'celebrate' + +export const validateGenerateRedirectParams = celebrate({ + [Segments.QUERY]: { + redirectPath: Joi.string() + .regex(/^[a-fA-F0-9]{24}(\/(preview|template|use-template))?/) + .required(), + }, +}) diff --git a/src/app/modules/frontend/frontend.routes.ts b/src/app/modules/frontend/frontend.routes.ts index 0fc0bdfddd..d0f0879220 100644 --- a/src/app/modules/frontend/frontend.routes.ts +++ b/src/app/modules/frontend/frontend.routes.ts @@ -1,4 +1,3 @@ -import { celebrate, Joi, Segments } from 'celebrate' import { Router } from 'express' import * as FrontendServerController from './frontend.controller' @@ -40,14 +39,4 @@ FrontendRouter.get('/features', FrontendServerController.showFeaturesStates) * @return 200 when redirect code is successful * @return 400 when redirect code fails */ -FrontendRouter.get( - '/redirect', - celebrate({ - [Segments.QUERY]: { - redirectPath: Joi.string() - .regex(/^[a-fA-F0-9]{24}(\/(preview|template|use-template))?/) - .required(), - }, - }), - FrontendServerController.generateRedirectUrl, -) +FrontendRouter.get('/redirect', FrontendServerController.generateRedirectUrl) diff --git a/src/app/modules/user/__tests__/user.controller.spec.ts b/src/app/modules/user/__tests__/user.controller.spec.ts index e081c0bf6a..038486391f 100644 --- a/src/app/modules/user/__tests__/user.controller.spec.ts +++ b/src/app/modules/user/__tests__/user.controller.spec.ts @@ -51,7 +51,7 @@ describe('user.controller', () => { MockSmsFactory.sendAdminContactOtp.mockReturnValueOnce(okAsync(true)) // Act - await UserController.handleContactSendOtp(MOCK_REQ, mockRes, jest.fn()) + await UserController._handleContactSendOtp(MOCK_REQ, mockRes, jest.fn()) // Assert // Check passed in params. @@ -78,7 +78,7 @@ describe('user.controller', () => { const mockRes = expressHandler.mockResponse() // Act - await UserController.handleContactSendOtp( + await UserController._handleContactSendOtp( reqWithoutSession, mockRes, jest.fn(), @@ -109,7 +109,7 @@ describe('user.controller', () => { const mockRes = expressHandler.mockResponse() // Act - await UserController.handleContactSendOtp( + await UserController._handleContactSendOtp( reqWithDiffUserParam, mockRes, jest.fn(), @@ -137,7 +137,7 @@ describe('user.controller', () => { ) // Act - await UserController.handleContactSendOtp(MOCK_REQ, mockRes, jest.fn()) + await UserController._handleContactSendOtp(MOCK_REQ, mockRes, jest.fn()) // Assert expect(mockRes.status).toBeCalledWith(422) @@ -158,7 +158,7 @@ describe('user.controller', () => { ) // Act - await UserController.handleContactSendOtp(MOCK_REQ, mockRes, jest.fn()) + await UserController._handleContactSendOtp(MOCK_REQ, mockRes, jest.fn()) // Assert expect(mockRes.status).toBeCalledWith(500) @@ -200,7 +200,7 @@ describe('user.controller', () => { ) // Act - await UserController.handleContactVerifyOtp(MOCK_REQ, mockRes, jest.fn()) + await UserController._handleContactVerifyOtp(MOCK_REQ, mockRes, jest.fn()) // Assert // Expect services to be called with correct arguments. @@ -229,7 +229,7 @@ describe('user.controller', () => { const mockRes = expressHandler.mockResponse() // Act - await UserController.handleContactVerifyOtp( + await UserController._handleContactVerifyOtp( reqWithoutSession, mockRes, jest.fn(), @@ -261,7 +261,7 @@ describe('user.controller', () => { const mockRes = expressHandler.mockResponse() // Act - await UserController.handleContactVerifyOtp( + await UserController._handleContactVerifyOtp( reqWithDiffUserParam, mockRes, jest.fn(), @@ -289,7 +289,7 @@ describe('user.controller', () => { ) // Act - await UserController.handleContactVerifyOtp(MOCK_REQ, mockRes, jest.fn()) + await UserController._handleContactVerifyOtp(MOCK_REQ, mockRes, jest.fn()) // Assert expect(mockRes.status).toBeCalledWith(500) @@ -309,7 +309,7 @@ describe('user.controller', () => { ) // Act - await UserController.handleContactVerifyOtp(MOCK_REQ, mockRes, jest.fn()) + await UserController._handleContactVerifyOtp(MOCK_REQ, mockRes, jest.fn()) // Assert expect(mockRes.status).toBeCalledWith(401) @@ -329,7 +329,7 @@ describe('user.controller', () => { ) // Act - await UserController.handleContactVerifyOtp(MOCK_REQ, mockRes, jest.fn()) + await UserController._handleContactVerifyOtp(MOCK_REQ, mockRes, jest.fn()) // Assert expect(mockRes.status).toBeCalledWith(422) @@ -349,7 +349,7 @@ describe('user.controller', () => { ) // Act - await UserController.handleContactVerifyOtp(MOCK_REQ, mockRes, jest.fn()) + await UserController._handleContactVerifyOtp(MOCK_REQ, mockRes, jest.fn()) // Assert expect(mockRes.status).toBeCalledWith(500) diff --git a/src/app/modules/user/user.controller.ts b/src/app/modules/user/user.controller.ts index a598ee7747..8920fe906d 100644 --- a/src/app/modules/user/user.controller.ts +++ b/src/app/modules/user/user.controller.ts @@ -7,6 +7,10 @@ import { getRequestIp } from '../../utils/request' import { getUserIdFromSession } from '../auth/auth.utils' import { ControllerHandler } from '../core/core.types' +import { + validateContactOtpVerificationParams, + validateContactSendOtpParams, +} from './user.middleware' import { createContactOtp, getPopulatedUserById, @@ -17,16 +21,7 @@ import { mapRouteError } from './user.utils' const logger = createLoggerWithLabel(module) -/** - * Generates an OTP and sends the OTP to the given contact in request body. - * @route POST /contact/otp/generate - * @returns 200 if OTP was successfully sent - * @returns 401 if user id does not match current session user or if user is not currently logged in - * @returns 422 on OTP creation or SMS send failure - * @returns 422 if user id does not exist in the database - * @returns 500 if database errors occurs - */ -export const handleContactSendOtp: ControllerHandler< +export const _handleContactSendOtp: ControllerHandler< unknown, string, { contact: string; userId: string } @@ -92,15 +87,20 @@ export const handleContactSendOtp: ControllerHandler< } /** - * Verifies given OTP with the hashed OTP data, and updates the user's contact - * number if the hash matches. - * @route POST /contact/otp/verify - * @returns 200 when user contact update success + * Generates an OTP and sends the OTP to the given contact in request body. + * @route POST /contact/otp/generate + * @returns 200 if OTP was successfully sent * @returns 401 if user id does not match current session user or if user is not currently logged in - * @returns 422 when OTP is invalid - * @returns 500 when OTP is malformed or for unknown errors + * @returns 422 on OTP creation or SMS send failure + * @returns 422 if user id does not exist in the database + * @returns 500 if database errors occurs */ -export const handleContactVerifyOtp: ControllerHandler< +export const handleContactSendOtp = [ + validateContactSendOtpParams, + _handleContactSendOtp, +] as ControllerHandler[] + +export const _handleContactVerifyOtp: ControllerHandler< unknown, string | IPopulatedUser, { @@ -158,6 +158,20 @@ export const handleContactVerifyOtp: ControllerHandler< return res.status(StatusCodes.OK).json(updateResult.value) } +/** + * Verifies given OTP with the hashed OTP data, and updates the user's contact + * number if the hash matches. + * @route POST /contact/otp/verify + * @returns 200 when user contact update success + * @returns 401 if user id does not match current session user or if user is not currently logged in + * @returns 422 when OTP is invalid + * @returns 500 when OTP is malformed or for unknown errors + */ +export const handleContactVerifyOtp = [ + validateContactOtpVerificationParams, + _handleContactVerifyOtp, +] as ControllerHandler[] + /** * Retrieves and returns the session user from the database. * @route GET / diff --git a/src/app/modules/user/user.middleware.ts b/src/app/modules/user/user.middleware.ts new file mode 100644 index 0000000000..4824d73b16 --- /dev/null +++ b/src/app/modules/user/user.middleware.ts @@ -0,0 +1,24 @@ +import { celebrate, Joi, Segments } from 'celebrate' + +/** + * Celebrate validation for the contact OTP sending endpoint. + */ +export const validateContactSendOtpParams = celebrate({ + [Segments.BODY]: Joi.object().keys({ + contact: Joi.string().required(), + userId: Joi.string().required(), + }), +}) + +/** + * Celebrate validation for the contact OTP verification endpoint. + */ +export const validateContactOtpVerificationParams = celebrate({ + [Segments.BODY]: Joi.object({ + userId: Joi.string().required(), + otp: Joi.string() + .required() + .regex(/^\d{6}$/), + contact: Joi.string().required(), + }), +}) diff --git a/src/app/modules/user/user.routes.ts b/src/app/modules/user/user.routes.ts index 7566344d1b..6dc5cb5188 100644 --- a/src/app/modules/user/user.routes.ts +++ b/src/app/modules/user/user.routes.ts @@ -1,4 +1,3 @@ -import { celebrate, Joi, Segments } from 'celebrate' import { Router } from 'express' import * as UserController from './user.controller' @@ -28,16 +27,7 @@ UserRouter.get('/', UserController.handleFetchUser) * @returns 422 on OTP creation or SMS send failure, or if the user cannot be found * @returns 500 on application or database errors */ -UserRouter.post( - '/contact/sendotp', - celebrate({ - [Segments.BODY]: Joi.object().keys({ - contact: Joi.string().required(), - userId: Joi.string().required(), - }), - }), - UserController.handleContactSendOtp, -) +UserRouter.post('/contact/sendotp', UserController.handleContactSendOtp) /** * Verify the contact verification one-time password (OTP) for the user as part @@ -50,18 +40,6 @@ UserRouter.post( * @returns 422 when OTP is invalid * @returns 500 when OTP is malformed or for unknown errors */ -UserRouter.post( - '/contact/verifyotp', - celebrate({ - [Segments.BODY]: Joi.object().keys({ - userId: Joi.string().required(), - otp: Joi.string() - .required() - .regex(/^\d{6}$/), - contact: Joi.string().required(), - }), - }), - UserController.handleContactVerifyOtp, -) +UserRouter.post('/contact/verifyotp', UserController.handleContactVerifyOtp) export default UserRouter diff --git a/src/app/routes/api/v3/admin/forms/admin-forms.settings.routes.ts b/src/app/routes/api/v3/admin/forms/admin-forms.settings.routes.ts index 40acc921a0..0bfcfbfab3 100644 --- a/src/app/routes/api/v3/admin/forms/admin-forms.settings.routes.ts +++ b/src/app/routes/api/v3/admin/forms/admin-forms.settings.routes.ts @@ -1,38 +1,9 @@ -import { celebrate, Joi, Segments } from 'celebrate' import { Router } from 'express' -import { - FormAuthType, - FormStatus, - SettingsUpdateDto, -} from '../../../../../../../shared/types' import * as AdminFormController from '../../../../../modules/form/admin-form/admin-form.controller' export const AdminFormsSettingsRouter = Router() -/** - * Joi validator for PATCH /forms/:formId/settings route. - */ -const updateSettingsValidator = celebrate({ - [Segments.BODY]: Joi.object({ - authType: Joi.string().valid(...Object.values(FormAuthType)), - emails: Joi.alternatives().try( - Joi.array().items(Joi.string().email()), - Joi.string().email({ multiple: true }), - ), - esrvcId: Joi.string().allow(''), - hasCaptcha: Joi.boolean(), - inactiveMessage: Joi.string(), - status: Joi.string().valid(...Object.values(FormStatus)), - submissionLimit: Joi.number().allow(null), - title: Joi.string(), - webhook: Joi.object({ - url: Joi.string().uri().allow(''), - isRetryEnabled: Joi.boolean(), - }).min(1), - }).min(1), -}) - AdminFormsSettingsRouter.route('/:formId([a-fA-F0-9]{24})/settings') /** * Update form settings according to given subset of settings. @@ -53,7 +24,7 @@ AdminFormsSettingsRouter.route('/:formId([a-fA-F0-9]{24})/settings') * @returns 422 when user in session cannot be retrieved from the database * @returns 500 when database error occurs */ - .patch(updateSettingsValidator, AdminFormController.handleUpdateSettings) + .patch(AdminFormController.handleUpdateSettings) /** * Retrieve the settings of the specified form * @route GET /admin/forms/:formId/settings diff --git a/src/app/routes/api/v3/auth/auth.routes.ts b/src/app/routes/api/v3/auth/auth.routes.ts index 1bf1f9ecac..f34f29b2b7 100644 --- a/src/app/routes/api/v3/auth/auth.routes.ts +++ b/src/app/routes/api/v3/auth/auth.routes.ts @@ -1,4 +1,3 @@ -import { celebrate, Joi, Segments } from 'celebrate' import { Router } from 'express' import { rateLimitConfig } from '../../../../config/config' @@ -14,19 +13,7 @@ export const AuthRouter = Router() * @return 200 when email domain is valid * @return 401 when email domain is invalid */ -AuthRouter.post( - '/email/validate', - celebrate({ - [Segments.BODY]: Joi.object().keys({ - email: Joi.string() - .required() - .email() - .message('Please enter a valid email') - .lowercase(), - }), - }), - AuthController.handleCheckUser, -) +AuthRouter.post('/email/validate', AuthController.handleCheckUser) /** * Send a one-time password (OTP) to the specified email address @@ -43,15 +30,6 @@ AuthRouter.post( AuthRouter.post( '/otp/generate', limitRate({ max: rateLimitConfig.sendAuthOtp }), - celebrate({ - [Segments.BODY]: Joi.object().keys({ - email: Joi.string() - .required() - .email() - .message('Please enter a valid email') - .lowercase(), - }), - }), AuthController.handleLoginSendOtp, ) @@ -68,23 +46,7 @@ AuthRouter.post( * @returns 422 when the OTP is invalid * @returns 500 when error occurred whilst verifying the OTP */ -AuthRouter.post( - '/otp/verify', - celebrate({ - [Segments.BODY]: Joi.object().keys({ - email: Joi.string() - .required() - .email() - .message('Please enter a valid email') - .lowercase(), - otp: Joi.string() - .required() - .regex(/^\d{6}$/) - .message('Please enter a valid OTP'), - }), - }), - AuthController.handleLoginVerifyOtp, -) +AuthRouter.post('/otp/verify', AuthController.handleLoginVerifyOtp) /** * Sign the user out of the session by clearing the relevant session cookie diff --git a/src/app/routes/api/v3/billings/billings.routes.ts b/src/app/routes/api/v3/billings/billings.routes.ts index 91f3b2d5f2..6185a0d151 100644 --- a/src/app/routes/api/v3/billings/billings.routes.ts +++ b/src/app/routes/api/v3/billings/billings.routes.ts @@ -1,4 +1,3 @@ -import { celebrate, Joi, Segments } from 'celebrate' import { Router } from 'express' import { withUserAuthentication } from '../../../../modules/auth/auth.middlewares' @@ -21,14 +20,4 @@ BillingsRouter.use(withUserAuthentication) * @return 401 when request does not contain a user session * @return 500 when error occurs whilst querying database */ -BillingsRouter.get( - '/', - celebrate({ - [Segments.QUERY]: Joi.object({ - esrvcId: Joi.string().required(), - yr: Joi.number().integer().min(2019).required(), - mth: Joi.number().integer().min(0).max(11).required(), - }), - }), - BillingController.handleGetBillInfo, -) +BillingsRouter.get('/', BillingController.handleGetBillInfo) diff --git a/src/app/routes/api/v3/client/client.routes.ts b/src/app/routes/api/v3/client/client.routes.ts index 521506d91a..6d0bf5830c 100644 --- a/src/app/routes/api/v3/client/client.routes.ts +++ b/src/app/routes/api/v3/client/client.routes.ts @@ -1,4 +1,3 @@ -import { celebrate, Joi, Segments } from 'celebrate' import { Router } from 'express' import * as FrontendServerController from '../../../../modules/frontend/frontend.controller' @@ -40,14 +39,4 @@ ClientRouter.get('/features', FrontendServerController.showFeaturesStates) * @return 200 when redirect code is successful * @return 400 when redirect code fails */ -ClientRouter.get( - '/redirect', - celebrate({ - [Segments.QUERY]: { - redirectPath: Joi.string() - .regex(/^[a-fA-F0-9]{24}(\/(preview|template|use-template))?/) - .required(), - }, - }), - FrontendServerController.generateRedirectUrl, -) +ClientRouter.get('/redirect', FrontendServerController.generateRedirectUrl) diff --git a/src/app/routes/api/v3/user/user.routes.ts b/src/app/routes/api/v3/user/user.routes.ts index d08165f93c..48c6392b57 100644 --- a/src/app/routes/api/v3/user/user.routes.ts +++ b/src/app/routes/api/v3/user/user.routes.ts @@ -1,4 +1,3 @@ -import { celebrate, Joi, Segments } from 'celebrate' import { Router } from 'express' import * as UserController from '../../../../modules/user/user.controller' @@ -28,16 +27,7 @@ UserRouter.get('/', UserController.handleFetchUser) * @returns 422 on OTP creation or SMS send failure, or if the user cannot be found * @returns 500 on application or database errors */ -UserRouter.post( - '/contact/otp/generate', - celebrate({ - [Segments.BODY]: Joi.object().keys({ - contact: Joi.string().required(), - userId: Joi.string().required(), - }), - }), - UserController.handleContactSendOtp, -) +UserRouter.post('/contact/otp/generate', UserController.handleContactSendOtp) /** * Verify the contact verification one-time password (OTP) for the user as part @@ -50,18 +40,6 @@ UserRouter.post( * @returns 422 when OTP is invalid * @returns 500 when OTP is malformed or for unknown errors */ -UserRouter.post( - '/contact/otp/verify', - celebrate({ - [Segments.BODY]: Joi.object().keys({ - userId: Joi.string().required(), - otp: Joi.string() - .required() - .regex(/^\d{6}$/), - contact: Joi.string().required(), - }), - }), - UserController.handleContactVerifyOtp, -) +UserRouter.post('/contact/otp/verify', UserController.handleContactVerifyOtp) export default UserRouter From a6e357a342c372e3c749939ef0a3bd139b888726 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Feb 2022 17:50:45 +0000 Subject: [PATCH 07/10] chore(deps-dev): bump @babel/core from 7.17.0 to 7.17.2 (#3430) Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.17.0 to 7.17.2. - [Release notes](https://github.com/babel/babel/releases) - [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md) - [Commits](https://github.com/babel/babel/commits/v7.17.2/packages/babel-core) --- updated-dependencies: - dependency-name: "@babel/core" dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 38 +++++++++++++++++++------------------- package.json | 2 +- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/package-lock.json b/package-lock.json index fd579669ce..1c6e1f3f44 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,9 +5,9 @@ "requires": true, "dependencies": { "@ampproject/remapping": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.0.4.tgz", - "integrity": "sha512-zU3pj3pf//YhaoozRTYKaL20KopXrzuZFc/8Ylc49AuV8grYKH23TTq9JJoR70F8zQbil58KjSchZTWeX+jrIQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.1.1.tgz", + "integrity": "sha512-Aolwjd7HSC2PyY0fDj/wA/EimQT4HfEnFYNp5s9CQlrdhyvWTtvZ5YzrUPu6R6/1jKiUlxu8bUhkdSnKHNAHMA==", "dev": true, "requires": { "@jridgewell/trace-mapping": "^0.3.0" @@ -29,9 +29,9 @@ "dev": true }, "@babel/core": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.17.0.tgz", - "integrity": "sha512-x/5Ea+RO5MvF9ize5DeVICJoVrNv0Mi2RnIABrZEKYvPEpldXwauPkgvYA17cKa6WpU3LoYvYbuEMFtSNFsarA==", + "version": "7.17.2", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.17.2.tgz", + "integrity": "sha512-R3VH5G42VSDolRHyUO4V2cfag8WHcZyxdq5Z/m8Xyb92lW/Erm/6kM+XtRFGf3Mulre3mveni2NHfEUws8wSvw==", "dev": true, "requires": { "@ampproject/remapping": "^2.0.0", @@ -39,7 +39,7 @@ "@babel/generator": "^7.17.0", "@babel/helper-compilation-targets": "^7.16.7", "@babel/helper-module-transforms": "^7.16.7", - "@babel/helpers": "^7.17.0", + "@babel/helpers": "^7.17.2", "@babel/parser": "^7.17.0", "@babel/template": "^7.16.7", "@babel/traverse": "^7.17.0", @@ -1053,9 +1053,9 @@ } }, "@babel/helpers": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.17.0.tgz", - "integrity": "sha512-Xe/9NFxjPwELUvW2dsukcMZIp6XwPSbI4ojFBJuX5ramHuVE22SVcZIwqzdWo5uCgeTXW8qV97lMvSOjq+1+nQ==", + "version": "7.17.2", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.17.2.tgz", + "integrity": "sha512-0Qu7RLR1dILozr/6M0xgj+DFPmi6Bnulgm9M8BVa9ZCWxDqlSnqt3cf8IDPB5m45sVXUZ0kuQAgUrdSFFH79fQ==", "dev": true, "requires": { "@babel/template": "^7.16.7", @@ -5182,21 +5182,21 @@ } }, "@jridgewell/resolve-uri": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.4.tgz", - "integrity": "sha512-cz8HFjOFfUBtvN+NXYSFMHYRdxZMaEl0XypVrhzxBgadKIXhIkRd8aMeHhmF56Sl7SuS8OnUpQ73/k9LE4VnLg==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.5.tgz", + "integrity": "sha512-VPeQ7+wH0itvQxnG+lIzWgkysKIr3L9sslimFW55rHMdGu/qCQ5z5h9zq4gI8uBtqkpHhsF4Z/OwExufUCThew==", "dev": true }, "@jridgewell/sourcemap-codec": { - "version": "1.4.10", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.10.tgz", - "integrity": "sha512-Ht8wIW5v165atIX1p+JvKR5ONzUyF4Ac8DZIQ5kZs9zrb6M8SJNXpx1zn04rn65VjBMygRoMXcyYwNK0fT7bEg==", + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz", + "integrity": "sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg==", "dev": true }, "@jridgewell/trace-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.2.tgz", - "integrity": "sha512-9KzzH4kMjA2XmBRHfqG2/Vtl7s92l6uNDd0wW7frDE+EUvQFGqNXhWp0UGJjSkt3v2AYjzOZn1QO9XaTNJIt1Q==", + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.4.tgz", + "integrity": "sha512-vFv9ttIedivx0ux3QSjhgtCVjPZd5l46ZOMDSCwnH1yUO2e964gO8LZGyv2QkqcgR6TnBU1v+1IFqmeoG+0UJQ==", "dev": true, "requires": { "@jridgewell/resolve-uri": "^3.0.3", diff --git a/package.json b/package.json index ca080a0c38..1ae52cc040 100644 --- a/package.json +++ b/package.json @@ -159,7 +159,7 @@ "zod": "^3.11.6" }, "devDependencies": { - "@babel/core": "^7.17.0", + "@babel/core": "^7.17.2", "@babel/plugin-transform-runtime": "^7.16.7", "@babel/preset-env": "^7.16.7", "@opengovsg/mockpass": "^2.7.9", From dba8f16238577c1dabcfab3ad750a6f2600597fc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Feb 2022 17:50:55 +0000 Subject: [PATCH 08/10] fix(deps): bump @sentry/browser from 6.16.1 to 6.17.7 (#3429) Bumps [@sentry/browser](https://github.com/getsentry/sentry-javascript) from 6.16.1 to 6.17.7. - [Release notes](https://github.com/getsentry/sentry-javascript/releases) - [Changelog](https://github.com/getsentry/sentry-javascript/blob/master/CHANGELOG.md) - [Commits](https://github.com/getsentry/sentry-javascript/compare/6.16.1...6.17.7) --- updated-dependencies: - dependency-name: "@sentry/browser" dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 103 +++++++++++++++++++++++++++++++++++----------- package.json | 2 +- 2 files changed, 80 insertions(+), 25 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1c6e1f3f44..4400511030 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5435,36 +5435,84 @@ "integrity": "sha512-UdkG3mLEqXgnlKsWanWcgb6dOjUzJ+XC5f+aWw30qrtjxeNUSfKX1cd5FBzOaXQumoe9nIqeZUvrRJS03HCCtw==" }, "@sentry/browser": { - "version": "6.16.1", - "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-6.16.1.tgz", - "integrity": "sha512-F2I5RL7RTLQF9CccMrqt73GRdK3FdqaChED3RulGQX5lH6U3exHGFxwyZxSrY4x6FedfBFYlfXWWCJXpLnFkow==", + "version": "6.17.7", + "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-6.17.7.tgz", + "integrity": "sha512-0Ad6TmB5KH5o152Hgk5tlxNiooV0Rfoj7HEzxdOnHFkl57aR7VsiPkzIBl9vxn4iyy7IheUONhHSOU1osJkv2w==", "requires": { - "@sentry/core": "6.16.1", - "@sentry/types": "6.16.1", - "@sentry/utils": "6.16.1", + "@sentry/core": "6.17.7", + "@sentry/types": "6.17.7", + "@sentry/utils": "6.17.7", "tslib": "^1.9.3" + }, + "dependencies": { + "@sentry/types": { + "version": "6.17.7", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.17.7.tgz", + "integrity": "sha512-iBlJDhrSowZKeqvutY0tCkUjrWqkLFsHrbaQ553r1Nx+/4mxHjzVYtEVGMjZAxQUEbkm0TbnQIkkT7ltglNJ9A==" + }, + "@sentry/utils": { + "version": "6.17.7", + "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.17.7.tgz", + "integrity": "sha512-HEEEeKlZtwfQvH0waSKv5FKRFjHkVgkkEiAigXoYGQAlaUIuwRTvZGFnsmBoKMIrA4pARkA00FwwdtMU7ziC8A==", + "requires": { + "@sentry/types": "6.17.7", + "tslib": "^1.9.3" + } + } } }, "@sentry/core": { - "version": "6.16.1", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.16.1.tgz", - "integrity": "sha512-UFI0264CPUc5cR1zJH+S2UPOANpm6dLJOnsvnIGTjsrwzR0h8Hdl6rC2R/GPq+WNbnipo9hkiIwDlqbqvIU5vw==", - "requires": { - "@sentry/hub": "6.16.1", - "@sentry/minimal": "6.16.1", - "@sentry/types": "6.16.1", - "@sentry/utils": "6.16.1", + "version": "6.17.7", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.17.7.tgz", + "integrity": "sha512-SRhLkD05lQb4eCt1ed9Dz72DKbRDlM8PJix8eC2oJLtwyFTS0IlJNkIYRrbsSKkJUm0VsKcDkzIHvUAgBBQICw==", + "requires": { + "@sentry/hub": "6.17.7", + "@sentry/minimal": "6.17.7", + "@sentry/types": "6.17.7", + "@sentry/utils": "6.17.7", "tslib": "^1.9.3" + }, + "dependencies": { + "@sentry/types": { + "version": "6.17.7", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.17.7.tgz", + "integrity": "sha512-iBlJDhrSowZKeqvutY0tCkUjrWqkLFsHrbaQ553r1Nx+/4mxHjzVYtEVGMjZAxQUEbkm0TbnQIkkT7ltglNJ9A==" + }, + "@sentry/utils": { + "version": "6.17.7", + "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.17.7.tgz", + "integrity": "sha512-HEEEeKlZtwfQvH0waSKv5FKRFjHkVgkkEiAigXoYGQAlaUIuwRTvZGFnsmBoKMIrA4pARkA00FwwdtMU7ziC8A==", + "requires": { + "@sentry/types": "6.17.7", + "tslib": "^1.9.3" + } + } } }, "@sentry/hub": { - "version": "6.16.1", - "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.16.1.tgz", - "integrity": "sha512-4PGtg6AfpqMkreTpL7ymDeQ/U1uXv03bKUuFdtsSTn/FRf9TLS4JB0KuTZCxfp1IRgAA+iFg6B784dDkT8R9eg==", + "version": "6.17.7", + "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.17.7.tgz", + "integrity": "sha512-siGzcg+quGOdjRaBGAz6T3ycwHUsGgvalptSJdf5Q783FVFhU+haPul++zGOYURXOgx0RjYGWqagwO8+jljl3Q==", "requires": { - "@sentry/types": "6.16.1", - "@sentry/utils": "6.16.1", + "@sentry/types": "6.17.7", + "@sentry/utils": "6.17.7", "tslib": "^1.9.3" + }, + "dependencies": { + "@sentry/types": { + "version": "6.17.7", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.17.7.tgz", + "integrity": "sha512-iBlJDhrSowZKeqvutY0tCkUjrWqkLFsHrbaQ553r1Nx+/4mxHjzVYtEVGMjZAxQUEbkm0TbnQIkkT7ltglNJ9A==" + }, + "@sentry/utils": { + "version": "6.17.7", + "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.17.7.tgz", + "integrity": "sha512-HEEEeKlZtwfQvH0waSKv5FKRFjHkVgkkEiAigXoYGQAlaUIuwRTvZGFnsmBoKMIrA4pARkA00FwwdtMU7ziC8A==", + "requires": { + "@sentry/types": "6.17.7", + "tslib": "^1.9.3" + } + } } }, "@sentry/integrations": { @@ -5479,13 +5527,20 @@ } }, "@sentry/minimal": { - "version": "6.16.1", - "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.16.1.tgz", - "integrity": "sha512-dq+mI1EQIvUM+zJtGCVgH3/B3Sbx4hKlGf2Usovm9KoqWYA+QpfVBholYDe/H2RXgO7LFEefDLvOdHDkqeJoyA==", + "version": "6.17.7", + "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.17.7.tgz", + "integrity": "sha512-+/FGem1uXsXikX9wHPw44nevO7YTVjkkiPjyLsvnWMjv64r4Au5s+NQSFHDaytRm9IlU//+OasCAS5VAwHcYRg==", "requires": { - "@sentry/hub": "6.16.1", - "@sentry/types": "6.16.1", + "@sentry/hub": "6.17.7", + "@sentry/types": "6.17.7", "tslib": "^1.9.3" + }, + "dependencies": { + "@sentry/types": { + "version": "6.17.7", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.17.7.tgz", + "integrity": "sha512-iBlJDhrSowZKeqvutY0tCkUjrWqkLFsHrbaQ553r1Nx+/4mxHjzVYtEVGMjZAxQUEbkm0TbnQIkkT7ltglNJ9A==" + } } }, "@sentry/types": { diff --git a/package.json b/package.json index 1ae52cc040..feab95be67 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "@opengovsg/ng-file-upload": "^12.2.15", "@opengovsg/sgid-client": "0.0.12", "@opengovsg/spcp-auth-client": "^1.4.15", - "@sentry/browser": "^6.16.1", + "@sentry/browser": "^6.17.7", "@sentry/integrations": "^6.16.1", "@stablelib/base64": "^1.0.1", "JSONStream": "^1.3.5", From e2f9a06c7722e146c282062a8277860aceeb3bb2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 15 Feb 2022 01:07:10 +0000 Subject: [PATCH 09/10] fix(deps): bump vm2 from 3.9.5 to 3.9.7 (#3431) Bumps [vm2](https://github.com/patriksimek/vm2) from 3.9.5 to 3.9.7. - [Release notes](https://github.com/patriksimek/vm2/releases) - [Changelog](https://github.com/patriksimek/vm2/blob/master/CHANGELOG.md) - [Commits](https://github.com/patriksimek/vm2/compare/3.9.5...3.9.7) --- updated-dependencies: - dependency-name: vm2 dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4400511030..b3f3cfb669 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24681,9 +24681,25 @@ "dev": true }, "vm2": { - "version": "3.9.5", - "resolved": "https://registry.npmjs.org/vm2/-/vm2-3.9.5.tgz", - "integrity": "sha512-LuCAHZN75H9tdrAiLFf030oW7nJV5xwNMuk1ymOZwopmuK3d2H4L1Kv4+GFHgarKiLfXXLFU+7LDABHnwOkWng==" + "version": "3.9.7", + "resolved": "https://registry.npmjs.org/vm2/-/vm2-3.9.7.tgz", + "integrity": "sha512-g/GZ7V0Mlmch3eDVOATvAXr1GsJNg6kQ5PjvYy3HbJMCRn5slNbo/u73Uy7r5yUej1cRa3ZjtoVwcWSQuQ/fow==", + "requires": { + "acorn": "^8.7.0", + "acorn-walk": "^8.2.0" + }, + "dependencies": { + "acorn": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", + "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==" + }, + "acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==" + } + } }, "w3c-hr-time": { "version": "1.0.2", From 55961a33d8627449a40b9e12369967bb979f7e26 Mon Sep 17 00:00:00 2001 From: Kar Rui Lau Date: Tue, 15 Feb 2022 10:25:55 +0800 Subject: [PATCH 10/10] chore: bump version to v5.43.0 --- CHANGELOG.md | 22 +++++++++++++++++++++- package-lock.json | 2 +- package.json | 2 +- 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 36c7f60dbf..e51b4afeb0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,8 +4,23 @@ All notable changes to this project will be documented in this file. Dates are d Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). +#### [v5.43.0](https://github.com/opengovsg/FormSG/compare/v5.42.0...v5.43.0) + +- fix(deps): bump vm2 from 3.9.5 to 3.9.7 [`#3431`](https://github.com/opengovsg/FormSG/pull/3431) +- fix(deps): bump @sentry/browser from 6.16.1 to 6.17.7 [`#3429`](https://github.com/opengovsg/FormSG/pull/3429) +- chore(deps-dev): bump @babel/core from 7.17.0 to 7.17.2 [`#3430`](https://github.com/opengovsg/FormSG/pull/3430) +- refactor: use combined route validators and handlers [`#3428`](https://github.com/opengovsg/FormSG/pull/3428) +- chore: bump spcp-auth-client to 1.14.15 [`#3341`](https://github.com/opengovsg/FormSG/pull/3341) +- fix(docs): Add missing characters for consistency [`#3426`](https://github.com/opengovsg/FormSG/pull/3426) +- fix(deps): bump helmet from 5.0.1 to 5.0.2 [`#3319`](https://github.com/opengovsg/FormSG/pull/3319) +- fix(deps): bump libphonenumber-js from 1.9.48 to 1.9.49 in /shared [`#3423`](https://github.com/opengovsg/FormSG/pull/3423) +- chore(deps-dev): bump eslint-plugin-jest from 26.0.0 to 26.1.0 [`#3419`](https://github.com/opengovsg/FormSG/pull/3419) +- build: merge release 5.42.0 into develop [`#3417`](https://github.com/opengovsg/FormSG/pull/3417) + #### [v5.42.0](https://github.com/opengovsg/FormSG/compare/v5.40.0...v5.42.0) +> 10 February 2022 + - chore(deps-dev): bump @types/node from 17.0.8 to 17.0.16 [`#3414`](https://github.com/opengovsg/FormSG/pull/3414) - feat: log ses message id [`#3391`](https://github.com/opengovsg/FormSG/pull/3391) - fix(deps): bump type-fest from 2.11.1 to 2.11.2 in /shared [`#3392`](https://github.com/opengovsg/FormSG/pull/3392) @@ -1201,7 +1216,7 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - fix(verification): loosen OTP waiting time by 2 seconds [`#1957`](https://github.com/opengovsg/FormSG/pull/1957) - chore: bump version to 5.12.0 [`85759bc`](https://github.com/opengovsg/FormSG/commit/85759bc9dc01f73da3cbd0ec73c636e58e983948) -#### [v5.11.0](https://github.com/opengovsg/FormSG/compare/v5.10.0...v5.11.0) +#### [v5.11.0](https://github.com/opengovsg/FormSG/compare/v5.10.1...v5.11.0) > 25 May 2021 @@ -1269,6 +1284,11 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - chore(deps-dev): bump @typescript-eslint/eslint-plugin [`#1868`](https://github.com/opengovsg/FormSG/pull/1868) - fix(deps): bump @sentry/integrations from 6.3.5 to 6.3.6 [`#1850`](https://github.com/opengovsg/FormSG/pull/1850) - chore: bump version to 5.11.0 [`54b1958`](https://github.com/opengovsg/FormSG/commit/54b1958d0968e670ef145461d9d7859384d573ef) + +#### [v5.10.1](https://github.com/opengovsg/FormSG/compare/v5.10.0...v5.10.1) + +> 17 May 2021 + - chore: bump version to v5.10.1 [`0442cd7`](https://github.com/opengovsg/FormSG/commit/0442cd72637019fb1e43bce5f8f5abe14ee79f8c) - fix: allow for unknown keys in updateEndPage validator [`617d86a`](https://github.com/opengovsg/FormSG/commit/617d86a28910eec6ebd3249a2de636086429d6a6) diff --git a/package-lock.json b/package-lock.json index b3f3cfb669..fd5237e92a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "FormSG", - "version": "5.42.0", + "version": "5.43.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index feab95be67..1979256802 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "FormSG", "description": "Form Manager for Government", - "version": "5.42.0", + "version": "5.43.0", "homepage": "https://form.gov.sg", "authors": [ "FormSG "