diff --git a/server/index.ts b/server/index.ts index 66c86f4c..bb4e1f5c 100644 --- a/server/index.ts +++ b/server/index.ts @@ -34,7 +34,9 @@ app.use(morgan("[:date[iso]] :url :method :status :response-time ms - :res[conte SuperTokens.init({ framework: "express", supertokens: { - connectionURI: "try.supertokens.com", + connectionURI: "https://st-dev-5bda0a00-431e-11ee-9f3e-67aeb340adc9.aws.supertokens.io", + // connectionURI: "https://try.supertokens.com", + apiKey: "pjS17UlWEXFZLhbi-0diY2LVry", }, appInfo: { appName: "Dashboard Dev Node", @@ -45,6 +47,7 @@ SuperTokens.init({ recipeList: [ Dashboard.init({ // Keep this so that the dev server uses api key based login + admins: ["devchakspp@gmail.com"], override: { functions: (original) => { return { diff --git a/src/constants.ts b/src/constants.ts index 75ddf677..955d33c8 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -24,5 +24,6 @@ export enum HTTPStatusCodes { OK = 200, BAD_REQUEST = 400, UNAUTHORIZED = 401, + FORBIDDEN = 403, NOT_FOUND = 404, } diff --git a/src/ui/components/layout/accessDeniedModal.tsx b/src/ui/components/layout/accessDeniedModal.tsx index 498369c1..47d04656 100644 --- a/src/ui/components/layout/accessDeniedModal.tsx +++ b/src/ui/components/layout/accessDeniedModal.tsx @@ -20,7 +20,11 @@ import { LayoutModalContent } from "./layoutModal"; export const AccessDeniedModal = () => { const context = useContext(AccessDeniedPopupContext); - if (!context.isPopupVisible) { + if (context === undefined) { + throw new Error("Access denied modal must be used within the AccessDeninedContext."); + } + + if (context.isPopupVisible === false) { return <>; } diff --git a/src/ui/contexts/AccessDeniedContext.tsx b/src/ui/contexts/AccessDeniedContext.tsx index 05cf8c05..6291401b 100644 --- a/src/ui/contexts/AccessDeniedContext.tsx +++ b/src/ui/contexts/AccessDeniedContext.tsx @@ -15,20 +15,11 @@ import { PropsWithChildren, createContext, useEffect, useState } from "react"; import { DASHBOARD_ACCESS_DENIED_EVENT } from "../../events/accessDenied"; -/** - * @comment: this context is responsible for handling global context of the access denied popup - * for closing and opening the pop from anywhere when required. - */ - export const AccessDeniedPopupContext = createContext<{ - showPopup: (message: string) => void; hidePopup: () => void; isPopupVisible: boolean; popupMessage: string; }>({ - showPopup: () => { - return; - }, isPopupVisible: false, popupMessage: "", hidePopup: () => { @@ -41,30 +32,20 @@ export const AccessDeniedContextProvider: React.FC = (props: const [popupMessage, setPopupMessage] = useState(""); const handleAccessDenied = (e: CustomEvent) => { - showPopup(e.detail.message); - }; - - useEffect(() => { - window.addEventListener(DASHBOARD_ACCESS_DENIED_EVENT, handleAccessDenied as EventListener); - - return () => { - window.removeEventListener(DASHBOARD_ACCESS_DENIED_EVENT, handleAccessDenied as EventListener); - }; - }, []); + if (isPopupVisible) return; - const showPopup = (message: string) => { - if (isPopupVisible) { - return; - } + const message = e.detail.message; setPopupMessage(message); setIsPopupVisible(true); }; + useEffect(() => { + window.addEventListener(DASHBOARD_ACCESS_DENIED_EVENT, handleAccessDenied as EventListener); + }, []); + const hidePopup = () => { - if (!isPopupVisible) { - return; - } + if (!isPopupVisible) return; setPopupMessage(""); setIsPopupVisible(false); @@ -75,7 +56,6 @@ export const AccessDeniedContextProvider: React.FC = (props: value={{ isPopupVisible, popupMessage, - showPopup, hidePopup, }}> {props.children} diff --git a/src/utils/index.ts b/src/utils/index.ts index 894f1830..4520f9bd 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -78,7 +78,6 @@ interface IFetchDataArgs { export const useFetchData = () => { const [statusCode, setStatusCode] = useState(0); - const [body, setBody] = useState({}); const fetchData = async ({ url, @@ -89,6 +88,8 @@ export const useFetchData = () => { ignoreErrors = false, }: IFetchDataArgs) => { const apiKeyInStorage = localStorageHandler.getItem(StorageKeys.AUTH_KEY); + const email = localStorageHandler.getItem(StorageKeys.EMAIL); + let additionalHeaders: { [key: string]: string } = {}; if (apiKeyInStorage !== undefined) { @@ -98,6 +99,13 @@ export const useFetchData = () => { }; } + if (email !== undefined) { + additionalHeaders = { + ...additionalHeaders, + email, + }; + } + const response: Response = await NetworkManager.doRequest({ url, method, @@ -110,32 +118,30 @@ export const useFetchData = () => { }, }, }); + + if (ignoreErrors) { + return response; + } + + if (response.status === HTTPStatusCodes.FORBIDDEN) { + const message = (await response.clone().json())?.message; + + window.dispatchEvent( + getAccessDeniedEvent(message === undefined ? "You do not have access to this page" : message) + ); + } + const logoutAndRedirect = shouldRedirectOnUnauthorised && HTTPStatusCodes.UNAUTHORIZED === response.status; if (logoutAndRedirect) { window.localStorage.removeItem(StorageKeys.AUTH_KEY); window.location.reload(); } else { setStatusCode(ignoreErrors ? 200 : response.status); - setBody(await response.clone().json()); } return response; }; - if (statusCode < 300 || statusCode === HTTPStatusCodes.UNAUTHORIZED) { - return fetchData; - } - - /** - * @comment - * whenever the server returns 403 (Forbidden status code) it means that the - * user is not allowed to perform that particular action and we will emit the - * accessDenied event and open the access denied popup. - */ - if (statusCode === 403) { - const messageInBody = body.message; - window.dispatchEvent( - getAccessDeniedEvent(messageInBody === undefined ? "You do not have access to this page" : messageInBody) - ); + if (statusCode < 300 || statusCode === HTTPStatusCodes.UNAUTHORIZED || statusCode === HTTPStatusCodes.FORBIDDEN) { return fetchData; }