// 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 from "react";
import {Link} from "react-router-dom";
import {Button, Checkbox, Col, Form, Input, Result, Row, Spin, Tabs} from "antd";
import {LockOutlined, UserOutlined} from "@ant-design/icons";
import * as UserWebauthnBackend from "../backend/UserWebauthnBackend";
import * as AuthBackend from "./AuthBackend";
import * as ApplicationBackend from "../backend/ApplicationBackend";
import * as Provider from "./Provider";
import * as Util from "./Util";
import * as Setting from "../Setting";
import SelfLoginButton from "./SelfLoginButton";
import {GithubLoginButton, GoogleLoginButton} from "react-social-login-buttons";
import FacebookLoginButton from "./FacebookLoginButton";
import QqLoginButton from "./QqLoginButton";
import DingTalkLoginButton from "./DingTalkLoginButton";
import GiteeLoginButton from "./GiteeLoginButton";
import WechatLoginButton from "./WechatLoginButton";
import WeiboLoginButton from "./WeiboLoginButton";
import i18next from "i18next";
import LinkedInLoginButton from "./LinkedInLoginButton";
import WeComLoginButton from "./WeComLoginButton";
import LarkLoginButton from "./LarkLoginButton";
import GitLabLoginButton from "./GitLabLoginButton";
import AdfsLoginButton from "./AdfsLoginButton";
import BaiduLoginButton from "./BaiduLoginButton";
import AlipayLoginButton from "./AlipayLoginButton";
import CasdoorLoginButton from "./CasdoorLoginButton";
import InfoflowLoginButton from "./InfoflowLoginButton";
import AppleLoginButton from "./AppleLoginButton";
import AzureADLoginButton from "./AzureADLoginButton";
import SlackLoginButton from "./SlackLoginButton";
import SteamLoginButton from "./SteamLoginButton";
import OktaLoginButton from "./OktaLoginButton";
import DouyinLoginButton from "./DouyinLoginButton";
import CustomGithubCorner from "../CustomGithubCorner";
import {CountDownInput} from "../common/CountDownInput";
import BilibiliLoginButton from "./BilibiliLoginButton";
const {TabPane} = Tabs;
class LoginPage extends React.Component {
constructor(props) {
super(props);
this.state = {
classes: props,
type: props.type,
applicationName: props.applicationName !== undefined ? props.applicationName : (props.match === undefined ? null : props.match.params.applicationName),
owner : props.owner !== undefined ? props.owner : (props.match === undefined ? null : props.match.params.owner),
application: null,
mode: props.mode !== undefined ? props.mode : (props.match === undefined ? null : props.match.params.mode), // "signup" or "signin"
isCodeSignin: false,
msg: null,
username: null,
validEmailOrPhone: false,
validEmail: false,
validPhone: false,
loginMethod: "password"
};
if (this.state.type === "cas" && props.match?.params.casApplicationName !== undefined) {
this.state.owner = props.match?.params.owner;
this.state.applicationName = props.match?.params.casApplicationName;
}
}
UNSAFE_componentWillMount() {
if (this.state.type === "login" || this.state.type === "cas") {
this.getApplication();
} else if (this.state.type === "code") {
this.getApplicationLogin();
} else if (this.state.type === "saml") {
this.getSamlApplication();
} else {
Util.showMessage("error", `Unknown authentication type: ${this.state.type}`);
}
}
getApplicationLogin() {
const oAuthParams = Util.getOAuthGetParameters();
AuthBackend.getApplicationLogin(oAuthParams)
.then((res) => {
if (res.status === "ok") {
this.setState({
application: res.data,
});
} else {
// Util.showMessage("error", res.msg);
this.setState({
application: res.data,
msg: res.msg,
});
}
});
}
getApplication() {
if (this.state.applicationName === null) {
return;
}
ApplicationBackend.getApplication("admin", this.state.applicationName)
.then((application) => {
this.setState({
application: application,
});
});
}
getSamlApplication() {
if (this.state.applicationName === null) {
return;
}
ApplicationBackend.getApplication(this.state.owner, this.state.applicationName)
.then((application) => {
this.setState({
application: application,
});
}
);
}
getApplicationObj() {
if (this.props.application !== undefined) {
return this.props.application;
} else {
return this.state.application;
}
}
onUpdateAccount(account) {
this.props.onUpdateAccount(account);
}
onFinish(values) {
const application = this.getApplicationObj();
const ths = this;
// here we are supposed to determine whether Casdoor is working as an OAuth server or CAS server
if (this.state.type === "cas") {
// CAS
const casParams = Util.getCasParameters();
values["type"] = this.state.type;
AuthBackend.loginCas(values, casParams).then((res) => {
if (res.status === "ok") {
let msg = "Logged in successfully. ";
if (casParams.service === "") {
// If service was not specified, Casdoor must display a message notifying the client that it has successfully initiated a single sign-on session.
msg += "Now you can visit apps protected by Casdoor.";
}
Util.showMessage("success", msg);
if (casParams.service !== "") {
let st = res.data;
let newUrl = new URL(casParams.service);
newUrl.searchParams.append("ticket", st);
window.location.href = newUrl.toString();
}
} else {
Util.showMessage("error", `Failed to log in: ${res.msg}`);
}
});
} else {
// OAuth
const oAuthParams = Util.getOAuthGetParameters();
if (oAuthParams !== null && oAuthParams.responseType != null && oAuthParams.responseType !== "") {
values["type"] = oAuthParams.responseType;
} else {
values["type"] = this.state.type;
}
values["phonePrefix"] = this.getApplicationObj()?.organizationObj.phonePrefix;
if (oAuthParams !== null) {
values["samlRequest"] = oAuthParams.samlRequest;
}
if (values["samlRequest"] != null && values["samlRequest"] !== "") {
values["type"] = "saml";
}
if (this.state.owner != null) {
values["organization"] = this.state.owner;
}
AuthBackend.login(values, oAuthParams)
.then((res) => {
if (res.status === "ok") {
const responseType = values["type"];
if (responseType === "login") {
Util.showMessage("success", "Logged in successfully");
const link = Setting.getFromLink();
Setting.goToLink(link);
} else if (responseType === "code") {
const code = res.data;
const concatChar = oAuthParams?.redirectUri?.includes("?") ? "&" : "?";
const noRedirect = oAuthParams.noRedirect;
if (Setting.hasPromptPage(application)) {
AuthBackend.getAccount("")
.then((res) => {
let account = null;
if (res.status === "ok") {
account = res.data;
account.organization = res.data2;
this.onUpdateAccount(account);
if (Setting.isPromptAnswered(account, application)) {
Setting.goToLink(`${oAuthParams.redirectUri}${concatChar}code=${code}&state=${oAuthParams.state}`);
} else {
Setting.goToLinkSoft(ths, `/prompt/${application.name}?redirectUri=${oAuthParams.redirectUri}&code=${code}&state=${oAuthParams.state}`);
}
} else {
Setting.showMessage("error", `Failed to sign in: ${res.msg}`);
}
});
} else {
if (noRedirect === "true") {
window.close();
const newWindow = window.open(`${oAuthParams.redirectUri}${concatChar}code=${code}&state=${oAuthParams.state}`);
if (newWindow) {
setInterval(() => {
if (!newWindow.closed) {
newWindow.close();
}
}, 1000);
}
} else {
Setting.goToLink(`${oAuthParams.redirectUri}${concatChar}code=${code}&state=${oAuthParams.state}`);
}
}
// Util.showMessage("success", `Authorization code: ${res.data}`);
} else if (responseType === "token" || responseType === "id_token") {
const accessToken = res.data;
Setting.goToLink(`${oAuthParams.redirectUri}#${responseType}=${accessToken}?state=${oAuthParams.state}&token_type=bearer`);
} else if (responseType === "saml") {
const SAMLResponse = res.data;
const redirectUri = res.data2;
Setting.goToLink(`${redirectUri}?SAMLResponse=${encodeURIComponent(SAMLResponse)}&RelayState=${oAuthParams.relayState}`);
}
} else {
Util.showMessage("error", `Failed to log in: ${res.msg}`);
}
});
}
}
getSigninButton(type) {
const text = i18next.t("login:Sign in with {type}").replace("{type}", type);
if (type === "GitHub") {
return
);
} else if (provider.category === "SAML") {
return (
);
}
} else {
return (