// 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, 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 {Controlled as CodeMirror} from "react-codemirror2"; import "codemirror/lib/codemirror.css"; require("codemirror/theme/material-darker.css"); require("codemirror/mode/htmlmixed/htmlmixed"); require("codemirror/mode/xml/xml"); require("codemirror/mode/css/css"); const {Option} = Select; const {TextArea} = Input; 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 || {}; 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; this.setState({ provider: provider, }); } updateUserMappingField(key, value) { const provider = this.state.provider; 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") { 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") { 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") { 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 { 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"); } } 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); } 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.type === "Custom" ? ( { this.state.provider.category === "OAuth" ? ( {Setting.getLabel(i18next.t("provider:Auth URL"), i18next.t("provider:Auth URL - Tooltip"))} { this.updateProviderField("customAuthUrl", e.target.value); }} /> {Setting.getLabel(i18next.t("provider:Token URL"), i18next.t("provider:Token URL - Tooltip"))} { this.updateProviderField("customTokenUrl", e.target.value); }} /> {Setting.getLabel(i18next.t("provider:Scope"), i18next.t("provider:Scope - Tooltip"))} { this.updateProviderField("scopes", e.target.value); }} /> {Setting.getLabel(i18next.t("provider:UserInfo URL"), i18next.t("provider:UserInfo URL - Tooltip"))} { this.updateProviderField("customUserInfoUrl", e.target.value); }} /> ) : null } {Setting.getLabel(i18next.t("provider:User mapping"), i18next.t("provider:User mapping - Tooltip"))} : {this.renderUserMappingInput()} {Setting.getLabel(i18next.t("general:Favicon"), i18next.t("general:Favicon - Tooltip"))} : {Setting.getLabel(i18next.t("general:URL"), i18next.t("general:URL - Tooltip"))} : } value={this.state.provider.customLogo} onChange={e => { this.updateProviderField("customLogo", e.target.value); }} /> {i18next.t("general:Preview")}: {this.state.provider.customLogo} ) : null } { (this.state.provider.category === "Captcha" && this.state.provider.type === "Default") || (this.state.provider.category === "Web3") || (this.state.provider.category === "Storage" && this.state.provider.type === "Local File System") || (this.state.provider.category === "SMS" && this.state.provider.type === "Custom HTTP SMS") || (this.state.provider.category === "Notification" && (this.state.provider.type === "Google Chat" || this.state.provider.type === "Custom HTTP")) ? null : ( { (this.state.provider.category === "Storage" && this.state.provider.type === "Google Cloud Storage") || (this.state.provider.category === "Email" && this.state.provider.type === "Azure ACS") || (this.state.provider.category === "Notification" && (this.state.provider.type === "Line" || this.state.provider.type === "Telegram" || this.state.provider.type === "Bark" || this.state.provider.type === "Discord" || this.state.provider.type === "Slack" || this.state.provider.type === "Pushbullet" || this.state.provider.type === "Pushover" || this.state.provider.type === "Lark" || this.state.provider.type === "Microsoft Teams")) ? null : ( {this.getClientIdLabel(this.state.provider)} : { this.updateProviderField("clientId", e.target.value); }} /> ) } {this.getClientSecretLabel(this.state.provider)} : { this.updateProviderField("clientSecret", e.target.value); }} /> ) } { this.state.provider.category !== "Email" && this.state.provider.type !== "WeChat" && this.state.provider.type !== "Apple" && this.state.provider.type !== "Aliyun Captcha" && this.state.provider.type !== "WeChat Pay" && this.state.provider.type !== "Twitter" && this.state.provider.type !== "Reddit" ? null : ( {this.getClientId2Label(this.state.provider)} : { this.updateProviderField("clientId2", e.target.value); }} /> { (this.state.provider.type === "WeChat Pay") || (this.state.provider.category === "Email" && this.state.provider.type === "Azure ACS") ? null : ( {this.getClientSecret2Label(this.state.provider)} : { this.updateProviderField("clientSecret2", e.target.value); }} /> ) } ) } { this.state.provider.type !== "WeChat" ? null : ( {Setting.getLabel(i18next.t("token:Access token"), i18next.t("token:Access token - Tooltip"))} : { this.updateProviderField("content", e.target.value); }} /> {Setting.getLabel(i18next.t("provider:Enable QR code"), i18next.t("provider:Enable QR code - Tooltip"))} : { this.updateProviderField("disableSsl", checked); }} /> ) } { this.state.provider.type !== "ADFS" && this.state.provider.type !== "AzureAD" && this.state.provider.type !== "AzureADB2C" && this.state.provider.type !== "Casdoor" && this.state.provider.type !== "Okta" ? null : ( {Setting.getLabel(i18next.t("provider:Domain"), i18next.t("provider:Domain - Tooltip"))} : } value={this.state.provider.domain} onChange={e => { this.updateProviderField("domain", e.target.value); }} /> ) } {this.state.provider.category === "Storage" || ["Custom HTTP SMS", "Custom HTTP Email"].includes(this.state.provider.type) ? (
{["Local File System"].includes(this.state.provider.type) ? null : ( {Setting.getLabel(i18next.t("provider:Endpoint"), i18next.t("provider:Region endpoint for Internet"))} : } value={this.state.provider.endpoint} onChange={e => { this.updateProviderField("endpoint", e.target.value); }} /> )} {["Custom HTTP SMS", "Local File System", "MinIO", "Tencent Cloud COS", "Google Cloud Storage", "Qiniu Cloud Kodo", "Synology"].includes(this.state.provider.type) ? null : ( {Setting.getLabel(i18next.t("provider:Endpoint (Intranet)"), i18next.t("provider:Region endpoint for Intranet"))} : } value={this.state.provider.intranetEndpoint} onChange={e => { this.updateProviderField("intranetEndpoint", e.target.value); }} /> )} {["Custom HTTP SMS", "Local File System"].includes(this.state.provider.type) ? null : ( {Setting.getLabel(i18next.t("provider:Bucket"), i18next.t("provider:Bucket - Tooltip"))} : { this.updateProviderField("bucket", e.target.value); }} /> )} {["Custom HTTP SMS"].includes(this.state.provider.type) ? null : ( {Setting.getLabel(i18next.t("provider:Path prefix"), i18next.t("provider:Path prefix - Tooltip"))} : { this.updateProviderField("pathPrefix", e.target.value); }} /> )} {["Custom HTTP SMS", "MinIO", "Google Cloud Storage", "Qiniu Cloud Kodo", "Synology"].includes(this.state.provider.type) ? null : ( {Setting.getLabel(i18next.t("provider:Domain"), i18next.t("provider:Domain - Tooltip"))} : } value={this.state.provider.domain} disabled={this.state.provider.type === "Local File System"} onChange={e => { this.updateProviderField("domain", e.target.value); }} /> )} {["AWS S3", "Tencent Cloud COS", "Qiniu Cloud Kodo"].includes(this.state.provider.type) ? ( {Setting.getLabel(i18next.t("provider:Region ID"), i18next.t("provider:Region ID - Tooltip"))} : { this.updateProviderField("regionId", e.target.value); }} /> ) : null}
) : null} {this.getAppIdRow(this.state.provider)} { this.state.provider.category === "Notification" ? ( {["Custom HTTP"].includes(this.state.provider.type) ? ( {Setting.getLabel(i18next.t("general:Method"), i18next.t("provider:Method - Tooltip"))} : ) : null} {["Custom HTTP"].includes(this.state.provider.type) ? ( {Setting.getLabel(i18next.t("provider:Parameter"), i18next.t("provider:Parameter - Tooltip"))} : { this.updateProviderField("title", e.target.value); }} /> ) : null} {["Google Chat"].includes(this.state.provider.type) ? ( {Setting.getLabel(i18next.t("provider:Metadata"), i18next.t("provider:Metadata - Tooltip"))} :