Validación de token existente en sessionStorage

This commit is contained in:
Germán Enríquez 2024-07-28 13:17:54 -05:00
parent 9afc3b2bd0
commit 1d6b93c51c
18 changed files with 2044 additions and 1306 deletions

View file

@ -1,6 +1,6 @@
/* eslint-env node */ /* eslint-env node */
module.exports = { module.exports={
env: { browser: true, es2020: true }, env: { browser: true, es2020: true },
extends: [ extends: [
'eslint:recommended', 'eslint:recommended',

2971
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
{ {
"name": "@chimera-pe/react-saas", "name": "@chimera-pe/react-saas",
"version": "0.2.1", "version": "0.3.0",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",
@ -8,42 +8,38 @@
"lint": "eslint src --ext js,jsx --report-unused-disable-directives --max-warnings 0", "lint": "eslint src --ext js,jsx --report-unused-disable-directives --max-warnings 0",
"preview": "vite preview" "preview": "vite preview"
}, },
"dependencies": { "peerDependencies": {
"@emotion/react": "^11.11.4", "@emotion/react": "^11.13.0",
"@emotion/styled": "^11.11.0", "@emotion/styled": "^11.13.0",
"@mui/icons-material": "^5.15.11", "@mui/icons-material": "^5.16.5",
"@mui/lab": "^5.0.0-alpha.166", "@mui/lab": "^5.0.0-alpha.171",
"@mui/material": "^5.15.11", "@mui/material": "^5.16.5",
"@mui/x-date-pickers": "^6.19.5", "@mui/x-date-pickers": "^7.11.1",
"@reduxjs/toolkit": "^2.2.1", "@reduxjs/toolkit": "^2.2.7",
"axios": "^1.6.7", "axios": "^1.7.2",
"date-fns": "^2.30.0", "date-fns": "^2.30.0",
"final-form": "^4.20.10", "final-form": "^4.20.10",
"jwt-decode": "^4.0.0", "jwt-decode": "^4.0.0",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"mui-rff": "^7.3.0", "mui-rff": "^7.4.1",
"navigator-languages": "^2.0.2", "navigator-languages": "^2.0.2",
"node-polyglot": "^2.5.0", "node-polyglot": "^2.6.0",
"react": "^18.2.0", "react": "^18.3.1",
"react-dom": "^18.2.0", "react-dom": "^18.3.1",
"react-final-form": "^6.5.9", "react-final-form": "^6.5.9",
"react-polyglot": "^0.7.2", "react-polyglot": "^0.7.2",
"react-redux": "^9.1.0", "react-redux": "^9.1.2",
"react-router-dom": "^6.22.2" "react-router-dom": "^6.25.1"
},
"peerDependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0"
}, },
"devDependencies": { "devDependencies": {
"@types/react": "^18.2.56", "@types/react": "^18.3.3",
"@types/react-dom": "^18.2.19", "@types/react-dom": "^18.3.0",
"@vitejs/plugin-react": "^4.2.1", "@vitejs/plugin-react": "^4.3.1",
"eslint": "^8.56.0", "eslint": "^8.57.0",
"eslint-plugin-react": "^7.33.2", "eslint-plugin-react": "^7.35.0",
"eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-hooks": "^4.6.2",
"eslint-plugin-react-refresh": "^0.4.5", "eslint-plugin-react-refresh": "^0.4.9",
"vite": "^5.1.4" "vite": "^5.3.5"
}, },
"description": "Componente integrador con SaaS", "description": "Componente integrador con SaaS",
"main": "./dist/react-saas.umd.cjs", "main": "./dist/react-saas.umd.cjs",

View file

@ -1,2 +1,6 @@
export const saasURL="https://saas.chimera.com.pe/backend"; export const saasURL="https://saas.chimera.com.pe/backend";
export const authURL="https://saas.chimera.com.pe/oauth"; export const authURL="https://saas.chimera.com.pe/oauth";
export const TOKEN="saas-token";
export const TOKEN_EXPIRATION="saas-token-expiration";
export const REFRESH_TOKEN="saas-refresh-token";

View file

@ -1,7 +1,7 @@
import axios from "axios"; import axios from "axios";
import {saasURL} from "../Constantes"; import {saasURL} from "../Constantes";
export const identidadApi = (url = saasURL,aplicacion) => axios({ export const identidadApi=(url=saasURL,aplicacion) => axios({
url: `${url}/identidad/`, url: `${url}/identidad/`,
params: { params: {
codigoAplicacion: aplicacion codigoAplicacion: aplicacion

View file

@ -1,7 +1,7 @@
import axios from "axios"; import axios from "axios";
import {authURL} from "../Constantes"; import {authURL} from "../Constantes";
export const loginApi = (url = authURL) => ({ export const loginApi=(url=authURL) => ({
login: (clientCredentials,data) => axios({ login: (clientCredentials,data) => axios({
url: `${url}/oauth/token`, url: `${url}/oauth/token`,
headers: { headers: {

View file

@ -2,8 +2,8 @@ import {Box,Alert,AlertTitle} from "@mui/material";
import {useTranslate} from "react-polyglot"; import {useTranslate} from "react-polyglot";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
const ErrorAlert = ({titulo,texto,align = "center",severity = "error"}) => { const ErrorAlert=({titulo,texto,align="center",severity="error"}) => {
const translate = useTranslate(); const translate=useTranslate();
return ( return (
<Box sx={{ <Box sx={{

View file

@ -9,10 +9,10 @@ import navigatorLanguages from "navigator-languages";
import {cambiarIdioma} from "../redux"; import {cambiarIdioma} from "../redux";
import saasMessages from "../i18n"; import saasMessages from "../i18n";
const supportedLocales = {en: enGB,es}; const supportedLocales={en: enGB,es};
const IdiomaInner = ({messages,children}) => { const IdiomaInner=({messages,children}) => {
const idioma = useSelector(store => store.ui.idioma); const idioma=useSelector(store => store.ui.idioma);
return ( return (
<I18n locale={idioma} messages={messages[idioma]}> <I18n locale={idioma} messages={messages[idioma]}>
@ -23,41 +23,41 @@ const IdiomaInner = ({messages,children}) => {
); );
}; };
IdiomaInner.propTypes = { IdiomaInner.propTypes={
messages: PropTypes.object, messages: PropTypes.object,
children: PropTypes.element.isRequired children: PropTypes.element.isRequired
}; };
const getIdiomaNavegador = () => { const getIdiomaNavegador=() => {
const idiomas = navigatorLanguages(); const idiomas=navigatorLanguages();
if(!idiomas?.length) { if(!idiomas?.length) {
return undefined; return undefined;
} }
const idioma = idiomas[0]; const idioma=idiomas[0];
if(idioma.indexOf("-")) { if(idioma.indexOf("-")) {
return idioma.substring(0,idioma.indexOf("-")); return idioma.substring(0,idioma.indexOf("-"));
} }
return idioma; return idioma;
}; };
const Idioma = ({messages,idiomaDefecto,children}) => { const Idioma=({messages,idiomaDefecto,children}) => {
const dispatch = useDispatch(); const dispatch=useDispatch();
const idiomaNavegador = getIdiomaNavegador(); const idiomaNavegador=getIdiomaNavegador();
useEffect(() => { useEffect(() => {
let idioma = Reflect.ownKeys(messages)[0]; let idioma=Reflect.ownKeys(messages)[0];
if(idiomaNavegador && Object.hasOwn(messages,idiomaNavegador)) { if(idiomaNavegador && Object.hasOwn(messages,idiomaNavegador)) {
idioma = idiomaNavegador; idioma=idiomaNavegador;
} }
else if(idiomaDefecto && Object.hasOwn(messages,idiomaDefecto)) { else if(idiomaDefecto && Object.hasOwn(messages,idiomaDefecto)) {
idioma = idiomaDefecto; idioma=idiomaDefecto;
} }
dispatch(cambiarIdioma(idioma)); dispatch(cambiarIdioma(idioma));
},[dispatch,messages,idiomaDefecto,idiomaNavegador]); },[dispatch,messages,idiomaDefecto,idiomaNavegador]);
const m = {}; const m={};
Object.keys(messages).forEach(key => { Object.keys(messages).forEach(key => {
m[key] = { m[key]={
...messages[key], ...messages[key],
saas: saasMessages[key] saas: saasMessages[key]
}; };
@ -70,7 +70,7 @@ const Idioma = ({messages,idiomaDefecto,children}) => {
); );
}; };
Idioma.propTypes = { Idioma.propTypes={
messages: PropTypes.object, messages: PropTypes.object,
idiomaDefecto: PropTypes.string, idiomaDefecto: PropTypes.string,
children: PropTypes.element.isRequired children: PropTypes.element.isRequired

View file

@ -10,8 +10,8 @@ import Idioma from "./Idioma";
import Tema from "./Tema"; import Tema from "./Tema";
import MainRouter from "./MainRouter"; import MainRouter from "./MainRouter";
const InicializarInner = ({devURL,basename,children}) => { const InicializarInner=({devURL,basename,children}) => {
const aplicacion = useSelector(store => store.aplicacion); const aplicacion=useSelector(store => store.aplicacion);
return ( return (
<Box sx={{ <Box sx={{
@ -47,7 +47,7 @@ InicializarInner.propTypes={
children: PropTypes.element.isRequired children: PropTypes.element.isRequired
}; };
const Inicializar = ({ const Inicializar=({
aplicacion, aplicacion,
devSaasURL, devSaasURL,
devAuthURL, devAuthURL,
@ -56,7 +56,7 @@ const Inicializar = ({
basename, basename,
children children
}) => { }) => {
const dispatch = useDispatch(); const dispatch=useDispatch();
useEffect(() => { useEffect(() => {
dispatch(inicializar({devURL: devSaasURL,aplicacion: aplicacion})); dispatch(inicializar({devURL: devSaasURL,aplicacion: aplicacion}));

View file

@ -24,14 +24,14 @@ import {useTranslate} from "react-polyglot";
import {requestToken} from "../redux"; import {requestToken} from "../redux";
import {useCheckLogin,useNotificar} from "../hooks"; import {useCheckLogin,useNotificar} from "../hooks";
const FormularioLogin = ({devURL}) => { const FormularioLogin=({devURL}) => {
const dispatch = useDispatch(); const dispatch=useDispatch();
const translate = useTranslate(); const translate=useTranslate();
const notificar = useNotificar(); const notificar=useNotificar();
const {cargando,error} = useSelector(store => store.login); const {cargando,error}=useSelector(store => store.login);
const instancia = useSelector(store => store.aplicacion.instancia); const instancia=useSelector(store => store.aplicacion.instancia);
const submit = values => { const submit=values => {
dispatch(requestToken({ dispatch(requestToken({
devURL: devURL, devURL: devURL,
clientCredentials: instancia.clientCredentials, clientCredentials: instancia.clientCredentials,
@ -42,14 +42,14 @@ const FormularioLogin = ({devURL}) => {
})); }));
}; };
const validate = values => { const validate=values => {
const errors = {correo: undefined,password: undefined}; const errors={correo: undefined,password: undefined};
if(!values.correo) { if(!values.correo) {
errors.correo = translate("saas.login.validacion.correo"); errors.correo=translate("saas.login.validacion.correo");
} }
if(!values.password) { if(!values.password) {
errors.password = translate("saas.login.validacion.password"); errors.password=translate("saas.login.validacion.password");
} }
return errors; return errors;
}; };
@ -121,16 +121,16 @@ const FormularioLogin = ({devURL}) => {
); );
}; };
FormularioLogin.propTypes = { FormularioLogin.propTypes={
devURL: PropTypes.string devURL: PropTypes.string
}; };
const Login = ({devURL}) => { const Login=({devURL}) => {
const instancia = useSelector(store => store.aplicacion.instancia); const instancia=useSelector(store => store.aplicacion.instancia);
const translate = useTranslate(); const translate=useTranslate();
const location = useLocation(); const location=useLocation();
const autenticado = useCheckLogin(devURL); const autenticado=useCheckLogin(devURL);
const {from} = location.state || {from: {pathname: "/"}}; const {from}=location.state || {from: {pathname: "/"}};
if(!instancia.requiereLogin || autenticado) { if(!instancia.requiereLogin || autenticado) {
return <Navigate to={from} />; return <Navigate to={from} />;
@ -204,7 +204,7 @@ const Login = ({devURL}) => {
); );
}; };
Login.propTypes = { Login.propTypes={
devURL: PropTypes.string devURL: PropTypes.string
}; };

View file

@ -9,9 +9,9 @@ import {
import {useCheckLogin} from "../hooks"; import {useCheckLogin} from "../hooks";
import Login from "./Login"; import Login from "./Login";
const RequiereAuth = ({devURL,redirectTo,children}) => { const RequiereAuth=({devURL,redirectTo,children}) => {
const location = useLocation(); const location=useLocation();
const autenticado = useCheckLogin(devURL); const autenticado=useCheckLogin(devURL);
return autenticado ? children : <Navigate to={redirectTo} state={{from: location}} replace />; return autenticado ? children : <Navigate to={redirectTo} state={{from: location}} replace />;
}; };
@ -22,7 +22,7 @@ RequiereAuth.propTypes={
children: PropTypes.element.isRequired children: PropTypes.element.isRequired
}; };
const MainRouter = ({ const MainRouter=({
devURL, devURL,
requiereLogin, requiereLogin,
basename, basename,

View file

@ -3,12 +3,12 @@ import {Provider} from "react-redux";
import {store} from "../redux"; import {store} from "../redux";
import Inicializar from "./Inicializar"; import Inicializar from "./Inicializar";
const SaasApp = ({ const SaasApp=({
customReducers, customReducers,
aplicacion, aplicacion,
devSaasURL, devSaasURL,
devAuthURL, devAuthURL,
dev = false, dev=false,
idiomaDefecto, idiomaDefecto,
messages, messages,
basename, basename,

View file

@ -1,24 +1,45 @@
import {useEffect} from "react"; import {useEffect} from "react";
import {useDispatch,useSelector} from "react-redux"; import {useDispatch,useSelector} from "react-redux";
import {logout,refreshToken} from "../redux"; import {TOKEN,TOKEN_EXPIRATION,REFRESH_TOKEN} from "../Constantes";
import {login,logout,refreshToken} from "../redux";
const useCheckLogin = (devURL) => { const useCheckLogin=(devURL) => {
const dispatch = useDispatch(); const dispatch=useDispatch();
const login = useSelector(store => store.login); const loginStatus=useSelector(store => store.loginStatus);
const instancia = useSelector(store => store.aplicacion.instancia); const instancia=useSelector(store => store.aplicacion.instancia);
useEffect(() => { useEffect(() => {
if(login.autenticado && !!login.expiracion && new Date(login.expiracion) < new Date()){ if(loginStatus.autenticado){
if(login.refreshToken){ if(!!loginStatus.expiracion && new Date(loginStatus.expiracion) < new Date()){
dispatch(refreshToken(devURL,instancia.clientCredentials,login.refreshToken)); if(loginStatus.refreshToken){
} dispatch(refreshToken(devURL,instancia.clientCredentials,loginStatus.refreshToken));
else{ }
dispatch(logout()); else{
dispatch(logout());
}
} }
} }
},[devURL,instancia.clientCredentials,login,dispatch]); else{
const token=sessionStorage.getItem(TOKEN);
const expiracion=sessionStorage.getItem(TOKEN_EXPIRATION);
const refreshToken=sessionStorage.getItem(REFRESH_TOKEN);
if(token && expiracion){
if(new Date(expiracion) < new Date()){
if(refreshToken){
dispatch(refreshToken(devURL,instancia.clientCredentials,refreshToken));
}
else{
dispatch(logout());
}
}
else{
dispatch(login({token,expiracion,refreshToken}));
}
}
}
},[devURL,instancia.clientCredentials,loginStatus,dispatch]);
return login.autenticado; return loginStatus.autenticado;
}; };
export default useCheckLogin; export default useCheckLogin;

View file

@ -2,9 +2,9 @@ import {useCallback} from "react";
import {useDispatch} from "react-redux"; import {useDispatch} from "react-redux";
import {mostrarNotificacion} from "../redux"; import {mostrarNotificacion} from "../redux";
const useNotificar = () => { const useNotificar=() => {
const dispatch = useDispatch(); const dispatch=useDispatch();
return useCallback((mensaje,tipo = "default") => { return useCallback((mensaje,tipo="default") => {
dispatch(mostrarNotificacion({mensaje,tipo})); dispatch(mostrarNotificacion({mensaje,tipo}));
},[dispatch]); },[dispatch]);
}; };

View file

@ -3,6 +3,7 @@ import {inicializar,getInstancia} from "./inicializarSlice";
import { import {
refreshToken, refreshToken,
requestToken, requestToken,
login,
logout, logout,
getPerfiles, getPerfiles,
getToken, getToken,
@ -16,6 +17,7 @@ export {
inicializar, inicializar,
refreshToken, refreshToken,
requestToken, requestToken,
login,
logout, logout,
mostrarNotificacion, mostrarNotificacion,
ocultarNotificacion, ocultarNotificacion,

View file

@ -1,7 +1,7 @@
import {createSlice,createAsyncThunk} from "@reduxjs/toolkit"; import {createSlice,createAsyncThunk} from "@reduxjs/toolkit";
import {identidadApi} from "../api/inicializarApi"; import {identidadApi} from "../api/inicializarApi";
const colorDefault = { const colorDefault={
primary: "#1C6CCC", primary: "#1C6CCC",
secondary: "#17A7FF", secondary: "#17A7FF",
error: "#f44336", error: "#f44336",
@ -10,7 +10,7 @@ const colorDefault = {
success: "#4caf50" success: "#4caf50"
}; };
const inicializarSlice = createSlice({ const inicializarSlice=createSlice({
name: "inicializar", name: "inicializar",
initialState: { initialState: {
inicializando: true, inicializando: true,
@ -23,12 +23,12 @@ const inicializarSlice = createSlice({
extraReducers(builder) { extraReducers(builder) {
builder builder
.addCase(inicializar.pending,state => { .addCase(inicializar.pending,state => {
state.inicializando = true; state.inicializando=true;
}) })
.addCase(inicializar.fulfilled,(state,action) => { .addCase(inicializar.fulfilled,(state,action) => {
state.inicializando = false; state.inicializando=false;
state.inicializado = true; state.inicializado=true;
state.instancia = { state.instancia={
...action.payload, ...action.payload,
abreviatura: action.payload.nombre.match(/\b([A-Z])/g).join(""), abreviatura: action.payload.nombre.match(/\b([A-Z])/g).join(""),
color: { color: {
@ -36,21 +36,21 @@ const inicializarSlice = createSlice({
...action.payload.color ...action.payload.color
} }
}; };
state.error = null; state.error=null;
}) })
.addCase(inicializar.rejected,(state,action) => { .addCase(inicializar.rejected,(state,action) => {
state.inicializando = false; state.inicializando=false;
state.inicializado = false; state.inicializado=false;
state.instancia = { state.instancia={
color: colorDefault color: colorDefault
}; };
state.error = action.payload; state.error=action.payload;
}); });
} }
}); });
export const inicializar = createAsyncThunk("inicializar",async (payload) => { export const inicializar=createAsyncThunk("inicializar",async (payload) => {
const response = await identidadApi(payload.devURL,payload.aplicacion); const response=await identidadApi(payload.devURL,payload.aplicacion);
return response.data; return response.data;
}); });

View file

@ -1,8 +1,9 @@
import {createSlice,createAsyncThunk} from "@reduxjs/toolkit"; import {createSlice,createAsyncThunk} from "@reduxjs/toolkit";
import {loginApi} from "../api/loginApi"; import {loginApi} from "../api/loginApi";
import {TOKEN,TOKEN_EXPIRATION,REFRESH_TOKEN} from "../Constantes";
import {jwtDecode} from "jwt-decode"; import {jwtDecode} from "jwt-decode";
const loginSlice = createSlice({ const loginSlice=createSlice({
name: "login", name: "login",
initialState: { initialState: {
cargando: false, cargando: false,
@ -15,96 +16,109 @@ const loginSlice = createSlice({
error: null error: null
}, },
reducers: { reducers: {
login: (state,action) => {
const token=action.payload.token;
const jwtToken=jwtDecode(token);
const expiracion=new Date();
expiracion.setSeconds(expiracion.getSeconds() + action.payload.expiracion);
state.cargando=false;
state.autenticado=true;
state.token=token;
state.refreshToken=action.payload.refreshToken;
state.expiracion=expiracion.getTime();
state.usuario=jwtToken.name;
state.perfiles=jwtToken.authorities;
},
logout: state => { logout: state => {
state.cargando = false; state.cargando=false;
state.autenticado = false; state.autenticado=false;
state.token = null; state.token=null;
state.refreshToken = null; state.refreshToken=null;
state.expiracion = null; state.expiracion=null;
state.usuario = null; state.usuario=null;
state.perfiles = []; state.perfiles=[];
state.error = null; state.error=null;
sessionStorage.removeItem("saas-token"); sessionStorage.removeItem(TOKEN);
sessionStorage.removeItem("saas-refresh-token"); sessionStorage.removeItem(REFRESH_TOKEN);
sessionStorage.removeItem("saas-expiration"); sessionStorage.removeItem(TOKEN_EXPIRATION);
} }
}, },
extraReducers(builder) { extraReducers(builder) {
builder builder
.addCase(requestToken.pending,state => { .addCase(requestToken.pending,state => {
state.cargando = true; state.cargando=true;
state.error = null; state.error=null;
}) })
.addCase(requestToken.fulfilled,(state,action) => { .addCase(requestToken.fulfilled,(state,action) => {
const token = action.payload.access_token; const token=action.payload.access_token;
const jwtToken = jwtDecode(token); const jwtToken=jwtDecode(token);
const expiracion = new Date(); const expiracion=new Date();
expiracion.setSeconds(expiracion.getSeconds() + action.payload.expires_in); expiracion.setSeconds(expiracion.getSeconds() + action.payload.expires_in);
state.cargando = false; state.cargando=false;
state.autenticado = true; state.autenticado=true;
state.token = token; state.token=token;
state.refreshToken = action.payload.refresh_token; state.refreshToken=action.payload.refresh_token;
state.expiracion = expiracion.getTime(); state.expiracion=expiracion.getTime();
state.usuario = jwtToken.name; state.usuario=jwtToken.name;
state.perfiles = jwtToken.authorities; state.perfiles=jwtToken.authorities;
sessionStorage.setItem("saas-token",token); sessionStorage.setItem(TOKEN,token);
sessionStorage.setItem("saas-refresh-token",action.payload.refresh_token); sessionStorage.setItem(REFRESH_TOKEN,action.payload.refresh_token);
sessionStorage.setItem("saas-expiration",expiracion.getTime()); sessionStorage.setItem(TOKEN_EXPIRATION,expiracion.getTime());
}) })
.addCase(requestToken.rejected,(state,action) => { .addCase(requestToken.rejected,(state,action) => {
console.log(action); console.log(action);
state.cargando = false; state.cargando=false;
state.autenticado = false; state.autenticado=false;
state.token = null; state.token=null;
state.refreshToken = null; state.refreshToken=null;
state.expiracion = null; state.expiracion=null;
state.usuario = null; state.usuario=null;
state.perfiles = []; state.perfiles=[];
state.error = action.error?.message; state.error=action.error?.message;
sessionStorage.removeItem("saas-token"); sessionStorage.removeItem(TOKEN);
sessionStorage.removeItem("saas-refresh-token"); sessionStorage.removeItem(REFRESH_TOKEN);
sessionStorage.removeItem("saas-expiration"); sessionStorage.removeItem(TOKEN_EXPIRATION);
}) })
.addCase(refreshToken.pending,state => { .addCase(refreshToken.pending,state => {
state.cargando = true; state.cargando=true;
}) })
.addCase(refreshToken.fulfilled,(state,action) => { .addCase(refreshToken.fulfilled,(state,action) => {
const expiracion = new Date(); const expiracion=new Date();
expiracion.setSeconds(expiracion.getSeconds() + action.payload.expires_in); expiracion.setSeconds(expiracion.getSeconds() + action.payload.expires_in);
state.token = action.payload.access_token; state.token=action.payload.access_token;
state.refreshToken = action.payload.refresh_token; state.refreshToken=action.payload.refresh_token;
state.expiracion = expiracion.getTime(); state.expiracion=expiracion.getTime();
sessionStorage.setItem("saas-token",action.payload.access_token); sessionStorage.setItem(TOKEN,action.payload.access_token);
sessionStorage.setItem("saas-refresh-token",action.payload.refresh_token); sessionStorage.setItem(REFRESH_TOKEN,action.payload.refresh_token);
sessionStorage.setItem("saas-expiration",expiracion.getTime()); sessionStorage.setItem(TOKEN_EXPIRATION,expiracion.getTime());
}) })
.addCase(refreshToken.rejected,(state,action) => { .addCase(refreshToken.rejected,(state,action) => {
state.cargando = false; state.cargando=false;
state.autenticado = false; state.autenticado=false;
state.token = null; state.token=null;
state.refreshToken = null; state.refreshToken=null;
state.expiracion = null; state.expiracion=null;
state.usuario = null; state.usuario=null;
state.perfiles = []; state.perfiles=[];
state.error = action.error?.message; state.error=action.error?.message;
sessionStorage.removeItem("saas-token"); sessionStorage.removeItem(TOKEN);
sessionStorage.removeItem("saas-refresh-token"); sessionStorage.removeItem(REFRESH_TOKEN);
sessionStorage.removeItem("saas-expiration"); sessionStorage.removeItem(TOKEN_EXPIRATION);
}); });
} }
}); });
export const requestToken = createAsyncThunk("login/requestToken",async (payload) => { export const requestToken=createAsyncThunk("login/requestToken",async (payload) => {
const response = await loginApi(payload.devURL).login(payload.clientCredentials,payload.data); const response=await loginApi(payload.devURL).login(payload.clientCredentials,payload.data);
return response.data; return response.data;
}); });
export const refreshToken = createAsyncThunk("login/refreshToken",async (devURL,clientCredentials,refreshToken) => { export const refreshToken=createAsyncThunk("login/refreshToken",async (devURL,clientCredentials,refreshToken) => {
const response = await loginApi(devURL).refreshToken(clientCredentials,refreshToken); const response=await loginApi(devURL).refreshToken(clientCredentials,refreshToken);
return response.data; return response.data;
}); });
export const {logout} = loginSlice.actions; export const {login,logout}=loginSlice.actions;
export const getToken=state => state.login.token; export const getToken=state => state.login.token;

View file

@ -19,7 +19,7 @@ const getMessage=(message,messageArgs,value,values) => (
const memoize=(fn) => lodashMemoize(fn,(...args) => JSON.stringify(args)); const memoize=(fn) => lodashMemoize(fn,(...args) => JSON.stringify(args));
export const composeValidators=(...validators) => (value,values,meta) => { export const composeValidators=(...validators) => (value,values,meta) => {
const allValidators = Array.isArray(validators[0]) ? validators[0] : validators; const allValidators=Array.isArray(validators[0]) ? validators[0] : validators;
return allValidators.reduce( return allValidators.reduce(
(error,validator) => (error,validator) =>
error || error ||