Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: Merge release into master #126

Merged
merged 13 commits into from
Aug 12, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 0 additions & 16 deletions .testcaferc.json

This file was deleted.

27 changes: 20 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,13 +133,26 @@ Scripts for common tasks in MongoDB can be found [here](docs/MONGODB.md).

## Maintenance Banners

Banners providing form-fillers with useful information can shown at the top of forms and configured using the following environment variables

- `IS_GENERAL_MAINTENANCE`: When defined, the value of this environment variable will be shown as a banner at the top of all public forms
- `IS_SP_MAINTENANCE`: When defined, the value of this environment variable will be shown as a banner at the top of all public SingPass-enabled forms
- `IS_CP_MAINTENANCE`: When defined, the value of this environment variable will be shown as a banner at the top of all public CorpPass-enabled forms

Note that if more than one of the above environment variables are defined, only one environment variable will be read in the precedence, `IS_GENERAL_MAINTENANCE`, `IS_SP_MAINTENANCE` and then `IS_CP_MAINTENANCE`
Banners providing form-fillers with useful information can shown at the top of
forms and configured using the environment variables below.

| Environment Variable | Value will be shown as a banner at the bottom of |
| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `ADMIN_BANNER_CONTENT` | private form routes such as `/forms` and `/{formId}/admin` |
| `SITE_BANNER_CONTENT` | both private routes that `ADMIN_BANNER_CONTENT` covers **and** public form routes that `IS_GENERAL_MAINTENANCE` covers. This supersedes **ALL** other banner environment variables |
| `IS_GENERAL_MAINTENANCE` | all public forms |
| `IS_SP_MAINTENANCE` | all public **SingPass-enabled** forms |
| `IS_CP_MAINTENANCE` | all public **CorpPass-enabled** forms |

> Note that if more than one of the above environment variables are defined,
> only one environment variable will be used to display the given values.
>
> For public form routes, only one environment variable will be read in the
> following precedence: `SITE_BANNER_CONTENT` > `IS_GENERAL_MAINTENANCE` >
> `IS_SP_MAINTENANCE` > `IS_CP_MAINTENANCE`
>
> For private form routes, only one environment variable will be read in the
> following precendence: `SITE_BANNER_CONTENT` > `ADMIN_BANNER_CONTENT`

## Contributing

Expand Down
134 changes: 68 additions & 66 deletions docs/DEPLOYMENT_SETUP.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 14 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "FormSG",
"description": "Form Manager for Government",
"version": "4.29.1",
"version": "4.30.2",
"homepage": "https://form.gov.sg",
"authors": [
"FormSG <[email protected]>"
Expand All @@ -19,16 +19,23 @@
"build": "npm run build-backend && npm run build-frontend",
"build-backend": "tsc",
"build-frontend": "webpack --config webpack.prod.js",
"build-frontend-dev": "webpack --config webpack.dev.js",
"start": "node dist/backend/server.js",
"dev": "docker-compose up --build",
"docker-dev": "webpack -w --config webpack.dev.js & ts-node-dev --respawn --transpileOnly --inspect=0.0.0.0 -- src/server.ts",
"test": "npm run build-backend && npm run test-backend && npm run test-frontend",
"test-ci": "npm run test-backend && npm run test-frontend",
"test-backend": "env-cmd -f .test-env --use-shell \"node tests/end-to-end/helpers/get-mongo-binary.js && jasmine --config=tests/unit/backend/jasmine.json\"",
"docker-dev": "npm run build-frontend-dev & ts-node-dev --respawn --transpileOnly --inspect=0.0.0.0 -- src/server.ts",
"test-backend": "env-cmd -f tests/.test-full-env --use-shell \"npm run download-binary && jasmine --config=tests/unit/backend/jasmine.json\"",
"test-frontend": "jest --config=tests/unit/frontend/jest.config.js",
"test-ci": "npm run test-backend && npm run test-frontend",
"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\"",
"test-e2e": "env-cmd -f .test-env --use-shell \"node tests/end-to-end/helpers/get-mongo-binary.js && npm run build-backend && webpack --config webpack.dev.js && testcafe\"",
"test-e2e-ci": "env-cmd -f .test-env --use-shell \"testcafe\"",
"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",
"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\"",
"test-e2e": "npm run test-e2e-build && npm run test-e2e-full && npm run test-e2e-basic",
"test-e2e-ci": "npm run test-e2e-full && npm run test-e2e-basic",
"lint-code": "eslint './src/**' --quiet --fix",
"lint-style": "stylelint '*/**/*.css' --quiet --fix",
"lint-html": "htmlhint && prettier --write './src/public/**/*.html' --ignore-path './dist/**' --loglevel silent",
Expand Down
5 changes: 3 additions & 2 deletions src/config/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -332,11 +332,12 @@ const awsConfig: AwsConfig = (function () {
// Else, the environment variables to instantiate S3 are used.
const awsEndpoint = isDev
? defaults.aws.endpoint
: `https://s3.${region}.amazonaws.com/`
: `https://s3.${region}.amazonaws.com` // NOTE NO TRAILING / AT THE END OF THIS URL!

const logoBucketUrl = `${awsEndpoint}/${logoS3Bucket}`
const imageBucketUrl = `${awsEndpoint}/${imageS3Bucket}`
const attachmentBucketUrl = `${awsEndpoint}/${attachmentS3Bucket}`
// NOTE THE TRAILING / AT THE END OF THIS URL! This is only for attachments!
const attachmentBucketUrl = `${awsEndpoint}/${attachmentS3Bucket}/`

const s3 = new aws.S3({
region,
Expand Down
17 changes: 11 additions & 6 deletions src/config/formsg-sdk.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
import formsgSdkPackage from '@opengovsg/formsg-sdk'
import { get } from 'lodash'

import * as vfnConstants from '../shared/util/verification'
import { formsgSdkMode } from './config'
import featureManager from './feature-manager'
import { FeatureNames } from './feature-manager/types'

const formsgSdk = formsgSdkPackage({
webhookSecretKey:
featureManager.props(FeatureNames.WebhookVerifiedContent)
.signingSecretKey || '',
webhookSecretKey: get(
featureManager.props(FeatureNames.WebhookVerifiedContent),
'signingSecretKey',
null,
),
mode: formsgSdkMode,
verificationOptions: {
secretKey:
featureManager.props(FeatureNames.VerifiedFields).verificationSecretKey ||
'',
secretKey: get(
featureManager.props(FeatureNames.VerifiedFields),
'verificationSecretKey',
null,
),
transactionExpiry: vfnConstants.TRANSACTION_EXPIRE_AFTER_SECONDS,
},
})
Expand Down
8 changes: 5 additions & 3 deletions src/config/logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ import { v4 as uuidv4 } from 'uuid'
import { format, LoggerOptions, loggers, transports } from 'winston'
import WinstonCloudWatch from 'winston-cloudwatch'

import { aws, customCloudWatchGroup } from './config'
import defaults from './defaults'

// Cannot use config's isDev due to logger being instantiated first, and
// Cannot use config due to logger being instantiated first, and
// having circular dependencies.
const isDev = process.env.NODE_ENV === 'development'
const customCloudWatchGroup = process.env.CUSTOM_CLOUDWATCH_LOG_GROUP
const awsRegion = process.env.AWS_REGION || defaults.aws.region

// Config to make winston logging like console logging, allowing multiple
// arguments.
Expand Down Expand Up @@ -121,7 +123,7 @@ export const createCloudWatchLogger = (label: string) => {
// not share sequence tokens. Hence generate a unique ID for each instance
// of the logger.
logStreamName: uuidv4(),
awsRegion: aws.region,
awsRegion,
jsonMessage: true,
}),
]
Expand Down
43 changes: 31 additions & 12 deletions src/loaders/express/locals.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import ejs from 'ejs'
import { get } from 'lodash'

import config from '../../config/config'
import featureManager from '../../config/feature-manager'
Expand All @@ -12,18 +13,36 @@ const frontendVars = {
adminBannerContent: config.adminBannerContent,
logoBucketUrl: config.aws.logoBucketUrl, // S3 bucket
formsgSdkMode: config.formsgSdkMode,
captchaPublicKey:
featureManager.props(FeatureNames.Captcha).captchaPublicKey || '', // Recaptcha
sentryConfigUrl:
featureManager.props(FeatureNames.Sentry).sentryConfigUrl || '', // Sentry.IO
isSPMaintenance:
featureManager.props(FeatureNames.SpcpMyInfo).isSPMaintenance || '', // Singpass maintenance message
isCPMaintenance:
featureManager.props(FeatureNames.SpcpMyInfo).isCPMaintenance || '', // Corppass maintenance message
GATrackingID:
featureManager.props(FeatureNames.GoogleAnalytics).GATrackingID || '',
spcpCookieDomain: featureManager.props(FeatureNames.SpcpMyInfo)
.spcpCookieDomain, // Cookie domain used for removing spcp cookies
captchaPublicKey: get(
featureManager.props(FeatureNames.Captcha),
'captchaPublicKey',
null,
), // Recaptcha
sentryConfigUrl: get(
featureManager.props(FeatureNames.Sentry),
'sentryConfigUrl',
null,
), // Sentry.IO
isSPMaintenance: get(
featureManager.props(FeatureNames.SpcpMyInfo),
'isSPMaintenance',
null,
), // Singpass maintenance message
isCPMaintenance: get(
featureManager.props(FeatureNames.SpcpMyInfo),
'isCPMaintenance',
null,
), // Corppass maintenance message
GATrackingID: get(
featureManager.props(FeatureNames.GoogleAnalytics),
'GATrackingID',
null,
),
spcpCookieDomain: get(
featureManager.props(FeatureNames.SpcpMyInfo),
'spcpCookieDomain',
null,
), // Cookie domain used for removing spcp cookies
}
const environment = ejs.render(
`
Expand Down
16 changes: 5 additions & 11 deletions src/public/modules/forms/admin/css/view-responses.css
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,6 @@
#secret-key .instructions-caption {
margin-top: 15px;
margin-bottom: 15px;
padding-left: 16px;
text-align: center;
}

Expand Down Expand Up @@ -327,9 +326,9 @@
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
-webkit-box-pack: justify;
-ms-flex-pack: justify;
justify-content: space-between;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
Expand Down Expand Up @@ -366,9 +365,8 @@
}

#secret-key #enter-secret-key input {
width: 513px;
height: 54px;
margin: 0 10px;
margin-right: 10px;
}

#secret-key .input-acknowledgement {
Expand Down Expand Up @@ -418,7 +416,6 @@

#secret-key .instructions {
text-align: left;
padding-left: 16px;
}

#secret-key .warning-acknowledgement {
Expand All @@ -434,10 +431,7 @@

@media (min-width: 576px) {
#secret-key .instructions-container {
width: min-content;
}
#secret-key .input-acknowledgement {
margin: 10px 10px 0;
width: calc(100% - 115px);
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/shared/constants.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Enum of actions that can be used to edit a form field
export enum EditFieldActions {
Create = 'Create',
Create = 'CREATE',
Duplicate = 'DUPLICATE',
Reorder = 'REORDER',
Update = 'UPDATE',
Expand Down
24 changes: 24 additions & 0 deletions tests/.test-basic-env
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
APP_NAME=FormSG

SES_PORT=1025
SES_HOST=
SES_USER=
SES_PASS=
DB_HOST=
PORT=

OTP_LIFE_SPAN=900000
FORMSG_LOCALSTACK_ENDPT=http://localhost:4572
SERVICES=s3

CHROMIUM_BIN=/usr/bin/chromium-browser
MONGO_BINARY_VERSION=3.6.12

IMAGE_S3_BUCKET=local-image-bucket
LOGO_S3_BUCKET=local-logo-bucket
ATTACHMENT_S3_BUCKET=local-attachment-bucket
NODE_ENV=development
FORMSG_SDK_MODE=test

AWS_ACCESS_KEY_ID=fakeAccessKeyId
AWS_SECRET_ACCESS_KEY=fakeSecretAccessKey
34 changes: 16 additions & 18 deletions .test-env → tests/.test-full-env
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
NODE_ENV=development

SP_FORMSG_KEY_PATH=./node_modules/@opengovsg/mockpass/static/certs/key.pem
SP_FORMSG_CERT_PATH=./node_modules/@opengovsg/mockpass/static/certs/server.crt
SP_IDP_CERT_PATH=./node_modules/@opengovsg/mockpass/static/certs/spcp.crt
Expand Down Expand Up @@ -35,39 +33,39 @@ MOCKPASS_UEN=123456789A
GOOGLE_CAPTCHA=123456789
GOOGLE_CAPTCHA_PUBLIC=987654321

APP_NAME=FormSG
GA_TRACKING_ID=UA-123456789-0
SENTRY_CONFIG_URL=https://[email protected]/1234567
CSP_REPORT_URI=https://[email protected]/1234567

TWILIO_ACCOUNT_SID=ACrandomTwilioSid
TWILIO_API_KEY=SKrandomTwilioAPIKEY
TWILIO_API_SECRET=verySecureSecretXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
TWILIO_MESSAGING_SERVICE_SID=MGXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

VERIFICATION_SECRET_KEY=zLnXIV0cGjODell5w1usEHcGOJ/xsQDuDOw2BPcPEQOKV4Ojfbw/9QCkE8A25L/E7o/gG4dKA+eNFEGJ+BBi+w==
SIGNING_SECRET_KEY=/u+LP57Ib9y5Ytpud56FzuitSC9O6lJ4EOLOFHpsHlYpRjVdPfRqv5et5WOxLXD9zcSkOzagBJsXobd6+9pQkw==

APP_NAME=FormSG

SES_PORT=1025
SES_HOST=
SES_USER=
SES_PASS=
MONGO_BINARY_VERSION=3.6.12
DB_HOST=
PORT=

TWILIO_ACCOUNT_SID=ACrandomTwilioSid
TWILIO_API_KEY=SKrandomTwilioAPIKEY
TWILIO_API_SECRET=verySecureSecretXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
TWILIO_MESSAGING_SERVICE_SID=MGXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

OTP_LIFE_SPAN=900000
FORMSG_LOCALSTACK_ENDPT=http://localhost:4572
SERVICES=s3

CHROMIUM_BIN=/usr/bin/chromium-browser
IMAGE_S3_BUCKET=local-image-bucket
LOGO_S3_BUCKET=local-logo-bucket
ATTACHMENT_S3_BUCKET=local-attachment-bucket

CHROMIUM_BIN=/usr/bin/chromium-browser

SIGNING_SECRET_KEY=/u+LP57Ib9y5Ytpud56FzuitSC9O6lJ4EOLOFHpsHlYpRjVdPfRqv5et5WOxLXD9zcSkOzagBJsXobd6+9pQkw==
NODE_ENV=development
FORMSG_SDK_MODE=test

VERIFICATION_SECRET_KEY=zLnXIV0cGjODell5w1usEHcGOJ/xsQDuDOw2BPcPEQOKV4Ojfbw/9QCkE8A25L/E7o/gG4dKA+eNFEGJ+BBi+w==

FORMSG_LOCALSTACK_ENDPT=http://localhost:4572
SERVICES=s3
MONGO_BINARY_VERSION=3.6.12

AWS_ACCESS_KEY_ID=fakeAccessKeyId
AWS_SECRET_ACCESS_KEY=fakeSecretAccessKey
AWS_SECRET_ACCESS_KEY=fakeSecretAccessKey
Loading