Skip to content

Commit 90279b9

Browse files
ManethKulatungetygobogo
authored andcommitted
Feature/153 accept hacker by email (#620)
* Route created * Middleware made for the route * Tests(need to be edited) * Edited route * status email middleware made * Edited tests * Fixed issues with referenced accounts * edited service used for obtaining hacker email * Comment changed for parseAcceptEmail * edited route description
1 parent f8b975f commit 90279b9

4 files changed

Lines changed: 213 additions & 0 deletions

File tree

constants/routes.constant.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,10 @@ const hackerRoutes = {
128128
requestType: Constants.REQUEST_TYPES.PATCH,
129129
uri: "/api/hacker/accept/" + Constants.ROLE_CATEGORIES.ALL,
130130
},
131+
patchAcceptHackerByEmail: {
132+
requestType: Constants.REQUEST_TYPES.PATCH,
133+
uri: "/api/hacker/acceptEmail/" + Constants.ROLE_CATEGORIES.ALL,
134+
},
131135
postAnySendWeekOfEmail: {
132136
requestType: Constants.REQUEST_TYPES.POST,
133137
uri: "/api/hacker/email/weekOf/" + Constants.ROLE_CATEGORIES.ALL

middlewares/hacker.middleware.js

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,40 @@ async function sendStatusUpdateEmail(req, res, next) {
328328
}
329329
}
330330

331+
/**
332+
* Sends a preset email to a user if a status change occured with email params.
333+
* @param {{body: {status?: string}, params: {email: string}}} req
334+
* @param {*} res
335+
* @param {(err?:*)=>void} next
336+
*/
337+
async function completeStatusUpdateEmail(req, res, next) {
338+
//skip if the status doesn't exist
339+
if (!req.body.hacker.status) {
340+
return next();
341+
} else {
342+
// send it to the hacker that is being updated.
343+
const hacker = await Services.Hacker.findById(req.body.hacker._id);
344+
const account = await Services.Account.findById(hacker.accountId);
345+
if (!hacker) {
346+
return next({
347+
status: 404,
348+
message: Constants.Error.HACKER_404_MESSAGE
349+
});
350+
} else if (!account) {
351+
return next({
352+
status: 500,
353+
message: Constants.Error.GENERIC_500_MESSAGE
354+
});
355+
}
356+
Services.Email.sendStatusUpdate(
357+
account.firstName,
358+
account.email,
359+
req.body.hacker.status,
360+
next
361+
);
362+
}
363+
}
364+
331365
/**
332366
* Sends an email telling the user that they have applied. This is used exclusively when we POST a hacker.
333367
* @param {{body: {hacker: {accountId: string}}}} req
@@ -523,6 +557,40 @@ async function updateHacker(req, res, next) {
523557
}
524558
}
525559

560+
/**
561+
* Updates a hacker that is specified by req.body.hacker._id, and then sets req.email
562+
* to the email of the hacker, found in Account.
563+
* @param {{params:{_id: string}, body: *}} req
564+
* @param {*} res
565+
* @param {*} next
566+
*/
567+
async function obtainEmailByHackerId(req, res, next) {
568+
const hacker = await Services.Hacker.findById(req.body.hacker._id);
569+
if (hacker) {
570+
const acct = await Services.Account.findById(hacker.accountId);
571+
if (!acct) {
572+
return next({
573+
status: 500,
574+
message: Constants.Error.HACKER_UPDATE_500_MESSAGE,
575+
data: {
576+
hackerId: hacker.id,
577+
accountId: hacker.accountId
578+
}
579+
});
580+
}
581+
req.email = acct.email;
582+
return next();
583+
} else {
584+
return next({
585+
status: 404,
586+
message: Constants.Error.HACKER_404_MESSAGE,
587+
data: {
588+
id: req.params.id
589+
}
590+
});
591+
}
592+
}
593+
526594
/**
527595
* Sets req.body.status to Accepted for next middleware.
528596
* @param {{params:{id: string}, body: *}} req
@@ -531,6 +599,19 @@ async function updateHacker(req, res, next) {
531599
*/
532600
function parseAccept(req, res, next) {
533601
req.body.status = Constants.General.HACKER_STATUS_ACCEPTED;
602+
req.hackerId = req.params.id;
603+
next();
604+
}
605+
606+
/**
607+
* Sets req.body.hacker.status to Accepted for next middleware.
608+
* @param {{params:{email: string}, body: *}} req
609+
* @param {*} res
610+
* @param {*} next
611+
*/
612+
function parseAcceptEmail(req, res, next) {
613+
req.body.hacker.status = Constants.General.HACKER_STATUS_ACCEPTED;
614+
req.hackerId = req.body.hacker._id;
534615
next();
535616
}
536617

@@ -652,7 +733,9 @@ module.exports = {
652733
sendAppliedStatusEmail
653734
),
654735
updateHacker: Middleware.Util.asyncMiddleware(updateHacker),
736+
obtainEmailByHackerId: Middleware.Util.asyncMiddleware(obtainEmailByHackerId),
655737
parseAccept: parseAccept,
738+
parseAcceptEmail: parseAcceptEmail,
656739
validateConfirmedStatusFromAccountId: Middleware.Util.asyncMiddleware(
657740
validateConfirmedStatusFromAccountId
658741
),
@@ -662,6 +745,9 @@ module.exports = {
662745
validateConfirmedStatusFromObject: Middleware.Util.asyncMiddleware(
663746
validateConfirmedStatusFromObject
664747
),
748+
completeStatusUpdateEmail: Middleware.Util.asyncMiddleware(
749+
completeStatusUpdateEmail
750+
),
665751
checkDuplicateAccountLinks: Middleware.Util.asyncMiddleware(
666752
checkDuplicateAccountLinks
667753
),

routes/api/hacker.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,37 @@ module.exports = {
307307
Middleware.Hacker.sendStatusUpdateEmail,
308308
Controllers.Hacker.updatedHacker
309309
);
310+
311+
/**
312+
* @api {patch} /hacker/acceptEmail/:email accept a Hacker by email
313+
* @apiName acceptHacker
314+
* @apiGroup Hacker
315+
* @apiVersion 2.0.0
316+
*
317+
* @apiSuccess {string} message Success message
318+
* @apiSuccess {object} data Hacker object
319+
* @apiSuccessExample {object} Success-Response:
320+
* {
321+
* "message": "Changed hacker information",
322+
* "data": {
323+
* "status": "Accepted"
324+
* }
325+
* }
326+
* @apiPermission Administrator
327+
*/
328+
hackerRouter
329+
.route("/acceptEmail/:email")
330+
.patch(
331+
Middleware.Auth.ensureAuthenticated(),
332+
Middleware.Auth.ensureAuthorized([Services.Hacker.findByEmail]),
333+
Middleware.Validator.RouteParam.emailValidator,
334+
Middleware.parseBody.middleware,
335+
Middleware.Hacker.findByEmail,
336+
Middleware.Hacker.parseAcceptEmail,
337+
Middleware.Hacker.obtainEmailByHackerId,
338+
Middleware.Hacker.completeStatusUpdateEmail,
339+
Controllers.Hacker.updatedHacker
340+
);
310341

311342
/**
312343
* @api {patch} /hacker/checkin/:id update a hacker's status to be 'Checked-in'. Note that the Hacker must eitehr be Accepted or Confirmed.

tests/hacker.test.js

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ const volunteerAccount0 = util.account.volunteerAccounts.stored[0];
2828

2929
const newHackerAccount0 = util.account.hackerAccounts.new[0];
3030
const newHacker0 = util.hacker.newHacker0;
31+
const invalidHackerAccount0 = util.account.hackerAccounts.invalid;
3132
const invalidHacker0 = util.hacker.invalidHacker0;
3233
const invalidHacker2 = util.hacker.invalidHacker2;
3334
const newHacker1 = util.hacker.newHacker1;
@@ -638,6 +639,7 @@ describe("PATCH update one hacker", function() {
638639
});
639640
});
640641

642+
//should FAIL on authentication
641643
it("should FAIL to accept a hacker on /api/hacker/accept/:id due to authentication", function(done) {
642644
chai.request(server.app)
643645
.patch(`/api/hacker/accept/${TeamHacker0._id}`)
@@ -730,6 +732,96 @@ describe("PATCH update one hacker", function() {
730732
});
731733
});
732734

735+
it("should FAIL to accept a hacker on /api/hacker/acceptEmail/:email due to authentication", function(done) {
736+
chai.request(server.app)
737+
.patch(`/api/hacker/acceptEmail/${teamHackerAccount0.email}`)
738+
.type("application/json")
739+
.send()
740+
.end(function(err, res) {
741+
res.should.have.status(401);
742+
res.should.be.json;
743+
res.body.should.have.property("message");
744+
res.body.message.should.equal(Constants.Error.AUTH_401_MESSAGE);
745+
done();
746+
});
747+
});
748+
749+
// should FAIL due to authorization
750+
it("should FAIL to accept hacker info due to lack of authorization on /api/hacker/acceptEmail/:email", function(done) {
751+
util.auth.login(agent, noTeamHackerAccount0, (error) => {
752+
if (error) {
753+
agent.close();
754+
return done(error);
755+
}
756+
return agent
757+
.patch(`/api/hacker/acceptEmail/${teamHackerAccount0.email}`)
758+
.type("application/json")
759+
.send()
760+
.end(function(err, res) {
761+
res.should.have.status(403);
762+
res.should.be.json;
763+
res.body.should.have.property("message");
764+
res.body.message.should.equal(
765+
Constants.Error.AUTH_403_MESSAGE
766+
);
767+
res.body.should.have.property("data");
768+
769+
done();
770+
});
771+
});
772+
});
773+
774+
it("should FAIL to accept an invalid hacker's info on /api/hacker/acceptEmail/:email", function(done) {
775+
util.auth.login(agent, Admin0, (error) => {
776+
if (error) {
777+
agent.close();
778+
return done(error);
779+
}
780+
return agent
781+
.patch(`/api/hacker/acceptEmail/${invalidHackerAccount0[0].email}`)
782+
.type("application/json")
783+
.send()
784+
.end(function(err, res) {
785+
res.should.have.status(404);
786+
res.should.be.json;
787+
res.body.should.have.property("message");
788+
res.body.message.should.equal(
789+
Constants.Error.ACCOUNT_404_MESSAGE
790+
);
791+
res.body.should.have.property("data");
792+
793+
done();
794+
});
795+
});
796+
});
797+
798+
it("should SUCCEED and accept a hacker on /api/hacker/acceptEmail/:email as an Admin", function(done) {
799+
util.auth.login(agent, Admin0, (error) => {
800+
if (error) {
801+
agent.close();
802+
return done(error);
803+
}
804+
return agent
805+
.patch(`/api/hacker/acceptEmail/${teamHackerAccount0.email}`)
806+
.type("application/json")
807+
.send()
808+
.end(function(err, res) {
809+
res.should.have.status(200);
810+
res.should.be.json;
811+
res.body.should.have.property("message");
812+
res.body.message.should.equal(
813+
Constants.Success.HACKER_UPDATE
814+
);
815+
res.body.should.have.property("data");
816+
chai.assert.equal(
817+
res.body.data.hacker.status,
818+
"Accepted"
819+
);
820+
done();
821+
});
822+
});
823+
});
824+
733825
// should succeed on admin case
734826
it("should SUCCEED and update a hacker using admin power", function(done) {
735827
util.auth.login(agent, Admin0, (error) => {

0 commit comments

Comments
 (0)