import { useMsal } from "@azure/msal-react"; import { AppDispatch } from "app/store"; import { isIdToken } from "common/token"; import { clearToken, isAdminUser, isApproveTier, isStandardUser, loadAccessToken, loadRefreshToken, } from "features/auth"; import { loginAsync, selectLocalStorageKeyforIdToken } from "features/login"; import React, { useCallback, useEffect } from "react"; import Footer from "components/footer"; import Header from "components/header"; import { useTranslation } from "react-i18next"; import { useDispatch, useSelector } from "react-redux"; import { useNavigate } from "react-router-dom"; import { isErrorObject } from "common/errors"; import { TIERS } from "components/auth/constants"; const LoginPage: React.FC = (): JSX.Element => { const { instance } = useMsal(); const dispatch: AppDispatch = useDispatch(); const navigate = useNavigate(); const [, i18n] = useTranslation(); const localStorageKeyforIdToken = useSelector( 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) => { // ログイン処理呼び出し const { meta, payload } = await dispatch(loginAsync({ idToken })); // ログイン失敗した場合、B2Cをログアウトしてからエラーページに遷移する if (meta.requestStatus === "rejected") { if (isErrorObject(payload)) { // 未同意の規約がある場合は利用規約同意画面に遷移する if (payload.error.code === "E010209") { navigate("/terms"); return; } } instance.logoutRedirect({ postLogoutRedirectUri: "/AuthError", }); } if (meta.requestStatus === "fulfilled") { const accessToken = loadAccessToken(); const refreshToken = loadRefreshToken(); const url = `${ import.meta.env.VITE_DESK_TOP_APP_SCHEME }:login?accessToken=${accessToken}&refreshToken=${refreshToken}&language=${ i18n.language }`; // カスタムURLスキーム const a = document.createElement("a"); a.href = url; document.body.appendChild(a); a.click(); document.body.removeChild(a); // ログイン成功した場合、適切なページに遷移する navigateToLoginedPage(); } }, [dispatch, i18n.language, instance, navigate, navigateToLoginedPage] ); useEffect(() => { // idTokenStringがあるか⇒認証中 // accessTokenがある場合⇒ログイン済み // どちらもなければ直打ち (async () => { 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)) { await tokenSet(idTokenObject.secret); } } })(); // 画面描画後のみ実行するため引数を設定しない // eslint-disable-next-line react-hooks/exhaustive-deps }, []); return ( <>

loading ...