Merge branch 'develop' into ccb

This commit is contained in:
x.yumoto.k 2024-02-09 17:37:38 +09:00
commit cd277f3f9a
8 changed files with 53 additions and 79 deletions

View File

@ -1,8 +1,6 @@
import AppRouter from "AppRouter";
import { BrowserRouter } from "react-router-dom";
import { PublicClientApplication } from "@azure/msal-browser";
import { MsalProvider, useMsal } from "@azure/msal-react";
import { msalConfig } from "common/msalConfig";
import { useMsal } from "@azure/msal-react";
import { useEffect, useLayoutEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import globalAxios, { AxiosError, AxiosResponse } from "axios";
@ -19,7 +17,6 @@ const App = (): JSX.Element => {
const { instance } = useMsal();
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const [t, i18n] = useTranslation();
const pca = new PublicClientApplication(msalConfig);
useEffect(() => {
const id = globalAxios.interceptors.response.use(
(response: AxiosResponse) => response,
@ -70,11 +67,9 @@ const App = (): JSX.Element => {
dispatch(closeSnackbar());
}}
/>
<MsalProvider instance={pca}>
<BrowserRouter>
<AppRouter />
</BrowserRouter>
</MsalProvider>
<BrowserRouter>
<AppRouter />
</BrowserRouter>
</>
);
};

View File

@ -76,3 +76,16 @@ export const getIdTokenFromLocalStorage = (
}
return null;
};
// JWTが有効期限切れかどうかを判定する
export const isTokenExpired = (token: string | null): boolean => {
if (token == null) {
return true;
}
const tokenObject = JSON.parse(atob(token.split(".")[1]));
if (isToken(tokenObject)) {
const now = Math.floor(Date.now() / 1000);
return tokenObject.exp < now;
}
return true;
};

View File

@ -3,18 +3,25 @@ import React from "react";
import { createRoot } from "react-dom/client";
import { I18nextProvider } from "react-i18next";
import { Provider } from "react-redux";
import { PublicClientApplication } from "@azure/msal-browser";
import { msalConfig } from "common/msalConfig";
import { MsalProvider } from "@azure/msal-react";
import App from "./App";
import * as serviceWorker from "./serviceWorker";
import i18n from "./i18n";
const pca = new PublicClientApplication(msalConfig);
const container = document.getElementById("root");
if (container) {
const root = createRoot(container);
root.render(
<React.StrictMode>
<Provider store={store}>
<I18nextProvider i18n={i18n} />
<App />
<MsalProvider instance={pca}>
<I18nextProvider i18n={i18n} />
<App />
</MsalProvider>
</Provider>
</React.StrictMode>
);

View File

@ -10,14 +10,6 @@ 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();
@ -34,38 +26,7 @@ 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;
}
// idTokenが有効セットされているかを確認する
const loginResult = await instance.handleRedirectPromise();
if (loginResult && loginResult.account) {
const { homeAccountId, idTokenClaims } = loginResult.account;

View File

@ -1,8 +1,10 @@
import React from "react";
import { Link } from "react-router-dom";
export const AuthErrorPage = (): JSX.Element => (
<div>
<p></p>
<p>login failed</p>
<br />
<Link to="/">return to TopPage</Link>
</div>
);

View File

@ -1,6 +1,6 @@
import { useMsal } from "@azure/msal-react";
import { AppDispatch } from "app/store";
import { isIdToken } from "common/token";
import { isIdToken, isTokenExpired } from "common/token";
import {
clearToken,
isAdminUser,
@ -52,10 +52,10 @@ const LoginPage: React.FC = (): JSX.Element => {
instance.logoutRedirect({
postLogoutRedirectUri: "/AuthError",
});
clearToken();
}, [instance, navigate]);
dispatch(clearToken());
}, [instance, navigate, dispatch]);
const tokenSet = useCallback(
const tokenSetAndNavigate = useCallback(
async (idToken: string) => {
// ログイン処理呼び出し
const { meta, payload } = await dispatch(loginAsync({ idToken }));
@ -96,31 +96,32 @@ const LoginPage: React.FC = (): JSX.Element => {
useEffect(() => {
// idTokenStringがあるか⇒認証中
// accessTokenがある場合⇒ログイン済み
// どちらもなければ直打ち
// accessTokenがある場合⇒ログイン済みなのにブラウザバックでログイン画面に戻ってきた場合
// どちらもなければURL直打ち
(async () => {
if (loadAccessToken()) {
navigateToLoginedPage();
return;
// ローカルストレージにidTokenがある場合は取得する
let idTokenString: string | null = null;
if (localStorageKeyforIdToken !== null) {
idTokenString = localStorage.getItem(localStorageKeyforIdToken);
}
// AADB2Cのログイン画面とLoginPageを経由していない場合はトップページに遷移する
if (!localStorageKeyforIdToken) {
navigate("/");
return;
}
const idTokenString = localStorage.getItem(localStorageKeyforIdToken);
// idTokenがない(=正常なログインプロセス中でない)場合は有効なアクセストークンを所持しているか確認し、
// 有効であればログイン画面に遷移 or 無効であればトップページに遷移
if (idTokenString === null) {
navigate("/");
const token = loadAccessToken();
// アクセストークンがない or 有効期限切れ場合はトップページに遷移
if (isTokenExpired(token)) {
navigate("/");
} else {
// 有効なアクセストークンがある場合はログイン画面に遷移
navigateToLoginedPage();
}
return;
}
if (idTokenString) {
const idTokenObject = JSON.parse(idTokenString);
if (isIdToken(idTokenObject)) {
await tokenSet(idTokenObject.secret);
}
const idTokenObject = JSON.parse(idTokenString);
if (isIdToken(idTokenObject)) {
await tokenSetAndNavigate(idTokenObject.secret);
}
})();
// 画面描画後のみ実行するため引数を設定しない

View File

@ -40,9 +40,6 @@ export class User {
@Column({ default: true })
auto_renew: boolean;
@Column({ default: true })
license_alert: boolean;
@Column({ default: true })
notification: boolean;

View File

@ -48,7 +48,6 @@ export const makeTestUser = async (
accepted_dpa_version: d?.accepted_dpa_version ?? "1.0",
email_verified: d?.email_verified ?? true,
auto_renew: d?.auto_renew ?? true,
license_alert: d?.license_alert ?? true,
notification: d?.notification ?? true,
encryption: d?.encryption ?? true,
encryption_password: d?.encryption_password,
@ -117,7 +116,6 @@ export const makeTestAccount = async (
accepted_dpa_version: d?.accepted_dpa_version ?? "1.0",
email_verified: d?.email_verified ?? true,
auto_renew: d?.auto_renew ?? true,
license_alert: d?.license_alert ?? true,
notification: d?.notification ?? true,
encryption: d?.encryption ?? true,
encryption_password: d?.encryption_password ?? "password",