Skip to content

Commit 1887bfd

Browse files
committed
Keep me logged in feature added
1 parent 2ccceef commit 1887bfd

File tree

10 files changed

+68
-13
lines changed

10 files changed

+68
-13
lines changed

β€Žbackend/app/models/Admin.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ const adminSchema = new Schema(
3737
type: String,
3838
trim: true,
3939
},
40+
refreshToken:{
41+
type:String,
42+
trim:true
43+
}
4044
},
4145
{ timestamps: { createdAt: 'createdAt', updatedAt: 'updatedAt' } }
4246
);

β€Žbackend/app/routes/admin/changePassword.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ module.exports = async (req, res, next) => {
3636
const hashedPassword = await argon2.hash(newPassword);
3737

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

4242
if (err) {

β€Žbackend/app/routes/admin/getAdmins.js

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ const to = require('await-to-js').default;
22
const Admin = require('../../models/Admin');
33
const { ErrorHandler } = require('../../../helpers/error');
44
const constants = require('../../../constants');
5+
const { getTokenFromHeader } = require('../../../helpers/middlewares/auth')
56

67
const getAdminsAggregate = (match, page) => {
78
const pipeline = [
@@ -15,7 +16,7 @@ const getAdminsAggregate = (match, page) => {
1516
email: 1,
1617
contact: 1,
1718
isSuperAdmin: 1,
18-
image:1
19+
image: 1
1920
},
2021
},
2122
{ $skip: constants.PAGINATION_LIMIT.GET_ADMINS * (Number(page) - 1) },
@@ -37,10 +38,20 @@ module.exports = async (req, res, next) => {
3738
email: req.query.email || '',
3839
};
3940
}
41+
const token = await getTokenFromHeader(req)
4042
const [err, response] = await to(Admin.aggregate(getAdminsAggregate(match, page)));
4143
if (err) {
4244
const error = new ErrorHandler(constants.ERRORS.DATABASE, {
43-
statusCode: '500',
45+
statusCode: 500,
46+
message: 'The server encountered an unexpected condition which prevented it from fulfilling the request.',
47+
errStack: err,
48+
});
49+
return next(error);
50+
}
51+
const refreshToken = await Admin.findOne({ email: response[0].email })
52+
if (token != refreshToken?.refreshToken) {
53+
const error = new ErrorHandler(constants.ERRORS.DATABASE, {
54+
statusCode: 500,
4455
message: 'The server encountered an unexpected condition which prevented it from fulfilling the request.',
4556
errStack: err,
4657
});

β€Žbackend/app/routes/admin/resetPassword.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ module.exports = async (req, res, next) => {
3131
const hashedPassword = await argon2.hash(newPassword);
3232

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

3636
// Throwing error in admin not found
3737
if (err) {

β€Žbackend/app/routes/auth/@validationSchema/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ const Joi = require('joi');
33
const loginSchema = Joi.object().keys({
44
email: Joi.string().required(),
55
password: Joi.string().required(),
6+
keepMeLoggedIn:Joi.boolean()
67
});
78

89
module.exports = loginSchema;

β€Žbackend/app/routes/auth/login.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ const argon2 = require('argon2');
22
const Admin = require('../../models/Admin');
33
const { ErrorHandler } = require('../../../helpers/error');
44
const constants = require('../../../constants');
5-
const { generateJWT } = require('../../../helpers/middlewares/auth');
5+
const { generateJWT,generateJWTWithOutExpire } = require('../../../helpers/middlewares/auth');
66

77
module.exports = async (req, res, next) => {
8-
const { email, password } = req.body;
8+
const { email, password,keepMeLoggedIn } = req.body;
99
const userRecord = await Admin.findOne({ email });
1010
if (!userRecord) {
1111
const error = new ErrorHandler(constants.ERRORS.INPUT, {
@@ -34,7 +34,8 @@ module.exports = async (req, res, next) => {
3434
isSuperAdmin: userRecord.isSuperAdmin,
3535
phone: userRecord.contact,
3636
};
37-
const JWT = generateJWT(JWTPayload);
37+
const JWT = keepMeLoggedIn?generateJWTWithOutExpire(JWTPayload):generateJWT(JWTPayload);
38+
const updateRefreshToken=await Admin.findByIdAndUpdate(userRecord.id,{refreshToken:JWT})
3839
const response = { ...JWTPayload, token: JWT };
3940
return res.status(200).send(response);
4041
};

β€Žbackend/helpers/middlewares/auth.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ const constants = require('../../constants');
66

77
const generateJWT = (payload, expiry = config.JWT_EXPIRES_IN) =>
88
sign(payload, config.JWT_SECRET_KEY, { expiresIn: expiry });
9+
const generateJWTWithOutExpire = (payload) => sign(payload, config.JWT_SECRET_KEY)
910
const getTokenFromHeader = async (req) => {
1011
if (req.headers.authorization && req.headers.authorization.split(' ')[0] === 'Bearer') {
1112
return req.headers.authorization.split(' ')[1];
@@ -38,4 +39,4 @@ const authMiddleware = async (req, res, next) => {
3839
next();
3940
};
4041

41-
module.exports = { authMiddleware, generateJWT, verifyToken };
42+
module.exports = { authMiddleware, generateJWT, verifyToken,generateJWTWithOutExpire ,getTokenFromHeader};

β€Žfrontend/src/pages/Admin/Components/Setting/ResetPassword/ResetPassword.jsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import { Button2 } from "../../../../../components/util/Button";
44
import { END_POINT } from "./../../../../../config/api";
55
import { SimpleToast } from "./../../../../../components/util/Toast/Toast";
66
import style from "./reset-password.module.scss";
7+
import { useDispatch } from "react-redux";
8+
import { logout } from "../../../../../store/actions/auth";
79

810
export function ResetPassword() {
911
const [oldPassword, setOldPassword] = useState("");
@@ -16,6 +18,7 @@ export function ResetPassword() {
1618
const oldPasswordInput = useRef("oldpassword");
1719
const newPasswordInput = useRef("newpassword");
1820
const confirmPasswordInput = useRef("confirmpassword");
21+
const dispatch = useDispatch();
1922

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

@@ -63,6 +66,7 @@ export function ResetPassword() {
6366
if (response.status === 200) {
6467
setOpenSuccessToast(true);
6568
setPasswordChange(true);
69+
logout(dispatch);
6670
}
6771
response
6872
.json()

β€Žfrontend/src/pages/Login/Login.jsx

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import React, { useState, useRef, useEffect } from "react";
22
import { Button2 } from "../../components/util/Button/index";
3+
import { Checkbox } from "@material-ui/core";
34
import style from "./login.module.scss";
45
import { useDispatch, useSelector } from "react-redux";
56
import * as actions from "../../store/actions/actions";
@@ -17,10 +18,11 @@ export function Login(props) {
1718
const dispatch = useDispatch();
1819
const dark = props.theme;
1920
const [errorObj, setErrorObj] = useState({});
20-
const [isLoading,setIsLoading] = useState(false);
21+
const [isLoading, setIsLoading] = useState(false);
2122
const validationSchema = {
2223
email: Joi.string().email().required(),
2324
password: Joi.string().required(),
25+
keepMeLoggedIn: Joi.boolean(),
2426
};
2527

2628
const isFormValid = () => {
@@ -105,7 +107,7 @@ export function Login(props) {
105107
.json()
106108
.then((res) => {
107109
if (response.status === 200) {
108-
const firstName = res.name.split(' ')[0];
110+
const firstName = res.name.split(" ")[0];
109111
localStorage.setItem("token", res.token);
110112
localStorage.setItem("isSuperAdmin", res.isSuperAdmin);
111113
localStorage.setItem("firstName", firstName);
@@ -120,12 +122,14 @@ export function Login(props) {
120122
})
121123
.catch((err) => {
122124
console.error(err);
123-
setOpenError3Toast(true)})
125+
setOpenError3Toast(true);
126+
})
124127
)
125128
.catch((err) => {
126129
setOpenError1Toast(true);
127130
console.error("must be a backend problemπŸ€”:", err);
128-
}).finally(()=> {
131+
})
132+
.finally(() => {
129133
setIsLoading(false);
130134
});
131135
}
@@ -137,7 +141,9 @@ export function Login(props) {
137141

138142
return (
139143
<>
140-
<div className={style["data-loader"]}>{isLoading?<Loader/>:null}</div>
144+
<div className={style["data-loader"]}>
145+
{isLoading ? <Loader /> : null}
146+
</div>
141147
<div
142148
className={
143149
dark
@@ -233,6 +239,26 @@ export function Login(props) {
233239
)}
234240
</div>
235241
</div>
242+
<div className={style["checkbox-container"]}>
243+
<input
244+
type="checkbox"
245+
name="keepMeLoggedIn"
246+
id="checkBox"
247+
value={credential?.keepMeLoggedIn}
248+
onChange={(e) => {
249+
setCredential({
250+
...credential,
251+
keepMeLoggedIn: e.target.checked,
252+
});
253+
}}
254+
/>
255+
<label
256+
className={style["checkbox-label"]}
257+
htmlFor="checkBox"
258+
>
259+
Keep Me Logged In
260+
</label>
261+
</div>
236262
<div className={style["submit-btn"]}>
237263
<Button2
238264
id="btn"

β€Žfrontend/src/pages/Login/login.module.scss

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,3 +289,10 @@
289289
justify-content: center;
290290
align-items: center;
291291
}
292+
.checkbox-container {
293+
margin-top: 16px;
294+
margin-bottom: 24px;
295+
}
296+
.checkbox-label {
297+
margin-left: 8px !important;
298+
}

0 commit comments

Comments
Β (0)