diff --git a/.eslintrc.js b/.eslintrc.js index 923c92b..85e96bd 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,3 +1,43 @@ module.exports = { - "extends": "airbnb-base" -}; \ No newline at end of file + "extends": "airbnb-base", + "env": { + "browser": true, + "es6": true, + "jquery": true, + "node": true, + "mocha": true + }, + "rules": { + "one-var": 0, + "one-var-declaration-per-line": 0, + "new-cap": 0, + "consistent-return": 0, + "no-param-reassign": 0, + "comma-dangle": 0, + "curly": ["error", "multi-line"], + "import/no-unresolved": [2, { + "commonjs": true + }], + "no-shadow": ["error", { + "allow": ["req", "res", "err"] + }], + "valid-jsdoc": ["error", { + "requireReturn": true, + "requireReturnType": true, + "requireParamDescription": false, + "requireReturnDescription": true + }], + "require-jsdoc": ["error", { + "require": { + "FunctionDeclaration": true, + "MethodDefinition": true, + "ClassDeclaration": true + } + }], + "max-len": ["error", { "code": 80 }], + "linebreak-style": [ + "error", + "windows" + ] + } +}; diff --git a/.travis.yml b/.travis.yml index e54ff98..95f246e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,5 +12,5 @@ script: after_success: - npm run coverage env: -global: - -- CODECLIMATE_REPO_TOKEN=c14abfc89b0eb06fcb10f480f4b3e47142ac181c60c21f0131b570e72b1fbeb7 \ No newline at end of file + global: + - CODECLIMATE_REPO_TOKEN=c14abfc89b0eb06fcb10f480f4b3e47142ac181c60c21f0131b570e72b1fbeb7 \ No newline at end of file diff --git a/package.json b/package.json index ba4c1e9..ba29e8c 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ "start": "node ./server/build/app.js", "build": "babel -d ./server/build ./server/v1 -s", "dev": "nodemon --exec babel-node ./server/v1/app.js", - "test": "mocha --timeout 20000 ./server/v1/test/tests.js --recursive --require @babel/register --exit || true", + "test": "nyc mocha --timeout 30000 ./server/v1/test/tests.js --recursive --require @babel/register --exit || true", "generate-lcov": "nyc report --reporter=text-lcov > lcov.info", "coveralls-coverage": "coveralls < lcov.info", "codeclimate-coverage": "codeclimate-test-reporter < lcov.info", diff --git a/server/swagger.json b/server/swagger.json index 04added..edfda99 100644 --- a/server/swagger.json +++ b/server/swagger.json @@ -11,7 +11,7 @@ "https" ], "paths": { - "/auth/signup": { + "v1/auth/signup": { "post": { "tags": [ "Signup" @@ -62,7 +62,7 @@ } } }, - "/auth/signup/addstaff": { + "v1/auth/signup/addstaff": { "post": { "tags": [ "Signup" @@ -132,7 +132,7 @@ ] } }, - "/auth/signin": { + "v1/auth/signin": { "post": { "tags": [ "Signin" diff --git a/server/v1/app.js b/server/v1/app.js index c05d87b..a35be23 100644 --- a/server/v1/app.js +++ b/server/v1/app.js @@ -1,47 +1,45 @@ -import express from 'express'; -import bodyParser from 'body-parser'; -import cors from 'cors'; -import debug from 'debug'; -import swaggerUi from 'swagger-ui-express'; -import dbConnection from './config/database'; -import swaggerDocument from '../swagger'; -import RegisterRoute from './routes/register'; -import LoginRoute from './routes/login'; -import CreateAccountRoute from './routes/createAccount'; -import TransactionRoute from './routes/transaction'; -import UsersRoute from './routes/users'; -import jwtMiddleware from './middleware/jwt'; - -// instantiate expressjs -const app = express(); -const PORT = process.env.PORT || 5100; - -app.use(cors()); - -app.use(bodyParser.json()); -app.use(bodyParser.urlencoded({ extended: false })); - -// swagger -app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument)); - -// creating database tables -dbConnection.createTable(); - -// Index Route -app.get('/', (req, res) => { - res.send('welcome to Banka API'); -}); - -// creating the api version route -app.use('/api/auth/signup', RegisterRoute); -app.use('/api/auth/signin', LoginRoute); -app.use('/api/v1/accounts', jwtMiddleware.checkToken, CreateAccountRoute); -app.use('/api/v1/transactions', jwtMiddleware.checkToken, TransactionRoute); -app.use('/api/v1/users', jwtMiddleware.checkToken, UsersRoute); - -// listening to our port -app.listen(PORT, () => { - debug('server')(`server running on port: ${PORT}`); -}); - -export default app; +import express from 'express'; +import bodyParser from 'body-parser'; +import cors from 'cors'; +import debug from 'debug'; +import swaggerUi from 'swagger-ui-express'; +import migration from './config/migration'; +import swaggerDocument from '../swagger'; +import AuthRoute from './routes/auth'; +import CreateAccountRoute from './routes/accounts'; +import TransactionRoute from './routes/transaction'; +import UsersRoute from './routes/users'; +import jwtMiddleware from './middleware/jwt'; + +// instantiate expressjs +const app = express(); +const PORT = process.env.PORT || 5100; + +app.use(cors()); + +app.use(bodyParser.json()); +app.use(bodyParser.urlencoded({ extended: false })); + +// swagger +app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument)); + +// creating database tables +migration.createTable(); + +// Index Route +app.get('/', (req, res) => { + res.send('welcome to Banka API'); +}); + +// creating the api version route +app.use('/api/v1/auth', AuthRoute); +app.use('/api/v1/accounts', jwtMiddleware.checkToken, CreateAccountRoute); +app.use('/api/v1/transactions', jwtMiddleware.checkToken, TransactionRoute); +app.use('/api/v1/users', jwtMiddleware.checkToken, UsersRoute); + +// listening to our port +app.listen(PORT, () => { + debug('server')(`server running on port: ${PORT}`); +}); + +export default app; diff --git a/server/v1/config/database.js b/server/v1/config/database.js index 267ff1e..a7a944a 100644 --- a/server/v1/config/database.js +++ b/server/v1/config/database.js @@ -1,107 +1,61 @@ -import { Pool } from 'pg'; -import debug from 'debug'; -import dotenv from 'dotenv'; -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 = { - async createTable() { - const users = - `CREATE TABLE IF NOT EXISTS - users ( - id SERIAL PRIMARY KEY UNIQUE, - email VARCHAR(80) UNIQUE, - firstName VARCHAR(20), - lastName VARCHAR(20), - password VARCHAR(80), - type VARCHAR(10), - isAdmin BOOLEAN - )`; - - const accounts = - `CREATE TABLE IF NOT EXISTS - 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 - )`; - - const transactions = - `CREATE TABLE IF NOT EXISTS - transactions ( - id SERIAL PRIMARY KEY UNIQUE, - createdOn VARCHAR(40), - type VARCHAR(10), - accountNumber BIGINT, - cashier INTEGER, - amount FLOAT, - oldBalance FLOAT, - newBalance FLOAT - )`; - - try { - return (async () => { - const client = await pool.connect(); - try { - await client.query(users); - await client.query(accounts); - await client.query(transactions); - await client.query('INSERT into users(email, firstName, lastName, password, type, isAdmin) values($1, $2, $3, $4, $5, $6)', - ['admin@banka.com', 'cavdy', 'admin', process.env.ADMIN_PWD, 'staff', true]); - } finally { - client.release(); - } - })(); - } catch (e) { - return debug('query')(e.stack); - } - }, - 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); - } - }, - 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 debug from 'debug'; +import dotenv from 'dotenv'; +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/config/migration.js b/server/v1/config/migration.js new file mode 100644 index 0000000..c8cff45 --- /dev/null +++ b/server/v1/config/migration.js @@ -0,0 +1,58 @@ +import dbConnection from './database'; + +const Migration = { + /** + * Migration + * @constructor + */ + async createTable() { + const users = ` + CREATE TABLE IF NOT EXISTS + users ( + id SERIAL PRIMARY KEY UNIQUE, + email VARCHAR(80) UNIQUE, + firstName VARCHAR(20), + lastName VARCHAR(20), + password VARCHAR(80), + type VARCHAR(10), + isAdmin BOOLEAN + )`; + + const accounts = ` + CREATE TABLE IF NOT EXISTS + 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 + )`; + + const transactions = ` + CREATE TABLE IF NOT EXISTS + transactions ( + id SERIAL PRIMARY KEY UNIQUE, + createdOn VARCHAR(40), + type VARCHAR(10), + accountNumber BIGINT, + cashier INTEGER, + amount FLOAT, + oldBalance FLOAT, + newBalance FLOAT + )`; + + await dbConnection.dbConnect(users); + await dbConnection.dbConnect(accounts); + await dbConnection.dbConnect(transactions); + await dbConnection + .dbConnect('INSERT into users(email, firstName, lastName, password, type, isAdmin) values($1, $2, $3, $4, $5, $6)', + ['admin@banka.com', 'cavdy', 'admin', process.env.ADMIN_PWD, 'client', true]); + }, +}; + +export default Migration; diff --git a/server/v1/controllers/accounts.js b/server/v1/controllers/accounts.js new file mode 100644 index 0000000..fee96db --- /dev/null +++ b/server/v1/controllers/accounts.js @@ -0,0 +1,128 @@ +import AccountsService from '../services/accounts'; +import statusHelper from '../helper/statusHelper'; + +const CreateAccountController = { + /** + * Create accounts + * @constructor + * @param {*} req - get request. + * @param {*} res -get response + */ + async createAccount(req, res) { + const accountData = req.body; + const createdAccount = await AccountsService + .createAccount(accountData, req.authorizedData); + + const data = await statusHelper + .statusHelper(req, + res, + createdAccount.returnStatus, + createdAccount.returnError, + createdAccount.returnSuccess); + return data; + }, + + /** + * Get all accounts + * @constructor + * @param {*} req - get request. + * @param {*} res -get response + */ + async allAccounts(req, res) { + const queryParams = req.query.status; + const queryLimit = req.query.limit; + const allAccounts = await AccountsService + .allAccounts(queryParams, queryLimit, req.authorizedData); + + const data = await statusHelper + .statusHelper(req, + res, + allAccounts.returnStatus, + allAccounts.returnError, + allAccounts.returnSuccess); + return data; + }, + + /** + * Get specific account + * @constructor + * @param {*} req - get request. + * @param {*} res -get response + */ + async specificAccounts(req, res) { + const { accountNumber } = req.params; + const specificAccounts = await AccountsService + .specificAccounts(accountNumber); + + const data = await statusHelper + .statusHelper(req, + res, + specificAccounts.returnStatus, + specificAccounts.returnError, + specificAccounts.returnSuccess); + return data; + }, + + /** + * Get account transactions + * @constructor + * @param {*} req - get request. + * @param {*} res -get response + */ + async allAccountTransaction(req, res) { + const { accountNumber } = req.params; + const transactionHistory = await AccountsService + .allAccountTransaction(accountNumber); + + const data = await statusHelper + .statusHelper(req, + res, + transactionHistory.returnStatus, + transactionHistory.returnError, + transactionHistory.returnSuccess); + return data; + }, + + /** + * Patch account + * @constructor + * @param {*} req - get request. + * @param {*} res -get response + */ + async patchAccount(req, res) { + const { accountNumber } = req.params; + const accountStatus = req.body; + const updatedAccount = await AccountsService + .patchAccount(accountNumber, accountStatus, req.authorizedData); + + const data = await statusHelper + .statusHelper(req, + res, + updatedAccount.returnStatus, + updatedAccount.returnError, + updatedAccount.returnSuccess); + return data; + }, + + /** + * Delete accounts + * @constructor + * @param {*} req - get request. + * @param {*} res -get response + */ + async deleteAccount(req, res) { + const { accountNumber } = req.params; + const deleteAccount = await AccountsService + .deleteAccount(accountNumber, req.authorizedData); + + const data = await statusHelper + .statusHelper(req, + res, + deleteAccount.returnStatus, + deleteAccount.returnError, + deleteAccount.returnSuccess); + return data; + }, +}; + +export default CreateAccountController; diff --git a/server/v1/controllers/auth.js b/server/v1/controllers/auth.js new file mode 100644 index 0000000..c369c49 --- /dev/null +++ b/server/v1/controllers/auth.js @@ -0,0 +1,65 @@ +import AuthService from '../services/auth'; +import statusHelper from '../helper/statusHelper'; + +const AuthController = { + /** + * Login user + * @constructor + * @param {*} req - get request. + * @param {*} res -get response + */ + async loginUser(req, res) { + const userData = req.body; + const loggedUser = await AuthService.loginUser(userData, req.signintoken); + + const data = await statusHelper + .statusHelper(req, + res, + loggedUser.returnStatus, + loggedUser.returnError, + loggedUser.returnSuccess); + return data; + }, + + /** + * Signup user + * @constructor + * @param {*} req - get request. + * @param {*} res -get response + */ + async registerUser(req, res) { + const userData = req.body; + const createdUser = await AuthService + .registerUser(userData, req.signintoken); + + const data = await statusHelper + .statusHelper(req, + res, + createdUser.returnStatus, + createdUser.returnError, + createdUser.returnSuccess); + return data; + }, + + /** + * Signup staff + * @constructor + * @param {*} req - get request. + * @param {*} res -get response + */ + async createStaffs(req, res) { + const userData = req.body; + const createdStaff = await AuthService + .createStaffs(userData, req.signintoken, req.authorizedData); + + const data = await statusHelper + .statusHelper(req, + res, + createdStaff.returnStatus, + createdStaff.returnError, + createdStaff.returnSuccess); + return data; + }, +}; + +export default AuthController; diff --git a/server/v1/controllers/createAccount.js b/server/v1/controllers/createAccount.js deleted file mode 100644 index f15baae..0000000 --- a/server/v1/controllers/createAccount.js +++ /dev/null @@ -1,73 +0,0 @@ -import CreateAccountService from '../services/createAccount'; -import statusHelper from '../helper/statusHelper'; - -const CreateAccountController = { - async createAccount(req, res) { - const accountData = req.body; - const createdAccount = await CreateAccountService - .createAccount(accountData, req.authorizedData); - - const data = await statusHelper - .statusHelper('nothing', res, createdAccount.returnStatus, createdAccount.returnError, createdAccount.returnSuccess); - return data; - }, - - // all accounts - async allAccounts(req, res) { - const queryParams = req.query.status; - const queryLimit = req.query.limit; - const allAccounts = await CreateAccountService - .allAccounts(queryParams, queryLimit, req.authorizedData); - - const data = await statusHelper - .statusHelper('nothing', res, allAccounts.returnStatus, allAccounts.returnError, allAccounts.returnSuccess); - return data; - }, - - // specific account - async specificAccounts(req, res) { - const { accountNumber } = req.params; - const specificAccounts = await CreateAccountService - .specificAccounts(accountNumber); - - const data = await statusHelper - .statusHelper('nothing', res, specificAccounts.returnStatus, specificAccounts.returnError, specificAccounts.returnSuccess); - return data; - }, - - // get transaction history - async allAccountTransaction(req, res) { - const { accountNumber } = req.params; - const transactionHistory = await CreateAccountService - .allAccountTransaction(accountNumber); - - const data = await statusHelper - .statusHelper('nothing', res, transactionHistory.returnStatus, transactionHistory.returnError, transactionHistory.returnSuccess); - return data; - }, - - // patchAccount - async patchAccount(req, res) { - const { accountNumber } = req.params; - const accountStatus = req.body; - const updatedAccount = await CreateAccountService - .patchAccount(accountNumber, accountStatus, req.authorizedData); - - const data = await statusHelper - .statusHelper('nothing', res, updatedAccount.returnStatus, updatedAccount.returnError, updatedAccount.returnSuccess); - return data; - }, - - // deleteAccount - async deleteAccount(req, res) { - const { accountNumber } = req.params; - const deleteAccount = await CreateAccountService - .deleteAccount(accountNumber, req.authorizedData); - - const data = await statusHelper - .statusHelper('nothing', res, deleteAccount.returnStatus, deleteAccount.returnError, deleteAccount.returnSuccess); - return data; - }, -}; - -export default CreateAccountController; diff --git a/server/v1/controllers/login.js b/server/v1/controllers/login.js deleted file mode 100644 index 3d571c7..0000000 --- a/server/v1/controllers/login.js +++ /dev/null @@ -1,15 +0,0 @@ -import LoginService from '../services/login'; -import statusHelper from '../helper/statusHelper'; - -const LoginController = { - async loginUser(req, res) { - const userData = req.body; - const loggedUser = await LoginService.loginUser(userData, req.signintoken); - - const data = await statusHelper - .statusHelper('nothing', res, loggedUser.returnStatus, loggedUser.returnError, loggedUser.returnSuccess); - return data; - }, -}; - -export default LoginController; diff --git a/server/v1/controllers/register.js b/server/v1/controllers/register.js deleted file mode 100644 index 955daa5..0000000 --- a/server/v1/controllers/register.js +++ /dev/null @@ -1,25 +0,0 @@ -import RegisterService from '../services/register'; -import statusHelper from '../helper/statusHelper'; - -const RegisterController = { - async registerUser(req, res) { - const userData = req.body; - const createdUser = await RegisterService.registerUser(userData, req.signintoken); - - const data = await statusHelper - .statusHelper('nothing', res, createdUser.returnStatus, createdUser.returnError, createdUser.returnSuccess); - return data; - }, - - async createStaffs(req, res) { - const userData = req.body; - const createdStaff = await RegisterService - .createStaffs(userData, req.signintoken, req.authorizedData); - - const data = await statusHelper - .statusHelper('nothing', res, createdStaff.returnStatus, createdStaff.returnError, createdStaff.returnSuccess); - return data; - }, -}; - -export default RegisterController; diff --git a/server/v1/controllers/transaction.js b/server/v1/controllers/transaction.js index 11eb56d..cd2aeb9 100644 --- a/server/v1/controllers/transaction.js +++ b/server/v1/controllers/transaction.js @@ -1,39 +1,68 @@ -/* eslint-disable consistent-return */ -import TransactionService from '../services/transaction'; -import statusHelper from '../helper/statusHelper'; - -const TransactionController = { - async debitTransaction(req, res) { - const { accountNumber } = req.params; - const transactionData = req.body; - const debitedData = await TransactionService - .debitTransaction(accountNumber, req.authorizedData, transactionData); - - const data = await statusHelper - .statusHelper('nothing', res, debitedData.returnStatus, debitedData.returnError, debitedData.returnSuccess); - return data; - }, - - async getSpecificTransaction(req, res) { - const { transactionid } = req.params; - const getTransaction = await TransactionService - .getSpecificTransaction(transactionid); - - const data = await statusHelper - .statusHelper('nothing', res, getTransaction.returnStatus, getTransaction.returnError, getTransaction.returnSuccess); - return data; - }, - - async creditTransaction(req, res) { - const { accountNumber } = req.params; - const transactionData = req.body; - const creditedData = await TransactionService - .creditTransaction(accountNumber, req.authorizedData, transactionData); - - const data = await statusHelper - .statusHelper('nothing', res, creditedData.returnStatus, creditedData.returnError, creditedData.returnSuccess); - return data; - }, -}; - -export default TransactionController; +import TransactionService from '../services/transaction'; +import statusHelper from '../helper/statusHelper'; + +const TransactionController = { + /** + * Debit Account + * @constructor + * @param {*} req - get request. + * @param {*} res -get response + */ + async debitTransaction(req, res) { + const { accountNumber } = req.params; + const transactionData = req.body; + const debitedData = await TransactionService + .debitTransaction(accountNumber, req.authorizedData, transactionData); + + const data = await statusHelper + .statusHelper(req, + res, + debitedData.returnStatus, + debitedData.returnError, + debitedData.returnSuccess); + return data; + }, + + /** + * Get specific transaction + * @constructor + * @param {*} req - get request. + * @param {*} res -get response + */ + async getSpecificTransaction(req, res) { + const { transactionid } = req.params; + const getTransaction = await TransactionService + .getSpecificTransaction(transactionid); + + const data = await statusHelper + .statusHelper(req, + res, + getTransaction.returnStatus, + getTransaction.returnError, + getTransaction.returnSuccess); + return data; + }, + + /** + * Credit Account + * @constructor + * @param {*} req - get request. + * @param {*} res -get response + */ + async creditTransaction(req, res) { + const { accountNumber } = req.params; + const transactionData = req.body; + const creditedData = await TransactionService + .creditTransaction(accountNumber, req.authorizedData, transactionData); + + const data = await statusHelper + .statusHelper(req, + res, + creditedData.returnStatus, + creditedData.returnError, + creditedData.returnSuccess); + return data; + }, +}; + +export default TransactionController; diff --git a/server/v1/controllers/users.js b/server/v1/controllers/users.js index 6670788..060f123 100644 --- a/server/v1/controllers/users.js +++ b/server/v1/controllers/users.js @@ -1,33 +1,64 @@ -import UserService from '../services/users'; -import statusHelper from '../helper/statusHelper'; - -const UsersController = { - async getAllUsers(req, res) { - const queryLimit = req.query.limit; - const allUsers = await UserService.getAllUsers(req.authorizedData, queryLimit); - - const data = await statusHelper - .statusHelper('nothing', res, allUsers.returnStatus, allUsers.returnError, allUsers.returnSuccess); - return data; - }, - - async getUsersAccounts(req, res) { - const { email } = req.params; - const getUsersAccounts = await UserService.getUsersAccounts(email); - - const data = await statusHelper - .statusHelper('nothing', res, getUsersAccounts.returnStatus, getUsersAccounts.returnError, getUsersAccounts.returnSuccess); - return data; - }, - - async deleteUser(req, res) { - const { id } = req.params; - const deleteUser = await UserService.deleteUser(id, req.authorizedData); - - const data = await statusHelper - .statusHelper('nothing', res, deleteUser.returnStatus, deleteUser.returnError, deleteUser.returnSuccess); - return data; - }, -}; - -export default UsersController; +import UserService from '../services/users'; +import statusHelper from '../helper/statusHelper'; + +const UsersController = { + /** + * Get users + * @constructor + * @param {*} req - get request. + * @param {*} res -get response + */ + async getAllUsers(req, res) { + const queryLimit = req.query.limit; + const allUsers = await UserService + .getAllUsers(req.authorizedData, queryLimit); + + const data = await statusHelper + .statusHelper(req, + res, + allUsers.returnStatus, + allUsers.returnError, + allUsers.returnSuccess); + return data; + }, + + /** + * Get user accounts + * @constructor + * @param {*} req - get request. + * @param {*} res -get response + */ + async getUsersAccounts(req, res) { + const { email } = req.params; + const getUsersAccounts = await UserService.getUsersAccounts(email); + + const data = await statusHelper + .statusHelper(req, + res, + getUsersAccounts.returnStatus, + getUsersAccounts.returnError, + getUsersAccounts.returnSuccess); + return data; + }, + + /** + * Delete user + * @constructor + * @param {*} req - get request. + * @param {*} res -get response + */ + async deleteUser(req, res) { + const { id } = req.params; + const deleteUser = await UserService.deleteUser(id, req.authorizedData); + + const data = await statusHelper + .statusHelper(req, + res, + deleteUser.returnStatus, + deleteUser.returnError, + deleteUser.returnSuccess); + return data; + }, +}; + +export default UsersController; diff --git a/server/v1/helper/registrationHelper.js b/server/v1/helper/registrationHelper.js index 50056c4..a424b81 100644 --- a/server/v1/helper/registrationHelper.js +++ b/server/v1/helper/registrationHelper.js @@ -1,44 +1,83 @@ -/* eslint-disable one-var */ -/* eslint-disable one-var-declaration-per-line */ -const registrationHelper = { - async registrationHelper(userData) { - const firstnameAndLastnameRegex = /^[a-zA-Z ]{2,15}$/; - const emailRegex = /^([a-zA-Z0-9_\-\.]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,10})$/; - const passwordRegex = /^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{8,}$/; - const returnValue = []; - let emailPassed, firstnamePassed, lastnamePassed, passwordPassed; - - // Check if email is valid - if (emailRegex.test(userData.email)) { - emailPassed = true; - } else { - returnValue.push('Email is required'); - } - - if (firstnameAndLastnameRegex.test(userData.firstName) && typeof userData.firstName !== 'undefined' && typeof userData.firstName === 'string') { - firstnamePassed = true; - } else { - returnValue.push('Firstname required'); - } - if (firstnameAndLastnameRegex.test(userData.lastName) && typeof userData.lastName !== 'undefined' && typeof userData.lastName === 'string') { - lastnamePassed = true; - } else { - returnValue.push('Lastname required'); - } - if (passwordRegex.test(userData.password) && typeof userData.password !== 'undefined' && userData.password !== null) { - passwordPassed = true; - } else { - returnValue.push('Password should contain atleast 8 characters, 1 uppercase letter, 1 lowercase letter, 1 number and 1 symbol or character'); - } - - return [ - firstnamePassed, - lastnamePassed, - emailPassed, - passwordPassed, - returnValue, - ]; - }, -}; - -export default registrationHelper; +const registrationHelper = { + /** + * Return validation status + * @constructor + * @param {*} userData - passed in user's data. + */ + async registrationHelper(userData) { + const firstnameAndLastnameRegex = /^[a-zA-Z ]{2,15}$/; + /* eslint max-len: ["error", { "ignoreRegExpLiterals": true }] */ + const emailRegex = /^([a-zA-Z0-9_\-\.]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,10})$/; + const passwordRegex = /^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{8,}$/; + const whiteSpaces = /\s/g; + const returnValue = []; + let emailPassed, firstnamePassed, lastnamePassed, passwordPassed; + + let email; + let fname; + let lname; + let password; + + // strip spaces + if (typeof userData.email !== 'undefined') { + email = userData.email.replace(whiteSpaces, ''); + email = userData.email.trim(); + } + + if (typeof userData.firstName !== 'undefined') { + fname = userData.firstName.replace(whiteSpaces, ''); + fname = userData.firstName.trim(); + } + + if (typeof userData.lastName !== 'undefined') { + lname = userData.lastName.replace(whiteSpaces, ''); + lname = userData.lastName.trim(); + } + + if (typeof userData.password !== 'undefined') { + password = userData.password.replace(whiteSpaces, ''); + password = userData.password.trim(); + } + + // Check if email is valid + if (emailRegex.test(email) + && email !== '') { + emailPassed = true; + } else { + returnValue.push('Email is required'); + } + + if (firstnameAndLastnameRegex.test(fname) + && typeof fname === 'string' + && fname !== '') { + firstnamePassed = true; + } else { + returnValue.push('Firstname required'); + } + if (firstnameAndLastnameRegex.test(lname) + && typeof lname === 'string' + && lname !== '') { + lastnamePassed = true; + } else { + returnValue.push('Lastname required'); + } + if (passwordRegex.test(password) + && typeof password === 'string' + && password !== '') { + passwordPassed = true; + } else { + returnValue + .push('Password should contain atleast 8 characters, 1 uppercase letter, 1 lowercase letter, 1 number and 1 symbol or character'); + } + + return [ + firstnamePassed, + lastnamePassed, + emailPassed, + passwordPassed, + returnValue, + ]; + }, +}; + +export default registrationHelper; diff --git a/server/v1/helper/statusHelper.js b/server/v1/helper/statusHelper.js index ddd8cad..a4b8df7 100644 --- a/server/v1/helper/statusHelper.js +++ b/server/v1/helper/statusHelper.js @@ -1,56 +1,53 @@ -/* eslint-disable no-else-return */ -const statusHelper = { - async statusHelper(req, res, status, error, data) { - if (status === 401) { // unauthorized - res.status(401); - return res.json({ - status: 401, - data: error, - }); - } else if (status === 500) { // internal error - res.status(500); - return res.json({ - status: 500, - data: 'Internal Server Error', - }); - } else if (status === 409) { // conflict - res.status(409); - return res.json({ - status: 409, - data: error, - }); - } else if (status === 201) { // created - res.status(201); - return res.json({ - status: 201, - data, - }); - } else if (status === 200) { // success - res.status(200); - return res.json({ - status: 200, - data, - }); - } else if (status === 404) { // not found - res.status(404); - return res.json({ - status: 404, - data: error, - }); - } else if (status === 204) { // no content - res.status(204); - return res.json({ - status: 204, - data: error, - }); - } else if (status === 422) { - res.status(422); - return res.json({ // unprocessable entity - status: 422, - data: error, - }); - } - }, -}; - -export default statusHelper; +/* eslint-disable no-else-return */ +const statusHelper = { + /** + * Return json data base on the status + * @constructor + * @param {*} req - passed in req. + * @param {*} res -passed in res + * @param {*} status - passed in status + * @param {*} error - passed in error message + * @param {*} data - passed in success data + */ + async statusHelper(req, res, status, error, data) { + if (status === 401) { // unauthorized + res.status(401); + return res.json({ + status: 401, + data: error, + }); + } else if (status === 409) { // conflict + res.status(409); + return res.json({ + status: 409, + data: error, + }); + } else if (status === 201) { // created + res.status(201); + return res.json({ + status: 201, + data, + }); + } else if (status === 200) { // success + res.status(200); + return res.json({ + status: 200, + data, + }); + } else if (status === 404) { // not found + res.status(404); + return res.json({ + status: 404, + data: error, + }); + } else if (status === 422) { + res.status(422); + return res.json({ // unprocessable entity + status: 422, + data: error, + }); + } + }, +}; + +export default statusHelper; diff --git a/server/v1/middleware/jwt.js b/server/v1/middleware/jwt.js index bf875df..47ee931 100644 --- a/server/v1/middleware/jwt.js +++ b/server/v1/middleware/jwt.js @@ -1,39 +1,62 @@ -import jwt from 'jsonwebtoken'; -import dotenv from 'dotenv'; - -dotenv.config(); - -const jwtMiddleware = { - 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); - } - }, - 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(); - }); - }, - 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'; + +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; diff --git a/server/v1/routes/accounts.js b/server/v1/routes/accounts.js new file mode 100644 index 0000000..fd8c343 --- /dev/null +++ b/server/v1/routes/accounts.js @@ -0,0 +1,15 @@ +import express from 'express'; +import jwtMiddleware from '../middleware/jwt'; +import AccountsController from '../controllers/accounts'; + +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); + +export default router; diff --git a/server/v1/routes/auth.js b/server/v1/routes/auth.js new file mode 100644 index 0000000..f1177eb --- /dev/null +++ b/server/v1/routes/auth.js @@ -0,0 +1,12 @@ +import express from 'express'; +import jwtMiddleware from '../middleware/jwt'; +import AuthController from '../controllers/auth'; + +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); + +export default router; diff --git a/server/v1/routes/createAccount.js b/server/v1/routes/createAccount.js deleted file mode 100644 index 9baac62..0000000 --- a/server/v1/routes/createAccount.js +++ /dev/null @@ -1,15 +0,0 @@ -import express from 'express'; -import jwtMiddleware from '../middleware/jwt'; -import CreateAccountController from '../controllers/createAccount'; - -const router = express.Router(); - -// creating our routes -router.get('/', jwtMiddleware.verifyJwt, CreateAccountController.allAccounts); -router.get('/:accountNumber', jwtMiddleware.verifyJwt, CreateAccountController.specificAccounts); -router.get('/:accountNumber/transactions', jwtMiddleware.verifyJwt, CreateAccountController.allAccountTransaction); -router.post('/', jwtMiddleware.verifyJwt, CreateAccountController.createAccount); -router.patch('/:accountNumber', jwtMiddleware.verifyJwt, CreateAccountController.patchAccount); -router.delete('/:accountNumber', jwtMiddleware.verifyJwt, CreateAccountController.deleteAccount); - -export default router; diff --git a/server/v1/routes/login.js b/server/v1/routes/login.js deleted file mode 100644 index 2314b3d..0000000 --- a/server/v1/routes/login.js +++ /dev/null @@ -1,10 +0,0 @@ -import express from 'express'; -import jwtMiddleware from '../middleware/jwt'; -import LoginController from '../controllers/login'; - -const router = express.Router(); - -// creating our routes -router.post('/', jwtMiddleware.signinJwt, LoginController.loginUser); - -export default router; diff --git a/server/v1/routes/register.js b/server/v1/routes/register.js deleted file mode 100644 index ab9b7c4..0000000 --- a/server/v1/routes/register.js +++ /dev/null @@ -1,11 +0,0 @@ -import express from 'express'; -import jwtMiddleware from '../middleware/jwt'; -import RegisterController from '../controllers/register'; - -const router = express.Router(); - -// creating our routes -router.post('/', jwtMiddleware.signinJwt, RegisterController.registerUser); -router.post('/addstaff', jwtMiddleware.checkToken, jwtMiddleware.signinJwt, jwtMiddleware.verifyJwt, RegisterController.createStaffs); - -export default router; diff --git a/server/v1/services/createAccount.js b/server/v1/services/accounts.js similarity index 70% rename from server/v1/services/createAccount.js rename to server/v1/services/accounts.js index 2d4ac4e..eae5a0f 100644 --- a/server/v1/services/createAccount.js +++ b/server/v1/services/accounts.js @@ -1,203 +1,248 @@ -/* eslint-disable no-param-reassign */ -import dbConnection from '../config/database'; -import AccountModel from '../model/CreateAccount'; - -const CreateAccountService = { - async createAccount(accountData, userData) { - let returnStatus; let returnSuccess = ''; let returnError = ''; - const accountNumberGenerator = 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 = 'active'; - - // 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]; - - // eslint-disable-next-line max-len - 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, accountNumberGenerator, 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', [accountNumberGenerator]); - 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, - }; - }, - - 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 for this user'; - } - } 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 { - returnStatus = 404; - returnError = 'no account found for this user'; - } - } else { - 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, - }; - }, - - 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 transaction found'; - } - return { - returnStatus, - returnSuccess, - returnError, - }; - }, - - 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, - }; - }, - - 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) { - // eslint-disable-next-line no-plusplus - 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 = 500; - } - } - } else { - returnStatus = 401; - returnError = 'Sorry you don\'t have permission to perform this task'; - } - - return { - returnStatus, - returnSuccess, - returnError, - }; - }, - - 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 = 204; - 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') { + 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; diff --git a/server/v1/services/auth.js b/server/v1/services/auth.js new file mode 100644 index 0000000..0783121 --- /dev/null +++ b/server/v1/services/auth.js @@ -0,0 +1,192 @@ +import bcrypt from 'bcryptjs'; +import dbConnection from '../config/database'; +import UserModel from '../model/users'; +import registrationHelper from '../helper/registrationHelper'; + +const AuthService = { + /** + * Login user + * @constructor + * @param {*} userData - user form data. + * @param {*} token - user's token + */ + async loginUser(userData, token) { + /* eslint max-len: ["error", { "ignoreRegExpLiterals": true }] */ + const emailRegex = /^([a-zA-Z0-9_\-\.]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,10})$/; + const passwordRegex = /^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{8,}$/; + let returnStatus; let returnSuccess = ''; let returnError = ''; + + // Check if email and password is valid + if (emailRegex.test(userData.email) + && passwordRegex.test(userData.password)) { + // check if email, if it exist get the user data + const emailresponse = await dbConnection + .dbConnect('SELECT * FROM users WHERE email=$1', [userData.email]); + if (emailresponse.rows.length > 0) { + // Load hash from your password DB. + const passwordUnhash = bcrypt + .compareSync(userData.password, emailresponse.rows[0].password); + if (passwordUnhash) { + // return users details + const user = new UserModel(); + user.id = emailresponse.rows[0].id; + user.firstName = emailresponse.rows[0].firstname; + user.lastName = emailresponse.rows[0].lastname; + user.email = emailresponse.rows[0].email; + user.token = token; + returnStatus = 201; + returnSuccess = user; + } else { + // else echo incorrect password + returnStatus = 422; + returnError = 'incorrect password'; + } + } else { + returnStatus = 404; + returnError = 'email does not exist'; + } + } else { + const error = []; + if (!emailRegex.test(userData.email)) { + returnStatus = 422; + error.push('invalid email address'); + } + + if (!passwordRegex.test(userData.password)) { + returnStatus = 422; + error + .push('Password should contain atleast 8 characters, 1 uppercase letter, 1 lowercase letter, 1 number and 1 symbol or character'); + } + returnError = error; + } + + + return { + returnStatus, + returnSuccess, + returnError, + }; + }, + + /** + * Register user + * @constructor + * @param {*} userData - user form data. + * @param {*} token - user's token + */ + async registerUser(userData, token) { + const returnData = await registrationHelper.registrationHelper(userData); + let returnStatus; let returnSuccess = ''; let returnError = ''; + + if (returnData[0] === true + && returnData[1] === true + && returnData[2] === true + && returnData[3] === true) { + const salt = bcrypt.genSaltSync(10); + const hash = bcrypt.hashSync(userData.password, salt); + userData.type = 'client'; + userData.isAdmin = false; + // checks if email exist + const emailresponse = await dbConnection + .dbConnect('SELECT email FROM users WHERE email=$1', + [userData.email]); + if (emailresponse.rows.length >= 1) { + returnStatus = 409; + returnError = 'email already exist'; + } else { + // email does not exist... you can insert data + const response = await dbConnection + .dbConnect('INSERT into users(email, firstName, lastName, password, type, isAdmin) values($1, $2, $3, $4, $5, $6)', + [userData.email, userData.firstName, userData.lastName, hash, userData.type, userData.isAdmin]); + if (response.command === 'INSERT') { + const userDbData = await dbConnection + .dbConnect('SELECT * FROM users WHERE email=$1', + [userData.email]); + const user = new UserModel(); + user.id = userDbData.rows[0].id; + user.firstName = userDbData.rows[0].firstname; + user.lastName = userDbData.rows[0].lastname; + user.email = userDbData.rows[0].email; + user.token = token; + returnStatus = 201; + returnSuccess = user; + } + } + } else { + returnStatus = 422; + // eslint-disable-next-line prefer-destructuring + returnError = returnData[4]; + } + return { + returnStatus, + returnSuccess, + returnError, + }; + }, + + /** + * Create staffs + * @constructor + * @param {*} userData - user form data. + * @param {*} token - user's token + * @param {*} admin - admin's token + */ + async createStaffs(userData, token, admin) { + const returnData = await registrationHelper.registrationHelper(userData); + let returnStatus; let returnSuccess = ''; let returnError = ''; + + const userDetails = await dbConnection + .dbConnect('SELECT isadmin FROM users WHERE email=$1', [admin.email]); + const { isadmin } = userDetails.rows[0]; + + if (isadmin === true) { + if (returnData[0] === true + && returnData[1] === true + && returnData[2] === true + && returnData[3] === true) { + const salt = bcrypt.genSaltSync(10); + const hash = bcrypt.hashSync(userData.password, salt); + // checks if email exist + const emailresponse = await dbConnection + .dbConnect('SELECT email FROM users WHERE email=$1', + [userData.email]); + if (emailresponse.rows.length >= 1) { + returnStatus = 409; + returnError = 'email already exist'; + } else { + // email does not exist... you can insert data + const response = await dbConnection + .dbConnect('INSERT into users(email, firstName, lastName, password, type, isAdmin) values($1, $2, $3, $4, $5, $6)', + [userData.email, userData.firstName, userData.lastName, hash, userData.type, userData.isAdmin]); + if (response.command === 'INSERT') { + const userDbData = await dbConnection + .dbConnect('SELECT * FROM users WHERE email=$1', + [userData.email]); + const user = new UserModel(); + user.id = userDbData.rows[0].id; + user.firstName = userDbData.rows[0].firstname; + user.lastName = userDbData.rows[0].lastname; + user.email = userDbData.rows[0].email; + user.token = token; + returnStatus = 201; + returnSuccess = user; + } + } + } else { + returnStatus = 422; + // eslint-disable-next-line prefer-destructuring + returnError = returnData[4]; + } + } else { + returnStatus = 401; + returnError = 'you must be an admin to create staffs'; + } + return { + returnStatus, + returnSuccess, + returnError, + }; + }, +}; + +export default AuthService; diff --git a/server/v1/services/login.js b/server/v1/services/login.js deleted file mode 100644 index f645676..0000000 --- a/server/v1/services/login.js +++ /dev/null @@ -1,61 +0,0 @@ -import bcrypt from 'bcryptjs'; -import dbConnection from '../config/database'; -import UserModel from '../model/users'; - -const LoginService = { - async loginUser(userData, token) { - const emailRegex = /^([a-zA-Z0-9_\-\.]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,10})$/; - const passwordRegex = /^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{8,}$/; - let returnStatus; let returnSuccess = ''; let returnError = ''; - - // Check if email and password is valid - if (emailRegex.test(userData.email) && passwordRegex.test(userData.password)) { - // check if email, if it exist get the user data - const emailresponse = await dbConnection.dbConnect('SELECT * FROM users WHERE email=$1', [userData.email]); - if (emailresponse.rows.length > 0) { - // Load hash from your password DB. - const passwordUnhash = bcrypt - .compareSync(userData.password, emailresponse.rows[0].password); - if (passwordUnhash) { - // return users details - const user = new UserModel(); - user.id = emailresponse.rows[0].id; - user.firstName = emailresponse.rows[0].firstname; - user.lastName = emailresponse.rows[0].lastname; - user.email = emailresponse.rows[0].email; - user.token = token; - returnStatus = 201; - returnSuccess = user; - } else { - // else echo incorrect password - returnStatus = 422; - returnError = 'incorrect password'; - } - } else { - returnStatus = 404; - returnError = 'email does not exist'; - } - } else { - const error = []; - if (!emailRegex.test(userData.email)) { - returnStatus = 422; - error.push('invalid email address'); - } - - if (!passwordRegex.test(userData.password)) { - returnStatus = 422; - error.push('Password should contain atleast 8 characters, 1 uppercase letter, 1 lowercase letter, 1 number and 1 symbol or character'); - } - returnError = error; - } - - - return { - returnStatus, - returnSuccess, - returnError, - }; - }, -}; - -export default LoginService; diff --git a/server/v1/services/register.js b/server/v1/services/register.js deleted file mode 100644 index e12958e..0000000 --- a/server/v1/services/register.js +++ /dev/null @@ -1,106 +0,0 @@ -/* eslint-disable no-param-reassign */ -import bcrypt from 'bcryptjs'; -import dbConnection from '../config/database'; -import registrationHelper from '../helper/registrationHelper'; -import UserModel from '../model/users'; - -const RegisterService = { - async registerUser(userData, token) { - const returnData = await registrationHelper.registrationHelper(userData); - let returnStatus; let returnSuccess = ''; let returnError = ''; - - // eslint-disable-next-line max-len - if (returnData[0] === true && returnData[1] === true && returnData[2] === true && returnData[3] === true) { - const salt = bcrypt.genSaltSync(10); - const hash = bcrypt.hashSync(userData.password, salt); - userData.type = 'client'; - userData.isAdmin = false; - // checks if email exist - const emailresponse = await dbConnection.dbConnect('SELECT email FROM users WHERE email=$1', [userData.email]); - if (emailresponse.rows.length >= 1) { - returnStatus = 409; - returnError = 'email already exist'; - } else { - // email does not exist... you can insert data - const response = await dbConnection.dbConnect('INSERT into users(email, firstName, lastName, password, type, isAdmin) values($1, $2, $3, $4, $5, $6)', - [userData.email, userData.firstName, userData.lastName, hash, userData.type, userData.isAdmin]); - if (response.command === 'INSERT') { - const userDbData = await dbConnection.dbConnect('SELECT * FROM users WHERE email=$1', [userData.email]); - const user = new UserModel(); - user.id = userDbData.rows[0].id; - user.firstName = userDbData.rows[0].firstname; - user.lastName = userDbData.rows[0].lastname; - user.email = userDbData.rows[0].email; - user.token = token; - returnStatus = 201; - returnSuccess = user; - } else { - returnStatus = 500; - } - } - } else { - returnStatus = 422; - // eslint-disable-next-line prefer-destructuring - returnError = returnData[4]; - } - return { - returnStatus, - returnSuccess, - returnError, - }; - }, - - async createStaffs(userData, token, admin) { - const returnData = await registrationHelper.registrationHelper(userData); - let returnStatus; let returnSuccess = ''; let returnError = ''; - - const userDetails = await dbConnection - .dbConnect('SELECT isadmin FROM users WHERE email=$1', [admin.email]); - const { isadmin } = userDetails.rows[0]; - - if (isadmin === true) { - // eslint-disable-next-line max-len - if (returnData[0] === true && returnData[1] === true && returnData[2] === true && returnData[3] === true) { - const salt = bcrypt.genSaltSync(10); - const hash = bcrypt.hashSync(userData.password, salt); - // checks if email exist - const emailresponse = await dbConnection.dbConnect('SELECT email FROM users WHERE email=$1', [userData.email]); - if (emailresponse.rows.length >= 1) { - returnStatus = 409; - returnError = 'email already exist'; - } else { - // email does not exist... you can insert data - const response = await dbConnection.dbConnect('INSERT into users(email, firstName, lastName, password, type, isAdmin) values($1, $2, $3, $4, $5, $6)', - [userData.email, userData.firstName, userData.lastName, hash, userData.type, userData.isAdmin]); - if (response.command === 'INSERT') { - const userDbData = await dbConnection.dbConnect('SELECT * FROM users WHERE email=$1', [userData.email]); - const user = new UserModel(); - user.id = userDbData.rows[0].id; - user.firstName = userDbData.rows[0].firstname; - user.lastName = userDbData.rows[0].lastname; - user.email = userDbData.rows[0].email; - user.token = token; - returnStatus = 201; - returnSuccess = user; - } else { - returnStatus = 500; - } - } - } else { - returnStatus = 422; - // eslint-disable-next-line prefer-destructuring - returnError = returnData[4]; - } - } else { - returnStatus = 401; - returnError = 'you must be an admin to create staffs'; - } - return { - returnStatus, - returnSuccess, - returnError, - }; - }, -}; - -export default RegisterService; diff --git a/server/v1/services/transaction.js b/server/v1/services/transaction.js index 9d659c0..b82101d 100644 --- a/server/v1/services/transaction.js +++ b/server/v1/services/transaction.js @@ -1,135 +1,182 @@ -/* eslint-disable no-param-reassign */ -import dbConnection from '../config/database'; -import TransactionModel from '../model/Transaction'; - -const TransactionService = { - async debitTransaction(accountNumber, loggedInUser, transactionData) { - let returnStatus; let returnSuccess = ''; let returnError = ''; - - // check the users table - const userDetails = await dbConnection - .dbConnect('SELECT id, type, isadmin FROM users WHERE email=$1', [loggedInUser.email]); - const { id, type, isadmin } = userDetails.rows[0]; - - // checks if logged in user is an admin or staff - if (type === 'staff' || isadmin === true) { - const date = new Date(); - const createdOn = `${date.getDate()}/${date.getMonth() + 1}/${date.getFullYear()}`; - - // pull accountnumber details from database - const accountDbData = await dbConnection - .dbConnect('SELECT accountnumber, balance FROM accounts WHERE accountnumber=$1', [accountNumber]); - const { accountnumber, balance } = accountDbData.rows[0]; - - // check if a string - const checkForDigit = /^-?\d+\.?\d*$/; - if (checkForDigit.test(transactionData.amount)) { - // substract the passed in amount from the current balance - const newBalance = balance - transactionData.amount; - const transactionDbData = await dbConnection - .dbConnect('INSERT into transactions(createdon, type, accountNumber, cashier, amount, oldbalance, newbalance) values($1, $2, $3, $4, $5,$6, $7)', - [createdOn, 'debit', accountnumber, id, transactionData.amount, balance, newBalance]); - if (transactionDbData.command === 'INSERT') { - // get the data from transaction - const accountData = await dbConnection.dbConnect('SELECT * FROM transactions WHERE accountnumber=$1', [accountNumber]); - // update the account table - await dbConnection.dbConnect('UPDATE accounts SET balance=$1 WHERE accountnumber=$2', [newBalance, accountNumber]); - const transaction = new TransactionModel(); - transaction.transactionId = accountData.rows[0].id; - transaction.accountNumber = accountData.rows[0].accountnumber; - transaction.amount = accountData.rows[0].amount; - transaction.cashier = accountData.rows[0].cashier; - transaction.transactionType = accountData.rows[0].type; - transaction.accountBalance = accountData.rows[0].newbalance; - returnStatus = 201; - returnSuccess = transaction; - } else { - returnStatus = 500; - } - } - } else { - returnStatus = 401; - returnError = 'You must be a staff or admin to perform this transaction'; - } - return { - returnStatus, - returnSuccess, - returnError, - }; - }, - - async getSpecificTransaction(transactionId) { - let returnStatus; let returnSuccess = ''; let returnError = ''; - const userTransaction = await dbConnection - .dbConnect('SELECT * from transactions WHERE id=$1', [transactionId]); - if (userTransaction.rows.length > 0) { - returnStatus = 200; - returnSuccess = userTransaction.rows; - } else { - returnStatus = 404; - returnError = 'no transaction found'; - } - return { - returnStatus, - returnSuccess, - returnError, - }; - }, - - async creditTransaction(accountNumber, loggedInUser, transactionData) { - let returnStatus; let returnSuccess = ''; let returnError = ''; - - // check the users table - const userDetails = await dbConnection - .dbConnect('SELECT id, type, isadmin FROM users WHERE email=$1', [loggedInUser.email]); - const { id, type, isadmin } = userDetails.rows[0]; - - // checks if logged in user is an admin or staff - if (type === 'staff' || isadmin === true) { - const date = new Date(); - const createdOn = `${date.getDate()}/${date.getMonth() + 1}/${date.getFullYear()}`; - - // pull accountnumber details from database - const accountDbData = await dbConnection - .dbConnect('SELECT accountnumber, balance FROM accounts WHERE accountnumber=$1', [accountNumber]); - const { accountnumber, balance } = accountDbData.rows[0]; - - // check if a string - const checkForDigit = /^-?\d+\.?\d*$/; - if (checkForDigit.test(transactionData.amount)) { - // add the passed in amount from the current balance - const newBalance = balance + transactionData.amount; - const transactionDbData = await dbConnection - .dbConnect('INSERT into transactions(createdon, type, accountNumber, cashier, amount, oldbalance, newbalance) values($1, $2, $3, $4, $5,$6, $7)', - [createdOn, 'credit', accountnumber, id, transactionData.amount, balance, newBalance]); - if (transactionDbData.command === 'INSERT') { - // get the data from transaction - const accountData = await dbConnection.dbConnect('SELECT * FROM transactions WHERE accountnumber=$1', [accountNumber]); - // update the account table - await dbConnection.dbConnect('UPDATE accounts SET balance=$1 WHERE accountnumber=$2', [newBalance, accountNumber]); - const transaction = new TransactionModel(); - transaction.transactionId = accountData.rows[0].id; - transaction.accountNumber = accountData.rows[0].accountnumber; - transaction.amount = accountData.rows[0].amount; - transaction.cashier = accountData.rows[0].cashier; - transaction.transactionType = accountData.rows[0].type; - transaction.accountBalance = accountData.rows[0].newbalance; - returnStatus = 201; - returnSuccess = transaction; - } else { - returnStatus = 500; - } - } - } else { - returnStatus = 401; - returnError = 'You must be a staff or admin to perform this transaction'; - } - return { - returnStatus, - returnSuccess, - returnError, - }; - }, -}; - -export default TransactionService; +/* eslint-disable no-param-reassign */ +import dbConnection from '../config/database'; +import TransactionModel from '../model/Transaction'; + +const TransactionService = { + + /** + * Debit Transaction + * @constructor + * @param {*} accountNumber - account number. + * @param {*} loggedInUser - logged in user + * @param {*} transactionData - transaction data + */ + async debitTransaction(accountNumber, loggedInUser, transactionData) { + let returnStatus; let returnSuccess = ''; let returnError = ''; + + // check the users table + const userDetails = await dbConnection + .dbConnect('SELECT id, type, isadmin FROM users WHERE email=$1', + [loggedInUser.email]); + const { id, type, isadmin } = userDetails.rows[0]; + + // checks if logged in user is an admin or staff + if (type === 'staff' || isadmin === true) { + const date = new Date(); + const createdOn = `${date.getDate()}/${date.getMonth() + 1}/${date.getFullYear()}`; + + // pull accountnumber details from database + const accountDbData = await dbConnection + .dbConnect( + 'SELECT accountnumber, balance FROM accounts WHERE accountnumber=$1', + [accountNumber] + ); + const { accountnumber, balance } = accountDbData.rows[0]; + + // check if a string + const checkForDigit = /^-?\d+\.?\d*$/; + if (checkForDigit.test(transactionData.amount)) { + // substract the passed in amount from the current balance + const newBalance = balance - transactionData.amount; + + // check if account balance is zero + if (newBalance < 0) { + returnStatus = 422; + returnError = 'Sorry this account is very low and can\'t be debited'; + } else { + const transactionDbData = await dbConnection + .dbConnect('INSERT into transactions(createdon, type, accountNumber, cashier, amount, oldbalance, newbalance) values($1, $2, $3, $4, $5,$6, $7)', + [createdOn, 'debit', accountnumber, id, transactionData.amount, balance, newBalance]); + if (transactionDbData.command === 'INSERT') { + // get the data from transaction + const accountData = await dbConnection + .dbConnect('SELECT * FROM transactions WHERE accountnumber=$1', + [accountNumber]); + // update the account table + const acBalance = await dbConnection + .dbConnect( + 'UPDATE accounts SET balance=$1 WHERE accountnumber=$2 RETURNING balance', + [newBalance, accountNumber] + ); + const transaction = new TransactionModel(); + transaction.transactionId = accountData.rows[0].id; + transaction.accountNumber = accountData.rows[0].accountnumber; + transaction.amount = accountData.rows[0].amount; + transaction.cashier = accountData.rows[0].cashier; + transaction.transactionType = accountData.rows[0].type; + transaction.accountBalance = acBalance.rows[0].balance; + returnStatus = 201; + returnSuccess = transaction; + } + } + } else { + returnStatus = 422; + returnError = 'please numbers only'; + } + } else { + returnStatus = 401; + returnError = 'You must be a staff or admin to perform this transaction'; + } + return { + returnStatus, + returnSuccess, + returnError, + }; + }, + + /** + * Get specific transaction + * @constructor + * @param {*} transactionId - transaction id. + */ + async getSpecificTransaction(transactionId) { + let returnStatus; let returnSuccess = ''; let returnError = ''; + const userTransaction = await dbConnection + .dbConnect('SELECT * from transactions WHERE id=$1', [transactionId]); + if (userTransaction.rows.length > 0) { + returnStatus = 200; + returnSuccess = userTransaction.rows; + } else { + returnStatus = 404; + returnError = 'no transaction found'; + } + return { + returnStatus, + returnSuccess, + returnError, + }; + }, + + /** + * Credit Transaction + * @constructor + * @param {*} accountNumber - account number. + * @param {*} loggedInUser - logged in user + * @param {*} transactionData - transaction data + */ + async creditTransaction(accountNumber, loggedInUser, transactionData) { + let returnStatus; let returnSuccess = ''; let returnError = ''; + + // check the users table + const userDetails = await dbConnection + .dbConnect('SELECT id, type, isadmin FROM users WHERE email=$1', + [loggedInUser.email]); + const { id, type, isadmin } = userDetails.rows[0]; + + // checks if logged in user is an admin or staff + if (type === 'staff' || isadmin === true) { + const date = new Date(); + const createdOn = `${date.getDate()}/${date.getMonth() + 1}/${date.getFullYear()}`; + + // pull accountnumber details from database + const accountDbData = await dbConnection + .dbConnect( + 'SELECT accountnumber, balance FROM accounts WHERE accountnumber=$1', + [accountNumber] + ); + const { accountnumber, balance } = accountDbData.rows[0]; + + // check if a string + const checkForDigit = /^-?\d+\.?\d*$/; + if (checkForDigit.test(transactionData.amount)) { + // add the passed in amount from the current balance + const newBalance = balance + transactionData.amount; + const transactionDbData = await dbConnection + .dbConnect('INSERT into transactions(createdon, type, accountNumber, cashier, amount, oldbalance, newbalance) values($1, $2, $3, $4, $5,$6, $7)', + [createdOn, 'credit', accountnumber, id, transactionData.amount, balance, newBalance]); + if (transactionDbData.command === 'INSERT') { + // get the data from transaction + const accountData = await dbConnection + .dbConnect('SELECT * FROM transactions WHERE accountnumber=$1', + [accountNumber]); + // update the account table + const acBalance = await dbConnection + .dbConnect('UPDATE accounts SET balance=$1 WHERE accountnumber=$2 RETURNING balance', + [newBalance, accountNumber]); + const transaction = new TransactionModel(); + transaction.transactionId = accountData.rows[0].id; + transaction.accountNumber = accountData.rows[0].accountnumber; + transaction.amount = accountData.rows[0].amount; + transaction.cashier = accountData.rows[0].cashier; + transaction.transactionType = accountData.rows[0].type; + transaction.accountBalance = acBalance.rows[0].balance; + returnStatus = 201; + returnSuccess = transaction; + } + } else { + returnStatus = 422; + returnError = 'please numbers only'; + } + } else { + returnStatus = 401; + returnError = 'You must be a staff or admin to perform this transaction'; + } + return { + returnStatus, + returnSuccess, + returnError, + }; + }, +}; + +export default TransactionService; diff --git a/server/v1/services/users.js b/server/v1/services/users.js index af71183..096426f 100644 --- a/server/v1/services/users.js +++ b/server/v1/services/users.js @@ -1,115 +1,130 @@ -import dbConnection from '../config/database'; - -const UsersServices = { - async getAllUsers(staff, queryLimit) { - let returnStatus; let returnSuccess = ''; let returnError = ''; - // check the users table - const userDetails = await dbConnection - .dbConnect('SELECT id, type, isadmin FROM users WHERE email=$1', [staff.email]); - const { type, isadmin } = userDetails.rows[0]; - - if (type === 'staff' || isadmin === true) { - if (typeof queryLimit !== 'undefined') { - const allAccounts = await dbConnection - .dbConnect('SELECT * from users LIMIT $1', [queryLimit]); - returnStatus = 200; - returnSuccess = allAccounts.rows; - } else { - const allAccounts = await dbConnection - .dbConnect('SELECT * from users LIMIT $1', [10]); - returnStatus = 200; - returnSuccess = allAccounts.rows; - } - } else { - returnStatus = 401; - returnError = 'You don\'t have permission to view this page'; - } - return { - returnStatus, - returnSuccess, - returnError, - }; - }, - - async getUsersAccounts(email) { - let returnStatus; let returnSuccess = ''; let returnError = ''; - const allAccounts = await dbConnection - .dbConnect('SELECT email from users WHERE email=$1', [email]); - if (allAccounts.rows.length > 0) { - const accountDbData = await dbConnection - .dbConnect('SELECT * from accounts WHERE email=$1', [email]); - if (accountDbData.rows.length > 0) { - returnStatus = 200; - returnSuccess = accountDbData.rows; - } else { - returnStatus = 404; - returnError = 'no account found for this user'; - } - } else { - returnStatus = 404; - returnError = 'email does not exist'; - } - return { - returnStatus, - returnSuccess, - returnError, - }; - }, - - async deleteUser(id, staff) { - let returnStatus; let returnSuccess = ''; let returnError = ''; - // check the users table - const userDetails = await dbConnection - .dbConnect('SELECT id, type, isadmin FROM users WHERE email=$1', [staff.email]); - const { type, isadmin } = userDetails.rows[0]; - - if (type === 'staff') { - const checkusers = await dbConnection - .dbConnect('SELECT type FROM users WHERE id=$1', [id]); - if (checkusers.rows.length > 0) { - if (checkusers.rows[0].type === 'client') { - const accountDbData = await dbConnection - .dbConnect('DELETE FROM users WHERE id=$1', [id]); - if (accountDbData.command === 'DELETE') { - returnStatus = 204; - returnSuccess = 'Account successfully deleted'; - } else { - returnStatus = 500; - } - } else { - returnStatus = 401; - returnError = 'you must be an admin to delete this staff'; - } - } else { - returnStatus = 404; - returnError = 'no account found'; - } - } else if (isadmin === true) { - const checkusers = await dbConnection - .dbConnect('SELECT type FROM users WHERE id=$1', [id]); - if (checkusers.rows.length > 0) { - const accountDbData = await dbConnection - .dbConnect('DELETE FROM users WHERE id=$1', [id]); - if (accountDbData.command === 'DELETE') { - returnStatus = 204; - returnSuccess = 'Account successfully deleted'; - } else { - returnStatus = 500; - } - } else { - returnStatus = 404; - returnError = 'no account found'; - } - } else { - returnStatus = 401; - returnError = 'You don\'t have permission to view this page'; - } - return { - returnStatus, - returnSuccess, - returnError, - }; - }, -}; - -export default UsersServices; +import dbConnection from '../config/database'; + +const UsersServices = { + /** + * Get all users + * @constructor + * @param {*} staff - get token details to check if staff or admin + * @param {*} queryLimit - Get query parameter + */ + async getAllUsers(staff, queryLimit) { + let returnStatus; let returnSuccess = ''; let returnError = ''; + // check the users table + const userDetails = await dbConnection + .dbConnect('SELECT id, type, isadmin FROM users WHERE email=$1', + [staff.email]); + const { type, isadmin } = userDetails.rows[0]; + + if (type === 'staff' || isadmin === true) { + if (typeof queryLimit !== 'undefined') { + const allAccounts = await dbConnection + .dbConnect('SELECT * from users LIMIT $1', [queryLimit]); + returnStatus = 200; + returnSuccess = allAccounts.rows; + } else { + const allAccounts = await dbConnection + .dbConnect('SELECT * from users LIMIT $1', [10]); + returnStatus = 200; + returnSuccess = allAccounts.rows; + } + } else { + returnStatus = 401; + returnError = 'You don\'t have permission to view this page'; + } + return { + returnStatus, + returnSuccess, + returnError, + }; + }, + + /** + * Get user's accounts by email + * @constructor + * @param {*} email - get user's email + */ + async getUsersAccounts(email) { + let returnStatus; let returnSuccess = ''; let returnError = ''; + const allAccounts = await dbConnection + .dbConnect('SELECT email from users WHERE email=$1', [email]); + if (allAccounts.rows.length > 0) { + const accountDbData = await dbConnection + .dbConnect('SELECT * from accounts WHERE email=$1', [email]); + if (accountDbData.rows.length > 0) { + returnStatus = 200; + returnSuccess = accountDbData.rows; + } else { + returnStatus = 404; + returnError = 'no account found for this user'; + } + } else { + returnStatus = 404; + returnError = 'email does not exist'; + } + return { + returnStatus, + returnSuccess, + returnError, + }; + }, + + /** + * Delete user + * @constructor + * @param {*} id - get user id + * @param {*} staff - get token details to check if staff or admin + */ + async deleteUser(id, staff) { + let returnStatus; let returnSuccess = ''; let returnError = ''; + // check the users table + const userDetails = await dbConnection + .dbConnect('SELECT id, type, isadmin FROM users WHERE email=$1', + [staff.email]); + const { type, isadmin } = userDetails.rows[0]; + + if (type === 'staff') { + const checkusers = await dbConnection + .dbConnect('SELECT type FROM users WHERE id=$1', [id]); + if (checkusers.rows.length > 0) { + if (checkusers.rows[0].type === 'client') { + const accountDbData = await dbConnection + .dbConnect('DELETE FROM users WHERE id=$1', [id]); + if (accountDbData.command === 'DELETE') { + returnStatus = 200; + returnSuccess = 'Account successfully deleted'; + } + } else { + returnStatus = 401; + returnError = 'you must be an admin to delete this staff'; + } + } else { + returnStatus = 404; + returnError = 'no account found'; + } + } else if (isadmin === true) { + const checkusers = await dbConnection + .dbConnect('SELECT type FROM users WHERE id=$1', [id]); + if (checkusers.rows.length > 0) { + const accountDbData = await dbConnection + .dbConnect('DELETE FROM users WHERE id=$1', [id]); + if (accountDbData.command === 'DELETE') { + returnStatus = 200; + returnSuccess = 'Account successfully deleted'; + } + } else { + returnStatus = 404; + returnError = 'no account found'; + } + } else { + returnStatus = 401; + returnError = 'You don\'t have permission to view this page'; + } + return { + returnStatus, + returnSuccess, + returnError, + }; + }, +}; + +export default UsersServices; diff --git a/server/v1/test/accounts.js b/server/v1/test/accounts.js index be5619f..e6904e4 100644 --- a/server/v1/test/accounts.js +++ b/server/v1/test/accounts.js @@ -1,180 +1,493 @@ -/* eslint-disable no-undef */ -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/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).to.have.status(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( - 'should not patch account if not staff or admin', - async () => { - const signinUrl = '/api/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).to.have.status(401); - expect(res1.body.data).to.equal('Sorry you don\'t have permission to perform this task'); - }, - ); - - it( - 'should not delete account if not staff or admin', - async () => { - const signinUrl = '/api/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).to.have.status(401); - expect(res1.body.data).to.equal('Sorry you don\'t have permission to perform this task'); - }, - ); - - it( - 'transaction should have these propertise', - async () => { - const signinUrl = '/api/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).to.have.status(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/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).to.have.status(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/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).to.have.status(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 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/signin.js b/server/v1/test/signin.js index a5ef6a5..cbfe7c6 100644 --- a/server/v1/test/signin.js +++ b/server/v1/test/signin.js @@ -1,104 +1,105 @@ -/* eslint-disable no-undef */ -import chaiHttp from 'chai-http'; -import chai, { expect } from 'chai'; - -import app from '../app'; - -chai.use(chaiHttp); - -describe('Testing User Controller', () => { - describe('Testing signin controller', () => { - const signinUrl = '/api/auth/signin'; - it( - 'should login when all the parameters are given', - async () => { - const response = await chai.request(app) - .post(signinUrl) - .send({ - email: 'banka872@banka4.com', - password: 'passworD4@', - }); - expect(response.body.data).to.be.an('object'); - expect(response).to.have.status(201); - expect(response.body.data).to.have.property('id'); - expect(response.body.data).to.have.property('email'); - expect(response.body.data).to.have.property('firstName'); - expect(response.body.data).to.have.property('lastName'); - expect(response.body.data).to.have.property('token'); - }, - ); - - it( - 'should not signin a user when the email is missing', - async () => { - const response = await chai.request(app) - .post(signinUrl) - .send({ - password: 'passworD4@', - }); - expect(response.body).to.be.an('object'); - expect(response).to.have.status(422); - expect(response.body.data[0]).to.equal('invalid email address'); - }, - ); - - it( - 'should not signin a user when the email does not exist', - async () => { - const response = await chai.request(app) - .post(signinUrl) - .send({ - email: 'banka85576@banka4.com', - password: 'passworD4@', - }); - expect(response.body).to.be.an('object'); - expect(response).to.have.status(404); - expect(response.body.data).to.equal('email does not exist'); - }, - ); - - it( - 'should not login a user when the password is missing', - async () => { - const response = await chai.request(app) - .post(signinUrl) - .send({ - email: 'banka872@banka4.com', - }); - expect(response.body).to.be.an('object'); - expect(response).to.have.status(422); - expect(response.body.data[0]).to.equal('Password should contain atleast 8 characters, 1 uppercase letter, 1 lowercase letter, 1 number and 1 symbol or character'); - }, - ); - - it( - 'should not login a user when the password is incorrect', - async () => { - const response = await chai.request(app) - .post(signinUrl) - .send({ - email: 'banka872@banka4.com', - password: 'passworD4@@', - }); - expect(response.body).to.be.an('object'); - expect(response).to.have.status(422); - expect(response.body.data).to.equal('incorrect password'); - }, - ); - - it( - 'should not register a user when the password do not meet requirement', - async () => { - const response = await chai.request(app) - .post(signinUrl) - .send({ - email: 'banka872@banka4.com', - password: 'passworD4', - }); - expect(response.body).to.be.an('object'); - expect(response).to.have.status(422); - expect(response.body.data[0]).to.equal('Password should contain atleast 8 characters, 1 uppercase letter, 1 lowercase letter, 1 number and 1 symbol or character'); - }, - ); - }); -}); +import chaiHttp from 'chai-http'; +import chai, { expect } from 'chai'; + +import app from '../app'; + +chai.use(chaiHttp); + +describe('Testing User Controller', () => { + describe('Testing signin controller', () => { + const signinUrl = '/api/v1/auth/signin'; + it( + 'should login when all the parameters are given', + async () => { + const response = await chai.request(app) + .post(signinUrl) + .send({ + email: 'banka872@banka4.com', + password: 'passworD4@', + }); + expect(response.body).to.be.an('object'); + expect(response.body.status).to.equal(201); + expect(response.body.data).to.have.property('id'); + expect(response.body.data).to.have.property('email'); + expect(response.body.data).to.have.property('firstName'); + expect(response.body.data).to.have.property('lastName'); + expect(response.body.data).to.have.property('token'); + }, + ); + + it( + 'should not signin a user when the email is missing', + async () => { + const response = await chai.request(app) + .post(signinUrl) + .send({ + password: 'passworD4@', + }); + expect(response.body).to.be.an('object'); + expect(response.body.status).to.equal(422); + expect(response.body.data[0]).to.equal('invalid email address'); + }, + ); + + it( + 'should not signin a user when the email does not exist', + async () => { + const response = await chai.request(app) + .post(signinUrl) + .send({ + email: 'banka85576@banka4.com', + password: 'passworD4@', + }); + expect(response.body).to.be.an('object'); + expect(response.body.status).to.equal(404); + expect(response.body.data).to.equal('email does not exist'); + }, + ); + + it( + 'should not login a user when the password is missing', + async () => { + const response = await chai.request(app) + .post(signinUrl) + .send({ + email: 'banka872@banka4.com', + }); + expect(response.body).to.be.an('object'); + expect(response.body.status).to.equal(422); + expect(response.body.data[0]) + .to.equal('Password should contain atleast 8 characters, 1 uppercase letter, 1 lowercase letter, 1 number and 1 symbol or character'); + }, + ); + + it( + 'should not login a user when the password is incorrect', + async () => { + const response = await chai.request(app) + .post(signinUrl) + .send({ + email: 'banka872@banka4.com', + password: 'passworD4@@', + }); + expect(response.body).to.be.an('object'); + expect(response.body.status).to.equal(422); + expect(response.body.data).to.equal('incorrect password'); + }, + ); + + it( + 'should not register a user when the password do not meet requirement', + async () => { + const response = await chai.request(app) + .post(signinUrl) + .send({ + email: 'banka872@banka4.com', + password: 'passworD4', + }); + expect(response.body).to.be.an('object'); + expect(response.body.status).to.equal(422); + expect(response.body.data[0]) + .to.equal('Password should contain atleast 8 characters, 1 uppercase letter, 1 lowercase letter, 1 number and 1 symbol or character'); + }, + ); + }); +}); diff --git a/server/v1/test/signup.js b/server/v1/test/signup.js index 3ec5839..ac7acb1 100644 --- a/server/v1/test/signup.js +++ b/server/v1/test/signup.js @@ -1,198 +1,280 @@ -/* eslint-disable no-undef */ -import '@babel/polyfill'; -import chaiHttp from 'chai-http'; -import chai, { expect } from 'chai'; -import dbConnection from '../config/database'; - -import app from '../app'; - -chai.use(chaiHttp); - -describe('Testing User Controller', () => { - before(async () => { - await dbConnection.dbTesting('DELETE FROM users'); - await dbConnection - .dbConnect('INSERT into users(email, firstName, lastName, password, type, isAdmin) values($1, $2, $3, $4, $5, $6)', ['staff@banka.com', 'cavdy', 'ikenna', '$2a$10$CmmIst1.D3QjaWuafKbBaOuAFu0r9o7xxQY.0SMKiAN.h9z52a2y2', 'staff', false]); - 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', 'staff', true]); - }); - after(async () => { - await dbConnection.dbConnect('DELETE FROM users WHERE email=$1', ['admin@banka.com']); - }); - describe('Testing signup controller', () => { - const signupUrl = '/api/auth/signup'; - it( - 'should register a new user when all the parameters are given', - async () => { - const response = await chai.request(app) - .post(signupUrl) - .send({ - firstName: 'cavdy', - lastName: 'isaiah', - email: 'banka872@banka4.com', - password: 'passworD4@', - }); - expect(response).to.be.an('object'); - expect(response).to.have.status(201); - expect(response.body.data).to.have.property('id'); - expect(response.body.data).to.have.property('firstName'); - expect(response.body.data).to.have.property('lastName'); - expect(response.body.data).to.have.property('email'); - expect(response.body.data).to.have.property('token'); - }, - ); - - it( - 'should not register a user when the email already exist', - async () => { - const response = await chai.request(app) - .post(signupUrl) - .send({ - firstName: 'cavdy', - lastName: 'isaiah', - email: 'banka872@banka4.com', - password: 'passworD4@', - }); - expect(response).to.be.an('object'); - expect(response).to.have.status(409); - expect(response.body.data).to.equal('email already exist'); - }, - ); - - it( - 'should not register a user when the email is missing', - async () => { - const response = await chai.request(app) - .post(signupUrl) - .send({ - firstName: 'cavdy', - lastName: 'isaiah', - password: 'passworD4@', - }); - expect(response).to.be.an('object'); - expect(response).to.have.status(422); - expect(response.body.data[0]).to.equal('Email is required'); - }, - ); - - it( - 'should not register a user when the first name is missing', - async () => { - const response = await chai.request(app) - .post(signupUrl) - .send({ - lastName: 'isaiah', - email: 'banka873@banka4.com', - password: 'passworD4@', - }); - expect(response).to.be.an('object'); - expect(response).to.have.status(422); - expect(response.body.data[0]).to.equal('Firstname required'); - }, - ); - - it( - 'should not register a user when the last name is missing', - async () => { - const response = await chai.request(app) - .post(signupUrl) - .send({ - firstName: 'cavdy', - email: 'banka873@banka4.com', - password: 'passworD4@', - }); - expect(response).to.be.an('object'); - expect(response).to.have.status(422); - expect(response.body.data[0]).to.equal('Lastname required'); - }, - ); - - it( - 'should not register a user when the password is missing', - async () => { - const response = await chai.request(app) - .post(signupUrl) - .send({ - firstName: 'cavdy', - lastName: 'isaiah', - email: 'banka873@banka4.com', - }); - expect(response).to.be.an('object'); - expect(response).to.have.status(422); - expect(response.body.data[0]).to.equal('Password should contain atleast 8 characters, 1 uppercase letter, 1 lowercase letter, 1 number and 1 symbol or character'); - }, - ); - it( - 'should not register a user when the password do not meet requirement', - async () => { - const response = await chai.request(app) - .post(signupUrl) - .send({ - firstName: 'cavdy', - lastName: 'isaiah', - email: 'banka873@banka4.com', - password: 'passworD4', - }); - expect(response).to.be.an('object'); - expect(response).to.have.status(422); - expect(response.body.data[0]).to.equal('Password should contain atleast 8 characters, 1 uppercase letter, 1 lowercase letter, 1 number and 1 symbol or character'); - }, - ); - - it( - 'only admin can create staffs', - async () => { - const signinUrl = '/api/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/auth/signup/addstaff') - .set('Authorization', `Bearer ${token}`) - .send({ - firstName: 'cavdy', - lastName: 'isaiah', - email: 'staff25@banka.com', - password: 'passworD4@', - }); - expect(res).to.be.an('object'); - expect(res).to.have.status(201); - expect(res.body.data).to.have.property('id'); - expect(res.body.data).to.have.property('firstName'); - expect(res.body.data).to.have.property('lastName'); - expect(res.body.data).to.have.property('email'); - expect(res.body.data).to.have.property('token'); - }, - ); - - it( - 'should not create staff if not admin', - async () => { - const signinUrl = '/api/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/auth/signup/addstaff') - .set('Authorization', `Bearer ${token}`) - .send({ - firstName: 'cavdy', - lastName: 'isaiah', - email: 'staff8@banka.com', - password: 'passworD4@', - }); - expect(res).to.be.an('object'); - expect(res).to.have.status(401); - expect(res.body.data).to.equal('you must be an admin to create staffs'); - }, - ); - }); -}); +import '@babel/polyfill'; +import chaiHttp from 'chai-http'; +import chai, { expect } from 'chai'; +import dbConnection from '../config/database'; + +import app from '../app'; + +chai.use(chaiHttp); + +describe('Testing User Controller', () => { + before(async () => { + await dbConnection.dbTesting('DELETE FROM users'); + await dbConnection + .dbConnect('INSERT into users(email, firstName, lastName, password, type, isAdmin) values($1, $2, $3, $4, $5, $6)', + ['staff@banka.com', 'cavdy', 'ikenna', '$2a$10$CmmIst1.D3QjaWuafKbBaOuAFu0r9o7xxQY.0SMKiAN.h9z52a2y2', 'staff', false]); + 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]); + await dbConnection + .dbConnect('INSERT into users(email, firstName, lastName, password, type, isAdmin) values($1, $2, $3, $4, $5, $6)', + ['deleteguy@banka.com', 'cavdy', 'ikenna', '$2a$10$CmmIst1.D3QjaWuafKbBaOuAFu0r9o7xxQY.0SMKiAN.h9z52a2y2', 'staff', true]); + await dbConnection + .dbConnect('INSERT into users(email, firstName, lastName, password, type, isAdmin) values($1, $2, $3, $4, $5, $6)', + ['deleteguy2@banka.com', 'cavdy', 'ikenna', '$2a$10$CmmIst1.D3QjaWuafKbBaOuAFu0r9o7xxQY.0SMKiAN.h9z52a2y2', 'client', true]); + }); + after(async () => { + await dbConnection + .dbConnect('DELETE FROM users WHERE email=$1', ['admin@banka.com']); + }); + describe('Testing signup controller', () => { + const signupUrl = '/api/v1/auth/signup'; + it( + 'should register a new user when all the parameters are given', + async () => { + const response = await chai.request(app) + .post(signupUrl) + .send({ + firstName: 'cavdy', + lastName: 'isaiah', + email: 'banka872@banka4.com', + password: 'passworD4@', + }); + expect(response).to.be.an('object'); + expect(response).to.have.status(201); + expect(response.body.data).to.have.property('id'); + expect(response.body.data).to.have.property('firstName'); + expect(response.body.data).to.have.property('lastName'); + expect(response.body.data).to.have.property('email'); + expect(response.body.data).to.have.property('token'); + }, + ); + + it( + 'should not register a user when the email already exist', + async () => { + const response = await chai.request(app) + .post(signupUrl) + .send({ + firstName: 'cavdy', + lastName: 'isaiah', + email: 'banka872@banka4.com', + password: 'passworD4@', + }); + expect(response).to.be.an('object'); + expect(response).to.have.status(409); + expect(response.body.data).to.equal('email already exist'); + }, + ); + + it( + 'should not create a staff when the email already 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) + .post('/api/v1/auth/signup/addstaff') + .set('Authorization', `Bearer ${token}`) + .send({ + firstName: 'cavdy', + lastName: 'isaiah', + email: 'banka872@banka4.com', + password: 'passworD4@', + type: 'staff', + isAdmin: false, + }); + expect(res).to.be.an('object'); + expect(res.body.status).to.equal(409); + expect(res.body.data).to.equal('email already exist'); + }, + ); + + it( + 'should not register when all fields are missing', + async () => { + const response = await chai.request(app) + .post(signupUrl) + .send(); + expect(response).to.be.an('object'); + expect(response).to.have.status(422); + expect(response.body.data[0]).to.equal('Email is required'); + expect(response.body.data[1]).to.equal('Firstname required'); + expect(response.body.data[2]).to.equal('Lastname required'); + expect(response.body.data[3]) + .to.equal('Password should contain atleast 8 characters, 1 uppercase letter, 1 lowercase letter, 1 number and 1 symbol or character'); + }, + ); + + it( + 'should not create staff when all fields are missing', + 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/auth/signup/addstaff') + .set('Authorization', `Bearer ${token}`) + .send({ + type: 'staff', + isAdmin: false, + }); + expect(res).to.be.an('object'); + expect(res.body.status).to.equal(422); + expect(res.body.data[0]).to.equal('Email is required'); + expect(res.body.data[1]).to.equal('Firstname required'); + expect(res.body.data[2]).to.equal('Lastname required'); + expect(res.body.data[3]) + .to.equal('Password should contain atleast 8 characters, 1 uppercase letter, 1 lowercase letter, 1 number and 1 symbol or character'); + }, + ); + + it( + 'should not register a user when the email is missing', + async () => { + const response = await chai.request(app) + .post(signupUrl) + .send({ + firstName: 'cavdy', + lastName: 'isaiah', + password: 'passworD4@', + }); + expect(response).to.be.an('object'); + expect(response).to.have.status(422); + expect(response.body.data[0]).to.equal('Email is required'); + }, + ); + + it( + 'should not register a user when the first name is missing', + async () => { + const response = await chai.request(app) + .post(signupUrl) + .send({ + lastName: 'isaiah', + email: 'banka873@banka4.com', + password: 'passworD4@', + }); + expect(response).to.be.an('object'); + expect(response).to.have.status(422); + expect(response.body.data[0]).to.equal('Firstname required'); + }, + ); + + it( + 'should not register a user when the last name is missing', + async () => { + const response = await chai.request(app) + .post(signupUrl) + .send({ + firstName: 'cavdy', + email: 'banka873@banka4.com', + password: 'passworD4@', + }); + expect(response).to.be.an('object'); + expect(response).to.have.status(422); + expect(response.body.data[0]).to.equal('Lastname required'); + }, + ); + + it( + 'should not register a user when the password is missing', + async () => { + const response = await chai.request(app) + .post(signupUrl) + .send({ + firstName: 'cavdy', + lastName: 'isaiah', + email: 'banka873@banka4.com', + }); + expect(response).to.be.an('object'); + expect(response).to.have.status(422); + expect(response.body.data[0]) + .to.equal('Password should contain atleast 8 characters, 1 uppercase letter, 1 lowercase letter, 1 number and 1 symbol or character'); + }, + ); + it( + 'should not register a user when the password do not meet requirement', + async () => { + const response = await chai.request(app) + .post(signupUrl) + .send({ + firstName: 'cavdy', + lastName: 'isaiah', + email: 'banka873@banka4.com', + password: 'passworD4', + }); + expect(response).to.be.an('object'); + expect(response).to.have.status(422); + expect(response.body.data[0]) + .to.equal('Password should contain atleast 8 characters, 1 uppercase letter, 1 lowercase letter, 1 number and 1 symbol or character'); + }, + ); + + it( + 'only admin can create staffs', + 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/auth/signup/addstaff') + .set('Authorization', `Bearer ${token}`) + .send({ + firstName: 'cavdy', + lastName: 'isaiah', + email: 'staff25@banka.com', + password: 'passworD4@', + }); + expect(res).to.be.an('object'); + expect(res).to.have.status(201); + expect(res.body.data).to.have.property('id'); + expect(res.body.data).to.have.property('firstName'); + expect(res.body.data).to.have.property('lastName'); + expect(res.body.data).to.have.property('email'); + expect(res.body.data).to.have.property('token'); + }, + ); + + it( + 'should not create staff if not 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/auth/signup/addstaff') + .set('Authorization', `Bearer ${token}`) + .send({ + firstName: 'cavdy', + lastName: 'isaiah', + email: 'staff8@banka.com', + password: 'passworD4@', + }); + expect(res).to.be.an('object'); + expect(res).to.have.status(401); + expect(res.body.data).to.equal('you must be an admin to create staffs'); + }, + ); + }); +}); diff --git a/server/v1/test/tests.js b/server/v1/test/tests.js index b81e147..67ccbd6 100644 --- a/server/v1/test/tests.js +++ b/server/v1/test/tests.js @@ -1,5 +1,26 @@ -import './accounts'; -import './signin'; -import './transactions'; -import './users'; -import './signup'; +import './accounts'; +import './signin'; +import './transactions'; +import './users'; +import './signup'; + +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 res = await chai.request(app) + .get('/') + .send(); + expect(res.text).to.equal('welcome to Banka API'); + }, + ); + }); +}); diff --git a/server/v1/test/transactions.js b/server/v1/test/transactions.js index d331009..95cb59f 100644 --- a/server/v1/test/transactions.js +++ b/server/v1/test/transactions.js @@ -1,113 +1,287 @@ -/* eslint-disable no-undef */ -import chaiHttp from 'chai-http'; -import chai, { expect } from 'chai'; - -import app from '../app'; - -chai.use(chaiHttp); - -describe('Testing Transactions Controller', () => { - describe('Testing transactions controller', () => { - it( - 'transactions should have all required propertise', - async () => { - const signinUrl = '/api/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/transactions/3003801983/debit') - .set('Authorization', `Bearer ${token}`) - .send({ - amount: 500, - }); - expect(res.body).to.be.an('object'); - expect(res).to.have.status(201); - expect(res.body.data).to.have.property('transactionId'); - expect(res.body.data).to.have.property('accountNumber'); - expect(res.body.data).to.have.property('cashier'); - expect(res.body.data).to.have.property('amount'); - expect(res.body.data).to.have.property('transactionType'); - expect(res.body.data).to.have.property('accountBalance'); - }, - ); - - it( - 'only admin and staffs should perform debit transaction', - async () => { - const signinUrl = '/api/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/transactions/3003801983/debit') - .set('Authorization', `Bearer ${token}`) - .send({ - amount: 500, - }); - expect(res.body).to.be.an('object'); - expect(res).to.have.status(401); - expect(res.body.data).to.equal('You must be a staff or admin to perform this transaction'); - }, - ); - - it( - 'transaction should have these propertise', - async () => { - const signinUrl = '/api/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/transactions/4') - .set('Authorization', `Bearer ${token}`) - .send(); - expect(res.body).to.be.an('object'); - expect(res).to.have.status(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( - 'only admin and staffs should perform credit transaction', - async () => { - const signinUrl = '/api/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/transactions/3003801983/credit') - .set('Authorization', `Bearer ${token}`) - .send({ - amount: 500, - }); - expect(res.body).to.be.an('object'); - expect(res).to.have.status(401); - expect(res.body.data).to.equal('You must be a staff or admin to perform this transaction'); - }, - ); - }); -}); +import chaiHttp from 'chai-http'; +import chai, { expect } from 'chai'; + +import app from '../app'; + +chai.use(chaiHttp); + +describe('Testing Transactions Controller', () => { + describe('Testing transactions controller', () => { + it( + 'transactions should have all required 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) + .post('/api/v1/transactions/3003801983/credit') + .set('Authorization', `Bearer ${token}`) + .send({ + amount: 500, + }); + expect(res.body).to.be.an('object'); + expect(res.body.status).to.equal(201); + expect(res.body.data).to.have.property('transactionId'); + expect(res.body.data).to.have.property('accountNumber'); + expect(res.body.data).to.have.property('cashier'); + expect(res.body.data).to.have.property('amount'); + expect(res.body.data).to.have.property('transactionType'); + expect(res.body.data).to.have.property('accountBalance'); + }, + ); + + it( + 'only admin and staffs should perform debit 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) + .post('/api/v1/transactions/3003801983/credit') + .set('Authorization', `Bearer ${token}`) + .send({ + amount: 1000, + }); + expect(res.body).to.be.an('object'); + expect(res.body.status).to.equal(401); + expect(res.body.data) + .to.equal('You must be a staff or admin to perform this transaction'); + }, + ); + + it( + 'should not perform debit transaction when on zero balance', + 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/transactions/3404704124/debit') + .set('Authorization', `Bearer ${token}`) + .send({ + amount: 500, + }); + expect(res.body).to.be.an('object'); + expect(res.body.status).to.equal(422); + expect(res.body.data) + .to.equal('Sorry this account is very low and can\'t be debited'); + }, + ); + + it( + 'admin and staff can debit account', + 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/transactions/3003801983/debit') + .set('Authorization', `Bearer ${token}`) + .send({ + amount: 500, + }); + expect(res.body).to.be.an('object'); + expect(res.body.status).to.equal(201); + expect(res.body.data).to.have.property('transactionId'); + expect(res.body.data).to.have.property('accountNumber'); + expect(res.body.data).to.have.property('amount'); + expect(res.body.data).to.have.property('cashier'); + expect(res.body.data).to.have.property('transactionType'); + expect(res.body.data).to.have.property('accountBalance'); + }, + ); + + 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/transactions/4') + .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( + 'only admin and staffs should perform credit 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) + .post('/api/v1/transactions/3003801983/credit') + .set('Authorization', `Bearer ${token}`) + .send({ + amount: 500, + }); + expect(res.body).to.be.an('object'); + expect(res.body.status).to.equal(401); + expect(res.body.data) + .to.equal('You must be a staff or admin to perform this transaction'); + }, + ); + + it( + 'only admin and staffs should perform debit 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) + .post('/api/v1/transactions/3003801983/debit') + .set('Authorization', `Bearer ${token}`) + .send({ + amount: 500, + }); + expect(res.body).to.be.an('object'); + expect(res.body.status).to.equal(401); + expect(res.body.data) + .to.equal('You must be a staff or admin to perform this transaction'); + }, + ); + + it( + 'should not debit when not number', + 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/transactions/3003801983/debit') + .set('Authorization', `Bearer ${token}`) + .send({ + amount: 'fffff', + }); + expect(res.body).to.be.an('object'); + expect(res.body.status).to.equal(422); + expect(res.body.data) + .to.equal('please numbers only'); + }, + ); + + it( + 'should not credit when not number', + 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/transactions/3003801983/credit') + .set('Authorization', `Bearer ${token}`) + .send({ + amount: 'fffff', + }); + expect(res.body).to.be.an('object'); + expect(res.body.status).to.equal(422); + expect(res.body.data) + .to.equal('please numbers only'); + }, + ); + + it( + 'admin and staffs can perform credit transaction', + 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/transactions/3003801983/credit') + .set('Authorization', `Bearer ${token}`) + .send({ + amount: 500, + }); + expect(res.body).to.be.an('object'); + expect(res.body.status).to.equal(201); + expect(res.body.data).to.have.property('transactionId'); + expect(res.body.data).to.have.property('accountNumber'); + expect(res.body.data).to.have.property('amount'); + expect(res.body.data).to.have.property('cashier'); + expect(res.body.data).to.have.property('transactionType'); + expect(res.body.data).to.have.property('accountBalance'); + }, + ); + + it( + 'check if transaction id 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) + .get('/api/v1/transactions/6000') + .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'); + }, + ); + }); +}); diff --git a/server/v1/test/users.js b/server/v1/test/users.js index 72948ff..9a6cb6a 100644 --- a/server/v1/test/users.js +++ b/server/v1/test/users.js @@ -1,101 +1,348 @@ -/* eslint-disable no-undef */ -import chaiHttp from 'chai-http'; -import chai, { expect } from 'chai'; - -import app from '../app'; - -chai.use(chaiHttp); - -describe('Testing All Users Controller', () => { - describe('Testing all accounts controller', () => { - it( - 'users should have all required details', - async () => { - const signinUrl = '/api/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/users') - .set('Authorization', `Bearer ${token}`) - .send(); - expect(res.body).to.be.an('object'); - expect(res).to.have.status(200); - expect(res.body.data[0]).to.have.property('id'); - 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('email'); - expect(res.body.data[0]).to.have.property('password'); - expect(res.body.data[0]).to.have.property('type'); - expect(res.body.data[0]).to.have.property('isadmin'); - }, - ); - - it( - 'should not see all users if not admin or staff', - async () => { - const signinUrl = '/api/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/users') - .set('Authorization', `Bearer ${token}`) - .send(); - expect(res.body).to.be.an('object'); - expect(res).to.have.status(401); - expect(res.body.data).to.equal('You don\'t have permission to view this page'); - }, - ); - - it( - 'only staffs and admin can delete users', - async () => { - const signinUrl = '/api/auth/signin'; - const response = await chai.request(app) - .post(signinUrl) - .send({ - email: 'banka872@banka4.com', - password: 'passworD4@', - }); - const { id, token } = response.body.data; - const res = await chai.request(app) - .delete(`/api/v1/users/${id}`) - .set('Authorization', `Bearer ${token}`) - .send(); - expect(res.body).to.be.an('object'); - expect(res).to.have.status(401); - expect(res.body.data).to.equal('You don\'t have permission to view this page'); - }, - ); - - it( - 'only admin can delete any users', - async () => { - const signinUrl = '/api/auth/signin'; - const response = await chai.request(app) - .post(signinUrl) - .send({ - email: 'staff@banka.com', - password: 'passworD4@', - }); - const { id, token } = response.body.data; - const res = await chai.request(app) - .delete(`/api/v1/users/${id}`) - .set('Authorization', `Bearer ${token}`) - .send(); - expect(res.body).to.be.an('object'); - expect(res).to.have.status(401); - expect(res.body.data).to.equal('you must be an admin to delete this staff'); - }, - ); - }); -}); +import chaiHttp from 'chai-http'; +import chai, { expect } from 'chai'; + +import app from '../app'; + +chai.use(chaiHttp); + +describe('Testing All Users Controller', () => { + describe('Testing all accounts controller', () => { + it( + 'users should have all required details', + 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/users') + .set('Authorization', `Bearer ${token}`) + .send(); + expect(res.body).to.be.an('object'); + expect(res).to.have.status(200); + expect(res.body.data[0]).to.have.property('id'); + 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('email'); + expect(res.body.data[0]).to.have.property('password'); + expect(res.body.data[0]).to.have.property('type'); + expect(res.body.data[0]).to.have.property('isadmin'); + }, + ); + + it( + 'when limit query is passed', + 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/users?limit=10') + .set('Authorization', `Bearer ${token}`) + .send(); + expect(res.body).to.be.an('object'); + expect(res).to.have.status(200); + expect(res.body.data[0]).to.have.property('id'); + 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('email'); + expect(res.body.data[0]).to.have.property('password'); + expect(res.body.data[0]).to.have.property('type'); + expect(res.body.data[0]).to.have.property('isadmin'); + }, + ); + + it( + 'check if email 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) + .get('/api/v1/users/banka872@ban.com/accounts') + .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('email does not exist'); + }, + ); + + it( + 'only admin or staff to see all users', + 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/users') + .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('You don\'t have permission to view this page'); + }, + ); + + it( + 'check if email does not have a bank account', + 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/users/deleteguy2@banka.com/accounts') + .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 for this user'); + }, + ); + + it( + 'get users account by email', + 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/users') + .set('Authorization', `Bearer ${token}`) + .send(); + expect(res.body).to.be.an('object'); + expect(res).to.have.status(200); + expect(res.body.data[0]).to.have.property('id'); + 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('email'); + expect(res.body.data[0]).to.have.property('password'); + expect(res.body.data[0]).to.have.property('type'); + expect(res.body.data[0]).to.have.property('isadmin'); + }, + ); + + it( + 'if no token was passed', + async () => { + const res = await chai.request(app) + .get('/api/v1/users') + .send(); + expect(res).to.have.status(403); + }, + ); + + it( + 'if wrong token was passed', + async () => { + const res = await chai.request(app) + .get('/api/v1/users') + .set('Authorization', 'Bearer ujhhs88s88s8888') + .send(); + expect(res.status).to.equal(403); + }, + ); + + it( + 'should not see all users if not admin or staff', + 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/users/banka872@banka4.com/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( + 'only staffs and admin can delete users', + async () => { + const signinUrl = '/api/v1/auth/signin'; + const response = await chai.request(app) + .post(signinUrl) + .send({ + email: 'banka872@banka4.com', + password: 'passworD4@', + }); + const { id, token } = response.body.data; + const res = await chai.request(app) + .delete(`/api/v1/users/${id}`) + .set('Authorization', `Bearer ${token}`) + .send(); + expect(res.body).to.be.an('object'); + expect(res).to.have.status(401); + expect(res.body.data) + .to.equal('You don\'t have permission to view this page'); + }, + ); + + it( + 'only admin can delete any users', + async () => { + const signinUrl = '/api/v1/auth/signin'; + const response = await chai.request(app) + .post(signinUrl) + .send({ + email: 'staff@banka.com', + password: 'passworD4@', + }); + const { id, token } = response.body.data; + const res = await chai.request(app) + .delete(`/api/v1/users/${id}`) + .set('Authorization', `Bearer ${token}`) + .send(); + expect(res.body).to.be.an('object'); + expect(res).to.have.status(401); + expect(res.body.data) + .to.equal('you must be an admin to delete this staff'); + }, + ); + + it( + 'only admin can delete all users', + async () => { + const signinUrl = '/api/v1/auth/signin'; + const response = await chai.request(app) + .post(signinUrl) + .send({ + email: 'admin@banka.com', + password: 'passworD4@', + }); + const res = await chai.request(app) + .post(signinUrl) + .send({ + email: 'deleteguy@banka.com', + password: 'passworD4@', + }); + const { token } = response.body.data; + const { id } = res.body.data; + const res1 = await chai.request(app) + .delete(`/api/v1/users/${id}`) + .set('Authorization', `Bearer ${token}`) + .send(); + expect(res1.body).to.be.an('object'); + expect(res1.body.status).to.equal(200); + expect(res1.body.data).to.equal('Account successfully deleted'); + }, + ); + + it( + 'staffs can delete all users that is not a staff or admin', + async () => { + const signinUrl = '/api/v1/auth/signin'; + const response = await chai.request(app) + .post(signinUrl) + .send({ + email: 'staff@banka.com', + password: 'passworD4@', + }); + const res = await chai.request(app) + .post(signinUrl) + .send({ + email: 'deleteguy2@banka.com', + password: 'passworD4@', + }); + const { token } = response.body.data; + const { id } = res.body.data; + const res1 = await chai.request(app) + .delete(`/api/v1/users/${id}`) + .set('Authorization', `Bearer ${token}`) + .send(); + expect(res1.body).to.be.an('object'); + expect(res1.body.status).to.equal(200); + expect(res1.body.data).to.equal('Account successfully deleted'); + }, + ); + + it( + 'check if user does not exist as an 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) + .delete('/api/v1/users/6000') + .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( + 'check if user does not exist as a staff', + async () => { + const signinUrl = '/api/v1/auth/signin'; + const response = await chai.request(app) + .post(signinUrl) + .send({ + email: 'staff@banka.com', + password: 'passworD4@', + }); + const { token } = response.body.data; + const res = await chai.request(app) + .delete('/api/v1/users/6000') + .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'); + }, + ); + }); +});