diff --git a/server/swagger.json b/server/swagger.json index edfda99..c6878c9 100644 --- a/server/swagger.json +++ b/server/swagger.json @@ -14,7 +14,7 @@ "v1/auth/signup": { "post": { "tags": [ - "Signup" + "Auth" ], "summary": "Users can signup", "description": "this endpoint uses get request to create users", @@ -65,7 +65,7 @@ "v1/auth/signup/addstaff": { "post": { "tags": [ - "Signup" + "Auth" ], "summary": "Admin can signup staffs", "description": "this endpoint uses get request to create users", @@ -135,7 +135,7 @@ "v1/auth/signin": { "post": { "tags": [ - "Signin" + "Auth" ], "summary": "Users can signup", "description": "this endpoint uses get request to create users", diff --git a/server/v1/config/account.sql b/server/v1/config/account.sql deleted file mode 100644 index 9099c28..0000000 --- a/server/v1/config/account.sql +++ /dev/null @@ -1,27 +0,0 @@ --- Accounts SQL query - --- create accounts table -CREATE TABLE accounts ( - id SERIAL PRIMARY KEY UNIQUE, - email VARCHAR(80), - firstName VARCHAR(20), - lastName VARCHAR(20), - accountNumber BIGINT UNIQUE, - createdOn VARCHAR(40), - owner INTEGER, - type VARCHAR(10), - status VARCHAR(10), - balance FLOAT -); - --- select all from accounts table -SELECT * FROM accounts LIMIT 10 - --- select account number fro accounts -SELECT accountNumber FROM accounts WHERE accountNumber=$1, ['accountNumber'] - --- insert into accounts table -INSERT into accounts values($1), ['value'] - --- delete from accounts table -DELETE FROM accounts; \ No newline at end of file diff --git a/server/v1/config/database.js b/server/v1/config/database.js index b6b0fbf..6dec7df 100644 --- a/server/v1/config/database.js +++ b/server/v1/config/database.js @@ -36,26 +36,6 @@ const dbConnection = { return debug('query')(e.stack); } }, - - /** - * Connect to database - For test - * @constructor - * @param {*} passedQuery - passed in SQL query. - */ - async dbTesting(passedQuery) { - try { - return (async () => { - const client = await pool.connect(); - try { - return await client.query(passedQuery); - } finally { - client.release(); - } - })(); - } catch (e) { - return debug('query')(e.stack); - } - }, }; export default dbConnection; diff --git a/server/v1/config/transaction.sql b/server/v1/config/transaction.sql deleted file mode 100644 index fbabb50..0000000 --- a/server/v1/config/transaction.sql +++ /dev/null @@ -1,28 +0,0 @@ --- Transactions SQL query - --- create transactions table -CREATE TABLE transactions ( - id SERIAL PRIMARY KEY UNIQUE, - createdOn VARCHAR(40), - type VARCHAR(10), - accountNumber BIGINT, - cashier INTEGER, - amount FLOAT, - oldBalance FLOAT, - newBalance FLOAT -); - --- select all from transactions table -SELECT * FROM transactions LIMIT 10 - --- select account number fro transactions -SELECT accountNumber FROM transactions WHERE accountNumber=$1, ['accountNumber'] - --- insert into transactions table -INSERT into transactions values($1), ['value'] - --- update -UPDATE transactions SET balance=$1 WHERE accountnumber=$2, [newBalance, accountNumber] - --- delete from transactions table -DELETE FROM transactions; \ No newline at end of file diff --git a/server/v1/config/user.sql b/server/v1/config/user.sql deleted file mode 100644 index 22a415d..0000000 --- a/server/v1/config/user.sql +++ /dev/null @@ -1,27 +0,0 @@ --- Users SQL query - --- create users table -CREATE TABLE users ( - id SERIAL PRIMARY KEY UNIQUE, - email VARCHAR(80) UNIQUE, - firstName VARCHAR(20), - lastName VARCHAR(20), - password VARCHAR(80), - type VARCHAR(10), - isAdmin BOOLEAN -); - --- select all from users table -SELECT * FROM users LIMIT 10 - --- select email fro users -SELECT email FROM users WHERE email=$1, ['email'] - --- insert into users table -INSERT into users values($1), ['value'] - --- delete from users table -DELETE FROM users; - --- admin -INSERT into users(email, firstName, lastName, password, type, isAdmin) values('admin@banka.com', 'cavdy', 'ikenna', '$2a$10$CmmIst1.D3QjaWuafKbBaOuAFu0r9o7xxQY.0SMKiAN.h9z52a2y2', 'staff', true) \ No newline at end of file diff --git a/server/v1/helper/statusHelper.js b/server/v1/helper/statusHelper.js index a4b8df7..9858ab2 100644 --- a/server/v1/helper/statusHelper.js +++ b/server/v1/helper/statusHelper.js @@ -22,6 +22,12 @@ const statusHelper = { status: 409, data: error, }); + } else if (status === 403) { // conflict + res.status(403); + return res.json({ + status: 403, + data: error, + }); } else if (status === 201) { // created res.status(201); return res.json({ diff --git a/server/v1/middleware/jwt.js b/server/v1/middleware/jwt.js index 47ee931..2363b21 100644 --- a/server/v1/middleware/jwt.js +++ b/server/v1/middleware/jwt.js @@ -1,62 +1,78 @@ -import jwt from 'jsonwebtoken'; -import dotenv from 'dotenv'; - -dotenv.config(); - -const jwtMiddleware = { - /** - * Check Token - * @constructor - * @param {*} req - get request. - * @param {*} res -get response - * @param {*} next - run next - */ - checkToken(req, res, next) { - const header = req.headers.authorization; - if (typeof header !== 'undefined') { - const bearer = header.split(' '); - const token = bearer[1]; - req.token = token; - next(); - } else { - // If header is undefined return Forbidden (403) - res.sendStatus(403); - } - }, - - /** - * Signin Jwt - * @constructor - * @param {*} req - get request. - * @param {*} res -get response - * @param {*} next - run next - */ - signinJwt(req, res, next) { - jwt.sign(req.body, process.env.JWTSECRETKEY, async (err, token) => { - if (err) { - return res.sendStatus(403); - } - req.signintoken = token; - return next(); - }); - }, - - /** - * Verify Jwt - * @constructor - * @param {*} req - get request. - * @param {*} res -get response - * @param {*} next - run next - */ - verifyJwt(req, res, next) { - jwt.verify(req.token, process.env.JWTSECRETKEY, (err, authorizedData) => { - if (err) { - return res.sendStatus(403); - } - req.authorizedData = authorizedData; - return next(); - }); - }, -}; - -export default jwtMiddleware; +import jwt from 'jsonwebtoken'; +import dotenv from 'dotenv'; +import statusHelper from '../helper/statusHelper'; + +dotenv.config(); + +const jwtMiddleware = { + /** + * Check Token + * @constructor + * @param {*} req - get request. + * @param {*} res -get response + * @param {*} next - run next + */ + checkToken(req, res, next) { + const header = req.headers.authorization; + if (typeof header !== 'undefined') { + const bearer = header.split(' '); + const token = bearer[1]; + req.token = token; + next(); + } else { + // If header is undefined return Forbidden (403) + return statusHelper + .statusHelper(req, + res, + 403, + 'you are not logged in', + ''); + } + }, + + /** + * Signin Jwt + * @constructor + * @param {*} req - get request. + * @param {*} res -get response + * @param {*} next - run next + */ + signinJwt(req, res, next) { + jwt.sign(req.body, process.env.JWTSECRETKEY, async (err, token) => { + if (err) { + return statusHelper + .statusHelper(req, + res, + 403, + 'you are not logged in', + ''); + } + req.signintoken = token; + return next(); + }); + }, + + /** + * Verify Jwt + * @constructor + * @param {*} req - get request. + * @param {*} res -get response + * @param {*} next - run next + */ + verifyJwt(req, res, next) { + jwt.verify(req.token, process.env.JWTSECRETKEY, (err, authorizedData) => { + if (err) { + return statusHelper + .statusHelper(req, + res, + 403, + 'invalid token', + ''); + } + req.authorizedData = authorizedData; + return next(); + }); + }, +}; + +export default jwtMiddleware; diff --git a/server/v1/model/CreateAccount.js b/server/v1/model/accounts.js similarity index 100% rename from server/v1/model/CreateAccount.js rename to server/v1/model/accounts.js diff --git a/server/v1/model/Transaction.js b/server/v1/model/transaction.js similarity index 100% rename from server/v1/model/Transaction.js rename to server/v1/model/transaction.js diff --git a/server/v1/services/accounts.js b/server/v1/services/accounts.js index dfb3d28..5e31f4a 100644 --- a/server/v1/services/accounts.js +++ b/server/v1/services/accounts.js @@ -1,5 +1,5 @@ import dbConnection from '../config/database'; -import AccountModel from '../model/CreateAccount'; +import AccountModel from '../model/accounts'; const CreateAccountService = { /** @@ -18,7 +18,7 @@ const CreateAccountService = { // pulling users data from database const userDetails = await dbConnection - .dbConnect('SELECT id,firstname,lastname FROM users WHERE email=$1', + .dbConnect('SELECT * FROM users WHERE email=$1', [userData.email]); const { firstname, lastname, id } = userDetails.rows[0]; @@ -175,21 +175,26 @@ const CreateAccountService = { const { type, isadmin } = userDetails.rows[0]; if (type === 'staff' || isadmin === true) { - const accountDbData = await dbConnection - .dbConnect('SELECT accountnumber FROM accounts WHERE accountnumber=$1', - [accountNumber]); - if (accountDbData.rows.length > 0) { - const updateAccount = await dbConnection - .dbConnect('UPDATE accounts SET status=$1 WHERE accountnumber=$2', - [accountUpdate.status, accountNumber]); - if (updateAccount.command === 'UPDATE') { - const userDbData = await dbConnection - .dbConnect('SELECT accountnumber, status FROM accounts WHERE accountnumber=$1', - [accountNumber]); - const { accountnumber, status } = userDbData.rows[0]; - returnStatus = 200; - returnSuccess = { accountnumber, status }; + if (accountUpdate.status === 'active' || accountUpdate.status === 'dormant') { + const accountDbData = await dbConnection + .dbConnect('SELECT accountnumber FROM accounts WHERE accountnumber=$1', + [accountNumber]); + if (accountDbData.rows.length > 0) { + const updateAccount = await dbConnection + .dbConnect('UPDATE accounts SET status=$1 WHERE accountnumber=$2 RETURNING accountnumber, status', + [accountUpdate.status, accountNumber]); + if (updateAccount.command === 'UPDATE') { + const { accountnumber, status } = updateAccount.rows[0]; + returnStatus = 200; + returnSuccess = { accountnumber, status }; + } + } else { + returnStatus = 404; + returnError = 'account not found'; } + } else { + returnStatus = 422; + returnError = 'account status can only be active or dormant'; } } else { returnStatus = 401; diff --git a/server/v1/services/transaction.js b/server/v1/services/transaction.js index b7d055e..970921e 100644 --- a/server/v1/services/transaction.js +++ b/server/v1/services/transaction.js @@ -1,6 +1,6 @@ /* eslint-disable no-param-reassign */ import dbConnection from '../config/database'; -import TransactionModel from '../model/Transaction'; +import TransactionModel from '../model/transaction'; const TransactionService = { @@ -33,9 +33,7 @@ const TransactionService = { ); const { accountnumber, balance } = accountDbData.rows[0]; - // check if a string - const checkForDigit = /^-?\d+\.?\d*$/; - if (checkForDigit.test(transactionData.amount)) { + if (typeof transactionData.amount === 'number') { // substract the passed in amount from the current balance const newBalance = balance - transactionData.amount; @@ -132,9 +130,7 @@ const TransactionService = { ); const { accountnumber, balance } = accountDbData.rows[0]; - // check if a string - const checkForDigit = /^-?\d+\.?\d*$/; - if (checkForDigit.test(transactionData.amount)) { + if (typeof transactionData.amount === 'number') { if (transactionData.amount <= 0) { returnStatus = 422; returnError = 'please credit an account with positive value'; diff --git a/server/v1/test/accounts.js b/server/v1/test/accounts.js index e6904e4..9e6b1de 100644 --- a/server/v1/test/accounts.js +++ b/server/v1/test/accounts.js @@ -1,493 +1,553 @@ -import chaiHttp from 'chai-http'; -import chai, { expect } from 'chai'; - -import app from '../app'; - -chai.use(chaiHttp); - -describe('Testing Accounts Controller', () => { - describe('Testing accounts controller', () => { - it( - 'accounts should have all required details', - async () => { - const signinUrl = '/api/v1/auth/signin'; - const response = await chai.request(app) - .post(signinUrl) - .send({ - email: 'banka872@banka4.com', - password: 'passworD4@', - }); - const { token } = response.body.data; - const res = await chai.request(app) - .post('/api/v1/accounts') - .set('Authorization', `Bearer ${token}`) - .send({ - type: 'savings', - }); - expect(res.body).to.be.an('object'); - expect(res.body.status).to.equal(201); - expect(res.body.data).to.have.property('id'); - expect(res.body.data).to.have.property('accountNumber'); - expect(res.body.data).to.have.property('createdOn'); - expect(res.body.data).to.have.property('owner'); - expect(res.body.data).to.have.property('type'); - expect(res.body.data).to.have.property('status'); - expect(res.body.data).to.have.property('balance'); - }, - ); - - it( - 'admin or staff should see all accounts', - async () => { - const signinUrl = '/api/v1/auth/signin'; - const response = await chai.request(app) - .post(signinUrl) - .send({ - email: 'admin@banka.com', - password: 'passworD4@', - }); - const { token } = response.body.data; - const res = await chai.request(app) - .get('/api/v1/accounts') - .set('Authorization', `Bearer ${token}`) - .send(); - expect(res.body).to.be.an('object'); - expect(res.body.status).to.equal(200); - expect(res.body.data[0]).to.have.property('id'); - expect(res.body.data[0]).to.have.property('email'); - expect(res.body.data[0]).to.have.property('firstname'); - expect(res.body.data[0]).to.have.property('lastname'); - expect(res.body.data[0]).to.have.property('accountnumber'); - expect(res.body.data[0]).to.have.property('createdon'); - expect(res.body.data[0]).to.have.property('owner'); - expect(res.body.data[0]).to.have.property('type'); - expect(res.body.data[0]).to.have.property('status'); - expect(res.body.data[0]).to.have.property('balance'); - }, - ); - - it( - 'admin or staff should see all accounts', - async () => { - const signinUrl = '/api/v1/auth/signin'; - const response = await chai.request(app) - .post(signinUrl) - .send({ - email: 'admin@banka.com', - password: 'passworD4@', - }); - const { token } = response.body.data; - const res = await chai.request(app) - .get('/api/v1/accounts') - .set('Authorization', `Bearer ${token}`) - .send(); - expect(res.body).to.be.an('object'); - expect(res.body.status).to.equal(200); - expect(res.body.data[0]).to.have.property('id'); - expect(res.body.data[0]).to.have.property('email'); - expect(res.body.data[0]).to.have.property('firstname'); - expect(res.body.data[0]).to.have.property('lastname'); - expect(res.body.data[0]).to.have.property('accountnumber'); - expect(res.body.data[0]).to.have.property('createdon'); - expect(res.body.data[0]).to.have.property('owner'); - expect(res.body.data[0]).to.have.property('type'); - expect(res.body.data[0]).to.have.property('status'); - expect(res.body.data[0]).to.have.property('balance'); - }, - ); - - it( - 'admin or staff can pass limit to see all accounts', - async () => { - const signinUrl = '/api/v1/auth/signin'; - const response = await chai.request(app) - .post(signinUrl) - .send({ - email: 'admin@banka.com', - password: 'passworD4@', - }); - const { token } = response.body.data; - const res = await chai.request(app) - .get('/api/v1/accounts?limit=5') - .set('Authorization', `Bearer ${token}`) - .send(); - expect(res.body).to.be.an('object'); - expect(res.body.status).to.equal(200); - expect(res.body.data[0]).to.have.property('id'); - expect(res.body.data[0]).to.have.property('email'); - expect(res.body.data[0]).to.have.property('firstname'); - expect(res.body.data[0]).to.have.property('lastname'); - expect(res.body.data[0]).to.have.property('accountnumber'); - expect(res.body.data[0]).to.have.property('createdon'); - expect(res.body.data[0]).to.have.property('owner'); - expect(res.body.data[0]).to.have.property('type'); - expect(res.body.data[0]).to.have.property('status'); - expect(res.body.data[0]).to.have.property('balance'); - }, - ); - - it( - 'admin or staff can pass status and limit to see all accounts', - async () => { - const signinUrl = '/api/v1/auth/signin'; - const response = await chai.request(app) - .post(signinUrl) - .send({ - email: 'admin@banka.com', - password: 'passworD4@', - }); - const { token } = response.body.data; - const res = await chai.request(app) - .get('/api/v1/accounts?status=active&limit=5') - .set('Authorization', `Bearer ${token}`) - .send(); - expect(res.body.data[0]).to.have.property('id'); - expect(res.body.data[0]).to.have.property('email'); - expect(res.body.data[0]).to.have.property('firstname'); - expect(res.body.data[0]).to.have.property('lastname'); - expect(res.body.data[0]).to.have.property('accountnumber'); - expect(res.body.data[0]).to.have.property('createdon'); - expect(res.body.data[0]).to.have.property('owner'); - expect(res.body.data[0]).to.have.property('type'); - expect(res.body.data[0]).to.have.property('status'); - expect(res.body.data[0]).to.have.property('balance'); - }, - ); - - it( - 'when query is not found', - async () => { - const signinUrl = '/api/v1/auth/signin'; - const response = await chai.request(app) - .post(signinUrl) - .send({ - email: 'admin@banka.com', - password: 'passworD4@', - }); - const { token } = response.body.data; - const res = await chai.request(app) - .get('/api/v1/accounts?status=engilsh&limit=5') - .set('Authorization', `Bearer ${token}`) - .send(); - expect(res.body).to.be.an('object'); - expect(res.body.status).to.equal(404); - expect(res.body.data) - .to.equal('no account found'); - }, - ); - - it( - 'only admin should access all accounts', - async () => { - const signinUrl = '/api/v1/auth/signin'; - const response = await chai.request(app) - .post(signinUrl) - .send({ - email: 'banka872@banka4.com', - password: 'passworD4@', - }); - const { token } = response.body.data; - const res = await chai.request(app) - .get('/api/v1/accounts') - .set('Authorization', `Bearer ${token}`) - .send(); - expect(res.body).to.be.an('object'); - expect(res.body.status).to.equal(401); - expect(res.body.data) - .to.equal('Sorry you don\'t have permission to perform this task'); - }, - ); - - it( - 'account type should only be savings or current', - async () => { - const signinUrl = '/api/v1/auth/signin'; - const response = await chai.request(app) - .post(signinUrl) - .send({ - email: 'banka872@banka4.com', - password: 'passworD4@', - }); - const { token } = response.body.data; - const res = await chai.request(app) - .post('/api/v1/accounts') - .set('Authorization', `Bearer ${token}`) - .send(); - expect(res.body).to.be.an('object'); - expect(res.body.status).to.equal(422); - expect(res.body.data) - .to.equal('account type can either be savings or current'); - }, - ); - - it( - 'should get specific account', - async () => { - const signinUrl = '/api/v1/auth/signin'; - const response = await chai.request(app) - .post(signinUrl) - .send({ - email: 'banka872@banka4.com', - password: 'passworD4@', - }); - const { token } = response.body.data; - const res = await chai.request(app) - .get(`/api/v1/accounts/${3003801983}`) - .set('Authorization', `Bearer ${token}`) - .send(); - expect(res.body).to.be.an('object'); - expect(res.body.status).to.equal(200); - expect(res.body.data).to.have.property('id'); - expect(res.body.data).to.have.property('email'); - expect(res.body.data).to.have.property('firstname'); - expect(res.body.data).to.have.property('lastname'); - expect(res.body.data).to.have.property('accountnumber'); - expect(res.body.data).to.have.property('createdon'); - expect(res.body.data).to.have.property('owner'); - expect(res.body.data).to.have.property('type'); - expect(res.body.data).to.have.property('status'); - expect(res.body.data).to.have.property('balance'); - }, - ); - - it( - 'when account does not have transaction', - async () => { - const signinUrl = '/api/v1/auth/signin'; - const response = await chai.request(app) - .post(signinUrl) - .send({ - email: 'banka872@banka4.com', - password: 'passworD4@', - }); - const { token } = response.body.data; - const res = await chai.request(app) - .get(`/api/v1/accounts/${3146859791}/transactions`) - .set('Authorization', `Bearer ${token}`) - .send(); - expect(res.body).to.be.an('object'); - expect(res.body.status).to.equal(404); - expect(res.body.data).to.equal('no transaction found'); - }, - ); - - it( - 'when specific account does not have transaction', - async () => { - const signinUrl = '/api/v1/auth/signin'; - const response = await chai.request(app) - .post(signinUrl) - .send({ - email: 'banka872@banka4.com', - password: 'passworD4@', - }); - const { token } = response.body.data; - const res = await chai.request(app) - .get(`/api/v1/accounts/${314685979881}`) - .set('Authorization', `Bearer ${token}`) - .send(); - expect(res.body).to.be.an('object'); - expect(res.body.status).to.equal(404); - expect(res.body.data).to.equal('no account found'); - }, - ); - - it( - 'should not patch account if not staff or admin', - async () => { - const signinUrl = '/api/v1/auth/signin'; - const response = await chai.request(app) - .post(signinUrl) - .send({ - email: 'banka872@banka4.com', - password: 'passworD4@', - }); - const { token } = response.body.data; - const res = await chai.request(app) - .post('/api/v1/accounts') - .set('Authorization', `Bearer ${token}`) - .send({ - type: 'savings', - }); - const { accountnumber } = res.body.data; - const res1 = await chai.request(app) - .patch(`/api/v1/accounts/${accountnumber}`) - .set('Authorization', `Bearer ${token}`) - .send({ - status: 'dormant', - }); - expect(res1.body).to.be.an('object'); - expect(res1.body.status).to.equal(401); - expect(res1.body.data) - .to.equal('Sorry you don\'t have permission to perform this task'); - }, - ); - - it( - 'should patch account if staff or admin', - async () => { - const signinUrl = '/api/v1/auth/signin'; - const response = await chai.request(app) - .post(signinUrl) - .send({ - email: 'admin@banka.com', - password: 'passworD4@', - }); - const { token } = response.body.data; - const res = await chai.request(app) - .post('/api/v1/accounts') - .set('Authorization', `Bearer ${token}`) - .send({ - type: 'savings', - }); - const { accountNumber } = res.body.data; - const res1 = await chai.request(app) - .patch(`/api/v1/accounts/${accountNumber}`) - .set('Authorization', `Bearer ${token}`) - .send({ - status: 'dormant', - }); - expect(res1.body).to.be.an('object'); - expect(res1.body.status).to.equal(200); - expect(res1.body.data).to.have.property('accountnumber'); - expect(res1.body.data).to.have.property('status'); - }, - ); - - it( - 'should not delete account if not staff or admin', - async () => { - const signinUrl = '/api/v1/auth/signin'; - const response = await chai.request(app) - .post(signinUrl) - .send({ - email: 'banka872@banka4.com', - password: 'passworD4@', - }); - const { token } = response.body.data; - const res = await chai.request(app) - .post('/api/v1/accounts') - .set('Authorization', `Bearer ${token}`) - .send({ - type: 'savings', - }); - const { accountnumber } = res.body.data; - const res1 = await chai.request(app) - .delete(`/api/v1/accounts/${accountnumber}`) - .set('Authorization', `Bearer ${token}`) - .send(); - expect(res1.body).to.be.an('object'); - expect(res1.body.status).to.equal(401); - expect(res1.body.data) - .to.equal('Sorry you don\'t have permission to perform this task'); - }, - ); - - it( - 'should delete account if staff or admin', - async () => { - const signinUrl = '/api/v1/auth/signin'; - const response = await chai.request(app) - .post(signinUrl) - .send({ - email: 'admin@banka.com', - password: 'passworD4@', - }); - const { token } = response.body.data; - const res = await chai.request(app) - .post('/api/v1/accounts') - .set('Authorization', `Bearer ${token}`) - .send({ - type: 'savings', - }); - const { accountNumber } = res.body.data; - const res1 = await chai.request(app) - .delete(`/api/v1/accounts/${accountNumber}`) - .set('Authorization', `Bearer ${token}`) - .send(); - expect(res1.body).to.be.an('object'); - expect(res1.status).to.equal(200); - expect(res1.body.data).to.equal('Account successfully deleted'); - }, - ); - - it( - 'transaction should have these propertise', - async () => { - const signinUrl = '/api/v1/auth/signin'; - const response = await chai.request(app) - .post(signinUrl) - .send({ - email: 'banka872@banka4.com', - password: 'passworD4@', - }); - const { token } = response.body.data; - const res = await chai.request(app) - .get('/api/v1/accounts/3003801983/transactions') - .set('Authorization', `Bearer ${token}`) - .send(); - expect(res.body).to.be.an('object'); - expect(res.body.status).to.equal(200); - expect(res.body.data[0]).to.have.property('id'); - expect(res.body.data[0]).to.have.property('createdon'); - expect(res.body.data[0]).to.have.property('type'); - expect(res.body.data[0]).to.have.property('accountnumber'); - expect(res.body.data[0]).to.have.property('cashier'); - expect(res.body.data[0]).to.have.property('amount'); - expect(res.body.data[0]).to.have.property('oldbalance'); - expect(res.body.data[0]).to.have.property('newbalance'); - }, - ); - - it( - 'get all accounts should have these propertise', - async () => { - const signinUrl = '/api/v1/auth/signin'; - const response = await chai.request(app) - .post(signinUrl) - .send({ - email: 'admin@banka.com', - password: 'passworD4@', - }); - const { token } = response.body.data; - const res = await chai.request(app) - .get('/api/v1/accounts') - .set('Authorization', `Bearer ${token}`) - .send(); - expect(res.body).to.be.an('object'); - expect(res.body.status).to.equal(200); - expect(res.body.data[0]).to.have.property('id'); - expect(res.body.data[0]).to.have.property('email'); - expect(res.body.data[0]).to.have.property('firstname'); - expect(res.body.data[0]).to.have.property('lastname'); - expect(res.body.data[0]).to.have.property('accountnumber'); - expect(res.body.data[0]).to.have.property('createdon'); - expect(res.body.data[0]).to.have.property('owner'); - expect(res.body.data[0]).to.have.property('type'); - expect(res.body.data[0]).to.have.property('status'); - expect(res.body.data[0]).to.have.property('balance'); - }, - ); - - it( - 'should notify when account does not exist', - async () => { - const signinUrl = '/api/v1/auth/signin'; - const response = await chai.request(app) - .post(signinUrl) - .send({ - email: 'admin@banka.com', - password: 'passworD4@', - }); - const { token } = response.body.data; - const res = await chai.request(app) - .delete('/api/v1/accounts/883939378372') - .set('Authorization', `Bearer ${token}`) - .send(); - expect(res.body).to.be.an('object'); - expect(res.body.status).to.equal(404); - expect(res.body.data).to.equal('no account found'); - }, - ); - }); -}); +import chaiHttp from 'chai-http'; +import chai, { expect } from 'chai'; + +import app from '../app'; + +chai.use(chaiHttp); + +describe('Testing Accounts Controller', () => { + describe('Testing accounts controller', () => { + it( + 'accounts should have all required details', + async () => { + const signinUrl = '/api/v1/auth/signin'; + const response = await chai.request(app) + .post(signinUrl) + .send({ + email: 'banka872@banka4.com', + password: 'passworD4@', + }); + const { token } = response.body.data; + const res = await chai.request(app) + .post('/api/v1/accounts') + .set('Authorization', `Bearer ${token}`) + .send({ + type: 'savings', + }); + expect(res.body).to.be.an('object'); + expect(res.body.status).to.equal(201); + expect(res.body.data).to.have.property('id'); + expect(res.body.data).to.have.property('accountNumber'); + expect(res.body.data).to.have.property('createdOn'); + expect(res.body.data).to.have.property('owner'); + expect(res.body.data).to.have.property('type'); + expect(res.body.data).to.have.property('status'); + expect(res.body.data).to.have.property('balance'); + }, + ); + + it( + 'admin or staff should see all accounts', + async () => { + const signinUrl = '/api/v1/auth/signin'; + const response = await chai.request(app) + .post(signinUrl) + .send({ + email: 'admin@banka.com', + password: 'passworD4@', + }); + const { token } = response.body.data; + const res = await chai.request(app) + .get('/api/v1/accounts') + .set('Authorization', `Bearer ${token}`) + .send(); + expect(res.body).to.be.an('object'); + expect(res.body.status).to.equal(200); + expect(res.body.data[0]).to.have.property('id'); + expect(res.body.data[0]).to.have.property('email'); + expect(res.body.data[0]).to.have.property('firstname'); + expect(res.body.data[0]).to.have.property('lastname'); + expect(res.body.data[0]).to.have.property('accountnumber'); + expect(res.body.data[0]).to.have.property('createdon'); + expect(res.body.data[0]).to.have.property('owner'); + expect(res.body.data[0]).to.have.property('type'); + expect(res.body.data[0]).to.have.property('status'); + expect(res.body.data[0]).to.have.property('balance'); + }, + ); + + it( + 'admin or staff should see all accounts', + async () => { + const signinUrl = '/api/v1/auth/signin'; + const response = await chai.request(app) + .post(signinUrl) + .send({ + email: 'admin@banka.com', + password: 'passworD4@', + }); + const { token } = response.body.data; + const res = await chai.request(app) + .get('/api/v1/accounts') + .set('Authorization', `Bearer ${token}`) + .send(); + expect(res.body).to.be.an('object'); + expect(res.body.status).to.equal(200); + expect(res.body.data[0]).to.have.property('id'); + expect(res.body.data[0]).to.have.property('email'); + expect(res.body.data[0]).to.have.property('firstname'); + expect(res.body.data[0]).to.have.property('lastname'); + expect(res.body.data[0]).to.have.property('accountnumber'); + expect(res.body.data[0]).to.have.property('createdon'); + expect(res.body.data[0]).to.have.property('owner'); + expect(res.body.data[0]).to.have.property('type'); + expect(res.body.data[0]).to.have.property('status'); + expect(res.body.data[0]).to.have.property('balance'); + }, + ); + + it( + 'admin or staff can pass limit to see all accounts', + async () => { + const signinUrl = '/api/v1/auth/signin'; + const response = await chai.request(app) + .post(signinUrl) + .send({ + email: 'admin@banka.com', + password: 'passworD4@', + }); + const { token } = response.body.data; + const res = await chai.request(app) + .get('/api/v1/accounts?limit=5') + .set('Authorization', `Bearer ${token}`) + .send(); + expect(res.body).to.be.an('object'); + expect(res.body.status).to.equal(200); + expect(res.body.data[0]).to.have.property('id'); + expect(res.body.data[0]).to.have.property('email'); + expect(res.body.data[0]).to.have.property('firstname'); + expect(res.body.data[0]).to.have.property('lastname'); + expect(res.body.data[0]).to.have.property('accountnumber'); + expect(res.body.data[0]).to.have.property('createdon'); + expect(res.body.data[0]).to.have.property('owner'); + expect(res.body.data[0]).to.have.property('type'); + expect(res.body.data[0]).to.have.property('status'); + expect(res.body.data[0]).to.have.property('balance'); + }, + ); + + it( + 'admin or staff can pass status and limit to see all accounts', + async () => { + const signinUrl = '/api/v1/auth/signin'; + const response = await chai.request(app) + .post(signinUrl) + .send({ + email: 'admin@banka.com', + password: 'passworD4@', + }); + const { token } = response.body.data; + const res = await chai.request(app) + .get('/api/v1/accounts?status=active&limit=5') + .set('Authorization', `Bearer ${token}`) + .send(); + expect(res.body.data[0]).to.have.property('id'); + expect(res.body.data[0]).to.have.property('email'); + expect(res.body.data[0]).to.have.property('firstname'); + expect(res.body.data[0]).to.have.property('lastname'); + expect(res.body.data[0]).to.have.property('accountnumber'); + expect(res.body.data[0]).to.have.property('createdon'); + expect(res.body.data[0]).to.have.property('owner'); + expect(res.body.data[0]).to.have.property('type'); + expect(res.body.data[0]).to.have.property('status'); + expect(res.body.data[0]).to.have.property('balance'); + }, + ); + + it( + 'when query is not found', + async () => { + const signinUrl = '/api/v1/auth/signin'; + const response = await chai.request(app) + .post(signinUrl) + .send({ + email: 'admin@banka.com', + password: 'passworD4@', + }); + const { token } = response.body.data; + const res = await chai.request(app) + .get('/api/v1/accounts?status=engilsh&limit=5') + .set('Authorization', `Bearer ${token}`) + .send(); + expect(res.body).to.be.an('object'); + expect(res.body.status).to.equal(404); + expect(res.body.data) + .to.equal('no account found'); + }, + ); + + it( + 'only admin should access all accounts', + async () => { + const signinUrl = '/api/v1/auth/signin'; + const response = await chai.request(app) + .post(signinUrl) + .send({ + email: 'banka872@banka4.com', + password: 'passworD4@', + }); + const { token } = response.body.data; + const res = await chai.request(app) + .get('/api/v1/accounts') + .set('Authorization', `Bearer ${token}`) + .send(); + expect(res.body).to.be.an('object'); + expect(res.body.status).to.equal(401); + expect(res.body.data) + .to.equal('Sorry you don\'t have permission to perform this task'); + }, + ); + + it( + 'account type should only be savings or current', + async () => { + const signinUrl = '/api/v1/auth/signin'; + const response = await chai.request(app) + .post(signinUrl) + .send({ + email: 'banka872@banka4.com', + password: 'passworD4@', + }); + const { token } = response.body.data; + const res = await chai.request(app) + .post('/api/v1/accounts') + .set('Authorization', `Bearer ${token}`) + .send(); + expect(res.body).to.be.an('object'); + expect(res.body.status).to.equal(422); + expect(res.body.data) + .to.equal('account type can either be savings or current'); + }, + ); + + it( + 'should get specific account', + async () => { + const signinUrl = '/api/v1/auth/signin'; + const response = await chai.request(app) + .post(signinUrl) + .send({ + email: 'banka872@banka4.com', + password: 'passworD4@', + }); + const { token } = response.body.data; + const res = await chai.request(app) + .get(`/api/v1/accounts/${3003801983}`) + .set('Authorization', `Bearer ${token}`) + .send(); + expect(res.body).to.be.an('object'); + expect(res.body.status).to.equal(200); + expect(res.body.data).to.have.property('id'); + expect(res.body.data).to.have.property('email'); + expect(res.body.data).to.have.property('firstname'); + expect(res.body.data).to.have.property('lastname'); + expect(res.body.data).to.have.property('accountnumber'); + expect(res.body.data).to.have.property('createdon'); + expect(res.body.data).to.have.property('owner'); + expect(res.body.data).to.have.property('type'); + expect(res.body.data).to.have.property('status'); + expect(res.body.data).to.have.property('balance'); + }, + ); + + it( + 'when account does not have transaction', + async () => { + const signinUrl = '/api/v1/auth/signin'; + const response = await chai.request(app) + .post(signinUrl) + .send({ + email: 'banka872@banka4.com', + password: 'passworD4@', + }); + const { token } = response.body.data; + const res = await chai.request(app) + .get(`/api/v1/accounts/${3146859791}/transactions`) + .set('Authorization', `Bearer ${token}`) + .send(); + expect(res.body).to.be.an('object'); + expect(res.body.status).to.equal(404); + expect(res.body.data).to.equal('no transaction found'); + }, + ); + + it( + 'when specific account does not have transaction', + async () => { + const signinUrl = '/api/v1/auth/signin'; + const response = await chai.request(app) + .post(signinUrl) + .send({ + email: 'banka872@banka4.com', + password: 'passworD4@', + }); + const { token } = response.body.data; + const res = await chai.request(app) + .get(`/api/v1/accounts/${314685979881}`) + .set('Authorization', `Bearer ${token}`) + .send(); + expect(res.body).to.be.an('object'); + expect(res.body.status).to.equal(404); + expect(res.body.data).to.equal('no account found'); + }, + ); + + it( + 'should not patch account if not staff or admin', + async () => { + const signinUrl = '/api/v1/auth/signin'; + const response = await chai.request(app) + .post(signinUrl) + .send({ + email: 'banka872@banka4.com', + password: 'passworD4@', + }); + const { token } = response.body.data; + const res = await chai.request(app) + .post('/api/v1/accounts') + .set('Authorization', `Bearer ${token}`) + .send({ + type: 'savings', + }); + const { accountnumber } = res.body.data; + const res1 = await chai.request(app) + .patch(`/api/v1/accounts/${accountnumber}`) + .set('Authorization', `Bearer ${token}`) + .send({ + status: 'dormant', + }); + expect(res1.body).to.be.an('object'); + expect(res1.body.status).to.equal(401); + expect(res1.body.data) + .to.equal('Sorry you don\'t have permission to perform this task'); + }, + ); + + it( + 'should patch account if staff or admin', + async () => { + const signinUrl = '/api/v1/auth/signin'; + const response = await chai.request(app) + .post(signinUrl) + .send({ + email: 'admin@banka.com', + password: 'passworD4@', + }); + const { token } = response.body.data; + const res = await chai.request(app) + .post('/api/v1/accounts') + .set('Authorization', `Bearer ${token}`) + .send({ + type: 'savings', + }); + const { accountNumber } = res.body.data; + const res1 = await chai.request(app) + .patch(`/api/v1/accounts/${accountNumber}`) + .set('Authorization', `Bearer ${token}`) + .send({ + status: 'dormant', + }); + expect(res1.body).to.be.an('object'); + expect(res1.body.status).to.equal(200); + expect(res1.body.data).to.have.property('accountnumber'); + expect(res1.body.data).to.have.property('status'); + }, + ); + + it( + 'should not patch account if not active or dormant', + async () => { + const signinUrl = '/api/v1/auth/signin'; + const response = await chai.request(app) + .post(signinUrl) + .send({ + email: 'admin@banka.com', + password: 'passworD4@', + }); + const { token } = response.body.data; + const res = await chai.request(app) + .post('/api/v1/accounts') + .set('Authorization', `Bearer ${token}`) + .send({ + type: 'savings', + }); + const { accountNumber } = res.body.data; + const res1 = await chai.request(app) + .patch(`/api/v1/accounts/${accountNumber}77`) + .set('Authorization', `Bearer ${token}`) + .send({ + status: 'dormants', + }); + expect(res1.body).to.be.an('object'); + expect(res1.body.status).to.equal(422); + expect(res1.body.data).to.equal('account status can only be active or dormant'); + }, + ); + + it( + 'when account not found', + async () => { + const signinUrl = '/api/v1/auth/signin'; + const response = await chai.request(app) + .post(signinUrl) + .send({ + email: 'admin@banka.com', + password: 'passworD4@', + }); + const { token } = response.body.data; + const res = await chai.request(app) + .post('/api/v1/accounts') + .set('Authorization', `Bearer ${token}`) + .send({ + type: 'savings', + }); + const { accountNumber } = res.body.data; + const res1 = await chai.request(app) + .patch(`/api/v1/accounts/${accountNumber}77`) + .set('Authorization', `Bearer ${token}`) + .send({ + status: 'dormant', + }); + expect(res1.body).to.be.an('object'); + expect(res1.body.status).to.equal(404); + expect(res1.body.data).to.equal('account not found'); + }, + ); + + it( + 'should not delete account if not staff or admin', + async () => { + const signinUrl = '/api/v1/auth/signin'; + const response = await chai.request(app) + .post(signinUrl) + .send({ + email: 'banka872@banka4.com', + password: 'passworD4@', + }); + const { token } = response.body.data; + const res = await chai.request(app) + .post('/api/v1/accounts') + .set('Authorization', `Bearer ${token}`) + .send({ + type: 'savings', + }); + const { accountnumber } = res.body.data; + const res1 = await chai.request(app) + .delete(`/api/v1/accounts/${accountnumber}`) + .set('Authorization', `Bearer ${token}`) + .send(); + expect(res1.body).to.be.an('object'); + expect(res1.body.status).to.equal(401); + expect(res1.body.data) + .to.equal('Sorry you don\'t have permission to perform this task'); + }, + ); + + it( + 'should delete account if staff or admin', + async () => { + const signinUrl = '/api/v1/auth/signin'; + const response = await chai.request(app) + .post(signinUrl) + .send({ + email: 'admin@banka.com', + password: 'passworD4@', + }); + const { token } = response.body.data; + const res = await chai.request(app) + .post('/api/v1/accounts') + .set('Authorization', `Bearer ${token}`) + .send({ + type: 'savings', + }); + const { accountNumber } = res.body.data; + const res1 = await chai.request(app) + .delete(`/api/v1/accounts/${accountNumber}`) + .set('Authorization', `Bearer ${token}`) + .send(); + expect(res1.body).to.be.an('object'); + expect(res1.status).to.equal(200); + expect(res1.body.data).to.equal('Account successfully deleted'); + }, + ); + + it( + 'transaction should have these propertise', + async () => { + const signinUrl = '/api/v1/auth/signin'; + const response = await chai.request(app) + .post(signinUrl) + .send({ + email: 'banka872@banka4.com', + password: 'passworD4@', + }); + const { token } = response.body.data; + const res = await chai.request(app) + .get('/api/v1/accounts/3003801983/transactions') + .set('Authorization', `Bearer ${token}`) + .send(); + expect(res.body).to.be.an('object'); + expect(res.body.status).to.equal(200); + expect(res.body.data[0]).to.have.property('id'); + expect(res.body.data[0]).to.have.property('createdon'); + expect(res.body.data[0]).to.have.property('type'); + expect(res.body.data[0]).to.have.property('accountnumber'); + expect(res.body.data[0]).to.have.property('cashier'); + expect(res.body.data[0]).to.have.property('amount'); + expect(res.body.data[0]).to.have.property('oldbalance'); + expect(res.body.data[0]).to.have.property('newbalance'); + }, + ); + + it( + 'get all accounts should have these propertise', + async () => { + const signinUrl = '/api/v1/auth/signin'; + const response = await chai.request(app) + .post(signinUrl) + .send({ + email: 'admin@banka.com', + password: 'passworD4@', + }); + const { token } = response.body.data; + const res = await chai.request(app) + .get('/api/v1/accounts') + .set('Authorization', `Bearer ${token}`) + .send(); + expect(res.body).to.be.an('object'); + expect(res.body.status).to.equal(200); + expect(res.body.data[0]).to.have.property('id'); + expect(res.body.data[0]).to.have.property('email'); + expect(res.body.data[0]).to.have.property('firstname'); + expect(res.body.data[0]).to.have.property('lastname'); + expect(res.body.data[0]).to.have.property('accountnumber'); + expect(res.body.data[0]).to.have.property('createdon'); + expect(res.body.data[0]).to.have.property('owner'); + expect(res.body.data[0]).to.have.property('type'); + expect(res.body.data[0]).to.have.property('status'); + expect(res.body.data[0]).to.have.property('balance'); + }, + ); + + it( + 'should notify when account does not exist', + async () => { + const signinUrl = '/api/v1/auth/signin'; + const response = await chai.request(app) + .post(signinUrl) + .send({ + email: 'admin@banka.com', + password: 'passworD4@', + }); + const { token } = response.body.data; + const res = await chai.request(app) + .delete('/api/v1/accounts/883939378372') + .set('Authorization', `Bearer ${token}`) + .send(); + expect(res.body).to.be.an('object'); + expect(res.body.status).to.equal(404); + expect(res.body.data).to.equal('no account found'); + }, + ); + }); +}); diff --git a/server/v1/test/signup.js b/server/v1/test/signup.js index 6f9ab52..cff88ac 100644 --- a/server/v1/test/signup.js +++ b/server/v1/test/signup.js @@ -12,7 +12,7 @@ chai.use(chaiHttp); describe('Testing User Controller', () => { before(async () => { - await dbConnection.dbTesting('DELETE FROM users'); + await dbConnection.dbConnect('DELETE FROM users'); await dbConnection .dbConnect('INSERT into users(email, firstName, lastName, password, type, isAdmin) values($1, $2, $3, $4, $5, $6)', ['admin@banka.com', 'cavdy', 'ikenna', '$2a$10$CmmIst1.D3QjaWuafKbBaOuAFu0r9o7xxQY.0SMKiAN.h9z52a2y2', 'client', true]);