From c500ea00287e693915ef32946816a6e56b53c219 Mon Sep 17 00:00:00 2001 From: cavdy Date: Thu, 25 Apr 2019 22:06:58 +0100 Subject: [PATCH] feature(Delete account data from database when deleted):Delete account data from database when deleted Delete account data from database when staff or admin delete an account, the account transacions should be deleted from the database [Starts #165619691] --- server/v1/config/database.js | 119 ++++---- server/v1/routes/accounts.js | 20 +- server/v1/routes/auth.js | 6 +- server/v1/routes/transaction.js | 12 +- server/v1/routes/users.js | 4 +- server/v1/services/accounts.js | 499 ++++++++++++++++---------------- 6 files changed, 344 insertions(+), 316 deletions(-) diff --git a/server/v1/config/database.js b/server/v1/config/database.js index 2727722..b6b0fbf 100644 --- a/server/v1/config/database.js +++ b/server/v1/config/database.js @@ -1,58 +1,61 @@ -import { Pool } from 'pg'; -import debug from 'debug'; -import { parse } from 'pg-connection-string'; - -let conString; - -if (process.env.HEROKU_ACCESS === 'heroku_access') { - conString = parse(process.env.BANKA_DB); -} else { - conString = parse(process.env.DB_CONFIG); -} - -const pool = new Pool(conString); - -const dbConnection = { - /** - * Connect to database - * @constructor - * @param {*} passedQuery - passed in SQL query. - * @param {*} passedData -passed in db values - */ - async dbConnect(passedQuery, passedData) { - try { - return (async () => { - const client = await pool.connect(); - try { - return await client.query(passedQuery, passedData); - } finally { - client.release(); - } - })(); - } catch (e) { - 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; +import { Pool } from 'pg'; +import dotenv from 'dotenv'; +import debug from 'debug'; +import { parse } from 'pg-connection-string'; + +dotenv.config(); + +let conString; + +if (process.env.HEROKU_ACCESS === 'heroku_access') { + conString = parse(process.env.BANKA_DB); +} else { + conString = parse(process.env.DB_CONFIG); +} + +const pool = new Pool(conString); + +const dbConnection = { + /** + * Connect to database + * @constructor + * @param {*} passedQuery - passed in SQL query. + * @param {*} passedData -passed in db values + */ + async dbConnect(passedQuery, passedData) { + try { + return (async () => { + const client = await pool.connect(); + try { + return await client.query(passedQuery, passedData); + } finally { + client.release(); + } + })(); + } catch (e) { + 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/routes/accounts.js b/server/v1/routes/accounts.js index fd8c343..a0a8bbb 100644 --- a/server/v1/routes/accounts.js +++ b/server/v1/routes/accounts.js @@ -6,10 +6,20 @@ const router = express.Router(); // creating our routes router.get('/', jwtMiddleware.verifyJwt, AccountsController.allAccounts); -router.get('/:accountNumber', jwtMiddleware.verifyJwt, AccountsController.specificAccounts); -router.get('/:accountNumber/transactions', jwtMiddleware.verifyJwt, AccountsController.allAccountTransaction); -router.post('/', jwtMiddleware.verifyJwt, AccountsController.createAccount); -router.patch('/:accountNumber', jwtMiddleware.verifyJwt, AccountsController.patchAccount); -router.delete('/:accountNumber', jwtMiddleware.verifyJwt, AccountsController.deleteAccount); +router.get('/:accountNumber', + jwtMiddleware.verifyJwt, + AccountsController.specificAccounts); +router.get('/:accountNumber/transactions', + jwtMiddleware.verifyJwt, + AccountsController.allAccountTransaction); +router.post('/', + jwtMiddleware.verifyJwt, + AccountsController.createAccount); +router.patch('/:accountNumber', + jwtMiddleware.verifyJwt, + AccountsController.patchAccount); +router.delete('/:accountNumber', + jwtMiddleware.verifyJwt, + AccountsController.deleteAccount); export default router; diff --git a/server/v1/routes/auth.js b/server/v1/routes/auth.js index f1177eb..b307ebc 100644 --- a/server/v1/routes/auth.js +++ b/server/v1/routes/auth.js @@ -7,6 +7,10 @@ const router = express.Router(); // creating our routes router.post('/signin', jwtMiddleware.signinJwt, AuthController.loginUser); router.post('/signup', jwtMiddleware.signinJwt, AuthController.registerUser); -router.post('/signup/addstaff', jwtMiddleware.checkToken, jwtMiddleware.signinJwt, jwtMiddleware.verifyJwt, AuthController.createStaffs); +router.post('/signup/addstaff', + jwtMiddleware.checkToken, + jwtMiddleware.signinJwt, + jwtMiddleware.verifyJwt, + AuthController.createStaffs); export default router; diff --git a/server/v1/routes/transaction.js b/server/v1/routes/transaction.js index 3986d5a..35897c8 100644 --- a/server/v1/routes/transaction.js +++ b/server/v1/routes/transaction.js @@ -5,8 +5,14 @@ import TransactionController from '../controllers/transaction'; const router = express.Router(); // creating our routes -router.get('/:transactionid', jwtMiddleware.verifyJwt, TransactionController.getSpecificTransaction); -router.post('/:accountNumber/debit', jwtMiddleware.verifyJwt, TransactionController.debitTransaction); -router.post('/:accountNumber/credit', jwtMiddleware.verifyJwt, TransactionController.creditTransaction); +router.get('/:transactionid', + jwtMiddleware.verifyJwt, + TransactionController.getSpecificTransaction); +router.post('/:accountNumber/debit', + jwtMiddleware.verifyJwt, + TransactionController.debitTransaction); +router.post('/:accountNumber/credit', + jwtMiddleware.verifyJwt, + TransactionController.creditTransaction); export default router; diff --git a/server/v1/routes/users.js b/server/v1/routes/users.js index 69d30cc..3a137a5 100644 --- a/server/v1/routes/users.js +++ b/server/v1/routes/users.js @@ -6,7 +6,9 @@ const router = express.Router(); // creating our routes router.get('/', jwtMiddleware.verifyJwt, UsersController.getAllUsers); -router.get('/:email/accounts', jwtMiddleware.verifyJwt, UsersController.getUsersAccounts); +router.get('/:email/accounts', + jwtMiddleware.verifyJwt, + UsersController.getUsersAccounts); router.delete('/:id', jwtMiddleware.verifyJwt, UsersController.deleteUser); export default router; diff --git a/server/v1/services/accounts.js b/server/v1/services/accounts.js index eae5a0f..dfb3d28 100644 --- a/server/v1/services/accounts.js +++ b/server/v1/services/accounts.js @@ -1,248 +1,251 @@ -import dbConnection from '../config/database'; -import AccountModel from '../model/CreateAccount'; - -const CreateAccountService = { - /** - * Create an account. - * @constructor - * @param {*} accountData - The title of the book. - * @param {*} userData - The author of the book. - */ - async createAccount(accountData, userData) { - let returnStatus; let returnSuccess = ''; let returnError = ''; - const ACNumberGenerator = Math.floor(Math.random() * 1000000000) + 3000000000; - const date = new Date(); - const createdOn = `${date.getDate()}/${date.getMonth() + 1}/${date.getFullYear()}`; - const balance = 0.00; - const status = 'draft'; - - // pulling users data from database - const userDetails = await dbConnection - .dbConnect('SELECT id,firstname,lastname FROM users WHERE email=$1', - [userData.email]); - const { firstname, lastname, id } = userDetails.rows[0]; - - if (accountData.type === 'savings' || accountData.type === 'current') { - const response = await dbConnection - .dbConnect('INSERT into accounts(email, firstName, lastName, accountNumber, createdOn, owner, type, status, balance) values($1, $2, $3, $4, $5, $6, $7, $8, $9)', - [userData.email, firstname, lastname, ACNumberGenerator, createdOn, id, accountData.type, status, balance]); - if (response.command === 'INSERT') { - const accountDbData = await dbConnection - .dbConnect('SELECT id, accountnumber, createdon, owner, type, status, balance FROM accounts WHERE accountnumber=$1', - [ACNumberGenerator]); - const account = new AccountModel(); - account.id = accountDbData.rows[0].id; - account.accountNumber = accountDbData.rows[0].accountnumber; - account.createdOn = accountDbData.rows[0].createdon; - account.owner = accountDbData.rows[0].owner; - account.type = accountDbData.rows[0].type; - account.status = accountDbData.rows[0].status; - account.balance = accountDbData.rows[0].balance; - returnStatus = 201; - returnSuccess = account; - } - } else { - returnStatus = 422; - returnError = 'account type can either be savings or current'; - } - - return { - returnStatus, - returnSuccess, - returnError, - }; - }, - - /** - * Get all accounts - * @constructor - * @param {*} queryParams - passed in query data. - * @param {*} queryLimit -passed query limit - * @param {*} staff - staff details passed in - */ - async allAccounts(queryParams, queryLimit, staff) { - let returnStatus; let returnSuccess = ''; let returnError = ''; - - // pulling users data from database - const userDetails = await dbConnection - .dbConnect('SELECT type, isadmin FROM users WHERE email=$1', - [staff.email]); - const { type, isadmin } = userDetails.rows[0]; - - if (type === 'staff' || isadmin === true) { - if (typeof queryParams !== 'undefined' - && typeof queryLimit !== 'undefined') { - const allAccounts = await dbConnection - .dbConnect('SELECT * from accounts WHERE status=$1 LIMIT $2', - [queryParams, queryLimit]); - if (allAccounts.rows.length > 0) { - returnStatus = 200; - returnSuccess = allAccounts.rows; - } else { - returnStatus = 404; - returnError = 'no account found'; - } - } else if (typeof queryParams === 'undefined' - || typeof queryLimit !== 'undefined') { - const allAccounts = await dbConnection - .dbConnect('SELECT * from accounts LIMIT $1', [queryLimit]); - if (allAccounts.rows.length > 0) { - returnStatus = 200; - returnSuccess = allAccounts.rows; - } - } else if (typeof queryParams === 'undefined' - && typeof queryLimit === 'undefined') { - const allAccounts = await dbConnection - .dbConnect('SELECT * from accounts LIMIT $1', [10]); - returnStatus = 200; - returnSuccess = allAccounts.rows; - } - } else { - returnStatus = 401; - returnError = 'Sorry you don\'t have permission to perform this task'; - } - - return { - returnStatus, - returnSuccess, - returnError, - }; - }, - - /** - * Get specific account - * @constructor - * @param {*} accountNumber - recieve account number. - */ - async specificAccounts(accountNumber) { - let returnStatus; let returnSuccess = ''; let returnError = ''; - const userAccount = await dbConnection - .dbConnect('SELECT * from accounts WHERE accountnumber=$1', - [accountNumber]); - if (userAccount.rows.length > 0) { - returnStatus = 200; - // eslint-disable-next-line prefer-destructuring - returnSuccess = userAccount.rows[0]; - } else { - returnStatus = 404; - returnError = 'no account found'; - } - return { - returnStatus, - returnSuccess, - returnError, - }; - }, - - /** - * Get all accounts trasactions that belongs to account number - * @constructor - * @param {*} accountNumber - recieve account number. - */ - async allAccountTransaction(accountNumber) { - let returnStatus; let returnSuccess = ''; let returnError = ''; - const userTransaction = await dbConnection - .dbConnect('SELECT * from transactions WHERE accountnumber=$1', - [accountNumber]); - if (userTransaction.rows.length > 0) { - returnStatus = 200; - returnSuccess = userTransaction.rows; - } else { - returnStatus = 404; - returnError = 'no transaction found'; - } - return { - returnStatus, - returnSuccess, - returnError, - }; - }, - - /** - * Patch account - * @constructor - * @param {*} accountNumber - recieve account number - * @param {*} accountUpdate -data to update - * @param {*} staff - staff details passed in - */ - async patchAccount(accountNumber, accountUpdate, staff) { - let returnStatus; let returnSuccess = ''; let returnError = ''; - - // pulling users data from database - const userDetails = await dbConnection - .dbConnect('SELECT type, isadmin FROM users WHERE email=$1', - [staff.email]); - 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 }; - } - } - } else { - returnStatus = 401; - returnError = 'Sorry you don\'t have permission to perform this task'; - } - - return { - returnStatus, - returnSuccess, - returnError, - }; - }, - - /** - * Delete account - * @constructor - * @param {*} accountNumber - recieve account number. - * @param {*} staff - staff details passed in - */ - async deleteAccount(accountNumber, staff) { - let returnStatus; let returnSuccess = ''; let returnError = ''; - - const userDetails = await dbConnection - .dbConnect('SELECT type, isadmin FROM users WHERE email=$1', - [staff.email]); - const { type, isadmin } = userDetails.rows[0]; - - if (type === 'staff' || isadmin === true) { - const checkAccount = await dbConnection - .dbConnect('SELECT accountnumber FROM accounts WHERE accountnumber=$1', - [accountNumber]); - if (checkAccount.rows.length > 0) { - const accountDbData = await dbConnection - .dbConnect('DELETE FROM accounts WHERE accountnumber=$1', - [accountNumber]); - if (accountDbData.command === 'DELETE') { - returnStatus = 200; - returnSuccess = 'Account successfully deleted'; - } - } else { - returnStatus = 404; - returnError = 'no account found'; - } - } else { - returnStatus = 401; - returnError = 'Sorry you don\'t have permission to perform this task'; - } - return { - returnStatus, - returnSuccess, - returnError, - }; - }, -}; - -export default CreateAccountService; +import dbConnection from '../config/database'; +import AccountModel from '../model/CreateAccount'; + +const CreateAccountService = { + /** + * Create an account. + * @constructor + * @param {*} accountData - The title of the book. + * @param {*} userData - The author of the book. + */ + async createAccount(accountData, userData) { + let returnStatus; let returnSuccess = ''; let returnError = ''; + const ACNumberGenerator = Math.floor(Math.random() * 1000000000) + 3000000000; + const date = new Date(); + const createdOn = `${date.getDate()}/${date.getMonth() + 1}/${date.getFullYear()}`; + const balance = 0.00; + const status = 'draft'; + + // pulling users data from database + const userDetails = await dbConnection + .dbConnect('SELECT id,firstname,lastname FROM users WHERE email=$1', + [userData.email]); + const { firstname, lastname, id } = userDetails.rows[0]; + + if (accountData.type === 'savings' || accountData.type === 'current') { + const response = await dbConnection + .dbConnect('INSERT into accounts(email, firstName, lastName, accountNumber, createdOn, owner, type, status, balance) values($1, $2, $3, $4, $5, $6, $7, $8, $9)', + [userData.email, firstname, lastname, ACNumberGenerator, createdOn, id, accountData.type, status, balance]); + if (response.command === 'INSERT') { + const accountDbData = await dbConnection + .dbConnect('SELECT id, accountnumber, createdon, owner, type, status, balance FROM accounts WHERE accountnumber=$1', + [ACNumberGenerator]); + const account = new AccountModel(); + account.id = accountDbData.rows[0].id; + account.accountNumber = accountDbData.rows[0].accountnumber; + account.createdOn = accountDbData.rows[0].createdon; + account.owner = accountDbData.rows[0].owner; + account.type = accountDbData.rows[0].type; + account.status = accountDbData.rows[0].status; + account.balance = accountDbData.rows[0].balance; + returnStatus = 201; + returnSuccess = account; + } + } else { + returnStatus = 422; + returnError = 'account type can either be savings or current'; + } + + return { + returnStatus, + returnSuccess, + returnError, + }; + }, + + /** + * Get all accounts + * @constructor + * @param {*} queryParams - passed in query data. + * @param {*} queryLimit -passed query limit + * @param {*} staff - staff details passed in + */ + async allAccounts(queryParams, queryLimit, staff) { + let returnStatus; let returnSuccess = ''; let returnError = ''; + + // pulling users data from database + const userDetails = await dbConnection + .dbConnect('SELECT type, isadmin FROM users WHERE email=$1', + [staff.email]); + const { type, isadmin } = userDetails.rows[0]; + + if (type === 'staff' || isadmin === true) { + if (typeof queryParams !== 'undefined' + && typeof queryLimit !== 'undefined') { + const allAccounts = await dbConnection + .dbConnect('SELECT * from accounts WHERE status=$1 LIMIT $2', + [queryParams, queryLimit]); + if (allAccounts.rows.length > 0) { + returnStatus = 200; + returnSuccess = allAccounts.rows; + } else { + returnStatus = 404; + returnError = 'no account found'; + } + } else if (typeof queryParams === 'undefined' + || typeof queryLimit !== 'undefined') { + const allAccounts = await dbConnection + .dbConnect('SELECT * from accounts LIMIT $1', [queryLimit]); + if (allAccounts.rows.length > 0) { + returnStatus = 200; + returnSuccess = allAccounts.rows; + } + } else if (typeof queryParams === 'undefined' + && typeof queryLimit === 'undefined') { + const allAccounts = await dbConnection + .dbConnect('SELECT * from accounts LIMIT $1', [10]); + returnStatus = 200; + returnSuccess = allAccounts.rows; + } + } else { + returnStatus = 401; + returnError = 'Sorry you don\'t have permission to perform this task'; + } + + return { + returnStatus, + returnSuccess, + returnError, + }; + }, + + /** + * Get specific account + * @constructor + * @param {*} accountNumber - recieve account number. + */ + async specificAccounts(accountNumber) { + let returnStatus; let returnSuccess = ''; let returnError = ''; + const userAccount = await dbConnection + .dbConnect('SELECT * from accounts WHERE accountnumber=$1', + [accountNumber]); + if (userAccount.rows.length > 0) { + returnStatus = 200; + // eslint-disable-next-line prefer-destructuring + returnSuccess = userAccount.rows[0]; + } else { + returnStatus = 404; + returnError = 'no account found'; + } + return { + returnStatus, + returnSuccess, + returnError, + }; + }, + + /** + * Get all accounts trasactions that belongs to account number + * @constructor + * @param {*} accountNumber - recieve account number. + */ + async allAccountTransaction(accountNumber) { + let returnStatus; let returnSuccess = ''; let returnError = ''; + const userTransaction = await dbConnection + .dbConnect('SELECT * from transactions WHERE accountnumber=$1', + [accountNumber]); + if (userTransaction.rows.length > 0) { + returnStatus = 200; + returnSuccess = userTransaction.rows; + } else { + returnStatus = 404; + returnError = 'no transaction found'; + } + return { + returnStatus, + returnSuccess, + returnError, + }; + }, + + /** + * Patch account + * @constructor + * @param {*} accountNumber - recieve account number + * @param {*} accountUpdate -data to update + * @param {*} staff - staff details passed in + */ + async patchAccount(accountNumber, accountUpdate, staff) { + let returnStatus; let returnSuccess = ''; let returnError = ''; + + // pulling users data from database + const userDetails = await dbConnection + .dbConnect('SELECT type, isadmin FROM users WHERE email=$1', + [staff.email]); + 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 }; + } + } + } else { + returnStatus = 401; + returnError = 'Sorry you don\'t have permission to perform this task'; + } + + return { + returnStatus, + returnSuccess, + returnError, + }; + }, + + /** + * Delete account + * @constructor + * @param {*} accountNumber - recieve account number. + * @param {*} staff - staff details passed in + */ + async deleteAccount(accountNumber, staff) { + let returnStatus; let returnSuccess = ''; let returnError = ''; + + const userDetails = await dbConnection + .dbConnect('SELECT type, isadmin FROM users WHERE email=$1', + [staff.email]); + const { type, isadmin } = userDetails.rows[0]; + + if (type === 'staff' || isadmin === true) { + const checkAccount = await dbConnection + .dbConnect('SELECT accountnumber FROM accounts WHERE accountnumber=$1', + [accountNumber]); + if (checkAccount.rows.length > 0) { + const accountDbData = await dbConnection + .dbConnect('DELETE FROM accounts WHERE accountnumber=$1', + [accountNumber]); + if (accountDbData.command === 'DELETE') { + await dbConnection + .dbConnect('DELETE FROM transactions WHERE accountnumber=$1', + [accountNumber]); + returnStatus = 200; + returnSuccess = 'Account successfully deleted'; + } + } else { + returnStatus = 404; + returnError = 'no account found'; + } + } else { + returnStatus = 401; + returnError = 'Sorry you don\'t have permission to perform this task'; + } + return { + returnStatus, + returnSuccess, + returnError, + }; + }, +}; + +export default CreateAccountService;