Skip to content

Commit 441c78e

Browse files
Changed emails templates and link from application validation expiration time
Co-authored-by: Daniel Ferreira <dsantosferreira@users.noreply.github.com>
1 parent 0bd0830 commit 441c78e

File tree

12 files changed

+45
-52
lines changed

12 files changed

+45
-52
lines changed

.env

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ JWT_SECRET=Lendas contam que o Rui foi membro do IEEE.
2020
# Frontend Password Recovery Base Route
2121
PASSWORD_RECOVERY_LINK=https://localhost:3000/recover
2222

23-
# Froantend Application Confirmation Base Route
24-
APPLICATION_CONFIRMATION_LINK=https://localhost:8087/apply/company/validate/
23+
# Frontend Application Confirmation Base Route
24+
APPLICATION_CONFIRMATION_LINK=https://localhost:3000/apply/company/validate/
2525

2626
# Specifies the port in which the app will be exposed
2727
PORT=8087
@@ -43,10 +43,10 @@ ACCESS_CONTROL_ALLOW_ORIGIN=
4343
# Check this for details on how to configure your personal account for testing (https://support.google.com/accounts/answer/185833?p=InvalidSecondFactor&visit_id=637446218993181653-2339409452&rd=1)
4444

4545
# The email address from which the emails are sent
46-
MAIL_FROM=jacky88@ethereal.email
46+
MAIL_FROM=
4747

4848
# Password for email above
49-
MAIL_FROM_PASSWORD=PgAnnVsAa6Sg8zJp6t
49+
MAIL_FROM_PASSWORD=
5050

5151
# Cloudinary API URL to save images
5252
CLOUDINARY_URL=

src/api/middleware/application.js

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,15 @@
11
import CompanyApplication, { CompanyApplicationRules } from "../../models/CompanyApplication.js";
22
import { APIError, ErrorTypes } from "./errorHandler.js";
33
import { StatusCodes as HTTPStatus } from "http-status-codes/build/cjs/status-codes.js";
4-
export const exceededCreationTimeLimit = async (email) => {
5-
const cursor = await CompanyApplication.findOne({ email, isVerified: false }).exec();
6-
if (cursor !== null && Date.now() - cursor.submittedAt < 5000 * 60) {
7-
throw new APIError(HTTPStatus.FORBIDDEN, ErrorTypes.FORBIDDEN, CompanyApplicationRules.APPLICATION_RECENTLY_CREATED);
4+
import { VALIDATION_LINK_EXPIRATION } from "../../models/constants/ApplicationStatus.js";
5+
import { SECOND_IN_MS } from "../../models/constants/TimeConstants.js";
6+
7+
export const exceededCreationTimeLimit = async (req, res, next) => {
8+
const application = await CompanyApplication.findOne({ email:req.body.email, isVerified: false });
9+
if (application !== null && Date.now() < application.submittedAt.getTime() + VALIDATION_LINK_EXPIRATION * SECOND_IN_MS) {
10+
return next( new APIError(HTTPStatus.FORBIDDEN, ErrorTypes.FORBIDDEN, CompanyApplicationRules.APPLICATION_RECENTLY_CREATED.msg));
811
}
9-
return true;
12+
return next();
1013
};
1114

12-
export const deleteApplications = async (email) => {
13-
await CompanyApplication.deleteMany({ email: email, isVerified: false }).catch(function(error) {
14-
console.error(error);
15-
throw (error); // Failure
16-
});
17-
};
15+

src/api/middleware/auth.js

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -78,16 +78,11 @@ export const hasAdminPrivileges = async (req, res, next) => {
7878
};
7979

8080
export const validToken = (req, res, next) => {
81-
try {
82-
const decoded = verifyAndDecodeToken(req.params.token, config.jwt_secret, next);
81+
const decoded = verifyAndDecodeToken(req.params.token, config.jwt_secret, next);
8382

84-
storeInLocals(req, {
85-
token: decoded,
86-
});
83+
storeInLocals(req, {
84+
token: decoded,
85+
});
8786

88-
return next();
89-
} catch (err) {
90-
console.log(err);
91-
return next(err);
92-
}
87+
return next();
9388
};

src/api/middleware/validators/validationReasons.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ const ValidationReasons = Object.freeze({
4949
IMAGE_FORMAT: "formats-supported-png-jpeg-jpg",
5050
OFFER_BLOCKED_ADMIN: "offer-blocked-by-admin",
5151
OFFER_HIDDEN: "offer-is-hidden",
52-
ALREADY_VALIDATED: "application-already-validated",
5352
NON_EXISTING_APPLICATION: "application-does-not-exist",
5453
FILE_TOO_LARGE: (max) => `file-cant-be-larger-than-${max}MB`
5554
});

src/api/routes/application.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,10 @@ export default (app) => {
1313
/**
1414
* Creates a new Company Application
1515
*/
16-
router.post("/", validators.create, async (req, res, next) => {
16+
router.post("/", validators.create, applicationMiddleware.exceededCreationTimeLimit, async (req, res, next) => {
1717
try {
18-
await applicationMiddleware.exceededCreationTimeLimit(req.body.email);
19-
await applicationMiddleware.deleteApplications(req.body.email);
2018
const applicationService = new ApplicationService();
19+
await applicationService.deleteApplications(req.body.email);
2120
// This is safe since the service is destructuring the passed object and the fields have been validated
2221
const application = await applicationService.create(req.body);
2322
return res.json(application);

src/email-templates/companyApplicationApproval.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,3 @@ export const REJECTION_NOTIFICATION = (companyName) => ({
2323
template: "rejection_notification",
2424
context: { companyName },
2525
});
26-

src/email-templates/confirm-application.handlebars

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<h1>Confirm your NIJobs application</h1>
2-
<p>Please follow this <a href="{{link}}" target="_blank">link</a> to finish the process. Note that the link will be expired in 5 minutes.</p>
2+
<p>We have successfully received your application!</p>
3+
<p>Please follow this <a href="{{link}}" target="_blank">link</a> to finish the process. Note that the link will expire in 10 minutes.</p>
34
<br>
45
<p>If you did not request this or need anything else, please contact us at <a href="mailto:nijobs@aefeup.pt">nijobs@aefeup.pt</a>!</p><br>
56
<p>Sincerely,</p>
Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
<h1>We have successfully received your application!</h1>
2-
<p>We will now review your application, and in case you're approved, you will receive another email with further instructions in order to complete your registration.</p>
1+
<h1>Your application has been validated!</h1>
2+
<p>We will now review your application, and in case you're approved, you will receive another email with further instructions in order to complete your registration.</p>
33
<p>Your Application ID is {{applicationId}} and you registered {{companyName}}</p>
4+
<p>Once you're approved, you will receive an email, and then you can log into NIJobs! Do not forget your password, you will need it on the first login.</p>
45
<br>
56
<p>If you did not request this or if you need anything else, don't hesitate to contact us at <a href="mailto:nijobs@aefeup.pt">nijobs@aefeup.pt</a>!</p>
67
<br>
78
<p>Sincerely,</p>
8-
<p>NIJobs team at NIAEFEUP</p>
9+
<p>NIJobs team at NIAEFEUP</p>

src/lib/emailService.js

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ export class EmailService {
66

77
async init({ email: user, password: pass }) {
88
this.email = user;
9-
/* const transporter = await nodemailer.createTransport({
9+
const transporter = await nodemailer.createTransport({
1010
pool: true,
1111
host: "smtp.gmail.com",
1212
port: 465,
@@ -17,15 +17,6 @@ export class EmailService {
1717
},
1818
connectionTimeout: 30000
1919
});
20-
console.log("transporter");*/
21-
const transporter = nodemailer.createTransport({
22-
host: "smtp.ethereal.email",
23-
port: 587,
24-
auth: {
25-
user: "naomie.koelpin2@ethereal.email",
26-
pass: "NGEVbMnTZzyA3MQD3V"
27-
}
28-
});
2920

3021
transporter.use("compile", hbs({
3122
viewEngine: {

src/models/CompanyApplication.js

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,11 @@ export const CompanyApplicationRules = Object.freeze({
3737
msg: "company-application-already-reviewed",
3838
},
3939
APPLICATION_RECENTLY_CREATED: {
40-
msg: "company-application-already-created-less-than-5-minutes-ago",
40+
msg: "company-application-recently-created",
4141
},
42+
APPLICATION_ALREADY_VALIDATED: {
43+
msg: "application-already-validated",
44+
}
4245
});
4346

4447
export const CompanyApplicationProps = {
@@ -127,9 +130,8 @@ function validateMutuallyExclusiveEvents(field) {
127130
export const applicationUniqueness = async (email) => {
128131
const existingApplications = await CompanyApplication.find({ email });
129132
if (existingApplications.some((application) =>
130-
(application.state === ApplicationStatus.PENDING ||
131-
application.state === ApplicationStatus.APPROVED) &&
132-
application.isVerified)
133+
application.state === ApplicationStatus.PENDING ||
134+
application.state === ApplicationStatus.APPROVED)
133135
) {
134136
throw new Error(CompanyApplicationRules.ONLY_ONE_APPLICATION_ACTIVE_PER_EMAIL.msg);
135137
}
@@ -164,7 +166,7 @@ export const isRejectable = (application) => {
164166

165167

166168
CompanyApplicationSchema.methods.companyValidation = function() {
167-
if (this.isVerified) throw new APIError(HTTPStatus.FORBIDDEN, ErrorTypes.FORBIDDEN, ValidationReasons.ALREADY_VALIDATED);
169+
if (this.isVerified) throw new Error(HTTPStatus.FORBIDDEN, ErrorTypes.FORBIDDEN, CompanyApplicationRules.APPLICATION_ALREADY_VALIDATED);
168170
this.isVerified = true;
169171
return this.save({ validateModifiedOnly: true });
170172
};

0 commit comments

Comments
 (0)