// Copyright 2021 The Casdoor Authors. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. import React, {Component, Suspense, lazy} from "react"; import "./App.less"; import {Helmet} from "react-helmet"; import * as Setting from "./Setting"; import {setIsTourVisible, setTourLogo} from "./TourConfig"; import {StyleProvider, legacyLogicalPropertiesTransformer} from "@ant-design/cssinjs"; import {GithubOutlined, InfoCircleFilled, ShareAltOutlined} from "@ant-design/icons"; import {Alert, Button, ConfigProvider, Drawer, FloatButton, Layout, Result, Tooltip} from "antd"; import {Route, Switch, withRouter} from "react-router-dom"; import CustomGithubCorner from "./common/CustomGithubCorner"; import * as Conf from "./Conf"; import * as Auth from "./auth/Auth"; import EntryPage from "./EntryPage"; import * as AuthBackend from "./auth/AuthBackend"; import AuthCallback from "./auth/AuthCallback"; import SamlCallback from "./auth/SamlCallback"; import i18next from "i18next"; import {withTranslation} from "react-i18next"; const ManagementPage = lazy(() => import("./ManagementPage")); const {Footer, Content} = Layout; import {setTwoToneColor} from "@ant-design/icons"; import * as ApplicationBackend from "./backend/ApplicationBackend"; setTwoToneColor("rgb(87,52,211)"); class App extends Component { constructor(props) { super(props); this.setThemeAlgorithm(); let storageThemeAlgorithm = []; try { storageThemeAlgorithm = localStorage.getItem("themeAlgorithm") ? JSON.parse(localStorage.getItem("themeAlgorithm")) : ["default"]; } catch { storageThemeAlgorithm = ["default"]; } this.state = { classes: props, selectedMenuKey: 0, account: undefined, accessToken: undefined, uri: null, themeAlgorithm: storageThemeAlgorithm, themeData: Conf.ThemeDefault, logo: this.getLogo(storageThemeAlgorithm), requiredEnableMfa: false, isAiAssistantOpen: false, application: undefined, }; Setting.initServerUrl(); Auth.initAuthWithConfig({ serverUrl: Setting.ServerUrl, appName: Conf.DefaultApplication, // the application used in Casdoor root path: "/" }); } UNSAFE_componentWillMount() { this.updateMenuKey(); this.getAccount(); this.getApplication(); } componentDidUpdate(prevProps, prevState, snapshot) { const uri = location.pathname; if (this.state.uri !== uri) { this.updateMenuKey(); } if (this.state.account !== prevState.account) { const requiredEnableMfa = Setting.isRequiredEnableMfa(this.state.account, this.state.account?.organization); this.setState({ requiredEnableMfa: requiredEnableMfa, }); if (requiredEnableMfa === true) { const mfaType = Setting.getMfaItemsByRules(this.state.account, this.state.account?.organization, [Setting.MfaRuleRequired]) .find((item) => item.rule === Setting.MfaRuleRequired)?.name; if (mfaType !== undefined) { this.props.history.push(`/mfa/setup?mfaType=${mfaType}`, {from: "/login"}); } } } } updateMenuKey() { const uri = location.pathname; this.setState({ uri: uri, }); if (uri === "/" || uri.includes("/shortcuts") || uri.includes("/apps")) { this.setState({selectedMenuKey: "/home"}); } else if (uri.includes("/organizations") || uri.includes("/trees") || uri.includes("/groups") || uri.includes("/users") || uri.includes("/invitations")) { this.setState({selectedMenuKey: "/orgs"}); } else if (uri.includes("/applications") || uri.includes("/providers") || uri.includes("/resources") || uri.includes("/certs")) { this.setState({selectedMenuKey: "/identity"}); } else if (uri.includes("/roles") || uri.includes("/permissions") || uri.includes("/models") || uri.includes("/adapters") || uri.includes("/enforcers")) { this.setState({selectedMenuKey: "/auth"}); } else if (uri.includes("/records") || uri.includes("/tokens") || uri.includes("/sessions")) { this.setState({selectedMenuKey: "/logs"}); } else if (uri.includes("/products") || uri.includes("/payments") || uri.includes("/plans") || uri.includes("/pricings") || uri.includes("/subscriptions")) { this.setState({selectedMenuKey: "/business"}); } else if (uri.includes("/sysinfo") || uri.includes("/syncers") || uri.includes("/webhooks")) { this.setState({selectedMenuKey: "/admin"}); } else if (uri.includes("/signup")) { this.setState({selectedMenuKey: "/signup"}); } else if (uri.includes("/login")) { this.setState({selectedMenuKey: "/login"}); } else if (uri.includes("/result")) { this.setState({selectedMenuKey: "/result"}); } else { this.setState({selectedMenuKey: -1}); } } getAccessTokenParam(params) { // "/page?access_token=123" const accessToken = params.get("access_token"); return accessToken === null ? "" : `?accessToken=${accessToken}`; } getCredentialParams(params) { // "/page?username=abc&password=123" if (params.get("username") === null || params.get("password") === null) { return ""; } return `?username=${params.get("username")}&password=${params.get("password")}`; } getUrlWithoutQuery() { return window.location.toString().replace(window.location.search, ""); } getLanguageParam(params) { // "/page?language=en" const language = params.get("language"); if (language !== null) { Setting.setLanguage(language); return `language=${language}`; } return ""; } getLogo(themes) { return Setting.getLogo(themes); } setThemeAlgorithm() { const currentUrl = window.location.href; const url = new URL(currentUrl); const themeType = url.searchParams.get("theme"); if (themeType === "dark" || themeType === "default") { localStorage.setItem("themeAlgorithm", JSON.stringify([themeType])); } } setLanguage(account) { const language = account?.language; if (language !== null && language !== "" && language !== i18next.language) { Setting.setLanguage(language); } } setTheme = (theme, initThemeAlgorithm) => { this.setState({ themeData: theme, }); if (initThemeAlgorithm) { if (localStorage.getItem("themeAlgorithm")) { let storageThemeAlgorithm = []; try { storageThemeAlgorithm = JSON.parse(localStorage.getItem("themeAlgorithm")); } catch { storageThemeAlgorithm = ["default"]; } this.setState({ logo: this.getLogo(storageThemeAlgorithm), themeAlgorithm: storageThemeAlgorithm, }); return; } this.setState({ logo: this.getLogo(Setting.getAlgorithmNames(theme)), themeAlgorithm: Setting.getAlgorithmNames(theme), }); } }; getApplication() { const applicationName = localStorage.getItem("applicationName"); if (!applicationName) { return; } ApplicationBackend.getApplication("admin", applicationName) .then((res) => { if (res.status === "error") { Setting.showMessage("error", res.msg); return; } this.setState({ application: res.data, }); }); } getAccount() { const params = new URLSearchParams(this.props.location.search); let query = this.getAccessTokenParam(params); if (query === "") { query = this.getCredentialParams(params); } const query2 = this.getLanguageParam(params); if (query2 !== "") { const url = window.location.toString().replace(new RegExp(`[?&]${query2}`), ""); window.history.replaceState({}, document.title, url); } if (query !== "") { window.history.replaceState({}, document.title, this.getUrlWithoutQuery()); } AuthBackend.getAccount(query) .then((res) => { let account = null; let accessToken = null; if (res.status === "ok") { account = res.data; account.organization = res.data2; accessToken = res.data.accessToken; this.setLanguage(account); this.setTheme(Setting.getThemeData(account.organization), Conf.InitThemeAlgorithm); setTourLogo(account.organization.logo); setIsTourVisible(account.organization.enableTour); } else { if (res.data !== "Please login first") { Setting.showMessage("error", `${i18next.t("application:Failed to sign in")}: ${res.msg}`); } } this.setState({ account: account, accessToken: accessToken, }); }); } onUpdateAccount(account) { this.setState({ account: account, }); } renderFooter() { return ( {!this.state.account ? null :
} {!this.state.account ? null :
}
{ this.state.application?.footerHtml && this.state.application.footerHtml !== "" ?
: ( Conf.CustomFooter !== null ? Conf.CustomFooter : ( Powered by {"Casdoor"} ) ) }
); } renderAiAssistant() { return ( help AI Assistant } placement="right" width={500} mask={false} onClose={() => { this.setState({ isAiAssistantOpen: false, }); }} visible={this.state.isAiAssistantOpen} >