Skip to content

Commit

Permalink
Merge branch 'master' into prevent-double-submit
Browse files Browse the repository at this point in the history
  • Loading branch information
quansenB committed Sep 19, 2019
2 parents eda279c + 3de0eab commit 0b1840f
Show file tree
Hide file tree
Showing 10 changed files with 189 additions and 11 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
**[Production Deployment](https://t-ndo.herokuapp.com)** <br/>
**[Staging Deployment](https://tndo-temp-staging.herokuapp.com/)**

[![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/128f9cfdf87dd2eb709d)
[![Run in Postman](https://run.pstmn.io/button.svg)](https://app.getpostman.com/run-collection/e0398fa3da81ee0a9ce2)

## Getting started

Expand Down Expand Up @@ -68,7 +68,7 @@ JWT_SECRET=<generated string>

## Endpoints

**[View API Reference Here](https://documenter.getpostman.com/view/8821479/SVmtzfpW?version=latest)**
**[View API Reference Here]https://documenter.getpostman.com/view/6785535/SVmvUeeT?version=latest**

# Data Model

Expand Down
27 changes: 25 additions & 2 deletions controllers/changeRequest/approveChangeRequest.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const { models } = require('../../models');
const { createError, GENERIC_ERROR } = require('../../helpers/error.js');
const { createError, GENERIC_ERROR, FORBIDDEN } = require('../../helpers/error.js');
const convertToDotNotationObject = require('../farmer/convertToDotNotationObject');

/**
Expand All @@ -15,16 +15,39 @@ const approveChangeRequest = async (req, res, next) => {
const changeRequestEntry = await models.ChangeRequest.findOne({
_id: req.params.id
});

if (changeRequestEntry) {
const convertedObject = convertToDotNotationObject(
changeRequestEntry.requested_changes
);

const farmer = await models.Farmer.findOne({ _id: changeRequestEntry.farmer_id }).lean();

if (!farmer) {
return next(
createError({
message: 'Farmer does not exist',
status: NOT_FOUND
})
);
}

if(farmer.archived){
await models.ChangeRequest.findOneAndRemove({ _id: req.params.id });
return next({
message: 'This Farmer is archived and can not be updated',
status: FORBIDDEN
})
}

await models.Farmer.findOneAndUpdate(
{ _id: changeRequestEntry.farmer_id },
convertedObject,
{ new: true, runValidators: true }
);

await models.ChangeRequest.findOneAndRemove({ _id: req.params.id });

return res.status(200).json({
success: true,
message: 'ChangeRequest approved',
Expand All @@ -34,7 +57,7 @@ const approveChangeRequest = async (req, res, next) => {
return res.status(404).json({
success: false,
message:
'There is no saved changeRequest with this ID, please subit a valid changeRequest-ID'
'There is no saved changeRequest with this ID, please submit a valid changeRequest-ID'
});
} catch (err) {
return next(
Expand Down
5 changes: 5 additions & 0 deletions controllers/farmer/statistics.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ const statistics = async (req, res, next) => {
(farmer) => farmer.personalInfo.gender.toLowerCase() === 'male'
).length;

const totalNumOfOtherFarmers = allFarmers.filter(
(farmer) => farmer.personalInfo.gender.toLowerCase() === 'others'
).length;

const farmersAgeGreaterThanOrEqualThirtyFive = allFarmers.filter(
(farmer) => calculateAge(farmer.personalInfo.date_of_birth) >= 35
).length;
Expand All @@ -35,6 +39,7 @@ const statistics = async (req, res, next) => {
totalNumOfFarmers,
totalNumOfMaleFarmers,
totalNumOfFemaleFarmers,
totalNumOfOtherFarmers,
farmersAgeGreaterThanOrEqualThirtyFive,
farmersAgeLesserThanThirtyFive
};
Expand Down
10 changes: 9 additions & 1 deletion controllers/farmer/updateFarmer.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ const convertToDotNotationObject = require('./convertToDotNotationObject');
const {
createError,
GENERIC_ERROR,
NOT_FOUND,
FORBIDDEN,
NOT_FOUND
} = require('../../helpers/error');

/**
Expand All @@ -29,6 +30,13 @@ const updateFarmer = async (req, res, next) => {
);
}

if(farmer.archived){
return next({
message: 'This Farmer is archived and can not be updated',
status: FORBIDDEN
})
}

if (isAdmin) {
const convertedObject = convertToDotNotationObject(farmerDetails);
const updatedFarmer = await models.Farmer.findOneAndUpdate(
Expand Down
9 changes: 6 additions & 3 deletions controllers/user/login.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,17 @@ const {
*/
const login = async (req, res, next) => {
try {
const { username, password } = req.body;

let { username } = req.body;
const { password } = req.body;
username = username.toLowerCase();
const userExist = await models.User.findOne({ username });

if (userExist) {
const compare = bcrypt.compareSync(password, userExist.password);

const user = await models.User.findOne({ username }).select(['-password']);
const user = await models.User.findOne({ username }).select([
'-password'
]);

if (compare) {
const token = await generateToken(userExist);
Expand Down
1 change: 1 addition & 0 deletions controllers/user/register.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const register = async (req, res, next) => {
const salt = bcrypt.genSaltSync(10);

userDetails.password = bcrypt.hashSync(userDetails.password, salt);
userDetails.username = userDetails.username.toLowerCase();

const newUser = await models.User.create(userDetails);
// convert Mongoose model to plain JS object to remove pw
Expand Down
42 changes: 42 additions & 0 deletions tests/changeRequest.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -139,4 +139,46 @@ describe('Request change route', () => {
done(err);
});
});

it('It creates a changerequest if farmer is updated by staff. Copy of test to have a changerequest in DB', (done) => {
chai
.request(server)
.patch(`/api/v1/farmers/${idCreatedByStaff}/update`)
.set('Authorization', staffToken)
.send({ personalInfo: { title : 'Chief' } })
.end(async (err, res) => {
res.should.have.status(201);
res.body.message.should.equal(
'Your change was created and is ready for admin approval'
);
const changeRequests = await models.ChangeRequest.find();
chai.expect(changeRequests).to.have.lengthOf(1);
changeRequestId = changeRequests[0]._id;
done(err);
});
});

it('It sets the farmer to archived, necessary for next test', (done) => {
chai
.request(server)
.delete(`/api/v1/farmers/${idCreatedByStaff}/delete`)
.set('Authorization', token)
.end((err, res) => {
res.should.have.status(200);
res.body.message.should.equal('Farmer details deleted successfully');
done(err);
});
});

it('It does not accept an update of an archived farmer details', (done) => {
chai
.request(server)
.post(`/api/v1/change-requests/${changeRequestId}/approve`)
.set('Authorization', token)
.end((err, res) => {
res.should.have.status(403);
res.body.message.should.equal('This Farmer is archived and can not be updated');
done(err);
});
});
});
80 changes: 80 additions & 0 deletions tests/farmers.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,33 @@ describe('Farmer route', () => {
done(err);
});
});
it('It does not update archived farmer details when done by admin', (done) => {
farmerInput.personalInfo.title = 'Chief';
chai
.request(server)
.patch(`/api/v1/farmers/${id}/update`)
.set('Authorization', token)
.send(farmerInput)
.end((err, res) => {
res.should.have.status(403);
res.body.message.should.equal('This Farmer is archived and can not be updated');
done(err);
});
});
it('It does not update archived farmer details if done by staff', (done) => {
farmerInput.personalInfo.title = 'Chief';

chai
.request(server)
.patch(`/api/v1/farmers/${idCreatedByStaff}/update`)
.set('Authorization', staffToken)
.send(farmerInput)
.end((err, res) => {
res.should.have.status(403);
res.body.message.should.equal('This Farmer is archived and can not be updated');
done(err);
});
});
it('It should return 404 if there are no farmers in the DB', (done) => {
chai
.request(server)
Expand Down Expand Up @@ -176,6 +203,59 @@ describe('Farmer route', () => {
});
});

it('It should 200 on GET farmer statistics', (done) => {
chai
.request(server)
.get('/api/v1/farmers/statistic')
.set('Authorization', token)
.end((err, res) => {
res.should.have.status(200);
done(err);
});
});

it('It should return num of M/F/O farmers that add up to total number of farmers', (done) => {
chai
.request(server)
.get('/api/v1/farmers/statistic')
.set('Authorization', token)
.end((err, res) => {
const {
totalNumOfFarmers,
totalNumOfMaleFarmers,
totalNumOfFemaleFarmers,
totalNumOfOtherFarmers
} = res.body;

totalNumOfFarmers.should.equal(
totalNumOfMaleFarmers
+ totalNumOfFemaleFarmers
+ totalNumOfOtherFarmers
);
done(err);
});
});

it('It should return num of <35/>35 y/o farmers that add up to total number of farmers', (done) => {
chai
.request(server)
.get('/api/v1/farmers/statistic')
.set('Authorization', token)
.end((err, res) => {
const {
totalNumOfFarmers,
farmersAgeGreaterThanOrEqualThirtyFive,
farmersAgeLesserThanThirtyFive
} = res.body;

totalNumOfFarmers.should.equal(
farmersAgeGreaterThanOrEqualThirtyFive
+ farmersAgeLesserThanThirtyFive
);
done(err);
});
});

it('It should return 400 bad request and "Not a valid ID" message on bad farmer ID', (done) => {
chai
.request(server)
Expand Down
6 changes: 3 additions & 3 deletions tests/testsSetup.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ const { models, connectDB } = require('../models');

const password = '123456';
const hashedPw = bcrypt.hashSync(password, 10);
const adminUsername = 'Admin';
const staffUsername = 'Staff';
const adminUsername = 'admin';
const staffUsername = 'staff';
const adminUser = {
username: adminUsername,
password: hashedPw,
Expand All @@ -17,7 +17,7 @@ const staffUser = {
};

const staffUser2 = {
username: 'Staff2',
username: 'staff2',
password: hashedPw
};

Expand Down
16 changes: 16 additions & 0 deletions tests/users.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,4 +111,20 @@ describe('Users route [user/signup]', () => {
done(err);
});
});

it('should return normalize username on add new user', (done) => {
const capitalUsername = seeds.staffUser2;
capitalUsername.username = 'BIGuserNAME';
chai
.request(server)
.post('/api/v1/user/signup')
.set('authorization', token)
.send(capitalUsername)
.end((err, res) => {
res.body.user.username.should.equal(
capitalUsername.username.toLowerCase()
);
done(err);
});
});
});

0 comments on commit 0b1840f

Please sign in to comment.