diff --git a/api/routes/pro.js b/api/routes/pro.js index 8f80146..475adcd 100644 --- a/api/routes/pro.js +++ b/api/routes/pro.js @@ -1,13 +1,13 @@ import path from 'path'; import views from 'co-views'; import Stripe from 'stripe'; -import sendgridInit from 'sendgrid'; +import sendgrid from '@sendgrid/mail'; import models from '../../models'; const render = views(path.join(__dirname, '/../views'), { default: 'ejs' }); const stripe = new Stripe(process.env.STRIPE_SECRET_KEY); -const sendgrid = sendgridInit(process.env.SENDGRID_KEY); +sendgrid.setApiKey(process.env.SENDGRID_KEY); const from = process.env.EMAIL_FROM; const fromname = process.env.EMAIL_NAME; @@ -55,16 +55,17 @@ export async function create(ctx) { — Jonathan Cremin, Hostr Founder `; - const mail = new sendgrid.Email({ + sendgrid.send({ to: ctx.user.email, subject: 'Hostr Pro', from, fromname, html, text, + categories: [ + 'pro-upgrade', + ], }); - mail.addCategory('pro-upgrade'); - sendgrid.send(mail); } export async function cancel(ctx) { diff --git a/app.js b/app.js index 25b943b..2642412 100644 --- a/app.js +++ b/app.js @@ -13,7 +13,6 @@ import debugname from 'debug'; import * as redis from './lib/redis'; import api, { ws } from './api/app'; import web from './web/app'; -import { isContext } from 'vm'; const debug = debugname('hostr'); diff --git a/package.json b/package.json index 2d9c3b3..53dd990 100644 --- a/package.json +++ b/package.json @@ -82,7 +82,7 @@ "pg": "^7.4.3", "raven": "^2.6.2", "redis": "^2.8.0", - "sendgrid": "^5.2.3", + "@sendgrid/mail": "^6.3.1", "sequelize": "^4.37.10", "smooth-scroll": "https://github.com/cferdinandi/smooth-scroll#5.3.7", "statsy": "~0.2.0", diff --git a/web/app.js b/web/app.js index ffdabfd..f118b94 100644 --- a/web/app.js +++ b/web/app.js @@ -35,7 +35,14 @@ router.use(async (ctx, next) => { await next(); }); -router.use(new CSRF()); +router.use(new CSRF({ + invalidSessionSecretMessage: 'Invalid session secret', + invalidSessionSecretStatusCode: 403, + invalidTokenMessage: 'Invalid CSRF token', + invalidTokenStatusCode: 403, + excludedMethods: ['GET', 'HEAD', 'OPTIONS'], + disableQuery: false, +})); router.use(views(path.join(__dirname, 'views'), { extension: 'ejs', diff --git a/web/lib/auth.js b/web/lib/auth.js index fb9b337..e91767d 100644 --- a/web/lib/auth.js +++ b/web/lib/auth.js @@ -4,12 +4,12 @@ import passwords from 'passwords'; import uuid from 'node-uuid'; import views from 'co-views'; import debugname from 'debug'; -import sendgridInit from 'sendgrid'; +import sendgrid from '@sendgrid/mail'; import models from '../../models'; const render = views(join(__dirname, '..', 'views'), { default: 'ejs' }); const debug = debugname('hostr-web:auth'); -const sendgrid = sendgridInit(process.env.SENDGRID_KEY); +sendgrid.setApiKey(process.env.SENDGRID_KEY); const from = process.env.EMAIL_FROM; const fromname = process.env.EMAIL_NAME; @@ -133,16 +133,17 @@ ${process.env.WEB_BASE_URL}/activate/${user.activation.id} — Jonathan Cremin, Hostr Founder `; - const mail = new sendgrid.Email({ + sendgrid.send({ to: user.email, subject: 'Welcome to Hostr', from, fromname, html, text, + categories: [ + 'activate', + ], }); - mail.addCategory('activate'); - sendgrid.send(mail); } @@ -163,16 +164,17 @@ export async function sendResetToken(email) { const text = `It seems you've forgotten your password :( Visit ${process.env.WEB_BASE_URL}/forgot/${reset.id} to set a new one. `; - const mail = new sendgrid.Email({ + sendgrid.send({ to: user.email, from: 'jonathan@hostr.co', fromname: 'Jonathan from Hostr', subject: 'Hostr Password Reset', html, text, + categories: [ + 'password-reset', + ], }); - mail.addCategory('password-reset'); - sendgrid.send(mail); } else { throw new Error('There was an error looking up your email address.'); } diff --git a/web/routes/user.js b/web/routes/user.js index 188a000..2684fa8 100644 --- a/web/routes/user.js +++ b/web/routes/user.js @@ -41,7 +41,6 @@ export async function signup(ctx) { return; } - ctx.assertCSRF(ctx.request.body); if (ctx.request.body.email !== ctx.request.body.confirm_email) { await ctx.render('signup', { error: 'Emails do not match.', csrf: ctx.csrf }); return; @@ -69,7 +68,7 @@ export async function signup(ctx) { ctx.statsd.incr('auth.signup', 1); await ctx.render('signup', { message: 'Thanks for signing up, we\'ve sent you an email to activate your account.', - csrf: '', + csrf: ctx.csrf, }); } @@ -86,7 +85,7 @@ export async function forgot(ctx) { }); return; } - ctx.assertCSRF(ctx.request.body); + const user = await validateResetToken(token); if (user) { await updatePassword(user.userId, ctx.request.body.password); @@ -109,7 +108,7 @@ export async function forgot(ctx) { } await ctx.render('forgot', { csrf: ctx.csrf, token }); } else if (ctx.request.body.email) { - ctx.assertCSRF(ctx.request.body); + try { const { email } = ctx.request.body; await sendResetToken.call(ctx, email); diff --git a/yarn.lock b/yarn.lock index a113d61..dc66794 100755 --- a/yarn.lock +++ b/yarn.lock @@ -78,6 +78,28 @@ lodash "^4.2.0" to-fast-properties "^2.0.0" +"@sendgrid/client@^6.3.0": + version "6.3.0" + resolved "https://registry.yarnpkg.com/@sendgrid/client/-/client-6.3.0.tgz#25c34b11bec392ab43ca7e52fb35e4105fb00901" + dependencies: + "@sendgrid/helpers" "^6.3.0" + "@types/request" "^2.0.3" + request "^2.81.0" + +"@sendgrid/helpers@^6.3.0": + version "6.3.0" + resolved "https://registry.yarnpkg.com/@sendgrid/helpers/-/helpers-6.3.0.tgz#1b1798af22aa7a4c98257fab3dd2a6a6afd8b467" + dependencies: + chalk "^2.0.1" + deepmerge "^2.1.1" + +"@sendgrid/mail@^6.3.1": + version "6.3.1" + resolved "https://registry.yarnpkg.com/@sendgrid/mail/-/mail-6.3.1.tgz#e5003af167ca4dd358f04075aad4cfc30cef6c34" + dependencies: + "@sendgrid/client" "^6.3.0" + "@sendgrid/helpers" "^6.3.0" + "@types/babel-types@*", "@types/babel-types@^7.0.0": version "7.0.2" resolved "https://registry.yarnpkg.com/@types/babel-types/-/babel-types-7.0.2.tgz#63dc3e5e7f6367e1819d2bba5213783cd926c5d5" @@ -88,6 +110,16 @@ dependencies: "@types/babel-types" "*" +"@types/caseless@*": + version "0.12.1" + resolved "https://registry.yarnpkg.com/@types/caseless/-/caseless-0.12.1.tgz#9794c69c8385d0192acc471a540d1f8e0d16218a" + +"@types/form-data@*": + version "2.2.1" + resolved "https://registry.yarnpkg.com/@types/form-data/-/form-data-2.2.1.tgz#ee2b3b8eaa11c0938289953606b745b738c54b1e" + dependencies: + "@types/node" "*" + "@types/geojson@^1.0.0": version "1.0.6" resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-1.0.6.tgz#3e02972728c69248c2af08d60a48cbb8680fffdf" @@ -96,6 +128,19 @@ version "10.3.0" resolved "https://registry.yarnpkg.com/@types/node/-/node-10.3.0.tgz#078516315a84d56216b5d4fed8f75d59d3b16cac" +"@types/request@^2.0.3": + version "2.47.1" + resolved "https://registry.yarnpkg.com/@types/request/-/request-2.47.1.tgz#25410d3afbdac04c91a94ad9efc9824100735824" + dependencies: + "@types/caseless" "*" + "@types/form-data" "*" + "@types/node" "*" + "@types/tough-cookie" "*" + +"@types/tough-cookie@*": + version "2.3.3" + resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-2.3.3.tgz#7f226d67d654ec9070e755f46daebf014628e9d9" + "@webassemblyjs/ast@1.5.9": version "1.5.9" resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.5.9.tgz#b2770182678691ab4949d593105c15d4074fedb6" @@ -269,10 +314,6 @@ acorn@^5.0.0, acorn@^5.5.0: version "5.6.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.6.1.tgz#c9e50c3e3717cf897f1b071ceadbb543bbc0a8d4" -addressparser@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/addressparser/-/addressparser-1.0.1.tgz#47afbe1a2a9262191db6838e4fd1d39b40821746" - ajv-keywords@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-2.1.1.tgz#617997fc5f60576894c435f940d819e135b80762" @@ -508,64 +549,6 @@ async-limiter@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8" -async.ensureasync@^0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/async.ensureasync/-/async.ensureasync-0.5.2.tgz#c3c7e4a4e9b31d96875d56b8504598446e1e305d" - dependencies: - async.util.ensureasync "0.5.2" - -async.queue@^0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/async.queue/-/async.queue-0.5.2.tgz#8d5d90812e1481066bc0904e8cc1712b17c3bd7c" - dependencies: - async.util.queue "0.5.2" - -async.util.arrayeach@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/async.util.arrayeach/-/async.util.arrayeach-0.5.2.tgz#58c4e98028d55d69bfb05aeb3af44e0a555a829c" - -async.util.ensureasync@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/async.util.ensureasync/-/async.util.ensureasync-0.5.2.tgz#10907f2cbd067a061f99ae6d22e08ced30db0d68" - dependencies: - async.util.restparam "0.5.2" - async.util.setimmediate "0.5.2" - -async.util.isarray@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/async.util.isarray/-/async.util.isarray-0.5.2.tgz#e62dac8f2636f65875dcf7521c2d24d0dfb2bbdf" - -async.util.map@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/async.util.map/-/async.util.map-0.5.2.tgz#e588ef86e0b3ab5f027d97af4d6835d055ca69d6" - -async.util.noop@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/async.util.noop/-/async.util.noop-0.5.2.tgz#bdd62b97cb0aa3f60b586ad148468698975e58b9" - -async.util.onlyonce@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/async.util.onlyonce/-/async.util.onlyonce-0.5.2.tgz#b8e6fc004adc923164d79e32f2813ee465c24ff2" - -async.util.queue@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/async.util.queue/-/async.util.queue-0.5.2.tgz#57f65abe1a3cdf273d31abd28ab95425f8222ee5" - dependencies: - async.util.arrayeach "0.5.2" - async.util.isarray "0.5.2" - async.util.map "0.5.2" - async.util.noop "0.5.2" - async.util.onlyonce "0.5.2" - async.util.setimmediate "0.5.2" - -async.util.restparam@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/async.util.restparam/-/async.util.restparam-0.5.2.tgz#03efebf3c0277b97220e525aba750f5e04fc80cd" - -async.util.setimmediate@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/async.util.setimmediate/-/async.util.setimmediate-0.5.2.tgz#2812ebabf2a58027758d4bc7793d1ccfaf10255f" - async@1.x, async@^1.4.0: version "1.5.2" resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" @@ -913,10 +896,6 @@ bootstrap-sass@^3.3.6: version "3.3.7" resolved "https://registry.yarnpkg.com/bootstrap-sass/-/bootstrap-sass-3.3.7.tgz#6596c7ab40f6637393323ab0bc80d064fc630498" -bottleneck@^1.12.0: - version "1.16.0" - resolved "https://registry.yarnpkg.com/bottleneck/-/bottleneck-1.16.0.tgz#d6ce13808527afc80b69092f15606655e5b21f1a" - boxen@^1.2.1: version "1.3.0" resolved "https://registry.yarnpkg.com/boxen/-/boxen-1.3.0.tgz#55c6c39a8ba58d9c61ad22cd877532deb665a20b" @@ -1740,6 +1719,10 @@ deep-is@~0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" +deepmerge@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-2.1.1.tgz#e862b4e45ea0555072bf51e7fd0d9845170ae768" + define-property@^0.2.5: version "0.2.5" resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" @@ -1946,12 +1929,6 @@ encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" -encoding@^0.1.12, encoding@~0.1.12: - version "0.1.12" - resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb" - dependencies: - iconv-lite "~0.4.13" - end-of-stream@^1.0.0, end-of-stream@^1.1.0: version "1.4.1" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43" @@ -1996,7 +1973,7 @@ escape-html@~1.0.1, escape-html@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" -escape-string-regexp@1.0.5, escape-string-regexp@^1.0.0, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5, escape-string-regexp@~1.0.5: +escape-string-regexp@1.0.5, escape-string-regexp@^1.0.0, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" @@ -2990,7 +2967,7 @@ iconv-lite@0.4.19: version "0.4.19" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b" -iconv-lite@0.4.23, iconv-lite@^0.4.17, iconv-lite@^0.4.4, iconv-lite@~0.4.13: +iconv-lite@0.4.23, iconv-lite@^0.4.17, iconv-lite@^0.4.4: version "0.4.23" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.23.tgz#297871f63be507adcfbfca715d0cd0eed84e9a63" dependencies: @@ -3918,10 +3895,6 @@ lodash.assign@^4.0.3, lodash.assign@^4.0.6, lodash.assign@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7" -lodash.chunk@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/lodash.chunk/-/lodash.chunk-4.2.0.tgz#66e5ce1f76ed27b4303d8c6512e8d1216e8106bc" - lodash.clonedeep@^4.3.2: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" @@ -3984,15 +3957,6 @@ lru-cache@^4.0.1, lru-cache@^4.1.1: pseudomap "^1.0.2" yallist "^2.1.2" -mailparser@^0.6.1: - version "0.6.2" - resolved "https://registry.yarnpkg.com/mailparser/-/mailparser-0.6.2.tgz#03c486039bdf4df6cd3b6adcaaac4107dfdbc068" - dependencies: - encoding "^0.1.12" - mime "^1.3.4" - mimelib "^0.3.0" - uue "^3.1.0" - make-dir@^1.0.0: version "1.3.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c" @@ -4141,13 +4105,6 @@ mime@^1.3.4, mime@^1.4.1: version "1.6.0" resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" -mimelib@^0.3.0: - version "0.3.1" - resolved "https://registry.yarnpkg.com/mimelib/-/mimelib-0.3.1.tgz#787add2415d827acb3af6ec4bca1ea9596418853" - dependencies: - addressparser "~1.0.1" - encoding "~0.1.12" - mimic-fn@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" @@ -5407,7 +5364,7 @@ repeating@^2.0.0: dependencies: is-finite "^1.0.0" -request@2, request@^2.65.0: +request@2, request@^2.65.0, request@^2.81.0: version "2.87.0" resolved "https://registry.yarnpkg.com/request/-/request-2.87.0.tgz#32f00235cd08d482b4d0d68db93a829c0ed5756e" dependencies: @@ -5669,22 +5626,6 @@ send@0.16.2: range-parser "~1.2.0" statuses "~1.4.0" -sendgrid-rest@^2.3.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/sendgrid-rest/-/sendgrid-rest-2.4.0.tgz#88e11a86375ec0e14b5faf1b4a0a191639ce90ef" - -sendgrid@^5.2.3: - version "5.2.3" - resolved "https://registry.yarnpkg.com/sendgrid/-/sendgrid-5.2.3.tgz#37cd28ddd93fca2d3fa7dda10a323b1f43ffecfc" - dependencies: - async.ensureasync "^0.5.2" - async.queue "^0.5.2" - bottleneck "^1.12.0" - debug "^2.2.0" - lodash.chunk "^4.2.0" - mailparser "^0.6.1" - sendgrid-rest "^2.3.0" - sequelize@^4.37.10: version "4.37.10" resolved "https://registry.yarnpkg.com/sequelize/-/sequelize-4.37.10.tgz#1ccca570956a5bfe1c4c00abbc927633ca8d12d8" @@ -6603,13 +6544,6 @@ utils-merge@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" -uue@^3.1.0: - version "3.1.2" - resolved "https://registry.yarnpkg.com/uue/-/uue-3.1.2.tgz#e99368414e87200012eb37de4dbaebaa1c742ad2" - dependencies: - escape-string-regexp "~1.0.5" - extend "~3.0.0" - uuid@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.0.0.tgz#6728fc0459c450d796a99c31837569bdf672d728"