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 (
<>