diff --git a/server/v1/controllers/accounts.js b/server/v1/controllers/accounts.js index fee96db..322a448 100644 --- a/server/v1/controllers/accounts.js +++ b/server/v1/controllers/accounts.js @@ -52,7 +52,7 @@ const CreateAccountController = { async specificAccounts(req, res) { const { accountNumber } = req.params; const specificAccounts = await AccountsService - .specificAccounts(accountNumber); + .specificAccounts(accountNumber, req.authorizedData); const data = await statusHelper .statusHelper(req, @@ -72,7 +72,7 @@ const CreateAccountController = { async allAccountTransaction(req, res) { const { accountNumber } = req.params; const transactionHistory = await AccountsService - .allAccountTransaction(accountNumber); + .allAccountTransaction(accountNumber, req.authorizedData); const data = await statusHelper .statusHelper(req, diff --git a/server/v1/controllers/auth.js b/server/v1/controllers/auth.js index c369c49..c11aead 100644 --- a/server/v1/controllers/auth.js +++ b/server/v1/controllers/auth.js @@ -40,26 +40,6 @@ const AuthController = { 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/users.js b/server/v1/controllers/users.js index 060f123..3759b49 100644 --- a/server/v1/controllers/users.js +++ b/server/v1/controllers/users.js @@ -59,6 +59,26 @@ const UsersController = { deleteUser.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 UserService + .createStaffs(userData, req.signintoken, req.authorizedData); + + const data = await statusHelper + .statusHelper(req, + res, + createdStaff.returnStatus, + createdStaff.returnError, + createdStaff.returnSuccess); + return data; + }, }; export default UsersController; diff --git a/server/v1/routes/auth.js b/server/v1/routes/auth.js index b307ebc..56093f7 100644 --- a/server/v1/routes/auth.js +++ b/server/v1/routes/auth.js @@ -7,10 +7,5 @@ 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/users.js b/server/v1/routes/users.js index 3a137a5..aaf9817 100644 --- a/server/v1/routes/users.js +++ b/server/v1/routes/users.js @@ -10,5 +10,10 @@ router.get('/:email/accounts', jwtMiddleware.verifyJwt, UsersController.getUsersAccounts); router.delete('/:id', jwtMiddleware.verifyJwt, UsersController.deleteUser); +router.post('/addstaff', + jwtMiddleware.checkToken, + jwtMiddleware.signinJwt, + jwtMiddleware.verifyJwt, + UsersController.createStaffs); export default router; diff --git a/server/v1/services/accounts.js b/server/v1/services/accounts.js index 5e31f4a..c575770 100644 --- a/server/v1/services/accounts.js +++ b/server/v1/services/accounts.js @@ -113,20 +113,38 @@ const CreateAccountService = { * Get specific account * @constructor * @param {*} accountNumber - recieve account number. + * @param {*} loggedIn - logged in details. */ - async specificAccounts(accountNumber) { + async specificAccounts(accountNumber, loggedIn) { let returnStatus; let returnSuccess = ''; let returnError = ''; + + const users = await dbConnection + .dbConnect('SELECT * from users WHERE email=$1', + [loggedIn.email]); + const { type, isadmin } = users.rows[0]; + 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]; + if (userAccount.rows[0].email === loggedIn.email) { + returnStatus = 200; + // eslint-disable-next-line prefer-destructuring + returnSuccess = userAccount.rows[0]; + } else if (type === 'staff' || isadmin === true) { + returnStatus = 200; + // eslint-disable-next-line prefer-destructuring + returnSuccess = userAccount.rows[0]; + } else { + returnStatus = 401; + returnError = 'sorry you can\'t view another user\'s account'; + } } else { returnStatus = 404; returnError = 'no account found'; } + return { returnStatus, returnSuccess, @@ -138,19 +156,42 @@ const CreateAccountService = { * Get all accounts trasactions that belongs to account number * @constructor * @param {*} accountNumber - recieve account number. + * @param {*} loggedIn - logged in details. */ - async allAccountTransaction(accountNumber) { + async allAccountTransaction(accountNumber, loggedIn) { let returnStatus; let returnSuccess = ''; let returnError = ''; + + const users = await dbConnection + .dbConnect('SELECT * from users WHERE email=$1', + [loggedIn.email]); + const { type, isadmin } = users.rows[0]; + const userTransaction = await dbConnection .dbConnect('SELECT * from transactions WHERE accountnumber=$1', [accountNumber]); + + const userAccount = await dbConnection + .dbConnect('SELECT email from accounts WHERE accountnumber=$1', + [accountNumber]); + if (userTransaction.rows.length > 0) { - returnStatus = 200; - returnSuccess = userTransaction.rows; + if (userAccount.rows[0].email === loggedIn.email) { + returnStatus = 200; + // eslint-disable-next-line prefer-destructuring + returnSuccess = userTransaction.rows; + } else if (type === 'staff' || isadmin === true) { + returnStatus = 200; + // eslint-disable-next-line prefer-destructuring + returnSuccess = userTransaction.rows; + } else { + returnStatus = 401; + returnError = 'sorry you can\'t view another user\'s transactions'; + } } else { returnStatus = 404; returnError = 'no transaction found'; } + return { returnStatus, returnSuccess, diff --git a/server/v1/services/auth.js b/server/v1/services/auth.js index 9af66d8..4c28fed 100644 --- a/server/v1/services/auth.js +++ b/server/v1/services/auth.js @@ -147,70 +147,6 @@ const AuthService = { 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/users.js b/server/v1/services/users.js index 47858dd..affaf17 100644 --- a/server/v1/services/users.js +++ b/server/v1/services/users.js @@ -1,4 +1,7 @@ +import bcrypt from 'bcryptjs'; import dbConnection from '../config/database'; +import UserModel from '../model/users'; +import registrationHelper from '../helper/registrationHelper'; const UsersServices = { /** @@ -125,6 +128,67 @@ const UsersServices = { 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) RETURNING id, firstname, lastname, email', + [userData.email, userData.firstName, userData.lastName, hash, userData.type, userData.isAdmin]); + if (response.command === 'INSERT') { + const user = new UserModel(); + user.id = response.rows[0].id; + user.firstName = response.rows[0].firstname; + user.lastName = response.rows[0].lastname; + user.email = response.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 UsersServices; diff --git a/server/v1/test/accounts.js b/server/v1/test/accounts.js index 9e6b1de..c152e95 100644 --- a/server/v1/test/accounts.js +++ b/server/v1/test/accounts.js @@ -36,6 +36,43 @@ describe('Testing Accounts Controller', () => { }, ); + it( + 'user can view their 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) + .post('/api/v1/accounts') + .set('Authorization', `Bearer ${token}`) + .send({ + type: 'savings', + }); + const { accountNumber } = res.body.data; + const res1 = await chai.request(app) + .get(`/api/v1/accounts/${accountNumber}`) + .set('Authorization', `Bearer ${token}`) + .send(); + expect(res1.body).to.be.an('object'); + expect(res1.body.status).to.equal(200); + expect(res1.body.data).to.have.property('id'); + expect(res1.body.data).to.have.property('email'); + expect(res1.body.data).to.have.property('firstname'); + expect(res1.body.data).to.have.property('lastname'); + expect(res1.body.data).to.have.property('accountnumber'); + expect(res1.body.data).to.have.property('createdon'); + expect(res1.body.data).to.have.property('owner'); + expect(res1.body.data).to.have.property('type'); + expect(res1.body.data).to.have.property('status'); + expect(res1.body.data).to.have.property('balance'); + }, + ); + it( 'admin or staff should see all accounts', async () => { @@ -250,6 +287,64 @@ describe('Testing Accounts Controller', () => { }, ); + it( + 'admin or staff should get any specific 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/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( + 'admin or staff should get any specific account transactions', + 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/${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( 'when account does not have transaction', async () => { @@ -272,7 +367,7 @@ describe('Testing Accounts Controller', () => { ); it( - 'when specific account does not have transaction', + 'when account does not have transaction', async () => { const signinUrl = '/api/v1/auth/signin'; const response = await chai.request(app) @@ -283,7 +378,72 @@ describe('Testing Accounts Controller', () => { }); const { token } = response.body.data; const res = await chai.request(app) - .get(`/api/v1/accounts/${314685979881}`) + .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 permission', + async () => { + const signinUrl = '/api/v1/auth/signin'; + const response = await chai.request(app) + .post(signinUrl) + .send({ + email: 'deleteguy3@banka.com', + password: 'passworD4@', + }); + const { token } = response.body.data; + const res = await chai.request(app) + .get(`/api/v1/accounts/${3146859791}`) + .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 can\'t view another user\'s account'); + }, + ); + + it( + 'when specific account transaction does not have permission', + async () => { + const signinUrl = '/api/v1/auth/signin'; + const response = await chai.request(app) + .post(signinUrl) + .send({ + email: 'deleteguy3@banka.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(401); + expect(res.body.data) + .to.equal('sorry you can\'t view another user\'s transactions'); + }, + ); + + 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: 'admin@banka.com', + password: 'passworD4@', + }); + const { token } = response.body.data; + const res = await chai.request(app) + .get(`/api/v1/accounts/${314685979133}`) .set('Authorization', `Bearer ${token}`) .send(); expect(res.body).to.be.an('object'); diff --git a/server/v1/test/signup.js b/server/v1/test/signup.js index cff88ac..31c7657 100644 --- a/server/v1/test/signup.js +++ b/server/v1/test/signup.js @@ -25,6 +25,9 @@ describe('Testing User Controller', () => { 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]); + await dbConnection + .dbConnect('INSERT into users(email, firstName, lastName, password, type, isAdmin) values($1, $2, $3, $4, $5, $6)', + ['deleteguy3@banka.com', 'cavdy', 'ikenna', '$2a$10$CmmIst1.D3QjaWuafKbBaOuAFu0r9o7xxQY.0SMKiAN.h9z52a2y2', 'client', false]); }); describe('Testing signup controller', () => { const signupUrl = '/api/v1/auth/signup'; @@ -78,7 +81,7 @@ describe('Testing User Controller', () => { }); const { token } = response.body.data; const res = await chai.request(app) - .post('/api/v1/auth/signup/addstaff') + .post('/api/v1/users/addstaff') .set('Authorization', `Bearer ${token}`) .send({ firstName: 'cavdy', @@ -122,7 +125,7 @@ describe('Testing User Controller', () => { }); const { token } = response.body.data; const res = await chai.request(app) - .post('/api/v1/auth/signup/addstaff') + .post('/api/v1/users/addstaff') .set('Authorization', `Bearer ${token}`) .send({ type: 'staff', @@ -232,7 +235,7 @@ describe('Testing User Controller', () => { }); const { token } = response.body.data; const res = await chai.request(app) - .post('/api/v1/auth/signup/addstaff') + .post('/api/v1/users/addstaff') .set('Authorization', `Bearer ${token}`) .send({ firstName: 'cavdy', @@ -262,7 +265,7 @@ describe('Testing User Controller', () => { }); const { token } = response.body.data; const res = await chai.request(app) - .post('/api/v1/auth/signup/addstaff') + .post('/api/v1/users/addstaff') .set('Authorization', `Bearer ${token}`) .send({ firstName: 'cavdy',