move authToken, userClaims, userRoles to AppContext

This commit is contained in:
Sidney Alcantara
2021-09-16 18:41:03 +10:00
parent a1a6339e37
commit 9a616924c5
8 changed files with 97 additions and 75 deletions

View File

@@ -37,8 +37,8 @@ export default function NavDrawer({
currentSection,
...props
}: INavDrawerProps) {
const { userDoc } = useAppContext();
const { userClaims, tables } = useProjectContext();
const { userDoc, userClaims } = useAppContext();
const { tables } = useProjectContext();
const favorites = Array.isArray(userDoc.state.doc?.favoriteTables)
? userDoc.state.doc.favoriteTables

View File

@@ -19,6 +19,7 @@ import LockIcon from "@mui/icons-material/LockOutlined";
import { FieldType } from "constants/fields";
import { getFieldProp } from "components/fields";
import { useAppContext } from "contexts/AppContext";
import { useProjectContext } from "contexts/ProjectContext";
import { TableOrder } from "@src/hooks/useTable";
@@ -115,7 +116,8 @@ export default function DraggableHeaderRenderer<R>({
}) {
const classes = useStyles();
const { tableState, tableActions, userClaims, columnMenuRef } =
const {userClaims}=useAppContext()
const { tableState, tableActions, columnMenuRef } =
useProjectContext();
const [{ isDragging }, drag] = useDrag({
item: { key: column.key, type: "COLUMN_DRAG" },

View File

@@ -21,8 +21,8 @@ import { FieldType } from "constants/fields";
export const TABLE_HEADER_HEIGHT = 44;
export default function TableHeader() {
const { currentUser } = useAppContext();
const { tableActions, tableState, userClaims } = useProjectContext();
const { currentUser, userClaims } = useAppContext();
const { tableActions, tableState, } = useProjectContext();
const hasDerivatives =
tableState &&

View File

@@ -43,4 +43,5 @@ export const RunRoutes: { [key: string]: RunRoute } = {
actionScript: { path: "/actionScript", method: "POST" },
buildFunction: { path: "/buildFunction", method: "POST" },
projectOwner: { path: "/projectOwner", method: "GET" },
setOwnerRoles: { path: "/setOwnerRoles", method: "GET" },
};

View File

@@ -20,9 +20,12 @@ const useThemeOverriddenState = createPersistedState(
"__ROWY__THEME_OVERRIDDEN"
);
interface AppContextInterface {
interface IAppContext {
projectId: string;
currentUser: firebase.User | null | undefined;
userClaims: Record<string, any> | undefined;
userRoles: null | string[];
authToken: string;
userDoc: any;
theme: keyof typeof themes;
themeOverridden: boolean;
@@ -30,9 +33,12 @@ interface AppContextInterface {
setThemeOverridden: React.Dispatch<React.SetStateAction<boolean>>;
}
export const AppContext = React.createContext<AppContextInterface>({
export const AppContext = React.createContext<IAppContext>({
projectId: "",
currentUser: undefined,
userClaims: undefined,
userRoles: [],
authToken: "",
userDoc: undefined,
theme: "light",
themeOverridden: false,
@@ -47,9 +53,23 @@ export const AppProvider: React.FC = ({ children }) => {
const [currentUser, setCurrentUser] = useState<
firebase.User | null | undefined
>();
// Store user auth data
const [userClaims, setUserClaims] =
useState<IAppContext["userClaims"]>(undefined);
const [userRoles, setUserRoles] = useState<IAppContext["userRoles"]>([]);
const [authToken, setAuthToken] = useState<IAppContext["authToken"]>("");
// Get user data from Firebase Auth event
useEffect(() => {
auth.onAuthStateChanged((auth) => {
setCurrentUser(auth);
if (auth)
auth.getIdTokenResult(true).then((results) => {
setAuthToken(results.token);
setUserRoles(results.claims.roles || []);
setUserClaims(results.claims);
});
});
}, []);
@@ -128,8 +148,11 @@ export const AppProvider: React.FC = ({ children }) => {
<AppContext.Provider
value={{
projectId,
userDoc: { state: userDoc, dispatch: dispatchUserDoc },
currentUser,
userClaims,
userRoles,
authToken,
userDoc: { state: userDoc, dispatch: dispatchUserDoc },
theme,
themeOverridden,
setTheme,

View File

@@ -10,7 +10,8 @@ import { useAppContext } from "./AppContext";
import { SideDrawerRef } from "components/SideDrawer";
import { ColumnMenuRef } from "components/Table/ColumnMenu";
import { ImportWizardRef } from "components/Wizards/ImportWizard";
import { RunRoute } from "@src/constants/runRoutes";
import { rowyRun, IRowyRunRequestProps } from "utils/rowyRun";
export type Table = {
id: string;
@@ -23,7 +24,7 @@ export type Table = {
tableType: string;
};
interface ProjectContextProps {
interface IProjectContext {
tables: Table[];
roles: string[];
tableState: TableState;
@@ -58,8 +59,6 @@ interface ProjectContextProps {
deleteTable: (id: string) => void;
};
userClaims: any;
// A ref to the data grid. Contains data grid functions
dataGridRef: React.RefObject<DataGridHandle>;
// A ref to the side drawer state. Prevents unnecessary re-renders
@@ -69,15 +68,12 @@ interface ProjectContextProps {
// A ref ot the import wizard. Prevents unnecessary re-renders
importWizardRef: React.MutableRefObject<ImportWizardRef | undefined>;
rowyRun: (args: {
route: RunRoute;
body?: any;
params?: string[];
localhost?: boolean;
}) => Promise<any>;
rowyRun: (
args: Omit<IRowyRunRequestProps, "rowyRunUrl" | "authToken">
) => Promise<any>;
}
const ProjectContext = React.createContext<Partial<ProjectContextProps>>({});
const ProjectContext = React.createContext<Partial<IProjectContext>>({});
export default ProjectContext;
export const rowyUser = (currentUser) => {
@@ -96,15 +92,13 @@ export const rowyUser = (currentUser) => {
export const useProjectContext = () => useContext(ProjectContext);
export const ProjectContextProvider: React.FC = ({ children }) => {
const { currentUser, userRoles, authToken } = useAppContext();
const { enqueueSnackbar } = useSnackbar();
const { tableState, tableActions } = useTable();
const [tables, setTables] = useState<ProjectContextProps["tables"]>();
const [tables, setTables] = useState<IProjectContext["tables"]>();
const [settings, settingsActions] = useSettings();
const [userRoles, setUserRoles] = useState<null | string[]>();
const [userClaims, setUserClaims] = useState<any>();
const { currentUser } = useAppContext();
const [authToken, setAuthToken] = useState("");
useEffect(() => {
const { tables } = settings;
if (tables && userRoles) {
@@ -138,17 +132,7 @@ export const ProjectContextProvider: React.FC = ({ children }) => {
[tables]
);
useEffect(() => {
if (currentUser && !userClaims) {
currentUser.getIdTokenResult(true).then((results) => {
setAuthToken(results.token);
setUserRoles(results.claims.roles || []);
setUserClaims(results.claims);
});
}
}, [currentUser]);
const updateCell: ProjectContextProps["updateCell"] = (
const updateCell: IProjectContext["updateCell"] = (
ref,
fieldName,
value,
@@ -182,40 +166,11 @@ export const ProjectContextProvider: React.FC = ({ children }) => {
}
);
};
// rowyRun access
const rowyRun = async ({
route,
body,
params,
localhost = false,
}: {
route: RunRoute;
body?: any;
params?: string[];
localhost?: boolean;
}) => {
const { method, path } = route;
let url = `${
localhost ? "http://localhost:8080" : settings.doc.rowyRunUrl
}${path}`;
if (params && params.length > 0) url = url + "/" + params.join("/");
const response = await fetch(url, {
method: method, // *GET, POST, PUT, DELETE, etc.
mode: "cors", // no-cors, *cors, same-origin
cache: "no-cache", // *default, no-cache, reload, force-cache, only-if-cached
credentials: "same-origin", // include, *same-origin, omit
headers: {
"Content-Type": "application/json",
// 'Content-Type': 'application/x-www-form-urlencoded',
Authorization: "Bearer " + authToken,
},
redirect: "follow", // manual, *follow, error
referrerPolicy: "no-referrer", // no-referrer, *no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin, unsafe-url
body: body && method !== "GET" ? JSON.stringify(body) : null, // body data type must match "Content-Type" header
});
console.log(response);
return response.json(); // parses JSON response into native JavaScript objects
};
const _rowyRun: IProjectContext["rowyRun"] = async (args) =>
rowyRun({ rowyRunUrl: settings.doc.rowyRunUrl, authToken, ...args });
// A ref to the data grid. Contains data grid functions
const dataGridRef = useRef<DataGridHandle>(null);
const sideDrawerRef = useRef<SideDrawerRef>();
@@ -231,12 +186,11 @@ export const ProjectContextProvider: React.FC = ({ children }) => {
settingsActions,
roles,
tables,
userClaims,
dataGridRef,
sideDrawerRef,
columnMenuRef,
importWizardRef,
rowyRun,
rowyRun: _rowyRun,
}}
>
{children}

View File

@@ -48,8 +48,8 @@ import { APP_BAR_HEIGHT } from "components/Navigation";
const useHomeViewState = createPersistedState("__ROWY__HOME_VIEW");
export default function HomePage() {
const { userDoc } = useAppContext();
const { tables, userClaims } = useProjectContext();
const { userDoc, userClaims } = useAppContext();
const { tables } = useProjectContext();
const [results, query, handleQuery] = useBasicSearch(
tables ?? [],
@@ -131,7 +131,7 @@ export default function HomePage() {
);
if (tables.length === 0) {
if (userClaims.roles.includes("ADMIN"))
if (userClaims?.roles.includes("ADMIN"))
return (
<>
<HomeWelcomePrompt />
@@ -167,7 +167,7 @@ export default function HomePage() {
const getActions = (table: Table) => (
<>
{userClaims.roles.includes("ADMIN") && (
{userClaims?.roles.includes("ADMIN") && (
<IconButton
aria-label="Edit table"
onClick={() =>
@@ -258,7 +258,7 @@ export default function HomePage() {
/>
)}
{userClaims.roles.includes("ADMIN") && (
{userClaims?.roles.includes("ADMIN") && (
<>
{createTableFab}
<TableSettingsDialog

42
src/utils/rowyRun.ts Normal file
View File

@@ -0,0 +1,42 @@
import { RunRoute } from "constants/runRoutes";
export interface IRowyRunRequestProps {
rowyRunUrl: string;
authToken?: string;
route: RunRoute;
body?: any;
params?: string[];
localhost?: boolean;
json?: boolean;
}
export const rowyRun = async ({
rowyRunUrl,
authToken,
route,
body,
params,
localhost = false,
json = true,
}: IRowyRunRequestProps) => {
const { method, path } = route;
let url = (localhost ? "http://localhost:8080" : rowyRunUrl) + path;
if (params && params.length > 0) url = url + "/" + params.join("/");
const response = await fetch(url, {
method: method,
mode: "cors",
cache: "no-cache",
credentials: "same-origin",
headers: {
"Content-Type": "application/json",
Authorization: "Bearer " + authToken,
},
redirect: "follow",
referrerPolicy: "no-referrer",
body: body && method !== "GET" ? JSON.stringify(body) : null, // body data type must match "Content-Type" header
});
if (json) return await response.json();
return response;
};