forked from casdoor/casdoor
Compare commits
7 Commits
copilot/fi
...
copilot/ex
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
22d287f7a8 | ||
|
|
4e1c56e3cd | ||
|
|
f48eccae98 | ||
|
|
b4049e6cf4 | ||
|
|
91c17b4092 | ||
|
|
2cac433b9f | ||
|
|
ac21a6b3c9 |
@@ -1,5 +1,5 @@
|
||||
<h1 align="center" style="border-bottom: none;">📦⚡️ Casdoor</h1>
|
||||
<h3 align="center">An open-source AI-first Identity and Access Management (IAM) /AI MCP gateway and auth server with web UI supporting MCP, A2A, OAuth 2.1, OIDC, SAML, CAS, LDAP, SCIM, WebAuthn, TOTP, MFA, Face ID, Google Workspace, Azure AD</h3>
|
||||
<h3 align="center">An open-source UI-first Identity and Access Management (IAM) / Single-Sign-On (SSO) platform with web UI supporting OAuth 2.0, OIDC, SAML, CAS, LDAP, SCIM, WebAuthn, TOTP, MFA and RADIUS</h3>
|
||||
<p align="center">
|
||||
<a href="#badge">
|
||||
<img alt="semantic-release" src="https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg">
|
||||
|
||||
@@ -185,14 +185,10 @@ func (c *ApiController) HandleLoggedIn(application *object.Application, user *ob
|
||||
} else {
|
||||
scope := c.Ctx.Input.Query("scope")
|
||||
nonce := c.Ctx.Input.Query("nonce")
|
||||
if !object.IsScopeValid(scope, application) {
|
||||
resp = &Response{Status: "error", Msg: "error: invalid_scope", Data: ""}
|
||||
} else {
|
||||
token, _ := object.GetTokenByUser(application, user, scope, nonce, c.Ctx.Request.Host)
|
||||
resp = tokenToResponse(token)
|
||||
token, _ := object.GetTokenByUser(application, user, scope, nonce, c.Ctx.Request.Host)
|
||||
resp = tokenToResponse(token)
|
||||
|
||||
resp.Data3 = user.NeedUpdatePassword
|
||||
}
|
||||
resp.Data3 = user.NeedUpdatePassword
|
||||
}
|
||||
} else if form.Type == ResponseTypeDevice {
|
||||
authCache, ok := object.DeviceAuthMap.LoadAndDelete(form.UserCode)
|
||||
@@ -743,11 +739,7 @@ func (c *ApiController) Login() {
|
||||
}
|
||||
} else if provider.Category == "OAuth" || provider.Category == "Web3" {
|
||||
// OAuth
|
||||
idpInfo, err := object.FromProviderToIdpInfo(c.Ctx, provider)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
idpInfo := object.FromProviderToIdpInfo(c.Ctx, provider)
|
||||
idpInfo.CodeVerifier = authForm.CodeVerifier
|
||||
var idProvider idp.IdProvider
|
||||
idProvider, err = idp.GetIdProvider(idpInfo, authForm.RedirectUri)
|
||||
|
||||
@@ -109,6 +109,7 @@
|
||||
"Insufficient balance: new balance %v would be below credit limit %v": "Unzureichendes Guthaben: neues Guthaben %v wäre unter dem Kreditlimit %v",
|
||||
"Insufficient balance: new organization balance %v would be below credit limit %v": "Unzureichendes Guthaben: neues Organisationsguthaben %v wäre unter dem Kreditlimit %v",
|
||||
"Missing parameter": "Fehlender Parameter",
|
||||
"Multiple captcha providers are not allowed in the same application: %s": "Multiple captcha providers are not allowed in the same application: %s",
|
||||
"Only admin user can specify user": "Nur Administrator kann Benutzer angeben",
|
||||
"Please login first": "Bitte zuerst einloggen",
|
||||
"The LDAP: %s does not exist": "Das LDAP: %s existiert nicht",
|
||||
@@ -187,7 +188,6 @@
|
||||
"Grant_type: %s is not supported in this application": "Grant_type: %s wird von dieser Anwendung nicht unterstützt",
|
||||
"Invalid application or wrong clientSecret": "Ungültige Anwendung oder falsches clientSecret",
|
||||
"Invalid client_id": "Ungültige client_id",
|
||||
"Invalid scope": "Ungültiger Scope",
|
||||
"Redirect URI: %s doesn't exist in the allowed Redirect URI list": "Weiterleitungs-URI: %s ist nicht in der Liste erlaubter Weiterleitungs-URIs vorhanden",
|
||||
"Token not found, invalid accessToken": "Token nicht gefunden, ungültiger Zugriffs-Token"
|
||||
},
|
||||
|
||||
@@ -109,6 +109,7 @@
|
||||
"Insufficient balance: new balance %v would be below credit limit %v": "Insufficient balance: new balance %v would be below credit limit %v",
|
||||
"Insufficient balance: new organization balance %v would be below credit limit %v": "Insufficient balance: new organization balance %v would be below credit limit %v",
|
||||
"Missing parameter": "Missing parameter",
|
||||
"Multiple captcha providers are not allowed in the same application: %s": "Multiple captcha providers are not allowed in the same application: %s",
|
||||
"Only admin user can specify user": "Only admin user can specify user",
|
||||
"Please login first": "Please login first",
|
||||
"The LDAP: %s does not exist": "The LDAP: %s does not exist",
|
||||
@@ -187,7 +188,6 @@
|
||||
"Grant_type: %s is not supported in this application": "Grant_type: %s is not supported in this application",
|
||||
"Invalid application or wrong clientSecret": "Invalid application or wrong clientSecret",
|
||||
"Invalid client_id": "Invalid client_id",
|
||||
"Invalid scope": "Invalid scope",
|
||||
"Redirect URI: %s doesn't exist in the allowed Redirect URI list": "Redirect URI: %s doesn't exist in the allowed Redirect URI list",
|
||||
"Token not found, invalid accessToken": "Token not found, invalid accessToken"
|
||||
},
|
||||
|
||||
@@ -109,6 +109,7 @@
|
||||
"Insufficient balance: new balance %v would be below credit limit %v": "Saldo insuficiente: el nuevo saldo %v estaría por debajo del límite de crédito %v",
|
||||
"Insufficient balance: new organization balance %v would be below credit limit %v": "Saldo insuficiente: el nuevo saldo de la organización %v estaría por debajo del límite de crédito %v",
|
||||
"Missing parameter": "Parámetro faltante",
|
||||
"Multiple captcha providers are not allowed in the same application: %s": "Multiple captcha providers are not allowed in the same application: %s",
|
||||
"Only admin user can specify user": "Solo el usuario administrador puede especificar usuario",
|
||||
"Please login first": "Por favor, inicia sesión primero",
|
||||
"The LDAP: %s does not exist": "El LDAP: %s no existe",
|
||||
@@ -187,7 +188,6 @@
|
||||
"Grant_type: %s is not supported in this application": "El tipo de subvención: %s no es compatible con esta aplicación",
|
||||
"Invalid application or wrong clientSecret": "Solicitud inválida o clientSecret incorrecto",
|
||||
"Invalid client_id": "Identificador de cliente no válido",
|
||||
"Invalid scope": "Alcance no válido",
|
||||
"Redirect URI: %s doesn't exist in the allowed Redirect URI list": "El URI de redirección: %s no existe en la lista de URI de redirección permitidos",
|
||||
"Token not found, invalid accessToken": "Token no encontrado, accessToken inválido"
|
||||
},
|
||||
|
||||
@@ -109,6 +109,7 @@
|
||||
"Insufficient balance: new balance %v would be below credit limit %v": "Solde insuffisant : le nouveau solde %v serait inférieur à la limite de crédit %v",
|
||||
"Insufficient balance: new organization balance %v would be below credit limit %v": "Solde insuffisant : le nouveau solde de l'organisation %v serait inférieur à la limite de crédit %v",
|
||||
"Missing parameter": "Paramètre manquant",
|
||||
"Multiple captcha providers are not allowed in the same application: %s": "Multiple captcha providers are not allowed in the same application: %s",
|
||||
"Only admin user can specify user": "Seul un administrateur peut désigner un utilisateur",
|
||||
"Please login first": "Veuillez d'abord vous connecter",
|
||||
"The LDAP: %s does not exist": "Le LDAP : %s n'existe pas",
|
||||
@@ -187,7 +188,6 @@
|
||||
"Grant_type: %s is not supported in this application": "Type_de_subvention : %s n'est pas pris en charge dans cette application",
|
||||
"Invalid application or wrong clientSecret": "Application invalide ou clientSecret incorrect",
|
||||
"Invalid client_id": "Identifiant de client invalide",
|
||||
"Invalid scope": "Portée invalide",
|
||||
"Redirect URI: %s doesn't exist in the allowed Redirect URI list": "URI de redirection: %s n'existe pas dans la liste des URI de redirection autorisés",
|
||||
"Token not found, invalid accessToken": "Jeton non trouvé, accessToken invalide"
|
||||
},
|
||||
|
||||
@@ -109,6 +109,7 @@
|
||||
"Insufficient balance: new balance %v would be below credit limit %v": "残高不足:新しい残高 %v がクレジット制限 %v を下回ります",
|
||||
"Insufficient balance: new organization balance %v would be below credit limit %v": "残高不足:新しい組織残高 %v がクレジット制限 %v を下回ります",
|
||||
"Missing parameter": "不足しているパラメーター",
|
||||
"Multiple captcha providers are not allowed in the same application: %s": "Multiple captcha providers are not allowed in the same application: %s",
|
||||
"Only admin user can specify user": "管理者ユーザーのみがユーザーを指定できます",
|
||||
"Please login first": "最初にログインしてください",
|
||||
"The LDAP: %s does not exist": "LDAP:%s は存在しません",
|
||||
@@ -187,7 +188,6 @@
|
||||
"Grant_type: %s is not supported in this application": "grant_type:%sはこのアプリケーションでサポートされていません",
|
||||
"Invalid application or wrong clientSecret": "無効なアプリケーションまたは誤ったクライアントシークレットです",
|
||||
"Invalid client_id": "client_idが無効です",
|
||||
"Invalid scope": "スコープが無効です",
|
||||
"Redirect URI: %s doesn't exist in the allowed Redirect URI list": "リダイレクトURI:%sは許可されたリダイレクトURIリストに存在しません",
|
||||
"Token not found, invalid accessToken": "トークンが見つかりません。無効なアクセストークンです"
|
||||
},
|
||||
|
||||
@@ -109,6 +109,7 @@
|
||||
"Insufficient balance: new balance %v would be below credit limit %v": "Niewystarczające saldo: nowe saldo %v byłoby poniżej limitu kredytowego %v",
|
||||
"Insufficient balance: new organization balance %v would be below credit limit %v": "Niewystarczające saldo: nowe saldo organizacji %v byłoby poniżej limitu kredytowego %v",
|
||||
"Missing parameter": "Brakujący parametr",
|
||||
"Multiple captcha providers are not allowed in the same application: %s": "Multiple captcha providers are not allowed in the same application: %s",
|
||||
"Only admin user can specify user": "Tylko administrator może wskazać użytkownika",
|
||||
"Please login first": "Najpierw się zaloguj",
|
||||
"The LDAP: %s does not exist": "LDAP: %s nie istnieje",
|
||||
@@ -187,7 +188,6 @@
|
||||
"Grant_type: %s is not supported in this application": "Grant_type: %s nie jest obsługiwany w tej aplikacji",
|
||||
"Invalid application or wrong clientSecret": "Nieprawidłowa aplikacja lub błędny clientSecret",
|
||||
"Invalid client_id": "Nieprawidłowy client_id",
|
||||
"Invalid scope": "Nieprawidłowy zakres",
|
||||
"Redirect URI: %s doesn't exist in the allowed Redirect URI list": "Redirect URI: %s nie istnieje na liście dozwolonych Redirect URI",
|
||||
"Token not found, invalid accessToken": "Token nie znaleziony, nieprawidłowy accessToken"
|
||||
},
|
||||
|
||||
@@ -109,6 +109,7 @@
|
||||
"Insufficient balance: new balance %v would be below credit limit %v": "Saldo insuficiente: o novo saldo %v estaria abaixo do limite de crédito %v",
|
||||
"Insufficient balance: new organization balance %v would be below credit limit %v": "Saldo insuficiente: o novo saldo da organização %v estaria abaixo do limite de crédito %v",
|
||||
"Missing parameter": "Parâmetro ausente",
|
||||
"Multiple captcha providers are not allowed in the same application: %s": "Multiple captcha providers are not allowed in the same application: %s",
|
||||
"Only admin user can specify user": "Apenas um administrador pode especificar um usuário",
|
||||
"Please login first": "Por favor, faça login primeiro",
|
||||
"The LDAP: %s does not exist": "O LDAP: %s não existe",
|
||||
@@ -187,7 +188,6 @@
|
||||
"Grant_type: %s is not supported in this application": "Grant_type: %s não é suportado neste aplicativo",
|
||||
"Invalid application or wrong clientSecret": "Aplicativo inválido ou clientSecret incorreto",
|
||||
"Invalid client_id": "client_id inválido",
|
||||
"Invalid scope": "Escopo inválido",
|
||||
"Redirect URI: %s doesn't exist in the allowed Redirect URI list": "O URI de redirecionamento: %s não existe na lista de URIs permitidos",
|
||||
"Token not found, invalid accessToken": "Token não encontrado, accessToken inválido"
|
||||
},
|
||||
|
||||
@@ -109,6 +109,7 @@
|
||||
"Insufficient balance: new balance %v would be below credit limit %v": "Yetersiz bakiye: yeni bakiye %v kredi limitinin altında olacak %v",
|
||||
"Insufficient balance: new organization balance %v would be below credit limit %v": "Yetersiz bakiye: yeni organizasyon bakiyesi %v kredi limitinin altında olacak %v",
|
||||
"Missing parameter": "Eksik parametre",
|
||||
"Multiple captcha providers are not allowed in the same application: %s": "Multiple captcha providers are not allowed in the same application: %s",
|
||||
"Only admin user can specify user": "Yalnızca yönetici kullanıcı kullanıcı belirleyebilir",
|
||||
"Please login first": "Lütfen önce giriş yapın",
|
||||
"The LDAP: %s does not exist": "LDAP: %s mevcut değil",
|
||||
@@ -187,7 +188,6 @@
|
||||
"Grant_type: %s is not supported in this application": "Grant_type: %s bu uygulamada desteklenmiyor",
|
||||
"Invalid application or wrong clientSecret": "Geçersiz uygulama veya yanlış clientSecret",
|
||||
"Invalid client_id": "Geçersiz client_id",
|
||||
"Invalid scope": "Geçersiz kapsam",
|
||||
"Redirect URI: %s doesn't exist in the allowed Redirect URI list": "Redirect URI: %s izin verilen Redirect URI listesinde yok",
|
||||
"Token not found, invalid accessToken": "Token bulunamadı, geçersiz accessToken"
|
||||
},
|
||||
|
||||
@@ -109,6 +109,7 @@
|
||||
"Insufficient balance: new balance %v would be below credit limit %v": "Недостатній баланс: новий баланс %v буде нижче кредитного ліміту %v",
|
||||
"Insufficient balance: new organization balance %v would be below credit limit %v": "Недостатній баланс: новий баланс організації %v буде нижче кредитного ліміту %v",
|
||||
"Missing parameter": "Відсутній параметр",
|
||||
"Multiple captcha providers are not allowed in the same application: %s": "Multiple captcha providers are not allowed in the same application: %s",
|
||||
"Only admin user can specify user": "Лише адміністратор може вказати користувача",
|
||||
"Please login first": "Спочатку увійдіть",
|
||||
"The LDAP: %s does not exist": "LDAP: %s не існує",
|
||||
@@ -187,7 +188,6 @@
|
||||
"Grant_type: %s is not supported in this application": "Grant_type: %s не підтримується в цьому додатку",
|
||||
"Invalid application or wrong clientSecret": "Недійсний додаток або неправильний clientSecret",
|
||||
"Invalid client_id": "Недійсний client_id",
|
||||
"Invalid scope": "Недійсний scope",
|
||||
"Redirect URI: %s doesn't exist in the allowed Redirect URI list": "Redirect URI: %s відсутній у списку дозволених",
|
||||
"Token not found, invalid accessToken": "Токен не знайдено, недійсний accessToken"
|
||||
},
|
||||
|
||||
@@ -109,6 +109,7 @@
|
||||
"Insufficient balance: new balance %v would be below credit limit %v": "Số dư không đủ: số dư mới %v sẽ thấp hơn giới hạn tín dụng %v",
|
||||
"Insufficient balance: new organization balance %v would be below credit limit %v": "Số dư không đủ: số dư tổ chức mới %v sẽ thấp hơn giới hạn tín dụng %v",
|
||||
"Missing parameter": "Thiếu tham số",
|
||||
"Multiple captcha providers are not allowed in the same application: %s": "Multiple captcha providers are not allowed in the same application: %s",
|
||||
"Only admin user can specify user": "Chỉ người dùng quản trị mới có thể chỉ định người dùng",
|
||||
"Please login first": "Vui lòng đăng nhập trước",
|
||||
"The LDAP: %s does not exist": "LDAP: %s không tồn tại",
|
||||
@@ -187,7 +188,6 @@
|
||||
"Grant_type: %s is not supported in this application": "Loại cấp phép: %s không được hỗ trợ trong ứng dụng này",
|
||||
"Invalid application or wrong clientSecret": "Đơn đăng ký không hợp lệ hoặc sai clientSecret",
|
||||
"Invalid client_id": "Client_id không hợp lệ",
|
||||
"Invalid scope": "Phạm vi không hợp lệ",
|
||||
"Redirect URI: %s doesn't exist in the allowed Redirect URI list": "Đường dẫn chuyển hướng URI: %s không tồn tại trong danh sách URI được phép chuyển hướng",
|
||||
"Token not found, invalid accessToken": "Token không tìm thấy, accessToken không hợp lệ"
|
||||
},
|
||||
|
||||
@@ -109,6 +109,7 @@
|
||||
"Insufficient balance: new balance %v would be below credit limit %v": "余额不足:新余额 %v 将低于信用限额 %v",
|
||||
"Insufficient balance: new organization balance %v would be below credit limit %v": "余额不足:新组织余额 %v 将低于信用限额 %v",
|
||||
"Missing parameter": "缺少参数",
|
||||
"Multiple captcha providers are not allowed in the same application: %s": "Multiple captcha providers are not allowed in the same application: %s",
|
||||
"Only admin user can specify user": "仅管理员用户可以指定用户",
|
||||
"Please login first": "请先登录",
|
||||
"The LDAP: %s does not exist": "LDAP: %s 不存在",
|
||||
@@ -187,7 +188,6 @@
|
||||
"Grant_type: %s is not supported in this application": "该应用不支持Grant_type: %s",
|
||||
"Invalid application or wrong clientSecret": "无效应用或错误的clientSecret",
|
||||
"Invalid client_id": "无效的ClientId",
|
||||
"Invalid scope": "无效的scope",
|
||||
"Redirect URI: %s doesn't exist in the allowed Redirect URI list": "重定向 URI:%s在许可跳转列表中未找到",
|
||||
"Token not found, invalid accessToken": "未查询到对应token, accessToken无效"
|
||||
},
|
||||
|
||||
@@ -264,31 +264,27 @@ func rsaSignWithRSA256(signContent string, privateKey string) (string, error) {
|
||||
|
||||
// privateKey in database is a string, format it to PEM style
|
||||
func formatPrivateKey(privateKey string) string {
|
||||
// Check if the key is already in PEM format
|
||||
if strings.HasPrefix(privateKey, "-----BEGIN PRIVATE KEY-----") ||
|
||||
strings.HasPrefix(privateKey, "-----BEGIN RSA PRIVATE KEY-----") {
|
||||
// Key is already in PEM format, return as is
|
||||
return privateKey
|
||||
}
|
||||
|
||||
// Remove any whitespace from the key
|
||||
privateKey = strings.ReplaceAll(privateKey, "\n", "")
|
||||
privateKey = strings.ReplaceAll(privateKey, "\r", "")
|
||||
privateKey = strings.ReplaceAll(privateKey, " ", "")
|
||||
|
||||
// Format the key with line breaks every 64 characters using strings.Builder
|
||||
var builder strings.Builder
|
||||
for i := 0; i < len(privateKey); i += 64 {
|
||||
end := i + 64
|
||||
if end > len(privateKey) {
|
||||
end = len(privateKey)
|
||||
}
|
||||
builder.WriteString(privateKey[i:end])
|
||||
if end < len(privateKey) {
|
||||
builder.WriteString("\n")
|
||||
// each line length is 64
|
||||
preFmtPrivateKey := ""
|
||||
for i := 0; ; {
|
||||
if i+64 <= len(privateKey) {
|
||||
preFmtPrivateKey = preFmtPrivateKey + privateKey[i:i+64] + "\n"
|
||||
i += 64
|
||||
} else {
|
||||
preFmtPrivateKey = preFmtPrivateKey + privateKey[i:]
|
||||
break
|
||||
}
|
||||
}
|
||||
privateKey = strings.Trim(preFmtPrivateKey, "\n")
|
||||
|
||||
// add pkcs#8 BEGIN and END
|
||||
return "-----BEGIN PRIVATE KEY-----\n" + builder.String() + "\n-----END PRIVATE KEY-----"
|
||||
PemBegin := "-----BEGIN PRIVATE KEY-----\n"
|
||||
PemEnd := "\n-----END PRIVATE KEY-----"
|
||||
if !strings.HasPrefix(privateKey, PemBegin) {
|
||||
privateKey = PemBegin + privateKey
|
||||
}
|
||||
if !strings.HasSuffix(privateKey, PemEnd) {
|
||||
privateKey = privateKey + PemEnd
|
||||
}
|
||||
return privateKey
|
||||
}
|
||||
|
||||
@@ -67,8 +67,6 @@
|
||||
{"name": "ID", "visible": true, "viewRule": "Public", "modifyRule": "Immutable"},
|
||||
{"name": "Name", "visible": true, "viewRule": "Public", "modifyRule": "Admin"},
|
||||
{"name": "Display name", "visible": true, "viewRule": "Public", "modifyRule": "Self"},
|
||||
{"name": "First name", "visible": true, "viewRule": "Public", "modifyRule": "Self"},
|
||||
{"name": "Last name", "visible": true, "viewRule": "Public", "modifyRule": "Self"},
|
||||
{"name": "Avatar", "visible": true, "viewRule": "Public", "modifyRule": "Self"},
|
||||
{"name": "User type", "visible": true, "viewRule": "Public", "modifyRule": "Admin"},
|
||||
{"name": "Password", "visible": true, "viewRule": "Self", "modifyRule": "Self"},
|
||||
@@ -83,7 +81,6 @@
|
||||
{"name": "Title", "visible": true, "viewRule": "Public", "modifyRule": "Self"},
|
||||
{"name": "ID card type", "visible": true, "viewRule": "Public", "modifyRule": "Self"},
|
||||
{"name": "ID card", "visible": true, "viewRule": "Public", "modifyRule": "Self"},
|
||||
{"name": "ID card info", "visible": true, "viewRule": "Self", "modifyRule": "Self"},
|
||||
{"name": "Real name", "visible": true, "viewRule": "Public", "modifyRule": "Self"},
|
||||
{"name": "ID verification", "visible": true, "viewRule": "Self", "modifyRule": "Self"},
|
||||
{"name": "Homepage", "visible": true, "viewRule": "Public", "modifyRule": "Self"},
|
||||
@@ -104,7 +101,6 @@
|
||||
{"name": "Signup application", "visible": true, "viewRule": "Public", "modifyRule": "Admin"},
|
||||
{"name": "Register type", "visible": true, "viewRule": "Public", "modifyRule": "Admin"},
|
||||
{"name": "Register source", "visible": true, "viewRule": "Public", "modifyRule": "Admin"},
|
||||
{"name": "API key", "visible": true, "viewRule": "Self", "modifyRule": "Self"},
|
||||
{"name": "Roles", "visible": true, "viewRule": "Public", "modifyRule": "Immutable"},
|
||||
{"name": "Permissions", "visible": true, "viewRule": "Public", "modifyRule": "Immutable"},
|
||||
{"name": "Groups", "visible": true, "viewRule": "Public", "modifyRule": "Admin"},
|
||||
@@ -114,14 +110,9 @@
|
||||
{"name": "Is forbidden", "visible": true, "viewRule": "Admin", "modifyRule": "Admin"},
|
||||
{"name": "Is deleted", "visible": true, "viewRule": "Admin", "modifyRule": "Admin"},
|
||||
{"name": "Multi-factor authentication", "visible": true, "viewRule": "Self", "modifyRule": "Self"},
|
||||
{"name": "MFA items", "visible": true, "viewRule": "Self", "modifyRule": "Self"},
|
||||
{"name": "WebAuthn credentials", "visible": true, "viewRule": "Self", "modifyRule": "Self"},
|
||||
{"name": "Last change password time", "visible": true, "viewRule": "Admin", "modifyRule": "Admin"},
|
||||
{"name": "Managed accounts", "visible": true, "viewRule": "Self", "modifyRule": "Self"},
|
||||
{"name": "Face ID", "visible": true, "viewRule": "Self", "modifyRule": "Self"},
|
||||
{"name": "MFA accounts", "visible": true, "viewRule": "Self", "modifyRule": "Self"},
|
||||
{"name": "Need update password", "visible": true, "viewRule": "Admin", "modifyRule": "Admin"},
|
||||
{"name": "IP whitelist", "visible": true, "viewRule": "Admin", "modifyRule": "Admin"}
|
||||
{"name": "MFA accounts", "visible": true, "viewRule": "Self", "modifyRule": "Self"}
|
||||
]
|
||||
}
|
||||
],
|
||||
|
||||
@@ -155,9 +155,9 @@ type Application struct {
|
||||
FailedSigninFrozenTime int `json:"failedSigninFrozenTime"`
|
||||
CodeResendTimeout int `json:"codeResendTimeout"`
|
||||
|
||||
// Reverse proxy fields
|
||||
// Reverse Proxy fields
|
||||
Domain string `xorm:"varchar(100)" json:"domain"`
|
||||
OtherDomains []string `xorm:"varchar(1000)" json:"otherDomains"`
|
||||
OtherDomains []string `xorm:"mediumtext" json:"otherDomains"`
|
||||
UpstreamHost string `xorm:"varchar(100)" json:"upstreamHost"`
|
||||
SslMode string `xorm:"varchar(100)" json:"sslMode"`
|
||||
SslCert string `xorm:"varchar(100)" json:"sslCert"`
|
||||
|
||||
@@ -53,8 +53,6 @@ func getBuiltInAccountItems() []*AccountItem {
|
||||
{Name: "ID", Visible: true, ViewRule: "Public", ModifyRule: "Immutable"},
|
||||
{Name: "Name", Visible: true, ViewRule: "Public", ModifyRule: "Admin"},
|
||||
{Name: "Display name", Visible: true, ViewRule: "Public", ModifyRule: "Self"},
|
||||
{Name: "First name", Visible: true, ViewRule: "Public", ModifyRule: "Self"},
|
||||
{Name: "Last name", Visible: true, ViewRule: "Public", ModifyRule: "Self"},
|
||||
{Name: "Avatar", Visible: true, ViewRule: "Public", ModifyRule: "Self"},
|
||||
{Name: "User type", Visible: true, ViewRule: "Public", ModifyRule: "Admin"},
|
||||
{Name: "Password", Visible: true, ViewRule: "Self", ModifyRule: "Self"},
|
||||
@@ -69,7 +67,6 @@ func getBuiltInAccountItems() []*AccountItem {
|
||||
{Name: "Title", Visible: true, ViewRule: "Public", ModifyRule: "Self"},
|
||||
{Name: "ID card type", Visible: true, ViewRule: "Public", ModifyRule: "Self"},
|
||||
{Name: "ID card", Visible: true, ViewRule: "Public", ModifyRule: "Self"},
|
||||
{Name: "ID card info", Visible: true, ViewRule: "Self", ModifyRule: "Self"},
|
||||
{Name: "Real name", Visible: true, ViewRule: "Public", ModifyRule: "Self"},
|
||||
{Name: "ID verification", Visible: true, ViewRule: "Self", ModifyRule: "Self"},
|
||||
{Name: "Homepage", Visible: true, ViewRule: "Public", ModifyRule: "Self"},
|
||||
@@ -90,7 +87,6 @@ func getBuiltInAccountItems() []*AccountItem {
|
||||
{Name: "Signup application", Visible: true, ViewRule: "Public", ModifyRule: "Admin"},
|
||||
{Name: "Register type", Visible: true, ViewRule: "Public", ModifyRule: "Admin"},
|
||||
{Name: "Register source", Visible: true, ViewRule: "Public", ModifyRule: "Admin"},
|
||||
{Name: "API key", Visible: true, ViewRule: "Self", ModifyRule: "Self"},
|
||||
{Name: "Roles", Visible: true, ViewRule: "Public", ModifyRule: "Immutable"},
|
||||
{Name: "Permissions", Visible: true, ViewRule: "Public", ModifyRule: "Immutable"},
|
||||
{Name: "Groups", Visible: true, ViewRule: "Public", ModifyRule: "Admin"},
|
||||
@@ -100,14 +96,9 @@ func getBuiltInAccountItems() []*AccountItem {
|
||||
{Name: "Is forbidden", Visible: true, ViewRule: "Admin", ModifyRule: "Admin"},
|
||||
{Name: "Is deleted", Visible: true, ViewRule: "Admin", ModifyRule: "Admin"},
|
||||
{Name: "Multi-factor authentication", Visible: true, ViewRule: "Self", ModifyRule: "Self"},
|
||||
{Name: "MFA items", Visible: true, ViewRule: "Self", ModifyRule: "Self"},
|
||||
{Name: "WebAuthn credentials", Visible: true, ViewRule: "Self", ModifyRule: "Self"},
|
||||
{Name: "Last change password time", Visible: true, ViewRule: "Admin", ModifyRule: "Admin"},
|
||||
{Name: "Managed accounts", Visible: true, ViewRule: "Self", ModifyRule: "Self"},
|
||||
{Name: "Face ID", Visible: true, ViewRule: "Self", ModifyRule: "Self"},
|
||||
{Name: "MFA accounts", Visible: true, ViewRule: "Self", ModifyRule: "Self"},
|
||||
{Name: "Need update password", Visible: true, ViewRule: "Admin", ModifyRule: "Admin"},
|
||||
{Name: "IP whitelist", Visible: true, ViewRule: "Admin", ModifyRule: "Admin"},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -62,12 +62,6 @@ func InitFlag() {
|
||||
configPath = *configPathPtr
|
||||
exportData = *exportDataPtr
|
||||
exportFilePath = *exportFilePathPtr
|
||||
|
||||
// Load beego config from the specified config path
|
||||
err := web.LoadAppConfig("ini", configPath)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("failed to load config from %s: %v", configPath, err))
|
||||
}
|
||||
}
|
||||
|
||||
func ShouldExportData() bool {
|
||||
|
||||
@@ -33,8 +33,6 @@ type Payment struct {
|
||||
// Product Info
|
||||
Products []string `xorm:"varchar(1000)" json:"products"`
|
||||
ProductsDisplayName string `xorm:"varchar(1000)" json:"productsDisplayName"`
|
||||
ProductName string `xorm:"varchar(1000)" json:"productName"`
|
||||
ProductDisplayName string `xorm:"varchar(1000)" json:"productDisplayName"`
|
||||
Detail string `xorm:"varchar(255)" json:"detail"`
|
||||
Currency string `xorm:"varchar(100)" json:"currency"`
|
||||
Price float64 `json:"price"`
|
||||
|
||||
@@ -564,7 +564,7 @@ func providerChangeTrigger(oldName string, newName string) error {
|
||||
return session.Commit()
|
||||
}
|
||||
|
||||
func FromProviderToIdpInfo(ctx *context.Context, provider *Provider) (*idp.ProviderInfo, error) {
|
||||
func FromProviderToIdpInfo(ctx *context.Context, provider *Provider) *idp.ProviderInfo {
|
||||
providerInfo := &idp.ProviderInfo{
|
||||
Type: provider.Type,
|
||||
SubType: provider.SubType,
|
||||
@@ -588,19 +588,9 @@ func FromProviderToIdpInfo(ctx *context.Context, provider *Provider) (*idp.Provi
|
||||
}
|
||||
} else if provider.Type == "ADFS" || provider.Type == "AzureAD" || provider.Type == "AzureADB2C" || provider.Type == "Casdoor" || provider.Type == "Okta" {
|
||||
providerInfo.HostUrl = provider.Domain
|
||||
} else if provider.Type == "Alipay" && provider.Cert != "" {
|
||||
// For Alipay with certificate mode, load private key from certificate
|
||||
cert, err := GetCert(util.GetId(provider.Owner, provider.Cert))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to load certificate for Alipay provider %s: %w", provider.Name, err)
|
||||
}
|
||||
if cert == nil {
|
||||
return nil, fmt.Errorf("certificate not found for Alipay provider %s", provider.Name)
|
||||
}
|
||||
providerInfo.ClientSecret = cert.PrivateKey
|
||||
}
|
||||
|
||||
return providerInfo, nil
|
||||
return providerInfo
|
||||
}
|
||||
|
||||
func GetIdvProviderFromProvider(provider *Provider) idv.IdvProvider {
|
||||
|
||||
@@ -154,10 +154,6 @@ func CheckOAuthLogin(clientId string, responseType string, redirectUri string, s
|
||||
return fmt.Sprintf(i18n.Translate(lang, "token:Redirect URI: %s doesn't exist in the allowed Redirect URI list"), redirectUri), application, nil
|
||||
}
|
||||
|
||||
if !IsScopeValid(scope, application) {
|
||||
return i18n.Translate(lang, "token:Invalid scope"), application, nil
|
||||
}
|
||||
|
||||
// Mask application for /api/get-app-login
|
||||
application.ClientSecret = ""
|
||||
return "", application, nil
|
||||
@@ -490,28 +486,6 @@ func IsGrantTypeValid(method string, grantTypes []string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// IsScopeValid checks whether all space-separated scopes in the scope string
|
||||
// are defined in the application's Scopes list.
|
||||
// If the application has no defined scopes, every scope is considered valid
|
||||
// (backward-compatible behaviour).
|
||||
func IsScopeValid(scope string, application *Application) bool {
|
||||
if len(application.Scopes) == 0 || scope == "" {
|
||||
return true
|
||||
}
|
||||
|
||||
allowed := make(map[string]bool, len(application.Scopes))
|
||||
for _, s := range application.Scopes {
|
||||
allowed[s.Name] = true
|
||||
}
|
||||
|
||||
for _, s := range strings.Fields(scope) {
|
||||
if !allowed[s] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// createGuestUserToken creates a new guest user and returns a token for them
|
||||
func createGuestUserToken(application *Application, clientSecret string, verifier string) (*Token, *TokenError, error) {
|
||||
// Verify client secret if provided
|
||||
@@ -741,13 +715,6 @@ func GetAuthorizationCodeToken(application *Application, clientSecret string, co
|
||||
// GetPasswordToken
|
||||
// Resource Owner Password Credentials flow
|
||||
func GetPasswordToken(application *Application, username string, password string, scope string, host string) (*Token, *TokenError, error) {
|
||||
if !IsScopeValid(scope, application) {
|
||||
return nil, &TokenError{
|
||||
Error: InvalidScope,
|
||||
ErrorDescription: "the requested scope is invalid or not defined in the application",
|
||||
}, nil
|
||||
}
|
||||
|
||||
user, err := GetUserByFields(application.Organization, username)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
@@ -829,12 +796,6 @@ func GetClientCredentialsToken(application *Application, clientSecret string, sc
|
||||
ErrorDescription: "client_secret is invalid",
|
||||
}, nil
|
||||
}
|
||||
if !IsScopeValid(scope, application) {
|
||||
return nil, &TokenError{
|
||||
Error: InvalidScope,
|
||||
ErrorDescription: "the requested scope is invalid or not defined in the application",
|
||||
}, nil
|
||||
}
|
||||
nullUser := &User{
|
||||
Owner: application.Owner,
|
||||
Id: application.GetId(),
|
||||
@@ -874,13 +835,6 @@ func GetClientCredentialsToken(application *Application, clientSecret string, sc
|
||||
// GetImplicitToken
|
||||
// Implicit flow
|
||||
func GetImplicitToken(application *Application, username string, scope string, nonce string, host string) (*Token, *TokenError, error) {
|
||||
if !IsScopeValid(scope, application) {
|
||||
return nil, &TokenError{
|
||||
Error: InvalidScope,
|
||||
ErrorDescription: "the requested scope is invalid or not defined in the application",
|
||||
}, nil
|
||||
}
|
||||
|
||||
user, err := GetUserByFields(application.Organization, username)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
|
||||
@@ -860,16 +860,16 @@ func UpdateUser(id string, user *User, columns []string, isAdmin bool) (bool, er
|
||||
if len(columns) == 0 {
|
||||
columns = []string{
|
||||
"owner", "display_name", "avatar", "first_name", "last_name",
|
||||
"location", "address", "addresses", "country_code", "region", "language", "affiliation", "title", "id_card_type", "id_card", "homepage", "bio", "tag", "language", "gender", "birthday", "education", "score", "karma", "ranking", "signup_application", "register_type", "register_source",
|
||||
"is_admin", "is_forbidden", "is_deleted", "hash", "is_default_avatar", "properties", "webauthnCredentials", "mfa_items", "last_change_password_time", "managedAccounts", "face_ids", "mfaAccounts",
|
||||
"signin_wrong_times", "last_signin_wrong_time", "groups", "access_key", "access_secret", "mfa_phone_enabled", "mfa_email_enabled", "email_verified",
|
||||
"location", "address", "country_code", "region", "language", "affiliation", "title", "id_card_type", "id_card", "homepage", "bio", "tag", "language", "gender", "birthday", "education", "score", "karma", "ranking", "signup_application",
|
||||
"is_admin", "is_forbidden", "is_deleted", "hash", "is_default_avatar", "properties", "webauthnCredentials", "managedAccounts", "face_ids", "mfaAccounts",
|
||||
"signin_wrong_times", "last_change_password_time", "last_signin_wrong_time", "groups", "access_key", "access_secret", "mfa_phone_enabled", "mfa_email_enabled", "email_verified",
|
||||
"github", "google", "qq", "wechat", "facebook", "dingtalk", "weibo", "gitee", "linkedin", "wecom", "lark", "gitlab", "adfs",
|
||||
"baidu", "alipay", "casdoor", "infoflow", "apple", "azuread", "azureadb2c", "slack", "steam", "bilibili", "okta", "douyin", "kwai", "line", "amazon",
|
||||
"auth0", "battlenet", "bitbucket", "box", "cloudfoundry", "dailymotion", "deezer", "digitalocean", "discord", "dropbox",
|
||||
"eveonline", "fitbit", "gitea", "heroku", "influxcloud", "instagram", "intercom", "kakao", "lastfm", "mailru", "meetup",
|
||||
"microsoftonline", "naver", "nextcloud", "onedrive", "oura", "patreon", "paypal", "salesforce", "shopify", "soundcloud",
|
||||
"spotify", "strava", "stripe", "type", "tiktok", "tumblr", "twitch", "twitter", "typetalk", "uber", "vk", "wepay", "xero", "yahoo",
|
||||
"yammer", "yandex", "zoom", "custom", "need_update_password", "ip_whitelist", "mfa_remember_deadline",
|
||||
"yammer", "yandex", "zoom", "custom", "need_update_password", "ip_whitelist", "mfa_items", "mfa_remember_deadline",
|
||||
"cart",
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,7 +158,7 @@ class AdapterEditPage extends React.Component {
|
||||
<React.Fragment>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("general:Type"), i18next.t("general:Type - Tooltip"))} :
|
||||
{Setting.getLabel(i18next.t("general:Type"), i18next.t("cert:Type - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Select virtual={false} disabled={Setting.builtInObject(this.state.adapter)} style={{width: "100%"}} value={this.state.adapter.type} onChange={(value => {
|
||||
|
||||
@@ -175,6 +175,10 @@ class ApplicationEditPage extends React.Component {
|
||||
application.tags = [];
|
||||
}
|
||||
|
||||
if (application.otherDomains === null || application.otherDomains === undefined) {
|
||||
application.otherDomains = [];
|
||||
}
|
||||
|
||||
this.setState({
|
||||
application: application,
|
||||
});
|
||||
@@ -505,160 +509,6 @@ class ApplicationEditPage extends React.Component {
|
||||
</React.Fragment>
|
||||
)}
|
||||
{this.state.activeMenuKey === "authentication" && (
|
||||
<React.Fragment>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 3}>
|
||||
{Setting.getLabel(i18next.t("application:Cookie expire"), i18next.t("application:Cookie expire - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={21} >
|
||||
<InputNumber style={{width: "150px"}} value={this.state.application.cookieExpireInHours || 720} min={1} step={1} precision={0} addonAfter="Hours" onChange={value => {
|
||||
this.updateApplicationField("cookieExpireInHours", value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 3}>
|
||||
{Setting.getLabel(i18next.t("ldap:Default group"), i18next.t("ldap:Default group - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={21}>
|
||||
<PaginateSelect
|
||||
virtual
|
||||
style={{width: "100%"}}
|
||||
allowClear
|
||||
placeholder={i18next.t("general:Default")}
|
||||
value={this.state.application.defaultGroup || undefined}
|
||||
fetchPage={GroupBackend.getGroups}
|
||||
buildFetchArgs={({page, pageSize, searchText}) => {
|
||||
const field = searchText ? "name" : "";
|
||||
return [this.state.owner, false, page, pageSize, field, searchText, "", ""];
|
||||
}}
|
||||
reloadKey={this.state.owner}
|
||||
optionMapper={(group) => Setting.getOption(
|
||||
<Space>
|
||||
{group.type === "Physical" ? <UsergroupAddOutlined /> : <HolderOutlined />}
|
||||
{group.displayName}
|
||||
</Space>,
|
||||
`${group.owner}/${group.name}`
|
||||
)}
|
||||
filterOption={false}
|
||||
onChange={(value) => {
|
||||
this.updateApplicationField("defaultGroup", value || "");
|
||||
}}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 19 : 2}>
|
||||
{Setting.getLabel(i18next.t("application:Enable signup"), i18next.t("application:Enable signup - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={1} >
|
||||
<Switch checked={this.state.application.enableSignUp} onChange={checked => {
|
||||
this.updateApplicationField("enableSignUp", checked);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 19 : 2}>
|
||||
{Setting.getLabel(i18next.t("application:Disable signin"), i18next.t("application:Disable signin - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={1} >
|
||||
<Switch checked={this.state.application.disableSignin} onChange={checked => {
|
||||
this.updateApplicationField("disableSignin", checked);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 19 : 2}>
|
||||
{Setting.getLabel(i18next.t("application:Enable exclusive signin"), i18next.t("application:Enable exclusive signin - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={1} >
|
||||
<Switch checked={this.state.application.enableExclusiveSignin} onChange={checked => {
|
||||
this.updateApplicationField("enableExclusiveSignin", checked);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 19 : 2}>
|
||||
{Setting.getLabel(i18next.t("application:Signin session"), i18next.t("application:Enable signin session - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={1} >
|
||||
<Switch checked={this.state.application.enableSigninSession} onChange={checked => {
|
||||
if (!checked) {
|
||||
this.updateApplicationField("enableAutoSignin", false);
|
||||
}
|
||||
|
||||
this.updateApplicationField("enableSigninSession", checked);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 19 : 2}>
|
||||
{Setting.getLabel(i18next.t("application:Auto signin"), i18next.t("application:Auto signin - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={1} >
|
||||
<Switch checked={this.state.application.enableAutoSignin} onChange={checked => {
|
||||
if (!this.state.application.enableSigninSession && checked) {
|
||||
Setting.showMessage("error", i18next.t("application:Please enable \"Signin session\" first before enabling \"Auto signin\""));
|
||||
return;
|
||||
}
|
||||
|
||||
this.updateApplicationField("enableAutoSignin", checked);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 19 : 2}>
|
||||
{Setting.getLabel(i18next.t("application:Enable Email linking"), i18next.t("application:Enable Email linking - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={1} >
|
||||
<Switch checked={this.state.application.enableLinkWithEmail} onChange={checked => {
|
||||
this.updateApplicationField("enableLinkWithEmail", checked);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 3}>
|
||||
{Setting.getLabel(i18next.t("general:Signup URL"), i18next.t("general:Signup URL - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={21} >
|
||||
<Input prefix={<LinkOutlined />} value={this.state.application.signupUrl} onChange={e => {
|
||||
this.updateApplicationField("signupUrl", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 3}>
|
||||
{Setting.getLabel(i18next.t("general:Signin URL"), i18next.t("general:Signin URL - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={21} >
|
||||
<Input prefix={<LinkOutlined />} value={this.state.application.signinUrl} onChange={e => {
|
||||
this.updateApplicationField("signinUrl", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 3}>
|
||||
{Setting.getLabel(i18next.t("general:Forget URL"), i18next.t("general:Forget URL - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={21} >
|
||||
<Input prefix={<LinkOutlined />} value={this.state.application.forgetUrl} onChange={e => {
|
||||
this.updateApplicationField("forgetUrl", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 3}>
|
||||
{Setting.getLabel(i18next.t("general:Affiliation URL"), i18next.t("general:Affiliation URL - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={21} >
|
||||
<Input prefix={<LinkOutlined />} value={this.state.application.affiliationUrl} onChange={e => {
|
||||
this.updateApplicationField("affiliationUrl", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
</React.Fragment>
|
||||
)}
|
||||
{this.state.activeMenuKey === "oidc-oauth" && (
|
||||
<React.Fragment>
|
||||
<Row style={{marginTop: "10px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 3}>
|
||||
@@ -811,11 +661,157 @@ class ApplicationEditPage extends React.Component {
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
</React.Fragment>
|
||||
)}
|
||||
{this.state.activeMenuKey === "saml" && (
|
||||
<React.Fragment>
|
||||
<Row style={{marginTop: "10px"}} >
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 3}>
|
||||
{Setting.getLabel(i18next.t("application:Cookie expire"), i18next.t("application:Cookie expire - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={21} >
|
||||
<InputNumber style={{width: "150px"}} value={this.state.application.cookieExpireInHours || 720} min={1} step={1} precision={0} addonAfter="Hours" onChange={value => {
|
||||
this.updateApplicationField("cookieExpireInHours", value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 3}>
|
||||
{Setting.getLabel(i18next.t("ldap:Default group"), i18next.t("ldap:Default group - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={21}>
|
||||
<PaginateSelect
|
||||
virtual
|
||||
style={{width: "100%"}}
|
||||
allowClear
|
||||
placeholder={i18next.t("general:Default")}
|
||||
value={this.state.application.defaultGroup || undefined}
|
||||
fetchPage={GroupBackend.getGroups}
|
||||
buildFetchArgs={({page, pageSize, searchText}) => {
|
||||
const field = searchText ? "name" : "";
|
||||
return [this.state.owner, false, page, pageSize, field, searchText, "", ""];
|
||||
}}
|
||||
reloadKey={this.state.owner}
|
||||
optionMapper={(group) => Setting.getOption(
|
||||
<Space>
|
||||
{group.type === "Physical" ? <UsergroupAddOutlined /> : <HolderOutlined />}
|
||||
{group.displayName}
|
||||
</Space>,
|
||||
`${group.owner}/${group.name}`
|
||||
)}
|
||||
filterOption={false}
|
||||
onChange={(value) => {
|
||||
this.updateApplicationField("defaultGroup", value || "");
|
||||
}}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 19 : 2}>
|
||||
{Setting.getLabel(i18next.t("application:Enable signup"), i18next.t("application:Enable signup - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={1} >
|
||||
<Switch checked={this.state.application.enableSignUp} onChange={checked => {
|
||||
this.updateApplicationField("enableSignUp", checked);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 19 : 2}>
|
||||
{Setting.getLabel(i18next.t("application:Disable signin"), i18next.t("application:Disable signin - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={1} >
|
||||
<Switch checked={this.state.application.disableSignin} onChange={checked => {
|
||||
this.updateApplicationField("disableSignin", checked);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 19 : 2}>
|
||||
{Setting.getLabel(i18next.t("application:Enable exclusive signin"), i18next.t("application:Enable exclusive signin - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={1} >
|
||||
<Switch checked={this.state.application.enableExclusiveSignin} onChange={checked => {
|
||||
this.updateApplicationField("enableExclusiveSignin", checked);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 19 : 2}>
|
||||
{Setting.getLabel(i18next.t("application:Signin session"), i18next.t("application:Enable signin session - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={1} >
|
||||
<Switch checked={this.state.application.enableSigninSession} onChange={checked => {
|
||||
if (!checked) {
|
||||
this.updateApplicationField("enableAutoSignin", false);
|
||||
}
|
||||
|
||||
this.updateApplicationField("enableSigninSession", checked);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 19 : 2}>
|
||||
{Setting.getLabel(i18next.t("application:Auto signin"), i18next.t("application:Auto signin - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={1} >
|
||||
<Switch checked={this.state.application.enableAutoSignin} onChange={checked => {
|
||||
if (!this.state.application.enableSigninSession && checked) {
|
||||
Setting.showMessage("error", i18next.t("application:Please enable \"Signin session\" first before enabling \"Auto signin\""));
|
||||
return;
|
||||
}
|
||||
|
||||
this.updateApplicationField("enableAutoSignin", checked);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 19 : 2}>
|
||||
{Setting.getLabel(i18next.t("application:Enable Email linking"), i18next.t("application:Enable Email linking - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={1} >
|
||||
<Switch checked={this.state.application.enableLinkWithEmail} onChange={checked => {
|
||||
this.updateApplicationField("enableLinkWithEmail", checked);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 3}>
|
||||
{Setting.getLabel(i18next.t("general:Signup URL"), i18next.t("general:Signup URL - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={21} >
|
||||
<Input prefix={<LinkOutlined />} value={this.state.application.signupUrl} onChange={e => {
|
||||
this.updateApplicationField("signupUrl", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 3}>
|
||||
{Setting.getLabel(i18next.t("general:Signin URL"), i18next.t("general:Signin URL - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={21} >
|
||||
<Input prefix={<LinkOutlined />} value={this.state.application.signinUrl} onChange={e => {
|
||||
this.updateApplicationField("signinUrl", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 3}>
|
||||
{Setting.getLabel(i18next.t("general:Forget URL"), i18next.t("general:Forget URL - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={21} >
|
||||
<Input prefix={<LinkOutlined />} value={this.state.application.forgetUrl} onChange={e => {
|
||||
this.updateApplicationField("forgetUrl", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 3}>
|
||||
{Setting.getLabel(i18next.t("general:Affiliation URL"), i18next.t("general:Affiliation URL - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={21} >
|
||||
<Input prefix={<LinkOutlined />} value={this.state.application.affiliationUrl} onChange={e => {
|
||||
this.updateApplicationField("affiliationUrl", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 3}>
|
||||
{Setting.getLabel(i18next.t("application:SAML reply URL"), i18next.t("application:Redirect URL (Assertion Consumer Service POST Binding URL) - Tooltip"))} :
|
||||
</Col>
|
||||
@@ -1386,44 +1382,47 @@ class ApplicationEditPage extends React.Component {
|
||||
<React.Fragment>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 3}>
|
||||
{Setting.getLabel(i18next.t("provider:Domain"), i18next.t("provider:Domain - Tooltip"))} :
|
||||
{Setting.getLabel("Domain", "The public-facing domain for this application (e.g., blog.example.com)")} :
|
||||
</Col>
|
||||
<Col span={21} >
|
||||
<Input value={this.state.application.domain} placeholder="e.g., blog.example.com" onChange={e => {
|
||||
<Input value={this.state.application.domain} placeholder="blog.example.com" onChange={e => {
|
||||
this.updateApplicationField("domain", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 3}>
|
||||
{Setting.getLabel(i18next.t("application:Other domains"), i18next.t("application:Other domains - Tooltip"))} :
|
||||
{Setting.getLabel("Other domains", "Additional domains that should also route to this application")} :
|
||||
</Col>
|
||||
<Col span={21} >
|
||||
<UrlTable
|
||||
title={i18next.t("application:Other domains")}
|
||||
table={this.state.application.otherDomains}
|
||||
onUpdateTable={(value) => {this.updateApplicationField("otherDomains", value);}}
|
||||
<Select
|
||||
mode="tags"
|
||||
style={{width: "100%"}}
|
||||
value={this.state.application.otherDomains}
|
||||
onChange={(value) => {
|
||||
this.updateApplicationField("otherDomains", value);
|
||||
}}
|
||||
placeholder="Please input additional domains"
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 3}>
|
||||
{Setting.getLabel(i18next.t("application:Upstream host"), i18next.t("application:Upstream host - Tooltip"))} :
|
||||
{Setting.getLabel("Upstream host", "The upstream backend address to forward requests to (e.g., localhost:8080 or 192.168.1.100)")} :
|
||||
</Col>
|
||||
<Col span={21} >
|
||||
<Input value={this.state.application.upstreamHost} placeholder="e.g., localhost:8080 or 192.168.1.100:3000" onChange={e => {
|
||||
<Input value={this.state.application.upstreamHost} placeholder="localhost:8080" onChange={e => {
|
||||
this.updateApplicationField("upstreamHost", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 3}>
|
||||
{Setting.getLabel(i18next.t("provider:SSL mode"), i18next.t("provider:SSL mode - Tooltip"))} :
|
||||
{Setting.getLabel("SSL mode", "SSL/TLS mode for the reverse proxy")} :
|
||||
</Col>
|
||||
<Col span={21} >
|
||||
<Select virtual={false} style={{width: "100%"}} value={this.state.application.sslMode} onChange={(value => {this.updateApplicationField("sslMode", value);})}>
|
||||
<Option value="">{i18next.t("general:None")}</Option>
|
||||
<Option value="HTTP">HTTP</Option>
|
||||
<Option value="HTTPS and HTTP">HTTPS and HTTP</Option>
|
||||
<Option value="HTTPS Only">HTTPS Only</Option>
|
||||
</Select>
|
||||
@@ -1431,7 +1430,7 @@ class ApplicationEditPage extends React.Component {
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 3}>
|
||||
{Setting.getLabel(i18next.t("application:SSL cert"), i18next.t("application:SSL cert - Tooltip"))} :
|
||||
{Setting.getLabel("SSL cert", "Certificate to use for TLS termination")} :
|
||||
</Col>
|
||||
<Col span={21} >
|
||||
<Select virtual={false} style={{width: "100%"}} value={this.state.application.sslCert} onChange={(value => {this.updateApplicationField("sslCert", value);})}>
|
||||
@@ -1460,7 +1459,7 @@ class ApplicationEditPage extends React.Component {
|
||||
<Layout style={{background: "inherit", height: "100%", overflow: "auto"}}>
|
||||
{
|
||||
this.state.menuMode === "horizontal" || !this.state.menuMode ? (
|
||||
<Header style={{background: "inherit", padding: "0px", position: "sticky", top: 0, height: 38, minHeight: 38}}>
|
||||
<Header style={{background: "inherit", padding: "0px", position: "sticky", top: 0}}>
|
||||
<div className="demo-logo" />
|
||||
<Tabs
|
||||
onChange={(key) => {
|
||||
@@ -1469,16 +1468,13 @@ class ApplicationEditPage extends React.Component {
|
||||
}}
|
||||
type="card"
|
||||
activeKey={this.state.activeMenuKey}
|
||||
tabBarStyle={{marginBottom: 0}}
|
||||
items={[
|
||||
{label: i18next.t("application:Basic"), key: "basic"},
|
||||
{label: i18next.t("application:Authentication"), key: "authentication"},
|
||||
{label: "OIDC/OAuth", key: "oidc-oauth"},
|
||||
{label: "SAML", key: "saml"},
|
||||
{label: i18next.t("application:Providers"), key: "providers"},
|
||||
{label: i18next.t("application:UI Customization"), key: "ui-customization"},
|
||||
{label: i18next.t("application:Security"), key: "security"},
|
||||
{label: i18next.t("application:Reverse Proxy"), key: "reverse-proxy"},
|
||||
{label: "Reverse Proxy", key: "reverse-proxy"},
|
||||
]}
|
||||
/>
|
||||
</Header>
|
||||
@@ -1499,12 +1495,10 @@ class ApplicationEditPage extends React.Component {
|
||||
>
|
||||
<Menu.Item key="basic">{i18next.t("application:Basic")}</Menu.Item>
|
||||
<Menu.Item key="authentication">{i18next.t("application:Authentication")}</Menu.Item>
|
||||
<Menu.Item key="oidc-oauth">OIDC/OAuth</Menu.Item>
|
||||
<Menu.Item key="saml">SAML</Menu.Item>
|
||||
<Menu.Item key="providers">{i18next.t("application:Providers")}</Menu.Item>
|
||||
<Menu.Item key="ui-customization">{i18next.t("application:UI Customization")}</Menu.Item>
|
||||
<Menu.Item key="security">{i18next.t("application:Security")}</Menu.Item>
|
||||
<Menu.Item key="reverse-proxy">{i18next.t("application:Reverse Proxy")}</Menu.Item>
|
||||
<Menu.Item key="reverse-proxy">Reverse Proxy</Menu.Item>
|
||||
</Menu>
|
||||
</Sider>) : null
|
||||
}
|
||||
|
||||
@@ -190,15 +190,19 @@ class ApplicationListPage extends BaseListPage {
|
||||
sorter: true,
|
||||
...this.getColumnSearchProps("category"),
|
||||
render: (text, record, index) => {
|
||||
if (!text) {
|
||||
text = "Default";
|
||||
}
|
||||
|
||||
if (text === "Agent") {
|
||||
return Setting.getTag("success", text);
|
||||
} else {
|
||||
return Setting.getTag("default", text);
|
||||
}
|
||||
const category = text;
|
||||
const tagColor = category === "Agent" ? "green" : "blue";
|
||||
return (
|
||||
<span style={{
|
||||
padding: "4px 8px",
|
||||
borderRadius: "4px",
|
||||
backgroundColor: tagColor,
|
||||
color: "white",
|
||||
fontWeight: "500",
|
||||
}}>
|
||||
{category}
|
||||
</span>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -133,7 +133,7 @@ class CertEditPage extends React.Component {
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("provider:Scope"), i18next.t("provider:Scope - Tooltip"))} :
|
||||
{Setting.getLabel(i18next.t("provider:Scope"), i18next.t("cert:Scope - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Select virtual={false} style={{width: "100%"}} value={this.state.cert.scope} onChange={(value => {
|
||||
@@ -149,7 +149,7 @@ class CertEditPage extends React.Component {
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("general:Type"), i18next.t("general:Type - Tooltip"))} :
|
||||
{Setting.getLabel(i18next.t("general:Type"), i18next.t("cert:Type - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Select virtual={false} style={{width: "100%"}} value={this.state.cert.type} onChange={(value => {
|
||||
|
||||
@@ -93,7 +93,7 @@ class FormEditPage extends React.Component {
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}}>
|
||||
<Col style={{marginTop: "5px"}} span={Setting.isMobile() ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("general:Type"), i18next.t("general:Type - Tooltip"))} :
|
||||
{Setting.getLabel(i18next.t("general:Type"), i18next.t("cert:Type - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22}>
|
||||
<Select
|
||||
|
||||
@@ -148,7 +148,7 @@ class GroupEditPage extends React.Component {
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("general:Type"), i18next.t("general:Type - Tooltip"))} :
|
||||
{Setting.getLabel(i18next.t("general:Type"), i18next.t("cert:Type - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Select style={{width: "100%"}}
|
||||
|
||||
@@ -57,8 +57,6 @@ class OrganizationListPage extends BaseListPage {
|
||||
{name: "ID", visible: true, viewRule: "Public", modifyRule: "Immutable"},
|
||||
{name: "Name", visible: true, viewRule: "Public", modifyRule: "Admin"},
|
||||
{name: "Display name", visible: true, viewRule: "Public", modifyRule: "Self"},
|
||||
{name: "First name", visible: true, viewRule: "Public", modifyRule: "Self"},
|
||||
{name: "Last name", visible: true, viewRule: "Public", modifyRule: "Self"},
|
||||
{name: "Avatar", visible: true, viewRule: "Public", modifyRule: "Self"},
|
||||
{name: "User type", visible: true, viewRule: "Public", modifyRule: "Admin"},
|
||||
{name: "Password", visible: true, viewRule: "Self", modifyRule: "Self"},
|
||||
@@ -68,7 +66,6 @@ class OrganizationListPage extends BaseListPage {
|
||||
{name: "Country/Region", visible: true, viewRule: "Public", modifyRule: "Self"},
|
||||
{name: "Location", visible: true, viewRule: "Public", modifyRule: "Self"},
|
||||
{name: "Address", visible: true, viewRule: "Public", modifyRule: "Self"},
|
||||
{name: "Addresses", visible: true, viewRule: "Public", modifyRule: "Self"},
|
||||
{name: "Affiliation", visible: true, viewRule: "Public", modifyRule: "Self"},
|
||||
{name: "Title", visible: true, viewRule: "Public", modifyRule: "Self"},
|
||||
{name: "ID card type", visible: true, viewRule: "Public", modifyRule: "Self"},
|
||||
@@ -89,8 +86,6 @@ class OrganizationListPage extends BaseListPage {
|
||||
{name: "Balance", visible: true, viewRule: "Public", modifyRule: "Admin"},
|
||||
{name: "Balance credit", visible: true, viewRule: "Public", modifyRule: "Admin"},
|
||||
{name: "Balance currency", visible: true, viewRule: "Public", modifyRule: "Admin"},
|
||||
{name: "Cart", visible: true, viewRule: "Self", modifyRule: "Self"},
|
||||
{name: "Transactions", visible: true, viewRule: "Self", modifyRule: "Self"},
|
||||
{name: "Signup application", visible: true, viewRule: "Public", modifyRule: "Admin"},
|
||||
{name: "Register type", visible: true, viewRule: "Public", modifyRule: "Admin"},
|
||||
{name: "Register source", visible: true, viewRule: "Public", modifyRule: "Admin"},
|
||||
@@ -104,15 +99,10 @@ class OrganizationListPage extends BaseListPage {
|
||||
{name: "Is admin", visible: true, viewRule: "Admin", modifyRule: "Admin"},
|
||||
{name: "Is forbidden", visible: true, viewRule: "Admin", modifyRule: "Admin"},
|
||||
{name: "Is deleted", visible: true, viewRule: "Admin", modifyRule: "Admin"},
|
||||
{name: "Multi-factor authentication", visible: true, viewRule: "Self", modifyRule: "Self"},
|
||||
{name: "MFA items", visible: true, viewRule: "Self", modifyRule: "Self"},
|
||||
{name: "WebAuthn credentials", visible: true, viewRule: "Self", modifyRule: "Self"},
|
||||
{name: "Last change password time", visible: true, viewRule: "Admin", modifyRule: "Admin"},
|
||||
{name: "Managed accounts", visible: true, viewRule: "Self", modifyRule: "Self"},
|
||||
{name: "Face ID", visible: true, viewRule: "Self", modifyRule: "Self"},
|
||||
{name: "MFA accounts", visible: true, viewRule: "Self", modifyRule: "Self"},
|
||||
{name: "Need update password", visible: true, viewRule: "Admin", modifyRule: "Admin"},
|
||||
{name: "IP whitelist", visible: true, viewRule: "Admin", modifyRule: "Admin"},
|
||||
{Name: "Multi-factor authentication", Visible: true, ViewRule: "Self", ModifyRule: "Self"},
|
||||
{Name: "WebAuthn credentials", Visible: true, ViewRule: "Self", ModifyRule: "Self"},
|
||||
{Name: "Managed accounts", Visible: true, ViewRule: "Self", ModifyRule: "Self"},
|
||||
{Name: "MFA accounts", Visible: true, ViewRule: "Self", ModifyRule: "Self"},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ import {InfoCircleTwoTone} from "@ant-design/icons";
|
||||
import * as PaymentBackend from "./backend/PaymentBackend";
|
||||
import * as Setting from "./Setting";
|
||||
import i18next from "i18next";
|
||||
import * as ProductBackend from "./backend/ProductBackend";
|
||||
|
||||
const {Option} = Select;
|
||||
|
||||
@@ -29,6 +30,7 @@ class PaymentEditPage extends React.Component {
|
||||
organizationName: props.organizationName !== undefined ? props.organizationName : props.match.params.organizationName,
|
||||
paymentName: props.match.params.paymentName,
|
||||
payment: null,
|
||||
products: [],
|
||||
isModalVisible: false,
|
||||
isInvoiceLoading: false,
|
||||
mode: props.location.mode !== undefined ? props.location.mode : "edit",
|
||||
@@ -37,6 +39,7 @@ class PaymentEditPage extends React.Component {
|
||||
|
||||
UNSAFE_componentWillMount() {
|
||||
this.getPayment();
|
||||
this.getProducts();
|
||||
}
|
||||
|
||||
getPayment() {
|
||||
@@ -55,6 +58,19 @@ class PaymentEditPage extends React.Component {
|
||||
});
|
||||
}
|
||||
|
||||
getProducts() {
|
||||
ProductBackend.getProducts(this.state.organizationName)
|
||||
.then((res) => {
|
||||
if (res.status === "ok") {
|
||||
this.setState({
|
||||
products: res.data,
|
||||
});
|
||||
} else {
|
||||
Setting.showMessage("error", `Failed to get products: ${res.msg}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
goToViewOrder() {
|
||||
const payment = this.state.payment;
|
||||
if (payment && payment.order) {
|
||||
@@ -216,7 +232,7 @@ class PaymentEditPage extends React.Component {
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("general:Type"), i18next.t("general:Type - Tooltip"))} :
|
||||
{Setting.getLabel(i18next.t("general:Type"), i18next.t("cert:Type - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input disabled={true} value={this.state.payment.type} onChange={e => {
|
||||
@@ -224,6 +240,29 @@ class PaymentEditPage extends React.Component {
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("general:Products"), i18next.t("payment:Products - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Select
|
||||
mode="multiple"
|
||||
style={{width: "100%"}}
|
||||
value={this.state.payment?.products || []}
|
||||
disabled={isViewMode}
|
||||
allowClear
|
||||
options={(this.state.products || [])
|
||||
.map((p) => ({
|
||||
label: Setting.getLanguageText(p?.displayName) || p?.name,
|
||||
value: p?.name,
|
||||
}))
|
||||
.filter((o) => o.value)}
|
||||
onChange={(value) => {
|
||||
this.updatePaymentField("products", value);
|
||||
}}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("order:Price"), i18next.t("plan:Price - Tooltip"))} :
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
import React from "react";
|
||||
import {Link} from "react-router-dom";
|
||||
import {Button, Col, List, Row, Table, Tooltip} from "antd";
|
||||
import {Button, List, Table, Tooltip} from "antd";
|
||||
import moment from "moment";
|
||||
import * as Setting from "./Setting";
|
||||
import * as PaymentBackend from "./backend/PaymentBackend";
|
||||
@@ -195,31 +195,21 @@ class PaymentListPage extends BaseListPage {
|
||||
paddingBottom: 8,
|
||||
}}
|
||||
renderItem={(productInfo, i) => {
|
||||
const price = productInfo.price || 0;
|
||||
const number = productInfo.quantity || 1;
|
||||
const price = productInfo.price * (productInfo.quantity || 1);
|
||||
const currency = record.currency || "USD";
|
||||
const productName = productInfo.displayName || productInfo.name;
|
||||
return (
|
||||
<List.Item>
|
||||
<Row style={{width: "100%"}} wrap={false} gutter={[12, 0]}>
|
||||
<Col flex="auto" style={{minWidth: 0}}>
|
||||
<div style={{display: "flex", alignItems: "center", minWidth: 0}}>
|
||||
<Tooltip placement="topLeft" title={i18next.t("general:Edit")}>
|
||||
<Button style={{marginRight: "5px"}} icon={<EditOutlined />} size="small" onClick={() => Setting.goToLinkSoft(this, `/products/${record.owner}/${productInfo.name}`)} />
|
||||
</Tooltip>
|
||||
<Tooltip placement="topLeft" title={productName}>
|
||||
<Link to={`/products/${record.owner}/${productInfo.name}`} style={{display: "inline-block", maxWidth: "100%", minWidth: 0, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap"}}>
|
||||
{productName}
|
||||
</Link>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</Col>
|
||||
<Col flex="none" style={{whiteSpace: "nowrap"}}>
|
||||
<span style={{color: "#666"}}>
|
||||
{Setting.getCurrencySymbol(currency)}{price} ({Setting.getCurrencyText(currency)}) × {number}
|
||||
</span>
|
||||
</Col>
|
||||
</Row>
|
||||
<div style={{display: "inline"}}>
|
||||
<Tooltip placement="topLeft" title={i18next.t("general:Edit")}>
|
||||
<Button style={{marginRight: "5px"}} icon={<EditOutlined />} size="small" onClick={() => Setting.goToLinkSoft(this, `/products/${record.owner}/${productInfo.name}`)} />
|
||||
</Tooltip>
|
||||
<Link to={`/products/${record.owner}/${productInfo.name}`}>
|
||||
{productInfo.displayName || productInfo.name}
|
||||
</Link>
|
||||
<span style={{marginLeft: "8px", color: "#666"}}>
|
||||
{Setting.getPriceDisplay(price, currency)}
|
||||
</span>
|
||||
</div>
|
||||
</List.Item>
|
||||
);
|
||||
}}
|
||||
|
||||
@@ -309,7 +309,7 @@ class PermissionEditPage extends React.Component {
|
||||
}
|
||||
const data = res.data.map((role) => Setting.getOption(`${role.owner}/${role.name}`, `${role.owner}/${role.name}`));
|
||||
if (args?.[1] === 1 && Array.isArray(res?.data)) {
|
||||
// res.data = [{owner: i18next.t("general:All"), name: "*"}, ...res.data];
|
||||
// res.data = [{owner: i18next.t("organization:All"), name: "*"}, ...res.data];
|
||||
res.data = [
|
||||
Setting.getOption(i18next.t("general:All"), "*"),
|
||||
...data,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -139,7 +139,7 @@ class ProviderListPage extends BaseListPage {
|
||||
...this.getColumnSearchProps("displayName"),
|
||||
},
|
||||
{
|
||||
title: i18next.t("general:Category"),
|
||||
title: i18next.t("provider:Category"),
|
||||
dataIndex: "category",
|
||||
key: "category",
|
||||
filterMultiple: false,
|
||||
|
||||
@@ -137,7 +137,7 @@ class RecordListPage extends BaseListPage {
|
||||
title: i18next.t("record:Status code"),
|
||||
dataIndex: "statusCode",
|
||||
key: "statusCode",
|
||||
width: "140px",
|
||||
width: "120px",
|
||||
sorter: true,
|
||||
...this.getColumnSearchProps("statusCode"),
|
||||
},
|
||||
|
||||
@@ -457,8 +457,8 @@ export const UserFields = ["owner", "name", "password", "display_name", "id", "t
|
||||
"is_admin", "homepage", "birthday", "gender", "password_type", "password_salt", "external_id", "avatar", "first_name", "last_name",
|
||||
"avatar_type", "permanent_avatar", "email_verified", "region", "location", "address",
|
||||
"affiliation", "title", "id_card_type", "id_card", "real_name", "is_verified", "bio", "tag", "language",
|
||||
"education", "score", "karma", "ranking", "balance", "balance_credit", "balance_currency", "currency", "is_default_avatar", "is_online",
|
||||
"is_forbidden", "is_deleted", "signup_application", "register_type", "register_source", "hash", "pre_hash", "access_key", "access_secret", "access_token",
|
||||
"education", "score", "karma", "ranking", "balance", "currency", "is_default_avatar", "is_online",
|
||||
"is_forbidden", "is_deleted", "signup_application", "hash", "pre_hash", "access_key", "access_secret", "access_token",
|
||||
"created_ip", "last_signin_time", "last_signin_ip", "github", "google", "qq", "wechat", "facebook", "dingtalk",
|
||||
"weibo", "gitee", "linkedin", "wecom", "lark", "gitlab", "adfs", "baidu", "alipay", "casdoor", "infoflow", "apple",
|
||||
"azuread", "azureadb2c", "slack", "steam", "bilibili", "okta", "douyin", "kwai", "line", "amazon", "auth0",
|
||||
@@ -469,7 +469,7 @@ export const UserFields = ["owner", "name", "password", "display_name", "id", "t
|
||||
"wepay", "xero", "yahoo", "yammer", "yandex", "zoom", "metamask", "web3onboard", "custom", "webauthnCredentials",
|
||||
"preferred_mfa_type", "recovery_codes", "totp_secret", "mfa_phone_enabled", "mfa_email_enabled", "invitation",
|
||||
"invitation_code", "face_ids", "ldap", "properties", "roles", "permissions", "groups", "last_change_password_time",
|
||||
"last_signin_wrong_time", "signin_wrong_times", "managedAccounts", "mfaAccounts", "mfaItems", "need_update_password",
|
||||
"last_signin_wrong_time", "signin_wrong_times", "managedAccounts", "mfaAccounts", "need_update_password",
|
||||
"created_time", "updated_time", "deleted_time",
|
||||
"ip_whitelist"];
|
||||
|
||||
@@ -500,7 +500,6 @@ export const GetTranslatedUserItems = () => {
|
||||
{name: "Country/Region", label: i18next.t("user:Country/Region")},
|
||||
{name: "Location", label: i18next.t("user:Location")},
|
||||
{name: "Address", label: i18next.t("user:Address")},
|
||||
{name: "Addresses", label: i18next.t("user:Addresses")},
|
||||
{name: "Affiliation", label: i18next.t("user:Affiliation")},
|
||||
{name: "Title", label: i18next.t("general:Title")},
|
||||
{name: "ID card type", label: i18next.t("user:ID card type")},
|
||||
@@ -524,8 +523,6 @@ export const GetTranslatedUserItems = () => {
|
||||
{name: "Karma", label: i18next.t("user:Karma")},
|
||||
{name: "Ranking", label: i18next.t("user:Ranking")},
|
||||
{name: "Signup application", label: i18next.t("general:Signup application")},
|
||||
{name: "Register type", label: i18next.t("user:Register type")},
|
||||
{name: "Register source", label: i18next.t("user:Register source")},
|
||||
{name: "API key", label: i18next.t("general:API key")},
|
||||
{name: "Groups", label: i18next.t("general:Groups")},
|
||||
{name: "Roles", label: i18next.t("general:Roles")},
|
||||
@@ -540,7 +537,6 @@ export const GetTranslatedUserItems = () => {
|
||||
{name: "IP whitelist", label: i18next.t("general:IP whitelist")},
|
||||
{name: "Multi-factor authentication", label: i18next.t("mfa:Multi-factor authentication")},
|
||||
{name: "WebAuthn credentials", label: i18next.t("user:WebAuthn credentials")},
|
||||
{name: "Last change password time", label: i18next.t("user:Last change password time")},
|
||||
{name: "Managed accounts", label: i18next.t("user:Managed accounts")},
|
||||
{name: "Face ID", label: i18next.t("login:Face ID")},
|
||||
{name: "MFA accounts", label: i18next.t("user:MFA accounts")},
|
||||
@@ -558,8 +554,6 @@ export function getUserColumns() {
|
||||
transField = "Country/Region";
|
||||
} else if (field === "mfaAccounts") {
|
||||
transField = "MFA accounts";
|
||||
} else if (field === "mfaItems") {
|
||||
transField = "MFA items";
|
||||
} else if (field === "face_ids") {
|
||||
transField = "Face ID";
|
||||
} else if (field === "managedAccounts") {
|
||||
@@ -2273,7 +2267,7 @@ export function getFormTypeItems(formType) {
|
||||
{name: "owner", label: "general:Organization", visible: true, width: "150"},
|
||||
{name: "createdTime", label: "general:Created time", visible: true, width: "180"},
|
||||
{name: "displayName", label: "general:Display name", visible: true, width: "150"},
|
||||
{name: "category", label: "general:Category", visible: true, width: "110"},
|
||||
{name: "category", label: "provider:Category", visible: true, width: "110"},
|
||||
{name: "type", label: "general:Type", visible: true, width: "110"},
|
||||
{name: "clientId", label: "provider:Client ID", visible: true, width: "100"},
|
||||
{name: "providerUrl", label: "provider:Provider URL", visible: true, width: "150"},
|
||||
|
||||
@@ -826,7 +826,7 @@ class SyncerEditPage extends React.Component {
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("general:Type"), i18next.t("general:Type - Tooltip"))} :
|
||||
{Setting.getLabel(i18next.t("general:Type"), i18next.t("cert:Type - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Select virtual={false} style={{width: "100%"}} value={this.state.syncer.type} onChange={(value => {
|
||||
@@ -878,7 +878,7 @@ class SyncerEditPage extends React.Component {
|
||||
this.state.syncer.databaseType !== "postgres" ? null : (
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("provider:SSL mode"), i18next.t("provider:SSL mode - Tooltip"))} :
|
||||
{Setting.getLabel(i18next.t("syncer:SSL mode"), i18next.t("syncer:SSL mode - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Select virtual={false} style={{width: "100%"}} value={this.state.syncer.sslMode} onChange={(value => {this.updateSyncerField("sslMode", value);})}>
|
||||
|
||||
@@ -158,7 +158,7 @@ class TokenEditPage extends React.Component {
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("provider:Scope"), i18next.t("provider:Scope - Tooltip"))}
|
||||
{Setting.getLabel(i18next.t("provider:Scope"), i18next.t("cert:Scope - Tooltip"))}
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={this.state.token.scope} onChange={e => {
|
||||
|
||||
@@ -261,7 +261,7 @@ class TransactionEditPage extends React.Component {
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("general:Category"), i18next.t("general:Category - Tooltip"))} :
|
||||
{Setting.getLabel(i18next.t("provider:Category"), i18next.t("provider:Category - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input disabled={true} value={this.state.transaction.category} />
|
||||
@@ -269,7 +269,7 @@ class TransactionEditPage extends React.Component {
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("general:Type"), i18next.t("general:Type - Tooltip"))} :
|
||||
{Setting.getLabel(i18next.t("general:Type"), i18next.t("cert:Type - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input disabled={true} value={this.state.transaction.type} onChange={e => {
|
||||
|
||||
@@ -609,20 +609,13 @@ class UserEditPage extends React.Component {
|
||||
);
|
||||
} else if (accountItem.name === "Addresses") {
|
||||
return (
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("user:Addresses"), i18next.t("user:Addresses"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<AddressTable
|
||||
title={i18next.t("user:Addresses")}
|
||||
table={this.state.user.addresses}
|
||||
onUpdateTable={(value) => {
|
||||
this.updateUserField("addresses", value);
|
||||
}}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
<AddressTable
|
||||
title={i18next.t("user:Addresses")}
|
||||
table={this.state.user.addresses}
|
||||
onUpdateTable={(value) => {
|
||||
this.updateUserField("addresses", value);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
} else if (accountItem.name === "Affiliation") {
|
||||
return (
|
||||
@@ -887,7 +880,7 @@ class UserEditPage extends React.Component {
|
||||
{Setting.getLabel(i18next.t("general:Transactions"), i18next.t("general:Transactions"))} :
|
||||
</Col>
|
||||
<Col span={22}>
|
||||
<TransactionTable title={i18next.t("general:Transactions")} transactions={this.state.transactions} hideTag={true} />
|
||||
<TransactionTable transactions={this.state.transactions} hideTag={true} />
|
||||
</Col>
|
||||
</Row>
|
||||
);
|
||||
@@ -1137,21 +1130,15 @@ class UserEditPage extends React.Component {
|
||||
{Setting.getLabel(i18next.t("mfa:Multi-factor authentication"), i18next.t("mfa:Multi-factor authentication - Tooltip "))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Card size="small" title={
|
||||
<div>
|
||||
{i18next.t("mfa:Multi-factor methods")}
|
||||
{this.state.multiFactorAuths?.some(mfaProps => mfaProps.enabled) ?
|
||||
<PopconfirmModal
|
||||
text={i18next.t("general:Disable")}
|
||||
title={i18next.t("general:Sure to disable") + "?"}
|
||||
onConfirm={() => this.deleteMfa()}
|
||||
size="small"
|
||||
/> : null
|
||||
}
|
||||
</div>
|
||||
}>
|
||||
<Card size="small" title={i18next.t("mfa:Multi-factor methods")}
|
||||
extra={this.state.multiFactorAuths?.some(mfaProps => mfaProps.enabled) ?
|
||||
<PopconfirmModal
|
||||
text={i18next.t("general:Disable")}
|
||||
title={i18next.t("general:Sure to disable") + "?"}
|
||||
onConfirm={() => this.deleteMfa()}
|
||||
/> : null
|
||||
}>
|
||||
<List
|
||||
size="small"
|
||||
rowKey="mfaType"
|
||||
itemLayout="horizontal"
|
||||
dataSource={this.state.multiFactorAuths}
|
||||
|
||||
@@ -44,15 +44,20 @@ function generateCodeChallenge(verifier) {
|
||||
}
|
||||
|
||||
function storeCodeVerifier(state, verifier) {
|
||||
localStorage.setItem(`pkce_verifier_${state}`, verifier);
|
||||
localStorage.setItem("pkce_verifier", `${state}#${verifier}`);
|
||||
}
|
||||
|
||||
export function getCodeVerifier(state) {
|
||||
return localStorage.getItem(`pkce_verifier_${state}`);
|
||||
const verifierStore = localStorage.getItem("pkce_verifier");
|
||||
const [storedState, verifier] = verifierStore ? verifierStore.split("#") : [null, null];
|
||||
if (storedState !== state) {
|
||||
return null;
|
||||
}
|
||||
return verifier;
|
||||
}
|
||||
|
||||
export function clearCodeVerifier(state) {
|
||||
localStorage.removeItem(`pkce_verifier_${state}`);
|
||||
localStorage.removeItem("pkce_verifier");
|
||||
}
|
||||
|
||||
const authInfo = {
|
||||
@@ -402,27 +407,24 @@ export function getProviderUrl(provider) {
|
||||
}
|
||||
}
|
||||
|
||||
export function getProviderLogoWidget(provider, options = {}) {
|
||||
export function getProviderLogoWidget(provider) {
|
||||
if (provider === undefined) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const url = getProviderUrl(provider);
|
||||
const disableLink = options.disableLink === true;
|
||||
const imgEl = <img width={36} height={36} src={Setting.getProviderLogoURL(provider)} alt={provider.displayName} />;
|
||||
|
||||
if (url !== "" && !disableLink) {
|
||||
if (url !== "") {
|
||||
return (
|
||||
<Tooltip title={provider.type}>
|
||||
<a target="_blank" rel="noreferrer" href={getProviderUrl(provider)}>
|
||||
{imgEl}
|
||||
<img width={36} height={36} src={Setting.getProviderLogoURL(provider)} alt={provider.displayName} />
|
||||
</a>
|
||||
</Tooltip>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<Tooltip title={provider.type}>
|
||||
{imgEl}
|
||||
<img width={36} height={36} src={Setting.getProviderLogoURL(provider)} alt={provider.displayName} />
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -23,24 +23,24 @@ class RegionSelect extends React.Component {
|
||||
super(props);
|
||||
this.state = {
|
||||
classes: props,
|
||||
value: "",
|
||||
};
|
||||
}
|
||||
|
||||
onChange(e) {
|
||||
this.props.onChange(e);
|
||||
this.setState({value: e});
|
||||
}
|
||||
|
||||
render() {
|
||||
const value = this.props.value !== undefined && this.props.value !== "" ? this.props.value : (this.props.defaultValue !== undefined && this.props.defaultValue !== "" ? this.props.defaultValue : undefined);
|
||||
return (
|
||||
<Select virtual={false}
|
||||
size={this.props.size}
|
||||
showSearch
|
||||
optionFilterProp="label"
|
||||
style={{width: "100%"}}
|
||||
value={value}
|
||||
defaultValue={this.props.defaultValue || undefined}
|
||||
placeholder="Please select country/region"
|
||||
onChange={(val) => {this.onChange(val);}}
|
||||
onChange={(value => {this.onChange(value);})}
|
||||
filterOption={(input, option) => (option?.label ?? "").toLowerCase().includes(input.toLowerCase())}
|
||||
filterSort={(optionA, optionB) =>
|
||||
(optionA?.label ?? "").toLowerCase().localeCompare((optionB?.label ?? "").toLowerCase())
|
||||
|
||||
@@ -113,12 +113,19 @@
|
||||
"Order - Tooltip": "Je kleiner der Wert, desto höher rangiert er auf der Apps-Seite",
|
||||
"Org choice mode": "Organisationsauswahlmodus",
|
||||
"Org choice mode - Tooltip": "Organisationsauswahlmodus - Hinweis",
|
||||
"Other domains": "Other domains",
|
||||
"Other domains - Tooltip": "Other domains - Tooltip",
|
||||
"Please enable \"Signin session\" first before enabling \"Auto signin\"": "Bitte aktivieren Sie zuerst \"Anmeldesitzung\", bevor Sie \"Automatische Anmeldung\" aktivieren.",
|
||||
"Please input additional domains": "Please input additional domains",
|
||||
"Please input your application!": "Bitte geben Sie Ihre Anwendung ein!",
|
||||
"Please input your organization!": "Bitte geben Sie Ihre Organisation ein!",
|
||||
"Please select a HTML file": "Bitte wählen Sie eine HTML-Datei aus",
|
||||
"Pop up": "Pop-up",
|
||||
"Providers": "Anbieter",
|
||||
"Proxy SSL mode": "Proxy SSL mode",
|
||||
"Proxy SSL mode - Tooltip": "Proxy SSL mode - Tooltip",
|
||||
"Proxy domain": "Proxy domain",
|
||||
"Proxy domain - Tooltip": "Proxy domain - Tooltip",
|
||||
"Random": "Zufällig",
|
||||
"Real name": "Echter Name",
|
||||
"Redirect URL": "Weiterleitungs-URL",
|
||||
@@ -128,6 +135,7 @@
|
||||
"Refresh token expire": "Gültigkeitsdauer des Refresh-Tokens",
|
||||
"Refresh token expire - Tooltip": "Angabe der Gültigkeitsdauer des Refresh Tokens",
|
||||
"Reset to Empty": "Auf leer zurücksetzen",
|
||||
"Reverse Proxy": "Reverse Proxy",
|
||||
"Right": "Rechts",
|
||||
"Rule": "Regel",
|
||||
"SAML hash algorithm": "SAML-Hash-Algorithmus",
|
||||
@@ -135,6 +143,8 @@
|
||||
"SAML metadata": "SAML-Metadaten",
|
||||
"SAML metadata - Tooltip": "Die Metadaten des SAML-Protokolls - Hinweis",
|
||||
"SAML reply URL": "SAML Reply-URL",
|
||||
"SSL cert": "SSL cert",
|
||||
"SSL cert - Tooltip": "SSL cert - Tooltip",
|
||||
"Security": "Sicherheit",
|
||||
"Select": "Auswählen",
|
||||
"Side panel HTML": "Sidepanel-HTML",
|
||||
@@ -165,6 +175,8 @@
|
||||
"Token signing method": "Token-Signaturmethode",
|
||||
"Token signing method - Tooltip": "Signaturmethode des JWT-Tokens muss mit dem Zertifikat übereinstimmen",
|
||||
"UI Customization": "UI-Anpassung",
|
||||
"Upstream host": "Upstream host",
|
||||
"Upstream host - Tooltip": "Upstream host - Tooltip",
|
||||
"Use Email as NameID": "E-Mail als NameID verwenden",
|
||||
"Use Email as NameID - Tooltip": "E-Mail als NameID verwenden",
|
||||
"Vertical": "Vertikal",
|
||||
@@ -186,7 +198,9 @@
|
||||
"Expire in years - Tooltip": "Gültigkeitsdauer des Zertifikats in Jahren",
|
||||
"New Cert": "Neues Zertifikat",
|
||||
"Private key": "Private-Key",
|
||||
"Private key - Tooltip": "Privater Schlüssel, der zum öffentlichen Schlüsselzertifikat gehört"
|
||||
"Private key - Tooltip": "Privater Schlüssel, der zum öffentlichen Schlüsselzertifikat gehört",
|
||||
"Scope - Tooltip": "Nutzungsszenarien des Zertifikats",
|
||||
"Type - Tooltip": "Art des Zertifikats"
|
||||
},
|
||||
"code": {
|
||||
"Code you received": "Der Code, den Sie erhalten haben",
|
||||
@@ -275,7 +289,6 @@
|
||||
"Applications that require authentication": "Anwendungen, die eine Authentifizierung erfordern",
|
||||
"Apps": "Anwendungen",
|
||||
"Authorization": "Autorisierung",
|
||||
"Auto": "Auto",
|
||||
"Avatar": "Profilbild",
|
||||
"Avatar - Tooltip": "Öffentliches Avatarbild für den Benutzer",
|
||||
"Back": "Zurück",
|
||||
@@ -757,6 +770,7 @@
|
||||
"Account menu - Tooltip": "Kontomenü - Tooltip",
|
||||
"Admin navbar items": "Admin-Navigationsleisten-Elemente",
|
||||
"Admin navbar items - Tooltip": "Admin-Navigationsleisten-Elemente - Tooltip",
|
||||
"All": "All",
|
||||
"Balance credit": "Guthaben (Credits)",
|
||||
"Balance credit - Tooltip": "Guthaben (Credits) - Tooltip",
|
||||
"Balance currency": "Guthabenwährung",
|
||||
@@ -921,6 +935,7 @@
|
||||
"Invalid product": "Invalid product",
|
||||
"Is recharge": "Ist Aufladung",
|
||||
"Is recharge - Tooltip": "Ob das Produkt zum Aufladen des Guthabens dient",
|
||||
"Name": "Name",
|
||||
"New Product": "Neues Produkt",
|
||||
"No recharge options available": "No recharge options available",
|
||||
"Order created successfully": "Bestellung erfolgreich erstellt",
|
||||
@@ -933,6 +948,7 @@
|
||||
"Please add at least one recharge option when custom amount is disabled": "Bitte fügen Sie mindestens eine Aufladeoption hinzu, wenn der benutzerdefinierte Betrag deaktiviert ist",
|
||||
"Please select a currency": "Bitte wählen Sie eine Währung",
|
||||
"Please select at least one payment provider": "Bitte wählen Sie mindestens einen Zahlungsanbieter aus",
|
||||
"Price": "Price",
|
||||
"Processing payment...": "Zahlung wird verarbeitet...",
|
||||
"Product list cannot be empty": "Produktliste darf nicht leer sein",
|
||||
"Product not found or invalid": "Product not found or invalid",
|
||||
@@ -977,6 +993,7 @@
|
||||
"Auth Key - Tooltip": "Authentifizierungsschlüssel für den Dienst",
|
||||
"Auth URL": "Auth-URL",
|
||||
"Auth URL - Tooltip": "URL für die Authentifizierung",
|
||||
"Auto": "Auto",
|
||||
"Base URL": "Basis-URL",
|
||||
"Base URL - Tooltip": "Basis-URL des Dienstes",
|
||||
"Bucket": "Eimer",
|
||||
@@ -985,6 +1002,8 @@
|
||||
"Can signin": "Kann sich einloggen",
|
||||
"Can signup": "Kann sich registrieren",
|
||||
"Can unlink": "Entlinken möglich",
|
||||
"Category": "Kategorie",
|
||||
"Category - Tooltip": "Kennung zur Kategorisierung und Gruppierung von Elementen oder Inhalten, erleichtert Filterung und Verwaltung",
|
||||
"Channel No.": "Kanal Nr.",
|
||||
"Channel No. - Tooltip": "Eindeutige Nummer zur Identifizierung eines Kommunikations- oder Datenübertragungskanals, verwendet zur Unterscheidung verschiedener Übertragungswege",
|
||||
"Chat ID": "Chat-ID",
|
||||
@@ -1001,6 +1020,7 @@
|
||||
"Content - Tooltip": "Spezifische Informationen oder Daten in Nachrichten, Benachrichtigungen oder Dokumenten",
|
||||
"DB test": "DB-Test",
|
||||
"DB test - Tooltip": "DB-Test - Tooltip",
|
||||
"Disable": "Disable",
|
||||
"Domain": "Domäne",
|
||||
"Domain - Tooltip": "Benutzerdefinierte Domain für Objektspeicher",
|
||||
"Edit Provider": "Provider bearbeiten",
|
||||
@@ -1010,6 +1030,7 @@
|
||||
"Email regex - Tooltip": "Nur E-Mails, die diesem regulären Ausdruck entsprechen, können sich registrieren oder anmelden",
|
||||
"Email title": "Email-Titel",
|
||||
"Email title - Tooltip": "Betreff der E-Mail",
|
||||
"Enable": "Enable",
|
||||
"Enable PKCE": "PKCE aktivieren",
|
||||
"Enable PKCE - Tooltip": "Enable PKCE - Tooltip",
|
||||
"Enable proxy": "Proxy aktivieren",
|
||||
@@ -1284,6 +1305,8 @@
|
||||
"SSH password": "SSH-Passwort",
|
||||
"SSH port": "SSH-Port",
|
||||
"SSH user": "SSH-Benutzer",
|
||||
"SSL mode": "SSL-Modus",
|
||||
"SSL mode - Tooltip": "SSL-Modus",
|
||||
"Service account key": "Service-Account-Schlüssel",
|
||||
"Sync interval": "Synchronisierungsintervall",
|
||||
"Sync interval - Tooltip": "Einheit in Sekunden",
|
||||
|
||||
@@ -113,12 +113,19 @@
|
||||
"Order - Tooltip": "The smaller the value, the higher it ranks in the Apps page",
|
||||
"Org choice mode": "Org choice mode",
|
||||
"Org choice mode - Tooltip": "Method used to select the organization to log in",
|
||||
"Other domains": "Other domains",
|
||||
"Other domains - Tooltip": "Additional domains that should also route to this application",
|
||||
"Please enable \"Signin session\" first before enabling \"Auto signin\"": "Please enable \"Signin session\" first before enabling \"Auto signin\"",
|
||||
"Please input additional domains": "Please input additional domains",
|
||||
"Please input your application!": "Please input your application!",
|
||||
"Please input your organization!": "Please input your organization!",
|
||||
"Please select a HTML file": "Please select a HTML file",
|
||||
"Pop up": "Pop up",
|
||||
"Providers": "Providers",
|
||||
"Proxy SSL mode": "Proxy SSL mode",
|
||||
"Proxy SSL mode - Tooltip": "SSL/TLS mode for the reverse proxy",
|
||||
"Proxy domain": "Proxy domain",
|
||||
"Proxy domain - Tooltip": "The public-facing domain for this application (e.g., blog.example.com)",
|
||||
"Random": "Random",
|
||||
"Real name": "Real name",
|
||||
"Redirect URL": "Redirect URL",
|
||||
@@ -128,6 +135,7 @@
|
||||
"Refresh token expire": "Refresh token expire",
|
||||
"Refresh token expire - Tooltip": "Refresh token expiration time",
|
||||
"Reset to Empty": "Reset to Empty",
|
||||
"Reverse Proxy": "Reverse Proxy",
|
||||
"Right": "Right",
|
||||
"Rule": "Rule",
|
||||
"SAML hash algorithm": "SAML hash algorithm",
|
||||
@@ -135,6 +143,8 @@
|
||||
"SAML metadata": "SAML metadata",
|
||||
"SAML metadata - Tooltip": "The metadata of SAML protocol",
|
||||
"SAML reply URL": "SAML reply URL",
|
||||
"SSL cert": "SSL cert",
|
||||
"SSL cert - Tooltip": "Certificate to use for TLS termination",
|
||||
"Security": "Security",
|
||||
"Select": "Select",
|
||||
"Side panel HTML": "Side panel HTML",
|
||||
@@ -165,6 +175,8 @@
|
||||
"Token signing method": "Token signing method",
|
||||
"Token signing method - Tooltip": "Signing method of JWT token, needs to be the same algorithm as the certificate",
|
||||
"UI Customization": "UI Customization",
|
||||
"Upstream host": "Upstream host",
|
||||
"Upstream host - Tooltip": "The upstream backend address to forward requests to (e.g., localhost:8080 or 192.168.1.100)",
|
||||
"Use Email as NameID": "Use Email as NameID",
|
||||
"Use Email as NameID - Tooltip": "Use Email as NameID",
|
||||
"Vertical": "Vertical",
|
||||
@@ -186,7 +198,9 @@
|
||||
"Expire in years - Tooltip": "Validity period of the certificate, in years",
|
||||
"New Cert": "New Cert",
|
||||
"Private key": "Private key",
|
||||
"Private key - Tooltip": "Private key corresponding to the public key certificate"
|
||||
"Private key - Tooltip": "Private key corresponding to the public key certificate",
|
||||
"Scope - Tooltip": "Usage scenarios of the certificate",
|
||||
"Type - Tooltip": "Type of certificate"
|
||||
},
|
||||
"code": {
|
||||
"Code you received": "Code you received",
|
||||
@@ -275,7 +289,6 @@
|
||||
"Applications that require authentication": "Applications that require authentication",
|
||||
"Apps": "Apps",
|
||||
"Authorization": "Authorization",
|
||||
"Auto": "Auto",
|
||||
"Avatar": "Avatar",
|
||||
"Avatar - Tooltip": "Public avatar image for the user",
|
||||
"Back": "Back",
|
||||
@@ -757,6 +770,7 @@
|
||||
"Account menu - Tooltip": "Account menu - Tooltip",
|
||||
"Admin navbar items": "Admin navbar items",
|
||||
"Admin navbar items - Tooltip": "Admin navbar items - Tooltip",
|
||||
"All": "All",
|
||||
"Balance credit": "Balance credit",
|
||||
"Balance credit - Tooltip": "Balance credit - Tooltip",
|
||||
"Balance currency": "Balance currency",
|
||||
@@ -921,6 +935,7 @@
|
||||
"Invalid product": "Invalid product",
|
||||
"Is recharge": "Is recharge",
|
||||
"Is recharge - Tooltip": "Whether the current product is to recharge balance",
|
||||
"Name": "Name",
|
||||
"New Product": "New Product",
|
||||
"No recharge options available": "No recharge options available",
|
||||
"Order created successfully": "Order created successfully",
|
||||
@@ -933,6 +948,7 @@
|
||||
"Please add at least one recharge option when custom amount is disabled": "Please add at least one recharge option when custom amount is disabled",
|
||||
"Please select a currency": "Please select a currency",
|
||||
"Please select at least one payment provider": "Please select at least one payment provider",
|
||||
"Price": "Price",
|
||||
"Processing payment...": "Processing payment...",
|
||||
"Product list cannot be empty": "Product list cannot be empty",
|
||||
"Product not found or invalid": "Product not found or invalid",
|
||||
@@ -977,6 +993,7 @@
|
||||
"Auth Key - Tooltip": "Authentication key for the service",
|
||||
"Auth URL": "Auth URL",
|
||||
"Auth URL - Tooltip": "URL for authentication",
|
||||
"Auto": "Auto",
|
||||
"Base URL": "Base URL",
|
||||
"Base URL - Tooltip": "Base URL of the service",
|
||||
"Bucket": "Bucket",
|
||||
@@ -985,6 +1002,8 @@
|
||||
"Can signin": "Can signin",
|
||||
"Can signup": "Can signup",
|
||||
"Can unlink": "Can unlink",
|
||||
"Category": "Category",
|
||||
"Category - Tooltip": "Identifier for categorizing and grouping items or content, facilitating filtering and management",
|
||||
"Channel No.": "Channel No.",
|
||||
"Channel No. - Tooltip": "Unique number identifying a communication or data transmission channel, used to distinguish different transmission paths",
|
||||
"Chat ID": "Chat ID",
|
||||
@@ -1001,6 +1020,7 @@
|
||||
"Content - Tooltip": "Specific information or data contained in messages, notifications, or documents",
|
||||
"DB test": "DB test",
|
||||
"DB test - Tooltip": "DB test - Tooltip",
|
||||
"Disable": "Disable",
|
||||
"Domain": "Domain",
|
||||
"Domain - Tooltip": "Custom domain for object storage",
|
||||
"Edit Provider": "Edit Provider",
|
||||
@@ -1010,6 +1030,7 @@
|
||||
"Email regex - Tooltip": "Only emails matching this regular expression can register or sign in",
|
||||
"Email title": "Email title",
|
||||
"Email title - Tooltip": "Subject of the email",
|
||||
"Enable": "Enable",
|
||||
"Enable PKCE": "Enable PKCE",
|
||||
"Enable PKCE - Tooltip": "Enable PKCE (Proof Key for Code Exchange) for enhanced OAuth 2.0 security",
|
||||
"Enable proxy": "Enable proxy",
|
||||
@@ -1284,6 +1305,8 @@
|
||||
"SSH password": "SSH password",
|
||||
"SSH port": "SSH port",
|
||||
"SSH user": "SSH user",
|
||||
"SSL mode": "SSL mode",
|
||||
"SSL mode - Tooltip": "The SSL mode used when connecting to the database",
|
||||
"Service account key": "Service account key",
|
||||
"Sync interval": "Sync interval",
|
||||
"Sync interval - Tooltip": "Unit in seconds",
|
||||
|
||||
@@ -113,12 +113,19 @@
|
||||
"Order - Tooltip": "Cuanto menor sea el valor, más alto se clasificará en la página de Aplicaciones",
|
||||
"Org choice mode": "Modo de selección de organización",
|
||||
"Org choice mode - Tooltip": "Método utilizado para seleccionar la organización para iniciar sesión - Sugerencia",
|
||||
"Other domains": "Other domains",
|
||||
"Other domains - Tooltip": "Other domains - Tooltip",
|
||||
"Please enable \"Signin session\" first before enabling \"Auto signin\"": "Por favor, habilita \"Sesión de inicio de sesión\" primero antes de habilitar \"Inicio de sesión automático\"",
|
||||
"Please input additional domains": "Please input additional domains",
|
||||
"Please input your application!": "¡Por favor, ingrese su solicitud!",
|
||||
"Please input your organization!": "¡Por favor, ingrese su organización!",
|
||||
"Please select a HTML file": "Por favor, seleccione un archivo HTML",
|
||||
"Pop up": "Ventana emergente",
|
||||
"Providers": "Proveedores",
|
||||
"Proxy SSL mode": "Proxy SSL mode",
|
||||
"Proxy SSL mode - Tooltip": "Proxy SSL mode - Tooltip",
|
||||
"Proxy domain": "Proxy domain",
|
||||
"Proxy domain - Tooltip": "Proxy domain - Tooltip",
|
||||
"Random": "Aleatorio",
|
||||
"Real name": "Nombre real",
|
||||
"Redirect URL": "Redireccionar URL",
|
||||
@@ -128,6 +135,7 @@
|
||||
"Refresh token expire": "Token de actualización expirado",
|
||||
"Refresh token expire - Tooltip": "Tiempo de caducidad del token de actualización",
|
||||
"Reset to Empty": "Restablecer a vacío",
|
||||
"Reverse Proxy": "Reverse Proxy",
|
||||
"Right": "Correcto",
|
||||
"Rule": "Regla",
|
||||
"SAML hash algorithm": "Algoritmo hash SAML",
|
||||
@@ -135,6 +143,8 @@
|
||||
"SAML metadata": "Metadatos de SAML",
|
||||
"SAML metadata - Tooltip": "Los metadatos del protocolo SAML - Sugerencia",
|
||||
"SAML reply URL": "URL de respuesta SAML",
|
||||
"SSL cert": "SSL cert",
|
||||
"SSL cert - Tooltip": "SSL cert - Tooltip",
|
||||
"Security": "Seguridad",
|
||||
"Select": "Seleccionar",
|
||||
"Side panel HTML": "Panel lateral HTML",
|
||||
@@ -165,6 +175,8 @@
|
||||
"Token signing method": "Método de firma del token",
|
||||
"Token signing method - Tooltip": "Método de firma del token JWT, debe ser el mismo algoritmo que el certificado",
|
||||
"UI Customization": "Personalización de la interfaz",
|
||||
"Upstream host": "Upstream host",
|
||||
"Upstream host - Tooltip": "Upstream host - Tooltip",
|
||||
"Use Email as NameID": "Usar correo electrónico como NameID",
|
||||
"Use Email as NameID - Tooltip": "Usar correo electrónico como NameID - Información adicional",
|
||||
"Vertical": "Vertical",
|
||||
@@ -186,7 +198,9 @@
|
||||
"Expire in years - Tooltip": "Período de validez del certificado, en años",
|
||||
"New Cert": "Nuevo certificado",
|
||||
"Private key": "Clave privada",
|
||||
"Private key - Tooltip": "Clave privada correspondiente al certificado de clave pública"
|
||||
"Private key - Tooltip": "Clave privada correspondiente al certificado de clave pública",
|
||||
"Scope - Tooltip": "Escenarios de uso del certificado",
|
||||
"Type - Tooltip": "Tipo de certificado"
|
||||
},
|
||||
"code": {
|
||||
"Code you received": "Código que recibió",
|
||||
@@ -275,7 +289,6 @@
|
||||
"Applications that require authentication": "Aplicaciones que requieren autenticación",
|
||||
"Apps": "Aplicaciones",
|
||||
"Authorization": "Autorización",
|
||||
"Auto": "Auto",
|
||||
"Avatar": "Avatar",
|
||||
"Avatar - Tooltip": "Imagen de avatar pública para el usuario",
|
||||
"Back": "Atrás",
|
||||
@@ -757,6 +770,7 @@
|
||||
"Account menu - Tooltip": "Menú de cuenta - Tooltip",
|
||||
"Admin navbar items": "Elementos de la barra de navegación del administrador",
|
||||
"Admin navbar items - Tooltip": "Elementos de la barra de navegación del administrador - Tooltip",
|
||||
"All": "All",
|
||||
"Balance credit": "Saldo (créditos)",
|
||||
"Balance credit - Tooltip": "Saldo (créditos) - Tooltip",
|
||||
"Balance currency": "Moneda del saldo",
|
||||
@@ -921,6 +935,7 @@
|
||||
"Invalid product": "Invalid product",
|
||||
"Is recharge": "Es recarga",
|
||||
"Is recharge - Tooltip": "Indica si el producto actual es para recargar saldo",
|
||||
"Name": "Name",
|
||||
"New Product": "Nuevo producto",
|
||||
"No recharge options available": "No recharge options available",
|
||||
"Order created successfully": "Pedido creado con éxito",
|
||||
@@ -933,6 +948,7 @@
|
||||
"Please add at least one recharge option when custom amount is disabled": "Por favor, añade al menos una opción de recarga cuando el importe personalizado esté desactivado",
|
||||
"Please select a currency": "Por favor, selecciona una moneda",
|
||||
"Please select at least one payment provider": "Por favor, selecciona al menos un proveedor de pago",
|
||||
"Price": "Price",
|
||||
"Processing payment...": "Procesando el pago...",
|
||||
"Product list cannot be empty": "La lista de productos no puede estar vacía",
|
||||
"Product not found or invalid": "Product not found or invalid",
|
||||
@@ -977,6 +993,7 @@
|
||||
"Auth Key - Tooltip": "Clave de autenticación para el servicio",
|
||||
"Auth URL": "URL de autenticación",
|
||||
"Auth URL - Tooltip": "URL para autenticación",
|
||||
"Auto": "Auto",
|
||||
"Base URL": "URL base",
|
||||
"Base URL - Tooltip": "URL base del servicio",
|
||||
"Bucket": "Cubo",
|
||||
@@ -985,6 +1002,8 @@
|
||||
"Can signin": "¿Puedes iniciar sesión?",
|
||||
"Can signup": "Puede registrarse",
|
||||
"Can unlink": "Desvincular",
|
||||
"Category": "Categoría",
|
||||
"Category - Tooltip": "Identificador para categorizar y agrupar elementos o contenido, facilitando el filtrado y la gestión",
|
||||
"Channel No.": "Canal No.",
|
||||
"Channel No. - Tooltip": "Número único que identifica un canal de comunicación o transmisión de datos, utilizado para distinguir diferentes rutas de transmisión",
|
||||
"Chat ID": "ID de chat",
|
||||
@@ -1001,6 +1020,7 @@
|
||||
"Content - Tooltip": "Contenido - Información adicional",
|
||||
"DB test": "Prueba de BD",
|
||||
"DB test - Tooltip": "Prueba de BD - Tooltip",
|
||||
"Disable": "Disable",
|
||||
"Domain": "Dominio",
|
||||
"Domain - Tooltip": "Dominio personalizado para almacenamiento de objetos",
|
||||
"Edit Provider": "Editar proveedor",
|
||||
@@ -1010,6 +1030,7 @@
|
||||
"Email regex - Tooltip": "Expresión regular de correo electrónico - Información adicional",
|
||||
"Email title": "Título del correo electrónico",
|
||||
"Email title - Tooltip": "Título del correo electrónico",
|
||||
"Enable": "Enable",
|
||||
"Enable PKCE": "Habilitar PKCE",
|
||||
"Enable PKCE - Tooltip": "Habilitar PKCE - Tooltip",
|
||||
"Enable proxy": "Habilitar proxy",
|
||||
@@ -1284,6 +1305,8 @@
|
||||
"SSH password": "Contraseña SSH",
|
||||
"SSH port": "Puerto SSH",
|
||||
"SSH user": "Usuario SSH",
|
||||
"SSL mode": "Modo SSL",
|
||||
"SSL mode - Tooltip": "Modo SSL",
|
||||
"Service account key": "Clave de la cuenta de servicio",
|
||||
"Sync interval": "Intervalo de sincronización",
|
||||
"Sync interval - Tooltip": "Unidad en segundos",
|
||||
|
||||
@@ -113,12 +113,19 @@
|
||||
"Order - Tooltip": "Plus la valeur est petite, plus elle est classée haut dans la page Applications",
|
||||
"Org choice mode": "Mode de choix d'organisation",
|
||||
"Org choice mode - Tooltip": "Méthode utilisée pour sélectionner l'organisation pour se connecter - Info-bulle",
|
||||
"Other domains": "Other domains",
|
||||
"Other domains - Tooltip": "Other domains - Tooltip",
|
||||
"Please enable \"Signin session\" first before enabling \"Auto signin\"": "Veuillez activer \"Session de connexion\" avant d'activer \"Connexion automatique\"",
|
||||
"Please input additional domains": "Please input additional domains",
|
||||
"Please input your application!": "Veuillez saisir votre application !",
|
||||
"Please input your organization!": "Veuillez saisir votre organisation !",
|
||||
"Please select a HTML file": "Veuillez sélectionner un fichier HTML",
|
||||
"Pop up": "Fenêtre contextuelle",
|
||||
"Providers": "Fournisseurs",
|
||||
"Proxy SSL mode": "Proxy SSL mode",
|
||||
"Proxy SSL mode - Tooltip": "Proxy SSL mode - Tooltip",
|
||||
"Proxy domain": "Proxy domain",
|
||||
"Proxy domain - Tooltip": "Proxy domain - Tooltip",
|
||||
"Random": "Aléatoire",
|
||||
"Real name": "Nom réel",
|
||||
"Redirect URL": "URL de redirection",
|
||||
@@ -128,6 +135,7 @@
|
||||
"Refresh token expire": "Expiration du jeton de rafraîchissement",
|
||||
"Refresh token expire - Tooltip": "Durée avant expiration du jeton de rafraîchissement",
|
||||
"Reset to Empty": "Réinitialiser à vide",
|
||||
"Reverse Proxy": "Reverse Proxy",
|
||||
"Right": "Droit",
|
||||
"Rule": "Règle",
|
||||
"SAML hash algorithm": "Algorithme de hachage SAML",
|
||||
@@ -135,6 +143,8 @@
|
||||
"SAML metadata": "Métadonnées SAML",
|
||||
"SAML metadata - Tooltip": "Métadonnées du protocole SAML - Info-bulle",
|
||||
"SAML reply URL": "URL de réponse SAML",
|
||||
"SSL cert": "SSL cert",
|
||||
"SSL cert - Tooltip": "SSL cert - Tooltip",
|
||||
"Security": "Sécurité",
|
||||
"Select": "Sélectionner",
|
||||
"Side panel HTML": "HTML du panneau latéral",
|
||||
@@ -165,6 +175,8 @@
|
||||
"Token signing method": "Méthode de signature du jeton",
|
||||
"Token signing method - Tooltip": "Méthode de signature du jeton JWT, doit être le même algorithme que le certificat",
|
||||
"UI Customization": "Personnalisation de l'interface",
|
||||
"Upstream host": "Upstream host",
|
||||
"Upstream host - Tooltip": "Upstream host - Tooltip",
|
||||
"Use Email as NameID": "Utiliser l'e-mail comme NameID",
|
||||
"Use Email as NameID - Tooltip": "Utiliser l'e-mail comme NameID - Infobulle",
|
||||
"Vertical": "Vertical",
|
||||
@@ -186,7 +198,9 @@
|
||||
"Expire in years - Tooltip": "Période de validité du certificat, en années",
|
||||
"New Cert": "Nouveau Certificat",
|
||||
"Private key": "Clé privée",
|
||||
"Private key - Tooltip": "Clé privée correspondant au certificat de la clé publique"
|
||||
"Private key - Tooltip": "Clé privée correspondant au certificat de la clé publique",
|
||||
"Scope - Tooltip": "Scénarios d'utilisation du certificat",
|
||||
"Type - Tooltip": "Type de certificat"
|
||||
},
|
||||
"code": {
|
||||
"Code you received": "Le code que vous avez reçu",
|
||||
@@ -275,7 +289,6 @@
|
||||
"Applications that require authentication": "Applications qui nécessitent une authentification",
|
||||
"Apps": "Applications",
|
||||
"Authorization": "Autorisation",
|
||||
"Auto": "Auto",
|
||||
"Avatar": "Avatar",
|
||||
"Avatar - Tooltip": "Image d'avatar publique pour le compte",
|
||||
"Back": "Retour",
|
||||
@@ -757,6 +770,7 @@
|
||||
"Account menu - Tooltip": "Menu du compte - Infobulle",
|
||||
"Admin navbar items": "Éléments de la barre de navigation admin",
|
||||
"Admin navbar items - Tooltip": "Éléments de la barre de navigation admin - Infobulle",
|
||||
"All": "All",
|
||||
"Balance credit": "Solde (crédits)",
|
||||
"Balance credit - Tooltip": "Solde (crédits) - Infobulle",
|
||||
"Balance currency": "Devise du solde",
|
||||
@@ -921,6 +935,7 @@
|
||||
"Invalid product": "Invalid product",
|
||||
"Is recharge": "Est un rechargement",
|
||||
"Is recharge - Tooltip": "Indique si le produit actuel permet de recharger le solde",
|
||||
"Name": "Name",
|
||||
"New Product": "Nouveau produit",
|
||||
"No recharge options available": "No recharge options available",
|
||||
"Order created successfully": "Commande créée avec succès",
|
||||
@@ -933,6 +948,7 @@
|
||||
"Please add at least one recharge option when custom amount is disabled": "Veuillez ajouter au moins une option de recharge lorsque le montant personnalisé est désactivé",
|
||||
"Please select a currency": "Veuillez sélectionner une devise",
|
||||
"Please select at least one payment provider": "Veuillez sélectionner au moins un fournisseur de paiement",
|
||||
"Price": "Price",
|
||||
"Processing payment...": "Traitement du paiement...",
|
||||
"Product list cannot be empty": "La liste des produits ne peut pas être vide",
|
||||
"Product not found or invalid": "Product not found or invalid",
|
||||
@@ -977,6 +993,7 @@
|
||||
"Auth Key - Tooltip": "Clé d'authentification - Infobulle",
|
||||
"Auth URL": "URL d'authentification",
|
||||
"Auth URL - Tooltip": "URL d'authentification",
|
||||
"Auto": "Auto",
|
||||
"Base URL": "URL de base",
|
||||
"Base URL - Tooltip": "URL de base - Infobulle",
|
||||
"Bucket": "seau",
|
||||
@@ -985,6 +1002,8 @@
|
||||
"Can signin": "Pouvez-vous vous connecter?",
|
||||
"Can signup": "Peut s'inscrire",
|
||||
"Can unlink": "Peut annuler le lien",
|
||||
"Category": "Catégorie",
|
||||
"Category - Tooltip": "Sélectionnez une catégorie",
|
||||
"Channel No.": "chaîne n°",
|
||||
"Channel No. - Tooltip": "Canal N°",
|
||||
"Chat ID": "ID de chat",
|
||||
@@ -1001,6 +1020,7 @@
|
||||
"Content - Tooltip": "Contenu - Infobulle",
|
||||
"DB test": "Test BD",
|
||||
"DB test - Tooltip": "Test BD - Infobulle",
|
||||
"Disable": "Disable",
|
||||
"Domain": "Domaine",
|
||||
"Domain - Tooltip": "Domaine personnalisé pour le stockage d'objets",
|
||||
"Edit Provider": "Modifier le fournisseur",
|
||||
@@ -1010,6 +1030,7 @@
|
||||
"Email regex - Tooltip": "Regex e-mail - Infobulle",
|
||||
"Email title": "Titre de l'email",
|
||||
"Email title - Tooltip": "Titre de l'email",
|
||||
"Enable": "Enable",
|
||||
"Enable PKCE": "Activer PKCE",
|
||||
"Enable PKCE - Tooltip": "Enable PKCE - Tooltip",
|
||||
"Enable proxy": "Activer le proxy",
|
||||
@@ -1284,6 +1305,8 @@
|
||||
"SSH password": "Mot de passe SSH",
|
||||
"SSH port": "Port SSH",
|
||||
"SSH user": "Utilisateur SSH",
|
||||
"SSL mode": "Mode SSL",
|
||||
"SSL mode - Tooltip": "Mode SSL",
|
||||
"Service account key": "Clé du compte de service",
|
||||
"Sync interval": "Intervalle de synchronisation",
|
||||
"Sync interval - Tooltip": "Unité en secondes",
|
||||
|
||||
@@ -113,12 +113,19 @@
|
||||
"Order - Tooltip": "値が小さいほど、アプリページで上位にランク付けされます",
|
||||
"Org choice mode": "組織選択モード",
|
||||
"Org choice mode - Tooltip": "ログインする組織を選択する方法 - ヒント",
|
||||
"Other domains": "Other domains",
|
||||
"Other domains - Tooltip": "Other domains - Tooltip",
|
||||
"Please enable \"Signin session\" first before enabling \"Auto signin\"": "\"自動サインイン\"を有効にする前に、まず\"サインインセッション\"を有効にしてください",
|
||||
"Please input additional domains": "Please input additional domains",
|
||||
"Please input your application!": "あなたの申請を入力してください!",
|
||||
"Please input your organization!": "あなたの組織を入力してください!",
|
||||
"Please select a HTML file": "HTMLファイルを選択してください",
|
||||
"Pop up": "ポップアップ",
|
||||
"Providers": "プロバイダー",
|
||||
"Proxy SSL mode": "Proxy SSL mode",
|
||||
"Proxy SSL mode - Tooltip": "Proxy SSL mode - Tooltip",
|
||||
"Proxy domain": "Proxy domain",
|
||||
"Proxy domain - Tooltip": "Proxy domain - Tooltip",
|
||||
"Random": "ランダム",
|
||||
"Real name": "本名",
|
||||
"Redirect URL": "リダイレクトURL",
|
||||
@@ -128,6 +135,7 @@
|
||||
"Refresh token expire": "リフレッシュトークンの有効期限が切れました",
|
||||
"Refresh token expire - Tooltip": "リフレッシュトークンの有効期限時間",
|
||||
"Reset to Empty": "空にリセット",
|
||||
"Reverse Proxy": "Reverse Proxy",
|
||||
"Right": "右",
|
||||
"Rule": "ルール",
|
||||
"SAML hash algorithm": "SAMLハッシュアルゴリズム",
|
||||
@@ -135,6 +143,8 @@
|
||||
"SAML metadata": "SAMLメタデータ",
|
||||
"SAML metadata - Tooltip": "SAMLプロトコルのメタデータ - ヒント",
|
||||
"SAML reply URL": "SAMLリプライURL",
|
||||
"SSL cert": "SSL cert",
|
||||
"SSL cert - Tooltip": "SSL cert - Tooltip",
|
||||
"Security": "セキュリティ",
|
||||
"Select": "選択",
|
||||
"Side panel HTML": "サイドパネルのHTML",
|
||||
@@ -165,6 +175,8 @@
|
||||
"Token signing method": "トークン署名方法",
|
||||
"Token signing method - Tooltip": "JWTトークンの署名方法。証明書と同じアルゴリズムである必要があります。",
|
||||
"UI Customization": "UIのカスタマイズ",
|
||||
"Upstream host": "Upstream host",
|
||||
"Upstream host - Tooltip": "Upstream host - Tooltip",
|
||||
"Use Email as NameID": "メールアドレスをNameIDとして使用",
|
||||
"Use Email as NameID - Tooltip": "メールアドレスをNameIDとして使用 - ツールチップ",
|
||||
"Vertical": "垂直",
|
||||
@@ -186,7 +198,9 @@
|
||||
"Expire in years - Tooltip": "証明書の有効期間、年数で",
|
||||
"New Cert": "新しい証明書",
|
||||
"Private key": "プライベートキー",
|
||||
"Private key - Tooltip": "公開鍵証明書に対応する秘密鍵"
|
||||
"Private key - Tooltip": "公開鍵証明書に対応する秘密鍵",
|
||||
"Scope - Tooltip": "証明書の使用シナリオ",
|
||||
"Type - Tooltip": "証明書の種類"
|
||||
},
|
||||
"code": {
|
||||
"Code you received": "受け取ったコード",
|
||||
@@ -275,7 +289,6 @@
|
||||
"Applications that require authentication": "認証が必要なアプリケーション",
|
||||
"Apps": "アプリ",
|
||||
"Authorization": "認可",
|
||||
"Auto": "Auto",
|
||||
"Avatar": "アバター",
|
||||
"Avatar - Tooltip": "ユーザーのパブリックアバター画像",
|
||||
"Back": "戻る",
|
||||
@@ -757,6 +770,7 @@
|
||||
"Account menu - Tooltip": "アカウントメニュー - ツールチップ",
|
||||
"Admin navbar items": "管理者ナビバー項目",
|
||||
"Admin navbar items - Tooltip": "管理者ナビバー項目 - ツールチップ",
|
||||
"All": "All",
|
||||
"Balance credit": "残高クレジット",
|
||||
"Balance credit - Tooltip": "残高クレジット - ツールチップ",
|
||||
"Balance currency": "残高通貨",
|
||||
@@ -921,6 +935,7 @@
|
||||
"Invalid product": "Invalid product",
|
||||
"Is recharge": "チャージ用か",
|
||||
"Is recharge - Tooltip": "現在の製品が残高をチャージするためかどうか",
|
||||
"Name": "Name",
|
||||
"New Product": "新製品",
|
||||
"No recharge options available": "No recharge options available",
|
||||
"Order created successfully": "注文が正常に作成されました",
|
||||
@@ -933,6 +948,7 @@
|
||||
"Please add at least one recharge option when custom amount is disabled": "任意金額が無効な場合は、少なくとも1つのチャージオプションを追加してください",
|
||||
"Please select a currency": "通貨を選択してください",
|
||||
"Please select at least one payment provider": "少なくとも1つの支払いプロバイダーを選択してください",
|
||||
"Price": "Price",
|
||||
"Processing payment...": "支払い処理中...",
|
||||
"Product list cannot be empty": "商品リストを空にできません",
|
||||
"Product not found or invalid": "Product not found or invalid",
|
||||
@@ -977,6 +993,7 @@
|
||||
"Auth Key - Tooltip": "認証キー - ツールチップ",
|
||||
"Auth URL": "認証URL",
|
||||
"Auth URL - Tooltip": "認証URL",
|
||||
"Auto": "Auto",
|
||||
"Base URL": "ベースURL",
|
||||
"Base URL - Tooltip": "ベースURL - ツールチップ",
|
||||
"Bucket": "バケツ",
|
||||
@@ -985,6 +1002,8 @@
|
||||
"Can signin": "サインインできますか?",
|
||||
"Can signup": "サインアップできますか?",
|
||||
"Can unlink": "アンリンクすることができます",
|
||||
"Category": "カテゴリー",
|
||||
"Category - Tooltip": "カテゴリーを選択してください",
|
||||
"Channel No.": "チャンネル番号",
|
||||
"Channel No. - Tooltip": "チャンネル番号",
|
||||
"Chat ID": "チャットID",
|
||||
@@ -1001,6 +1020,7 @@
|
||||
"Content - Tooltip": "コンテンツ - ツールチップ",
|
||||
"DB test": "DBテスト",
|
||||
"DB test - Tooltip": "DBテスト - ツールチップ",
|
||||
"Disable": "Disable",
|
||||
"Domain": "ドメイン",
|
||||
"Domain - Tooltip": "オブジェクトストレージのカスタムドメイン",
|
||||
"Edit Provider": "編集プロバイダー",
|
||||
@@ -1010,6 +1030,7 @@
|
||||
"Email regex - Tooltip": "メール正規表現 - ツールチップ",
|
||||
"Email title": "電子メールのタイトル",
|
||||
"Email title - Tooltip": "メールのタイトル",
|
||||
"Enable": "Enable",
|
||||
"Enable PKCE": "PKCEを有効にする",
|
||||
"Enable PKCE - Tooltip": "PKCEを有効にする - ツールチップ",
|
||||
"Enable proxy": "プロキシを有効にする",
|
||||
@@ -1284,6 +1305,8 @@
|
||||
"SSH password": "SSHパスワード",
|
||||
"SSH port": "SSHポート",
|
||||
"SSH user": "SSHユーザー",
|
||||
"SSL mode": "SSLモード",
|
||||
"SSL mode - Tooltip": "SSLモード",
|
||||
"Service account key": "サービスアカウントキー",
|
||||
"Sync interval": "同期の間隔",
|
||||
"Sync interval - Tooltip": "単位は秒です",
|
||||
|
||||
@@ -113,12 +113,19 @@
|
||||
"Order - Tooltip": "Im mniejsza wartość, tym wyżej jest rangowana na stronie Aplikacji",
|
||||
"Org choice mode": "Tryb wyboru organizacji",
|
||||
"Org choice mode - Tooltip": "Metoda wyboru organizacji do logowania - Podpowiedź",
|
||||
"Other domains": "Other domains",
|
||||
"Other domains - Tooltip": "Other domains - Tooltip",
|
||||
"Please enable \"Signin session\" first before enabling \"Auto signin\"": "Najpierw włącz \"sesję logowania\", zanim włączysz \"automatyczne logowanie\"",
|
||||
"Please input additional domains": "Please input additional domains",
|
||||
"Please input your application!": "Proszę wprowadzić swoją aplikację!",
|
||||
"Please input your organization!": "Proszę wprowadzić swoją organizację!",
|
||||
"Please select a HTML file": "Proszę wybrać plik HTML",
|
||||
"Pop up": "Wyskakujące okno",
|
||||
"Providers": "Dostawcy",
|
||||
"Proxy SSL mode": "Proxy SSL mode",
|
||||
"Proxy SSL mode - Tooltip": "Proxy SSL mode - Tooltip",
|
||||
"Proxy domain": "Proxy domain",
|
||||
"Proxy domain - Tooltip": "Proxy domain - Tooltip",
|
||||
"Random": "Losowy",
|
||||
"Real name": "Prawdziwe imię",
|
||||
"Redirect URL": "URL przekierowania",
|
||||
@@ -128,6 +135,7 @@
|
||||
"Refresh token expire": "Czas wygaśnięcia odświeżania tokena",
|
||||
"Refresh token expire - Tooltip": "Czas wygaśnięcia tokena odświeżania",
|
||||
"Reset to Empty": "Resetuj do pustego",
|
||||
"Reverse Proxy": "Reverse Proxy",
|
||||
"Right": "Prawo",
|
||||
"Rule": "Reguła",
|
||||
"SAML hash algorithm": "Algorytm skrótu SAML",
|
||||
@@ -135,6 +143,8 @@
|
||||
"SAML metadata": "Metadane SAML",
|
||||
"SAML metadata - Tooltip": "Metadane protokołu SAML - Podpowiedź",
|
||||
"SAML reply URL": "URL odpowiedzi SAML",
|
||||
"SSL cert": "SSL cert",
|
||||
"SSL cert - Tooltip": "SSL cert - Tooltip",
|
||||
"Security": "Bezpieczeństwo",
|
||||
"Select": "Wybierz",
|
||||
"Side panel HTML": "HTML panelu bocznego",
|
||||
@@ -165,6 +175,8 @@
|
||||
"Token signing method": "Metoda podpisywania tokena",
|
||||
"Token signing method - Tooltip": "Metoda podpisywania tokena JWT, musi być tym samym algorytmem co certyfikat",
|
||||
"UI Customization": "Dostosowanie interfejsu",
|
||||
"Upstream host": "Upstream host",
|
||||
"Upstream host - Tooltip": "Upstream host - Tooltip",
|
||||
"Use Email as NameID": "Użyj e-maila jako NameID",
|
||||
"Use Email as NameID - Tooltip": "Użyj e-maila jako NameID - Podpowiedź",
|
||||
"Vertical": "Pionowy",
|
||||
@@ -186,7 +198,9 @@
|
||||
"Expire in years - Tooltip": "Okres ważności certyfikatu, w latach",
|
||||
"New Cert": "Nowy certyfikat",
|
||||
"Private key": "Klucz prywatny",
|
||||
"Private key - Tooltip": "Klucz prywatny odpowiadający certyfikatowi klucza publicznego"
|
||||
"Private key - Tooltip": "Klucz prywatny odpowiadający certyfikatowi klucza publicznego",
|
||||
"Scope - Tooltip": "Scenariusze użycia certyfikatu",
|
||||
"Type - Tooltip": "Typ certyfikatu"
|
||||
},
|
||||
"code": {
|
||||
"Code you received": "Kod, który otrzymałeś",
|
||||
@@ -275,7 +289,6 @@
|
||||
"Applications that require authentication": "Aplikacje wymagające uwierzytelniania",
|
||||
"Apps": "Aplikacje",
|
||||
"Authorization": "Autoryzacja",
|
||||
"Auto": "Auto",
|
||||
"Avatar": "Awatar",
|
||||
"Avatar - Tooltip": "Publiczny obraz awatara użytkownika",
|
||||
"Back": "Wstecz",
|
||||
@@ -757,6 +770,7 @@
|
||||
"Account menu - Tooltip": "Menu konta - Podpowiedź",
|
||||
"Admin navbar items": "Elementy paska nawigacji administratora",
|
||||
"Admin navbar items - Tooltip": "Elementy paska nawigacji administratora - Podpowiedź",
|
||||
"All": "All",
|
||||
"Balance credit": "Saldo kredytów",
|
||||
"Balance credit - Tooltip": "Saldo kredytów - Podpowiedź",
|
||||
"Balance currency": "Waluta salda",
|
||||
@@ -921,6 +935,7 @@
|
||||
"Invalid product": "Invalid product",
|
||||
"Is recharge": "Jest doładowaniem",
|
||||
"Is recharge - Tooltip": "Czy bieżący produkt służy do doładowania salda",
|
||||
"Name": "Name",
|
||||
"New Product": "Nowy produkt",
|
||||
"No recharge options available": "No recharge options available",
|
||||
"Order created successfully": "Zamówienie utworzone pomyślnie",
|
||||
@@ -933,6 +948,7 @@
|
||||
"Please add at least one recharge option when custom amount is disabled": "Dodaj co najmniej jedną opcję doładowania, gdy kwota niestandardowa jest wyłączona",
|
||||
"Please select a currency": "Wybierz walutę",
|
||||
"Please select at least one payment provider": "Wybierz co najmniej jednego dostawcę płatności",
|
||||
"Price": "Price",
|
||||
"Processing payment...": "Przetwarzanie płatności...",
|
||||
"Product list cannot be empty": "Lista produktów nie może być pusta",
|
||||
"Product not found or invalid": "Product not found or invalid",
|
||||
@@ -977,6 +993,7 @@
|
||||
"Auth Key - Tooltip": "Klucz autoryzacji - Podpowiedź",
|
||||
"Auth URL": "Adres URL autoryzacji",
|
||||
"Auth URL - Tooltip": "Adres URL autoryzacji",
|
||||
"Auto": "Auto",
|
||||
"Base URL": "Podstawowy adres URL",
|
||||
"Base URL - Tooltip": "Podstawowy adres URL",
|
||||
"Bucket": "Wiadro",
|
||||
@@ -985,6 +1002,8 @@
|
||||
"Can signin": "Można się zalogować",
|
||||
"Can signup": "Można się zarejestrować",
|
||||
"Can unlink": "Można odłączyć",
|
||||
"Category": "Kategoria",
|
||||
"Category - Tooltip": "Wybierz kategorię",
|
||||
"Channel No.": "Channel No.",
|
||||
"Channel No. - Tooltip": "Channel No. - Tooltip",
|
||||
"Chat ID": "Chat ID",
|
||||
@@ -1001,6 +1020,7 @@
|
||||
"Content - Tooltip": "Treść",
|
||||
"DB test": "Test bazy danych",
|
||||
"DB test - Tooltip": "Test bazy danych",
|
||||
"Disable": "Disable",
|
||||
"Domain": "Domain",
|
||||
"Domain - Tooltip": "Domain - Tooltip",
|
||||
"Edit Provider": "Edit Provider",
|
||||
@@ -1010,6 +1030,7 @@
|
||||
"Email regex - Tooltip": "Email regex - Tooltip",
|
||||
"Email title": "Email title",
|
||||
"Email title - Tooltip": "Email title - Tooltip",
|
||||
"Enable": "Enable",
|
||||
"Enable PKCE": "Enable PKCE",
|
||||
"Enable PKCE - Tooltip": "Enable PKCE - Tooltip",
|
||||
"Enable proxy": "Enable proxy",
|
||||
@@ -1284,6 +1305,8 @@
|
||||
"SSH password": "Hasło SSH",
|
||||
"SSH port": "Port SSH",
|
||||
"SSH user": "Użytkownik SSH",
|
||||
"SSL mode": "Tryb SSL",
|
||||
"SSL mode - Tooltip": "Tryb SSL - etykietka",
|
||||
"Service account key": "Klucz konta usługi",
|
||||
"Sync interval": "Interwał synchronizacji",
|
||||
"Sync interval - Tooltip": "Jednostka w sekundach",
|
||||
|
||||
@@ -113,12 +113,19 @@
|
||||
"Order - Tooltip": "Quanto menor o valor, maior a classificação na página de Aplicativos",
|
||||
"Org choice mode": "Modo de escolha da organização",
|
||||
"Org choice mode - Tooltip": "Método usado para selecionar a organização para fazer login - Dica",
|
||||
"Other domains": "Other domains",
|
||||
"Other domains - Tooltip": "Other domains - Tooltip",
|
||||
"Please enable \"Signin session\" first before enabling \"Auto signin\"": "Por favor, habilite a \"Sessão de login\" primeiro antes de habilitar o \"Login automático\"",
|
||||
"Please input additional domains": "Please input additional domains",
|
||||
"Please input your application!": "Por favor, insira o nome da sua aplicação!",
|
||||
"Please input your organization!": "Por favor, insira o nome da sua organização!",
|
||||
"Please select a HTML file": "Por favor, selecione um arquivo HTML",
|
||||
"Pop up": "Abrir em pop-up",
|
||||
"Providers": "Provedores",
|
||||
"Proxy SSL mode": "Proxy SSL mode",
|
||||
"Proxy SSL mode - Tooltip": "Proxy SSL mode - Tooltip",
|
||||
"Proxy domain": "Proxy domain",
|
||||
"Proxy domain - Tooltip": "Proxy domain - Tooltip",
|
||||
"Random": "Aleatório",
|
||||
"Real name": "Nome real",
|
||||
"Redirect URL": "URL de redirecionamento",
|
||||
@@ -128,6 +135,7 @@
|
||||
"Refresh token expire": "Expiração do token de atualização",
|
||||
"Refresh token expire - Tooltip": "Tempo de expiração do token de atualização",
|
||||
"Reset to Empty": "Redefinir para vazio",
|
||||
"Reverse Proxy": "Reverse Proxy",
|
||||
"Right": "Direita",
|
||||
"Rule": "Regra",
|
||||
"SAML hash algorithm": "Algoritmo de hash SAML",
|
||||
@@ -135,6 +143,8 @@
|
||||
"SAML metadata": "Metadados do SAML",
|
||||
"SAML metadata - Tooltip": "Os metadados do protocolo SAML - Dica",
|
||||
"SAML reply URL": "URL de resposta do SAML",
|
||||
"SSL cert": "SSL cert",
|
||||
"SSL cert - Tooltip": "SSL cert - Tooltip",
|
||||
"Security": "Segurança",
|
||||
"Select": "Selecionar",
|
||||
"Side panel HTML": "HTML do painel lateral",
|
||||
@@ -165,6 +175,8 @@
|
||||
"Token signing method": "Método de assinatura do token",
|
||||
"Token signing method - Tooltip": "Método de assinatura do token JWT. Deve ser o mesmo algoritmo do certificado.",
|
||||
"UI Customization": "Personalização da interface",
|
||||
"Upstream host": "Upstream host",
|
||||
"Upstream host - Tooltip": "Upstream host - Tooltip",
|
||||
"Use Email as NameID": "Usar e-mail como NameID",
|
||||
"Use Email as NameID - Tooltip": "Dica: usar e-mail como NameID",
|
||||
"Vertical": "Vertical",
|
||||
@@ -186,7 +198,9 @@
|
||||
"Expire in years - Tooltip": "Período de validade do certificado, em anos",
|
||||
"New Cert": "Novo Certificado",
|
||||
"Private key": "Chave privada",
|
||||
"Private key - Tooltip": "Chave privada correspondente ao certificado de chave pública"
|
||||
"Private key - Tooltip": "Chave privada correspondente ao certificado de chave pública",
|
||||
"Scope - Tooltip": "Cenários de uso do certificado",
|
||||
"Type - Tooltip": "Tipo de certificado"
|
||||
},
|
||||
"code": {
|
||||
"Code you received": "Código que você recebeu",
|
||||
@@ -275,7 +289,6 @@
|
||||
"Applications that require authentication": "Aplicações que requerem autenticação",
|
||||
"Apps": "Aplicativos",
|
||||
"Authorization": "Autorização",
|
||||
"Auto": "Auto",
|
||||
"Avatar": "Avatar",
|
||||
"Avatar - Tooltip": "Imagem de avatar pública do usuário",
|
||||
"Back": "Voltar",
|
||||
@@ -757,6 +770,7 @@
|
||||
"Account menu - Tooltip": "Dica: menu da conta",
|
||||
"Admin navbar items": "Itens da barra de navegação do administrador",
|
||||
"Admin navbar items - Tooltip": "Dica: itens da barra de navegação do administrador",
|
||||
"All": "All",
|
||||
"Balance credit": "Saldo de créditos",
|
||||
"Balance credit - Tooltip": "Dica: saldo de créditos",
|
||||
"Balance currency": "Moeda do saldo",
|
||||
@@ -921,6 +935,7 @@
|
||||
"Invalid product": "Invalid product",
|
||||
"Is recharge": "É recarga",
|
||||
"Is recharge - Tooltip": "Se o produto atual é para recarregar saldo",
|
||||
"Name": "Name",
|
||||
"New Product": "Novo Produto",
|
||||
"No recharge options available": "No recharge options available",
|
||||
"Order created successfully": "Pedido criado com sucesso",
|
||||
@@ -933,6 +948,7 @@
|
||||
"Please add at least one recharge option when custom amount is disabled": "Por favor, adicione pelo menos uma opção de recarga quando o valor personalizado estiver desativado",
|
||||
"Please select a currency": "Por favor, selecione uma moeda",
|
||||
"Please select at least one payment provider": "Por favor, selecione pelo menos um provedor de pagamento",
|
||||
"Price": "Price",
|
||||
"Processing payment...": "Processando pagamento...",
|
||||
"Product list cannot be empty": "A lista de produtos não pode estar vazia",
|
||||
"Product not found or invalid": "Product not found or invalid",
|
||||
@@ -977,6 +993,7 @@
|
||||
"Auth Key - Tooltip": "Dica: chave de autenticação",
|
||||
"Auth URL": "URL de autenticação",
|
||||
"Auth URL - Tooltip": "URL de autenticação",
|
||||
"Auto": "Auto",
|
||||
"Base URL": "URL base",
|
||||
"Base URL - Tooltip": "Dica: URL base",
|
||||
"Bucket": "Bucket",
|
||||
@@ -985,6 +1002,8 @@
|
||||
"Can signin": "Pode fazer login",
|
||||
"Can signup": "Pode se inscrever",
|
||||
"Can unlink": "Pode desvincular",
|
||||
"Category": "Categoria",
|
||||
"Category - Tooltip": "Selecione uma categoria",
|
||||
"Channel No.": "Número do canal",
|
||||
"Channel No. - Tooltip": "Número do canal",
|
||||
"Chat ID": "ID do chat",
|
||||
@@ -1001,6 +1020,7 @@
|
||||
"Content - Tooltip": "Dica: conteúdo",
|
||||
"DB test": "Teste do banco de dados",
|
||||
"DB test - Tooltip": "Dica: teste do banco de dados",
|
||||
"Disable": "Disable",
|
||||
"Domain": "Domínio",
|
||||
"Domain - Tooltip": "Domínio personalizado para armazenamento de objetos",
|
||||
"Edit Provider": "Editar Provedor",
|
||||
@@ -1010,6 +1030,7 @@
|
||||
"Email regex - Tooltip": "Dica: regex de e-mail",
|
||||
"Email title": "Título do e-mail",
|
||||
"Email title - Tooltip": "Título do e-mail",
|
||||
"Enable": "Enable",
|
||||
"Enable PKCE": "Ativar PKCE",
|
||||
"Enable PKCE - Tooltip": "Dica: ativar PKCE",
|
||||
"Enable proxy": "Ativar proxy",
|
||||
@@ -1284,6 +1305,8 @@
|
||||
"SSH password": "Senha SSH",
|
||||
"SSH port": "Porta SSH",
|
||||
"SSH user": "Usuário SSH",
|
||||
"SSL mode": "Modo SSL",
|
||||
"SSL mode - Tooltip": "Dica: modo SSL",
|
||||
"Service account key": "Chave da conta de serviço",
|
||||
"Sync interval": "Intervalo de sincronização",
|
||||
"Sync interval - Tooltip": "Unidade em segundos",
|
||||
|
||||
@@ -113,12 +113,19 @@
|
||||
"Order - Tooltip": "Değer ne kadar küçükse, Uygulamalar sayfasında o kadar yüksek sıralanır",
|
||||
"Org choice mode": "Organizasyon seçim modu",
|
||||
"Org choice mode - Tooltip": "Giriş yapmak için organizasyon seçme yöntemi - İpucu",
|
||||
"Other domains": "Other domains",
|
||||
"Other domains - Tooltip": "Other domains - Tooltip",
|
||||
"Please enable \"Signin session\" first before enabling \"Auto signin\"": "Lütfen \"Oturum açma oturumu\"nu etkinleştirmeden önce \"Otomatik oturum açma\"yı etkinleştirin",
|
||||
"Please input additional domains": "Please input additional domains",
|
||||
"Please input your application!": "Lütfen uygulamanızı girin!",
|
||||
"Please input your organization!": "Lütfen organizasyonunuzu girin!",
|
||||
"Please select a HTML file": "Lütfen bir HTML dosyası seçin",
|
||||
"Pop up": "Açılır pencere",
|
||||
"Providers": "Sağlayıcılar",
|
||||
"Proxy SSL mode": "Proxy SSL mode",
|
||||
"Proxy SSL mode - Tooltip": "Proxy SSL mode - Tooltip",
|
||||
"Proxy domain": "Proxy domain",
|
||||
"Proxy domain - Tooltip": "Proxy domain - Tooltip",
|
||||
"Random": "Rastgele",
|
||||
"Real name": "Gerçek ad",
|
||||
"Redirect URL": "Yönlendirme URL'si",
|
||||
@@ -128,6 +135,7 @@
|
||||
"Refresh token expire": "Yenileme jetonu sona erer",
|
||||
"Refresh token expire - Tooltip": "Yenileme jetonunun son kullanma süresi",
|
||||
"Reset to Empty": "Boşalt",
|
||||
"Reverse Proxy": "Reverse Proxy",
|
||||
"Right": "Sağ",
|
||||
"Rule": "Kural",
|
||||
"SAML hash algorithm": "SAML karma algoritması",
|
||||
@@ -135,6 +143,8 @@
|
||||
"SAML metadata": "SAML meta verileri",
|
||||
"SAML metadata - Tooltip": "SAML protokolünün meta verileri - İpucu",
|
||||
"SAML reply URL": "SAML yanıt URL'si",
|
||||
"SSL cert": "SSL cert",
|
||||
"SSL cert - Tooltip": "SSL cert - Tooltip",
|
||||
"Security": "Güvenlik",
|
||||
"Select": "Seç",
|
||||
"Side panel HTML": "Yan panel HTML",
|
||||
@@ -165,6 +175,8 @@
|
||||
"Token signing method": "Token imzalama yöntemi",
|
||||
"Token signing method - Tooltip": "JWT token'ın imzalama yöntemi, sertifika ile aynı algoritma olmalıdır",
|
||||
"UI Customization": "Arayüz Özelleştirme",
|
||||
"Upstream host": "Upstream host",
|
||||
"Upstream host - Tooltip": "Upstream host - Tooltip",
|
||||
"Use Email as NameID": "NameID olarak E-posta kullan",
|
||||
"Use Email as NameID - Tooltip": "NameID olarak E-posta kullanın - Araç ipucu",
|
||||
"Vertical": "Dikey",
|
||||
@@ -186,7 +198,9 @@
|
||||
"Expire in years - Tooltip": "Sertifikanın geçerlilik süresi, yıllarda",
|
||||
"New Cert": "Yeni Sertifika",
|
||||
"Private key": "Özel anahtar",
|
||||
"Private key - Tooltip": "Genel anahtar sertifikasına karşılık gelen özel anahtar"
|
||||
"Private key - Tooltip": "Genel anahtar sertifikasına karşılık gelen özel anahtar",
|
||||
"Scope - Tooltip": "Sertifikanın kullanım senaryoları",
|
||||
"Type - Tooltip": "Sertifika türü"
|
||||
},
|
||||
"code": {
|
||||
"Code you received": "Aldığınız kod",
|
||||
@@ -275,7 +289,6 @@
|
||||
"Applications that require authentication": "Kimlik doğrulaması gerektiren uygulamalar",
|
||||
"Apps": "Uygulamalar",
|
||||
"Authorization": "Yetkilendirme",
|
||||
"Auto": "Auto",
|
||||
"Avatar": "Avatar",
|
||||
"Avatar - Tooltip": "Kullanıcı için genel avatar resmi",
|
||||
"Back": "Geri",
|
||||
@@ -757,6 +770,7 @@
|
||||
"Account menu - Tooltip": "Hesap menüsü - Araç ipucu",
|
||||
"Admin navbar items": "Yönetici gezinme çubuğu öğeleri",
|
||||
"Admin navbar items - Tooltip": "Yönetici gezinme çubuğu öğeleri - Araç ipucu",
|
||||
"All": "All",
|
||||
"Balance credit": "Bakiye kredisi",
|
||||
"Balance credit - Tooltip": "Bakiye kredisi - Araç ipucu",
|
||||
"Balance currency": "Bakiye para birimi",
|
||||
@@ -921,6 +935,7 @@
|
||||
"Invalid product": "Invalid product",
|
||||
"Is recharge": "Yeniden yükleme mi",
|
||||
"Is recharge - Tooltip": "Mevcut ürün bakiye yeniden yüklemesi ise",
|
||||
"Name": "Name",
|
||||
"New Product": "Yeni Ürün",
|
||||
"No recharge options available": "No recharge options available",
|
||||
"Order created successfully": "Sipariş başarıyla oluşturuldu",
|
||||
@@ -933,6 +948,7 @@
|
||||
"Please add at least one recharge option when custom amount is disabled": "Özel tutar devre dışıyken en az bir yeniden yükleme seçeneği ekleyin",
|
||||
"Please select a currency": "Lütfen bir para birimi seçin",
|
||||
"Please select at least one payment provider": "Lütfen en az bir ödeme sağlayıcısı seçin",
|
||||
"Price": "Price",
|
||||
"Processing payment...": "Ödeme işleniyor...",
|
||||
"Product list cannot be empty": "Ürün listesi boş olamaz",
|
||||
"Product not found or invalid": "Product not found or invalid",
|
||||
@@ -977,6 +993,7 @@
|
||||
"Auth Key - Tooltip": "Kimlik Doğrulama Anahtarı - Araç ipucu",
|
||||
"Auth URL": "Yetkilendirme URL'si",
|
||||
"Auth URL - Tooltip": "Yetkilendirme URL'si",
|
||||
"Auto": "Auto",
|
||||
"Base URL": "Temel URL",
|
||||
"Base URL - Tooltip": "Temel URL - Araç ipucu",
|
||||
"Bucket": "Bucket",
|
||||
@@ -985,6 +1002,8 @@
|
||||
"Can signin": "Giriş yapabilir",
|
||||
"Can signup": "Kayıt yapabilir",
|
||||
"Can unlink": "Bağlantıyı kesebilir",
|
||||
"Category": "Kategori",
|
||||
"Category - Tooltip": "Bir kategori seçin",
|
||||
"Channel No.": "Kanal Numarası",
|
||||
"Channel No. - Tooltip": "Kanal Numarası",
|
||||
"Chat ID": "Sohbet Kimliği",
|
||||
@@ -1001,6 +1020,7 @@
|
||||
"Content - Tooltip": "İçerik - Araç ipucu",
|
||||
"DB test": "Veritabanı testi",
|
||||
"DB test - Tooltip": "Veritabanı testi - Araç ipucu",
|
||||
"Disable": "Disable",
|
||||
"Domain": "Alan adı",
|
||||
"Domain - Tooltip": "Nesne depolama için özel alan adı",
|
||||
"Edit Provider": "Sağlayıcıyı Düzenle",
|
||||
@@ -1010,6 +1030,7 @@
|
||||
"Email regex - Tooltip": "E-posta düzenli ifadesi - Araç ipucu",
|
||||
"Email title": "E-posta başlığı",
|
||||
"Email title - Tooltip": "E-posta başlığı",
|
||||
"Enable": "Enable",
|
||||
"Enable PKCE": "PKCE'yi etkinleştir",
|
||||
"Enable PKCE - Tooltip": "PKCE'yi etkinleştir - Araç ipucu",
|
||||
"Enable proxy": "Proxy'yi etkinleştir",
|
||||
@@ -1284,6 +1305,8 @@
|
||||
"SSH password": "SSH şifresi",
|
||||
"SSH port": "SSH portu",
|
||||
"SSH user": "SSH kullanıcısı",
|
||||
"SSL mode": "SSL modu",
|
||||
"SSL mode - Tooltip": "SSL modu - İpucu",
|
||||
"Service account key": "Service account key",
|
||||
"Sync interval": "Senkronizasyon aralığı",
|
||||
"Sync interval - Tooltip": "Birimi saniye cinsinden",
|
||||
|
||||
@@ -113,12 +113,19 @@
|
||||
"Order - Tooltip": "Чим менше значення, тим вище воно ранжується на сторінці програм",
|
||||
"Org choice mode": "Режим вибору організації",
|
||||
"Org choice mode - Tooltip": "Режим вибору організації – підказка",
|
||||
"Other domains": "Other domains",
|
||||
"Other domains - Tooltip": "Other domains - Tooltip",
|
||||
"Please enable \"Signin session\" first before enabling \"Auto signin\"": "Спочатку увімкніть \"Сесію входу\", перш ніж увімкнути \"Автоматичний вхід\"",
|
||||
"Please input additional domains": "Please input additional domains",
|
||||
"Please input your application!": "Будь ласка, введіть свою заявку!",
|
||||
"Please input your organization!": "Будь ласка, введіть вашу організацію!",
|
||||
"Please select a HTML file": "Виберіть файл HTML",
|
||||
"Pop up": "Вспливаюче вікно",
|
||||
"Providers": "Постачальники",
|
||||
"Proxy SSL mode": "Proxy SSL mode",
|
||||
"Proxy SSL mode - Tooltip": "Proxy SSL mode - Tooltip",
|
||||
"Proxy domain": "Proxy domain",
|
||||
"Proxy domain - Tooltip": "Proxy domain - Tooltip",
|
||||
"Random": "Випадковий",
|
||||
"Real name": "Справжнє ім'я",
|
||||
"Redirect URL": "URL-адреса перенаправлення",
|
||||
@@ -128,6 +135,7 @@
|
||||
"Refresh token expire": "Термін дії маркера оновлення закінчився",
|
||||
"Refresh token expire - Tooltip": "Оновити термін дії маркера",
|
||||
"Reset to Empty": "Скинути до порожнього",
|
||||
"Reverse Proxy": "Reverse Proxy",
|
||||
"Right": "правильно",
|
||||
"Rule": "правило",
|
||||
"SAML hash algorithm": "Хеш-алгоритм SAML",
|
||||
@@ -135,6 +143,8 @@
|
||||
"SAML metadata": "Метадані SAML",
|
||||
"SAML metadata - Tooltip": "Метадані протоколу SAML",
|
||||
"SAML reply URL": "URL-адреса відповіді SAML",
|
||||
"SSL cert": "SSL cert",
|
||||
"SSL cert - Tooltip": "SSL cert - Tooltip",
|
||||
"Security": "Безпека",
|
||||
"Select": "Виберіть",
|
||||
"Side panel HTML": "HTML бічної панелі",
|
||||
@@ -165,6 +175,8 @@
|
||||
"Token signing method": "Метод підпису токена",
|
||||
"Token signing method - Tooltip": "Метод підпису JWT-токена, повинен бути тим же алгоритмом, що і сертифікат",
|
||||
"UI Customization": "Налаштування інтерфейсу",
|
||||
"Upstream host": "Upstream host",
|
||||
"Upstream host - Tooltip": "Upstream host - Tooltip",
|
||||
"Use Email as NameID": "Використовувати Email як NameID",
|
||||
"Use Email as NameID - Tooltip": "Використовувати Email як NameID - підказка",
|
||||
"Vertical": "Вертикальний",
|
||||
@@ -186,7 +198,9 @@
|
||||
"Expire in years - Tooltip": "Термін дії сертифіката, років",
|
||||
"New Cert": "Новий сертифікат",
|
||||
"Private key": "Приватний ключ",
|
||||
"Private key - Tooltip": "Закритий ключ, що відповідає сертифікату відкритого ключа"
|
||||
"Private key - Tooltip": "Закритий ключ, що відповідає сертифікату відкритого ключа",
|
||||
"Scope - Tooltip": "Сценарії використання сертифіката",
|
||||
"Type - Tooltip": "Тип сертифіката"
|
||||
},
|
||||
"code": {
|
||||
"Code you received": "Код, який ви отримали",
|
||||
@@ -275,7 +289,6 @@
|
||||
"Applications that require authentication": "Програми, які потребують автентифікації",
|
||||
"Apps": "програми",
|
||||
"Authorization": "Авторизація",
|
||||
"Auto": "Auto",
|
||||
"Avatar": "Аватар",
|
||||
"Avatar - Tooltip": "Публічний аватар користувача",
|
||||
"Back": "Назад",
|
||||
@@ -757,6 +770,7 @@
|
||||
"Account menu - Tooltip": "Account menu - Tooltip",
|
||||
"Admin navbar items": "Admin navbar items",
|
||||
"Admin navbar items - Tooltip": "Admin navbar items - Tooltip",
|
||||
"All": "All",
|
||||
"Balance credit": "Balance credit",
|
||||
"Balance credit - Tooltip": "Balance credit - Tooltip",
|
||||
"Balance currency": "Balance currency",
|
||||
@@ -921,6 +935,7 @@
|
||||
"Invalid product": "Invalid product",
|
||||
"Is recharge": "Чи є поповненням",
|
||||
"Is recharge - Tooltip": "Чи є поточний продукт для поповнення балансу",
|
||||
"Name": "Name",
|
||||
"New Product": "Новий продукт",
|
||||
"No recharge options available": "No recharge options available",
|
||||
"Order created successfully": "Order created successfully",
|
||||
@@ -933,6 +948,7 @@
|
||||
"Please add at least one recharge option when custom amount is disabled": "Please add at least one recharge option when custom amount is disabled",
|
||||
"Please select a currency": "Please select a currency",
|
||||
"Please select at least one payment provider": "Please select at least one payment provider",
|
||||
"Price": "Price",
|
||||
"Processing payment...": "Processing payment...",
|
||||
"Product list cannot be empty": "Product list cannot be empty",
|
||||
"Product not found or invalid": "Product not found or invalid",
|
||||
@@ -977,6 +993,7 @@
|
||||
"Auth Key - Tooltip": "Ключ автентифікації для сервісу",
|
||||
"Auth URL": "URL авторизації",
|
||||
"Auth URL - Tooltip": "URL для автентифікації",
|
||||
"Auto": "Auto",
|
||||
"Base URL": "Базовий URL",
|
||||
"Base URL - Tooltip": "Базовий URL сервісу",
|
||||
"Bucket": "Відро",
|
||||
@@ -985,6 +1002,8 @@
|
||||
"Can signin": "Можна ввійти",
|
||||
"Can signup": "Можна записатися",
|
||||
"Can unlink": "Можна від’єднати",
|
||||
"Category": "Категорія",
|
||||
"Category - Tooltip": "Ідентифікатор для категоризації та групування елементів або контенту, що полегшує фільтрацію та управління",
|
||||
"Channel No.": "Номер каналу",
|
||||
"Channel No. - Tooltip": "Унікальний номер, що ідентифікує канал зв'язку або передачі даних, використовується для розрізнення різних шляхів передачі",
|
||||
"Chat ID": "Ідентифікатор чату",
|
||||
@@ -1001,6 +1020,7 @@
|
||||
"Content - Tooltip": "Вміст – підказка",
|
||||
"DB test": "Тест БД",
|
||||
"DB test - Tooltip": "Тест бази даних - підказка",
|
||||
"Disable": "Disable",
|
||||
"Domain": "Домен",
|
||||
"Domain - Tooltip": "Спеціальний домен для зберігання об'єктів",
|
||||
"Edit Provider": "Редагувати постачальника",
|
||||
@@ -1010,6 +1030,7 @@
|
||||
"Email regex - Tooltip": "Email регулярний вираз - підказка",
|
||||
"Email title": "Назва електронної пошти",
|
||||
"Email title - Tooltip": "Заголовок електронного листа",
|
||||
"Enable": "Enable",
|
||||
"Enable PKCE": "Увімкнути PKCE",
|
||||
"Enable PKCE - Tooltip": "Увімкнути PKCE - підказка",
|
||||
"Enable proxy": "Увімкнути проксі",
|
||||
@@ -1284,6 +1305,8 @@
|
||||
"SSH password": "пароль SSH",
|
||||
"SSH port": "порт SSH",
|
||||
"SSH user": "Користувач SSH",
|
||||
"SSL mode": "Режим SSL",
|
||||
"SSL mode - Tooltip": "Режим SSL – підказка",
|
||||
"Service account key": "Service account key",
|
||||
"Sync interval": "Інтервал синхронізації",
|
||||
"Sync interval - Tooltip": "Одиниця в секундах",
|
||||
|
||||
@@ -113,12 +113,19 @@
|
||||
"Order - Tooltip": "Giá trị càng nhỏ, xếp hạng càng cao trong trang Ứng dụng",
|
||||
"Org choice mode": "Chế độ chọn tổ chức",
|
||||
"Org choice mode - Tooltip": "Phương thức chọn tổ chức để đăng nhập - Gợi ý",
|
||||
"Other domains": "Other domains",
|
||||
"Other domains - Tooltip": "Other domains - Tooltip",
|
||||
"Please enable \"Signin session\" first before enabling \"Auto signin\"": "Vui lòng kích hoạt \"Phiên đăng nhập\" trước khi kích hoạt \"Đăng nhập tự động\"",
|
||||
"Please input additional domains": "Please input additional domains",
|
||||
"Please input your application!": "Vui lòng nhập ứng dụng của bạn!",
|
||||
"Please input your organization!": "Vui lòng nhập tổ chức của bạn!",
|
||||
"Please select a HTML file": "Vui lòng chọn tệp HTML",
|
||||
"Pop up": "Bật lên",
|
||||
"Providers": "Nhà cung cấp",
|
||||
"Proxy SSL mode": "Proxy SSL mode",
|
||||
"Proxy SSL mode - Tooltip": "Proxy SSL mode - Tooltip",
|
||||
"Proxy domain": "Proxy domain",
|
||||
"Proxy domain - Tooltip": "Proxy domain - Tooltip",
|
||||
"Random": "Ngẫu nhiên",
|
||||
"Real name": "Tên thật",
|
||||
"Redirect URL": "Chuyển hướng URL",
|
||||
@@ -128,6 +135,7 @@
|
||||
"Refresh token expire": "Làm mới mã thông báo hết hạn",
|
||||
"Refresh token expire - Tooltip": "Thời gian hết hạn của mã thông báo làm mới",
|
||||
"Reset to Empty": "Đặt lại thành trống",
|
||||
"Reverse Proxy": "Reverse Proxy",
|
||||
"Right": "Đúng",
|
||||
"Rule": "Quy tắc",
|
||||
"SAML hash algorithm": "Thuật toán hash SAML",
|
||||
@@ -135,6 +143,8 @@
|
||||
"SAML metadata": "SAML metadata: Siêu dữ liệu SAML",
|
||||
"SAML metadata - Tooltip": "Metadata của giao thức SAML - Gợi ý",
|
||||
"SAML reply URL": "URL phản hồi SAML",
|
||||
"SSL cert": "SSL cert",
|
||||
"SSL cert - Tooltip": "SSL cert - Tooltip",
|
||||
"Security": "Bảo mật",
|
||||
"Select": "Chọn",
|
||||
"Side panel HTML": "Bảng điều khiển HTML bên lề",
|
||||
@@ -165,6 +175,8 @@
|
||||
"Token signing method": "Phương thức ký token",
|
||||
"Token signing method - Tooltip": "Phương thức ký token JWT, cần cùng thuật toán với chứng chỉ",
|
||||
"UI Customization": "Tùy chỉnh giao diện",
|
||||
"Upstream host": "Upstream host",
|
||||
"Upstream host - Tooltip": "Upstream host - Tooltip",
|
||||
"Use Email as NameID": "Sử dụng Email làm NameID",
|
||||
"Use Email as NameID - Tooltip": "Gợi ý sử dụng Email làm NameID",
|
||||
"Vertical": "Dọc",
|
||||
@@ -186,7 +198,9 @@
|
||||
"Expire in years - Tooltip": "Thời hạn hiệu lực của chứng chỉ, tính bằng năm",
|
||||
"New Cert": "Chứng chỉ mới",
|
||||
"Private key": "Khóa bí mật",
|
||||
"Private key - Tooltip": "Khóa riêng tương ứng với chứng thư khóa công khai"
|
||||
"Private key - Tooltip": "Khóa riêng tương ứng với chứng thư khóa công khai",
|
||||
"Scope - Tooltip": "Các kịch bản sử dụng của giấy chứng nhận",
|
||||
"Type - Tooltip": "Loại chứng chỉ"
|
||||
},
|
||||
"code": {
|
||||
"Code you received": "Mã bạn nhận được",
|
||||
@@ -275,7 +289,6 @@
|
||||
"Applications that require authentication": "Các ứng dụng yêu cầu xác thực",
|
||||
"Apps": "Ứng dụng",
|
||||
"Authorization": "Ủy quyền",
|
||||
"Auto": "Auto",
|
||||
"Avatar": "Ảnh đại diện",
|
||||
"Avatar - Tooltip": "Ảnh đại diện công khai cho người dùng",
|
||||
"Back": "Quay lại",
|
||||
@@ -757,6 +770,7 @@
|
||||
"Account menu - Tooltip": "Menu tài khoản",
|
||||
"Admin navbar items": "Mục navbar quản trị",
|
||||
"Admin navbar items - Tooltip": "Mục navbar quản trị",
|
||||
"All": "All",
|
||||
"Balance credit": "Số dư tín dụng",
|
||||
"Balance credit - Tooltip": "Số dư tín dụng",
|
||||
"Balance currency": "Đơn vị tiền tệ",
|
||||
@@ -921,6 +935,7 @@
|
||||
"Invalid product": "Invalid product",
|
||||
"Is recharge": "Là nạp tiền",
|
||||
"Is recharge - Tooltip": "Sản phẩm hiện tại có phải để nạp số dư",
|
||||
"Name": "Name",
|
||||
"New Product": "Sản phẩm mới",
|
||||
"No recharge options available": "No recharge options available",
|
||||
"Order created successfully": "Tạo đơn hàng thành công",
|
||||
@@ -933,6 +948,7 @@
|
||||
"Please add at least one recharge option when custom amount is disabled": "Vui lòng thêm ít nhất một tùy chọn nạp tiền khi số tiền tùy chỉnh bị tắt",
|
||||
"Please select a currency": "Vui lòng chọn một loại tiền tệ",
|
||||
"Please select at least one payment provider": "Vui lòng chọn ít nhất một nhà cung cấp thanh toán",
|
||||
"Price": "Price",
|
||||
"Processing payment...": "Đang xử lý thanh toán...",
|
||||
"Product list cannot be empty": "Danh sách sản phẩm không thể trống",
|
||||
"Product not found or invalid": "Product not found or invalid",
|
||||
@@ -977,6 +993,7 @@
|
||||
"Auth Key - Tooltip": "Gợi ý khóa xác thực",
|
||||
"Auth URL": "URL xác thực",
|
||||
"Auth URL - Tooltip": "URL chứng thực",
|
||||
"Auto": "Auto",
|
||||
"Base URL": "URL cơ sở",
|
||||
"Base URL - Tooltip": "Gợi ý URL cơ sở",
|
||||
"Bucket": "Thùng đựng nước",
|
||||
@@ -985,6 +1002,8 @@
|
||||
"Can signin": "Đăng nhập được không?",
|
||||
"Can signup": "Đăng ký có thể được thực hiện",
|
||||
"Can unlink": "Không liên kết được",
|
||||
"Category": "Thể loại",
|
||||
"Category - Tooltip": "Chọn một danh mục",
|
||||
"Channel No.": "Kênh số.",
|
||||
"Channel No. - Tooltip": "Kênh Số.",
|
||||
"Chat ID": "ID trò chuyện",
|
||||
@@ -1001,6 +1020,7 @@
|
||||
"Content - Tooltip": "Gợi ý nội dung",
|
||||
"DB test": "DB test",
|
||||
"DB test - Tooltip": "Kiểm tra DB - Gợi ý",
|
||||
"Disable": "Disable",
|
||||
"Domain": "Miền",
|
||||
"Domain - Tooltip": "Tên miền tùy chỉnh cho lưu trữ đối tượng",
|
||||
"Edit Provider": "Chỉnh sửa nhà cung cấp",
|
||||
@@ -1010,6 +1030,7 @@
|
||||
"Email regex - Tooltip": "Gợi ý biểu thức chính quy Email",
|
||||
"Email title": "Tiêu đề email",
|
||||
"Email title - Tooltip": "Tiêu đề của email",
|
||||
"Enable": "Enable",
|
||||
"Enable PKCE": "Enable PKCE",
|
||||
"Enable PKCE - Tooltip": "Kích hoạt PKCE - Gợi ý",
|
||||
"Enable proxy": "Enable proxy",
|
||||
@@ -1284,6 +1305,8 @@
|
||||
"SSH password": "Mật khẩu SSH",
|
||||
"SSH port": "Cổng SSH",
|
||||
"SSH user": "Người dùng SSH",
|
||||
"SSL mode": "Chế độ SSL",
|
||||
"SSL mode - Tooltip": "Chế độ kết nối SSL với cơ sở dữ liệu",
|
||||
"Service account key": "Khóa tài khoản dịch vụ",
|
||||
"Sync interval": "Khoảng thời gian đồng bộ",
|
||||
"Sync interval - Tooltip": "Khoảng thời gian giữa các lần đồng bộ (tính bằng giây)",
|
||||
|
||||
@@ -113,12 +113,19 @@
|
||||
"Order - Tooltip": "数值越小,在应用列表页面中排序越靠前",
|
||||
"Org choice mode": "组织选择模式",
|
||||
"Org choice mode - Tooltip": "采用什么方式选择要登录的组织",
|
||||
"Other domains": "其他域名",
|
||||
"Other domains - Tooltip": "也应路由到此应用的其他域名",
|
||||
"Please enable \"Signin session\" first before enabling \"Auto signin\"": "开启 \"保持登录会话\" 后才能开启 \"自动登录\"",
|
||||
"Please input additional domains": "请输入其他域名",
|
||||
"Please input your application!": "请输入你的应用",
|
||||
"Please input your organization!": "请输入你的组织",
|
||||
"Please select a HTML file": "请选择一个HTML文件",
|
||||
"Pop up": "弹框",
|
||||
"Providers": "提供商",
|
||||
"Proxy SSL mode": "代理SSL模式",
|
||||
"Proxy SSL mode - Tooltip": "反向代理的SSL/TLS模式",
|
||||
"Proxy domain": "代理域名",
|
||||
"Proxy domain - Tooltip": "此应用的公开访问域名(例如:blog.example.com)",
|
||||
"Random": "随机",
|
||||
"Real name": "真实姓名",
|
||||
"Redirect URL": "重定向 URL",
|
||||
@@ -128,6 +135,7 @@
|
||||
"Refresh token expire": "Refresh Token过期",
|
||||
"Refresh token expire - Tooltip": "Refresh Token过期时间",
|
||||
"Reset to Empty": "重置为空",
|
||||
"Reverse Proxy": "反向代理",
|
||||
"Right": "居右",
|
||||
"Rule": "规则",
|
||||
"SAML hash algorithm": "SAML哈希算法",
|
||||
@@ -135,6 +143,8 @@
|
||||
"SAML metadata": "SAML元数据",
|
||||
"SAML metadata - Tooltip": "SAML协议的元数据(Metadata)信息",
|
||||
"SAML reply URL": "SAML回复 URL",
|
||||
"SSL cert": "SSL证书",
|
||||
"SSL cert - Tooltip": "用于TLS终止的证书",
|
||||
"Security": "安全设置",
|
||||
"Select": "选择",
|
||||
"Side panel HTML": "侧面板HTML",
|
||||
@@ -165,6 +175,8 @@
|
||||
"Token signing method": "Token签名算法",
|
||||
"Token signing method - Tooltip": "JWT token的签名算法,需要与证书算法相匹配",
|
||||
"UI Customization": "界面定制",
|
||||
"Upstream host": "上游主机",
|
||||
"Upstream host - Tooltip": "转发请求的上游后端地址(例如:localhost:8080 或 192.168.1.100)",
|
||||
"Use Email as NameID": "使用邮箱作为NameID",
|
||||
"Use Email as NameID - Tooltip": "使用邮箱作为NameID",
|
||||
"Vertical": "垂直",
|
||||
@@ -186,7 +198,9 @@
|
||||
"Expire in years - Tooltip": "公钥证书的有效期,以年为单位",
|
||||
"New Cert": "添加证书",
|
||||
"Private key": "私钥",
|
||||
"Private key - Tooltip": "公钥证书对应的私钥"
|
||||
"Private key - Tooltip": "公钥证书对应的私钥",
|
||||
"Scope - Tooltip": "公钥证书的使用场景",
|
||||
"Type - Tooltip": "公钥证书的类型"
|
||||
},
|
||||
"code": {
|
||||
"Code you received": "验证码",
|
||||
@@ -268,14 +282,13 @@
|
||||
"Admin": "管理工具",
|
||||
"Affiliation URL": "工作单位URL",
|
||||
"Affiliation URL - Tooltip": "工作单位的官网URL",
|
||||
"All": "全部",
|
||||
"All": "全部允许",
|
||||
"Application": "应用",
|
||||
"Application - Tooltip": "可以访问的应用",
|
||||
"Applications": "应用",
|
||||
"Applications that require authentication": "需要认证和鉴权的应用",
|
||||
"Apps": "应用列表",
|
||||
"Authorization": "Casbin权限管理",
|
||||
"Auto": "Auto",
|
||||
"Avatar": "头像",
|
||||
"Avatar - Tooltip": "公开展示的用户头像",
|
||||
"Back": "返回",
|
||||
@@ -757,6 +770,7 @@
|
||||
"Account menu - Tooltip": "账户相关的菜单项",
|
||||
"Admin navbar items": "管理员导航栏项",
|
||||
"Admin navbar items - Tooltip": "管理员导航栏中的项目",
|
||||
"All": "All",
|
||||
"Balance credit": "余额积分",
|
||||
"Balance credit - Tooltip": "用户的余额积分信息",
|
||||
"Balance currency": "余额币种",
|
||||
@@ -921,6 +935,7 @@
|
||||
"Invalid product": "Invalid product",
|
||||
"Is recharge": "充值",
|
||||
"Is recharge - Tooltip": "当前商品是否为充值商品",
|
||||
"Name": "Name",
|
||||
"New Product": "添加商品",
|
||||
"No recharge options available": "No recharge options available",
|
||||
"Order created successfully": "订单创建成功",
|
||||
@@ -933,6 +948,7 @@
|
||||
"Please add at least one recharge option when custom amount is disabled": "当禁用自定义金额时,请至少添加一个充值选项",
|
||||
"Please select a currency": "请选择一种货币",
|
||||
"Please select at least one payment provider": "请至少选择一个支付提供商",
|
||||
"Price": "Price",
|
||||
"Processing payment...": "正在处理支付...",
|
||||
"Product list cannot be empty": "商品列表不能为空",
|
||||
"Product not found or invalid": "Product not found or invalid",
|
||||
@@ -977,6 +993,7 @@
|
||||
"Auth Key - Tooltip": "服务的认证密钥",
|
||||
"Auth URL": "认证URL",
|
||||
"Auth URL - Tooltip": "用于认证的URL",
|
||||
"Auto": "Auto",
|
||||
"Base URL": "基本URL",
|
||||
"Base URL - Tooltip": "服务的基本URL",
|
||||
"Bucket": "存储桶",
|
||||
@@ -985,6 +1002,8 @@
|
||||
"Can signin": "可用于登录",
|
||||
"Can signup": "可用于注册",
|
||||
"Can unlink": "可解绑定",
|
||||
"Category": "分类",
|
||||
"Category - Tooltip": "用于对项目或内容进行归类分组的标识",
|
||||
"Channel No.": "Channel号码",
|
||||
"Channel No. - Tooltip": "标识通信或数据传输通道的唯一编号",
|
||||
"Chat ID": "聊天ID",
|
||||
@@ -1001,6 +1020,7 @@
|
||||
"Content - Tooltip": "消息、通知或文档中包含的具体信息或数据内容",
|
||||
"DB test": "数据库测试",
|
||||
"DB test - Tooltip": "测试数据库连接是否正常",
|
||||
"Disable": "Disable",
|
||||
"Domain": "域名",
|
||||
"Domain - Tooltip": "对象存储的自定义域名",
|
||||
"Edit Provider": "编辑提供商",
|
||||
@@ -1010,6 +1030,7 @@
|
||||
"Email regex - Tooltip": "只有符合此正则表达式的Email才能进行注册或登录",
|
||||
"Email title": "邮件标题",
|
||||
"Email title - Tooltip": "邮件标题",
|
||||
"Enable": "Enable",
|
||||
"Enable PKCE": "启用PKCE",
|
||||
"Enable PKCE - Tooltip": "是否启用PKCE扩展协议",
|
||||
"Enable proxy": "启用代理",
|
||||
@@ -1284,6 +1305,8 @@
|
||||
"SSH password": "SSH密码",
|
||||
"SSH port": "SSH端口",
|
||||
"SSH user": "SSH用户",
|
||||
"SSL mode": "SSL模式",
|
||||
"SSL mode - Tooltip": "连接数据库采用哪种SSL模式",
|
||||
"Service account key": "Service account key",
|
||||
"Sync interval": "同步间隔",
|
||||
"Sync interval - Tooltip": "单位为秒",
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
// Copyright 2026 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 {Col, Row} from "antd";
|
||||
import * as Setting from "../Setting";
|
||||
import i18next from "i18next";
|
||||
import {CaptchaPreview} from "../common/CaptchaPreview";
|
||||
|
||||
export function renderCaptchaProviderFields(provider, providerName) {
|
||||
return (
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("general:Preview"), i18next.t("general:Preview - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<CaptchaPreview
|
||||
owner={provider.owner}
|
||||
name={provider.name}
|
||||
provider={provider}
|
||||
providerName={providerName}
|
||||
captchaType={provider.type}
|
||||
subType={provider.subType}
|
||||
clientId={provider.clientId}
|
||||
clientSecret={provider.clientSecret}
|
||||
clientId2={provider.clientId2}
|
||||
clientSecret2={provider.clientSecret2}
|
||||
providerUrl={provider.providerUrl}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
);
|
||||
}
|
||||
@@ -1,255 +0,0 @@
|
||||
// Copyright 2026 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import React from "react";
|
||||
import {Button, Col, Input, InputNumber, Row, Select, Switch} from "antd";
|
||||
import {LinkOutlined} from "@ant-design/icons";
|
||||
import * as Setting from "../Setting";
|
||||
import i18next from "i18next";
|
||||
import * as ProviderEditTestEmail from "../common/TestEmailWidget";
|
||||
import Editor from "../common/Editor";
|
||||
import HttpHeaderTable from "../table/HttpHeaderTable";
|
||||
|
||||
const {Option} = Select;
|
||||
|
||||
export function renderEmailProviderFields(provider, updateProviderField, renderEmailMappingInput, account) {
|
||||
return (
|
||||
<React.Fragment>
|
||||
{
|
||||
["Custom HTTP Email", "SendGrid"].includes(provider.type) ? (
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={2}>
|
||||
{Setting.getLabel(i18next.t("provider:Endpoint"), i18next.t("provider:Region endpoint for Internet"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input prefix={<LinkOutlined />} value={provider.endpoint} onChange={e => {
|
||||
updateProviderField("endpoint", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>) : null
|
||||
}
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("provider:Host"), i18next.t("provider:Host - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input prefix={<LinkOutlined />} value={provider.host} onChange={e => {
|
||||
updateProviderField("host", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
{["Azure ACS", "SendGrid"].includes(provider.type) ? null : (
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("provider:Port"), i18next.t("provider:Port - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<InputNumber value={provider.port} onChange={value => {
|
||||
updateProviderField("port", value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
)}
|
||||
{["Azure ACS", "SendGrid"].includes(provider.type) ? null : (
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("provider:SSL mode"), i18next.t("provider:SSL mode - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Select virtual={false} style={{width: "200px"}} value={provider.sslMode || "Auto"} onChange={value => {
|
||||
updateProviderField("sslMode", value);
|
||||
}}>
|
||||
<Option value="Auto">{i18next.t("general:Auto")}</Option>
|
||||
<Option value="Enable">{i18next.t("general:Enable")}</Option>
|
||||
<Option value="Disable">{i18next.t("general:Disable")}</Option>
|
||||
</Select>
|
||||
</Col>
|
||||
</Row>
|
||||
)}
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("provider:Enable proxy"), i18next.t("provider:Enable proxy - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={1} >
|
||||
<Switch checked={provider.enableProxy} onChange={checked => {
|
||||
updateProviderField("enableProxy", checked);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
{
|
||||
provider.type === "Custom HTTP Email" ? (
|
||||
<React.Fragment>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("general:Method"), i18next.t("provider:Method - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Select virtual={false} style={{width: "100%"}} value={provider.method} onChange={value => {
|
||||
updateProviderField("method", value);
|
||||
}}>
|
||||
{
|
||||
[
|
||||
{id: "GET", name: "GET"},
|
||||
{id: "POST", name: "POST"},
|
||||
{id: "PUT", name: "PUT"},
|
||||
{id: "DELETE", name: "DELETE"},
|
||||
].map((method, index) => <Option key={index} value={method.id}>{method.name}</Option>)
|
||||
}
|
||||
</Select>
|
||||
</Col>
|
||||
</Row>
|
||||
{
|
||||
provider.method !== "GET" ? (<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("webhook:Content type"), i18next.t("webhook:Content type - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Select virtual={false} style={{width: "100%"}} value={provider.issuerUrl === "" ? "application/x-www-form-urlencoded" : provider.issuerUrl} onChange={value => {
|
||||
updateProviderField("issuerUrl", value);
|
||||
}}>
|
||||
{
|
||||
[
|
||||
{id: "application/json", name: "application/json"},
|
||||
{id: "application/x-www-form-urlencoded", name: "application/x-www-form-urlencoded"},
|
||||
].map((method, index) => <Option key={index} value={method.id}>{method.name}</Option>)
|
||||
}
|
||||
</Select>
|
||||
</Col>
|
||||
</Row>) : null
|
||||
}
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("provider:HTTP header"), i18next.t("provider:HTTP header - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<HttpHeaderTable httpHeaders={provider.httpHeaders} onUpdateTable={(value) => {updateProviderField("httpHeaders", value);}} />
|
||||
</Col>
|
||||
</Row>
|
||||
{provider.method !== "GET" ? <Row style={{marginTop: "20px"}}>
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("provider:HTTP body mapping"), i18next.t("provider:HTTP body mapping - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22}>
|
||||
{renderEmailMappingInput()}
|
||||
</Col>
|
||||
</Row> : null}
|
||||
</React.Fragment>
|
||||
) : null
|
||||
}
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("provider:Email title"), i18next.t("provider:Email title - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={provider.title} onChange={e => {
|
||||
updateProviderField("title", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("provider:Email content"), i18next.t("provider:Email content - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Button style={{marginLeft: "10px", marginBottom: "5px"}} onClick={() => updateProviderField("content", "You have requested a verification code at Casdoor. Here is your code: %s, please enter in 5 minutes. <reset-link>Or click %link to reset</reset-link>")} >
|
||||
{i18next.t("general:Reset to Default")} (Text)
|
||||
</Button>
|
||||
<Button style={{marginLeft: "10px", marginBottom: "5px"}} type="primary" onClick={() => updateProviderField("content", Setting.getDefaultHtmlEmailContent())} >
|
||||
{i18next.t("general:Reset to Default")} (HTML)
|
||||
</Button>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col span={Setting.isMobile() ? 22 : 11}>
|
||||
<div style={{height: "300px", margin: "10px"}}>
|
||||
<Editor
|
||||
value={provider.content}
|
||||
fillHeight
|
||||
dark
|
||||
lang="html"
|
||||
onChange={value => {
|
||||
updateProviderField("content", value);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</Col>
|
||||
<Col span={1} />
|
||||
<Col span={Setting.isMobile() ? 22 : 11}>
|
||||
<div style={{margin: "10px"}}>
|
||||
<div dangerouslySetInnerHTML={{__html: provider.content.replace("%s", "123456").replace("%{user.friendlyName}", Setting.getFriendlyUserName(account))}} />
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(`${i18next.t("provider:Email content")}-${i18next.t("general:Invitations")}`, i18next.t("provider:Email content - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Button style={{marginLeft: "10px", marginBottom: "5px"}} onClick={() => updateProviderField("metadata", "You have invited to join Casdoor. Here is your invitation code: %s, please enter in 5 minutes. Or click %link to signup")} >
|
||||
{i18next.t("general:Reset to Default")} (Text)
|
||||
</Button>
|
||||
<Button style={{marginLeft: "10px", marginBottom: "5px"}} type="primary" onClick={() => updateProviderField("metadata", Setting.getDefaultInvitationHtmlEmailContent())} >
|
||||
{i18next.t("general:Reset to Default")} (HTML)
|
||||
</Button>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col span={Setting.isMobile() ? 22 : 11}>
|
||||
<div style={{height: "300px", margin: "10px"}}>
|
||||
<Editor
|
||||
value={provider.metadata}
|
||||
fillHeight
|
||||
dark
|
||||
lang="html"
|
||||
onChange={value => {
|
||||
updateProviderField("metadata", value);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</Col>
|
||||
<Col span={1} />
|
||||
<Col span={Setting.isMobile() ? 22 : 11}>
|
||||
<div style={{margin: "10px"}}>
|
||||
<div dangerouslySetInnerHTML={{__html: provider.metadata.replace("%code", "123456").replace("%s", "123456")}} />
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}}>
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("provider:Test Email"), i18next.t("provider:Test Email - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={4}>
|
||||
<Input value={provider.receiver} placeholder={i18next.t("user:Input your email")}
|
||||
onChange={e => {
|
||||
updateProviderField("receiver", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
{["Azure ACS", "SendGrid"].includes(provider.type) ? null : (
|
||||
<Button style={{marginLeft: "10px", marginBottom: "5px"}} onClick={() => ProviderEditTestEmail.connectSmtpServer(provider)} >
|
||||
{i18next.t("provider:Test SMTP Connection")}
|
||||
</Button>
|
||||
)}
|
||||
<Button style={{marginLeft: "10px", marginBottom: "5px"}} type="primary"
|
||||
disabled={!Setting.isValidEmail(provider.receiver)}
|
||||
onClick={() => ProviderEditTestEmail.sendTestEmail(provider, provider.receiver)} >
|
||||
{i18next.t("provider:Send Testing Email")}
|
||||
</Button>
|
||||
</Row>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
// Copyright 2026 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 {Col, Input, Row} from "antd";
|
||||
import {LinkOutlined} from "@ant-design/icons";
|
||||
import * as Setting from "../Setting";
|
||||
import i18next from "i18next";
|
||||
|
||||
export function renderFaceIdProviderFields(provider, updateProviderField) {
|
||||
return (
|
||||
<>
|
||||
{["Alibaba Cloud Facebody"].includes(provider.type) ? null : (
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={2}>
|
||||
{Setting.getLabel(i18next.t("provider:Endpoint (Intranet)"), i18next.t("provider:Region endpoint for Intranet"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input prefix={<LinkOutlined />} value={provider.intranetEndpoint} onChange={e => {
|
||||
updateProviderField("intranetEndpoint", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
)}
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={2}>
|
||||
{Setting.getLabel(i18next.t("provider:Endpoint"), i18next.t("provider:Region endpoint for Internet"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input prefix={<LinkOutlined />} value={provider.endpoint} onChange={e => {
|
||||
updateProviderField("endpoint", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
// Copyright 2026 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 {Col, Input, Row} from "antd";
|
||||
import {LinkOutlined} from "@ant-design/icons";
|
||||
import * as Setting from "../Setting";
|
||||
import i18next from "i18next";
|
||||
|
||||
export function renderIDVerificationProviderFields(provider, updateProviderField) {
|
||||
return (
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={2}>
|
||||
{Setting.getLabel(i18next.t("provider:Endpoint"), i18next.t("provider:Region endpoint for Internet"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input prefix={<LinkOutlined />} value={provider.endpoint} onChange={e => {
|
||||
updateProviderField("endpoint", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
);
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
// Copyright 2026 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 {Col, Input, InputNumber, Row} from "antd";
|
||||
import {LinkOutlined} from "@ant-design/icons";
|
||||
import * as Setting from "../Setting";
|
||||
import i18next from "i18next";
|
||||
|
||||
export function renderMfaProviderFields(provider, updateProviderField) {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("provider:Host"), i18next.t("provider:Host - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input prefix={<LinkOutlined />} value={provider.host} placeholder="10.10.10.10" onChange={e => {
|
||||
updateProviderField("host", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("provider:Port"), i18next.t("provider:Port - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<InputNumber value={provider.port} onChange={value => {
|
||||
updateProviderField("port", value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("provider:Client secret"), i18next.t("provider:RADIUS Shared Secret - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={provider.clientSecret} placeholder="Shared secret" onChange={e => {
|
||||
updateProviderField("clientSecret", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
@@ -1,103 +0,0 @@
|
||||
// Copyright 2026 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import React from "react";
|
||||
import {Button, Col, Input, Row, Select} from "antd";
|
||||
import * as Setting from "../Setting";
|
||||
import i18next from "i18next";
|
||||
import * as ProviderNotification from "../common/TestNotificationWidget";
|
||||
|
||||
const {Option} = Select;
|
||||
const {TextArea} = Input;
|
||||
|
||||
export function renderNotificationProviderFields(provider, updateProviderField, getReceiverRow) {
|
||||
return (
|
||||
<React.Fragment>
|
||||
{["CUCloud"].includes(provider.type) ? (
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={2}>
|
||||
{["Casdoor"].includes(provider.type) ?
|
||||
Setting.getLabel(i18next.t("general:Application"), i18next.t("general:Application - Tooltip")) :
|
||||
Setting.getLabel(i18next.t("provider:Region ID"), i18next.t("provider:Region ID - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={provider.regionId} onChange={e => {
|
||||
updateProviderField("regionId", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
) : null}
|
||||
{["Custom HTTP"].includes(provider.type) ? (
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("general:Method"), i18next.t("provider:Method - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Select virtual={false} style={{width: "100%"}} value={provider.method} onChange={value => {
|
||||
updateProviderField("method", value);
|
||||
}}>
|
||||
{
|
||||
[
|
||||
{id: "GET", name: "GET"},
|
||||
{id: "POST", name: "POST"},
|
||||
].map((method, index) => <Option key={index} value={method.id}>{method.name}</Option>)
|
||||
}
|
||||
</Select>
|
||||
</Col>
|
||||
</Row>
|
||||
) : null}
|
||||
{["Custom HTTP", "CUCloud"].includes(provider.type) ? (
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("provider:Parameter"), i18next.t("provider:Parameter - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={provider.title} onChange={e => {
|
||||
updateProviderField("title", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
) : null}
|
||||
{["Google Chat", "CUCloud"].includes(provider.type) ? (
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("provider:Metadata"), i18next.t("provider:Metadata - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22}>
|
||||
<TextArea rows={4} value={provider.metadata} onChange={e => {
|
||||
updateProviderField("metadata", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
) : null}
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("provider:Content"), i18next.t("provider:Content - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<TextArea autoSize={{minRows: 3, maxRows: 100}} value={provider.content} onChange={e => {
|
||||
updateProviderField("content", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
{getReceiverRow(provider)}
|
||||
<Button style={{marginLeft: "10px", marginBottom: "5px"}} type="primary"
|
||||
onClick={() => ProviderNotification.sendTestNotification(provider)} >
|
||||
{i18next.t("provider:Send Testing Notification")}
|
||||
</Button>
|
||||
</Row>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
@@ -1,218 +0,0 @@
|
||||
// Copyright 2026 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 {Col, Input, Radio, Row, Switch} from "antd";
|
||||
import {LinkOutlined} from "@ant-design/icons";
|
||||
import * as Setting from "../Setting";
|
||||
import i18next from "i18next";
|
||||
|
||||
const {TextArea} = Input;
|
||||
|
||||
export function renderOAuthProviderFields(provider, updateProviderField, renderUserMappingInput) {
|
||||
const getDomainLabel = provider => {
|
||||
switch (provider.category) {
|
||||
case "OAuth":
|
||||
if (provider.type === "AzureAD" || provider.type === "AzureADB2C") {
|
||||
return Setting.getLabel(i18next.t("provider:Tenant ID"), i18next.t("provider:Tenant ID - Tooltip"));
|
||||
} else {
|
||||
return Setting.getLabel(i18next.t("provider:Domain"), i18next.t("provider:Domain - Tooltip"));
|
||||
}
|
||||
default:
|
||||
return Setting.getLabel(i18next.t("provider:Domain"), i18next.t("provider:Domain - Tooltip"));
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("provider:Email regex"), i18next.t("provider:Email regex - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22}>
|
||||
<TextArea rows={4} value={provider.emailRegex} onChange={e => {
|
||||
updateProviderField("emailRegex", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
{
|
||||
provider.type !== "WeChat" ? null : (
|
||||
<React.Fragment>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("provider:Use WeChat Media Platform in PC"), i18next.t("provider:Use WeChat Media Platform in PC - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={1} >
|
||||
<Switch disabled={!provider.clientId} checked={provider.disableSsl} onChange={checked => {
|
||||
updateProviderField("disableSsl", checked);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("token:Access token"), i18next.t("token:Access token - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={provider.content} disabled={!provider.disableSsl || !provider.clientId2} onChange={e => {
|
||||
updateProviderField("content", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("provider:Follow-up action"), i18next.t("provider:Follow-up action - Tooltip"))} :
|
||||
</Col>
|
||||
<Col>
|
||||
<Radio.Group value={provider.signName}
|
||||
disabled={!provider.disableSsl || !provider.clientId || !provider.clientId2}
|
||||
buttonStyle="solid"
|
||||
onChange={e => {
|
||||
updateProviderField("signName", e.target.value);
|
||||
}}>
|
||||
<Radio.Button value="open">{i18next.t("provider:Use WeChat Open Platform to login")}</Radio.Button>
|
||||
<Radio.Button value="media">{i18next.t("provider:Use WeChat Media Platform to login")}</Radio.Button>
|
||||
</Radio.Group>
|
||||
</Col>
|
||||
</Row>
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
{
|
||||
provider.type !== "ADFS" && provider.type !== "AzureAD"
|
||||
&& provider.type !== "AzureADB2C" && (provider.type !== "Casdoor" && provider.category !== "Storage")
|
||||
&& provider.type !== "Okta" && provider.type !== "Nextcloud" ? null : (
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={2}>
|
||||
{getDomainLabel(provider)} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input prefix={<LinkOutlined />} value={provider.domain} onChange={e => {
|
||||
updateProviderField("domain", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
)
|
||||
}
|
||||
{
|
||||
provider.type !== "Google" && provider.type !== "Lark" ? null : (
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{provider.type === "Google" ?
|
||||
Setting.getLabel(i18next.t("provider:Get phone number"), i18next.t("provider:Get phone number - Tooltip"))
|
||||
: Setting.getLabel(i18next.t("provider:Use global endpoint"), i18next.t("provider:Use global endpoint - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={1} >
|
||||
<Switch disabled={!provider.clientId} checked={provider.disableSsl} onChange={checked => {
|
||||
updateProviderField("disableSsl", checked);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
)
|
||||
}
|
||||
{
|
||||
provider.type.startsWith("Custom") ? (
|
||||
<React.Fragment>
|
||||
<Col>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("provider:Auth URL"), i18next.t("provider:Auth URL - Tooltip"))}
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={provider.customAuthUrl} onChange={e => {
|
||||
updateProviderField("customAuthUrl", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("provider:Token URL"), i18next.t("provider:Token URL - Tooltip"))}
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={provider.customTokenUrl} onChange={e => {
|
||||
updateProviderField("customTokenUrl", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("provider:Scope"), i18next.t("provider:Scope - Tooltip"))}
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={provider.scopes} onChange={e => {
|
||||
updateProviderField("scopes", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("provider:UserInfo URL"), i18next.t("provider:UserInfo URL - Tooltip"))}
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={provider.customUserInfoUrl} onChange={e => {
|
||||
updateProviderField("customUserInfoUrl", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("provider:Enable PKCE"), i18next.t("provider:Enable PKCE - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Switch checked={provider.enablePkce} onChange={checked => {
|
||||
updateProviderField("enablePkce", checked);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
</Col>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("provider:User mapping"), i18next.t("provider:User mapping - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
{renderUserMappingInput()}
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("general:Favicon"), i18next.t("general:Favicon - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 1}>
|
||||
{Setting.getLabel(i18next.t("general:URL"), i18next.t("general:URL - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={23} >
|
||||
<Input prefix={<LinkOutlined />} value={provider.customLogo} onChange={e => {
|
||||
updateProviderField("customLogo", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 1}>
|
||||
{i18next.t("general:Preview")}:
|
||||
</Col>
|
||||
<Col span={23} >
|
||||
<a target="_blank" rel="noreferrer" href={provider.customLogo}>
|
||||
<img src={provider.customLogo} alt={provider.customLogo} height={90} style={{marginBottom: "20px"}} />
|
||||
</a>
|
||||
</Col>
|
||||
</Row>
|
||||
</Col>
|
||||
</Row>
|
||||
</React.Fragment>
|
||||
) : null
|
||||
}
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
// Copyright 2026 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 {Col, Input, Row, Select} from "antd";
|
||||
import * as Setting from "../Setting";
|
||||
import i18next from "i18next";
|
||||
import {LinkOutlined} from "@ant-design/icons";
|
||||
|
||||
const {Option} = Select;
|
||||
|
||||
export function renderPaymentProviderFields(provider, updateProviderField, certs) {
|
||||
return (
|
||||
<React.Fragment>
|
||||
{
|
||||
(provider.type === "Alipay" || provider.type === "WeChat Pay" || provider.type === "Casdoor") ? (
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("general:Cert"), i18next.t("general:Cert - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Select virtual={false} style={{width: "100%"}} value={provider.cert} onChange={(value => {updateProviderField("cert", value);})}>
|
||||
{
|
||||
certs.map((cert, index) => <Option key={index} value={cert.name}>{cert.name}</Option>)
|
||||
}
|
||||
</Select>
|
||||
</Col>
|
||||
</Row>
|
||||
) : null
|
||||
}
|
||||
{
|
||||
(provider.type === "Alipay") ? (
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("general:Root cert"), i18next.t("general:Root cert - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Select virtual={false} style={{width: "100%"}} value={provider.metadata} onChange={(value => {updateProviderField("metadata", value);})}>
|
||||
{
|
||||
certs.map((cert, index) => <Option key={index} value={cert.name}>{cert.name}</Option>)
|
||||
}
|
||||
</Select>
|
||||
</Col>
|
||||
</Row>
|
||||
) : null
|
||||
}
|
||||
{(provider.type === "GC" || provider.type === "FastSpring") ? (
|
||||
<Row style={{marginTop: "20px"}}>
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("provider:Host"), i18next.t("provider:Host - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22}>
|
||||
<Input prefix={<LinkOutlined />} value={provider.host} onChange={e => {
|
||||
updateProviderField("host", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
) : null}
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
@@ -1,133 +0,0 @@
|
||||
// Copyright 2026 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import React from "react";
|
||||
import {Button, Col, Input, Row, Switch} from "antd";
|
||||
import * as Setting from "../Setting";
|
||||
import i18next from "i18next";
|
||||
import {authConfig} from "../auth/Auth";
|
||||
import copy from "copy-to-clipboard";
|
||||
|
||||
const {TextArea} = Input;
|
||||
|
||||
export function renderSamlProviderFields(provider, updateProviderField, metadataConfig) {
|
||||
const {requestUrl, setRequestUrl, metadataLoading, fetchSamlMetadata, parseSamlMetadata} = metadataConfig;
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("provider:Sign request"), i18next.t("provider:Sign request - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Switch checked={provider.enableSignAuthnRequest} onChange={checked => {
|
||||
updateProviderField("enableSignAuthnRequest", checked);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("provider:Metadata url"), i18next.t("provider:Metadata url - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={6} >
|
||||
<Input value={requestUrl} onChange={e => {
|
||||
setRequestUrl(e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
<Col span={16} >
|
||||
<Button style={{marginLeft: "10px"}} type="primary" loading={metadataLoading} onClick={() => {fetchSamlMetadata();}}>{i18next.t("general:Request")}</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("provider:Metadata"), i18next.t("provider:Metadata - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22}>
|
||||
<TextArea rows={4} value={provider.metadata} onChange={e => {
|
||||
updateProviderField("metadata", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}}>
|
||||
<Col style={{marginTop: "5px"}} span={2} />
|
||||
<Col span={2}>
|
||||
<Button type="primary" onClick={() => {parseSamlMetadata();}}>
|
||||
{i18next.t("provider:Parse")}
|
||||
</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("provider:Endpoint"), i18next.t("provider:SAML 2.0 Endpoint (HTTP)"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={provider.endpoint} onChange={e => {
|
||||
updateProviderField("endpoint", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("provider:IdP"), i18next.t("provider:IdP certificate"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={provider.idP} onChange={e => {
|
||||
updateProviderField("idP", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("provider:Issuer URL"), i18next.t("provider:Issuer URL - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={provider.issuerUrl} onChange={e => {
|
||||
updateProviderField("issuerUrl", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("provider:SP ACS URL"), i18next.t("provider:SP ACS URL - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={21} >
|
||||
<Input value={`${authConfig.serverUrl}/api/acs`} readOnly="readonly" />
|
||||
</Col>
|
||||
<Col span={1}>
|
||||
<Button type="primary" onClick={() => {
|
||||
copy(`${authConfig.serverUrl}/api/acs`);
|
||||
Setting.showMessage("success", i18next.t("general:Copied to clipboard successfully"));
|
||||
}}>
|
||||
{i18next.t("general:Copy")}
|
||||
</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("provider:SP Entity ID"), i18next.t("provider:SP Entity ID - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={21} >
|
||||
<Input value={`${authConfig.serverUrl}/api/acs`} readOnly="readonly" />
|
||||
</Col>
|
||||
<Col span={1}>
|
||||
<Button type="primary" onClick={() => {
|
||||
copy(`${authConfig.serverUrl}/api/acs`);
|
||||
Setting.showMessage("success", i18next.t("general:Copied to clipboard successfully"));
|
||||
}}>
|
||||
{i18next.t("general:Copy")}
|
||||
</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
@@ -1,182 +0,0 @@
|
||||
// Copyright 2026 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import React from "react";
|
||||
import {Button, Col, Input, Row, Select, Switch} from "antd";
|
||||
import * as Setting from "../Setting";
|
||||
import i18next from "i18next";
|
||||
import * as ProviderEditTestSms from "../common/TestSmsWidget";
|
||||
import {CountryCodeSelect} from "../common/select/CountryCodeSelect";
|
||||
import HttpHeaderTable from "../table/HttpHeaderTable";
|
||||
import {LinkOutlined} from "@ant-design/icons";
|
||||
|
||||
const {Option} = Select;
|
||||
|
||||
const SMS_PROVIDERS_WITHOUT_SIGN_NAME = ["Custom HTTP SMS", "Twilio SMS", "Amazon SNS", "Msg91 SMS", "Infobip SMS"];
|
||||
const SMS_PROVIDERS_WITHOUT_TEMPLATE_CODE = ["Infobip SMS", "Custom HTTP SMS"];
|
||||
|
||||
export function renderSmsProviderFields(provider, updateProviderField, renderSmsMappingInput, account) {
|
||||
return (
|
||||
<React.Fragment>
|
||||
{SMS_PROVIDERS_WITHOUT_SIGN_NAME.includes(provider.type) ?
|
||||
null :
|
||||
(<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("provider:Sign Name"), i18next.t("provider:Sign Name - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={provider.signName} onChange={e => {
|
||||
updateProviderField("signName", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
)
|
||||
}
|
||||
{SMS_PROVIDERS_WITHOUT_TEMPLATE_CODE.includes(provider.type) ?
|
||||
null :
|
||||
(<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("provider:Template code"), i18next.t("provider:Template code - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={provider.templateCode} onChange={e => {
|
||||
updateProviderField("templateCode", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
)
|
||||
}
|
||||
{
|
||||
provider.type === "Custom HTTP SMS" ? (
|
||||
<React.Fragment>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={2}>
|
||||
{Setting.getLabel(i18next.t("provider:Endpoint"), i18next.t("provider:Region endpoint for Internet"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input prefix={<LinkOutlined />} value={provider.endpoint} onChange={e => {
|
||||
updateProviderField("endpoint", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("general:Method"), i18next.t("provider:Method - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Select virtual={false} style={{width: "100%"}} value={provider.method} onChange={value => {
|
||||
updateProviderField("method", value);
|
||||
}}>
|
||||
{
|
||||
[
|
||||
{id: "GET", name: "GET"},
|
||||
{id: "POST", name: "POST"},
|
||||
{id: "PUT", name: "PUT"},
|
||||
{id: "DELETE", name: "DELETE"},
|
||||
].map((method, index) => <Option key={index} value={method.id}>{method.name}</Option>)
|
||||
}
|
||||
</Select>
|
||||
</Col>
|
||||
</Row>
|
||||
{
|
||||
provider.method !== "GET" ? (<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("webhook:Content type"), i18next.t("webhook:Content type - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Select virtual={false} style={{width: "100%"}} value={provider.issuerUrl === "" ? "application/x-www-form-urlencoded" : provider.issuerUrl} onChange={value => {
|
||||
updateProviderField("issuerUrl", value);
|
||||
}}>
|
||||
{
|
||||
[
|
||||
{id: "application/json", name: "application/json"},
|
||||
{id: "application/x-www-form-urlencoded", name: "application/x-www-form-urlencoded"},
|
||||
].map((method, index) => <Option key={index} value={method.id}>{method.name}</Option>)
|
||||
}
|
||||
</Select>
|
||||
</Col>
|
||||
</Row>) : null
|
||||
}
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("provider:HTTP header"), i18next.t("provider:HTTP header - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<HttpHeaderTable httpHeaders={provider.httpHeaders} onUpdateTable={(value) => {updateProviderField("httpHeaders", value);}} />
|
||||
</Col>
|
||||
</Row>
|
||||
{provider.method !== "GET" ? <Row style={{marginTop: "20px"}}>
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("provider:HTTP body mapping"), i18next.t("provider:HTTP body mapping - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22}>
|
||||
{renderSmsMappingInput()}
|
||||
</Col>
|
||||
</Row> : null}
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("provider:Parameter"), i18next.t("provider:Parameter - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={provider.title} onChange={e => {
|
||||
updateProviderField("title", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
</React.Fragment>
|
||||
) : null
|
||||
}
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("provider:Enable proxy"), i18next.t("provider:Enable proxy - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={1} >
|
||||
<Switch checked={provider.enableProxy} onChange={checked => {
|
||||
updateProviderField("enableProxy", checked);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("provider:SMS Test"), i18next.t("provider:SMS Test - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={4} >
|
||||
<Input.Group compact>
|
||||
<CountryCodeSelect
|
||||
style={{width: "90px"}}
|
||||
initValue={provider.content}
|
||||
onChange={(value) => {
|
||||
updateProviderField("content", value);
|
||||
}}
|
||||
countryCodes={account.organization.countryCodes}
|
||||
/>
|
||||
<Input value={provider.receiver}
|
||||
style={{width: "150px"}}
|
||||
placeholder = {i18next.t("user:Input your phone number")}
|
||||
onChange={e => {
|
||||
updateProviderField("receiver", e.target.value);
|
||||
}} />
|
||||
</Input.Group>
|
||||
</Col>
|
||||
<Col span={2} >
|
||||
<Button style={{marginLeft: "10px", marginBottom: "5px"}} type="primary"
|
||||
disabled={!Setting.isValidPhone(provider.receiver) || (provider.type === "Custom HTTP SMS" && provider.endpoint === "")}
|
||||
onClick={() => ProviderEditTestSms.sendTestSms(provider, "+" + Setting.getCountryCode(provider.content) + provider.receiver)} >
|
||||
{i18next.t("provider:Send Testing SMS")}
|
||||
</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
@@ -1,112 +0,0 @@
|
||||
// Copyright 2026 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 {Col, Input, Row} from "antd";
|
||||
import {LinkOutlined} from "@ant-design/icons";
|
||||
import * as Setting from "../Setting";
|
||||
import i18next from "i18next";
|
||||
|
||||
export function renderStorageProviderFields(provider, updateProviderField) {
|
||||
return (
|
||||
<React.Fragment>
|
||||
{["Local File System", "MinIO", "Tencent Cloud COS", "Google Cloud Storage", "Qiniu Cloud Kodo", "Synology", "Casdoor"].includes(provider.type) ? null : (
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={2}>
|
||||
{Setting.getLabel(i18next.t("provider:Endpoint (Intranet)"), i18next.t("provider:Region endpoint for Intranet"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input prefix={<LinkOutlined />} value={provider.intranetEndpoint} onChange={e => {
|
||||
updateProviderField("intranetEndpoint", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
)}
|
||||
{["Local File System"].includes(provider.type) ? null : (
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={2}>
|
||||
{Setting.getLabel(i18next.t("provider:Endpoint"), i18next.t("provider:Region endpoint for Internet"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input prefix={<LinkOutlined />} value={provider.endpoint} onChange={e => {
|
||||
updateProviderField("endpoint", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
)}
|
||||
{["Local File System"].includes(provider.type) ? null : (
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={2}>
|
||||
{["Casdoor"].includes(provider.type) ?
|
||||
Setting.getLabel(i18next.t("general:Provider"), i18next.t("general:Provider - Tooltip"))
|
||||
: Setting.getLabel(i18next.t("provider:Bucket"), i18next.t("provider:Bucket - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={provider.bucket} onChange={e => {
|
||||
updateProviderField("bucket", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
)}
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={2}>
|
||||
{Setting.getLabel(i18next.t("provider:Path prefix"), i18next.t("provider:Path prefix - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={provider.pathPrefix} onChange={e => {
|
||||
updateProviderField("pathPrefix", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
{["Synology", "Casdoor"].includes(provider.type) ? null : (
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={2}>
|
||||
{Setting.getLabel(i18next.t("provider:Domain"), i18next.t("provider:Domain - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input prefix={<LinkOutlined />} value={provider.domain} disabled={provider.type === "Local File System"} onChange={e => {
|
||||
updateProviderField("domain", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
)}
|
||||
{["Casdoor"].includes(provider.type) ? (
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={2}>
|
||||
{Setting.getLabel(i18next.t("general:Organization"), i18next.t("general:Organization - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={provider.content} onChange={e => {
|
||||
updateProviderField("content", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
) : null}
|
||||
{["AWS S3", "Tencent Cloud COS", "Qiniu Cloud Kodo", "Casdoor", "CUCloud OSS", "MinIO"].includes(provider.type) ? (
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={2}>
|
||||
{["Casdoor"].includes(provider.type) ?
|
||||
Setting.getLabel(i18next.t("general:Application"), i18next.t("general:Application - Tooltip")) :
|
||||
Setting.getLabel(i18next.t("provider:Region ID"), i18next.t("provider:Region ID - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<Input value={provider.regionId} onChange={e => {
|
||||
updateProviderField("regionId", e.target.value);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
) : null}
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
// Copyright 2026 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 {Checkbox, Col, Row} from "antd";
|
||||
import * as Setting from "../Setting";
|
||||
import i18next from "i18next";
|
||||
import * as Web3Auth from "../auth/Web3Auth";
|
||||
|
||||
export function renderWeb3ProviderFields(provider, updateProviderField) {
|
||||
const getWalletValue = () => {
|
||||
try {
|
||||
return JSON.parse(provider.metadata);
|
||||
} catch {
|
||||
return ["injected"];
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
provider.type === "Web3Onboard" ? (
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("provider:Wallets"), i18next.t("provider:Wallets - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22}>
|
||||
<Checkbox.Group
|
||||
options={Web3Auth.getWeb3OnboardWalletsOptions()}
|
||||
value={getWalletValue()}
|
||||
onChange={options => {
|
||||
updateProviderField("metadata", JSON.stringify(options));
|
||||
}}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
) : null
|
||||
);
|
||||
}
|
||||
@@ -14,16 +14,12 @@
|
||||
|
||||
import React from "react";
|
||||
import {DeleteOutlined, DownOutlined, UpOutlined} from "@ant-design/icons";
|
||||
import {AutoComplete, Button, Col, Input, Row, Table, Tooltip} from "antd";
|
||||
import {Button, Col, Input, Row, Select, Table, Tooltip} from "antd";
|
||||
import * as Setting from "../Setting";
|
||||
import i18next from "i18next";
|
||||
import RegionSelect from "../common/select/RegionSelect";
|
||||
|
||||
const TAG_OPTIONS = [
|
||||
{value: "Home", label: "Home"},
|
||||
{value: "Work", label: "Work"},
|
||||
{value: "Other", label: "Other"},
|
||||
];
|
||||
const {Option} = Select;
|
||||
|
||||
class AddressTable extends React.Component {
|
||||
constructor(props) {
|
||||
@@ -90,20 +86,16 @@ class AddressTable extends React.Component {
|
||||
key: "tag",
|
||||
width: "100px",
|
||||
render: (text, record, index) => {
|
||||
const tagOptions = TAG_OPTIONS.map(opt => ({...opt, label: opt.value === "Home" ? i18next.t("general:Home") : opt.value === "Work" ? i18next.t("user:Work") : i18next.t("user:Other")}));
|
||||
return (
|
||||
<AutoComplete
|
||||
size="small"
|
||||
style={{width: "100%"}}
|
||||
value={text || ""}
|
||||
options={tagOptions}
|
||||
<Select virtual={false} style={{width: "100%"}}
|
||||
value={text}
|
||||
onChange={value => {
|
||||
this.updateField(table, index, "tag", value);
|
||||
}}
|
||||
onSelect={value => {
|
||||
this.updateField(table, index, "tag", value);
|
||||
}}
|
||||
/>
|
||||
}} >
|
||||
<Option value="Home">{i18next.t("general:Home")}</Option>
|
||||
<Option value="Work">{i18next.t("user:Work")}</Option>
|
||||
<Option value="Other">{i18next.t("user:Other")}</Option>
|
||||
</Select>
|
||||
);
|
||||
},
|
||||
},
|
||||
@@ -114,7 +106,7 @@ class AddressTable extends React.Component {
|
||||
width: "150px",
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<Input size="small" value={text} onChange={e => {
|
||||
<Input value={text} onChange={e => {
|
||||
this.updateField(table, index, "line1", e.target.value);
|
||||
}} />
|
||||
);
|
||||
@@ -127,7 +119,7 @@ class AddressTable extends React.Component {
|
||||
width: "150px",
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<Input size="small" value={text} onChange={e => {
|
||||
<Input value={text} onChange={e => {
|
||||
this.updateField(table, index, "line2", e.target.value);
|
||||
}} />
|
||||
);
|
||||
@@ -140,7 +132,7 @@ class AddressTable extends React.Component {
|
||||
width: "120px",
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<Input size="small" value={text} onChange={e => {
|
||||
<Input value={text} onChange={e => {
|
||||
this.updateField(table, index, "city", e.target.value);
|
||||
}} />
|
||||
);
|
||||
@@ -153,7 +145,7 @@ class AddressTable extends React.Component {
|
||||
width: "100px",
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<Input size="small" value={text} onChange={e => {
|
||||
<Input value={text} onChange={e => {
|
||||
this.updateField(table, index, "state", e.target.value);
|
||||
}} />
|
||||
);
|
||||
@@ -166,7 +158,7 @@ class AddressTable extends React.Component {
|
||||
width: "100px",
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<Input size="small" value={text} onChange={e => {
|
||||
<Input value={text} onChange={e => {
|
||||
this.updateField(table, index, "zipCode", e.target.value);
|
||||
}} />
|
||||
);
|
||||
@@ -180,7 +172,6 @@ class AddressTable extends React.Component {
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<RegionSelect
|
||||
size="small"
|
||||
value={text}
|
||||
onChange={value => {
|
||||
this.updateField(table, index, "region", value);
|
||||
|
||||
@@ -21,7 +21,7 @@ class CartTable extends React.Component {
|
||||
render() {
|
||||
const columns = [
|
||||
{
|
||||
title: i18next.t("general:Name"),
|
||||
title: i18next.t("product:Name"),
|
||||
dataIndex: "displayName",
|
||||
key: "displayName",
|
||||
width: "200px",
|
||||
@@ -43,7 +43,7 @@ class CartTable extends React.Component {
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18next.t("order:Price"),
|
||||
title: i18next.t("product:Price"),
|
||||
dataIndex: "price",
|
||||
key: "price",
|
||||
width: "120px",
|
||||
|
||||
@@ -86,7 +86,7 @@ class ManagedAccountTable extends React.Component {
|
||||
render: (text, record, index) => {
|
||||
const items = this.props.applications;
|
||||
return (
|
||||
<Select virtual={false} size="small" style={{width: "100%"}}
|
||||
<Select virtual={false} style={{width: "100%"}}
|
||||
value={text}
|
||||
onChange={value => {
|
||||
this.updateField(table, index, "application", value);
|
||||
@@ -105,7 +105,7 @@ class ManagedAccountTable extends React.Component {
|
||||
// width: "420px",
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<Input size="small" prefix={<LinkOutlined />} value={text} onChange={e => {
|
||||
<Input prefix={<LinkOutlined />} value={text} onChange={e => {
|
||||
this.updateField(table, index, "signinUrl", e.target.value);
|
||||
}} />
|
||||
);
|
||||
@@ -118,7 +118,7 @@ class ManagedAccountTable extends React.Component {
|
||||
width: "200px",
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<Input size="small" value={text} onChange={e => {
|
||||
<Input value={text} onChange={e => {
|
||||
this.updateField(table, index, "username", e.target.value);
|
||||
}} />
|
||||
);
|
||||
@@ -131,7 +131,7 @@ class ManagedAccountTable extends React.Component {
|
||||
width: "200px",
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<Input.Password size="small" value={text} onChange={e => {
|
||||
<Input.Password value={text} onChange={e => {
|
||||
this.updateField(table, index, "password", e.target.value);
|
||||
}} />
|
||||
);
|
||||
|
||||
@@ -86,7 +86,7 @@ class MfaAccountTable extends React.Component {
|
||||
width: "400px",
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<Input size="small" value={text} onChange={e => {
|
||||
<Input value={text} onChange={e => {
|
||||
this.updateField(table, index, "accountName", e.target.value);
|
||||
}} />
|
||||
);
|
||||
@@ -99,7 +99,7 @@ class MfaAccountTable extends React.Component {
|
||||
width: "300px",
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<Input size="small" value={text} onChange={e => {
|
||||
<Input value={text} onChange={e => {
|
||||
this.updateField(table, index, "issuer", e.target.value);
|
||||
}} />
|
||||
);
|
||||
@@ -111,7 +111,7 @@ class MfaAccountTable extends React.Component {
|
||||
key: "origin",
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<Input size="small" value={text} onChange={e => {
|
||||
<Input value={text} onChange={e => {
|
||||
this.updateField(table, index, "origin", e.target.value);
|
||||
}} />
|
||||
);
|
||||
@@ -123,7 +123,7 @@ class MfaAccountTable extends React.Component {
|
||||
key: "secretKey",
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<Input.Password size="small" value={text} onChange={e => {
|
||||
<Input.Password value={text} onChange={e => {
|
||||
this.updateField(table, index, "secretKey", e.target.value);
|
||||
}} />
|
||||
);
|
||||
|
||||
@@ -84,7 +84,7 @@ class MfaTable extends React.Component {
|
||||
key: "name",
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<Select virtual={false} size="small" style={{width: "100%"}}
|
||||
<Select virtual={false} style={{width: "100%"}}
|
||||
value={text}
|
||||
onChange={value => {
|
||||
this.updateField(table, index, "name", value);
|
||||
@@ -103,7 +103,7 @@ class MfaTable extends React.Component {
|
||||
width: "100px",
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<Select virtual={false} size="small" style={{width: "100%"}}
|
||||
<Select virtual={false} style={{width: "100%"}}
|
||||
value={text}
|
||||
defaultValue="Optional"
|
||||
options={RuleItems.map((item) =>
|
||||
|
||||
@@ -104,23 +104,13 @@ class ProviderTable extends React.Component {
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18next.t("general:Category"),
|
||||
title: i18next.t("provider:Category"),
|
||||
dataIndex: "category",
|
||||
key: "category",
|
||||
width: "100px",
|
||||
render: (text, record, index) => {
|
||||
const provider = Setting.getArrayItem(this.props.providers, "name", record.name);
|
||||
const owner = provider?.owner || this.getUserOrganization()?.name;
|
||||
const editUrl = provider && owner && provider.name ? `/providers/${owner}/${provider.name}` : null;
|
||||
const categoryText = provider?.category;
|
||||
if (editUrl && categoryText) {
|
||||
return (
|
||||
<a href={editUrl} target="_blank" rel="noopener noreferrer">
|
||||
{categoryText}
|
||||
</a>
|
||||
);
|
||||
}
|
||||
return categoryText;
|
||||
return provider?.category;
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -130,17 +120,7 @@ class ProviderTable extends React.Component {
|
||||
width: "80px",
|
||||
render: (text, record, index) => {
|
||||
const provider = Setting.getArrayItem(this.props.providers, "name", record.name);
|
||||
const owner = provider?.owner || this.getUserOrganization()?.name;
|
||||
const editUrl = provider && owner && provider.name ? `/providers/${owner}/${provider.name}` : null;
|
||||
const typeWidget = Provider.getProviderLogoWidget(provider, {disableLink: !!editUrl});
|
||||
if (editUrl && typeWidget) {
|
||||
return (
|
||||
<a href={editUrl} target="_blank" rel="noopener noreferrer">
|
||||
{typeWidget}
|
||||
</a>
|
||||
);
|
||||
}
|
||||
return typeWidget;
|
||||
return Provider.getProviderLogoWidget(provider);
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -131,18 +131,13 @@ class TransactionTable extends React.Component {
|
||||
columns={columns}
|
||||
dataSource={this.props.transactions}
|
||||
rowKey={(record) => `${record.owner}/${record.name}`}
|
||||
size="middle"
|
||||
size="small"
|
||||
bordered
|
||||
pagination={{
|
||||
pageSize: 10,
|
||||
showSizeChanger: true,
|
||||
pageSizeOptions: ["10", "20", "50", "100"],
|
||||
}}
|
||||
title={this.props.title ? () => (
|
||||
<div>
|
||||
{this.props.title}
|
||||
</div>
|
||||
) : undefined}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -168,7 +168,7 @@ export function getTransactionTableColumns(options = {}) {
|
||||
});
|
||||
|
||||
columns.push({
|
||||
title: i18next.t("general:Category"),
|
||||
title: i18next.t("provider:Category"),
|
||||
dataIndex: "category",
|
||||
key: "category",
|
||||
width: "120px",
|
||||
|
||||
Reference in New Issue
Block a user