Browse Source

Added access token and authentication interceptors

master
Lazar Kostic 3 years ago
parent
commit
3aa126d45d

+ 1
- 1
.env View File

@@ -1,2 +1,2 @@

REACT_APP_BASE_API_URL=https://portalgatewayapi.bullioninternational.info/
REACT_APP_BASE_API_URL=http://localhost:4000/

+ 172
- 173
src/pages/LoginPage/LoginPageMUI.js View File

@@ -1,190 +1,189 @@
/* eslint-disable */
import React, { useEffect, useState } from 'react';
import PropTypes from 'prop-types';
import { useFormik } from 'formik';
import { useDispatch, useSelector } from 'react-redux';
import { NavLink } from 'react-router-dom';
import * as Yup from 'yup';
import { useTranslation } from 'react-i18next';
import React, { useEffect, useState } from "react";
import PropTypes from "prop-types";
import { useFormik } from "formik";
import { useDispatch, useSelector } from "react-redux";
import { NavLink } from "react-router-dom";
import { useTranslation } from "react-i18next";
import {
clearLoginErrors,
fetchUser,
} from '../../store/actions/login/loginActions';
import { selectLoginError } from '../../store/selectors/loginSelectors';
import { FORGOT_PASSWORD_PAGE, HOME_PAGE } from '../../constants/pages';
clearLoginErrors,
fetchUser,
} from "../../store/actions/login/loginActions";
import { selectLoginError } from "../../store/selectors/loginSelectors";
import { FORGOT_PASSWORD_PAGE, HOME_PAGE } from "../../constants/pages";
import {
Box,
Button,
Container,
Grid,
IconButton,
InputAdornment,
Link,
TextField,
Typography,
} from '@mui/material';
import { Visibility, VisibilityOff } from '@mui/icons-material';
import Backdrop from '../../components/MUI/BackdropComponent';
import ErrorMessage from '../../components/MUI/ErrorMessageComponent';
import { selectIsLoadingByActionType } from '../../store/selectors/loadingSelectors';
import { LOGIN_USER_LOADING } from '../../store/actions/login/loginActionConstants';
import loginValidation from '../../validations/loginValidation';
import loginInitialValues from '../../initialValues/loginInitialValues';
Box,
Button,
Container,
Grid,
IconButton,
InputAdornment,
Link,
TextField,
Typography,
} from "@mui/material";
import { Visibility, VisibilityOff } from "@mui/icons-material";
import Backdrop from "../../components/MUI/BackdropComponent";
import ErrorMessage from "../../components/MUI/ErrorMessageComponent";
import { selectIsLoadingByActionType } from "../../store/selectors/loadingSelectors";
import {
LOGIN_USER_SCOPE,
} from "../../store/actions/login/loginActionConstants";
import loginValidation from "../../validations/loginValidation";
import loginInitialValues from "../../initialValues/loginInitialValues";

const LoginPage = ({ history }) => {
const dispatch = useDispatch();
const { t } = useTranslation();
const error = useSelector(selectLoginError);
const dispatch = useDispatch();
const { t } = useTranslation();
const error = useSelector(selectLoginError);

const [showPassword, setShowPassword] = useState(false);
const handleClickShowPassword = () => setShowPassword(!showPassword);
const handleMouseDownPassword = () => setShowPassword(!showPassword);
const [showPassword, setShowPassword] = useState(false);
const handleClickShowPassword = () => setShowPassword(!showPassword);
const handleMouseDownPassword = () => setShowPassword(!showPassword);

// Clear login errors when user firstly enters the page
useEffect(() => {
dispatch(clearLoginErrors())
}, [])
// Clear login errors when user firstly enters the page
useEffect(() => {
dispatch(clearLoginErrors());
}, []);

const isLoading = useSelector(
selectIsLoadingByActionType(LOGIN_USER_LOADING)
);
const isLoading = useSelector(selectIsLoadingByActionType(LOGIN_USER_SCOPE));

const handleApiResponseSuccess = () => {
history.push({
pathname: HOME_PAGE,
state: {
from: history.location.pathname,
},
});
};
const handleApiResponseSuccess = () => {
history.push({
pathname: HOME_PAGE,
state: {
from: history.location.pathname,
},
});
};

const handleSubmit = (values) => {
const { email: Username, password: Password } = values;
dispatch(clearLoginErrors());
dispatch(
fetchUser({
Username,
Password,
handleApiResponseSuccess,
})
);
};
const handleSubmit = (values) => {
const { email, password} = values;
dispatch(clearLoginErrors());
dispatch(
fetchUser({
email,
password,
handleApiResponseSuccess,
})
);
};

const formik = useFormik({
initialValues: loginInitialValues,
validationSchema: loginValidation,
onSubmit: handleSubmit,
validateOnBlur: true,
enableReinitialize: true,
});
const formik = useFormik({
initialValues: loginInitialValues,
validationSchema: loginValidation,
onSubmit: handleSubmit,
validateOnBlur: true,
enableReinitialize: true,
});

return (
<Container component="main" maxWidth="md">
<Box
sx={{
marginTop: 32,
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
}}
>
<Typography component="h1" variant="h5">
{t('login.logInTitle')}
</Typography>
{error && <ErrorMessage error={error} />}
<Box
component="form"
onSubmit={formik.handleSubmit}
sx={{ position: 'relative', mt: 1, p: 1 }}
>
<Backdrop position="absolute" isLoading={isLoading} />
<TextField
name="email"
label={t('common.labelEmail')}
margin="normal"
value={formik.values.email}
onChange={formik.handleChange}
error={formik.touched.email && Boolean(formik.errors.email)}
helperText={formik.touched.email && formik.errors.email}
autoFocus
fullWidth
/>
<TextField
name="password"
label={t('common.labelPassword')}
margin="normal"
type={showPassword ? 'text' : 'password'}
value={formik.values.password}
onChange={formik.handleChange}
error={formik.touched.password && Boolean(formik.errors.password)}
helperText={formik.touched.password && formik.errors.password}
fullWidth
InputProps={{
endAdornment: (
<InputAdornment position="end">
<IconButton
onClick={handleClickShowPassword}
onMouseDown={handleMouseDownPassword}
>
{showPassword ? <Visibility /> : <VisibilityOff />}
</IconButton>
</InputAdornment>
),
}}
/>
<Button
type="submit"
variant="contained"
sx={{ mt: 3, mb: 2 }}
fullWidth
>
{t('login.logIn')}
</Button>
<Grid container>
<Grid
item
xs={12}
md={6}
sx={{ textAlign: { xs: 'center', md: 'left' } }}
>
<Link
to={FORGOT_PASSWORD_PAGE}
component={NavLink}
variant="body2"
underline="hover"
>
{t('login.forgotYourPassword')}
</Link>
</Grid>
<Grid
item
xs={12}
md={6}
sx={{ textAlign: { xs: 'center', md: 'right' } }}
>
<Link
to="#"
component={NavLink}
variant="body2"
underline="hover"
>
{t('login.dontHaveAccount')}
</Link>
</Grid>
</Grid>
</Box>
</Box>
</Container>
);
return (
<Container component="main" maxWidth="md">
<Box
sx={{
marginTop: 32,
display: "flex",
flexDirection: "column",
alignItems: "center",
}}
>
<Typography component="h1" variant="h5">
{t("login.logInTitle")}
</Typography>
{error && <ErrorMessage error={error} />}
<Box
component="form"
onSubmit={formik.handleSubmit}
sx={{ position: "relative", mt: 1, p: 1 }}
>
<Backdrop position="absolute" isLoading={isLoading} />
<TextField
name="email"
label={t("common.labelEmail")}
margin="normal"
value={formik.values.email}
onChange={formik.handleChange}
error={formik.touched.email && Boolean(formik.errors.email)}
helperText={formik.touched.email && formik.errors.email}
autoFocus
fullWidth
/>
<TextField
name="password"
label={t("common.labelPassword")}
margin="normal"
type={showPassword ? "text" : "password"}
value={formik.values.password}
onChange={formik.handleChange}
error={formik.touched.password && Boolean(formik.errors.password)}
helperText={formik.touched.password && formik.errors.password}
fullWidth
InputProps={{
endAdornment: (
<InputAdornment position="end">
<IconButton
onClick={handleClickShowPassword}
onMouseDown={handleMouseDownPassword}
>
{showPassword ? <Visibility /> : <VisibilityOff />}
</IconButton>
</InputAdornment>
),
}}
/>
<Button
type="submit"
variant="contained"
sx={{ mt: 3, mb: 2 }}
fullWidth
>
{t("login.logIn")}
</Button>
<Grid container>
<Grid
item
xs={12}
md={6}
sx={{ textAlign: { xs: "center", md: "left" } }}
>
<Link
to={FORGOT_PASSWORD_PAGE}
component={NavLink}
variant="body2"
underline="hover"
>
{t("login.forgotYourPassword")}
</Link>
</Grid>
<Grid
item
xs={12}
md={6}
sx={{ textAlign: { xs: "center", md: "right" } }}
>
<Link
to="#"
component={NavLink}
variant="body2"
underline="hover"
>
{t("login.dontHaveAccount")}
</Link>
</Grid>
</Grid>
</Box>
</Box>
</Container>
);
};

LoginPage.propTypes = {
history: PropTypes.shape({
replace: PropTypes.func,
push: PropTypes.func,
location: PropTypes.shape({
pathname: PropTypes.string,
}),
}),
history: PropTypes.shape({
replace: PropTypes.func,
push: PropTypes.func,
location: PropTypes.shape({
pathname: PropTypes.string,
}),
}),
};
export default LoginPage;

+ 3
- 3
src/request/apiEndpoints.js View File

@@ -17,12 +17,12 @@ export default {
},
authentications: {
getUsernames: 'authenticate/usernames',
login: 'authenticate',
login: 'auth/token',
getUserSecurityQuestion: 'users/username/securityquestion',
confirmSecurityQuestion: 'authenticate/confirm',
confirmForgotPassword: 'users/passwords/reset_token',
resetPassword: 'users/passwords',
refreshToken: '/authenticate/refresh',
refreshToken: 'auth/refresh',
generateToken: '/authenticate/generate',
authenticate:
'/authenticate?fp={fp}&offer={offer}&landingPageUrl={landingPageUrl}&registrationFlowType={registrationFlowType}',
@@ -108,7 +108,7 @@ export default {
getRegistrationAccounts: '/users/{userUid}/accounts',
updateUser: '/users/{userUid}?updateUserActionType={actionType}',
updateUserPassword: '/users/{userUid}/passwords',
logout: '/users/{userUid}/logout',
logout: 'auth/logout',
getUsernames: '/users/email',
createUser:
'/users?fp={fp}&offer={offer}&landingPageUrl={landingPageUrl}&registrationFlowType={registrationFlowType}',

+ 4
- 4
src/request/index.js View File

@@ -1,14 +1,14 @@
import axios from 'axios';
import queryString from 'qs';
// import queryString from 'qs';

const request = axios.create({
baseURL: process.env.REACT_APP_BASE_API_URL,
headers: {
'Content-Type': 'application/json',
},
withCredentials: true,
paramsSerializer: (params) =>
queryString.stringify(params, { arrayFormat: 'comma' }),
// withCredentials: true,
// paramsSerializer: (params) =>
// queryString.stringify(params, { arrayFormat: 'comma' }),
});

export const getRequest = (url, params = null, options = null) =>

+ 4
- 8
src/request/loginRequest.js View File

@@ -1,5 +1,5 @@
import { getRequest, postRequest, replaceInUrl } from './index';
import apiEndpoints from './apiEndpoints';
import { getRequest, postRequest } from "./index";
import apiEndpoints from "./apiEndpoints";

export const getUsernames = (emailorusername) =>
getRequest(apiEndpoints.authentications.getUsernames, {
@@ -15,12 +15,8 @@ export const updateSecurityAnswer = (payload) =>
export const refreshTokenRequest = (payload) =>
postRequest(apiEndpoints.authentications.refreshToken, payload);

export const logoutUserRequest = (userUid) =>
postRequest(
replaceInUrl(apiEndpoints.users.logout, {
userUid,
}),
);
export const logoutUserRequest = (payload) =>
postRequest(apiEndpoints.users.logout, payload);

export const generateTokenRequest = (payload) =>
postRequest(apiEndpoints.authentications.generateToken, payload);

+ 4
- 2
src/store/actions/app/appActionConstants.js View File

@@ -1,3 +1,5 @@
import { createLoadingType } from '../actionHelpers';
import { createLoadingType } from "../actionHelpers";

export const APP_LOADING = createLoadingType('APP_LOADING');
export const APP_LOADING = createLoadingType("APP_LOADING");
export const ADD_LOADER = createLoadingType("ADD_LOADER");
export const REMOVE_LOADER = createLoadingType("REMOVE_LOADER");

+ 9
- 3
src/store/actions/app/appActions.js View File

@@ -1,5 +1,11 @@
import { APP_LOADING } from './appActionConstants';
import { ADD_LOADER, REMOVE_LOADER } from "./appActionConstants";

export const setAppReady = () => ({
type: APP_LOADING,
export const addLoader = (payload) => ({
type: ADD_LOADER,
payload,
});

export const removeLoader = (payload) => ({
type: REMOVE_LOADER,
payload,
});

+ 1
- 1
src/store/actions/login/loginActionConstants.js View File

@@ -8,7 +8,7 @@ import {
} from '../actionHelpers';


const LOGIN_USER_SCOPE = 'LOGIN_USER';
export const LOGIN_USER_SCOPE = 'LOGIN_USER';
export const LOGIN_USER_FETCH = createFetchType(LOGIN_USER_SCOPE);
export const LOGIN_USER_SUCCESS = createSuccessType(LOGIN_USER_SCOPE);
export const LOGIN_USER_ERROR = createErrorType(LOGIN_USER_SCOPE);

+ 2
- 1
src/store/actions/login/loginActions.js View File

@@ -50,8 +50,9 @@ export const logoutUser = () => ({
type: LOGOUT_USER,
});

export const refreshUserToken = () => ({
export const refreshUserToken = (payload) => ({
type: REFRESH_TOKEN,
payload
});

export const generateToken = (payload) => ({

+ 5
- 3
src/store/index.js View File

@@ -5,8 +5,8 @@ import rootSaga from "./saga";
import loadingMiddleware from "./middleware/loadingMiddleware";
import requestStatusMiddleware from "./middleware/requestStatusMiddleware";
import internalServerErrorMiddleware from "./middleware/internalServerErrorMiddleware";
// import accessTokenMiddleware from "./middleware/accessTokenMiddleware";
// import authenticationMiddleware from "./middleware/authenticationMiddleware";
import accessTokenMiddleware from "./middleware/accessTokenMiddleware";
import authenticationMiddleware from "./middleware/authenticationMiddleware";

const composeEnhancers =
(window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ &&
@@ -23,7 +23,9 @@ export default createStore(
sagaMiddleware,
loadingMiddleware,
requestStatusMiddleware,
internalServerErrorMiddleware
internalServerErrorMiddleware,
accessTokenMiddleware,
authenticationMiddleware
)
)
);

+ 27
- 6
src/store/middleware/accessTokenMiddleware.js View File

@@ -1,8 +1,11 @@
import axios from "axios";
import jwt from "jsonwebtoken";
import { JWT_TOKEN } from "../../constants/localStorage";
import { JWT_REFRESH_TOKEN, JWT_TOKEN } from "../../constants/localStorage";
import { attachBeforeRequestListener } from "../../request/index";
import { authScopeStringGetHelper } from "../../util/helpers/authScopeHelpers";
import { refreshUserToken } from "../actions/login/loginActions";
import {
authScopeStringGetHelper,
} from "../../util/helpers/authScopeHelpers";
import { logoutUser, refreshUserToken } from "../actions/login/loginActions";

export const accessTokensMiddlewareInterceptorName = "ACCESS_TOKEN_INTERCEPTOR";

@@ -11,19 +14,37 @@ export default ({ dispatch }) =>
(action) => {
attachBeforeRequestListener(async (response) => {
const jwtToken = authScopeStringGetHelper(JWT_TOKEN);
const refresh = authScopeStringGetHelper(JWT_REFRESH_TOKEN);
if (!jwtToken || !refresh) return Promise.resolve(response);
const jwtTokenDecoded = jwt.decode(jwtToken);
const refreshTokenDecoded = jwt.decode(refresh);
if (!response.headers?.Authorization) {
response.headers.Authorization = `Bearer ${jwtToken}`;
}

// If refresh token is expired, log out user
if (new Date() > new Date(refreshTokenDecoded?.exp * 1000)) {
dispatch(logoutUser());
return Promise.resolve(response);
}

// If access token is expired, refresh access token
if (new Date() > new Date(jwtTokenDecoded.exp * 1000)) {
console.log('response', response)
dispatch(refreshUserToken());
const axiosResponse = await axios.post(
`${process.env.REACT_APP_BASE_API_URL}auth/refresh`,
{
token: refresh,
}
);
const newToken = axiosResponse.data.newAccessToken;

response.headers.Authorization = `Bearer ${newToken}`;

dispatch(refreshUserToken(newToken));
}

return Promise.resolve(response);
}, accessTokensMiddlewareInterceptorName);

next(action);
};
};

+ 6
- 17
src/store/middleware/loadingMiddleware.js View File

@@ -6,6 +6,7 @@ import {
UPDATE,
SUBMIT,
} from '../actions/actionHelpers';
import { addLoader, removeLoader } from '../actions/app/appActions';

const promiseTypes = [FETCH, UPDATE, DELETE, SUBMIT];
export default ({ dispatch }) => (next) => (action) => {
@@ -13,28 +14,16 @@ export default ({ dispatch }) => (next) => (action) => {
action.type.includes(promiseType),
);
if (promiseType) {
dispatch({
type: 'UPDATE_LOADER',
payload: {
actionType: action.type.replace(promiseType, '[LOADING]'),
isLoading: true,
},
});
dispatch(addLoader(action.type));
return next(action);
}

if (action.type.includes(SUCCESS) || action.type.includes(ERROR)) {
const actionType = action.type.includes(SUCCESS)
? action.type.replace(SUCCESS, '[LOADING]')
: action.type.replace(ERROR, '[LOADING]');
// const actionType = action.type.includes(SUCCESS)
// ? action.type.replace(SUCCESS, '[LOADING]')
// : action.type.replace(ERROR, '[LOADING]');

dispatch({
type: 'UPDATE_LOADER',
payload: {
actionType,
isLoading: false,
},
});
dispatch(removeLoader(action.type));
return next(action);
}
next(action);

+ 1
- 1
src/store/middleware/requestStatusMiddleware.js View File

@@ -16,7 +16,7 @@ export default ({ dispatch }) =>
error.response.config.url !== apiEndpoints.authentications.login &&
error.response.config.url !==
apiEndpoints.authentications.confirmSecurityQuestion &&
error.response.status === 401
error.response.status === 4003
) {
return dispatch(logoutUser());
}

+ 27
- 18
src/store/reducers/loading/loadingReducer.js View File

@@ -1,36 +1,45 @@
import createReducer from '../../utils/createReducer';
import { APP_LOADING } from '../../actions/app/appActionConstants';
import { RESET_LOGIN_STATE } from '../../actions/login/loginActionConstants';
import createReducer from "../../utils/createReducer";
import {
ADD_LOADER,
REMOVE_LOADER,
} from "../../actions/app/appActionConstants";

const initialState = {
[APP_LOADING]: true,
loaderCount: 0,
};
export default createReducer(
{
UPDATE_LOADER: updateLoader,
[APP_LOADING]: updateAppReadyLoader,
[RESET_LOGIN_STATE]: setAppNotReady,
[ADD_LOADER]: addLoader,
[REMOVE_LOADER]: removeLoader,
},
initialState,
initialState
);

function updateLoader(state, action) {
function addLoader(state, action) {
let loaderCount = state.loaderCount;
let actionType = action.payload.replace("[FETCH]", "");
if (!state[actionType]) {
loaderCount++;
}
return {
...state,
[action.payload.actionType]: action.payload.isLoading,
[actionType]: true,
loaderCount,
};
}

function updateAppReadyLoader(state) {
return {
...state,
[APP_LOADING]: false,
};
}
function removeLoader(state, action) {
let actionType = action.payload
.replace("[SUCCESS]", "")
.replace("[ERROR]", "");
let loaderCount = state.loaderCount;
if (state[actionType] === true) {
loaderCount--;
}

function setAppNotReady(state) {
return {
...state,
[APP_LOADING]: true,
[actionType]: false,
loaderCount,
};
}

+ 5
- 1
src/store/reducers/login/loginReducer.js View File

@@ -36,7 +36,11 @@ export default createReducer(
function setUser(state, action) {
return {
...state,
token: action.payload,
token: {
...state.token,
JwtToken: action.payload.token,
JwtRefreshToken: action.payload.refresh
},
};
}


+ 30
- 90
src/store/saga/loginSaga.js View File

@@ -1,57 +1,43 @@
import { all, call, put, takeLatest } from '@redux-saga/core/effects';
import jwt from 'jsonwebtoken';
import history from '../utils/history';
import { all, call, put, takeLatest } from "@redux-saga/core/effects";
import jwt from "jsonwebtoken";
import history from "../utils/history";
import {
AUTHENTICATE_USER,
LOGIN_USER_FETCH,
LOGOUT_USER,
REFRESH_TOKEN,
GENERATE_TOKEN,
} from '../actions/login/loginActionConstants';
import {
attemptLogin,
logoutUserRequest,
refreshTokenRequest,
generateTokenRequest,
} from '../../request/loginRequest';
} from "../actions/login/loginActionConstants";
import { attemptLogin, logoutUserRequest } from "../../request/loginRequest";
import {
fetchUserError,
fetchUserSuccess,
resetLoginState,
updateUserToken,
} from '../actions/login/loginActions';
import { LOGIN_PAGE } from '../../constants/pages';
import { setUser } from '../actions/user/userActions';
import {
addHeaderToken,
removeHeaderToken,
} from '../../request';
import {
IMPERSONATE_USER_UID,
REGISTRATION_USER_UID,
} from '../../constants/sessionStorage';
} from "../actions/login/loginActions";
import { LOGIN_PAGE } from "../../constants/pages";
import { setUser } from "../actions/user/userActions";
import { addHeaderToken, removeHeaderToken } from "../../request";
import {
JWT_REFRESH_TOKEN,
JWT_TOKEN,
REFRESH_TOKEN_CONST,
} from '../../constants/localStorage';
} from "../../constants/localStorage";
import {
authScopeClearHelper,
authScopeStringGetHelper,
authScopeRemoveHelper,
authScopeSetHelper,
} from '../../util/helpers/authScopeHelpers';
import { rejectErrorCodeHelper } from '../../util/helpers/rejectErrorCodeHelper';
} from "../../util/helpers/authScopeHelpers";
import { rejectErrorCodeHelper } from "../../util/helpers/rejectErrorCodeHelper";

function* fetchUser({ payload }) {
try {
const { data } = yield call(attemptLogin, payload);
if (data.JwtToken) {
const user = jwt.decode(data.JwtToken);
yield call(authScopeSetHelper, JWT_TOKEN, data.JwtToken);
yield call(authScopeSetHelper, JWT_REFRESH_TOKEN, data.JwtRefreshToken);
yield call(authScopeSetHelper, REFRESH_TOKEN_CONST, data.RefreshToken);
yield call(addHeaderToken, data.JwtToken);
if (data?.token) {
const user = jwt.decode(data.token);
yield call(authScopeSetHelper, JWT_TOKEN, data.token);
yield call(authScopeSetHelper, JWT_REFRESH_TOKEN, data.refresh);
yield call(addHeaderToken, data.token);
yield put(setUser(user));
}
yield put(fetchUserSuccess(data));
@@ -76,7 +62,7 @@ function* authenticateUser() {
return yield put(
fetchUserSuccess({
JwtToken,
}),
})
);
} catch (error) {
const errorMessage = yield call(rejectErrorCodeHelper, error);
@@ -89,10 +75,11 @@ function* authenticateUser() {

function* logoutUser() {
try {
const JwtToken = yield call(authScopeStringGetHelper, JWT_TOKEN);
const user = jwt.decode(JwtToken);
const token = yield call(authScopeStringGetHelper, JWT_REFRESH_TOKEN);
const user = yield call(jwt.decode, token);
if (user) {
yield call(logoutUserRequest, user.UserUid);
let requestData = { token };
yield call(logoutUserRequest, requestData);
}
} catch (error) {
console.log(error); // eslint-disable-line
@@ -104,64 +91,18 @@ function* logoutUser() {
}
}

export function* refreshToken() {
try {
const JwtToken = yield call(authScopeStringGetHelper, JWT_TOKEN);
const JwtRefreshToken = yield call(
authScopeStringGetHelper,
JWT_REFRESH_TOKEN,
);

if (JwtToken && JwtRefreshToken) {
const { data } = yield call(refreshTokenRequest, {
JwtRefreshToken,
JwtToken,
});

yield call(authScopeSetHelper, JWT_TOKEN, data.JwtToken);
yield call(authScopeSetHelper, JWT_REFRESH_TOKEN, data.JwtRefreshToken);
const user = jwt.decode(data.JwtToken);
addHeaderToken(data.JwtToken);
yield put(setUser(user));
yield put(updateUserToken(data.JwtToken));
}
} catch (error) {
yield call(logoutUser);
console.log(error); // eslint-disable-line
}
}

export function* generateToken({ payload }) {
export function* refreshToken({ payload }) {
try {
const { data } = yield call(generateTokenRequest, payload.data);
const { JwtToken, JwtRefreshToken } = data;
const newTokenDecoded = jwt.decode(payload);

if (JwtToken && JwtRefreshToken) {
yield call(authScopeSetHelper, JWT_TOKEN, data.JwtToken);
yield call(authScopeSetHelper, JWT_REFRESH_TOKEN, data.JwtRefreshToken);

if (payload.impersonate) {
sessionStorage.setItem(IMPERSONATE_USER_UID, payload.accountUid);
}

if (payload.registration) {
sessionStorage.setItem(REGISTRATION_USER_UID, payload.accountUid);
}

const user = jwt.decode(data.JwtToken);
addHeaderToken(data.JwtToken);
if (user) {
yield put(setUser(user));
}
yield put(updateUserToken(data.JwtToken));

if (payload.onSuccess) {
yield call(payload.onSuccess);
}
}
yield call(authScopeSetHelper, JWT_TOKEN, payload);
addHeaderToken(payload);
yield put(setUser(newTokenDecoded));
yield put(updateUserToken(payload));
return true;
} catch (error) {
yield call(logoutUser);
console.log(error); // eslint-disable-line
return false;
}
}

@@ -171,6 +112,5 @@ export default function* loginSaga() {
takeLatest(AUTHENTICATE_USER, authenticateUser),
takeLatest(LOGOUT_USER, logoutUser),
takeLatest(REFRESH_TOKEN, refreshToken),
takeLatest(GENERATE_TOKEN, generateToken),
]);
}

+ 8
- 6
src/store/selectors/loadingSelectors.js View File

@@ -1,14 +1,16 @@
import { createSelector } from 'reselect';
import { createSelector } from "reselect";

const loadingSelector = (state) => state.loading;

export const selectIsLoadingByActionType = (loadingActionType) =>
createSelector(
loadingSelector,
(state) => state[`${loadingActionType}`] || false,
);
createSelector(loadingSelector, (state) => state[`${loadingActionType}`]);

export const selectIsLoadingByActionTypes = (actionTypes) =>
createSelector(loadingSelector, (state) =>
actionTypes.some((actionType) => state[`${actionType}`]),
actionTypes.some((actionType) => state[`${actionType}`])
);

export const selectLoaderCount = createSelector(
loadingSelector,
(state) => state.loaderCount
);

+ 0
- 0
src/themes/index.js View File


Loading…
Cancel
Save