From d429deb872b2aa739c4650b1c3110941c55948a3 Mon Sep 17 00:00:00 2001 From: lakhara Date: Mon, 12 Feb 2018 18:34:56 +0530 Subject: [PATCH 01/20] receive money partially implemented --- routes/Handler/rcvHandler.js | 79 ++++++++++++++++++++++++++++++++++++ routes/rcv.js | 23 +++++++++++ 2 files changed, 102 insertions(+) create mode 100644 routes/Handler/rcvHandler.js create mode 100644 routes/rcv.js diff --git a/routes/Handler/rcvHandler.js b/routes/Handler/rcvHandler.js new file mode 100644 index 0000000..8fbc2d0 --- /dev/null +++ b/routes/Handler/rcvHandler.js @@ -0,0 +1,79 @@ +const Models = require('../../models'); + +const transferMoney = (fromId, currentUserId, amt) => new Promise((resolve) => { + Models.userDetails.findOne({ where: { userId: currentUserId } }) // increase money from currentUser + .then((currentUserInfo) => { + const newBalance = currentUserInfo.balance + amt; // get current balance + Models.userDetails.update( + { balance: newBalance }, + { where: { userId: currentUserId } }, + ) + .then(() => { + Models.blockedmoney.destroy({ + where: { // delete the data from blocked money table + fromId, + toId: currentUserId, + }, + }) + .then(() => { // update transaction in transaction history + Models.transactions.update({ + status: 'COMPLETED', + }, { + where: { + fromId, + toId: currentUserId, + }, + }) + .then(() => { + resolve(); + }); + }); + }); + }); +}); + +const restoreMoney = (fromId, currentUserId, amt) => new Promise((resolve) => { + Models.userDetails.findOne({ where: { userId: fromId } }) // increase money from currentUser + .then((currentUserInfo) => { + const newBalance = currentUserInfo.balance + amt; // get current balance + Models.userDetails.update( + { balance: newBalance }, + { where: { userId: fromId } }, + ) + .then(() => { + Models.blockedmoney.destroy({ + where: { // delete the data from blocked money table + fromId, + toId: currentUserId, + }, + }) + .then(() => { // update transaction in transaction history + Models.transactions.update({ + status: 'FAILED', + }, { + where: { + fromId, + toId: currentUserId, + }, + }) + .then(() => { + resolve(); + }); + }); + }); + }); +}); + +const handlerFn = (fromId, currentUserId, amt, decision) => new Promise((resolve) => { + if (decision) { + transferMoney(fromId, currentUserId, amt).then(() => { + resolve(); + }); + } else { + restoreMoney(fromId, currentUserId, amt).then(() => { + resolve(); + }); + } +}); + +module.exports = handlerFn; diff --git a/routes/rcv.js b/routes/rcv.js new file mode 100644 index 0000000..693c991 --- /dev/null +++ b/routes/rcv.js @@ -0,0 +1,23 @@ +const rcvHandler = require('./Handler/rcvHandler'); + +module.exports = [{ + method: 'POST', + path: '/transaction/rcv', + handler: (req, reply) => { + const fromId = req.payload.from; + const amt = req.payload.amount; + const goAhead = req.payload.decision; + // const currentUserId = getFromAuths; + if (goAhead === 'NO') { + rcvHandler(fromId, currentUserId, amt, 0).then(() => { + // send notification back at fromId + reply('Transaction cancelled'); + }); + } else { + rcvHandler(fromId, currentUserId, amt, 1).then(() => { + // send notification back at fromId + reply('Amount transferred'); + }); + } + }, +}]; From 482e83b16fd81faa0f0e111882a9e25e5caaec57 Mon Sep 17 00:00:00 2001 From: lakhara Date: Mon, 12 Feb 2018 22:04:39 +0530 Subject: [PATCH 02/20] Approve request partially implemented --- routes/Handler/approveHandler.js | 77 ++++++++++++++++++++++++++++++++ routes/approve.js | 23 ++++++++++ 2 files changed, 100 insertions(+) create mode 100644 routes/Handler/approveHandler.js create mode 100644 routes/approve.js diff --git a/routes/Handler/approveHandler.js b/routes/Handler/approveHandler.js new file mode 100644 index 0000000..f4adb59 --- /dev/null +++ b/routes/Handler/approveHandler.js @@ -0,0 +1,77 @@ +const Models = require('../../models'); + +const decreaseBalance = (fromId, amt) => new Promise((resolve) => { + Models.userDetails.findOne({ where: { userId: fromId } }) + .then((userObject) => { + const newBalance = amt - userObject.balance; + Models.userDetails.update( + { balance: newBalance }, + { where: { userId: fromId } }, + ) + .then(() => { + resolve(); + }); + }); +}); + +const increaseBalance = (currentUserId, amt) => new Promise((resolve) => { + Models.userDetails.findOne({ where: { userId: currentUserId } }) + .then((userObject) => { + const newBalance = amt + userObject.balance; + Models.userDetails.update( + { balance: newBalance }, + { where: { userId: currentUserId } }, + ) + .then(() => { + resolve(); + }); + }); +}); + +const transferMoney = (fromId, currentUserId, amt) => new Promise((resolve) => { + decreaseBalance(fromId, amt).then(() => { + increaseBalance(currentUserId, amt).then(() => { + Models.transactions.update({ + status: 'COMPLETED', + }, { + where: { + fromId, + toId: currentUserId, + }, + }).then(() => { + resolve(); + }); + }); + }); +}); + + +const cancelTransaction = (fromId, currentUserId) => new Promise((resolve) => { + // update transaction status in transaction history + Models.transactions.update({ + status: 'FAILED', + }, { + where: { + fromId, + toId: currentUserId, + }, + }) + .then(() => { + resolve(); + }); +}); + + +const handlerFn = (fromId, currentUserId, amt, decision) => new Promise((resolve) => { + if (decision) { + transferMoney(fromId, currentUserId, amt).then(() => { + resolve(); + }); + } else { + cancelTransaction(fromId, currentUserId).then(() => { + resolve(); + }); + } +}); + +module.exports = handlerFn; diff --git a/routes/approve.js b/routes/approve.js new file mode 100644 index 0000000..b90dc53 --- /dev/null +++ b/routes/approve.js @@ -0,0 +1,23 @@ +const approveHandler = require('./Handler/approveHandler'); + +module.exports = [{ + method: 'POST', + path: '/transaction/approve', + handler: (req, reply) => { + const fromId = req.payload.from; + const amt = req.payload.amount; + const goAhead = req.payload.decision; + // const currentUserId = getFromAuths; + if (goAhead === 'NO') { + approveHandler(fromId, currentUserId, amt, 0).then(() => { + // send notification back at fromId + reply('Transaction cancelled'); + }); + } else { + approveHandler(fromId, currentUserId, amt, 1).then(() => { + // send notification back at fromId + reply('Amount transferred'); + }); + } + }, +}]; From 156828eee0ccf620c8d315285bdea4635fb1a682 Mon Sep 17 00:00:00 2001 From: lakhara Date: Tue, 13 Feb 2018 18:07:19 +0530 Subject: [PATCH 03/20] Modified config JSON for local --- config/config.json | 4 ++-- routes/index.js | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/config/config.json b/config/config.json index 6c2f503..993f2a5 100644 --- a/config/config.json +++ b/config/config.json @@ -1,14 +1,14 @@ { "development": { "username": "teamsix", - "password": null, + "password": "root", "database": "wallet_development", "host": "127.0.0.1", "dialect": "postgres" }, "test": { "username": "teamsix", - "password": null, + "password": "root", "database": "wallet_test", "host": "127.0.0.1", "dialect": "postgres" diff --git a/routes/index.js b/routes/index.js index 08bc059..a2442c5 100644 --- a/routes/index.js +++ b/routes/index.js @@ -1,5 +1,7 @@ const ping = require('./ping'); const { route: userRegistration } = require('./userRegister'); const userLogin = require('./userLogin'); +const rcvMoney = require('./rcv'); +const approve = require('./approve'); -module.exports = [].concat(ping, userRegistration, userLogin); +module.exports = [].concat(ping, userRegistration, userLogin, rcvMoney, approve); From 66fa1c272d6634664b24a887155d444ef6781ba7 Mon Sep 17 00:00:00 2001 From: lakhara Date: Thu, 22 Feb 2018 19:01:07 +0530 Subject: [PATCH 04/20] added userId from auth --- routes/Handler/rcvHandler.js | 2 +- routes/approve.js | 4 +--- routes/rcv.js | 4 ++-- server.js | 5 ++++- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/routes/Handler/rcvHandler.js b/routes/Handler/rcvHandler.js index 8fbc2d0..57c83dd 100644 --- a/routes/Handler/rcvHandler.js +++ b/routes/Handler/rcvHandler.js @@ -1,7 +1,7 @@ const Models = require('../../models'); const transferMoney = (fromId, currentUserId, amt) => new Promise((resolve) => { - Models.userDetails.findOne({ where: { userId: currentUserId } }) // increase money from currentUser + Models.userDetails.findOne({ where: { userId: currentUserId } })// increase money from currentUser .then((currentUserInfo) => { const newBalance = currentUserInfo.balance + amt; // get current balance Models.userDetails.update( diff --git a/routes/approve.js b/routes/approve.js index b90dc53..3542781 100644 --- a/routes/approve.js +++ b/routes/approve.js @@ -7,15 +7,13 @@ module.exports = [{ const fromId = req.payload.from; const amt = req.payload.amount; const goAhead = req.payload.decision; - // const currentUserId = getFromAuths; + const currentUserId = req.auth.credentials.userId; if (goAhead === 'NO') { approveHandler(fromId, currentUserId, amt, 0).then(() => { - // send notification back at fromId reply('Transaction cancelled'); }); } else { approveHandler(fromId, currentUserId, amt, 1).then(() => { - // send notification back at fromId reply('Amount transferred'); }); } diff --git a/routes/rcv.js b/routes/rcv.js index 693c991..3d339f2 100644 --- a/routes/rcv.js +++ b/routes/rcv.js @@ -2,12 +2,12 @@ const rcvHandler = require('./Handler/rcvHandler'); module.exports = [{ method: 'POST', - path: '/transaction/rcv', + path: '/transaction/receive', handler: (req, reply) => { const fromId = req.payload.from; const amt = req.payload.amount; const goAhead = req.payload.decision; - // const currentUserId = getFromAuths; + const currentUserId = req.auth.credentials.userId; if (goAhead === 'NO') { rcvHandler(fromId, currentUserId, amt, 0).then(() => { // send notification back at fromId diff --git a/server.js b/server.js index fa9b575..8ebb0bb 100644 --- a/server.js +++ b/server.js @@ -27,7 +27,10 @@ server.auth.default('jwt'); server.route(Routes); if (!module.parent) { - server.start(); + server.start((err) => { + if (err) { console.log(err); } + console.log('Server listening on: '); + }); } module.exports = server; From c6fbc8a8fbc9f19fd155930aa31a475c8fab6e93 Mon Sep 17 00:00:00 2001 From: lakhara Date: Thu, 22 Feb 2018 23:03:22 +0530 Subject: [PATCH 05/20] removed blockedMoney Table --- routes/Handler/rcvHandler.js | 70 ++++++++++++++---------------------- 1 file changed, 26 insertions(+), 44 deletions(-) diff --git a/routes/Handler/rcvHandler.js b/routes/Handler/rcvHandler.js index 57c83dd..958147b 100644 --- a/routes/Handler/rcvHandler.js +++ b/routes/Handler/rcvHandler.js @@ -7,28 +7,19 @@ const transferMoney = (fromId, currentUserId, amt) => new Promise((resolve) => { Models.userDetails.update( { balance: newBalance }, { where: { userId: currentUserId } }, - ) - .then(() => { - Models.blockedmoney.destroy({ - where: { // delete the data from blocked money table - fromId, - toId: currentUserId, - }, - }) - .then(() => { // update transaction in transaction history - Models.transactions.update({ - status: 'COMPLETED', - }, { - where: { - fromId, - toId: currentUserId, - }, - }) - .then(() => { - resolve(); - }); - }); - }); + ).then(() => { // update transaction in transaction history + Models.transactions.update({ + status: 'COMPLETED', + }, { + where: { + fromId, + toId: currentUserId, + }, + }) + .then(() => { + resolve(); + }); + }); }); }); @@ -39,28 +30,19 @@ const restoreMoney = (fromId, currentUserId, amt) => new Promise((resolve) => { Models.userDetails.update( { balance: newBalance }, { where: { userId: fromId } }, - ) - .then(() => { - Models.blockedmoney.destroy({ - where: { // delete the data from blocked money table - fromId, - toId: currentUserId, - }, - }) - .then(() => { // update transaction in transaction history - Models.transactions.update({ - status: 'FAILED', - }, { - where: { - fromId, - toId: currentUserId, - }, - }) - .then(() => { - resolve(); - }); - }); - }); + ).then(() => { // update transaction in transaction history + Models.transactions.update({ + status: 'FAILED', + }, { + where: { + fromId, + toId: currentUserId, + }, + }) + .then(() => { + resolve(); + }); + }); }); }); From 403861b997f735bc2533e1ef537c2910e93d8087 Mon Sep 17 00:00:00 2001 From: lakhara Date: Fri, 23 Feb 2018 00:09:16 +0530 Subject: [PATCH 06/20] written joi validation --- routes/rcv.js | 10 +++ tests/routes/receive.test.js | 121 +++++++++++++++++++++++++++++++++++ 2 files changed, 131 insertions(+) create mode 100644 tests/routes/receive.test.js diff --git a/routes/rcv.js b/routes/rcv.js index 3d339f2..a593881 100644 --- a/routes/rcv.js +++ b/routes/rcv.js @@ -1,8 +1,18 @@ const rcvHandler = require('./Handler/rcvHandler'); +const Joi = require('joi'); module.exports = [{ method: 'POST', path: '/transaction/receive', + config: { + validate: { + payload: Joi.object({ + from: Joi.number().integer().min(0), + amount: Joi.number().integer().min(0), + decision: Joi.string().min(2).max(2), + }), + }, + }, handler: (req, reply) => { const fromId = req.payload.from; const amt = req.payload.amount; diff --git a/tests/routes/receive.test.js b/tests/routes/receive.test.js new file mode 100644 index 0000000..fa7f633 --- /dev/null +++ b/tests/routes/receive.test.js @@ -0,0 +1,121 @@ +const Models = require('../../models'); +const server = require('../../server'); + +describe('url validation', () => { + test('Responds with 200 status code when provided credentials', (done) => { + const request = { + method: 'POST', + url: '/transactions/receive', + credentials: { + userId: 1, + userName: 'John_Doe', + }, + payload: { + from: 2, + amount: 100, + decision: 'YES', + }, + }; + server.inject(request, (response) => { + expect(response.statusCode).toBe(200); + done(); + }); + }); + + test('Responds with 401 status code when no credentials are provided', (done) => { + const request = { + method: 'POST', + url: '/transactions/receive', + payload: { + from: 2, + amount: 100, + decision: 'YES', + }, + }; + server.inject(request, (response) => { + expect(response.statusCode).toBe(401); + done(); + }); + }); +}); + +describe('request validation', () => { + test('rejects request if fromId is not provided', (done) => { + const request = { + method: 'POST', + url: '/transactions/receive', + credentials: { + userId: 1, + userName: 'John_Doe', + }, + payload: { + amount: 100, + decision: 'YES', + }, + }; + server.inject(request, (response) => { + expect(response.statusCode).toBe(401); + done(); + }); + }); + + test('rejects request if amount is not provided', (done) => { + const request = { + method: 'POST', + url: '/transactions/receive', + credentials: { + userId: 1, + userName: 'John_Doe', + }, + payload: { + from: 2, + decision: 'YES', + }, + }; + server.inject(request, (response) => { + expect(response.statusCode).toBe(401); + done(); + }); + }); + + test('rejects request if user decision is not provided', (done) => { + const request = { + method: 'POST', + url: '/transactions/receive', + credentials: { + userId: 1, + userName: 'John_Doe', + }, + payload: { + from: 2, + amount: 100, + }, + }; + server.inject(request, (response) => { + expect(response.statusCode).toBe(401); + done(); + }); + }); +}); + +describe('functionality tests', () => { + test('Responds with 200 status code when provided credentials', (done) => { + const request = { + method: 'POST', + url: '/transactions/receive', + credentials: { + userId: 1, + userName: 'John_Doe', + }, + payload: { + from: 2, + amount: 100, + decision: 'YES', + }, + }; + server.inject(request, (response) => { + expect(response.statusCode).toBe(200); + done(); + }); + }); +}); From fffa8d390d47aa55ec81114f5bf0960075aba4c2 Mon Sep 17 00:00:00 2001 From: lakhara Date: Fri, 23 Feb 2018 00:12:34 +0530 Subject: [PATCH 07/20] seeders made for transaction table --- seeders/20180210195615-demo-transactions.js | 22 ++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/seeders/20180210195615-demo-transactions.js b/seeders/20180210195615-demo-transactions.js index 3adb26f..faf5dc9 100644 --- a/seeders/20180210195615-demo-transactions.js +++ b/seeders/20180210195615-demo-transactions.js @@ -14,7 +14,7 @@ module.exports = { }, { transactionId: 23456, fromId: 3, - toId: 1, + toId: 2, amount: 200, reason: 'black panther tickets', status: 'pending', @@ -24,12 +24,24 @@ module.exports = { createdAt: new Date(), updatedAt: new Date(), }, { - transactionId: 34567, + transactionId: 11212, fromId: 3, - toId: 2, - amount: 4000, + toId: 1, + amount: 100, + reason: 'flight tickets to delhi', + status: 'PENDING', + timeStamp: new Date(), + category: 'travel', + type: 2, + createdAt: new Date(), + updatedAt: new Date(), + }, { + transactionId: 11111, + fromId: 2, + toId: 1, + amount: 100, reason: 'flight tickets to delhi', - status: 'declined', + status: 'PENDING', timeStamp: new Date(), category: 'travel', type: 2, From ecfa8932ad9f7f0e113484088f2afcb8ae5a69c8 Mon Sep 17 00:00:00 2001 From: lakhara Date: Fri, 23 Feb 2018 00:16:42 +0530 Subject: [PATCH 08/20] added tests --- tests/routes/receive.test.js | 36 +++++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/tests/routes/receive.test.js b/tests/routes/receive.test.js index fa7f633..fa29ffe 100644 --- a/tests/routes/receive.test.js +++ b/tests/routes/receive.test.js @@ -99,7 +99,7 @@ describe('request validation', () => { }); describe('functionality tests', () => { - test('Responds with 200 status code when provided credentials', (done) => { + test('Updates status when transaction is completed', (done) => { const request = { method: 'POST', url: '/transactions/receive', @@ -108,14 +108,40 @@ describe('functionality tests', () => { userName: 'John_Doe', }, payload: { - from: 2, + from: 3, amount: 100, decision: 'YES', }, }; - server.inject(request, (response) => { - expect(response.statusCode).toBe(200); - done(); + server.inject(request, () => { + Models.transactions.findOne({ where: { fromId: 3, toId: 1 } }) + .then((row) => { + expect(row.status).toEqual('COMPLETED'); + done(); + }); + }); + }); + + test('Updates status when transaction is failed', (done) => { + const request = { + method: 'POST', + url: '/transactions/receive', + credentials: { + userId: 1, + userName: 'John_Doe', + }, + payload: { + from: 2, + amount: 100, + decision: 'NO', + }, + }; + server.inject(request, () => { + Models.transactions.findOne({ where: { fromId: 2, toId: 1 } }) + .then((row) => { + expect(row.status).toEqual('FAILED'); + done(); + }); }); }); }); From 929d403b1e08ca8529ece21772e0c0dad3afce4c Mon Sep 17 00:00:00 2001 From: lakhara Date: Fri, 23 Feb 2018 04:45:07 +0530 Subject: [PATCH 09/20] tested without auths --- routes/rcv.js | 6 ++++-- seeders/20180207093117-demo-userDetails.js | 1 + ...0180210195346-add-aditional-userDetails.js | 2 ++ server.js | 20 +++++++++---------- swagger/routes/approve.js | 17 ++++++++++++++++ swagger/routes/receive.js | 17 ++++++++++++++++ 6 files changed, 51 insertions(+), 12 deletions(-) create mode 100644 swagger/routes/approve.js create mode 100644 swagger/routes/receive.js diff --git a/routes/rcv.js b/routes/rcv.js index a593881..285e0d1 100644 --- a/routes/rcv.js +++ b/routes/rcv.js @@ -6,10 +6,11 @@ module.exports = [{ path: '/transaction/receive', config: { validate: { + // auth: 'jwt', payload: Joi.object({ from: Joi.number().integer().min(0), amount: Joi.number().integer().min(0), - decision: Joi.string().min(2).max(2), + decision: Joi.string().min(2).max(3), }), }, }, @@ -17,7 +18,8 @@ module.exports = [{ const fromId = req.payload.from; const amt = req.payload.amount; const goAhead = req.payload.decision; - const currentUserId = req.auth.credentials.userId; + const currentUserId = 1; + // const currentUserId = req.auth.credentials.userId; if (goAhead === 'NO') { rcvHandler(fromId, currentUserId, amt, 0).then(() => { // send notification back at fromId diff --git a/seeders/20180207093117-demo-userDetails.js b/seeders/20180207093117-demo-userDetails.js index 1a9ace6..f6c3252 100644 --- a/seeders/20180207093117-demo-userDetails.js +++ b/seeders/20180207093117-demo-userDetails.js @@ -3,6 +3,7 @@ module.exports = { userId: 1, phone: '1234567890', accountNo: '0987654321', + balance: 100, createdAt: new Date(), updatedAt: new Date(), }], {}), diff --git a/seeders/20180210195346-add-aditional-userDetails.js b/seeders/20180210195346-add-aditional-userDetails.js index 1477e8a..97af2e7 100644 --- a/seeders/20180210195346-add-aditional-userDetails.js +++ b/seeders/20180210195346-add-aditional-userDetails.js @@ -5,6 +5,7 @@ module.exports = { accountNo: '0987654321', firstName: 'Alice', lastName: 'A', + balance: 100, createdAt: new Date(), updatedAt: new Date(), }, { @@ -13,6 +14,7 @@ module.exports = { accountNo: '0987654321', firstName: 'Bob', lastName: 'B', + balance: 100, createdAt: new Date(), updatedAt: new Date(), }], {}), diff --git a/server.js b/server.js index 8ebb0bb..a3b1787 100644 --- a/server.js +++ b/server.js @@ -12,17 +12,17 @@ server.connection({ host: 'localhost', }); -server.register(Jwt); - -server.auth.strategy('jwt', 'jwt', { - key: secret, - validateFunc: validate, - verifyOptions: { - algorithms: ['HS256'], - }, -}); +// server.register(Jwt); + +// server.auth.strategy('jwt', 'jwt', { +// key: secret, +// validateFunc: validate, +// verifyOptions: { +// algorithms: ['HS256'], +// }, +// }); -server.auth.default('jwt'); +// server.auth.default('jwt'); server.route(Routes); diff --git a/swagger/routes/approve.js b/swagger/routes/approve.js new file mode 100644 index 0000000..1cd470b --- /dev/null +++ b/swagger/routes/approve.js @@ -0,0 +1,17 @@ +const Joi = require('joi'); + +const receiveMoneySwagger = { + responses: { + 200: { + description: 'Success', + schema: Joi.object({ + message: Joi.string().example('Transaction completed'), + }), + }.label('Result'), + }, + 400: { description: 'Invalid request' }, + 401: { description: 'Unauthorized' }, +}; + + +module.exports = receiveMoneySwagger; diff --git a/swagger/routes/receive.js b/swagger/routes/receive.js new file mode 100644 index 0000000..1cd470b --- /dev/null +++ b/swagger/routes/receive.js @@ -0,0 +1,17 @@ +const Joi = require('joi'); + +const receiveMoneySwagger = { + responses: { + 200: { + description: 'Success', + schema: Joi.object({ + message: Joi.string().example('Transaction completed'), + }), + }.label('Result'), + }, + 400: { description: 'Invalid request' }, + 401: { description: 'Unauthorized' }, +}; + + +module.exports = receiveMoneySwagger; From 66f3dcc294802c9c00efc519f9737cc738adeeeb Mon Sep 17 00:00:00 2001 From: lakhara Date: Fri, 23 Feb 2018 06:37:03 +0530 Subject: [PATCH 10/20] joi validation done, swagger added --- routes/Handler/approveHandler.js | 30 ++++--- routes/approve.js | 27 +++++- routes/rcv.js | 12 ++- swagger/routes/approve.js | 4 +- tests/routes/approve.test.js | 147 +++++++++++++++++++++++++++++++ tests/routes/receive.test.js | 6 +- 6 files changed, 206 insertions(+), 20 deletions(-) create mode 100644 tests/routes/approve.test.js diff --git a/routes/Handler/approveHandler.js b/routes/Handler/approveHandler.js index f4adb59..f3cbcb5 100644 --- a/routes/Handler/approveHandler.js +++ b/routes/Handler/approveHandler.js @@ -1,16 +1,20 @@ const Models = require('../../models'); -const decreaseBalance = (fromId, amt) => new Promise((resolve) => { +const decreaseBalance = (fromId, amt) => new Promise((resolve, reject) => { Models.userDetails.findOne({ where: { userId: fromId } }) .then((userObject) => { - const newBalance = amt - userObject.balance; - Models.userDetails.update( - { balance: newBalance }, - { where: { userId: fromId } }, - ) - .then(() => { - resolve(); - }); + const newBalance = userObject.balance - amt; + if (newBalance >= 0) { + Models.userDetails.update( + { balance: newBalance }, + { where: { userId: fromId } }, + ) + .then(() => { + resolve(); + }); + } else { + reject(new Error('Insufficient Balance')); + } }); }); @@ -28,7 +32,7 @@ const increaseBalance = (currentUserId, amt) => new Promise((resolve) => { }); }); -const transferMoney = (fromId, currentUserId, amt) => new Promise((resolve) => { +const transferMoney = (fromId, currentUserId, amt) => new Promise((resolve, reject) => { decreaseBalance(fromId, amt).then(() => { increaseBalance(currentUserId, amt).then(() => { Models.transactions.update({ @@ -42,6 +46,8 @@ const transferMoney = (fromId, currentUserId, amt) => new Promise((resolve) => { resolve(); }); }); + }).catch((err) => { + reject(new Error(err).message); }); }); @@ -62,10 +68,12 @@ const cancelTransaction = (fromId, currentUserId) => new Promise((resolve) => { }); -const handlerFn = (fromId, currentUserId, amt, decision) => new Promise((resolve) => { +const handlerFn = (fromId, currentUserId, amt, decision) => new Promise((resolve, reject) => { if (decision) { transferMoney(fromId, currentUserId, amt).then(() => { resolve(); + }).catch((err) => { + reject(new Error(err.message)); }); } else { cancelTransaction(fromId, currentUserId).then(() => { diff --git a/routes/approve.js b/routes/approve.js index 3542781..97dce2e 100644 --- a/routes/approve.js +++ b/routes/approve.js @@ -1,21 +1,42 @@ const approveHandler = require('./Handler/approveHandler'); +const Joi = require('joi'); +// const approveSwagger = require('../swagger/routes/approve'); module.exports = [{ method: 'POST', path: '/transaction/approve', + config: { + // auth: 'jwt', + // tags: ['api'], + // description: 'Handles approving a money request', + // plugins: { + // 'hapi-swagger': approveSwagger, + // }, + validate: { + // auth: 'jwt', + payload: Joi.object({ + from: Joi.number().integer().min(0), + amount: Joi.number().integer().min(0), + decision: Joi.string().min(2).max(3), + }), + + }, + }, handler: (req, reply) => { const fromId = req.payload.from; const amt = req.payload.amount; const goAhead = req.payload.decision; - const currentUserId = req.auth.credentials.userId; + const currentUserId = 1; + // const currentUserId = req.auth.credentials.userId; if (goAhead === 'NO') { approveHandler(fromId, currentUserId, amt, 0).then(() => { reply('Transaction cancelled'); }); } else { - approveHandler(fromId, currentUserId, amt, 1).then(() => { - reply('Amount transferred'); + approveHandler(fromId, currentUserId, amt, 1).then((resolve, reject) => { + if (resolve) { reply('Amount transferred'); } else { reply('insufficient balance'); } }); } }, + }]; diff --git a/routes/rcv.js b/routes/rcv.js index 285e0d1..2519f08 100644 --- a/routes/rcv.js +++ b/routes/rcv.js @@ -1,10 +1,17 @@ const rcvHandler = require('./Handler/rcvHandler'); const Joi = require('joi'); +// const receiveSwagger = require('../swagger/routes/receive'); module.exports = [{ method: 'POST', path: '/transaction/receive', config: { + // auth: 'jwt', + // tags: ['api'], + // description: 'Handles approving a money request', + // plugins: { + // 'hapi-swagger': receiveSwagger, + // }, validate: { // auth: 'jwt', payload: Joi.object({ @@ -29,7 +36,10 @@ module.exports = [{ rcvHandler(fromId, currentUserId, amt, 1).then(() => { // send notification back at fromId reply('Amount transferred'); - }); + }) + .catch((err) => { + reply(err.message); + }); } }, }]; diff --git a/swagger/routes/approve.js b/swagger/routes/approve.js index 1cd470b..0379531 100644 --- a/swagger/routes/approve.js +++ b/swagger/routes/approve.js @@ -1,6 +1,6 @@ const Joi = require('joi'); -const receiveMoneySwagger = { +const approveMoneySwagger = { responses: { 200: { description: 'Success', @@ -14,4 +14,4 @@ const receiveMoneySwagger = { }; -module.exports = receiveMoneySwagger; +module.exports = approveMoneySwagger; diff --git a/tests/routes/approve.test.js b/tests/routes/approve.test.js new file mode 100644 index 0000000..e7e5f12 --- /dev/null +++ b/tests/routes/approve.test.js @@ -0,0 +1,147 @@ +const Models = require('../../models'); +const server = require('../../server'); + +describe('url validation', () => { + test('Responds with 200 status code when provided credentials', (done) => { + const request = { + method: 'POST', + url: '/transactions/approve', + credentials: { + userId: 1, + userName: 'John_Doe', + }, + payload: { + from: 2, + amount: 100, + decision: 'YES', + }, + }; + server.inject(request, (response) => { + expect(response.statusCode).toBe(200); + done(); + }); + }); + + test('Responds with 401 status code when no credentials are provided', (done) => { + const request = { + method: 'POST', + url: '/transactions/approve', + payload: { + from: 2, + amount: 100, + decision: 'YES', + }, + }; + server.inject(request, (response) => { + expect(response.statusCode).toBe(401); + done(); + }); + }); +}); + +describe('request validation', () => { + test('rejects request if from is not provided', (done) => { + const request = { + method: 'POST', + url: '/transactions/approve', + credentials: { + userId: 1, + userName: 'John_Doe', + }, + payload: { + amount: 100, + decision: 'YES', + }, + }; + server.inject(request, (response) => { + expect(response.statusCode).toBe(400); + done(); + }); + }); + + test('rejects request if amount is not provided', (done) => { + const request = { + method: 'POST', + url: '/transactions/approve', + credentials: { + userId: 1, + userName: 'John_Doe', + }, + payload: { + from: 2, + decision: 'YES', + }, + }; + server.inject(request, (response) => { + expect(response.statusCode).toBe(400); + done(); + }); + }); + + test('rejects request if user decision is not provided', (done) => { + const request = { + method: 'POST', + url: '/transactions/approve', + credentials: { + userId: 1, + userName: 'John_Doe', + }, + payload: { + from: 2, + amount: 100, + }, + }; + server.inject(request, (response) => { + expect(response.statusCode).toBe(400); + done(); + }); + }); +}); + +describe('functionality tests', () => { + test('Updates status when transaction is completed', (done) => { + const request = { + method: 'POST', + url: '/transactions/approve', + credentials: { + userId: 1, + userName: 'John_Doe', + }, + payload: { + from: 3, + amount: 100, + decision: 'YES', + }, + }; + server.inject(request, () => { + Models.transactions.findOne({ where: { fromId: 3, toId: 1 } }) + .then((row) => { + expect(row.status).toEqual('COMPLETED'); + done(); + }); + }); + }); + + test('Updates status when transaction is failed', (done) => { + const request = { + method: 'POST', + url: '/transactions/approve', + credentials: { + userId: 1, + userName: 'John_Doe', + }, + payload: { + from: 2, + amount: 100, + decision: 'NO', + }, + }; + server.inject(request, () => { + Models.transactions.findOne({ where: { fromId: 2, toId: 1 } }) + .then((row) => { + expect(row.status).toEqual('FAILED'); + done(); + }); + }); + }); +}); diff --git a/tests/routes/receive.test.js b/tests/routes/receive.test.js index fa29ffe..0d0e909 100644 --- a/tests/routes/receive.test.js +++ b/tests/routes/receive.test.js @@ -54,7 +54,7 @@ describe('request validation', () => { }, }; server.inject(request, (response) => { - expect(response.statusCode).toBe(401); + expect(response.statusCode).toBe(400); done(); }); }); @@ -73,7 +73,7 @@ describe('request validation', () => { }, }; server.inject(request, (response) => { - expect(response.statusCode).toBe(401); + expect(response.statusCode).toBe(400); done(); }); }); @@ -92,7 +92,7 @@ describe('request validation', () => { }, }; server.inject(request, (response) => { - expect(response.statusCode).toBe(401); + expect(response.statusCode).toBe(400); done(); }); }); From fd50d1400d123f0bd5f030314d8213c30d057e64 Mon Sep 17 00:00:00 2001 From: lakhara Date: Fri, 23 Feb 2018 08:04:00 +0530 Subject: [PATCH 11/20] swagger --- package-lock.json | 259 ++++++++++++++++++++++++++++++++++++++-------- package.json | 5 +- routes/approve.js | 12 +-- routes/rcv.js | 12 +-- server.js | 32 +++++- 5 files changed, 256 insertions(+), 64 deletions(-) diff --git a/package-lock.json b/package-lock.json index 38993db..58f49af 100644 --- a/package-lock.json +++ b/package-lock.json @@ -110,7 +110,6 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", - "dev": true, "requires": { "kind-of": "3.2.2", "longest": "1.0.1", @@ -120,8 +119,7 @@ "amdefine": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", - "dev": true + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=" }, "ammo": { "version": "2.0.4", @@ -183,7 +181,6 @@ "version": "1.0.9", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=", - "dev": true, "requires": { "sprintf-js": "1.0.3" } @@ -595,6 +592,22 @@ } } }, + "bounce": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/bounce/-/bounce-1.2.0.tgz", + "integrity": "sha512-8syCGe8B2/WC53118/F/tFy5aW00j+eaGPXmAUP7iBhxc+EBZZxS1vKelWyBCH6IqojgS2t1gF0glH30qAJKEw==", + "requires": { + "boom": "7.1.1", + "hoek": "5.0.3" + }, + "dependencies": { + "hoek": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-5.0.3.tgz", + "integrity": "sha512-Bmr56pxML1c9kU+NS51SMFkiVQAb+9uFfXwyqR2tn4w2FPvmPt65eZ9aCcEfRXd9G74HkZnILC6p967pED4aiw==" + } + } + }, "brace-expansion": { "version": "1.1.8", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", @@ -683,6 +696,11 @@ } } }, + "call-me-maybe": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", + "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=" + }, "caller-path": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", @@ -702,7 +720,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", - "dev": true, "optional": true }, "caseless": { @@ -754,7 +771,6 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", - "dev": true, "optional": true, "requires": { "align-text": "0.1.4", @@ -843,7 +859,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", - "dev": true, "optional": true, "requires": { "center-align": "0.1.3", @@ -855,7 +870,6 @@ "version": "0.0.2", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", - "dev": true, "optional": true } } @@ -908,8 +922,7 @@ "commander": { "version": "2.14.0", "resolved": "https://registry.npmjs.org/commander/-/commander-2.14.0.tgz", - "integrity": "sha512-okPpdvdJr6mUGi2XzupC+irQxzwGLVaBzacFC14hjLv8NColXEsxsU+QaeuSSXpQUak5g2K0vQ7WjA1e8svczg==", - "dev": true + "integrity": "sha512-okPpdvdJr6mUGi2XzupC+irQxzwGLVaBzacFC14hjLv8NColXEsxsU+QaeuSSXpQUak5g2K0vQ7WjA1e8svczg==" }, "concat-map": { "version": "0.0.1", @@ -1058,8 +1071,7 @@ "decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" }, "deep-is": { "version": "0.1.3", @@ -1470,8 +1482,7 @@ "esprima": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", - "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", - "dev": true + "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==" }, "esquery": { "version": "1.0.0", @@ -1637,6 +1648,11 @@ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", "dev": true }, + "fast-safe-stringify": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-1.2.3.tgz", + "integrity": "sha512-QJYT/i0QYoiZBQ71ivxdyTqkwKkQ0oxACXHYxH2zYHJEgzi2LsbjgvtzTbLi1SZcF190Db2YP7I7eTsU2egOlw==" + }, "fb-watchman": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.0.tgz", @@ -1754,6 +1770,11 @@ "mime-types": "2.1.17" } }, + "format-util": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/format-util/-/format-util-1.0.3.tgz", + "integrity": "sha1-Ay3KShFiYqEsQ/TD7IVmQWxbLZU=" + }, "fs-extra": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz", @@ -2782,7 +2803,6 @@ "version": "4.0.11", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.11.tgz", "integrity": "sha1-Ywo13+ApS8KB7a5v/F0yn8eYLcw=", - "dev": true, "requires": { "async": "1.5.2", "optimist": "0.6.1", @@ -2793,14 +2813,12 @@ "async": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" }, "source-map": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", - "dev": true, "requires": { "amdefine": "1.0.1" } @@ -2920,6 +2938,28 @@ } } }, + "hapi-swagger": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/hapi-swagger/-/hapi-swagger-9.1.1.tgz", + "integrity": "sha512-3y8fa6OaDMO3duaPz6+vRc2Otn+CKwkmmc5CXuFOBzSYhYdZ7cqvv6NlUnBxf+V0gaGKgZiXMvdhI5E53v4dag==", + "requires": { + "boom": "7.1.1", + "fast-safe-stringify": "1.2.3", + "handlebars": "4.0.11", + "hoek": "5.0.3", + "http-status": "1.0.1", + "joi": "13.1.2", + "json-schema-ref-parser": "4.1.0", + "swagger-parser": "4.0.2" + }, + "dependencies": { + "hoek": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-5.0.3.tgz", + "integrity": "sha512-Bmr56pxML1c9kU+NS51SMFkiVQAb+9uFfXwyqR2tn4w2FPvmPt65eZ9aCcEfRXd9G74HkZnILC6p967pED4aiw==" + } + } + }, "har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", @@ -3055,6 +3095,11 @@ "sshpk": "1.13.1" } }, + "http-status": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/http-status/-/http-status-1.0.1.tgz", + "integrity": "sha1-3EMAGov8UKyH1IWokvdXiWS8lKI=" + }, "iconv-lite": { "version": "0.4.19", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", @@ -3103,6 +3148,45 @@ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", "dev": true }, + "inert": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/inert/-/inert-5.1.0.tgz", + "integrity": "sha512-5rJZbezGEkBN4QrP/HEEwsQ0N+7YzqDZrvBZrE7B0CrNY6I4XKI434aL3UNLCmbI4HzPGQs7Ae/4h1tiTMJ6Wg==", + "requires": { + "ammo": "3.0.0", + "boom": "7.1.1", + "bounce": "1.2.0", + "hoek": "5.0.3", + "joi": "13.1.2", + "lru-cache": "4.1.1" + }, + "dependencies": { + "ammo": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ammo/-/ammo-3.0.0.tgz", + "integrity": "sha512-6yoz9MXYV9sgCHrwprHWPxBaJ9/roQRfXzS//4JCNgKfPYcghFNwJQKBt6vWOoSGGRHsP6qsLJ+xtKStKJWdLQ==", + "requires": { + "boom": "6.0.0", + "hoek": "5.0.3" + }, + "dependencies": { + "boom": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/boom/-/boom-6.0.0.tgz", + "integrity": "sha512-LYLa8BmiiOWjvxTMVh73lcZzd2E5yczrKvxAny1UuzO2tkarLrw4tdp3rdfmus3+YfKcZP0vRSM3Obh+fGK6eA==", + "requires": { + "hoek": "5.0.3" + } + } + } + }, + "hoek": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-5.0.3.tgz", + "integrity": "sha512-Bmr56pxML1c9kU+NS51SMFkiVQAb+9uFfXwyqR2tn4w2FPvmPt65eZ9aCcEfRXd9G74HkZnILC6p967pED4aiw==" + } + } + }, "inflection": { "version": "1.12.0", "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.12.0.tgz", @@ -3201,8 +3285,7 @@ "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" }, "is-builtin-module": { "version": "1.0.0", @@ -3926,7 +4009,6 @@ "version": "3.10.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz", "integrity": "sha512-O2v52ffjLa9VeM43J4XocZE//WT9N0IiwDa3KSHH7Tu8CtH+1qM8SIZvnsTh6v+4yFy5KUY3BHUVwjpfAWsjIA==", - "dev": true, "requires": { "argparse": "1.0.9", "esprima": "4.0.0" @@ -3985,6 +4067,27 @@ "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", "dev": true }, + "json-schema-ref-parser": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/json-schema-ref-parser/-/json-schema-ref-parser-4.1.0.tgz", + "integrity": "sha512-xiTwbw9Bl9HLEKjFSUfTJmdMSTBaGvV/qjbEMzM5Db3rEBIMWgz/pFtzxZxeuc+s3gYkInUCMZl/8qc1bRPHkQ==", + "requires": { + "call-me-maybe": "1.0.1", + "debug": "3.1.0", + "js-yaml": "3.10.0", + "ono": "4.0.3" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + } + } + }, "json-schema-traverse": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", @@ -4099,7 +4202,6 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, "requires": { "is-buffer": "1.1.6" } @@ -4108,7 +4210,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", - "dev": true, "optional": true }, "lcid": { @@ -4183,6 +4284,11 @@ "integrity": "sha1-9HGh2khr5g9quVXRcRVSPdHSVdU=", "dev": true }, + "lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" + }, "lodash.includes": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", @@ -4193,6 +4299,11 @@ "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=" }, + "lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=" + }, "lodash.isinteger": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", @@ -4227,8 +4338,7 @@ "longest": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", - "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", - "dev": true + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=" }, "loose-envify": { "version": "1.3.1", @@ -4243,7 +4353,6 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==", - "dev": true, "requires": { "pseudomap": "1.0.2", "yallist": "2.1.2" @@ -4377,8 +4486,7 @@ "minimist": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" }, "mkdirp": { "version": "0.5.1", @@ -4566,11 +4674,18 @@ "mimic-fn": "1.2.0" } }, + "ono": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/ono/-/ono-4.0.3.tgz", + "integrity": "sha512-7QIxG4UB00H7CR7fhXC/U7VhB5DK9wsYLwaYBui1JmQoXtLkhIBn3fbuk6FgAP+ctWeBsWVTM+R/bThvUZN+ww==", + "requires": { + "format-util": "1.0.3" + } + }, "optimist": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", - "dev": true, "requires": { "minimist": "0.0.8", "wordwrap": "0.0.3" @@ -4579,8 +4694,7 @@ "wordwrap": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", - "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", - "dev": true + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=" } } }, @@ -4975,8 +5089,7 @@ "pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "dev": true + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" }, "punycode": { "version": "2.1.0", @@ -5116,8 +5229,7 @@ "repeat-string": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" }, "repeating": { "version": "2.0.1", @@ -5255,7 +5367,6 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", - "dev": true, "optional": true, "requires": { "align-text": "0.1.4" @@ -5562,8 +5673,7 @@ "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" }, "source-map-support": { "version": "0.5.3", @@ -5614,8 +5724,7 @@ "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" }, "sshpk": { "version": "1.13.1", @@ -5777,6 +5886,40 @@ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", "dev": true }, + "swagger-methods": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/swagger-methods/-/swagger-methods-1.0.4.tgz", + "integrity": "sha512-xrKFLbrZ6VxRsg+M3uJozJtsEpNI/aPfZsOkoEjXw8vhAqdMIqwTYGj1f4dmUgvJvCdZhV5iArgtqXgs403ltg==" + }, + "swagger-parser": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/swagger-parser/-/swagger-parser-4.0.2.tgz", + "integrity": "sha512-hKslog8LhsXICJ1sMLsA8b8hQ3oUEX0457aLCFJc4zz6m8drmnCtyjbVqS5HycaKFOKVolJc2wFoe8KDPWfp4g==", + "requires": { + "call-me-maybe": "1.0.1", + "debug": "3.1.0", + "json-schema-ref-parser": "4.1.0", + "ono": "4.0.3", + "swagger-methods": "1.0.4", + "swagger-schema-official": "2.0.0-bab6bed", + "z-schema": "3.19.1" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + } + } + }, + "swagger-schema-official": { + "version": "2.0.0-bab6bed", + "resolved": "https://registry.npmjs.org/swagger-schema-official/-/swagger-schema-official-2.0.0-bab6bed.tgz", + "integrity": "sha1-cAcEaNbSl3ylI3suUZyn0Gouo/0=" + }, "symbol-tree": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.2.tgz", @@ -6010,7 +6153,6 @@ "version": "2.8.29", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", - "dev": true, "optional": true, "requires": { "source-map": "0.5.7", @@ -6022,7 +6164,6 @@ "version": "3.10.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", - "dev": true, "optional": true, "requires": { "camelcase": "1.2.1", @@ -6037,7 +6178,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", - "dev": true, "optional": true }, "ultron": { @@ -6119,6 +6259,24 @@ "hoek": "4.2.0" } }, + "vision": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/vision/-/vision-5.3.1.tgz", + "integrity": "sha512-JW6T9EC/1f0DX7Jh5yjbMzLe3tcOotLUDMdGhO1me8aVApPHV/HV1CCDPVjK870kE/eGxBLD7Y4ubuTz2vR3hg==", + "requires": { + "boom": "7.1.1", + "hoek": "5.0.3", + "items": "2.1.1", + "joi": "13.1.2" + }, + "dependencies": { + "hoek": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-5.0.3.tgz", + "integrity": "sha512-Bmr56pxML1c9kU+NS51SMFkiVQAb+9uFfXwyqR2tn4w2FPvmPt65eZ9aCcEfRXd9G74HkZnILC6p967pED4aiw==" + } + } + }, "w3c-hr-time": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz", @@ -6200,7 +6358,6 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", - "dev": true, "optional": true }, "wkx": { @@ -6334,8 +6491,7 @@ "yallist": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" }, "yargs": { "version": "10.1.2", @@ -6395,6 +6551,17 @@ "dev": true } } + }, + "z-schema": { + "version": "3.19.1", + "resolved": "https://registry.npmjs.org/z-schema/-/z-schema-3.19.1.tgz", + "integrity": "sha512-jPNzqmOu3+AGbb4krDODqo4QBzwUGDVzyfGyy1HtWaUnafltQotatSpxxWd6Mp0iSZOUwHU5sqKYi+U8HsHMkg==", + "requires": { + "commander": "2.14.0", + "lodash.get": "4.4.2", + "lodash.isequal": "4.5.0", + "validator": "9.4.0" + } } } } diff --git a/package.json b/package.json index 2cc95b9..7bd335f 100644 --- a/package.json +++ b/package.json @@ -36,10 +36,13 @@ "hapi": "^16.6.2", "hapi-auth-basic": "^4.2.0", "hapi-auth-jwt2": "^4.0.0", + "hapi-swagger": "^9.1.1", + "inert": "^5.1.0", "joi": "^13.1.2", "jsonwebtoken": "^8.1.1", "jwt-decode": "^2.2.0", "pg": "^6.4.2", - "sequelize": "^4.32.6" + "sequelize": "^4.32.6", + "vision": "^5.3.1" } } diff --git a/routes/approve.js b/routes/approve.js index 97dce2e..c663a18 100644 --- a/routes/approve.js +++ b/routes/approve.js @@ -1,17 +1,17 @@ const approveHandler = require('./Handler/approveHandler'); const Joi = require('joi'); -// const approveSwagger = require('../swagger/routes/approve'); +const approveSwagger = require('../swagger/routes/approve'); module.exports = [{ method: 'POST', path: '/transaction/approve', config: { // auth: 'jwt', - // tags: ['api'], - // description: 'Handles approving a money request', - // plugins: { - // 'hapi-swagger': approveSwagger, - // }, + tags: ['api'], + description: 'Handles approving a money request', + plugins: { + 'hapi-swagger': approveSwagger, + }, validate: { // auth: 'jwt', payload: Joi.object({ diff --git a/routes/rcv.js b/routes/rcv.js index 2519f08..b22ae39 100644 --- a/routes/rcv.js +++ b/routes/rcv.js @@ -1,17 +1,17 @@ const rcvHandler = require('./Handler/rcvHandler'); const Joi = require('joi'); -// const receiveSwagger = require('../swagger/routes/receive'); +const receiveSwagger = require('../swagger/routes/receive'); module.exports = [{ method: 'POST', path: '/transaction/receive', config: { // auth: 'jwt', - // tags: ['api'], - // description: 'Handles approving a money request', - // plugins: { - // 'hapi-swagger': receiveSwagger, - // }, + tags: ['api'], + description: 'Handles approving a money request', + plugins: { + 'hapi-swagger': receiveSwagger, + }, validate: { // auth: 'jwt', payload: Joi.object({ diff --git a/server.js b/server.js index a3b1787..8b5c193 100644 --- a/server.js +++ b/server.js @@ -1,10 +1,14 @@ const Hapi = require('hapi'); -const secret = require('./secret'); +// const secret = require('./secret'); const Routes = require('./routes'); -const Jwt = require('hapi-auth-jwt2'); +// const Jwt = require('hapi-auth-jwt2'); const validate = require('./validate'); +const Inert = require('inert'); +const Vision = require('vision'); +const HapiSwagger = require('hapi-swagger'); + const server = new Hapi.Server(); server.connection({ @@ -12,7 +16,25 @@ server.connection({ host: 'localhost', }); -// server.register(Jwt); +const options = { + info: { + title: 'Wallet Documentation', + version: '1.0', + }, +}; + +server.register([ + // Jwt, + Inert, + Vision, + { + register: HapiSwagger, + options, + }], (err) => { + if (err) { + throw err; + } +}); // server.auth.strategy('jwt', 'jwt', { // key: secret, @@ -28,8 +50,8 @@ server.route(Routes); if (!module.parent) { server.start((err) => { - if (err) { console.log(err); } - console.log('Server listening on: '); + if (err) throw (err); + console.log('Server running at:', server.info.uri); }); } From a03dc421ed9594759bab25238cc45165e4daf201 Mon Sep 17 00:00:00 2001 From: lakhara Date: Fri, 23 Feb 2018 10:40:33 +0530 Subject: [PATCH 12/20] bug with swagger fixed --- package-lock.json | 190 ++++++++++++++++++++----------- package.json | 6 +- routes/Handler/approveHandler.js | 13 ++- routes/Handler/rcvHandler.js | 2 + routes/approve.js | 6 +- routes/rcv.js | 4 +- swagger/routes/approve.js | 4 +- swagger/routes/receive.js | 4 +- tests/routes/approve.test.js | 23 ++++ 9 files changed, 171 insertions(+), 81 deletions(-) diff --git a/package-lock.json b/package-lock.json index 58f49af..67f2c74 100644 --- a/package-lock.json +++ b/package-lock.json @@ -592,22 +592,6 @@ } } }, - "bounce": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/bounce/-/bounce-1.2.0.tgz", - "integrity": "sha512-8syCGe8B2/WC53118/F/tFy5aW00j+eaGPXmAUP7iBhxc+EBZZxS1vKelWyBCH6IqojgS2t1gF0glH30qAJKEw==", - "requires": { - "boom": "7.1.1", - "hoek": "5.0.3" - }, - "dependencies": { - "hoek": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-5.0.3.tgz", - "integrity": "sha512-Bmr56pxML1c9kU+NS51SMFkiVQAb+9uFfXwyqR2tn4w2FPvmPt65eZ9aCcEfRXd9G74HkZnILC6p967pED4aiw==" - } - } - }, "brace-expansion": { "version": "1.1.8", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", @@ -1277,6 +1261,11 @@ "es6-symbol": "3.1.1" } }, + "es6-promise": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.4.tgz", + "integrity": "sha512-/NdNZVJg+uZgtm9eS3O6lrOLYmQag2DjdEXuPaHlZ6RuVqgqaVZfgYCepEIKsLqwdQArOPtC3XzRLqGGfT8KQQ==" + }, "es6-symbol": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", @@ -2939,24 +2928,45 @@ } }, "hapi-swagger": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/hapi-swagger/-/hapi-swagger-9.1.1.tgz", - "integrity": "sha512-3y8fa6OaDMO3duaPz6+vRc2Otn+CKwkmmc5CXuFOBzSYhYdZ7cqvv6NlUnBxf+V0gaGKgZiXMvdhI5E53v4dag==", + "version": "7.10.0", + "resolved": "https://registry.npmjs.org/hapi-swagger/-/hapi-swagger-7.10.0.tgz", + "integrity": "sha512-Efo4HQx8rR43OqfU+/w/UywY5KuFUjPnXR+hykdGvIpEWBOE0Y0k1CGoK4Qt93CJhnJO+WuVN43drUR7bxDZxw==", "requires": { - "boom": "7.1.1", + "boom": "5.2.0", "fast-safe-stringify": "1.2.3", "handlebars": "4.0.11", - "hoek": "5.0.3", + "hoek": "4.2.0", "http-status": "1.0.1", - "joi": "13.1.2", + "joi": "11.4.0", "json-schema-ref-parser": "4.1.0", - "swagger-parser": "4.0.2" + "swagger-parser": "3.4.2" }, "dependencies": { - "hoek": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-5.0.3.tgz", - "integrity": "sha512-Bmr56pxML1c9kU+NS51SMFkiVQAb+9uFfXwyqR2tn4w2FPvmPt65eZ9aCcEfRXd9G74HkZnILC6p967pED4aiw==" + "boom": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", + "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", + "requires": { + "hoek": "4.2.0" + } + }, + "isemail": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/isemail/-/isemail-3.1.1.tgz", + "integrity": "sha512-mVjAjvdPkpwXW61agT2E9AkGoegZO7SdJGCezWwxnETL58f5KwJ4vSVAMBUL5idL6rTlYAIGkX3n4suiviMLNw==", + "requires": { + "punycode": "2.1.0" + } + }, + "joi": { + "version": "11.4.0", + "resolved": "https://registry.npmjs.org/joi/-/joi-11.4.0.tgz", + "integrity": "sha512-O7Uw+w/zEWgbL6OcHbyACKSj0PkQeUgmehdoXVSxt92QFCq4+1390Rwh5moI2K/OgC7D8RHRZqHZxT2husMJHA==", + "requires": { + "hoek": "4.2.0", + "isemail": "3.1.1", + "topo": "2.0.2" + } } } }, @@ -3149,41 +3159,36 @@ "dev": true }, "inert": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/inert/-/inert-5.1.0.tgz", - "integrity": "sha512-5rJZbezGEkBN4QrP/HEEwsQ0N+7YzqDZrvBZrE7B0CrNY6I4XKI434aL3UNLCmbI4HzPGQs7Ae/4h1tiTMJ6Wg==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/inert/-/inert-4.2.1.tgz", + "integrity": "sha512-qmbbZYPSzU/eOUOStPQvSjrU9IR1Q3uDtsEsVwnBQeZG43xu7Nrj6yuUrX3ice/03rv5dj/KiKB+NGCbiqH+aQ==", "requires": { - "ammo": "3.0.0", - "boom": "7.1.1", - "bounce": "1.2.0", - "hoek": "5.0.3", - "joi": "13.1.2", + "ammo": "2.0.4", + "boom": "5.2.0", + "hoek": "4.2.0", + "items": "2.1.1", + "joi": "10.6.0", "lru-cache": "4.1.1" }, "dependencies": { - "ammo": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ammo/-/ammo-3.0.0.tgz", - "integrity": "sha512-6yoz9MXYV9sgCHrwprHWPxBaJ9/roQRfXzS//4JCNgKfPYcghFNwJQKBt6vWOoSGGRHsP6qsLJ+xtKStKJWdLQ==", + "boom": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", + "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", "requires": { - "boom": "6.0.0", - "hoek": "5.0.3" - }, - "dependencies": { - "boom": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/boom/-/boom-6.0.0.tgz", - "integrity": "sha512-LYLa8BmiiOWjvxTMVh73lcZzd2E5yczrKvxAny1UuzO2tkarLrw4tdp3rdfmus3+YfKcZP0vRSM3Obh+fGK6eA==", - "requires": { - "hoek": "5.0.3" - } - } + "hoek": "4.2.0" } }, - "hoek": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-5.0.3.tgz", - "integrity": "sha512-Bmr56pxML1c9kU+NS51SMFkiVQAb+9uFfXwyqR2tn4w2FPvmPt65eZ9aCcEfRXd9G74HkZnILC6p967pED4aiw==" + "joi": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/joi/-/joi-10.6.0.tgz", + "integrity": "sha512-hBF3LcqyAid+9X/pwg+eXjD2QBZI5eXnBFJYaAkH4SK3mp9QSRiiQnDYlmlz5pccMvnLcJRS4whhDOTCkmsAdQ==", + "requires": { + "hoek": "4.2.0", + "isemail": "2.2.1", + "items": "2.1.1", + "topo": "2.0.2" + } } } }, @@ -5892,13 +5897,14 @@ "integrity": "sha512-xrKFLbrZ6VxRsg+M3uJozJtsEpNI/aPfZsOkoEjXw8vhAqdMIqwTYGj1f4dmUgvJvCdZhV5iArgtqXgs403ltg==" }, "swagger-parser": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/swagger-parser/-/swagger-parser-4.0.2.tgz", - "integrity": "sha512-hKslog8LhsXICJ1sMLsA8b8hQ3oUEX0457aLCFJc4zz6m8drmnCtyjbVqS5HycaKFOKVolJc2wFoe8KDPWfp4g==", + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/swagger-parser/-/swagger-parser-3.4.2.tgz", + "integrity": "sha512-himpIkA50AjTvrgtz0PPbzwWoTjj3F3ye/y1PcW/514YEp1A3IhAcJFkkEu7b1zHnSIthnzxC8aTy+XZG0D+iA==", "requires": { "call-me-maybe": "1.0.1", "debug": "3.1.0", - "json-schema-ref-parser": "4.1.0", + "es6-promise": "4.2.4", + "json-schema-ref-parser": "1.4.1", "ono": "4.0.3", "swagger-methods": "1.0.4", "swagger-schema-official": "2.0.0-bab6bed", @@ -5912,6 +5918,38 @@ "requires": { "ms": "2.0.0" } + }, + "json-schema-ref-parser": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/json-schema-ref-parser/-/json-schema-ref-parser-1.4.1.tgz", + "integrity": "sha1-wMLkOL8HlnI7AkUbrovH3Qs3/tA=", + "requires": { + "call-me-maybe": "1.0.1", + "debug": "2.6.9", + "es6-promise": "3.3.1", + "js-yaml": "3.10.0", + "ono": "2.2.5" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "es6-promise": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz", + "integrity": "sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM=" + }, + "ono": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/ono/-/ono-2.2.5.tgz", + "integrity": "sha1-2vCUiLURdNp6fkJ136sxtDj/oOM=" + } + } } } }, @@ -6260,20 +6298,34 @@ } }, "vision": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/vision/-/vision-5.3.1.tgz", - "integrity": "sha512-JW6T9EC/1f0DX7Jh5yjbMzLe3tcOotLUDMdGhO1me8aVApPHV/HV1CCDPVjK870kE/eGxBLD7Y4ubuTz2vR3hg==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/vision/-/vision-4.1.1.tgz", + "integrity": "sha1-4bYSstLi8gMQoDkpD9SdUSSPgto=", "requires": { - "boom": "7.1.1", - "hoek": "5.0.3", + "boom": "4.3.1", + "hoek": "4.2.0", "items": "2.1.1", - "joi": "13.1.2" + "joi": "10.6.0" }, "dependencies": { - "hoek": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-5.0.3.tgz", - "integrity": "sha512-Bmr56pxML1c9kU+NS51SMFkiVQAb+9uFfXwyqR2tn4w2FPvmPt65eZ9aCcEfRXd9G74HkZnILC6p967pED4aiw==" + "boom": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz", + "integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=", + "requires": { + "hoek": "4.2.0" + } + }, + "joi": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/joi/-/joi-10.6.0.tgz", + "integrity": "sha512-hBF3LcqyAid+9X/pwg+eXjD2QBZI5eXnBFJYaAkH4SK3mp9QSRiiQnDYlmlz5pccMvnLcJRS4whhDOTCkmsAdQ==", + "requires": { + "hoek": "4.2.0", + "isemail": "2.2.1", + "items": "2.1.1", + "topo": "2.0.2" + } } } }, diff --git a/package.json b/package.json index 7bd335f..f8a2352 100644 --- a/package.json +++ b/package.json @@ -36,13 +36,13 @@ "hapi": "^16.6.2", "hapi-auth-basic": "^4.2.0", "hapi-auth-jwt2": "^4.0.0", - "hapi-swagger": "^9.1.1", - "inert": "^5.1.0", + "hapi-swagger": "7", + "inert": "4", "joi": "^13.1.2", "jsonwebtoken": "^8.1.1", "jwt-decode": "^2.2.0", "pg": "^6.4.2", "sequelize": "^4.32.6", - "vision": "^5.3.1" + "vision": "4" } } diff --git a/routes/Handler/approveHandler.js b/routes/Handler/approveHandler.js index f3cbcb5..887fd53 100644 --- a/routes/Handler/approveHandler.js +++ b/routes/Handler/approveHandler.js @@ -60,6 +60,7 @@ const cancelTransaction = (fromId, currentUserId) => new Promise((resolve) => { where: { fromId, toId: currentUserId, + status: 'PENDING', }, }) .then(() => { @@ -73,7 +74,17 @@ const handlerFn = (fromId, currentUserId, amt, decision) => new Promise((resolve transferMoney(fromId, currentUserId, amt).then(() => { resolve(); }).catch((err) => { - reject(new Error(err.message)); + Models.transactions.update({ + status: 'FAILED', + }, { + where: { + fromId, + toId: currentUserId, + status: 'PENDING', + }, + }).then(() => { + reject(new Error(err.message)); + }); }); } else { cancelTransaction(fromId, currentUserId).then(() => { diff --git a/routes/Handler/rcvHandler.js b/routes/Handler/rcvHandler.js index 958147b..5718c0f 100644 --- a/routes/Handler/rcvHandler.js +++ b/routes/Handler/rcvHandler.js @@ -14,6 +14,7 @@ const transferMoney = (fromId, currentUserId, amt) => new Promise((resolve) => { where: { fromId, toId: currentUserId, + status: 'PENDING', }, }) .then(() => { @@ -37,6 +38,7 @@ const restoreMoney = (fromId, currentUserId, amt) => new Promise((resolve) => { where: { fromId, toId: currentUserId, + status: 'PENDING', }, }) .then(() => { diff --git a/routes/approve.js b/routes/approve.js index c663a18..2631b82 100644 --- a/routes/approve.js +++ b/routes/approve.js @@ -33,8 +33,10 @@ module.exports = [{ reply('Transaction cancelled'); }); } else { - approveHandler(fromId, currentUserId, amt, 1).then((resolve, reject) => { - if (resolve) { reply('Amount transferred'); } else { reply('insufficient balance'); } + approveHandler(fromId, currentUserId, amt, 1).then((resolve) => { + reply('Amount transferred'); + }).catch(() => { + reply('insufficient balance'); }); } }, diff --git a/routes/rcv.js b/routes/rcv.js index b22ae39..e4a7bf8 100644 --- a/routes/rcv.js +++ b/routes/rcv.js @@ -6,9 +6,9 @@ module.exports = [{ method: 'POST', path: '/transaction/receive', config: { - // auth: 'jwt', + // // auth: 'jwt', tags: ['api'], - description: 'Handles approving a money request', + description: 'Handles receiving a money request', plugins: { 'hapi-swagger': receiveSwagger, }, diff --git a/swagger/routes/approve.js b/swagger/routes/approve.js index 0379531..2853755 100644 --- a/swagger/routes/approve.js +++ b/swagger/routes/approve.js @@ -6,8 +6,8 @@ const approveMoneySwagger = { description: 'Success', schema: Joi.object({ message: Joi.string().example('Transaction completed'), - }), - }.label('Result'), + }).label('Result'), + }, }, 400: { description: 'Invalid request' }, 401: { description: 'Unauthorized' }, diff --git a/swagger/routes/receive.js b/swagger/routes/receive.js index 1cd470b..351ae5c 100644 --- a/swagger/routes/receive.js +++ b/swagger/routes/receive.js @@ -6,8 +6,8 @@ const receiveMoneySwagger = { description: 'Success', schema: Joi.object({ message: Joi.string().example('Transaction completed'), - }), - }.label('Result'), + }).label('Result'), + }, }, 400: { description: 'Invalid request' }, 401: { description: 'Unauthorized' }, diff --git a/tests/routes/approve.test.js b/tests/routes/approve.test.js index e7e5f12..5e451bc 100644 --- a/tests/routes/approve.test.js +++ b/tests/routes/approve.test.js @@ -122,6 +122,29 @@ describe('functionality tests', () => { }); }); + test('Transaction is approved but user has insufficient balance', (done) => { + const request = { + method: 'POST', + url: '/transactions/approve', + credentials: { + userId: 1, + userName: 'John_Doe', + }, + payload: { + from: 2, + amount: 1000, + decision: 'NO', + }, + }; + server.inject(request, () => { + Models.transactions.findOne({ where: { fromId: 2, toId: 1 } }) + .then((row) => { + expect(row.status).toEqual('FAILED'); + done(); + }); + }); + }); + test('Updates status when transaction is failed', (done) => { const request = { method: 'POST', From fcb9ed53bbe8ff21aa44c79b125680e19e529672 Mon Sep 17 00:00:00 2001 From: lakhara Date: Fri, 23 Feb 2018 12:21:29 +0530 Subject: [PATCH 13/20] test written for receive --- routes/approve.js | 9 +++++--- routes/rcv.js | 18 ++++++++++------ seeders/20180210195615-demo-transactions.js | 4 ++-- server.js | 23 +++++++++++---------- tests/routes/receive.test.js | 22 +++++++++++--------- 5 files changed, 44 insertions(+), 32 deletions(-) diff --git a/routes/approve.js b/routes/approve.js index 2631b82..1faddf9 100644 --- a/routes/approve.js +++ b/routes/approve.js @@ -6,7 +6,7 @@ module.exports = [{ method: 'POST', path: '/transaction/approve', config: { - // auth: 'jwt', + auth: 'jwt', tags: ['api'], description: 'Handles approving a money request', plugins: { @@ -14,6 +14,9 @@ module.exports = [{ }, validate: { // auth: 'jwt', + headers: Joi.object({ + authorization: Joi.string(), + }).unknown(), payload: Joi.object({ from: Joi.number().integer().min(0), amount: Joi.number().integer().min(0), @@ -26,8 +29,8 @@ module.exports = [{ const fromId = req.payload.from; const amt = req.payload.amount; const goAhead = req.payload.decision; - const currentUserId = 1; - // const currentUserId = req.auth.credentials.userId; + // const currentUserId = 1; + const currentUserId = req.auth.credentials.userId; if (goAhead === 'NO') { approveHandler(fromId, currentUserId, amt, 0).then(() => { reply('Transaction cancelled'); diff --git a/routes/rcv.js b/routes/rcv.js index e4a7bf8..1ff0288 100644 --- a/routes/rcv.js +++ b/routes/rcv.js @@ -6,7 +6,7 @@ module.exports = [{ method: 'POST', path: '/transaction/receive', config: { - // // auth: 'jwt', + auth: 'jwt', tags: ['api'], description: 'Handles receiving a money request', plugins: { @@ -14,10 +14,16 @@ module.exports = [{ }, validate: { // auth: 'jwt', + headers: Joi.object({ + authorization: Joi.string(), + }).unknown(), payload: Joi.object({ - from: Joi.number().integer().min(0), - amount: Joi.number().integer().min(0), - decision: Joi.string().min(2).max(3), + from: Joi.number().integer().min(0).required() + .example(2), + amount: Joi.number().integer().min(0).required() + .example(100), + decision: Joi.string().min(2).max(3).required() + .example('YES'), }), }, }, @@ -25,8 +31,8 @@ module.exports = [{ const fromId = req.payload.from; const amt = req.payload.amount; const goAhead = req.payload.decision; - const currentUserId = 1; - // const currentUserId = req.auth.credentials.userId; + // const currentUserId = 1; + const currentUserId = req.auth.credentials.userId; if (goAhead === 'NO') { rcvHandler(fromId, currentUserId, amt, 0).then(() => { // send notification back at fromId diff --git a/seeders/20180210195615-demo-transactions.js b/seeders/20180210195615-demo-transactions.js index faf5dc9..6ec1a9e 100644 --- a/seeders/20180210195615-demo-transactions.js +++ b/seeders/20180210195615-demo-transactions.js @@ -5,7 +5,7 @@ module.exports = { toId: 2, amount: 300, reason: 'mcdonalds', - status: 'completed', + status: 'COMPLETED', timeStamp: new Date(), category: 'food', type: 1, @@ -17,7 +17,7 @@ module.exports = { toId: 2, amount: 200, reason: 'black panther tickets', - status: 'pending', + status: 'PENDING', timeStamp: new Date(), category: 'movie', type: 2, diff --git a/server.js b/server.js index 8b5c193..f21cde6 100644 --- a/server.js +++ b/server.js @@ -1,7 +1,8 @@ const Hapi = require('hapi'); -// const secret = require('./secret'); +const secret = require('./secret'); const Routes = require('./routes'); -// const Jwt = require('hapi-auth-jwt2'); + +const Jwt = require('hapi-auth-jwt2'); const validate = require('./validate'); @@ -24,7 +25,7 @@ const options = { }; server.register([ - // Jwt, + Jwt, Inert, Vision, { @@ -36,15 +37,15 @@ server.register([ } }); -// server.auth.strategy('jwt', 'jwt', { -// key: secret, -// validateFunc: validate, -// verifyOptions: { -// algorithms: ['HS256'], -// }, -// }); +server.auth.strategy('jwt', 'jwt', { + key: secret, + validateFunc: validate, + verifyOptions: { + algorithms: ['HS256'], + }, +}); -// server.auth.default('jwt'); +server.auth.default('jwt'); server.route(Routes); diff --git a/tests/routes/receive.test.js b/tests/routes/receive.test.js index 0d0e909..6679fbf 100644 --- a/tests/routes/receive.test.js +++ b/tests/routes/receive.test.js @@ -5,10 +5,10 @@ describe('url validation', () => { test('Responds with 200 status code when provided credentials', (done) => { const request = { method: 'POST', - url: '/transactions/receive', + url: '/transaction/receive', credentials: { - userId: 1, - userName: 'John_Doe', + userId: 3, + userName: 'Bob_B', }, payload: { from: 2, @@ -17,6 +17,7 @@ describe('url validation', () => { }, }; server.inject(request, (response) => { + // console.log(response.payload); expect(response.statusCode).toBe(200); done(); }); @@ -25,7 +26,7 @@ describe('url validation', () => { test('Responds with 401 status code when no credentials are provided', (done) => { const request = { method: 'POST', - url: '/transactions/receive', + url: '/transaction/receive', payload: { from: 2, amount: 100, @@ -43,7 +44,7 @@ describe('request validation', () => { test('rejects request if fromId is not provided', (done) => { const request = { method: 'POST', - url: '/transactions/receive', + url: '/transaction/receive', credentials: { userId: 1, userName: 'John_Doe', @@ -62,7 +63,7 @@ describe('request validation', () => { test('rejects request if amount is not provided', (done) => { const request = { method: 'POST', - url: '/transactions/receive', + url: '/transaction/receive', credentials: { userId: 1, userName: 'John_Doe', @@ -81,7 +82,7 @@ describe('request validation', () => { test('rejects request if user decision is not provided', (done) => { const request = { method: 'POST', - url: '/transactions/receive', + url: '/transaction/receive', credentials: { userId: 1, userName: 'John_Doe', @@ -102,7 +103,7 @@ describe('functionality tests', () => { test('Updates status when transaction is completed', (done) => { const request = { method: 'POST', - url: '/transactions/receive', + url: '/transaction/receive', credentials: { userId: 1, userName: 'John_Doe', @@ -125,7 +126,7 @@ describe('functionality tests', () => { test('Updates status when transaction is failed', (done) => { const request = { method: 'POST', - url: '/transactions/receive', + url: '/transaction/receive', credentials: { userId: 1, userName: 'John_Doe', @@ -137,8 +138,9 @@ describe('functionality tests', () => { }, }; server.inject(request, () => { - Models.transactions.findOne({ where: { fromId: 2, toId: 1 } }) + Models.transactions.findOne({ where: { fromId: 2, toId: 1, amount: 100 } }) .then((row) => { + console.log(row); expect(row.status).toEqual('FAILED'); done(); }); From 93ecd9d6f566f2b43f908f9c508ff6651b135587 Mon Sep 17 00:00:00 2001 From: lakhara Date: Fri, 23 Feb 2018 12:55:33 +0530 Subject: [PATCH 14/20] tests for approve --- routes/approve.js | 6 +++--- seeders/20180210195615-demo-transactions.js | 15 ++++++++++++- tests/routes/approve.test.js | 24 ++++++++++----------- 3 files changed, 29 insertions(+), 16 deletions(-) diff --git a/routes/approve.js b/routes/approve.js index 1faddf9..2cb5120 100644 --- a/routes/approve.js +++ b/routes/approve.js @@ -18,9 +18,9 @@ module.exports = [{ authorization: Joi.string(), }).unknown(), payload: Joi.object({ - from: Joi.number().integer().min(0), - amount: Joi.number().integer().min(0), - decision: Joi.string().min(2).max(3), + from: Joi.number().integer().min(0).required(), + amount: Joi.number().integer().min(0).required(), + decision: Joi.string().min(2).max(3).required(), }), }, diff --git a/seeders/20180210195615-demo-transactions.js b/seeders/20180210195615-demo-transactions.js index 6ec1a9e..9f9418c 100644 --- a/seeders/20180210195615-demo-transactions.js +++ b/seeders/20180210195615-demo-transactions.js @@ -47,7 +47,20 @@ module.exports = { type: 2, createdAt: new Date(), updatedAt: new Date(), - }], {}), + }, { + transactionId: 17111, + fromId: 2, + toId: 1, + amount: 1000, + reason: 'borrowed money', + status: 'PENDING', + timeStamp: new Date(), + category: 'travel', + type: 2, + createdAt: new Date(), + updatedAt: new Date(), + }, + ], {}), down: (queryInterface, Sequelize) => queryInterface.bulkDelete('transactions', null, {}), }; diff --git a/tests/routes/approve.test.js b/tests/routes/approve.test.js index 5e451bc..6767756 100644 --- a/tests/routes/approve.test.js +++ b/tests/routes/approve.test.js @@ -5,10 +5,10 @@ describe('url validation', () => { test('Responds with 200 status code when provided credentials', (done) => { const request = { method: 'POST', - url: '/transactions/approve', + url: '/transaction/approve', credentials: { - userId: 1, - userName: 'John_Doe', + userId: 3, + userName: 'Bob_B', }, payload: { from: 2, @@ -25,7 +25,7 @@ describe('url validation', () => { test('Responds with 401 status code when no credentials are provided', (done) => { const request = { method: 'POST', - url: '/transactions/approve', + url: '/transaction/approve', payload: { from: 2, amount: 100, @@ -43,7 +43,7 @@ describe('request validation', () => { test('rejects request if from is not provided', (done) => { const request = { method: 'POST', - url: '/transactions/approve', + url: '/transaction/approve', credentials: { userId: 1, userName: 'John_Doe', @@ -62,7 +62,7 @@ describe('request validation', () => { test('rejects request if amount is not provided', (done) => { const request = { method: 'POST', - url: '/transactions/approve', + url: '/transaction/approve', credentials: { userId: 1, userName: 'John_Doe', @@ -81,7 +81,7 @@ describe('request validation', () => { test('rejects request if user decision is not provided', (done) => { const request = { method: 'POST', - url: '/transactions/approve', + url: '/transaction/approve', credentials: { userId: 1, userName: 'John_Doe', @@ -102,7 +102,7 @@ describe('functionality tests', () => { test('Updates status when transaction is completed', (done) => { const request = { method: 'POST', - url: '/transactions/approve', + url: '/transaction/approve', credentials: { userId: 1, userName: 'John_Doe', @@ -125,7 +125,7 @@ describe('functionality tests', () => { test('Transaction is approved but user has insufficient balance', (done) => { const request = { method: 'POST', - url: '/transactions/approve', + url: '/transaction/approve', credentials: { userId: 1, userName: 'John_Doe', @@ -137,7 +137,7 @@ describe('functionality tests', () => { }, }; server.inject(request, () => { - Models.transactions.findOne({ where: { fromId: 2, toId: 1 } }) + Models.transactions.findOne({ where: { fromId: 2, toId: 1, amount: 1000 } }) .then((row) => { expect(row.status).toEqual('FAILED'); done(); @@ -148,7 +148,7 @@ describe('functionality tests', () => { test('Updates status when transaction is failed', (done) => { const request = { method: 'POST', - url: '/transactions/approve', + url: '/transaction/approve', credentials: { userId: 1, userName: 'John_Doe', @@ -160,7 +160,7 @@ describe('functionality tests', () => { }, }; server.inject(request, () => { - Models.transactions.findOne({ where: { fromId: 2, toId: 1 } }) + Models.transactions.findOne({ where: { fromId: 2, toId: 1, amount: 100 } }) .then((row) => { expect(row.status).toEqual('FAILED'); done(); From 2dc065a50ee461efc3d1d5a3b048b9d24c32e50b Mon Sep 17 00:00:00 2001 From: lakhara Date: Fri, 23 Feb 2018 12:55:33 +0530 Subject: [PATCH 15/20] updated package json --- config/config.json | 4 ++-- routes/approve.js | 6 +++--- seeders/20180210195615-demo-transactions.js | 15 ++++++++++++- tests/routes/approve.test.js | 24 ++++++++++----------- 4 files changed, 31 insertions(+), 18 deletions(-) diff --git a/config/config.json b/config/config.json index 993f2a5..6c2f503 100644 --- a/config/config.json +++ b/config/config.json @@ -1,14 +1,14 @@ { "development": { "username": "teamsix", - "password": "root", + "password": null, "database": "wallet_development", "host": "127.0.0.1", "dialect": "postgres" }, "test": { "username": "teamsix", - "password": "root", + "password": null, "database": "wallet_test", "host": "127.0.0.1", "dialect": "postgres" diff --git a/routes/approve.js b/routes/approve.js index 1faddf9..2cb5120 100644 --- a/routes/approve.js +++ b/routes/approve.js @@ -18,9 +18,9 @@ module.exports = [{ authorization: Joi.string(), }).unknown(), payload: Joi.object({ - from: Joi.number().integer().min(0), - amount: Joi.number().integer().min(0), - decision: Joi.string().min(2).max(3), + from: Joi.number().integer().min(0).required(), + amount: Joi.number().integer().min(0).required(), + decision: Joi.string().min(2).max(3).required(), }), }, diff --git a/seeders/20180210195615-demo-transactions.js b/seeders/20180210195615-demo-transactions.js index 6ec1a9e..9f9418c 100644 --- a/seeders/20180210195615-demo-transactions.js +++ b/seeders/20180210195615-demo-transactions.js @@ -47,7 +47,20 @@ module.exports = { type: 2, createdAt: new Date(), updatedAt: new Date(), - }], {}), + }, { + transactionId: 17111, + fromId: 2, + toId: 1, + amount: 1000, + reason: 'borrowed money', + status: 'PENDING', + timeStamp: new Date(), + category: 'travel', + type: 2, + createdAt: new Date(), + updatedAt: new Date(), + }, + ], {}), down: (queryInterface, Sequelize) => queryInterface.bulkDelete('transactions', null, {}), }; diff --git a/tests/routes/approve.test.js b/tests/routes/approve.test.js index 5e451bc..6767756 100644 --- a/tests/routes/approve.test.js +++ b/tests/routes/approve.test.js @@ -5,10 +5,10 @@ describe('url validation', () => { test('Responds with 200 status code when provided credentials', (done) => { const request = { method: 'POST', - url: '/transactions/approve', + url: '/transaction/approve', credentials: { - userId: 1, - userName: 'John_Doe', + userId: 3, + userName: 'Bob_B', }, payload: { from: 2, @@ -25,7 +25,7 @@ describe('url validation', () => { test('Responds with 401 status code when no credentials are provided', (done) => { const request = { method: 'POST', - url: '/transactions/approve', + url: '/transaction/approve', payload: { from: 2, amount: 100, @@ -43,7 +43,7 @@ describe('request validation', () => { test('rejects request if from is not provided', (done) => { const request = { method: 'POST', - url: '/transactions/approve', + url: '/transaction/approve', credentials: { userId: 1, userName: 'John_Doe', @@ -62,7 +62,7 @@ describe('request validation', () => { test('rejects request if amount is not provided', (done) => { const request = { method: 'POST', - url: '/transactions/approve', + url: '/transaction/approve', credentials: { userId: 1, userName: 'John_Doe', @@ -81,7 +81,7 @@ describe('request validation', () => { test('rejects request if user decision is not provided', (done) => { const request = { method: 'POST', - url: '/transactions/approve', + url: '/transaction/approve', credentials: { userId: 1, userName: 'John_Doe', @@ -102,7 +102,7 @@ describe('functionality tests', () => { test('Updates status when transaction is completed', (done) => { const request = { method: 'POST', - url: '/transactions/approve', + url: '/transaction/approve', credentials: { userId: 1, userName: 'John_Doe', @@ -125,7 +125,7 @@ describe('functionality tests', () => { test('Transaction is approved but user has insufficient balance', (done) => { const request = { method: 'POST', - url: '/transactions/approve', + url: '/transaction/approve', credentials: { userId: 1, userName: 'John_Doe', @@ -137,7 +137,7 @@ describe('functionality tests', () => { }, }; server.inject(request, () => { - Models.transactions.findOne({ where: { fromId: 2, toId: 1 } }) + Models.transactions.findOne({ where: { fromId: 2, toId: 1, amount: 1000 } }) .then((row) => { expect(row.status).toEqual('FAILED'); done(); @@ -148,7 +148,7 @@ describe('functionality tests', () => { test('Updates status when transaction is failed', (done) => { const request = { method: 'POST', - url: '/transactions/approve', + url: '/transaction/approve', credentials: { userId: 1, userName: 'John_Doe', @@ -160,7 +160,7 @@ describe('functionality tests', () => { }, }; server.inject(request, () => { - Models.transactions.findOne({ where: { fromId: 2, toId: 1 } }) + Models.transactions.findOne({ where: { fromId: 2, toId: 1, amount: 100 } }) .then((row) => { expect(row.status).toEqual('FAILED'); done(); From aef1c7a4eebfd50164f00e72340518203d4c426e Mon Sep 17 00:00:00 2001 From: lakhara Date: Fri, 23 Feb 2018 15:33:25 +0530 Subject: [PATCH 16/20] modified config json --- config/config.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/config.json b/config/config.json index 6c2f503..993f2a5 100644 --- a/config/config.json +++ b/config/config.json @@ -1,14 +1,14 @@ { "development": { "username": "teamsix", - "password": null, + "password": "root", "database": "wallet_development", "host": "127.0.0.1", "dialect": "postgres" }, "test": { "username": "teamsix", - "password": null, + "password": "root", "database": "wallet_test", "host": "127.0.0.1", "dialect": "postgres" From e508c7fed3226156b339774531facba3d33d1cfc Mon Sep 17 00:00:00 2001 From: lakhara Date: Sun, 25 Feb 2018 10:29:59 +0530 Subject: [PATCH 17/20] modified recieve to use transaction id --- routes/Handler/rcvHandler.js | 105 ++++++++++++++++++++--------------- routes/rcv.js | 18 +++--- 2 files changed, 68 insertions(+), 55 deletions(-) diff --git a/routes/Handler/rcvHandler.js b/routes/Handler/rcvHandler.js index 5718c0f..63aa931 100644 --- a/routes/Handler/rcvHandler.js +++ b/routes/Handler/rcvHandler.js @@ -1,60 +1,75 @@ const Models = require('../../models'); -const transferMoney = (fromId, currentUserId, amt) => new Promise((resolve) => { - Models.userDetails.findOne({ where: { userId: currentUserId } })// increase money from currentUser - .then((currentUserInfo) => { - const newBalance = currentUserInfo.balance + amt; // get current balance - Models.userDetails.update( - { balance: newBalance }, - { where: { userId: currentUserId } }, - ).then(() => { // update transaction in transaction history - Models.transactions.update({ - status: 'COMPLETED', - }, { - where: { - fromId, - toId: currentUserId, - status: 'PENDING', - }, - }) - .then(() => { - resolve(); - }); +const transferMoney = (txnId, currentUserId) => new Promise((resolve) => { + Models.transactions.findOne({ + where: { + transactionId: txnId, + toId: currentUserId, + }, + }).then((transactionDetails) => { + const { amount } = transactionDetails; + Models.userDetails.findOne({ where: { userId: currentUserId } }) + // increase money from currentUser + .then((currentUserInfo) => { + const newBalance = currentUserInfo.balance + amount; // get current balance + Models.userDetails.update( + { balance: newBalance }, + { where: { userId: currentUserId } }, + ).then(() => { // update transaction in transaction history + Models.transactions.update({ + status: 'COMPLETED', + }, { + where: { + transactionId: txnId, + status: 'PENDING', + }, + }) + .then(() => { + resolve(); + }); + }); }); - }); + }); }); -const restoreMoney = (fromId, currentUserId, amt) => new Promise((resolve) => { - Models.userDetails.findOne({ where: { userId: fromId } }) // increase money from currentUser - .then((currentUserInfo) => { - const newBalance = currentUserInfo.balance + amt; // get current balance - Models.userDetails.update( - { balance: newBalance }, - { where: { userId: fromId } }, - ).then(() => { // update transaction in transaction history - Models.transactions.update({ - status: 'FAILED', - }, { - where: { - fromId, - toId: currentUserId, - status: 'PENDING', - }, - }) - .then(() => { - resolve(); - }); +const restoreMoney = txnId => new Promise((resolve) => { + Models.transactions.findOne({ + where: { + transactionId: txnId, + }, + }).then((transactionDetails) => { + const { fromId } = transactionDetails; + const { amount } = transactionDetails; + Models.userDetails.findOne({ where: { userId: fromId } }) // increase money from currentUser + .then((currentUserInfo) => { + const newBalance = currentUserInfo.balance + amount; // get current balance + Models.userDetails.update( + { balance: newBalance }, + { where: { userId: fromId } }, + ).then(() => { // update transaction in transaction history + Models.transactions.update({ + status: 'FAILED', + }, { + where: { + transactionId: txnId, + status: 'PENDING', + }, + }) + .then(() => { + resolve(); + }); + }); }); - }); + }); }); -const handlerFn = (fromId, currentUserId, amt, decision) => new Promise((resolve) => { +const handlerFn = (txnId, currentUserId, decision) => new Promise((resolve) => { if (decision) { - transferMoney(fromId, currentUserId, amt).then(() => { + transferMoney(txnId, currentUserId).then(() => { resolve(); }); } else { - restoreMoney(fromId, currentUserId, amt).then(() => { + restoreMoney(txnId).then(() => { resolve(); }); } diff --git a/routes/rcv.js b/routes/rcv.js index 1ff0288..61ed71c 100644 --- a/routes/rcv.js +++ b/routes/rcv.js @@ -18,29 +18,27 @@ module.exports = [{ authorization: Joi.string(), }).unknown(), payload: Joi.object({ - from: Joi.number().integer().min(0).required() - .example(2), - amount: Joi.number().integer().min(0).required() - .example(100), + transactionId: Joi.number().integer().min(10000).max(99999) + .required() + .example(11212), decision: Joi.string().min(2).max(3).required() .example('YES'), }), }, }, handler: (req, reply) => { - const fromId = req.payload.from; - const amt = req.payload.amount; + const txnId = req.payload.transactionId; const goAhead = req.payload.decision; // const currentUserId = 1; const currentUserId = req.auth.credentials.userId; if (goAhead === 'NO') { - rcvHandler(fromId, currentUserId, amt, 0).then(() => { - // send notification back at fromId + rcvHandler(txnId, currentUserId, 0).then(() => { + // send notification back at user reply('Transaction cancelled'); }); } else { - rcvHandler(fromId, currentUserId, amt, 1).then(() => { - // send notification back at fromId + rcvHandler(txnId, currentUserId, 1).then(() => { + // send notification back at user reply('Amount transferred'); }) .catch((err) => { From d0c2c909cd6955873e905b350a78ddffe31a54ec Mon Sep 17 00:00:00 2001 From: lakhara Date: Sun, 25 Feb 2018 10:58:41 +0530 Subject: [PATCH 18/20] modified approve to use transaction id --- routes/Handler/approveHandler.js | 95 ++++++++++++++++---------------- routes/approve.js | 16 +++--- 2 files changed, 57 insertions(+), 54 deletions(-) diff --git a/routes/Handler/approveHandler.js b/routes/Handler/approveHandler.js index 887fd53..378065a 100644 --- a/routes/Handler/approveHandler.js +++ b/routes/Handler/approveHandler.js @@ -1,13 +1,13 @@ const Models = require('../../models'); -const decreaseBalance = (fromId, amt) => new Promise((resolve, reject) => { - Models.userDetails.findOne({ where: { userId: fromId } }) +const decreaseBalance = (Id, amt) => new Promise((resolve, reject) => { + Models.userDetails.findOne({ where: { userId: Id } }) .then((userObject) => { const newBalance = userObject.balance - amt; if (newBalance >= 0) { Models.userDetails.update( { balance: newBalance }, - { where: { userId: fromId } }, + { where: { userId: Id } }, ) .then(() => { resolve(); @@ -18,13 +18,13 @@ const decreaseBalance = (fromId, amt) => new Promise((resolve, reject) => { }); }); -const increaseBalance = (currentUserId, amt) => new Promise((resolve) => { - Models.userDetails.findOne({ where: { userId: currentUserId } }) +const increaseBalance = (Id, amt) => new Promise((resolve) => { + Models.userDetails.findOne({ where: { userId: Id } }) .then((userObject) => { const newBalance = amt + userObject.balance; Models.userDetails.update( { balance: newBalance }, - { where: { userId: currentUserId } }, + { where: { userId: Id } }, ) .then(() => { resolve(); @@ -32,34 +32,38 @@ const increaseBalance = (currentUserId, amt) => new Promise((resolve) => { }); }); -const transferMoney = (fromId, currentUserId, amt) => new Promise((resolve, reject) => { - decreaseBalance(fromId, amt).then(() => { - increaseBalance(currentUserId, amt).then(() => { - Models.transactions.update({ - status: 'COMPLETED', - }, { - where: { - fromId, - toId: currentUserId, - }, - }).then(() => { - resolve(); +const transferMoney = transactionId => new Promise((resolve, reject) => { + Models.transactions.findOne({ where: { transactionId } }) + .then((transactionDetails) => { + const { fromId } = transactionDetails; + const { amount } = transactionDetails; + const { toId } = transactionDetails; + decreaseBalance(fromId, amount).then(() => { + increaseBalance(toId, amount).then(() => { + Models.transactions.update({ + status: 'COMPLETED', + }, { + where: { + transactionId, + }, + }).then(() => { + resolve(); + }); + }); + }).catch((err) => { + reject(new Error(err).message); }); }); - }).catch((err) => { - reject(new Error(err).message); - }); }); -const cancelTransaction = (fromId, currentUserId) => new Promise((resolve) => { +const cancelTransaction = transactionId => new Promise((resolve) => { // update transaction status in transaction history Models.transactions.update({ status: 'FAILED', }, { where: { - fromId, - toId: currentUserId, + transactionId, status: 'PENDING', }, }) @@ -69,28 +73,27 @@ const cancelTransaction = (fromId, currentUserId) => new Promise((resolve) => { }); -const handlerFn = (fromId, currentUserId, amt, decision) => new Promise((resolve, reject) => { - if (decision) { - transferMoney(fromId, currentUserId, amt).then(() => { - resolve(); - }).catch((err) => { - Models.transactions.update({ - status: 'FAILED', - }, { - where: { - fromId, - toId: currentUserId, - status: 'PENDING', - }, - }).then(() => { - reject(new Error(err.message)); +const handlerFn = (transactionId, currentUserId, decision) => + new Promise((resolve, reject) => { + if (decision) { + transferMoney(transactionId).then(() => { + resolve(); + }).catch((err) => { + Models.transactions.update({ + status: 'FAILED', + }, { + where: { + transactionId, + }, + }).then(() => { + reject(new Error(err.message)); + }); }); - }); - } else { - cancelTransaction(fromId, currentUserId).then(() => { - resolve(); - }); - } -}); + } else { + cancelTransaction(transactionId).then(() => { + resolve(); + }); + } + }); module.exports = handlerFn; diff --git a/routes/approve.js b/routes/approve.js index 2cb5120..42709d1 100644 --- a/routes/approve.js +++ b/routes/approve.js @@ -18,25 +18,25 @@ module.exports = [{ authorization: Joi.string(), }).unknown(), payload: Joi.object({ - from: Joi.number().integer().min(0).required(), - amount: Joi.number().integer().min(0).required(), - decision: Joi.string().min(2).max(3).required(), + transactionId: Joi.number().integer().min(10000).max(99999) + .required() + .example(11212), + decision: Joi.string().min(2).max(3).required() + .example('NO'), }), }, }, handler: (req, reply) => { - const fromId = req.payload.from; - const amt = req.payload.amount; + const { transactionId } = req.payload; const goAhead = req.payload.decision; - // const currentUserId = 1; const currentUserId = req.auth.credentials.userId; if (goAhead === 'NO') { - approveHandler(fromId, currentUserId, amt, 0).then(() => { + approveHandler(transactionId, currentUserId, 0).then(() => { reply('Transaction cancelled'); }); } else { - approveHandler(fromId, currentUserId, amt, 1).then((resolve) => { + approveHandler(transactionId, currentUserId, 1).then(() => { reply('Amount transferred'); }).catch(() => { reply('insufficient balance'); From 0a85d875cfdcf614921a88e9baed9a757f5ab177 Mon Sep 17 00:00:00 2001 From: lakhara Date: Mon, 26 Feb 2018 23:38:13 +0530 Subject: [PATCH 19/20] modified tests --- tests/routes/approve.test.js | 52 +++++++++--------------------------- tests/routes/receive.test.js | 49 +++++++++------------------------ 2 files changed, 25 insertions(+), 76 deletions(-) diff --git a/tests/routes/approve.test.js b/tests/routes/approve.test.js index 6767756..8635865 100644 --- a/tests/routes/approve.test.js +++ b/tests/routes/approve.test.js @@ -11,9 +11,8 @@ describe('url validation', () => { userName: 'Bob_B', }, payload: { - from: 2, - amount: 100, - decision: 'YES', + transactionId: 23456, + decision: 'NO', }, }; server.inject(request, (response) => { @@ -27,9 +26,8 @@ describe('url validation', () => { method: 'POST', url: '/transaction/approve', payload: { - from: 2, - amount: 100, - decision: 'YES', + transactionId: 23456, + decision: 'NO', }, }; server.inject(request, (response) => { @@ -40,7 +38,7 @@ describe('url validation', () => { }); describe('request validation', () => { - test('rejects request if from is not provided', (done) => { + test('rejects request if transactionId is not provided', (done) => { const request = { method: 'POST', url: '/transaction/approve', @@ -49,27 +47,7 @@ describe('request validation', () => { userName: 'John_Doe', }, payload: { - amount: 100, - decision: 'YES', - }, - }; - server.inject(request, (response) => { - expect(response.statusCode).toBe(400); - done(); - }); - }); - - test('rejects request if amount is not provided', (done) => { - const request = { - method: 'POST', - url: '/transaction/approve', - credentials: { - userId: 1, - userName: 'John_Doe', - }, - payload: { - from: 2, - decision: 'YES', + decision: 'NO', }, }; server.inject(request, (response) => { @@ -87,8 +65,7 @@ describe('request validation', () => { userName: 'John_Doe', }, payload: { - from: 2, - amount: 100, + transactionId: 11111, }, }; server.inject(request, (response) => { @@ -108,13 +85,12 @@ describe('functionality tests', () => { userName: 'John_Doe', }, payload: { - from: 3, - amount: 100, + transactionId: 11111, decision: 'YES', }, }; server.inject(request, () => { - Models.transactions.findOne({ where: { fromId: 3, toId: 1 } }) + Models.transactions.findOne({ transactionId: request.payload.transactionId }) .then((row) => { expect(row.status).toEqual('COMPLETED'); done(); @@ -131,13 +107,12 @@ describe('functionality tests', () => { userName: 'John_Doe', }, payload: { - from: 2, - amount: 1000, + transactionId: 17111, decision: 'NO', }, }; server.inject(request, () => { - Models.transactions.findOne({ where: { fromId: 2, toId: 1, amount: 1000 } }) + Models.transactions.findOne({ where: { transactionId: request.payload.transactionId } }) .then((row) => { expect(row.status).toEqual('FAILED'); done(); @@ -154,13 +129,12 @@ describe('functionality tests', () => { userName: 'John_Doe', }, payload: { - from: 2, - amount: 100, + transactionId: 11212, decision: 'NO', }, }; server.inject(request, () => { - Models.transactions.findOne({ where: { fromId: 2, toId: 1, amount: 100 } }) + Models.transactions.findOne({ where: { transactionId: request.payload.transactionId } }) .then((row) => { expect(row.status).toEqual('FAILED'); done(); diff --git a/tests/routes/receive.test.js b/tests/routes/receive.test.js index 6679fbf..001b05c 100644 --- a/tests/routes/receive.test.js +++ b/tests/routes/receive.test.js @@ -5,15 +5,14 @@ describe('url validation', () => { test('Responds with 200 status code when provided credentials', (done) => { const request = { method: 'POST', - url: '/transaction/receive', + url: '/transaction/approve', credentials: { userId: 3, userName: 'Bob_B', }, payload: { - from: 2, - amount: 100, - decision: 'YES', + transactionId: 23456, + decision: 'NO', }, }; server.inject(request, (response) => { @@ -28,9 +27,8 @@ describe('url validation', () => { method: 'POST', url: '/transaction/receive', payload: { - from: 2, - amount: 100, - decision: 'YES', + transactionId: 23456, + decision: 'NO', }, }; server.inject(request, (response) => { @@ -41,26 +39,7 @@ describe('url validation', () => { }); describe('request validation', () => { - test('rejects request if fromId is not provided', (done) => { - const request = { - method: 'POST', - url: '/transaction/receive', - credentials: { - userId: 1, - userName: 'John_Doe', - }, - payload: { - amount: 100, - decision: 'YES', - }, - }; - server.inject(request, (response) => { - expect(response.statusCode).toBe(400); - done(); - }); - }); - - test('rejects request if amount is not provided', (done) => { + test('rejects request if transactionId is not provided', (done) => { const request = { method: 'POST', url: '/transaction/receive', @@ -69,8 +48,7 @@ describe('request validation', () => { userName: 'John_Doe', }, payload: { - from: 2, - decision: 'YES', + decision: 'NO', }, }; server.inject(request, (response) => { @@ -88,8 +66,7 @@ describe('request validation', () => { userName: 'John_Doe', }, payload: { - from: 2, - amount: 100, + transactionId: 23456, }, }; server.inject(request, (response) => { @@ -109,13 +86,12 @@ describe('functionality tests', () => { userName: 'John_Doe', }, payload: { - from: 3, - amount: 100, + transactionId: 11111, decision: 'YES', }, }; server.inject(request, () => { - Models.transactions.findOne({ where: { fromId: 3, toId: 1 } }) + Models.transactions.findOne({ where: { transactionId: request.payload.transactionId } }) .then((row) => { expect(row.status).toEqual('COMPLETED'); done(); @@ -132,13 +108,12 @@ describe('functionality tests', () => { userName: 'John_Doe', }, payload: { - from: 2, - amount: 100, + transactionId: 11212, decision: 'NO', }, }; server.inject(request, () => { - Models.transactions.findOne({ where: { fromId: 2, toId: 1, amount: 100 } }) + Models.transactions.findOne({ where: { transactionId: request.payload.transactionId } }) .then((row) => { console.log(row); expect(row.status).toEqual('FAILED'); From 601b95ed851f3aedefd1146b6cabcbaf91b76924 Mon Sep 17 00:00:00 2001 From: lakhara Date: Sun, 18 Mar 2018 18:07:17 +0530 Subject: [PATCH 20/20] updating with socket-send --- routes/Handler/rcvHandler.js | 78 ------------------------------------ routes/approve.js | 2 +- routes/index.js | 3 +- routes/rcv.js | 49 ---------------------- 4 files changed, 2 insertions(+), 130 deletions(-) delete mode 100644 routes/Handler/rcvHandler.js delete mode 100644 routes/rcv.js diff --git a/routes/Handler/rcvHandler.js b/routes/Handler/rcvHandler.js deleted file mode 100644 index 63aa931..0000000 --- a/routes/Handler/rcvHandler.js +++ /dev/null @@ -1,78 +0,0 @@ -const Models = require('../../models'); - -const transferMoney = (txnId, currentUserId) => new Promise((resolve) => { - Models.transactions.findOne({ - where: { - transactionId: txnId, - toId: currentUserId, - }, - }).then((transactionDetails) => { - const { amount } = transactionDetails; - Models.userDetails.findOne({ where: { userId: currentUserId } }) - // increase money from currentUser - .then((currentUserInfo) => { - const newBalance = currentUserInfo.balance + amount; // get current balance - Models.userDetails.update( - { balance: newBalance }, - { where: { userId: currentUserId } }, - ).then(() => { // update transaction in transaction history - Models.transactions.update({ - status: 'COMPLETED', - }, { - where: { - transactionId: txnId, - status: 'PENDING', - }, - }) - .then(() => { - resolve(); - }); - }); - }); - }); -}); - -const restoreMoney = txnId => new Promise((resolve) => { - Models.transactions.findOne({ - where: { - transactionId: txnId, - }, - }).then((transactionDetails) => { - const { fromId } = transactionDetails; - const { amount } = transactionDetails; - Models.userDetails.findOne({ where: { userId: fromId } }) // increase money from currentUser - .then((currentUserInfo) => { - const newBalance = currentUserInfo.balance + amount; // get current balance - Models.userDetails.update( - { balance: newBalance }, - { where: { userId: fromId } }, - ).then(() => { // update transaction in transaction history - Models.transactions.update({ - status: 'FAILED', - }, { - where: { - transactionId: txnId, - status: 'PENDING', - }, - }) - .then(() => { - resolve(); - }); - }); - }); - }); -}); - -const handlerFn = (txnId, currentUserId, decision) => new Promise((resolve) => { - if (decision) { - transferMoney(txnId, currentUserId).then(() => { - resolve(); - }); - } else { - restoreMoney(txnId).then(() => { - resolve(); - }); - } -}); - -module.exports = handlerFn; diff --git a/routes/approve.js b/routes/approve.js index 42709d1..b9366d2 100644 --- a/routes/approve.js +++ b/routes/approve.js @@ -3,7 +3,7 @@ const Joi = require('joi'); const approveSwagger = require('../swagger/routes/approve'); module.exports = [{ - method: 'POST', + method: 'PATCH', path: '/transaction/approve', config: { auth: 'jwt', diff --git a/routes/index.js b/routes/index.js index 25edb21..cd6f1d3 100644 --- a/routes/index.js +++ b/routes/index.js @@ -1,9 +1,8 @@ const ping = require('./ping'); const userRegistration = require('./userRegister'); const userLogin = require('./userLogin'); -const rcvMoney = require('./rcv'); const approve = require('./approve'); const auth = require('./auth'); const history = require('./history'); -module.exports = [].concat(ping, userRegistration, userLogin, rcvMoney, approve, auth, history); +module.exports = [].concat(ping, userRegistration, userLogin, approve, auth, history); diff --git a/routes/rcv.js b/routes/rcv.js deleted file mode 100644 index 61ed71c..0000000 --- a/routes/rcv.js +++ /dev/null @@ -1,49 +0,0 @@ -const rcvHandler = require('./Handler/rcvHandler'); -const Joi = require('joi'); -const receiveSwagger = require('../swagger/routes/receive'); - -module.exports = [{ - method: 'POST', - path: '/transaction/receive', - config: { - auth: 'jwt', - tags: ['api'], - description: 'Handles receiving a money request', - plugins: { - 'hapi-swagger': receiveSwagger, - }, - validate: { - // auth: 'jwt', - headers: Joi.object({ - authorization: Joi.string(), - }).unknown(), - payload: Joi.object({ - transactionId: Joi.number().integer().min(10000).max(99999) - .required() - .example(11212), - decision: Joi.string().min(2).max(3).required() - .example('YES'), - }), - }, - }, - handler: (req, reply) => { - const txnId = req.payload.transactionId; - const goAhead = req.payload.decision; - // const currentUserId = 1; - const currentUserId = req.auth.credentials.userId; - if (goAhead === 'NO') { - rcvHandler(txnId, currentUserId, 0).then(() => { - // send notification back at user - reply('Transaction cancelled'); - }); - } else { - rcvHandler(txnId, currentUserId, 1).then(() => { - // send notification back at user - reply('Amount transferred'); - }) - .catch((err) => { - reply(err.message); - }); - } - }, -}];