From fdc2ee2f5f41db333d167926f56720c334c7547d Mon Sep 17 00:00:00 2001 From: Muhammad Hassan Zahid Date: Mon, 28 Dec 2020 02:33:03 +0500 Subject: [PATCH 1/4] added verify/ on client --- client/src/API/API.js | 6 ++++-- client/src/App.js | 8 ++++++-- client/src/pages/Verify.js | 6 ++++++ client/src/services/verify.js | 12 ++++++++++++ 4 files changed, 28 insertions(+), 4 deletions(-) create mode 100644 client/src/pages/Verify.js create mode 100644 client/src/services/verify.js diff --git a/client/src/API/API.js b/client/src/API/API.js index 6c7c6b6..8278019 100644 --- a/client/src/API/API.js +++ b/client/src/API/API.js @@ -7,7 +7,7 @@ class API { }, 'credentials': 'include', }); - if(response.status===403) { + if(response.status === 401) { localStorage.removeItem('loggedIn'); localStorage.removeItem('firstLogin'); const data = await response.json(); @@ -35,8 +35,10 @@ class API { 'credentials': 'include', }); - if(response.status===403) { + if(response.status === 401) { localStorage.removeItem('loggedIn'); + localStorage.removeItem('firstLogin'); + localStorage.removeItem('verified'); const data = await response.json(); throw new Error(data.msg); } diff --git a/client/src/App.js b/client/src/App.js index d8da46b..d34ee8b 100644 --- a/client/src/App.js +++ b/client/src/App.js @@ -7,6 +7,7 @@ import Home from './pages/home'; import Feed from './pages/feed'; import Error404 from './pages/error404'; import Post from './pages/post'; +import Verify from './pages/Verify'; import Publish from './pages/publish'; import Profile from './pages/profile'; import Search from './pages/search'; @@ -35,7 +36,9 @@ function App() { {loggedIn ? : } - + + {loggedIn ? : } + @@ -51,12 +54,13 @@ function App() { + {loggedIn ? : } - + diff --git a/client/src/pages/Verify.js b/client/src/pages/Verify.js new file mode 100644 index 0000000..9d3d48a --- /dev/null +++ b/client/src/pages/Verify.js @@ -0,0 +1,6 @@ +import React from 'react'; +import MainContent from '../components/Verify/MainContent'; + +const Verify = () => ; + +export default Verify; diff --git a/client/src/services/verify.js b/client/src/services/verify.js new file mode 100644 index 0000000..36e41fc --- /dev/null +++ b/client/src/services/verify.js @@ -0,0 +1,12 @@ +import API from '../API/API'; + +export const verifyUser = async (__hash) => { + try { + const { status } = await API.postRequest(`${process.env.REACT_APP_API_URL}/verify`, + { hash: __hash } + ); + return (status); + } catch (error) { + throw new Error(error.message); + } +}; From aac0276b6b9b10acf671d764257af4dc6f265b9c Mon Sep 17 00:00:00 2001 From: Muhammad Hassan Zahid Date: Mon, 28 Dec 2020 02:33:34 +0500 Subject: [PATCH 2/4] added verify services --- server/services/verify.js | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 server/services/verify.js diff --git a/server/services/verify.js b/server/services/verify.js new file mode 100644 index 0000000..0017725 --- /dev/null +++ b/server/services/verify.js @@ -0,0 +1,24 @@ +const { ValidationSet } = require('../models/valdation.js'); + +const getUserVerificationStatus = async (__handle) => { + try { + const userValidationDetails = await ValidationSet.findById(__handle); + return (userValidationDetails.isVerified); + } catch (error) { + throw new Error(error.message); + } +}; + +const verifyUser = async (__hash) => { + try { + const userValidationDetails = await ValidationSet.findOne({ verificationHash: __hash }); + userValidationDetails.isVerified = true; + await userValidationDetails.save(); + return (userValidationDetails.isVerified); + } catch (error) { + throw new Error(error.message); + } +}; + +module.exports.getUserVerificationStatus = getUserVerificationStatus; +module.exports.verifyUser = verifyUser; From b82c8228c4c294d2db7383ea93580d4d53e29050 Mon Sep 17 00:00:00 2001 From: Muhammad Hassan Zahid Date: Mon, 28 Dec 2020 02:34:16 +0500 Subject: [PATCH 3/4] updated styles, services, templates --- client/src/components/Login/MainContent.js | 4 +- client/src/components/NewsFeed/Content.js | 2 +- client/src/components/Verify/MainContent.js | 61 +++++++++++++++++++ client/src/style/Error/MainContent.module.css | 7 +++ server/controllers/index.js | 18 +++++- server/db/mongo/connection.js | 50 +++++++-------- server/db/mysql/sqlScript.js | 19 +++--- server/middleware/index.js | 4 +- server/routes/index.js | 1 + server/services/forgetPassword.js | 22 ++++++- server/services/register.js | 30 +++++++++ server/services/template.js | 13 ++-- 12 files changed, 180 insertions(+), 51 deletions(-) create mode 100644 client/src/components/Verify/MainContent.js diff --git a/client/src/components/Login/MainContent.js b/client/src/components/Login/MainContent.js index fbf5b29..218bbd1 100644 --- a/client/src/components/Login/MainContent.js +++ b/client/src/components/Login/MainContent.js @@ -34,9 +34,9 @@ const MainContent = () => {
{ try { - const { status } = await loginUser(email, password); + const { verificationStatus, firstLoginStatus } = await loginUser(email, password); localStorage.setItem('loggedIn', true); - localStorage.setItem('firstLogin', status); + localStorage.setItem('firstLogin', firstLoginStatus); setTimeout(() => { history.push('/feed'); }, 3000); diff --git a/client/src/components/NewsFeed/Content.js b/client/src/components/NewsFeed/Content.js index 28a1b9a..83c5599 100644 --- a/client/src/components/NewsFeed/Content.js +++ b/client/src/components/NewsFeed/Content.js @@ -6,7 +6,7 @@ import API from '../../API/API'; const Content = () => { const [feedData, setFeedData] = useState([]); - const [loading, setLoading] = useState(true) + const [loading, setLoading] = useState(true); useEffect(async () => { try { diff --git a/client/src/components/Verify/MainContent.js b/client/src/components/Verify/MainContent.js new file mode 100644 index 0000000..be00808 --- /dev/null +++ b/client/src/components/Verify/MainContent.js @@ -0,0 +1,61 @@ +import React, { useState, useEffect } from 'react'; +import { useParams } from 'react-router-dom'; +import { CenterAlign } from '../FlexAlignment'; +import Logo from '../../assets/img/icon/Logo.svg'; +import ComponentStyling from '../../style/Error/MainContent.module.css'; +import { verifyUser } from '../../services/verify'; + +const MainContent = () => { + const { hash } = useParams(); + const [loading, setLoading] = useState(true); + + useEffect(async () => { + try { + const status = await verifyUser(hash); + setLoading(!status); + } catch (error) { + alert(error.message); + } + }, []) + + if(loading) { + return ( + <> + + ) + } + + return ( +
+
+ +
+ +
+
+
+
+

+ Terrabuzz +

+
+
+

+ Your account is succesfully verified. Please Login to use Terrabuzz. +
+ + Login + + + Register + +

+
+
+
+ ; +
+ ); +}; + +export default MainContent; diff --git a/client/src/style/Error/MainContent.module.css b/client/src/style/Error/MainContent.module.css index 4df0dd7..97f2376 100644 --- a/client/src/style/Error/MainContent.module.css +++ b/client/src/style/Error/MainContent.module.css @@ -63,3 +63,10 @@ text-decoration: underline; color: black; } + +.textStyling { + margin-right: 100px; + text-decoration: none; + color: #000; + font-weight: 800; +}; \ No newline at end of file diff --git a/server/controllers/index.js b/server/controllers/index.js index ab9829e..b818b5d 100644 --- a/server/controllers/index.js +++ b/server/controllers/index.js @@ -21,6 +21,7 @@ const { postExternDataToDB } = require('../services/postExternalLinks.js'); const { postProfileDataToDB } = require('../services/postExternalProfile.js'); const { postNotification } = require('../services/postNotification.js'); const { getNavbarInformationFromDatabase } = require('../services/getNavbarInfo.js'); +const { getUserVerificationStatus, verifyUser } = require('../services/verify.js'); module.exports.getHomePage = async (req, res) => { try { @@ -193,8 +194,9 @@ module.exports.loginUser = async (req, res) => { try { const { token, handle } = await generateAccessToken(req.body); res.cookie('access-token', token, { httpOnly: true, sameSite: true }); - const status = await checkForFirstLogin(handle); - return res.status(200).json({ msg: 'User logged in!!', status }); + const firstLoginStatus = await checkForFirstLogin(handle); + const verificationStatus = await getUserVerificationStatus(handle); + return res.status(200).json({ msg: 'User logged in!!', firstLoginStatus, verificationStatus }); } catch (error) { return res.status(401).json({ msg: error.message }); } @@ -248,7 +250,7 @@ module.exports.logoutUser = async (req, res) => { res.clearCookie('access-token'); return res.status(200).json({ msg: 'User succesfully logged out' }); } catch (error) { - return res.status(403).json({ msg: error.message }); + return res.status(401).json({ msg: error.message }); } }; @@ -287,3 +289,13 @@ module.exports.postNotificationController = async (req, res) => { return res.status(500).json({ msg: `Failed to post notification to database due to error "${error.message}"` }); } }; + +module.exports.verifyUser = async (req, res) => { + try { + const { hash } = req.body; + const status = await verifyUser(hash); + res.json({ msg: 'User successfully verified', status }); + } catch (error) { + res.status(404).json({ msg: error.message }); + } +}; diff --git a/server/db/mongo/connection.js b/server/db/mongo/connection.js index fc51ea4..9fc7c8b 100644 --- a/server/db/mongo/connection.js +++ b/server/db/mongo/connection.js @@ -1,7 +1,7 @@ const MONGOOSE = require('mongoose'); -const { NotificationList } = require('../../models/notification.js'); -const { PostList } = require('../../models/post.js'); -const { ValidationSet } = require('../../models/valdation.js'); +// const { NotificationList } = require('../../models/notification.js'); +// const { PostList } = require('../../models/post.js'); +// const { ValidationSet } = require('../../models/valdation.js'); require('dotenv').config(); const connect = async () => { @@ -12,31 +12,31 @@ const connect = async () => { return console.log('Mongoose not connected, some error occured!'); }); - const defaultHandlers = ['TashikMoin', 'hassanzhd', 'Saif', 'Johndoe']; + // const defaultHandlers = ['TashikMoin', 'hassanzhd', 'Saif', 'Johndoe']; - /* eslint-disable no-await-in-loop */ - for (let i = 0; i < defaultHandlers.length; i += 1) { - const userPostList = new PostList({ - _id: defaultHandlers[i], - payload: [], - }); - await userPostList.save(); + // /* eslint-disable no-await-in-loop */ + // for (let i = 0; i < defaultHandlers.length; i += 1) { + // const userPostList = new PostList({ + // _id: defaultHandlers[i], + // payload: [], + // }); + // await userPostList.save(); - const notificationList = new NotificationList({ - _id: defaultHandlers[i], - payload: [], - }); - await notificationList.save(); + // const notificationList = new NotificationList({ + // _id: defaultHandlers[i], + // payload: [], + // }); + // await notificationList.save(); - const validationSet = new ValidationSet({ - _id: defaultHandlers[i], - verificationHash: '', - isVerified: true, - resetHash: '', - isFirstLogin: false, - }); - await validationSet.save(); - } + // const validationSet = new ValidationSet({ + // _id: defaultHandlers[i], + // verificationHash: '', + // isVerified: true, + // resetHash: '', + // isFirstLogin: false, + // }); + // await validationSet.save(); + // } /* eslint-enable no-await-in-loop */ }; diff --git a/server/db/mysql/sqlScript.js b/server/db/mysql/sqlScript.js index be90d78..b5615d3 100644 --- a/server/db/mysql/sqlScript.js +++ b/server/db/mysql/sqlScript.js @@ -3,7 +3,7 @@ const fs = require('fs'); const MYSQL_CONNECTOR = (require('./connection.js')); const createAndInsert = async () => { - let script = fs.readFileSync(path.join(__dirname, './ddl.sql')).toString(); + const script = fs.readFileSync(path.join(__dirname, './ddl.sql')).toString(); try { const result = await MYSQL_CONNECTOR.connection.query(script); console.log('DDL Created Successfully for MySQL'); @@ -12,14 +12,15 @@ const createAndInsert = async () => { console.log(`DDL Creation query not executed successfully for MySQL because --> ${error.message}`); } - script = fs.readFileSync(path.join(__dirname, './insertSql.sql')).toString(); - try { - const result = await MYSQL_CONNECTOR.connection.query(script); - console.log('Insertions Done Successfully for MYSQL'); - console.log(result); - } catch (error) { - console.log(`Insertion query Not Executed Successfully For MySQL Because --> ${error.message}`); - } + // script = fs.readFileSync(path.join(__dirname, './insertSql.sql')).toString(); + // try { + // const result = await MYSQL_CONNECTOR.connection.query(script); + // console.log('Insertions Done Successfully for MYSQL'); + // console.log(result); + // } catch (error) { + // console.log(`Insertion query Not Executed Successfully + // For MySQL Because --> ${error.message}`); + // } }; module.exports.createAndInsert = createAndInsert; diff --git a/server/middleware/index.js b/server/middleware/index.js index a381518..9c9a5f6 100644 --- a/server/middleware/index.js +++ b/server/middleware/index.js @@ -24,7 +24,7 @@ module.exports.authorizeUser = (req, res, next) => { req.userHandle = handle; return next(); } catch (error) { - return res.status(403).json({ msg: 'Unauthorized! Please login again.' }); + return res.status(401).json({ msg: 'Unauthorized! Please login again.' }); } }; @@ -38,6 +38,6 @@ module.exports.forwardUnAuthorizedUser = (req, res, next) => { req.userHandle = handle; return next(); } catch (error) { - return res.status(403).json({ msg: 'Unauthorized! Please login again.' }); + return res.status(401).json({ msg: 'Unauthorized! Please login again.' }); } }; diff --git a/server/routes/index.js b/server/routes/index.js index b4422b2..8acaba6 100644 --- a/server/routes/index.js +++ b/server/routes/index.js @@ -30,4 +30,5 @@ Router.post('/changepassword', authorizeUser, indexContoller.changePassword); Router.post('/externalLinks', authorizeUser, indexContoller.postExternalInformationDetails); Router.post('/externalProfile', authorizeUser, indexContoller.postExternalProfileDetails); Router.post('/notification', authorizeUser, indexContoller.postNotificationController); +Router.post('/verify', indexContoller.verifyUser); module.exports = Router; diff --git a/server/services/forgetPassword.js b/server/services/forgetPassword.js index 5bc581a..69b808d 100644 --- a/server/services/forgetPassword.js +++ b/server/services/forgetPassword.js @@ -4,6 +4,14 @@ const { InsertValidationDocument } = require('./resetHash.js'); const { GmailMailer } = require('./gmailAuth.js'); const { HTMLResetPasswordForm } = require('./template.js'); +const emailData = { + title: 'Reset your password', + content: 'You\'re receiving this e-mail because you requested a password reset for your Terrabuzz account.', + description: 'Please tap the button below to choose a new password.', + route: 'newPassword', + buttonText: 'Reset password', +}; + const forgetPasswordUpdation = async (__email) => { // If the user exists in the database try { @@ -24,8 +32,18 @@ const forgetPasswordUpdation = async (__email) => { } catch (error) { throw new Error(`InsertValidationDocument failed due to error ${error.message}`); } - const mail = new GmailMailer(__email, HTMLResetPasswordForm(hashedResetLink)); - mail.send(); + const mail = new GmailMailer( + __email, + HTMLResetPasswordForm( + hashedResetLink, + emailData.title, + emailData.content, + emailData.description, + emailData.route, + emailData.buttonText, + ), + ); + await mail.send(); } catch (error) { throw new Error(`Unable to send a reset email. Encountered error "${error.message}"`); } diff --git a/server/services/register.js b/server/services/register.js index 0be628b..d80e2cd 100644 --- a/server/services/register.js +++ b/server/services/register.js @@ -1,7 +1,19 @@ const bcrypt = require('bcrypt'); +const crypto = require('crypto'); const mysql = require('../db/mysql/connection.js'); const { PostList } = require('../models/post.js'); const { NotificationList } = require('../models/notification.js'); +const { ValidationSet } = require('../models/valdation.js'); +const { GmailMailer } = require('./gmailAuth.js'); +const { HTMLResetPasswordForm } = require('./template.js'); + +const emailData = { + title: 'Verify your account', + content: 'You\'re receiving this e-mail because you are required to verify your Terrabuzz account.', + description: 'Please tap the button below to verify your account.', + route: 'verify', + buttonText: 'Verify account', +}; const postUserCredentialsInDatabase = async (__registerForm) => { if (!__registerForm.password || !__registerForm.cpassword @@ -28,6 +40,24 @@ const postUserCredentialsInDatabase = async (__registerForm) => { payload: [], }); await notificationList.save(); + const verificationHash = crypto.randomBytes(50).toString('hex'); + const validationSet = new ValidationSet({ + _id: __registerForm.userhandler, + verificationHash, + }); + await validationSet.save(); + const mail = new GmailMailer( + __registerForm.email, + HTMLResetPasswordForm( + verificationHash, + emailData.title, + emailData.content, + emailData.description, + emailData.route, + emailData.buttonText, + ), + ); + await mail.send(); } catch (error) { throw new Error(error.message); } diff --git a/server/services/template.js b/server/services/template.js index 99d4064..01b2a0a 100644 --- a/server/services/template.js +++ b/server/services/template.js @@ -1,4 +1,4 @@ -const HTMLResetPasswordForm = (__hashedLink) => (` +const HTMLResetPasswordForm = (__hashedLink, __title, __content, __description, __route, __buttonText) => (` Rating Reminder @@ -88,7 +88,7 @@ const HTMLResetPasswordForm = (__hashedLink) => (` line-height: 52px; mso-line-height-rule: exactly; text-decoration: none;"> - Reset your password + ${__title} @@ -126,8 +126,7 @@ const HTMLResetPasswordForm = (__hashedLink) => (` vertical-align: top; width: 100%; "> - You're receiving this e-mail because you requested a password reset - for your Terrabuzz account. + ${__content} @@ -150,12 +149,12 @@ const HTMLResetPasswordForm = (__hashedLink) => (` vertical-align: top; width: 100%; "> - Please tap the button below to choose a new password. + ${__description} - - Reset Password + ${__buttonText} From 5568582150c4e98384cde15bdb88f1a566c5c1fe Mon Sep 17 00:00:00 2001 From: Muhammad Hassan Zahid Date: Mon, 28 Dec 2020 02:58:53 +0500 Subject: [PATCH 4/4] resolved conflicts --- server/routes/index.js | 1 - 1 file changed, 1 deletion(-) diff --git a/server/routes/index.js b/server/routes/index.js index 07a0012..06966cd 100644 --- a/server/routes/index.js +++ b/server/routes/index.js @@ -31,7 +31,6 @@ Router.post('/firstLogin', authorizeUser, indexContoller.postFirstLoginInformati Router.post('/changepassword', authorizeUser, indexContoller.changePassword); Router.post('/externalLinks', authorizeUser, indexContoller.postExternalInformationDetails); Router.post('/externalProfile', authorizeUser, indexContoller.postExternalProfileDetails); -Router.post('/notification', authorizeUser, indexContoller.postNotificationController); Router.post('/verify', indexContoller.verifyUser); Router.post('/notification-comment', authorizeUser, indexContoller.postCommentNotification); Router.post('/notification-like', authorizeUser, indexContoller.postLikeNotification);