| REACT_APP_BASE_API_URL=https://portalgatewayapi.bullioninternational.info/ | |||||
| REACT_APP_BASE_API_URL=http://localhost:4000/ |
| /* eslint-disable */ | /* 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 { | 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 { | 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 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 = { | 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; | export default LoginPage; |
| }, | }, | ||||
| authentications: { | authentications: { | ||||
| getUsernames: 'authenticate/usernames', | getUsernames: 'authenticate/usernames', | ||||
| login: 'authenticate', | |||||
| login: 'auth/token', | |||||
| getUserSecurityQuestion: 'users/username/securityquestion', | getUserSecurityQuestion: 'users/username/securityquestion', | ||||
| confirmSecurityQuestion: 'authenticate/confirm', | confirmSecurityQuestion: 'authenticate/confirm', | ||||
| confirmForgotPassword: 'users/passwords/reset_token', | confirmForgotPassword: 'users/passwords/reset_token', | ||||
| resetPassword: 'users/passwords', | resetPassword: 'users/passwords', | ||||
| refreshToken: '/authenticate/refresh', | |||||
| refreshToken: 'auth/refresh', | |||||
| generateToken: '/authenticate/generate', | generateToken: '/authenticate/generate', | ||||
| authenticate: | authenticate: | ||||
| '/authenticate?fp={fp}&offer={offer}&landingPageUrl={landingPageUrl}®istrationFlowType={registrationFlowType}', | '/authenticate?fp={fp}&offer={offer}&landingPageUrl={landingPageUrl}®istrationFlowType={registrationFlowType}', | ||||
| getRegistrationAccounts: '/users/{userUid}/accounts', | getRegistrationAccounts: '/users/{userUid}/accounts', | ||||
| updateUser: '/users/{userUid}?updateUserActionType={actionType}', | updateUser: '/users/{userUid}?updateUserActionType={actionType}', | ||||
| updateUserPassword: '/users/{userUid}/passwords', | updateUserPassword: '/users/{userUid}/passwords', | ||||
| logout: '/users/{userUid}/logout', | |||||
| logout: 'auth/logout', | |||||
| getUsernames: '/users/email', | getUsernames: '/users/email', | ||||
| createUser: | createUser: | ||||
| '/users?fp={fp}&offer={offer}&landingPageUrl={landingPageUrl}®istrationFlowType={registrationFlowType}', | '/users?fp={fp}&offer={offer}&landingPageUrl={landingPageUrl}®istrationFlowType={registrationFlowType}', |
| import axios from 'axios'; | import axios from 'axios'; | ||||
| import queryString from 'qs'; | |||||
| // import queryString from 'qs'; | |||||
| const request = axios.create({ | const request = axios.create({ | ||||
| baseURL: process.env.REACT_APP_BASE_API_URL, | baseURL: process.env.REACT_APP_BASE_API_URL, | ||||
| headers: { | headers: { | ||||
| 'Content-Type': 'application/json', | '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) => | export const getRequest = (url, params = null, options = null) => |
| import { getRequest, postRequest, replaceInUrl } from './index'; | |||||
| import apiEndpoints from './apiEndpoints'; | |||||
| import { getRequest, postRequest } from "./index"; | |||||
| import apiEndpoints from "./apiEndpoints"; | |||||
| export const getUsernames = (emailorusername) => | export const getUsernames = (emailorusername) => | ||||
| getRequest(apiEndpoints.authentications.getUsernames, { | getRequest(apiEndpoints.authentications.getUsernames, { | ||||
| export const refreshTokenRequest = (payload) => | export const refreshTokenRequest = (payload) => | ||||
| postRequest(apiEndpoints.authentications.refreshToken, 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) => | export const generateTokenRequest = (payload) => | ||||
| postRequest(apiEndpoints.authentications.generateToken, payload); | postRequest(apiEndpoints.authentications.generateToken, payload); |
| 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"); |
| 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, | |||||
| }); | }); |
| } from '../actionHelpers'; | } 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_FETCH = createFetchType(LOGIN_USER_SCOPE); | ||||
| export const LOGIN_USER_SUCCESS = createSuccessType(LOGIN_USER_SCOPE); | export const LOGIN_USER_SUCCESS = createSuccessType(LOGIN_USER_SCOPE); | ||||
| export const LOGIN_USER_ERROR = createErrorType(LOGIN_USER_SCOPE); | export const LOGIN_USER_ERROR = createErrorType(LOGIN_USER_SCOPE); |
| type: LOGOUT_USER, | type: LOGOUT_USER, | ||||
| }); | }); | ||||
| export const refreshUserToken = () => ({ | |||||
| export const refreshUserToken = (payload) => ({ | |||||
| type: REFRESH_TOKEN, | type: REFRESH_TOKEN, | ||||
| payload | |||||
| }); | }); | ||||
| export const generateToken = (payload) => ({ | export const generateToken = (payload) => ({ |
| import loadingMiddleware from "./middleware/loadingMiddleware"; | import loadingMiddleware from "./middleware/loadingMiddleware"; | ||||
| import requestStatusMiddleware from "./middleware/requestStatusMiddleware"; | import requestStatusMiddleware from "./middleware/requestStatusMiddleware"; | ||||
| import internalServerErrorMiddleware from "./middleware/internalServerErrorMiddleware"; | 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 = | const composeEnhancers = | ||||
| (window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ && | (window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ && | ||||
| sagaMiddleware, | sagaMiddleware, | ||||
| loadingMiddleware, | loadingMiddleware, | ||||
| requestStatusMiddleware, | requestStatusMiddleware, | ||||
| internalServerErrorMiddleware | |||||
| internalServerErrorMiddleware, | |||||
| accessTokenMiddleware, | |||||
| authenticationMiddleware | |||||
| ) | ) | ||||
| ) | ) | ||||
| ); | ); |
| import axios from "axios"; | |||||
| import jwt from "jsonwebtoken"; | 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 { 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"; | export const accessTokensMiddlewareInterceptorName = "ACCESS_TOKEN_INTERCEPTOR"; | ||||
| (action) => { | (action) => { | ||||
| attachBeforeRequestListener(async (response) => { | attachBeforeRequestListener(async (response) => { | ||||
| const jwtToken = authScopeStringGetHelper(JWT_TOKEN); | const jwtToken = authScopeStringGetHelper(JWT_TOKEN); | ||||
| const refresh = authScopeStringGetHelper(JWT_REFRESH_TOKEN); | |||||
| if (!jwtToken || !refresh) return Promise.resolve(response); | |||||
| const jwtTokenDecoded = jwt.decode(jwtToken); | const jwtTokenDecoded = jwt.decode(jwtToken); | ||||
| const refreshTokenDecoded = jwt.decode(refresh); | |||||
| if (!response.headers?.Authorization) { | if (!response.headers?.Authorization) { | ||||
| response.headers.Authorization = `Bearer ${jwtToken}`; | 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 access token is expired, refresh access token | ||||
| if (new Date() > new Date(jwtTokenDecoded.exp * 1000)) { | 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); | return Promise.resolve(response); | ||||
| }, accessTokensMiddlewareInterceptorName); | }, accessTokensMiddlewareInterceptorName); | ||||
| next(action); | next(action); | ||||
| }; | |||||
| }; |
| UPDATE, | UPDATE, | ||||
| SUBMIT, | SUBMIT, | ||||
| } from '../actions/actionHelpers'; | } from '../actions/actionHelpers'; | ||||
| import { addLoader, removeLoader } from '../actions/app/appActions'; | |||||
| const promiseTypes = [FETCH, UPDATE, DELETE, SUBMIT]; | const promiseTypes = [FETCH, UPDATE, DELETE, SUBMIT]; | ||||
| export default ({ dispatch }) => (next) => (action) => { | export default ({ dispatch }) => (next) => (action) => { | ||||
| action.type.includes(promiseType), | action.type.includes(promiseType), | ||||
| ); | ); | ||||
| if (promiseType) { | if (promiseType) { | ||||
| dispatch({ | |||||
| type: 'UPDATE_LOADER', | |||||
| payload: { | |||||
| actionType: action.type.replace(promiseType, '[LOADING]'), | |||||
| isLoading: true, | |||||
| }, | |||||
| }); | |||||
| dispatch(addLoader(action.type)); | |||||
| return next(action); | return next(action); | ||||
| } | } | ||||
| if (action.type.includes(SUCCESS) || action.type.includes(ERROR)) { | 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); | return next(action); | ||||
| } | } | ||||
| next(action); | next(action); |
| error.response.config.url !== apiEndpoints.authentications.login && | error.response.config.url !== apiEndpoints.authentications.login && | ||||
| error.response.config.url !== | error.response.config.url !== | ||||
| apiEndpoints.authentications.confirmSecurityQuestion && | apiEndpoints.authentications.confirmSecurityQuestion && | ||||
| error.response.status === 401 | |||||
| error.response.status === 4003 | |||||
| ) { | ) { | ||||
| return dispatch(logoutUser()); | return dispatch(logoutUser()); | ||||
| } | } |
| 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 = { | const initialState = { | ||||
| [APP_LOADING]: true, | |||||
| loaderCount: 0, | |||||
| }; | }; | ||||
| export default createReducer( | 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 { | return { | ||||
| ...state, | ...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 { | return { | ||||
| ...state, | ...state, | ||||
| [APP_LOADING]: true, | |||||
| [actionType]: false, | |||||
| loaderCount, | |||||
| }; | }; | ||||
| } | } |
| function setUser(state, action) { | function setUser(state, action) { | ||||
| return { | return { | ||||
| ...state, | ...state, | ||||
| token: action.payload, | |||||
| token: { | |||||
| ...state.token, | |||||
| JwtToken: action.payload.token, | |||||
| JwtRefreshToken: action.payload.refresh | |||||
| }, | |||||
| }; | }; | ||||
| } | } | ||||
| 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 { | import { | ||||
| AUTHENTICATE_USER, | AUTHENTICATE_USER, | ||||
| LOGIN_USER_FETCH, | LOGIN_USER_FETCH, | ||||
| LOGOUT_USER, | LOGOUT_USER, | ||||
| REFRESH_TOKEN, | 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 { | import { | ||||
| fetchUserError, | fetchUserError, | ||||
| fetchUserSuccess, | fetchUserSuccess, | ||||
| resetLoginState, | resetLoginState, | ||||
| updateUserToken, | 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 { | import { | ||||
| JWT_REFRESH_TOKEN, | JWT_REFRESH_TOKEN, | ||||
| JWT_TOKEN, | JWT_TOKEN, | ||||
| REFRESH_TOKEN_CONST, | REFRESH_TOKEN_CONST, | ||||
| } from '../../constants/localStorage'; | |||||
| } from "../../constants/localStorage"; | |||||
| import { | import { | ||||
| authScopeClearHelper, | authScopeClearHelper, | ||||
| authScopeStringGetHelper, | authScopeStringGetHelper, | ||||
| authScopeRemoveHelper, | authScopeRemoveHelper, | ||||
| authScopeSetHelper, | authScopeSetHelper, | ||||
| } from '../../util/helpers/authScopeHelpers'; | |||||
| import { rejectErrorCodeHelper } from '../../util/helpers/rejectErrorCodeHelper'; | |||||
| } from "../../util/helpers/authScopeHelpers"; | |||||
| import { rejectErrorCodeHelper } from "../../util/helpers/rejectErrorCodeHelper"; | |||||
| function* fetchUser({ payload }) { | function* fetchUser({ payload }) { | ||||
| try { | try { | ||||
| const { data } = yield call(attemptLogin, payload); | 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(setUser(user)); | ||||
| } | } | ||||
| yield put(fetchUserSuccess(data)); | yield put(fetchUserSuccess(data)); | ||||
| return yield put( | return yield put( | ||||
| fetchUserSuccess({ | fetchUserSuccess({ | ||||
| JwtToken, | JwtToken, | ||||
| }), | |||||
| }) | |||||
| ); | ); | ||||
| } catch (error) { | } catch (error) { | ||||
| const errorMessage = yield call(rejectErrorCodeHelper, error); | const errorMessage = yield call(rejectErrorCodeHelper, error); | ||||
| function* logoutUser() { | function* logoutUser() { | ||||
| try { | 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) { | if (user) { | ||||
| yield call(logoutUserRequest, user.UserUid); | |||||
| let requestData = { token }; | |||||
| yield call(logoutUserRequest, requestData); | |||||
| } | } | ||||
| } catch (error) { | } catch (error) { | ||||
| console.log(error); // eslint-disable-line | console.log(error); // eslint-disable-line | ||||
| } | } | ||||
| } | } | ||||
| 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 { | 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) { | } catch (error) { | ||||
| yield call(logoutUser); | |||||
| console.log(error); // eslint-disable-line | console.log(error); // eslint-disable-line | ||||
| return false; | |||||
| } | } | ||||
| } | } | ||||
| takeLatest(AUTHENTICATE_USER, authenticateUser), | takeLatest(AUTHENTICATE_USER, authenticateUser), | ||||
| takeLatest(LOGOUT_USER, logoutUser), | takeLatest(LOGOUT_USER, logoutUser), | ||||
| takeLatest(REFRESH_TOKEN, refreshToken), | takeLatest(REFRESH_TOKEN, refreshToken), | ||||
| takeLatest(GENERATE_TOKEN, generateToken), | |||||
| ]); | ]); | ||||
| } | } |
| import { createSelector } from 'reselect'; | |||||
| import { createSelector } from "reselect"; | |||||
| const loadingSelector = (state) => state.loading; | const loadingSelector = (state) => state.loading; | ||||
| export const selectIsLoadingByActionType = (loadingActionType) => | export const selectIsLoadingByActionType = (loadingActionType) => | ||||
| createSelector( | |||||
| loadingSelector, | |||||
| (state) => state[`${loadingActionType}`] || false, | |||||
| ); | |||||
| createSelector(loadingSelector, (state) => state[`${loadingActionType}`]); | |||||
| export const selectIsLoadingByActionTypes = (actionTypes) => | export const selectIsLoadingByActionTypes = (actionTypes) => | ||||
| createSelector(loadingSelector, (state) => | createSelector(loadingSelector, (state) => | ||||
| actionTypes.some((actionType) => state[`${actionType}`]), | |||||
| actionTypes.some((actionType) => state[`${actionType}`]) | |||||
| ); | ); | ||||
| export const selectLoaderCount = createSelector( | |||||
| loadingSelector, | |||||
| (state) => state.loaderCount | |||||
| ); |