From f26b8ece56acdcb8bfb9181b26e2a0180a07c99c Mon Sep 17 00:00:00 2001 From: Sorrel Bri Date: Mon, 13 Jan 2020 14:47:45 -0800 Subject: [PATCH] add sign jwt function and hook to auth/signup --- .../play-node-go/server/controllers/auth.js | 14 ++- packages/play-node-go/server/data/db.js | 4 +- .../data/migrations/20200107214047_init.js | 2 - .../server/{knexfile.js => knexConfig.js} | 0 .../play-node-go/server/package-lock.json | 96 +++++++++++++++++++ packages/play-node-go/server/package.json | 2 + packages/play-node-go/server/server.js | 2 +- .../play-node-go/server/services/signToken.js | 20 ++++ .../play-node-go/server/test/auth.spec.js | 32 +++++++ packages/play-node-go/server/test/spec.js | 62 +++++++++++- 10 files changed, 223 insertions(+), 11 deletions(-) rename packages/play-node-go/server/{knexfile.js => knexConfig.js} (100%) create mode 100644 packages/play-node-go/server/services/signToken.js create mode 100644 packages/play-node-go/server/test/auth.spec.js diff --git a/packages/play-node-go/server/controllers/auth.js b/packages/play-node-go/server/controllers/auth.js index 61f3a26..5b3c44c 100644 --- a/packages/play-node-go/server/controllers/auth.js +++ b/packages/play-node-go/server/controllers/auth.js @@ -1,7 +1,15 @@ +const signToken = require('../services/signToken'); - -const signUp = (req, res, next) => { - +const signUp = async (req, res, next) => { + + const user = req.body; + try { + signToken(res, user); + res.send('ok').status(200); + } + catch (err) { + res.status(500).json(err) + } } const login = (req, res, next) => { diff --git a/packages/play-node-go/server/data/db.js b/packages/play-node-go/server/data/db.js index 9a5f292..947e794 100644 --- a/packages/play-node-go/server/data/db.js +++ b/packages/play-node-go/server/data/db.js @@ -1,8 +1,8 @@ const knex = require('knex'); -const knexfile = require('../knexfile'); +const knexConfig = require('../knexConfig'); const env = process.env.NODE_ENV || 'development'; -const configOptions = knexfile[env]; +const configOptions = knexConfig[env]; module.exports = knex(configOptions); \ No newline at end of file diff --git a/packages/play-node-go/server/data/migrations/20200107214047_init.js b/packages/play-node-go/server/data/migrations/20200107214047_init.js index 99dc14f..38e13fe 100644 --- a/packages/play-node-go/server/data/migrations/20200107214047_init.js +++ b/packages/play-node-go/server/data/migrations/20200107214047_init.js @@ -1,8 +1,6 @@ exports.up = function(knex) { - }; exports.down = function(knex) { - }; diff --git a/packages/play-node-go/server/knexfile.js b/packages/play-node-go/server/knexConfig.js similarity index 100% rename from packages/play-node-go/server/knexfile.js rename to packages/play-node-go/server/knexConfig.js diff --git a/packages/play-node-go/server/package-lock.json b/packages/play-node-go/server/package-lock.json index 82b0d9c..09a6fa3 100644 --- a/packages/play-node-go/server/package-lock.json +++ b/packages/play-node-go/server/package-lock.json @@ -316,6 +316,11 @@ "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true }, + "buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" + }, "buffer-writer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", @@ -746,6 +751,14 @@ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz", "integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==" }, + "ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "requires": { + "safe-buffer": "^5.0.1" + } + }, "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -1644,6 +1657,54 @@ "esprima": "^4.0.0" } }, + "jsonwebtoken": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", + "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", + "requires": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^5.6.0" + }, + "dependencies": { + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + } + } + }, + "jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "requires": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "requires": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, "kind-of": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", @@ -1726,6 +1787,41 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" }, + "lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=" + }, + "lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=" + }, + "lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=" + }, + "lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=" + }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" + }, + "lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=" + }, + "lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=" + }, "log-symbols": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", diff --git a/packages/play-node-go/server/package.json b/packages/play-node-go/server/package.json index aa8a014..e2b871c 100644 --- a/packages/play-node-go/server/package.json +++ b/packages/play-node-go/server/package.json @@ -7,6 +7,7 @@ "test": "mocha ./test/*", "make-migration": "./node_modules/.bin/knex migrate:make", "migrate": "./node_modules/.bin/knex migrate:latest", + "migrate-test": "./node_modules/.bin/knex migrate:latest --env test", "seed": "./node_modules/.bin/knex seed:run" }, "dependencies": { @@ -16,6 +17,7 @@ "dotenv": "^8.2.0", "express": "~4.16.1", "http-errors": "~1.6.3", + "jsonwebtoken": "^8.5.1", "knex": "^0.20.7", "morgan": "~1.9.1", "pg": "^7.17.0", diff --git a/packages/play-node-go/server/server.js b/packages/play-node-go/server/server.js index 427012a..b469e0c 100644 --- a/packages/play-node-go/server/server.js +++ b/packages/play-node-go/server/server.js @@ -38,7 +38,7 @@ app.use('/', indexRouter); app.use('/users', usersRouter); app.use('/auth', authRouter); // @auth -app.use('/api', apiRouter); +app.use('/api/v1', apiRouter); // catch 404 and forward to error handler app.use(function(req, res, next) { diff --git a/packages/play-node-go/server/services/signToken.js b/packages/play-node-go/server/services/signToken.js new file mode 100644 index 0000000..06de9fd --- /dev/null +++ b/packages/play-node-go/server/services/signToken.js @@ -0,0 +1,20 @@ +const jwt = require('jsonwebtoken'); +require('dotenv').config(); + +const msDayOffset = 86400000; +const msHourOffset = 3600000; + +const signToken = (res, user) => { + const expiration = process.env.NODE_ENV === 'test' ? msHourOffset : msDayOffset; + const secret = process.env.NODE_ENV === 'test' ? process.env.TEST_SECRET : process.env.JWT_SECRET; + console.log(process.env.NODE_ENV) + const token = jwt.sign({ user }, secret, { + expiresIn: process.env.NODE_ENV === 'test' ? '1h' : '24h', + }); + return res.cookie('token', token, { + expires: new Date(Date.now() + expiration), + secure: false, // set to true if your using https + httpOnly: true, + }); +}; +module.exports = signToken; \ No newline at end of file diff --git a/packages/play-node-go/server/test/auth.spec.js b/packages/play-node-go/server/test/auth.spec.js new file mode 100644 index 0000000..251c5bc --- /dev/null +++ b/packages/play-node-go/server/test/auth.spec.js @@ -0,0 +1,32 @@ +const authSpec = (chai, server) => { + const newUserFormData = { + 'username':'newUser', + 'password':'password', + 'email':'user@example.com' + } + + it('post to sign up should return 200 status', done => { + chai.request(server) + .post('/auth/signup') + .type('form') + .send(newUserFormData) + .end((err, res) => { + if (err) done(err); + res.should.status(200); + done(); + }); + }); + + it('post to sign up should return token', done => { + chai.request(server) + .post('/auth/signup') + .type('form') + .send(newUserFormData) + .end((err, res) => { + if (err) done(err); + res.should.cookie('token'); + done(); + }); + }); +} +module.exports = authSpec; \ No newline at end of file diff --git a/packages/play-node-go/server/test/spec.js b/packages/play-node-go/server/test/spec.js index 6fab825..d4efcb8 100644 --- a/packages/play-node-go/server/test/spec.js +++ b/packages/play-node-go/server/test/spec.js @@ -2,19 +2,75 @@ process.env.NODE_ENV = 'test'; const chai = require('chai'); const chaiHttp = require('chai-http'); +var knex = require('../data/db'); -const app = require('../server'); +const server = require('../server'); const should = chai.should(); +// const authSpec = require('./auth.spec'); chai.use(chaiHttp); // ! to run tests from other testing modules // import someTest from './endpoint/someTest'; +const setupDb = () => { + beforeEach(done => { + knex.migrate.rollback(true) + .then(() => knex.migrate.latest()) + .then(() => done()); + }); +} + +describe('Auth Routes', function() { + setupDb(); + + // authSpec(chai, server) + + const newUserFormData = { + 'username':'newUser', + 'password':'password', + 'email':'user@example.com' + } + + it('post to sign up should return 200 status', function(done) { + chai.request(server) + .post('/auth/signup') + .type('form') + .send(newUserFormData) + .end((err, res) => { + if (err) done(err); + res.should.status(200); + done(); + }); + }); + + it('post to sign up should return token', done => { + chai.request(server) + .post('/auth/signup') + .type('form') + .send(newUserFormData) + .end((err, res) => { + if (err) done(err); + res.should.cookie('token'); + done(); + }); + }); + +}) + describe('API Routes', function() { - // ! should be a function that returns tests to be run - // someTest(chai) + setupDb(); + + it('home should return 200 status', done => { + chai.request(server) + .get('/') + .end((err,res)=> { + if(err) done(err); + res.should.status(200); + done(); + }) + }) });