From 23e4e75a594d5eefdcedf006fad33a2b235646ee Mon Sep 17 00:00:00 2001 From: Sergio Betanzos Date: Wed, 23 Jun 2021 10:39:45 +0200 Subject: [PATCH] F OpenNebula/one#5422: Fix error by unauthorized --- .../src/client/features/Auth/slice.js | 5 ++- .../src/client/features/General/slice.js | 4 +- src/fireedge/src/client/features/One/slice.js | 5 ++- src/fireedge/src/client/features/One/utils.js | 39 +++++++++++++++++-- src/fireedge/src/client/utils/rest.js | 8 ++-- 5 files changed, 47 insertions(+), 14 deletions(-) diff --git a/src/fireedge/src/client/features/Auth/slice.js b/src/fireedge/src/client/features/Auth/slice.js index 7664827f00..facd4ed3a3 100644 --- a/src/fireedge/src/client/features/Auth/slice.js +++ b/src/fireedge/src/client/features/Auth/slice.js @@ -28,7 +28,10 @@ const { actions, reducer } = createSlice({ initialState: initial({ firstRender: true }), extraReducers: builder => { builder - .addCase(logout, (_, { error }) => ({ ...initial(), error })) + .addMatcher( + ({ type }) => type === logout.type, + (_, { error }) => ({ ...initial(), error }) + ) .addMatcher( ({ type }) => { return [ diff --git a/src/fireedge/src/client/features/General/slice.js b/src/fireedge/src/client/features/General/slice.js index 2b32c69e7a..9957b92d4a 100644 --- a/src/fireedge/src/client/features/General/slice.js +++ b/src/fireedge/src/client/features/General/slice.js @@ -1,5 +1,6 @@ import { createSlice } from '@reduxjs/toolkit' +import { logout } from 'client/features/Auth/actions' import * as actions from 'client/features/General/actions' import { generateKey } from 'client/utils' @@ -17,8 +18,6 @@ const { reducer } = createSlice({ initialState: initial, extraReducers: builder => { builder - .addCase('logout', ({ title }) => ({ ...initial, title })) - /* UI ACTIONS */ .addCase(actions.fixMenu, (state, { payload }) => { return { ...state, isFixMenu: !!payload } @@ -69,6 +68,7 @@ const { reducer } = createSlice({ }) /* REQUESTS API MATCHES */ + .addMatcher(({ type }) => type === logout.type, () => initial) .addMatcher( ({ type }) => type.endsWith('/pending') && !type.includes('auth'), state => ({ ...state, isLoading: true }) diff --git a/src/fireedge/src/client/features/One/slice.js b/src/fireedge/src/client/features/One/slice.js index 2ec7774319..445e341b78 100644 --- a/src/fireedge/src/client/features/One/slice.js +++ b/src/fireedge/src/client/features/One/slice.js @@ -1,5 +1,6 @@ import { createSlice } from '@reduxjs/toolkit' +import { logout } from 'client/features/Auth/actions' import { updateResourceList } from 'client/features/One/utils' import { eventUpdateResourceState } from 'client/features/One/socket/actions' @@ -69,13 +70,13 @@ const { actions, reducer } = createSlice({ initialState: initial, extraReducers: builder => { builder - .addCase('logout', () => initial) + .addMatcher(({ type }) => type === logout.type, () => initial) .addMatcher( ({ type }) => type.endsWith('/fulfilled') && (type.includes(eventUpdateResourceState.typePrefix) || type.includes('/detail')), (state, { payload, type }) => { - // TYPE and DATA can be force with the payload + // TYPE and DATA can be force by payload const name = getNameListFromType(payload?.type ?? type) const newList = updateResourceList(state[name], payload?.data ?? payload) diff --git a/src/fireedge/src/client/features/One/utils.js b/src/fireedge/src/client/features/One/utils.js index c50e1587d9..ade077debd 100644 --- a/src/fireedge/src/client/features/One/utils.js +++ b/src/fireedge/src/client/features/One/utils.js @@ -1,10 +1,14 @@ import { createAsyncThunk } from '@reduxjs/toolkit' -import { httpCodes } from 'server/utils/constants' +import { logout } from 'client/features/Auth/actions' +import { ATTRIBUTES_EDITABLE } from 'client/features/One/slice' import { requestParams, RestClient } from 'client/utils' +import { T } from 'client/constants' +import { httpCodes } from 'server/utils/constants' + export const createAction = (type, service, wrapResult) => - createAsyncThunk(type, async (payload, { getState, rejectWithValue }) => { + createAsyncThunk(type, async (payload, { dispatch, getState, rejectWithValue }) => { try { const { auth: { filterPool }, one } = getState() @@ -14,8 +18,12 @@ export const createAction = (type, service, wrapResult) => }) return wrapResult ? wrapResult(response, one) : response - } catch (err) { - return rejectWithValue(typeof err === 'string' ? err : err?.response?.data) + } catch (error) { + const { data, status, statusText } = error + + status === httpCodes.unauthorized.id && dispatch(logout(T.SessionExpired)) + + return rejectWithValue(data?.message ?? statusText) } }, { condition: (_, { getState }) => { @@ -35,3 +43,26 @@ export const poolRequest = async (data = {}, command, element) => { return [response?.data?.[`${element}_POOL`]?.[element] ?? []].flat() } + +/** + * @param {Object} currentList Current state from redux + * @param {Object} value OpenNebula resource + * @returns {Array} Returns a new list with the attributes editable modified + */ +export const updateResourceList = (currentList, value) => { + const id = value.ID + + const newItem = currentList?.find(({ ID }) => ID === id) + + const editedItem = ATTRIBUTES_EDITABLE.reduce( + (item, attr) => value[attr] ? ({ ...item, [attr]: value[attr] }) : item, + newItem || {} + ) + + // update if exists in current list, if not add it to list + const updatedList = newItem + ? currentList?.map(item => item?.ID === id ? editedItem : item) + : [value, currentList] + + return updatedList +} \ No newline at end of file diff --git a/src/fireedge/src/client/utils/rest.js b/src/fireedge/src/client/utils/rest.js index e1e9238696..f7ba106fa9 100644 --- a/src/fireedge/src/client/utils/rest.js +++ b/src/fireedge/src/client/utils/rest.js @@ -28,19 +28,17 @@ http.interceptors.response.use( : response.data } - const error = response?.data?.message ?? response?.statusText - - if (response.status === 401) { + if (response.status === httpCodes.unauthorized.id) { const configErrorParser = { color: 'red', - type: error, + type: response?.data?.message ?? response?.statusText, message: 'Error request: %s' } isDevelopment() && messageTerminal(configErrorParser) } - return Promise.reject(error) + return Promise.reject(response) }, error => { console.log('error interceptor', error)