2022-02-13 23:39:27 +08:00
|
|
|
|
// Copyright 2021 The Casdoor Authors. All Rights Reserved.
|
2021-02-13 12:15:19 +08:00
|
|
|
|
//
|
|
|
|
|
// 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.
|
|
|
|
|
|
2022-10-27 20:23:57 +02:00
|
|
|
|
import React from "react";
|
2022-11-13 05:16:49 +01:00
|
|
|
|
import {Link} from "react-router-dom";
|
2025-01-27 19:37:26 +08:00
|
|
|
|
import {Button, Select, Tag, Tooltip, message, theme} from "antd";
|
2021-06-25 00:13:43 +08:00
|
|
|
|
import {QuestionCircleTwoTone} from "@ant-design/icons";
|
2021-02-13 12:15:19 +08:00
|
|
|
|
import {isMobile as isMobileDevice} from "react-device-detect";
|
2021-02-19 23:23:59 +08:00
|
|
|
|
import "./i18n";
|
|
|
|
|
import i18next from "i18next";
|
2021-03-14 23:08:08 +08:00
|
|
|
|
import copy from "copy-to-clipboard";
|
2021-04-28 22:40:21 +08:00
|
|
|
|
import {authConfig} from "./auth/Auth";
|
2021-04-29 21:28:24 +08:00
|
|
|
|
import {Helmet} from "react-helmet";
|
2022-03-27 16:03:25 +08:00
|
|
|
|
import * as Conf from "./Conf";
|
2023-02-16 22:53:28 +08:00
|
|
|
|
import * as phoneNumber from "libphonenumber-js";
|
2023-05-23 15:09:53 +08:00
|
|
|
|
import moment from "moment";
|
2025-01-27 19:37:26 +08:00
|
|
|
|
import {MfaAuthVerifyForm, NextMfa, RequiredMfa} from "./auth/mfa/MfaAuthVerifyForm";
|
|
|
|
|
import {EmailMfaType, SmsMfaType, TotpMfaType} from "./auth/MfaSetupPage";
|
2021-02-13 12:15:19 +08:00
|
|
|
|
|
2023-02-25 15:25:47 +08:00
|
|
|
|
const {Option} = Select;
|
|
|
|
|
|
2022-08-08 23:35:24 +08:00
|
|
|
|
export const ServerUrl = "";
|
2021-02-13 12:15:19 +08:00
|
|
|
|
|
2021-06-12 12:07:24 +08:00
|
|
|
|
export const StaticBaseUrl = "https://cdn.casbin.org";
|
2021-06-12 11:52:59 +08:00
|
|
|
|
|
2023-09-02 18:49:43 +08:00
|
|
|
|
export const Countries = [
|
|
|
|
|
{label: "English", key: "en", country: "US", alt: "English"},
|
2023-02-16 22:53:28 +08:00
|
|
|
|
{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"},
|
2023-07-07 00:13:05 +08:00
|
|
|
|
{label: "中文", key: "zh", country: "CN", alt: "中文"},
|
2023-03-19 21:47:49 +08:00
|
|
|
|
{label: "Indonesia", key: "id", country: "ID", alt: "Indonesia"},
|
2023-02-16 22:53:28 +08:00
|
|
|
|
{label: "日本語", key: "ja", country: "JP", alt: "日本語"},
|
|
|
|
|
{label: "한국어", key: "ko", country: "KR", alt: "한국어"},
|
|
|
|
|
{label: "Русский", key: "ru", country: "RU", alt: "Русский"},
|
2023-04-15 14:16:49 +08:00
|
|
|
|
{label: "TiếngViệt", key: "vi", country: "VN", alt: "TiếngViệt"},
|
2023-09-02 18:11:52 +08:00
|
|
|
|
{label: "Português", key: "pt", country: "PT", alt: "Português"},
|
|
|
|
|
{label: "Italiano", key: "it", country: "IT", alt: "Italiano"},
|
|
|
|
|
{label: "Malay", key: "ms", country: "MY", alt: "Malay"},
|
|
|
|
|
{label: "Türkçe", key: "tr", country: "TR", alt: "Türkçe"},
|
|
|
|
|
{label: "لغة عربية", key: "ar", country: "SA", alt: "لغة عربية"},
|
2023-08-16 15:54:34 +08:00
|
|
|
|
{label: "עִבְרִית", key: "he", country: "IL", alt: "עִבְרִית"},
|
2023-09-02 18:49:43 +08:00
|
|
|
|
{label: "Nederlands", key: "nl", country: "NL", alt: "Nederlands"},
|
|
|
|
|
{label: "Polski", key: "pl", country: "PL", alt: "Polski"},
|
|
|
|
|
{label: "Suomi", key: "fi", country: "FI", alt: "Suomi"},
|
|
|
|
|
{label: "Svenska", key: "sv", country: "SE", alt: "Svenska"},
|
|
|
|
|
{label: "Українська", key: "uk", country: "UA", alt: "Українська"},
|
|
|
|
|
{label: "Қазақ", key: "kk", country: "KZ", alt: "Қазақ"},
|
|
|
|
|
{label: "فارسی", key: "fa", country: "IR", alt: "فارسی"},
|
2024-08-02 03:39:47 +02:00
|
|
|
|
{label: "Čeština", key: "cs", country: "CZ", alt: "Čeština"},
|
|
|
|
|
{label: "Slovenčina", key: "sk", country: "SK", alt: "Slovenčina"},
|
2023-02-16 22:53:28 +08:00
|
|
|
|
];
|
|
|
|
|
|
2023-02-01 22:06:40 +08:00
|
|
|
|
export function getThemeData(organization, application) {
|
|
|
|
|
if (application?.themeData?.isEnabled) {
|
|
|
|
|
return application.themeData;
|
|
|
|
|
} else if (organization?.themeData?.isEnabled) {
|
|
|
|
|
return organization.themeData;
|
|
|
|
|
} else {
|
2023-02-12 18:56:56 +08:00
|
|
|
|
return Conf.ThemeDefault;
|
2023-02-01 22:06:40 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function getAlgorithm(themeAlgorithmNames) {
|
2024-02-24 16:56:12 +08:00
|
|
|
|
return themeAlgorithmNames.sort().reverse().map((algorithmName) => {
|
2023-02-01 22:06:40 +08:00
|
|
|
|
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;
|
|
|
|
|
}
|
2022-12-29 15:30:37 +01:00
|
|
|
|
|
2024-03-13 23:33:43 +08:00
|
|
|
|
export function getLogo(themes) {
|
|
|
|
|
if (themes.includes("dark")) {
|
|
|
|
|
return `${StaticBaseUrl}/img/casdoor-logo_1185x256_dark.png`;
|
|
|
|
|
} else {
|
|
|
|
|
return `${StaticBaseUrl}/img/casdoor-logo_1185x256.png`;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-21 21:52:34 +08:00
|
|
|
|
export const OtherProviderInfo = {
|
|
|
|
|
SMS: {
|
|
|
|
|
"Aliyun SMS": {
|
|
|
|
|
logo: `${StaticBaseUrl}/img/social_aliyun.png`,
|
|
|
|
|
url: "https://aliyun.com/product/sms",
|
|
|
|
|
},
|
2023-08-07 00:59:17 +08:00
|
|
|
|
"Amazon SNS": {
|
|
|
|
|
logo: `${StaticBaseUrl}/img/social_aws.png`,
|
|
|
|
|
url: "https://aws.amazon.com/cn/sns/",
|
|
|
|
|
},
|
|
|
|
|
"Azure ACS": {
|
|
|
|
|
logo: `${StaticBaseUrl}/img/social_azure.png`,
|
|
|
|
|
url: "https://azure.microsoft.com/en-us/products/communication-services",
|
|
|
|
|
},
|
|
|
|
|
"Infobip SMS": {
|
|
|
|
|
logo: `${StaticBaseUrl}/img/social_infobip.png`,
|
|
|
|
|
url: "https://portal.infobip.com/homepage/",
|
|
|
|
|
},
|
2022-04-21 21:52:34 +08:00
|
|
|
|
"Tencent Cloud SMS": {
|
|
|
|
|
logo: `${StaticBaseUrl}/img/social_tencent_cloud.jpg`,
|
|
|
|
|
url: "https://cloud.tencent.com/product/sms",
|
|
|
|
|
},
|
2023-08-07 00:59:17 +08:00
|
|
|
|
"Baidu Cloud SMS": {
|
|
|
|
|
logo: `${StaticBaseUrl}/img/social_baidu_cloud.png`,
|
|
|
|
|
url: "https://cloud.baidu.com/product/sms.html",
|
|
|
|
|
},
|
2022-04-21 21:52:34 +08:00
|
|
|
|
"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",
|
|
|
|
|
},
|
2023-08-07 00:59:17 +08:00
|
|
|
|
"UCloud SMS": {
|
|
|
|
|
logo: `${StaticBaseUrl}/img/social_ucloud.png`,
|
|
|
|
|
url: "https://www.ucloud.cn/site/product/usms.html",
|
|
|
|
|
},
|
2022-09-25 17:58:12 +08:00
|
|
|
|
"Twilio SMS": {
|
2023-02-25 15:08:08 +08:00
|
|
|
|
logo: `${StaticBaseUrl}/img/social_twilio.svg`,
|
2022-09-25 17:58:12 +08:00
|
|
|
|
url: "https://www.twilio.com/messaging",
|
|
|
|
|
},
|
2022-09-27 08:37:55 +08:00
|
|
|
|
"SmsBao SMS": {
|
|
|
|
|
logo: `${StaticBaseUrl}/img/social_smsbao.png`,
|
|
|
|
|
url: "https://www.smsbao.com/",
|
|
|
|
|
},
|
2023-03-06 21:23:45 +08:00
|
|
|
|
"SUBMAIL SMS": {
|
|
|
|
|
logo: `${StaticBaseUrl}/img/social_submail.svg`,
|
|
|
|
|
url: "https://www.mysubmail.com",
|
|
|
|
|
},
|
2023-08-07 00:59:17 +08:00
|
|
|
|
"Msg91 SMS": {
|
|
|
|
|
logo: `${StaticBaseUrl}/img/social_msg91.ico`,
|
|
|
|
|
url: "https://control.msg91.com/app/",
|
|
|
|
|
},
|
2024-03-03 22:05:53 +05:00
|
|
|
|
"OSON SMS": {
|
|
|
|
|
logo: "https://osonsms.com/images/osonsms-logo.svg",
|
|
|
|
|
url: "https://osonsms.com/",
|
|
|
|
|
},
|
2023-12-07 16:59:41 +08:00
|
|
|
|
"Custom HTTP SMS": {
|
|
|
|
|
logo: `${StaticBaseUrl}/img/social_default.png`,
|
|
|
|
|
url: "https://casdoor.org/docs/provider/sms/overview",
|
|
|
|
|
},
|
2022-08-17 22:02:45 +08:00
|
|
|
|
"Mock SMS": {
|
|
|
|
|
logo: `${StaticBaseUrl}/img/social_default.png`,
|
|
|
|
|
url: "",
|
|
|
|
|
},
|
2022-04-21 21:52:34 +08:00
|
|
|
|
},
|
|
|
|
|
Email: {
|
|
|
|
|
"Default": {
|
2023-02-06 20:28:40 +08:00
|
|
|
|
logo: `${StaticBaseUrl}/img/email_default.png`,
|
|
|
|
|
url: "",
|
|
|
|
|
},
|
|
|
|
|
"SUBMAIL": {
|
2023-02-11 15:59:23 +08:00
|
|
|
|
logo: `${StaticBaseUrl}/img/social_submail.svg`,
|
|
|
|
|
url: "https://www.mysubmail.com",
|
|
|
|
|
},
|
|
|
|
|
"Mailtrap": {
|
|
|
|
|
logo: `${StaticBaseUrl}/img/email_mailtrap.png`,
|
|
|
|
|
url: "https://mailtrap.io",
|
2022-04-21 21:52:34 +08:00
|
|
|
|
},
|
2023-09-12 02:13:37 +08:00
|
|
|
|
"Azure ACS": {
|
|
|
|
|
logo: `${StaticBaseUrl}/img/social_azure.png`,
|
|
|
|
|
url: "https://learn.microsoft.com/zh-cn/azure/communication-services",
|
|
|
|
|
},
|
2024-04-09 22:16:01 +08:00
|
|
|
|
"SendGrid": {
|
|
|
|
|
logo: `${StaticBaseUrl}/img/email_sendgrid.png`,
|
|
|
|
|
url: "https://sendgrid.com/",
|
|
|
|
|
},
|
2023-12-14 22:35:25 +08:00
|
|
|
|
"Custom HTTP Email": {
|
|
|
|
|
logo: `${StaticBaseUrl}/img/social_default.png`,
|
|
|
|
|
url: "https://casdoor.org/docs/provider/email/overview",
|
|
|
|
|
},
|
2022-04-21 21:52:34 +08:00
|
|
|
|
},
|
|
|
|
|
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",
|
|
|
|
|
},
|
2022-08-20 00:30:13 -03:00
|
|
|
|
"MinIO": {
|
|
|
|
|
logo: "https://min.io/resources/img/logo.svg",
|
|
|
|
|
url: "https://min.io/",
|
|
|
|
|
},
|
2022-04-21 21:52:34 +08:00
|
|
|
|
"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",
|
|
|
|
|
},
|
2022-05-03 17:59:07 +08:00
|
|
|
|
"Azure Blob": {
|
2022-09-10 00:56:37 +08:00
|
|
|
|
logo: `${StaticBaseUrl}/img/social_azure.png`,
|
2022-08-06 23:54:56 +08:00
|
|
|
|
url: "https://azure.microsoft.com/en-us/services/storage/blobs/",
|
|
|
|
|
},
|
2023-08-08 22:30:19 +08:00
|
|
|
|
"Qiniu Cloud Kodo": {
|
|
|
|
|
logo: `${StaticBaseUrl}/img/social_qiniu_cloud.png`,
|
|
|
|
|
url: "https://www.qiniu.com/solutions/storage",
|
|
|
|
|
},
|
|
|
|
|
"Google Cloud Storage": {
|
|
|
|
|
logo: `${StaticBaseUrl}/img/social_google_cloud.png`,
|
|
|
|
|
url: "https://cloud.google.com/storage",
|
|
|
|
|
},
|
2024-01-14 22:38:31 +08:00
|
|
|
|
"Synology": {
|
|
|
|
|
logo: `${StaticBaseUrl}/img/social_synology.png`,
|
|
|
|
|
url: "https://www.synology.com/en-global/dsm/feature/file_sharing",
|
|
|
|
|
},
|
2024-08-27 23:54:03 +08:00
|
|
|
|
"Casdoor": {
|
|
|
|
|
logo: `${StaticBaseUrl}/img/casdoor.png`,
|
|
|
|
|
url: "https://casdoor.org/docs/provider/storage/overview",
|
|
|
|
|
},
|
2024-12-08 20:24:38 +08:00
|
|
|
|
"CUCloud OSS": {
|
|
|
|
|
logo: `${StaticBaseUrl}/img/social_cucloud.png`,
|
|
|
|
|
url: "https://www.cucloud.cn/product/oss.html",
|
|
|
|
|
},
|
2022-04-21 21:52:34 +08:00
|
|
|
|
},
|
|
|
|
|
SAML: {
|
|
|
|
|
"Aliyun IDaaS": {
|
|
|
|
|
logo: `${StaticBaseUrl}/img/social_aliyun.png`,
|
2022-08-06 23:54:56 +08:00
|
|
|
|
url: "https://aliyun.com/product/idaas",
|
2022-04-21 21:52:34 +08:00
|
|
|
|
},
|
|
|
|
|
"Keycloak": {
|
|
|
|
|
logo: `${StaticBaseUrl}/img/social_keycloak.png`,
|
2022-08-06 23:54:56 +08:00
|
|
|
|
url: "https://www.keycloak.org/",
|
2022-04-21 21:52:34 +08:00
|
|
|
|
},
|
2023-10-20 21:11:36 +08:00
|
|
|
|
"Custom": {
|
|
|
|
|
logo: `${StaticBaseUrl}/img/social_custom.png`,
|
|
|
|
|
url: "https://door.casdoor.com/",
|
|
|
|
|
},
|
2022-04-21 21:52:34 +08:00
|
|
|
|
},
|
|
|
|
|
Payment: {
|
2023-05-30 23:25:58 +08:00
|
|
|
|
"Dummy": {
|
|
|
|
|
logo: `${StaticBaseUrl}/img/payment_paypal.png`,
|
|
|
|
|
url: "",
|
|
|
|
|
},
|
2024-07-12 15:48:37 +08:00
|
|
|
|
"Balance": {
|
|
|
|
|
logo: `${StaticBaseUrl}/img/payment_balance.svg`,
|
|
|
|
|
url: "",
|
|
|
|
|
},
|
2022-04-21 21:52:34 +08:00
|
|
|
|
"Alipay": {
|
|
|
|
|
logo: `${StaticBaseUrl}/img/payment_alipay.png`,
|
2022-08-06 23:54:56 +08:00
|
|
|
|
url: "https://www.alipay.com/",
|
2022-04-21 21:52:34 +08:00
|
|
|
|
},
|
|
|
|
|
"WeChat Pay": {
|
|
|
|
|
logo: `${StaticBaseUrl}/img/payment_wechat_pay.png`,
|
2022-08-06 23:54:56 +08:00
|
|
|
|
url: "https://pay.weixin.qq.com/",
|
2022-04-21 21:52:34 +08:00
|
|
|
|
},
|
|
|
|
|
"PayPal": {
|
|
|
|
|
logo: `${StaticBaseUrl}/img/payment_paypal.png`,
|
2022-08-06 23:54:56 +08:00
|
|
|
|
url: "https://www.paypal.com/",
|
2022-04-21 21:52:34 +08:00
|
|
|
|
},
|
2023-08-15 00:16:30 +08:00
|
|
|
|
"Stripe": {
|
|
|
|
|
logo: `${StaticBaseUrl}/img/social_stripe.png`,
|
|
|
|
|
url: "https://stripe.com/",
|
|
|
|
|
},
|
2025-02-07 19:19:30 +08:00
|
|
|
|
"AirWallex": {
|
|
|
|
|
logo: `${StaticBaseUrl}/img/payment_airwallex.svg`,
|
|
|
|
|
url: "https://airwallex.com/",
|
|
|
|
|
},
|
2022-04-21 21:52:34 +08:00
|
|
|
|
"GC": {
|
|
|
|
|
logo: `${StaticBaseUrl}/img/payment_gc.png`,
|
2022-08-06 23:54:56 +08:00
|
|
|
|
url: "https://gc.org",
|
2022-04-21 21:52:34 +08:00
|
|
|
|
},
|
|
|
|
|
},
|
2022-06-18 16:00:31 +08:00
|
|
|
|
Captcha: {
|
|
|
|
|
"Default": {
|
2023-02-06 20:28:40 +08:00
|
|
|
|
logo: `${StaticBaseUrl}/img/captcha_default.png`,
|
2022-06-18 16:00:31 +08:00
|
|
|
|
url: "https://pkg.go.dev/github.com/dchest/captcha",
|
|
|
|
|
},
|
2024-08-20 17:56:53 +08:00
|
|
|
|
"reCAPTCHA": {
|
2022-06-18 16:00:31 +08:00
|
|
|
|
logo: `${StaticBaseUrl}/img/social_recaptcha.png`,
|
|
|
|
|
url: "https://www.google.com/recaptcha",
|
|
|
|
|
},
|
2024-09-02 22:15:03 +08:00
|
|
|
|
"reCAPTCHA v2": {
|
|
|
|
|
logo: `${StaticBaseUrl}/img/social_recaptcha.png`,
|
|
|
|
|
url: "https://www.google.com/recaptcha",
|
|
|
|
|
},
|
|
|
|
|
"reCAPTCHA v3": {
|
|
|
|
|
logo: `${StaticBaseUrl}/img/social_recaptcha.png`,
|
|
|
|
|
url: "https://www.google.com/recaptcha",
|
|
|
|
|
},
|
2022-06-18 16:00:31 +08:00
|
|
|
|
"hCaptcha": {
|
|
|
|
|
logo: `${StaticBaseUrl}/img/social_hcaptcha.png`,
|
|
|
|
|
url: "https://www.hcaptcha.com",
|
2022-06-29 11:31:32 +08:00
|
|
|
|
},
|
|
|
|
|
"Aliyun Captcha": {
|
|
|
|
|
logo: `${StaticBaseUrl}/img/social_aliyun.png`,
|
|
|
|
|
url: "https://help.aliyun.com/product/28308.html",
|
2022-08-04 20:55:04 +08:00
|
|
|
|
},
|
|
|
|
|
"GEETEST": {
|
|
|
|
|
logo: `${StaticBaseUrl}/img/social_geetest.png`,
|
|
|
|
|
url: "https://www.geetest.com",
|
2022-08-06 23:54:56 +08:00
|
|
|
|
},
|
2022-11-26 17:17:49 +08:00
|
|
|
|
"Cloudflare Turnstile": {
|
|
|
|
|
logo: `${StaticBaseUrl}/img/social_cloudflare.png`,
|
|
|
|
|
url: "https://www.cloudflare.com/products/turnstile/",
|
|
|
|
|
},
|
2022-08-06 23:54:56 +08:00
|
|
|
|
},
|
2023-04-22 23:18:18 +08:00
|
|
|
|
AI: {
|
|
|
|
|
"OpenAI API - GPT": {
|
|
|
|
|
logo: `${StaticBaseUrl}/img/social_openai.svg`,
|
|
|
|
|
url: "https://platform.openai.com",
|
|
|
|
|
},
|
|
|
|
|
},
|
2023-07-20 17:51:36 +08:00
|
|
|
|
Web3: {
|
|
|
|
|
"MetaMask": {
|
|
|
|
|
logo: `${StaticBaseUrl}/img/social_metamask.svg`,
|
|
|
|
|
url: "https://metamask.io/",
|
|
|
|
|
},
|
2023-08-13 23:58:57 +08:00
|
|
|
|
"Web3Onboard": {
|
|
|
|
|
logo: `${StaticBaseUrl}/img/social_web3onboard.svg`,
|
|
|
|
|
url: "https://onboard.blocknative.com/",
|
|
|
|
|
},
|
2023-07-20 17:51:36 +08:00
|
|
|
|
},
|
2023-08-19 12:33:00 +08:00
|
|
|
|
Notification: {
|
|
|
|
|
"Telegram": {
|
|
|
|
|
logo: `${StaticBaseUrl}/img/social_telegram.png`,
|
|
|
|
|
url: "https://telegram.org/",
|
|
|
|
|
},
|
2023-08-20 21:04:30 +08:00
|
|
|
|
"Custom HTTP": {
|
|
|
|
|
logo: `${StaticBaseUrl}/img/email_default.png`,
|
2023-08-26 23:39:02 +08:00
|
|
|
|
url: "https://casdoor.org/docs/provider/notification/overview",
|
2023-08-20 21:04:30 +08:00
|
|
|
|
},
|
2023-09-05 17:05:34 +08:00
|
|
|
|
"DingTalk": {
|
|
|
|
|
logo: `${StaticBaseUrl}/img/social_dingtalk.png`,
|
|
|
|
|
url: "https://www.dingtalk.com/",
|
|
|
|
|
},
|
|
|
|
|
"Lark": {
|
|
|
|
|
logo: `${StaticBaseUrl}/img/social_lark.png`,
|
|
|
|
|
url: "https://www.larksuite.com/",
|
|
|
|
|
},
|
|
|
|
|
"Microsoft Teams": {
|
|
|
|
|
logo: `${StaticBaseUrl}/img/social_teams.png`,
|
|
|
|
|
url: "https://www.microsoft.com/microsoft-teams",
|
|
|
|
|
},
|
|
|
|
|
"Bark": {
|
|
|
|
|
logo: `${StaticBaseUrl}/img/social_bark.png`,
|
|
|
|
|
url: "https://apps.apple.com/us/app/bark-customed-notifications/id1403753865",
|
|
|
|
|
},
|
|
|
|
|
"Pushover": {
|
|
|
|
|
logo: `${StaticBaseUrl}/img/social_pushover.png`,
|
|
|
|
|
url: "https://pushover.net/",
|
|
|
|
|
},
|
|
|
|
|
"Pushbullet": {
|
|
|
|
|
logo: `${StaticBaseUrl}/img/social_pushbullet.png`,
|
|
|
|
|
url: "https://www.pushbullet.com/",
|
|
|
|
|
},
|
|
|
|
|
"Slack": {
|
|
|
|
|
logo: `${StaticBaseUrl}/img/social_slack.png`,
|
|
|
|
|
url: "https://slack.com/",
|
|
|
|
|
},
|
|
|
|
|
"Webpush": {
|
|
|
|
|
logo: `${StaticBaseUrl}/img/email_default.png`,
|
|
|
|
|
url: "https://developer.mozilla.org/en-US/docs/Web/API/Push_API",
|
|
|
|
|
},
|
|
|
|
|
"Discord": {
|
|
|
|
|
logo: `${StaticBaseUrl}/img/social_discord.png`,
|
|
|
|
|
url: "https://discord.com/",
|
|
|
|
|
},
|
|
|
|
|
"Google Chat": {
|
|
|
|
|
logo: `${StaticBaseUrl}/img/social_google_chat.png`,
|
|
|
|
|
url: "https://workspace.google.com/intl/en/products/chat/",
|
|
|
|
|
},
|
|
|
|
|
"Line": {
|
|
|
|
|
logo: `${StaticBaseUrl}/img/social_line.png`,
|
|
|
|
|
url: "https://line.me/",
|
|
|
|
|
},
|
|
|
|
|
"Matrix": {
|
|
|
|
|
logo: `${StaticBaseUrl}/img/social_matrix.png`,
|
|
|
|
|
url: "https://www.matrix.org/",
|
|
|
|
|
},
|
|
|
|
|
"Twitter": {
|
|
|
|
|
logo: `${StaticBaseUrl}/img/social_twitter.png`,
|
|
|
|
|
url: "https://twitter.com/",
|
|
|
|
|
},
|
|
|
|
|
"Reddit": {
|
|
|
|
|
logo: `${StaticBaseUrl}/img/social_reddit.png`,
|
|
|
|
|
url: "https://www.reddit.com/",
|
|
|
|
|
},
|
|
|
|
|
"Rocket Chat": {
|
|
|
|
|
logo: `${StaticBaseUrl}/img/social_rocket_chat.png`,
|
|
|
|
|
url: "https://rocket.chat/",
|
|
|
|
|
},
|
|
|
|
|
"Viber": {
|
|
|
|
|
logo: `${StaticBaseUrl}/img/social_viber.png`,
|
|
|
|
|
url: "https://www.viber.com/",
|
|
|
|
|
},
|
2025-01-17 08:35:31 +08:00
|
|
|
|
"CUCloud": {
|
|
|
|
|
logo: `${StaticBaseUrl}/img/cucloud.png`,
|
|
|
|
|
url: "https://www.cucloud.cn/",
|
|
|
|
|
},
|
2023-08-19 12:33:00 +08:00
|
|
|
|
},
|
2025-03-19 22:57:35 +08:00
|
|
|
|
"Face ID": {
|
|
|
|
|
"Alibaba Cloud Facebody": {
|
|
|
|
|
logo: `${StaticBaseUrl}/img/social_aliyun.png`,
|
|
|
|
|
url: "https://vision.aliyun.com/facebody",
|
|
|
|
|
},
|
|
|
|
|
},
|
2022-04-21 21:52:34 +08:00
|
|
|
|
};
|
|
|
|
|
|
2023-02-16 22:53:28 +08:00
|
|
|
|
export function initCountries() {
|
2022-08-08 23:35:24 +08:00
|
|
|
|
const countries = require("i18n-iso-countries");
|
2023-02-12 18:56:56 +08:00
|
|
|
|
countries.registerLocale(require("i18n-iso-countries/langs/" + getLanguage() + ".json"));
|
|
|
|
|
return countries;
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-25 15:46:54 +08:00
|
|
|
|
export function getCountryCode(country) {
|
2023-03-01 22:09:48 +08:00
|
|
|
|
if (phoneNumber.isSupportedCountry(country)) {
|
|
|
|
|
return phoneNumber.getCountryCallingCode(country);
|
|
|
|
|
}
|
|
|
|
|
return "";
|
2023-02-25 15:46:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
2023-02-25 15:25:47 +08:00
|
|
|
|
export function getCountryCodeData(countryCodes = phoneNumber.getCountries()) {
|
2024-10-03 22:58:09 +08:00
|
|
|
|
if (countryCodes?.includes("All")) {
|
|
|
|
|
countryCodes = phoneNumber.getCountries();
|
|
|
|
|
}
|
2023-02-16 22:53:28 +08:00
|
|
|
|
return countryCodes?.map((countryCode) => {
|
|
|
|
|
if (phoneNumber.isSupportedCountry(countryCode)) {
|
|
|
|
|
const name = initCountries().getName(countryCode, getLanguage());
|
|
|
|
|
return {
|
|
|
|
|
code: countryCode,
|
|
|
|
|
name: name || "",
|
|
|
|
|
phone: phoneNumber.getCountryCallingCode(countryCode),
|
|
|
|
|
};
|
|
|
|
|
}
|
2023-02-25 15:08:08 +08:00
|
|
|
|
}).filter(item => item.name !== "")
|
|
|
|
|
.sort((a, b) => a.phone - b.phone);
|
2021-11-10 22:27:58 +08:00
|
|
|
|
}
|
2021-07-31 16:02:48 +08:00
|
|
|
|
|
2023-02-25 15:25:47 +08:00
|
|
|
|
export function getCountryCodeOption(country) {
|
|
|
|
|
return (
|
|
|
|
|
<Option key={country.code} value={country.code} label={`+${country.phone}`} text={`${country.name}, ${country.code}, ${country.phone}`} >
|
|
|
|
|
<div style={{display: "flex", justifyContent: "space-between", marginRight: "10px"}}>
|
|
|
|
|
<div>
|
2024-10-03 22:58:09 +08:00
|
|
|
|
{country.code === "All" ? null : getCountryImage(country)}
|
2023-02-25 15:25:47 +08:00
|
|
|
|
{`${country.name}`}
|
|
|
|
|
</div>
|
2024-10-03 22:58:09 +08:00
|
|
|
|
{country.code === "All" ? null : `+${country.phone}`}
|
2023-02-25 15:25:47 +08:00
|
|
|
|
</div>
|
|
|
|
|
</Option>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function getCountryImage(country) {
|
2023-02-16 22:53:28 +08:00
|
|
|
|
return <img src={`${StaticBaseUrl}/flag-icons/${country.code}.svg`} alt={country.name} height={20} style={{marginRight: 10}} />;
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-13 12:15:19 +08:00
|
|
|
|
export function initServerUrl() {
|
2022-07-10 15:45:55 +08:00
|
|
|
|
// const hostname = window.location.hostname;
|
2022-01-29 21:52:04 +08:00
|
|
|
|
// if (hostname === "localhost") {
|
|
|
|
|
// ServerUrl = `http://${hostname}:8000`;
|
|
|
|
|
// }
|
2021-02-13 12:15:19 +08:00
|
|
|
|
}
|
|
|
|
|
|
2021-09-12 12:09:44 +08:00
|
|
|
|
export function isLocalhost() {
|
2021-05-14 15:55:50 +08:00
|
|
|
|
const hostname = window.location.hostname;
|
|
|
|
|
return hostname === "localhost";
|
|
|
|
|
}
|
|
|
|
|
|
2021-08-08 14:18:44 +08:00
|
|
|
|
export function getFullServerUrl() {
|
|
|
|
|
let fullServerUrl = window.location.origin;
|
|
|
|
|
if (fullServerUrl === "http://localhost:7001") {
|
|
|
|
|
fullServerUrl = "http://localhost:8000";
|
|
|
|
|
}
|
|
|
|
|
return fullServerUrl;
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-14 21:35:19 +08:00
|
|
|
|
export function isProviderVisible(providerItem) {
|
|
|
|
|
if (providerItem.provider === undefined || providerItem.provider === null) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-20 17:51:36 +08:00
|
|
|
|
if (!["OAuth", "SAML", "Web3"].includes(providerItem.provider.category)) {
|
2021-06-17 01:49:05 +08:00
|
|
|
|
return false;
|
2021-05-14 15:55:50 +08:00
|
|
|
|
}
|
|
|
|
|
|
2022-07-10 15:45:55 +08:00
|
|
|
|
if (providerItem.provider.type === "WeChatMiniProgram") {
|
|
|
|
|
return false;
|
2022-04-15 11:49:56 +08:00
|
|
|
|
}
|
|
|
|
|
|
2022-03-19 19:43:54 +08:00
|
|
|
|
return true;
|
2021-06-14 21:35:19 +08:00
|
|
|
|
}
|
|
|
|
|
|
2023-02-18 16:21:12 +08:00
|
|
|
|
export function isResponseDenied(data) {
|
|
|
|
|
if (data.msg === "Unauthorized operation" || data.msg === "未授权的操作") {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-14 21:35:19 +08:00
|
|
|
|
export function isProviderVisibleForSignUp(providerItem) {
|
|
|
|
|
if (providerItem.canSignUp === false) {
|
|
|
|
|
return false;
|
2021-05-14 15:55:50 +08:00
|
|
|
|
}
|
2021-06-14 21:35:19 +08:00
|
|
|
|
|
|
|
|
|
return isProviderVisible(providerItem);
|
2021-05-14 15:55:50 +08:00
|
|
|
|
}
|
|
|
|
|
|
2021-06-14 21:35:19 +08:00
|
|
|
|
export function isProviderVisibleForSignIn(providerItem) {
|
|
|
|
|
if (providerItem.canSignIn === false) {
|
2021-06-09 20:39:43 +08:00
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-14 21:35:19 +08:00
|
|
|
|
return isProviderVisible(providerItem);
|
2021-06-09 20:39:43 +08:00
|
|
|
|
}
|
|
|
|
|
|
2021-06-18 23:43:36 +08:00
|
|
|
|
export function isProviderPrompted(providerItem) {
|
|
|
|
|
return isProviderVisible(providerItem) && providerItem.prompted;
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-21 11:12:23 +08:00
|
|
|
|
export function isSignupItemPrompted(signupItem) {
|
|
|
|
|
return signupItem.visible && signupItem.prompted;
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-20 09:46:06 +08:00
|
|
|
|
export function getAllPromptedProviderItems(application) {
|
2023-05-16 22:17:39 +08:00
|
|
|
|
return application.providers?.filter(providerItem => isProviderPrompted(providerItem));
|
2021-06-20 09:46:06 +08:00
|
|
|
|
}
|
|
|
|
|
|
2022-08-21 11:12:23 +08:00
|
|
|
|
export function getAllPromptedSignupItems(application) {
|
2023-05-16 22:17:39 +08:00
|
|
|
|
return application.signupItems?.filter(signupItem => isSignupItemPrompted(signupItem));
|
2022-08-21 11:12:23 +08:00
|
|
|
|
}
|
|
|
|
|
|
2021-06-20 09:46:06 +08:00
|
|
|
|
export function getSignupItem(application, itemName) {
|
2021-06-22 11:31:53 +08:00
|
|
|
|
const signupItems = application.signupItems?.filter(signupItem => signupItem.name === itemName);
|
2023-05-16 22:17:39 +08:00
|
|
|
|
if (signupItems?.length > 0) {
|
|
|
|
|
return signupItems[0];
|
2021-06-20 09:46:06 +08:00
|
|
|
|
}
|
2023-05-16 22:17:39 +08:00
|
|
|
|
return null;
|
2021-06-20 09:46:06 +08:00
|
|
|
|
}
|
|
|
|
|
|
2022-04-25 21:39:46 +08:00
|
|
|
|
export function isValidPersonName(personName) {
|
2022-09-21 21:35:39 +08:00
|
|
|
|
return personName !== "";
|
|
|
|
|
|
|
|
|
|
// // https://blog.css8.cn/post/14210975.html
|
|
|
|
|
// const personNameRegex = /^[\u4e00-\u9fa5]{2,6}$/;
|
|
|
|
|
// return personNameRegex.test(personName);
|
2022-04-25 21:39:46 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function isValidIdCard(idCard) {
|
2022-12-12 01:07:31 +08:00
|
|
|
|
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);
|
2022-04-25 21:39:46 +08:00
|
|
|
|
}
|
|
|
|
|
|
2021-09-21 14:04:17 +08:00
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-16 22:53:28 +08:00
|
|
|
|
export function isValidPhone(phone, countryCode = "") {
|
2023-02-27 20:10:59 +08:00
|
|
|
|
if (countryCode !== "" && countryCode !== "CN") {
|
2023-02-16 22:53:28 +08:00
|
|
|
|
return phoneNumber.isValidPhoneNumber(phone, countryCode);
|
|
|
|
|
}
|
2022-04-26 23:56:41 +08:00
|
|
|
|
|
2023-02-27 20:10:59 +08:00
|
|
|
|
// https://learnku.com/articles/31543, `^s*$` filter empty email individually.
|
|
|
|
|
const phoneCnRegex = /^1(3\d|4[5-9]|5[0-35-9]|6[2567]|7[0-8]|8\d|9[0-35-9])\d{8}$/;
|
2023-02-16 22:53:28 +08:00
|
|
|
|
const phoneRegex = /[0-9]{4,15}$/;
|
2023-02-27 20:10:59 +08:00
|
|
|
|
|
|
|
|
|
return countryCode === "CN" ? phoneCnRegex.test(phone) : phoneRegex.test(phone);
|
2021-09-21 14:04:17 +08:00
|
|
|
|
}
|
|
|
|
|
|
2022-04-25 21:39:46 +08:00
|
|
|
|
export function isValidInvoiceTitle(invoiceTitle) {
|
2022-12-12 01:07:31 +08:00
|
|
|
|
return invoiceTitle !== "";
|
2022-04-26 23:56:41 +08:00
|
|
|
|
|
2022-12-12 01:07:31 +08:00
|
|
|
|
// if (invoiceTitle === "") {
|
|
|
|
|
// return false;
|
|
|
|
|
// }
|
|
|
|
|
//
|
|
|
|
|
// // https://blog.css8.cn/post/14210975.html
|
|
|
|
|
// const invoiceTitleRegex = /^[()()\u4e00-\u9fa5]{0,50}$/;
|
|
|
|
|
// return invoiceTitleRegex.test(invoiceTitle);
|
2022-04-25 21:39:46 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function isValidTaxId(taxId) {
|
2022-12-12 01:07:31 +08:00
|
|
|
|
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;
|
2022-04-25 21:39:46 +08:00
|
|
|
|
}
|
|
|
|
|
|
2021-06-20 09:46:06 +08:00
|
|
|
|
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);
|
2023-05-16 22:17:39 +08:00
|
|
|
|
if (providerItems?.length > 0) {
|
2021-06-20 09:46:06 +08:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-21 11:12:23 +08:00
|
|
|
|
const signupItems = getAllPromptedSignupItems(application);
|
2023-05-16 22:17:39 +08:00
|
|
|
|
if (signupItems?.length > 0) {
|
2022-08-21 11:12:23 +08:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-20 09:46:06 +08:00
|
|
|
|
return isAffiliationPrompted(application);
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-20 22:17:03 +08:00
|
|
|
|
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 !== "";
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-21 17:41:07 +08:00
|
|
|
|
function isSignupItemAnswered(user, signupItem) {
|
|
|
|
|
if (user === null) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (signupItem.name !== "Country/Region") {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const value = user["region"];
|
|
|
|
|
return value !== undefined && value !== "";
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-20 22:17:03 +08:00
|
|
|
|
export function isPromptAnswered(user, application) {
|
|
|
|
|
if (!isAffiliationAnswered(user, application)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const providerItems = getAllPromptedProviderItems(application);
|
2022-08-06 23:43:09 +08:00
|
|
|
|
for (let i = 0; i < providerItems.length; i++) {
|
2021-06-20 22:17:03 +08:00
|
|
|
|
if (!isProviderItemAnswered(user, application, providerItems[i])) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-08-21 17:41:07 +08:00
|
|
|
|
|
|
|
|
|
const signupItems = getAllPromptedSignupItems(application);
|
|
|
|
|
for (let i = 0; i < signupItems.length; i++) {
|
|
|
|
|
if (!isSignupItemAnswered(user, signupItems[i])) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-06-20 22:17:03 +08:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-07 12:30:07 +08:00
|
|
|
|
export const MfaRuleRequired = "Required";
|
|
|
|
|
export const MfaRulePrompted = "Prompted";
|
|
|
|
|
export const MfaRuleOptional = "Optional";
|
|
|
|
|
|
|
|
|
|
export function isRequiredEnableMfa(user, organization) {
|
|
|
|
|
if (!user || !organization || !organization.mfaItems) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return getMfaItemsByRules(user, organization, [MfaRuleRequired]).length > 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function getMfaItemsByRules(user, organization, mfaRules = []) {
|
|
|
|
|
if (!user || !organization || !organization.mfaItems) {
|
|
|
|
|
return [];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return organization.mfaItems.filter((mfaItem) => mfaRules.includes(mfaItem.rule))
|
|
|
|
|
.filter((mfaItem) => user.multiFactorAuths.some((mfa) => mfa.mfaType === mfaItem.name && !mfa.enabled));
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-10 00:56:37 +08:00
|
|
|
|
export function parseObject(s) {
|
|
|
|
|
try {
|
|
|
|
|
return eval("(" + s + ")");
|
|
|
|
|
} catch (e) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-13 12:15:19 +08:00
|
|
|
|
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);
|
2022-07-10 15:45:55 +08:00
|
|
|
|
const w = window.open("about:blank");
|
2021-02-13 12:15:19 +08:00
|
|
|
|
w.location.href = link;
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-26 22:17:45 +08:00
|
|
|
|
export function openLinkSafe(link) {
|
|
|
|
|
// Javascript window.open issue in safari
|
|
|
|
|
// https://stackoverflow.com/questions/45569893/javascript-window-open-issue-in-safari
|
2022-08-08 23:35:24 +08:00
|
|
|
|
const a = document.createElement("a");
|
2022-04-26 22:17:45 +08:00
|
|
|
|
a.href = link;
|
2022-07-10 15:45:55 +08:00
|
|
|
|
a.setAttribute("target", "_blank");
|
2022-04-26 22:17:45 +08:00
|
|
|
|
a.click();
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-13 12:15:19 +08:00
|
|
|
|
export function goToLink(link) {
|
|
|
|
|
window.location.href = link;
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-26 21:58:19 +08:00
|
|
|
|
export function goToLinkSoft(ths, link) {
|
2022-04-25 13:27:26 +08:00
|
|
|
|
if (link.startsWith("http")) {
|
|
|
|
|
openLink(link);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-26 21:58:19 +08:00
|
|
|
|
ths.props.history.push(link);
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-06 01:07:52 +08:00
|
|
|
|
export function goToLinkSoftOrJumpSelf(ths, link) {
|
|
|
|
|
if (link.startsWith("http")) {
|
|
|
|
|
goToLink(link);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ths.props.history.push(link);
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-13 12:15:19 +08:00
|
|
|
|
export function showMessage(type, text) {
|
2022-11-25 16:02:20 +08:00
|
|
|
|
if (type === "success") {
|
2021-02-13 12:15:19 +08:00
|
|
|
|
message.success(text);
|
|
|
|
|
} else if (type === "error") {
|
|
|
|
|
message.error(text);
|
2022-04-27 21:24:50 +08:00
|
|
|
|
} else if (type === "info") {
|
|
|
|
|
message.info(text);
|
2021-02-13 12:15:19 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-13 17:34:32 +08:00
|
|
|
|
export function isAdminUser(account) {
|
2021-03-28 16:35:59 +08:00
|
|
|
|
if (account === undefined || account === null) {
|
2021-03-21 00:44:19 +08:00
|
|
|
|
return false;
|
|
|
|
|
}
|
2023-08-19 12:23:15 +08:00
|
|
|
|
return account.owner === "built-in";
|
2021-02-13 17:34:32 +08:00
|
|
|
|
}
|
|
|
|
|
|
2022-08-15 14:09:12 +08:00
|
|
|
|
export function isLocalAdminUser(account) {
|
|
|
|
|
if (account === undefined || account === null) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return account.isAdmin === true || isAdminUser(account);
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-13 12:15:19 +08:00
|
|
|
|
export function deepCopy(obj) {
|
|
|
|
|
return Object.assign({}, obj);
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-25 16:02:20 +08:00
|
|
|
|
export function addRow(array, row, position = "end") {
|
|
|
|
|
return position === "end" ? [...array, row] : [row, ...array];
|
2021-02-13 12:15:19 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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)];
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-24 20:48:04 +08:00
|
|
|
|
export function trim(str, ch) {
|
|
|
|
|
if (str === undefined) {
|
|
|
|
|
return undefined;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let start = 0;
|
|
|
|
|
let end = str.length;
|
|
|
|
|
|
2022-09-04 19:40:30 +08:00
|
|
|
|
while (start < end && str[start] === ch) {++start;}
|
2021-05-24 20:48:04 +08:00
|
|
|
|
|
2022-09-04 19:40:30 +08:00
|
|
|
|
while (end > start && str[end - 1] === ch) {--end;}
|
2021-05-24 20:48:04 +08:00
|
|
|
|
|
|
|
|
|
return (start > 0 || end < str.length) ? str.substring(start, end) : str;
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-13 12:15:19 +08:00
|
|
|
|
export function isMobile() {
|
|
|
|
|
// return getIsMobileView();
|
|
|
|
|
return isMobileDevice;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function getFormattedDate(date) {
|
2023-09-24 09:56:06 +08:00
|
|
|
|
if (!date) {
|
2021-02-13 12:15:19 +08:00
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-23 15:09:53 +08:00
|
|
|
|
const m = moment(date).local();
|
|
|
|
|
return m.format("YYYY-MM-DD HH:mm:ss");
|
2021-02-13 12:15:19 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function getFormattedDateShort(date) {
|
|
|
|
|
return date.slice(0, 10);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function getShortName(s) {
|
2022-07-10 15:45:55 +08:00
|
|
|
|
return s.split("/").slice(-1)[0];
|
2021-02-13 12:15:19 +08:00
|
|
|
|
}
|
|
|
|
|
|
2023-03-18 18:54:05 +08:00
|
|
|
|
export function getNameAtLeast(s) {
|
|
|
|
|
s = getShortName(s);
|
|
|
|
|
if (s.length >= 6) {
|
|
|
|
|
return s;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<React.Fragment>
|
|
|
|
|
|
|
|
|
|
{s}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
</React.Fragment>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-06 23:43:09 +08:00
|
|
|
|
export function getShortText(s, maxLength = 35) {
|
2021-02-13 23:00:43 +08:00
|
|
|
|
if (s.length > maxLength) {
|
|
|
|
|
return `${s.slice(0, maxLength)}...`;
|
|
|
|
|
} else {
|
|
|
|
|
return s;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-08-15 00:17:53 +08:00
|
|
|
|
export function getFriendlyFileSize(size) {
|
|
|
|
|
if (size < 1024) {
|
2022-07-10 15:45:55 +08:00
|
|
|
|
return size + " B";
|
2021-08-15 00:17:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
2022-08-08 23:35:24 +08:00
|
|
|
|
const i = Math.floor(Math.log(size) / Math.log(1024));
|
2021-08-15 00:17:53 +08:00
|
|
|
|
let num = (size / Math.pow(1024, i));
|
2022-08-08 23:35:24 +08:00
|
|
|
|
const round = Math.round(num);
|
2021-08-15 00:17:53 +08:00
|
|
|
|
num = round < 10 ? num.toFixed(2) : round < 100 ? num.toFixed(1) : round;
|
2022-08-06 23:43:09 +08:00
|
|
|
|
return `${num} ${"KMGTPEZY"[i - 1]}B`;
|
2021-08-15 00:17:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
2022-09-09 11:43:54 +08:00
|
|
|
|
function getHashInt(s) {
|
2021-02-13 12:15:19 +08:00
|
|
|
|
let hash = 0;
|
|
|
|
|
if (s.length !== 0) {
|
2022-08-06 23:43:09 +08:00
|
|
|
|
for (let i = 0; i < s.length; i++) {
|
2022-08-08 23:35:24 +08:00
|
|
|
|
const char = s.charCodeAt(i);
|
2021-02-13 12:15:19 +08:00
|
|
|
|
hash = ((hash << 5) - hash) + char;
|
|
|
|
|
hash = hash & hash;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-09 11:43:54 +08:00
|
|
|
|
if (hash < 0) {
|
|
|
|
|
hash = -hash;
|
|
|
|
|
}
|
2021-02-13 12:15:19 +08:00
|
|
|
|
return hash;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function getAvatarColor(s) {
|
2022-07-10 15:45:55 +08:00
|
|
|
|
const colorList = ["#f56a00", "#7265e6", "#ffbf00", "#00a2ae"];
|
2022-09-09 11:43:54 +08:00
|
|
|
|
const hash = getHashInt(s);
|
|
|
|
|
return colorList[hash % 4];
|
2021-02-13 12:15:19 +08:00
|
|
|
|
}
|
2021-02-19 23:23:59 +08:00
|
|
|
|
|
2022-12-07 01:53:03 +08:00
|
|
|
|
export function getLanguageText(text) {
|
|
|
|
|
if (!text.includes("|")) {
|
|
|
|
|
return text;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let res;
|
|
|
|
|
const tokens = text.split("|");
|
|
|
|
|
if (getLanguage() !== "zh") {
|
|
|
|
|
res = trim(tokens[0], "");
|
|
|
|
|
} else {
|
|
|
|
|
res = trim(tokens[1], "");
|
|
|
|
|
}
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-27 14:02:52 +08:00
|
|
|
|
export function getLanguage() {
|
2023-06-03 00:29:08 +08:00
|
|
|
|
return (i18next.language !== undefined && i18next.language !== null && i18next.language !== "" && i18next.language !== "null") ? i18next.language : Conf.DefaultLanguage;
|
2022-02-27 14:02:52 +08:00
|
|
|
|
}
|
|
|
|
|
|
2021-09-14 01:22:13 +08:00
|
|
|
|
export function setLanguage(language) {
|
|
|
|
|
localStorage.setItem("language", language);
|
|
|
|
|
i18next.changeLanguage(language);
|
2021-02-19 23:23:59 +08:00
|
|
|
|
}
|
|
|
|
|
|
2022-10-23 15:16:24 +08:00
|
|
|
|
export function getAcceptLanguage() {
|
2022-11-24 20:43:35 +08:00
|
|
|
|
if (i18next.language === null || i18next.language === "") {
|
|
|
|
|
return "en;q=0.9,en;q=0.8";
|
|
|
|
|
}
|
2022-10-23 15:16:24 +08:00
|
|
|
|
return i18next.language + ";q=0.9,en;q=0.8";
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-14 23:08:08 +08:00
|
|
|
|
export function getClickable(text) {
|
|
|
|
|
return (
|
|
|
|
|
<a onClick={() => {
|
|
|
|
|
copy(text);
|
2024-12-07 21:22:57 +08:00
|
|
|
|
showMessage("success", i18next.t("general:Copied to clipboard successfully"));
|
2021-03-14 23:08:08 +08:00
|
|
|
|
}}>
|
|
|
|
|
{text}
|
|
|
|
|
</a>
|
2022-07-10 15:45:55 +08:00
|
|
|
|
);
|
2021-03-14 23:08:08 +08:00
|
|
|
|
}
|
2021-04-18 23:14:46 +08:00
|
|
|
|
|
2022-04-21 21:52:34 +08:00
|
|
|
|
export function getProviderLogoURL(provider) {
|
2023-10-20 21:11:36 +08:00
|
|
|
|
if (provider.type === "Custom" && provider.customLogo) {
|
|
|
|
|
return provider.customLogo;
|
|
|
|
|
}
|
2022-04-21 21:52:34 +08:00
|
|
|
|
if (provider.category === "OAuth") {
|
|
|
|
|
return `${StaticBaseUrl}/img/social_${provider.type.toLowerCase()}.png`;
|
|
|
|
|
} else {
|
2022-08-17 22:02:45 +08:00
|
|
|
|
const info = OtherProviderInfo[provider.category][provider.type];
|
|
|
|
|
// avoid crash when provider is not found
|
|
|
|
|
if (info) {
|
|
|
|
|
return info.logo;
|
|
|
|
|
}
|
|
|
|
|
return "";
|
2022-04-21 21:52:34 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-19 01:14:41 +08:00
|
|
|
|
export function getProviderLogo(provider) {
|
2022-07-10 15:45:55 +08:00
|
|
|
|
const idp = provider.type.toLowerCase().trim().split(" ")[0];
|
2022-04-21 21:52:34 +08:00
|
|
|
|
const url = getProviderLogoURL(provider);
|
2021-04-18 23:14:46 +08:00
|
|
|
|
return (
|
|
|
|
|
<img width={30} height={30} src={url} alt={idp} />
|
2022-07-10 15:45:55 +08:00
|
|
|
|
);
|
2021-04-18 23:14:46 +08:00
|
|
|
|
}
|
2021-04-28 15:54:50 +08:00
|
|
|
|
|
2021-12-25 10:55:10 +08:00
|
|
|
|
export function getProviderTypeOptions(category) {
|
|
|
|
|
if (category === "OAuth") {
|
|
|
|
|
return (
|
|
|
|
|
[
|
2022-07-10 15:45:55 +08:00
|
|
|
|
{id: "Google", name: "Google"},
|
|
|
|
|
{id: "GitHub", name: "GitHub"},
|
|
|
|
|
{id: "QQ", name: "QQ"},
|
|
|
|
|
{id: "WeChat", name: "WeChat"},
|
|
|
|
|
{id: "WeChatMiniProgram", name: "WeChat Mini Program"},
|
|
|
|
|
{id: "Facebook", name: "Facebook"},
|
|
|
|
|
{id: "DingTalk", name: "DingTalk"},
|
|
|
|
|
{id: "Weibo", name: "Weibo"},
|
|
|
|
|
{id: "Gitee", name: "Gitee"},
|
|
|
|
|
{id: "LinkedIn", name: "LinkedIn"},
|
|
|
|
|
{id: "WeCom", name: "WeCom"},
|
|
|
|
|
{id: "Lark", name: "Lark"},
|
|
|
|
|
{id: "GitLab", name: "GitLab"},
|
2023-07-30 17:31:36 +08:00
|
|
|
|
{id: "ADFS", name: "ADFS"},
|
2022-07-10 15:45:55 +08:00
|
|
|
|
{id: "Baidu", name: "Baidu"},
|
|
|
|
|
{id: "Alipay", name: "Alipay"},
|
|
|
|
|
{id: "Casdoor", name: "Casdoor"},
|
|
|
|
|
{id: "Infoflow", name: "Infoflow"},
|
|
|
|
|
{id: "Apple", name: "Apple"},
|
2023-12-17 02:37:28 +08:00
|
|
|
|
{id: "AzureAD", name: "Azure AD"},
|
|
|
|
|
{id: "AzureADB2C", name: "Azure AD B2C"},
|
2022-07-10 15:45:55 +08:00
|
|
|
|
{id: "Slack", name: "Slack"},
|
|
|
|
|
{id: "Steam", name: "Steam"},
|
|
|
|
|
{id: "Bilibili", name: "Bilibili"},
|
|
|
|
|
{id: "Okta", name: "Okta"},
|
|
|
|
|
{id: "Douyin", name: "Douyin"},
|
2025-01-08 00:09:16 +08:00
|
|
|
|
{id: "Kwai", name: "Kwai"},
|
2022-12-21 02:25:58 +08:00
|
|
|
|
{id: "Line", name: "Line"},
|
2023-02-04 12:20:18 +08:00
|
|
|
|
{id: "Amazon", name: "Amazon"},
|
|
|
|
|
{id: "Auth0", name: "Auth0"},
|
|
|
|
|
{id: "BattleNet", name: "Battle.net"},
|
|
|
|
|
{id: "Bitbucket", name: "Bitbucket"},
|
|
|
|
|
{id: "Box", name: "Box"},
|
|
|
|
|
{id: "CloudFoundry", name: "Cloud Foundry"},
|
|
|
|
|
{id: "Dailymotion", name: "Dailymotion"},
|
|
|
|
|
{id: "Deezer", name: "Deezer"},
|
|
|
|
|
{id: "DigitalOcean", name: "DigitalOcean"},
|
|
|
|
|
{id: "Discord", name: "Discord"},
|
|
|
|
|
{id: "Dropbox", name: "Dropbox"},
|
|
|
|
|
{id: "EveOnline", name: "Eve Online"},
|
|
|
|
|
{id: "Fitbit", name: "Fitbit"},
|
|
|
|
|
{id: "Gitea", name: "Gitea"},
|
|
|
|
|
{id: "Heroku", name: "Heroku"},
|
|
|
|
|
{id: "InfluxCloud", name: "InfluxCloud"},
|
|
|
|
|
{id: "Instagram", name: "Instagram"},
|
|
|
|
|
{id: "Intercom", name: "Intercom"},
|
|
|
|
|
{id: "Kakao", name: "Kakao"},
|
|
|
|
|
{id: "Lastfm", name: "Lastfm"},
|
|
|
|
|
{id: "Mailru", name: "Mailru"},
|
|
|
|
|
{id: "Meetup", name: "Meetup"},
|
|
|
|
|
{id: "MicrosoftOnline", name: "MicrosoftOnline"},
|
|
|
|
|
{id: "Naver", name: "Naver"},
|
|
|
|
|
{id: "Nextcloud", name: "Nextcloud"},
|
|
|
|
|
{id: "OneDrive", name: "OneDrive"},
|
|
|
|
|
{id: "Oura", name: "Oura"},
|
|
|
|
|
{id: "Patreon", name: "Patreon"},
|
2023-03-18 18:54:05 +08:00
|
|
|
|
{id: "PayPal", name: "PayPal"},
|
2023-02-04 12:20:18 +08:00
|
|
|
|
{id: "SalesForce", name: "SalesForce"},
|
|
|
|
|
{id: "Shopify", name: "Shopify"},
|
|
|
|
|
{id: "Soundcloud", name: "Soundcloud"},
|
|
|
|
|
{id: "Spotify", name: "Spotify"},
|
|
|
|
|
{id: "Strava", name: "Strava"},
|
|
|
|
|
{id: "Stripe", name: "Stripe"},
|
|
|
|
|
{id: "TikTok", name: "TikTok"},
|
|
|
|
|
{id: "Tumblr", name: "Tumblr"},
|
|
|
|
|
{id: "Twitch", name: "Twitch"},
|
|
|
|
|
{id: "Twitter", name: "Twitter"},
|
|
|
|
|
{id: "Typetalk", name: "Typetalk"},
|
|
|
|
|
{id: "Uber", name: "Uber"},
|
|
|
|
|
{id: "VK", name: "VK"},
|
|
|
|
|
{id: "Wepay", name: "Wepay"},
|
|
|
|
|
{id: "Xero", name: "Xero"},
|
|
|
|
|
{id: "Yahoo", name: "Yahoo"},
|
|
|
|
|
{id: "Yammer", name: "Yammer"},
|
|
|
|
|
{id: "Yandex", name: "Yandex"},
|
|
|
|
|
{id: "Zoom", name: "Zoom"},
|
2022-07-10 15:45:55 +08:00
|
|
|
|
{id: "Custom", name: "Custom"},
|
2021-12-25 10:55:10 +08:00
|
|
|
|
]
|
|
|
|
|
);
|
|
|
|
|
} else if (category === "Email") {
|
|
|
|
|
return (
|
|
|
|
|
[
|
2022-07-10 15:45:55 +08:00
|
|
|
|
{id: "Default", name: "Default"},
|
2022-09-04 11:21:20 +08:00
|
|
|
|
{id: "SUBMAIL", name: "SUBMAIL"},
|
2023-02-11 15:59:23 +08:00
|
|
|
|
{id: "Mailtrap", name: "Mailtrap"},
|
2023-09-12 02:13:37 +08:00
|
|
|
|
{id: "Azure ACS", name: "Azure ACS"},
|
2024-04-09 22:16:01 +08:00
|
|
|
|
{id: "SendGrid", name: "SendGrid"},
|
2023-12-14 22:35:25 +08:00
|
|
|
|
{id: "Custom HTTP Email", name: "Custom HTTP Email"},
|
2021-12-25 10:55:10 +08:00
|
|
|
|
]
|
|
|
|
|
);
|
|
|
|
|
} else if (category === "SMS") {
|
|
|
|
|
return (
|
|
|
|
|
[
|
2023-08-05 17:52:16 +08:00
|
|
|
|
{id: "Aliyun SMS", name: "Alibaba Cloud SMS"},
|
2023-08-07 00:59:17 +08:00
|
|
|
|
{id: "Amazon SNS", name: "Amazon SNS"},
|
|
|
|
|
{id: "Azure ACS", name: "Azure ACS"},
|
2023-12-07 16:59:41 +08:00
|
|
|
|
{id: "Custom HTTP SMS", name: "Custom HTTP SMS"},
|
|
|
|
|
{id: "Mock SMS", name: "Mock SMS"},
|
2024-03-03 22:05:53 +05:00
|
|
|
|
{id: "OSON SMS", name: "OSON SMS"},
|
2023-08-07 00:59:17 +08:00
|
|
|
|
{id: "Infobip SMS", name: "Infobip SMS"},
|
2022-07-10 15:45:55 +08:00
|
|
|
|
{id: "Tencent Cloud SMS", name: "Tencent Cloud SMS"},
|
2023-08-07 00:59:17 +08:00
|
|
|
|
{id: "Baidu Cloud SMS", name: "Baidu Cloud SMS"},
|
2022-07-10 15:45:55 +08:00
|
|
|
|
{id: "Volc Engine SMS", name: "Volc Engine SMS"},
|
|
|
|
|
{id: "Huawei Cloud SMS", name: "Huawei Cloud SMS"},
|
2023-08-07 00:59:17 +08:00
|
|
|
|
{id: "UCloud SMS", name: "UCloud SMS"},
|
2022-09-25 17:58:12 +08:00
|
|
|
|
{id: "Twilio SMS", name: "Twilio SMS"},
|
2022-09-27 08:37:55 +08:00
|
|
|
|
{id: "SmsBao SMS", name: "SmsBao SMS"},
|
2023-03-06 21:23:45 +08:00
|
|
|
|
{id: "SUBMAIL SMS", name: "SUBMAIL SMS"},
|
2023-08-07 00:59:17 +08:00
|
|
|
|
{id: "Msg91 SMS", name: "Msg91 SMS"},
|
2021-12-25 10:55:10 +08:00
|
|
|
|
]
|
|
|
|
|
);
|
|
|
|
|
} else if (category === "Storage") {
|
|
|
|
|
return (
|
|
|
|
|
[
|
2022-07-10 15:45:55 +08:00
|
|
|
|
{id: "Local File System", name: "Local File System"},
|
|
|
|
|
{id: "AWS S3", name: "AWS S3"},
|
2022-08-20 00:30:13 -03:00
|
|
|
|
{id: "MinIO", name: "MinIO"},
|
2023-08-26 23:39:02 +08:00
|
|
|
|
{id: "Aliyun OSS", name: "Alibaba Cloud OSS"},
|
2022-07-10 15:45:55 +08:00
|
|
|
|
{id: "Tencent Cloud COS", name: "Tencent Cloud COS"},
|
2022-08-06 23:54:56 +08:00
|
|
|
|
{id: "Azure Blob", name: "Azure Blob"},
|
2023-08-08 22:30:19 +08:00
|
|
|
|
{id: "Qiniu Cloud Kodo", name: "Qiniu Cloud Kodo"},
|
|
|
|
|
{id: "Google Cloud Storage", name: "Google Cloud Storage"},
|
2024-01-14 22:38:31 +08:00
|
|
|
|
{id: "Synology", name: "Synology"},
|
2024-08-27 23:54:03 +08:00
|
|
|
|
{id: "Casdoor", name: "Casdoor"},
|
2024-12-08 20:24:38 +08:00
|
|
|
|
{id: "CUCloud OSS", name: "CUCloud OSS"},
|
2021-12-25 10:55:10 +08:00
|
|
|
|
]
|
|
|
|
|
);
|
|
|
|
|
} else if (category === "SAML") {
|
|
|
|
|
return ([
|
2022-07-10 15:45:55 +08:00
|
|
|
|
{id: "Aliyun IDaaS", name: "Aliyun IDaaS"},
|
|
|
|
|
{id: "Keycloak", name: "Keycloak"},
|
2023-10-20 21:11:36 +08:00
|
|
|
|
{id: "Custom", name: "Custom"},
|
2021-12-25 10:55:10 +08:00
|
|
|
|
]);
|
2022-02-05 01:18:13 +08:00
|
|
|
|
} else if (category === "Payment") {
|
|
|
|
|
return ([
|
2023-05-30 23:25:58 +08:00
|
|
|
|
{id: "Dummy", name: "Dummy"},
|
2024-07-12 15:48:37 +08:00
|
|
|
|
{id: "Balance", name: "Balance"},
|
2022-07-10 15:45:55 +08:00
|
|
|
|
{id: "Alipay", name: "Alipay"},
|
|
|
|
|
{id: "WeChat Pay", name: "WeChat Pay"},
|
|
|
|
|
{id: "PayPal", name: "PayPal"},
|
2023-08-15 00:16:30 +08:00
|
|
|
|
{id: "Stripe", name: "Stripe"},
|
2025-02-07 19:19:30 +08:00
|
|
|
|
{id: "AirWallex", name: "AirWallex"},
|
2022-07-10 15:45:55 +08:00
|
|
|
|
{id: "GC", name: "GC"},
|
2022-02-05 01:18:13 +08:00
|
|
|
|
]);
|
2022-06-18 16:00:31 +08:00
|
|
|
|
} else if (category === "Captcha") {
|
|
|
|
|
return ([
|
2022-07-10 15:45:55 +08:00
|
|
|
|
{id: "Default", name: "Default"},
|
2024-09-02 22:15:03 +08:00
|
|
|
|
{id: "reCAPTCHA v2", name: "reCAPTCHA v2"},
|
|
|
|
|
{id: "reCAPTCHA v3", name: "reCAPTCHA v3"},
|
2022-07-10 15:45:55 +08:00
|
|
|
|
{id: "hCaptcha", name: "hCaptcha"},
|
|
|
|
|
{id: "Aliyun Captcha", name: "Aliyun Captcha"},
|
2022-08-04 20:55:04 +08:00
|
|
|
|
{id: "GEETEST", name: "GEETEST"},
|
2022-11-26 17:17:49 +08:00
|
|
|
|
{id: "Cloudflare Turnstile", name: "Cloudflare Turnstile"},
|
2022-06-18 16:00:31 +08:00
|
|
|
|
]);
|
2023-07-20 17:51:36 +08:00
|
|
|
|
} else if (category === "Web3") {
|
|
|
|
|
return ([
|
|
|
|
|
{id: "MetaMask", name: "MetaMask"},
|
2023-08-13 23:58:57 +08:00
|
|
|
|
{id: "Web3Onboard", name: "Web3-Onboard"},
|
2023-07-20 17:51:36 +08:00
|
|
|
|
]);
|
2023-08-19 12:33:00 +08:00
|
|
|
|
} else if (category === "Notification") {
|
|
|
|
|
return ([
|
|
|
|
|
{id: "Telegram", name: "Telegram"},
|
2023-08-20 21:04:30 +08:00
|
|
|
|
{id: "Custom HTTP", name: "Custom HTTP"},
|
2023-09-05 17:05:34 +08:00
|
|
|
|
{id: "DingTalk", name: "DingTalk"},
|
|
|
|
|
{id: "Lark", name: "Lark"},
|
|
|
|
|
{id: "Microsoft Teams", name: "Microsoft Teams"},
|
|
|
|
|
{id: "Bark", name: "Bark"},
|
|
|
|
|
{id: "Pushover", name: "Pushover"},
|
|
|
|
|
{id: "Pushbullet", name: "Pushbullet"},
|
|
|
|
|
{id: "Slack", name: "Slack"},
|
|
|
|
|
{id: "Webpush", name: "Webpush"},
|
|
|
|
|
{id: "Discord", name: "Discord"},
|
|
|
|
|
{id: "Google Chat", name: "Google Chat"},
|
|
|
|
|
{id: "Line", name: "Line"},
|
|
|
|
|
{id: "Matrix", name: "Matrix"},
|
|
|
|
|
{id: "Twitter", name: "Twitter"},
|
|
|
|
|
{id: "Reddit", name: "Reddit"},
|
|
|
|
|
{id: "Rocket Chat", name: "Rocket Chat"},
|
|
|
|
|
{id: "Viber", name: "Viber"},
|
2025-01-17 08:35:31 +08:00
|
|
|
|
{id: "CUCloud", name: "CUCloud"},
|
2023-08-19 12:33:00 +08:00
|
|
|
|
]);
|
2025-03-19 22:57:35 +08:00
|
|
|
|
} else if (category === "Face ID") {
|
|
|
|
|
return ([
|
|
|
|
|
{id: "Alibaba Cloud Facebody", name: "Alibaba Cloud Facebody"},
|
|
|
|
|
]);
|
2021-12-25 10:55:10 +08:00
|
|
|
|
} else {
|
|
|
|
|
return [];
|
2023-11-13 15:57:46 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function getCryptoAlgorithmOptions(cryptoAlgorithm) {
|
2024-03-10 19:30:05 +08:00
|
|
|
|
if (cryptoAlgorithm.startsWith("ES")) {
|
|
|
|
|
return [];
|
|
|
|
|
} else {
|
2023-11-13 15:57:46 +08:00
|
|
|
|
return (
|
|
|
|
|
[
|
|
|
|
|
{id: 1024, name: "1024"},
|
|
|
|
|
{id: 2048, name: "2048"},
|
|
|
|
|
{id: 4096, name: "4096"},
|
|
|
|
|
]
|
|
|
|
|
);
|
2021-12-25 10:55:10 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-28 15:54:50 +08:00
|
|
|
|
export function renderLogo(application) {
|
|
|
|
|
if (application === null) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (application.homepageUrl !== "") {
|
|
|
|
|
return (
|
|
|
|
|
<a target="_blank" rel="noreferrer" href={application.homepageUrl}>
|
2022-12-06 00:50:17 +08:00
|
|
|
|
<img className="panel-logo" width={250} src={application.logo} alt={application.displayName} />
|
2021-04-28 15:54:50 +08:00
|
|
|
|
</a>
|
2022-07-10 15:45:55 +08:00
|
|
|
|
);
|
2021-04-28 15:54:50 +08:00
|
|
|
|
} else {
|
|
|
|
|
return (
|
2022-12-06 00:50:17 +08:00
|
|
|
|
<img className="panel-logo" width={250} src={application.logo} alt={application.displayName} />
|
2021-04-28 15:54:50 +08:00
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-04-28 22:40:21 +08:00
|
|
|
|
|
2024-01-13 11:35:06 +08:00
|
|
|
|
function isSigninMethodEnabled(application, signinMethod) {
|
|
|
|
|
if (application && application.signinMethods) {
|
2024-12-07 21:22:57 +08:00
|
|
|
|
return application.signinMethods.filter(item => item.name === signinMethod && item.rule !== "Hide password").length > 0;
|
2024-01-02 21:11:52 +08:00
|
|
|
|
} else {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-13 11:35:06 +08:00
|
|
|
|
export function isPasswordEnabled(application) {
|
|
|
|
|
return isSigninMethodEnabled(application, "Password");
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-02 21:11:52 +08:00
|
|
|
|
export function isCodeSigninEnabled(application) {
|
2024-01-13 11:35:06 +08:00
|
|
|
|
return isSigninMethodEnabled(application, "Verification code");
|
2024-01-02 21:11:52 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function isWebAuthnEnabled(application) {
|
2024-01-13 11:35:06 +08:00
|
|
|
|
return isSigninMethodEnabled(application, "WebAuthn");
|
2024-01-02 21:11:52 +08:00
|
|
|
|
}
|
|
|
|
|
|
2024-01-08 21:07:34 +08:00
|
|
|
|
export function isLdapEnabled(application) {
|
2024-01-13 11:35:06 +08:00
|
|
|
|
return isSigninMethodEnabled(application, "LDAP");
|
2024-01-08 21:07:34 +08:00
|
|
|
|
}
|
|
|
|
|
|
2024-03-16 09:04:00 +08:00
|
|
|
|
export function isFaceIdEnabled(application) {
|
|
|
|
|
return isSigninMethodEnabled(application, "Face ID");
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-27 20:23:57 +02:00
|
|
|
|
export function getLoginLink(application) {
|
|
|
|
|
let url;
|
2021-04-28 22:40:21 +08:00
|
|
|
|
if (application === null) {
|
2022-10-27 20:23:57 +02:00
|
|
|
|
url = null;
|
2024-02-20 17:40:39 +08:00
|
|
|
|
} else if (window.location.pathname.includes("/signup/oauth/authorize")) {
|
2024-02-24 12:59:09 +08:00
|
|
|
|
url = window.location.pathname.replace("/signup/oauth/authorize", "/login/oauth/authorize");
|
2022-10-27 20:23:57 +02:00
|
|
|
|
} else if (authConfig.appName === application.name) {
|
|
|
|
|
url = "/login";
|
|
|
|
|
} else if (application.signinUrl === "") {
|
2023-04-21 23:56:33 +08:00
|
|
|
|
url = trim(application.homepageUrl, "/") + "/login";
|
2022-10-27 20:23:57 +02:00
|
|
|
|
} else {
|
|
|
|
|
url = application.signinUrl;
|
2021-04-28 22:40:21 +08:00
|
|
|
|
}
|
2024-02-24 12:59:09 +08:00
|
|
|
|
return url + window.location.search;
|
2022-10-27 20:23:57 +02:00
|
|
|
|
}
|
2021-04-28 22:40:21 +08:00
|
|
|
|
|
2022-11-13 05:16:49 +01:00
|
|
|
|
export function redirectToLoginPage(application, history) {
|
2022-10-27 20:23:57 +02:00
|
|
|
|
const loginLink = getLoginLink(application);
|
2023-04-21 23:56:33 +08:00
|
|
|
|
if (loginLink.startsWith("http://") || loginLink.startsWith("https://")) {
|
|
|
|
|
goToLink(loginLink);
|
|
|
|
|
} else {
|
|
|
|
|
history.push(loginLink);
|
2022-12-23 04:05:15 +01:00
|
|
|
|
}
|
2021-04-28 22:40:21 +08:00
|
|
|
|
}
|
2021-04-29 21:28:24 +08:00
|
|
|
|
|
2022-10-22 23:48:59 +08:00
|
|
|
|
function renderLink(url, text, onClick) {
|
2022-10-22 17:17:50 +02:00
|
|
|
|
if (url === null) {
|
2022-10-22 23:48:59 +08:00
|
|
|
|
return null;
|
2021-05-03 00:48:02 +08:00
|
|
|
|
}
|
2022-10-22 23:48:59 +08:00
|
|
|
|
|
2022-10-22 17:17:50 +02:00
|
|
|
|
if (url.startsWith("/")) {
|
2022-10-22 23:48:59 +08:00
|
|
|
|
return (
|
|
|
|
|
<Link style={{float: "right"}} to={url} onClick={() => {
|
|
|
|
|
if (onClick !== null) {
|
|
|
|
|
onClick();
|
|
|
|
|
}
|
|
|
|
|
}}>{text}</Link>
|
|
|
|
|
);
|
2022-10-22 17:17:50 +02:00
|
|
|
|
} else if (url.startsWith("http")) {
|
2022-10-22 23:48:59 +08:00
|
|
|
|
return (
|
2024-02-14 09:45:21 +08:00
|
|
|
|
<a style={{float: "right"}} href={url} onClick={() => {
|
2022-10-22 23:48:59 +08:00
|
|
|
|
if (onClick !== null) {
|
|
|
|
|
onClick();
|
|
|
|
|
}
|
|
|
|
|
}}>{text}</a>
|
|
|
|
|
);
|
2022-10-22 17:17:50 +02:00
|
|
|
|
} else {
|
2022-10-22 23:48:59 +08:00
|
|
|
|
return null;
|
2021-06-14 23:23:59 +08:00
|
|
|
|
}
|
2022-10-22 17:17:50 +02:00
|
|
|
|
}
|
2021-06-14 23:23:59 +08:00
|
|
|
|
|
2022-10-22 17:17:50 +02:00
|
|
|
|
export function renderSignupLink(application, text) {
|
2022-10-22 23:48:59 +08:00
|
|
|
|
let url;
|
2022-10-22 17:17:50 +02:00
|
|
|
|
if (application === null) {
|
2022-10-22 23:48:59 +08:00
|
|
|
|
url = null;
|
2024-02-14 09:45:21 +08:00
|
|
|
|
} else if (window.location.pathname.includes("/login/oauth/authorize")) {
|
2024-02-24 12:59:09 +08:00
|
|
|
|
url = window.location.pathname.replace("/login/oauth/authorize", "/signup/oauth/authorize");
|
2022-10-22 17:17:50 +02:00
|
|
|
|
} else if (authConfig.appName === application.name) {
|
2022-10-22 23:48:59 +08:00
|
|
|
|
url = "/signup";
|
2021-05-03 00:48:02 +08:00
|
|
|
|
} else {
|
|
|
|
|
if (application.signupUrl === "") {
|
2022-10-22 23:48:59 +08:00
|
|
|
|
url = `/signup/${application.name}`;
|
2021-05-03 00:48:02 +08:00
|
|
|
|
} else {
|
2022-10-22 23:48:59 +08:00
|
|
|
|
url = application.signupUrl;
|
2021-05-03 00:48:02 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2022-10-22 17:17:50 +02:00
|
|
|
|
|
2022-10-22 23:48:59 +08:00
|
|
|
|
const storeSigninUrl = () => {
|
2024-02-24 12:59:09 +08:00
|
|
|
|
sessionStorage.setItem("signinUrl", window.location.pathname + window.location.search);
|
2022-10-22 23:48:59 +08:00
|
|
|
|
};
|
|
|
|
|
|
2024-02-24 12:59:09 +08:00
|
|
|
|
return renderLink(url + window.location.search, text, storeSigninUrl);
|
2021-05-03 00:48:02 +08:00
|
|
|
|
}
|
|
|
|
|
|
2022-10-22 17:17:50 +02:00
|
|
|
|
export function renderForgetLink(application, text) {
|
2022-10-22 23:48:59 +08:00
|
|
|
|
let url;
|
2021-05-03 00:48:02 +08:00
|
|
|
|
if (application === null) {
|
2022-10-22 23:48:59 +08:00
|
|
|
|
url = null;
|
2022-10-22 17:17:50 +02:00
|
|
|
|
} else if (authConfig.appName === application.name) {
|
2022-10-22 23:48:59 +08:00
|
|
|
|
url = "/forget";
|
2021-05-03 00:48:02 +08:00
|
|
|
|
} else {
|
2021-06-04 01:21:53 +08:00
|
|
|
|
if (application.forgetUrl === "") {
|
2022-10-22 23:48:59 +08:00
|
|
|
|
url = `/forget/${application.name}`;
|
2021-05-03 00:48:02 +08:00
|
|
|
|
} else {
|
2022-10-22 23:48:59 +08:00
|
|
|
|
url = application.forgetUrl;
|
2021-05-03 00:48:02 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2022-10-22 23:48:59 +08:00
|
|
|
|
|
2024-02-14 02:36:52 +08:00
|
|
|
|
const storeSigninUrl = () => {
|
2024-02-24 12:59:09 +08:00
|
|
|
|
sessionStorage.setItem("signinUrl", window.location.pathname + window.location.search);
|
2024-02-14 02:36:52 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return renderLink(url, text, storeSigninUrl);
|
2021-05-03 00:48:02 +08:00
|
|
|
|
}
|
|
|
|
|
|
2021-04-29 21:28:24 +08:00
|
|
|
|
export function renderHelmet(application) {
|
2022-08-06 23:43:09 +08:00
|
|
|
|
if (application === undefined || application === null || application.organizationObj === undefined || application.organizationObj === null || application.organizationObj === "") {
|
2021-04-29 21:28:24 +08:00
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<Helmet>
|
|
|
|
|
<title>{application.organizationObj.displayName}</title>
|
|
|
|
|
<link rel="icon" href={application.organizationObj.favicon} />
|
|
|
|
|
</Helmet>
|
2022-07-10 15:45:55 +08:00
|
|
|
|
);
|
2021-04-29 21:28:24 +08:00
|
|
|
|
}
|
2021-06-25 00:13:43 +08:00
|
|
|
|
|
|
|
|
|
export function getLabel(text, tooltip) {
|
|
|
|
|
return (
|
|
|
|
|
<React.Fragment>
|
2022-07-10 15:45:55 +08:00
|
|
|
|
<span style={{marginRight: 4}}>{text}</span>
|
2021-06-25 00:13:43 +08:00
|
|
|
|
<Tooltip placement="top" title={tooltip}>
|
|
|
|
|
<QuestionCircleTwoTone twoToneColor="rgb(45,120,213)" />
|
|
|
|
|
</Tooltip>
|
|
|
|
|
</React.Fragment>
|
|
|
|
|
);
|
|
|
|
|
}
|
2021-06-25 21:35:20 +08:00
|
|
|
|
|
2022-12-04 23:05:30 +08:00
|
|
|
|
export function getItem(label, key, icon, children, type) {
|
2023-08-05 17:41:35 +08:00
|
|
|
|
return {label: label, key: key, icon: icon, children: children, type: type};
|
2022-12-04 23:05:30 +08:00
|
|
|
|
}
|
2023-01-12 23:11:11 +08:00
|
|
|
|
|
|
|
|
|
export function getOption(label, value) {
|
|
|
|
|
return {
|
|
|
|
|
label,
|
|
|
|
|
value,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-09 23:05:50 +08:00
|
|
|
|
export function getArrayItem(array, key, value) {
|
|
|
|
|
const res = array.filter(item => item[key] === value)[0];
|
|
|
|
|
return res;
|
|
|
|
|
}
|
2021-07-09 23:12:13 +08:00
|
|
|
|
|
|
|
|
|
export function getDeduplicatedArray(array, filterArray, key) {
|
2023-05-05 21:23:59 +08:00
|
|
|
|
const res = array.filter(item => !filterArray.some(tableItem => tableItem[key] === item[key]));
|
2021-07-09 23:12:13 +08:00
|
|
|
|
return res;
|
|
|
|
|
}
|
2021-11-07 15:41:24 +08:00
|
|
|
|
|
2021-11-28 18:21:34 +08:00
|
|
|
|
export function getNewRowNameForTable(table, rowName) {
|
|
|
|
|
const emptyCount = table.filter(row => row.name.includes(rowName)).length;
|
|
|
|
|
let res = rowName;
|
2022-08-06 23:43:09 +08:00
|
|
|
|
for (let i = 0; i < emptyCount; i++) {
|
2021-11-28 18:21:34 +08:00
|
|
|
|
res = res + " ";
|
|
|
|
|
}
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-07 15:41:24 +08:00
|
|
|
|
export function getTagColor(s) {
|
2022-01-01 15:11:16 +08:00
|
|
|
|
return "processing";
|
2021-11-07 15:41:24 +08:00
|
|
|
|
}
|
|
|
|
|
|
2023-04-09 14:47:08 +08:00
|
|
|
|
export function getTags(tags, urlPrefix = null) {
|
2022-08-08 23:35:24 +08:00
|
|
|
|
const res = [];
|
2022-08-21 23:17:14 +08:00
|
|
|
|
if (!tags) {
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-07 15:41:24 +08:00
|
|
|
|
tags.forEach((tag, i) => {
|
2023-04-09 14:47:08 +08:00
|
|
|
|
if (urlPrefix === null) {
|
|
|
|
|
res.push(
|
|
|
|
|
<Tag color={getTagColor(tag)}>
|
|
|
|
|
{tag}
|
|
|
|
|
</Tag>
|
|
|
|
|
);
|
|
|
|
|
} else {
|
|
|
|
|
res.push(
|
|
|
|
|
<Link to={`/${urlPrefix}/${tag}`}>
|
|
|
|
|
<Tag color={getTagColor(tag)}>
|
|
|
|
|
{tag}
|
|
|
|
|
</Tag>
|
|
|
|
|
</Link>
|
|
|
|
|
);
|
|
|
|
|
}
|
2021-11-07 15:41:24 +08:00
|
|
|
|
});
|
|
|
|
|
return res;
|
|
|
|
|
}
|
2021-11-28 20:57:14 +08:00
|
|
|
|
|
2023-08-24 23:20:50 +08:00
|
|
|
|
export function getTag(color, text, icon) {
|
2022-08-21 23:17:14 +08:00
|
|
|
|
return (
|
2023-08-24 23:20:50 +08:00
|
|
|
|
<Tag color={color} icon={icon}>
|
2022-08-21 23:17:14 +08:00
|
|
|
|
{text}
|
|
|
|
|
</Tag>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2022-07-10 00:40:52 +08:00
|
|
|
|
export function getApplicationName(application) {
|
2025-02-06 15:33:23 +05:30
|
|
|
|
let name = `${application?.owner}/${application?.name}`;
|
|
|
|
|
|
|
|
|
|
if (application?.isShared && application?.organization) {
|
|
|
|
|
name += `-org-${application.organization}`;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return name;
|
2022-07-10 00:40:52 +08:00
|
|
|
|
}
|
|
|
|
|
|
2024-08-09 15:43:25 +08:00
|
|
|
|
export function getApplicationDisplayName(application) {
|
|
|
|
|
if (application.isShared) {
|
|
|
|
|
return `${application.name}(Shared)`;
|
|
|
|
|
}
|
|
|
|
|
return application.name;
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-12 18:51:12 +08:00
|
|
|
|
export function getRandomName() {
|
|
|
|
|
return Math.random().toString(36).slice(-6);
|
|
|
|
|
}
|
2021-12-23 21:28:40 +08:00
|
|
|
|
|
|
|
|
|
export function getRandomNumber() {
|
|
|
|
|
return Math.random().toString(10).slice(-11);
|
|
|
|
|
}
|
2022-02-12 09:55:06 +08:00
|
|
|
|
|
|
|
|
|
export function getFromLink() {
|
|
|
|
|
const from = sessionStorage.getItem("from");
|
|
|
|
|
if (from === null) {
|
|
|
|
|
return "/";
|
|
|
|
|
}
|
|
|
|
|
return from;
|
|
|
|
|
}
|
2022-04-06 20:38:14 +08:00
|
|
|
|
|
2022-04-27 01:06:54 +08:00
|
|
|
|
export function scrollToDiv(divId) {
|
|
|
|
|
if (divId) {
|
2022-08-08 23:35:24 +08:00
|
|
|
|
const ele = document.getElementById(divId);
|
2022-04-27 01:06:54 +08:00
|
|
|
|
if (ele) {
|
|
|
|
|
ele.scrollIntoView({behavior: "smooth"});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-12 00:01:18 +08:00
|
|
|
|
export function inIframe() {
|
|
|
|
|
try {
|
|
|
|
|
return window !== window.parent;
|
|
|
|
|
} catch (e) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-06-29 20:32:34 +03:00
|
|
|
|
|
|
|
|
|
export function getOrganization() {
|
|
|
|
|
const organization = localStorage.getItem("organization");
|
2023-06-30 01:38:48 +08:00
|
|
|
|
return organization !== null ? organization : "All";
|
2023-06-29 20:32:34 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function setOrganization(organization) {
|
|
|
|
|
localStorage.setItem("organization", organization);
|
2023-06-30 01:38:48 +08:00
|
|
|
|
window.dispatchEvent(new Event("storageOrganizationChanged"));
|
2023-06-29 20:32:34 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function getRequestOrganization(account) {
|
|
|
|
|
if (isAdminUser(account)) {
|
2023-06-30 01:38:48 +08:00
|
|
|
|
return getOrganization() === "All" ? account.owner : getOrganization();
|
2023-06-29 20:32:34 +03:00
|
|
|
|
}
|
|
|
|
|
return account.owner;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function isDefaultOrganizationSelected(account) {
|
|
|
|
|
if (isAdminUser(account)) {
|
2023-06-30 01:38:48 +08:00
|
|
|
|
return getOrganization() === "All";
|
2023-06-29 20:32:34 +03:00
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2023-07-29 15:07:04 +08:00
|
|
|
|
|
|
|
|
|
const BuiltInObjects = [
|
|
|
|
|
"api-enforcer-built-in",
|
2023-08-06 13:07:30 +08:00
|
|
|
|
"user-enforcer-built-in",
|
2023-07-29 15:07:04 +08:00
|
|
|
|
"api-model-built-in",
|
2023-08-06 13:07:30 +08:00
|
|
|
|
"user-model-built-in",
|
2023-07-29 15:07:04 +08:00
|
|
|
|
"api-adapter-built-in",
|
2023-08-06 13:07:30 +08:00
|
|
|
|
"user-adapter-built-in",
|
2023-07-29 15:07:04 +08:00
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
export function builtInObject(obj) {
|
|
|
|
|
if (obj === undefined || obj === null) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return obj.owner === "built-in" && BuiltInObjects.includes(obj.name);
|
|
|
|
|
}
|
2023-08-24 23:20:50 +08:00
|
|
|
|
|
|
|
|
|
export function getCurrencySymbol(currency) {
|
|
|
|
|
if (currency === "USD" || currency === "usd") {
|
|
|
|
|
return "$";
|
|
|
|
|
} else if (currency === "CNY" || currency === "cny") {
|
|
|
|
|
return "¥";
|
|
|
|
|
} else {
|
|
|
|
|
return currency;
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-12-30 00:47:10 +08:00
|
|
|
|
|
|
|
|
|
export function getFriendlyUserName(account) {
|
|
|
|
|
if (account.firstName !== "" && account.lastName !== "") {
|
|
|
|
|
return `${account.firstName}, ${account.lastName}`;
|
|
|
|
|
} else if (account.displayName !== "") {
|
|
|
|
|
return account.displayName;
|
|
|
|
|
} else if (account.name !== "") {
|
|
|
|
|
return account.name;
|
|
|
|
|
} else {
|
|
|
|
|
return account.id;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-09 22:09:21 +08:00
|
|
|
|
export function getUserCommonFields() {
|
2024-01-30 07:18:32 -08:00
|
|
|
|
return ["Owner", "Name", "CreatedTime", "UpdatedTime", "DeletedTime", "Id", "Type", "Password", "PasswordSalt", "DisplayName", "FirstName", "LastName", "Avatar", "PermanentAvatar",
|
2024-01-09 22:09:21 +08:00
|
|
|
|
"Email", "EmailVerified", "Phone", "Location", "Address", "Affiliation", "Title", "IdCardType", "IdCard", "Homepage", "Bio", "Tag", "Region",
|
|
|
|
|
"Language", "Gender", "Birthday", "Education", "Score", "Ranking", "IsDefaultAvatar", "IsOnline", "IsAdmin", "IsForbidden", "IsDeleted", "CreatedIp",
|
2024-05-27 01:06:59 +08:00
|
|
|
|
"PreferredMfaType", "TotpSecret", "SignupApplication", "RecoveryCodes", "MfaPhoneEnabled", "MfaEmailEnabled"];
|
2024-01-09 22:09:21 +08:00
|
|
|
|
}
|
|
|
|
|
|
2024-03-08 23:11:03 +08:00
|
|
|
|
export function getDefaultFooterContent() {
|
2025-03-26 21:32:23 +08:00
|
|
|
|
return `Powered by <a target="_blank" href="https://casdoor.org" rel="noreferrer"><img style="padding-bottom: 3px" height="20" alt="Casdoor" src="${StaticBaseUrl}/img/casdoor-logo_1185x256.png"/></a>`;
|
2024-03-08 23:11:03 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function getEmptyFooterContent() {
|
|
|
|
|
return `<style>
|
|
|
|
|
#footer {
|
|
|
|
|
display: none;
|
|
|
|
|
}
|
|
|
|
|
<style>
|
|
|
|
|
`;
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-30 00:47:10 +08:00
|
|
|
|
export function getDefaultHtmlEmailContent() {
|
|
|
|
|
return `<!DOCTYPE html>
|
|
|
|
|
<html lang="en">
|
|
|
|
|
<head>
|
|
|
|
|
<meta charset="UTF-8">
|
|
|
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
|
|
|
<title>Verification Code Email</title>
|
|
|
|
|
<style>
|
|
|
|
|
body { font-family: Arial, sans-serif; }
|
|
|
|
|
.email-container { width: 600px; margin: 0 auto; }
|
|
|
|
|
.header { text-align: center; }
|
|
|
|
|
.code { font-size: 24px; margin: 20px 0; text-align: center; }
|
|
|
|
|
.footer { font-size: 12px; text-align: center; margin-top: 50px; }
|
|
|
|
|
.footer a { color: #000; text-decoration: none; }
|
|
|
|
|
</style>
|
|
|
|
|
</head>
|
|
|
|
|
<body>
|
|
|
|
|
<div class="email-container">
|
|
|
|
|
<div class="header">
|
|
|
|
|
<h3>Casbin Organization</h3>
|
2025-03-26 21:32:23 +08:00
|
|
|
|
<img src="${StaticBaseUrl}/img/casdoor-logo_1185x256.png" alt="Casdoor Logo" width="300">
|
2023-12-30 00:47:10 +08:00
|
|
|
|
</div>
|
|
|
|
|
<p><strong>%{user.friendlyName}</strong>, here is your verification code</p>
|
|
|
|
|
<p>Use this code for your transaction. It's valid for 5 minutes</p>
|
|
|
|
|
<div class="code">
|
|
|
|
|
%s
|
|
|
|
|
</div>
|
|
|
|
|
<p>Thanks</p>
|
|
|
|
|
<p>Casbin Team</p>
|
|
|
|
|
<hr>
|
|
|
|
|
<div class="footer">
|
|
|
|
|
<p>Casdoor is a brand operated by Casbin organization. For more info please refer to <a href="https://casdoor.org">https://casdoor.org</a></p>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</body>
|
|
|
|
|
</html>`;
|
|
|
|
|
}
|
2024-06-22 14:05:53 +08:00
|
|
|
|
|
|
|
|
|
export function getCurrencyText(product) {
|
|
|
|
|
if (product?.currency === "USD") {
|
2024-12-07 21:22:57 +08:00
|
|
|
|
return i18next.t("currency:USD");
|
2024-06-22 14:05:53 +08:00
|
|
|
|
} else if (product?.currency === "CNY") {
|
2024-12-07 21:22:57 +08:00
|
|
|
|
return i18next.t("currency:CNY");
|
2024-12-01 21:46:44 +08:00
|
|
|
|
} else if (product?.currency === "EUR") {
|
2024-12-07 21:22:57 +08:00
|
|
|
|
return i18next.t("currency:EUR");
|
2024-12-01 21:46:44 +08:00
|
|
|
|
} else if (product?.currency === "JPY") {
|
2024-12-07 21:22:57 +08:00
|
|
|
|
return i18next.t("currency:JPY");
|
2024-12-01 21:46:44 +08:00
|
|
|
|
} else if (product?.currency === "GBP") {
|
2024-12-07 21:22:57 +08:00
|
|
|
|
return i18next.t("currency:GBP");
|
2024-12-01 21:46:44 +08:00
|
|
|
|
} else if (product?.currency === "AUD") {
|
2024-12-07 21:22:57 +08:00
|
|
|
|
return i18next.t("currency:AUD");
|
2024-12-01 21:46:44 +08:00
|
|
|
|
} else if (product?.currency === "CAD") {
|
2024-12-07 21:22:57 +08:00
|
|
|
|
return i18next.t("currency:CAD");
|
2024-12-01 21:46:44 +08:00
|
|
|
|
} else if (product?.currency === "CHF") {
|
2024-12-07 21:22:57 +08:00
|
|
|
|
return i18next.t("currency:CHF");
|
2024-12-01 21:46:44 +08:00
|
|
|
|
} else if (product?.currency === "HKD") {
|
2024-12-07 21:22:57 +08:00
|
|
|
|
return i18next.t("currency:HKD");
|
2024-12-01 21:46:44 +08:00
|
|
|
|
} else if (product?.currency === "SGD") {
|
2024-12-07 21:22:57 +08:00
|
|
|
|
return i18next.t("currency:SGD");
|
2025-04-11 22:24:34 +08:00
|
|
|
|
} else if (product?.currency === "BRL") {
|
|
|
|
|
return i18next.t("currency:BRL");
|
2024-06-22 14:05:53 +08:00
|
|
|
|
} else {
|
|
|
|
|
return "(Unknown currency)";
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-10-13 22:31:54 +08:00
|
|
|
|
|
|
|
|
|
export function isDarkTheme(themeAlgorithm) {
|
|
|
|
|
return themeAlgorithm && themeAlgorithm.includes("dark");
|
|
|
|
|
}
|
2025-01-27 19:37:26 +08:00
|
|
|
|
|
|
|
|
|
function getPreferredMfaProp(mfaProps) {
|
|
|
|
|
for (const i in mfaProps) {
|
2025-05-15 21:04:36 +08:00
|
|
|
|
if (mfaProps[i].isPreferred) {
|
2025-01-27 19:37:26 +08:00
|
|
|
|
return mfaProps[i];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return mfaProps[0];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function checkLoginMfa(res, body, params, handleLogin, componentThis, requireRedirect = null) {
|
|
|
|
|
if (res.data === RequiredMfa) {
|
|
|
|
|
if (!requireRedirect) {
|
|
|
|
|
componentThis.props.onLoginSuccess(window.location.href);
|
|
|
|
|
} else {
|
|
|
|
|
componentThis.props.onLoginSuccess(requireRedirect);
|
|
|
|
|
}
|
|
|
|
|
} else if (res.data === NextMfa) {
|
|
|
|
|
componentThis.setState({
|
|
|
|
|
mfaProps: res.data2,
|
|
|
|
|
selectedMfaProp: getPreferredMfaProp(res.data2),
|
|
|
|
|
}, () => {
|
|
|
|
|
body["providerBack"] = body["provider"];
|
|
|
|
|
body["provider"] = "";
|
|
|
|
|
componentThis.setState({
|
|
|
|
|
getVerifyTotp: () => renderMfaAuthVerifyForm(body, params, handleLogin, componentThis),
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
} else if (res.data === "SelectPlan") {
|
|
|
|
|
// paid-user does not have active or pending subscription, go to application default pricing page to select-plan
|
|
|
|
|
const pricing = res.data2;
|
|
|
|
|
goToLink(`/select-plan/${pricing.owner}/${pricing.name}?user=${body.username}`);
|
|
|
|
|
} else if (res.data === "BuyPlanResult") {
|
|
|
|
|
// paid-user has pending subscription, go to buy-plan/result apge to notify payment result
|
|
|
|
|
const sub = res.data2;
|
|
|
|
|
goToLink(`/buy-plan/${sub.owner}/${sub.pricing}/result?subscription=${sub.name}`);
|
|
|
|
|
} else {
|
|
|
|
|
handleLogin(res);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function getApplicationObj(componentThis) {
|
|
|
|
|
return componentThis.props.application;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function parseOffset(offset) {
|
|
|
|
|
if (offset === 2 || offset === 4 || inIframe() || isMobile()) {
|
|
|
|
|
return "0 auto";
|
|
|
|
|
}
|
|
|
|
|
if (offset === 1) {
|
|
|
|
|
return "0 10%";
|
|
|
|
|
}
|
|
|
|
|
if (offset === 3) {
|
|
|
|
|
return "0 60%";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function renderMfaAuthVerifyForm(values, authParams, onSuccess, componentThis) {
|
|
|
|
|
return (
|
|
|
|
|
<div>
|
|
|
|
|
<MfaAuthVerifyForm
|
|
|
|
|
mfaProps={componentThis.state.selectedMfaProp}
|
|
|
|
|
formValues={values}
|
|
|
|
|
authParams={authParams}
|
|
|
|
|
application={getApplicationObj(componentThis)}
|
|
|
|
|
onFail={(errorMessage) => {
|
|
|
|
|
showMessage("error", errorMessage);
|
|
|
|
|
}}
|
|
|
|
|
onSuccess={(res) => onSuccess(res)}
|
|
|
|
|
/>
|
|
|
|
|
<div>
|
|
|
|
|
{
|
|
|
|
|
componentThis.state.mfaProps.map((mfa) => {
|
|
|
|
|
if (componentThis.state.selectedMfaProp.mfaType === mfa.mfaType) {return null;}
|
|
|
|
|
let mfaI18n = "";
|
|
|
|
|
switch (mfa.mfaType) {
|
|
|
|
|
case SmsMfaType: mfaI18n = i18next.t("mfa:Use SMS"); break;
|
|
|
|
|
case TotpMfaType: mfaI18n = i18next.t("mfa:Use Authenticator App"); break ;
|
|
|
|
|
case EmailMfaType: mfaI18n = i18next.t("mfa:Use Email") ;break;
|
|
|
|
|
}
|
|
|
|
|
return <div key={mfa.mfaType}><Button type={"link"} onClick={() => {
|
|
|
|
|
componentThis.setState({
|
|
|
|
|
selectedMfaProp: mfa,
|
|
|
|
|
});
|
|
|
|
|
}}>{mfaI18n}</Button></div>;
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
</div>
|
|
|
|
|
</div>);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function renderLoginPanel(application, getInnerComponent, componentThis) {
|
|
|
|
|
return (
|
|
|
|
|
<div className="login-content" style={{margin: componentThis.props.preview ?? parseOffset(application.formOffset)}}>
|
|
|
|
|
{inIframe() || isMobile() ? null : <div dangerouslySetInnerHTML={{__html: application.formCss}} />}
|
|
|
|
|
{inIframe() || !isMobile() ? null : <div dangerouslySetInnerHTML={{__html: application.formCssMobile}} />}
|
|
|
|
|
<div className={isDarkTheme(componentThis.props.themeAlgorithm) ? "login-panel-dark" : "login-panel"}>
|
|
|
|
|
<div className="side-image" style={{display: application.formOffset !== 4 ? "none" : null}}>
|
|
|
|
|
<div dangerouslySetInnerHTML={{__html: application.formSideHtml}} />
|
|
|
|
|
</div>
|
|
|
|
|
<div className="login-form">
|
|
|
|
|
<div>
|
|
|
|
|
{
|
|
|
|
|
getInnerComponent()
|
|
|
|
|
}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|