Skip to content

Commit b135286

Browse files
author
Harsh Patel
committed
Finished email
1 parent d8b634a commit b135286

File tree

9 files changed

+200
-102
lines changed

9 files changed

+200
-102
lines changed

constants/routes.constant.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -215,9 +215,13 @@ const searchRoutes = {
215215
requestType: Constants.REQUEST_TYPES.GET,
216216
uri: "/api/search/"
217217
},
218-
"bactchAction": {
218+
"updateStatus": {
219219
requestType: Constants.REQUEST_TYPES.GET,
220-
uri: "/api/search/action",
220+
uri: "/api/search/updateStatus",
221+
},
222+
"sendEmails": {
223+
requestType: Constants.REQUEST_TYPES.GET,
224+
uri: "/api/search/sendEmails",
221225
},
222226
};
223227

constants/success.constant.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ const HACKER_GET_BY_ID = "Hacker found by id.";
2121
const HACKER_READ = "Hacker retrieval successful.";
2222
const HACKER_CREATE = "Hacker creation successful.";
2323
const HACKER_UPDATE = "Hacker update successful.";
24+
const HACKER_UPDATE_EMAILS = "Hacker update emails sent."
2425
const HACKER_SENT_WEEK_OF = "Hacker week-of email sent."
2526

2627
const RESUME_UPLOAD = "Resume upload successful.";
@@ -67,6 +68,7 @@ module.exports = {
6768
HACKER_READ: HACKER_READ,
6869
HACKER_CREATE: HACKER_CREATE,
6970
HACKER_UPDATE: HACKER_UPDATE,
71+
HACKER_UPDATE_EMAILS: HACKER_UPDATE_EMAILS,
7072

7173
HACKER_SENT_WEEK_OF: HACKER_SENT_WEEK_OF,
7274

controllers/search.controller.js

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ const Services = {
55
};
66
const Util = require("../middlewares/util.middleware");
77
const Success = require("../constants/success.constant");
8+
const ErrorMessages = require("../constants/error.constant")
89

910
async function searchResults(req, res) {
1011
let results = req.body.results;
@@ -21,6 +22,22 @@ async function searchResults(req, res) {
2122
});
2223
}
2324

25+
async function emailResults(req, res) {
26+
let results = req.body.results;
27+
let message;
28+
if (results == undefined) {
29+
message = Success.HACKER_UPDATE_EMAILS;
30+
results = {}
31+
} else {
32+
message = ErrorMessages.EMAIL_500_MESSAGE;
33+
}
34+
return res.status(200).json({
35+
message: message,
36+
data: results
37+
});
38+
}
39+
2440
module.exports = {
25-
searchResults: Util.asyncMiddleware(searchResults)
41+
searchResults: Util.asyncMiddleware(searchResults),
42+
emailResults: Util.asyncMiddleware(emailResults)
2643
};

middlewares/search.middleware.js

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ const Services = {
55
const Middleware = {
66
Util: require("../middlewares/util.middleware")
77
}
8-
const Constants = require("../../constants/general.constant");
98

109
/**
1110
* @function parseQuery
@@ -71,9 +70,28 @@ async function executeQuery(req, res, next) {
7170
* @returns
7271
*/
7372
async function executeStatusAction(req, res, next) {
74-
// NOW HAVE req.body.results as an array of "hackers potentially"
75-
console.log("GETS IN EXECUTE STATUS ACTION BRO!")
76-
req.body.results = await Services.Search.executeAction(req.body.model,
73+
req.body.results = await Services.Search.executeStatusAction(req.body.model,
74+
req.body.q,
75+
req.body.page,
76+
req.body.limit,
77+
req.body.sort,
78+
req.body.sort_by,
79+
req.body.expand,
80+
req.body.update
81+
);
82+
return next();
83+
}
84+
85+
/**
86+
*
87+
* @param {} req
88+
* @param {*} res
89+
* @param {*} next
90+
*
91+
* @returns
92+
*/
93+
async function executeEmailAction(req, res, next) {
94+
req.body.results = await Services.Search.executeEmailAction(req.body.model,
7795
req.body.q,
7896
req.body.page,
7997
req.body.limit,
@@ -95,5 +113,6 @@ module.exports = {
95113
parseQuery: parseQuery,
96114
executeQuery: Middleware.Util.asyncMiddleware(executeQuery),
97115
executeStatusAction: Middleware.Util.asyncMiddleware(executeStatusAction),
116+
executeEmailAction: Middleware.Util.asyncMiddleware(executeEmailAction),
98117
setExpandTrue: setExpandTrue,
99118
};

middlewares/validators/search.validator.js

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,24 @@ module.exports = {
1111
VALIDATOR.booleanValidator("query", "expand", true),
1212
VALIDATOR.searchValidator("query", "q")
1313
],
14-
searchActionValidator: [
14+
statusValidator: [
1515
VALIDATOR.searchModelValidator("query", "model", false),
1616
VALIDATOR.alphaValidator("query", "sort", true),
1717
VALIDATOR.integerValidator("query", "page", true, 0),
1818
VALIDATOR.integerValidator("query", "limit", true, 0, 1000),
1919
VALIDATOR.searchSortValidator("query", "sort_by"),
2020
VALIDATOR.booleanValidator("query", "expand", true),
2121
VALIDATOR.searchValidator("query", "q"),
22-
/* ACTION VALIDATOR NEED TO MAKE WORK! */
23-
VALIDATOR.actionValidator("query", "action"),
24-
VALIDATOR.statusValidator("query", "status")
22+
VALIDATOR.updateObjectValidator("query", "update")
2523
],
24+
emailValidator: [
25+
VALIDATOR.searchModelValidator("query", "model", false),
26+
VALIDATOR.alphaValidator("query", "sort", true),
27+
VALIDATOR.integerValidator("query", "page", true, 0),
28+
VALIDATOR.integerValidator("query", "limit", true, 0, 1000),
29+
VALIDATOR.searchSortValidator("query", "sort_by"),
30+
VALIDATOR.booleanValidator("query", "expand", true),
31+
VALIDATOR.searchValidator("query", "q"),
32+
VALIDATOR.statusValidator("query", "status")
33+
]
2634
};

middlewares/validators/validator.helper.js

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -566,12 +566,43 @@ function actionValidator(fieldLocation, actionFieldName) {
566566
}
567567

568568

569+
/**
570+
* Validates that action field is a valid action from constants passed, and checks if corresponding new status is valid.
571+
* @param {"query" | "body" | "header" | "param"} fieldLocation The location where the field should be found.
572+
* @param {string} actionFieldName The name of the action that needs to be performed.
573+
* @param {string} statusFieldName The name of the action that needs to be performed.
574+
*/
575+
function updateObjectValidator(fieldLocation, actionFieldName) {
576+
const updateObjectValue = setProperValidationChainBuilder(fieldLocation, actionFieldName, "Invalid update object string.");
577+
578+
return updateObjectValue.exists()
579+
.withMessage("The update object string must exist.")
580+
.custom(updateObjectValidatorHelper).withMessage("The value must be a valid update object.");
581+
}
582+
583+
function updateObjectValidatorHelper(update) {
584+
try {
585+
var updateObject = JSON.parse(update);
586+
587+
if (updateObject && typeof updateObject === "object" && !("password" in updateObject)) {
588+
for (var key in updateObject) {
589+
var schemaPath = Models.Hacker.searchableField(key);
590+
if (!schemaPath) return false;
591+
}
592+
return true;
593+
}
594+
}
595+
catch (e) {
596+
return false;
597+
}
598+
}
599+
569600
function statusValidator(fieldLocation, statusFieldName) {
570601
const statusValue = setProperValidationChainBuilder(fieldLocation, statusFieldName, "Invalid status.");
571602
return statusValue.exists().withMessage("The status must exist!").custom((val, {
572603
req
573604
}) => {
574-
return Constants.CORRESPONDING_STATUSES[req.query.action].includes(val);
605+
return Constants.HACKER_STATUSES.includes(val);
575606
}).withMessage("The value must be a proper status.")
576607
}
577608

@@ -647,5 +678,6 @@ module.exports = {
647678
enumValidator: enumValidator,
648679
routesValidator: routesValidator,
649680
actionValidator: actionValidator,
650-
statusValidator: statusValidator
681+
statusValidator: statusValidator,
682+
updateObjectValidator: updateObjectValidator,
651683
};

routes/api/search.js

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ module.exports = {
6868
);
6969

7070
/**
71-
* @api {get} /search/action execute an action on a specific query for any defined model
71+
* @api {get} /search/updateStatus execute an action on a specific query for any defined model
7272
* @apiName search
7373
* @apiGroup Search
7474
* @apiVersion 0.0.8
@@ -81,8 +81,7 @@ module.exports = {
8181
* @apiParam (query) {number} limit the maximum number of results that you would like returned
8282
* @apiParam (query) {any} sort_by any parameter you want to sort the results by
8383
* @apiParam (query) {boolean} expand whether you want to expand sub documents within the results
84-
* @apiParam (query) {String} action type of action either Status or Email
85-
* @apiParam (query) {String} status new status or type of email
84+
* @apiParam (query) {String} update new status or type of email
8685
*
8786
* @apiSuccess {String} message Success message
8887
* @apiSuccess {Object} data Results
@@ -107,16 +106,26 @@ module.exports = {
107106
* @apiErrorExample {object} Error-Response:
108107
* {"message": "Validation failed", "data": {}}
109108
*/
110-
searchRouter.route("/action").get(
109+
searchRouter.route("/updateStatus").get(
111110
Middleware.Auth.ensureAuthenticated(),
112111
Middleware.Auth.ensureAuthorized(),
113-
Middleware.Validator.Search.searchActionValidator,
112+
Middleware.Validator.Search.statusValidator,
114113
Middleware.parseBody.middleware,
115114
Middleware.Search.parseQuery,
116115
Middleware.Search.executeStatusAction,
117116
Controllers.Search.searchResults
118117
);
119118

119+
searchRouter.route("/sendEmails").get(
120+
Middleware.Auth.ensureAuthenticated(),
121+
Middleware.Auth.ensureAuthorized(),
122+
Middleware.Validator.Search.emailValidator,
123+
Middleware.parseBody.middleware,
124+
Middleware.Search.parseQuery,
125+
Middleware.Search.executeEmailAction,
126+
Controllers.Search.emailResults
127+
);
128+
120129
apiRouter.use("/search", searchRouter);
121130
}
122131
};

services/email.service.js

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class EmailService {
1818
* @param {*} mailData
1919
* @param {(err?)=>void} callback
2020
*/
21-
send(mailData, callback = () => {}) {
21+
send(mailData, callback = () => { }) {
2222
if (env.isTest()) {
2323
//Silence all actual emails if we're testing
2424
mailData.mailSettings = {
@@ -41,7 +41,7 @@ class EmailService {
4141
* @param {*} mailData
4242
* @param {(err?)=>void} callback
4343
*/
44-
sendMultiple(mailData, callback = () => {}) {
44+
sendMultiple(mailData, callback = () => { }) {
4545
return client.sendMultiple(mailData, (error) => {
4646
if (error) {
4747
logger.error(`${TAG} ` + JSON.stringify(error));
@@ -100,6 +100,27 @@ class EmailService {
100100
}
101101
}, callback);
102102
}
103+
104+
async sendStatusUpdateAsync(firstName, recipient, status) {
105+
const handlebarsPath = path.join(__dirname, `../assets/email/statusEmail/${status}.hbs`);
106+
const mailData = {
107+
to: recipient,
108+
from: process.env.NO_REPLY_EMAIL,
109+
subject: Constants.EMAIL_SUBJECTS[status],
110+
html: this.renderEmail(handlebarsPath, {
111+
firstName: firstName
112+
})
113+
};
114+
return this.send(mailData).then(
115+
(response) => {
116+
if (response[0].statusCode >= 200 && response[0].statusCode < 300) {
117+
return undefined;
118+
} else {
119+
return response[0];
120+
}
121+
});
122+
}
123+
103124
/**
104125
* Generates the HTML from the handlebars template file found at the given path.
105126
* @param {string} path the absolute path to the handlebars template file

0 commit comments

Comments
 (0)