// Copyright 2023 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 from "react"; import {Button, Col, Result, Row, Steps} from "antd"; import {withRouter} from "react-router-dom"; import * as ApplicationBackend from "../backend/ApplicationBackend"; import * as Setting from "../Setting"; import i18next from "i18next"; import * as MfaBackend from "../backend/MfaBackend"; import {CheckOutlined, KeyOutlined, UserOutlined} from "@ant-design/icons"; import CheckPasswordForm from "./mfa/CheckPasswordForm"; import MfaEnableForm from "./mfa/MfaEnableForm"; import {MfaVerifyForm} from "./mfa/MfaVerifyForm"; export const EmailMfaType = "email"; export const SmsMfaType = "sms"; export const TotpMfaType = "app"; export const RecoveryMfaType = "recovery"; class MfaSetupPage extends React.Component { constructor(props) { super(props); const params = new URLSearchParams(props.location.search); const {location} = this.props; this.state = { account: props.account, application: null, applicationName: props.account.signupApplication ?? "", current: location.state?.from !== undefined ? 1 : 0, mfaProps: null, mfaType: params.get("mfaType") ?? SmsMfaType, isPromptPage: props.isPromptPage || location.state?.from !== undefined, }; } componentDidMount() { this.getApplication(); if (this.state.current === 1) { this.initMfaProps(); } } componentDidUpdate(prevProps, prevState, snapshot) { if (this.state.mfaType !== prevState.mfaType || this.state.current !== prevState.current) { if (this.state.current === 1) { this.initMfaProps(); } } } getApplication() { ApplicationBackend.getApplication("admin", this.state.applicationName) .then((res) => { if (res !== null) { if (res.status === "error") { Setting.showMessage("error", res.msg); return; } this.setState({ application: res, }); } else { Setting.showMessage("error", i18next.t("mfa:Failed to get application")); } }); } initMfaProps() { MfaBackend.MfaSetupInitiate({ mfaType: this.state.mfaType, ...this.getUser(), }).then((res) => { if (res.status === "ok") { this.setState({ mfaProps: res.data, }); } else { Setting.showMessage("error", i18next.t("mfa:Failed to initiate MFA")); } }); } getUser() { return this.props.account; } renderMfaTypeSwitch() { const renderSmsLink = () => { if (this.state.mfaType === SmsMfaType || this.props.account.mfaPhoneEnabled) { return null; } return ( ); }; const renderEmailLink = () => { if (this.state.mfaType === EmailMfaType || this.props.account.mfaEmailEnabled) { return null; } return ( ); }; const renderTotpLink = () => { if (this.state.mfaType === TotpMfaType || this.props.account.totpSecret !== "") { return null; } return ( ); }; return !this.state.isPromptPage ? ( {renderSmsLink()} {renderEmailLink()} {renderTotpLink()} ) : null; } renderStep() { switch (this.state.current) { case 0: return ( { this.setState({ current: this.state.current + 1, }); }} onFail={(res) => { Setting.showMessage("error", i18next.t("mfa:Failed to initiate MFA") + ": " + res.msg); }} /> ); case 1: return (
{ this.setState({ current: this.state.current + 1, }); }} onFail={(res) => { Setting.showMessage("error", i18next.t("general:Failed to verify") + ": " + res.msg); }} /> {this.renderMfaTypeSwitch()}
); case 2: return ( { Setting.showMessage("success", i18next.t("general:Enabled successfully")); this.props.onfinish(); if (localStorage.getItem("mfaRedirectUrl") !== null) { Setting.goToLink(localStorage.getItem("mfaRedirectUrl")); localStorage.removeItem("mfaRedirectUrl"); } else { this.props.history.push("/account"); } }} onFail={(res) => { Setting.showMessage("error", `${i18next.t("general:Failed to enable")}: ${res.msg}`); }} /> ); default: return null; } } render() { if (!this.props.account) { return ( } /> ); } return (

{i18next.t("mfa:Protect your account with Multi-factor authentication")}

{i18next.t("mfa:Each time you sign in to your Account, you'll need your password and a authentication code")}

}, {title: i18next.t("mfa:Verify Code"), icon: }, {title: i18next.t("general:Enable"), icon: }, ]} style={{width: "90%", maxWidth: "500px", margin: "auto", marginTop: "50px", }} >
{this.renderStep()}
); } } export default withRouter(MfaSetupPage);