From 6111583678e1c51ff1e00660f68eb4d5c3f3c745 Mon Sep 17 00:00:00 2001 From: "makabe.t" Date: Thu, 11 Jan 2024 08:22:31 +0000 Subject: [PATCH] =?UTF-8?q?Merged=20PR=20673:=20=E3=83=AD=E3=82=B0?= =?UTF-8?q?=E3=82=A4=E3=83=B3=E7=94=BB=E9=9D=A2=E3=81=B8=E3=81=AE=E3=83=96?= =?UTF-8?q?=E3=83=A9=E3=82=A6=E3=82=B6=E3=83=90=E3=83=83=E3=82=AF=E6=99=82?= =?UTF-8?q?=E3=81=AE=E3=83=AD=E3=83=BC=E3=83=87=E3=82=A3=E3=83=B3=E3=82=B0?= =?UTF-8?q?=E5=AF=BE=E5=BF=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 概要 [Task3380: ログイン画面へのブラウザバック時のローディング対応](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/3380) - ログイン済み後にブラウザバックした際にローディング画面からログイン後の画面に遷移する処理を追加しました。 - loginPage - AuthPage - TermsPage ## レビューポイント - 対応ページと対応する箇所は適切でしょうか? - 既存のuseEffectの中に処理を追加しています。 ## UIの変更 - なし ## 動作確認状況 - ローカルで確認 --- dictation_client/src/pages/AuthPage/index.tsx | 41 ++++++++++ .../pages/DictationPage/filePropertyPopup.tsx | 2 +- .../src/pages/LoginPage/index.tsx | 81 ++++++++++++------- .../src/pages/TermsPage/index.tsx | 37 +++++++++ 4 files changed, 129 insertions(+), 32 deletions(-) diff --git a/dictation_client/src/pages/AuthPage/index.tsx b/dictation_client/src/pages/AuthPage/index.tsx index a1559bd..a17880d 100644 --- a/dictation_client/src/pages/AuthPage/index.tsx +++ b/dictation_client/src/pages/AuthPage/index.tsx @@ -10,6 +10,14 @@ import { import React, { useEffect } from "react"; import { useDispatch, useSelector } from "react-redux"; import { useNavigate } from "react-router-dom"; +import { + clearToken, + isAdminUser, + isApproveTier, + isStandardUser, + loadAccessToken, +} from "features/auth"; +import { TIERS } from "components/auth/constants"; const AuthPage: React.FC = (): JSX.Element => { const { instance } = useMsal(); @@ -26,6 +34,39 @@ const AuthPage: React.FC = (): JSX.Element => { (async () => { try { + // ログイン済みの場合、ログイン後の遷移先を決定する + if (loadAccessToken()) { + // 第一~第四階層の管理者はライセンス画面へ遷移 + if ( + isApproveTier([ + TIERS.TIER1, + TIERS.TIER2, + TIERS.TIER3, + TIERS.TIER4, + ]) && + isAdminUser() + ) { + navigate("/license"); + return; + } + // 第五階層の管理者はユーザー画面へ遷移 + if (isApproveTier([TIERS.TIER5]) && isAdminUser()) { + navigate("/user"); + return; + } + // 一般ユーザーはdictationPageへ遷移 + if (isStandardUser()) { + navigate("/dictations"); + return; + } + // それ以外は認証エラー画面へ遷移 + instance.logoutRedirect({ + postLogoutRedirectUri: "/AuthError", + }); + clearToken(); + return; + } + const loginResult = await instance.handleRedirectPromise(); // eslint-disable-next-line diff --git a/dictation_client/src/pages/DictationPage/filePropertyPopup.tsx b/dictation_client/src/pages/DictationPage/filePropertyPopup.tsx index 0bcd5ba..1a4104c 100644 --- a/dictation_client/src/pages/DictationPage/filePropertyPopup.tsx +++ b/dictation_client/src/pages/DictationPage/filePropertyPopup.tsx @@ -122,7 +122,7 @@ export const FilePropertyPopup: React.FC = (props) => {
{t(getTranslationID("dictationPage.label.transcriptionist"))}
{selectedFileTask?.typist?.name ?? ""}
- {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions */} + {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */} close {t(getTranslationID("filePropertyPopup.label.close"))} diff --git a/dictation_client/src/pages/LoginPage/index.tsx b/dictation_client/src/pages/LoginPage/index.tsx index e298c40..c335bd3 100644 --- a/dictation_client/src/pages/LoginPage/index.tsx +++ b/dictation_client/src/pages/LoginPage/index.tsx @@ -28,6 +28,33 @@ const LoginPage: React.FC = (): JSX.Element => { selectLocalStorageKeyforIdToken ); + // ログイン後の遷移先を決定する + const navigateToLoginedPage = useCallback(() => { + // 第一~第四階層の管理者はライセンス画面へ遷移 + if ( + isApproveTier([TIERS.TIER1, TIERS.TIER2, TIERS.TIER3, TIERS.TIER4]) && + isAdminUser() + ) { + navigate("/license"); + return; + } + // 第五階層の管理者はユーザー画面へ遷移 + if (isApproveTier([TIERS.TIER5]) && isAdminUser()) { + navigate("/user"); + return; + } + // 一般ユーザーはdictationPageへ遷移 + if (isStandardUser()) { + navigate("/dictations"); + return; + } + // それ以外は認証エラー画面へ遷移 + instance.logoutRedirect({ + postLogoutRedirectUri: "/AuthError", + }); + clearToken(); + }, [instance, navigate]); + const tokenSet = useCallback( async (idToken: string) => { // ログイン処理呼び出し @@ -59,44 +86,36 @@ const LoginPage: React.FC = (): JSX.Element => { document.body.appendChild(a); a.click(); document.body.removeChild(a); - // 第一~第四階層の管理者はライセンス画面へ遷移 - if ( - isApproveTier([TIERS.TIER1, TIERS.TIER2, TIERS.TIER3, TIERS.TIER4]) && - isAdminUser() - ) { - navigate("/license"); - return; - } - // 第五階層の管理者はユーザー画面へ遷移 - if (isApproveTier([TIERS.TIER5]) && isAdminUser()) { - navigate("/user"); - return; - } - // 一般ユーザーはdictationPageへ遷移 - if (isStandardUser()) { - navigate("/dictations"); - return; - } - // それ以外は認証エラー画面へ遷移 - instance.logoutRedirect({ - postLogoutRedirectUri: "/AuthError", - }); - clearToken(); + + // ログイン成功した場合、適切なページに遷移する + navigateToLoginedPage(); } }, - [dispatch, i18n.language, instance, navigate] + [dispatch, i18n.language, instance, navigate, navigateToLoginedPage] ); useEffect(() => { - // AADB2Cのログイン画面とLoginPageを経由していない場合はトップページに遷移する - if (!localStorageKeyforIdToken) { - navigate("/"); - return; - } - + // idTokenStringがあるか⇒認証中 + // accessTokenがある場合⇒ログイン済み + // どちらもなければ直打ち (async () => { - // IDトークンの取得 + if (loadAccessToken()) { + navigateToLoginedPage(); + return; + } + + // AADB2Cのログイン画面とLoginPageを経由していない場合はトップページに遷移する + if (!localStorageKeyforIdToken) { + navigate("/"); + return; + } const idTokenString = localStorage.getItem(localStorageKeyforIdToken); + + if (idTokenString === null) { + navigate("/"); + return; + } + if (idTokenString) { const idTokenObject = JSON.parse(idTokenString); if (isIdToken(idTokenObject)) { diff --git a/dictation_client/src/pages/TermsPage/index.tsx b/dictation_client/src/pages/TermsPage/index.tsx index 974487e..52f2a0b 100644 --- a/dictation_client/src/pages/TermsPage/index.tsx +++ b/dictation_client/src/pages/TermsPage/index.tsx @@ -18,10 +18,19 @@ import { } from "features//terms"; import { selectLocalStorageKeyforIdToken } from "features/login"; import { useNavigate } from "react-router-dom"; +import { + clearToken, + isAdminUser, + isApproveTier, + isStandardUser, + loadAccessToken, +} from "features/auth"; +import { useMsal } from "@azure/msal-react"; const TermsPage: React.FC = (): JSX.Element => { const [t] = useTranslation(); const dispatch: AppDispatch = useDispatch(); + const { instance } = useMsal(); const navigate = useNavigate(); const updateAccceptVersions = useSelector(selectTermVersions); const localStorageKeyforIdToken = useSelector( @@ -40,6 +49,34 @@ const TermsPage: React.FC = (): JSX.Element => { // 画面起動時 useEffect(() => { + // ログイン済みの場合、ログイン後の遷移先を決定する + if (loadAccessToken()) { + // 第一~第四階層の管理者はライセンス画面へ遷移 + if ( + isApproveTier([TIERS.TIER1, TIERS.TIER2, TIERS.TIER3, TIERS.TIER4]) && + isAdminUser() + ) { + navigate("/license"); + return; + } + // 第五階層の管理者はユーザー画面へ遷移 + if (isApproveTier([TIERS.TIER5]) && isAdminUser()) { + navigate("/user"); + return; + } + // 一般ユーザーはdictationPageへ遷移 + if (isStandardUser()) { + navigate("/dictations"); + return; + } + // それ以外は認証エラー画面へ遷移 + instance.logoutRedirect({ + postLogoutRedirectUri: "/AuthError", + }); + clearToken(); + return; + } + dispatch(getTermsInfoAsync()); if (localStorageKeyforIdToken) { dispatch(getAccountInfoMinimalAccessAsync({ localStorageKeyforIdToken }));