🐛 fix(authContext.tsx): initialize accessToken and refreshToken with values from cookies to maintain user session
✨ feat(authContext.tsx): add support for process.env.PORT environment variable to be able to run app on a configurable port 🐛 fix(tabsContext.tsx): import missing AuthContext and use getAuthentication function to conditionally fetch data 🐛 fix(typesContext.tsx): import missing AuthContext and use getAuthentication function to conditionally fetch data 🐛 fix(api.tsx): add check to not refresh token if refreshToken is "auto"
This commit is contained in:
parent
38eb1a2d79
commit
89d69af7f8
4 changed files with 61 additions and 58 deletions
|
|
@ -24,13 +24,13 @@ const initialValue: AuthContextType = {
|
||||||
export const AuthContext = createContext<AuthContextType>(initialValue);
|
export const AuthContext = createContext<AuthContextType>(initialValue);
|
||||||
|
|
||||||
export function AuthProvider({ children }): React.ReactElement {
|
export function AuthProvider({ children }): React.ReactElement {
|
||||||
const [accessToken, setAccessToken] = useState<string | null>(null);
|
const cookies = new Cookies();
|
||||||
const [refreshToken, setRefreshToken] = useState<string | null>(null);
|
const [accessToken, setAccessToken] = useState<string | null>(cookies.get("access_token"));
|
||||||
|
const [refreshToken, setRefreshToken] = useState<string | null>(cookies.get("refresh_token"));
|
||||||
const [isAuthenticated, setIsAuthenticated] = useState<boolean>(false);
|
const [isAuthenticated, setIsAuthenticated] = useState<boolean>(false);
|
||||||
const [isAdmin, setIsAdmin] = useState<boolean>(false);
|
const [isAdmin, setIsAdmin] = useState<boolean>(false);
|
||||||
const [userData, setUserData] = useState<Users | null>(null);
|
const [userData, setUserData] = useState<Users | null>(null);
|
||||||
const [autoLogin, setAutoLogin] = useState<boolean>(false);
|
const [autoLogin, setAutoLogin] = useState<boolean>(false);
|
||||||
const cookies = new Cookies();
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const storedAccessToken = cookies.get("access_token");
|
const storedAccessToken = cookies.get("access_token");
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { AxiosError } from "axios";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
import {
|
import {
|
||||||
ReactNode,
|
ReactNode,
|
||||||
|
|
@ -21,7 +22,7 @@ import {
|
||||||
import { APIClassType, APITemplateType } from "../types/api";
|
import { APIClassType, APITemplateType } from "../types/api";
|
||||||
import { tweakType } from "../types/components";
|
import { tweakType } from "../types/components";
|
||||||
import { FlowType, NodeDataType, NodeType } from "../types/flow";
|
import { FlowType, NodeDataType, NodeType } from "../types/flow";
|
||||||
import { TabsContextType, TabsState, errorsVarType } from "../types/tabs";
|
import { TabsContextType, TabsState } from "../types/tabs";
|
||||||
import {
|
import {
|
||||||
addVersionToDuplicates,
|
addVersionToDuplicates,
|
||||||
updateIds,
|
updateIds,
|
||||||
|
|
@ -29,8 +30,8 @@ import {
|
||||||
} from "../utils/reactflowUtils";
|
} from "../utils/reactflowUtils";
|
||||||
import { getRandomDescription, getRandomName } from "../utils/utils";
|
import { getRandomDescription, getRandomName } from "../utils/utils";
|
||||||
import { alertContext } from "./alertContext";
|
import { alertContext } from "./alertContext";
|
||||||
|
import { AuthContext } from "./authContext";
|
||||||
import { typesContext } from "./typesContext";
|
import { typesContext } from "./typesContext";
|
||||||
import { AxiosError } from "axios";
|
|
||||||
|
|
||||||
const uid = new ShortUniqueId({ length: 5 });
|
const uid = new ShortUniqueId({ length: 5 });
|
||||||
|
|
||||||
|
|
@ -69,7 +70,9 @@ export const TabsContext = createContext<TabsContextType>(
|
||||||
);
|
);
|
||||||
|
|
||||||
export function TabsProvider({ children }: { children: ReactNode }) {
|
export function TabsProvider({ children }: { children: ReactNode }) {
|
||||||
const { setErrorData, setNoticeData, setSuccessData } = useContext(alertContext);
|
const { setErrorData, setNoticeData, setSuccessData } =
|
||||||
|
useContext(alertContext);
|
||||||
|
const { getAuthentication } = useContext(AuthContext);
|
||||||
|
|
||||||
const [tabId, setTabId] = useState("");
|
const [tabId, setTabId] = useState("");
|
||||||
|
|
||||||
|
|
@ -113,7 +116,6 @@ export function TabsProvider({ children }: { children: ReactNode }) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function refreshFlows() {
|
function refreshFlows() {
|
||||||
setTimeout(() => {
|
|
||||||
getTabsDataFromDB().then((DbData) => {
|
getTabsDataFromDB().then((DbData) => {
|
||||||
if (DbData && Object.keys(templates).length > 0) {
|
if (DbData && Object.keys(templates).length > 0) {
|
||||||
try {
|
try {
|
||||||
|
|
@ -124,20 +126,22 @@ export function TabsProvider({ children }: { children: ReactNode }) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}, 2000);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// get data from db
|
if (getAuthentication() === true) {
|
||||||
//get tabs locally saved
|
// get data from db
|
||||||
// let tabsData = getLocalStorageTabsData();
|
//get tabs locally saved
|
||||||
refreshFlows();
|
// let tabsData = getLocalStorageTabsData();
|
||||||
}, [templates]);
|
refreshFlows();
|
||||||
|
}
|
||||||
|
}, [templates, getAuthentication()]);
|
||||||
|
|
||||||
function getTabsDataFromDB() {
|
function getTabsDataFromDB() {
|
||||||
//get tabs from db
|
//get tabs from db
|
||||||
return readFlowsFromDatabase();
|
return readFlowsFromDatabase();
|
||||||
}
|
}
|
||||||
|
|
||||||
function processDBData(DbData: FlowType[]) {
|
function processDBData(DbData: FlowType[]) {
|
||||||
DbData.forEach((flow: FlowType) => {
|
DbData.forEach((flow: FlowType) => {
|
||||||
try {
|
try {
|
||||||
|
|
@ -605,7 +609,10 @@ export function TabsProvider({ children }: { children: ReactNode }) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setErrorData({title: "Error while saving changes",list:[(err as AxiosError).message]});
|
setErrorData({
|
||||||
|
title: "Error while saving changes",
|
||||||
|
list: [(err as AxiosError).message],
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import { getAll, getHealth } from "../controllers/API";
|
||||||
import { APIKindType } from "../types/api";
|
import { APIKindType } from "../types/api";
|
||||||
import { typesContextType } from "../types/typesContext";
|
import { typesContextType } from "../types/typesContext";
|
||||||
import { alertContext } from "./alertContext";
|
import { alertContext } from "./alertContext";
|
||||||
|
import { AuthContext } from "./authContext";
|
||||||
|
|
||||||
//context to share types adn functions from nodes to flow
|
//context to share types adn functions from nodes to flow
|
||||||
|
|
||||||
|
|
@ -37,60 +38,55 @@ export function TypesProvider({ children }: { children: ReactNode }) {
|
||||||
const [data, setData] = useState({});
|
const [data, setData] = useState({});
|
||||||
const [fetchError, setFetchError] = useState(false);
|
const [fetchError, setFetchError] = useState(false);
|
||||||
const { setLoading } = useContext(alertContext);
|
const { setLoading } = useContext(alertContext);
|
||||||
|
const { getAuthentication } = useContext(AuthContext);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
if (getAuthentication() === true) {
|
||||||
|
getTypes();
|
||||||
|
}
|
||||||
|
}, [getAuthentication()]);
|
||||||
|
|
||||||
setTimeout(() => {
|
async function getTypes(): Promise<void> {
|
||||||
|
|
||||||
// We will keep a flag to handle the case where the component is unmounted before the API call resolves.
|
// We will keep a flag to handle the case where the component is unmounted before the API call resolves.
|
||||||
let isMounted = true;
|
let isMounted = true;
|
||||||
|
try {
|
||||||
async function getTypes(): Promise<void> {
|
const result = await getAll();
|
||||||
try {
|
// Make sure to only update the state if the component is still mounted.
|
||||||
const result = await getAll();
|
if (isMounted && result?.status === 200) {
|
||||||
// Make sure to only update the state if the component is still mounted.
|
setLoading(false);
|
||||||
if (isMounted && result?.status === 200) {
|
setData(result.data);
|
||||||
setLoading(false);
|
setTemplates(
|
||||||
setData(result.data);
|
Object.keys(result.data).reduce((acc, curr) => {
|
||||||
setTemplates(
|
Object.keys(result.data[curr]).forEach((c: keyof APIKindType) => {
|
||||||
Object.keys(result.data).reduce((acc, curr) => {
|
acc[c] = result.data[curr][c];
|
||||||
|
});
|
||||||
|
return acc;
|
||||||
|
}, {})
|
||||||
|
);
|
||||||
|
// Set the types by reducing over the keys of the result data and updating the accumulator.
|
||||||
|
setTypes(
|
||||||
|
// Reverse the keys so the tool world does not overlap
|
||||||
|
Object.keys(result.data)
|
||||||
|
.reverse()
|
||||||
|
.reduce((acc, curr) => {
|
||||||
Object.keys(result.data[curr]).forEach((c: keyof APIKindType) => {
|
Object.keys(result.data[curr]).forEach((c: keyof APIKindType) => {
|
||||||
acc[c] = result.data[curr][c];
|
acc[c] = curr;
|
||||||
|
// Add the base classes to the accumulator as well.
|
||||||
|
result.data[curr][c].base_classes?.forEach((b) => {
|
||||||
|
acc[b] = curr;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
return acc;
|
return acc;
|
||||||
}, {})
|
}, {})
|
||||||
);
|
);
|
||||||
// Set the types by reducing over the keys of the result data and updating the accumulator.
|
|
||||||
setTypes(
|
|
||||||
// Reverse the keys so the tool world does not overlap
|
|
||||||
Object.keys(result.data)
|
|
||||||
.reverse()
|
|
||||||
.reduce((acc, curr) => {
|
|
||||||
Object.keys(result.data[curr]).forEach(
|
|
||||||
(c: keyof APIKindType) => {
|
|
||||||
acc[c] = curr;
|
|
||||||
// Add the base classes to the accumulator as well.
|
|
||||||
result.data[curr][c].base_classes?.forEach((b) => {
|
|
||||||
acc[b] = curr;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
return acc;
|
|
||||||
}, {})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error("An error has occurred while fetching types.");
|
|
||||||
await getHealth().catch((e) => {
|
|
||||||
setFetchError(true);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("An error has occurred while fetching types.");
|
||||||
|
await getHealth().catch((e) => {
|
||||||
|
setFetchError(true);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
getTypes();
|
|
||||||
}, 2000);
|
|
||||||
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
function deleteNode(idx: string) {
|
function deleteNode(idx: string) {
|
||||||
reactFlowInstance!.setNodes(
|
reactFlowInstance!.setNodes(
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ function ApiInterceptor() {
|
||||||
async (error: AxiosError) => {
|
async (error: AxiosError) => {
|
||||||
if (error.response?.status === 401) {
|
if (error.response?.status === 401) {
|
||||||
const refreshToken = cookies.get("refresh_token");
|
const refreshToken = cookies.get("refresh_token");
|
||||||
if (refreshToken) {
|
if (refreshToken && refreshToken !== "auto") {
|
||||||
authenticationErrorCount = authenticationErrorCount + 1;
|
authenticationErrorCount = authenticationErrorCount + 1;
|
||||||
if (authenticationErrorCount > 3) {
|
if (authenticationErrorCount > 3) {
|
||||||
authenticationErrorCount = 0;
|
authenticationErrorCount = 0;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue