diff --git a/backend/.env.example b/backend/.env.example index 9ad53576..003f0d90 100644 --- a/backend/.env.example +++ b/backend/.env.example @@ -10,4 +10,4 @@ JWT_EXPIRES_IN=`JWT expiry time` JWT_SECRET=`JWT Secret` JWT_COOKIE_EXPIRES_IN=`cookie expiry time` JWT_COOKIE_DOMAIN=`.example.com` -PORT=`Put numeric port here` +PORT=`Put numeric port here` \ No newline at end of file diff --git a/backend/app.js b/backend/app.js index 808eccea..0513912a 100644 --- a/backend/app.js +++ b/backend/app.js @@ -3,6 +3,7 @@ const rateLimit = require('express-rate-limit'); const helmet = require('helmet'); const mongoSanitize = require('express-mongo-sanitize'); const xss = require('xss-clean'); +const cors = require('cors'); const authRouter = require('./routes/authRoutes'); const storyRouter = require('./routes/storyRoutes'); const orgRouter = require('./routes/orgRoutes'); @@ -18,6 +19,9 @@ const app = express(); // Data sanitization against XSS app.use(xss()); +// for cross site request origin +app.use(cors({ credentials: true, origin: 'http://localhost:3000' })); + // Data sanitization against no-sql query injection app.use(mongoSanitize()); diff --git a/backend/config/dotenv.js b/backend/config/dotenv.js index 317eadf9..13f593c2 100644 --- a/backend/config/dotenv.js +++ b/backend/config/dotenv.js @@ -11,7 +11,7 @@ if (process.env.NODE_ENV === "development") { */ // load the .env file (for development) require('dotenv').config({ path: path.resolve(`.env`) }); -} +} // default the environment to production else { diff --git a/backend/controllers/authController.js b/backend/controllers/authController.js index ce3332a7..28405ca5 100644 --- a/backend/controllers/authController.js +++ b/backend/controllers/authController.js @@ -3,7 +3,6 @@ const bcrypt = require('bcryptjs'); const nodemailer = require('nodemailer'); const jwt = require('jsonwebtoken'); const sendgridTransport = require('nodemailer-sendgrid-transport'); -require('../config/dotenv'); const User = require('../database/models/userModel'); @@ -15,10 +14,8 @@ const transporter = nodemailer.createTransport( }) ); -const getAuthCookie = (token) => { - const expiry = new Date(Date.now() + +process.env.JWT_COOKIE_EXPIRES_IN); - return `token=${token}; Domain=${process.env.JWT_COOKIE_DOMAIN}; Expires=${expiry.toGMTString()}; Path=/; HttpOnly=true; SameSite=Lax; Secure=true;` -}; + + //signup /** @@ -32,7 +29,6 @@ const getAuthCookie = (token) => { */ exports.signup = async (req, res) => { const { name, email, phone, photo, password, passwordConfirm } = req.body; - console.log(req.body); // checking all credentials are present or not if (!name || !email || !phone || !password) return res.status(400).json({ msg: 'fill up all the credentials' }); @@ -62,14 +58,18 @@ exports.signup = async (req, res) => { await newUser.save(); - // generating auth token - let token = jwt.sign({ id: newUser._id }, process.env.JWT_SECRET, { - expiresIn: '1h', - }); - //set cookie - res.set('Cookie', getAuthCookie(token)); - + // if we want to login user directly when he register then we use this + // let token = jwt.sign({ id: existingUser._id }, process.env.JWT_SECRET, { + // expiresIn: process.env.JWT_COOKIE_EXPIRES_IN, + // }); + + // res.cookie("jwt", `Bearer ${token}`, { + // expiresIn: '1h', + // secure: true, + // httpOnly: true + // }) + // returning final response res.status(201).json({ success: true, @@ -80,7 +80,7 @@ exports.signup = async (req, res) => { }, }); } catch (e) { - console.log(e.message); + console.log(e); return res.status(400).json({ msg: 'cannot signup' }); } }; @@ -92,6 +92,7 @@ exports.signup = async (req, res) => { * @route api/auth/signin */ exports.signin = async (req, res) => { + const { email, password } = req.body; if (!email || !password) return res.status(400).json({ msg: 'fill up all the credentials' }); @@ -108,19 +109,19 @@ exports.signin = async (req, res) => { .status(400) .json({ msg: 'invalid credentials,check your password' }); - let token = jwt.sign({ id: existingUser._id }, process.env.JWT_SECRET, { - expiresIn: '1h', + // send token to frontend + let token = jwt.sign({ id: existingUser._id, email: existingUser.email }, process.env.JWT_SECRET, { + expiresIn: process.env.JWT_COOKIE_EXPIRES_IN, }); - //set cookie - res.set('Cookie', getAuthCookie(token)); res.status(200).json({ success: true, data: { ...existingUser._doc, password: '', - passwordConfirm: "" + passwordConfirm: "", + token: `Bearer ${token}` }, }); } catch (err) { @@ -234,11 +235,16 @@ exports.postNewPassword = async (req, res) => { * @param {Number} userId * @param {String} token */ + + + exports.isSignedIn = async (req, res, next) => { - const token = req.header('Authorization').replace('Bearer ', ''); - const data = jwt.verify(token, process.env.JWT_SECRET); + + const token = req.cookies.token.split(' ')[1]; + const { id } = jwt.verify(token, process.env.JWT_SECRET); try { - const user = User.findOne({ _id: userId, token: token }); + const user = await User.findOne({ _id: id }); + if (!user) { throw new NoUserFoundError('User is currently not logged in'); } @@ -246,6 +252,7 @@ exports.isSignedIn = async (req, res, next) => { req.token = token; next(); } catch (error) { + console.log(error) const err_code = error.err_code ? err.code >= 100 && err.code <= 599 ? err.code @@ -253,7 +260,7 @@ exports.isSignedIn = async (req, res, next) => { : 500; res.status(err_code).json({ status: 'fail', - message: err.message || 'Internal Server Error', + message: error.message || 'Internal Server Error', }); } }; @@ -261,7 +268,7 @@ exports.isSignedIn = async (req, res, next) => { exports.validateCookie = (req, res, next) => { try { const res = jwt.verify(req.cookies.token, process.env.JWT_SECRET) - if (res.id) { + if (res.id) { next(); } else { throw new Error("Invalid USER ID"); diff --git a/backend/database/index.js b/backend/database/index.js index ee4c60cd..5405b7bc 100644 --- a/backend/database/index.js +++ b/backend/database/index.js @@ -1,5 +1,4 @@ const mongoose = require('mongoose'); -require('../config/dotenv'); const db = () => { return mongoose diff --git a/backend/package.json b/backend/package.json index ab5571b5..9685b0c6 100644 --- a/backend/package.json +++ b/backend/package.json @@ -17,6 +17,7 @@ "aws-sdk": "^2.739.0", "bcryptjs": "^2.4.3", "cookie-parser": "^1.4.5", + "cors": "^2.8.5", "cross-env": "^7.0.3", "dotenv": "^8.2.0", "express": "^4.17.1", diff --git a/backend/server.js b/backend/server.js index 5824b0ad..1296a4c1 100644 --- a/backend/server.js +++ b/backend/server.js @@ -5,7 +5,7 @@ const db = require('./database/index') const port = process.env.PORT || 8080; (async () => { - + // Connect to DB await db(); diff --git a/backend/yarn.lock b/backend/yarn.lock index 46d6d083..0a9c0b0c 100644 --- a/backend/yarn.lock +++ b/backend/yarn.lock @@ -959,6 +959,14 @@ core-util-is@1.0.2, core-util-is@~1.0.0: resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= +cors@^2.8.5: + version "2.8.5" + resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" + integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== + dependencies: + object-assign "^4" + vary "^1" + cross-env@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-7.0.3.tgz#865264b29677dc015ba8418918965dd232fc54cf" @@ -2668,7 +2676,7 @@ oauth-sign@~0.9.0: resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== -object-assign@^4.1.1: +object-assign@^4, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= @@ -3703,7 +3711,7 @@ validator@^13.1.17: resolved "https://registry.yarnpkg.com/validator/-/validator-13.5.2.tgz#c97ae63ed4224999fb6f42c91eaca9567fe69a46" integrity sha512-mD45p0rvHVBlY2Zuy3F3ESIe1h5X58GPfAtslBjY7EtTqGquZTj+VX/J4RnHWN8FKq0C9WRVt1oWAcytWRuYLQ== -vary@~1.1.2: +vary@^1, vary@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= @@ -3911,11 +3919,6 @@ yargs@^15.0.2: y18n "^4.0.0" yargs-parser "^18.1.2" -yarn@^1.22.10: - version "1.22.10" - resolved "https://registry.yarnpkg.com/yarn/-/yarn-1.22.10.tgz#c99daa06257c80f8fa2c3f1490724e394c26b18c" - integrity sha512-IanQGI9RRPAN87VGTF7zs2uxkSyQSrSPsju0COgbsKQOOXr5LtcVPeyXWgwVa0ywG3d8dg6kSYKGBuYK021qeA== - yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" diff --git a/frontend/package.json b/frontend/package.json index 77052168..6106abc6 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -8,11 +8,17 @@ "@testing-library/react": "^9.3.2", "@testing-library/user-event": "^7.1.2", "axios": "^0.21.1", + "js-cookie": "^2.2.1", + "jwt-decode": "^3.1.2", "node-sass": "^4.14.1", "react": "^16.13.1", "react-dom": "^17.0.2", + "react-redux": "^7.2.3", "react-router-dom": "^5.2.0", - "react-scripts": "^4.0.3" + "react-scripts": "^4.0.3", + "redux": "^4.0.5", + "redux-thunk": "^2.3.0", + "remove": "^0.1.5" }, "scripts": { "start": "react-scripts start", diff --git a/frontend/src/App.js b/frontend/src/App.js index 1aa60a71..4c941c1f 100644 --- a/frontend/src/App.js +++ b/frontend/src/App.js @@ -12,7 +12,7 @@ import { Header } from "./components/Header/index"; import { Home } from "./pages/Home/index"; import { Registration } from "./pages/Registration/index"; import { Login } from "./pages/Login/index"; -import {AboutUs} from "./pages/AboutUs/index"; +import { AboutUs } from "./pages/AboutUs/index"; import AdminProfile from "./pages/adminProfile.jsx"; import { OrganizationList } from "./pages/OrganizationList/index"; import { Stories } from "./pages/Stories/index"; @@ -24,25 +24,38 @@ import { CodeOfConduct } from "./pages/CodeOfConduct/index"; // images import avatar_image from "./images/placeholder-images/avatar.png"; +// redux +import store from "./redux/store"; +import { Provider } from "react-redux"; +import { isLoggedIn } from "./redux/action/userAction"; function App() { + + // check whether token expire or not + React.useEffect(() => { + store.dispatch(isLoggedIn()) + }) + return ( - -
- - - - - - - - - - - - - -