Skip to content

Commit

Permalink
Fix verify email endpoints
Browse files Browse the repository at this point in the history
  • Loading branch information
hagopj13 committed Mar 30, 2021
1 parent a360787 commit 40b6294
Show file tree
Hide file tree
Showing 7 changed files with 101 additions and 133 deletions.
8 changes: 4 additions & 4 deletions src/controllers/auth.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ const resetPassword = catchAsync(async (req, res) => {
res.status(httpStatus.NO_CONTENT).send();
});

const verificationEmail = catchAsync(async (req, res) => {
const verifyEmailToken = await tokenService.generateVerificationEmailToken(req.body.email);
await emailService.sendVerificationEmail(req.body.email, verifyEmailToken);
const sendVerificationEmail = catchAsync(async (req, res) => {
const verifyEmailToken = await tokenService.generateVerifyEmailToken(req.user);
await emailService.sendVerificationEmail(req.user.email, verifyEmailToken);
res.status(httpStatus.NO_CONTENT).send();
});

Expand All @@ -54,6 +54,6 @@ module.exports = {
refreshTokens,
forgotPassword,
resetPassword,
verificationEmail,
sendVerificationEmail,
verifyEmail,
};
88 changes: 36 additions & 52 deletions src/routes/v1/auth.route.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ router.post('/logout', validate(authValidation.logout), authController.logout);
router.post('/refresh-tokens', validate(authValidation.refreshTokens), authController.refreshTokens);
router.post('/forgot-password', validate(authValidation.forgotPassword), authController.forgotPassword);
router.post('/reset-password', validate(authValidation.resetPassword), authController.resetPassword);
router.post('/verification-email', auth(), validate(authValidation.verificationEmail), authController.verificationEmail);
router.post('/send-verification-email', auth(), authController.sendVerificationEmail);
router.post('/verify-email', validate(authValidation.verifyEmail), authController.verifyEmail);

module.exports = router;
Expand Down Expand Up @@ -249,59 +249,43 @@ module.exports = router;

/**
* @swagger
* path:
* /auth/verification-email:
* post:
* summary: verification-email Email
* description: An email will be sent to verify email.
* tags: [Auth]
* security:
* - bearerAuth: []
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required:
* - email
* properties:
* email:
* type: string
* format: email
* example:
* email: fake@example.com
* responses:
* "204":
* description: No content
* "404":
* $ref: '#/components/responses/NotFound'
* /auth/send-verification-email:
* post:
* summary: Send verification email
* description: An email will be sent to verify email.
* tags: [Auth]
* security:
* - bearerAuth: []
* responses:
* "204":
* description: No content
* "401":
* $ref: '#/components/responses/Unauthorized'
*/

/**
* @swagger
* path:
* /auth/verify-email:
* post:
* summary: verify email
* tags: [Auth]
* parameters:
* - in: query
* name: token
* required: true
* schema:
* type: string
* description: The verify email token
* responses:
* "204":
* description: No content
* "401":
* description: verify email failed
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/Error'
* example:
* code: 401
* message: verify email failed
* /auth/verify-email:
* post:
* summary: verify email
* tags: [Auth]
* parameters:
* - in: query
* name: token
* required: true
* schema:
* type: string
* description: The verify email token
* responses:
* "204":
* description: No content
* "401":
* description: verify email failed
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/Error'
* example:
* code: 401
* message: verify email failed
*/
13 changes: 7 additions & 6 deletions src/services/auth.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,22 +70,23 @@ const resetPassword = async (resetPasswordToken, newPassword) => {
throw new ApiError(httpStatus.UNAUTHORIZED, 'Password reset failed');
}
};

/**
* Verify Email
* @param {string} EmailVerificationToken
* Verify email
* @param {string} verifyEmailToken
* @returns {Promise}
*/
const verifyEmail = async (emailVarificationToken) => {
const verifyEmail = async (verifyEmailToken) => {
try {
const emailVarificationTokenDoc = await tokenService.verifyToken(emailVarificationToken, tokenTypes.VERIFY_EMAIL);
const user = await userService.getUserById(emailVarificationTokenDoc.user);
const verifyEmailTokenDoc = await tokenService.verifyToken(verifyEmailToken, tokenTypes.VERIFY_EMAIL);
const user = await userService.getUserById(verifyEmailTokenDoc.user);
if (!user) {
throw new Error();
}
await Token.deleteMany({ user: user.id, type: tokenTypes.VERIFY_EMAIL });
await userService.updateUserById(user.id, { isEmailVerified: true });
} catch (error) {
throw new ApiError(httpStatus.UNAUTHORIZED, 'email verification failed');
throw new ApiError(httpStatus.UNAUTHORIZED, 'Email verification failed');
}
};

Expand Down
16 changes: 12 additions & 4 deletions src/services/email.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,21 +32,29 @@ const sendEmail = async (to, subject, text) => {
const sendResetPasswordEmail = async (to, token) => {
const subject = 'Reset password';
// replace this url with the link to the reset password page of your front-end app
const resetPasswordUrl = `http://link-to-app/verify-email?token=${token}`;
const resetPasswordUrl = `http://link-to-app/reset-password?token=${token}`;
const text = `Dear user,
To reset your password, click on this link: ${resetPasswordUrl}
If you did not request any password resets, then ignore this email.`;
await sendEmail(to, subject, text);
};

/**
* Send verification email
* @param {string} to
* @param {string} token
* @returns {Promise}
*/
const sendVerificationEmail = async (to, token) => {
const subject = 'Email Verification';
// replace this url with the link to the reset password page of your front-end app
// replace this url with the link to the email verification page of your front-end app
const verificationEmailUrl = `http://link-to-app/verify-email?token=${token}`;
const text = `Dear user,
To verify your email, click on this link: ${verificationEmailUrl}
If you did not request any email verification, then ignore this email.`;
To verify your email, click on this link: ${verificationEmailUrl}
If you did not create an account, then ignore this email.`;
await sendEmail(to, subject, text);
};

module.exports = {
transport,
sendEmail,
Expand Down
21 changes: 12 additions & 9 deletions src/services/token.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,21 +99,24 @@ const generateResetPasswordToken = async (email) => {
await saveToken(resetPasswordToken, user.id, expires, tokenTypes.RESET_PASSWORD);
return resetPasswordToken;
};
const generateVerificationEmailToken = async (email) => {
const user = await userService.getUserByEmail(email);
if (!user) {
throw new ApiError(httpStatus.NOT_FOUND, 'No users found with this email');
}

/**
* Generate verify email token
* @param {string} email
* @returns {Promise<string>}
*/
const generateVerifyEmailToken = async (user) => {
const expires = moment().add(config.jwt.verifyEmailExpirationMinutes, 'minutes');
const verificationEmailToken = generateToken(user.id, expires);
await saveToken(verificationEmailToken, user.id, expires, tokenTypes.VERIFY_EMAIL);
return verificationEmailToken;
const verifyEmailToken = generateToken(user.id, expires, tokenTypes.VERIFY_EMAIL);
await saveToken(verifyEmailToken, user.id, expires, tokenTypes.VERIFY_EMAIL);
return verifyEmailToken;
};

module.exports = {
generateToken,
saveToken,
verifyToken,
generateAuthTokens,
generateResetPasswordToken,
generateVerificationEmailToken,
generateVerifyEmailToken,
};
11 changes: 2 additions & 9 deletions src/validations/auth.validation.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
/* eslint-disable no-unused-vars */
/* eslint-disable prettier/prettier */
const Joi = require('joi');
const { password } = require('./custom.validation');

Expand Down Expand Up @@ -45,23 +43,18 @@ const resetPassword = {
}),
};

const verificationEmail = {
body: Joi.object().keys({
email: Joi.string().required(),
})
};
const verifyEmail = {
query: Joi.object().keys({
token: Joi.string().required(),
})
}),
};

module.exports = {
register,
login,
logout,
refreshTokens,
forgotPassword,
resetPassword,
verificationEmail,
verifyEmail,
};
Loading

0 comments on commit 40b6294

Please sign in to comment.