// 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 {Checkbox, Form, Modal, Select, Tag, Tooltip, message, theme} from "antd"; import {QuestionCircleTwoTone} from "@ant-design/icons"; import {isMobile as isMobileDevice} from "react-device-detect"; import "./i18n"; import i18next from "i18next"; import copy from "copy-to-clipboard"; import {authConfig} from "./auth/Auth"; import {Helmet} from "react-helmet"; import * as Conf from "./Conf"; import * as phoneNumber from "libphonenumber-js"; import * as path from "path-browserify"; const {Option} = Select; export const ServerUrl = ""; // export const StaticBaseUrl = "https://cdn.jsdelivr.net/gh/casbin/static"; export const StaticBaseUrl = "https://cdn.casbin.org"; export const Countries = [{label: "English", key: "en", country: "US", alt: "English"}, {label: "中文", key: "zh", country: "CN", alt: "中文"}, {label: "Español", key: "es", country: "ES", alt: "Español"}, {label: "Français", key: "fr", country: "FR", alt: "Français"}, {label: "Deutsch", key: "de", country: "DE", alt: "Deutsch"}, {label: "日本語", key: "ja", country: "JP", alt: "日本語"}, {label: "한국어", key: "ko", country: "KR", alt: "한국어"}, {label: "Русский", key: "ru", country: "RU", alt: "Русский"}, {label: "TiếngViệt", key: "vi", country: "VI", alt: "TiếngViệt"}, ]; export function getThemeData(organization, application) { if (application?.themeData?.isEnabled) { return application.themeData; } else if (organization?.themeData?.isEnabled) { return organization.themeData; } else { return Conf.ThemeDefault; } } export function getAlgorithm(themeAlgorithmNames) { return themeAlgorithmNames.map((algorithmName) => { if (algorithmName === "dark") { return theme.darkAlgorithm; } if (algorithmName === "compact") { return theme.compactAlgorithm; } return theme.defaultAlgorithm; }); } export function getAlgorithmNames(themeData) { const algorithms = [themeData?.themeType !== "dark" ? "default" : "dark"]; if (themeData?.isCompact === true) { algorithms.push("compact"); } return algorithms; } export const OtherProviderInfo = { SMS: { "Aliyun SMS": { logo: `${StaticBaseUrl}/img/social_aliyun.png`, url: "https://aliyun.com/product/sms", }, "Tencent Cloud SMS": { logo: `${StaticBaseUrl}/img/social_tencent_cloud.jpg`, url: "https://cloud.tencent.com/product/sms", }, "Volc Engine SMS": { logo: `${StaticBaseUrl}/img/social_volc_engine.jpg`, url: "https://www.volcengine.com/products/cloud-sms", }, "Huawei Cloud SMS": { logo: `${StaticBaseUrl}/img/social_huawei.png`, url: "https://www.huaweicloud.com/product/msgsms.html", }, "Twilio SMS": { logo: `${StaticBaseUrl}/img/social_twilio.svg`, url: "https://www.twilio.com/messaging", }, "SmsBao SMS": { logo: `${StaticBaseUrl}/img/social_smsbao.png`, url: "https://www.smsbao.com/", }, "Mock SMS": { logo: `${StaticBaseUrl}/img/social_default.png`, url: "", }, }, Email: { "Default": { logo: `${StaticBaseUrl}/img/email_default.png`, url: "", }, "SUBMAIL": { logo: `${StaticBaseUrl}/img/social_submail.svg`, url: "https://www.mysubmail.com", }, "Mailtrap": { logo: `${StaticBaseUrl}/img/email_mailtrap.png`, url: "https://mailtrap.io", }, }, Storage: { "Local File System": { logo: `${StaticBaseUrl}/img/social_file.png`, url: "", }, "AWS S3": { logo: `${StaticBaseUrl}/img/social_aws.png`, url: "https://aws.amazon.com/s3", }, "MinIO": { logo: "https://min.io/resources/img/logo.svg", url: "https://min.io/", }, "Aliyun OSS": { logo: `${StaticBaseUrl}/img/social_aliyun.png`, url: "https://aliyun.com/product/oss", }, "Tencent Cloud COS": { logo: `${StaticBaseUrl}/img/social_tencent_cloud.jpg`, url: "https://cloud.tencent.com/product/cos", }, "Azure Blob": { logo: `${StaticBaseUrl}/img/social_azure.png`, url: "https://azure.microsoft.com/en-us/services/storage/blobs/", }, }, SAML: { "Aliyun IDaaS": { logo: `${StaticBaseUrl}/img/social_aliyun.png`, url: "https://aliyun.com/product/idaas", }, "Keycloak": { logo: `${StaticBaseUrl}/img/social_keycloak.png`, url: "https://www.keycloak.org/", }, }, Payment: { "Alipay": { logo: `${StaticBaseUrl}/img/payment_alipay.png`, url: "https://www.alipay.com/", }, "WeChat Pay": { logo: `${StaticBaseUrl}/img/payment_wechat_pay.png`, url: "https://pay.weixin.qq.com/", }, "PayPal": { logo: `${StaticBaseUrl}/img/payment_paypal.png`, url: "https://www.paypal.com/", }, "GC": { logo: `${StaticBaseUrl}/img/payment_gc.png`, url: "https://gc.org", }, }, Captcha: { "Default": { logo: `${StaticBaseUrl}/img/captcha_default.png`, url: "https://pkg.go.dev/github.com/dchest/captcha", }, "reCAPTCHA": { logo: `${StaticBaseUrl}/img/social_recaptcha.png`, url: "https://www.google.com/recaptcha", }, "hCaptcha": { logo: `${StaticBaseUrl}/img/social_hcaptcha.png`, url: "https://www.hcaptcha.com", }, "Aliyun Captcha": { logo: `${StaticBaseUrl}/img/social_aliyun.png`, url: "https://help.aliyun.com/product/28308.html", }, "GEETEST": { logo: `${StaticBaseUrl}/img/social_geetest.png`, url: "https://www.geetest.com", }, "Cloudflare Turnstile": { logo: `${StaticBaseUrl}/img/social_cloudflare.png`, url: "https://www.cloudflare.com/products/turnstile/", }, }, }; export function initCountries() { const countries = require("i18n-iso-countries"); countries.registerLocale(require("i18n-iso-countries/langs/" + getLanguage() + ".json")); return countries; } export function getCountryCode(country) { return phoneNumber.getCountryCallingCode(country); } export function getCountryCodeData(countryCodes = phoneNumber.getCountries()) { return countryCodes?.map((countryCode) => { if (phoneNumber.isSupportedCountry(countryCode)) { const name = initCountries().getName(countryCode, getLanguage()); return { code: countryCode, name: name || "", phone: phoneNumber.getCountryCallingCode(countryCode), }; } }).filter(item => item.name !== "") .sort((a, b) => a.phone - b.phone); } export function getCountryCodeOption(country) { return ( ); } export function getCountryImage(country) { return {country.name}; } export function initServerUrl() { // const hostname = window.location.hostname; // if (hostname === "localhost") { // ServerUrl = `http://${hostname}:8000`; // } } export function isLocalhost() { const hostname = window.location.hostname; return hostname === "localhost"; } export function getFullServerUrl() { let fullServerUrl = window.location.origin; if (fullServerUrl === "http://localhost:7001") { fullServerUrl = "http://localhost:8000"; } return fullServerUrl; } export function isProviderVisible(providerItem) { if (providerItem.provider === undefined || providerItem.provider === null) { return false; } if (providerItem.provider.category !== "OAuth" && providerItem.provider.category !== "SAML") { return false; } if (providerItem.provider.type === "WeChatMiniProgram") { return false; } return true; } export function isResponseDenied(data) { if (data.msg === "Unauthorized operation" || data.msg === "未授权的操作") { return true; } return false; } export function isProviderVisibleForSignUp(providerItem) { if (providerItem.canSignUp === false) { return false; } return isProviderVisible(providerItem); } export function isProviderVisibleForSignIn(providerItem) { if (providerItem.canSignIn === false) { return false; } return isProviderVisible(providerItem); } export function isProviderPrompted(providerItem) { return isProviderVisible(providerItem) && providerItem.prompted; } export function isSignupItemPrompted(signupItem) { return signupItem.visible && signupItem.prompted; } export function getAllPromptedProviderItems(application) { return application.providers.filter(providerItem => isProviderPrompted(providerItem)); } export function getAllPromptedSignupItems(application) { return application.signupItems.filter(signupItem => isSignupItemPrompted(signupItem)); } export function getSignupItem(application, itemName) { const signupItems = application.signupItems?.filter(signupItem => signupItem.name === itemName); if (signupItems.length === 0) { return null; } return signupItems[0]; } export function isValidPersonName(personName) { return personName !== ""; // // https://blog.css8.cn/post/14210975.html // const personNameRegex = /^[\u4e00-\u9fa5]{2,6}$/; // return personNameRegex.test(personName); } export function isValidIdCard(idCard) { return idCard !== ""; // const idCardRegex = /^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9X]$/; // return idCardRegex.test(idCard); } export function isValidEmail(email) { // https://github.com/yiminghe/async-validator/blob/057b0b047f88fac65457bae691d6cb7c6fe48ce1/src/rule/type.ts#L9 const emailRegex = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; return emailRegex.test(email); } export function isValidPhone(phone, countryCode = "") { if (countryCode !== "") { return phoneNumber.isValidPhoneNumber(phone, countryCode); } // // https://learnku.com/articles/31543, `^s*$` filter empty email individually. const phoneRegex = /[0-9]{4,15}$/; return phoneRegex.test(phone); } export function isValidInvoiceTitle(invoiceTitle) { return invoiceTitle !== ""; // if (invoiceTitle === "") { // return false; // } // // // https://blog.css8.cn/post/14210975.html // const invoiceTitleRegex = /^[()()\u4e00-\u9fa5]{0,50}$/; // return invoiceTitleRegex.test(invoiceTitle); } export function isValidTaxId(taxId) { return taxId !== ""; // // https://www.codetd.com/article/8592083 // const regArr = [/^[\da-z]{10,15}$/i, /^\d{6}[\da-z]{10,12}$/i, /^[a-z]\d{6}[\da-z]{9,11}$/i, /^[a-z]{2}\d{6}[\da-z]{8,10}$/i, /^\d{14}[\dx][\da-z]{4,5}$/i, /^\d{17}[\dx][\da-z]{1,2}$/i, /^[a-z]\d{14}[\dx][\da-z]{3,4}$/i, /^[a-z]\d{17}[\dx][\da-z]{0,1}$/i, /^[\d]{6}[\da-z]{13,14}$/i]; // for (let i = 0; i < regArr.length; i++) { // if (regArr[i].test(taxId)) { // return true; // } // } // return false; } export function isAffiliationPrompted(application) { const signupItem = getSignupItem(application, "Affiliation"); if (signupItem === null) { return false; } return signupItem.prompted; } export function hasPromptPage(application) { const providerItems = getAllPromptedProviderItems(application); if (providerItems.length !== 0) { return true; } const signupItems = getAllPromptedSignupItems(application); if (signupItems.length !== 0) { return true; } return isAffiliationPrompted(application); } function isAffiliationAnswered(user, application) { if (!isAffiliationPrompted(application)) { return true; } if (user === null) { return false; } return user.affiliation !== ""; } function isProviderItemAnswered(user, application, providerItem) { if (user === null) { return false; } const provider = providerItem.provider; const linkedValue = user[provider.type.toLowerCase()]; return linkedValue !== undefined && linkedValue !== ""; } function isSignupItemAnswered(user, signupItem) { if (user === null) { return false; } if (signupItem.name !== "Country/Region") { return true; } const value = user["region"]; return value !== undefined && value !== ""; } export function isPromptAnswered(user, application) { if (!isAffiliationAnswered(user, application)) { return false; } const providerItems = getAllPromptedProviderItems(application); for (let i = 0; i < providerItems.length; i++) { if (!isProviderItemAnswered(user, application, providerItems[i])) { return false; } } const signupItems = getAllPromptedSignupItems(application); for (let i = 0; i < signupItems.length; i++) { if (!isSignupItemAnswered(user, signupItems[i])) { return false; } } return true; } export function parseObject(s) { try { return eval("(" + s + ")"); } catch (e) { return null; } } export function parseJson(s) { if (s === "") { return null; } else { return JSON.parse(s); } } export function myParseInt(i) { const res = parseInt(i); return isNaN(res) ? 0 : res; } export function openLink(link) { // this.props.history.push(link); const w = window.open("about:blank"); w.location.href = link; } export function openLinkSafe(link) { // Javascript window.open issue in safari // https://stackoverflow.com/questions/45569893/javascript-window-open-issue-in-safari const a = document.createElement("a"); a.href = link; a.setAttribute("target", "_blank"); a.click(); } export function goToLink(link) { window.location.href = link; } export function goToLinkSoft(ths, link) { if (link.startsWith("http")) { openLink(link); return; } ths.props.history.push(link); } export function showMessage(type, text) { if (type === "success") { message.success(text); } else if (type === "error") { message.error(text); } else if (type === "info") { message.info(text); } } export function isAdminUser(account) { if (account === undefined || account === null) { return false; } return account.owner === "built-in" || account.isGlobalAdmin === true; } export function isLocalAdminUser(account) { if (account === undefined || account === null) { return false; } return account.isAdmin === true || isAdminUser(account); } export function deepCopy(obj) { return Object.assign({}, obj); } export function addRow(array, row, position = "end") { return position === "end" ? [...array, row] : [row, ...array]; } export function prependRow(array, row) { return [row, ...array]; } export function deleteRow(array, i) { // return array = array.slice(0, i).concat(array.slice(i + 1)); return [...array.slice(0, i), ...array.slice(i + 1)]; } export function swapRow(array, i, j) { return [...array.slice(0, i), array[j], ...array.slice(i + 1, j), array[i], ...array.slice(j + 1)]; } export function trim(str, ch) { if (str === undefined) { return undefined; } let start = 0; let end = str.length; while (start < end && str[start] === ch) {++start;} while (end > start && str[end - 1] === ch) {--end;} return (start > 0 || end < str.length) ? str.substring(start, end) : str; } export function isMobile() { // return getIsMobileView(); return isMobileDevice; } export function getTermsOfUseContent(url, setTermsOfUseContent) { fetch(url, { method: "GET", }).then(r => { r.text().then(setTermsOfUseContent); }); } export function isAgreementRequired(application) { if (application) { const agreementItem = application.signupItems.find(item => item.name === "Agreement"); if (!agreementItem || agreementItem.rule === "None" || !agreementItem.rule) { return false; } if (agreementItem.required) { return true; } } return false; } export function isDefaultTrue(application) { const agreementItem = application.signupItems.find(item => item.name === "Agreement"); return isAgreementRequired(application) && agreementItem.rule === "Signin (Default True)"; } export function renderAgreement(required, onClick, noStyle, layout, initialValue) { return ( {i18next.t("signup:Accept")}  {i18next.t("signup:Terms of Use")} ); } export function renderModal(isOpen, onOk, onCancel, doc) { return (