Skip to content

Commit

Permalink
Adding custom errors for token validation
Browse files Browse the repository at this point in the history
Co-authored-by: Daniel Ferreira <[email protected]>
  • Loading branch information
FranciscoCardoso913 and dsantosferreira committed Feb 11, 2023
1 parent 278310b commit 0bd0830
Show file tree
Hide file tree
Showing 8 changed files with 44 additions and 24 deletions.
5 changes: 3 additions & 2 deletions src/api/middleware/application.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import CompanyApplication, { CompanyApplicationRules } from "../../models/CompanyApplication.js";

import { APIError, ErrorTypes } from "./errorHandler.js";
import { StatusCodes as HTTPStatus } from "http-status-codes/build/cjs/status-codes.js";
export const exceededCreationTimeLimit = async (email) => {
const cursor = await CompanyApplication.findOne({ email, isVerified: false }).exec();
if (cursor !== null && Date.now() - cursor.submittedAt < 5000 * 60) {
throw new Error(CompanyApplicationRules.APPLICATION_RECENTLY_CREATED.msg);
throw new APIError(HTTPStatus.FORBIDDEN, ErrorTypes.FORBIDDEN, CompanyApplicationRules.APPLICATION_RECENTLY_CREATED);
}
return true;
};
Expand Down
19 changes: 10 additions & 9 deletions src/api/middleware/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,15 +78,16 @@ export const hasAdminPrivileges = async (req, res, next) => {
};

export const validToken = (req, res, next) => {
const decoded = verifyAndDecodeToken(req.params.token, config.jwt_secret);

if (!decoded) {
return next(new APIError(HTTPStatus.FORBIDDEN, ErrorTypes.FORBIDDEN, ValidationReasons.INVALID_TOKEN));
}
try {
const decoded = verifyAndDecodeToken(req.params.token, config.jwt_secret, next);

storeInLocals(req, {
token: decoded,
});
storeInLocals(req, {
token: decoded,
});

return next();
return next();
} catch (err) {
console.log(err);
return next(err);
}
};
6 changes: 1 addition & 5 deletions src/api/middleware/validators/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,10 +119,6 @@ export const token = param("token", ValidationReasons.DEFAULT)
.isString().withMessage(ValidationReasons.STRING)
.trim();

export const confirmValidation = useExpressValidators([
token,
]);

export const finishValidation = useExpressValidators([
token,
token.exists().withMessage(ValidationReasons.NON_EXISTING_APPLICATION).bail(),
]);
3 changes: 3 additions & 0 deletions src/api/middleware/validators/validationReasons.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,16 @@ const ValidationReasons = Object.freeze({
OFFER_EDIT_PERIOD_OVER: (value) => `offer-edit-period-over:${value}-hours`,
INVALID_QUERY_TOKEN: "invalid-query-token",
INVALID_TOKEN: "invalid-token",
EXPIRED_TOKEN: "expired-token",
JOB_MIN_DURATION_NOT_SPECIFIED: "job-max-duration-requires-job-min-duration",
REGISTRATION_FINISHED: "registration-already-finished",
REGISTRATION_NOT_FINISHED: "registration-not-finished-yet",
FAILED_SAVE: "failed-save",
IMAGE_FORMAT: "formats-supported-png-jpeg-jpg",
OFFER_BLOCKED_ADMIN: "offer-blocked-by-admin",
OFFER_HIDDEN: "offer-is-hidden",
ALREADY_VALIDATED: "application-already-validated",
NON_EXISTING_APPLICATION: "application-does-not-exist",
FILE_TOO_LARGE: (max) => `file-cant-be-larger-than-${max}MB`
});

Expand Down
12 changes: 10 additions & 2 deletions src/lib/emailService.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export class EmailService {

async init({ email: user, password: pass }) {
this.email = user;
const transporter = await nodemailer.createTransport({
/* const transporter = await nodemailer.createTransport({
pool: true,
host: "smtp.gmail.com",
port: 465,
Expand All @@ -17,7 +17,15 @@ export class EmailService {
},
connectionTimeout: 30000
});
console.log("transporter");
console.log("transporter");*/
const transporter = nodemailer.createTransport({
host: "smtp.ethereal.email",
port: 587,
auth: {
user: "[email protected]",
pass: "NGEVbMnTZzyA3MQD3V"
}
});

transporter.use("compile", hbs({
viewEngine: {
Expand Down
13 changes: 10 additions & 3 deletions src/lib/token.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
import jwt from "jsonwebtoken";
import { APIError, ErrorTypes } from "../api/middleware/errorHandler.js";
import { StatusCodes as HTTPStatus } from "http-status-codes/build/cjs/status-codes.js";
import ValidationReasons from "../api/middleware/validators/validationReasons.js";

export const generateToken = (data, secret, expiresInSeconds) => jwt.sign(
{ ...data },
secret,
{ expiresIn: `${expiresInSeconds} seconds`, algorithm: "HS256" }
);

export const verifyAndDecodeToken = (token, secret) => {
export const verifyAndDecodeToken = (token, secret, next) => {
try {
return jwt.verify(token, secret, { algorithm: "HS256" });
} catch (err) {
return null;
} catch (jwtErr) {
if (jwtErr.name === "TokenExpiredError") {
return next(new APIError(HTTPStatus.FORBIDDEN, ErrorTypes.FORBIDDEN, ValidationReasons.EXPIRED_TOKEN));
} else {
return next(new APIError(HTTPStatus.FORBIDDEN, ErrorTypes.FORBIDDEN, ValidationReasons.INVALID_TOKEN));
}
}
};
5 changes: 4 additions & 1 deletion src/models/CompanyApplication.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ import mongoose from "mongoose";
import ApplicationStatus from "./constants/ApplicationStatus.js";
import CompanyApplicationConstants from "./constants/CompanyApplication.js";
import { checkDuplicatedEmail } from "../api/middleware/validators/validatorUtils.js";
import { APIError, ErrorTypes } from "../api/middleware/errorHandler.js";
import { StatusCodes as HTTPStatus } from "http-status-codes/build/cjs/status-codes.js";
import ValidationReasons from "../api/middleware/validators/validationReasons.js";

const { Schema } = mongoose;

Expand Down Expand Up @@ -161,7 +164,7 @@ export const isRejectable = (application) => {


CompanyApplicationSchema.methods.companyValidation = function() {
if (this.isVerified) throw new Error("Application was already validated by the company");
if (this.isVerified) throw new APIError(HTTPStatus.FORBIDDEN, ErrorTypes.FORBIDDEN, ValidationReasons.ALREADY_VALIDATED);
this.isVerified = true;
return this.save({ validateModifiedOnly: true });
};
Expand Down
5 changes: 3 additions & 2 deletions src/services/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@ import { RECOVERY_LINK_EXPIRATION } from "../models/constants/ApplicationStatus.
import { APPLICATION_CONFIRMATION } from "../email-templates/companyApplicationConfirmation.js";
import AccountService from "./account.js";
import EmailService from "../lib/emailService.js";
import { StatusCodes as HTTPStatus } from "http-status-codes/build/cjs/status-codes.js";
import {
NEW_COMPANY_APPLICATION_ADMINS,
NEW_COMPANY_APPLICATION_COMPANY,
APPROVAL_NOTIFICATION,
REJECTION_NOTIFICATION,
} from "../email-templates/companyApplicationApproval.js";
import config from "../config/env.js";
import { APIError, ErrorTypes } from "../api/middleware/errorHandler.js";
import ValidationReasons from "../api/middleware/validators/validationReasons.js";

export class CompanyApplicationNotFound extends Error {
constructor(msg) {
Expand Down Expand Up @@ -44,13 +47,11 @@ class CompanyApplicationService {
submittedAt: Date.now(),
isVerified: false,
});
console.log("criar");
const link = this.buildConfirmationLink(application._id);
await EmailService.sendMail({
to: email,
...APPLICATION_CONFIRMATION(link),
});
console.log("Criado");
return application.toObject();
}

Expand Down

0 comments on commit 0bd0830

Please sign in to comment.