From 8f3c872d5db9ac5c2eee0989fca01d965974f427 Mon Sep 17 00:00:00 2001 From: Yuan Ruo Date: Wed, 9 Sep 2020 10:40:56 +0800 Subject: [PATCH 01/18] Greater clarity for available features, project roadmap and deployment instructions; disable E2E tests (#301) * doc(contributing): instructions for security findings; minor touchups * doc(readme): instructions and clarifications on scope of contributions * doc(readme): clarify product roadmap * fix(readme): mailto syntax * refactor(e2e)!: disable end-to-end tests E2E tests are disabled due to apparent race condition when evaluating webhooks in Travis. Link to example: https://travis-ci.com/github/opengovsg/FormSG/builds/183369046 Co-authored-by: syan-syan <55272802+syan-syan@users.noreply.github.com> Co-authored-by: Antariksh Mahajan --- .travis.yml | 2 +- CONTRIBUTING.md | 26 +++--- README.md | 32 ++++++-- docs/DEPLOYMENT_SETUP.md | 172 +++++++++++++++++++++------------------ 4 files changed, 135 insertions(+), 97 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1188c390ba..36623c1df1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -35,7 +35,7 @@ script: - npm run lint-ci - npm run build - npm run test-ci - - npm run test-e2e-ci + # - npm run test-e2e-ci before_deploy: # Workaround to run before_deploy only once diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2ca5cda003..1b86e1e19d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,23 +2,30 @@ Welcome to FormSG! The following are guidelines for contribution. Use your best judgment, and feel free to propose changes to this document in an issue. -## How can I contribute? +## Getting started -When contributing to this repository, **please first discuss the change you wish to make via issue**, email, or any other method with the repository owners before making the change. +To contribute, you can start by taking a look at our open issues marked 'contribute' under GitHub's 'Issues' tab. Feel free to assign yourself to any 'contribute' issue that interests you, and comment with questions or clarifications. -## Bug reports and feature requests +Otherwise, please **first discuss the change you wish to make via GitHub issue**, [email](mailto:formsg@tech.gov.sg), or any other method with the repository owners beforehand. + +## Security reports + +Please do not file an open issue for ongoing security bugs. Instead, email us directly with your findings at [formsg@tech.gov.sg](mailto:formsg@tech.gov.sg). + +## Bug reports and feature requests The following guidelines help maintainers and the community understand your report, reproduce the behavior, and find related reports. Before submitting bug reports or feature request, please check [existing or past issues](https://go.gov.sg/formsg-issues) and [existing or past pull requests](https://go.gov.sg/formsg-pulls). -You might find out that you don't need to create one. +You might find out that you don't need to create one. When **submitting a bug report**, please include as many details as possible, such as the steps to reproduce this bug, expected and actual behaviour. When **submitting a feature request**, please include the motivation, alternatives that you've considered and any additional contexts that could help us better understand your goal. Here are some tips to writing good issues: -- **Use clear and descriptive title** to identify the problem + +- **Use a clear and descriptive title** to identify the problem - **Describe the exact steps to reproduce the problem** and **explain how you did it** - **Provide specific examples to demonstrate the steps** - **Include screenshots or animated GIFs if you can** @@ -31,18 +38,17 @@ Issues available to be picked up by the community are labeled with `contribute`. If you're submitting a pull request, some points to note: 1. Ensure any install or build dependencies are removed before the end of the layer when doing a build. Refer to [README.md](https://go.gov.sg/formsg-readme) for more details -2. Update the [README.md](https://go.gov.sg/formsg-readme) with details of changes to the interface, this includes new environment variables, exposed ports, useful file locations and container parameters. +2. Update the [README.md](https://go.gov.sg/formsg-readme) with details of changes to the interface, including new environment variables, exposed ports, useful file locations and container parameters. 3. You may merge the Pull Request in once you have the sign-off of two other developers, or if you do not have permission to do that, you may request the second reviewer to merge it for you. ## Contributor License Agreement -Code contributions to this project must be accompanied by a Contributor License Agreement. You (or your employer) retain the copyright to your contribution; this simply gives us permission to use and redistribute your contributions as part of the project. -Head over [here](https://go.gov.sg/ogp-cla) to submit one. +Code contributions to this project must be accompanied by a Contributor License Agreement. You (or your employer) retain the copyright to your contribution; this simply gives us permission to use and redistribute your contributions as part of the project. +Head over [here](https://go.gov.sg/ogp-cla) to submit one. You generally only need to submit a CLA once, so if you've already submitted one (even if it was for a different project owned by [GovTech](https://www.tech.gov.sg)), you probably don't need to do it again. ## Contact us -Have questions? Feel free out to us [here](formsg@tech.gov.sg). - +Have questions? Feel free to reach out to us at [formsg@tech.gov.sg](mailto:formsg@tech.gov.sg). diff --git a/README.md b/README.md index c67584ab15..f00489325e 100755 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ - [FormSG](#formsg) - [Table of Contents](#table-of-contents) + - [Features](#features) - [Local Development (Docker)](#local-development-docker) - [Prerequisites](#prerequisites) - [Running Locally](#running-locally) @@ -23,6 +24,29 @@ - [Contributing](#contributing) - [Support](#support) +## Features + +FormSG is a form builder application built, open sourced and maintained by the [Open Government Products](https://open.gov.sg) team of the Singapore [Government Technology Agency](https://tech.gov.sg) to digitise paper processes. + +Notable features include: + +- 19 different form field types, including attachments, tables, email and mobile +- Verified email and mobile phone fields via integrations with Twilio and AWS SES +- Automatic emailing of submissions for forms built with Email Mode +- End-to-end encryption for forms built with Storage Mode +- (Singapore government agencies only) Citizen authentication with [SingPass](https://www.singpass.gov.sg/singpass/common/aboutus) +- (Singapore government agencies only) Corporate authentication with [CorpPass](https://www.corppass.gov.sg/corppass/common/aboutus) +- (Singapore government agencies only) Automatic prefill of verified data with [MyInfo](https://www.singpass.gov.sg/myinfo/common/aboutus) +- (beta) Webhooks functionality via the [FormSG JavaScript SDK](https://github.com/opengovsg/formsg-sdk). + +The current product roadmap includes: + +- (in progress) Migrating backend code from JavaScript to [TypeScript](https://www.typescriptlang.org/) +- (in progress) Refactoring backend code to use [Domain-driven Design](https://en.wikipedia.org/wiki/Domain-driven_design) +- (in progress) Migrating backend tests from [Jasmine](https://jasmine.github.io/) to [Jest](https://jestjs.io/) and expanding unit vs integration tests +- (yet to start) Support for webhooks attachments +- (yet to start) Frontend rewrite from [AngularJS](https://angularjs.org/) to [React](https://reactjs.org/) + ## Local Development (Docker) ### Prerequisites @@ -31,16 +55,14 @@ Install [docker and docker-compose](https://docs.docker.com/get-docker/). ### Running Locally -Run +Run the following shell command to build the Docker image from scratch. This will usually take 10 or so minutes. ```bash npm run dev ``` -to build the Docker image from scratch. This will usually take 10 or so minutes. - If there have been no dependency changes in `package.json` or changes in the -root `server.js` file, you can run +`src/server.ts` file, you can run ```bash docker-compose up @@ -165,7 +187,7 @@ forms and configured using the environment variables below. ## Contributing -We welcome contributions to code open sourced by the Government Technology Agency of Singapore. All contributors will 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) in order to ensure that everybody is free to use their contributions. ## Support diff --git a/docs/DEPLOYMENT_SETUP.md b/docs/DEPLOYMENT_SETUP.md index db64c833dd..67d88b327c 100644 --- a/docs/DEPLOYMENT_SETUP.md +++ b/docs/DEPLOYMENT_SETUP.md @@ -12,39 +12,49 @@ $ npm start ## Deploying to AWS Elastic Beanstalk -As a prerequisite for EB deployment, make sure you have already created your AWS environment. Some of the services used are listed below: +Make sure you have created an AWS cloud environment as a prerequisite. Some of the services used are listed below: -- Elastic Beanstalk / EC2 for hosting and deployment -- VPC with peering to MongoDB Atlas -- NAT Gateway (for static IP whitelisting with SingPass) -- S3 for image and logo hosting -- Elastic Container Registry for built Docker images -- SES for sending emails -- EFS for mounting files e.g. SingPass/MyInfo private keys into the `/certs` directory -- Secrets Manager +Infrastructure -### Dockerrun.aws.json +- AWS Elastic Beanstalk / EC2 for hosting and deployment +- AWS Elastic File System for mounting files (i.e. SingPass/MyInfo private keys into the `/certs` directory) +- AWS S3 for image and logo hosting, attachments for Storage Mode forms -```json -{ - "AWSEBDockerrunVersion": "1", - "Image": { - "Name": "", - "Update": "true" - }, - "Ports": [ - { - "ContainerPort": "4545" - } - ], - "Volumes": [ - { - "HostDirectory": "/certs", - "ContainerDirectory": "/certs" - } - ] -} -``` +DevOps + +- TravisCI for running tests and builds +- AWS Elastic Container Registry to host built Docker images + +Network + +- AWS VPC (with peering preferred) for managed database hosted by MongoDB Atlas +- AWS NAT Gateway (for static IP whitelisting with SingPass) + +Database + +- MongoDB instance (we use Mongo Atlas) + +Emails + +- AWS Simple Email Service with SMTP integration for sending emails to login/send OTPs/form submissions/submission autoreplies + +SMS + +- Twilio for sending OTPs +- AWS Secrets Manager (to manage user-provided or hosted Twilio credentials) + +Analytics and Monitoring + +- Sentry.io +- Google Analytics + +Spam protection + +- Google reCAPTCHA + +### Mounting Elastic File System into Docker container on Elastic Beanstalk + +Please see [Dockerrun.aws.json](../Dockerrun.aws.json). This file is required for SingPass/MyInfo/CorpPass functionality to be enabled. ### Secrets Manager (Optional) @@ -54,10 +64,10 @@ Firstly, name the secret with a unique secret name and store the secret value in ```json { - "accountSid": "", - "apiKey": "", - "apiSecret": "", - "messagingServiceSid": "" + "accountSid": "", + "apiKey": "redacted>", + "apiSecret": "redacted>", + "messagingServiceSid": "redacted>" } ``` @@ -73,7 +83,7 @@ For more information about the various environment variables, please refer to The following env variables are set in Travis: | Variable | Description| |:---------|------------| -|`REPO`|The repository of the AWS ECR| +|`REPO`|The repository of the AWS Elastic Container Registry| |`STAGING_BRANCH`|Name of staging branch, usually `master`.| |`STAGING_ALT_BRANCH`|Name of staging-alt (if any) branch, usually `release`. An alternate staging branch is used to host diverging feature sets, useful for A/B testing.| |`PROD_BRANCH`|Name of production branch, usually `release`.| @@ -98,34 +108,34 @@ The following env variables are set in Travis: #### App Config -| Variable | Description | -| :----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `APP_NAME` | Application name in window title; also used as an identifier for MyInfo. Defaults to `'FormSG'`. | -| `APP_DESC` | Defaults to `'Form Manager for Government'`. | -| `APP_URL` | Defaults to `'https://form.gov.sg'`. | -| `APP_KEYWORDS` | Defaults to `'forms, formbuilder, nodejs'`. | -| `APP_IMAGES` | Defaults to `'/public/modules/core/img/og/img_metatag.png,/public/modules/core/img/og/logo-vertical-color.png'`. | -| `APP_TWITTER_IMAGE` | Path to Twitter image. Defaults to `'/public/modules/core/img/og/logo-vertical-color.png'`. | +| Variable | Description | +| :------------------ | ---------------------------------------------------------------------------------------------------------------- | +| `APP_NAME` | Application name in window title; also used as an identifier for MyInfo. Defaults to `'FormSG'`. | +| `APP_DESC` | Defaults to `'Form Manager for Government'`. | +| `APP_URL` | Defaults to `'https://form.gov.sg'`. | +| `APP_KEYWORDS` | Defaults to `'forms, formbuilder, nodejs'`. | +| `APP_IMAGES` | Defaults to `'/public/modules/core/img/og/img_metatag.png,/public/modules/core/img/og/logo-vertical-color.png'`. | +| `APP_TWITTER_IMAGE` | Path to Twitter image. Defaults to `'/public/modules/core/img/og/logo-vertical-color.png'`. | #### App and Database -| Variable | Description | -| :----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `DB_HOST` | A MongoDB URI. | -| `OTP_LIFE_SPAN` | Time in milliseconds that admin login OTP is valid for. Defaults to 900000ms or 15 minutes. | -| `PORT` | Server port. Defaults to `5000`. | -| `NODE_ENV` | [Express environment mode](https://expressjs.com/en/advanced/best-practice-performance.html#set-node_env-to-production). Defaults to `'development'`. This should always be set to a production environment | -| `SESSION_SECRET` | Secret for `express-session`. Defaults to `'sandcrawler-138577'`. This should always be set in a production environment. | -| `SUBMISSIONS_TOP_UP` | Use this to inflate the number of submissions displayed on the landing page. Defaults to `0`. | +| Variable | Description | +| :------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `DB_HOST` | A MongoDB URI. | +| `OTP_LIFE_SPAN` | Time in milliseconds that admin login OTP is valid for. Defaults to 900000ms or 15 minutes. | +| `PORT` | Server port. Defaults to `5000`. | +| `NODE_ENV` | [Express environment mode](https://expressjs.com/en/advanced/best-practice-performance.html#set-node_env-to-production). Defaults to `'production'`. This should always be set to a production environment | +| `SESSION_SECRET` | Secret for `express-session` for session management. This should always be set to a secret and random value in a production environment. | +| `SUBMISSIONS_TOP_UP` | Use this to inflate the number of submissions displayed on the landing page. Defaults to `0`. | #### Banners -| Variable | Description | -| :----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `SITE_BANNER_CONTENT` | If set, displays a banner message on both private routes that `ADMIN_BANNER_CONTENT` covers **and** public form routes that `IS_GENERAL_MAINTENANCE` covers. Overrides all other banner environment variables | -| `ADMIN_BANNER_CONTENT` | If set, displays a banner message on private admin routes such as the form list page as well as form builder pages. | -| `IS_LOGIN_BANNER` | If set, displays a banner message on the login page | -| `IS_GENERAL_MAINTENANCE` | If set, displays a banner message on all forms. Overrides `IS_SP_MAINTENANCE` and `IS_CP_MAINTENANCE`. | +| Variable | Description | +| :----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `SITE_BANNER_CONTENT` | If set, displays a banner message on both private routes that `ADMIN_BANNER_CONTENT` covers **and** public form routes that `IS_GENERAL_MAINTENANCE` covers. Overrides all other banner environment variables | +| `ADMIN_BANNER_CONTENT` | If set, displays a banner message on private admin routes such as the form list page as well as form builder pages. | +| `IS_LOGIN_BANNER` | If set, displays a banner message on the login page | +| `IS_GENERAL_MAINTENANCE` | If set, displays a banner message on all forms. Overrides `IS_SP_MAINTENANCE` and `IS_CP_MAINTENANCE`. | #### AWS services @@ -134,10 +144,10 @@ The following env variables are set in Travis: | `AWS_REGION` | AWS region. | | `AWS_ACCESS_KEY_ID` | AWS IAM access key ID used to access S3. | | `AWS_SECRET_ACCESS_KEY` | AWS IAM access secret used to access S3. | -| `AWS_ENDPOINT` | AWS S3 bucket endpoint. | +| `AWS_ENDPOINT` | AWS S3 bucket endpoint. | | `IMAGE_S3_BUCKET` | Name of S3 bucket for image field uploads. | | `LOGO_S3_BUCKET` | Name of S3 bucket for form logo uploads. | -| `LOGO_S3_BUCKET` | Name of S3 bucket for form logo uploads. | +| `ATTACHMENT_S3_BUCKET` | Name of S3 bucket for attachment uploads on Storage Mode. | | `CUSTOM_CLOUDWATCH_LOG_GROUP` | Name of CloudWatch log group to send custom logs. Use this if you want some logs to have custom settings, e.g. shorter expiry time. | #### [FormSG JavaScript SDK](https://www.npmjs.com/package/@opengovsg/formsg-sdk) @@ -148,20 +158,20 @@ The following env variables are set in Travis: #### Email and Nodemailer -| Variable | Description | -| :-------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `SES_HOST` | SMTP hostname. | -| `SES_PORT` | SMTP port number. | -| `SES_USER` | SMTP username. | -| `SES_PASS` | SMTP password. | -| `SES_MAX_MESSAGES` | Nodemailer configuration. Connection removed and new one created when this limit is reached. This helps to keep the connection up-to-date for long-running email messaging. Defaults to `100`. | -| `SES_POOL` | Connection pool to send email in parallel to the SMTP server. Defaults to `38`. | -| `MAIL_FROM` | Sender email address. Defaults to `'donotreply@mail.form.gov.sg'`. | | -| `MAIL_SOCKET_TIMEOUT` | Milliseconds of inactivity to allow before killing a connection. This helps to keep the connection up-to-date for long-running email messaging. Defaults to `600000`. | -| `MAIL_LOGGER` | If set to true then logs to console. If value is not set or is false then nothing is logged. | -| `MAIL_DEBUG` | If set to `true`, then logs SMTP traffic, otherwise logs only transaction events. | -| `CHROMIUM_BIN` | Filepath to chromium binary. Required for email autoreply PDF generation with Puppeteer. | -| `BOUNCE_LIFE_SPAN` | Time in milliseconds that bounces are tracked for each form. Defaults to 10800000ms or 3 hours. Only relevant if you have set up AWS to send bounce and delivery notifications to the /emailnotifications endpoint. | +| Variable | Description | +| :-------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `SES_HOST` | SMTP hostname. | +| `SES_PORT` | SMTP port number. | +| `SES_USER` | SMTP username. | +| `SES_PASS` | SMTP password. | +| `SES_MAX_MESSAGES` | Nodemailer configuration. Connection removed and new one created when this limit is reached. This helps to keep the connection up-to-date for long-running email messaging. Defaults to `100`. | +| `SES_POOL` | Connection pool to send email in parallel to the SMTP server. Defaults to `38`. | +| `MAIL_FROM` | Sender email address. Defaults to `'donotreply@mail.form.gov.sg'`. | +| `MAIL_SOCKET_TIMEOUT` | Milliseconds of inactivity to allow before killing a connection. This helps to keep the connection up-to-date for long-running email messaging. Defaults to `600000`. | +| `MAIL_LOGGER` | If set to true then logs to console. If value is not set or is false then nothing is logged. | +| `MAIL_DEBUG` | If set to `true`, then logs SMTP traffic, otherwise logs only transaction events. | +| `CHROMIUM_BIN` | Filepath to chromium binary. Required for email autoreply PDF generation with Puppeteer. | +| `BOUNCE_LIFE_SPAN` | Time in milliseconds that bounces are tracked for each form. Defaults to 10800000ms or 3 hours. Only relevant if you have set up AWS to send bounce and delivery notifications to the /emailnotifications endpoint. | ### Additional Features @@ -246,8 +256,8 @@ Note that MyInfo is currently not supported for storage mode forms and enabling | `MYINFO_CLIENT_CONFIG` | Configures [MyInfoGovClient](https://github.com/opengovsg/myinfo-gov-client). Set this to either`stg` or `prod` to fetch MyInfo data from the corresponding endpoints. | | `MYINFO_FORMSG_KEY_PATH` | Filepath to MyInfo private key, which is used to decrypt returned responses. | | `MYINFO_APP_KEY` | (deprecated) Directly specify contents of the MyInfo FormSG private key. Only works if `NODE_ENV` is set to `development`. | -| `IS_SP_MAINTENANCE` | If set, displays a banner message on SingPass forms. Overrides `IS_CP_MAINTENANCE`. | -| `IS_CP_MAINTENANCE` | If set, displays a banner message on CorpPass forms. | +| `IS_SP_MAINTENANCE` | If set, displays a banner message on SingPass forms. Overrides `IS_CP_MAINTENANCE`. | +| `IS_CP_MAINTENANCE` | If set, displays a banner message on CorpPass forms. | #### Verified Emails/SMSes @@ -271,9 +281,9 @@ If this feature is enabled, storage mode forms will also support authentication ### Tests -| Variable | Description | -| :--------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | -| `MONGO_BINARY_VERSION` | Version of the Mongo binary used. Defaults to `'latest'` according to [MongoMemoryServer](https://github.com/nodkz/mongodb-memory-server) docs. | -| `PWD` | Path of working directory. | -| `MOCK_WEBHOOK_CONFIG_FILE` | Path of configuration file for mock webhook server | -| `MOCK_WEBHOOK_PORT` | Port of mock webhook server | +| Variable | Description | +| :------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | +| `MONGO_BINARY_VERSION` | Version of the Mongo binary used. Defaults to `'latest'` according to [MongoMemoryServer](https://github.com/nodkz/mongodb-memory-server) docs. | +| `PWD` | Path of working directory. | +| `MOCK_WEBHOOK_CONFIG_FILE` | Path of configuration file for mock webhook server | +| `MOCK_WEBHOOK_PORT` | Port of mock webhook server | From 2e4c80c04bc6046f388a956b8a1df6b8fe06634f Mon Sep 17 00:00:00 2001 From: arshadali172 Date: Wed, 9 Sep 2020 13:59:06 +0800 Subject: [PATCH 02/18] chore: document env vars needed for EFS (#303) * Document cert path and file system id for SingPass/CorpPass/MyInfo Co-authored-by: Arshad Ali --- docs/DEPLOYMENT_SETUP.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/DEPLOYMENT_SETUP.md b/docs/DEPLOYMENT_SETUP.md index 67d88b327c..384faa974c 100644 --- a/docs/DEPLOYMENT_SETUP.md +++ b/docs/DEPLOYMENT_SETUP.md @@ -258,6 +258,8 @@ Note that MyInfo is currently not supported for storage mode forms and enabling | `MYINFO_APP_KEY` | (deprecated) Directly specify contents of the MyInfo FormSG private key. Only works if `NODE_ENV` is set to `development`. | | `IS_SP_MAINTENANCE` | If set, displays a banner message on SingPass forms. Overrides `IS_CP_MAINTENANCE`. | | `IS_CP_MAINTENANCE` | If set, displays a banner message on CorpPass forms. | +| `FILE_SYSTEM_ID` | The id of the AWS Elastic File System (EFS) file system to mount onto the instances. | +| `CERT_PATH` | The specific directory within the network file system that is to be mounted. This directory is expected to contain the public certs and private keys relevant to SingPass, CorpPass and MyInfo. | #### Verified Emails/SMSes From d090fedeee0257075b31b8431d6bf68dfc48803e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 9 Sep 2020 15:53:21 +0800 Subject: [PATCH 03/18] fix(deps): bump ejs from 2.7.4 to 3.1.5 (#282) Bumps [ejs](https://github.com/mde/ejs) from 2.7.4 to 3.1.5. - [Release notes](https://github.com/mde/ejs/releases) - [Changelog](https://github.com/mde/ejs/blob/main/CHANGELOG.md) - [Commits](https://github.com/mde/ejs/compare/v2.7.4...v3.1.5) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 40 +++++++++++++++++++++++++++++++++++++--- package.json | 2 +- 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 67290cc072..b2c3c09a3e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10342,9 +10342,12 @@ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" }, "ejs": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.7.4.tgz", - "integrity": "sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA==" + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.5.tgz", + "integrity": "sha512-dldq3ZfFtgVTJMLjOe+/3sROTzALlL9E34V4/sDtUd/KlBSS0s6U1/+WPE1B4sj9CXHJpL1M6rhNJnc9Wbal9w==", + "requires": { + "jake": "^10.6.1" + } }, "electron-to-chromium": { "version": "1.3.475", @@ -11950,6 +11953,14 @@ "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" }, + "filelist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.1.tgz", + "integrity": "sha512-8zSK6Nu0DQIC08mUC46sWGXi+q3GGpKydAG36k+JDba6VRpkevvOWUW5a/PhShij4+vHT9M+ghgG7eM+a9JDUQ==", + "requires": { + "minimatch": "^3.0.4" + } + }, "fill-keys": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/fill-keys/-/fill-keys-1.0.2.tgz", @@ -14268,6 +14279,24 @@ "istanbul-lib-report": "^3.0.0" } }, + "jake": { + "version": "10.8.2", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.2.tgz", + "integrity": "sha512-eLpKyrfG3mzvGE2Du8VoPbeSkRry093+tyNjdYaBbJS9v17knImYGNXQCUV0gLxQtF82m3E8iRb/wdSQZLoq7A==", + "requires": { + "async": "0.9.x", + "chalk": "^2.4.2", + "filelist": "^1.0.1", + "minimatch": "^3.0.4" + }, + "dependencies": { + "async": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", + "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=" + } + } + }, "jasmine": { "version": "3.6.1", "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-3.6.1.tgz", @@ -27094,6 +27123,11 @@ "xpath": "0.0.27" }, "dependencies": { + "ejs": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.7.4.tgz", + "integrity": "sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA==" + }, "node-forge": { "version": "0.7.6", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.6.tgz", diff --git a/package.json b/package.json index 85cff22f9e..9844e7e8aa 100644 --- a/package.json +++ b/package.json @@ -110,7 +110,7 @@ "csv-string": "^3.1.5", "dedent-js": "^1.0.1", "deep-diff": "^1.0.1", - "ejs": "^2.6.1", + "ejs": "^3.1.5", "express": "^4.16.4", "express-device": "~0.4.2", "express-session": "^1.15.6", From 4e872221d7fa231d114694b45567882a07eab6ee Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 9 Sep 2020 16:44:20 +0800 Subject: [PATCH 04/18] chore(deps-dev): bump eslint-plugin-jest from 23.20.0 to 24.0.0 (#299) Bumps [eslint-plugin-jest](https://github.com/jest-community/eslint-plugin-jest) from 23.20.0 to 24.0.0. - [Release notes](https://github.com/jest-community/eslint-plugin-jest/releases) - [Changelog](https://github.com/jest-community/eslint-plugin-jest/blob/master/CHANGELOG.md) - [Commits](https://github.com/jest-community/eslint-plugin-jest/compare/v23.20.0...v24.0.0) 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, 5 insertions(+), 49 deletions(-) diff --git a/package-lock.json b/package-lock.json index b2c3c09a3e..c5be454592 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11174,56 +11174,12 @@ } }, "eslint-plugin-jest": { - "version": "23.20.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-23.20.0.tgz", - "integrity": "sha512-+6BGQt85OREevBDWCvhqj1yYA4+BFK4XnRZSGJionuEYmcglMZYLNNBBemwzbqUAckURaHdJSBcjHPyrtypZOw==", + "version": "24.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-24.0.0.tgz", + "integrity": "sha512-a0G7hSDbuBCW4PNT6MVpAyfnGbUDOqxzOyhR6wT2BIBnR7MhvfAqd6KKfsTjX+Z3gxzIHiEsihzdClU4cSc6qQ==", "dev": true, "requires": { - "@typescript-eslint/experimental-utils": "^2.5.0" - }, - "dependencies": { - "@typescript-eslint/experimental-utils": { - "version": "2.34.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-2.34.0.tgz", - "integrity": "sha512-eS6FTkq+wuMJ+sgtuNTtcqavWXqsflWcfBnlYhg/nS4aZ1leewkXGbvBhaapn1q6qf4M71bsR1tez5JTRMuqwA==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.3", - "@typescript-eslint/typescript-estree": "2.34.0", - "eslint-scope": "^5.0.0", - "eslint-utils": "^2.0.0" - } - }, - "@typescript-eslint/typescript-estree": { - "version": "2.34.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-2.34.0.tgz", - "integrity": "sha512-OMAr+nJWKdlVM9LOqCqh3pQQPwxHAN7Du8DR6dmwCrAmxtiXQnhHJ6tBNtf+cggqfo51SG/FCwnKhXCIM7hnVg==", - "dev": true, - "requires": { - "debug": "^4.1.1", - "eslint-visitor-keys": "^1.1.0", - "glob": "^7.1.6", - "is-glob": "^4.0.1", - "lodash": "^4.17.15", - "semver": "^7.3.2", - "tsutils": "^3.17.1" - } - }, - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "semver": { - "version": "7.3.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", - "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", - "dev": true - } + "@typescript-eslint/experimental-utils": "^4.0.1" } }, "eslint-plugin-prettier": { diff --git a/package.json b/package.json index 9844e7e8aa..b6e06ea7b7 100644 --- a/package.json +++ b/package.json @@ -206,7 +206,7 @@ "eslint-plugin-angular": "^4.0.1", "eslint-plugin-html": "^6.0.2", "eslint-plugin-import": "^2.21.2", - "eslint-plugin-jest": "^23.20.0", + "eslint-plugin-jest": "^24.0.0", "eslint-plugin-prettier": "^3.1.3", "eslint-plugin-simple-import-sort": "^5.0.3", "google-fonts-plugin": "4.1.0", From 4124cc144a6e809df9be7e8638bdc13a424b1128 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 9 Sep 2020 17:46:46 +0800 Subject: [PATCH 05/18] fix(deps): bump angular-translate-loader-partial from 2.18.2 to 2.18.3 (#298) Bumps [angular-translate-loader-partial](https://github.com/angular-translate/bower-angular-translate-loader-partial) from 2.18.2 to 2.18.3. - [Release notes](https://github.com/angular-translate/bower-angular-translate-loader-partial/releases) - [Commits](https://github.com/angular-translate/bower-angular-translate-loader-partial/compare/2.18.2...2.18.3) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 18 ++++++++++++++---- package.json | 2 +- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index c5be454592..3ea7aae4dd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5428,11 +5428,21 @@ } }, "angular-translate-loader-partial": { - "version": "2.18.2", - "resolved": "https://registry.npmjs.org/angular-translate-loader-partial/-/angular-translate-loader-partial-2.18.2.tgz", - "integrity": "sha512-rtLOUU8ImyWyERugDtuFck8G6fFJ9KsF3It4tgYd91JS9t8tGnarDORmUhMPF8M2wMjdgRKFDcp4nAZLHso5vA==", + "version": "2.18.3", + "resolved": "https://registry.npmjs.org/angular-translate-loader-partial/-/angular-translate-loader-partial-2.18.3.tgz", + "integrity": "sha512-Wi8x45aScHYcxLd2Pi761F0rDjPV3cKeAjuxUadYtOqov0pWWH18nBELUFMhaELt6qUi4fFxQ9o5rfqDNXqVoQ==", "requires": { - "angular-translate": "~2.18.2" + "angular-translate": "~2.18.3" + }, + "dependencies": { + "angular-translate": { + "version": "2.18.3", + "resolved": "https://registry.npmjs.org/angular-translate/-/angular-translate-2.18.3.tgz", + "integrity": "sha512-ziEi1nTaNIsdn3iKpcALaSFjM9CjwvoIWE/EKepajB/6qT5oB3K1IU5VcaH7Bd0scNRfaJpW+qUD6nsHWDEZ6A==", + "requires": { + "angular": "^1.8.0" + } + } } }, "angular-ui-bootstrap": { diff --git a/package.json b/package.json index b6e06ea7b7..ee96e8d2c5 100644 --- a/package.json +++ b/package.json @@ -82,7 +82,7 @@ "angular-resource": "^1.8.0", "angular-sanitize": "^1.8.0", "angular-translate": "^2.18.2", - "angular-translate-loader-partial": "^2.18.2", + "angular-translate-loader-partial": "^2.18.3", "angular-ui-bootstrap": "~2.5.6", "angular-ui-router": "~1.0.22", "async": "~1.5.2", From 2cd667b70ce2dcb239e6e6b0aee02064abe20b87 Mon Sep 17 00:00:00 2001 From: Yuan Ruo Date: Thu, 10 Sep 2020 10:27:22 +0800 Subject: [PATCH 06/18] refactor(proxy): do not override X-Forwarded-Proto headers (#304) --- src/loaders/express/index.ts | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/loaders/express/index.ts b/src/loaders/express/index.ts index 38b517e1c3..cf71cb02ae 100644 --- a/src/loaders/express/index.ts +++ b/src/loaders/express/index.ts @@ -29,13 +29,8 @@ const loadExpressApp = async (connection: Connection) => { const environmentConfigs = { production(app: Express) { - // Add x-forwarded-proto headers to handle https cookie, - // and trust the proxy that is in front of you - app.use(function (req, res, next) { - req.headers['x-forwarded-proto'] = 'https' - return next() - }) - app.set('trust proxy', 1) + // Trust the load balancer that is in front of the server + app.set('trust proxy', true) return app }, } From be7ed6ee4bb8db444dfa5e7ab4d7dc8b8a093482 Mon Sep 17 00:00:00 2001 From: arshadali172 Date: Fri, 11 Sep 2020 12:56:49 +0800 Subject: [PATCH 07/18] chore: reduce number of e2e tests and other fixes (#305) * Skip uncaught js errors during decryption * Run e2e on either basic or full env * Revert upgrade of test-cafe * Downgrade to testcafe 1.8.6 instead * Add back tests * Remove duplicative tests from email submissions e2e Co-authored-by: Arshad Ali --- .travis.yml | 2 +- package-lock.json | 131 +++++---------------- package.json | 6 +- tests/end-to-end/email-submission.e2e.js | 113 ++++++++---------- tests/end-to-end/encrypt-submission.e2e.js | 60 ++++------ tests/end-to-end/login.e2e.js | 5 - 6 files changed, 104 insertions(+), 213 deletions(-) diff --git a/.travis.yml b/.travis.yml index 36623c1df1..1188c390ba 100644 --- a/.travis.yml +++ b/.travis.yml @@ -35,7 +35,7 @@ script: - npm run lint-ci - npm run build - npm run test-ci - # - npm run test-e2e-ci + - npm run test-e2e-ci before_deploy: # Workaround to run before_deploy only once diff --git a/package-lock.json b/package-lock.json index 64cca63742..ba5193f005 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11233,9 +11233,9 @@ "dev": true }, "esotope-hammerhead": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/esotope-hammerhead/-/esotope-hammerhead-0.5.5.tgz", - "integrity": "sha512-EuSYJDtF8gLMB24lzjHw2KotauPsVJybFrtGfQyMm48oC7sTkspA26DqcqcbnRl4GC6sPVKWEx+ex72eqopX9Q==", + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/esotope-hammerhead/-/esotope-hammerhead-0.5.3.tgz", + "integrity": "sha512-EMZvx+2MXsAZxqa+bOJZp+5qWzKZ6jx/tYung2dOalujGWW5WKb52UhXR8rb60XyW/WbmoVBjOB1WMPkaSjEzw==", "dev": true, "requires": { "@types/estree": "^0.0.39" @@ -23912,9 +23912,9 @@ } }, "testcafe": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/testcafe/-/testcafe-1.9.2.tgz", - "integrity": "sha512-85du0zDvzFWleVqRTTsAr8Lo+3gn4yETs9qFZBIEufk6oN1fLzgv6Q14GeaH3/IaKi+/smv55umTce/OXX0mbA==", + "version": "1.8.6", + "resolved": "https://registry.npmjs.org/testcafe/-/testcafe-1.8.6.tgz", + "integrity": "sha512-h4cpvyBZqBXAxCqjaf3iswWFWJ4ZCtNP64+BniWj+bU0MZbTD64DOsyF92zQg09x+odQhU8Hm2zyCxKgAMCbtg==", "dev": true, "requires": { "@types/node": "^10.12.19", @@ -23941,12 +23941,10 @@ "dedent": "^0.4.0", "del": "^3.0.0", "device-specs": "^1.0.0", - "diff": "^4.0.2", "elegant-spinner": "^1.0.1", "emittery": "^0.4.1", "endpoint-utils": "^1.0.2", "error-stack-parser": "^1.3.6", - "execa": "^4.0.3", "globby": "^9.2.0", "graceful-fs": "^4.1.11", "graphlib": "^2.1.5", @@ -23981,8 +23979,8 @@ "sanitize-filename": "^1.6.0", "source-map-support": "^0.5.16", "strip-bom": "^2.0.0", - "testcafe-browser-tools": "2.0.13", - "testcafe-hammerhead": "17.1.15", + "testcafe-browser-tools": "2.0.12", + "testcafe-hammerhead": "17.1.2", "testcafe-legacy-api": "4.0.0", "testcafe-reporter-json": "^2.1.0", "testcafe-reporter-list": "^2.1.0", @@ -24002,9 +24000,9 @@ "dev": true }, "@types/node": { - "version": "10.17.29", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.29.tgz", - "integrity": "sha512-zLo9rjUeQ5+QVhOufDwrb3XKyso31fJBJnk9wUUQIBDExF/O4LryvpOfozfUaxgqifTnlt7FyqsAPXUq5yFZSA==", + "version": "10.17.30", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.30.tgz", + "integrity": "sha512-euU8QLX0ipj+5mOYa4ZqZoTv+53BY7yTg9I2ZIhDXgiI3M+0n4mdAt9TQCuvxVAgU179g8OsRLaBt0qEi0T6xA==", "dev": true }, "array-union": { @@ -24057,17 +24055,6 @@ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "dev": true }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -24092,31 +24079,6 @@ "path-type": "^3.0.0" } }, - "execa": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/execa/-/execa-4.0.3.tgz", - "integrity": "sha512-WFDXGHckXPWZX19t1kCsXzOpqX9LWYNqn4C+HqZlk/V0imTkzJZqf87ZBhvpHaftERYknpk0fjSylnXVlVgI0A==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.0", - "get-stream": "^5.0.0", - "human-signals": "^1.1.1", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.0", - "onetime": "^5.1.0", - "signal-exit": "^3.0.2", - "strip-final-newline": "^2.0.0" - }, - "dependencies": { - "is-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", - "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", - "dev": true - } - } - }, "fast-glob": { "version": "2.2.7", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.7.tgz", @@ -24342,27 +24304,12 @@ "integrity": "sha512-KpMNwdQsYz3O/SBS1qJ/o3sqUJ5wSb8gb0pul8CO0S56b9Y2ALm8zCfsjPXsqGFfoNBkDwZuZIAjhsZI03gYVQ==", "dev": true }, - "npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "requires": { - "path-key": "^3.0.0" - } - }, "parse5": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/parse5/-/parse5-1.5.1.tgz", "integrity": "sha1-m387DeMr543CQBsXVzzK8Pb1nZQ=", "dev": true }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, "pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", @@ -24407,21 +24354,6 @@ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, "slash": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", @@ -24461,22 +24393,13 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.7.tgz", "integrity": "sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw==", "dev": true - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } } } }, "testcafe-browser-tools": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/testcafe-browser-tools/-/testcafe-browser-tools-2.0.13.tgz", - "integrity": "sha512-r0AfCNsOJWXHAR+KADumfCffsH3LYoEbJXfmGOG47uEt1FBEw8cWTSWRBp5As+DaAmh9pi75P+ZF6K09WudM/g==", + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/testcafe-browser-tools/-/testcafe-browser-tools-2.0.12.tgz", + "integrity": "sha512-5oNNYlcZiDspqJB6L8CfI4vxjzkvARSZv3pa+JrFAoqYmEA3VPiAvzrn+P0zi0D5jEPkKngW2KTpq6r3GfdDNw==", "dev": true, "requires": { "array-find": "^1.0.0", @@ -24650,9 +24573,9 @@ } }, "testcafe-hammerhead": { - "version": "17.1.15", - "resolved": "https://registry.npmjs.org/testcafe-hammerhead/-/testcafe-hammerhead-17.1.15.tgz", - "integrity": "sha512-FvuaODbFUkoqyzH0OapiMO3/ISCB/v+0kKi0+5DhcIz1tRBishzyfLbHFyKXUf6rm0IhGJlME93uKFOM9NNOMw==", + "version": "17.1.2", + "resolved": "https://registry.npmjs.org/testcafe-hammerhead/-/testcafe-hammerhead-17.1.2.tgz", + "integrity": "sha512-WkTRrZoMYIZkB0NGiT+xrlD71hcMDX/a34iHNdrUBwcw9o/xi7ym4YzyZO0LXrG5b1pzuLS3ll/o5OqkhfRZnw==", "dev": true, "requires": { "acorn-hammerhead": "^0.3.0", @@ -24662,18 +24585,18 @@ "crypto-md5": "^1.0.0", "css": "2.2.3", "debug": "4.1.1", - "esotope-hammerhead": "0.5.5", + "esotope-hammerhead": "0.5.3", "iconv-lite": "0.5.1", - "lodash": "^4.17.19", + "lodash": "^4.17.13", "lru-cache": "2.6.3", "match-url-wildcard": "0.0.4", "merge-stream": "^1.0.1", "mime": "~1.4.1", "mustache": "^2.1.1", - "nanoid": "^3.1.12", + "nanoid": "^0.2.2", "os-family": "^1.0.0", "parse5": "2.2.3", - "pinkie": "2.0.4", + "pinkie": "1.0.0", "read-file-relative": "^1.2.0", "semver": "5.5.0", "tough-cookie": "2.3.3", @@ -24733,9 +24656,9 @@ "dev": true }, "nanoid": { - "version": "3.1.12", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.12.tgz", - "integrity": "sha512-1qstj9z5+x491jfiC4Nelk+f8XBad7LN20PmyWINJEMRSf3wcAjAWysw1qaA8z6NSKe2sjq1hRSDpBH5paCb6A==", + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-0.2.2.tgz", + "integrity": "sha512-GHoRrvNEKiwdkwQ/enKL8AhQkkrBC/2KxMZkDvQzp8OtkpX8ZAmoYJWFVl7l8F2+HcEJUfdg21Ab2wXXfrvACQ==", "dev": true }, "parse5": { @@ -24744,6 +24667,12 @@ "integrity": "sha1-DE/EHBAAxea5PUiwP4CDg3g06fY=", "dev": true }, + "pinkie": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-1.0.0.tgz", + "integrity": "sha1-Wkfyi6EBXQIBvae/DzWOR77Ix+Q=", + "dev": true + }, "punycode": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", diff --git a/package.json b/package.json index b1d12db5be..f1ab498110 100644 --- a/package.json +++ b/package.json @@ -33,8 +33,8 @@ "test": "npm run build-backend && npm run test-backend && npm run test-frontend", "test-e2e-build": "npm run build-backend && npm run build-frontend-dev", "test-run": "concurrently --success last --kill-others \"mockpass\" \"maildev\" \"node dist/backend/server.js\" \"localstack start --host\" \"node ./tests/mock-webhook-server.js\"", - "testcafe-full-env": "testcafe -c 3 chrome:headless ./tests/end-to-end --test-meta full-env=true --app \"npm run test-run\" --app-init-delay 10000", - "testcafe-basic-env": "testcafe -c 3 chrome:headless ./tests/end-to-end --test-meta basic-env=true --app \"npm run test-run\" --app-init-delay 10000", + "testcafe-full-env": "testcafe --skip-js-errors -c 3 chrome:headless ./tests/end-to-end --test-meta full-env=true --app \"npm run test-run\" --app-init-delay 10000", + "testcafe-basic-env": "testcafe --skip-js-errors -c 3 chrome:headless ./tests/end-to-end --test-meta basic-env=true --app \"npm run test-run\" --app-init-delay 10000", "download-binary": "node tests/end-to-end/helpers/get-mongo-binary.js", "test-e2e-full": "env-cmd -f tests/.test-full-env --use-shell \"npm run download-binary && npm run testcafe-full-env\"", "test-e2e-basic": "env-cmd -f tests/.test-basic-env --use-shell \"npm run download-binary && npm run testcafe-basic-env\"", @@ -233,7 +233,7 @@ "stylelint-prettier": "^1.1.2", "supertest": "^3.3.0", "terser-webpack-plugin": "^1.2.3", - "testcafe": "^1.9.1", + "testcafe": "^1.8.6", "ts-jest": "^26.1.4", "ts-loader": "^7.0.5", "ts-mock-imports": "^1.3.0", diff --git a/tests/end-to-end/email-submission.e2e.js b/tests/end-to-end/email-submission.e2e.js index 60a4c46aae..f49c4d3228 100644 --- a/tests/end-to-end/email-submission.e2e.js +++ b/tests/end-to-end/email-submission.e2e.js @@ -65,75 +65,60 @@ fixture('Email mode submissions') // the form and reach the end page. // Form with all basic field types -test - .meta('basic-env', 'true') - .meta('full-env', 'true') - .before(async (t) => { - const formData = await getDefaultFormOptions() - formData.formFields = cloneDeep(allFields) - t.ctx.formData = formData - })('Create and submit form with all form fields', async (t) => { +test.meta('basic-env', 'true').before(async (t) => { + const formData = await getDefaultFormOptions() + formData.formFields = cloneDeep(allFields) + t.ctx.formData = formData +})('Create and submit form with all form fields', async (t) => { t.ctx.form = await createForm(t, t.ctx.formData, Form, captchaEnabled) await verifySubmissionE2e(t, t.ctx.form, t.ctx.formData) }) // Form where all basic field types are hidden by logic -test - .meta('basic-env', 'true') - .meta('full-env', 'true') - .before(async (t) => { - const formData = await getDefaultFormOptions() - formData.formFields = cloneDeep(hiddenFieldsData) - formData.logicData = cloneDeep(hiddenFieldsLogicData) - t.ctx.formData = formData - })('Create and submit form with all field types hidden', async (t) => { +test.meta('basic-env', 'true').before(async (t) => { + const formData = await getDefaultFormOptions() + formData.formFields = cloneDeep(hiddenFieldsData) + formData.logicData = cloneDeep(hiddenFieldsLogicData) + t.ctx.formData = formData +})('Create and submit form with all field types hidden', async (t) => { t.ctx.form = await createForm(t, t.ctx.formData, Form, captchaEnabled) await verifySubmissionE2e(t, t.ctx.form, t.ctx.formData) }) // Form where all fields are optional and no field is answered -test - .meta('basic-env', 'true') - .meta('full-env', 'true') - .before(async (t) => { - const formData = await getDefaultFormOptions() - formData.formFields = allFields.map((field) => { - return getBlankVersion(getOptionalVersion(field)) - }) - t.ctx.formData = formData - })('Create and submit form with all field types optional', async (t) => { +test.meta('basic-env', 'true').before(async (t) => { + const formData = await getDefaultFormOptions() + formData.formFields = allFields.map((field) => { + return getBlankVersion(getOptionalVersion(field)) + }) + t.ctx.formData = formData +})('Create and submit form with all field types optional', async (t) => { t.ctx.form = await createForm(t, t.ctx.formData, Form, captchaEnabled) await verifySubmissionE2e(t, t.ctx.form, t.ctx.formData) }) // Form with three attachments to test de-duplication of attachment names -test - .meta('basic-env', 'true') - .meta('full-env', 'true') - .before(async (t) => { - const formData = await getDefaultFormOptions() - formData.formFields = cloneDeep(tripleAttachment) - t.ctx.formData = formData - })('Create and submit form with identical attachment names', async (t) => { +test.meta('basic-env', 'true').before(async (t) => { + const formData = await getDefaultFormOptions() + formData.formFields = cloneDeep(tripleAttachment) + t.ctx.formData = formData +})('Create and submit form with identical attachment names', async (t) => { t.ctx.form = await createForm(t, t.ctx.formData, Form, captchaEnabled) await verifySubmissionE2e(t, t.ctx.form, t.ctx.formData) }) // Form with optional attachment in between mandatory ones -test - .meta('basic-env', 'true') - .meta('full-env', 'true') - .before(async (t) => { - const formData = await getDefaultFormOptions() - formData.formFields = cloneDeep(tripleAttachment) - // Modify middle attachment field to be optional and unfilled - formData.formFields[1] = getBlankVersion( - getOptionalVersion(formData.formFields[1]), - ) - // Modify first filename to account for middle field left blank - formData.formFields[0].val = '1-test-att.txt' - t.ctx.formData = formData - })( +test.meta('basic-env', 'true').before(async (t) => { + const formData = await getDefaultFormOptions() + formData.formFields = cloneDeep(tripleAttachment) + // Modify middle attachment field to be optional and unfilled + formData.formFields[1] = getBlankVersion( + getOptionalVersion(formData.formFields[1]), + ) + // Modify first filename to account for middle field left blank + formData.formFields[0].val = '1-test-att.txt' + t.ctx.formData = formData +})( 'Create and submit form with optional and required attachments', async (t) => { t.ctx.form = await createForm(t, t.ctx.formData, Form, captchaEnabled) @@ -142,15 +127,12 @@ test ) // Form where submission is prevented using chained logic -test - .meta('basic-env', 'true') - .meta('full-env', 'true') - .before(async (t) => { - const formData = await getDefaultFormOptions() - formData.formFields = cloneDeep(chainDisabled.fields) - formData.logicData = cloneDeep(chainDisabled.logicData) - t.ctx.formData = formData - })('Create and disable form with chained logic', async (t) => { +test.meta('basic-env', 'true').before(async (t) => { + const formData = await getDefaultFormOptions() + formData.formFields = cloneDeep(chainDisabled.fields) + formData.logicData = cloneDeep(chainDisabled.logicData) + t.ctx.formData = formData +})('Create and disable form with chained logic', async (t) => { t.ctx.form = await createForm(t, t.ctx.formData, Form, captchaEnabled) await verifySubmissionDisabled( t, @@ -160,15 +142,12 @@ test ) }) -test - .meta('basic-env', 'true') - .meta('full-env', 'true') - .before(async (t) => { - const formData = await getDefaultFormOptions() - t.ctx.formData = formData - // cloneDeep in case other tests in future import and modify templateFields - t.ctx.formData.formFields = cloneDeep(templateFields) - })('Create a form from COVID19 Templates', async (t) => { +test.meta('basic-env', 'true').before(async (t) => { + const formData = await getDefaultFormOptions() + t.ctx.formData = formData + // cloneDeep in case other tests in future import and modify templateFields + t.ctx.formData.formFields = cloneDeep(templateFields) +})('Create a form from COVID19 Templates', async (t) => { t.ctx.form = await createFormFromTemplate( t, t.ctx.formData, diff --git a/tests/end-to-end/encrypt-submission.e2e.js b/tests/end-to-end/encrypt-submission.e2e.js index d3abe457f1..46f71abeef 100644 --- a/tests/end-to-end/encrypt-submission.e2e.js +++ b/tests/end-to-end/encrypt-submission.e2e.js @@ -75,57 +75,45 @@ fixture('Storage mode submissions') }) // Form with all field types available in storage mode -test - .meta('basic-env', 'true') - .meta('full-env', 'true') - .before(async (t) => { - const formData = await getDefaultFormOptions() - formData.formFields = cloneDeep(allFields) - t.ctx.formData = formData - })('Create and submit form with all field types', async (t) => { +test.meta('basic-env', 'true').before(async (t) => { + const formData = await getDefaultFormOptions() + formData.formFields = cloneDeep(allFields) + t.ctx.formData = formData +})('Create and submit form with all field types', async (t) => { t.ctx.form = await createForm(t, t.ctx.formData, Form, captchaEnabled) await verifySubmissionE2e(t, t.ctx.form, t.ctx.formData) }) // Form where all basic field types are hidden by logic -test - .meta('basic-env', 'true') - .meta('full-env', 'true') - .before(async (t) => { - const formData = await getDefaultFormOptions() - formData.formFields = cloneDeep(hiddenFieldsData) - formData.logicData = cloneDeep(hiddenFieldsLogicData) - t.ctx.formData = formData - })('Create and submit form with all field types hidden', async (t) => { +test.meta('basic-env', 'true').before(async (t) => { + const formData = await getDefaultFormOptions() + formData.formFields = cloneDeep(hiddenFieldsData) + formData.logicData = cloneDeep(hiddenFieldsLogicData) + t.ctx.formData = formData +})('Create and submit form with all field types hidden', async (t) => { t.ctx.form = await createForm(t, t.ctx.formData, Form, captchaEnabled) await verifySubmissionE2e(t, t.ctx.form, t.ctx.formData) }) // Form where all fields are optional and no field is answered -test - .meta('basic-env', 'true') - .meta('full-env', 'true') - .before(async (t) => { - const formData = await getDefaultFormOptions() - formData.formFields = allFields.map((field) => { - return getBlankVersion(getOptionalVersion(field)) - }) - t.ctx.formData = formData - })('Create and submit form with all field types optional', async (t) => { +test.meta('basic-env', 'true').before(async (t) => { + const formData = await getDefaultFormOptions() + formData.formFields = allFields.map((field) => { + return getBlankVersion(getOptionalVersion(field)) + }) + t.ctx.formData = formData +})('Create and submit form with all field types optional', async (t) => { t.ctx.form = await createForm(t, t.ctx.formData, Form, captchaEnabled) await verifySubmissionE2e(t, t.ctx.form, t.ctx.formData) }) // Form where submission is prevented using chained logic -test - .meta('basic-env', 'true') - .meta('full-env', 'true') - .before(async (t) => { - const formData = await getDefaultFormOptions() - formData.formFields = cloneDeep(chainDisabled.fields) - formData.logicData = cloneDeep(chainDisabled.logicData) - t.ctx.formData = formData - })('Create and disable form with chained logic', async (t) => { +test.meta('basic-env', 'true').before(async (t) => { + const formData = await getDefaultFormOptions() + formData.formFields = cloneDeep(chainDisabled.fields) + formData.logicData = cloneDeep(chainDisabled.logicData) + t.ctx.formData = formData +})('Create and disable form with chained logic', async (t) => { t.ctx.form = await createForm(t, t.ctx.formData, Form, captchaEnabled) await verifySubmissionDisabled( t, diff --git a/tests/end-to-end/login.e2e.js b/tests/end-to-end/login.e2e.js index ed4aaacfb0..7c7e4c0601 100644 --- a/tests/end-to-end/login.e2e.js +++ b/tests/end-to-end/login.e2e.js @@ -62,7 +62,6 @@ test.meta('basic-env', 'true').meta('full-env', 'true')( test .meta('basic-env', 'true') - .meta('full-env', 'true') .before(async (t) => { t.ctx.user = await createUser('existinguser@data.gov.sg') }) @@ -87,7 +86,6 @@ test test .meta('basic-env', 'true') - .meta('full-env', 'true') .before((t) => { t.ctx.email = 'newuser@data.gov.sg' }) @@ -111,7 +109,6 @@ test test .meta('basic-env', 'true') - .meta('full-env', 'true') .before(async (t) => { t.ctx.user = await createUser('preventuseremail@data.gov.sg') }) @@ -144,7 +141,6 @@ test test .meta('basic-env', 'true') - .meta('full-env', 'true') .before(async (t) => { t.ctx.user = await createUser('resenduseremail@data.gov.sg') }) @@ -179,7 +175,6 @@ test test .meta('basic-env', 'true') - .meta('full-env', 'true') .before(async (t) => { t.ctx.user = await createUser('logoutuseremail@data.gov.sg') }) From df4cfc43f94a2d3d12af0fdfee89a584d8e13b20 Mon Sep 17 00:00:00 2001 From: Yuan Ruo Date: Sat, 12 Sep 2020 20:51:36 +0800 Subject: [PATCH 08/18] feat(changelog): autogenerate CHANGELOG.md from conventional commits (#306) --- CHANGELOG.md | 190 ++++++++++++++++++++++++++++++++++++++++++++++ package-lock.json | 73 ++++++++++++++++++ package.json | 4 +- 3 files changed, 266 insertions(+), 1 deletion(-) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000000..9f11895fac --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,190 @@ +### Changelog + +All notable changes to this project will be documented in this file. Dates are displayed in UTC. + +Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). + +#### [v4.34.0](https://github.com/opengovsg/formsg/compare/v4.33.0...v4.34.0) + +> 8 September 2020 + +- refactor: migrate /auth endpoint handling to Typescript, Domain Driven Design [`#215`](https://github.com/opengovsg/formsg/pull/215) +- chore(deps-dev): bump stylelint-config-prettier from 8.0.1 to 8.0.2 [`#280`](https://github.com/opengovsg/formsg/pull/280) +- fix: upgrade mongoose from 5.9.19 to 5.10.0 [`#289`](https://github.com/opengovsg/formsg/pull/289) +- revert: reintroduce convict [`#287`](https://github.com/opengovsg/formsg/pull/287) +- revert(convict): "refactor: use convict for configuration (#190)" [`#285`](https://github.com/opengovsg/formsg/pull/285) +- chore(deps-dev): bump @typescript-eslint/eslint-plugin and @typescript-eslint/parser [`#246`](https://github.com/opengovsg/formsg/pull/246) +- feat: verified sms modal [`#274`](https://github.com/opengovsg/formsg/pull/274) +- feat: add try-catch block to custom logger for js files [`#267`](https://github.com/opengovsg/formsg/pull/267) +- fix: fix invocations of logger that does not adhere to expected shape [`#273`](https://github.com/opengovsg/formsg/pull/273) +- chore(deps-dev): bump @babel/core from 7.10.2 to 7.11.5 [`#270`](https://github.com/opengovsg/formsg/pull/270) +- feat: upgrade localstack version [`#275`](https://github.com/opengovsg/formsg/pull/275) +- chore(deps-dev): bump testcafe from 1.8.6 to 1.9.1 [`#271`](https://github.com/opengovsg/formsg/pull/271) +- chore(deps-dev): bump @babel/preset-env from 7.11.0 to 7.11.5 [`#268`](https://github.com/opengovsg/formsg/pull/268) +- refactor: use convict for configuration [`#190`](https://github.com/opengovsg/formsg/pull/190) +- fix: revert changes to configureAws [`#266`](https://github.com/opengovsg/formsg/pull/266) +- refactor: remove redundant feature factory [`#261`](https://github.com/opengovsg/formsg/pull/261) +- chore: remove form_field.isFutureOnly key [`#235`](https://github.com/opengovsg/formsg/pull/235) +- refactor: remove unused Nodemailer env vars [`#253`](https://github.com/opengovsg/formsg/pull/253) +- feat: upgrade Sentry SDK [`#254`](https://github.com/opengovsg/formsg/pull/254) +- fix(deps): bump lodash from 4.17.19 to 4.17.20 [`#259`](https://github.com/opengovsg/formsg/pull/259) +- chore(deps-dev): bump eslint from 7.7.0 to 7.8.1 [`#258`](https://github.com/opengovsg/formsg/pull/258) +- chore(deps-dev): bump jest from 26.2.2 to 26.4.2 [`#257`](https://github.com/opengovsg/formsg/pull/257) +- refactor: typify webhook and migrate from middleware pattern [`#251`](https://github.com/opengovsg/formsg/pull/251) +- fix(dev): fix Localstack yet again [`#252`](https://github.com/opengovsg/formsg/pull/252) +- chore(deps-dev): bump prettier from 2.0.5 to 2.1.1 [`#249`](https://github.com/opengovsg/formsg/pull/249) +- fix: prevent discriminated models from being created before their base model [`#244`](https://github.com/opengovsg/formsg/pull/244) +- fix(deps): remove ajv as dependency [`#248`](https://github.com/opengovsg/formsg/pull/248) +- chore(deps-dev): bump @typescript-eslint/parser from 3.3.0 to 3.10.1 [`#247`](https://github.com/opengovsg/formsg/pull/247) +- feat: merge Release 4.33.0 into develop [`#245`](https://github.com/opengovsg/formsg/pull/245) +- Bump version [`830211a`](https://github.com/opengovsg/formsg/commit/830211a541ff55ccd2fa1c74dc2ec4bfc29839ef) + +#### [v4.33.0](https://github.com/opengovsg/formsg/compare/v4.32.1...v4.33.0) + +> 1 September 2020 + +- fix: use original questionCount [`#242`](https://github.com/opengovsg/formsg/pull/242) +- fix: correct left margin in acknowledgment error when activating storage mode form [`#240`](https://github.com/opengovsg/formsg/pull/240) +- feat: log more info about critical bounces [`#237`](https://github.com/opengovsg/formsg/pull/237) +- fix: remove filetype from permission levels imports [`#236`](https://github.com/opengovsg/formsg/pull/236) +- fix(deps): bump http-status-codes from 1.4.0 to 2.1.2 [`#229`](https://github.com/opengovsg/formsg/pull/229) +- refactor: use express router for modules [`#204`](https://github.com/opengovsg/formsg/pull/204) +- chore(deps-dev): bump @types/helmet from 0.0.47 to 0.0.48 [`#232`](https://github.com/opengovsg/formsg/pull/232) +- refactor(utils/attachment): typescriptify [`#166`](https://github.com/opengovsg/formsg/pull/166) +- fix(deps): bump validator from 11.1.0 to 13.1.1 [`#209`](https://github.com/opengovsg/formsg/pull/209) +- refactor: typify utils [`#171`](https://github.com/opengovsg/formsg/pull/171) +- feat: mailto option after form activation [`#213`](https://github.com/opengovsg/formsg/pull/213) +- fix(deps): bump axios from 0.19.2 to 0.20.0 [`#218`](https://github.com/opengovsg/formsg/pull/218) +- chore(deps-dev): bump @types/mongoose from 5.7.25 to 5.7.36 [`#230`](https://github.com/opengovsg/formsg/pull/230) +- feat: Bulk download of storage mode attachments in a zip file [`#141`](https://github.com/opengovsg/formsg/pull/141) +- feat: merge release v4.32.1 back into develop branch [`#226`](https://github.com/opengovsg/formsg/pull/226) +- fix(deps): bump opossum from 5.0.0 to 5.0.1 [`#221`](https://github.com/opengovsg/formsg/pull/221) +- chore(deps-dev): bump eslint from 6.8.0 to 7.7.0 [`#220`](https://github.com/opengovsg/formsg/pull/220) +- feat: standardize logger format and output [`#211`](https://github.com/opengovsg/formsg/pull/211) +- fix: fix linting not working on frontend code [`#217`](https://github.com/opengovsg/formsg/pull/217) +- fix: pass missing $state param into EditContactNumberModalController [`#216`](https://github.com/opengovsg/formsg/pull/216) +- feat: add Emergency Contact feature frontend [`#142`](https://github.com/opengovsg/formsg/pull/142) +- refactor: convert webhook service to Typescript [`#83`](https://github.com/opengovsg/formsg/pull/83) +- chore(deps-dev): bump sinon from 6.3.5 to 9.0.3 [`#207`](https://github.com/opengovsg/formsg/pull/207) +- feat: Share form secret keys across browser tabs using BroadcastChannel [`#203`](https://github.com/opengovsg/formsg/pull/203) +- chore: merge Release v4.32.0 into develop branch [`#205`](https://github.com/opengovsg/formsg/pull/205) +- Introduce minimum test coverage thresholds, coveralls.io for threshold reporting and repo badge [`#185`](https://github.com/opengovsg/formsg/pull/185) +- feat: MailService#sendNodeMail invocations to retry on 4xx errors(#227) [`61d5103`](https://github.com/opengovsg/formsg/commit/61d510312affdea6e971147dd547a6f5449b270b) +- build: bump version to 4.33.0 [`6c0951e`](https://github.com/opengovsg/formsg/commit/6c0951e877e498751c94a539ce93b03eb0ff9d53) + +#### [v4.32.1](https://github.com/opengovsg/formsg/compare/v4.32.0...v4.32.1) + +> 27 August 2020 + +- chore: bump version to v4.32.1 [`0bf07cf`](https://github.com/opengovsg/formsg/commit/0bf07cfc9b804a2e602a096032065d73805acfea) +- fix: split mail by semicolon in addition to comma when validating [`824380e`](https://github.com/opengovsg/formsg/commit/824380ef2a015674b5931cc3f9516036eb80a917) + +#### [v4.32.0](https://github.com/opengovsg/formsg/compare/v4.30.4...v4.32.0) + +> 25 August 2020 + +- fix: shift userEmail retrieval to GA service [`#192`](https://github.com/opengovsg/formsg/pull/192) +- chore(deps-dev): bump @opengovsg/mockpass from 2.2.0 to 2.4.6 [`#198`](https://github.com/opengovsg/formsg/pull/198) +- feat: remove beta field validations [`#194`](https://github.com/opengovsg/formsg/pull/194) +- fix(deps): bump uid-generator from 1.0.0 to 2.0.0 [`#187`](https://github.com/opengovsg/formsg/pull/187) +- fix(deps): bump puppeteer-core from 4.0.0 to 5.2.1 [`#188`](https://github.com/opengovsg/formsg/pull/188) +- chore(deps-dev): bump @typescript-eslint/eslint-plugin [`#197`](https://github.com/opengovsg/formsg/pull/197) +- feat: add core ApplicationError for express app [`#195`](https://github.com/opengovsg/formsg/pull/195) +- chore(deps-dev): bump typescript to 4.0.2 [`#196`](https://github.com/opengovsg/formsg/pull/196) +- fix(deps): bump font-awesome from 4.6.1 to 4.7.0 [`#186`](https://github.com/opengovsg/formsg/pull/186) +- feat: migrate `util/response` to new Submission module (service, utils, etc) [`#176`](https://github.com/opengovsg/formsg/pull/176) +- feat: log form ID in GA event labels [`#154`](https://github.com/opengovsg/formsg/pull/154) +- refactor(verification): convert to module and typescriptify [`#172`](https://github.com/opengovsg/formsg/pull/172) +- feat: support &`;'" in form title [`#156`](https://github.com/opengovsg/formsg/pull/156) +- fix: run npm audit fix to resolve security issues with minimist dependency in the selectize package [`#181`](https://github.com/opengovsg/formsg/pull/181) +- chore(deps-dev): bump jasmine from 3.5.0 to 3.6.1 [`#158`](https://github.com/opengovsg/formsg/pull/158) +- chore(deps-dev): bump env-cmd from 9.0.3 to 10.1.0 [`#133`](https://github.com/opengovsg/formsg/pull/133) +- feat: mailto link for secret key [`#150`](https://github.com/opengovsg/formsg/pull/150) +- fix: enable forceDelivery on twilio message sending [`#178`](https://github.com/opengovsg/formsg/pull/178) +- feat: increase breaker window time and add minimum volume threshold [`#165`](https://github.com/opengovsg/formsg/pull/165) +- refactor: migrate encryption util to typescript [`#167`](https://github.com/opengovsg/formsg/pull/167) +- refactor: delete render promise util [`#168`](https://github.com/opengovsg/formsg/pull/168) +- refactor: convert date util to typescript [`#161`](https://github.com/opengovsg/formsg/pull/161) +- feat: create bounce collection and alarms [`#131`](https://github.com/opengovsg/formsg/pull/131) +- [develop] Release v4.31.0 [`#155`](https://github.com/opengovsg/formsg/pull/155) +- refactor: convert MailService to a class based Typescript implementation [`#76`](https://github.com/opengovsg/formsg/pull/76) +- fix(deps): bump aws-sdk from 2.699.0 to 2.734.0 [`#146`](https://github.com/opengovsg/formsg/pull/146) +- fix(deps): bump node-cache from 5.1.1 to 5.1.2 [`#145`](https://github.com/opengovsg/formsg/pull/145) +- feat: include user ip address when sending otp [`#147`](https://github.com/opengovsg/formsg/pull/147) +- chore(deps-dev): bump htmlhint from 0.11.0 to 0.14.1 [`#116`](https://github.com/opengovsg/formsg/pull/116) +- fix(deps): bump angular-* dependency packages from 1.7.9 to 1.8.0 [`#108`](https://github.com/opengovsg/formsg/pull/108) +- feat: log IP, submissionId and formId together [`#130`](https://github.com/opengovsg/formsg/pull/130) +- fix(deps): bump crypto-js from 3.3.0 to 4.0.0 [`#110`](https://github.com/opengovsg/formsg/pull/110) +- [develop] Release 4.30.4 [`#138`](https://github.com/opengovsg/formsg/pull/138) +- fix(deps): bump express-winston from 4.0.3 to 4.0.5 [`#109`](https://github.com/opengovsg/formsg/pull/109) +- chore: add --watch flag back to build-frontend-dev script [`#128`](https://github.com/opengovsg/formsg/pull/128) +- docs: create trouble shooting guide [`#119`](https://github.com/opengovsg/formsg/pull/119) +- chore: Merge release 4.30.3 into develop [`#127`](https://github.com/opengovsg/formsg/pull/127) +- fix(deps): bump bcrypt from 3.0.8 to 5.0.0 [`#88`](https://github.com/opengovsg/formsg/pull/88) +- fix(deps): bump nodemailer from 6.4.10 to 6.4.11 [`#117`](https://github.com/opengovsg/formsg/pull/117) +- tests: fix flakiness and migrate remaining mongoose model tests to Typescript [`#122`](https://github.com/opengovsg/formsg/pull/122) +- chore: bump version to v4.32.0 [`aa34114`](https://github.com/opengovsg/formsg/commit/aa341141d47a806ece786fcccbe0faef0945ccfc) + +#### [v4.30.4](https://github.com/opengovsg/formsg/compare/v4.30.3...v4.30.4) + +> 14 August 2020 + +- Revert "feat: Filter Storage Mode Responses by Submission Id (#71)" [`ffe4218`](https://github.com/opengovsg/formsg/commit/ffe42187130d1d4147f22b37687992062af7d7c6) +- chore: bump version to 4.30.4 [`35d68de`](https://github.com/opengovsg/formsg/commit/35d68debce62bd86f001724608bbc59bce483aa3) + +#### [v4.30.3](https://github.com/opengovsg/formsg/compare/v4.30.2...v4.30.3) + +> 12 August 2020 + +- fix: Revert url loader [`#125`](https://github.com/opengovsg/formsg/pull/125) +- feat: show error upon FileReader failure [`#121`](https://github.com/opengovsg/formsg/pull/121) +- [develop] Release 4.30.2 [`#114`](https://github.com/opengovsg/formsg/pull/114) +- refactor: remove unused mongoTimestamp plugin [`#120`](https://github.com/opengovsg/formsg/pull/120) +- docs: updating contributing, readme, license for open source [`#86`](https://github.com/opengovsg/formsg/pull/86) +- chore: setup jest for use with Typescript tests [`#106`](https://github.com/opengovsg/formsg/pull/106) +- fix: fix myInfoError typo [`#115`](https://github.com/opengovsg/formsg/pull/115) +- docs(readme): point build status image to new repo [`#112`](https://github.com/opengovsg/formsg/pull/112) +- feat: add getQuestion instance method to form field schema [`#103`](https://github.com/opengovsg/formsg/pull/103) +- chore(deps-dev): bump webpack-cli from 3.3.11 to 3.3.12 [`#105`](https://github.com/opengovsg/formsg/pull/105) +- feat: Filter Storage Mode Responses by Submission Id [`#71`](https://github.com/opengovsg/formsg/pull/71) +- fix(deps): bump angular-cookies from 1.7.9 to 1.8.0 [`#104`](https://github.com/opengovsg/formsg/pull/104) +- chore(deps-dev): bump angular from 1.7.9 to 1.8.0 [`#10`](https://github.com/opengovsg/formsg/pull/10) +- docs: updated docs for open source [`#95`](https://github.com/opengovsg/formsg/pull/95) +- test: add tests for verification model [`#99`](https://github.com/opengovsg/formsg/pull/99) +- chore(deps-dev): bump url-loader from 1.1.2 to 4.1.0 [`#90`](https://github.com/opengovsg/formsg/pull/90) +- refactor: migrate `utils/request` to Typescript [`#98`](https://github.com/opengovsg/formsg/pull/98) +- fix: phone validation now only accepts 8 digit #s starting with 8 or 9 [`#101`](https://github.com/opengovsg/formsg/pull/101) +- [develop] Release 4.30.1 [`#80`](https://github.com/opengovsg/formsg/pull/80) +- [develop] Release 4.30.0 [`#79`](https://github.com/opengovsg/formsg/pull/79) +- fix(deps): bump uuid from 8.2.0 to 8.3.0 [`#96`](https://github.com/opengovsg/formsg/pull/96) +- chore(deps-dev): bump jasmine-spec-reporter from 4.2.1 to 5.0.2 [`#89`](https://github.com/opengovsg/formsg/pull/89) +- chore(deps-dev): bump @babel/preset-env from 7.10.2 to 7.11.0 [`#87`](https://github.com/opengovsg/formsg/pull/87) +- fix(deps): bump lodash from 4.17.15 to 4.17.19 [`#91`](https://github.com/opengovsg/formsg/pull/91) +- refactor(logic): typescriptify [`#81`](https://github.com/opengovsg/formsg/pull/81) +- fix: update dependabot config to use v2 syntax [`#85`](https://github.com/opengovsg/formsg/pull/85) +- chore: add dependabot.yml [`#82`](https://github.com/opengovsg/formsg/pull/82) +- feat: remove allowSms beta flag [`#73`](https://github.com/opengovsg/formsg/pull/73) +- feat(FormSchema): Document new indexes for form dashboard [`#77`](https://github.com/opengovsg/formsg/pull/77) +- refactor: add _id to all model interfaces [`#75`](https://github.com/opengovsg/formsg/pull/75) +- Bump version to 4.30.3 [`4e97a48`](https://github.com/opengovsg/formsg/commit/4e97a48e52eefa621b1ef84f1d991d90e96a57b4) + +#### [v4.30.2](https://github.com/opengovsg/formsg/compare/v4.30.1...v4.30.2) + +> 5 August 2020 + +- fix: get env vars directly, not from config [`5397c06`](https://github.com/opengovsg/formsg/commit/5397c06107f52d7d3d5032ce6507daeb9d0604cf) +- fix: add trailing / only for attachments [`1b9d1c0`](https://github.com/opengovsg/formsg/commit/1b9d1c045c4f250533452f8a0448b37ebd6346f7) +- chore: bump version to 4.30.2 [`f623c1a`](https://github.com/opengovsg/formsg/commit/f623c1abb8bd85dd06d36994c783ed0409cd8a5d) + +#### v4.30.1 + +> 4 August 2020 + +- fix: change enum to uppercase [`#72`](https://github.com/opengovsg/formsg/pull/72) +- fix: activation modal width change when activation succeeds [`#69`](https://github.com/opengovsg/formsg/pull/69) +- Extend e2e [`#65`](https://github.com/opengovsg/formsg/pull/65) +- chore: update documentation for banner environment variables [`#3`](https://github.com/opengovsg/formsg/pull/3) +- fix: add fake aws credentials [`#64`](https://github.com/opengovsg/formsg/pull/64) +- Initial commit [`203e62d`](https://github.com/opengovsg/formsg/commit/203e62dfc346cef9fb893c7b84c481b762216dea) +- chore: bump version to 4.30.1 [`9ea64ac`](https://github.com/opengovsg/formsg/commit/9ea64ac0c19df843839357223abda0d449603704) +- chore: bump version to 4.30.0 [`bf0cca8`](https://github.com/opengovsg/formsg/commit/bf0cca862f9c25b0984986aae295b42938c81884) diff --git a/package-lock.json b/package-lock.json index ba5193f005..ab7e1c30af 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5768,6 +5768,34 @@ "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", "dev": true }, + "auto-changelog": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/auto-changelog/-/auto-changelog-2.2.0.tgz", + "integrity": "sha512-RBY0hhVNXstggOQL0SyUaCfSiVD11CVXEHvDwB+mEt9UnhXPqhdpQ7nIVGDEog7JopTdYbydULLLt6v//qrWjw==", + "dev": true, + "requires": { + "commander": "^5.0.0", + "handlebars": "^4.7.3", + "lodash.uniqby": "^4.7.0", + "node-fetch": "^2.6.0", + "parse-github-url": "^1.0.2", + "semver": "^6.3.0" + }, + "dependencies": { + "commander": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", + "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, "autoprefixer": { "version": "9.8.0", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.8.0.tgz", @@ -12756,6 +12784,33 @@ "integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=", "dev": true }, + "handlebars": { + "version": "4.7.6", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.6.tgz", + "integrity": "sha512-1f2BACcBfiwAfStCKZNrUCgqNZkGsAT7UM3kkYtXuLo0KnaVfjKOyf7PRzB6++aK9STyT1Pd2ZCPe3EGOXleXA==", + "dev": true, + "requires": { + "minimist": "^1.2.5", + "neo-async": "^2.6.0", + "source-map": "^0.6.1", + "uglify-js": "^3.1.4", + "wordwrap": "^1.0.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + } + } + }, "har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", @@ -17577,6 +17632,12 @@ "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", "dev": true }, + "lodash.uniqby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz", + "integrity": "sha1-2ZwHpmnp5tJOE2Lf4mbGdhavEwI=", + "dev": true + }, "log-driver": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.7.tgz", @@ -19230,6 +19291,12 @@ "clone": "2.x" } }, + "node-fetch": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", + "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==", + "dev": true + }, "node-forge": { "version": "0.8.5", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.8.5.tgz", @@ -20020,6 +20087,12 @@ "is-hexadecimal": "^1.0.0" } }, + "parse-github-url": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-github-url/-/parse-github-url-1.0.2.tgz", + "integrity": "sha512-kgBf6avCbO3Cn6+RnzRGLkUsv4ZVqv/VfAYkRsyBcgkshNvVBkRn1FEZcW0Jb+npXQWm2vHPnnOqFteZxRRGNw==", + "dev": true + }, "parse-glob": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", diff --git a/package.json b/package.json index f1ab498110..6b44954dcb 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,8 @@ "lint-style": "stylelint '*/**/*.css' --quiet --fix", "lint-html": "htmlhint && prettier --write './src/public/**/*.html' --ignore-path './dist/**' --loglevel silent", "lint": "npm run lint-code && npm run lint-style && npm run lint-html", - "lint-ci": "eslint src/ --quiet && stylelint '*/**/*.css' --quiet && htmlhint && prettier --c './src/public/**/*.html' --ignore-path './dist/**'" + "lint-ci": "eslint src/ --quiet && stylelint '*/**/*.css' --quiet && htmlhint && prettier --c './src/public/**/*.html' --ignore-path './dist/**'", + "version": "auto-changelog -p && git add CHANGELOG.md" }, "husky": { "hooks": { @@ -193,6 +194,7 @@ "@types/validator": "^13.0.0", "@typescript-eslint/eslint-plugin": "^4.0.1", "@typescript-eslint/parser": "^4.0.0", + "auto-changelog": "^2.2.0", "axios-mock-adapter": "^1.18.1", "babel-loader": "^8.0.5", "concurrently": "^3.6.1", From 77b5b9408e1184c82ff690a175f1d1d683c29b41 Mon Sep 17 00:00:00 2001 From: Antariksh Mahajan Date: Mon, 14 Sep 2020 10:44:19 +0800 Subject: [PATCH 09/18] fix: allow inline styles from angular-sanitize (#316) --- src/loaders/express/helmet.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/loaders/express/helmet.ts b/src/loaders/express/helmet.ts index 32a20d05e2..46a0122584 100644 --- a/src/loaders/express/helmet.ts +++ b/src/loaders/express/helmet.ts @@ -73,6 +73,8 @@ const helmetMiddlewares = () => { 'https://www.recaptcha.net/recaptcha/', 'https://www.gstatic.com/recaptcha/', 'https://www.gstatic.cn/', + // For inline styles in angular-sanitize.js + "'sha256-b3IrgBVvuKx/Q3tmAi79fnf6AFClibrz/0S5x1ghdGU='", ], formAction: ["'self'"], upgradeInsecureRequests: !config.isDev, From 6f8892e92e214ca74a442e0ff16359717ff4b1c8 Mon Sep 17 00:00:00 2001 From: Kar Rui Lau Date: Mon, 14 Sep 2020 16:55:40 +0800 Subject: [PATCH 10/18] refactor: turn on strict mode in Typescript configuration (#262) --- package-lock.json | 130 ++--- package.json | 6 +- src/app/models/field/attachmentField.ts | 2 +- src/app/models/field/dateField.ts | 2 +- src/app/models/field/longTextField.ts | 2 +- src/app/models/field/numberField.ts | 2 +- src/app/models/field/shortTextField.ts | 2 +- src/app/models/form.server.model.ts | 25 +- src/app/models/submission.server.model.ts | 2 +- src/app/models/user.server.model.ts | 6 +- src/app/models/verification.server.model.ts | 2 +- src/app/modules/auth/auth.controller.ts | 9 +- .../__tests__/bounce.controller.spec.ts | 5 +- .../bounce/__tests__/bounce.model.spec.ts | 8 +- .../bounce/__tests__/bounce.service.spec.ts | 38 +- src/app/modules/bounce/bounce.model.ts | 35 +- src/app/modules/bounce/bounce.service.ts | 8 +- src/app/modules/bounce/bounce.util.ts | 4 +- .../modules/submission/submission.service.ts | 5 +- src/app/modules/user/user.controller.ts | 2 +- src/app/modules/user/user.service.ts | 4 +- .../verification/verification.factory.ts | 8 +- .../verification/verification.service.ts | 39 +- src/app/modules/webhook/webhook.controller.ts | 2 +- src/app/modules/webhook/webhook.service.ts | 3 +- src/app/services/mail.service.ts | 8 +- src/app/services/sms.service.ts | 2 +- src/app/utils/attachment.ts | 2 +- src/config/config.ts | 7 +- .../util/FeatureManager.class.ts | 24 +- src/config/formsg-sdk.ts | 4 +- src/config/logger.ts | 13 +- src/loaders/express/index.ts | 26 +- src/loaders/mongoose.ts | 5 +- src/shared/util/file-validation.ts | 7 +- src/shared/util/logic.ts | 137 ++--- src/shared/util/phone-num-validation.ts | 6 +- src/shared/util/stringify-safe.ts | 21 +- src/shared/util/verified-content.ts | 12 +- src/types/admin_verification.ts | 12 +- src/types/form.ts | 2 +- src/types/submission.ts | 8 +- src/types/vendor/aws-info.d.ts | 12 + src/types/vendor/bson-ext.d.ts | 508 ++++++++++++++++++ .../vendor/convict-format-with-validator.d.ts | 22 + src/types/vendor/express-device.d.ts | 23 + src/types/verification.ts | 14 +- tests/unit/backend/helpers/jest-db.ts | 4 +- tests/unit/backend/helpers/jest-express.ts | 12 +- .../admin_verification.server.model.spec.ts | 3 + .../backend/models/form.server.model.spec.ts | 15 +- .../backend/models/form_fields.schema.spec.ts | 7 +- .../models/sms_count.server.model.spec.ts | 4 +- .../submission/submission.service.spec.ts | 50 +- .../submission/submission.utils.spec.ts | 2 +- .../backend/modules/user/user.service.spec.ts | 2 +- .../verification.controller.spec.ts | 105 ++-- .../verification/verification.service.spec.ts | 58 +- .../modules/webhook/webhook.service.spec.ts | 10 +- .../backend/services/mail.service.spec.ts | 2 +- tests/unit/backend/utils/attachment.spec.ts | 3 +- tsconfig.json | 2 +- 62 files changed, 1068 insertions(+), 437 deletions(-) create mode 100644 src/types/vendor/aws-info.d.ts create mode 100644 src/types/vendor/bson-ext.d.ts create mode 100644 src/types/vendor/convict-format-with-validator.d.ts create mode 100644 src/types/vendor/express-device.d.ts diff --git a/package-lock.json b/package-lock.json index ab7e1c30af..ddec81b71d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4160,13 +4160,13 @@ } }, "@shelf/jest-mongodb": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@shelf/jest-mongodb/-/jest-mongodb-1.2.2.tgz", - "integrity": "sha512-FgNmvYmfXuOFyffziRheSwCBXrFwBZ0zTcNny04YyBD5VO1ukr7jnR+rKkKSMZ8E9LOVFU8Go8Ex24E2J917kw==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@shelf/jest-mongodb/-/jest-mongodb-1.2.3.tgz", + "integrity": "sha512-RGECov7b9anpHqrEoegYeZFWN3WEOw/3hPu3fQUi4gnNIGH0jyMVCQd4DgB37n2aoEWFfe7Kq59aQUrgIQRITA==", "dev": true, "requires": { "debug": "4.1.1", - "mongodb-memory-server": "6.6.3", + "mongodb-memory-server": "6.6.7", "uuid": "8.3.0" }, "dependencies": { @@ -4545,6 +4545,12 @@ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.5.tgz", "integrity": "sha512-7+2BITlgjgDhH0vvwZU/HZJVyk+2XUlvxXe8dFMedNX/aMkaOq++rMAFXc0tM7ij15QaWlbdQASBR9dihi+bDQ==" }, + "@types/json-stringify-safe": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/json-stringify-safe/-/json-stringify-safe-5.0.0.tgz", + "integrity": "sha512-UUA1sH0RSRROdInuDOA1yoRzbi5xVFD1RHCoOvNRPTNwR8zBkJ/84PZ6NhKVDtKp0FTeIccJCdQz1X2aJPr4uw==", + "dev": true + }, "@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", @@ -4605,6 +4611,12 @@ "@types/node": "*" } }, + "@types/mongodb-uri": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@types/mongodb-uri/-/mongodb-uri-0.9.0.tgz", + "integrity": "sha512-N52kUCiYyH4H2xOMHV7lIDjv4ZLRcRgEiN0xut/BNKHD/dLox10Q6WVl1vjnfA+rvdL9rFZGUxs9EQunQosAlA==", + "dev": true + }, "@types/mongoose": { "version": "5.7.36", "resolved": "https://registry.npmjs.org/@types/mongoose/-/mongoose-5.7.36.tgz", @@ -4795,6 +4807,12 @@ "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", "dev": true }, + "@types/semver": { + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.3.tgz", + "integrity": "sha512-jQxClWFzv9IXdLdhSaTf16XI3NYe6zrEbckSpb5xhKfPbWgIyAY0AFyWWWfaiDcBuj3UHmMkCIwSRqpKMTZL2Q==", + "dev": true + }, "@types/serve-static": { "version": "1.13.4", "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.4.tgz", @@ -16594,12 +16612,12 @@ } }, "jest-util": { - "version": "26.2.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-26.2.0.tgz", - "integrity": "sha512-YmDwJxLZ1kFxpxPfhSJ0rIkiZOM0PQbRcfH0TzJOhqCisCAsI1WcmoQqO83My9xeVA2k4n+rzg2UuexVKzPpig==", + "version": "26.3.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-26.3.0.tgz", + "integrity": "sha512-4zpn6bwV0+AMFN0IYhH/wnzIQzRaYVrz1A8sYnRnj4UXDXbOVtWmlaZkO9mipFqZ13okIfN87aDoJWB7VH6hcw==", "dev": true, "requires": { - "@jest/types": "^26.2.0", + "@jest/types": "^26.3.0", "@types/node": "*", "chalk": "^4.0.0", "graceful-fs": "^4.2.4", @@ -16608,18 +16626,27 @@ }, "dependencies": { "@jest/types": { - "version": "26.2.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.2.0.tgz", - "integrity": "sha512-lvm3rJvctxd7+wxKSxxbzpDbr4FXDLaC57WEKdUIZ2cjTYuxYSc0zlyD7Z4Uqr5VdKxRUrtwIkiqBuvgf8uKJA==", + "version": "26.3.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.3.0.tgz", + "integrity": "sha512-BDPG23U0qDeAvU4f99haztXwdAg3hz4El95LkAM+tHAqqhiVzRpEGHHU8EDxT/AnxOrA65YjLBwDahdJ9pTLJQ==", "dev": true, "requires": { "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", + "@types/istanbul-reports": "^3.0.0", "@types/node": "*", "@types/yargs": "^15.0.0", "chalk": "^4.0.0" } }, + "@types/istanbul-reports": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.0.tgz", + "integrity": "sha512-nwKNbvnwJ2/mndE9ItP/zc2TCzw6uuodnF4EHYWD+gCQDVBuRQL5UzbZD0/ezy1iKsFU2ZQiDqg4M9dN4+wZgA==", + "dev": true, + "requires": { + "@types/istanbul-lib-report": "*" + } + }, "ansi-styles": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", @@ -16662,9 +16689,9 @@ "dev": true }, "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { "has-flag": "^4.0.0" @@ -18497,12 +18524,12 @@ } }, "mongodb-memory-server": { - "version": "6.6.3", - "resolved": "https://registry.npmjs.org/mongodb-memory-server/-/mongodb-memory-server-6.6.3.tgz", - "integrity": "sha512-zx91SQQUBafVfBX8IJjfZa0lIMzdDYs/UB1vnr33e5bSPBwSai+mVV6gW3osF4paLFxOkcvOwx758G9F9HytgA==", + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/mongodb-memory-server/-/mongodb-memory-server-6.6.7.tgz", + "integrity": "sha512-azRGr5csTAl0MCLR/amPCJrmV5TFwRcVtal56dHrPy1o2T8wZRc3AaJyukob8a/JP38JYa/pQnw1AQH7lFA2Cg==", "dev": true, "requires": { - "mongodb-memory-server-core": "6.6.3" + "mongodb-memory-server-core": "6.6.7" }, "dependencies": { "agent-base": { @@ -18514,17 +18541,6 @@ "debug": "4" } }, - "bl": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.0.2.tgz", - "integrity": "sha512-j4OH8f6Qg2bGuWfRiltT2HYGx0e1QcBTrK9KAHNMwMZdQnDZFk0ZSYIpADjYCB3U12nicC5tVJwSIhwOWjb4RQ==", - "dev": true, - "requires": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, "camelcase": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.0.0.tgz", @@ -18598,6 +18614,14 @@ "dev": true, "requires": { "semver": "^6.0.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } } }, "md5-file": { @@ -18613,9 +18637,9 @@ "dev": true }, "mongodb-memory-server-core": { - "version": "6.6.3", - "resolved": "https://registry.npmjs.org/mongodb-memory-server-core/-/mongodb-memory-server-core-6.6.3.tgz", - "integrity": "sha512-MTs2qCb+5JG4qPCenqo+L0cxQiO09EqTZNk4I5+dz8nRUiVPFLL64tO/oJ1WDuSJ6vcyk8dC+QsNAD1wjZxx8g==", + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/mongodb-memory-server-core/-/mongodb-memory-server-core-6.6.7.tgz", + "integrity": "sha512-21g2FpQdgqN3sFsj5lbGje1BhrSRGNHgz6gMAl8bvmdpRpoZErclkImVtjBXNHCNmCc1Dxr+EBvH11KaVE+9iQ==", "dev": true, "requires": { "@types/cross-spawn": "^6.0.2", @@ -18626,12 +18650,12 @@ "@types/lockfile": "^1.0.1", "@types/md5-file": "^4.0.2", "@types/mkdirp": "^1.0.1", + "@types/semver": "^7.3.3", "@types/tmp": "^0.2.0", "@types/uuid": "^8.0.0", "camelcase": "^6.0.0", "cross-spawn": "^7.0.3", "debug": "^4.1.1", - "dedent": "^0.7.0", "find-cache-dir": "^3.3.1", "find-package-json": "^1.2.0", "get-port": "^5.1.1", @@ -18640,6 +18664,7 @@ "md5-file": "^5.0.0", "mkdirp": "^1.0.4", "mongodb": "^3.5.9", + "semver": "^7.3.2", "tar-stream": "^2.1.3", "tmp": "^0.2.1", "uuid": "^8.2.0", @@ -18691,21 +18716,10 @@ "find-up": "^4.0.0" } }, - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", "dev": true }, "shebang-command": { @@ -18723,19 +18737,6 @@ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true }, - "tar-stream": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.1.3.tgz", - "integrity": "sha512-Z9yri56Dih8IaK8gncVPx4Wqt86NDmQTSh49XLZgjWpGZL9GK9HKParS2scqHCC4w6X9Gh2jwaU45V47XTKwVA==", - "dev": true, - "requires": { - "bl": "^4.0.1", - "end-of-stream": "^1.4.1", - "fs-constants": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1" - } - }, "tmp": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", @@ -25167,11 +25168,12 @@ } }, "ts-jest": { - "version": "26.1.4", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-26.1.4.tgz", - "integrity": "sha512-Nd7diUX6NZWfWq6FYyvcIPR/c7GbEF75fH1R6coOp3fbNzbRJBZZAn0ueVS0r8r9ral1VcrpneAFAwB3TsVS1Q==", + "version": "26.3.0", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-26.3.0.tgz", + "integrity": "sha512-Jq2uKfx6bPd9+JDpZNMBJMdMQUC3sJ08acISj8NXlVgR2d5OqslEHOR2KHMgwymu8h50+lKIm0m0xj/ioYdW2Q==", "dev": true, "requires": { + "@types/jest": "26.x", "bs-logger": "0.x", "buffer-from": "1.x", "fast-json-stable-stringify": "2.x", diff --git a/package.json b/package.json index 6b44954dcb..9f6519252b 100644 --- a/package.json +++ b/package.json @@ -169,7 +169,7 @@ "@babel/core": "^7.11.5", "@babel/preset-env": "^7.11.5", "@opengovsg/mockpass": "^2.4.6", - "@shelf/jest-mongodb": "^1.2.2", + "@shelf/jest-mongodb": "^1.2.3", "@types/bcrypt": "^3.0.0", "@types/compression": "^1.7.0", "@types/convict": "^5.2.1", @@ -181,6 +181,8 @@ "@types/helmet": "0.0.48", "@types/ip": "^1.1.0", "@types/jest": "^26.0.9", + "@types/json-stringify-safe": "^5.0.0", + "@types/mongodb-uri": "^0.9.0", "@types/mongoose": "^5.7.36", "@types/node": "^14.0.13", "@types/nodemailer": "^6.4.0", @@ -236,7 +238,7 @@ "supertest": "^3.3.0", "terser-webpack-plugin": "^1.2.3", "testcafe": "^1.8.6", - "ts-jest": "^26.1.4", + "ts-jest": "^26.3.0", "ts-loader": "^7.0.5", "ts-mock-imports": "^1.3.0", "ts-node": "^8.10.2", diff --git a/src/app/models/field/attachmentField.ts b/src/app/models/field/attachmentField.ts index 0fb57f9f55..3b9639d7e3 100644 --- a/src/app/models/field/attachmentField.ts +++ b/src/app/models/field/attachmentField.ts @@ -30,7 +30,7 @@ const createAttachmentFieldSchema = () => { ) { const { webhook, responseMode } = this.parent() - if (responseMode === ResponseMode.Encrypt && webhook.url) { + if (responseMode === ResponseMode.Encrypt && webhook?.url) { return next( Error('Attachments are not allowed when a form has a webhook url'), ) diff --git a/src/app/models/field/dateField.ts b/src/app/models/field/dateField.ts index b8a87b7eb8..e7c3716093 100644 --- a/src/app/models/field/dateField.ts +++ b/src/app/models/field/dateField.ts @@ -18,7 +18,7 @@ const createDateFieldSchema = () => { }, selectedDateValidation: { type: String, - enum: Object.values(DateSelectedValidation).concat([null]), + enum: [...Object.values(DateSelectedValidation), null], default: null, }, }, diff --git a/src/app/models/field/longTextField.ts b/src/app/models/field/longTextField.ts index e7e20f4caa..984ecfdc92 100644 --- a/src/app/models/field/longTextField.ts +++ b/src/app/models/field/longTextField.ts @@ -22,7 +22,7 @@ const createLongTextFieldSchema = () => { }, selectedValidation: { type: String, - enum: Object.values(LongTextSelectedValidation).concat([null]), + enum: [...Object.values(LongTextSelectedValidation), null], default: null, }, }, diff --git a/src/app/models/field/numberField.ts b/src/app/models/field/numberField.ts index 648a272b85..759fb45ebe 100644 --- a/src/app/models/field/numberField.ts +++ b/src/app/models/field/numberField.ts @@ -22,7 +22,7 @@ const createNumberFieldSchema = () => { }, selectedValidation: { type: String, - enum: Object.values(NumberSelectedValidation).concat([null]), + enum: [...Object.values(NumberSelectedValidation), null], default: null, }, }, diff --git a/src/app/models/field/shortTextField.ts b/src/app/models/field/shortTextField.ts index 3e41accdae..fcfa32ff7b 100644 --- a/src/app/models/field/shortTextField.ts +++ b/src/app/models/field/shortTextField.ts @@ -25,7 +25,7 @@ const createShortTextFieldSchema = () => { }, selectedValidation: { type: String, - enum: Object.values(ShortTextSelectedValidation).concat([null]), + enum: [...Object.values(ShortTextSelectedValidation), null], default: null, }, }, diff --git a/src/app/models/form.server.model.ts b/src/app/models/form.server.model.ts index 41d0459105..b16f42f966 100644 --- a/src/app/models/form.server.model.ts +++ b/src/app/models/form.server.model.ts @@ -392,7 +392,7 @@ const compileFormModel = (db: Mongoose): IFormModel => { } // Compact is used to remove undefined from array - return compact(uniq(this.form_fields.map((field) => field.myInfo?.attr))) + return compact(uniq(this.form_fields?.map((field) => field.myInfo?.attr))) } // Return a duplicate form object with the given properties @@ -416,15 +416,16 @@ const compileFormModel = (db: Mongoose): IFormModel => { path: 'admin', select: 'email', }) - const otpData: FormOtpData = { - form: data._id, - formAdmin: { - email: data.admin.email, - userId: data.admin._id, - }, - msgSrvcName: data.msgSrvcName, - } - return otpData + return data + ? ({ + form: data._id, + formAdmin: { + email: data.admin.email, + userId: data.admin._id, + }, + msgSrvcName: data.msgSrvcName, + } as FormOtpData) + : null } catch { return null } @@ -434,8 +435,8 @@ const compileFormModel = (db: Mongoose): IFormModel => { FormSchema.statics.getFullFormById = async function ( this: IFormModel, formId: string, - ): Promise { - const data: IPopulatedForm = await this.findById(formId).populate({ + ): Promise { + const data: IPopulatedForm | null = await this.findById(formId).populate({ path: 'admin', populate: { path: 'agency', diff --git a/src/app/models/submission.server.model.ts b/src/app/models/submission.server.model.ts index ffe0a2b50e..1ce4759c8c 100644 --- a/src/app/models/submission.server.model.ts +++ b/src/app/models/submission.server.model.ts @@ -136,7 +136,7 @@ const encryptSubmissionSchema = new Schema({ * which will be posted to the webhook URL. */ encryptSubmissionSchema.methods.getWebhookView = function ( - this: ISubmissionSchema, + this: IEncryptedSubmissionSchema, ): WebhookView { const webhookData: WebhookData = { formId: String(this.form), diff --git a/src/app/models/user.server.model.ts b/src/app/models/user.server.model.ts index 047e6634eb..32aaad4d37 100644 --- a/src/app/models/user.server.model.ts +++ b/src/app/models/user.server.model.ts @@ -69,7 +69,11 @@ const compileUserModel = (db: Mongoose) => { * * See: https://masteringjs.io/tutorials/mongoose/e11000-duplicate-key. */ - UserSchema.post('save', function (err, doc, next) { + UserSchema.post('save', function ( + err: any, + _doc: IUserSchema, + next: any, + ) { if (err.name === 'MongoError' && err.code === 11000) { next(new Error('Account already exists with this email')) } else { diff --git a/src/app/models/verification.server.model.ts b/src/app/models/verification.server.model.ts index 9313edca4a..063cb81165 100644 --- a/src/app/models/verification.server.model.ts +++ b/src/app/models/verification.server.model.ts @@ -28,7 +28,7 @@ const VerificationFieldSchema = new Schema({ hashRetries: { type: Number, default: 0 }, }) -const compileVerificationModel = (db: Mongoose) => { +const compileVerificationModel = (db: Mongoose): IVerificationModel => { const VerificationSchema = new Schema({ formId: { type: Schema.Types.ObjectId, diff --git a/src/app/modules/auth/auth.controller.ts b/src/app/modules/auth/auth.controller.ts index 6bee99769a..4fa51633a4 100644 --- a/src/app/modules/auth/auth.controller.ts +++ b/src/app/modules/auth/auth.controller.ts @@ -46,11 +46,11 @@ export const handleLoginSendOtp: RequestHandler = async ( // Create OTP. const [otpErr, otp] = await to(AuthService.createLoginOtp(email)) - if (otpErr) { + if (otpErr || !otp) { logger.error({ message: 'Error generating OTP', meta: logMeta, - error: otpErr, + error: otpErr ?? undefined, }) return res .status(StatusCodes.INTERNAL_SERVER_ERROR) @@ -138,7 +138,8 @@ export const handleLoginVerifyOtp: RequestHandler = async ( // OTP is valid, proceed to login user. try { - const user = await UserService.retrieveUser(email, agency) + // TODO (#317): remove usage of non-null assertion + const user = await UserService.retrieveUser(email, agency!) // Create user object to return to frontend. const userObj = { ...user.toObject(), agency } @@ -181,7 +182,7 @@ export const handleSignout: RequestHandler = async (req, res) => { return res.sendStatus(StatusCodes.BAD_REQUEST) } - req.session.destroy((error) => { + req.session!.destroy((error) => { if (error) { logger.error({ message: 'Failed to destroy session', diff --git a/src/app/modules/bounce/__tests__/bounce.controller.spec.ts b/src/app/modules/bounce/__tests__/bounce.controller.spec.ts index ac73b3cdb2..9b2df51dbe 100644 --- a/src/app/modules/bounce/__tests__/bounce.controller.spec.ts +++ b/src/app/modules/bounce/__tests__/bounce.controller.spec.ts @@ -4,11 +4,14 @@ import { mocked } from 'ts-jest/utils' import { handleSns } from 'src/app/modules/bounce/bounce.controller' import * as BounceService from 'src/app/modules/bounce/bounce.service' +import { ISnsNotification } from 'src/types' jest.mock('src/app/modules/bounce/bounce.service') const MockBounceService = mocked(BounceService, true) -const MOCK_REQ = expressHandler.mockRequest({ body: { someKey: 'someValue' } }) +const MOCK_REQ = expressHandler.mockRequest({ + body: ({ someKey: 'someValue' } as unknown) as ISnsNotification, +}) const MOCK_RES = expressHandler.mockResponse() describe('handleSns', () => { diff --git a/src/app/modules/bounce/__tests__/bounce.model.spec.ts b/src/app/modules/bounce/__tests__/bounce.model.spec.ts index 0475c12b0d..d90a425095 100644 --- a/src/app/modules/bounce/__tests__/bounce.model.spec.ts +++ b/src/app/modules/bounce/__tests__/bounce.model.spec.ts @@ -146,12 +146,12 @@ describe('Bounce Model', () => { ).Message, ) const actual = Bounce.fromSnsNotification(notification) - expect(omit(extractBounceObject(actual), 'expireAt')).toEqual({ + expect(omit(extractBounceObject(actual!), 'expireAt')).toEqual({ formId, bounces: [{ email: MOCK_EMAIL, hasBounced: false }], hasAlarmed: false, }) - expect(actual.expireAt).toBeInstanceOf(Date) + expect(actual!.expireAt).toBeInstanceOf(Date) }) it('should create documents correctly when bounce notification is valid', () => { @@ -166,12 +166,12 @@ describe('Bounce Model', () => { ).Message, ) const actual = Bounce.fromSnsNotification(notification) - expect(omit(extractBounceObject(actual), 'expireAt')).toEqual({ + expect(omit(extractBounceObject(actual!), 'expireAt')).toEqual({ formId, bounces: [{ email: MOCK_EMAIL, hasBounced: true }], hasAlarmed: false, }) - expect(actual.expireAt).toBeInstanceOf(Date) + expect(actual!.expireAt).toBeInstanceOf(Date) }) }) }) diff --git a/src/app/modules/bounce/__tests__/bounce.service.spec.ts b/src/app/modules/bounce/__tests__/bounce.service.spec.ts index 90df58a7a2..c8804005d9 100644 --- a/src/app/modules/bounce/__tests__/bounce.service.spec.ts +++ b/src/app/modules/bounce/__tests__/bounce.service.spec.ts @@ -41,22 +41,20 @@ import { const Bounce = getBounceModel(mongoose) describe('isValidSnsRequest', () => { - let keys, body: ISnsNotification - - beforeAll(() => { - keys = crypto.generateKeyPairSync('rsa', { - modulusLength: 2048, - publicKeyEncoding: { - type: 'pkcs1', - format: 'pem', - }, - privateKeyEncoding: { - type: 'pkcs8', - format: 'pem', - }, - }) + const keys = crypto.generateKeyPairSync('rsa', { + modulusLength: 2048, + publicKeyEncoding: { + type: 'pkcs1', + format: 'pem', + }, + privateKeyEncoding: { + type: 'pkcs8', + format: 'pem', + }, }) + let body: ISnsNotification + beforeEach(() => { body = cloneDeep(MOCK_SNS_BODY) mockAxios.get.mockResolvedValue({ @@ -65,12 +63,12 @@ describe('isValidSnsRequest', () => { }) it('should gracefully reject when input is empty', () => { - return expect(isValidSnsRequest(undefined)).resolves.toBe(false) + return expect(isValidSnsRequest(undefined!)).resolves.toBe(false) }) it('should reject requests when their structure is invalid', () => { - delete body.Type - return expect(isValidSnsRequest(body)).resolves.toBe(false) + const invalidBody = omit(cloneDeep(body), 'Type') as ISnsNotification + return expect(isValidSnsRequest(invalidBody)).resolves.toBe(false) }) it('should reject requests when their certificate URL is invalid', () => { @@ -140,7 +138,7 @@ describe('updateBounces', () => { ) await updateBounces(notification) const actualBounceDoc = await Bounce.findOne({ formId }) - const actualBounce = extractBounceObject(actualBounceDoc) + const actualBounce = extractBounceObject(actualBounceDoc!) const expectedBounces = recipientList.map((email) => ({ email, hasBounced: false, @@ -175,7 +173,7 @@ describe('updateBounces', () => { ) await updateBounces(notification) const actualBounceDoc = await Bounce.findOne({ formId }) - const actualBounce = extractBounceObject(actualBounceDoc) + const actualBounce = extractBounceObject(actualBounceDoc!) const expectedBounces = recipientList.map((email) => ({ email, hasBounced: bounces[email], @@ -208,7 +206,7 @@ describe('updateBounces', () => { ) await updateBounces(notification) const actualBounceDoc = await Bounce.findOne({ formId }) - const actualBounce = extractBounceObject(actualBounceDoc) + const actualBounce = extractBounceObject(actualBounceDoc!) const expectedBounces = recipientList.map((email) => ({ email, hasBounced: true, diff --git a/src/app/modules/bounce/bounce.model.ts b/src/app/modules/bounce/bounce.model.ts index affb7c9f45..e3735c96ce 100644 --- a/src/app/modules/bounce/bounce.model.ts +++ b/src/app/modules/bounce/bounce.model.ts @@ -1,4 +1,3 @@ -import { get } from 'lodash' import { Model, Mongoose, Schema } from 'mongoose' import validator from 'validator' @@ -62,21 +61,25 @@ const BounceSchema = new Schema({ }) BounceSchema.index({ expireAt: 1 }, { expireAfterSeconds: 0 }) -// Create a new Bounce document from an SNS notification. -// More info on format of SNS notifications: -// https://docs.aws.amazon.com/sns/latest/dg/sns-verify-signature-of-message.html +/** + * Create a new Bounce document from an SNS notification. + * More info on format of SNS notifications: + * https://docs.aws.amazon.com/sns/latest/dg/sns-verify-signature-of-message.html. + * @param snsInfo the SNS notification to create a document from + * @returns the created Bounce document + */ BounceSchema.statics.fromSnsNotification = function ( this: IBounceModel, snsInfo: IEmailNotification, ): IBounceSchema | null { const emailType = extractHeader(snsInfo, EMAIL_HEADERS.emailType) const formId = extractHeader(snsInfo, EMAIL_HEADERS.formId) - // We only care about admin emails + // Only care about admin emails if (emailType !== EmailType.AdminResponse || !formId) { return null } const isBounce = isBounceNotification(snsInfo) - const bounces: ISingleBounce[] = get(snsInfo, 'mail.commonHeaders.to').map( + const bounces: ISingleBounce[] = snsInfo.mail.commonHeaders.to.map( (email) => { if (isBounce && hasEmailBounced(snsInfo as IBounceNotification, email)) { return { email, hasBounced: true } @@ -88,14 +91,18 @@ BounceSchema.statics.fromSnsNotification = function ( return new this({ formId, bounces }) } -// Updates an old bounce document with info from a new bounce document as well -// as an SNS notification. This function does 3 things: -// 1) If the old bounce document indicates that an email bounced, set hasBounced -// to true for that email. -// 2) If the new delivery notification indicates that an email was delivered -// successfully, set hasBounced to false for that email, even if the old bounce -// document indicates that that email previously bounced. -// 3) Update the old recipient list according to the newest bounce notification. +/** + * Updates an old bounce document with info from a new bounce document as well + * as an SNS notification. This function does 3 things: + * 1) If the old bounce document indicates that an email bounced, set + * `hasBounced` to `true` for that email. + * 2) If the new delivery notification indicates that an email was delivered + * successfully, set `hasBounced` to `false` for that email, even if the old + * bounce document indicates that that email previously bounced. + * 3) Update the old recipient list according to the newest bounce notification. + * @param latestBounces the newer bounce document to merge into the current document + * @param snsInfo the notification information to merge + */ BounceSchema.methods.merge = function ( this: IBounceSchema, latestBounces: IBounceSchema, diff --git a/src/app/modules/bounce/bounce.service.ts b/src/app/modules/bounce/bounce.service.ts index 288884b504..aec827fa67 100644 --- a/src/app/modules/bounce/bounce.service.ts +++ b/src/app/modules/bounce/bounce.service.ts @@ -108,7 +108,7 @@ export const isValidSnsRequest = async ( // Writes a log message if all recipients have bounced const logCriticalBounce = ( bounceDoc: IBounceSchema, - submissionId: string, + submissionId: string | undefined, bounceInfo: IBounceNotification['bounce'] | undefined, ): void => { if (bounceDoc.isCriticalBounce()) { @@ -118,7 +118,7 @@ const logCriticalBounce = ( action: 'updateBounces', hasAlarmed: bounceDoc.hasAlarmed, formId: String(bounceDoc.formId), - submissionId, + submissionId: submissionId, recipients: bounceDoc.bounces.map((emailInfo) => emailInfo.email), // We know for sure that critical bounces can only happen because of bounce // notifications, so we don't expect this to be undefined @@ -169,7 +169,9 @@ export const updateBounces = async (body: ISnsNotification): Promise => { if (!latestBounces) return const formId = latestBounces.formId const submissionId = extractHeader(notification, EMAIL_HEADERS.submissionId) - const bounceInfo = isBounceNotification(notification) && notification.bounce + const bounceInfo = isBounceNotification(notification) + ? notification.bounce + : undefined const oldBounces = await Bounce.findOne({ formId }) if (oldBounces) { oldBounces.merge(latestBounces, notification) diff --git a/src/app/modules/bounce/bounce.util.ts b/src/app/modules/bounce/bounce.util.ts index 36e2eb3cf7..8d9d27e751 100644 --- a/src/app/modules/bounce/bounce.util.ts +++ b/src/app/modules/bounce/bounce.util.ts @@ -8,11 +8,12 @@ import { * and email type (admin response, email confirmation OTP etc). * @param body Body of SNS notification * @param header Key of header to extract + * @returns the header from the body, if any. */ export const extractHeader = ( body: IEmailNotification, header: string, -): string => { +): string | undefined => { return body.mail.headers.find( (mailHeader) => mailHeader.name.toLowerCase() === header.toLowerCase(), )?.value @@ -22,6 +23,7 @@ export const extractHeader = ( * Whether a bounce notification says a given email has bounced. * @param bounceInfo Bounce notification from SNS * @param email Email address to check + * @returns true if the email as bounced, false otherwise */ export const hasEmailBounced = ( bounceInfo: IBounceNotification, diff --git a/src/app/modules/submission/submission.service.ts b/src/app/modules/submission/submission.service.ts index 63ce51ee1e..f99f2f4e67 100644 --- a/src/app/modules/submission/submission.service.ts +++ b/src/app/modules/submission/submission.service.ts @@ -27,7 +27,8 @@ const getFilteredResponses = ( const modeFilter = getModeFilter(form.responseMode) // _id must be transformed to string as form response is jsonified. - const fieldIds = modeFilter(form.form_fields).map((field) => ({ + // TODO (#317): remove usage of non-null assertion + const fieldIds = modeFilter(form.form_fields!).map((field) => ({ _id: String(field._id), })) const uniqueResponses = _.uniqBy(modeFilter(responses), '_id') @@ -69,7 +70,7 @@ export const getProcessedResponses = ( } // Create a map keyed by field._id for easier access - const fieldMap = form.form_fields.reduce<{ + const fieldMap = form.form_fields!.reduce<{ [fieldId: string]: IFieldSchema }>((acc, field) => { acc[field._id] = field diff --git a/src/app/modules/user/user.controller.ts b/src/app/modules/user/user.controller.ts index 8a941ad0c3..c35b35cf30 100644 --- a/src/app/modules/user/user.controller.ts +++ b/src/app/modules/user/user.controller.ts @@ -128,7 +128,7 @@ export const handleFetchUser: RequestHandler = async (req, res) => { action: 'handleFetchUser', userId: sessionUserId, }, - error: dbErr, + error: dbErr ?? undefined, }) return res .status(StatusCodes.INTERNAL_SERVER_ERROR) diff --git a/src/app/modules/user/user.service.ts b/src/app/modules/user/user.service.ts index 7bad460194..358953227a 100644 --- a/src/app/modules/user/user.service.ts +++ b/src/app/modules/user/user.service.ts @@ -98,7 +98,7 @@ export const verifyContactOtp = async ( ) if (contactHashErr || otpHashError) { - throw new MalformedOtpError(null, `bcrypt error for ${userId}`) + throw new MalformedOtpError(undefined, `bcrypt error for ${userId}`) } if (!isOtpMatch) { @@ -149,7 +149,7 @@ export const updateUserContact = async ( export const getPopulatedUserById = async ( userId: IUserSchema['_id'], -): Promise => { +): Promise => { return UserModel.findById(userId).populate({ path: 'agency', model: AGENCY_SCHEMA_ID, diff --git a/src/app/modules/verification/verification.factory.ts b/src/app/modules/verification/verification.factory.ts index 2327aedeb1..3914e633b9 100644 --- a/src/app/modules/verification/verification.factory.ts +++ b/src/app/modules/verification/verification.factory.ts @@ -8,10 +8,10 @@ import * as verification from './verification.controller' interface IVerifiedFieldsFactory { createTransaction: RequestHandler - getTransactionMetadata: RequestHandler - resetFieldInTransaction: RequestHandler - getNewOtp: RequestHandler - verifyOtp: RequestHandler + getTransactionMetadata: RequestHandler<{ transactionId: string }> + resetFieldInTransaction: RequestHandler<{ transactionId: string }> + getNewOtp: RequestHandler<{ transactionId: string }> + verifyOtp: RequestHandler<{ transactionId: string }> } const verifiedFieldsFactory = ({ diff --git a/src/app/modules/verification/verification.service.ts b/src/app/modules/verification/verification.service.ts index 0e3d456ffc..90272a8662 100644 --- a/src/app/modules/verification/verification.service.ts +++ b/src/app/modules/verification/verification.service.ts @@ -40,6 +40,11 @@ export const createTransaction = async ( formId: string, ): Promise => { const form = await Form.findById(formId) + + if (!form) { + return null + } + const fields = initializeVerifiableFields(form) if (!_.isEmpty(fields)) { const verification = new Verification({ formId, fields }) @@ -74,8 +79,8 @@ export const getTransaction = async ( transactionId: string, ): Promise => { const transaction = await Verification.findById(transactionId) - if (transaction === null) { - throwError(VfnErrors.TransactionNotFound) + if (!transaction) { + return throwError(VfnErrors.TransactionNotFound) } return transaction } @@ -117,17 +122,19 @@ export const getNewOtp = async ( fieldId: string, answer: string, ): Promise => { - if (isTransactionExpired(transaction.expireAt)) { + // TODO (#317): remove usage of non-null assertion + if (isTransactionExpired(transaction.expireAt!)) { throwError(VfnErrors.TransactionNotFound) } const field = getFieldFromTransaction(transaction, fieldId) - if (field === undefined) { - throwError('Field not found in transaction', VfnErrors.FieldNotFound) + if (!field) { + return throwError('Field not found in transaction', VfnErrors.FieldNotFound) } const { _id: transactionId, formId } = transaction - const waitForSeconds = waitToResendOtpSeconds(field.hashCreatedAt) + // TODO (#317): remove usage of non-null assertion + const waitForSeconds = waitToResendOtpSeconds(field.hashCreatedAt!) if (waitForSeconds > 0) { - throwError( + return throwError( `Wait for ${waitForSeconds} seconds before requesting for a new otp`, VfnErrors.WaitForOtp, ) @@ -135,7 +142,8 @@ export const getNewOtp = async ( const hashCreatedAt = new Date() const otp = generateOtp() const hashedOtp = await bcrypt.hash(otp, SALT_ROUNDS) - const signedData = formsgSdk.verification.generateSignature({ + + const signedData = formsgSdk.verification.generateSignature!({ transactionId, formId, fieldId, @@ -171,32 +179,33 @@ export const verifyOtp = async ( fieldId: string, inputOtp: string, ): Promise => { - if (isTransactionExpired(transaction.expireAt)) { + // TODO (#317): remove usage of non-null assertion + if (isTransactionExpired(transaction.expireAt!)) { throwError(VfnErrors.TransactionNotFound) } const field = getFieldFromTransaction(transaction, fieldId) - if (field === undefined) { - throwError('Field not found in transaction', VfnErrors.FieldNotFound) + if (!field) { + return throwError('Field not found in transaction', VfnErrors.FieldNotFound) } const { hashedOtp, hashCreatedAt, signedData, hashRetries } = field if ( hashedOtp && hashCreatedAt && !isHashedOtpExpired(hashCreatedAt) && - hashRetries < NUM_OTP_RETRIES + NUM_OTP_RETRIES > hashRetries! ) { await Verification.updateOne( { _id: transaction._id, 'fields._id': fieldId }, { $set: { - 'fields.$.hashRetries': hashRetries + 1, + 'fields.$.hashRetries': hashRetries! + 1, }, }, ) const validOtp = await bcrypt.compare(inputOtp, hashedOtp) - return validOtp ? signedData : throwError(VfnErrors.InvalidOtp) + return validOtp ? signedData! : throwError(VfnErrors.InvalidOtp) } - throwError(VfnErrors.ResendOtp) + return throwError(VfnErrors.ResendOtp) } /** diff --git a/src/app/modules/webhook/webhook.controller.ts b/src/app/modules/webhook/webhook.controller.ts index d8b199c65f..10a2aa7b4e 100644 --- a/src/app/modules/webhook/webhook.controller.ts +++ b/src/app/modules/webhook/webhook.controller.ts @@ -22,7 +22,7 @@ export const post = ( // There should only be a webhook service, which is called within the submission controller // This will also remove the need for retrieval of form/submission from req. const { form, submission } = req - const webhookUrl = form.webhook.url + const webhookUrl = form.webhook?.url const submissionWebhookView = submission.getWebhookView() if (webhookUrl) { // Note that we push data to webhook endpoints on a best effort basis diff --git a/src/app/modules/webhook/webhook.service.ts b/src/app/modules/webhook/webhook.service.ts index 636a282566..947e394e76 100644 --- a/src/app/modules/webhook/webhook.service.ts +++ b/src/app/modules/webhook/webhook.service.ts @@ -273,7 +273,7 @@ const getFormattedResponse = ( */ export const pushData = async ( webhookUrl: WebhookParams['webhookUrl'], - submissionWebhookView: WebhookView, + submissionWebhookView: WebhookView | null, ): Promise => { const now = Date.now() // Log and return, this should not happen. @@ -282,7 +282,6 @@ export const pushData = async ( new WebhookValidationError('submissionWebhookView was null'), { webhookUrl, - submissionWebhookView, now, }, ) diff --git a/src/app/services/mail.service.ts b/src/app/services/mail.service.ts index c319649eea..4803b4853b 100644 --- a/src/app/services/mail.service.ts +++ b/src/app/services/mail.service.ts @@ -90,20 +90,20 @@ export class MailService { * The application name to be shown in some sent emails' fields such as mail * subject or mail body. */ - #appName: Required + #appName: Required['appName'] /** * The application URL to be shown in some sent emails' fields such as mail * subject or mail body. */ - #appUrl: Required + #appUrl: Required['appUrl'] /** * The transporter to be used to send mail. */ - #transporter: Required + #transporter: Required['transporter'] /** * The email string to denote the "from" field of the email. */ - #senderMail: Required + #senderMail: Required['senderMail'] /** * The full string that can be shown in the mail's "from" field created from * the given `appName` and `senderMail` arguments. diff --git a/src/app/services/sms.service.ts b/src/app/services/sms.service.ts index ff2bc93d2b..316a4d31c8 100644 --- a/src/app/services/sms.service.ts +++ b/src/app/services/sms.service.ts @@ -82,7 +82,7 @@ type TwilioConfig = { * @returns A TwilioConfig containing the client and the sid linked to the msgSrvcName if defined, or the defaultConfig if not. */ const getTwilio = async ( - msgSrvcName: string, + msgSrvcName: string | undefined, defaultConfig: TwilioConfig, ): Promise => { if (msgSrvcName) { diff --git a/src/app/utils/attachment.ts b/src/app/utils/attachment.ts index a7821450af..dc48bc94fc 100644 --- a/src/app/utils/attachment.ts +++ b/src/app/utils/attachment.ts @@ -69,7 +69,7 @@ export const addAttachmentToResponses = ( const attachmentMap: Record< IAttachmentInfo['fieldId'], IAttachmentInfo - > = attachments.reduce((acc, attachment) => { + > = attachments.reduce>((acc, attachment) => { acc[attachment.fieldId] = attachment return acc }, {}) diff --git a/src/config/config.ts b/src/config/config.ts index c498e0d166..0158ebf57e 100644 --- a/src/config/config.ts +++ b/src/config/config.ts @@ -99,7 +99,8 @@ if (isDev) { } const dbConfig: DbConfig = { - uri: dbUri, + // TODO (#317): remove usage of non-null assertion + uri: dbUri!, options: { user: '', pass: '', @@ -196,10 +197,10 @@ const configureAws = async () => { }) } await getCredentials() - if (!aws.config.credentials.accessKeyId) { + if (!aws.config.credentials?.accessKeyId) { throw new Error(`AWS Access Key Id is missing`) } - if (!aws.config.credentials.secretAccessKey) { + if (!aws.config.credentials?.secretAccessKey) { throw new Error(`AWS Secret Access Key is missing`) } } diff --git a/src/config/feature-manager/util/FeatureManager.class.ts b/src/config/feature-manager/util/FeatureManager.class.ts index bb7ff7bd35..09e5aaa84b 100644 --- a/src/config/feature-manager/util/FeatureManager.class.ts +++ b/src/config/feature-manager/util/FeatureManager.class.ts @@ -78,38 +78,42 @@ export default class FeatureManager { } /** - * Return whether requested feature is enabled - * @param name + * Return true if requested feature is enabled. Else, throw error. + * @param name the feature name to check enabledness + * @returns true if the feature is enabled, false if disabled + * @throws {Error} if name given is not a registered feature */ isEnabled(name: FeatureNames): boolean { if (this.states[name] !== undefined) { - return this.states[name] - } else { - throw new Error(`A feature called ${name} does not exist`) + return !!this.states[name] } + + // Only throw error if state is undefined. + throw new Error(`A feature called ${name} does not exist`) } /** * Return props registered for requested feature - * @param name + * @param name the feature to return properties for */ props(name: K) { if (this.states[name] !== undefined) { return this.properties[name] - } else { - throw new Error(`A feature called ${name} does not exist`) } + // Not enabled or not in state. + throw new Error(`A feature called ${name} does not exist`) } /** * Return properties registered for requested feature * and whether requested feature is enabled - * @param name + * @param name the name of the feature to return */ get(name: FeatureNames): RegisteredFeature { return { isEnabled: this.isEnabled(name), - props: this.props(name), + // TODO (#317): remove usage of non-null assertion + props: this.props(name)!, } } } diff --git a/src/config/formsg-sdk.ts b/src/config/formsg-sdk.ts index ab76498d5a..84aa64ea8e 100644 --- a/src/config/formsg-sdk.ts +++ b/src/config/formsg-sdk.ts @@ -11,14 +11,14 @@ const formsgSdk = formsgSdkPackage({ webhookSecretKey: get( featureManager.props(FeatureNames.WebhookVerifiedContent), 'signingSecretKey', - null, + undefined, ), mode: formsgSdkMode, verificationOptions: { secretKey: get( featureManager.props(FeatureNames.VerifiedFields), 'verificationSecretKey', - null, + undefined, ), transactionExpiry: vfnConstants.TRANSACTION_EXPIRE_AFTER_SECONDS, }, diff --git a/src/config/logger.ts b/src/config/logger.ts index c1753217f0..bf4ef0e4b3 100644 --- a/src/config/logger.ts +++ b/src/config/logger.ts @@ -122,21 +122,22 @@ export const customFormat = format.printf((info) => { * Function courtesy of * https://github.com/winstonjs/winston/issues/1243#issuecomment-463548194. */ -const jsonErrorReplacer = (_key: never, value: any) => { +function jsonErrorReplacer(this: any, key: string, value: any) { if (value instanceof Error) { return Object.getOwnPropertyNames(value).reduce((all, valKey) => { if (valKey === 'stack') { + const errStack = value.stack ?? '' return { ...all, - at: value[valKey] + at: errStack .split('\n') - .filter((va) => va.trim().slice(0, 5) != 'Error') - .map((va, i) => `stack ${i} ${va.trim().slice(3).trim()}`), + .filter((va) => va.trim().slice(0, 5) !== 'Error') + .map((va, i) => `stack ${i} ${va.trim()}`), } } else { return { ...all, - [valKey]: value[valKey], + [valKey]: value[valKey as keyof Error], } } }, {}) @@ -180,7 +181,7 @@ const getModuleLabel = (callingModule: NodeModule) => { // Remove the file extension from the filename and split with path separator. const parts = callingModule.filename.replace(/\.[^/.]+$/, '').split(path.sep) // Join the last two parts of the file path together. - return path.join(parts[parts.length - 2], parts.pop()) + return path.join(parts[parts.length - 2], parts.pop() ?? '') } /** diff --git a/src/loaders/express/index.ts b/src/loaders/express/index.ts index cf71cb02ae..8a2ffe5238 100644 --- a/src/loaders/express/index.ts +++ b/src/loaders/express/index.ts @@ -23,25 +23,31 @@ import sentryMiddlewares from './sentry' import sessionMiddlewares from './session' const loadExpressApp = async (connection: Connection) => { - // Initialize express app + // Initialize express app. let app = express() app.locals = appLocals - const environmentConfigs = { - production(app: Express) { - // Trust the load balancer that is in front of the server - app.set('trust proxy', true) - return app - }, + const getConfigFunctionFor = (environment: string) => { + switch (environment) { + case 'production': { + return function (app: Express) { + // Trust the load balancer that is in front of the server + app.set('trust proxy', true) + return app + } + } + default: + return null + } } - const configureEnvironmentFor = environmentConfigs[config.nodeEnv] - if (typeof configureEnvironmentFor === 'function') { + const configureEnvironmentFor = getConfigFunctionFor(config.nodeEnv) + if (configureEnvironmentFor) { app = configureEnvironmentFor(app) } app.use(function (req, res, next) { - const urlPath = url.parse(req.url).path.split('/') + const urlPath = url.parse(req.url).path?.split('/') ?? [] if ( urlPath.indexOf('static') > -1 && urlPath.indexOf('view') === urlPath.indexOf('static') - 1 diff --git a/src/loaders/mongoose.ts b/src/loaders/mongoose.ts index 53190820e2..2b14368727 100644 --- a/src/loaders/mongoose.ts +++ b/src/loaders/mongoose.ts @@ -7,7 +7,7 @@ import { createLoggerWithLabel } from '../config/logger' const logger = createLoggerWithLabel(module) export default async (): Promise => { - const usingMockedDb = config.db.uri === undefined + const usingMockedDb = !config.db.uri // Mock out the database if we're developing locally if (usingMockedDb) { logger.warn({ @@ -43,7 +43,8 @@ export default async (): Promise => { // Actually connect to the database function connect() { - return mongoose.connect(config.db.uri, config.db.options) + // TODO (#317): remove usage of non-null assertion + return mongoose.connect(config.db.uri!, config.db.options) } // Only required for initial connection errors, reconnect on error. diff --git a/src/shared/util/file-validation.ts b/src/shared/util/file-validation.ts index 1426d7df0c..1b17a33e30 100644 --- a/src/shared/util/file-validation.ts +++ b/src/shared/util/file-validation.ts @@ -109,9 +109,11 @@ export const getInvalidFileExtensionsInZip = ( // We wrap this checker into a closure because the data format // needs to be different for frontend vs backend. - const checkZipForInvalidFiles = async function (file: File | Buffer) { + const checkZipForInvalidFiles = async ( + file: Blob | Buffer, + ): Promise => { const zip = await JSZip.loadAsync(file) - const invalidFileExtensions = [] + const invalidFileExtensions: (string | string[] | Promise)[] = [] zip.forEach((relativePath, fileEntry) => { if (fileEntry.dir) return const fileExt = getFileExtension(fileEntry.name) @@ -124,6 +126,7 @@ export const getInvalidFileExtensionsInZip = ( ) } }) + const results = await Promise.all(invalidFileExtensions) return uniq(flattenDeep(results)) } diff --git a/src/shared/util/logic.ts b/src/shared/util/logic.ts index bd0b1387d9..860fd68934 100644 --- a/src/shared/util/logic.ts +++ b/src/shared/util/logic.ts @@ -6,10 +6,11 @@ import { ILogicSchema, IPreventSubmitLogicSchema, IShowFieldsLogicSchema, + LogicConditionState, LogicType, } from '../../types' -type GroupedLogic = Record +type GroupedLogic = Record type FieldIdSet = Set // This module handles logic on both the client side (IFieldSchema[]) // and server side (FieldResponse[]) @@ -31,11 +32,13 @@ const isPreventSubmitLogic = ( } /** - * Parse logic into a map of fields that are shown/hidden depending on the values of other fields - * Discards invalid logic, where the id in show or conditions do not exist in form_field + * Parse logic into a map of fields that are shown/hidden depending on the + * values of other fields. + * Discards invalid logic, where the id in show or conditions do not exist in + * the form_field. * - * Example: - Show Email (_id: 1001) and Number (_id: 1002) if Dropdown (_id: 1003) is "Option 1" and Yes_No (_id: 1004) is "Yes" + * @example + * Show Email (_id: 1001) and Number (_id: 1002) if Dropdown (_id: 1003) is "Option 1" and Yes_No (_id: 1004) is "Yes" Then, form_logics: [ { @@ -54,30 +57,24 @@ const isPreventSubmitLogic = ( "1002": [ [{field: "1003", ifValueType: "single-select", state: "is equals to", value: "Option 1"}, {field: "1004", ifValueType: "single-select", state: "is equals to", value: "Yes"}] ] } - - If "1001" is deleted, "1002" will still be rendered since we just won't add "1001" into logicUnitsGroupedByField + * @caption If "1001" is deleted, "1002" will still be rendered since we just won't add "1001" into logicUnitsGroupedByField * - * @param {Object} form - * @param {Mongoose.ObjectId} form._id : id of form - * @param {Array} form.form_logics : An array of objects containing the conditions and ids of fields to be displayed. See FormLogicSchema - * @param {Array} form.form_fields : An array of form fields containing the ids of the fields - * @returns {Object} Object containing fields to be displayed and their corresponding conditions, keyed by id of the displayable field + * @param form the form object to group its logic by field for + * @returns an object containing fields to be displayed and their corresponding conditions, keyed by id of the displayable field */ export const groupLogicUnitsByField = (form: IForm): GroupedLogic => { const formId = form._id - const formLogics = form.form_logics.filter(isShowFieldsLogic) + const formLogics = form.form_logics?.filter(isShowFieldsLogic) ?? [] const formFieldIds = new Set( - form.form_fields.map((field) => String(field._id)), + form.form_fields?.map((field) => String(field._id)), ) - /** - * @type {Object.>>} An index of logic units keyed by the field id to be shown. See FormLogicSchema - */ + /** An index of logic units keyed by the field id to be shown. */ const logicUnitsGroupedByField: GroupedLogic = {} let hasInvalidLogic = false formLogics.forEach(function (logicUnit) { - // Only add fields with valid logic conditions to the returned map + // Only add fields with valid logic conditions to the returned map. if (allConditionsExist(logicUnit.conditions, formFieldIds)) { logicUnit.show.forEach(function (fieldId) { fieldId = String(fieldId) @@ -98,54 +95,55 @@ export const groupLogicUnitsByField = (form: IForm): GroupedLogic => { } /** - * Parse logic to get a list of conditions where, if any condition in this list is - * fulfilled, form submission is prevented. - * @param {Object} form Form object - * @returns {Array} Array of conditions to prevent submission + * Parse logic to get a list of conditions where, if any condition in this list + * is fulfilled, form submission is prevented. + * @param form the form document to check + * @returns array of conditions that prevent submission, can be empty */ const getPreventSubmitConditions = ( form: IForm, ): IPreventSubmitLogicSchema[] => { const formFieldIds = new Set( - form.form_fields.map((field) => String(field._id)), + form.form_fields?.map((field) => String(field._id)), ) - return form.form_logics.filter((formLogic) => { - return ( - isPreventSubmitLogic(formLogic) && - allConditionsExist(formLogic.conditions, formFieldIds) - ) - }) + const preventFormLogics = + form.form_logics?.filter( + (formLogic) => + isPreventSubmitLogic(formLogic) && + allConditionsExist(formLogic.conditions, formFieldIds), + ) ?? [] + + return preventFormLogics } /** * Determines whether the submission should be prevented by form logic. If so, * return the condition preventing the submission. If not, return undefined. - * @param {Array} submission - form_fields (on client), or req.body.responses (on server) - * @param {Object} form Form object - * @param {Set} [visibleFieldIds] Optional set of currently visible fields. If this is not - * provided, the function recomputes it. - * @returns {Object} Condition if submission is to prevented, otherwise undefined + * @param submission the submission responses to retrieve logic units for. Can be `form_fields` (on client), or `req.body.responses` (on server) + * @param form the form document for the submission + * @param optionalVisibleFieldIds the optional set of currently visible fields. If this is not provided, it will be recomputed using the given form parameter. + * @returns a condition if submission is to prevented, otherwise `undefined` */ export const getLogicUnitPreventingSubmit = ( submission: LogicFieldArray, form: IForm, visibleFieldIds?: FieldIdSet, -): IPreventSubmitLogicSchema => { +): IPreventSubmitLogicSchema | undefined => { if (!visibleFieldIds) { visibleFieldIds = getVisibleFieldIds(submission, form) } const preventSubmitConditions = getPreventSubmitConditions(form) return preventSubmitConditions.find((logicUnit) => - isLogicUnitSatisfied(submission, logicUnit.conditions, visibleFieldIds), + // TODO (#317): remove usage of non-null assertion + isLogicUnitSatisfied(submission, logicUnit.conditions, visibleFieldIds!), ) } /** - * Checks if the field ids in logic's conditions all exist in the fieldIds - * - * @param {Array} conditions - * @param {Set} formFieldIds - * @returns {Boolean} + * Checks if the field ids in logic's conditions all exist in the fieldIds. + * @param conditions the list of conditions to check + * @param formFieldIds the set of form field ids to check + * @returns true if every condition's related form field id exists in the set of formFieldIds, false otherwise. */ const allConditionsExist = ( conditions: IConditionSchema[], @@ -158,13 +156,12 @@ const allConditionsExist = ( /** * Gets the IDs of visible fields in a form according to its responses. - * This function loops through all the form fields until the set of visible fields no longer - * changes. The first loop adds all the fields with no conditions attached, the second adds - * fields which are made visible due to fields added in the previous loop, and so on. - * @param {Array} submission - form_fields (on client), or req.body.responses (on server) - * @param {Object} form - Form object - * @var {Array} logicUnits - Array of logic units - * @returns {Set} Set of IDs of visible fields + * This function loops through all the form fields until the set of visible + * fields no longer changes. The first loop adds all the fields with no + * conditions attached, the second adds fields which are made visible due to fields added in the previous loop, and so on. + * @param submission the submission responses to retrieve logic units for. Can be `form_fields` (on client), or `req.body.responses` (on server) + * @param form the form document for the submission + * @returns a set of IDs of visible fields in the submission */ export const getVisibleFieldIds = ( submission: LogicFieldArray, @@ -176,10 +173,12 @@ export const getVisibleFieldIds = ( let changesMade = true while (changesMade) { changesMade = false - form.form_fields.forEach((field) => { + form.form_fields?.forEach((field) => { const logicUnits = logicUnitsGroupedByField[String(field._id)] - // If a field's visibility does not have any conditions, it is always visible. - // Otherwise, a field's visibility can be toggled by a combination of conditions. + // If a field's visibility does not have any conditions, it is always + // visible. + // Otherwise, a field's visibility can be toggled by a combination of + // conditions. // Eg. the following are logicUnits - just one of them has to be satisfied // 1) Show X if Y=yes and Z=yes // Or @@ -201,9 +200,10 @@ export const getVisibleFieldIds = ( /** * Checks if an array of conditions is satisfied. - * @param {Object} submission - form_fields (on client), or req.body.responses (on server) - * @param {Object} logicUnit - Object containing the conditions specified in a single modal of `add new logic` on the form logic tab - * @param {Set} visibleFieldIds - Set of field IDs that are visible, which is used to ensure that conditions are visible + * @param submission the submission responses to retrieve logic units for. Can be `form_fields` (on client), or `req.body.responses` (on server) + * @param logicUnit an object containing the conditions specified in a single modal of `add new logic` on the form logic tab + * @param visibleFieldIds the set of field IDs that are visible, which is used to ensure that conditions are visible + * @returns true if all the conditions are satisfied, false otherwise */ const isLogicUnitSatisfied = ( submission: LogicFieldArray, @@ -220,7 +220,9 @@ const isLogicUnitSatisfied = ( }) } -const getCurrentValue = (field: LogicField): string => { +const getCurrentValue = ( + field: LogicField, +): string | null | undefined | string[] => { if ('fieldValue' in field) { // client return field.fieldValue @@ -250,11 +252,16 @@ const isConditionFulfilled = ( currentValue.length === 0 ) { return false - } else if ( - condition.state === 'is equals to' || - condition.state === 'is either' + } + + if ( + condition.state === LogicConditionState.Equal || + condition.state === LogicConditionState.Either ) { - const conditionValues = [].concat(condition.value).map(String) // condition.value can be a string (is equals to), or an array (is either) + // condition.value can be a string (is equals to), or an array (is either) + const conditionValues = ([] as unknown[]) + .concat(condition.value) + .map(String) currentValue = String(currentValue) /* Handling 'Others' for radiobutton @@ -293,16 +300,16 @@ const isConditionFulfilled = ( } /** - * Find the field in the current submission corresponding to the condition to be checked - * - * @param {Array} submission - form_fields (on client), or req.body.responses (on server) - * @param {String} fieldId - id of condition field - * @returns + * Find the field in the current submission corresponding to the condition to be + * checked. + * @param submission the submission responses to retrieve logic units for. Can be `form_fields` (on client), or `req.body.responses` (on server) + * @param fieldId the id of condition field to find + * @returns the condition field if it exists, `undefined` otherwise */ const findConditionField = ( submission: LogicFieldArray, fieldId: IConditionSchema['field'], -): LogicField => { +): LogicField | undefined => { return submission.find( (submittedField) => String(submittedField._id) === String(fieldId), ) diff --git a/src/shared/util/phone-num-validation.ts b/src/shared/util/phone-num-validation.ts index 7bd51f93b3..ec80919053 100644 --- a/src/shared/util/phone-num-validation.ts +++ b/src/shared/util/phone-num-validation.ts @@ -39,12 +39,16 @@ export const isMobilePhoneNumber = (mobileNumber: string): boolean => { ) } + // Not Singapore number, check type and early return if undefined. + const parsedType = parsedNumber.getType() + if (!parsedType) return false + // All other countries uses number type to check for validity. return ( isPhoneNumber(mobileNumber) && // Have to include both MOBILE, FIXED_LINE_OR_MOBILE as some countries lump // the types together. - ['FIXED_LINE_OR_MOBILE', 'MOBILE'].includes(parsedNumber.getType()) + ['FIXED_LINE_OR_MOBILE', 'MOBILE'].includes(parsedType) ) } diff --git a/src/shared/util/stringify-safe.ts b/src/shared/util/stringify-safe.ts index 8e86d84413..131c7a1163 100644 --- a/src/shared/util/stringify-safe.ts +++ b/src/shared/util/stringify-safe.ts @@ -1,18 +1,21 @@ import stringify from 'json-stringify-safe' /** - * JSON.stringify docs: + * `JSON.stringify` docs: * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify * - * JSON.stringify throws an exception in two cases: if circular references are found, - * and if a value is of type 'bigint'. This function wraps JSON.stringify in checks - * to make sure circular references are dealt with (by the json-stringify-safe - * library) and BigInts are converted to Numbers, so JSON.stringify does not throw - * any errors. It is useful for stringifying objects which are passed to us by - * external systems, e.g. HTTP responses. + * `JSON.stringify` throws an exception in two cases: if circular references are + * found, and if a value is of type `bigint`. * - * Currently does not support the replacer or spaces arguments to JSON.stringify. - * @param obj Object to be stringified + * This function wraps JSON.stringify + * in checks to make sure circular references are dealt with (by the + * `json-stringify-safe` library) and `BigInts` are converted to `Numbers`, so + * `JSON.stringify` does not throw any errors. It is useful for stringifying + * objects which are passed to us by external systems, e.g. HTTP responses. + * + * Currently does not support the replacer or spaces arguments to + * JSON.stringify. + * @param obj the object to be stringified */ export const stringifySafe = (obj: any): string => { const bigIntReplacer = (_key: any, value: any): any => { diff --git a/src/shared/util/verified-content.ts b/src/shared/util/verified-content.ts index f29cb14483..e276b8d4d9 100644 --- a/src/shared/util/verified-content.ts +++ b/src/shared/util/verified-content.ts @@ -35,7 +35,7 @@ const CpVerifiedKeys: ICpVerifiedKeys = { // Array determines the order to process and display the verified fields in both // the detailed responses page and the csv file. -export const CURRENT_VERIFIED_FIELDS: VerifiedKeys[] = [] +export const CURRENT_VERIFIED_FIELDS: VerifiedKeys[] = ([] as VerifiedKeys[]) .concat(values(SpVerifiedKeys)) .concat(values(CpVerifiedKeys)) @@ -68,10 +68,7 @@ const getVerifiedKeyMap = (type?: 'SP' | 'CP'): VerifiedKeyMap => { * @param newKeys The oldKey-newKey mapping * @returns A new object with the renamed keys */ -const renameKeys = ( - obj: Record, - newKeys: VerifiedKeyMap, -): Record => { +const renameKeys = (obj: Record, newKeys: Record) => { const keyValues = Object.keys(obj).map((key) => { const newKey = newKeys[key] || key return { [newKey]: obj[key] } @@ -99,10 +96,7 @@ export const mapDataToKey = ({ data, }: IMappableData): Record => { const fieldMap = getVerifiedKeyMap(type) - const subsetKeys = pick(data, Object.keys(fieldMap)) as Record< - VerifiedKeys, - unknown - > + const subsetKeys = pick(data, Object.keys(fieldMap)) return renameKeys(subsetKeys, fieldMap) } diff --git a/src/types/admin_verification.ts b/src/types/admin_verification.ts index a432ee041b..17c9b350af 100644 --- a/src/types/admin_verification.ts +++ b/src/types/admin_verification.ts @@ -9,15 +9,21 @@ export interface IAdminVerification { expireAt: Date numOtpAttempts?: number numOtpSent?: number - _id?: Document['_id'] } export interface IAdminVerificationSchema extends IAdminVerification, Document { - _id: Document['_id'] createdAt?: Date updatedAt?: Date } +// Fully created document with defaults populated. +export interface IAdminVerificationDoc extends IAdminVerificationSchema { + createdAt: Date + updatedAt: Date + numOtpAttempts: number + numOtpSent: number +} + export type UpsertOtpParams = Pick< IAdminVerificationSchema, 'hashedOtp' | 'hashedContact' | 'admin' | 'expireAt' @@ -27,5 +33,5 @@ export interface IAdminVerificationModel upsertOtp: (params: UpsertOtpParams) => Promise incrementAttemptsByAdminId: ( adminId: IUserSchema['_id'], - ) => Promise + ) => Promise } diff --git a/src/types/form.ts b/src/types/form.ts index 0e83e0639a..8c1de9af5f 100644 --- a/src/types/form.ts +++ b/src/types/form.ts @@ -109,7 +109,7 @@ export interface IFormSchema extends IForm, Document { } export interface IPopulatedForm extends IFormSchema { - admin: IPopulatedUser | null + admin: IPopulatedUser } export interface IEncryptedForm extends IForm { diff --git a/src/types/submission.ts b/src/types/submission.ts index ff38a680ad..70cf5bd3a7 100644 --- a/src/types/submission.ts +++ b/src/types/submission.ts @@ -31,10 +31,10 @@ export interface ISubmission { export interface WebhookData { formId: string submissionId: string - encryptedContent: string - verifiedContent: string - version: number - created: Date + encryptedContent: IEncryptedSubmissionSchema['encryptedContent'] + verifiedContent: IEncryptedSubmissionSchema['verifiedContent'] + version: IEncryptedSubmissionSchema['version'] + created: IEncryptedSubmissionSchema['created'] } export interface WebhookView { diff --git a/src/types/vendor/aws-info.d.ts b/src/types/vendor/aws-info.d.ts new file mode 100644 index 0000000000..4657e95c7f --- /dev/null +++ b/src/types/vendor/aws-info.d.ts @@ -0,0 +1,12 @@ +declare module 'aws-info' { + type Data = { + regions: Record + services: Record + } + + export const data: Data + + export function endpoint(serviceName: string, regionName: string): string + + export function regionName(regionNameShort: string): string +} diff --git a/src/types/vendor/bson-ext.d.ts b/src/types/vendor/bson-ext.d.ts new file mode 100644 index 0000000000..e80b6acf20 --- /dev/null +++ b/src/types/vendor/bson-ext.d.ts @@ -0,0 +1,508 @@ +/* eslint-disable @typescript-eslint/no-empty-function */ +/* eslint-disable @typescript-eslint/ban-types */ +// Internal type definitions for bson-ext 2.0.3 +// !!! Typings are not verified !!! +// Definitions retrieved from https://www.npmjs.com/package/@types/bson and +// typed to follow bson-ext's exports. +/// + +declare module 'bson-ext' { + interface CommonSerializeOptions { + /** {default:false}, the serializer will check if keys are valid. */ + checkKeys?: boolean + /** {default:false}, serialize the javascript functions. */ + serializeFunctions?: boolean + /** {default:true}, ignore undefined fields. */ + ignoreUndefined?: boolean + } + + export interface SerializeOptions extends CommonSerializeOptions { + /** {default:1024*1024*17}, minimum size of the internal temporary serialization buffer. */ + minInternalBufferSize?: number + } + + export interface SerializeWithBufferAndIndexOptions + extends CommonSerializeOptions { + /** {default:0}, the index in the buffer where we wish to start serializing into. */ + index?: number + } + + export interface DeserializeOptions { + /** {default:false}, evaluate functions in the BSON document scoped to the object deserialized. */ + evalFunctions?: boolean + /** {default:false}, cache evaluated functions for reuse. */ + cacheFunctions?: boolean + /** {default:false}, use a crc32 code for caching, otherwise use the string of the function. */ + cacheFunctionsCrc32?: boolean + /** {default:true}, when deserializing a Long will fit it into a Number if it's smaller than 53 bits. */ + promoteLongs?: boolean + /** {default:false}, deserialize Binary data directly into node.js Buffer object. */ + promoteBuffers?: boolean + /** {default:false}, when deserializing will promote BSON values to their Node.js closest equivalent types. */ + promoteValues?: boolean + /** {default:null}, allow to specify if there what fields we wish to return as unserialized raw buffer. */ + fieldsAsRaw?: { readonly [fieldName: string]: boolean } + /** {default:false}, return BSON regular expressions as BSONRegExp instances. */ + bsonRegExp?: boolean + /** {default:false}, allows the buffer to be larger than the parsed BSON object. */ + allowObjectSmallerThanBufferSize?: boolean + } + + export interface CalculateObjectSizeOptions { + /** {default:false}, serialize the javascript functions */ + serializeFunctions?: boolean + /** {default:true}, ignore undefined fields. */ + ignoreUndefined?: boolean + } + + /** + * Base class for Long and Timestamp. + * In original js-node@1.0.x code 'Timestamp' is a 100% copy-paste of 'Long' + * with 'Long' replaced by 'Timestamp' (changed to inheritance in js-node@2.0.0) + */ + class LongLike { + /** + * @param low The low (signed) 32 bits. + * @param high The high (signed) 32 bits. + */ + constructor(low: number, high: number) + + /** Returns the sum of `this` and the `other`. */ + add(other: T): T + /** Returns the bitwise-AND of `this` and the `other`. */ + and(other: T): T + /** + * Compares `this` with the given `other`. + * @returns 0 if they are the same, 1 if the this is greater, and -1 if the given one is greater. + */ + compare(other: T): number + /** Returns `this` divided by the given `other`. */ + div(other: T): T + /** Return whether `this` equals the `other` */ + equals(other: T): boolean + /** Return the high 32-bits value. */ + getHighBits(): number + /** Return the low 32-bits value. */ + getLowBits(): number + /** Return the low unsigned 32-bits value. */ + getLowBitsUnsigned(): number + /** Returns the number of bits needed to represent the absolute value of `this`. */ + getNumBitsAbs(): number + /** Return whether `this` is greater than the `other`. */ + greaterThan(other: T): boolean + /** Return whether `this` is greater than or equal to the `other`. */ + greaterThanOrEqual(other: T): boolean + /** Return whether `this` value is negative. */ + isNegative(): boolean + /** Return whether `this` value is odd. */ + isOdd(): boolean + /** Return whether `this` value is zero. */ + isZero(): boolean + /** Return whether `this` is less than the `other`. */ + lessThan(other: T): boolean + /** Return whether `this` is less than or equal to the `other`. */ + lessThanOrEqual(other: T): boolean + /** Returns `this` modulo the given `other`. */ + modulo(other: T): T + /** Returns the product of `this` and the given `other`. */ + multiply(other: T): T + /** The negation of this value. */ + negate(): T + /** The bitwise-NOT of this value. */ + not(): T + /** Return whether `this` does not equal to the `other`. */ + notEquals(other: T): boolean + /** Returns the bitwise-OR of `this` and the given `other`. */ + or(other: T): T + /** + * Returns `this` with bits shifted to the left by the given amount. + * @param numBits The number of bits by which to shift. + */ + shiftLeft(numBits: number): T + /** + * Returns `this` with bits shifted to the right by the given amount. + * @param numBits The number of bits by which to shift. + */ + shiftRight(numBits: number): T + /** + * Returns `this` with bits shifted to the right by the given amount, with the new top bits matching the current sign bit. + * @param numBits The number of bits by which to shift. + */ + shiftRightUnsigned(numBits: number): T + /** Returns the difference of `this` and the given `other`. */ + subtract(other: T): T + /** Return the int value (low 32 bits). */ + toInt(): number + /** Return the JSON value. */ + toJSON(): string + /** Returns closest floating-point representation to `this` value */ + toNumber(): number + /** + * Return as a string + * @param radix the radix in which the text should be written. {default:10} + */ + toString(radix?: number): string + /** Returns the bitwise-XOR of `this` and the given `other`. */ + xor(other: T): T + } + + /** A class representation of the BSON Binary type. */ + export class Binary { + static readonly SUBTYPE_DEFAULT: number + static readonly SUBTYPE_FUNCTION: number + static readonly SUBTYPE_BYTE_ARRAY: number + static readonly SUBTYPE_UUID_OLD: number + static readonly SUBTYPE_UUID: number + static readonly SUBTYPE_MD5: number + static readonly SUBTYPE_USER_DEFINED: number + + /** + * @param buffer A buffer object containing the binary data + * @param subType Binary data subtype + */ + constructor(buffer: Buffer, subType?: number) + + /** The underlying Buffer which stores the binary data. */ + readonly buffer: Buffer + /** Binary data subtype */ + readonly sub_type?: number + + /** The length of the binary. */ + length(): number + /** Updates this binary with byte_value */ + put(byte_value: number | string): void + /** Reads length bytes starting at position. */ + read(position: number, length: number): Buffer + /** Returns the value of this binary as a string. */ + value(): string + /** Writes a buffer or string to the binary */ + write(buffer: Buffer | string, offset: number): void + } + + /** A class representation of the BSON Code type. */ + export class Code { + /** + * @param code A string or function. + * @param scope An optional scope for the function. + */ + constructor(code: string | Function, scope?: any) + + readonly code: string | Function + readonly scope?: any + } + + /** + * A class representation of the BSON DBRef type. + */ + export class DBRef { + /** + * @param namespace The collection name. + * @param oid The reference ObjectId. + * @param db Optional db name, if omitted the reference is local to the current db + */ + constructor(namespace: string, oid: ObjectId, db?: string) + namespace: string + oid: ObjectId + db?: string + } + + /** A class representation of the BSON Double type. */ + export class Double { + /** + * @param value The number we want to represent as a double. + */ + constructor(value: number) + + /** + * https://github.com/mongodb/js-bson/blob/master/lib/double.js#L17 + */ + value: number + + valueOf(): number + } + + /** A class representation of the BSON Int32 type. */ + export class Int32 { + /** + * @param value The number we want to represent as an int32. + */ + constructor(value: number) + + valueOf(): number + } + + /** A class representation of the BSON Decimal128 type. */ + export class Decimal128 { + /** Create a Decimal128 instance from a string representation. */ + static fromString(s: string): Decimal128 + + /** + * @param bytes A buffer containing the raw Decimal128 bytes. + */ + constructor(bytes: Buffer) + + /** A buffer containing the raw Decimal128 bytes. */ + readonly bytes: Buffer + + toJSON(): string + toString(): string + } + + /** + * A class representation of the BSON Long type, a 64-bit two's-complement + * integer value, which faithfully simulates the behavior of a Java "Long". This + * implementation is derived from LongLib in GWT. + */ + export class Long extends LongLike { + static readonly MAX_VALUE: Long + static readonly MIN_VALUE: Long + static readonly NEG_ONE: Long + static readonly ONE: Long + static readonly ZERO: Long + + /** Returns a Long representing the given (32-bit) integer value. */ + static fromInt(i: number): Long + /** Returns a Long representing the given value, provided that it is a finite number. Otherwise, zero is returned. */ + static fromNumber(n: number): Long + /** + * Returns a Long representing the 64-bit integer that comes by concatenating the given high and low bits. Each is assumed to use 32 bits. + * @param lowBits The low 32-bits. + * @param highBits The high 32-bits. + */ + static fromBits(lowBits: number, highBits: number): Long + /** + * Returns a Long representation of the given string + * @param opt_radix The radix in which the text is written. {default:10} + */ + static fromString(s: string, opt_radix?: number): Long + } + + /** A class representation of the BSON MaxKey type. */ + export class MaxKey { + constructor() + } + + /** A class representation of the BSON MinKey type. */ + export class MinKey { + constructor() + } + + /** A class representation of the BSON ObjectId type. */ + export class ObjectId { + /** + * Create a new ObjectId instance + * @param {(string|number|ObjectId)} id Can be a 24 byte hex string, 12 byte binary string or a Number. + */ + constructor(id?: string | number | ObjectId) + /** The generation time of this ObjectId instance */ + generationTime: number + /** If true cache the hex string representation of ObjectId */ + static cacheHexString?: boolean + /** + * Creates an ObjectId from a hex string representation of an ObjectId. + * @param {string} hexString create a ObjectId from a passed in 24 byte hexstring. + * @return {ObjectId} return the created ObjectId + */ + static createFromHexString(hexString: string): ObjectId + /** + * Creates an ObjectId from a second based number, with the rest of the ObjectId zeroed out. Used for comparisons or sorting the ObjectId. + * @param {number} time an integer number representing a number of seconds. + * @return {ObjectId} return the created ObjectId + */ + static createFromTime(time: number): ObjectId + /** + * Checks if a value is a valid bson ObjectId + * + * @return {boolean} return true if the value is a valid bson ObjectId, return false otherwise. + */ + static isValid(id: string | number | ObjectId): boolean + /** + * Compares the equality of this ObjectId with `otherID`. + * @param {ObjectId|string} otherID ObjectId instance to compare against. + * @return {boolean} the result of comparing two ObjectId's + */ + equals(otherID: ObjectId | string): boolean + /** + * Generate a 12 byte id string used in ObjectId's + * @param {number} time optional parameter allowing to pass in a second based timestamp. + * @return {string} return the 12 byte id binary string. + */ + static generate(time?: number): Buffer + /** + * Returns the generation date (accurate up to the second) that this ID was generated. + * @return {Date} the generation date + */ + getTimestamp(): Date + /** + * Return the ObjectId id as a 24 byte hex string representation + * @return {string} return the 24 byte hex string representation. + */ + toHexString(): string + } + + /** A class representation of the BSON RegExp type. */ + export class BSONRegExp { + constructor(pattern: string, options: string) + + readonly pattern: string + readonly options: string + } + + /** + * A class representation of the BSON Symbol type. + * @deprecated + */ + export class Symbol { + constructor(value: string) + + /** Access the wrapped string value. */ + valueOf(): string + } + + /** A class representation of the BSON Timestamp type. */ + export class Timestamp extends LongLike { + static readonly MAX_VALUE: Timestamp + static readonly MIN_VALUE: Timestamp + static readonly NEG_ONE: Timestamp + static readonly ONE: Timestamp + static readonly ZERO: Timestamp + + /** Returns a Timestamp represented by the given (32-bit) integer value */ + static fromInt(value: number): Timestamp + /** Returns a Timestamp representing the given number value, provided that it is a finite number. */ + static fromNumber(value: number): Timestamp + /** + * Returns a Timestamp for the given high and low bits. Each is assumed to use 32 bits. + * @param lowBits The low 32-bits. + * @param highBits The high 32-bits. + */ + static fromBits(lowBits: number, highBits: number): Timestamp + /** + * Returns a Timestamp from the given string. + * @param opt_radix The radix in which the text is written. {default:10} + */ + static fromString(str: string, opt_radix?: number): Timestamp + } + + /** + * A class representation of the BSON Map type. + * @deprecated + */ + export class Map { + constructor() + } + + export default class BSON { + constructor(types: any[]) {} + + // BSON MAX VALUES + static readonly BSON_INT32_MAX = 0x7fffffff + static readonly BSON_INT32_MIN = -0x80000000 + + static readonly BSON_INT64_MAX = Math.pow(2, 63) - 1 + static readonly BSON_INT64_MIN = -Math.pow(2, 63) + + // JS MAX PRECISE VALUES + static readonly JS_INT_MAX = 0x20000000000000 // Any integer up to 2^53 can be precisely represented by a double. + static readonly JS_INT_MIN = -0x20000000000000 // Any integer down to -2^53 can be precisely represented by a double. + + static Binary = Binary + static Code = Code + static DBRef = DBRef + static Decimal128 = Decimal128 + static Double = Double + static Int32 = Int32 + static Long = Long + /** @deprecated */ + static Map = Map + static MaxKey = MaxKey + static MinKey = MinKey + static ObjectId = ObjectId + // special case for deprecated names + /** @deprecated */ + static ObjectID = ObjectId + static BSONRegExp = BSONRegExp + /** @deprecated */ + static Symbol = Symbol + static Timestamp = Timestamp + + // Just add constants to the Native BSON parser + static readonly BSON_BINARY_SUBTYPE_DEFAULT = 0 + static readonly BSON_BINARY_SUBTYPE_FUNCTION = 1 + static readonly BSON_BINARY_SUBTYPE_BYTE_ARRAY = 2 + static readonly BSON_BINARY_SUBTYPE_UUID = 3 + static readonly BSON_BINARY_SUBTYPE_MD5 = 4 + static readonly BSON_BINARY_SUBTYPE_USER_DEFINED = 128 + + /** + * Calculate the bson size for a passed in Javascript object. + * + * @param {Object} object the Javascript object to calculate the BSON byte size for. + * @param {CalculateObjectSizeOptions} Options + * @return {Number} returns the number of bytes the BSON object will take up. + */ + calculateObjectSize( + object: any, + options?: CalculateObjectSizeOptions, + ): number + + /** + * Serialize a Javascript object. + * + * @param object The Javascript object to serialize. + * @param options Serialize options. + * @return The Buffer object containing the serialized object. + */ + serialize(object: any, options?: SerializeOptions): Buffer + + /** + * Serialize a Javascript object using a predefined Buffer and index into the buffer, useful when pre-allocating the space for serialization. + * + * @param object The Javascript object to serialize. + * @param buffer The Buffer you pre-allocated to store the serialized BSON object. + * @param options Serialize options. + * @returns The index pointing to the last written byte in the buffer + */ + serializeWithBufferAndIndex( + object: any, + buffer: Buffer, + options?: SerializeWithBufferAndIndexOptions, + ): number + + /** + * Deserialize data as BSON. + * + * @param buffer The buffer containing the serialized set of BSON documents. + * @param options Deserialize options. + * @returns The deserialized Javascript Object. + */ + deserialize(buffer: Buffer, options?: DeserializeOptions): any + + /** + * Deserialize stream data as BSON documents. + * + * @param data The buffer containing the serialized set of BSON documents. + * @param startIndex The start index in the data Buffer where the deserialization is to start. + * @param numberOfDocuments Number of documents to deserialize + * @param documents An array where to store the deserialized documents + * @param docStartIndex The index in the documents array from where to start inserting documents + * @param options Additional options used for the deserialization + * @returns The next index in the buffer after deserialization of the `numberOfDocuments` + */ + deserializeStream( + data: Buffer, + startIndex: number, + numberOfDocuments: number, + documents: Array, + docStartIndex: number, + options?: DeserializeOptions, + ): number + } + + /** + * ObjectID (with capital "D") is deprecated. Use ObjectId (lowercase "d") + * instead. + * @deprecated + */ + export { ObjectId as ObjectID } +} diff --git a/src/types/vendor/convict-format-with-validator.d.ts b/src/types/vendor/convict-format-with-validator.d.ts new file mode 100644 index 0000000000..afe9b43f8c --- /dev/null +++ b/src/types/vendor/convict-format-with-validator.d.ts @@ -0,0 +1,22 @@ +declare module 'convict-format-with-validator' { + function coerce(v): string + function validate(x): void + + export const url = { + name: 'url' as const, + coerce, + validate, + } + + export const ipaddress = { + name: 'ipaddress' as const, + coerce, + validate, + } + + export const email = { + name: 'email' as const, + coerce, + validate, + } +} diff --git a/src/types/vendor/express-device.d.ts b/src/types/vendor/express-device.d.ts new file mode 100644 index 0000000000..3fa6cd4e15 --- /dev/null +++ b/src/types/vendor/express-device.d.ts @@ -0,0 +1,23 @@ +declare module 'express-device' { + import { RequestHandler } from 'express' + + type UserAgentDevice = 'desktop' | 'tv' | 'tablet' | 'phone' | 'bot' | 'car' + + type CaptureOptions = { + emptyUserAgentDeviceType?: UserAgentDevice + unknownUserAgentDeviceType?: UserAgentDevice + botUserAgentDeviceType?: UserAgentDevice + carUserAgentDeviceType?: UserAgentDevice + parseUserAgent?: boolean + } + + function capture(options: CaptureOptions): RequestHandler + + // This typing is incomplete, to be typed when other functionality is needed. + // See https://github.com/rguerreiro/express-device/blob/master/lib/device.js + // for the module exports. + + export default { + capture, + } +} diff --git a/src/types/verification.ts b/src/types/verification.ts index 9d728784c3..570706987e 100644 --- a/src/types/verification.ts +++ b/src/types/verification.ts @@ -3,11 +3,15 @@ import { Document } from 'mongoose' import { IFormSchema } from './form' export interface IVerificationField { + // _id is basically a generated transactionId, so it has to be a string, + // instead of being converted to a string from ObjectId. + // This must be a string, or transaction fetching will fail. + _id: string fieldType: string - signedData: string | null - hashedOtp: string | null - hashCreatedAt: Date | null - hashRetries: number + signedData?: string | null + hashedOtp?: string | null + hashCreatedAt?: Date | null + hashRetries?: number } export interface IVerificationFieldSchema extends IVerificationField, Document { @@ -19,7 +23,7 @@ export interface IVerificationFieldSchema extends IVerificationField, Document { export interface IVerification { formId: IFormSchema['_id'] - expireAt: Date + expireAt?: Date fields: IVerificationFieldSchema[] } diff --git a/tests/unit/backend/helpers/jest-db.ts b/tests/unit/backend/helpers/jest-db.ts index 996ca47731..49b286cd26 100644 --- a/tests/unit/backend/helpers/jest-db.ts +++ b/tests/unit/backend/helpers/jest-db.ts @@ -1,4 +1,6 @@ +// @ts-ignore import mongoSetup from '@shelf/jest-mongodb/setup' +// @ts-ignore import mongoTeardown from '@shelf/jest-mongodb/teardown' import { ObjectID } from 'bson' import mongoose from 'mongoose' @@ -14,7 +16,7 @@ const connect = async () => { // Do it here so each test can have it's own mongoose instance. await mongoSetup() // process.env.MONGO_URL is now set by jest-mongodb. - const conn = await mongoose.connect(process.env.MONGO_URL, { + const conn = await mongoose.connect(process.env.MONGO_URL!, { useNewUrlParser: true, useUnifiedTopology: true, useCreateIndex: true, diff --git a/tests/unit/backend/helpers/jest-express.ts b/tests/unit/backend/helpers/jest-express.ts index 6b04951830..46672e5324 100644 --- a/tests/unit/backend/helpers/jest-express.ts +++ b/tests/unit/backend/helpers/jest-express.ts @@ -1,12 +1,12 @@ import { Request, Response } from 'express' -const mockRequest = ({ - body, +const mockRequest =

, B>({ params, + body, session, }: { - body?: Record - params?: Record + params?: P + body?: B session?: any } = {}) => { return { @@ -15,9 +15,9 @@ const mockRequest = ({ session: session ?? {}, get(name: string) { if (name === 'cf-connecting-ip') return 'MOCK_IP' - return null + return undefined }, - } as Request + } as Request } const mockResponse = (extraArgs: Partial> = {}) => { diff --git a/tests/unit/backend/models/admin_verification.server.model.spec.ts b/tests/unit/backend/models/admin_verification.server.model.spec.ts index d14b12ccdb..5476933b23 100644 --- a/tests/unit/backend/models/admin_verification.server.model.spec.ts +++ b/tests/unit/backend/models/admin_verification.server.model.spec.ts @@ -87,6 +87,7 @@ describe('AdminVerification Model', () => { } // Act + // @ts-ignore const actualPromise = AdminVerification.create(missingContactParams) // Assert @@ -103,6 +104,7 @@ describe('AdminVerification Model', () => { } // Act + // @ts-ignore const actualPromise = AdminVerification.create(missingOtpParams) // Assert @@ -119,6 +121,7 @@ describe('AdminVerification Model', () => { } // Act + // @ts-ignore const actualPromise = AdminVerification.create(missingExpireParams) // Assert diff --git a/tests/unit/backend/models/form.server.model.spec.ts b/tests/unit/backend/models/form.server.model.spec.ts index 2ddf825d5c..02c8e926fb 100644 --- a/tests/unit/backend/models/form.server.model.spec.ts +++ b/tests/unit/backend/models/form.server.model.spec.ts @@ -10,6 +10,7 @@ import { IAgencySchema, IEncryptedForm, IUserSchema, + Permission, ResponseMode, } from 'src/types' @@ -167,7 +168,9 @@ describe('Form Model', () => { // Remove indeterministic id from actual permission list const actualPermissionList = saved .toObject() - .permissionList.map((permission) => omit(permission, '_id')) + .permissionList!.map((permission: Permission[]) => + omit(permission, '_id'), + ) expect(actualPermissionList).toEqual(permissionList) }) @@ -351,7 +354,7 @@ describe('Form Model', () => { expect(actualSavedObject).toEqual(expectedObject) // Remove indeterministic id from actual permission list - const actualPermissionList = (saved.toObject() as IEncryptedForm).permissionList.map( + const actualPermissionList = (saved.toObject() as IEncryptedForm).permissionList!.map( (permission) => omit(permission, '_id'), ) expect(actualPermissionList).toEqual(permissionList) @@ -555,7 +558,9 @@ describe('Form Model', () => { // Remove indeterministic id from actual permission list const actualPermissionList = saved .toObject() - .permissionList.map((permission) => omit(permission, '_id')) + .permissionList!.map((permission: Permission[]) => + omit(permission, '_id'), + ) expect(actualPermissionList).toEqual(permissionList) }) @@ -690,7 +695,7 @@ describe('Form Model', () => { const form = (await Form.create(emailFormParams)).toObject() // Act - const actualForm = (await Form.getFullFormById(form._id)).toObject() + const actualForm = (await Form.getFullFormById(form._id))!.toObject() // Assert // Form should be returned @@ -721,7 +726,7 @@ describe('Form Model', () => { const form = (await Form.create(encryptFormParams)).toObject() // Act - const actualForm = (await Form.getFullFormById(form._id)).toObject() + const actualForm = (await Form.getFullFormById(form._id))!.toObject() // Assert // Form should be returned diff --git a/tests/unit/backend/models/form_fields.schema.spec.ts b/tests/unit/backend/models/form_fields.schema.spec.ts index ff0cd9b410..04f96228b2 100644 --- a/tests/unit/backend/models/form_fields.schema.spec.ts +++ b/tests/unit/backend/models/form_fields.schema.spec.ts @@ -2,7 +2,7 @@ import { ObjectID } from 'bson' import mongoose from 'mongoose' import getFormModel from 'src/app/models/form.server.model' -import { BasicField, ResponseMode } from 'src/types' +import { BasicField, IFieldSchema, ResponseMode } from 'src/types' import dbHandler from '../helpers/jest-db' @@ -121,9 +121,10 @@ const createAndReturnFormField = async ( const formParam = { ...baseParams, - form_fields: [formFieldParams], + responseMode: formType, + form_fields: [formFieldParams] as IFieldSchema[], } const form = await Form.create(formParam) - return form.form_fields[0] + return form.form_fields![0] } diff --git a/tests/unit/backend/models/sms_count.server.model.spec.ts b/tests/unit/backend/models/sms_count.server.model.spec.ts index 5643225324..a3faddf2d2 100644 --- a/tests/unit/backend/models/sms_count.server.model.spec.ts +++ b/tests/unit/backend/models/sms_count.server.model.spec.ts @@ -194,7 +194,7 @@ describe('SmsCount', () => { form: MOCK_FORM_ID, }).lean() - expect(actualLog._id).toBeDefined() + expect(actualLog!._id).toBeDefined() // Retrieve object and compare to params, remove indeterministic keys const actualSavedObject = omit(actualLog, ['_id', 'createdAt', '__v']) expect(actualSavedObject).toEqual(expectedLog) @@ -220,7 +220,7 @@ describe('SmsCount', () => { form: MOCK_FORM_ID, }).lean() - expect(actualLog._id).toBeDefined() + expect(actualLog!._id).toBeDefined() // Retrieve object and compare to params, remove indeterministic keys const actualSavedObject = omit(actualLog, ['_id', 'createdAt', '__v']) expect(actualSavedObject).toEqual(expectedLog) diff --git a/tests/unit/backend/modules/submission/submission.service.spec.ts b/tests/unit/backend/modules/submission/submission.service.spec.ts index 97936c8e34..ec61a325eb 100644 --- a/tests/unit/backend/modules/submission/submission.service.spec.ts +++ b/tests/unit/backend/modules/submission/submission.service.spec.ts @@ -13,6 +13,7 @@ import { FieldResponse, IEmailFormSchema, IEncryptedFormSchema, + IFieldSchema, IPreventSubmitLogicSchema, ISingleAnswerResponse, LogicType, @@ -32,12 +33,12 @@ const MOCK_FORM_PARAMS = { const MOCK_ENCRYPTED_FORM_PARAMS = { ...MOCK_FORM_PARAMS, publicKey: 'mockPublicKey', - responseMode: 'encrypt', + responseMode: ResponseMode.Encrypt, } const MOCK_EMAIL_FORM_PARAMS = { ...MOCK_FORM_PARAMS, emails: ['test@example.com'], - responseMode: 'email', + responseMode: ResponseMode.Email, } // Declare here so the array is static. @@ -66,13 +67,14 @@ describe('submission.service', () => { defaultFormFields, ResponseMode.Email, )) as IEmailFormSchema + defaultEncryptForm = (await createAndReturnFormWithFields( defaultFormFields, ResponseMode.Encrypt, )) as IEncryptedFormSchema // Process default responses - defaultEmailResponses = defaultEmailForm.form_fields.map((field) => { + defaultEmailResponses = defaultEmailForm.form_fields!.map((field) => { return { _id: String(field._id), fieldType: field.fieldType, @@ -80,7 +82,8 @@ describe('submission.service', () => { answer: '', } }) - defaultEncryptResponses = defaultEncryptForm.form_fields.map((field) => { + + defaultEncryptResponses = defaultEncryptForm.form_fields!.map((field) => { return { _id: String(field._id), fieldType: field.fieldType, @@ -165,7 +168,7 @@ describe('submission.service', () => { isVisible: true, } - if (defaultEmailForm.form_fields[index].isVerifiable) { + if (defaultEmailForm.form_fields![index].isVerifiable) { expectedProcessed.isUserVerified = true } expectedParsed.push(expectedProcessed) @@ -178,10 +181,10 @@ describe('submission.service', () => { // Arrange const extraFieldForm = cloneDeep(defaultEmailForm) const secondMobileField = cloneDeep( - extraFieldForm.form_fields[TYPE_TO_INDEX_MAP[BasicField.Mobile]], + extraFieldForm.form_fields![TYPE_TO_INDEX_MAP[BasicField.Mobile]], ) secondMobileField._id = new ObjectID() - extraFieldForm.form_fields.push(secondMobileField) + extraFieldForm.form_fields!.push(secondMobileField) // Act + Assert expect(() => @@ -196,10 +199,10 @@ describe('submission.service', () => { // Arrange const extraFieldForm = cloneDeep(defaultEncryptForm) const secondMobileField = cloneDeep( - extraFieldForm.form_fields[TYPE_TO_INDEX_MAP[BasicField.Mobile]], + extraFieldForm.form_fields![TYPE_TO_INDEX_MAP[BasicField.Mobile]], ) secondMobileField._id = new ObjectID() - extraFieldForm.form_fields.push(secondMobileField) + extraFieldForm.form_fields!.push(secondMobileField) // Act + Assert expect(() => @@ -217,7 +220,7 @@ describe('submission.service', () => { const mobileFieldIndex = TYPE_TO_INDEX_MAP[BasicField.Mobile] const requireMobileEncryptForm = cloneDeep(defaultEncryptForm) - requireMobileEncryptForm.form_fields[mobileFieldIndex].required = true + requireMobileEncryptForm.form_fields![mobileFieldIndex].required = true // Act + Assert expect(() => @@ -233,7 +236,7 @@ describe('submission.service', () => { // Set NRIC field in form as required. const nricFieldIndex = TYPE_TO_INDEX_MAP[BasicField.Nric] const requireNricEmailForm = cloneDeep(defaultEmailForm) - requireNricEmailForm.form_fields[nricFieldIndex].required = true + requireNricEmailForm.form_fields![nricFieldIndex].required = true // Act + Assert expect(() => @@ -249,12 +252,12 @@ describe('submission.service', () => { // Mock logic util to return non-empty to check if error is thrown jest .spyOn(LogicUtil, 'getLogicUnitPreventingSubmit') - .mockReturnValueOnce({ + .mockReturnValueOnce(({ preventSubmitMessage: 'mock prevent submit', conditions: [], logicType: LogicType.PreventSubmit, _id: 'some id', - } as IPreventSubmitLogicSchema) + } as unknown) as IPreventSubmitLogicSchema) // Act + Assert expect(() => @@ -267,15 +270,17 @@ describe('submission.service', () => { it('should throw error when email form submission is prevented by logic', async () => { // Arrange - // Mock logic util to return non-empty to check if error is thrown + // Mock logic util to return non-empty to check if error is thrown. + const mockReturnLogicUnit = ({ + preventSubmitMessage: 'mock prevent submit', + conditions: [], + logicType: LogicType.PreventSubmit, + _id: 'some id', + } as unknown) as IPreventSubmitLogicSchema + jest .spyOn(LogicUtil, 'getLogicUnitPreventingSubmit') - .mockReturnValueOnce({ - preventSubmitMessage: 'mock prevent submit', - conditions: [], - logicType: LogicType.PreventSubmit, - _id: 'some id', - } as IPreventSubmitLogicSchema) + .mockReturnValueOnce(mockReturnLogicUnit) // Act + Assert expect(() => @@ -300,9 +305,6 @@ const createAndReturnFormWithFields = async ( break case ResponseMode.Encrypt: baseParams = MOCK_ENCRYPTED_FORM_PARAMS - break - default: - baseParams = MOCK_FORM_PARAMS } const processedParamList = formFieldParamsList.map((params) => { @@ -325,7 +327,7 @@ const createAndReturnFormWithFields = async ( const formParam = { ...baseParams, - form_fields: processedParamList, + form_fields: processedParamList as IFieldSchema[], } const form = await Form.create(formParam) diff --git a/tests/unit/backend/modules/submission/submission.utils.spec.ts b/tests/unit/backend/modules/submission/submission.utils.spec.ts index 854914e77b..0e7e9ed8b0 100644 --- a/tests/unit/backend/modules/submission/submission.utils.spec.ts +++ b/tests/unit/backend/modules/submission/submission.utils.spec.ts @@ -47,7 +47,7 @@ describe('submission.utils', () => { it('should throw error if called with invalid responseMode', async () => { // Act + Assert - expect(() => getModeFilter(undefined)).toThrowError( + expect(() => getModeFilter(undefined!)).toThrowError( 'getResponsesForEachField: Invalid response mode parameter', ) }) diff --git a/tests/unit/backend/modules/user/user.service.spec.ts b/tests/unit/backend/modules/user/user.service.spec.ts index c37e4e24d8..d14e0a8447 100644 --- a/tests/unit/backend/modules/user/user.service.spec.ts +++ b/tests/unit/backend/modules/user/user.service.spec.ts @@ -221,7 +221,7 @@ describe('user.service', () => { const actual = await UserService.getPopulatedUserById(USER_ID) // Assert - expect(actual.toObject()).toEqual(expected) + expect(actual!.toObject()).toEqual(expected) }) it('should return null when user cannot be found', async () => { diff --git a/tests/unit/backend/modules/verification/verification.controller.spec.ts b/tests/unit/backend/modules/verification/verification.controller.spec.ts index 6de8a16cfc..d70bce024e 100644 --- a/tests/unit/backend/modules/verification/verification.controller.spec.ts +++ b/tests/unit/backend/modules/verification/verification.controller.spec.ts @@ -33,12 +33,10 @@ const invalidOtpError = 'INVALID_OTP' describe('Verification controller', () => { describe('createTransaction', () => { - let mockReq - afterEach(() => jest.clearAllMocks()) - - beforeAll(() => { - mockReq = expressHandler.mockRequest({ body: { formId: MOCK_FORM_ID } }) + const MOCK_REQ = expressHandler.mockRequest({ + body: { formId: MOCK_FORM_ID }, }) + afterEach(() => jest.clearAllMocks()) it('should correctly return transaction when parameters are valid', async () => { const returnValue = { @@ -48,7 +46,7 @@ describe('Verification controller', () => { MockVfnService.createTransaction.mockReturnValueOnce( Promise.resolve(returnValue), ) - await createTransaction(mockReq, MOCK_RES, noop) + await createTransaction(MOCK_REQ, MOCK_RES, noop) expect(MockVfnService.createTransaction).toHaveBeenCalledWith( MOCK_FORM_ID, ) @@ -57,8 +55,8 @@ describe('Verification controller', () => { }) it('should correctly return 200 when transaction is not found', async () => { - MockVfnService.createTransaction.mockReturnValueOnce(null) - await createTransaction(mockReq, MOCK_RES, noop) + MockVfnService.createTransaction.mockResolvedValueOnce(null) + await createTransaction(MOCK_REQ, MOCK_RES, noop) expect(MockVfnService.createTransaction).toHaveBeenCalledWith( MOCK_FORM_ID, ) @@ -67,15 +65,11 @@ describe('Verification controller', () => { }) describe('getTransactionMetadata', () => { - let mockReq - afterEach(() => jest.clearAllMocks()) - - beforeAll(() => { - mockReq = expressHandler.mockRequest({ - body: {}, - params: { transactionId: MOCK_TRANSACTION_ID }, - }) + const MOCK_REQ = expressHandler.mockRequest({ + body: {}, + params: { transactionId: MOCK_TRANSACTION_ID }, }) + afterEach(() => jest.clearAllMocks()) it('should correctly return metadata when parameters are valid', async () => { // Coerce type @@ -85,7 +79,7 @@ describe('Verification controller', () => { MockVfnService.getTransactionMetadata.mockReturnValueOnce( Promise.resolve(transaction), ) - await getTransactionMetadata(mockReq, MOCK_RES, noop) + await getTransactionMetadata(MOCK_REQ, MOCK_RES, noop) expect(MockVfnService.getTransactionMetadata).toHaveBeenCalledWith( MOCK_TRANSACTION_ID, ) @@ -99,7 +93,7 @@ describe('Verification controller', () => { error.name = notFoundError throw error }) - await getTransactionMetadata(mockReq, MOCK_RES, noop) + await getTransactionMetadata(MOCK_REQ, MOCK_RES, noop) expect(MockVfnService.getTransactionMetadata).toHaveBeenCalledWith( MOCK_TRANSACTION_ID, ) @@ -109,22 +103,18 @@ describe('Verification controller', () => { }) describe('resetFieldInTransaction', () => { - let mockReq - afterEach(() => jest.clearAllMocks()) - - beforeAll(() => { - mockReq = expressHandler.mockRequest({ - body: { fieldId: MOCK_FIELD_ID }, - params: { transactionId: MOCK_TRANSACTION_ID }, - }) + const MOCK_REQ = expressHandler.mockRequest({ + body: { fieldId: MOCK_FIELD_ID }, + params: { transactionId: MOCK_TRANSACTION_ID }, }) + afterEach(() => jest.clearAllMocks()) it('should correctly call service when params are valid', async () => { const transaction = new Verification({ formId: new ObjectId() }) MockVfnService.getTransaction.mockReturnValueOnce( Promise.resolve(transaction), ) - await resetFieldInTransaction(mockReq, MOCK_RES, noop) + await resetFieldInTransaction(MOCK_REQ, MOCK_RES, noop) expect(MockVfnService.getTransaction).toHaveBeenCalledWith( MOCK_TRANSACTION_ID, ) @@ -141,7 +131,7 @@ describe('Verification controller', () => { error.name = notFoundError throw error }) - await resetFieldInTransaction(mockReq, MOCK_RES, noop) + await resetFieldInTransaction(MOCK_REQ, MOCK_RES, noop) expect(MockVfnService.getTransaction).toHaveBeenCalledWith( MOCK_TRANSACTION_ID, ) @@ -151,27 +141,25 @@ describe('Verification controller', () => { }) describe('getNewOtp', () => { - let mockReq, transaction - afterEach(() => jest.clearAllMocks()) - - beforeAll(() => { - mockReq = expressHandler.mockRequest({ - body: { fieldId: MOCK_FIELD_ID, answer: MOCK_ANSWER }, - params: { transactionId: MOCK_TRANSACTION_ID }, - }) - transaction = new Verification({ formId: new ObjectId() }) - MockVfnService.getTransaction.mockReturnValue( - Promise.resolve(transaction), - ) + const MOCK_REQ = expressHandler.mockRequest({ + body: { fieldId: MOCK_FIELD_ID, answer: MOCK_ANSWER }, + params: { transactionId: MOCK_TRANSACTION_ID }, }) + const MOCK_TRANSACTION = new Verification({ formId: new ObjectId() }) + MockVfnService.getTransaction.mockReturnValue( + Promise.resolve(MOCK_TRANSACTION), + ) + + afterEach(() => jest.clearAllMocks()) + it('should call service correctly when params are valid', async () => { - await getNewOtp(mockReq, MOCK_RES, noop) + await getNewOtp(MOCK_REQ, MOCK_RES, noop) expect(MockVfnService.getTransaction).toHaveBeenCalledWith( MOCK_TRANSACTION_ID, ) expect(MockVfnService.getNewOtp).toHaveBeenCalledWith( - transaction, + MOCK_TRANSACTION, MOCK_FIELD_ID, MOCK_ANSWER, ) @@ -184,12 +172,12 @@ describe('Verification controller', () => { error.name = notFoundError throw error }) - await getNewOtp(mockReq, MOCK_RES, noop) + await getNewOtp(MOCK_REQ, MOCK_RES, noop) expect(MockVfnService.getTransaction).toHaveBeenCalledWith( MOCK_TRANSACTION_ID, ) expect(MockVfnService.getNewOtp).toHaveBeenCalledWith( - transaction, + MOCK_TRANSACTION, MOCK_FIELD_ID, MOCK_ANSWER, ) @@ -203,12 +191,12 @@ describe('Verification controller', () => { error.name = waitOtpError throw error }) - await getNewOtp(mockReq, MOCK_RES, noop) + await getNewOtp(MOCK_REQ, MOCK_RES, noop) expect(MockVfnService.getTransaction).toHaveBeenCalledWith( MOCK_TRANSACTION_ID, ) expect(MockVfnService.getNewOtp).toHaveBeenCalledWith( - transaction, + MOCK_TRANSACTION, MOCK_FIELD_ID, MOCK_ANSWER, ) @@ -222,12 +210,12 @@ describe('Verification controller', () => { error.name = sendOtpError throw error }) - await getNewOtp(mockReq, MOCK_RES, noop) + await getNewOtp(MOCK_REQ, MOCK_RES, noop) expect(MockVfnService.getTransaction).toHaveBeenCalledWith( MOCK_TRANSACTION_ID, ) expect(MockVfnService.getNewOtp).toHaveBeenCalledWith( - transaction, + MOCK_TRANSACTION, MOCK_FIELD_ID, MOCK_ANSWER, ) @@ -237,29 +225,28 @@ describe('Verification controller', () => { }) describe('verifyOtp', () => { - let mockReq, transaction + const MOCK_REQ = expressHandler.mockRequest({ + body: { fieldId: MOCK_FIELD_ID, otp: MOCK_OTP }, + params: { transactionId: MOCK_TRANSACTION_ID }, + }) + const MOCK_TRANSACTION = new Verification({ formId: new ObjectId() }) afterEach(() => jest.clearAllMocks()) beforeAll(() => { - mockReq = expressHandler.mockRequest({ - body: { fieldId: MOCK_FIELD_ID, otp: MOCK_OTP }, - params: { transactionId: MOCK_TRANSACTION_ID }, - }) - transaction = new Verification({ formId: new ObjectId() }) MockVfnService.getTransaction.mockReturnValue( - Promise.resolve(transaction), + Promise.resolve(MOCK_TRANSACTION), ) }) it('should call service correctly when params are valid', async () => { MockVfnService.verifyOtp.mockReturnValue(Promise.resolve(MOCK_DATA)) - await verifyOtp(mockReq, MOCK_RES, noop) + await verifyOtp(MOCK_REQ, MOCK_RES, noop) expect(MockVfnService.getTransaction).toHaveBeenCalledWith( MOCK_TRANSACTION_ID, ) expect(MockVfnService.verifyOtp).toHaveBeenCalledWith( - transaction, + MOCK_TRANSACTION, MOCK_FIELD_ID, MOCK_OTP, ) @@ -273,12 +260,12 @@ describe('Verification controller', () => { error.name = invalidOtpError throw error }) - await verifyOtp(mockReq, MOCK_RES, noop) + await verifyOtp(MOCK_REQ, MOCK_RES, noop) expect(MockVfnService.getTransaction).toHaveBeenCalledWith( MOCK_TRANSACTION_ID, ) expect(MockVfnService.verifyOtp).toHaveBeenCalledWith( - transaction, + MOCK_TRANSACTION, MOCK_FIELD_ID, MOCK_OTP, ) diff --git a/tests/unit/backend/modules/verification/verification.service.spec.ts b/tests/unit/backend/modules/verification/verification.service.spec.ts index 052c1b6c78..babde3bff3 100644 --- a/tests/unit/backend/modules/verification/verification.service.spec.ts +++ b/tests/unit/backend/modules/verification/verification.service.spec.ts @@ -90,8 +90,8 @@ describe('Verification service', () => { }) expect(foundTransaction).toBeTruthy() expect(returnedTransaction).toEqual({ - transactionId: foundTransaction._id, - expireAt: foundTransaction.expireAt, + transactionId: foundTransaction!._id, + expireAt: foundTransaction!.expireAt, }) }) }) @@ -138,7 +138,7 @@ describe('Verification service', () => { const hashRetries = 1 const transaction = new Verification({ formId, - fields: testForm.form_fields.map(({ _id, fieldType }) => ({ + fields: testForm.form_fields!.map(({ _id, fieldType }) => ({ _id, fieldType, hashCreatedAt, @@ -148,19 +148,19 @@ describe('Verification service', () => { })), }) await transaction.save() - await resetFieldInTransaction(transaction, testForm.form_fields[0]._id) + await resetFieldInTransaction(transaction, testForm.form_fields![0]._id) const actual = await Verification.findOne({ formId }) - expect(actual.fields[0].toObject()).toEqual({ - _id: String(testForm.form_fields[0]._id), - fieldType: testForm.form_fields[0].fieldType, + expect(actual!.fields[0].toObject()).toEqual({ + _id: String(testForm.form_fields![0]._id), + fieldType: testForm.form_fields![0].fieldType, hashCreatedAt: null, hashedOtp: null, signedData: null, hashRetries: 0, }) - expect(actual.fields[1].toObject()).toEqual({ - _id: String(testForm.form_fields[1]._id), - fieldType: testForm.form_fields[1].fieldType, + expect(actual!.fields[1].toObject()).toEqual({ + _id: String(testForm.form_fields![1]._id), + fieldType: testForm.form_fields![1].fieldType, hashCreatedAt, hashedOtp, signedData, @@ -221,7 +221,7 @@ describe('Verification service', () => { }) MockGenerateOtp.mockReturnValue(mockOtp) MockBcrypt.hash.mockReturnValue(Promise.resolve(hashedOtp)) - MockFormsgSdk.verification.generateSignature.mockReturnValue(signedData) + MockFormsgSdk.verification.generateSignature!.mockReturnValue(signedData) }) afterEach(async () => await dbHandler.clearDatabase()) @@ -260,7 +260,7 @@ describe('Verification service', () => { expect(MockGenerateOtp).toHaveBeenCalled() expect(MockBcrypt.hash.mock.calls[0][0]).toBe(mockOtp) expect( - MockFormsgSdk.verification.generateSignature.mock.calls[0][0], + MockFormsgSdk.verification.generateSignature!.mock.calls[0][0], ).toEqual({ transactionId: transaction._id, formId: transaction.formId, @@ -274,10 +274,10 @@ describe('Verification service', () => { const foundTransaction = await Verification.findOne({ _id: transaction._id, }) - expect(foundTransaction.fields[0].hashCreatedAt).toBeInstanceOf(Date) - expect(foundTransaction.fields[0].hashedOtp).toBe(hashedOtp) - expect(foundTransaction.fields[0].signedData).toBe(signedData) - expect(foundTransaction.fields[0].hashRetries).toBe(0) + expect(foundTransaction!.fields[0].hashCreatedAt).toBeInstanceOf(Date) + expect(foundTransaction!.fields[0].hashedOtp).toBe(hashedOtp) + expect(foundTransaction!.fields[0].signedData).toBe(signedData) + expect(foundTransaction!.fields[0].hashRetries).toBe(0) }) it('should send OTP when params are valid for mobile field', async () => { @@ -291,7 +291,7 @@ describe('Verification service', () => { expect(MockGenerateOtp).toHaveBeenCalled() expect(MockBcrypt.hash.mock.calls[0][0]).toBe(mockOtp) expect( - MockFormsgSdk.verification.generateSignature.mock.calls[0][0], + MockFormsgSdk.verification.generateSignature!.mock.calls[0][0], ).toEqual({ transactionId: transaction._id, formId: transaction.formId, @@ -306,10 +306,10 @@ describe('Verification service', () => { const foundTransaction = await Verification.findOne({ _id: transaction._id, }) - expect(foundTransaction.fields[1].hashCreatedAt).toBeInstanceOf(Date) - expect(foundTransaction.fields[1].hashedOtp).toBe(hashedOtp) - expect(foundTransaction.fields[1].signedData).toBe(signedData) - expect(foundTransaction.fields[1].hashRetries).toBe(0) + expect(foundTransaction!.fields[1].hashCreatedAt).toBeInstanceOf(Date) + expect(foundTransaction!.fields[1].hashedOtp).toBe(hashedOtp) + expect(foundTransaction!.fields[1].signedData).toBe(signedData) + expect(foundTransaction!.fields[1].hashRetries).toBe(0) }) it('should catch and re-throw errors thrown when sending email', async () => { @@ -390,7 +390,7 @@ describe('Verification service', () => { const foundTransaction = await Verification.findOne({ _id: transaction._id, }) - expect(foundTransaction.fields[0].hashRetries).toBe(hashRetries) + expect(foundTransaction!.fields[0].hashRetries).toBe(hashRetries) }) it('should throw error when field ID is invalid', async () => { @@ -402,7 +402,7 @@ describe('Verification service', () => { const foundTransaction = await Verification.findOne({ _id: transaction._id, }) - expect(foundTransaction.fields[0].hashRetries).toBe(hashRetries) + expect(foundTransaction!.fields[0].hashRetries).toBe(hashRetries) }) it('should throw error when hashed OTP is invalid', async () => { @@ -415,7 +415,7 @@ describe('Verification service', () => { const foundTransaction = await Verification.findOne({ _id: transaction._id, }) - expect(foundTransaction.fields[0].hashRetries).toBe(hashRetries) + expect(foundTransaction!.fields[0].hashRetries).toBe(hashRetries) }) it('should throw error when hashCreatedAt is invalid', async () => { @@ -428,7 +428,7 @@ describe('Verification service', () => { const foundTransaction = await Verification.findOne({ _id: transaction._id, }) - expect(foundTransaction.fields[0].hashRetries).toBe(hashRetries) + expect(foundTransaction!.fields[0].hashRetries).toBe(hashRetries) }) it('should throw error when hash is expired', async () => { @@ -442,7 +442,7 @@ describe('Verification service', () => { const foundTransaction = await Verification.findOne({ _id: transaction._id, }) - expect(foundTransaction.fields[0].hashRetries).toBe(hashRetries) + expect(foundTransaction!.fields[0].hashRetries).toBe(hashRetries) }) it('should throw error when retries are maxed out', async () => { @@ -456,7 +456,7 @@ describe('Verification service', () => { const foundTransaction = await Verification.findOne({ _id: transaction._id, }) - expect(foundTransaction.fields[0].hashRetries).toBe(tooManyRetries) + expect(foundTransaction!.fields[0].hashRetries).toBe(tooManyRetries) }) it('should reject when OTP is invalid', async () => { @@ -469,7 +469,7 @@ describe('Verification service', () => { const foundTransaction = await Verification.findOne({ _id: transaction._id, }) - expect(foundTransaction.fields[0].hashRetries).toBe(hashRetries + 1) + expect(foundTransaction!.fields[0].hashRetries).toBe(hashRetries + 1) }) it('should resolve when OTP is invalid', async () => { @@ -482,7 +482,7 @@ describe('Verification service', () => { const foundTransaction = await Verification.findOne({ _id: transaction._id, }) - expect(foundTransaction.fields[0].hashRetries).toBe(hashRetries + 1) + expect(foundTransaction!.fields[0].hashRetries).toBe(hashRetries + 1) }) }) }) diff --git a/tests/unit/backend/modules/webhook/webhook.service.spec.ts b/tests/unit/backend/modules/webhook/webhook.service.spec.ts index 2e2d9dd27c..3dfd079ce1 100644 --- a/tests/unit/backend/modules/webhook/webhook.service.spec.ts +++ b/tests/unit/backend/modules/webhook/webhook.service.spec.ts @@ -76,7 +76,7 @@ describe('WebhooksService', () => { let testEncryptSubmission: IEncryptedSubmissionSchema let testConfig: AxiosRequestConfig - let testSubmissionWebhookView: WebhookView + let testSubmissionWebhookView: WebhookView | null let testSignature: string beforeEach(async () => { @@ -147,7 +147,7 @@ describe('WebhooksService', () => { let submission = await EncryptSubmission.findById( testEncryptSubmission._id, ) - expect(submission.webhookResponses[0]).toEqual( + expect(submission!.webhookResponses[0]).toEqual( expect.objectContaining({ webhookUrl: MOCK_WEBHOOK_URL, signature: testSignature, @@ -172,7 +172,7 @@ describe('WebhooksService', () => { let submission = await EncryptSubmission.findById( testEncryptSubmission._id, ) - expect(submission.webhookResponses[0]).toEqual( + expect(submission!.webhookResponses[0]).toEqual( expect.objectContaining({ webhookUrl: MOCK_WEBHOOK_URL, signature: testSignature, @@ -188,7 +188,7 @@ describe('WebhooksService', () => { toJSON: () => {} config: object response: AxiosResponse - constructor(msg, response) { + constructor(msg: string, response: AxiosResponse) { super(msg) this.isAxiosError = false this.response = response @@ -220,7 +220,7 @@ describe('WebhooksService', () => { let submission = await EncryptSubmission.findById( testEncryptSubmission._id, ) - expect(submission.webhookResponses[0]).toEqual( + expect(submission!.webhookResponses[0]).toEqual( expect.objectContaining({ webhookUrl: MOCK_WEBHOOK_URL, signature: testSignature, diff --git a/tests/unit/backend/services/mail.service.spec.ts b/tests/unit/backend/services/mail.service.spec.ts index ddc8a6a462..5193414b88 100644 --- a/tests/unit/backend/services/mail.service.spec.ts +++ b/tests/unit/backend/services/mail.service.spec.ts @@ -850,7 +850,7 @@ describe('mail.service', () => { html: expectedMailBody, // Attachments should be concatted with mock pdf response attachments: [ - ...MOCK_AUTOREPLY_PARAMS.attachments, + ...MOCK_AUTOREPLY_PARAMS.attachments!, { content: MOCK_PDF, filename: 'response.pdf', diff --git a/tests/unit/backend/utils/attachment.spec.ts b/tests/unit/backend/utils/attachment.spec.ts index b651e115fa..800478ed77 100644 --- a/tests/unit/backend/utils/attachment.spec.ts +++ b/tests/unit/backend/utils/attachment.spec.ts @@ -11,6 +11,7 @@ import { } from 'src/app/utils/attachment' import { BasicField, + FieldResponse, IAttachmentResponse, ISingleAnswerResponse, } from 'src/types' @@ -182,7 +183,7 @@ describe('addAttachmentToResponses', () => { }) it('should do nothing when responses are empty', () => { - const responses = [] + const responses: FieldResponse[] = [] addAttachmentToResponses(responses, [validSingleFile]) expect(responses).toEqual([]) }) diff --git a/tsconfig.json b/tsconfig.json index c63b3ba484..cb1031ed8d 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -27,7 +27,7 @@ // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ /* Strict Type-Checking Options */ - // "strict": true, /* Enable all strict type-checking options. */ + "strict": true, /* Enable all strict type-checking options. */ // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ // "strictNullChecks": true, /* Enable strict null checks. */ // "strictFunctionTypes": true, /* Enable strict checking of function types. */ From fc7f9c92a5bcf65728bf0436e732f561b016be37 Mon Sep 17 00:00:00 2001 From: shuli-ogp Date: Tue, 15 Sep 2020 11:21:31 +0800 Subject: [PATCH 11/18] build: bump version to v4.35.0 --- CHANGELOG.md | 330 ++++++++++++++++++++++++---------------------- package-lock.json | 2 +- package.json | 2 +- 3 files changed, 176 insertions(+), 158 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f11895fac..2c594a4b4f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,187 +4,205 @@ 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). -#### [v4.34.0](https://github.com/opengovsg/formsg/compare/v4.33.0...v4.34.0) +#### [v4.35.0](https://github.com/opengovsg/FormSG/compare/v4.34.0...v4.35.0) + +> 15 September 2020 + +- refactor: turn on strict mode in Typescript configuration [`#262`](https://github.com/opengovsg/FormSG/pull/262) +- fix: allow inline styles from angular-sanitize [`#316`](https://github.com/opengovsg/FormSG/pull/316) +- feat(changelog): autogenerate CHANGELOG.md from conventional commits [`#306`](https://github.com/opengovsg/FormSG/pull/306) +- chore: reduce number of e2e tests and other fixes [`#305`](https://github.com/opengovsg/FormSG/pull/305) +- feat: merge release 4.34.1 into develop [`#312`](https://github.com/opengovsg/FormSG/pull/312) +- feat: log all critical bounces [`#288`](https://github.com/opengovsg/FormSG/pull/288) +- refactor(proxy): do not override X-Forwarded-Proto headers [`#304`](https://github.com/opengovsg/FormSG/pull/304) +- fix(deps): bump angular-translate-loader-partial from 2.18.2 to 2.18.3 [`#298`](https://github.com/opengovsg/FormSG/pull/298) +- chore(deps-dev): bump eslint-plugin-jest from 23.20.0 to 24.0.0 [`#299`](https://github.com/opengovsg/FormSG/pull/299) +- fix(deps): bump ejs from 2.7.4 to 3.1.5 [`#282`](https://github.com/opengovsg/FormSG/pull/282) +- chore: document env vars needed for EFS [`#303`](https://github.com/opengovsg/FormSG/pull/303) +- Greater clarity for available features, project roadmap and deployment instructions; disable E2E tests [`#301`](https://github.com/opengovsg/FormSG/pull/301) +- build: bump version to 4.34.1 [`d5bfd5a`](https://github.com/opengovsg/FormSG/commit/d5bfd5a60a9b006ad2329eb6ec95979b38522358) + +#### [v4.34.0](https://github.com/opengovsg/FormSG/compare/v4.33.0...v4.34.0) > 8 September 2020 -- refactor: migrate /auth endpoint handling to Typescript, Domain Driven Design [`#215`](https://github.com/opengovsg/formsg/pull/215) -- chore(deps-dev): bump stylelint-config-prettier from 8.0.1 to 8.0.2 [`#280`](https://github.com/opengovsg/formsg/pull/280) -- fix: upgrade mongoose from 5.9.19 to 5.10.0 [`#289`](https://github.com/opengovsg/formsg/pull/289) -- revert: reintroduce convict [`#287`](https://github.com/opengovsg/formsg/pull/287) -- revert(convict): "refactor: use convict for configuration (#190)" [`#285`](https://github.com/opengovsg/formsg/pull/285) -- chore(deps-dev): bump @typescript-eslint/eslint-plugin and @typescript-eslint/parser [`#246`](https://github.com/opengovsg/formsg/pull/246) -- feat: verified sms modal [`#274`](https://github.com/opengovsg/formsg/pull/274) -- feat: add try-catch block to custom logger for js files [`#267`](https://github.com/opengovsg/formsg/pull/267) -- fix: fix invocations of logger that does not adhere to expected shape [`#273`](https://github.com/opengovsg/formsg/pull/273) -- chore(deps-dev): bump @babel/core from 7.10.2 to 7.11.5 [`#270`](https://github.com/opengovsg/formsg/pull/270) -- feat: upgrade localstack version [`#275`](https://github.com/opengovsg/formsg/pull/275) -- chore(deps-dev): bump testcafe from 1.8.6 to 1.9.1 [`#271`](https://github.com/opengovsg/formsg/pull/271) -- chore(deps-dev): bump @babel/preset-env from 7.11.0 to 7.11.5 [`#268`](https://github.com/opengovsg/formsg/pull/268) -- refactor: use convict for configuration [`#190`](https://github.com/opengovsg/formsg/pull/190) -- fix: revert changes to configureAws [`#266`](https://github.com/opengovsg/formsg/pull/266) -- refactor: remove redundant feature factory [`#261`](https://github.com/opengovsg/formsg/pull/261) -- chore: remove form_field.isFutureOnly key [`#235`](https://github.com/opengovsg/formsg/pull/235) -- refactor: remove unused Nodemailer env vars [`#253`](https://github.com/opengovsg/formsg/pull/253) -- feat: upgrade Sentry SDK [`#254`](https://github.com/opengovsg/formsg/pull/254) -- fix(deps): bump lodash from 4.17.19 to 4.17.20 [`#259`](https://github.com/opengovsg/formsg/pull/259) -- chore(deps-dev): bump eslint from 7.7.0 to 7.8.1 [`#258`](https://github.com/opengovsg/formsg/pull/258) -- chore(deps-dev): bump jest from 26.2.2 to 26.4.2 [`#257`](https://github.com/opengovsg/formsg/pull/257) -- refactor: typify webhook and migrate from middleware pattern [`#251`](https://github.com/opengovsg/formsg/pull/251) -- fix(dev): fix Localstack yet again [`#252`](https://github.com/opengovsg/formsg/pull/252) -- chore(deps-dev): bump prettier from 2.0.5 to 2.1.1 [`#249`](https://github.com/opengovsg/formsg/pull/249) -- fix: prevent discriminated models from being created before their base model [`#244`](https://github.com/opengovsg/formsg/pull/244) -- fix(deps): remove ajv as dependency [`#248`](https://github.com/opengovsg/formsg/pull/248) -- chore(deps-dev): bump @typescript-eslint/parser from 3.3.0 to 3.10.1 [`#247`](https://github.com/opengovsg/formsg/pull/247) -- feat: merge Release 4.33.0 into develop [`#245`](https://github.com/opengovsg/formsg/pull/245) -- Bump version [`830211a`](https://github.com/opengovsg/formsg/commit/830211a541ff55ccd2fa1c74dc2ec4bfc29839ef) - -#### [v4.33.0](https://github.com/opengovsg/formsg/compare/v4.32.1...v4.33.0) +- refactor: migrate /auth endpoint handling to Typescript, Domain Driven Design [`#215`](https://github.com/opengovsg/FormSG/pull/215) +- chore(deps-dev): bump stylelint-config-prettier from 8.0.1 to 8.0.2 [`#280`](https://github.com/opengovsg/FormSG/pull/280) +- fix: upgrade mongoose from 5.9.19 to 5.10.0 [`#289`](https://github.com/opengovsg/FormSG/pull/289) +- revert: reintroduce convict [`#287`](https://github.com/opengovsg/FormSG/pull/287) +- revert(convict): "refactor: use convict for configuration (#190)" [`#285`](https://github.com/opengovsg/FormSG/pull/285) +- chore(deps-dev): bump @typescript-eslint/eslint-plugin and @typescript-eslint/parser [`#246`](https://github.com/opengovsg/FormSG/pull/246) +- feat: verified sms modal [`#274`](https://github.com/opengovsg/FormSG/pull/274) +- feat: add try-catch block to custom logger for js files [`#267`](https://github.com/opengovsg/FormSG/pull/267) +- fix: fix invocations of logger that does not adhere to expected shape [`#273`](https://github.com/opengovsg/FormSG/pull/273) +- chore(deps-dev): bump @babel/core from 7.10.2 to 7.11.5 [`#270`](https://github.com/opengovsg/FormSG/pull/270) +- feat: upgrade localstack version [`#275`](https://github.com/opengovsg/FormSG/pull/275) +- chore(deps-dev): bump testcafe from 1.8.6 to 1.9.1 [`#271`](https://github.com/opengovsg/FormSG/pull/271) +- chore(deps-dev): bump @babel/preset-env from 7.11.0 to 7.11.5 [`#268`](https://github.com/opengovsg/FormSG/pull/268) +- refactor: use convict for configuration [`#190`](https://github.com/opengovsg/FormSG/pull/190) +- fix: revert changes to configureAws [`#266`](https://github.com/opengovsg/FormSG/pull/266) +- refactor: remove redundant feature factory [`#261`](https://github.com/opengovsg/FormSG/pull/261) +- chore: remove form_field.isFutureOnly key [`#235`](https://github.com/opengovsg/FormSG/pull/235) +- refactor: remove unused Nodemailer env vars [`#253`](https://github.com/opengovsg/FormSG/pull/253) +- feat: upgrade Sentry SDK [`#254`](https://github.com/opengovsg/FormSG/pull/254) +- fix(deps): bump lodash from 4.17.19 to 4.17.20 [`#259`](https://github.com/opengovsg/FormSG/pull/259) +- chore(deps-dev): bump eslint from 7.7.0 to 7.8.1 [`#258`](https://github.com/opengovsg/FormSG/pull/258) +- chore(deps-dev): bump jest from 26.2.2 to 26.4.2 [`#257`](https://github.com/opengovsg/FormSG/pull/257) +- refactor: typify webhook and migrate from middleware pattern [`#251`](https://github.com/opengovsg/FormSG/pull/251) +- fix(dev): fix Localstack yet again [`#252`](https://github.com/opengovsg/FormSG/pull/252) +- chore(deps-dev): bump prettier from 2.0.5 to 2.1.1 [`#249`](https://github.com/opengovsg/FormSG/pull/249) +- fix: prevent discriminated models from being created before their base model [`#244`](https://github.com/opengovsg/FormSG/pull/244) +- fix(deps): remove ajv as dependency [`#248`](https://github.com/opengovsg/FormSG/pull/248) +- chore(deps-dev): bump @typescript-eslint/parser from 3.3.0 to 3.10.1 [`#247`](https://github.com/opengovsg/FormSG/pull/247) +- feat: merge Release 4.33.0 into develop [`#245`](https://github.com/opengovsg/FormSG/pull/245) +- Bump version [`830211a`](https://github.com/opengovsg/FormSG/commit/830211a541ff55ccd2fa1c74dc2ec4bfc29839ef) + +#### [v4.33.0](https://github.com/opengovsg/FormSG/compare/v4.32.1...v4.33.0) > 1 September 2020 -- fix: use original questionCount [`#242`](https://github.com/opengovsg/formsg/pull/242) -- fix: correct left margin in acknowledgment error when activating storage mode form [`#240`](https://github.com/opengovsg/formsg/pull/240) -- feat: log more info about critical bounces [`#237`](https://github.com/opengovsg/formsg/pull/237) -- fix: remove filetype from permission levels imports [`#236`](https://github.com/opengovsg/formsg/pull/236) -- fix(deps): bump http-status-codes from 1.4.0 to 2.1.2 [`#229`](https://github.com/opengovsg/formsg/pull/229) -- refactor: use express router for modules [`#204`](https://github.com/opengovsg/formsg/pull/204) -- chore(deps-dev): bump @types/helmet from 0.0.47 to 0.0.48 [`#232`](https://github.com/opengovsg/formsg/pull/232) -- refactor(utils/attachment): typescriptify [`#166`](https://github.com/opengovsg/formsg/pull/166) -- fix(deps): bump validator from 11.1.0 to 13.1.1 [`#209`](https://github.com/opengovsg/formsg/pull/209) -- refactor: typify utils [`#171`](https://github.com/opengovsg/formsg/pull/171) -- feat: mailto option after form activation [`#213`](https://github.com/opengovsg/formsg/pull/213) -- fix(deps): bump axios from 0.19.2 to 0.20.0 [`#218`](https://github.com/opengovsg/formsg/pull/218) -- chore(deps-dev): bump @types/mongoose from 5.7.25 to 5.7.36 [`#230`](https://github.com/opengovsg/formsg/pull/230) -- feat: Bulk download of storage mode attachments in a zip file [`#141`](https://github.com/opengovsg/formsg/pull/141) -- feat: merge release v4.32.1 back into develop branch [`#226`](https://github.com/opengovsg/formsg/pull/226) -- fix(deps): bump opossum from 5.0.0 to 5.0.1 [`#221`](https://github.com/opengovsg/formsg/pull/221) -- chore(deps-dev): bump eslint from 6.8.0 to 7.7.0 [`#220`](https://github.com/opengovsg/formsg/pull/220) -- feat: standardize logger format and output [`#211`](https://github.com/opengovsg/formsg/pull/211) -- fix: fix linting not working on frontend code [`#217`](https://github.com/opengovsg/formsg/pull/217) -- fix: pass missing $state param into EditContactNumberModalController [`#216`](https://github.com/opengovsg/formsg/pull/216) -- feat: add Emergency Contact feature frontend [`#142`](https://github.com/opengovsg/formsg/pull/142) -- refactor: convert webhook service to Typescript [`#83`](https://github.com/opengovsg/formsg/pull/83) -- chore(deps-dev): bump sinon from 6.3.5 to 9.0.3 [`#207`](https://github.com/opengovsg/formsg/pull/207) -- feat: Share form secret keys across browser tabs using BroadcastChannel [`#203`](https://github.com/opengovsg/formsg/pull/203) -- chore: merge Release v4.32.0 into develop branch [`#205`](https://github.com/opengovsg/formsg/pull/205) -- Introduce minimum test coverage thresholds, coveralls.io for threshold reporting and repo badge [`#185`](https://github.com/opengovsg/formsg/pull/185) -- feat: MailService#sendNodeMail invocations to retry on 4xx errors(#227) [`61d5103`](https://github.com/opengovsg/formsg/commit/61d510312affdea6e971147dd547a6f5449b270b) -- build: bump version to 4.33.0 [`6c0951e`](https://github.com/opengovsg/formsg/commit/6c0951e877e498751c94a539ce93b03eb0ff9d53) - -#### [v4.32.1](https://github.com/opengovsg/formsg/compare/v4.32.0...v4.32.1) +- fix: use original questionCount [`#242`](https://github.com/opengovsg/FormSG/pull/242) +- fix: correct left margin in acknowledgment error when activating storage mode form [`#240`](https://github.com/opengovsg/FormSG/pull/240) +- feat: log more info about critical bounces [`#237`](https://github.com/opengovsg/FormSG/pull/237) +- fix: remove filetype from permission levels imports [`#236`](https://github.com/opengovsg/FormSG/pull/236) +- fix(deps): bump http-status-codes from 1.4.0 to 2.1.2 [`#229`](https://github.com/opengovsg/FormSG/pull/229) +- refactor: use express router for modules [`#204`](https://github.com/opengovsg/FormSG/pull/204) +- chore(deps-dev): bump @types/helmet from 0.0.47 to 0.0.48 [`#232`](https://github.com/opengovsg/FormSG/pull/232) +- refactor(utils/attachment): typescriptify [`#166`](https://github.com/opengovsg/FormSG/pull/166) +- fix(deps): bump validator from 11.1.0 to 13.1.1 [`#209`](https://github.com/opengovsg/FormSG/pull/209) +- refactor: typify utils [`#171`](https://github.com/opengovsg/FormSG/pull/171) +- feat: mailto option after form activation [`#213`](https://github.com/opengovsg/FormSG/pull/213) +- fix(deps): bump axios from 0.19.2 to 0.20.0 [`#218`](https://github.com/opengovsg/FormSG/pull/218) +- chore(deps-dev): bump @types/mongoose from 5.7.25 to 5.7.36 [`#230`](https://github.com/opengovsg/FormSG/pull/230) +- feat: Bulk download of storage mode attachments in a zip file [`#141`](https://github.com/opengovsg/FormSG/pull/141) +- feat: merge release v4.32.1 back into develop branch [`#226`](https://github.com/opengovsg/FormSG/pull/226) +- fix(deps): bump opossum from 5.0.0 to 5.0.1 [`#221`](https://github.com/opengovsg/FormSG/pull/221) +- chore(deps-dev): bump eslint from 6.8.0 to 7.7.0 [`#220`](https://github.com/opengovsg/FormSG/pull/220) +- feat: standardize logger format and output [`#211`](https://github.com/opengovsg/FormSG/pull/211) +- fix: fix linting not working on frontend code [`#217`](https://github.com/opengovsg/FormSG/pull/217) +- fix: pass missing $state param into EditContactNumberModalController [`#216`](https://github.com/opengovsg/FormSG/pull/216) +- feat: add Emergency Contact feature frontend [`#142`](https://github.com/opengovsg/FormSG/pull/142) +- refactor: convert webhook service to Typescript [`#83`](https://github.com/opengovsg/FormSG/pull/83) +- chore(deps-dev): bump sinon from 6.3.5 to 9.0.3 [`#207`](https://github.com/opengovsg/FormSG/pull/207) +- feat: Share form secret keys across browser tabs using BroadcastChannel [`#203`](https://github.com/opengovsg/FormSG/pull/203) +- chore: merge Release v4.32.0 into develop branch [`#205`](https://github.com/opengovsg/FormSG/pull/205) +- Introduce minimum test coverage thresholds, coveralls.io for threshold reporting and repo badge [`#185`](https://github.com/opengovsg/FormSG/pull/185) +- feat: MailService#sendNodeMail invocations to retry on 4xx errors(#227) [`61d5103`](https://github.com/opengovsg/FormSG/commit/61d510312affdea6e971147dd547a6f5449b270b) +- build: bump version to 4.33.0 [`6c0951e`](https://github.com/opengovsg/FormSG/commit/6c0951e877e498751c94a539ce93b03eb0ff9d53) + +#### [v4.32.1](https://github.com/opengovsg/FormSG/compare/v4.32.0...v4.32.1) > 27 August 2020 -- chore: bump version to v4.32.1 [`0bf07cf`](https://github.com/opengovsg/formsg/commit/0bf07cfc9b804a2e602a096032065d73805acfea) -- fix: split mail by semicolon in addition to comma when validating [`824380e`](https://github.com/opengovsg/formsg/commit/824380ef2a015674b5931cc3f9516036eb80a917) +- chore: bump version to v4.32.1 [`0bf07cf`](https://github.com/opengovsg/FormSG/commit/0bf07cfc9b804a2e602a096032065d73805acfea) +- fix: split mail by semicolon in addition to comma when validating [`824380e`](https://github.com/opengovsg/FormSG/commit/824380ef2a015674b5931cc3f9516036eb80a917) -#### [v4.32.0](https://github.com/opengovsg/formsg/compare/v4.30.4...v4.32.0) +#### [v4.32.0](https://github.com/opengovsg/FormSG/compare/v4.30.4...v4.32.0) > 25 August 2020 -- fix: shift userEmail retrieval to GA service [`#192`](https://github.com/opengovsg/formsg/pull/192) -- chore(deps-dev): bump @opengovsg/mockpass from 2.2.0 to 2.4.6 [`#198`](https://github.com/opengovsg/formsg/pull/198) -- feat: remove beta field validations [`#194`](https://github.com/opengovsg/formsg/pull/194) -- fix(deps): bump uid-generator from 1.0.0 to 2.0.0 [`#187`](https://github.com/opengovsg/formsg/pull/187) -- fix(deps): bump puppeteer-core from 4.0.0 to 5.2.1 [`#188`](https://github.com/opengovsg/formsg/pull/188) -- chore(deps-dev): bump @typescript-eslint/eslint-plugin [`#197`](https://github.com/opengovsg/formsg/pull/197) -- feat: add core ApplicationError for express app [`#195`](https://github.com/opengovsg/formsg/pull/195) -- chore(deps-dev): bump typescript to 4.0.2 [`#196`](https://github.com/opengovsg/formsg/pull/196) -- fix(deps): bump font-awesome from 4.6.1 to 4.7.0 [`#186`](https://github.com/opengovsg/formsg/pull/186) -- feat: migrate `util/response` to new Submission module (service, utils, etc) [`#176`](https://github.com/opengovsg/formsg/pull/176) -- feat: log form ID in GA event labels [`#154`](https://github.com/opengovsg/formsg/pull/154) -- refactor(verification): convert to module and typescriptify [`#172`](https://github.com/opengovsg/formsg/pull/172) -- feat: support &`;'" in form title [`#156`](https://github.com/opengovsg/formsg/pull/156) -- fix: run npm audit fix to resolve security issues with minimist dependency in the selectize package [`#181`](https://github.com/opengovsg/formsg/pull/181) -- chore(deps-dev): bump jasmine from 3.5.0 to 3.6.1 [`#158`](https://github.com/opengovsg/formsg/pull/158) -- chore(deps-dev): bump env-cmd from 9.0.3 to 10.1.0 [`#133`](https://github.com/opengovsg/formsg/pull/133) -- feat: mailto link for secret key [`#150`](https://github.com/opengovsg/formsg/pull/150) -- fix: enable forceDelivery on twilio message sending [`#178`](https://github.com/opengovsg/formsg/pull/178) -- feat: increase breaker window time and add minimum volume threshold [`#165`](https://github.com/opengovsg/formsg/pull/165) -- refactor: migrate encryption util to typescript [`#167`](https://github.com/opengovsg/formsg/pull/167) -- refactor: delete render promise util [`#168`](https://github.com/opengovsg/formsg/pull/168) -- refactor: convert date util to typescript [`#161`](https://github.com/opengovsg/formsg/pull/161) -- feat: create bounce collection and alarms [`#131`](https://github.com/opengovsg/formsg/pull/131) -- [develop] Release v4.31.0 [`#155`](https://github.com/opengovsg/formsg/pull/155) -- refactor: convert MailService to a class based Typescript implementation [`#76`](https://github.com/opengovsg/formsg/pull/76) -- fix(deps): bump aws-sdk from 2.699.0 to 2.734.0 [`#146`](https://github.com/opengovsg/formsg/pull/146) -- fix(deps): bump node-cache from 5.1.1 to 5.1.2 [`#145`](https://github.com/opengovsg/formsg/pull/145) -- feat: include user ip address when sending otp [`#147`](https://github.com/opengovsg/formsg/pull/147) -- chore(deps-dev): bump htmlhint from 0.11.0 to 0.14.1 [`#116`](https://github.com/opengovsg/formsg/pull/116) -- fix(deps): bump angular-* dependency packages from 1.7.9 to 1.8.0 [`#108`](https://github.com/opengovsg/formsg/pull/108) -- feat: log IP, submissionId and formId together [`#130`](https://github.com/opengovsg/formsg/pull/130) -- fix(deps): bump crypto-js from 3.3.0 to 4.0.0 [`#110`](https://github.com/opengovsg/formsg/pull/110) -- [develop] Release 4.30.4 [`#138`](https://github.com/opengovsg/formsg/pull/138) -- fix(deps): bump express-winston from 4.0.3 to 4.0.5 [`#109`](https://github.com/opengovsg/formsg/pull/109) -- chore: add --watch flag back to build-frontend-dev script [`#128`](https://github.com/opengovsg/formsg/pull/128) -- docs: create trouble shooting guide [`#119`](https://github.com/opengovsg/formsg/pull/119) -- chore: Merge release 4.30.3 into develop [`#127`](https://github.com/opengovsg/formsg/pull/127) -- fix(deps): bump bcrypt from 3.0.8 to 5.0.0 [`#88`](https://github.com/opengovsg/formsg/pull/88) -- fix(deps): bump nodemailer from 6.4.10 to 6.4.11 [`#117`](https://github.com/opengovsg/formsg/pull/117) -- tests: fix flakiness and migrate remaining mongoose model tests to Typescript [`#122`](https://github.com/opengovsg/formsg/pull/122) -- chore: bump version to v4.32.0 [`aa34114`](https://github.com/opengovsg/formsg/commit/aa341141d47a806ece786fcccbe0faef0945ccfc) - -#### [v4.30.4](https://github.com/opengovsg/formsg/compare/v4.30.3...v4.30.4) +- fix: shift userEmail retrieval to GA service [`#192`](https://github.com/opengovsg/FormSG/pull/192) +- chore(deps-dev): bump @opengovsg/mockpass from 2.2.0 to 2.4.6 [`#198`](https://github.com/opengovsg/FormSG/pull/198) +- feat: remove beta field validations [`#194`](https://github.com/opengovsg/FormSG/pull/194) +- fix(deps): bump uid-generator from 1.0.0 to 2.0.0 [`#187`](https://github.com/opengovsg/FormSG/pull/187) +- fix(deps): bump puppeteer-core from 4.0.0 to 5.2.1 [`#188`](https://github.com/opengovsg/FormSG/pull/188) +- chore(deps-dev): bump @typescript-eslint/eslint-plugin [`#197`](https://github.com/opengovsg/FormSG/pull/197) +- feat: add core ApplicationError for express app [`#195`](https://github.com/opengovsg/FormSG/pull/195) +- chore(deps-dev): bump typescript to 4.0.2 [`#196`](https://github.com/opengovsg/FormSG/pull/196) +- fix(deps): bump font-awesome from 4.6.1 to 4.7.0 [`#186`](https://github.com/opengovsg/FormSG/pull/186) +- feat: migrate `util/response` to new Submission module (service, utils, etc) [`#176`](https://github.com/opengovsg/FormSG/pull/176) +- feat: log form ID in GA event labels [`#154`](https://github.com/opengovsg/FormSG/pull/154) +- refactor(verification): convert to module and typescriptify [`#172`](https://github.com/opengovsg/FormSG/pull/172) +- feat: support &`;'" in form title [`#156`](https://github.com/opengovsg/FormSG/pull/156) +- fix: run npm audit fix to resolve security issues with minimist dependency in the selectize package [`#181`](https://github.com/opengovsg/FormSG/pull/181) +- chore(deps-dev): bump jasmine from 3.5.0 to 3.6.1 [`#158`](https://github.com/opengovsg/FormSG/pull/158) +- chore(deps-dev): bump env-cmd from 9.0.3 to 10.1.0 [`#133`](https://github.com/opengovsg/FormSG/pull/133) +- feat: mailto link for secret key [`#150`](https://github.com/opengovsg/FormSG/pull/150) +- fix: enable forceDelivery on twilio message sending [`#178`](https://github.com/opengovsg/FormSG/pull/178) +- feat: increase breaker window time and add minimum volume threshold [`#165`](https://github.com/opengovsg/FormSG/pull/165) +- refactor: migrate encryption util to typescript [`#167`](https://github.com/opengovsg/FormSG/pull/167) +- refactor: delete render promise util [`#168`](https://github.com/opengovsg/FormSG/pull/168) +- refactor: convert date util to typescript [`#161`](https://github.com/opengovsg/FormSG/pull/161) +- feat: create bounce collection and alarms [`#131`](https://github.com/opengovsg/FormSG/pull/131) +- [develop] Release v4.31.0 [`#155`](https://github.com/opengovsg/FormSG/pull/155) +- refactor: convert MailService to a class based Typescript implementation [`#76`](https://github.com/opengovsg/FormSG/pull/76) +- fix(deps): bump aws-sdk from 2.699.0 to 2.734.0 [`#146`](https://github.com/opengovsg/FormSG/pull/146) +- fix(deps): bump node-cache from 5.1.1 to 5.1.2 [`#145`](https://github.com/opengovsg/FormSG/pull/145) +- feat: include user ip address when sending otp [`#147`](https://github.com/opengovsg/FormSG/pull/147) +- chore(deps-dev): bump htmlhint from 0.11.0 to 0.14.1 [`#116`](https://github.com/opengovsg/FormSG/pull/116) +- fix(deps): bump angular-* dependency packages from 1.7.9 to 1.8.0 [`#108`](https://github.com/opengovsg/FormSG/pull/108) +- feat: log IP, submissionId and formId together [`#130`](https://github.com/opengovsg/FormSG/pull/130) +- fix(deps): bump crypto-js from 3.3.0 to 4.0.0 [`#110`](https://github.com/opengovsg/FormSG/pull/110) +- [develop] Release 4.30.4 [`#138`](https://github.com/opengovsg/FormSG/pull/138) +- fix(deps): bump express-winston from 4.0.3 to 4.0.5 [`#109`](https://github.com/opengovsg/FormSG/pull/109) +- chore: add --watch flag back to build-frontend-dev script [`#128`](https://github.com/opengovsg/FormSG/pull/128) +- docs: create trouble shooting guide [`#119`](https://github.com/opengovsg/FormSG/pull/119) +- chore: Merge release 4.30.3 into develop [`#127`](https://github.com/opengovsg/FormSG/pull/127) +- fix(deps): bump bcrypt from 3.0.8 to 5.0.0 [`#88`](https://github.com/opengovsg/FormSG/pull/88) +- fix(deps): bump nodemailer from 6.4.10 to 6.4.11 [`#117`](https://github.com/opengovsg/FormSG/pull/117) +- tests: fix flakiness and migrate remaining mongoose model tests to Typescript [`#122`](https://github.com/opengovsg/FormSG/pull/122) +- chore: bump version to v4.32.0 [`aa34114`](https://github.com/opengovsg/FormSG/commit/aa341141d47a806ece786fcccbe0faef0945ccfc) + +#### [v4.30.4](https://github.com/opengovsg/FormSG/compare/v4.30.3...v4.30.4) > 14 August 2020 -- Revert "feat: Filter Storage Mode Responses by Submission Id (#71)" [`ffe4218`](https://github.com/opengovsg/formsg/commit/ffe42187130d1d4147f22b37687992062af7d7c6) -- chore: bump version to 4.30.4 [`35d68de`](https://github.com/opengovsg/formsg/commit/35d68debce62bd86f001724608bbc59bce483aa3) +- Revert "feat: Filter Storage Mode Responses by Submission Id (#71)" [`ffe4218`](https://github.com/opengovsg/FormSG/commit/ffe42187130d1d4147f22b37687992062af7d7c6) +- chore: bump version to 4.30.4 [`35d68de`](https://github.com/opengovsg/FormSG/commit/35d68debce62bd86f001724608bbc59bce483aa3) -#### [v4.30.3](https://github.com/opengovsg/formsg/compare/v4.30.2...v4.30.3) +#### [v4.30.3](https://github.com/opengovsg/FormSG/compare/v4.30.2...v4.30.3) > 12 August 2020 -- fix: Revert url loader [`#125`](https://github.com/opengovsg/formsg/pull/125) -- feat: show error upon FileReader failure [`#121`](https://github.com/opengovsg/formsg/pull/121) -- [develop] Release 4.30.2 [`#114`](https://github.com/opengovsg/formsg/pull/114) -- refactor: remove unused mongoTimestamp plugin [`#120`](https://github.com/opengovsg/formsg/pull/120) -- docs: updating contributing, readme, license for open source [`#86`](https://github.com/opengovsg/formsg/pull/86) -- chore: setup jest for use with Typescript tests [`#106`](https://github.com/opengovsg/formsg/pull/106) -- fix: fix myInfoError typo [`#115`](https://github.com/opengovsg/formsg/pull/115) -- docs(readme): point build status image to new repo [`#112`](https://github.com/opengovsg/formsg/pull/112) -- feat: add getQuestion instance method to form field schema [`#103`](https://github.com/opengovsg/formsg/pull/103) -- chore(deps-dev): bump webpack-cli from 3.3.11 to 3.3.12 [`#105`](https://github.com/opengovsg/formsg/pull/105) -- feat: Filter Storage Mode Responses by Submission Id [`#71`](https://github.com/opengovsg/formsg/pull/71) -- fix(deps): bump angular-cookies from 1.7.9 to 1.8.0 [`#104`](https://github.com/opengovsg/formsg/pull/104) -- chore(deps-dev): bump angular from 1.7.9 to 1.8.0 [`#10`](https://github.com/opengovsg/formsg/pull/10) -- docs: updated docs for open source [`#95`](https://github.com/opengovsg/formsg/pull/95) -- test: add tests for verification model [`#99`](https://github.com/opengovsg/formsg/pull/99) -- chore(deps-dev): bump url-loader from 1.1.2 to 4.1.0 [`#90`](https://github.com/opengovsg/formsg/pull/90) -- refactor: migrate `utils/request` to Typescript [`#98`](https://github.com/opengovsg/formsg/pull/98) -- fix: phone validation now only accepts 8 digit #s starting with 8 or 9 [`#101`](https://github.com/opengovsg/formsg/pull/101) -- [develop] Release 4.30.1 [`#80`](https://github.com/opengovsg/formsg/pull/80) -- [develop] Release 4.30.0 [`#79`](https://github.com/opengovsg/formsg/pull/79) -- fix(deps): bump uuid from 8.2.0 to 8.3.0 [`#96`](https://github.com/opengovsg/formsg/pull/96) -- chore(deps-dev): bump jasmine-spec-reporter from 4.2.1 to 5.0.2 [`#89`](https://github.com/opengovsg/formsg/pull/89) -- chore(deps-dev): bump @babel/preset-env from 7.10.2 to 7.11.0 [`#87`](https://github.com/opengovsg/formsg/pull/87) -- fix(deps): bump lodash from 4.17.15 to 4.17.19 [`#91`](https://github.com/opengovsg/formsg/pull/91) -- refactor(logic): typescriptify [`#81`](https://github.com/opengovsg/formsg/pull/81) -- fix: update dependabot config to use v2 syntax [`#85`](https://github.com/opengovsg/formsg/pull/85) -- chore: add dependabot.yml [`#82`](https://github.com/opengovsg/formsg/pull/82) -- feat: remove allowSms beta flag [`#73`](https://github.com/opengovsg/formsg/pull/73) -- feat(FormSchema): Document new indexes for form dashboard [`#77`](https://github.com/opengovsg/formsg/pull/77) -- refactor: add _id to all model interfaces [`#75`](https://github.com/opengovsg/formsg/pull/75) -- Bump version to 4.30.3 [`4e97a48`](https://github.com/opengovsg/formsg/commit/4e97a48e52eefa621b1ef84f1d991d90e96a57b4) - -#### [v4.30.2](https://github.com/opengovsg/formsg/compare/v4.30.1...v4.30.2) +- fix: Revert url loader [`#125`](https://github.com/opengovsg/FormSG/pull/125) +- feat: show error upon FileReader failure [`#121`](https://github.com/opengovsg/FormSG/pull/121) +- [develop] Release 4.30.2 [`#114`](https://github.com/opengovsg/FormSG/pull/114) +- refactor: remove unused mongoTimestamp plugin [`#120`](https://github.com/opengovsg/FormSG/pull/120) +- docs: updating contributing, readme, license for open source [`#86`](https://github.com/opengovsg/FormSG/pull/86) +- chore: setup jest for use with Typescript tests [`#106`](https://github.com/opengovsg/FormSG/pull/106) +- fix: fix myInfoError typo [`#115`](https://github.com/opengovsg/FormSG/pull/115) +- docs(readme): point build status image to new repo [`#112`](https://github.com/opengovsg/FormSG/pull/112) +- feat: add getQuestion instance method to form field schema [`#103`](https://github.com/opengovsg/FormSG/pull/103) +- chore(deps-dev): bump webpack-cli from 3.3.11 to 3.3.12 [`#105`](https://github.com/opengovsg/FormSG/pull/105) +- feat: Filter Storage Mode Responses by Submission Id [`#71`](https://github.com/opengovsg/FormSG/pull/71) +- fix(deps): bump angular-cookies from 1.7.9 to 1.8.0 [`#104`](https://github.com/opengovsg/FormSG/pull/104) +- chore(deps-dev): bump angular from 1.7.9 to 1.8.0 [`#10`](https://github.com/opengovsg/FormSG/pull/10) +- docs: updated docs for open source [`#95`](https://github.com/opengovsg/FormSG/pull/95) +- test: add tests for verification model [`#99`](https://github.com/opengovsg/FormSG/pull/99) +- chore(deps-dev): bump url-loader from 1.1.2 to 4.1.0 [`#90`](https://github.com/opengovsg/FormSG/pull/90) +- refactor: migrate `utils/request` to Typescript [`#98`](https://github.com/opengovsg/FormSG/pull/98) +- fix: phone validation now only accepts 8 digit #s starting with 8 or 9 [`#101`](https://github.com/opengovsg/FormSG/pull/101) +- [develop] Release 4.30.1 [`#80`](https://github.com/opengovsg/FormSG/pull/80) +- [develop] Release 4.30.0 [`#79`](https://github.com/opengovsg/FormSG/pull/79) +- fix(deps): bump uuid from 8.2.0 to 8.3.0 [`#96`](https://github.com/opengovsg/FormSG/pull/96) +- chore(deps-dev): bump jasmine-spec-reporter from 4.2.1 to 5.0.2 [`#89`](https://github.com/opengovsg/FormSG/pull/89) +- chore(deps-dev): bump @babel/preset-env from 7.10.2 to 7.11.0 [`#87`](https://github.com/opengovsg/FormSG/pull/87) +- fix(deps): bump lodash from 4.17.15 to 4.17.19 [`#91`](https://github.com/opengovsg/FormSG/pull/91) +- refactor(logic): typescriptify [`#81`](https://github.com/opengovsg/FormSG/pull/81) +- fix: update dependabot config to use v2 syntax [`#85`](https://github.com/opengovsg/FormSG/pull/85) +- chore: add dependabot.yml [`#82`](https://github.com/opengovsg/FormSG/pull/82) +- feat: remove allowSms beta flag [`#73`](https://github.com/opengovsg/FormSG/pull/73) +- feat(FormSchema): Document new indexes for form dashboard [`#77`](https://github.com/opengovsg/FormSG/pull/77) +- refactor: add _id to all model interfaces [`#75`](https://github.com/opengovsg/FormSG/pull/75) +- Bump version to 4.30.3 [`4e97a48`](https://github.com/opengovsg/FormSG/commit/4e97a48e52eefa621b1ef84f1d991d90e96a57b4) + +#### [v4.30.2](https://github.com/opengovsg/FormSG/compare/v4.30.1...v4.30.2) > 5 August 2020 -- fix: get env vars directly, not from config [`5397c06`](https://github.com/opengovsg/formsg/commit/5397c06107f52d7d3d5032ce6507daeb9d0604cf) -- fix: add trailing / only for attachments [`1b9d1c0`](https://github.com/opengovsg/formsg/commit/1b9d1c045c4f250533452f8a0448b37ebd6346f7) -- chore: bump version to 4.30.2 [`f623c1a`](https://github.com/opengovsg/formsg/commit/f623c1abb8bd85dd06d36994c783ed0409cd8a5d) +- fix: get env vars directly, not from config [`5397c06`](https://github.com/opengovsg/FormSG/commit/5397c06107f52d7d3d5032ce6507daeb9d0604cf) +- fix: add trailing / only for attachments [`1b9d1c0`](https://github.com/opengovsg/FormSG/commit/1b9d1c045c4f250533452f8a0448b37ebd6346f7) +- chore: bump version to 4.30.2 [`f623c1a`](https://github.com/opengovsg/FormSG/commit/f623c1abb8bd85dd06d36994c783ed0409cd8a5d) #### v4.30.1 > 4 August 2020 -- fix: change enum to uppercase [`#72`](https://github.com/opengovsg/formsg/pull/72) -- fix: activation modal width change when activation succeeds [`#69`](https://github.com/opengovsg/formsg/pull/69) -- Extend e2e [`#65`](https://github.com/opengovsg/formsg/pull/65) -- chore: update documentation for banner environment variables [`#3`](https://github.com/opengovsg/formsg/pull/3) -- fix: add fake aws credentials [`#64`](https://github.com/opengovsg/formsg/pull/64) -- Initial commit [`203e62d`](https://github.com/opengovsg/formsg/commit/203e62dfc346cef9fb893c7b84c481b762216dea) -- chore: bump version to 4.30.1 [`9ea64ac`](https://github.com/opengovsg/formsg/commit/9ea64ac0c19df843839357223abda0d449603704) -- chore: bump version to 4.30.0 [`bf0cca8`](https://github.com/opengovsg/formsg/commit/bf0cca862f9c25b0984986aae295b42938c81884) +- fix: change enum to uppercase [`#72`](https://github.com/opengovsg/FormSG/pull/72) +- fix: activation modal width change when activation succeeds [`#69`](https://github.com/opengovsg/FormSG/pull/69) +- Extend e2e [`#65`](https://github.com/opengovsg/FormSG/pull/65) +- chore: update documentation for banner environment variables [`#3`](https://github.com/opengovsg/FormSG/pull/3) +- fix: add fake aws credentials [`#64`](https://github.com/opengovsg/FormSG/pull/64) +- Initial commit [`203e62d`](https://github.com/opengovsg/FormSG/commit/203e62dfc346cef9fb893c7b84c481b762216dea) +- chore: bump version to 4.30.1 [`9ea64ac`](https://github.com/opengovsg/FormSG/commit/9ea64ac0c19df843839357223abda0d449603704) +- chore: bump version to 4.30.0 [`bf0cca8`](https://github.com/opengovsg/FormSG/commit/bf0cca862f9c25b0984986aae295b42938c81884) diff --git a/package-lock.json b/package-lock.json index ddec81b71d..d218b2405a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "FormSG", - "version": "4.34.1", + "version": "4.35.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 9f6519252b..d6c4289a65 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "FormSG", "description": "Form Manager for Government", - "version": "4.34.1", + "version": "4.35.0", "homepage": "https://form.gov.sg", "authors": [ "FormSG " From d7d74eaeeb222b42df300bbc37a8f3677e8b66a0 Mon Sep 17 00:00:00 2001 From: Antariksh Mahajan Date: Tue, 15 Sep 2020 14:26:19 +0800 Subject: [PATCH 12/18] feat: update copy for email fields, intranet, privacy (#321) * feat: update secret key error * feat: update email confirmation tooltip * feat: update intranet captcha messaging * feat: update privacy policy --- .../edit-captcha.client.view.html | 2 +- .../verify-secret-key.client.directive.js | 2 +- .../admin/views/edit-fields.client.modal.html | 19 +++++++--- .../submit-form.directive.view.html | 16 --------- .../forms/services/captcha.client.service.js | 2 +- .../views/static/privacy.client.view.html | 35 +++++++++++++++---- 6 files changed, 46 insertions(+), 30 deletions(-) diff --git a/src/public/modules/forms/admin/directiveViews/edit-captcha.client.view.html b/src/public/modules/forms/admin/directiveViews/edit-captcha.client.view.html index 658f281383..aeaa8c1b24 100644 --- a/src/public/modules/forms/admin/directiveViews/edit-captcha.client.view.html +++ b/src/public/modules/forms/admin/directiveViews/edit-captcha.client.view.html @@ -3,7 +3,7 @@ Enable Captcha diff --git a/src/public/modules/forms/admin/directives/verify-secret-key.client.directive.js b/src/public/modules/forms/admin/directives/verify-secret-key.client.directive.js index 0eb2a17b28..bdc7865490 100644 --- a/src/public/modules/forms/admin/directives/verify-secret-key.client.directive.js +++ b/src/public/modules/forms/admin/directives/verify-secret-key.client.directive.js @@ -54,7 +54,7 @@ function verifySecretKeyDirective(FormSgSdk) { case 'reader-abort': return 'File could not be read. Please try again.' case 'invalid-key': - return 'Form activation unsuccessful. Secret Key error, please try again.' + return 'Secret Key error. Please try again.' default: return 'An error occurred. Please try again.' } diff --git a/src/public/modules/forms/admin/views/edit-fields.client.modal.html b/src/public/modules/forms/admin/views/edit-fields.client.modal.html index ed1ebe7e34..8d518d7997 100644 --- a/src/public/modules/forms/admin/views/edit-fields.client.modal.html +++ b/src/public/modules/forms/admin/views/edit-fields.client.modal.html @@ -593,11 +593,20 @@

Annex

+ +

Name of Service: form.gov.sg

+

+ 1. If you are a form creator, please note that GovTech will collect your + email address and other contact details. As GovTech may collect, store + and/or process data requested by you from the form respondents, please + ensure that your privacy policy adequately provides the respondents with + notice of the same and that your privacy policy complies with applicable + rules/laws. +

+

+ 2. If you are a form respondent, please note that GovTech may collect, + store and/or process data that you submit in accordance with this Privacy + Policy (which applies in addition to the privacy policy of the form + creator) and disclose the data to the form creator, or process the data + for the form creator. If you have questions on the use of your data, + please consult the privacy policy of the form creator or contact the form + creator directly. +

From 0cb682e53fff5b0fed24ffc74ee9ee88ff026dd6 Mon Sep 17 00:00:00 2001 From: Arshad Ali Date: Thu, 17 Sep 2020 18:26:50 +0800 Subject: [PATCH 13/18] Change to generic error msg --- src/loaders/express/error-handler.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/loaders/express/error-handler.ts b/src/loaders/express/error-handler.ts index 5f7630d524..e1b4e4950a 100644 --- a/src/loaders/express/error-handler.ts +++ b/src/loaders/express/error-handler.ts @@ -43,7 +43,9 @@ const errorHandlerMiddlewares = () => { }, error: err, }) - return res.status(StatusCodes.BAD_REQUEST).send(errorMessage) + return res + .status(StatusCodes.BAD_REQUEST) + .send('Some required parameters are missing') } logger.error({ From 588b24da28be5cb8a80847f6ee6c8f31cdc1c0b0 Mon Sep 17 00:00:00 2001 From: Arshad Ali Date: Thu, 17 Sep 2020 18:33:03 +0800 Subject: [PATCH 14/18] Removed unused variable --- src/loaders/express/error-handler.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/loaders/express/error-handler.ts b/src/loaders/express/error-handler.ts index e1b4e4950a..ef3fd38a9f 100644 --- a/src/loaders/express/error-handler.ts +++ b/src/loaders/express/error-handler.ts @@ -28,11 +28,6 @@ const errorHandlerMiddlewares = () => { 'Apologies, something odd happened. Please try again later!' // Error page if (isCelebrate(err)) { - const errorMessage = get( - err, - 'joi.details[0].message', - genericErrorMessage, - ) // formId is only present for Joi validated routes that require it const formId = get(req, 'form._id', null) logger.error({ From 2ea5bae974a4dbfd9080408df3b177839d05b3c4 Mon Sep 17 00:00:00 2001 From: Arshad Ali Date: Thu, 17 Sep 2020 18:48:22 +0800 Subject: [PATCH 15/18] chore: bump version to v4.35.1 --- CHANGELOG.md | 351 +++++++++++++++++++++++----------------------- package-lock.json | 2 +- package.json | 2 +- 3 files changed, 179 insertions(+), 176 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c594a4b4f..7af702c5b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,205 +4,208 @@ 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). -#### [v4.35.0](https://github.com/opengovsg/FormSG/compare/v4.34.0...v4.35.0) - -> 15 September 2020 - -- refactor: turn on strict mode in Typescript configuration [`#262`](https://github.com/opengovsg/FormSG/pull/262) -- fix: allow inline styles from angular-sanitize [`#316`](https://github.com/opengovsg/FormSG/pull/316) -- feat(changelog): autogenerate CHANGELOG.md from conventional commits [`#306`](https://github.com/opengovsg/FormSG/pull/306) -- chore: reduce number of e2e tests and other fixes [`#305`](https://github.com/opengovsg/FormSG/pull/305) -- feat: merge release 4.34.1 into develop [`#312`](https://github.com/opengovsg/FormSG/pull/312) -- feat: log all critical bounces [`#288`](https://github.com/opengovsg/FormSG/pull/288) -- refactor(proxy): do not override X-Forwarded-Proto headers [`#304`](https://github.com/opengovsg/FormSG/pull/304) -- fix(deps): bump angular-translate-loader-partial from 2.18.2 to 2.18.3 [`#298`](https://github.com/opengovsg/FormSG/pull/298) -- chore(deps-dev): bump eslint-plugin-jest from 23.20.0 to 24.0.0 [`#299`](https://github.com/opengovsg/FormSG/pull/299) -- fix(deps): bump ejs from 2.7.4 to 3.1.5 [`#282`](https://github.com/opengovsg/FormSG/pull/282) -- chore: document env vars needed for EFS [`#303`](https://github.com/opengovsg/FormSG/pull/303) -- Greater clarity for available features, project roadmap and deployment instructions; disable E2E tests [`#301`](https://github.com/opengovsg/FormSG/pull/301) -- build: bump version to 4.34.1 [`d5bfd5a`](https://github.com/opengovsg/FormSG/commit/d5bfd5a60a9b006ad2329eb6ec95979b38522358) - -#### [v4.34.0](https://github.com/opengovsg/FormSG/compare/v4.33.0...v4.34.0) +#### [v4.35.1](https://github.com/opengovsg/formsg/compare/v4.34.0...v4.35.1) + +> 17 September 2020 + +- feat: update copy for email fields, intranet, privacy [`#321`](https://github.com/opengovsg/formsg/pull/321) +- refactor: turn on strict mode in Typescript configuration [`#262`](https://github.com/opengovsg/formsg/pull/262) +- fix: allow inline styles from angular-sanitize [`#316`](https://github.com/opengovsg/formsg/pull/316) +- feat(changelog): autogenerate CHANGELOG.md from conventional commits [`#306`](https://github.com/opengovsg/formsg/pull/306) +- chore: reduce number of e2e tests and other fixes [`#305`](https://github.com/opengovsg/formsg/pull/305) +- feat: merge release 4.34.1 into develop [`#312`](https://github.com/opengovsg/formsg/pull/312) +- feat: log all critical bounces [`#288`](https://github.com/opengovsg/formsg/pull/288) +- refactor(proxy): do not override X-Forwarded-Proto headers [`#304`](https://github.com/opengovsg/formsg/pull/304) +- fix(deps): bump angular-translate-loader-partial from 2.18.2 to 2.18.3 [`#298`](https://github.com/opengovsg/formsg/pull/298) +- chore(deps-dev): bump eslint-plugin-jest from 23.20.0 to 24.0.0 [`#299`](https://github.com/opengovsg/formsg/pull/299) +- fix(deps): bump ejs from 2.7.4 to 3.1.5 [`#282`](https://github.com/opengovsg/formsg/pull/282) +- chore: document env vars needed for EFS [`#303`](https://github.com/opengovsg/formsg/pull/303) +- Greater clarity for available features, project roadmap and deployment instructions; disable E2E tests [`#301`](https://github.com/opengovsg/formsg/pull/301) +- build: bump version to v4.35.0 [`fc7f9c9`](https://github.com/opengovsg/formsg/commit/fc7f9c92a5bcf65728bf0436e732f561b016be37) +- build: bump version to 4.34.1 [`d5bfd5a`](https://github.com/opengovsg/formsg/commit/d5bfd5a60a9b006ad2329eb6ec95979b38522358) +- Removed unused variable [`588b24d`](https://github.com/opengovsg/formsg/commit/588b24da28be5cb8a80847f6ee6c8f31cdc1c0b0) + +#### [v4.34.0](https://github.com/opengovsg/formsg/compare/v4.33.0...v4.34.0) > 8 September 2020 -- refactor: migrate /auth endpoint handling to Typescript, Domain Driven Design [`#215`](https://github.com/opengovsg/FormSG/pull/215) -- chore(deps-dev): bump stylelint-config-prettier from 8.0.1 to 8.0.2 [`#280`](https://github.com/opengovsg/FormSG/pull/280) -- fix: upgrade mongoose from 5.9.19 to 5.10.0 [`#289`](https://github.com/opengovsg/FormSG/pull/289) -- revert: reintroduce convict [`#287`](https://github.com/opengovsg/FormSG/pull/287) -- revert(convict): "refactor: use convict for configuration (#190)" [`#285`](https://github.com/opengovsg/FormSG/pull/285) -- chore(deps-dev): bump @typescript-eslint/eslint-plugin and @typescript-eslint/parser [`#246`](https://github.com/opengovsg/FormSG/pull/246) -- feat: verified sms modal [`#274`](https://github.com/opengovsg/FormSG/pull/274) -- feat: add try-catch block to custom logger for js files [`#267`](https://github.com/opengovsg/FormSG/pull/267) -- fix: fix invocations of logger that does not adhere to expected shape [`#273`](https://github.com/opengovsg/FormSG/pull/273) -- chore(deps-dev): bump @babel/core from 7.10.2 to 7.11.5 [`#270`](https://github.com/opengovsg/FormSG/pull/270) -- feat: upgrade localstack version [`#275`](https://github.com/opengovsg/FormSG/pull/275) -- chore(deps-dev): bump testcafe from 1.8.6 to 1.9.1 [`#271`](https://github.com/opengovsg/FormSG/pull/271) -- chore(deps-dev): bump @babel/preset-env from 7.11.0 to 7.11.5 [`#268`](https://github.com/opengovsg/FormSG/pull/268) -- refactor: use convict for configuration [`#190`](https://github.com/opengovsg/FormSG/pull/190) -- fix: revert changes to configureAws [`#266`](https://github.com/opengovsg/FormSG/pull/266) -- refactor: remove redundant feature factory [`#261`](https://github.com/opengovsg/FormSG/pull/261) -- chore: remove form_field.isFutureOnly key [`#235`](https://github.com/opengovsg/FormSG/pull/235) -- refactor: remove unused Nodemailer env vars [`#253`](https://github.com/opengovsg/FormSG/pull/253) -- feat: upgrade Sentry SDK [`#254`](https://github.com/opengovsg/FormSG/pull/254) -- fix(deps): bump lodash from 4.17.19 to 4.17.20 [`#259`](https://github.com/opengovsg/FormSG/pull/259) -- chore(deps-dev): bump eslint from 7.7.0 to 7.8.1 [`#258`](https://github.com/opengovsg/FormSG/pull/258) -- chore(deps-dev): bump jest from 26.2.2 to 26.4.2 [`#257`](https://github.com/opengovsg/FormSG/pull/257) -- refactor: typify webhook and migrate from middleware pattern [`#251`](https://github.com/opengovsg/FormSG/pull/251) -- fix(dev): fix Localstack yet again [`#252`](https://github.com/opengovsg/FormSG/pull/252) -- chore(deps-dev): bump prettier from 2.0.5 to 2.1.1 [`#249`](https://github.com/opengovsg/FormSG/pull/249) -- fix: prevent discriminated models from being created before their base model [`#244`](https://github.com/opengovsg/FormSG/pull/244) -- fix(deps): remove ajv as dependency [`#248`](https://github.com/opengovsg/FormSG/pull/248) -- chore(deps-dev): bump @typescript-eslint/parser from 3.3.0 to 3.10.1 [`#247`](https://github.com/opengovsg/FormSG/pull/247) -- feat: merge Release 4.33.0 into develop [`#245`](https://github.com/opengovsg/FormSG/pull/245) -- Bump version [`830211a`](https://github.com/opengovsg/FormSG/commit/830211a541ff55ccd2fa1c74dc2ec4bfc29839ef) - -#### [v4.33.0](https://github.com/opengovsg/FormSG/compare/v4.32.1...v4.33.0) +- refactor: migrate /auth endpoint handling to Typescript, Domain Driven Design [`#215`](https://github.com/opengovsg/formsg/pull/215) +- chore(deps-dev): bump stylelint-config-prettier from 8.0.1 to 8.0.2 [`#280`](https://github.com/opengovsg/formsg/pull/280) +- fix: upgrade mongoose from 5.9.19 to 5.10.0 [`#289`](https://github.com/opengovsg/formsg/pull/289) +- revert: reintroduce convict [`#287`](https://github.com/opengovsg/formsg/pull/287) +- revert(convict): "refactor: use convict for configuration (#190)" [`#285`](https://github.com/opengovsg/formsg/pull/285) +- chore(deps-dev): bump @typescript-eslint/eslint-plugin and @typescript-eslint/parser [`#246`](https://github.com/opengovsg/formsg/pull/246) +- feat: verified sms modal [`#274`](https://github.com/opengovsg/formsg/pull/274) +- feat: add try-catch block to custom logger for js files [`#267`](https://github.com/opengovsg/formsg/pull/267) +- fix: fix invocations of logger that does not adhere to expected shape [`#273`](https://github.com/opengovsg/formsg/pull/273) +- chore(deps-dev): bump @babel/core from 7.10.2 to 7.11.5 [`#270`](https://github.com/opengovsg/formsg/pull/270) +- feat: upgrade localstack version [`#275`](https://github.com/opengovsg/formsg/pull/275) +- chore(deps-dev): bump testcafe from 1.8.6 to 1.9.1 [`#271`](https://github.com/opengovsg/formsg/pull/271) +- chore(deps-dev): bump @babel/preset-env from 7.11.0 to 7.11.5 [`#268`](https://github.com/opengovsg/formsg/pull/268) +- refactor: use convict for configuration [`#190`](https://github.com/opengovsg/formsg/pull/190) +- fix: revert changes to configureAws [`#266`](https://github.com/opengovsg/formsg/pull/266) +- refactor: remove redundant feature factory [`#261`](https://github.com/opengovsg/formsg/pull/261) +- chore: remove form_field.isFutureOnly key [`#235`](https://github.com/opengovsg/formsg/pull/235) +- refactor: remove unused Nodemailer env vars [`#253`](https://github.com/opengovsg/formsg/pull/253) +- feat: upgrade Sentry SDK [`#254`](https://github.com/opengovsg/formsg/pull/254) +- fix(deps): bump lodash from 4.17.19 to 4.17.20 [`#259`](https://github.com/opengovsg/formsg/pull/259) +- chore(deps-dev): bump eslint from 7.7.0 to 7.8.1 [`#258`](https://github.com/opengovsg/formsg/pull/258) +- chore(deps-dev): bump jest from 26.2.2 to 26.4.2 [`#257`](https://github.com/opengovsg/formsg/pull/257) +- refactor: typify webhook and migrate from middleware pattern [`#251`](https://github.com/opengovsg/formsg/pull/251) +- fix(dev): fix Localstack yet again [`#252`](https://github.com/opengovsg/formsg/pull/252) +- chore(deps-dev): bump prettier from 2.0.5 to 2.1.1 [`#249`](https://github.com/opengovsg/formsg/pull/249) +- fix: prevent discriminated models from being created before their base model [`#244`](https://github.com/opengovsg/formsg/pull/244) +- fix(deps): remove ajv as dependency [`#248`](https://github.com/opengovsg/formsg/pull/248) +- chore(deps-dev): bump @typescript-eslint/parser from 3.3.0 to 3.10.1 [`#247`](https://github.com/opengovsg/formsg/pull/247) +- feat: merge Release 4.33.0 into develop [`#245`](https://github.com/opengovsg/formsg/pull/245) +- Bump version [`830211a`](https://github.com/opengovsg/formsg/commit/830211a541ff55ccd2fa1c74dc2ec4bfc29839ef) + +#### [v4.33.0](https://github.com/opengovsg/formsg/compare/v4.32.1...v4.33.0) > 1 September 2020 -- fix: use original questionCount [`#242`](https://github.com/opengovsg/FormSG/pull/242) -- fix: correct left margin in acknowledgment error when activating storage mode form [`#240`](https://github.com/opengovsg/FormSG/pull/240) -- feat: log more info about critical bounces [`#237`](https://github.com/opengovsg/FormSG/pull/237) -- fix: remove filetype from permission levels imports [`#236`](https://github.com/opengovsg/FormSG/pull/236) -- fix(deps): bump http-status-codes from 1.4.0 to 2.1.2 [`#229`](https://github.com/opengovsg/FormSG/pull/229) -- refactor: use express router for modules [`#204`](https://github.com/opengovsg/FormSG/pull/204) -- chore(deps-dev): bump @types/helmet from 0.0.47 to 0.0.48 [`#232`](https://github.com/opengovsg/FormSG/pull/232) -- refactor(utils/attachment): typescriptify [`#166`](https://github.com/opengovsg/FormSG/pull/166) -- fix(deps): bump validator from 11.1.0 to 13.1.1 [`#209`](https://github.com/opengovsg/FormSG/pull/209) -- refactor: typify utils [`#171`](https://github.com/opengovsg/FormSG/pull/171) -- feat: mailto option after form activation [`#213`](https://github.com/opengovsg/FormSG/pull/213) -- fix(deps): bump axios from 0.19.2 to 0.20.0 [`#218`](https://github.com/opengovsg/FormSG/pull/218) -- chore(deps-dev): bump @types/mongoose from 5.7.25 to 5.7.36 [`#230`](https://github.com/opengovsg/FormSG/pull/230) -- feat: Bulk download of storage mode attachments in a zip file [`#141`](https://github.com/opengovsg/FormSG/pull/141) -- feat: merge release v4.32.1 back into develop branch [`#226`](https://github.com/opengovsg/FormSG/pull/226) -- fix(deps): bump opossum from 5.0.0 to 5.0.1 [`#221`](https://github.com/opengovsg/FormSG/pull/221) -- chore(deps-dev): bump eslint from 6.8.0 to 7.7.0 [`#220`](https://github.com/opengovsg/FormSG/pull/220) -- feat: standardize logger format and output [`#211`](https://github.com/opengovsg/FormSG/pull/211) -- fix: fix linting not working on frontend code [`#217`](https://github.com/opengovsg/FormSG/pull/217) -- fix: pass missing $state param into EditContactNumberModalController [`#216`](https://github.com/opengovsg/FormSG/pull/216) -- feat: add Emergency Contact feature frontend [`#142`](https://github.com/opengovsg/FormSG/pull/142) -- refactor: convert webhook service to Typescript [`#83`](https://github.com/opengovsg/FormSG/pull/83) -- chore(deps-dev): bump sinon from 6.3.5 to 9.0.3 [`#207`](https://github.com/opengovsg/FormSG/pull/207) -- feat: Share form secret keys across browser tabs using BroadcastChannel [`#203`](https://github.com/opengovsg/FormSG/pull/203) -- chore: merge Release v4.32.0 into develop branch [`#205`](https://github.com/opengovsg/FormSG/pull/205) -- Introduce minimum test coverage thresholds, coveralls.io for threshold reporting and repo badge [`#185`](https://github.com/opengovsg/FormSG/pull/185) -- feat: MailService#sendNodeMail invocations to retry on 4xx errors(#227) [`61d5103`](https://github.com/opengovsg/FormSG/commit/61d510312affdea6e971147dd547a6f5449b270b) -- build: bump version to 4.33.0 [`6c0951e`](https://github.com/opengovsg/FormSG/commit/6c0951e877e498751c94a539ce93b03eb0ff9d53) - -#### [v4.32.1](https://github.com/opengovsg/FormSG/compare/v4.32.0...v4.32.1) +- fix: use original questionCount [`#242`](https://github.com/opengovsg/formsg/pull/242) +- fix: correct left margin in acknowledgment error when activating storage mode form [`#240`](https://github.com/opengovsg/formsg/pull/240) +- feat: log more info about critical bounces [`#237`](https://github.com/opengovsg/formsg/pull/237) +- fix: remove filetype from permission levels imports [`#236`](https://github.com/opengovsg/formsg/pull/236) +- fix(deps): bump http-status-codes from 1.4.0 to 2.1.2 [`#229`](https://github.com/opengovsg/formsg/pull/229) +- refactor: use express router for modules [`#204`](https://github.com/opengovsg/formsg/pull/204) +- chore(deps-dev): bump @types/helmet from 0.0.47 to 0.0.48 [`#232`](https://github.com/opengovsg/formsg/pull/232) +- refactor(utils/attachment): typescriptify [`#166`](https://github.com/opengovsg/formsg/pull/166) +- fix(deps): bump validator from 11.1.0 to 13.1.1 [`#209`](https://github.com/opengovsg/formsg/pull/209) +- refactor: typify utils [`#171`](https://github.com/opengovsg/formsg/pull/171) +- feat: mailto option after form activation [`#213`](https://github.com/opengovsg/formsg/pull/213) +- fix(deps): bump axios from 0.19.2 to 0.20.0 [`#218`](https://github.com/opengovsg/formsg/pull/218) +- chore(deps-dev): bump @types/mongoose from 5.7.25 to 5.7.36 [`#230`](https://github.com/opengovsg/formsg/pull/230) +- feat: Bulk download of storage mode attachments in a zip file [`#141`](https://github.com/opengovsg/formsg/pull/141) +- feat: merge release v4.32.1 back into develop branch [`#226`](https://github.com/opengovsg/formsg/pull/226) +- fix(deps): bump opossum from 5.0.0 to 5.0.1 [`#221`](https://github.com/opengovsg/formsg/pull/221) +- chore(deps-dev): bump eslint from 6.8.0 to 7.7.0 [`#220`](https://github.com/opengovsg/formsg/pull/220) +- feat: standardize logger format and output [`#211`](https://github.com/opengovsg/formsg/pull/211) +- fix: fix linting not working on frontend code [`#217`](https://github.com/opengovsg/formsg/pull/217) +- fix: pass missing $state param into EditContactNumberModalController [`#216`](https://github.com/opengovsg/formsg/pull/216) +- feat: add Emergency Contact feature frontend [`#142`](https://github.com/opengovsg/formsg/pull/142) +- refactor: convert webhook service to Typescript [`#83`](https://github.com/opengovsg/formsg/pull/83) +- chore(deps-dev): bump sinon from 6.3.5 to 9.0.3 [`#207`](https://github.com/opengovsg/formsg/pull/207) +- feat: Share form secret keys across browser tabs using BroadcastChannel [`#203`](https://github.com/opengovsg/formsg/pull/203) +- chore: merge Release v4.32.0 into develop branch [`#205`](https://github.com/opengovsg/formsg/pull/205) +- Introduce minimum test coverage thresholds, coveralls.io for threshold reporting and repo badge [`#185`](https://github.com/opengovsg/formsg/pull/185) +- feat: MailService#sendNodeMail invocations to retry on 4xx errors(#227) [`61d5103`](https://github.com/opengovsg/formsg/commit/61d510312affdea6e971147dd547a6f5449b270b) +- build: bump version to 4.33.0 [`6c0951e`](https://github.com/opengovsg/formsg/commit/6c0951e877e498751c94a539ce93b03eb0ff9d53) + +#### [v4.32.1](https://github.com/opengovsg/formsg/compare/v4.32.0...v4.32.1) > 27 August 2020 -- chore: bump version to v4.32.1 [`0bf07cf`](https://github.com/opengovsg/FormSG/commit/0bf07cfc9b804a2e602a096032065d73805acfea) -- fix: split mail by semicolon in addition to comma when validating [`824380e`](https://github.com/opengovsg/FormSG/commit/824380ef2a015674b5931cc3f9516036eb80a917) +- chore: bump version to v4.32.1 [`0bf07cf`](https://github.com/opengovsg/formsg/commit/0bf07cfc9b804a2e602a096032065d73805acfea) +- fix: split mail by semicolon in addition to comma when validating [`824380e`](https://github.com/opengovsg/formsg/commit/824380ef2a015674b5931cc3f9516036eb80a917) -#### [v4.32.0](https://github.com/opengovsg/FormSG/compare/v4.30.4...v4.32.0) +#### [v4.32.0](https://github.com/opengovsg/formsg/compare/v4.30.4...v4.32.0) > 25 August 2020 -- fix: shift userEmail retrieval to GA service [`#192`](https://github.com/opengovsg/FormSG/pull/192) -- chore(deps-dev): bump @opengovsg/mockpass from 2.2.0 to 2.4.6 [`#198`](https://github.com/opengovsg/FormSG/pull/198) -- feat: remove beta field validations [`#194`](https://github.com/opengovsg/FormSG/pull/194) -- fix(deps): bump uid-generator from 1.0.0 to 2.0.0 [`#187`](https://github.com/opengovsg/FormSG/pull/187) -- fix(deps): bump puppeteer-core from 4.0.0 to 5.2.1 [`#188`](https://github.com/opengovsg/FormSG/pull/188) -- chore(deps-dev): bump @typescript-eslint/eslint-plugin [`#197`](https://github.com/opengovsg/FormSG/pull/197) -- feat: add core ApplicationError for express app [`#195`](https://github.com/opengovsg/FormSG/pull/195) -- chore(deps-dev): bump typescript to 4.0.2 [`#196`](https://github.com/opengovsg/FormSG/pull/196) -- fix(deps): bump font-awesome from 4.6.1 to 4.7.0 [`#186`](https://github.com/opengovsg/FormSG/pull/186) -- feat: migrate `util/response` to new Submission module (service, utils, etc) [`#176`](https://github.com/opengovsg/FormSG/pull/176) -- feat: log form ID in GA event labels [`#154`](https://github.com/opengovsg/FormSG/pull/154) -- refactor(verification): convert to module and typescriptify [`#172`](https://github.com/opengovsg/FormSG/pull/172) -- feat: support &`;'" in form title [`#156`](https://github.com/opengovsg/FormSG/pull/156) -- fix: run npm audit fix to resolve security issues with minimist dependency in the selectize package [`#181`](https://github.com/opengovsg/FormSG/pull/181) -- chore(deps-dev): bump jasmine from 3.5.0 to 3.6.1 [`#158`](https://github.com/opengovsg/FormSG/pull/158) -- chore(deps-dev): bump env-cmd from 9.0.3 to 10.1.0 [`#133`](https://github.com/opengovsg/FormSG/pull/133) -- feat: mailto link for secret key [`#150`](https://github.com/opengovsg/FormSG/pull/150) -- fix: enable forceDelivery on twilio message sending [`#178`](https://github.com/opengovsg/FormSG/pull/178) -- feat: increase breaker window time and add minimum volume threshold [`#165`](https://github.com/opengovsg/FormSG/pull/165) -- refactor: migrate encryption util to typescript [`#167`](https://github.com/opengovsg/FormSG/pull/167) -- refactor: delete render promise util [`#168`](https://github.com/opengovsg/FormSG/pull/168) -- refactor: convert date util to typescript [`#161`](https://github.com/opengovsg/FormSG/pull/161) -- feat: create bounce collection and alarms [`#131`](https://github.com/opengovsg/FormSG/pull/131) -- [develop] Release v4.31.0 [`#155`](https://github.com/opengovsg/FormSG/pull/155) -- refactor: convert MailService to a class based Typescript implementation [`#76`](https://github.com/opengovsg/FormSG/pull/76) -- fix(deps): bump aws-sdk from 2.699.0 to 2.734.0 [`#146`](https://github.com/opengovsg/FormSG/pull/146) -- fix(deps): bump node-cache from 5.1.1 to 5.1.2 [`#145`](https://github.com/opengovsg/FormSG/pull/145) -- feat: include user ip address when sending otp [`#147`](https://github.com/opengovsg/FormSG/pull/147) -- chore(deps-dev): bump htmlhint from 0.11.0 to 0.14.1 [`#116`](https://github.com/opengovsg/FormSG/pull/116) -- fix(deps): bump angular-* dependency packages from 1.7.9 to 1.8.0 [`#108`](https://github.com/opengovsg/FormSG/pull/108) -- feat: log IP, submissionId and formId together [`#130`](https://github.com/opengovsg/FormSG/pull/130) -- fix(deps): bump crypto-js from 3.3.0 to 4.0.0 [`#110`](https://github.com/opengovsg/FormSG/pull/110) -- [develop] Release 4.30.4 [`#138`](https://github.com/opengovsg/FormSG/pull/138) -- fix(deps): bump express-winston from 4.0.3 to 4.0.5 [`#109`](https://github.com/opengovsg/FormSG/pull/109) -- chore: add --watch flag back to build-frontend-dev script [`#128`](https://github.com/opengovsg/FormSG/pull/128) -- docs: create trouble shooting guide [`#119`](https://github.com/opengovsg/FormSG/pull/119) -- chore: Merge release 4.30.3 into develop [`#127`](https://github.com/opengovsg/FormSG/pull/127) -- fix(deps): bump bcrypt from 3.0.8 to 5.0.0 [`#88`](https://github.com/opengovsg/FormSG/pull/88) -- fix(deps): bump nodemailer from 6.4.10 to 6.4.11 [`#117`](https://github.com/opengovsg/FormSG/pull/117) -- tests: fix flakiness and migrate remaining mongoose model tests to Typescript [`#122`](https://github.com/opengovsg/FormSG/pull/122) -- chore: bump version to v4.32.0 [`aa34114`](https://github.com/opengovsg/FormSG/commit/aa341141d47a806ece786fcccbe0faef0945ccfc) - -#### [v4.30.4](https://github.com/opengovsg/FormSG/compare/v4.30.3...v4.30.4) +- fix: shift userEmail retrieval to GA service [`#192`](https://github.com/opengovsg/formsg/pull/192) +- chore(deps-dev): bump @opengovsg/mockpass from 2.2.0 to 2.4.6 [`#198`](https://github.com/opengovsg/formsg/pull/198) +- feat: remove beta field validations [`#194`](https://github.com/opengovsg/formsg/pull/194) +- fix(deps): bump uid-generator from 1.0.0 to 2.0.0 [`#187`](https://github.com/opengovsg/formsg/pull/187) +- fix(deps): bump puppeteer-core from 4.0.0 to 5.2.1 [`#188`](https://github.com/opengovsg/formsg/pull/188) +- chore(deps-dev): bump @typescript-eslint/eslint-plugin [`#197`](https://github.com/opengovsg/formsg/pull/197) +- feat: add core ApplicationError for express app [`#195`](https://github.com/opengovsg/formsg/pull/195) +- chore(deps-dev): bump typescript to 4.0.2 [`#196`](https://github.com/opengovsg/formsg/pull/196) +- fix(deps): bump font-awesome from 4.6.1 to 4.7.0 [`#186`](https://github.com/opengovsg/formsg/pull/186) +- feat: migrate `util/response` to new Submission module (service, utils, etc) [`#176`](https://github.com/opengovsg/formsg/pull/176) +- feat: log form ID in GA event labels [`#154`](https://github.com/opengovsg/formsg/pull/154) +- refactor(verification): convert to module and typescriptify [`#172`](https://github.com/opengovsg/formsg/pull/172) +- feat: support &`;'" in form title [`#156`](https://github.com/opengovsg/formsg/pull/156) +- fix: run npm audit fix to resolve security issues with minimist dependency in the selectize package [`#181`](https://github.com/opengovsg/formsg/pull/181) +- chore(deps-dev): bump jasmine from 3.5.0 to 3.6.1 [`#158`](https://github.com/opengovsg/formsg/pull/158) +- chore(deps-dev): bump env-cmd from 9.0.3 to 10.1.0 [`#133`](https://github.com/opengovsg/formsg/pull/133) +- feat: mailto link for secret key [`#150`](https://github.com/opengovsg/formsg/pull/150) +- fix: enable forceDelivery on twilio message sending [`#178`](https://github.com/opengovsg/formsg/pull/178) +- feat: increase breaker window time and add minimum volume threshold [`#165`](https://github.com/opengovsg/formsg/pull/165) +- refactor: migrate encryption util to typescript [`#167`](https://github.com/opengovsg/formsg/pull/167) +- refactor: delete render promise util [`#168`](https://github.com/opengovsg/formsg/pull/168) +- refactor: convert date util to typescript [`#161`](https://github.com/opengovsg/formsg/pull/161) +- feat: create bounce collection and alarms [`#131`](https://github.com/opengovsg/formsg/pull/131) +- [develop] Release v4.31.0 [`#155`](https://github.com/opengovsg/formsg/pull/155) +- refactor: convert MailService to a class based Typescript implementation [`#76`](https://github.com/opengovsg/formsg/pull/76) +- fix(deps): bump aws-sdk from 2.699.0 to 2.734.0 [`#146`](https://github.com/opengovsg/formsg/pull/146) +- fix(deps): bump node-cache from 5.1.1 to 5.1.2 [`#145`](https://github.com/opengovsg/formsg/pull/145) +- feat: include user ip address when sending otp [`#147`](https://github.com/opengovsg/formsg/pull/147) +- chore(deps-dev): bump htmlhint from 0.11.0 to 0.14.1 [`#116`](https://github.com/opengovsg/formsg/pull/116) +- fix(deps): bump angular-* dependency packages from 1.7.9 to 1.8.0 [`#108`](https://github.com/opengovsg/formsg/pull/108) +- feat: log IP, submissionId and formId together [`#130`](https://github.com/opengovsg/formsg/pull/130) +- fix(deps): bump crypto-js from 3.3.0 to 4.0.0 [`#110`](https://github.com/opengovsg/formsg/pull/110) +- [develop] Release 4.30.4 [`#138`](https://github.com/opengovsg/formsg/pull/138) +- fix(deps): bump express-winston from 4.0.3 to 4.0.5 [`#109`](https://github.com/opengovsg/formsg/pull/109) +- chore: add --watch flag back to build-frontend-dev script [`#128`](https://github.com/opengovsg/formsg/pull/128) +- docs: create trouble shooting guide [`#119`](https://github.com/opengovsg/formsg/pull/119) +- chore: Merge release 4.30.3 into develop [`#127`](https://github.com/opengovsg/formsg/pull/127) +- fix(deps): bump bcrypt from 3.0.8 to 5.0.0 [`#88`](https://github.com/opengovsg/formsg/pull/88) +- fix(deps): bump nodemailer from 6.4.10 to 6.4.11 [`#117`](https://github.com/opengovsg/formsg/pull/117) +- tests: fix flakiness and migrate remaining mongoose model tests to Typescript [`#122`](https://github.com/opengovsg/formsg/pull/122) +- chore: bump version to v4.32.0 [`aa34114`](https://github.com/opengovsg/formsg/commit/aa341141d47a806ece786fcccbe0faef0945ccfc) + +#### [v4.30.4](https://github.com/opengovsg/formsg/compare/v4.30.3...v4.30.4) > 14 August 2020 -- Revert "feat: Filter Storage Mode Responses by Submission Id (#71)" [`ffe4218`](https://github.com/opengovsg/FormSG/commit/ffe42187130d1d4147f22b37687992062af7d7c6) -- chore: bump version to 4.30.4 [`35d68de`](https://github.com/opengovsg/FormSG/commit/35d68debce62bd86f001724608bbc59bce483aa3) +- Revert "feat: Filter Storage Mode Responses by Submission Id (#71)" [`ffe4218`](https://github.com/opengovsg/formsg/commit/ffe42187130d1d4147f22b37687992062af7d7c6) +- chore: bump version to 4.30.4 [`35d68de`](https://github.com/opengovsg/formsg/commit/35d68debce62bd86f001724608bbc59bce483aa3) -#### [v4.30.3](https://github.com/opengovsg/FormSG/compare/v4.30.2...v4.30.3) +#### [v4.30.3](https://github.com/opengovsg/formsg/compare/v4.30.2...v4.30.3) > 12 August 2020 -- fix: Revert url loader [`#125`](https://github.com/opengovsg/FormSG/pull/125) -- feat: show error upon FileReader failure [`#121`](https://github.com/opengovsg/FormSG/pull/121) -- [develop] Release 4.30.2 [`#114`](https://github.com/opengovsg/FormSG/pull/114) -- refactor: remove unused mongoTimestamp plugin [`#120`](https://github.com/opengovsg/FormSG/pull/120) -- docs: updating contributing, readme, license for open source [`#86`](https://github.com/opengovsg/FormSG/pull/86) -- chore: setup jest for use with Typescript tests [`#106`](https://github.com/opengovsg/FormSG/pull/106) -- fix: fix myInfoError typo [`#115`](https://github.com/opengovsg/FormSG/pull/115) -- docs(readme): point build status image to new repo [`#112`](https://github.com/opengovsg/FormSG/pull/112) -- feat: add getQuestion instance method to form field schema [`#103`](https://github.com/opengovsg/FormSG/pull/103) -- chore(deps-dev): bump webpack-cli from 3.3.11 to 3.3.12 [`#105`](https://github.com/opengovsg/FormSG/pull/105) -- feat: Filter Storage Mode Responses by Submission Id [`#71`](https://github.com/opengovsg/FormSG/pull/71) -- fix(deps): bump angular-cookies from 1.7.9 to 1.8.0 [`#104`](https://github.com/opengovsg/FormSG/pull/104) -- chore(deps-dev): bump angular from 1.7.9 to 1.8.0 [`#10`](https://github.com/opengovsg/FormSG/pull/10) -- docs: updated docs for open source [`#95`](https://github.com/opengovsg/FormSG/pull/95) -- test: add tests for verification model [`#99`](https://github.com/opengovsg/FormSG/pull/99) -- chore(deps-dev): bump url-loader from 1.1.2 to 4.1.0 [`#90`](https://github.com/opengovsg/FormSG/pull/90) -- refactor: migrate `utils/request` to Typescript [`#98`](https://github.com/opengovsg/FormSG/pull/98) -- fix: phone validation now only accepts 8 digit #s starting with 8 or 9 [`#101`](https://github.com/opengovsg/FormSG/pull/101) -- [develop] Release 4.30.1 [`#80`](https://github.com/opengovsg/FormSG/pull/80) -- [develop] Release 4.30.0 [`#79`](https://github.com/opengovsg/FormSG/pull/79) -- fix(deps): bump uuid from 8.2.0 to 8.3.0 [`#96`](https://github.com/opengovsg/FormSG/pull/96) -- chore(deps-dev): bump jasmine-spec-reporter from 4.2.1 to 5.0.2 [`#89`](https://github.com/opengovsg/FormSG/pull/89) -- chore(deps-dev): bump @babel/preset-env from 7.10.2 to 7.11.0 [`#87`](https://github.com/opengovsg/FormSG/pull/87) -- fix(deps): bump lodash from 4.17.15 to 4.17.19 [`#91`](https://github.com/opengovsg/FormSG/pull/91) -- refactor(logic): typescriptify [`#81`](https://github.com/opengovsg/FormSG/pull/81) -- fix: update dependabot config to use v2 syntax [`#85`](https://github.com/opengovsg/FormSG/pull/85) -- chore: add dependabot.yml [`#82`](https://github.com/opengovsg/FormSG/pull/82) -- feat: remove allowSms beta flag [`#73`](https://github.com/opengovsg/FormSG/pull/73) -- feat(FormSchema): Document new indexes for form dashboard [`#77`](https://github.com/opengovsg/FormSG/pull/77) -- refactor: add _id to all model interfaces [`#75`](https://github.com/opengovsg/FormSG/pull/75) -- Bump version to 4.30.3 [`4e97a48`](https://github.com/opengovsg/FormSG/commit/4e97a48e52eefa621b1ef84f1d991d90e96a57b4) - -#### [v4.30.2](https://github.com/opengovsg/FormSG/compare/v4.30.1...v4.30.2) +- fix: Revert url loader [`#125`](https://github.com/opengovsg/formsg/pull/125) +- feat: show error upon FileReader failure [`#121`](https://github.com/opengovsg/formsg/pull/121) +- [develop] Release 4.30.2 [`#114`](https://github.com/opengovsg/formsg/pull/114) +- refactor: remove unused mongoTimestamp plugin [`#120`](https://github.com/opengovsg/formsg/pull/120) +- docs: updating contributing, readme, license for open source [`#86`](https://github.com/opengovsg/formsg/pull/86) +- chore: setup jest for use with Typescript tests [`#106`](https://github.com/opengovsg/formsg/pull/106) +- fix: fix myInfoError typo [`#115`](https://github.com/opengovsg/formsg/pull/115) +- docs(readme): point build status image to new repo [`#112`](https://github.com/opengovsg/formsg/pull/112) +- feat: add getQuestion instance method to form field schema [`#103`](https://github.com/opengovsg/formsg/pull/103) +- chore(deps-dev): bump webpack-cli from 3.3.11 to 3.3.12 [`#105`](https://github.com/opengovsg/formsg/pull/105) +- feat: Filter Storage Mode Responses by Submission Id [`#71`](https://github.com/opengovsg/formsg/pull/71) +- fix(deps): bump angular-cookies from 1.7.9 to 1.8.0 [`#104`](https://github.com/opengovsg/formsg/pull/104) +- chore(deps-dev): bump angular from 1.7.9 to 1.8.0 [`#10`](https://github.com/opengovsg/formsg/pull/10) +- docs: updated docs for open source [`#95`](https://github.com/opengovsg/formsg/pull/95) +- test: add tests for verification model [`#99`](https://github.com/opengovsg/formsg/pull/99) +- chore(deps-dev): bump url-loader from 1.1.2 to 4.1.0 [`#90`](https://github.com/opengovsg/formsg/pull/90) +- refactor: migrate `utils/request` to Typescript [`#98`](https://github.com/opengovsg/formsg/pull/98) +- fix: phone validation now only accepts 8 digit #s starting with 8 or 9 [`#101`](https://github.com/opengovsg/formsg/pull/101) +- [develop] Release 4.30.1 [`#80`](https://github.com/opengovsg/formsg/pull/80) +- [develop] Release 4.30.0 [`#79`](https://github.com/opengovsg/formsg/pull/79) +- fix(deps): bump uuid from 8.2.0 to 8.3.0 [`#96`](https://github.com/opengovsg/formsg/pull/96) +- chore(deps-dev): bump jasmine-spec-reporter from 4.2.1 to 5.0.2 [`#89`](https://github.com/opengovsg/formsg/pull/89) +- chore(deps-dev): bump @babel/preset-env from 7.10.2 to 7.11.0 [`#87`](https://github.com/opengovsg/formsg/pull/87) +- fix(deps): bump lodash from 4.17.15 to 4.17.19 [`#91`](https://github.com/opengovsg/formsg/pull/91) +- refactor(logic): typescriptify [`#81`](https://github.com/opengovsg/formsg/pull/81) +- fix: update dependabot config to use v2 syntax [`#85`](https://github.com/opengovsg/formsg/pull/85) +- chore: add dependabot.yml [`#82`](https://github.com/opengovsg/formsg/pull/82) +- feat: remove allowSms beta flag [`#73`](https://github.com/opengovsg/formsg/pull/73) +- feat(FormSchema): Document new indexes for form dashboard [`#77`](https://github.com/opengovsg/formsg/pull/77) +- refactor: add _id to all model interfaces [`#75`](https://github.com/opengovsg/formsg/pull/75) +- Bump version to 4.30.3 [`4e97a48`](https://github.com/opengovsg/formsg/commit/4e97a48e52eefa621b1ef84f1d991d90e96a57b4) + +#### [v4.30.2](https://github.com/opengovsg/formsg/compare/v4.30.1...v4.30.2) > 5 August 2020 -- fix: get env vars directly, not from config [`5397c06`](https://github.com/opengovsg/FormSG/commit/5397c06107f52d7d3d5032ce6507daeb9d0604cf) -- fix: add trailing / only for attachments [`1b9d1c0`](https://github.com/opengovsg/FormSG/commit/1b9d1c045c4f250533452f8a0448b37ebd6346f7) -- chore: bump version to 4.30.2 [`f623c1a`](https://github.com/opengovsg/FormSG/commit/f623c1abb8bd85dd06d36994c783ed0409cd8a5d) +- fix: get env vars directly, not from config [`5397c06`](https://github.com/opengovsg/formsg/commit/5397c06107f52d7d3d5032ce6507daeb9d0604cf) +- fix: add trailing / only for attachments [`1b9d1c0`](https://github.com/opengovsg/formsg/commit/1b9d1c045c4f250533452f8a0448b37ebd6346f7) +- chore: bump version to 4.30.2 [`f623c1a`](https://github.com/opengovsg/formsg/commit/f623c1abb8bd85dd06d36994c783ed0409cd8a5d) #### v4.30.1 > 4 August 2020 -- fix: change enum to uppercase [`#72`](https://github.com/opengovsg/FormSG/pull/72) -- fix: activation modal width change when activation succeeds [`#69`](https://github.com/opengovsg/FormSG/pull/69) -- Extend e2e [`#65`](https://github.com/opengovsg/FormSG/pull/65) -- chore: update documentation for banner environment variables [`#3`](https://github.com/opengovsg/FormSG/pull/3) -- fix: add fake aws credentials [`#64`](https://github.com/opengovsg/FormSG/pull/64) -- Initial commit [`203e62d`](https://github.com/opengovsg/FormSG/commit/203e62dfc346cef9fb893c7b84c481b762216dea) -- chore: bump version to 4.30.1 [`9ea64ac`](https://github.com/opengovsg/FormSG/commit/9ea64ac0c19df843839357223abda0d449603704) -- chore: bump version to 4.30.0 [`bf0cca8`](https://github.com/opengovsg/FormSG/commit/bf0cca862f9c25b0984986aae295b42938c81884) +- fix: change enum to uppercase [`#72`](https://github.com/opengovsg/formsg/pull/72) +- fix: activation modal width change when activation succeeds [`#69`](https://github.com/opengovsg/formsg/pull/69) +- Extend e2e [`#65`](https://github.com/opengovsg/formsg/pull/65) +- chore: update documentation for banner environment variables [`#3`](https://github.com/opengovsg/formsg/pull/3) +- fix: add fake aws credentials [`#64`](https://github.com/opengovsg/formsg/pull/64) +- Initial commit [`203e62d`](https://github.com/opengovsg/formsg/commit/203e62dfc346cef9fb893c7b84c481b762216dea) +- chore: bump version to 4.30.1 [`9ea64ac`](https://github.com/opengovsg/formsg/commit/9ea64ac0c19df843839357223abda0d449603704) +- chore: bump version to 4.30.0 [`bf0cca8`](https://github.com/opengovsg/formsg/commit/bf0cca862f9c25b0984986aae295b42938c81884) diff --git a/package-lock.json b/package-lock.json index d218b2405a..889ce93bc5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "FormSG", - "version": "4.35.0", + "version": "4.35.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index d6c4289a65..fc71dcde4c 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "FormSG", "description": "Form Manager for Government", - "version": "4.35.0", + "version": "4.35.1", "homepage": "https://form.gov.sg", "authors": [ "FormSG " From 6d0ffde17207589d34c760f1b0aa9825d0323d0b Mon Sep 17 00:00:00 2001 From: Arshad Ali Date: Thu, 17 Sep 2020 19:15:52 +0800 Subject: [PATCH 16/18] Fix tests --- src/app/modules/auth/__tests__/auth.routes.spec.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/app/modules/auth/__tests__/auth.routes.spec.ts b/src/app/modules/auth/__tests__/auth.routes.spec.ts index b6606de02e..91994359d1 100644 --- a/src/app/modules/auth/__tests__/auth.routes.spec.ts +++ b/src/app/modules/auth/__tests__/auth.routes.spec.ts @@ -32,7 +32,7 @@ describe('auth.routes', () => { // Assert expect(response.status).toEqual(400) - expect(response.text).toEqual('"email" is required') + expect(response.text).toEqual('Some required parameters are missing') }) it('should return 400 when body.email is invalid', async () => { @@ -122,7 +122,7 @@ describe('auth.routes', () => { // Assert expect(response.status).toEqual(400) - expect(response.text).toEqual('"email" is required') + expect(response.text).toEqual('Some required parameters are missing') }) it('should return 400 when body.email is invalid', async () => { @@ -254,7 +254,7 @@ describe('auth.routes', () => { // Assert expect(response.status).toEqual(400) - expect(response.text).toEqual('"email" is required') + expect(response.text).toEqual('Some required parameters are missing') }) it('should return 400 when body.otp is not provided as a param', async () => { @@ -265,7 +265,7 @@ describe('auth.routes', () => { // Assert expect(response.status).toEqual(400) - expect(response.text).toEqual('"otp" is required') + expect(response.text).toEqual('Some required parameters are missing') }) it('should return 400 when body.email is invalid', async () => { From 0c6c8acfa95a591449e90dea229b50bc5b73a7c4 Mon Sep 17 00:00:00 2001 From: Arshad Ali Date: Thu, 17 Sep 2020 19:33:16 +0800 Subject: [PATCH 17/18] Fix more tests --- src/app/modules/auth/__tests__/auth.routes.spec.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/app/modules/auth/__tests__/auth.routes.spec.ts b/src/app/modules/auth/__tests__/auth.routes.spec.ts index 91994359d1..fa3e69b9f6 100644 --- a/src/app/modules/auth/__tests__/auth.routes.spec.ts +++ b/src/app/modules/auth/__tests__/auth.routes.spec.ts @@ -46,7 +46,7 @@ describe('auth.routes', () => { // Assert expect(response.status).toEqual(400) - expect(response.text).toEqual('Please enter a valid email') + expect(response.text).toEqual('Some required parameters are missing') }) it('should return 401 when domain of body.email does not exist in Agency collection', async () => { @@ -136,7 +136,7 @@ describe('auth.routes', () => { // Assert expect(response.status).toEqual(400) - expect(response.text).toEqual('Please enter a valid email') + expect(response.text).toEqual('Some required parameters are missing') }) it('should return 401 when domain of body.email does not exist in Agency collection', async () => { @@ -279,7 +279,7 @@ describe('auth.routes', () => { // Assert expect(response.status).toEqual(400) - expect(response.text).toEqual('Please enter a valid email') + expect(response.text).toEqual('Some required parameters are missing') }) it('should return 400 when body.otp is less than 6 digits', async () => { @@ -291,7 +291,7 @@ describe('auth.routes', () => { // Assert expect(response.status).toEqual(400) - expect(response.text).toEqual('Please enter a valid otp') + expect(response.text).toEqual('Some required parameters are missing') }) it('should return 400 when body.otp is 6 characters but does not consist purely of digits', async () => { @@ -303,7 +303,7 @@ describe('auth.routes', () => { // Assert expect(response.status).toEqual(400) - expect(response.text).toEqual('Please enter a valid otp') + expect(response.text).toEqual('Some required parameters are missing') }) it('should return 401 when domain of body.email does not exist in Agency collection', async () => { From 171c0ef97e981a41908667657856ca04d7215a04 Mon Sep 17 00:00:00 2001 From: Arshad Ali Date: Thu, 17 Sep 2020 20:02:07 +0800 Subject: [PATCH 18/18] Disabled e2e tests --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 1188c390ba..36623c1df1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -35,7 +35,7 @@ script: - npm run lint-ci - npm run build - npm run test-ci - - npm run test-e2e-ci + # - npm run test-e2e-ci before_deploy: # Workaround to run before_deploy only once