Skip to content

Commit

Permalink
Merge pull request #238 from opengovsg/release-v4.32.1
Browse files Browse the repository at this point in the history
  • Loading branch information
liangyuanruo authored Sep 1, 2020
2 parents 7849419 + 0bf07cf commit 49a64dd
Show file tree
Hide file tree
Showing 88 changed files with 5,453 additions and 2,554 deletions.
1 change: 1 addition & 0 deletions .template-env
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ FORMSG_SDK_MODE=
## App Config
# APP_NAME=FormSG
# OTP_LIFE_SPAN=900000
# BOUNCE_LIFE_SPAN=1800000
# AGGREGATE_COLLECTION=

# If provided, a banner with the provided message will show up in every form.
Expand Down
1 change: 1 addition & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ services:
- IMAGE_S3_BUCKET=local-image-bucket
- LOGO_S3_BUCKET=local-logo-bucket
- FORMSG_SDK_MODE=development
- BOUNCE_LIFE_SPAN=1800000
- GA_TRACKING_ID
- SENTRY_CONFIG_URL
- TWILIO_ACCOUNT_SID
Expand Down
72 changes: 35 additions & 37 deletions docs/DEPLOYMENT_SETUP.md

Large diffs are not rendered by default.

496 changes: 438 additions & 58 deletions package-lock.json

Large diffs are not rendered by default.

26 changes: 15 additions & 11 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.31.0",
"version": "4.32.1",
"homepage": "https://form.gov.sg",
"authors": [
"FormSG <[email protected]>"
Expand Down Expand Up @@ -67,6 +67,7 @@
"@opengovsg/ng-file-upload": "^12.2.14",
"@opengovsg/spcp-auth-client": "^1.3.0",
"@stablelib/base64": "^1.0.0",
"@types/bcrypt": "^3.0.0",
"JSONStream": "^1.3.5",
"ajv": "^5.2.3",
"angular": "~1.8.0",
Expand Down Expand Up @@ -94,7 +95,7 @@
"boxicons": "1.8.0",
"bson-ext": "^2.0.3",
"busboy": "^0.3.1",
"celebrate": "^12.1.0",
"celebrate": "^12.2.0",
"compression": "~1.7.2",
"connect": "^3.6.6",
"connect-mongo": "^3.2.0",
Expand All @@ -115,7 +116,7 @@
"fetch-readablestream": "^0.2.0",
"file-loader": "^4.0.0",
"file-saver": "^2.0.2",
"font-awesome": "4.6.1",
"font-awesome": "4.7.0",
"glob": "^7.1.2",
"has-ansi": "^4.0.0",
"helmet": "^3.21.3",
Expand All @@ -128,7 +129,7 @@
"libphonenumber-js": "^1.7.55",
"lodash": "^4.17.19",
"mobile-detect": "^1.4.2",
"moment-timezone": "0.5.13",
"moment-timezone": "0.5.31",
"mongoose": "^5.9.10",
"multiparty": ">=4.1.3",
"ng-infinite-scroll": "^1.3.0",
Expand All @@ -140,7 +141,7 @@
"nodemailer-direct-transport": "~3.3.2",
"opossum": "^5.0.0",
"proxyquire": "^2.1.0",
"puppeteer-core": "^4.0.0",
"puppeteer-core": "^5.2.1",
"raven-js": "^3.27.0",
"rimraf": "^3.0.2",
"selectize": "0.12.4",
Expand All @@ -151,7 +152,7 @@
"tweetnacl": "^1.0.1",
"twilio": "^3.33.1",
"ui-select": "^0.19.8",
"uid-generator": "^1.0.0",
"uid-generator": "^2.0.0",
"uuid": "^8.3.0",
"validator": "^11.1.0",
"web-streams-polyfill": "^2.1.1",
Expand All @@ -162,11 +163,12 @@
"devDependencies": {
"@babel/core": "^7.4.3",
"@babel/preset-env": "^7.11.0",
"@opengovsg/mockpass": "^2.1.1",
"@opengovsg/mockpass": "^2.4.6",
"@shelf/jest-mongodb": "^1.2.2",
"@types/compression": "^1.7.0",
"@types/convict": "^5.2.1",
"@types/cookie-parser": "^1.4.2",
"@types/ejs": "^3.0.4",
"@types/express": "^4.17.6",
"@types/express-session": "^1.17.0",
"@types/has-ansi": "^3.0.0",
Expand All @@ -177,18 +179,19 @@
"@types/node": "^14.0.13",
"@types/nodemailer": "^6.4.0",
"@types/nodemailer-direct-transport": "^1.0.31",
"@types/puppeteer-core": "^2.0.0",
"@types/uid-generator": "^2.0.2",
"@types/uuid": "^8.0.0",
"@types/validator": "^13.0.0",
"@typescript-eslint/eslint-plugin": "^3.3.0",
"@typescript-eslint/eslint-plugin": "^3.9.1",
"@typescript-eslint/parser": "^3.3.0",
"axios-mock-adapter": "^1.18.1",
"babel-loader": "^8.0.5",
"concurrently": "^3.6.1",
"copy-webpack-plugin": "^6.0.2",
"core-js": "^3.6.4",
"css-loader": "^2.1.1",
"env-cmd": "^9.0.3",
"env-cmd": "^10.1.0",
"eslint": "^6.8.0",
"eslint-config-prettier": "^6.11.0",
"eslint-plugin-angular": "^4.0.1",
Expand All @@ -201,7 +204,7 @@
"html-loader": "~0.5.5",
"htmlhint": "^0.14.1",
"husky": "^4.2.5",
"jasmine": "^3.1.0",
"jasmine": "^3.6.1",
"jasmine-core": "^3.1.0",
"jasmine-sinon": "^0.4.0",
"jasmine-spec-reporter": "^5.0.2",
Expand All @@ -223,9 +226,10 @@
"testcafe": "^1.8.0",
"ts-jest": "^26.1.4",
"ts-loader": "^7.0.5",
"ts-mock-imports": "^1.3.0",
"ts-node": "^8.10.2",
"ts-node-dev": "^1.0.0-pre.44",
"typescript": "^3.9.7",
"typescript": "^4.0.2",
"url-loader": "^1.1.2",
"webpack": "^4.43.0",
"webpack-cli": "^3.3.12",
Expand Down
2 changes: 2 additions & 0 deletions src/app/constants/filesize.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// 1 megabyte in bytes
export const MB = 1048576
23 changes: 23 additions & 0 deletions src/app/constants/mail.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/**
* Headers to send to SES so we can parse email notifications
*
* NOTE: ALWAYS DO CASE-INSENSITIVE CHECKS FOR THE HEADERS!
* SES will automatically convert the case, so case-sensitive
* checks might fail.
*
* For example, 'X-FormSG-Form-Id' gets changed to 'X-Formsg-Form-ID'.
*/
export const EMAIL_HEADERS = {
formId: 'X-Formsg-Form-ID',
submissionId: 'X-Formsg-Submission-ID',
emailType: 'X-Formsg-Email-Type',
}

// Types of emails we send
export const EMAIL_TYPES = {
adminResponse: 'Admin (response)',
loginOtp: 'Login OTP',
verificationOtp: 'Verification OTP',
emailConfirmation: 'Email confirmation',
adminBounce: 'Admin (bounce notification)',
}
50 changes: 9 additions & 41 deletions src/app/controllers/authentication.server.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,10 @@ const config = require('../../config/config')
const defaults = require('../../config/defaults').default
const PERMISSIONS = require('../utils/permission-levels.js')
const { getRequestIp } = require('../utils/request')
const { renderPromise } = require('../utils/render-promise')
const logger = require('../../config/logger').createLoggerWithLabel(
'authentication',
)
const { sendNodeMail } = require('../services/mail.service')
const { EMAIL_HEADERS, EMAIL_TYPES } = require('../utils/constants')
const MailService = require('../services/mail.service').default

const MAX_OTP_ATTEMPTS = 10

Expand Down Expand Up @@ -201,48 +199,18 @@ exports.sendOtp = async function (req, res) {
// 2. Return success statement to front end

let otp = res.locals.otp
let email = res.locals.email
let recipient = res.locals.email

let emailHTML
try {
emailHTML = await renderPromise(res, 'templates/otp-email', {
appName: res.app.locals.title,
appUrl: config.app.appUrl,
otp: otp,
await MailService.sendLoginOtp({
recipient,
otp,
ipAddress: getRequestIp(req),
})
} catch (renderErr) {
logger.error(getRequestIp(req), req.url, req.headers, renderErr)
return res
.status(HttpStatus.INTERNAL_SERVER_ERROR)
.send(
'Error rendering OTP. Please try again later and if the problem persists, contact us.',
)
}
let mailOptions = {
to: email,
from: config.mail.mailer.from,
subject: 'One-Time Password (OTP) for ' + res.app.locals.title,
html: emailHTML,
headers: {
[EMAIL_HEADERS.emailType]: EMAIL_TYPES.loginOtp,
},
}
try {
await sendNodeMail({
mail: mailOptions,
options: { mailId: 'OTP' },
})
logger.info(`Login OTP sent:\temail=${email} ip=${getRequestIp(req)}`)
return res.status(HttpStatus.OK).send('OTP sent to ' + email + '!')
} catch (emailErr) {
logger.error(
'Mail otp error',
getRequestIp(req),
req.url,
req.headers,
emailErr,
)
logger.info(`Login OTP sent:\temail=${recipient} ip=${getRequestIp(req)}`)
return res.status(HttpStatus.OK).send(`OTP sent to ${recipient}!`)
} catch (err) {
logger.error('Mail otp error', getRequestIp(req), req.url, req.headers, err)
return res
.status(HttpStatus.INTERNAL_SERVER_ERROR)
.send(
Expand Down
Loading

0 comments on commit 49a64dd

Please sign in to comment.