From 7daff1e6a774ef599987f7ec7c74ec1d9206b222 Mon Sep 17 00:00:00 2001 From: TsurutaYoshiki Date: Tue, 21 Jan 2025 04:53:36 +0000 Subject: [PATCH 01/17] topic/delete cookie and use getIdToken --- web/src/pages/App/AppPage.jsx | 10 +++------- web/src/pages/Login/LoginPage.jsx | 9 +-------- web/src/services/firebaseApi.js | 8 +++++++- web/src/services/tcApi.js | 2 +- 4 files changed, 12 insertions(+), 17 deletions(-) diff --git a/web/src/pages/App/AppPage.jsx b/web/src/pages/App/AppPage.jsx index ac65a1ed..30857295 100644 --- a/web/src/pages/App/AppPage.jsx +++ b/web/src/pages/App/AppPage.jsx @@ -1,6 +1,5 @@ import { Box } from "@mui/material"; import React, { useEffect } from "react"; -import { useCookies } from "react-cookie"; import { ErrorBoundary } from "react-error-boundary"; import { useDispatch, useSelector } from "react-redux"; import { useLocation, useNavigate } from "react-router-dom"; @@ -9,7 +8,7 @@ import { useSkipUntilAuthTokenIsReady } from "../../hooks/auth"; import { useTryLoginMutation } from "../../services/tcApi"; import { setAuthToken } from "../../slices/auth"; import { mainMaxWidth } from "../../utils/const"; -import { authCookieName } from "../Login/LoginPage"; +import { auth } from "../../utils/firebase"; import { AppBar } from "./AppBar"; import { AppFallback } from "./AppFallback"; @@ -18,9 +17,6 @@ import { Main } from "./Main"; import { OutletWithCheckedParams } from "./OutletWithCheckedParams"; export function App() { - /* eslint-disable-next-line no-unused-vars */ - const [cookies, _setCookie, _removeCookie] = useCookies([authCookieName]); - const skip = useSkipUntilAuthTokenIsReady(); const dispatch = useDispatch(); @@ -34,7 +30,7 @@ export function App() { if (!skip) return; // auth token is ready const _checkToken = async () => { try { - const accessToken = cookies[authCookieName]; + const accessToken = await auth.currentUser?.getIdToken(true); if (!accessToken) throw new Error("Missing cookie"); dispatch(setAuthToken(accessToken)); await tryLogin().unwrap(); // throw error if accessToken is expired @@ -49,7 +45,7 @@ export function App() { } }; _checkToken(); - }, [cookies, dispatch, location, navigate, skip, tryLogin]); + }, [dispatch, location, navigate, skip, tryLogin]); return ( <> diff --git a/web/src/pages/Login/LoginPage.jsx b/web/src/pages/Login/LoginPage.jsx index a0acee00..80376b8e 100644 --- a/web/src/pages/Login/LoginPage.jsx +++ b/web/src/pages/Login/LoginPage.jsx @@ -16,7 +16,6 @@ import { } from "@mui/material"; import { sendEmailVerification } from "firebase/auth"; import React, { useEffect, useState } from "react"; -import { useCookies } from "react-cookie"; import { useDispatch } from "react-redux"; import { useLocation, useNavigate } from "react-router-dom"; @@ -39,9 +38,6 @@ export function Login() { const location = useLocation(); const navigate = useNavigate(); - /* eslint-disable-next-line no-unused-vars */ - const [_cookies, setCookie, removeCookie] = useCookies([authCookieName]); - const metemcyberAuthUrl = process.env.REACT_APP_METEMCYBER_AUTH_URL; const [signInWithEmailAndPassword] = useSignInWithEmailAndPasswordMutation(); @@ -51,9 +47,8 @@ export function Login() { useEffect(() => { dispatch(clearAuth()); - removeCookie(authCookieName, cookiesOptions); setMessage(location.state?.message); - }, [dispatch, location, removeCookie]); + }, [dispatch, location]); const callSignInWithEmailAndPassword = async (email, password) => { return await signInWithEmailAndPassword({ email, password }) @@ -83,8 +78,6 @@ export function Login() { }; const navigateInternalPage = async (userCredential) => { - const accessToken = userCredential.user.accessToken; - setCookie(authCookieName, accessToken, cookiesOptions); try { await tryLogin().unwrap(); navigate({ diff --git a/web/src/services/firebaseApi.js b/web/src/services/firebaseApi.js index f06f530d..60231790 100644 --- a/web/src/services/firebaseApi.js +++ b/web/src/services/firebaseApi.js @@ -1,5 +1,10 @@ import { createApi, fakeBaseQuery } from "@reduxjs/toolkit/query/react"; -import { signInWithEmailAndPassword, signInWithPopup } from "firebase/auth"; +import { + signInWithEmailAndPassword, + signInWithPopup, + setPersistence, + browserSessionPersistence, +} from "firebase/auth"; import { setAuthToken } from "../slices/auth"; import { auth, samlProvider } from "../utils/firebase"; @@ -26,6 +31,7 @@ export const firebaseApi = createApi({ */ signInWithEmailAndPassword: builder.mutation({ queryFn: async ({ email, password }, { dispatch }) => { + await setPersistence(auth, browserSessionPersistence); return await signInWithEmailAndPassword(auth, email, password) .then((credential) => { dispatch(setAuthToken(credential.user.accessToken)); diff --git a/web/src/services/tcApi.js b/web/src/services/tcApi.js index 6dfb6b35..d7d19b28 100644 --- a/web/src/services/tcApi.js +++ b/web/src/services/tcApi.js @@ -24,7 +24,7 @@ export const tcApi = createApi({ baseQuery: fetchBaseQuery({ baseUrl: process.env.REACT_APP_API_BASE_URL, prepareHeaders: (headers, { getState }) => { - /* Note: access token is stored in auth.token via firebaseApi or cookie */ + /* Note: access token is stored in auth.token via firebaseApi */ const token = getState().auth.token; if (token) { headers.set("authorization", `Bearer ${token}`); From 4eb970ce48e99cbf93a534247ead6c08da034466 Mon Sep 17 00:00:00 2001 From: TsurutaYoshiki Date: Wed, 22 Jan 2025 04:24:21 +0000 Subject: [PATCH 02/17] delete cookie --- web/package-lock.json | 51 +-------------------- web/package.json | 1 - web/src/index.jsx | 75 +++++++++++++++---------------- web/src/pages/App/AppPage.jsx | 2 +- web/src/pages/Login/LoginPage.jsx | 1 - 5 files changed, 38 insertions(+), 92 deletions(-) diff --git a/web/package-lock.json b/web/package-lock.json index c914f3f5..27dfc23e 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -24,7 +24,6 @@ "notistack": "^3.0.1", "prop-types": "^15.8.1", "react": "^18.2.0", - "react-cookie": "^7.2.1", "react-dom": "^18.2.0", "react-error-boundary": "^5.0.0", "react-icons": "^5.0.1", @@ -5235,12 +5234,6 @@ "@types/node": "*" } }, - "node_modules/@types/cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==", - "license": "MIT" - }, "node_modules/@types/eslint": { "version": "8.56.12", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.12.tgz", @@ -5319,16 +5312,6 @@ "@types/node": "*" } }, - "node_modules/@types/hoist-non-react-statics": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.6.tgz", - "integrity": "sha512-lPByRJUer/iN/xa4qpyL0qmL11DqNW81iU/IG1S3uvRUq4oKagz8VCxZjiWkumgt66YT3vOdDgZ0o32sGKtCEw==", - "license": "MIT", - "dependencies": { - "@types/react": "*", - "hoist-non-react-statics": "^3.3.0" - } - }, "node_modules/@types/html-minifier-terser": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", @@ -5465,6 +5448,7 @@ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.0.4.tgz", "integrity": "sha512-3O4QisJDYr1uTUMZHA2YswiQZRq+Pd8D+GdVFYikTutYsTz+QZgWkAPnP7rx9txoI6EXKcPiluMqWPFV3tT9Wg==", "license": "MIT", + "peer": true, "dependencies": { "csstype": "^3.0.2" } @@ -7734,15 +7718,6 @@ "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", "license": "MIT" }, - "node_modules/cookie": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", - "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, "node_modules/cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", @@ -16528,20 +16503,6 @@ "react-scripts": ">=2.1.3" } }, - "node_modules/react-cookie": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/react-cookie/-/react-cookie-7.2.2.tgz", - "integrity": "sha512-e+hi6axHcw9VODoeVu8WyMWyoosa1pzpyjfvrLdF7CexfU+WSGZdDuRfHa4RJgTpfv3ZjdIpHE14HpYBieHFhg==", - "license": "MIT", - "dependencies": { - "@types/hoist-non-react-statics": "^3.3.5", - "hoist-non-react-statics": "^3.3.2", - "universal-cookie": "^7.0.0" - }, - "peerDependencies": { - "react": ">= 16.3.0" - } - }, "node_modules/react-dev-utils": { "version": "12.0.1", "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz", @@ -19547,16 +19508,6 @@ "node": ">=8" } }, - "node_modules/universal-cookie": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/universal-cookie/-/universal-cookie-7.2.2.tgz", - "integrity": "sha512-fMiOcS3TmzP2x5QV26pIH3mvhexLIT0HmPa3V7Q7knRfT9HG6kTwq02HZGLPw0sAOXrAmotElGRvTLCMbJsvxQ==", - "license": "MIT", - "dependencies": { - "@types/cookie": "^0.6.0", - "cookie": "^0.7.2" - } - }, "node_modules/universalify": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", diff --git a/web/package.json b/web/package.json index 87100e6f..c4f02e90 100644 --- a/web/package.json +++ b/web/package.json @@ -19,7 +19,6 @@ "notistack": "^3.0.1", "prop-types": "^15.8.1", "react": "^18.2.0", - "react-cookie": "^7.2.1", "react-dom": "^18.2.0", "react-error-boundary": "^5.0.0", "react-icons": "^5.0.1", diff --git a/web/src/index.jsx b/web/src/index.jsx index df7c0a94..917a85ea 100644 --- a/web/src/index.jsx +++ b/web/src/index.jsx @@ -2,7 +2,6 @@ import { CssBaseline } from "@mui/material"; import { createTheme, ThemeProvider } from "@mui/material/styles"; import { SnackbarProvider } from "notistack"; import React from "react"; -import { CookiesProvider } from "react-cookie"; import { createRoot } from "react-dom/client"; import { Provider } from "react-redux"; import { BrowserRouter as Router, Navigate, Route, Routes } from "react-router-dom"; @@ -26,44 +25,42 @@ const root = createRoot(container); root.render( - - - - - - - - } /> - } /> - }> - } /> - - } /> - - - } /> - } /> - - - } /> - } /> - - } /> - - } /> - } /> - + + + + + + + } /> + } /> + }> + } /> + + } /> - - - - - - + + } /> + } /> + + + } /> + } /> + + } /> + + } /> + } /> + + + + + + + , ); diff --git a/web/src/pages/App/AppPage.jsx b/web/src/pages/App/AppPage.jsx index 30857295..0a4a4bc3 100644 --- a/web/src/pages/App/AppPage.jsx +++ b/web/src/pages/App/AppPage.jsx @@ -31,7 +31,7 @@ export function App() { const _checkToken = async () => { try { const accessToken = await auth.currentUser?.getIdToken(true); - if (!accessToken) throw new Error("Missing cookie"); + if (!accessToken) throw new Error("Missing accessToken"); dispatch(setAuthToken(accessToken)); await tryLogin().unwrap(); // throw error if accessToken is expired } catch (error) { diff --git a/web/src/pages/Login/LoginPage.jsx b/web/src/pages/Login/LoginPage.jsx index 80376b8e..5a93abc4 100644 --- a/web/src/pages/Login/LoginPage.jsx +++ b/web/src/pages/Login/LoginPage.jsx @@ -28,7 +28,6 @@ import { clearAuth } from "../../slices/auth"; import { samlProvider } from "../../utils/firebase"; export const authCookieName = "Authorization"; -export const cookiesOptions = { path: process.env.PUBLIC_URL || "/" }; export function Login() { const [message, setMessage] = useState(null); From 35358f8e35bcbe8a8ba93c8ea1cf2c10c01012c9 Mon Sep 17 00:00:00 2001 From: TsurutaYoshiki Date: Thu, 23 Jan 2025 04:15:54 +0000 Subject: [PATCH 03/17] delet useSkipUntilAuthTokenIsReady --- web/src/components/PTeamLabel.jsx | 5 +---- web/src/components/PTeamSettingsModal.jsx | 3 +-- web/src/hooks/auth.js | 7 ------- .../AcceptPTeamInvitationPage.jsx | 5 +---- web/src/pages/Account/AccountPage.jsx | 5 +---- web/src/pages/App/OutletWithCheckedParams.jsx | 6 +----- web/src/pages/App/TeamSelector.jsx | 5 +---- web/src/pages/PTeam/PTeamMemberMenu.jsx | 3 +-- web/src/pages/PTeam/PTeamPage.jsx | 3 +-- web/src/pages/Status/PTeamServiceDelete.jsx | 3 +-- .../pages/Status/PTeamServicesListModal.jsx | 3 +-- web/src/pages/Status/StatusPage.jsx | 11 ++++------ web/src/pages/Tag/PTeamTaggedTopics.jsx | 3 +-- web/src/pages/Tag/ReportCompletedActions.jsx | 5 +---- web/src/pages/Tag/TagPage.jsx | 8 +++---- web/src/pages/Tag/TopicCard.jsx | 21 ++++++------------- web/src/pages/Tag/TopicTagSelector.jsx | 5 +---- web/src/pages/Tag/TopicTicketAccordion.jsx | 5 +---- web/src/pages/TopicDetail/TopicDetailPage.jsx | 12 ++--------- .../TopicManagement/TopicManagementPage.jsx | 18 ++++------------ 20 files changed, 33 insertions(+), 103 deletions(-) delete mode 100644 web/src/hooks/auth.js diff --git a/web/src/components/PTeamLabel.jsx b/web/src/components/PTeamLabel.jsx index f623fb6a..e213cd0d 100644 --- a/web/src/components/PTeamLabel.jsx +++ b/web/src/components/PTeamLabel.jsx @@ -3,7 +3,6 @@ import { Box, IconButton, Typography } from "@mui/material"; import PropTypes from "prop-types"; import React, { useState } from "react"; -import { useSkipUntilAuthTokenIsReady } from "../hooks/auth"; import { useGetUserMeQuery } from "../services/tcApi"; import { APIError } from "../utils/APIError"; import { errorToString } from "../utils/func"; @@ -16,14 +15,12 @@ export function PTeamLabel(props) { const [pteamSettingsModalOpen, setPTeamSettingsModalOpen] = useState(false); - const skip = useSkipUntilAuthTokenIsReady(); const { data: userMe, error: userMeError, isLoading: userMeIsLoading, - } = useGetUserMeQuery(undefined, { skip }); + } = useGetUserMeQuery(undefined); - if (skip) return <>; if (userMeError) throw new APIError(errorToString(userMeError), { api: "getUserMe", diff --git a/web/src/components/PTeamSettingsModal.jsx b/web/src/components/PTeamSettingsModal.jsx index 89d99fa3..4dd2a624 100644 --- a/web/src/components/PTeamSettingsModal.jsx +++ b/web/src/components/PTeamSettingsModal.jsx @@ -15,7 +15,6 @@ import React, { useState } from "react"; import { TabPanel } from "../components/TabPanel"; import dialogStyle from "../cssModule/dialog.module.css"; -import { useSkipUntilAuthTokenIsReady } from "../hooks/auth"; import { useGetPTeamQuery } from "../services/tcApi"; import { APIError } from "../utils/APIError"; import { a11yProps, errorToString } from "../utils/func.js"; @@ -27,7 +26,7 @@ export function PTeamSettingsModal(props) { const { pteamId, onSetShow, show, defaultTabIndex } = props; const [tab, setTab] = useState(defaultTabIndex ?? 0); - const skip = useSkipUntilAuthTokenIsReady() || !pteamId; + const skip = !pteamId; const { data: pteam, diff --git a/web/src/hooks/auth.js b/web/src/hooks/auth.js deleted file mode 100644 index f6ca66bd..00000000 --- a/web/src/hooks/auth.js +++ /dev/null @@ -1,7 +0,0 @@ -import { useSelector } from "react-redux"; - -export function useSkipUntilAuthTokenIsReady() { - const authToken = useSelector((state) => state.auth.token); - const skip = authToken === undefined; - return skip; -} diff --git a/web/src/pages/AcceptPTeamInvitation/AcceptPTeamInvitationPage.jsx b/web/src/pages/AcceptPTeamInvitation/AcceptPTeamInvitationPage.jsx index 888fcbf9..d25c1694 100644 --- a/web/src/pages/AcceptPTeamInvitation/AcceptPTeamInvitationPage.jsx +++ b/web/src/pages/AcceptPTeamInvitation/AcceptPTeamInvitationPage.jsx @@ -3,7 +3,6 @@ import { useSnackbar } from "notistack"; import React from "react"; import { useLocation, useNavigate } from "react-router-dom"; -import { useSkipUntilAuthTokenIsReady } from "../../hooks/auth"; import { useApplyPTeamInvitationMutation, useGetPTeamInvitationQuery } from "../../services/tcApi"; import { APIError } from "../../utils/APIError"; import { commonButtonStyle } from "../../utils/const"; @@ -19,14 +18,12 @@ export function AcceptPTeamInvitation() { const params = new URLSearchParams(useLocation().search); const tokenId = params.get("token"); - const skip = useSkipUntilAuthTokenIsReady(); const { data: detail, error: detailError, isLoading: detailIsLoading, - } = useGetPTeamInvitationQuery(tokenId, { skip }); + } = useGetPTeamInvitationQuery(tokenId); - if (skip) return <>; if (detailError) throw new APIError("This invitation is invalid or already expired.", { api: "getPTeamInvitation", diff --git a/web/src/pages/Account/AccountPage.jsx b/web/src/pages/Account/AccountPage.jsx index f15f54df..e4656882 100644 --- a/web/src/pages/Account/AccountPage.jsx +++ b/web/src/pages/Account/AccountPage.jsx @@ -14,7 +14,6 @@ import { useSnackbar } from "notistack"; import React, { useState } from "react"; import { UUIDTypography } from "../../components/UUIDTypography"; -import { useSkipUntilAuthTokenIsReady } from "../../hooks/auth"; import { useGetUserMeQuery, useUpdateUserMutation } from "../../services/tcApi"; import { APIError } from "../../utils/APIError"; import { errorToString } from "../../utils/func"; @@ -28,14 +27,12 @@ export function Account() { const { enqueueSnackbar } = useSnackbar(); const [updateUser] = useUpdateUserMutation(); - const skip = useSkipUntilAuthTokenIsReady(); const { data: userMe, error: userMeError, isLoading: userMeIsLoading, - } = useGetUserMeQuery(undefined, { skip }); + } = useGetUserMeQuery(undefined); - if (skip) return <>; if (userMeError) throw new APIError(errorToString(userMeError), { api: "getUserMe", diff --git a/web/src/pages/App/OutletWithCheckedParams.jsx b/web/src/pages/App/OutletWithCheckedParams.jsx index 365d99fc..1309baf8 100644 --- a/web/src/pages/App/OutletWithCheckedParams.jsx +++ b/web/src/pages/App/OutletWithCheckedParams.jsx @@ -1,7 +1,6 @@ import React, { useEffect } from "react"; import { Outlet, useLocation, useNavigate } from "react-router-dom"; -import { useSkipUntilAuthTokenIsReady } from "../../hooks/auth"; import { useGetUserMeQuery } from "../../services/tcApi"; import { APIError } from "../../utils/APIError"; import { errorToString } from "../../utils/func"; @@ -11,21 +10,18 @@ export function OutletWithCheckedParams() { const navigate = useNavigate(); const location = useLocation(); - const skip = useSkipUntilAuthTokenIsReady(); - const { data: userMe, error: userMeError, isLoading: userMeIsLoading, isFetching: userMeIsFetching, - } = useGetUserMeQuery(undefined, { skip }); + } = useGetUserMeQuery(undefined); useEffect(() => { if (!userMe || userMeIsFetching) return; navigateSpecifiedPteam(location, userMe.pteam_roles, navigate); }, [navigate, location, userMe, userMeIsFetching]); - if (skip) return <>; if (userMeError) throw new APIError(errorToString(userMeError), { api: "getUserMe" }); if (userMeIsLoading) return <>Now loading UserInfo...; diff --git a/web/src/pages/App/TeamSelector.jsx b/web/src/pages/App/TeamSelector.jsx index 3af76d8e..26fd54ae 100644 --- a/web/src/pages/App/TeamSelector.jsx +++ b/web/src/pages/App/TeamSelector.jsx @@ -4,7 +4,6 @@ import { grey } from "@mui/material/colors"; import React, { useEffect, useMemo, useState } from "react"; import { useLocation, useNavigate } from "react-router-dom"; -import { useSkipUntilAuthTokenIsReady } from "../../hooks/auth"; import { useGetUserMeQuery } from "../../services/tcApi"; import { APIError } from "../../utils/APIError"; import { LocationReader } from "../../utils/LocationReader"; @@ -35,12 +34,11 @@ export function TeamSelector() { const [openPTeamCreationModal, setOpenPTeamCreationModal] = useState(false); const locationReader = useMemo(() => new LocationReader(location), [location]); - const skip = useSkipUntilAuthTokenIsReady(); const { data: userMe, error: userMeError, isLoading: userMeIsLoading, - } = useGetUserMeQuery(undefined, { skip }); + } = useGetUserMeQuery(undefined); useEffect(() => { if (!userMe) return; @@ -50,7 +48,6 @@ export function TeamSelector() { ); }, [userMe, locationReader]); - if (skip) return <>; if (userMeError) throw new APIError(errorToString(userMeError), { api: "getUserMe" }); if (userMeIsLoading) return <>Now loading UserInfo...; diff --git a/web/src/pages/PTeam/PTeamMemberMenu.jsx b/web/src/pages/PTeam/PTeamMemberMenu.jsx index 1dc764bf..2f2f95f8 100644 --- a/web/src/pages/PTeam/PTeamMemberMenu.jsx +++ b/web/src/pages/PTeam/PTeamMemberMenu.jsx @@ -7,7 +7,6 @@ import { Button, Dialog, DialogContent, Menu, MenuItem } from "@mui/material"; import PropTypes from "prop-types"; import React, { useState } from "react"; -import { useSkipUntilAuthTokenIsReady } from "../../hooks/auth"; import { useGetPTeamQuery, useGetUserMeQuery } from "../../services/tcApi"; import { APIError } from "../../utils/APIError"; import { errorToString, checkAdmin } from "../../utils/func"; @@ -23,7 +22,7 @@ export function PTeamMemberMenu(props) { const [anchorEl, setAnchorEl] = useState(null); const open = Boolean(anchorEl); - const skip = useSkipUntilAuthTokenIsReady() || !pteamId; + const skip = !pteamId; const { data: userMe, error: userMeError, diff --git a/web/src/pages/PTeam/PTeamPage.jsx b/web/src/pages/PTeam/PTeamPage.jsx index 28f994f5..d5b09683 100644 --- a/web/src/pages/PTeam/PTeamPage.jsx +++ b/web/src/pages/PTeam/PTeamPage.jsx @@ -4,7 +4,6 @@ import { useLocation } from "react-router"; import { PTeamLabel } from "../../components/PTeamLabel"; import { TabPanel } from "../../components/TabPanel"; -import { useSkipUntilAuthTokenIsReady } from "../../hooks/auth"; import { useGetPTeamMembersQuery } from "../../services/tcApi"; import { APIError } from "../../utils/APIError"; import { experienceColors, noPTeamMessage } from "../../utils/const"; @@ -19,7 +18,7 @@ export function PTeam() { const params = new URLSearchParams(location.search); const pteamId = params.get("pteamId"); - const skip = useSkipUntilAuthTokenIsReady() || !pteamId; + const skip = !pteamId; const { data: members, error: membersError, diff --git a/web/src/pages/Status/PTeamServiceDelete.jsx b/web/src/pages/Status/PTeamServiceDelete.jsx index 4bf2775d..4b10b496 100644 --- a/web/src/pages/Status/PTeamServiceDelete.jsx +++ b/web/src/pages/Status/PTeamServiceDelete.jsx @@ -15,7 +15,6 @@ import React, { useState } from "react"; import { useLocation, useNavigate } from "react-router"; import styles from "../../cssModule/dialog.module.css"; -import { useSkipUntilAuthTokenIsReady } from "../../hooks/auth"; import { useDeletePTeamServiceMutation, useGetPTeamQuery } from "../../services/tcApi"; import { APIError } from "../../utils/APIError"; import { errorToString } from "../../utils/func"; @@ -32,7 +31,7 @@ export function PTeamServiceDelete(props) { const params = new URLSearchParams(location.search); const serviceId = params.get("serviceId"); - const skip = useSkipUntilAuthTokenIsReady() || !pteamId; + const skip = !pteamId; const { data: pteam, error: pteamError, diff --git a/web/src/pages/Status/PTeamServicesListModal.jsx b/web/src/pages/Status/PTeamServicesListModal.jsx index 330fedc1..b667561b 100644 --- a/web/src/pages/Status/PTeamServicesListModal.jsx +++ b/web/src/pages/Status/PTeamServicesListModal.jsx @@ -22,7 +22,6 @@ import PropTypes from "prop-types"; import React, { useState } from "react"; import { useNavigate, useLocation } from "react-router-dom"; -import { useSkipUntilAuthTokenIsReady } from "../../hooks/auth"; import { useGetPTeamServiceThumbnailQuery, useGetPTeamQuery } from "../../services/tcApi"; import { APIError } from "../../utils/APIError"; import { errorToString } from "../../utils/func"; @@ -84,7 +83,7 @@ export function PTeamServicesListModal(props) { const params = new URLSearchParams(useLocation().search); const pteamId = params.get("pteamId"); - const skip = useSkipUntilAuthTokenIsReady() || !pteamId; + const skip = !pteamId; const { data: pteam, error: pteamError, diff --git a/web/src/pages/Status/StatusPage.jsx b/web/src/pages/Status/StatusPage.jsx index 5c0d29eb..f58aa270 100644 --- a/web/src/pages/Status/StatusPage.jsx +++ b/web/src/pages/Status/StatusPage.jsx @@ -32,7 +32,6 @@ import { useLocation, useNavigate } from "react-router"; import { Android12Switch } from "../../components/Android12Switch"; import { PTeamLabel } from "../../components/PTeamLabel"; -import { useSkipUntilAuthTokenIsReady } from "../../hooks/auth"; import { useGetPTeamQuery, useGetPTeamTagsSummaryQuery, @@ -141,14 +140,12 @@ export function Status() { serviceIds: [], }); - const skipByAuth = useSkipUntilAuthTokenIsReady(); - const { data: pteam, error: pteamError, isFetching: pteamIsFetching, isLoading: pteamIsLoading, - } = useGetPTeamQuery(pteamId, { skip: skipByAuth || !pteamId }); + } = useGetPTeamQuery(pteamId, { skip: !pteamId }); const { currentData: serviceTagsSummary, @@ -156,7 +153,7 @@ export function Status() { isFetching: serviceTagsSummaryIsFetching, } = useGetPTeamServiceTagsSummaryQuery( { pteamId, serviceId }, - { skip: skipByAuth || !pteamId || !serviceId || isActiveAllServicesMode }, + { skip: !pteamId || !serviceId || isActiveAllServicesMode }, ); const { @@ -164,7 +161,7 @@ export function Status() { error: pteamTagsSummaryError, isFetching: pteamTagsSummaryIsFetching, } = useGetPTeamTagsSummaryQuery(pteamId, { - skip: skipByAuth || !pteamId || !isActiveAllServicesMode, + skip: !pteamId || !isActiveAllServicesMode, }); useEffect(() => { @@ -185,7 +182,7 @@ export function Status() { }, [pteamId, pteam, pteamId, serviceId, isActiveAllServicesMode]); if (!pteamId) return <>{noPTeamMessage}; - if (skipByAuth || !pteamId) return <>; + if (!pteamId) return <>; if (pteamError) throw new APIError(errorToString(pteamError), { api: "getPTeam", diff --git a/web/src/pages/Tag/PTeamTaggedTopics.jsx b/web/src/pages/Tag/PTeamTaggedTopics.jsx index a0ebda85..53678395 100644 --- a/web/src/pages/Tag/PTeamTaggedTopics.jsx +++ b/web/src/pages/Tag/PTeamTaggedTopics.jsx @@ -2,7 +2,6 @@ import { Box, List, ListItem, MenuItem, Pagination, Select, Typography } from "@ import PropTypes from "prop-types"; import React, { useState } from "react"; -import { useSkipUntilAuthTokenIsReady } from "../../hooks/auth"; import { useGetPTeamMembersQuery } from "../../services/tcApi"; import { APIError } from "../../utils/APIError"; import { sortedSSVCPriorities } from "../../utils/const"; @@ -17,7 +16,7 @@ export function PTeamTaggedTopics(props) { const [page, setPage] = useState(1); const [perPage, setPerPage] = useState(10); - const skip = useSkipUntilAuthTokenIsReady() || !pteamId; + const skip = !pteamId; const { data: members, diff --git a/web/src/pages/Tag/ReportCompletedActions.jsx b/web/src/pages/Tag/ReportCompletedActions.jsx index 23ee1ce5..beb36f4b 100644 --- a/web/src/pages/Tag/ReportCompletedActions.jsx +++ b/web/src/pages/Tag/ReportCompletedActions.jsx @@ -18,7 +18,6 @@ import React, { useState } from "react"; import { ActionTypeIcon } from "../../components/ActionTypeIcon"; import { UUIDTypography } from "../../components/UUIDTypography"; import dialogStyle from "../../cssModule/dialog.module.css"; -import { useSkipUntilAuthTokenIsReady } from "../../hooks/auth"; import { useCreateActionLogMutation, useUpdateTicketStatusMutation, @@ -40,16 +39,14 @@ export function ReportCompletedActions(props) { const { enqueueSnackbar } = useSnackbar(); - const skip = useSkipUntilAuthTokenIsReady(); const { data: userMe, error: userMeError, isLoading: userMeIsLoading, - } = useGetUserMeQuery(undefined, { skip }); + } = useGetUserMeQuery(undefined); const [createActionLog] = useCreateActionLogMutation(); const [updateTicketStatus] = useUpdateTicketStatusMutation(); - if (skip) return <>; if (userMeError) throw new APIError(errorToString(userMeError), { api: "getUserMe" }); if (userMeIsLoading) return <>Now loading UserInfo...; diff --git a/web/src/pages/Tag/TagPage.jsx b/web/src/pages/Tag/TagPage.jsx index 42448677..ae2e7ed9 100644 --- a/web/src/pages/Tag/TagPage.jsx +++ b/web/src/pages/Tag/TagPage.jsx @@ -5,7 +5,6 @@ import { useParams, useLocation } from "react-router-dom"; import { TabPanel } from "../../components/TabPanel"; import { UUIDTypography } from "../../components/UUIDTypography"; -import { useSkipUntilAuthTokenIsReady } from "../../hooks/auth"; import { useGetPTeamQuery, useGetPTeamServiceTaggedTopicIdsQuery, @@ -22,19 +21,18 @@ import { TagReferences } from "./TagReferences.jsx"; export function Tag() { const [tabValue, setTabValue] = useState(0); - const skipByAuth = useSkipUntilAuthTokenIsReady(); const { data: allTags, error: allTagsError, isLoading: allTagsIsLoading, - } = useGetTagsQuery(undefined, { skipByAuth }); + } = useGetTagsQuery(undefined); const { tagId } = useParams(); const params = new URLSearchParams(useLocation().search); const pteamId = params.get("pteamId"); const serviceId = params.get("serviceId"); - const getDependenciesReady = !skipByAuth && pteamId && serviceId; - const getPTeamReady = !skipByAuth && pteamId; + const getDependenciesReady = pteamId && serviceId; + const getPTeamReady = pteamId; const getTopicIdsReady = getPTeamReady && serviceId && tagId; const { diff --git a/web/src/pages/Tag/TopicCard.jsx b/web/src/pages/Tag/TopicCard.jsx index 8770e03c..87ad614a 100644 --- a/web/src/pages/Tag/TopicCard.jsx +++ b/web/src/pages/Tag/TopicCard.jsx @@ -18,7 +18,6 @@ import React, { useState } from "react"; import { useParams } from "react-router-dom"; import { UUIDTypography } from "../../components/UUIDTypography"; -import { useSkipUntilAuthTokenIsReady } from "../../hooks/auth"; import { useGetPTeamTopicActionsQuery, useGetTicketsQuery, @@ -40,19 +39,14 @@ export function TopicCard(props) { const [detailOpen, setDetailOpen] = useState(false); const [actionFilter, setActionFilter] = useState(true); - const skipByAuth = useSkipUntilAuthTokenIsReady(); - const { - data: topic, - error: topicError, - isLoading: topicIsLoading, - } = useGetTopicQuery(topicId, { skipByAuth }); + const { data: topic, error: topicError, isLoading: topicIsLoading } = useGetTopicQuery(topicId); const skipByPTeamId = pteamId === undefined; const skipByTopicId = topicId === undefined; const skipByServiceId = serviceId === undefined; const skipBytagId = tagId === undefined; - const getDependenciesReady = !skipByAuth && pteamId && serviceId; + const getDependenciesReady = pteamId && serviceId; const { data: serviceDependencies, @@ -63,15 +57,12 @@ export function TopicCard(props) { data: allTags, error: allTagsError, isLoading: allTagsIsLoading, - } = useGetTagsQuery(undefined, { skipByAuth }); + } = useGetTagsQuery(undefined); const { data: pteamTopicActionsData, error: pteamTopicActionsError, isLoading: pteamTopicActionsIsLoading, - } = useGetPTeamTopicActionsQuery( - { topicId, pteamId }, - { skip: skipByAuth || skipByPTeamId || skipByTopicId }, - ); + } = useGetPTeamTopicActionsQuery({ topicId, pteamId }, { skip: skipByPTeamId || skipByTopicId }); const { data: tickets, @@ -79,12 +70,12 @@ export function TopicCard(props) { isLoading: ticketsRelatedToServiceTopicTagIsLoading, } = useGetTicketsQuery( { pteamId, serviceId, topicId, tagId }, - { skip: skipByAuth || skipByPTeamId || skipByTopicId || skipByServiceId || skipBytagId }, + { skip: skipByPTeamId || skipByTopicId || skipByServiceId || skipBytagId }, ); const handleDetailOpen = () => setDetailOpen(!detailOpen); - if (skipByAuth || skipByPTeamId || skipByTopicId || skipByServiceId || skipBytagId) return <>; + if (skipByPTeamId || skipByTopicId || skipByServiceId || skipBytagId) return <>; if (pteamTopicActionsError) throw new APIError(errorToString(pteamTopicActionsError), { api: "getPTeamTopicActions" }); if (pteamTopicActionsIsLoading) return <>Now loading topicActions...; diff --git a/web/src/pages/Tag/TopicTagSelector.jsx b/web/src/pages/Tag/TopicTagSelector.jsx index e588c43c..fb16b481 100644 --- a/web/src/pages/Tag/TopicTagSelector.jsx +++ b/web/src/pages/Tag/TopicTagSelector.jsx @@ -21,7 +21,6 @@ import React, { useEffect, useState } from "react"; import { FixedSizeList } from "react-window"; import dialogStyle from "../../cssModule/dialog.module.css"; -import { useSkipUntilAuthTokenIsReady } from "../../hooks/auth"; import { useCreateTagMutation, useGetTagsQuery } from "../../services/tcApi"; import { APIError } from "../../utils/APIError"; import { commonButtonStyle } from "../../utils/const"; @@ -38,12 +37,11 @@ export function TopicTagSelector(props) { const [createTag] = useCreateTagMutation(); - const skip = useSkipUntilAuthTokenIsReady(); const { data: allTags, error: allTagsError, isLoading: allTagsIsLoading, - } = useGetTagsQuery(undefined, { skip }); + } = useGetTagsQuery(undefined); const fixedTag = (orig) => orig.trim().toLowerCase(); // normalize to compare @@ -53,7 +51,6 @@ export function TopicTagSelector(props) { } }, [allTags, search]); - if (skip) return <>; if (allTagsError) throw new APIError(errorToString(allTagsError), { api: "getTags" }); if (allTagsIsLoading) return <>Now loading allTags...; diff --git a/web/src/pages/Tag/TopicTicketAccordion.jsx b/web/src/pages/Tag/TopicTicketAccordion.jsx index c4dc7549..123684d4 100644 --- a/web/src/pages/Tag/TopicTicketAccordion.jsx +++ b/web/src/pages/Tag/TopicTicketAccordion.jsx @@ -20,7 +20,6 @@ import PropTypes from "prop-types"; import React from "react"; import { SSVCPriorityStatusChip } from "../../components/SSVCPriorityStatusChip"; -import { useSkipUntilAuthTokenIsReady } from "../../hooks/auth"; import { useGetThreatQuery } from "../../services/tcApi"; import { APIError } from "../../utils/APIError"; import { @@ -71,14 +70,12 @@ export function TopicTicketAccordion(props) { const ticketStatus = ticket.ticket_status; const ssvcPriority = ticket.ssvc_deployer_priority || "defer"; - const skipByAuth = useSkipUntilAuthTokenIsReady(); const { data: threat, error: threatError, isLoading: threatIsLoading, - } = useGetThreatQuery(ticket.threat_id, { skipByAuth }); + } = useGetThreatQuery(ticket.threat_id); - if (skipByAuth) return <>; if (threatIsLoading) return ErrorAccordion("Now loading Threat...", defaultExpanded); if (threatError) throw new APIError(errorToString(threatError), { api: "getThreat" }); diff --git a/web/src/pages/TopicDetail/TopicDetailPage.jsx b/web/src/pages/TopicDetail/TopicDetailPage.jsx index b66b1da2..d4d38b55 100644 --- a/web/src/pages/TopicDetail/TopicDetailPage.jsx +++ b/web/src/pages/TopicDetail/TopicDetailPage.jsx @@ -20,7 +20,6 @@ import React, { useState } from "react"; import { useParams } from "react-router-dom"; import { ActionTypeIcon } from "../../components/ActionTypeIcon"; -import { useSkipUntilAuthTokenIsReady } from "../../hooks/auth"; import { useGetTopicActionsQuery, useGetTopicQuery } from "../../services/tcApi"; import { APIError } from "../../utils/APIError"; import { cvssProps } from "../../utils/const"; @@ -49,21 +48,14 @@ export function TopicDetail() { const [showAllArtifacts, setShowAllArtifacts] = useState(false); - const skip = useSkipUntilAuthTokenIsReady(); - - const { - data: topic, - error: topicError, - isLoading: topicIsLoading, - } = useGetTopicQuery(topicId, { skip }); + const { data: topic, error: topicError, isLoading: topicIsLoading } = useGetTopicQuery(topicId); const { data: topicActions, error: topicActionsError, isLoading: topicActionsIsLoading, - } = useGetTopicActionsQuery(topicId, { skip }); + } = useGetTopicActionsQuery(topicId); - if (skip) return <>; if (topicError) throw new APIError(errorToString(topicError), { api: "getTopic" }); if (topicIsLoading) return <>Now loading Topic...; if (topicActionsError) diff --git a/web/src/pages/TopicManagement/TopicManagementPage.jsx b/web/src/pages/TopicManagement/TopicManagementPage.jsx index 41555989..0192f0d6 100644 --- a/web/src/pages/TopicManagement/TopicManagementPage.jsx +++ b/web/src/pages/TopicManagement/TopicManagementPage.jsx @@ -31,7 +31,6 @@ import { useNavigate } from "react-router"; import { useLocation } from "react-router-dom"; import styles from "../../cssModule/button.module.css"; -import { useSkipUntilAuthTokenIsReady } from "../../hooks/auth"; import { useGetTopicActionsQuery, useGetTopicQuery, @@ -58,19 +57,13 @@ function TopicManagementTableRow(props) { const params = new URLSearchParams(location.search); - const skip = useSkipUntilAuthTokenIsReady(); - - const { - data: topic, - error: topicError, - isLoading: topicIsLoading, - } = useGetTopicQuery(topicId, { skip }); + const { data: topic, error: topicError, isLoading: topicIsLoading } = useGetTopicQuery(topicId); const { data: topicActions, error: topicActionsError, isLoading: topicActionsIsLoading, - } = useGetTopicActionsQuery(topicId, { skip }); + } = useGetTopicActionsQuery(topicId); if (topicError) throw new APIError(errorToString(topicError), { @@ -82,7 +75,7 @@ function TopicManagementTableRow(props) { api: "getTopicActions", }); - if (skip || topicIsLoading || topicActionsIsLoading) + if (topicIsLoading || topicActionsIsLoading) return ( {getDisplayMessage(topicIsLoading, topicActionsIsLoading)} @@ -147,8 +140,6 @@ export function TopicManagement() { const [perPage, setPerPage] = useState(perPageItems[0]); const [searchConditions, setSearchConditions] = useState({}); - const skip = useSkipUntilAuthTokenIsReady(); - const params = new URLSearchParams(useLocation().search); const pteamId = params.get("pteamId"); @@ -163,9 +154,8 @@ export function TopicManagement() { data: searchResult, error: searchResultError, isLoading: searchResultIsLoading, - } = useSearchTopicsQuery(searchParams, { skip, refetchOnMountOrArgChange: true }); + } = useSearchTopicsQuery(searchParams, { refetchOnMountOrArgChange: true }); - if (skip) return <>Now loading auth token...; if (searchResultError) throw new APIError(errorToString(searchResultError), { api: "searchTopics", From ea59e2b37becc71e4992fb7bbdf03e5b6eb62c1a Mon Sep 17 00:00:00 2001 From: TsurutaYoshiki Date: Thu, 23 Jan 2025 04:17:05 +0000 Subject: [PATCH 04/17] delete auth slice --- web/src/pages/App/AppPage.jsx | 37 ++----------------------------- web/src/pages/Login/LoginPage.jsx | 2 -- web/src/services/firebaseApi.js | 8 +++---- web/src/slices/auth.js | 25 --------------------- web/src/slices/index.js | 3 +-- 5 files changed, 6 insertions(+), 69 deletions(-) delete mode 100644 web/src/slices/auth.js diff --git a/web/src/pages/App/AppPage.jsx b/web/src/pages/App/AppPage.jsx index 0a4a4bc3..8aeb9aee 100644 --- a/web/src/pages/App/AppPage.jsx +++ b/web/src/pages/App/AppPage.jsx @@ -1,14 +1,9 @@ import { Box } from "@mui/material"; -import React, { useEffect } from "react"; +import React from "react"; import { ErrorBoundary } from "react-error-boundary"; -import { useDispatch, useSelector } from "react-redux"; -import { useLocation, useNavigate } from "react-router-dom"; +import { useSelector } from "react-redux"; -import { useSkipUntilAuthTokenIsReady } from "../../hooks/auth"; -import { useTryLoginMutation } from "../../services/tcApi"; -import { setAuthToken } from "../../slices/auth"; import { mainMaxWidth } from "../../utils/const"; -import { auth } from "../../utils/firebase"; import { AppBar } from "./AppBar"; import { AppFallback } from "./AppFallback"; @@ -17,35 +12,7 @@ import { Main } from "./Main"; import { OutletWithCheckedParams } from "./OutletWithCheckedParams"; export function App() { - const skip = useSkipUntilAuthTokenIsReady(); - - const dispatch = useDispatch(); const system = useSelector((state) => state.system); - const location = useLocation(); - const navigate = useNavigate(); - - const [tryLogin] = useTryLoginMutation(); - - useEffect(() => { - if (!skip) return; // auth token is ready - const _checkToken = async () => { - try { - const accessToken = await auth.currentUser?.getIdToken(true); - if (!accessToken) throw new Error("Missing accessToken"); - dispatch(setAuthToken(accessToken)); - await tryLogin().unwrap(); // throw error if accessToken is expired - } catch (error) { - navigate("/login", { - state: { - from: location.pathname, - search: location.search, - message: "Please login to continue.", - }, - }); - } - }; - _checkToken(); - }, [dispatch, location, navigate, skip, tryLogin]); return ( <> diff --git a/web/src/pages/Login/LoginPage.jsx b/web/src/pages/Login/LoginPage.jsx index 5a93abc4..c5a25ac9 100644 --- a/web/src/pages/Login/LoginPage.jsx +++ b/web/src/pages/Login/LoginPage.jsx @@ -24,7 +24,6 @@ import { useSignInWithSamlPopupMutation, } from "../../services/firebaseApi"; import { useCreateUserMutation, useTryLoginMutation } from "../../services/tcApi"; -import { clearAuth } from "../../slices/auth"; import { samlProvider } from "../../utils/firebase"; export const authCookieName = "Authorization"; @@ -45,7 +44,6 @@ export function Login() { const [tryLogin] = useTryLoginMutation(); useEffect(() => { - dispatch(clearAuth()); setMessage(location.state?.message); }, [dispatch, location]); diff --git a/web/src/services/firebaseApi.js b/web/src/services/firebaseApi.js index 60231790..c7db534b 100644 --- a/web/src/services/firebaseApi.js +++ b/web/src/services/firebaseApi.js @@ -6,7 +6,7 @@ import { browserSessionPersistence, } from "firebase/auth"; -import { setAuthToken } from "../slices/auth"; +// import { setAuthToken } from "../slices/auth"; import { auth, samlProvider } from "../utils/firebase"; export const firebaseApi = createApi({ @@ -30,11 +30,10 @@ export const firebaseApi = createApi({ }), */ signInWithEmailAndPassword: builder.mutation({ - queryFn: async ({ email, password }, { dispatch }) => { + queryFn: async ({ email, password }) => { await setPersistence(auth, browserSessionPersistence); return await signInWithEmailAndPassword(auth, email, password) .then((credential) => { - dispatch(setAuthToken(credential.user.accessToken)); return { data: credential }; }) .catch((error) => ({ error })); @@ -42,13 +41,12 @@ export const firebaseApi = createApi({ invalidatesTags: () => [{ type: "Credential" }], }), signInWithSamlPopup: builder.mutation({ - queryFn: async (_, { dispatch }) => { + queryFn: async () => { if (!samlProvider) { return { error: "SAML not supported" }; } return await signInWithPopup(auth, samlProvider) .then((credential) => { - dispatch(setAuthToken(credential.user.accessToken)); return { data: credential }; }) .catch((error) => ({ error })); diff --git a/web/src/slices/auth.js b/web/src/slices/auth.js deleted file mode 100644 index df8908f4..00000000 --- a/web/src/slices/auth.js +++ /dev/null @@ -1,25 +0,0 @@ -import { createSlice } from "@reduxjs/toolkit"; - -const _initialState = { - token: undefined, -}; - -const authSlice = createSlice({ - name: "auth", - initialState: _initialState, - reducers: { - clearAuth: (state, action) => ({ - ..._initialState, - }), - setAuthToken: (state, action) => ({ - ...state, - token: action.payload, - }), - }, -}); - -const { actions, reducer } = authSlice; - -export const { clearAuth, setAuthToken } = actions; - -export default reducer; diff --git a/web/src/slices/index.js b/web/src/slices/index.js index c97d9104..1c51582f 100644 --- a/web/src/slices/index.js +++ b/web/src/slices/index.js @@ -1,9 +1,8 @@ import { combineReducers } from "redux"; -import auth from "./auth"; import system from "./system"; -export const sliceReducers = { auth, system }; +export const sliceReducers = { system }; const rootReducer = combineReducers(sliceReducers); From 66fe3f8e2413ff53834fe1623431fb42b24a6e4b Mon Sep 17 00:00:00 2001 From: TsurutaYoshiki Date: Thu, 23 Jan 2025 04:17:32 +0000 Subject: [PATCH 05/17] Replace with getIdToken --- web/src/services/tcApi.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/web/src/services/tcApi.js b/web/src/services/tcApi.js index d7d19b28..50764640 100644 --- a/web/src/services/tcApi.js +++ b/web/src/services/tcApi.js @@ -1,5 +1,6 @@ import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react"; +import { auth } from "../utils/firebase"; import { blobToDataURL } from "../utils/func"; const _responseListToDictConverter = @@ -23,9 +24,8 @@ export const tcApi = createApi({ reducerPath: "tcApi", baseQuery: fetchBaseQuery({ baseUrl: process.env.REACT_APP_API_BASE_URL, - prepareHeaders: (headers, { getState }) => { - /* Note: access token is stored in auth.token via firebaseApi */ - const token = getState().auth.token; + prepareHeaders: async (headers) => { + const token = await auth.currentUser?.getIdToken(true); if (token) { headers.set("authorization", `Bearer ${token}`); } From 69a20fb5390c05a573b099af1b51d3cbc57ca544 Mon Sep 17 00:00:00 2001 From: TsurutaYoshiki Date: Thu, 23 Jan 2025 04:39:24 +0000 Subject: [PATCH 06/17] delete comment out --- web/src/services/firebaseApi.js | 1 - 1 file changed, 1 deletion(-) diff --git a/web/src/services/firebaseApi.js b/web/src/services/firebaseApi.js index c7db534b..8c772600 100644 --- a/web/src/services/firebaseApi.js +++ b/web/src/services/firebaseApi.js @@ -6,7 +6,6 @@ import { browserSessionPersistence, } from "firebase/auth"; -// import { setAuthToken } from "../slices/auth"; import { auth, samlProvider } from "../utils/firebase"; export const firebaseApi = createApi({ From 96d48619582af23e78fad4156ba60c97f3f4412f Mon Sep 17 00:00:00 2001 From: TsurutaYoshiki Date: Thu, 23 Jan 2025 05:15:16 +0000 Subject: [PATCH 07/17] add tryLogin --- web/src/pages/App/AppPage.jsx | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/web/src/pages/App/AppPage.jsx b/web/src/pages/App/AppPage.jsx index 8aeb9aee..d5b93bb4 100644 --- a/web/src/pages/App/AppPage.jsx +++ b/web/src/pages/App/AppPage.jsx @@ -1,8 +1,10 @@ import { Box } from "@mui/material"; -import React from "react"; +import React, { useEffect } from "react"; import { ErrorBoundary } from "react-error-boundary"; import { useSelector } from "react-redux"; +import { useLocation, useNavigate } from "react-router-dom"; +import { useTryLoginMutation } from "../../services/tcApi"; import { mainMaxWidth } from "../../utils/const"; import { AppBar } from "./AppBar"; @@ -13,6 +15,27 @@ import { OutletWithCheckedParams } from "./OutletWithCheckedParams"; export function App() { const system = useSelector((state) => state.system); + const location = useLocation(); + const navigate = useNavigate(); + + const [tryLogin] = useTryLoginMutation(); + + useEffect(() => { + const _checkToken = async () => { + try { + await tryLogin().unwrap(); // throw error if accessToken is expired + } catch (error) { + navigate("/login", { + state: { + from: location.pathname, + search: location.search, + message: "Please login to continue.", + }, + }); + } + }; + _checkToken(); + }, [location, navigate, tryLogin]); return ( <> From 2ab4eefd72d0d8d943c608d47b24da9eaab9494d Mon Sep 17 00:00:00 2001 From: TsurutaYoshiki Date: Mon, 27 Jan 2025 08:37:02 +0000 Subject: [PATCH 08/17] add skip --- web/src/components/PTeamLabel.jsx | 6 +++++- web/src/components/PTeamSettingsModal.jsx | 3 ++- web/src/hooks/auth.js | 7 +++++++ .../AcceptPTeamInvitationPage.jsx | 5 ++++- web/src/pages/Account/AccountPage.jsx | 5 ++++- web/src/pages/App/OutletWithCheckedParams.jsx | 6 +++++- web/src/pages/App/TeamSelector.jsx | 5 ++++- web/src/pages/PTeam/PTeamMemberMenu.jsx | 3 ++- web/src/pages/PTeam/PTeamPage.jsx | 3 ++- web/src/pages/Status/PTeamServiceDelete.jsx | 3 ++- .../pages/Status/PTeamServicesListModal.jsx | 3 ++- web/src/pages/Status/StatusPage.jsx | 11 ++++++---- web/src/pages/Tag/PTeamTaggedTopics.jsx | 3 ++- web/src/pages/Tag/ReportCompletedActions.jsx | 5 ++++- web/src/pages/Tag/TagPage.jsx | 8 ++++--- web/src/pages/Tag/TopicCard.jsx | 21 +++++++++++++------ web/src/pages/Tag/TopicTagSelector.jsx | 5 ++++- web/src/pages/Tag/TopicTicketAccordion.jsx | 5 ++++- web/src/pages/TopicDetail/TopicDetailPage.jsx | 11 ++++++++-- .../TopicManagement/TopicManagementPage.jsx | 18 ++++++++++++---- 20 files changed, 103 insertions(+), 33 deletions(-) create mode 100644 web/src/hooks/auth.js diff --git a/web/src/components/PTeamLabel.jsx b/web/src/components/PTeamLabel.jsx index e213cd0d..8ace3a4a 100644 --- a/web/src/components/PTeamLabel.jsx +++ b/web/src/components/PTeamLabel.jsx @@ -3,6 +3,7 @@ import { Box, IconButton, Typography } from "@mui/material"; import PropTypes from "prop-types"; import React, { useState } from "react"; +import { useSkipUntilAuthUserIsReady } from "../hooks/auth"; import { useGetUserMeQuery } from "../services/tcApi"; import { APIError } from "../utils/APIError"; import { errorToString } from "../utils/func"; @@ -15,12 +16,15 @@ export function PTeamLabel(props) { const [pteamSettingsModalOpen, setPTeamSettingsModalOpen] = useState(false); + const skip = useSkipUntilAuthUserIsReady(); + const { data: userMe, error: userMeError, isLoading: userMeIsLoading, - } = useGetUserMeQuery(undefined); + } = useGetUserMeQuery(undefined, { skip }); + if (skip) return <>; if (userMeError) throw new APIError(errorToString(userMeError), { api: "getUserMe", diff --git a/web/src/components/PTeamSettingsModal.jsx b/web/src/components/PTeamSettingsModal.jsx index 4dd2a624..146ffddd 100644 --- a/web/src/components/PTeamSettingsModal.jsx +++ b/web/src/components/PTeamSettingsModal.jsx @@ -15,6 +15,7 @@ import React, { useState } from "react"; import { TabPanel } from "../components/TabPanel"; import dialogStyle from "../cssModule/dialog.module.css"; +import { useSkipUntilAuthUserIsReady } from "../hooks/auth"; import { useGetPTeamQuery } from "../services/tcApi"; import { APIError } from "../utils/APIError"; import { a11yProps, errorToString } from "../utils/func.js"; @@ -26,7 +27,7 @@ export function PTeamSettingsModal(props) { const { pteamId, onSetShow, show, defaultTabIndex } = props; const [tab, setTab] = useState(defaultTabIndex ?? 0); - const skip = !pteamId; + const skip = useSkipUntilAuthUserIsReady() || !pteamId; const { data: pteam, diff --git a/web/src/hooks/auth.js b/web/src/hooks/auth.js new file mode 100644 index 00000000..f4f8a5a9 --- /dev/null +++ b/web/src/hooks/auth.js @@ -0,0 +1,7 @@ +import { auth } from "../utils/firebase"; + +export function useSkipUntilAuthUserIsReady() { + const skip = auth.currentUser === null || auth.currentUser === undefined; + + return skip; +} diff --git a/web/src/pages/AcceptPTeamInvitation/AcceptPTeamInvitationPage.jsx b/web/src/pages/AcceptPTeamInvitation/AcceptPTeamInvitationPage.jsx index d25c1694..c8fb56db 100644 --- a/web/src/pages/AcceptPTeamInvitation/AcceptPTeamInvitationPage.jsx +++ b/web/src/pages/AcceptPTeamInvitation/AcceptPTeamInvitationPage.jsx @@ -3,6 +3,7 @@ import { useSnackbar } from "notistack"; import React from "react"; import { useLocation, useNavigate } from "react-router-dom"; +import { useSkipUntilAuthUserIsReady } from "../../hooks/auth"; import { useApplyPTeamInvitationMutation, useGetPTeamInvitationQuery } from "../../services/tcApi"; import { APIError } from "../../utils/APIError"; import { commonButtonStyle } from "../../utils/const"; @@ -18,12 +19,14 @@ export function AcceptPTeamInvitation() { const params = new URLSearchParams(useLocation().search); const tokenId = params.get("token"); + const skip = useSkipUntilAuthUserIsReady(); const { data: detail, error: detailError, isLoading: detailIsLoading, - } = useGetPTeamInvitationQuery(tokenId); + } = useGetPTeamInvitationQuery(tokenId, { skip }); + if (skip) return <>; if (detailError) throw new APIError("This invitation is invalid or already expired.", { api: "getPTeamInvitation", diff --git a/web/src/pages/Account/AccountPage.jsx b/web/src/pages/Account/AccountPage.jsx index e4656882..5b728b7c 100644 --- a/web/src/pages/Account/AccountPage.jsx +++ b/web/src/pages/Account/AccountPage.jsx @@ -14,6 +14,7 @@ import { useSnackbar } from "notistack"; import React, { useState } from "react"; import { UUIDTypography } from "../../components/UUIDTypography"; +import { useSkipUntilAuthUserIsReady } from "../../hooks/auth"; import { useGetUserMeQuery, useUpdateUserMutation } from "../../services/tcApi"; import { APIError } from "../../utils/APIError"; import { errorToString } from "../../utils/func"; @@ -27,12 +28,14 @@ export function Account() { const { enqueueSnackbar } = useSnackbar(); const [updateUser] = useUpdateUserMutation(); + const skip = useSkipUntilAuthUserIsReady(); const { data: userMe, error: userMeError, isLoading: userMeIsLoading, - } = useGetUserMeQuery(undefined); + } = useGetUserMeQuery(undefined, { skip }); + if (skip) return <>; if (userMeError) throw new APIError(errorToString(userMeError), { api: "getUserMe", diff --git a/web/src/pages/App/OutletWithCheckedParams.jsx b/web/src/pages/App/OutletWithCheckedParams.jsx index 1309baf8..d3efeb25 100644 --- a/web/src/pages/App/OutletWithCheckedParams.jsx +++ b/web/src/pages/App/OutletWithCheckedParams.jsx @@ -1,6 +1,7 @@ import React, { useEffect } from "react"; import { Outlet, useLocation, useNavigate } from "react-router-dom"; +import { useSkipUntilAuthUserIsReady } from "../../hooks/auth"; import { useGetUserMeQuery } from "../../services/tcApi"; import { APIError } from "../../utils/APIError"; import { errorToString } from "../../utils/func"; @@ -10,18 +11,21 @@ export function OutletWithCheckedParams() { const navigate = useNavigate(); const location = useLocation(); + const skip = useSkipUntilAuthUserIsReady(); + const { data: userMe, error: userMeError, isLoading: userMeIsLoading, isFetching: userMeIsFetching, - } = useGetUserMeQuery(undefined); + } = useGetUserMeQuery(undefined, { skip }); useEffect(() => { if (!userMe || userMeIsFetching) return; navigateSpecifiedPteam(location, userMe.pteam_roles, navigate); }, [navigate, location, userMe, userMeIsFetching]); + if (skip) return <>; if (userMeError) throw new APIError(errorToString(userMeError), { api: "getUserMe" }); if (userMeIsLoading) return <>Now loading UserInfo...; diff --git a/web/src/pages/App/TeamSelector.jsx b/web/src/pages/App/TeamSelector.jsx index 26fd54ae..5df65dbf 100644 --- a/web/src/pages/App/TeamSelector.jsx +++ b/web/src/pages/App/TeamSelector.jsx @@ -4,6 +4,7 @@ import { grey } from "@mui/material/colors"; import React, { useEffect, useMemo, useState } from "react"; import { useLocation, useNavigate } from "react-router-dom"; +import { useSkipUntilAuthUserIsReady } from "../../hooks/auth"; import { useGetUserMeQuery } from "../../services/tcApi"; import { APIError } from "../../utils/APIError"; import { LocationReader } from "../../utils/LocationReader"; @@ -34,11 +35,12 @@ export function TeamSelector() { const [openPTeamCreationModal, setOpenPTeamCreationModal] = useState(false); const locationReader = useMemo(() => new LocationReader(location), [location]); + const skip = useSkipUntilAuthUserIsReady(); const { data: userMe, error: userMeError, isLoading: userMeIsLoading, - } = useGetUserMeQuery(undefined); + } = useGetUserMeQuery(undefined, { skip }); useEffect(() => { if (!userMe) return; @@ -48,6 +50,7 @@ export function TeamSelector() { ); }, [userMe, locationReader]); + if (skip) return <>; if (userMeError) throw new APIError(errorToString(userMeError), { api: "getUserMe" }); if (userMeIsLoading) return <>Now loading UserInfo...; diff --git a/web/src/pages/PTeam/PTeamMemberMenu.jsx b/web/src/pages/PTeam/PTeamMemberMenu.jsx index 2f2f95f8..043875bf 100644 --- a/web/src/pages/PTeam/PTeamMemberMenu.jsx +++ b/web/src/pages/PTeam/PTeamMemberMenu.jsx @@ -7,6 +7,7 @@ import { Button, Dialog, DialogContent, Menu, MenuItem } from "@mui/material"; import PropTypes from "prop-types"; import React, { useState } from "react"; +import { useSkipUntilAuthUserIsReady } from "../../hooks/auth"; import { useGetPTeamQuery, useGetUserMeQuery } from "../../services/tcApi"; import { APIError } from "../../utils/APIError"; import { errorToString, checkAdmin } from "../../utils/func"; @@ -22,7 +23,7 @@ export function PTeamMemberMenu(props) { const [anchorEl, setAnchorEl] = useState(null); const open = Boolean(anchorEl); - const skip = !pteamId; + const skip = useSkipUntilAuthUserIsReady() || !pteamId; const { data: userMe, error: userMeError, diff --git a/web/src/pages/PTeam/PTeamPage.jsx b/web/src/pages/PTeam/PTeamPage.jsx index d5b09683..67ffa81b 100644 --- a/web/src/pages/PTeam/PTeamPage.jsx +++ b/web/src/pages/PTeam/PTeamPage.jsx @@ -4,6 +4,7 @@ import { useLocation } from "react-router"; import { PTeamLabel } from "../../components/PTeamLabel"; import { TabPanel } from "../../components/TabPanel"; +import { useSkipUntilAuthUserIsReady } from "../../hooks/auth"; import { useGetPTeamMembersQuery } from "../../services/tcApi"; import { APIError } from "../../utils/APIError"; import { experienceColors, noPTeamMessage } from "../../utils/const"; @@ -18,7 +19,7 @@ export function PTeam() { const params = new URLSearchParams(location.search); const pteamId = params.get("pteamId"); - const skip = !pteamId; + const skip = useSkipUntilAuthUserIsReady() || !pteamId; const { data: members, error: membersError, diff --git a/web/src/pages/Status/PTeamServiceDelete.jsx b/web/src/pages/Status/PTeamServiceDelete.jsx index 4b10b496..56d7a171 100644 --- a/web/src/pages/Status/PTeamServiceDelete.jsx +++ b/web/src/pages/Status/PTeamServiceDelete.jsx @@ -15,6 +15,7 @@ import React, { useState } from "react"; import { useLocation, useNavigate } from "react-router"; import styles from "../../cssModule/dialog.module.css"; +import { useSkipUntilAuthUserIsReady } from "../../hooks/auth"; import { useDeletePTeamServiceMutation, useGetPTeamQuery } from "../../services/tcApi"; import { APIError } from "../../utils/APIError"; import { errorToString } from "../../utils/func"; @@ -31,7 +32,7 @@ export function PTeamServiceDelete(props) { const params = new URLSearchParams(location.search); const serviceId = params.get("serviceId"); - const skip = !pteamId; + const skip = useSkipUntilAuthUserIsReady() || !!pteamId; const { data: pteam, error: pteamError, diff --git a/web/src/pages/Status/PTeamServicesListModal.jsx b/web/src/pages/Status/PTeamServicesListModal.jsx index b667561b..8313ff29 100644 --- a/web/src/pages/Status/PTeamServicesListModal.jsx +++ b/web/src/pages/Status/PTeamServicesListModal.jsx @@ -22,6 +22,7 @@ import PropTypes from "prop-types"; import React, { useState } from "react"; import { useNavigate, useLocation } from "react-router-dom"; +import { useSkipUntilAuthUserIsReady } from "../../hooks/auth"; import { useGetPTeamServiceThumbnailQuery, useGetPTeamQuery } from "../../services/tcApi"; import { APIError } from "../../utils/APIError"; import { errorToString } from "../../utils/func"; @@ -83,7 +84,7 @@ export function PTeamServicesListModal(props) { const params = new URLSearchParams(useLocation().search); const pteamId = params.get("pteamId"); - const skip = !pteamId; + const skip = useSkipUntilAuthUserIsReady() || !pteamId; const { data: pteam, error: pteamError, diff --git a/web/src/pages/Status/StatusPage.jsx b/web/src/pages/Status/StatusPage.jsx index f58aa270..913ab4b5 100644 --- a/web/src/pages/Status/StatusPage.jsx +++ b/web/src/pages/Status/StatusPage.jsx @@ -32,6 +32,7 @@ import { useLocation, useNavigate } from "react-router"; import { Android12Switch } from "../../components/Android12Switch"; import { PTeamLabel } from "../../components/PTeamLabel"; +import { useSkipUntilAuthUserIsReady } from "../../hooks/auth"; import { useGetPTeamQuery, useGetPTeamTagsSummaryQuery, @@ -140,12 +141,14 @@ export function Status() { serviceIds: [], }); + const skipByAuth = useSkipUntilAuthUserIsReady(); + const { data: pteam, error: pteamError, isFetching: pteamIsFetching, isLoading: pteamIsLoading, - } = useGetPTeamQuery(pteamId, { skip: !pteamId }); + } = useGetPTeamQuery(pteamId, { skip: skipByAuth || !pteamId }); const { currentData: serviceTagsSummary, @@ -153,7 +156,7 @@ export function Status() { isFetching: serviceTagsSummaryIsFetching, } = useGetPTeamServiceTagsSummaryQuery( { pteamId, serviceId }, - { skip: !pteamId || !serviceId || isActiveAllServicesMode }, + { skip: skipByAuth || !pteamId || !serviceId || isActiveAllServicesMode }, ); const { @@ -161,7 +164,7 @@ export function Status() { error: pteamTagsSummaryError, isFetching: pteamTagsSummaryIsFetching, } = useGetPTeamTagsSummaryQuery(pteamId, { - skip: !pteamId || !isActiveAllServicesMode, + skip: skipByAuth || !pteamId || !isActiveAllServicesMode, }); useEffect(() => { @@ -182,7 +185,7 @@ export function Status() { }, [pteamId, pteam, pteamId, serviceId, isActiveAllServicesMode]); if (!pteamId) return <>{noPTeamMessage}; - if (!pteamId) return <>; + if (skipByAuth || !pteamId) return <>; if (pteamError) throw new APIError(errorToString(pteamError), { api: "getPTeam", diff --git a/web/src/pages/Tag/PTeamTaggedTopics.jsx b/web/src/pages/Tag/PTeamTaggedTopics.jsx index 53678395..291ac9b6 100644 --- a/web/src/pages/Tag/PTeamTaggedTopics.jsx +++ b/web/src/pages/Tag/PTeamTaggedTopics.jsx @@ -2,6 +2,7 @@ import { Box, List, ListItem, MenuItem, Pagination, Select, Typography } from "@ import PropTypes from "prop-types"; import React, { useState } from "react"; +import { useSkipUntilAuthUserIsReady } from "../../hooks/auth"; import { useGetPTeamMembersQuery } from "../../services/tcApi"; import { APIError } from "../../utils/APIError"; import { sortedSSVCPriorities } from "../../utils/const"; @@ -16,7 +17,7 @@ export function PTeamTaggedTopics(props) { const [page, setPage] = useState(1); const [perPage, setPerPage] = useState(10); - const skip = !pteamId; + const skip = useSkipUntilAuthUserIsReady() || !pteamId; const { data: members, diff --git a/web/src/pages/Tag/ReportCompletedActions.jsx b/web/src/pages/Tag/ReportCompletedActions.jsx index beb36f4b..173800aa 100644 --- a/web/src/pages/Tag/ReportCompletedActions.jsx +++ b/web/src/pages/Tag/ReportCompletedActions.jsx @@ -18,6 +18,7 @@ import React, { useState } from "react"; import { ActionTypeIcon } from "../../components/ActionTypeIcon"; import { UUIDTypography } from "../../components/UUIDTypography"; import dialogStyle from "../../cssModule/dialog.module.css"; +import { useSkipUntilAuthUserIsReady } from "../../hooks/auth"; import { useCreateActionLogMutation, useUpdateTicketStatusMutation, @@ -39,14 +40,16 @@ export function ReportCompletedActions(props) { const { enqueueSnackbar } = useSnackbar(); + const skip = useSkipUntilAuthUserIsReady(); const { data: userMe, error: userMeError, isLoading: userMeIsLoading, - } = useGetUserMeQuery(undefined); + } = useGetUserMeQuery(undefined, { skip }); const [createActionLog] = useCreateActionLogMutation(); const [updateTicketStatus] = useUpdateTicketStatusMutation(); + if (skip) return <>; if (userMeError) throw new APIError(errorToString(userMeError), { api: "getUserMe" }); if (userMeIsLoading) return <>Now loading UserInfo...; diff --git a/web/src/pages/Tag/TagPage.jsx b/web/src/pages/Tag/TagPage.jsx index ae2e7ed9..7cf5e449 100644 --- a/web/src/pages/Tag/TagPage.jsx +++ b/web/src/pages/Tag/TagPage.jsx @@ -5,6 +5,7 @@ import { useParams, useLocation } from "react-router-dom"; import { TabPanel } from "../../components/TabPanel"; import { UUIDTypography } from "../../components/UUIDTypography"; +import { useSkipUntilAuthUserIsReady } from "../../hooks/auth"; import { useGetPTeamQuery, useGetPTeamServiceTaggedTopicIdsQuery, @@ -21,18 +22,19 @@ import { TagReferences } from "./TagReferences.jsx"; export function Tag() { const [tabValue, setTabValue] = useState(0); + const skipByAuth = useSkipUntilAuthUserIsReady(); const { data: allTags, error: allTagsError, isLoading: allTagsIsLoading, - } = useGetTagsQuery(undefined); + } = useGetTagsQuery(undefined, { skipByAuth }); const { tagId } = useParams(); const params = new URLSearchParams(useLocation().search); const pteamId = params.get("pteamId"); const serviceId = params.get("serviceId"); - const getDependenciesReady = pteamId && serviceId; - const getPTeamReady = pteamId; + const getDependenciesReady = !skipByAuth && pteamId && serviceId; + const getPTeamReady = !skipByAuth && pteamId; const getTopicIdsReady = getPTeamReady && serviceId && tagId; const { diff --git a/web/src/pages/Tag/TopicCard.jsx b/web/src/pages/Tag/TopicCard.jsx index 87ad614a..17b2a17b 100644 --- a/web/src/pages/Tag/TopicCard.jsx +++ b/web/src/pages/Tag/TopicCard.jsx @@ -18,6 +18,7 @@ import React, { useState } from "react"; import { useParams } from "react-router-dom"; import { UUIDTypography } from "../../components/UUIDTypography"; +import { useSkipUntilAuthUserIsReady } from "../../hooks/auth"; import { useGetPTeamTopicActionsQuery, useGetTicketsQuery, @@ -40,13 +41,18 @@ export function TopicCard(props) { const [detailOpen, setDetailOpen] = useState(false); const [actionFilter, setActionFilter] = useState(true); - const { data: topic, error: topicError, isLoading: topicIsLoading } = useGetTopicQuery(topicId); + const skipByAuth = useSkipUntilAuthUserIsReady(); + const { + data: topic, + error: topicError, + isLoading: topicIsLoading, + } = useGetTopicQuery(topicId, { skipByAuth }); const skipByPTeamId = pteamId === undefined; const skipByTopicId = topicId === undefined; const skipByServiceId = serviceId === undefined; const skipBytagId = tagId === undefined; - const getDependenciesReady = pteamId && serviceId; + const getDependenciesReady = !skipByAuth && pteamId && serviceId; const { data: serviceDependencies, @@ -57,12 +63,15 @@ export function TopicCard(props) { data: allTags, error: allTagsError, isLoading: allTagsIsLoading, - } = useGetTagsQuery(undefined); + } = useGetTagsQuery(undefined, { skipByAuth }); const { data: pteamTopicActionsData, error: pteamTopicActionsError, isLoading: pteamTopicActionsIsLoading, - } = useGetPTeamTopicActionsQuery({ topicId, pteamId }, { skip: skipByPTeamId || skipByTopicId }); + } = useGetPTeamTopicActionsQuery( + { topicId, pteamId }, + { skip: skipByAuth || skipByPTeamId || skipByTopicId }, + ); const { data: tickets, @@ -70,12 +79,12 @@ export function TopicCard(props) { isLoading: ticketsRelatedToServiceTopicTagIsLoading, } = useGetTicketsQuery( { pteamId, serviceId, topicId, tagId }, - { skip: skipByPTeamId || skipByTopicId || skipByServiceId || skipBytagId }, + { skip: skipByAuth || skipByPTeamId || skipByTopicId || skipByServiceId || skipBytagId }, ); const handleDetailOpen = () => setDetailOpen(!detailOpen); - if (skipByPTeamId || skipByTopicId || skipByServiceId || skipBytagId) return <>; + if (skipByAuth || skipByPTeamId || skipByTopicId || skipByServiceId || skipBytagId) return <>; if (pteamTopicActionsError) throw new APIError(errorToString(pteamTopicActionsError), { api: "getPTeamTopicActions" }); if (pteamTopicActionsIsLoading) return <>Now loading topicActions...; diff --git a/web/src/pages/Tag/TopicTagSelector.jsx b/web/src/pages/Tag/TopicTagSelector.jsx index fb16b481..a86dddaa 100644 --- a/web/src/pages/Tag/TopicTagSelector.jsx +++ b/web/src/pages/Tag/TopicTagSelector.jsx @@ -21,6 +21,7 @@ import React, { useEffect, useState } from "react"; import { FixedSizeList } from "react-window"; import dialogStyle from "../../cssModule/dialog.module.css"; +import { useSkipUntilAuthUserIsReady } from "../../hooks/auth"; import { useCreateTagMutation, useGetTagsQuery } from "../../services/tcApi"; import { APIError } from "../../utils/APIError"; import { commonButtonStyle } from "../../utils/const"; @@ -37,11 +38,12 @@ export function TopicTagSelector(props) { const [createTag] = useCreateTagMutation(); + const skip = useSkipUntilAuthUserIsReady(); const { data: allTags, error: allTagsError, isLoading: allTagsIsLoading, - } = useGetTagsQuery(undefined); + } = useGetTagsQuery(undefined, { skip }); const fixedTag = (orig) => orig.trim().toLowerCase(); // normalize to compare @@ -51,6 +53,7 @@ export function TopicTagSelector(props) { } }, [allTags, search]); + if (skip) return <>; if (allTagsError) throw new APIError(errorToString(allTagsError), { api: "getTags" }); if (allTagsIsLoading) return <>Now loading allTags...; diff --git a/web/src/pages/Tag/TopicTicketAccordion.jsx b/web/src/pages/Tag/TopicTicketAccordion.jsx index 123684d4..36f046f6 100644 --- a/web/src/pages/Tag/TopicTicketAccordion.jsx +++ b/web/src/pages/Tag/TopicTicketAccordion.jsx @@ -20,6 +20,7 @@ import PropTypes from "prop-types"; import React from "react"; import { SSVCPriorityStatusChip } from "../../components/SSVCPriorityStatusChip"; +import { useSkipUntilAuthUserIsReady } from "../../hooks/auth"; import { useGetThreatQuery } from "../../services/tcApi"; import { APIError } from "../../utils/APIError"; import { @@ -70,12 +71,14 @@ export function TopicTicketAccordion(props) { const ticketStatus = ticket.ticket_status; const ssvcPriority = ticket.ssvc_deployer_priority || "defer"; + const skipByAuth = useSkipUntilAuthUserIsReady(); const { data: threat, error: threatError, isLoading: threatIsLoading, - } = useGetThreatQuery(ticket.threat_id); + } = useGetThreatQuery(ticket.threat_id, { skipByAuth }); + if (skipByAuth) return <>; if (threatIsLoading) return ErrorAccordion("Now loading Threat...", defaultExpanded); if (threatError) throw new APIError(errorToString(threatError), { api: "getThreat" }); diff --git a/web/src/pages/TopicDetail/TopicDetailPage.jsx b/web/src/pages/TopicDetail/TopicDetailPage.jsx index d4d38b55..6060c308 100644 --- a/web/src/pages/TopicDetail/TopicDetailPage.jsx +++ b/web/src/pages/TopicDetail/TopicDetailPage.jsx @@ -20,6 +20,7 @@ import React, { useState } from "react"; import { useParams } from "react-router-dom"; import { ActionTypeIcon } from "../../components/ActionTypeIcon"; +import { useSkipUntilAuthUserIsReady } from "../../hooks/auth"; import { useGetTopicActionsQuery, useGetTopicQuery } from "../../services/tcApi"; import { APIError } from "../../utils/APIError"; import { cvssProps } from "../../utils/const"; @@ -48,14 +49,20 @@ export function TopicDetail() { const [showAllArtifacts, setShowAllArtifacts] = useState(false); - const { data: topic, error: topicError, isLoading: topicIsLoading } = useGetTopicQuery(topicId); + const skip = useSkipUntilAuthUserIsReady(); + const { + data: topic, + error: topicError, + isLoading: topicIsLoading, + } = useGetTopicQuery(topicId, { skip }); const { data: topicActions, error: topicActionsError, isLoading: topicActionsIsLoading, - } = useGetTopicActionsQuery(topicId); + } = useGetTopicActionsQuery(topicId, { skip }); + if (skip) return <>; if (topicError) throw new APIError(errorToString(topicError), { api: "getTopic" }); if (topicIsLoading) return <>Now loading Topic...; if (topicActionsError) diff --git a/web/src/pages/TopicManagement/TopicManagementPage.jsx b/web/src/pages/TopicManagement/TopicManagementPage.jsx index 0192f0d6..f9d4e401 100644 --- a/web/src/pages/TopicManagement/TopicManagementPage.jsx +++ b/web/src/pages/TopicManagement/TopicManagementPage.jsx @@ -31,6 +31,7 @@ import { useNavigate } from "react-router"; import { useLocation } from "react-router-dom"; import styles from "../../cssModule/button.module.css"; +import { useSkipUntilAuthUserIsReady } from "../../hooks/auth"; import { useGetTopicActionsQuery, useGetTopicQuery, @@ -57,13 +58,19 @@ function TopicManagementTableRow(props) { const params = new URLSearchParams(location.search); - const { data: topic, error: topicError, isLoading: topicIsLoading } = useGetTopicQuery(topicId); + const skip = useSkipUntilAuthUserIsReady(); + + const { + data: topic, + error: topicError, + isLoading: topicIsLoading, + } = useGetTopicQuery(topicId, { skip }); const { data: topicActions, error: topicActionsError, isLoading: topicActionsIsLoading, - } = useGetTopicActionsQuery(topicId); + } = useGetTopicActionsQuery(topicId, { skip }); if (topicError) throw new APIError(errorToString(topicError), { @@ -75,7 +82,7 @@ function TopicManagementTableRow(props) { api: "getTopicActions", }); - if (topicIsLoading || topicActionsIsLoading) + if (skip || topicIsLoading || topicActionsIsLoading) return ( {getDisplayMessage(topicIsLoading, topicActionsIsLoading)} @@ -140,6 +147,8 @@ export function TopicManagement() { const [perPage, setPerPage] = useState(perPageItems[0]); const [searchConditions, setSearchConditions] = useState({}); + const skip = useSkipUntilAuthUserIsReady(); + const params = new URLSearchParams(useLocation().search); const pteamId = params.get("pteamId"); @@ -154,8 +163,9 @@ export function TopicManagement() { data: searchResult, error: searchResultError, isLoading: searchResultIsLoading, - } = useSearchTopicsQuery(searchParams, { refetchOnMountOrArgChange: true }); + } = useSearchTopicsQuery(searchParams, { skip, refetchOnMountOrArgChange: true }); + if (skip) return <>Now loading auth token...; if (searchResultError) throw new APIError(errorToString(searchResultError), { api: "searchTopics", From 38938032ce5902b5c0bdcdcf9da8e78bd7b5e1d8 Mon Sep 17 00:00:00 2001 From: Shikou Date: Tue, 28 Jan 2025 16:08:55 +0900 Subject: [PATCH 09/17] change reference Firebase --- web/src/hooks/auth.js | 3 ++- web/src/services/tcApi.js | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/web/src/hooks/auth.js b/web/src/hooks/auth.js index f4f8a5a9..218d3b93 100644 --- a/web/src/hooks/auth.js +++ b/web/src/hooks/auth.js @@ -1,6 +1,7 @@ -import { auth } from "../utils/firebase"; +import Firebase from "../utils/Firebase"; export function useSkipUntilAuthUserIsReady() { + const auth = Firebase.getAuth(); const skip = auth.currentUser === null || auth.currentUser === undefined; return skip; diff --git a/web/src/services/tcApi.js b/web/src/services/tcApi.js index 7cd28c0b..a5ff6d3b 100644 --- a/web/src/services/tcApi.js +++ b/web/src/services/tcApi.js @@ -1,6 +1,6 @@ import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react"; -import { auth } from "../utils/firebase"; +import Firebase from "../utils/Firebase"; import { blobToDataURL } from "../utils/func"; const _responseListToDictConverter = @@ -25,7 +25,7 @@ export const tcApi = createApi({ baseQuery: fetchBaseQuery({ baseUrl: import.meta.env.VITE_API_BASE_URL, prepareHeaders: async (headers) => { - const token = await auth.currentUser?.getIdToken(true); + const token = await Firebase.getAuth().currentUser?.getIdToken(true); if (token) { headers.set("authorization", `Bearer ${token}`); } From a7abfdbd3d61b6b518d88ea2e4491b42f71b3fb0 Mon Sep 17 00:00:00 2001 From: TsurutaYoshiki Date: Tue, 28 Jan 2025 07:39:24 +0000 Subject: [PATCH 10/17] delete cookie --- web/src/utils/const.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/web/src/utils/const.js b/web/src/utils/const.js index f9efbcb7..859e7800 100644 --- a/web/src/utils/const.js +++ b/web/src/utils/const.js @@ -18,9 +18,6 @@ import { export const rootPrefix = import.meta.env.VITE_PUBLIC_URL.replace(/\/+$/, ""); // trim trailing slash -export const authCookieName = "Authorization"; -export const cookiesOptions = { path: import.meta.env.VITE_PUBLIC_URL || "/" }; - export const systemAccount = { uuid: "00000000-0000-0000-0000-0000cafe0011", email: import.meta.env.VITE_SYSTEM_EMAIL || "SYSTEM_ACCOUNT", From fa2772d676d0c4c6e59dd765289c584364477d17 Mon Sep 17 00:00:00 2001 From: TsurutaYoshiki Date: Wed, 29 Jan 2025 08:16:11 +0000 Subject: [PATCH 11/17] delete useSkipUntilAuthUserIsReady --- web/src/components/PTeamLabel.jsx | 4 ++-- web/src/components/PTeamSettingsModal.jsx | 4 ++-- web/src/hooks/auth.js | 8 -------- .../AcceptPTeamInvitation/AcceptPTeamInvitationPage.jsx | 4 ++-- web/src/pages/Account/AccountPage.jsx | 4 ++-- web/src/pages/App/OutletWithCheckedParams.jsx | 4 ++-- web/src/pages/App/TeamSelector.jsx | 4 ++-- web/src/pages/PTeam/PTeamMemberMenu.jsx | 4 ++-- web/src/pages/PTeam/PTeamPage.jsx | 4 ++-- web/src/pages/Status/PTeamServiceDelete.jsx | 4 ++-- web/src/pages/Status/PTeamServicesListModal.jsx | 4 ++-- web/src/pages/Status/StatusPage.jsx | 4 ++-- web/src/pages/Tag/PTeamTaggedTopics.jsx | 4 ++-- web/src/pages/Tag/ReportCompletedActions.jsx | 4 ++-- web/src/pages/Tag/TagPage.jsx | 4 ++-- web/src/pages/Tag/TopicCard.jsx | 4 ++-- web/src/pages/Tag/TopicTagSelector.jsx | 4 ++-- web/src/pages/Tag/TopicTicketAccordion.jsx | 4 ++-- web/src/pages/TopicDetail/TopicDetailPage.jsx | 4 ++-- web/src/pages/TopicManagement/TopicManagementPage.jsx | 6 +++--- 20 files changed, 39 insertions(+), 47 deletions(-) delete mode 100644 web/src/hooks/auth.js diff --git a/web/src/components/PTeamLabel.jsx b/web/src/components/PTeamLabel.jsx index 8ace3a4a..ffad0b56 100644 --- a/web/src/components/PTeamLabel.jsx +++ b/web/src/components/PTeamLabel.jsx @@ -2,8 +2,8 @@ import { Settings as SettingsIcon } from "@mui/icons-material"; import { Box, IconButton, Typography } from "@mui/material"; import PropTypes from "prop-types"; import React, { useState } from "react"; +import { useSelector } from "react-redux"; -import { useSkipUntilAuthUserIsReady } from "../hooks/auth"; import { useGetUserMeQuery } from "../services/tcApi"; import { APIError } from "../utils/APIError"; import { errorToString } from "../utils/func"; @@ -16,7 +16,7 @@ export function PTeamLabel(props) { const [pteamSettingsModalOpen, setPTeamSettingsModalOpen] = useState(false); - const skip = useSkipUntilAuthUserIsReady(); + const skip = !useSelector((state) => state.auth.authUserIsReady); const { data: userMe, diff --git a/web/src/components/PTeamSettingsModal.jsx b/web/src/components/PTeamSettingsModal.jsx index 146ffddd..838c5ce2 100644 --- a/web/src/components/PTeamSettingsModal.jsx +++ b/web/src/components/PTeamSettingsModal.jsx @@ -12,10 +12,10 @@ import { import { grey } from "@mui/material/colors"; import PropTypes from "prop-types"; import React, { useState } from "react"; +import { useSelector } from "react-redux"; import { TabPanel } from "../components/TabPanel"; import dialogStyle from "../cssModule/dialog.module.css"; -import { useSkipUntilAuthUserIsReady } from "../hooks/auth"; import { useGetPTeamQuery } from "../services/tcApi"; import { APIError } from "../utils/APIError"; import { a11yProps, errorToString } from "../utils/func.js"; @@ -27,7 +27,7 @@ export function PTeamSettingsModal(props) { const { pteamId, onSetShow, show, defaultTabIndex } = props; const [tab, setTab] = useState(defaultTabIndex ?? 0); - const skip = useSkipUntilAuthUserIsReady() || !pteamId; + const skip = !useSelector((state) => state.auth.authUserIsReady) || !pteamId; const { data: pteam, diff --git a/web/src/hooks/auth.js b/web/src/hooks/auth.js deleted file mode 100644 index 218d3b93..00000000 --- a/web/src/hooks/auth.js +++ /dev/null @@ -1,8 +0,0 @@ -import Firebase from "../utils/Firebase"; - -export function useSkipUntilAuthUserIsReady() { - const auth = Firebase.getAuth(); - const skip = auth.currentUser === null || auth.currentUser === undefined; - - return skip; -} diff --git a/web/src/pages/AcceptPTeamInvitation/AcceptPTeamInvitationPage.jsx b/web/src/pages/AcceptPTeamInvitation/AcceptPTeamInvitationPage.jsx index c8fb56db..9ebf99db 100644 --- a/web/src/pages/AcceptPTeamInvitation/AcceptPTeamInvitationPage.jsx +++ b/web/src/pages/AcceptPTeamInvitation/AcceptPTeamInvitationPage.jsx @@ -2,8 +2,8 @@ import { Box, Button, Typography } from "@mui/material"; import { useSnackbar } from "notistack"; import React from "react"; import { useLocation, useNavigate } from "react-router-dom"; +import { useSelector } from "react-redux"; -import { useSkipUntilAuthUserIsReady } from "../../hooks/auth"; import { useApplyPTeamInvitationMutation, useGetPTeamInvitationQuery } from "../../services/tcApi"; import { APIError } from "../../utils/APIError"; import { commonButtonStyle } from "../../utils/const"; @@ -19,7 +19,7 @@ export function AcceptPTeamInvitation() { const params = new URLSearchParams(useLocation().search); const tokenId = params.get("token"); - const skip = useSkipUntilAuthUserIsReady(); + const skip = !useSelector((state) => state.auth.authUserIsReady); const { data: detail, error: detailError, diff --git a/web/src/pages/Account/AccountPage.jsx b/web/src/pages/Account/AccountPage.jsx index 5b728b7c..cdd8f5fd 100644 --- a/web/src/pages/Account/AccountPage.jsx +++ b/web/src/pages/Account/AccountPage.jsx @@ -12,9 +12,9 @@ import { import { grey } from "@mui/material/colors"; import { useSnackbar } from "notistack"; import React, { useState } from "react"; +import { useSelector } from "react-redux"; import { UUIDTypography } from "../../components/UUIDTypography"; -import { useSkipUntilAuthUserIsReady } from "../../hooks/auth"; import { useGetUserMeQuery, useUpdateUserMutation } from "../../services/tcApi"; import { APIError } from "../../utils/APIError"; import { errorToString } from "../../utils/func"; @@ -28,7 +28,7 @@ export function Account() { const { enqueueSnackbar } = useSnackbar(); const [updateUser] = useUpdateUserMutation(); - const skip = useSkipUntilAuthUserIsReady(); + const skip = !useSelector((state) => state.auth.authUserIsReady); const { data: userMe, error: userMeError, diff --git a/web/src/pages/App/OutletWithCheckedParams.jsx b/web/src/pages/App/OutletWithCheckedParams.jsx index d3efeb25..e5b6e1e6 100644 --- a/web/src/pages/App/OutletWithCheckedParams.jsx +++ b/web/src/pages/App/OutletWithCheckedParams.jsx @@ -1,7 +1,7 @@ import React, { useEffect } from "react"; import { Outlet, useLocation, useNavigate } from "react-router-dom"; +import { useSelector } from "react-redux"; -import { useSkipUntilAuthUserIsReady } from "../../hooks/auth"; import { useGetUserMeQuery } from "../../services/tcApi"; import { APIError } from "../../utils/APIError"; import { errorToString } from "../../utils/func"; @@ -11,7 +11,7 @@ export function OutletWithCheckedParams() { const navigate = useNavigate(); const location = useLocation(); - const skip = useSkipUntilAuthUserIsReady(); + const skip = !useSelector((state) => state.auth.authUserIsReady); const { data: userMe, diff --git a/web/src/pages/App/TeamSelector.jsx b/web/src/pages/App/TeamSelector.jsx index 5df65dbf..cad5ed40 100644 --- a/web/src/pages/App/TeamSelector.jsx +++ b/web/src/pages/App/TeamSelector.jsx @@ -3,8 +3,8 @@ import { Box, Button, Menu, MenuItem } from "@mui/material"; import { grey } from "@mui/material/colors"; import React, { useEffect, useMemo, useState } from "react"; import { useLocation, useNavigate } from "react-router-dom"; +import { useSelector } from "react-redux"; -import { useSkipUntilAuthUserIsReady } from "../../hooks/auth"; import { useGetUserMeQuery } from "../../services/tcApi"; import { APIError } from "../../utils/APIError"; import { LocationReader } from "../../utils/LocationReader"; @@ -35,7 +35,7 @@ export function TeamSelector() { const [openPTeamCreationModal, setOpenPTeamCreationModal] = useState(false); const locationReader = useMemo(() => new LocationReader(location), [location]); - const skip = useSkipUntilAuthUserIsReady(); + const skip = !useSelector((state) => state.auth.authUserIsReady); const { data: userMe, error: userMeError, diff --git a/web/src/pages/PTeam/PTeamMemberMenu.jsx b/web/src/pages/PTeam/PTeamMemberMenu.jsx index 043875bf..0e428220 100644 --- a/web/src/pages/PTeam/PTeamMemberMenu.jsx +++ b/web/src/pages/PTeam/PTeamMemberMenu.jsx @@ -6,8 +6,8 @@ import { import { Button, Dialog, DialogContent, Menu, MenuItem } from "@mui/material"; import PropTypes from "prop-types"; import React, { useState } from "react"; +import { useSelector } from "react-redux"; -import { useSkipUntilAuthUserIsReady } from "../../hooks/auth"; import { useGetPTeamQuery, useGetUserMeQuery } from "../../services/tcApi"; import { APIError } from "../../utils/APIError"; import { errorToString, checkAdmin } from "../../utils/func"; @@ -23,7 +23,7 @@ export function PTeamMemberMenu(props) { const [anchorEl, setAnchorEl] = useState(null); const open = Boolean(anchorEl); - const skip = useSkipUntilAuthUserIsReady() || !pteamId; + const skip = !useSelector((state) => state.auth.authUserIsReady) || !pteamId; const { data: userMe, error: userMeError, diff --git a/web/src/pages/PTeam/PTeamPage.jsx b/web/src/pages/PTeam/PTeamPage.jsx index 67ffa81b..b9aab314 100644 --- a/web/src/pages/PTeam/PTeamPage.jsx +++ b/web/src/pages/PTeam/PTeamPage.jsx @@ -1,10 +1,10 @@ import { Avatar, Box, Tab, Tabs, Tooltip } from "@mui/material"; import React, { useState } from "react"; import { useLocation } from "react-router"; +import { useSelector } from "react-redux"; import { PTeamLabel } from "../../components/PTeamLabel"; import { TabPanel } from "../../components/TabPanel"; -import { useSkipUntilAuthUserIsReady } from "../../hooks/auth"; import { useGetPTeamMembersQuery } from "../../services/tcApi"; import { APIError } from "../../utils/APIError"; import { experienceColors, noPTeamMessage } from "../../utils/const"; @@ -19,7 +19,7 @@ export function PTeam() { const params = new URLSearchParams(location.search); const pteamId = params.get("pteamId"); - const skip = useSkipUntilAuthUserIsReady() || !pteamId; + const skip = !useSelector((state) => state.auth.authUserIsReady) || !pteamId; const { data: members, error: membersError, diff --git a/web/src/pages/Status/PTeamServiceDelete.jsx b/web/src/pages/Status/PTeamServiceDelete.jsx index 56d7a171..bcc7041c 100644 --- a/web/src/pages/Status/PTeamServiceDelete.jsx +++ b/web/src/pages/Status/PTeamServiceDelete.jsx @@ -13,9 +13,9 @@ import { useSnackbar } from "notistack"; import PropTypes from "prop-types"; import React, { useState } from "react"; import { useLocation, useNavigate } from "react-router"; +import { useSelector } from "react-redux"; import styles from "../../cssModule/dialog.module.css"; -import { useSkipUntilAuthUserIsReady } from "../../hooks/auth"; import { useDeletePTeamServiceMutation, useGetPTeamQuery } from "../../services/tcApi"; import { APIError } from "../../utils/APIError"; import { errorToString } from "../../utils/func"; @@ -32,7 +32,7 @@ export function PTeamServiceDelete(props) { const params = new URLSearchParams(location.search); const serviceId = params.get("serviceId"); - const skip = useSkipUntilAuthUserIsReady() || !!pteamId; + const skip = !useSelector((state) => state.auth.authUserIsReady) || !!pteamId; const { data: pteam, error: pteamError, diff --git a/web/src/pages/Status/PTeamServicesListModal.jsx b/web/src/pages/Status/PTeamServicesListModal.jsx index 8313ff29..6e4d7da8 100644 --- a/web/src/pages/Status/PTeamServicesListModal.jsx +++ b/web/src/pages/Status/PTeamServicesListModal.jsx @@ -21,8 +21,8 @@ import { grey } from "@mui/material/colors"; import PropTypes from "prop-types"; import React, { useState } from "react"; import { useNavigate, useLocation } from "react-router-dom"; +import { useSelector } from "react-redux"; -import { useSkipUntilAuthUserIsReady } from "../../hooks/auth"; import { useGetPTeamServiceThumbnailQuery, useGetPTeamQuery } from "../../services/tcApi"; import { APIError } from "../../utils/APIError"; import { errorToString } from "../../utils/func"; @@ -84,7 +84,7 @@ export function PTeamServicesListModal(props) { const params = new URLSearchParams(useLocation().search); const pteamId = params.get("pteamId"); - const skip = useSkipUntilAuthUserIsReady() || !pteamId; + const skip = !useSelector((state) => state.auth.authUserIsReady) || !pteamId; const { data: pteam, error: pteamError, diff --git a/web/src/pages/Status/StatusPage.jsx b/web/src/pages/Status/StatusPage.jsx index 913ab4b5..17ea2477 100644 --- a/web/src/pages/Status/StatusPage.jsx +++ b/web/src/pages/Status/StatusPage.jsx @@ -29,10 +29,10 @@ import PropTypes from "prop-types"; import React, { useEffect, useState } from "react"; import { ErrorBoundary } from "react-error-boundary"; import { useLocation, useNavigate } from "react-router"; +import { useSelector } from "react-redux"; import { Android12Switch } from "../../components/Android12Switch"; import { PTeamLabel } from "../../components/PTeamLabel"; -import { useSkipUntilAuthUserIsReady } from "../../hooks/auth"; import { useGetPTeamQuery, useGetPTeamTagsSummaryQuery, @@ -141,7 +141,7 @@ export function Status() { serviceIds: [], }); - const skipByAuth = useSkipUntilAuthUserIsReady(); + const skipByAuth = !useSelector((state) => state.auth.authUserIsReady); const { data: pteam, diff --git a/web/src/pages/Tag/PTeamTaggedTopics.jsx b/web/src/pages/Tag/PTeamTaggedTopics.jsx index 291ac9b6..77dc101c 100644 --- a/web/src/pages/Tag/PTeamTaggedTopics.jsx +++ b/web/src/pages/Tag/PTeamTaggedTopics.jsx @@ -1,8 +1,8 @@ import { Box, List, ListItem, MenuItem, Pagination, Select, Typography } from "@mui/material"; import PropTypes from "prop-types"; import React, { useState } from "react"; +import { useSelector } from "react-redux"; -import { useSkipUntilAuthUserIsReady } from "../../hooks/auth"; import { useGetPTeamMembersQuery } from "../../services/tcApi"; import { APIError } from "../../utils/APIError"; import { sortedSSVCPriorities } from "../../utils/const"; @@ -17,7 +17,7 @@ export function PTeamTaggedTopics(props) { const [page, setPage] = useState(1); const [perPage, setPerPage] = useState(10); - const skip = useSkipUntilAuthUserIsReady() || !pteamId; + const skip = !useSelector((state) => state.auth.authUserIsReady) || !pteamId; const { data: members, diff --git a/web/src/pages/Tag/ReportCompletedActions.jsx b/web/src/pages/Tag/ReportCompletedActions.jsx index 173800aa..c5b6658d 100644 --- a/web/src/pages/Tag/ReportCompletedActions.jsx +++ b/web/src/pages/Tag/ReportCompletedActions.jsx @@ -14,11 +14,11 @@ import { grey } from "@mui/material/colors"; import { useSnackbar } from "notistack"; import PropTypes from "prop-types"; import React, { useState } from "react"; +import { useSelector } from "react-redux"; import { ActionTypeIcon } from "../../components/ActionTypeIcon"; import { UUIDTypography } from "../../components/UUIDTypography"; import dialogStyle from "../../cssModule/dialog.module.css"; -import { useSkipUntilAuthUserIsReady } from "../../hooks/auth"; import { useCreateActionLogMutation, useUpdateTicketStatusMutation, @@ -40,7 +40,7 @@ export function ReportCompletedActions(props) { const { enqueueSnackbar } = useSnackbar(); - const skip = useSkipUntilAuthUserIsReady(); + const skip = !useSelector((state) => state.auth.authUserIsReady); const { data: userMe, error: userMeError, diff --git a/web/src/pages/Tag/TagPage.jsx b/web/src/pages/Tag/TagPage.jsx index 7cf5e449..12583ae8 100644 --- a/web/src/pages/Tag/TagPage.jsx +++ b/web/src/pages/Tag/TagPage.jsx @@ -2,10 +2,10 @@ import { Box, Divider, Tab, Tabs, Typography, Chip } from "@mui/material"; import { grey } from "@mui/material/colors"; import React, { useState } from "react"; import { useParams, useLocation } from "react-router-dom"; +import { useSelector } from "react-redux"; import { TabPanel } from "../../components/TabPanel"; import { UUIDTypography } from "../../components/UUIDTypography"; -import { useSkipUntilAuthUserIsReady } from "../../hooks/auth"; import { useGetPTeamQuery, useGetPTeamServiceTaggedTopicIdsQuery, @@ -22,7 +22,7 @@ import { TagReferences } from "./TagReferences.jsx"; export function Tag() { const [tabValue, setTabValue] = useState(0); - const skipByAuth = useSkipUntilAuthUserIsReady(); + const skipByAuth = !useSelector((state) => state.auth.authUserIsReady); const { data: allTags, error: allTagsError, diff --git a/web/src/pages/Tag/TopicCard.jsx b/web/src/pages/Tag/TopicCard.jsx index 17b2a17b..f9c01fe0 100644 --- a/web/src/pages/Tag/TopicCard.jsx +++ b/web/src/pages/Tag/TopicCard.jsx @@ -16,9 +16,9 @@ import { grey } from "@mui/material/colors"; import PropTypes from "prop-types"; import React, { useState } from "react"; import { useParams } from "react-router-dom"; +import { useSelector } from "react-redux"; import { UUIDTypography } from "../../components/UUIDTypography"; -import { useSkipUntilAuthUserIsReady } from "../../hooks/auth"; import { useGetPTeamTopicActionsQuery, useGetTicketsQuery, @@ -41,7 +41,7 @@ export function TopicCard(props) { const [detailOpen, setDetailOpen] = useState(false); const [actionFilter, setActionFilter] = useState(true); - const skipByAuth = useSkipUntilAuthUserIsReady(); + const skipByAuth = !useSelector((state) => state.auth.authUserIsReady); const { data: topic, error: topicError, diff --git a/web/src/pages/Tag/TopicTagSelector.jsx b/web/src/pages/Tag/TopicTagSelector.jsx index a86dddaa..5faa1ad4 100644 --- a/web/src/pages/Tag/TopicTagSelector.jsx +++ b/web/src/pages/Tag/TopicTagSelector.jsx @@ -19,9 +19,9 @@ import { useSnackbar } from "notistack"; import PropTypes from "prop-types"; import React, { useEffect, useState } from "react"; import { FixedSizeList } from "react-window"; +import { useSelector } from "react-redux"; import dialogStyle from "../../cssModule/dialog.module.css"; -import { useSkipUntilAuthUserIsReady } from "../../hooks/auth"; import { useCreateTagMutation, useGetTagsQuery } from "../../services/tcApi"; import { APIError } from "../../utils/APIError"; import { commonButtonStyle } from "../../utils/const"; @@ -38,7 +38,7 @@ export function TopicTagSelector(props) { const [createTag] = useCreateTagMutation(); - const skip = useSkipUntilAuthUserIsReady(); + const skip = !useSelector((state) => state.auth.authUserIsReady); const { data: allTags, error: allTagsError, diff --git a/web/src/pages/Tag/TopicTicketAccordion.jsx b/web/src/pages/Tag/TopicTicketAccordion.jsx index 36f046f6..895d2701 100644 --- a/web/src/pages/Tag/TopicTicketAccordion.jsx +++ b/web/src/pages/Tag/TopicTicketAccordion.jsx @@ -18,9 +18,9 @@ import { grey } from "@mui/material/colors"; import { styled } from "@mui/material/styles"; import PropTypes from "prop-types"; import React from "react"; +import { useSelector } from "react-redux"; import { SSVCPriorityStatusChip } from "../../components/SSVCPriorityStatusChip"; -import { useSkipUntilAuthUserIsReady } from "../../hooks/auth"; import { useGetThreatQuery } from "../../services/tcApi"; import { APIError } from "../../utils/APIError"; import { @@ -71,7 +71,7 @@ export function TopicTicketAccordion(props) { const ticketStatus = ticket.ticket_status; const ssvcPriority = ticket.ssvc_deployer_priority || "defer"; - const skipByAuth = useSkipUntilAuthUserIsReady(); + const skipByAuth = !useSelector((state) => state.auth.authUserIsReady); const { data: threat, error: threatError, diff --git a/web/src/pages/TopicDetail/TopicDetailPage.jsx b/web/src/pages/TopicDetail/TopicDetailPage.jsx index 6060c308..d58028f1 100644 --- a/web/src/pages/TopicDetail/TopicDetailPage.jsx +++ b/web/src/pages/TopicDetail/TopicDetailPage.jsx @@ -18,9 +18,9 @@ import { import { green, grey, yellow } from "@mui/material/colors"; import React, { useState } from "react"; import { useParams } from "react-router-dom"; +import { useSelector } from "react-redux"; import { ActionTypeIcon } from "../../components/ActionTypeIcon"; -import { useSkipUntilAuthUserIsReady } from "../../hooks/auth"; import { useGetTopicActionsQuery, useGetTopicQuery } from "../../services/tcApi"; import { APIError } from "../../utils/APIError"; import { cvssProps } from "../../utils/const"; @@ -49,7 +49,7 @@ export function TopicDetail() { const [showAllArtifacts, setShowAllArtifacts] = useState(false); - const skip = useSkipUntilAuthUserIsReady(); + const skip = !useSelector((state) => state.auth.authUserIsReady); const { data: topic, error: topicError, diff --git a/web/src/pages/TopicManagement/TopicManagementPage.jsx b/web/src/pages/TopicManagement/TopicManagementPage.jsx index f9d4e401..fd05b36a 100644 --- a/web/src/pages/TopicManagement/TopicManagementPage.jsx +++ b/web/src/pages/TopicManagement/TopicManagementPage.jsx @@ -29,9 +29,9 @@ import PropTypes from "prop-types"; import React, { useState } from "react"; import { useNavigate } from "react-router"; import { useLocation } from "react-router-dom"; +import { useSelector } from "react-redux"; import styles from "../../cssModule/button.module.css"; -import { useSkipUntilAuthUserIsReady } from "../../hooks/auth"; import { useGetTopicActionsQuery, useGetTopicQuery, @@ -58,7 +58,7 @@ function TopicManagementTableRow(props) { const params = new URLSearchParams(location.search); - const skip = useSkipUntilAuthUserIsReady(); + const skip = !useSelector((state) => state.auth.authUserIsReady); const { data: topic, @@ -147,7 +147,7 @@ export function TopicManagement() { const [perPage, setPerPage] = useState(perPageItems[0]); const [searchConditions, setSearchConditions] = useState({}); - const skip = useSkipUntilAuthUserIsReady(); + const skip = !useSelector((state) => state.auth.authUserIsReady); const params = new URLSearchParams(useLocation().search); const pteamId = params.get("pteamId"); From 9d4872ec62ab56845802be6e110d9904aca67f7f Mon Sep 17 00:00:00 2001 From: TsurutaYoshiki Date: Wed, 29 Jan 2025 08:17:02 +0000 Subject: [PATCH 12/17] add onAuthStateChanged --- web/src/pages/App/AppPage.jsx | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/web/src/pages/App/AppPage.jsx b/web/src/pages/App/AppPage.jsx index d5b93bb4..b6fcfb3e 100644 --- a/web/src/pages/App/AppPage.jsx +++ b/web/src/pages/App/AppPage.jsx @@ -1,11 +1,15 @@ import { Box } from "@mui/material"; +import { onAuthStateChanged } from "firebase/auth"; import React, { useEffect } from "react"; import { ErrorBoundary } from "react-error-boundary"; +import { useDispatch } from "react-redux"; import { useSelector } from "react-redux"; import { useLocation, useNavigate } from "react-router-dom"; +import { setAuthUserIsReady } from "../../slices/auth"; import { useTryLoginMutation } from "../../services/tcApi"; import { mainMaxWidth } from "../../utils/const"; +import Firebase from "../../utils/Firebase"; import { AppBar } from "./AppBar"; import { AppFallback } from "./AppFallback"; @@ -18,13 +22,12 @@ export function App() { const location = useLocation(); const navigate = useNavigate(); + const dispatch = useDispatch(); const [tryLogin] = useTryLoginMutation(); useEffect(() => { - const _checkToken = async () => { - try { - await tryLogin().unwrap(); // throw error if accessToken is expired - } catch (error) { + onAuthStateChanged(Firebase.getAuth(), (user) => { + if (!user) { navigate("/login", { state: { from: location.pathname, @@ -32,10 +35,11 @@ export function App() { message: "Please login to continue.", }, }); + } else { + dispatch(setAuthUserIsReady(true)); } - }; - _checkToken(); - }, [location, navigate, tryLogin]); + }); + }, [location, dispatch, navigate, tryLogin]); return ( <> From ed82362363c9928e9ab9413ce151cc28aea00dc5 Mon Sep 17 00:00:00 2001 From: TsurutaYoshiki Date: Wed, 29 Jan 2025 08:17:36 +0000 Subject: [PATCH 13/17] add authUserIsReady in redux store --- web/src/slices/auth.js | 22 ++++++++++++++++++++++ web/src/slices/index.js | 3 ++- 2 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 web/src/slices/auth.js diff --git a/web/src/slices/auth.js b/web/src/slices/auth.js new file mode 100644 index 00000000..3661c142 --- /dev/null +++ b/web/src/slices/auth.js @@ -0,0 +1,22 @@ +import { createSlice } from "@reduxjs/toolkit"; + +const _initialState = { + authUserIsReady: false, +}; + +const authSlice = createSlice({ + name: "auth", + initialState: _initialState, + reducers: { + setAuthUserIsReady: (state, action) => ({ + ...state, + authUserIsReady: action.payload, + }), + }, +}); + +const { actions, reducer } = authSlice; + +export const { setAuthUserIsReady } = actions; + +export default reducer; diff --git a/web/src/slices/index.js b/web/src/slices/index.js index 1c51582f..c97d9104 100644 --- a/web/src/slices/index.js +++ b/web/src/slices/index.js @@ -1,8 +1,9 @@ import { combineReducers } from "redux"; +import auth from "./auth"; import system from "./system"; -export const sliceReducers = { system }; +export const sliceReducers = { auth, system }; const rootReducer = combineReducers(sliceReducers); From af50ee62bdb0edece5cb464d8228a738c587038e Mon Sep 17 00:00:00 2001 From: TsurutaYoshiki Date: Wed, 29 Jan 2025 08:31:53 +0000 Subject: [PATCH 14/17] fix formtat --- .../AcceptPTeamInvitation/AcceptPTeamInvitationPage.jsx | 2 +- web/src/pages/App/AppPage.jsx | 7 +++---- web/src/pages/App/OutletWithCheckedParams.jsx | 2 +- web/src/pages/App/TeamSelector.jsx | 2 +- web/src/pages/PTeam/PTeamPage.jsx | 2 +- web/src/pages/Status/PTeamServiceDelete.jsx | 2 +- web/src/pages/Status/PTeamServicesListModal.jsx | 2 +- web/src/pages/Status/StatusPage.jsx | 2 +- web/src/pages/Tag/TagPage.jsx | 2 +- web/src/pages/Tag/TopicCard.jsx | 2 +- web/src/pages/Tag/TopicTagSelector.jsx | 2 +- web/src/pages/TopicDetail/TopicDetailPage.jsx | 2 +- web/src/pages/TopicManagement/TopicManagementPage.jsx | 2 +- 13 files changed, 15 insertions(+), 16 deletions(-) diff --git a/web/src/pages/AcceptPTeamInvitation/AcceptPTeamInvitationPage.jsx b/web/src/pages/AcceptPTeamInvitation/AcceptPTeamInvitationPage.jsx index 9ebf99db..4793443a 100644 --- a/web/src/pages/AcceptPTeamInvitation/AcceptPTeamInvitationPage.jsx +++ b/web/src/pages/AcceptPTeamInvitation/AcceptPTeamInvitationPage.jsx @@ -1,8 +1,8 @@ import { Box, Button, Typography } from "@mui/material"; import { useSnackbar } from "notistack"; import React from "react"; -import { useLocation, useNavigate } from "react-router-dom"; import { useSelector } from "react-redux"; +import { useLocation, useNavigate } from "react-router-dom"; import { useApplyPTeamInvitationMutation, useGetPTeamInvitationQuery } from "../../services/tcApi"; import { APIError } from "../../utils/APIError"; diff --git a/web/src/pages/App/AppPage.jsx b/web/src/pages/App/AppPage.jsx index b6fcfb3e..3b8c1451 100644 --- a/web/src/pages/App/AppPage.jsx +++ b/web/src/pages/App/AppPage.jsx @@ -2,14 +2,13 @@ import { Box } from "@mui/material"; import { onAuthStateChanged } from "firebase/auth"; import React, { useEffect } from "react"; import { ErrorBoundary } from "react-error-boundary"; -import { useDispatch } from "react-redux"; -import { useSelector } from "react-redux"; +import { useDispatch, useSelector } from "react-redux"; import { useLocation, useNavigate } from "react-router-dom"; -import { setAuthUserIsReady } from "../../slices/auth"; import { useTryLoginMutation } from "../../services/tcApi"; -import { mainMaxWidth } from "../../utils/const"; +import { setAuthUserIsReady } from "../../slices/auth"; import Firebase from "../../utils/Firebase"; +import { mainMaxWidth } from "../../utils/const"; import { AppBar } from "./AppBar"; import { AppFallback } from "./AppFallback"; diff --git a/web/src/pages/App/OutletWithCheckedParams.jsx b/web/src/pages/App/OutletWithCheckedParams.jsx index e5b6e1e6..9e1e45ee 100644 --- a/web/src/pages/App/OutletWithCheckedParams.jsx +++ b/web/src/pages/App/OutletWithCheckedParams.jsx @@ -1,6 +1,6 @@ import React, { useEffect } from "react"; -import { Outlet, useLocation, useNavigate } from "react-router-dom"; import { useSelector } from "react-redux"; +import { Outlet, useLocation, useNavigate } from "react-router-dom"; import { useGetUserMeQuery } from "../../services/tcApi"; import { APIError } from "../../utils/APIError"; diff --git a/web/src/pages/App/TeamSelector.jsx b/web/src/pages/App/TeamSelector.jsx index cad5ed40..b8875d7a 100644 --- a/web/src/pages/App/TeamSelector.jsx +++ b/web/src/pages/App/TeamSelector.jsx @@ -2,8 +2,8 @@ import { Add as AddIcon, KeyboardArrowDown as KeyboardArrowDownIcon } from "@mui import { Box, Button, Menu, MenuItem } from "@mui/material"; import { grey } from "@mui/material/colors"; import React, { useEffect, useMemo, useState } from "react"; -import { useLocation, useNavigate } from "react-router-dom"; import { useSelector } from "react-redux"; +import { useLocation, useNavigate } from "react-router-dom"; import { useGetUserMeQuery } from "../../services/tcApi"; import { APIError } from "../../utils/APIError"; diff --git a/web/src/pages/PTeam/PTeamPage.jsx b/web/src/pages/PTeam/PTeamPage.jsx index b9aab314..96455f8d 100644 --- a/web/src/pages/PTeam/PTeamPage.jsx +++ b/web/src/pages/PTeam/PTeamPage.jsx @@ -1,7 +1,7 @@ import { Avatar, Box, Tab, Tabs, Tooltip } from "@mui/material"; import React, { useState } from "react"; -import { useLocation } from "react-router"; import { useSelector } from "react-redux"; +import { useLocation } from "react-router"; import { PTeamLabel } from "../../components/PTeamLabel"; import { TabPanel } from "../../components/TabPanel"; diff --git a/web/src/pages/Status/PTeamServiceDelete.jsx b/web/src/pages/Status/PTeamServiceDelete.jsx index bcc7041c..61617abd 100644 --- a/web/src/pages/Status/PTeamServiceDelete.jsx +++ b/web/src/pages/Status/PTeamServiceDelete.jsx @@ -12,8 +12,8 @@ import { import { useSnackbar } from "notistack"; import PropTypes from "prop-types"; import React, { useState } from "react"; -import { useLocation, useNavigate } from "react-router"; import { useSelector } from "react-redux"; +import { useLocation, useNavigate } from "react-router"; import styles from "../../cssModule/dialog.module.css"; import { useDeletePTeamServiceMutation, useGetPTeamQuery } from "../../services/tcApi"; diff --git a/web/src/pages/Status/PTeamServicesListModal.jsx b/web/src/pages/Status/PTeamServicesListModal.jsx index 6e4d7da8..e377ad98 100644 --- a/web/src/pages/Status/PTeamServicesListModal.jsx +++ b/web/src/pages/Status/PTeamServicesListModal.jsx @@ -20,8 +20,8 @@ import { import { grey } from "@mui/material/colors"; import PropTypes from "prop-types"; import React, { useState } from "react"; -import { useNavigate, useLocation } from "react-router-dom"; import { useSelector } from "react-redux"; +import { useNavigate, useLocation } from "react-router-dom"; import { useGetPTeamServiceThumbnailQuery, useGetPTeamQuery } from "../../services/tcApi"; import { APIError } from "../../utils/APIError"; diff --git a/web/src/pages/Status/StatusPage.jsx b/web/src/pages/Status/StatusPage.jsx index 17ea2477..d27e6eb2 100644 --- a/web/src/pages/Status/StatusPage.jsx +++ b/web/src/pages/Status/StatusPage.jsx @@ -28,8 +28,8 @@ import { grey } from "@mui/material/colors"; import PropTypes from "prop-types"; import React, { useEffect, useState } from "react"; import { ErrorBoundary } from "react-error-boundary"; -import { useLocation, useNavigate } from "react-router"; import { useSelector } from "react-redux"; +import { useLocation, useNavigate } from "react-router"; import { Android12Switch } from "../../components/Android12Switch"; import { PTeamLabel } from "../../components/PTeamLabel"; diff --git a/web/src/pages/Tag/TagPage.jsx b/web/src/pages/Tag/TagPage.jsx index 12583ae8..afb81b33 100644 --- a/web/src/pages/Tag/TagPage.jsx +++ b/web/src/pages/Tag/TagPage.jsx @@ -1,8 +1,8 @@ import { Box, Divider, Tab, Tabs, Typography, Chip } from "@mui/material"; import { grey } from "@mui/material/colors"; import React, { useState } from "react"; -import { useParams, useLocation } from "react-router-dom"; import { useSelector } from "react-redux"; +import { useParams, useLocation } from "react-router-dom"; import { TabPanel } from "../../components/TabPanel"; import { UUIDTypography } from "../../components/UUIDTypography"; diff --git a/web/src/pages/Tag/TopicCard.jsx b/web/src/pages/Tag/TopicCard.jsx index f9c01fe0..6bcc592a 100644 --- a/web/src/pages/Tag/TopicCard.jsx +++ b/web/src/pages/Tag/TopicCard.jsx @@ -15,8 +15,8 @@ import { import { grey } from "@mui/material/colors"; import PropTypes from "prop-types"; import React, { useState } from "react"; -import { useParams } from "react-router-dom"; import { useSelector } from "react-redux"; +import { useParams } from "react-router-dom"; import { UUIDTypography } from "../../components/UUIDTypography"; import { diff --git a/web/src/pages/Tag/TopicTagSelector.jsx b/web/src/pages/Tag/TopicTagSelector.jsx index 5faa1ad4..61437853 100644 --- a/web/src/pages/Tag/TopicTagSelector.jsx +++ b/web/src/pages/Tag/TopicTagSelector.jsx @@ -18,8 +18,8 @@ import { import { useSnackbar } from "notistack"; import PropTypes from "prop-types"; import React, { useEffect, useState } from "react"; -import { FixedSizeList } from "react-window"; import { useSelector } from "react-redux"; +import { FixedSizeList } from "react-window"; import dialogStyle from "../../cssModule/dialog.module.css"; import { useCreateTagMutation, useGetTagsQuery } from "../../services/tcApi"; diff --git a/web/src/pages/TopicDetail/TopicDetailPage.jsx b/web/src/pages/TopicDetail/TopicDetailPage.jsx index d58028f1..72d8e4ff 100644 --- a/web/src/pages/TopicDetail/TopicDetailPage.jsx +++ b/web/src/pages/TopicDetail/TopicDetailPage.jsx @@ -17,8 +17,8 @@ import { } from "@mui/material"; import { green, grey, yellow } from "@mui/material/colors"; import React, { useState } from "react"; -import { useParams } from "react-router-dom"; import { useSelector } from "react-redux"; +import { useParams } from "react-router-dom"; import { ActionTypeIcon } from "../../components/ActionTypeIcon"; import { useGetTopicActionsQuery, useGetTopicQuery } from "../../services/tcApi"; diff --git a/web/src/pages/TopicManagement/TopicManagementPage.jsx b/web/src/pages/TopicManagement/TopicManagementPage.jsx index fd05b36a..6c893d03 100644 --- a/web/src/pages/TopicManagement/TopicManagementPage.jsx +++ b/web/src/pages/TopicManagement/TopicManagementPage.jsx @@ -27,9 +27,9 @@ import { grey } from "@mui/material/colors"; import { styled } from "@mui/material/styles"; import PropTypes from "prop-types"; import React, { useState } from "react"; +import { useSelector } from "react-redux"; import { useNavigate } from "react-router"; import { useLocation } from "react-router-dom"; -import { useSelector } from "react-redux"; import styles from "../../cssModule/button.module.css"; import { From 875522904a2cfe01af8cfdedad7da64df9ebb572 Mon Sep 17 00:00:00 2001 From: TsurutaYoshiki Date: Thu, 30 Jan 2025 02:10:39 +0000 Subject: [PATCH 15/17] delete tryLogin --- web/src/pages/App/AppPage.jsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/web/src/pages/App/AppPage.jsx b/web/src/pages/App/AppPage.jsx index 3b8c1451..c18e84a8 100644 --- a/web/src/pages/App/AppPage.jsx +++ b/web/src/pages/App/AppPage.jsx @@ -5,7 +5,6 @@ import { ErrorBoundary } from "react-error-boundary"; import { useDispatch, useSelector } from "react-redux"; import { useLocation, useNavigate } from "react-router-dom"; -import { useTryLoginMutation } from "../../services/tcApi"; import { setAuthUserIsReady } from "../../slices/auth"; import Firebase from "../../utils/Firebase"; import { mainMaxWidth } from "../../utils/const"; @@ -22,7 +21,6 @@ export function App() { const navigate = useNavigate(); const dispatch = useDispatch(); - const [tryLogin] = useTryLoginMutation(); useEffect(() => { onAuthStateChanged(Firebase.getAuth(), (user) => { @@ -38,7 +36,7 @@ export function App() { dispatch(setAuthUserIsReady(true)); } }); - }, [location, dispatch, navigate, tryLogin]); + }, [location, dispatch, navigate]); return ( <> From 5218f807ccfd20749a6b52ad1ef81327d135c6f2 Mon Sep 17 00:00:00 2001 From: TsurutaYoshiki Date: Thu, 30 Jan 2025 02:11:35 +0000 Subject: [PATCH 16/17] add useSkipUntilAuthUserIsReady --- web/src/components/PTeamLabel.jsx | 4 ++-- web/src/components/PTeamSettingsModal.jsx | 4 ++-- web/src/hooks/auth.js | 5 +++++ .../AcceptPTeamInvitation/AcceptPTeamInvitationPage.jsx | 4 ++-- web/src/pages/Account/AccountPage.jsx | 4 ++-- web/src/pages/App/OutletWithCheckedParams.jsx | 4 ++-- web/src/pages/App/TeamSelector.jsx | 4 ++-- web/src/pages/PTeam/PTeamMemberMenu.jsx | 4 ++-- web/src/pages/PTeam/PTeamPage.jsx | 4 ++-- web/src/pages/Status/PTeamServiceDelete.jsx | 4 ++-- web/src/pages/Status/PTeamServicesListModal.jsx | 4 ++-- web/src/pages/Status/StatusPage.jsx | 4 ++-- web/src/pages/Tag/PTeamTaggedTopics.jsx | 4 ++-- web/src/pages/Tag/ReportCompletedActions.jsx | 4 ++-- web/src/pages/Tag/TagPage.jsx | 4 ++-- web/src/pages/Tag/TopicCard.jsx | 4 ++-- web/src/pages/Tag/TopicTagSelector.jsx | 4 ++-- web/src/pages/Tag/TopicTicketAccordion.jsx | 4 ++-- web/src/pages/TopicDetail/TopicDetailPage.jsx | 4 ++-- web/src/pages/TopicManagement/TopicManagementPage.jsx | 7 +++---- 20 files changed, 44 insertions(+), 40 deletions(-) create mode 100644 web/src/hooks/auth.js diff --git a/web/src/components/PTeamLabel.jsx b/web/src/components/PTeamLabel.jsx index ffad0b56..8ace3a4a 100644 --- a/web/src/components/PTeamLabel.jsx +++ b/web/src/components/PTeamLabel.jsx @@ -2,8 +2,8 @@ import { Settings as SettingsIcon } from "@mui/icons-material"; import { Box, IconButton, Typography } from "@mui/material"; import PropTypes from "prop-types"; import React, { useState } from "react"; -import { useSelector } from "react-redux"; +import { useSkipUntilAuthUserIsReady } from "../hooks/auth"; import { useGetUserMeQuery } from "../services/tcApi"; import { APIError } from "../utils/APIError"; import { errorToString } from "../utils/func"; @@ -16,7 +16,7 @@ export function PTeamLabel(props) { const [pteamSettingsModalOpen, setPTeamSettingsModalOpen] = useState(false); - const skip = !useSelector((state) => state.auth.authUserIsReady); + const skip = useSkipUntilAuthUserIsReady(); const { data: userMe, diff --git a/web/src/components/PTeamSettingsModal.jsx b/web/src/components/PTeamSettingsModal.jsx index 838c5ce2..146ffddd 100644 --- a/web/src/components/PTeamSettingsModal.jsx +++ b/web/src/components/PTeamSettingsModal.jsx @@ -12,10 +12,10 @@ import { import { grey } from "@mui/material/colors"; import PropTypes from "prop-types"; import React, { useState } from "react"; -import { useSelector } from "react-redux"; import { TabPanel } from "../components/TabPanel"; import dialogStyle from "../cssModule/dialog.module.css"; +import { useSkipUntilAuthUserIsReady } from "../hooks/auth"; import { useGetPTeamQuery } from "../services/tcApi"; import { APIError } from "../utils/APIError"; import { a11yProps, errorToString } from "../utils/func.js"; @@ -27,7 +27,7 @@ export function PTeamSettingsModal(props) { const { pteamId, onSetShow, show, defaultTabIndex } = props; const [tab, setTab] = useState(defaultTabIndex ?? 0); - const skip = !useSelector((state) => state.auth.authUserIsReady) || !pteamId; + const skip = useSkipUntilAuthUserIsReady() || !pteamId; const { data: pteam, diff --git a/web/src/hooks/auth.js b/web/src/hooks/auth.js new file mode 100644 index 00000000..39edaafc --- /dev/null +++ b/web/src/hooks/auth.js @@ -0,0 +1,5 @@ +import { useSelector } from "react-redux"; + +export function useSkipUntilAuthUserIsReady() { + return !useSelector((state) => state.auth.authUserIsReady); +} diff --git a/web/src/pages/AcceptPTeamInvitation/AcceptPTeamInvitationPage.jsx b/web/src/pages/AcceptPTeamInvitation/AcceptPTeamInvitationPage.jsx index 4793443a..c8fb56db 100644 --- a/web/src/pages/AcceptPTeamInvitation/AcceptPTeamInvitationPage.jsx +++ b/web/src/pages/AcceptPTeamInvitation/AcceptPTeamInvitationPage.jsx @@ -1,9 +1,9 @@ import { Box, Button, Typography } from "@mui/material"; import { useSnackbar } from "notistack"; import React from "react"; -import { useSelector } from "react-redux"; import { useLocation, useNavigate } from "react-router-dom"; +import { useSkipUntilAuthUserIsReady } from "../../hooks/auth"; import { useApplyPTeamInvitationMutation, useGetPTeamInvitationQuery } from "../../services/tcApi"; import { APIError } from "../../utils/APIError"; import { commonButtonStyle } from "../../utils/const"; @@ -19,7 +19,7 @@ export function AcceptPTeamInvitation() { const params = new URLSearchParams(useLocation().search); const tokenId = params.get("token"); - const skip = !useSelector((state) => state.auth.authUserIsReady); + const skip = useSkipUntilAuthUserIsReady(); const { data: detail, error: detailError, diff --git a/web/src/pages/Account/AccountPage.jsx b/web/src/pages/Account/AccountPage.jsx index cdd8f5fd..5b728b7c 100644 --- a/web/src/pages/Account/AccountPage.jsx +++ b/web/src/pages/Account/AccountPage.jsx @@ -12,9 +12,9 @@ import { import { grey } from "@mui/material/colors"; import { useSnackbar } from "notistack"; import React, { useState } from "react"; -import { useSelector } from "react-redux"; import { UUIDTypography } from "../../components/UUIDTypography"; +import { useSkipUntilAuthUserIsReady } from "../../hooks/auth"; import { useGetUserMeQuery, useUpdateUserMutation } from "../../services/tcApi"; import { APIError } from "../../utils/APIError"; import { errorToString } from "../../utils/func"; @@ -28,7 +28,7 @@ export function Account() { const { enqueueSnackbar } = useSnackbar(); const [updateUser] = useUpdateUserMutation(); - const skip = !useSelector((state) => state.auth.authUserIsReady); + const skip = useSkipUntilAuthUserIsReady(); const { data: userMe, error: userMeError, diff --git a/web/src/pages/App/OutletWithCheckedParams.jsx b/web/src/pages/App/OutletWithCheckedParams.jsx index 9e1e45ee..d3efeb25 100644 --- a/web/src/pages/App/OutletWithCheckedParams.jsx +++ b/web/src/pages/App/OutletWithCheckedParams.jsx @@ -1,7 +1,7 @@ import React, { useEffect } from "react"; -import { useSelector } from "react-redux"; import { Outlet, useLocation, useNavigate } from "react-router-dom"; +import { useSkipUntilAuthUserIsReady } from "../../hooks/auth"; import { useGetUserMeQuery } from "../../services/tcApi"; import { APIError } from "../../utils/APIError"; import { errorToString } from "../../utils/func"; @@ -11,7 +11,7 @@ export function OutletWithCheckedParams() { const navigate = useNavigate(); const location = useLocation(); - const skip = !useSelector((state) => state.auth.authUserIsReady); + const skip = useSkipUntilAuthUserIsReady(); const { data: userMe, diff --git a/web/src/pages/App/TeamSelector.jsx b/web/src/pages/App/TeamSelector.jsx index b8875d7a..5df65dbf 100644 --- a/web/src/pages/App/TeamSelector.jsx +++ b/web/src/pages/App/TeamSelector.jsx @@ -2,9 +2,9 @@ import { Add as AddIcon, KeyboardArrowDown as KeyboardArrowDownIcon } from "@mui import { Box, Button, Menu, MenuItem } from "@mui/material"; import { grey } from "@mui/material/colors"; import React, { useEffect, useMemo, useState } from "react"; -import { useSelector } from "react-redux"; import { useLocation, useNavigate } from "react-router-dom"; +import { useSkipUntilAuthUserIsReady } from "../../hooks/auth"; import { useGetUserMeQuery } from "../../services/tcApi"; import { APIError } from "../../utils/APIError"; import { LocationReader } from "../../utils/LocationReader"; @@ -35,7 +35,7 @@ export function TeamSelector() { const [openPTeamCreationModal, setOpenPTeamCreationModal] = useState(false); const locationReader = useMemo(() => new LocationReader(location), [location]); - const skip = !useSelector((state) => state.auth.authUserIsReady); + const skip = useSkipUntilAuthUserIsReady(); const { data: userMe, error: userMeError, diff --git a/web/src/pages/PTeam/PTeamMemberMenu.jsx b/web/src/pages/PTeam/PTeamMemberMenu.jsx index 0e428220..043875bf 100644 --- a/web/src/pages/PTeam/PTeamMemberMenu.jsx +++ b/web/src/pages/PTeam/PTeamMemberMenu.jsx @@ -6,8 +6,8 @@ import { import { Button, Dialog, DialogContent, Menu, MenuItem } from "@mui/material"; import PropTypes from "prop-types"; import React, { useState } from "react"; -import { useSelector } from "react-redux"; +import { useSkipUntilAuthUserIsReady } from "../../hooks/auth"; import { useGetPTeamQuery, useGetUserMeQuery } from "../../services/tcApi"; import { APIError } from "../../utils/APIError"; import { errorToString, checkAdmin } from "../../utils/func"; @@ -23,7 +23,7 @@ export function PTeamMemberMenu(props) { const [anchorEl, setAnchorEl] = useState(null); const open = Boolean(anchorEl); - const skip = !useSelector((state) => state.auth.authUserIsReady) || !pteamId; + const skip = useSkipUntilAuthUserIsReady() || !pteamId; const { data: userMe, error: userMeError, diff --git a/web/src/pages/PTeam/PTeamPage.jsx b/web/src/pages/PTeam/PTeamPage.jsx index 96455f8d..67ffa81b 100644 --- a/web/src/pages/PTeam/PTeamPage.jsx +++ b/web/src/pages/PTeam/PTeamPage.jsx @@ -1,10 +1,10 @@ import { Avatar, Box, Tab, Tabs, Tooltip } from "@mui/material"; import React, { useState } from "react"; -import { useSelector } from "react-redux"; import { useLocation } from "react-router"; import { PTeamLabel } from "../../components/PTeamLabel"; import { TabPanel } from "../../components/TabPanel"; +import { useSkipUntilAuthUserIsReady } from "../../hooks/auth"; import { useGetPTeamMembersQuery } from "../../services/tcApi"; import { APIError } from "../../utils/APIError"; import { experienceColors, noPTeamMessage } from "../../utils/const"; @@ -19,7 +19,7 @@ export function PTeam() { const params = new URLSearchParams(location.search); const pteamId = params.get("pteamId"); - const skip = !useSelector((state) => state.auth.authUserIsReady) || !pteamId; + const skip = useSkipUntilAuthUserIsReady() || !pteamId; const { data: members, error: membersError, diff --git a/web/src/pages/Status/PTeamServiceDelete.jsx b/web/src/pages/Status/PTeamServiceDelete.jsx index 61617abd..56d7a171 100644 --- a/web/src/pages/Status/PTeamServiceDelete.jsx +++ b/web/src/pages/Status/PTeamServiceDelete.jsx @@ -12,10 +12,10 @@ import { import { useSnackbar } from "notistack"; import PropTypes from "prop-types"; import React, { useState } from "react"; -import { useSelector } from "react-redux"; import { useLocation, useNavigate } from "react-router"; import styles from "../../cssModule/dialog.module.css"; +import { useSkipUntilAuthUserIsReady } from "../../hooks/auth"; import { useDeletePTeamServiceMutation, useGetPTeamQuery } from "../../services/tcApi"; import { APIError } from "../../utils/APIError"; import { errorToString } from "../../utils/func"; @@ -32,7 +32,7 @@ export function PTeamServiceDelete(props) { const params = new URLSearchParams(location.search); const serviceId = params.get("serviceId"); - const skip = !useSelector((state) => state.auth.authUserIsReady) || !!pteamId; + const skip = useSkipUntilAuthUserIsReady() || !!pteamId; const { data: pteam, error: pteamError, diff --git a/web/src/pages/Status/PTeamServicesListModal.jsx b/web/src/pages/Status/PTeamServicesListModal.jsx index e377ad98..8313ff29 100644 --- a/web/src/pages/Status/PTeamServicesListModal.jsx +++ b/web/src/pages/Status/PTeamServicesListModal.jsx @@ -20,9 +20,9 @@ import { import { grey } from "@mui/material/colors"; import PropTypes from "prop-types"; import React, { useState } from "react"; -import { useSelector } from "react-redux"; import { useNavigate, useLocation } from "react-router-dom"; +import { useSkipUntilAuthUserIsReady } from "../../hooks/auth"; import { useGetPTeamServiceThumbnailQuery, useGetPTeamQuery } from "../../services/tcApi"; import { APIError } from "../../utils/APIError"; import { errorToString } from "../../utils/func"; @@ -84,7 +84,7 @@ export function PTeamServicesListModal(props) { const params = new URLSearchParams(useLocation().search); const pteamId = params.get("pteamId"); - const skip = !useSelector((state) => state.auth.authUserIsReady) || !pteamId; + const skip = useSkipUntilAuthUserIsReady() || !pteamId; const { data: pteam, error: pteamError, diff --git a/web/src/pages/Status/StatusPage.jsx b/web/src/pages/Status/StatusPage.jsx index d27e6eb2..913ab4b5 100644 --- a/web/src/pages/Status/StatusPage.jsx +++ b/web/src/pages/Status/StatusPage.jsx @@ -28,11 +28,11 @@ import { grey } from "@mui/material/colors"; import PropTypes from "prop-types"; import React, { useEffect, useState } from "react"; import { ErrorBoundary } from "react-error-boundary"; -import { useSelector } from "react-redux"; import { useLocation, useNavigate } from "react-router"; import { Android12Switch } from "../../components/Android12Switch"; import { PTeamLabel } from "../../components/PTeamLabel"; +import { useSkipUntilAuthUserIsReady } from "../../hooks/auth"; import { useGetPTeamQuery, useGetPTeamTagsSummaryQuery, @@ -141,7 +141,7 @@ export function Status() { serviceIds: [], }); - const skipByAuth = !useSelector((state) => state.auth.authUserIsReady); + const skipByAuth = useSkipUntilAuthUserIsReady(); const { data: pteam, diff --git a/web/src/pages/Tag/PTeamTaggedTopics.jsx b/web/src/pages/Tag/PTeamTaggedTopics.jsx index 77dc101c..291ac9b6 100644 --- a/web/src/pages/Tag/PTeamTaggedTopics.jsx +++ b/web/src/pages/Tag/PTeamTaggedTopics.jsx @@ -1,8 +1,8 @@ import { Box, List, ListItem, MenuItem, Pagination, Select, Typography } from "@mui/material"; import PropTypes from "prop-types"; import React, { useState } from "react"; -import { useSelector } from "react-redux"; +import { useSkipUntilAuthUserIsReady } from "../../hooks/auth"; import { useGetPTeamMembersQuery } from "../../services/tcApi"; import { APIError } from "../../utils/APIError"; import { sortedSSVCPriorities } from "../../utils/const"; @@ -17,7 +17,7 @@ export function PTeamTaggedTopics(props) { const [page, setPage] = useState(1); const [perPage, setPerPage] = useState(10); - const skip = !useSelector((state) => state.auth.authUserIsReady) || !pteamId; + const skip = useSkipUntilAuthUserIsReady() || !pteamId; const { data: members, diff --git a/web/src/pages/Tag/ReportCompletedActions.jsx b/web/src/pages/Tag/ReportCompletedActions.jsx index c5b6658d..173800aa 100644 --- a/web/src/pages/Tag/ReportCompletedActions.jsx +++ b/web/src/pages/Tag/ReportCompletedActions.jsx @@ -14,11 +14,11 @@ import { grey } from "@mui/material/colors"; import { useSnackbar } from "notistack"; import PropTypes from "prop-types"; import React, { useState } from "react"; -import { useSelector } from "react-redux"; import { ActionTypeIcon } from "../../components/ActionTypeIcon"; import { UUIDTypography } from "../../components/UUIDTypography"; import dialogStyle from "../../cssModule/dialog.module.css"; +import { useSkipUntilAuthUserIsReady } from "../../hooks/auth"; import { useCreateActionLogMutation, useUpdateTicketStatusMutation, @@ -40,7 +40,7 @@ export function ReportCompletedActions(props) { const { enqueueSnackbar } = useSnackbar(); - const skip = !useSelector((state) => state.auth.authUserIsReady); + const skip = useSkipUntilAuthUserIsReady(); const { data: userMe, error: userMeError, diff --git a/web/src/pages/Tag/TagPage.jsx b/web/src/pages/Tag/TagPage.jsx index afb81b33..7cf5e449 100644 --- a/web/src/pages/Tag/TagPage.jsx +++ b/web/src/pages/Tag/TagPage.jsx @@ -1,11 +1,11 @@ import { Box, Divider, Tab, Tabs, Typography, Chip } from "@mui/material"; import { grey } from "@mui/material/colors"; import React, { useState } from "react"; -import { useSelector } from "react-redux"; import { useParams, useLocation } from "react-router-dom"; import { TabPanel } from "../../components/TabPanel"; import { UUIDTypography } from "../../components/UUIDTypography"; +import { useSkipUntilAuthUserIsReady } from "../../hooks/auth"; import { useGetPTeamQuery, useGetPTeamServiceTaggedTopicIdsQuery, @@ -22,7 +22,7 @@ import { TagReferences } from "./TagReferences.jsx"; export function Tag() { const [tabValue, setTabValue] = useState(0); - const skipByAuth = !useSelector((state) => state.auth.authUserIsReady); + const skipByAuth = useSkipUntilAuthUserIsReady(); const { data: allTags, error: allTagsError, diff --git a/web/src/pages/Tag/TopicCard.jsx b/web/src/pages/Tag/TopicCard.jsx index 6bcc592a..17b2a17b 100644 --- a/web/src/pages/Tag/TopicCard.jsx +++ b/web/src/pages/Tag/TopicCard.jsx @@ -15,10 +15,10 @@ import { import { grey } from "@mui/material/colors"; import PropTypes from "prop-types"; import React, { useState } from "react"; -import { useSelector } from "react-redux"; import { useParams } from "react-router-dom"; import { UUIDTypography } from "../../components/UUIDTypography"; +import { useSkipUntilAuthUserIsReady } from "../../hooks/auth"; import { useGetPTeamTopicActionsQuery, useGetTicketsQuery, @@ -41,7 +41,7 @@ export function TopicCard(props) { const [detailOpen, setDetailOpen] = useState(false); const [actionFilter, setActionFilter] = useState(true); - const skipByAuth = !useSelector((state) => state.auth.authUserIsReady); + const skipByAuth = useSkipUntilAuthUserIsReady(); const { data: topic, error: topicError, diff --git a/web/src/pages/Tag/TopicTagSelector.jsx b/web/src/pages/Tag/TopicTagSelector.jsx index 61437853..a86dddaa 100644 --- a/web/src/pages/Tag/TopicTagSelector.jsx +++ b/web/src/pages/Tag/TopicTagSelector.jsx @@ -18,10 +18,10 @@ import { import { useSnackbar } from "notistack"; import PropTypes from "prop-types"; import React, { useEffect, useState } from "react"; -import { useSelector } from "react-redux"; import { FixedSizeList } from "react-window"; import dialogStyle from "../../cssModule/dialog.module.css"; +import { useSkipUntilAuthUserIsReady } from "../../hooks/auth"; import { useCreateTagMutation, useGetTagsQuery } from "../../services/tcApi"; import { APIError } from "../../utils/APIError"; import { commonButtonStyle } from "../../utils/const"; @@ -38,7 +38,7 @@ export function TopicTagSelector(props) { const [createTag] = useCreateTagMutation(); - const skip = !useSelector((state) => state.auth.authUserIsReady); + const skip = useSkipUntilAuthUserIsReady(); const { data: allTags, error: allTagsError, diff --git a/web/src/pages/Tag/TopicTicketAccordion.jsx b/web/src/pages/Tag/TopicTicketAccordion.jsx index 895d2701..36f046f6 100644 --- a/web/src/pages/Tag/TopicTicketAccordion.jsx +++ b/web/src/pages/Tag/TopicTicketAccordion.jsx @@ -18,9 +18,9 @@ import { grey } from "@mui/material/colors"; import { styled } from "@mui/material/styles"; import PropTypes from "prop-types"; import React from "react"; -import { useSelector } from "react-redux"; import { SSVCPriorityStatusChip } from "../../components/SSVCPriorityStatusChip"; +import { useSkipUntilAuthUserIsReady } from "../../hooks/auth"; import { useGetThreatQuery } from "../../services/tcApi"; import { APIError } from "../../utils/APIError"; import { @@ -71,7 +71,7 @@ export function TopicTicketAccordion(props) { const ticketStatus = ticket.ticket_status; const ssvcPriority = ticket.ssvc_deployer_priority || "defer"; - const skipByAuth = !useSelector((state) => state.auth.authUserIsReady); + const skipByAuth = useSkipUntilAuthUserIsReady(); const { data: threat, error: threatError, diff --git a/web/src/pages/TopicDetail/TopicDetailPage.jsx b/web/src/pages/TopicDetail/TopicDetailPage.jsx index 72d8e4ff..6060c308 100644 --- a/web/src/pages/TopicDetail/TopicDetailPage.jsx +++ b/web/src/pages/TopicDetail/TopicDetailPage.jsx @@ -17,10 +17,10 @@ import { } from "@mui/material"; import { green, grey, yellow } from "@mui/material/colors"; import React, { useState } from "react"; -import { useSelector } from "react-redux"; import { useParams } from "react-router-dom"; import { ActionTypeIcon } from "../../components/ActionTypeIcon"; +import { useSkipUntilAuthUserIsReady } from "../../hooks/auth"; import { useGetTopicActionsQuery, useGetTopicQuery } from "../../services/tcApi"; import { APIError } from "../../utils/APIError"; import { cvssProps } from "../../utils/const"; @@ -49,7 +49,7 @@ export function TopicDetail() { const [showAllArtifacts, setShowAllArtifacts] = useState(false); - const skip = !useSelector((state) => state.auth.authUserIsReady); + const skip = useSkipUntilAuthUserIsReady(); const { data: topic, error: topicError, diff --git a/web/src/pages/TopicManagement/TopicManagementPage.jsx b/web/src/pages/TopicManagement/TopicManagementPage.jsx index 6c893d03..0d144afc 100644 --- a/web/src/pages/TopicManagement/TopicManagementPage.jsx +++ b/web/src/pages/TopicManagement/TopicManagementPage.jsx @@ -27,11 +27,11 @@ import { grey } from "@mui/material/colors"; import { styled } from "@mui/material/styles"; import PropTypes from "prop-types"; import React, { useState } from "react"; -import { useSelector } from "react-redux"; import { useNavigate } from "react-router"; import { useLocation } from "react-router-dom"; import styles from "../../cssModule/button.module.css"; +import { useSkipUntilAuthUserIsReady } from "../../hooks/auth"; import { useGetTopicActionsQuery, useGetTopicQuery, @@ -58,8 +58,7 @@ function TopicManagementTableRow(props) { const params = new URLSearchParams(location.search); - const skip = !useSelector((state) => state.auth.authUserIsReady); - + const skip = useSkipUntilAuthUserIsReady(); const { data: topic, error: topicError, @@ -147,7 +146,7 @@ export function TopicManagement() { const [perPage, setPerPage] = useState(perPageItems[0]); const [searchConditions, setSearchConditions] = useState({}); - const skip = !useSelector((state) => state.auth.authUserIsReady); + const skip = useSkipUntilAuthUserIsReady(); const params = new URLSearchParams(useLocation().search); const pteamId = params.get("pteamId"); From a684189eadc0c540e9c3d9f4f7cc0255197dcb39 Mon Sep 17 00:00:00 2001 From: TsurutaYoshiki Date: Thu, 30 Jan 2025 04:43:06 +0000 Subject: [PATCH 17/17] add signOut --- web/src/pages/App/AppBar.jsx | 16 +++++++++++++--- web/src/pages/App/AppPage.jsx | 3 ++- web/src/pages/Login/LoginPage.jsx | 4 ++++ 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/web/src/pages/App/AppBar.jsx b/web/src/pages/App/AppBar.jsx index 22891207..193f482b 100644 --- a/web/src/pages/App/AppBar.jsx +++ b/web/src/pages/App/AppBar.jsx @@ -1,6 +1,7 @@ import { Menu as MenuIcon } from "@mui/icons-material"; import { AppBar as MuiAppBar, Box, Button, Divider, IconButton, Toolbar } from "@mui/material"; import { styled } from "@mui/material/styles"; +import { signOut } from "firebase/auth"; import React from "react"; import { ErrorBoundary } from "react-error-boundary"; import { useDispatch, useSelector } from "react-redux"; @@ -8,7 +9,9 @@ import { useNavigate } from "react-router-dom"; import { firebaseApi } from "../../services/firebaseApi"; import { tcApi } from "../../services/tcApi"; +import { setAuthUserIsReady } from "../../slices/auth"; import { setDrawerOpen } from "../../slices/system"; +import Firebase from "../../utils/Firebase"; import { drawerWidth } from "../../utils/const"; import { AppFallback } from "./AppFallback"; @@ -46,9 +49,16 @@ export function AppBar() { const handleLogout = () => { dispatch(firebaseApi.util.resetApiState()); // reset RTKQ dispatch(tcApi.util.resetApiState()); // reset RTKQ - navigate("/login", { - state: { message: "Logged out successfully.", from: null, search: null }, - }); + dispatch(setAuthUserIsReady(false)); + signOut(Firebase.getAuth()) + .then(() => { + navigate("/login", { + state: { message: "Logged out successfully.", from: null, search: null }, + }); + }) + .catch((error) => { + console.error(error); + }); }; return ( diff --git a/web/src/pages/App/AppPage.jsx b/web/src/pages/App/AppPage.jsx index c18e84a8..4cd10622 100644 --- a/web/src/pages/App/AppPage.jsx +++ b/web/src/pages/App/AppPage.jsx @@ -1,5 +1,5 @@ import { Box } from "@mui/material"; -import { onAuthStateChanged } from "firebase/auth"; +import { onAuthStateChanged, signOut } from "firebase/auth"; import React, { useEffect } from "react"; import { ErrorBoundary } from "react-error-boundary"; import { useDispatch, useSelector } from "react-redux"; @@ -25,6 +25,7 @@ export function App() { useEffect(() => { onAuthStateChanged(Firebase.getAuth(), (user) => { if (!user) { + dispatch(setAuthUserIsReady(false)); navigate("/login", { state: { from: location.pathname, diff --git a/web/src/pages/Login/LoginPage.jsx b/web/src/pages/Login/LoginPage.jsx index add55a87..6c58657c 100644 --- a/web/src/pages/Login/LoginPage.jsx +++ b/web/src/pages/Login/LoginPage.jsx @@ -14,6 +14,7 @@ import { TextField, Typography, } from "@mui/material"; +import { signOut } from "firebase/auth"; import React, { useEffect, useState } from "react"; import { useDispatch } from "react-redux"; import { useLocation, useNavigate } from "react-router-dom"; @@ -24,6 +25,7 @@ import { useSignInWithSamlPopupMutation, } from "../../services/firebaseApi"; import { useCreateUserMutation, useTryLoginMutation } from "../../services/tcApi"; +import { setAuthUserIsReady } from "../../slices/auth"; import Firebase from "../../utils/Firebase"; export function Login() { @@ -41,7 +43,9 @@ export function Login() { const [tryLogin] = useTryLoginMutation(); useEffect(() => { + dispatch(setAuthUserIsReady(false)); setMessage(location.state?.message); + signOut(Firebase.getAuth()); }, [dispatch, location]); const callSignInWithEmailAndPassword = async (email, password) => {