Skip to content

Commit

Permalink
🌸 Feature : Keep me logged In feature added (#1129)
Browse files Browse the repository at this point in the history
* Upvote and Downvotes fixed

* Keep me logged in feature added
  • Loading branch information
BHS-Harish authored Aug 10, 2024
1 parent 6692aa6 commit 09e05bf
Show file tree
Hide file tree
Showing 10 changed files with 68 additions and 13 deletions.
4 changes: 4 additions & 0 deletions backend/app/models/Admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ const adminSchema = new Schema(
type: String,
trim: true,
},
refreshToken:{
type:String,
trim:true
}
},
{ timestamps: { createdAt: 'createdAt', updatedAt: 'updatedAt' } }
);
Expand Down
2 changes: 1 addition & 1 deletion backend/app/routes/admin/changePassword.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ module.exports = async (req, res, next) => {
const hashedPassword = await argon2.hash(newPassword);

const [err] = await to(
Admin.findOneAndUpdate({ email: userRecord.email }, { $set: { passwordHash: hashedPassword } })
Admin.findOneAndUpdate({ email: userRecord.email }, { $set: { passwordHash: hashedPassword,refreshToken:"" } })
);

if (err) {
Expand Down
15 changes: 13 additions & 2 deletions backend/app/routes/admin/getAdmins.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const to = require('await-to-js').default;
const Admin = require('../../models/Admin');
const { ErrorHandler } = require('../../../helpers/error');
const constants = require('../../../constants');
const { getTokenFromHeader } = require('../../../helpers/middlewares/auth')

const getAdminsAggregate = (match, page) => {
const pipeline = [
Expand All @@ -15,7 +16,7 @@ const getAdminsAggregate = (match, page) => {
email: 1,
contact: 1,
isSuperAdmin: 1,
image:1
image: 1
},
},
{ $skip: constants.PAGINATION_LIMIT.GET_ADMINS * (Number(page) - 1) },
Expand All @@ -37,10 +38,20 @@ module.exports = async (req, res, next) => {
email: req.query.email || '',
};
}
const token = await getTokenFromHeader(req)
const [err, response] = await to(Admin.aggregate(getAdminsAggregate(match, page)));
if (err) {
const error = new ErrorHandler(constants.ERRORS.DATABASE, {
statusCode: '500',
statusCode: 500,
message: 'The server encountered an unexpected condition which prevented it from fulfilling the request.',
errStack: err,
});
return next(error);
}
const refreshToken = await Admin.findOne({ email: response[0].email })
if (token != refreshToken?.refreshToken) {
const error = new ErrorHandler(constants.ERRORS.DATABASE, {
statusCode: 500,
message: 'The server encountered an unexpected condition which prevented it from fulfilling the request.',
errStack: err,
});
Expand Down
2 changes: 1 addition & 1 deletion backend/app/routes/admin/resetPassword.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ module.exports = async (req, res, next) => {
const hashedPassword = await argon2.hash(newPassword);

// Finding and updating the admin password
const [err] = await to(Admin.findOneAndUpdate({ email }, { passwordHash: hashedPassword }, { new: true }));
const [err] = await to(Admin.findOneAndUpdate({ email }, { passwordHash: hashedPassword,refreshToken:"" }, { new: true }));

// Throwing error in admin not found
if (err) {
Expand Down
1 change: 1 addition & 0 deletions backend/app/routes/auth/@validationSchema/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ const Joi = require('joi');
const loginSchema = Joi.object().keys({
email: Joi.string().required(),
password: Joi.string().required(),
keepMeLoggedIn:Joi.boolean()
});

module.exports = loginSchema;
7 changes: 4 additions & 3 deletions backend/app/routes/auth/login.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ const argon2 = require('argon2');
const Admin = require('../../models/Admin');
const { ErrorHandler } = require('../../../helpers/error');
const constants = require('../../../constants');
const { generateJWT } = require('../../../helpers/middlewares/auth');
const { generateJWT,generateJWTWithOutExpire } = require('../../../helpers/middlewares/auth');

module.exports = async (req, res, next) => {
const { email, password } = req.body;
const { email, password,keepMeLoggedIn } = req.body;
const userRecord = await Admin.findOne({ email });
if (!userRecord) {
const error = new ErrorHandler(constants.ERRORS.INPUT, {
Expand Down Expand Up @@ -34,7 +34,8 @@ module.exports = async (req, res, next) => {
isSuperAdmin: userRecord.isSuperAdmin,
phone: userRecord.contact,
};
const JWT = generateJWT(JWTPayload);
const JWT = keepMeLoggedIn?generateJWTWithOutExpire(JWTPayload):generateJWT(JWTPayload);
const updateRefreshToken=await Admin.findByIdAndUpdate(userRecord.id,{refreshToken:JWT})
const response = { ...JWTPayload, token: JWT };
return res.status(200).send(response);
};
3 changes: 2 additions & 1 deletion backend/helpers/middlewares/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const constants = require('../../constants');

const generateJWT = (payload, expiry = config.JWT_EXPIRES_IN) =>
sign(payload, config.JWT_SECRET_KEY, { expiresIn: expiry });
const generateJWTWithOutExpire = (payload) => sign(payload, config.JWT_SECRET_KEY)
const getTokenFromHeader = async (req) => {
if (req.headers.authorization && req.headers.authorization.split(' ')[0] === 'Bearer') {
return req.headers.authorization.split(' ')[1];
Expand Down Expand Up @@ -38,4 +39,4 @@ const authMiddleware = async (req, res, next) => {
next();
};

module.exports = { authMiddleware, generateJWT, verifyToken };
module.exports = { authMiddleware, generateJWT, verifyToken,generateJWTWithOutExpire ,getTokenFromHeader};
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { Button2 } from "../../../../../components/util/Button";
import { END_POINT } from "./../../../../../config/api";
import { SimpleToast } from "./../../../../../components/util/Toast/Toast";
import style from "./reset-password.module.scss";
import { useDispatch } from "react-redux";
import { logout } from "../../../../../store/actions/auth";

export function ResetPassword() {
const [oldPassword, setOldPassword] = useState("");
Expand All @@ -16,6 +18,7 @@ export function ResetPassword() {
const oldPasswordInput = useRef("oldpassword");
const newPasswordInput = useRef("newpassword");
const confirmPasswordInput = useRef("confirmpassword");
const dispatch = useDispatch();

const token = useSelector((state) => state.token);

Expand Down Expand Up @@ -63,6 +66,7 @@ export function ResetPassword() {
if (response.status === 200) {
setOpenSuccessToast(true);
setPasswordChange(true);
logout(dispatch);
}
response
.json()
Expand Down
36 changes: 31 additions & 5 deletions frontend/src/pages/Login/Login.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, { useState, useRef, useEffect } from "react";
import { Button2 } from "../../components/util/Button/index";
import { Checkbox } from "@material-ui/core";
import style from "./login.module.scss";
import { useDispatch, useSelector } from "react-redux";
import * as actions from "../../store/actions/actions";
Expand All @@ -17,10 +18,11 @@ export function Login(props) {
const dispatch = useDispatch();
const dark = props.theme;
const [errorObj, setErrorObj] = useState({});
const [isLoading,setIsLoading] = useState(false);
const [isLoading, setIsLoading] = useState(false);
const validationSchema = {
email: Joi.string().email().required(),
password: Joi.string().required(),
keepMeLoggedIn: Joi.boolean(),
};

const isFormValid = () => {
Expand Down Expand Up @@ -105,7 +107,7 @@ export function Login(props) {
.json()
.then((res) => {
if (response.status === 200) {
const firstName = res.name.split(' ')[0];
const firstName = res.name.split(" ")[0];
localStorage.setItem("token", res.token);
localStorage.setItem("isSuperAdmin", res.isSuperAdmin);
localStorage.setItem("firstName", firstName);
Expand All @@ -120,12 +122,14 @@ export function Login(props) {
})
.catch((err) => {
console.error(err);
setOpenError3Toast(true)})
setOpenError3Toast(true);
})
)
.catch((err) => {
setOpenError1Toast(true);
console.error("must be a backend problemπŸ€”:", err);
}).finally(()=> {
})
.finally(() => {
setIsLoading(false);
});
}
Expand All @@ -137,7 +141,9 @@ export function Login(props) {

return (
<>
<div className={style["data-loader"]}>{isLoading?<Loader/>:null}</div>
<div className={style["data-loader"]}>
{isLoading ? <Loader /> : null}
</div>
<div
className={
dark
Expand Down Expand Up @@ -233,6 +239,26 @@ export function Login(props) {
)}
</div>
</div>
<div className={style["checkbox-container"]}>
<input
type="checkbox"
name="keepMeLoggedIn"
id="checkBox"
value={credential?.keepMeLoggedIn}
onChange={(e) => {
setCredential({
...credential,
keepMeLoggedIn: e.target.checked,
});
}}
/>
<label
className={style["checkbox-label"]}
htmlFor="checkBox"
>
Keep Me Logged In
</label>
</div>
<div className={style["submit-btn"]}>
<Button2
id="btn"
Expand Down
7 changes: 7 additions & 0 deletions frontend/src/pages/Login/login.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -289,3 +289,10 @@
justify-content: center;
align-items: center;
}
.checkbox-container {
margin-top: 16px;
margin-bottom: 24px;
}
.checkbox-label {
margin-left: 8px !important;
}

0 comments on commit 09e05bf

Please sign in to comment.