// 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 {Button, Card, Checkbox, Col, Input, InputNumber, Radio, Row, Select, Switch} from "antd"; import {LinkOutlined} from "@ant-design/icons"; import * as ProviderBackend from "./backend/ProviderBackend"; import * as OrganizationBackend from "./backend/OrganizationBackend"; import * as CertBackend from "./backend/CertBackend"; import * as Setting from "./Setting"; import i18next from "i18next"; import {authConfig} from "./auth/Auth"; import * as ProviderEditTestEmail from "./common/TestEmailWidget"; import * as ProviderNotification from "./common/TestNotificationWidget"; import * as ProviderEditTestSms from "./common/TestSmsWidget"; import copy from "copy-to-clipboard"; import {CaptchaPreview} from "./common/CaptchaPreview"; import {CountryCodeSelect} from "./common/select/CountryCodeSelect"; import * as Web3Auth from "./auth/Web3Auth"; import Editor from "./common/Editor"; const {Option} = Select; const {TextArea} = Input; const defaultUserMapping = { id: "id", username: "username", displayName: "displayName", email: "email", avatarUrl: "avatarUrl", }; class ProviderEditPage extends React.Component { constructor(props) { super(props); this.state = { classes: props, providerName: props.match.params.providerName, owner: props.organizationName !== undefined ? props.organizationName : props.match.params.organizationName, provider: null, certs: [], organizations: [], mode: props.location.mode !== undefined ? props.location.mode : "edit", }; } UNSAFE_componentWillMount() { this.getOrganizations(); this.getProvider(); this.getCerts(this.state.owner); } getProvider() { ProviderBackend.getProvider(this.state.owner, this.state.providerName) .then((res) => { if (res.data === null) { this.props.history.push("/404"); return; } if (res.status === "ok") { const provider = res.data; provider.userMapping = provider.userMapping || defaultUserMapping; this.setState({ provider: provider, }); } else { Setting.showMessage("error", res.msg); } }); } getOrganizations() { if (Setting.isAdminUser(this.props.account)) { OrganizationBackend.getOrganizations("admin") .then((res) => { this.setState({ organizations: res.data || [], }); }); } } getCerts(owner) { CertBackend.getCerts(owner) .then((res) => { if (res.status === "ok") { this.setState({ certs: res.data || [], }); } }); } parseProviderField(key, value) { if (["port"].includes(key)) { value = Setting.myParseInt(value); } return value; } updateProviderField(key, value) { value = this.parseProviderField(key, value); const provider = this.state.provider; if (key === "owner" && provider["owner"] !== value) { // the provider change the owner, reset the cert provider["cert"] = ""; this.getCerts(value); } provider[key] = value; if (provider["type"] === "WeChat") { if (!provider["clientId"]) { provider["signName"] = "media"; provider["disableSsl"] = true; } if (!provider["clientId2"]) { provider["signName"] = "open"; provider["disableSsl"] = false; } if (!provider["disableSsl"]) { provider["signName"] = "open"; } } this.setState({ provider: provider, }); } updateUserMappingField(key, value) { const requiredKeys = ["id", "username", "displayName"]; const provider = this.state.provider; if (value === "" && requiredKeys.includes(key)) { Setting.showMessage("error", i18next.t("provider:This field is required")); return; } provider.userMapping[key] = value; this.setState({ provider: provider, }); } renderUserMappingInput() { return ( {Setting.getLabel(i18next.t("general:ID"), i18next.t("general:ID - Tooltip"))} : { this.updateUserMappingField("id", e.target.value); }} /> {Setting.getLabel(i18next.t("signup:Username"), i18next.t("signup:Username - Tooltip"))} : { this.updateUserMappingField("username", e.target.value); }} /> {Setting.getLabel(i18next.t("general:Display name"), i18next.t("general:Display name - Tooltip"))} : { this.updateUserMappingField("displayName", e.target.value); }} /> {Setting.getLabel(i18next.t("general:Email"), i18next.t("general:Email - Tooltip"))} : { this.updateUserMappingField("email", e.target.value); }} /> {Setting.getLabel(i18next.t("general:Avatar"), i18next.t("general:Avatar - Tooltip"))} : { this.updateUserMappingField("avatarUrl", e.target.value); }} /> ); } getClientIdLabel(provider) { switch (provider.category) { case "OAuth": if (provider.type === "Apple") { return Setting.getLabel(i18next.t("provider:Service ID identifier"), i18next.t("provider:Service ID identifier - Tooltip")); } else { return Setting.getLabel(i18next.t("provider:Client ID"), i18next.t("provider:Client ID - Tooltip")); } case "Email": return Setting.getLabel(i18next.t("signup:Username"), i18next.t("signup:Username - Tooltip")); case "SMS": if (provider.type === "Volc Engine SMS" || provider.type === "Amazon SNS" || provider.type === "Baidu Cloud SMS") { return Setting.getLabel(i18next.t("provider:Access key"), i18next.t("provider:Access key - Tooltip")); } else if (provider.type === "Huawei Cloud SMS") { return Setting.getLabel(i18next.t("provider:App key"), i18next.t("provider:App key - Tooltip")); } else if (provider.type === "UCloud SMS") { return Setting.getLabel(i18next.t("provider:Public key"), i18next.t("provider:Public key - Tooltip")); } else if (provider.type === "Msg91 SMS" || provider.type === "Infobip SMS" || provider.type === "OSON SMS") { return Setting.getLabel(i18next.t("provider:Sender Id"), i18next.t("provider:Sender Id - Tooltip")); } else { return Setting.getLabel(i18next.t("provider:Client ID"), i18next.t("provider:Client ID - Tooltip")); } case "Captcha": if (provider.type === "Aliyun Captcha") { return Setting.getLabel(i18next.t("provider:Access key"), i18next.t("provider:Access key - Tooltip")); } else { return Setting.getLabel(i18next.t("provider:Site key"), i18next.t("provider:Site key - Tooltip")); } case "Notification": if (provider.type === "DingTalk") { return Setting.getLabel(i18next.t("provider:Access key"), i18next.t("provider:Access key - Tooltip")); } else { return Setting.getLabel(i18next.t("provider:Client ID"), i18next.t("provider:Client ID - Tooltip")); } default: return Setting.getLabel(i18next.t("provider:Client ID"), i18next.t("provider:Client ID - Tooltip")); } } getClientSecretLabel(provider) { switch (provider.category) { case "OAuth": if (provider.type === "Apple") { return Setting.getLabel(i18next.t("provider:Team ID"), i18next.t("provider:Team ID - Tooltip")); } else { return Setting.getLabel(i18next.t("provider:Client secret"), i18next.t("provider:Client secret - Tooltip")); } case "Storage": if (provider.type === "Google Cloud Storage") { return Setting.getLabel(i18next.t("provider:Service account JSON"), i18next.t("provider:Service account JSON - Tooltip")); } else { return Setting.getLabel(i18next.t("provider:Client secret"), i18next.t("provider:Client secret - Tooltip")); } case "Email": if (provider.type === "Azure ACS" || provider.type === "SendGrid") { return Setting.getLabel(i18next.t("provider:Secret key"), i18next.t("provider:Secret key - Tooltip")); } else { return Setting.getLabel(i18next.t("general:Password"), i18next.t("general:Password - Tooltip")); } case "SMS": if (provider.type === "Volc Engine SMS" || provider.type === "Amazon SNS" || provider.type === "Baidu Cloud SMS" || provider.type === "OSON SMS") { return Setting.getLabel(i18next.t("provider:Secret access key"), i18next.t("provider:Secret access key - Tooltip")); } else if (provider.type === "Huawei Cloud SMS") { return Setting.getLabel(i18next.t("provider:App secret"), i18next.t("provider:AppSecret - Tooltip")); } else if (provider.type === "UCloud SMS") { return Setting.getLabel(i18next.t("provider:Private Key"), i18next.t("provider:Private Key - Tooltip")); } else if (provider.type === "Msg91 SMS") { return Setting.getLabel(i18next.t("provider:Auth Key"), i18next.t("provider:Auth Key - Tooltip")); } else if (provider.type === "Infobip SMS") { return Setting.getLabel(i18next.t("provider:Api Key"), i18next.t("provider:Api Key - Tooltip")); } else { return Setting.getLabel(i18next.t("provider:Client secret"), i18next.t("provider:Client secret - Tooltip")); } case "Captcha": if (provider.type === "Aliyun Captcha") { return Setting.getLabel(i18next.t("provider:Secret access key"), i18next.t("provider:Secret access key - Tooltip")); } else { return Setting.getLabel(i18next.t("provider:Secret key"), i18next.t("provider:Secret key - Tooltip")); } case "Notification": if (provider.type === "Line" || provider.type === "Telegram" || provider.type === "Bark" || provider.type === "DingTalk" || provider.type === "Discord" || provider.type === "Slack" || provider.type === "Pushover" || provider.type === "Pushbullet") { return Setting.getLabel(i18next.t("provider:Secret key"), i18next.t("provider:Secret key - Tooltip")); } else if (provider.type === "Lark" || provider.type === "Microsoft Teams") { return Setting.getLabel(i18next.t("provider:Endpoint"), i18next.t("provider:Endpoint - Tooltip")); } else { return Setting.getLabel(i18next.t("provider:Client secret"), i18next.t("provider:Client secret - Tooltip")); } default: return Setting.getLabel(i18next.t("provider:Client secret"), i18next.t("provider:Client secret - Tooltip")); } } getClientId2Label(provider) { switch (provider.category) { case "OAuth": if (provider.type === "Apple") { return Setting.getLabel(i18next.t("provider:Key ID"), i18next.t("provider:Key ID - Tooltip")); } else { return Setting.getLabel(i18next.t("provider:Client ID 2"), i18next.t("provider:Client ID 2 - Tooltip")); } case "Email": return Setting.getLabel(i18next.t("provider:From address"), i18next.t("provider:From address - Tooltip")); default: if (provider.type === "Aliyun Captcha") { return Setting.getLabel(i18next.t("provider:Scene"), i18next.t("provider:Scene - Tooltip")); } else if (provider.type === "WeChat Pay") { return Setting.getLabel(i18next.t("provider:App ID"), i18next.t("provider:App ID - Tooltip")); } else if (provider.type === "CUCloud") { return Setting.getLabel(i18next.t("provider:Account ID"), i18next.t("provider:Account ID - Tooltip")); } else { return Setting.getLabel(i18next.t("provider:Client ID 2"), i18next.t("provider:Client ID 2 - Tooltip")); } } } getClientSecret2Label(provider) { switch (provider.category) { case "OAuth": if (provider.type === "Apple") { return Setting.getLabel(i18next.t("provider:Key text"), i18next.t("provider:Key text - Tooltip")); } else { return Setting.getLabel(i18next.t("provider:Client secret 2"), i18next.t("provider:Client secret 2 - Tooltip")); } case "Email": return Setting.getLabel(i18next.t("provider:From name"), i18next.t("provider:From name - Tooltip")); default: if (provider.type === "Aliyun Captcha") { return Setting.getLabel(i18next.t("provider:App key"), i18next.t("provider:App key - Tooltip")); } else { return Setting.getLabel(i18next.t("provider:Client secret 2"), i18next.t("provider:Client secret 2 - Tooltip")); } } } getProviderSubTypeOptions(type) { if (type === "WeCom" || type === "Infoflow") { return ( [ {id: "Internal", name: i18next.t("provider:Internal")}, {id: "Third-party", name: i18next.t("provider:Third-party")}, ] ); } else if (type === "Aliyun Captcha") { return [ {id: "nc", name: i18next.t("provider:Sliding Validation")}, {id: "ic", name: i18next.t("provider:Intelligent Validation")}, ]; } else { return []; } } getAppIdRow(provider) { let text = ""; let tooltip = ""; if (provider.category === "OAuth") { if (provider.type === "WeCom" && provider.subType === "Internal") { text = i18next.t("provider:Agent ID"); tooltip = i18next.t("provider:Agent ID - Tooltip"); } else if (provider.type === "Infoflow") { text = i18next.t("provider:Agent ID"); tooltip = i18next.t("provider:Agent ID - Tooltip"); } else if (provider.type === "AzureADB2C") { text = i18next.t("provider:User flow"); tooltip = i18next.t("provider:User flow - Tooltip"); } } else if (provider.category === "SMS") { if (provider.type === "Twilio SMS" || provider.type === "Azure ACS") { text = i18next.t("provider:Sender number"); tooltip = i18next.t("provider:Sender number - Tooltip"); } else if (provider.type === "Tencent Cloud SMS") { text = i18next.t("provider:App ID"); tooltip = i18next.t("provider:App ID - Tooltip"); } else if (provider.type === "Volc Engine SMS") { text = i18next.t("provider:SMS account"); tooltip = i18next.t("provider:SMS account - Tooltip"); } else if (provider.type === "Huawei Cloud SMS") { text = i18next.t("provider:Channel No."); tooltip = i18next.t("provider:Channel No. - Tooltip"); } else if (provider.type === "Amazon SNS") { text = i18next.t("provider:Region"); tooltip = i18next.t("provider:Region - Tooltip"); } else if (provider.type === "Baidu Cloud SMS") { text = i18next.t("provider:Endpoint"); tooltip = i18next.t("provider:Endpoint - Tooltip"); } else if (provider.type === "Infobip SMS") { text = i18next.t("provider:Base URL"); tooltip = i18next.t("provider:Base URL - Tooltip"); } else if (provider.type === "UCloud SMS") { text = i18next.t("provider:Project Id"); tooltip = i18next.t("provider:Project Id - Tooltip"); } } else if (provider.category === "Email") { if (provider.type === "SUBMAIL") { text = i18next.t("provider:App ID"); tooltip = i18next.t("provider:App ID - Tooltip"); } } else if (provider.category === "Notification") { if (provider.type === "Viber") { text = i18next.t("provider:Domain"); tooltip = i18next.t("provider:Domain - Tooltip"); } else if (provider.type === "Line" || provider.type === "Matrix" || provider.type === "Rocket Chat") { text = i18next.t("provider:App Key"); tooltip = i18next.t("provider:App Key - Tooltip"); } else if (provider.type === "CUCloud") { text = i18next.t("provider:Topic name"); tooltip = i18next.t("provider:Topic name - Tooltip"); } } if (text === "" && tooltip === "") { return null; } else { return ( {Setting.getLabel(text, tooltip)} : { this.updateProviderField("appId", e.target.value); }} /> ); } } getReceiverRow(provider) { let text = ""; let tooltip = ""; if (provider.type === "Telegram" || provider.type === "Pushover" || provider.type === "Pushbullet" || provider.type === "Slack" || provider.type === "Discord" || provider.type === "Line" || provider.type === "Twitter" || provider.type === "Reddit" || provider.type === "Rocket Chat" || provider.type === "Viber") { text = i18next.t("provider:Chat ID"); tooltip = i18next.t("provider:Chat ID - Tooltip"); } else if (provider.type === "Custom HTTP" || provider.type === "Webpush" || provider.type === "Matrix") { text = i18next.t("provider:Endpoint"); tooltip = i18next.t("provider:Endpoint - Tooltip"); } if (text === "" && tooltip === "") { return ( {Setting.getLabel("Test Notification", "Test Notification")} : ); } else { return ( {Setting.getLabel(text, tooltip)} : { this.updateProviderField("receiver", e.target.value); }} /> ); } } loadSamlConfiguration() { const parser = new DOMParser(); const rawXml = this.state.provider.metadata.replace("\n", ""); const xmlDoc = parser.parseFromString(rawXml, "text/xml"); const cert = xmlDoc.querySelector("X509Certificate").childNodes[0].nodeValue.replace(" ", ""); const endpoint = xmlDoc.querySelector("SingleSignOnService").getAttribute("Location"); const issuerUrl = xmlDoc.querySelector("EntityDescriptor").getAttribute("entityID"); this.updateProviderField("idP", cert); this.updateProviderField("endpoint", endpoint); this.updateProviderField("issuerUrl", issuerUrl); } fetchSamlMetadata() { this.setState({ metadataLoading: true, }); fetch(this.state.requestUrl, { method: "GET", }).then(res => { if (!res.ok) { return Promise.reject("error"); } return res.text(); }).then(text => { this.updateProviderField("metadata", text); this.parseSamlMetadata(); Setting.showMessage("success", i18next.t("general:Successfully added")); }).catch(err => { Setting.showMessage("error", err.message); }).finally(() => { this.setState({ metadataLoading: false, }); }); } parseSamlMetadata() { try { this.loadSamlConfiguration(); Setting.showMessage("success", i18next.t("provider:Parse metadata successfully")); } catch (err) { Setting.showMessage("error", i18next.t("provider:Can not parse metadata")); } } renderProvider() { return ( {this.state.mode === "add" ? i18next.t("provider:New Provider") : i18next.t("provider:Edit Provider")}     {this.state.mode === "add" ? : null} } style={(Setting.isMobile()) ? {margin: "5px"} : {}} type="inner"> {Setting.getLabel(i18next.t("general:Name"), i18next.t("general:Name - Tooltip"))} : { this.updateProviderField("name", e.target.value); }} /> {Setting.getLabel(i18next.t("general:Display name"), i18next.t("general:Display name - Tooltip"))} : { this.updateProviderField("displayName", e.target.value); }} /> {Setting.getLabel(i18next.t("general:Organization"), i18next.t("general:Organization - Tooltip"))} : {Setting.getLabel(i18next.t("provider:Category"), i18next.t("provider:Category - Tooltip"))} : {Setting.getLabel(i18next.t("provider:Type"), i18next.t("provider:Type - Tooltip"))} : { this.state.provider.type !== "WeCom" && this.state.provider.type !== "Infoflow" && this.state.provider.type !== "Aliyun Captcha" ? null : ( {Setting.getLabel(i18next.t("provider:Sub type"), i18next.t("provider:Sub type - Tooltip"))} : { this.state.provider.type !== "WeCom" ? null : ( {Setting.getLabel(i18next.t("general:Method"), i18next.t("provider:Method - Tooltip"))} : ) } ) } { this.state.provider.category === "OAuth" ? ( {Setting.getLabel(i18next.t("provider:Email regex"), i18next.t("provider:Email regex - Tooltip"))} :