mirror of
https://github.com/casdoor/casdoor.git
synced 2025-08-10 15:27:48 +08:00
Compare commits
12 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
d12117324c | ||
![]() |
1a6c9fbf69 | ||
![]() |
dd60d79af9 | ||
![]() |
73d314c7fe | ||
![]() |
27959e0f6f | ||
![]() |
47f40c5b24 | ||
![]() |
2ff9020884 | ||
![]() |
abaf4ca8d9 | ||
![]() |
8ff0cfd6ec | ||
![]() |
7a2a40edcc | ||
![]() |
b7a001ea39 | ||
![]() |
891e8e21d8 |
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
@@ -110,7 +110,7 @@ jobs:
|
||||
with:
|
||||
start: yarn start
|
||||
wait-on: 'http://localhost:7001'
|
||||
wait-on-timeout: 180
|
||||
wait-on-timeout: 210
|
||||
working-directory: ./web
|
||||
|
||||
- uses: actions/upload-artifact@v3
|
||||
|
10
README.md
10
README.md
@@ -11,7 +11,7 @@
|
||||
<img alt="GitHub Workflow Status (branch)" src="https://github.com/casdoor/casdoor/workflows/Build/badge.svg?style=flat-square">
|
||||
</a>
|
||||
<a href="https://github.com/casdoor/casdoor/releases/latest">
|
||||
<img alt="GitHub Release" src="https://img.shields.io/github/v/release/casbin/casdoor.svg">
|
||||
<img alt="GitHub Release" src="https://img.shields.io/github/v/release/casdoor/casdoor.svg">
|
||||
</a>
|
||||
<a href="https://hub.docker.com/repository/docker/casbin/casdoor">
|
||||
<img alt="Docker Image Version (latest semver)" src="https://img.shields.io/badge/Docker%20Hub-latest-brightgreen">
|
||||
@@ -23,16 +23,16 @@
|
||||
<img alt="Go Report Card" src="https://goreportcard.com/badge/github.com/casdoor/casdoor?style=flat-square">
|
||||
</a>
|
||||
<a href="https://github.com/casdoor/casdoor/blob/master/LICENSE">
|
||||
<img src="https://img.shields.io/github/license/casbin/casdoor?style=flat-square" alt="license">
|
||||
<img src="https://img.shields.io/github/license/casdoor/casdoor?style=flat-square" alt="license">
|
||||
</a>
|
||||
<a href="https://github.com/casdoor/casdoor/issues">
|
||||
<img alt="GitHub issues" src="https://img.shields.io/github/issues/casbin/casdoor?style=flat-square">
|
||||
<img alt="GitHub issues" src="https://img.shields.io/github/issues/casdoor/casdoor?style=flat-square">
|
||||
</a>
|
||||
<a href="#">
|
||||
<img alt="GitHub stars" src="https://img.shields.io/github/stars/casbin/casdoor?style=flat-square">
|
||||
<img alt="GitHub stars" src="https://img.shields.io/github/stars/casdoor/casdoor?style=flat-square">
|
||||
</a>
|
||||
<a href="https://github.com/casdoor/casdoor/network">
|
||||
<img alt="GitHub forks" src="https://img.shields.io/github/forks/casbin/casdoor?style=flat-square">
|
||||
<img alt="GitHub forks" src="https://img.shields.io/github/forks/casdoor/casdoor?style=flat-square">
|
||||
</a>
|
||||
<a href="https://crowdin.com/project/casdoor-site">
|
||||
<img alt="Crowdin" src="https://badges.crowdin.net/casdoor-site/localized.svg">
|
||||
|
33
controllers/get-dashboard.go
Normal file
33
controllers/get-dashboard.go
Normal file
@@ -0,0 +1,33 @@
|
||||
// Copyright 2021 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package controllers
|
||||
|
||||
import "github.com/casdoor/casdoor/object"
|
||||
|
||||
// GetDashboard
|
||||
// @Title GetDashboard
|
||||
// @Tag GetDashboard API
|
||||
// @Description get information of dashboard
|
||||
// @Success 200 {object} controllers.Response The Response object
|
||||
// @router /get-dashboard [get]
|
||||
func (c *ApiController) GetDashboard() {
|
||||
data, err := object.GetDashboard()
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.ResponseOk(data)
|
||||
}
|
@@ -361,6 +361,9 @@ func (c *ApiController) UploadResource() {
|
||||
return
|
||||
}
|
||||
|
||||
if user.Properties == nil {
|
||||
user.Properties = map[string]string{}
|
||||
}
|
||||
user.Properties[tag] = fileUrl
|
||||
user.Properties["isIdCardVerified"] = "false"
|
||||
_, err = object.UpdateUser(user.GetId(), user, []string{"properties"}, false)
|
||||
|
1
go.mod
1
go.mod
@@ -51,6 +51,7 @@ require (
|
||||
github.com/siddontang/go-log v0.0.0-20190221022429-1e957dd83bed
|
||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
|
||||
github.com/stretchr/testify v1.8.3
|
||||
github.com/stripe/stripe-go/v74 v74.29.0 // indirect
|
||||
github.com/tealeg/xlsx v1.0.5
|
||||
github.com/thanhpk/randstr v1.0.4
|
||||
github.com/tklauser/go-sysconf v0.3.10 // indirect
|
||||
|
3
go.sum
3
go.sum
@@ -1476,6 +1476,8 @@ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o
|
||||
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY=
|
||||
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stripe/stripe-go/v74 v74.29.0 h1:ffJ+1Ta1Ccg7yDDz+SfjixX0KizEEJ/wNVRoFYkdwFY=
|
||||
github.com/stripe/stripe-go/v74 v74.29.0/go.mod h1:f9L6LvaXa35ja7eyvP6GQswoaIPaBRvGAimAO+udbBw=
|
||||
github.com/syndtr/goleveldb v0.0.0-20160425020131-cfa635847112/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0=
|
||||
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
|
||||
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
|
||||
@@ -1699,6 +1701,7 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
|
||||
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
|
@@ -36,6 +36,9 @@ func TestGenerateI18nFrontend(t *testing.T) {
|
||||
applyToOtherLanguage("frontend", "it", data)
|
||||
applyToOtherLanguage("frontend", "ms", data)
|
||||
applyToOtherLanguage("frontend", "tr", data)
|
||||
applyToOtherLanguage("frontend", "ar", data)
|
||||
applyToOtherLanguage("frontend", "he", data)
|
||||
applyToOtherLanguage("frontend", "fi", data)
|
||||
}
|
||||
|
||||
func TestGenerateI18nBackend(t *testing.T) {
|
||||
@@ -55,4 +58,7 @@ func TestGenerateI18nBackend(t *testing.T) {
|
||||
applyToOtherLanguage("backend", "it", data)
|
||||
applyToOtherLanguage("backend", "ms", data)
|
||||
applyToOtherLanguage("backend", "tr", data)
|
||||
applyToOtherLanguage("backend", "ar", data)
|
||||
applyToOtherLanguage("backend", "he", data)
|
||||
applyToOtherLanguage("backend", "fi", data)
|
||||
}
|
||||
|
142
i18n/locales/ar/data.json
Normal file
142
i18n/locales/ar/data.json
Normal file
@@ -0,0 +1,142 @@
|
||||
{
|
||||
"account": {
|
||||
"Failed to add user": "Failed to add user",
|
||||
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
||||
"Please sign out first": "Please sign out first",
|
||||
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
|
||||
},
|
||||
"auth": {
|
||||
"Challenge method should be S256": "Challenge method should be S256",
|
||||
"Failed to create user, user information is invalid: %s": "Failed to create user, user information is invalid: %s",
|
||||
"Failed to login in: %s": "Failed to login in: %s",
|
||||
"Invalid token": "Invalid token",
|
||||
"State expected: %s, but got: %s": "State expected: %s, but got: %s",
|
||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up",
|
||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support",
|
||||
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)",
|
||||
"The application: %s does not exist": "The application: %s does not exist",
|
||||
"The login method: login with password is not enabled for the application": "The login method: login with password is not enabled for the application",
|
||||
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
||||
"Unauthorized operation": "Unauthorized operation",
|
||||
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s",
|
||||
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags"
|
||||
},
|
||||
"cas": {
|
||||
"Service %s and %s do not match": "Service %s and %s do not match"
|
||||
},
|
||||
"check": {
|
||||
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
||||
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
||||
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
||||
"Email already exists": "Email already exists",
|
||||
"Email cannot be empty": "Email cannot be empty",
|
||||
"Email is invalid": "Email is invalid",
|
||||
"Empty username.": "Empty username.",
|
||||
"FirstName cannot be blank": "FirstName cannot be blank",
|
||||
"LDAP user name or password incorrect": "LDAP user name or password incorrect",
|
||||
"LastName cannot be blank": "LastName cannot be blank",
|
||||
"Multiple accounts with same uid, please check your ldap server": "Multiple accounts with same uid, please check your ldap server",
|
||||
"Organization does not exist": "Organization does not exist",
|
||||
"Password must have at least 6 characters": "Password must have at least 6 characters",
|
||||
"Phone already exists": "Phone already exists",
|
||||
"Phone cannot be empty": "Phone cannot be empty",
|
||||
"Phone number is invalid": "Phone number is invalid",
|
||||
"Session outdated, please login again": "Session outdated, please login again",
|
||||
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
||||
"The user: %s doesn't exist in LDAP server": "The user: %s doesn't exist in LDAP server",
|
||||
"The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.": "The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.",
|
||||
"Username already exists": "Username already exists",
|
||||
"Username cannot be an email address": "Username cannot be an email address",
|
||||
"Username cannot contain white spaces": "Username cannot contain white spaces",
|
||||
"Username cannot start with a digit": "Username cannot start with a digit",
|
||||
"Username is too long (maximum is 39 characters).": "Username is too long (maximum is 39 characters).",
|
||||
"Username must have at least 2 characters": "Username must have at least 2 characters",
|
||||
"You have entered the wrong password or code too many times, please wait for %d minutes and try again": "You have entered the wrong password or code too many times, please wait for %d minutes and try again",
|
||||
"Your region is not allow to signup by phone": "Your region is not allow to signup by phone",
|
||||
"password or code is incorrect": "password or code is incorrect",
|
||||
"password or code is incorrect, you have %d remaining chances": "password or code is incorrect, you have %d remaining chances",
|
||||
"unsupported password type: %s": "unsupported password type: %s"
|
||||
},
|
||||
"general": {
|
||||
"Missing parameter": "Missing parameter",
|
||||
"Please login first": "Please login first",
|
||||
"The user: %s doesn't exist": "The user: %s doesn't exist",
|
||||
"don't support captchaProvider: ": "don't support captchaProvider: ",
|
||||
"this operation is not allowed in demo mode": "this operation is not allowed in demo mode"
|
||||
},
|
||||
"ldap": {
|
||||
"Ldap server exist": "Ldap server exist"
|
||||
},
|
||||
"link": {
|
||||
"Please link first": "Please link first",
|
||||
"This application has no providers": "This application has no providers",
|
||||
"This application has no providers of type": "This application has no providers of type",
|
||||
"This provider can't be unlinked": "This provider can't be unlinked",
|
||||
"You are not the global admin, you can't unlink other users": "You are not the global admin, you can't unlink other users",
|
||||
"You can't unlink yourself, you are not a member of any application": "You can't unlink yourself, you are not a member of any application"
|
||||
},
|
||||
"organization": {
|
||||
"Only admin can modify the %s.": "Only admin can modify the %s.",
|
||||
"The %s is immutable.": "The %s is immutable.",
|
||||
"Unknown modify rule %s.": "Unknown modify rule %s."
|
||||
},
|
||||
"provider": {
|
||||
"Invalid application id": "Invalid application id",
|
||||
"the provider: %s does not exist": "the provider: %s does not exist"
|
||||
},
|
||||
"resource": {
|
||||
"User is nil for tag: avatar": "User is nil for tag: avatar",
|
||||
"Username or fullFilePath is empty: username = %s, fullFilePath = %s": "Username or fullFilePath is empty: username = %s, fullFilePath = %s"
|
||||
},
|
||||
"saml": {
|
||||
"Application %s not found": "Application %s not found"
|
||||
},
|
||||
"saml_sp": {
|
||||
"provider %s's category is not SAML": "provider %s's category is not SAML"
|
||||
},
|
||||
"service": {
|
||||
"Empty parameters for emailForm: %v": "Empty parameters for emailForm: %v",
|
||||
"Invalid Email receivers: %s": "Invalid Email receivers: %s",
|
||||
"Invalid phone receivers: %s": "Invalid phone receivers: %s"
|
||||
},
|
||||
"storage": {
|
||||
"The objectKey: %s is not allowed": "The objectKey: %s is not allowed",
|
||||
"The provider type: %s is not supported": "The provider type: %s is not supported"
|
||||
},
|
||||
"token": {
|
||||
"Empty clientId or clientSecret": "Empty clientId or clientSecret",
|
||||
"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",
|
||||
"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"
|
||||
},
|
||||
"user": {
|
||||
"Display name cannot be empty": "Display name cannot be empty",
|
||||
"New password cannot contain blank space.": "New password cannot contain blank space."
|
||||
},
|
||||
"user_upload": {
|
||||
"Failed to import users": "Failed to import users"
|
||||
},
|
||||
"util": {
|
||||
"No application is found for userId: %s": "No application is found for userId: %s",
|
||||
"No provider for category: %s is found for application: %s": "No provider for category: %s is found for application: %s",
|
||||
"The provider: %s is not found": "The provider: %s is not found"
|
||||
},
|
||||
"verification": {
|
||||
"Code has not been sent yet!": "Code has not been sent yet!",
|
||||
"Invalid captcha provider.": "Invalid captcha provider.",
|
||||
"Phone number is invalid in your region %s": "Phone number is invalid in your region %s",
|
||||
"Turing test failed.": "Turing test failed.",
|
||||
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
|
||||
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
|
||||
"Unknown type": "Unknown type",
|
||||
"Wrong verification code!": "Wrong verification code!",
|
||||
"You should verify your code in %d min!": "You should verify your code in %d min!",
|
||||
"the user does not exist, please sign up first": "the user does not exist, please sign up first"
|
||||
},
|
||||
"webauthn": {
|
||||
"Found no credentials for this user": "Found no credentials for this user",
|
||||
"Please call WebAuthnSigninBegin first": "Please call WebAuthnSigninBegin first"
|
||||
}
|
||||
}
|
142
i18n/locales/fi/data.json
Normal file
142
i18n/locales/fi/data.json
Normal file
@@ -0,0 +1,142 @@
|
||||
{
|
||||
"account": {
|
||||
"Failed to add user": "Failed to add user",
|
||||
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
||||
"Please sign out first": "Please sign out first",
|
||||
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
|
||||
},
|
||||
"auth": {
|
||||
"Challenge method should be S256": "Challenge method should be S256",
|
||||
"Failed to create user, user information is invalid: %s": "Failed to create user, user information is invalid: %s",
|
||||
"Failed to login in: %s": "Failed to login in: %s",
|
||||
"Invalid token": "Invalid token",
|
||||
"State expected: %s, but got: %s": "State expected: %s, but got: %s",
|
||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up",
|
||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support",
|
||||
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)",
|
||||
"The application: %s does not exist": "The application: %s does not exist",
|
||||
"The login method: login with password is not enabled for the application": "The login method: login with password is not enabled for the application",
|
||||
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
||||
"Unauthorized operation": "Unauthorized operation",
|
||||
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s",
|
||||
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags"
|
||||
},
|
||||
"cas": {
|
||||
"Service %s and %s do not match": "Service %s and %s do not match"
|
||||
},
|
||||
"check": {
|
||||
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
||||
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
||||
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
||||
"Email already exists": "Email already exists",
|
||||
"Email cannot be empty": "Email cannot be empty",
|
||||
"Email is invalid": "Email is invalid",
|
||||
"Empty username.": "Empty username.",
|
||||
"FirstName cannot be blank": "FirstName cannot be blank",
|
||||
"LDAP user name or password incorrect": "LDAP user name or password incorrect",
|
||||
"LastName cannot be blank": "LastName cannot be blank",
|
||||
"Multiple accounts with same uid, please check your ldap server": "Multiple accounts with same uid, please check your ldap server",
|
||||
"Organization does not exist": "Organization does not exist",
|
||||
"Password must have at least 6 characters": "Password must have at least 6 characters",
|
||||
"Phone already exists": "Phone already exists",
|
||||
"Phone cannot be empty": "Phone cannot be empty",
|
||||
"Phone number is invalid": "Phone number is invalid",
|
||||
"Session outdated, please login again": "Session outdated, please login again",
|
||||
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
||||
"The user: %s doesn't exist in LDAP server": "The user: %s doesn't exist in LDAP server",
|
||||
"The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.": "The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.",
|
||||
"Username already exists": "Username already exists",
|
||||
"Username cannot be an email address": "Username cannot be an email address",
|
||||
"Username cannot contain white spaces": "Username cannot contain white spaces",
|
||||
"Username cannot start with a digit": "Username cannot start with a digit",
|
||||
"Username is too long (maximum is 39 characters).": "Username is too long (maximum is 39 characters).",
|
||||
"Username must have at least 2 characters": "Username must have at least 2 characters",
|
||||
"You have entered the wrong password or code too many times, please wait for %d minutes and try again": "You have entered the wrong password or code too many times, please wait for %d minutes and try again",
|
||||
"Your region is not allow to signup by phone": "Your region is not allow to signup by phone",
|
||||
"password or code is incorrect": "password or code is incorrect",
|
||||
"password or code is incorrect, you have %d remaining chances": "password or code is incorrect, you have %d remaining chances",
|
||||
"unsupported password type: %s": "unsupported password type: %s"
|
||||
},
|
||||
"general": {
|
||||
"Missing parameter": "Missing parameter",
|
||||
"Please login first": "Please login first",
|
||||
"The user: %s doesn't exist": "The user: %s doesn't exist",
|
||||
"don't support captchaProvider: ": "don't support captchaProvider: ",
|
||||
"this operation is not allowed in demo mode": "this operation is not allowed in demo mode"
|
||||
},
|
||||
"ldap": {
|
||||
"Ldap server exist": "Ldap server exist"
|
||||
},
|
||||
"link": {
|
||||
"Please link first": "Please link first",
|
||||
"This application has no providers": "This application has no providers",
|
||||
"This application has no providers of type": "This application has no providers of type",
|
||||
"This provider can't be unlinked": "This provider can't be unlinked",
|
||||
"You are not the global admin, you can't unlink other users": "You are not the global admin, you can't unlink other users",
|
||||
"You can't unlink yourself, you are not a member of any application": "You can't unlink yourself, you are not a member of any application"
|
||||
},
|
||||
"organization": {
|
||||
"Only admin can modify the %s.": "Only admin can modify the %s.",
|
||||
"The %s is immutable.": "The %s is immutable.",
|
||||
"Unknown modify rule %s.": "Unknown modify rule %s."
|
||||
},
|
||||
"provider": {
|
||||
"Invalid application id": "Invalid application id",
|
||||
"the provider: %s does not exist": "the provider: %s does not exist"
|
||||
},
|
||||
"resource": {
|
||||
"User is nil for tag: avatar": "User is nil for tag: avatar",
|
||||
"Username or fullFilePath is empty: username = %s, fullFilePath = %s": "Username or fullFilePath is empty: username = %s, fullFilePath = %s"
|
||||
},
|
||||
"saml": {
|
||||
"Application %s not found": "Application %s not found"
|
||||
},
|
||||
"saml_sp": {
|
||||
"provider %s's category is not SAML": "provider %s's category is not SAML"
|
||||
},
|
||||
"service": {
|
||||
"Empty parameters for emailForm: %v": "Empty parameters for emailForm: %v",
|
||||
"Invalid Email receivers: %s": "Invalid Email receivers: %s",
|
||||
"Invalid phone receivers: %s": "Invalid phone receivers: %s"
|
||||
},
|
||||
"storage": {
|
||||
"The objectKey: %s is not allowed": "The objectKey: %s is not allowed",
|
||||
"The provider type: %s is not supported": "The provider type: %s is not supported"
|
||||
},
|
||||
"token": {
|
||||
"Empty clientId or clientSecret": "Empty clientId or clientSecret",
|
||||
"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",
|
||||
"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"
|
||||
},
|
||||
"user": {
|
||||
"Display name cannot be empty": "Display name cannot be empty",
|
||||
"New password cannot contain blank space.": "New password cannot contain blank space."
|
||||
},
|
||||
"user_upload": {
|
||||
"Failed to import users": "Failed to import users"
|
||||
},
|
||||
"util": {
|
||||
"No application is found for userId: %s": "No application is found for userId: %s",
|
||||
"No provider for category: %s is found for application: %s": "No provider for category: %s is found for application: %s",
|
||||
"The provider: %s is not found": "The provider: %s is not found"
|
||||
},
|
||||
"verification": {
|
||||
"Code has not been sent yet!": "Code has not been sent yet!",
|
||||
"Invalid captcha provider.": "Invalid captcha provider.",
|
||||
"Phone number is invalid in your region %s": "Phone number is invalid in your region %s",
|
||||
"Turing test failed.": "Turing test failed.",
|
||||
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
|
||||
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
|
||||
"Unknown type": "Unknown type",
|
||||
"Wrong verification code!": "Wrong verification code!",
|
||||
"You should verify your code in %d min!": "You should verify your code in %d min!",
|
||||
"the user does not exist, please sign up first": "the user does not exist, please sign up first"
|
||||
},
|
||||
"webauthn": {
|
||||
"Found no credentials for this user": "Found no credentials for this user",
|
||||
"Please call WebAuthnSigninBegin first": "Please call WebAuthnSigninBegin first"
|
||||
}
|
||||
}
|
142
i18n/locales/he/data.json
Normal file
142
i18n/locales/he/data.json
Normal file
@@ -0,0 +1,142 @@
|
||||
{
|
||||
"account": {
|
||||
"Failed to add user": "Failed to add user",
|
||||
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
||||
"Please sign out first": "Please sign out first",
|
||||
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
|
||||
},
|
||||
"auth": {
|
||||
"Challenge method should be S256": "Challenge method should be S256",
|
||||
"Failed to create user, user information is invalid: %s": "Failed to create user, user information is invalid: %s",
|
||||
"Failed to login in: %s": "Failed to login in: %s",
|
||||
"Invalid token": "Invalid token",
|
||||
"State expected: %s, but got: %s": "State expected: %s, but got: %s",
|
||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up",
|
||||
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support": "The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support",
|
||||
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)",
|
||||
"The application: %s does not exist": "The application: %s does not exist",
|
||||
"The login method: login with password is not enabled for the application": "The login method: login with password is not enabled for the application",
|
||||
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
||||
"Unauthorized operation": "Unauthorized operation",
|
||||
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s",
|
||||
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags"
|
||||
},
|
||||
"cas": {
|
||||
"Service %s and %s do not match": "Service %s and %s do not match"
|
||||
},
|
||||
"check": {
|
||||
"Affiliation cannot be blank": "Affiliation cannot be blank",
|
||||
"DisplayName cannot be blank": "DisplayName cannot be blank",
|
||||
"DisplayName is not valid real name": "DisplayName is not valid real name",
|
||||
"Email already exists": "Email already exists",
|
||||
"Email cannot be empty": "Email cannot be empty",
|
||||
"Email is invalid": "Email is invalid",
|
||||
"Empty username.": "Empty username.",
|
||||
"FirstName cannot be blank": "FirstName cannot be blank",
|
||||
"LDAP user name or password incorrect": "LDAP user name or password incorrect",
|
||||
"LastName cannot be blank": "LastName cannot be blank",
|
||||
"Multiple accounts with same uid, please check your ldap server": "Multiple accounts with same uid, please check your ldap server",
|
||||
"Organization does not exist": "Organization does not exist",
|
||||
"Password must have at least 6 characters": "Password must have at least 6 characters",
|
||||
"Phone already exists": "Phone already exists",
|
||||
"Phone cannot be empty": "Phone cannot be empty",
|
||||
"Phone number is invalid": "Phone number is invalid",
|
||||
"Session outdated, please login again": "Session outdated, please login again",
|
||||
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
||||
"The user: %s doesn't exist in LDAP server": "The user: %s doesn't exist in LDAP server",
|
||||
"The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.": "The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.",
|
||||
"Username already exists": "Username already exists",
|
||||
"Username cannot be an email address": "Username cannot be an email address",
|
||||
"Username cannot contain white spaces": "Username cannot contain white spaces",
|
||||
"Username cannot start with a digit": "Username cannot start with a digit",
|
||||
"Username is too long (maximum is 39 characters).": "Username is too long (maximum is 39 characters).",
|
||||
"Username must have at least 2 characters": "Username must have at least 2 characters",
|
||||
"You have entered the wrong password or code too many times, please wait for %d minutes and try again": "You have entered the wrong password or code too many times, please wait for %d minutes and try again",
|
||||
"Your region is not allow to signup by phone": "Your region is not allow to signup by phone",
|
||||
"password or code is incorrect": "password or code is incorrect",
|
||||
"password or code is incorrect, you have %d remaining chances": "password or code is incorrect, you have %d remaining chances",
|
||||
"unsupported password type: %s": "unsupported password type: %s"
|
||||
},
|
||||
"general": {
|
||||
"Missing parameter": "Missing parameter",
|
||||
"Please login first": "Please login first",
|
||||
"The user: %s doesn't exist": "The user: %s doesn't exist",
|
||||
"don't support captchaProvider: ": "don't support captchaProvider: ",
|
||||
"this operation is not allowed in demo mode": "this operation is not allowed in demo mode"
|
||||
},
|
||||
"ldap": {
|
||||
"Ldap server exist": "Ldap server exist"
|
||||
},
|
||||
"link": {
|
||||
"Please link first": "Please link first",
|
||||
"This application has no providers": "This application has no providers",
|
||||
"This application has no providers of type": "This application has no providers of type",
|
||||
"This provider can't be unlinked": "This provider can't be unlinked",
|
||||
"You are not the global admin, you can't unlink other users": "You are not the global admin, you can't unlink other users",
|
||||
"You can't unlink yourself, you are not a member of any application": "You can't unlink yourself, you are not a member of any application"
|
||||
},
|
||||
"organization": {
|
||||
"Only admin can modify the %s.": "Only admin can modify the %s.",
|
||||
"The %s is immutable.": "The %s is immutable.",
|
||||
"Unknown modify rule %s.": "Unknown modify rule %s."
|
||||
},
|
||||
"provider": {
|
||||
"Invalid application id": "Invalid application id",
|
||||
"the provider: %s does not exist": "the provider: %s does not exist"
|
||||
},
|
||||
"resource": {
|
||||
"User is nil for tag: avatar": "User is nil for tag: avatar",
|
||||
"Username or fullFilePath is empty: username = %s, fullFilePath = %s": "Username or fullFilePath is empty: username = %s, fullFilePath = %s"
|
||||
},
|
||||
"saml": {
|
||||
"Application %s not found": "Application %s not found"
|
||||
},
|
||||
"saml_sp": {
|
||||
"provider %s's category is not SAML": "provider %s's category is not SAML"
|
||||
},
|
||||
"service": {
|
||||
"Empty parameters for emailForm: %v": "Empty parameters for emailForm: %v",
|
||||
"Invalid Email receivers: %s": "Invalid Email receivers: %s",
|
||||
"Invalid phone receivers: %s": "Invalid phone receivers: %s"
|
||||
},
|
||||
"storage": {
|
||||
"The objectKey: %s is not allowed": "The objectKey: %s is not allowed",
|
||||
"The provider type: %s is not supported": "The provider type: %s is not supported"
|
||||
},
|
||||
"token": {
|
||||
"Empty clientId or clientSecret": "Empty clientId or clientSecret",
|
||||
"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",
|
||||
"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"
|
||||
},
|
||||
"user": {
|
||||
"Display name cannot be empty": "Display name cannot be empty",
|
||||
"New password cannot contain blank space.": "New password cannot contain blank space."
|
||||
},
|
||||
"user_upload": {
|
||||
"Failed to import users": "Failed to import users"
|
||||
},
|
||||
"util": {
|
||||
"No application is found for userId: %s": "No application is found for userId: %s",
|
||||
"No provider for category: %s is found for application: %s": "No provider for category: %s is found for application: %s",
|
||||
"The provider: %s is not found": "The provider: %s is not found"
|
||||
},
|
||||
"verification": {
|
||||
"Code has not been sent yet!": "Code has not been sent yet!",
|
||||
"Invalid captcha provider.": "Invalid captcha provider.",
|
||||
"Phone number is invalid in your region %s": "Phone number is invalid in your region %s",
|
||||
"Turing test failed.": "Turing test failed.",
|
||||
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
|
||||
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
|
||||
"Unknown type": "Unknown type",
|
||||
"Wrong verification code!": "Wrong verification code!",
|
||||
"You should verify your code in %d min!": "You should verify your code in %d min!",
|
||||
"the user does not exist, please sign up first": "the user does not exist, please sign up first"
|
||||
},
|
||||
"webauthn": {
|
||||
"Found no credentials for this user": "Found no credentials for this user",
|
||||
"Please call WebAuthnSigninBegin first": "Please call WebAuthnSigninBegin first"
|
||||
}
|
||||
}
|
@@ -24,20 +24,10 @@ import (
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
const Web3AuthTokenKey = "web3AuthToken"
|
||||
|
||||
type MetaMaskIdProvider struct {
|
||||
Client *http.Client
|
||||
}
|
||||
|
||||
type Web3AuthToken struct {
|
||||
Address string `json:"address"`
|
||||
Nonce string `json:"nonce"`
|
||||
CreateAt uint64 `json:"createAt"`
|
||||
TypedData string `json:"typedData"`
|
||||
Signature string `json:"signature"` // signature for typed data
|
||||
}
|
||||
|
||||
func NewMetaMaskIdProvider() *MetaMaskIdProvider {
|
||||
idp := &MetaMaskIdProvider{}
|
||||
return idp
|
||||
|
@@ -111,6 +111,8 @@ func GetIdProvider(idpInfo *ProviderInfo, redirectUrl string) IdProvider {
|
||||
return NewBilibiliIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl)
|
||||
case "MetaMask":
|
||||
return NewMetaMaskIdProvider()
|
||||
case "Web3Onboard":
|
||||
return NewWeb3OnboardIdProvider()
|
||||
default:
|
||||
if isGothSupport(idpInfo.Type) {
|
||||
return NewGothIdProvider(idpInfo.Type, idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl, idpInfo.HostUrl)
|
||||
|
103
idp/web3onboard.go
Normal file
103
idp/web3onboard.go
Normal file
@@ -0,0 +1,103 @@
|
||||
// Copyright 2023 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.
|
||||
|
||||
package idp
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
const Web3AuthTokenKey = "web3AuthToken"
|
||||
|
||||
type Web3AuthToken struct {
|
||||
Address string `json:"address"`
|
||||
Nonce string `json:"nonce"`
|
||||
CreateAt uint64 `json:"createAt"`
|
||||
TypedData string `json:"typedData"` // typed data use for application
|
||||
Signature string `json:"signature"` // signature for typed data
|
||||
WalletType string `json:"walletType"` // e.g."MetaMask", "Coinbase"
|
||||
}
|
||||
|
||||
type Web3OnboardIdProvider struct {
|
||||
Client *http.Client
|
||||
}
|
||||
|
||||
func NewWeb3OnboardIdProvider() *Web3OnboardIdProvider {
|
||||
idp := &Web3OnboardIdProvider{}
|
||||
return idp
|
||||
}
|
||||
|
||||
func (idp *Web3OnboardIdProvider) SetHttpClient(client *http.Client) {
|
||||
idp.Client = client
|
||||
}
|
||||
|
||||
func (idp *Web3OnboardIdProvider) GetToken(code string) (*oauth2.Token, error) {
|
||||
web3AuthToken := Web3AuthToken{}
|
||||
if err := json.Unmarshal([]byte(code), &web3AuthToken); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
token := &oauth2.Token{
|
||||
AccessToken: fmt.Sprintf("%v:%v", Web3AuthTokenKey, web3AuthToken.Address),
|
||||
TokenType: "Bearer",
|
||||
Expiry: time.Now().AddDate(0, 1, 0),
|
||||
}
|
||||
|
||||
token = token.WithExtra(map[string]interface{}{
|
||||
Web3AuthTokenKey: web3AuthToken,
|
||||
})
|
||||
return token, nil
|
||||
}
|
||||
|
||||
func (idp *Web3OnboardIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error) {
|
||||
web3AuthToken, ok := token.Extra(Web3AuthTokenKey).(Web3AuthToken)
|
||||
if !ok {
|
||||
return nil, errors.New("invalid web3AuthToken")
|
||||
}
|
||||
|
||||
fmtAddress := fmt.Sprintf("%v_%v",
|
||||
strings.ReplaceAll(strings.TrimSpace(web3AuthToken.WalletType), " ", "_"),
|
||||
web3AuthToken.Address,
|
||||
)
|
||||
userInfo := &UserInfo{
|
||||
Id: fmtAddress,
|
||||
Username: fmtAddress,
|
||||
DisplayName: fmtAddress,
|
||||
AvatarUrl: fmt.Sprintf("metamask:%v", forceEthereumAddress(web3AuthToken.Address)),
|
||||
}
|
||||
return userInfo, nil
|
||||
}
|
||||
|
||||
func forceEthereumAddress(address string) string {
|
||||
// The required address to general MetaMask avatar is a string of length 42 that represents an Ethereum address.
|
||||
// This function is used to force any address as an Ethereum address
|
||||
address = strings.TrimSpace(address)
|
||||
var builder strings.Builder
|
||||
for _, ch := range address {
|
||||
builder.WriteRune(ch)
|
||||
}
|
||||
for len(builder.String()) < 42 {
|
||||
builder.WriteString("0")
|
||||
}
|
||||
if len(builder.String()) > 42 {
|
||||
return builder.String()[:42]
|
||||
}
|
||||
return builder.String()
|
||||
}
|
@@ -9,11 +9,11 @@
|
||||
"passwordType": "plain",
|
||||
"passwordSalt": "",
|
||||
"passwordOptions": ["AtLeast6"],
|
||||
"countryCodes": ["US", "ES", "CN", "FR", "DE", "GB", "JP", "KR", "VN", "ID", "SG", "IN", "IT", "MY", "TR"],
|
||||
"countryCodes": ["US", "ES", "CN", "FR", "DE", "GB", "JP", "KR", "VN", "ID", "SG", "IN", "IT", "MY", "TR", "DZ", "IL", "PH"],
|
||||
"defaultAvatar": "",
|
||||
"defaultApplication": "",
|
||||
"tags": [],
|
||||
"languages": ["en", "zh", "es", "fr", "de", "id", "ja", "ko", "ru", "vi", "it", "ms", "tr"],
|
||||
"languages": ["en", "zh", "es", "fr", "de", "id", "ja", "ko", "ru", "vi", "it", "ms", "tr","ar", "he", "fi"],
|
||||
"masterPassword": "",
|
||||
"initScore": 2000,
|
||||
"enableSoftDeletion": false,
|
||||
|
140
object/get-dashboard.go
Normal file
140
object/get-dashboard.go
Normal file
@@ -0,0 +1,140 @@
|
||||
// Copyright 2021 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package object
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Dashboard struct {
|
||||
OrganizationCounts []int `json:"organizationCounts"`
|
||||
UserCounts []int `json:"userCounts"`
|
||||
ProviderCounts []int `json:"providerCounts"`
|
||||
ApplicationCounts []int `json:"applicationCounts"`
|
||||
SubscriptionCounts []int `json:"subscriptionCounts"`
|
||||
}
|
||||
|
||||
func GetDashboard() (*Dashboard, error) {
|
||||
dashboard := &Dashboard{
|
||||
OrganizationCounts: make([]int, 31),
|
||||
UserCounts: make([]int, 31),
|
||||
ProviderCounts: make([]int, 31),
|
||||
ApplicationCounts: make([]int, 31),
|
||||
SubscriptionCounts: make([]int, 31),
|
||||
}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
|
||||
organizations := []Organization{}
|
||||
users := []User{}
|
||||
providers := []Provider{}
|
||||
applications := []Application{}
|
||||
subscriptions := []Subscription{}
|
||||
|
||||
wg.Add(5)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
if err := ormer.Engine.Find(&organizations); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
|
||||
if err := ormer.Engine.Find(&users); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
|
||||
if err := ormer.Engine.Find(&providers); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
|
||||
if err := ormer.Engine.Find(&applications); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
|
||||
if err := ormer.Engine.Find(&subscriptions); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
wg.Wait()
|
||||
|
||||
nowTime := time.Now()
|
||||
for i := 30; i >= 0; i-- {
|
||||
cutTime := nowTime.AddDate(0, 0, -i)
|
||||
dashboard.OrganizationCounts[30-i] = countCreatedBefore(organizations, cutTime)
|
||||
dashboard.UserCounts[30-i] = countCreatedBefore(users, cutTime)
|
||||
dashboard.ProviderCounts[30-i] = countCreatedBefore(providers, cutTime)
|
||||
dashboard.ApplicationCounts[30-i] = countCreatedBefore(applications, cutTime)
|
||||
dashboard.SubscriptionCounts[30-i] = countCreatedBefore(subscriptions, cutTime)
|
||||
}
|
||||
return dashboard, nil
|
||||
}
|
||||
|
||||
func countCreatedBefore(objects interface{}, before time.Time) int {
|
||||
count := 0
|
||||
switch obj := objects.(type) {
|
||||
case []Organization:
|
||||
for _, o := range obj {
|
||||
createdTime, _ := time.Parse("2006-01-02T15:04:05-07:00", o.CreatedTime)
|
||||
if createdTime.Before(before) {
|
||||
count++
|
||||
}
|
||||
}
|
||||
case []User:
|
||||
for _, u := range obj {
|
||||
createdTime, _ := time.Parse("2006-01-02T15:04:05-07:00", u.CreatedTime)
|
||||
if createdTime.Before(before) {
|
||||
count++
|
||||
}
|
||||
}
|
||||
case []Provider:
|
||||
for _, p := range obj {
|
||||
createdTime, _ := time.Parse("2006-01-02T15:04:05-07:00", p.CreatedTime)
|
||||
if createdTime.Before(before) {
|
||||
count++
|
||||
}
|
||||
}
|
||||
case []Application:
|
||||
for _, a := range obj {
|
||||
createdTime, _ := time.Parse("2006-01-02T15:04:05-07:00", a.CreatedTime)
|
||||
if createdTime.Before(before) {
|
||||
count++
|
||||
}
|
||||
}
|
||||
case []Subscription:
|
||||
for _, s := range obj {
|
||||
createdTime, _ := time.Parse("2006-01-02T15:04:05-07:00", s.CreatedTime)
|
||||
if createdTime.Before(before) {
|
||||
count++
|
||||
}
|
||||
}
|
||||
}
|
||||
return count
|
||||
}
|
@@ -17,6 +17,7 @@ package object
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/beego/beego"
|
||||
"github.com/beego/beego/context"
|
||||
@@ -25,7 +26,10 @@ import (
|
||||
"github.com/pquerna/otp/totp"
|
||||
)
|
||||
|
||||
const MfaTotpSecretSession = "mfa_totp_secret"
|
||||
const (
|
||||
MfaTotpSecretSession = "mfa_totp_secret"
|
||||
MfaTotpPeriodInSeconds = 30
|
||||
)
|
||||
|
||||
type TotpMfa struct {
|
||||
Config *MfaProps
|
||||
@@ -76,7 +80,13 @@ func (mfa *TotpMfa) SetupVerify(ctx *context.Context, passcode string) error {
|
||||
if secret == nil {
|
||||
return errors.New("totp secret is missing")
|
||||
}
|
||||
result := totp.Validate(passcode, secret.(string))
|
||||
|
||||
result, _ := totp.ValidateCustom(passcode, secret.(string), time.Now().UTC(), totp.ValidateOpts{
|
||||
Period: MfaTotpPeriodInSeconds,
|
||||
Skew: 1,
|
||||
Digits: otp.DigitsSix,
|
||||
Algorithm: otp.AlgorithmSHA1,
|
||||
})
|
||||
|
||||
if result {
|
||||
return nil
|
||||
@@ -133,7 +143,7 @@ func NewTotpMfaUtil(config *MfaProps) *TotpMfa {
|
||||
|
||||
return &TotpMfa{
|
||||
Config: config,
|
||||
period: 30,
|
||||
period: MfaTotpPeriodInSeconds,
|
||||
secretSize: 20,
|
||||
digits: otp.DigitsSix,
|
||||
}
|
||||
|
@@ -309,8 +309,7 @@ func GetAllRoles(userId string) []string {
|
||||
|
||||
func GetBuiltInModel(modelText string) (model.Model, error) {
|
||||
if modelText == "" {
|
||||
modelText = `
|
||||
[request_definition]
|
||||
modelText = `[request_definition]
|
||||
r = sub, obj, act
|
||||
|
||||
[policy_definition]
|
||||
|
@@ -36,7 +36,7 @@ type Provider struct {
|
||||
Type string `xorm:"varchar(100)" json:"type"`
|
||||
SubType string `xorm:"varchar(100)" json:"subType"`
|
||||
Method string `xorm:"varchar(100)" json:"method"`
|
||||
ClientId string `xorm:"varchar(100)" json:"clientId"`
|
||||
ClientId string `xorm:"varchar(200)" json:"clientId"`
|
||||
ClientSecret string `xorm:"varchar(2000)" json:"clientSecret"`
|
||||
ClientId2 string `xorm:"varchar(100)" json:"clientId2"`
|
||||
ClientSecret2 string `xorm:"varchar(100)" json:"clientSecret2"`
|
||||
|
@@ -170,6 +170,7 @@ type User struct {
|
||||
Yandex string `xorm:"yandex varchar(100)" json:"yandex"`
|
||||
Zoom string `xorm:"zoom varchar(100)" json:"zoom"`
|
||||
MetaMask string `xorm:"metamask varchar(100)" json:"metamask"`
|
||||
Web3Onboard string `xorm:"web3onboard varchar(100)" json:"web3onboard"`
|
||||
Custom string `xorm:"custom varchar(100)" json:"custom"`
|
||||
|
||||
WebauthnCredentials []webauthn.Credential `xorm:"webauthnCredentials blob" json:"webauthnCredentials"`
|
||||
|
@@ -90,7 +90,7 @@ func (pp *AlipayPaymentProvider) Notify(request *http.Request, body []byte, auth
|
||||
ProductName: productName,
|
||||
ProductDisplayName: productDisplayName,
|
||||
ProviderName: providerName,
|
||||
OutOrderId: orderId,
|
||||
OrderId: orderId,
|
||||
PaymentStatus: PaymentStatePaid,
|
||||
Price: price,
|
||||
PaymentName: paymentName,
|
||||
|
2
pp/gc.go
2
pp/gc.go
@@ -255,7 +255,7 @@ func (pp *GcPaymentProvider) Notify(request *http.Request, body []byte, authorit
|
||||
ProductName: productName,
|
||||
ProductDisplayName: productDisplayName,
|
||||
ProviderName: providerName,
|
||||
OutOrderId: orderId,
|
||||
OrderId: orderId,
|
||||
Price: price,
|
||||
PaymentStatus: PaymentStatePaid,
|
||||
PaymentName: paymentName,
|
||||
|
12
pp/paypal.go
12
pp/paypal.go
@@ -52,13 +52,12 @@ func NewPaypalPaymentProvider(clientID string, secret string) (*PaypalPaymentPro
|
||||
|
||||
func (pp *PaypalPaymentProvider) Pay(providerName string, productName string, payerName string, paymentName string, productDisplayName string, price float64, currency string, returnUrl string, notifyUrl string) (string, string, error) {
|
||||
// https://github.com/go-pay/gopay/blob/main/doc/paypal.md
|
||||
priceStr := strconv.FormatFloat(price, 'f', 2, 64)
|
||||
units := make([]*paypal.PurchaseUnit, 0, 1)
|
||||
unit := &paypal.PurchaseUnit{
|
||||
ReferenceId: util.GetRandomString(16),
|
||||
Amount: &paypal.Amount{
|
||||
CurrencyCode: currency, // e.g."USD"
|
||||
Value: priceStr, // e.g."100.00"
|
||||
CurrencyCode: currency, // e.g."USD"
|
||||
Value: priceFloat64ToString(price), // e.g."100.00"
|
||||
},
|
||||
Description: joinAttachString([]string{productDisplayName, productName, providerName}),
|
||||
}
|
||||
@@ -147,16 +146,15 @@ func (pp *PaypalPaymentProvider) Notify(request *http.Request, body []byte, auth
|
||||
paymentStatus = PaymentStateError
|
||||
}
|
||||
notifyResult = &NotifyResult{
|
||||
PaymentStatus: paymentStatus,
|
||||
PaymentName: paymentName,
|
||||
|
||||
PaymentStatus: paymentStatus,
|
||||
PaymentName: paymentName,
|
||||
ProductName: productName,
|
||||
ProductDisplayName: productDisplayName,
|
||||
ProviderName: providerName,
|
||||
Price: price,
|
||||
Currency: currency,
|
||||
|
||||
OutOrderId: orderId,
|
||||
OrderId: orderId,
|
||||
}
|
||||
return notifyResult, nil
|
||||
}
|
||||
|
@@ -24,6 +24,7 @@ const (
|
||||
PaymentStatePaid PaymentState = "Paid"
|
||||
PaymentStateCreated PaymentState = "Created"
|
||||
PaymentStateCanceled PaymentState = "Canceled"
|
||||
PaymentStateTimeout PaymentState = "Timeout"
|
||||
PaymentStateError PaymentState = "Error"
|
||||
)
|
||||
|
||||
@@ -32,13 +33,13 @@ type NotifyResult struct {
|
||||
PaymentStatus PaymentState
|
||||
NotifyMessage string
|
||||
|
||||
ProviderName string
|
||||
ProductName string
|
||||
ProductDisplayName string
|
||||
ProviderName string
|
||||
Price float64
|
||||
Currency string
|
||||
|
||||
OutOrderId string
|
||||
OrderId string
|
||||
}
|
||||
|
||||
type PaymentProvider interface {
|
||||
@@ -75,6 +76,12 @@ func GetPaymentProvider(typ string, clientId string, clientSecret string, host s
|
||||
return nil, err
|
||||
}
|
||||
return pp, nil
|
||||
} else if typ == "Stripe" {
|
||||
pp, err := NewStripePaymentProvider(clientId, clientSecret)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return pp, nil
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
|
166
pp/stripe.go
Normal file
166
pp/stripe.go
Normal file
@@ -0,0 +1,166 @@
|
||||
// Copyright 2023 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.
|
||||
|
||||
package pp
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/casdoor/casdoor/conf"
|
||||
"github.com/stripe/stripe-go/v74"
|
||||
stripeCheckout "github.com/stripe/stripe-go/v74/checkout/session"
|
||||
stripeIntent "github.com/stripe/stripe-go/v74/paymentintent"
|
||||
stripePrice "github.com/stripe/stripe-go/v74/price"
|
||||
stripeProduct "github.com/stripe/stripe-go/v74/product"
|
||||
)
|
||||
|
||||
type StripePaymentProvider struct {
|
||||
PublishableKey string
|
||||
SecretKey string
|
||||
isProd bool
|
||||
}
|
||||
|
||||
func NewStripePaymentProvider(PublishableKey, SecretKey string) (*StripePaymentProvider, error) {
|
||||
isProd := false
|
||||
if conf.GetConfigString("runmode") == "prod" {
|
||||
isProd = true
|
||||
}
|
||||
pp := &StripePaymentProvider{
|
||||
PublishableKey: PublishableKey,
|
||||
SecretKey: SecretKey,
|
||||
isProd: isProd,
|
||||
}
|
||||
stripe.Key = pp.SecretKey
|
||||
return pp, nil
|
||||
}
|
||||
|
||||
func (pp *StripePaymentProvider) Pay(providerName string, productName string, payerName string, paymentName string, productDisplayName string, price float64, currency string, returnUrl string, notifyUrl string) (payUrl string, orderId string, err error) {
|
||||
// Create a temp product
|
||||
description := joinAttachString([]string{productName, productDisplayName, providerName})
|
||||
productParams := &stripe.ProductParams{
|
||||
Name: stripe.String(productDisplayName),
|
||||
Description: stripe.String(description),
|
||||
DefaultPriceData: &stripe.ProductDefaultPriceDataParams{
|
||||
UnitAmount: stripe.Int64(priceFloat64ToInt64(price)),
|
||||
Currency: stripe.String(currency),
|
||||
},
|
||||
}
|
||||
sProduct, err := stripeProduct.New(productParams)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
// Create a price for an existing product
|
||||
priceParams := &stripe.PriceParams{
|
||||
Currency: stripe.String(currency),
|
||||
UnitAmount: stripe.Int64(priceFloat64ToInt64(price)),
|
||||
Product: stripe.String(sProduct.ID),
|
||||
}
|
||||
sPrice, err := stripePrice.New(priceParams)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
// Create a Checkout Session
|
||||
checkoutParams := &stripe.CheckoutSessionParams{
|
||||
LineItems: []*stripe.CheckoutSessionLineItemParams{
|
||||
{
|
||||
Price: stripe.String(sPrice.ID),
|
||||
Quantity: stripe.Int64(1),
|
||||
},
|
||||
},
|
||||
Mode: stripe.String(string(stripe.CheckoutSessionModePayment)),
|
||||
SuccessURL: stripe.String(returnUrl),
|
||||
CancelURL: stripe.String(returnUrl),
|
||||
ClientReferenceID: stripe.String(paymentName),
|
||||
ExpiresAt: stripe.Int64(time.Now().Add(30 * time.Minute).Unix()),
|
||||
}
|
||||
checkoutParams.AddMetadata("product_description", description)
|
||||
sCheckout, err := stripeCheckout.New(checkoutParams)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
return sCheckout.URL, sCheckout.ID, nil
|
||||
}
|
||||
|
||||
func (pp *StripePaymentProvider) Notify(request *http.Request, body []byte, authorityPublicKey string, orderId string) (*NotifyResult, error) {
|
||||
notifyResult := &NotifyResult{}
|
||||
sCheckout, err := stripeCheckout.Get(orderId, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch sCheckout.Status {
|
||||
case "open":
|
||||
// The checkout session is still in progress. Payment processing has not started
|
||||
notifyResult.PaymentStatus = PaymentStateCreated
|
||||
return notifyResult, nil
|
||||
case "complete":
|
||||
// The checkout session is complete. Payment processing may still be in progress
|
||||
case "expired":
|
||||
// The checkout session has expired. No further processing will occur
|
||||
notifyResult.PaymentStatus = PaymentStateTimeout
|
||||
return notifyResult, nil
|
||||
default:
|
||||
notifyResult.PaymentStatus = PaymentStateError
|
||||
notifyResult.NotifyMessage = fmt.Sprintf("unexpected stripe checkout status: %v", sCheckout.Status)
|
||||
return notifyResult, nil
|
||||
}
|
||||
switch sCheckout.PaymentStatus {
|
||||
case "paid":
|
||||
// Skip
|
||||
case "unpaid":
|
||||
notifyResult.PaymentStatus = PaymentStateCreated
|
||||
return notifyResult, nil
|
||||
default:
|
||||
notifyResult.PaymentStatus = PaymentStateError
|
||||
notifyResult.NotifyMessage = fmt.Sprintf("unexpected stripe checkout payment status: %v", sCheckout.PaymentStatus)
|
||||
return notifyResult, nil
|
||||
}
|
||||
// Once payment is successful, the Checkout Session will contain a reference to the successful `PaymentIntent`
|
||||
sIntent, err := stripeIntent.Get(sCheckout.PaymentIntent.ID, nil)
|
||||
var (
|
||||
productName string
|
||||
productDisplayName string
|
||||
providerName string
|
||||
)
|
||||
if description, ok := sCheckout.Metadata["product_description"]; ok {
|
||||
productName, productDisplayName, providerName, _ = parseAttachString(description)
|
||||
}
|
||||
notifyResult = &NotifyResult{
|
||||
PaymentName: sCheckout.ClientReferenceID,
|
||||
PaymentStatus: PaymentStatePaid,
|
||||
|
||||
ProductName: productName,
|
||||
ProductDisplayName: productDisplayName,
|
||||
ProviderName: providerName,
|
||||
|
||||
Price: priceInt64ToFloat64(sIntent.Amount),
|
||||
Currency: string(sIntent.Currency),
|
||||
|
||||
OrderId: orderId,
|
||||
}
|
||||
return notifyResult, nil
|
||||
}
|
||||
|
||||
func (pp *StripePaymentProvider) GetInvoice(paymentName string, personName string, personIdCard string, personEmail string, personPhone string, invoiceType string, invoiceTitle string, invoiceTaxId string) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (pp *StripePaymentProvider) GetResponseError(err error) string {
|
||||
if err == nil {
|
||||
return "success"
|
||||
} else {
|
||||
return "fail"
|
||||
}
|
||||
}
|
14
pp/util.go
14
pp/util.go
@@ -16,6 +16,8 @@ package pp
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
@@ -35,3 +37,15 @@ func parseAttachString(s string) (string, string, string, error) {
|
||||
}
|
||||
return tokens[0], tokens[1], tokens[2], nil
|
||||
}
|
||||
|
||||
func priceInt64ToFloat64(price int64) float64 {
|
||||
return float64(price) / 100
|
||||
}
|
||||
|
||||
func priceFloat64ToInt64(price float64) int64 {
|
||||
return int64(math.Round(price * 100))
|
||||
}
|
||||
|
||||
func priceFloat64ToString(price float64) string {
|
||||
return strconv.FormatFloat(price, 'f', 2, 64)
|
||||
}
|
||||
|
@@ -113,7 +113,7 @@ func (pp *WechatPaymentProvider) Notify(request *http.Request, body []byte, auth
|
||||
ProductName: productName,
|
||||
ProductDisplayName: productDisplayName,
|
||||
ProviderName: providerName,
|
||||
OutOrderId: orderId,
|
||||
OrderId: orderId,
|
||||
Price: price,
|
||||
PaymentStatus: PaymentStatePaid,
|
||||
PaymentName: paymentName,
|
||||
|
@@ -51,6 +51,7 @@ func initAPI() {
|
||||
beego.Router("/api/signup", &controllers.ApiController{}, "POST:Signup")
|
||||
beego.Router("/api/login", &controllers.ApiController{}, "POST:Login")
|
||||
beego.Router("/api/get-app-login", &controllers.ApiController{}, "GET:GetApplicationLogin")
|
||||
beego.Router("/api/get-dashboard", &controllers.ApiController{}, "GET:GetDashboard")
|
||||
beego.Router("/api/logout", &controllers.ApiController{}, "GET,POST:Logout")
|
||||
beego.Router("/api/get-account", &controllers.ApiController{}, "GET:GetAccount")
|
||||
beego.Router("/api/userinfo", &controllers.ApiController{}, "GET:GetUserinfo")
|
||||
|
@@ -51,31 +51,46 @@ module.exports = {
|
||||
},
|
||||
],
|
||||
webpack: {
|
||||
// use polyfill Buffer with Webpack 5
|
||||
// https://viglucci.io/articles/how-to-polyfill-buffer-with-webpack-5
|
||||
// https://craco.js.org/docs/configuration/webpack/
|
||||
configure: (webpackConfig, { env, paths }) => {
|
||||
webpackConfig.resolve.fallback = {
|
||||
// "process": require.resolve('process/browser'),
|
||||
// "util": require.resolve("util/"),
|
||||
// "url": require.resolve("url/"),
|
||||
// "zlib": require.resolve("browserify-zlib"),
|
||||
// "stream": require.resolve("stream-browserify"),
|
||||
// "http": require.resolve("stream-http"),
|
||||
// "https": require.resolve("https-browserify"),
|
||||
// "assert": require.resolve("assert/"),
|
||||
"buffer": require.resolve('buffer/'),
|
||||
"process": false,
|
||||
"util": false,
|
||||
"url": false,
|
||||
"zlib": false,
|
||||
"stream": false,
|
||||
"http": false,
|
||||
"https": false,
|
||||
"assert": false,
|
||||
"buffer": false,
|
||||
};
|
||||
return webpackConfig;
|
||||
configure: {
|
||||
// ignore webpack warnings by source-map-loader
|
||||
// https://github.com/facebook/create-react-app/pull/11752#issuecomment-1345231546
|
||||
ignoreWarnings: [
|
||||
function ignoreSourcemapsloaderWarnings(warning) {
|
||||
return (
|
||||
warning.module &&
|
||||
warning.module.resource.includes('node_modules') &&
|
||||
warning.details &&
|
||||
warning.details.includes('source-map-loader')
|
||||
)
|
||||
},
|
||||
],
|
||||
// use polyfill Buffer with Webpack 5
|
||||
// https://viglucci.io/articles/how-to-polyfill-buffer-with-webpack-5
|
||||
// https://craco.js.org/docs/configuration/webpack/
|
||||
resolve: {
|
||||
fallback: {
|
||||
// "process": require.resolve('process/browser'),
|
||||
// "util": require.resolve("util/"),
|
||||
// "url": require.resolve("url/"),
|
||||
// "zlib": require.resolve("browserify-zlib"),
|
||||
// "stream": require.resolve("stream-browserify"),
|
||||
// "http": require.resolve("stream-http"),
|
||||
// "https": require.resolve("https-browserify"),
|
||||
// "assert": require.resolve("assert/"),
|
||||
"buffer": require.resolve('buffer/'),
|
||||
"process": false,
|
||||
"util": false,
|
||||
"url": false,
|
||||
"zlib": false,
|
||||
"stream": false,
|
||||
"http": false,
|
||||
"https": false,
|
||||
"assert": false,
|
||||
"buffer": false,
|
||||
"crypto": false,
|
||||
"os": false,
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
|
@@ -13,6 +13,16 @@
|
||||
"@testing-library/jest-dom": "^4.2.4",
|
||||
"@testing-library/react": "^9.3.2",
|
||||
"@testing-library/user-event": "^7.1.2",
|
||||
"@web3-onboard/coinbase": "^2.2.5",
|
||||
"@web3-onboard/core": "^2.20.5",
|
||||
"@web3-onboard/frontier": "^2.0.4",
|
||||
"@web3-onboard/gnosis": "^2.1.10",
|
||||
"@web3-onboard/infinity-wallet": "^2.0.4",
|
||||
"@web3-onboard/injected-wallets": "^2.10.4",
|
||||
"@web3-onboard/react": "^2.8.10",
|
||||
"@web3-onboard/sequence": "^2.0.8",
|
||||
"@web3-onboard/taho": "^2.0.5",
|
||||
"@web3-onboard/trust": "^2.0.4",
|
||||
"antd": "5.2.3",
|
||||
"antd-token-previewer": "^1.1.0-22",
|
||||
"buffer": "^6.0.3",
|
||||
@@ -20,7 +30,9 @@
|
||||
"copy-to-clipboard": "^3.3.1",
|
||||
"core-js": "^3.25.0",
|
||||
"craco-less": "^2.0.0",
|
||||
"echarts": "^5.4.3",
|
||||
"eslint-plugin-unused-imports": "^2.0.0",
|
||||
"ethers": "5.6.9",
|
||||
"file-saver": "^2.0.5",
|
||||
"i18n-iso-countries": "^7.0.0",
|
||||
"i18next": "^19.8.9",
|
||||
@@ -44,7 +56,7 @@
|
||||
},
|
||||
"scripts": {
|
||||
"start": "cross-env PORT=7001 craco start",
|
||||
"build": "craco build",
|
||||
"build": "craco --max_old_space_size=4096 build",
|
||||
"test": "craco test",
|
||||
"eject": "craco eject",
|
||||
"crowdin:sync": "crowdin upload && crowdin download",
|
||||
|
@@ -351,7 +351,7 @@ class App extends Component {
|
||||
}
|
||||
|
||||
|
||||
{Setting.isMobile() ? null : Setting.getNameAtLeast(this.state.account.displayName)} <DownOutlined />
|
||||
{Setting.isMobile() ? null : Setting.getShortText(Setting.getNameAtLeast(this.state.account.displayName), 30)} <DownOutlined />
|
||||
|
||||
|
||||
|
||||
|
@@ -169,7 +169,7 @@ class EnforcerEditPage extends React.Component {
|
||||
<Select virtual={false} disabled={Setting.builtInObject(this.state.enforcer)} style={{width: "100%"}} value={this.state.enforcer.model} onChange={(model => {
|
||||
this.updateEnforcerField("model", model);
|
||||
})}
|
||||
options={this.state.models.map((model) => Setting.getOption(model.displayName, `${model.owner}/${model.name}`))
|
||||
options={this.state.models.map((model) => Setting.getOption(`${model.owner}/${model.name}`, `${model.owner}/${model.name}`))
|
||||
} />
|
||||
</Col>
|
||||
</Row>
|
||||
@@ -181,7 +181,7 @@ class EnforcerEditPage extends React.Component {
|
||||
<Select virtual={false} disabled={Setting.builtInObject(this.state.enforcer)} style={{width: "100%"}} value={this.state.enforcer.adapter} onChange={(adapter => {
|
||||
this.updateEnforcerField("adapter", adapter);
|
||||
})}
|
||||
options={this.state.adapters.map((adapter) => Setting.getOption(adapter.name, `${adapter.owner}/${adapter.name}`))
|
||||
options={this.state.adapters.map((adapter) => Setting.getOption(`${adapter.owner}/${adapter.name}`, `${adapter.owner}/${adapter.name}`))
|
||||
} />
|
||||
</Col>
|
||||
</Row>
|
||||
|
@@ -75,7 +75,7 @@ class EnforcerListPage extends BaseListPage {
|
||||
title: i18next.t("general:Name"),
|
||||
dataIndex: "name",
|
||||
key: "name",
|
||||
width: "150px",
|
||||
width: "200px",
|
||||
fixed: "left",
|
||||
sorter: true,
|
||||
...this.getColumnSearchProps("name"),
|
||||
@@ -116,10 +116,42 @@ class EnforcerListPage extends BaseListPage {
|
||||
title: i18next.t("general:Display name"),
|
||||
dataIndex: "displayName",
|
||||
key: "displayName",
|
||||
width: "200px",
|
||||
// width: "200px",
|
||||
sorter: true,
|
||||
...this.getColumnSearchProps("displayName"),
|
||||
},
|
||||
{
|
||||
title: i18next.t("general:Model"),
|
||||
dataIndex: "model",
|
||||
key: "model",
|
||||
width: "250px",
|
||||
fixed: "left",
|
||||
sorter: true,
|
||||
...this.getColumnSearchProps("name"),
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<Link to={`/models/${text}`}>
|
||||
{text}
|
||||
</Link>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18next.t("general:Adapter"),
|
||||
dataIndex: "adapter",
|
||||
key: "adapter",
|
||||
width: "250px",
|
||||
fixed: "left",
|
||||
sorter: true,
|
||||
...this.getColumnSearchProps("name"),
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<Link to={`/adapters/${text}`}>
|
||||
{text}
|
||||
</Link>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: i18next.t("general:Is enabled"),
|
||||
dataIndex: "isEnabled",
|
||||
@@ -136,7 +168,7 @@ class EnforcerListPage extends BaseListPage {
|
||||
title: i18next.t("general:Action"),
|
||||
dataIndex: "",
|
||||
key: "op",
|
||||
width: "170px",
|
||||
width: "180px",
|
||||
fixed: (Setting.isMobile()) ? "false" : "right",
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
|
@@ -103,7 +103,7 @@ class GroupListPage extends BaseListPage {
|
||||
title: i18next.t("general:Name"),
|
||||
dataIndex: "name",
|
||||
key: "name",
|
||||
width: "120px",
|
||||
width: "150px",
|
||||
fixed: "left",
|
||||
sorter: true,
|
||||
...this.getColumnSearchProps("name"),
|
||||
@@ -119,7 +119,7 @@ class GroupListPage extends BaseListPage {
|
||||
title: i18next.t("general:Organization"),
|
||||
dataIndex: "owner",
|
||||
key: "owner",
|
||||
width: "120px",
|
||||
width: "140px",
|
||||
sorter: true,
|
||||
...this.getColumnSearchProps("owner"),
|
||||
render: (text, record, index) => {
|
||||
@@ -134,7 +134,7 @@ class GroupListPage extends BaseListPage {
|
||||
title: i18next.t("general:Created time"),
|
||||
dataIndex: "createdTime",
|
||||
key: "createdTime",
|
||||
width: "150px",
|
||||
width: "180px",
|
||||
sorter: true,
|
||||
render: (text, record, index) => {
|
||||
return Setting.getFormattedDate(text);
|
||||
@@ -144,7 +144,7 @@ class GroupListPage extends BaseListPage {
|
||||
title: i18next.t("general:Updated time"),
|
||||
dataIndex: "updatedTime",
|
||||
key: "updatedTime",
|
||||
width: "150px",
|
||||
width: "180px",
|
||||
sorter: true,
|
||||
render: (text, record, index) => {
|
||||
return Setting.getFormattedDate(text);
|
||||
@@ -154,7 +154,7 @@ class GroupListPage extends BaseListPage {
|
||||
title: i18next.t("general:Display name"),
|
||||
dataIndex: "displayName",
|
||||
key: "displayName",
|
||||
width: "100px",
|
||||
// width: "200px",
|
||||
sorter: true,
|
||||
...this.getColumnSearchProps("displayName"),
|
||||
},
|
||||
@@ -162,7 +162,7 @@ class GroupListPage extends BaseListPage {
|
||||
title: i18next.t("general:Type"),
|
||||
dataIndex: "type",
|
||||
key: "type",
|
||||
width: "110px",
|
||||
width: "140px",
|
||||
sorter: true,
|
||||
filterMultiple: false,
|
||||
filters: [
|
||||
@@ -177,7 +177,7 @@ class GroupListPage extends BaseListPage {
|
||||
title: i18next.t("group:Parent group"),
|
||||
dataIndex: "parentId",
|
||||
key: "parentId",
|
||||
width: "110px",
|
||||
width: "220px",
|
||||
sorter: true,
|
||||
...this.getColumnSearchProps("parentId"),
|
||||
render: (text, record, index) => {
|
||||
@@ -199,7 +199,7 @@ class GroupListPage extends BaseListPage {
|
||||
title: i18next.t("general:Action"),
|
||||
dataIndex: "",
|
||||
key: "op",
|
||||
width: "170px",
|
||||
width: "180px",
|
||||
fixed: (Setting.isMobile()) ? "false" : "right",
|
||||
render: (text, record, index) => {
|
||||
const haveChildren = this.state.groups.find((group) => group.parentId === record.id) !== undefined;
|
||||
|
@@ -182,7 +182,7 @@ class OrganizationListPage extends BaseListPage {
|
||||
title: i18next.t("organization:Website URL"),
|
||||
dataIndex: "websiteUrl",
|
||||
key: "websiteUrl",
|
||||
width: "300px",
|
||||
width: "200px",
|
||||
sorter: true,
|
||||
...this.getColumnSearchProps("websiteUrl"),
|
||||
render: (text, record, index) => {
|
||||
@@ -243,7 +243,7 @@ class OrganizationListPage extends BaseListPage {
|
||||
title: i18next.t("general:Action"),
|
||||
dataIndex: "",
|
||||
key: "op",
|
||||
width: "320px",
|
||||
width: "350px",
|
||||
fixed: (Setting.isMobile()) ? "false" : "right",
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
|
@@ -48,7 +48,7 @@ class PaymentResultPage extends React.Component {
|
||||
});
|
||||
// window.console.log("payment=", res.data);
|
||||
if (res.data.state === "Created") {
|
||||
if (res.data.type === "PayPal") {
|
||||
if (["PayPal", "Stripe"].includes(res.data.type)) {
|
||||
this.setState({
|
||||
timeout: setTimeout(() => {
|
||||
PaymentBackend.notifyPayment(this.state.organizationName, this.state.paymentName)
|
||||
@@ -135,6 +135,26 @@ class PaymentResultPage extends React.Component {
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
} else if (payment.state === "Timeout") {
|
||||
return (
|
||||
<div>
|
||||
{
|
||||
Setting.renderHelmet(payment)
|
||||
}
|
||||
<Result
|
||||
status="warning"
|
||||
title={`${i18next.t("payment:The payment has time out")}: ${payment.productDisplayName}, ${i18next.t("payment:the current state is")}: ${payment.state}`}
|
||||
subTitle={i18next.t("payment:Please click the below button to return to the original website")}
|
||||
extra={[
|
||||
<Button type="primary" key="returnUrl" onClick={() => {
|
||||
this.goToPaymentUrl(payment);
|
||||
}}>
|
||||
{i18next.t("payment:Return to Website")}
|
||||
</Button>,
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<div>
|
||||
|
@@ -163,6 +163,8 @@ class ProductBuyPage extends React.Component {
|
||||
text = i18next.t("product:WeChat Pay");
|
||||
} else if (provider.type === "PayPal") {
|
||||
text = i18next.t("product:PayPal");
|
||||
} else if (provider.type === "Stripe") {
|
||||
text = i18next.t("product:Stripe");
|
||||
}
|
||||
|
||||
return (
|
||||
|
@@ -13,7 +13,7 @@
|
||||
// limitations under the License.
|
||||
|
||||
import React from "react";
|
||||
import {Button, Card, Col, Input, InputNumber, Row, Select, Switch} from "antd";
|
||||
import {Button, Card, Checkbox, Col, Input, InputNumber, Row, Select, Switch} from "antd";
|
||||
import {LinkOutlined} from "@ant-design/icons";
|
||||
import * as ProviderBackend from "./backend/ProviderBackend";
|
||||
import * as Setting from "./Setting";
|
||||
@@ -25,6 +25,7 @@ import copy from "copy-to-clipboard";
|
||||
import {CaptchaPreview} from "./common/CaptchaPreview";
|
||||
import * as OrganizationBackend from "./backend/OrganizationBackend";
|
||||
import {CountryCodeSelect} from "./common/select/CountryCodeSelect";
|
||||
import * as Web3Auth from "./auth/Web3Auth";
|
||||
|
||||
const {Option} = Select;
|
||||
const {TextArea} = Input;
|
||||
@@ -1011,6 +1012,30 @@ class ProviderEditPage extends React.Component {
|
||||
</Row>
|
||||
) : null
|
||||
}
|
||||
{
|
||||
this.state.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={() => {
|
||||
try {
|
||||
return JSON.parse(this.state.provider.metadata);
|
||||
} catch {
|
||||
return ["injected"];
|
||||
}
|
||||
}}
|
||||
onChange={options => {
|
||||
this.updateProviderField("metadata", JSON.stringify(options));
|
||||
}}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
) : null
|
||||
}
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("provider:Provider URL"), i18next.t("provider:Provider URL - Tooltip"))} :
|
||||
|
@@ -46,6 +46,9 @@ export const Countries = [{label: "English", key: "en", country: "US", alt: "Eng
|
||||
{label: "Itariano", key: "it", country: "IT", alt: "Itariano"},
|
||||
{label: "Marley", key: "ms", country: "MY", alt: "Marley"},
|
||||
{label: "Tkiš", key: "tr", country: "TR", alt: "Tkiš"},
|
||||
{label: "لغة عربية", key: "ar", country: "DZ", alt: "لغة عربية"},
|
||||
{label: "עִבְרִית", key: "he", country: "IL", alt: "עִבְרִית"},
|
||||
{label: "Filipino", key: "fi", country: "PH", alt: "Filipino"},
|
||||
];
|
||||
|
||||
export function getThemeData(organization, application) {
|
||||
@@ -217,6 +220,10 @@ export const OtherProviderInfo = {
|
||||
logo: `${StaticBaseUrl}/img/payment_paypal.png`,
|
||||
url: "https://www.paypal.com/",
|
||||
},
|
||||
"Stripe": {
|
||||
logo: `${StaticBaseUrl}/img/social_stripe.png`,
|
||||
url: "https://stripe.com/",
|
||||
},
|
||||
"GC": {
|
||||
logo: `${StaticBaseUrl}/img/payment_gc.png`,
|
||||
url: "https://gc.org",
|
||||
@@ -259,6 +266,10 @@ export const OtherProviderInfo = {
|
||||
logo: `${StaticBaseUrl}/img/social_metamask.svg`,
|
||||
url: "https://metamask.io/",
|
||||
},
|
||||
"Web3Onboard": {
|
||||
logo: `${StaticBaseUrl}/img/social_web3onboard.svg`,
|
||||
url: "https://onboard.blocknative.com/",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -929,6 +940,7 @@ export function getProviderTypeOptions(category) {
|
||||
{id: "Alipay", name: "Alipay"},
|
||||
{id: "WeChat Pay", name: "WeChat Pay"},
|
||||
{id: "PayPal", name: "PayPal"},
|
||||
{id: "Stripe", name: "Stripe"},
|
||||
{id: "GC", name: "GC"},
|
||||
]);
|
||||
} else if (category === "Captcha") {
|
||||
@@ -943,6 +955,7 @@ export function getProviderTypeOptions(category) {
|
||||
} else if (category === "Web3") {
|
||||
return ([
|
||||
{id: "MetaMask", name: "MetaMask"},
|
||||
{id: "Web3Onboard", name: "Web3-Onboard"},
|
||||
]);
|
||||
} else {
|
||||
return [];
|
||||
|
@@ -15,9 +15,11 @@
|
||||
import React from "react";
|
||||
import {Button, Card, Col, Input, InputNumber, List, Result, Row, Select, Space, Spin, Switch, Tag} from "antd";
|
||||
import {withRouter} from "react-router-dom";
|
||||
import {TotpMfaType} from "./auth/MfaSetupPage";
|
||||
import * as GroupBackend from "./backend/GroupBackend";
|
||||
import * as UserBackend from "./backend/UserBackend";
|
||||
import * as OrganizationBackend from "./backend/OrganizationBackend";
|
||||
import EnableMfaModal from "./common/modal/EnableMfaModal";
|
||||
import * as Setting from "./Setting";
|
||||
import i18next from "i18next";
|
||||
import CropperDivModal from "./common/modal/CropperDivModal.js";
|
||||
@@ -138,6 +140,10 @@ class UserEditPage extends React.Component {
|
||||
}
|
||||
|
||||
getUserOrganization() {
|
||||
if (this.state.user === null || this.state.organizations.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return this.state.organizations.filter(organization => organization.name === this.state.user.owner)[0];
|
||||
}
|
||||
|
||||
@@ -206,23 +212,6 @@ class UserEditPage extends React.Component {
|
||||
return this.props.account.countryCode;
|
||||
}
|
||||
|
||||
loadMore = (table, type) => {
|
||||
return <div
|
||||
style={{
|
||||
textAlign: "center",
|
||||
marginTop: 12,
|
||||
height: 32,
|
||||
lineHeight: "32px",
|
||||
}}
|
||||
>
|
||||
<Button onClick={() => {
|
||||
this.setState({
|
||||
multiFactorAuths: Setting.addRow(table, {"type": type}),
|
||||
});
|
||||
}}>{i18next.t("general:Add")}</Button>
|
||||
</div>;
|
||||
};
|
||||
|
||||
deleteMfa = () => {
|
||||
this.setState({
|
||||
RemoveMfaLoading: true,
|
||||
@@ -570,7 +559,7 @@ class UserEditPage extends React.Component {
|
||||
{name: "ID card back", value: "idCardBack"},
|
||||
{name: "ID card with person", value: "idCardWithPerson"},
|
||||
].map((entry) => {
|
||||
return this.renderImage(this.state.user.properties[entry.value] || "", this.getIdCardType(entry.name), this.getIdCardText(entry.name), entry.value, disabled);
|
||||
return this.renderImage(this.state.user.properties === null ? "" : (this.state.user.properties[entry.value] || ""), this.getIdCardType(entry.name), this.getIdCardText(entry.name), entry.value, disabled);
|
||||
})
|
||||
}
|
||||
</Row>
|
||||
@@ -947,11 +936,18 @@ class UserEditPage extends React.Component {
|
||||
</Button>
|
||||
}
|
||||
</Space>
|
||||
) : <Button type={"default"} onClick={() => {
|
||||
this.props.history.push(`/mfa/setup?mfaType=${item.mfaType}`);
|
||||
}}>
|
||||
{i18next.t("mfa:Setup")}
|
||||
</Button>}
|
||||
) :
|
||||
<Space>
|
||||
{item.mfaType !== TotpMfaType && Setting.isAdminUser(this.props.account) && window.location.href.indexOf("/users") !== -1 ?
|
||||
<EnableMfaModal user={this.state.user} mfaType={item.mfaType} onSuccess={() => {
|
||||
this.getUser();
|
||||
}} /> : null}
|
||||
<Button type={"default"} onClick={() => {
|
||||
this.props.history.push(`/mfa/setup?mfaType=${item.mfaType}`);
|
||||
}}>
|
||||
{i18next.t("mfa:Setup")}
|
||||
</Button>
|
||||
</Space>}
|
||||
</List.Item>
|
||||
)}
|
||||
/>
|
||||
@@ -995,11 +991,13 @@ class UserEditPage extends React.Component {
|
||||
<Col span={4} style={{textAlign: "center", margin: "auto"}} key={tag}>
|
||||
{
|
||||
imgUrl ?
|
||||
<a target="_blank" rel="noreferrer" href={imgUrl} style={{marginBottom: "10px"}}>
|
||||
<AccountAvatar src={imgUrl} alt={imgUrl} size={90} style={{marginBottom: "20px"}} />
|
||||
</a>
|
||||
<div style={{marginBottom: "10px"}}>
|
||||
<a target="_blank" rel="noreferrer" href={imgUrl} style={{marginBottom: "10px"}}>
|
||||
<AccountAvatar src={imgUrl} alt={imgUrl} height={150} />
|
||||
</a>
|
||||
</div>
|
||||
:
|
||||
<Col style={{height: "78%", border: "1px dotted grey", borderRadius: 3, marginBottom: 5}}>
|
||||
<Col style={{height: "78%", border: "1px dotted grey", borderRadius: 3, marginBottom: "10px"}}>
|
||||
<div style={{fontSize: 30, margin: 10}}>+</div>
|
||||
<div style={{verticalAlign: "middle", marginBottom: 10}}>{`Upload ${title}...`}</div>
|
||||
</Col>
|
||||
|
@@ -17,7 +17,7 @@ import {MetaMaskAvatar} from "react-metamask-avatar";
|
||||
|
||||
class AccountAvatar extends React.Component {
|
||||
render() {
|
||||
const {src, size} = this.props;
|
||||
const {src, size, width, height} = this.props;
|
||||
// The avatar for Metamask account is directly generated by an algorithm based on the address
|
||||
// src = "metamask:0xC304b2cC0Be8E9ce10fF3Afd34820Ed306A23600";
|
||||
const matchMetaMask = src.match(/^metamask:(\w+)$/);
|
||||
@@ -27,9 +27,19 @@ class AccountAvatar extends React.Component {
|
||||
<MetaMaskAvatar address={address} size={size} />
|
||||
);
|
||||
}
|
||||
return (
|
||||
<img width={size} height={size} src={src} />
|
||||
);
|
||||
if (size !== undefined) {
|
||||
return (
|
||||
<img width={size} height={size} src={src} />
|
||||
);
|
||||
} else if (width === undefined) {
|
||||
return (
|
||||
<img height={height} src={src} />
|
||||
);
|
||||
} else if (height === undefined) {
|
||||
return (
|
||||
<img width={width} src={src} />
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -95,7 +95,7 @@ class AuthCallback extends React.Component {
|
||||
if (code === null) {
|
||||
code = params.get("authCode");
|
||||
}
|
||||
// The code for Metamask is the JSON-serialized string of Web3AuthToken
|
||||
// The code for Web3 is the JSON-serialized string of Web3AuthToken
|
||||
// Due to the limited length of URLs, we only pass the web3AuthTokenKey
|
||||
if (code === null) {
|
||||
code = params.get("web3AuthTokenKey");
|
||||
|
@@ -321,6 +321,10 @@ const authInfo = {
|
||||
scope: "",
|
||||
endpoint: "",
|
||||
},
|
||||
Web3Onboard: {
|
||||
scope: "",
|
||||
endpoint: "",
|
||||
},
|
||||
};
|
||||
|
||||
export function getProviderUrl(provider) {
|
||||
@@ -465,5 +469,7 @@ export function getAuthUrl(application, provider, method) {
|
||||
return `${endpoint}?client_id=${provider.clientId}&redirect_uri=${redirectUri}&state=${state}&response_type=code&scope=${scope}&code_challenge=${codeChallenge}&code_challenge_method=S256`;
|
||||
} else if (provider.type === "MetaMask") {
|
||||
return `${redirectUri}?state=${state}`;
|
||||
} else if (provider.type === "Web3Onboard") {
|
||||
return `${redirectUri}?state=${state}`;
|
||||
}
|
||||
}
|
||||
|
@@ -17,7 +17,7 @@ import i18next from "i18next";
|
||||
import * as Provider from "./Provider";
|
||||
import {getProviderLogoURL} from "../Setting";
|
||||
import {GithubLoginButton, GoogleLoginButton} from "react-social-login-buttons";
|
||||
import {authViaMetaMask} from "./Web3Auth";
|
||||
import {authViaMetaMask, authViaWeb3Onboard} from "./Web3Auth";
|
||||
import QqLoginButton from "./QqLoginButton";
|
||||
import FacebookLoginButton from "./FacebookLoginButton";
|
||||
import WeiboLoginButton from "./WeiboLoginButton";
|
||||
@@ -121,6 +121,8 @@ function goToSamlUrl(provider, location) {
|
||||
export function goToWeb3Url(application, provider, method) {
|
||||
if (provider.type === "MetaMask") {
|
||||
authViaMetaMask(application, provider, method);
|
||||
} else if (provider.type === "Web3Onboard") {
|
||||
authViaWeb3Onboard(application, provider, method);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -18,7 +18,25 @@ import {v4 as uuidv4} from "uuid";
|
||||
import {SignTypedDataVersion, recoverTypedSignature} from "@metamask/eth-sig-util";
|
||||
import {getAuthUrl} from "./Provider";
|
||||
import {Buffer} from "buffer";
|
||||
// import {toChecksumAddress} from "ethereumjs-util";
|
||||
import Onboard from "@web3-onboard/core";
|
||||
import injectedModule from "@web3-onboard/injected-wallets";
|
||||
import infinityWalletModule from "@web3-onboard/infinity-wallet";
|
||||
import sequenceModule from "@web3-onboard/sequence";
|
||||
import trustModule from "@web3-onboard/trust";
|
||||
import frontierModule from "@web3-onboard/frontier";
|
||||
import tahoModule from "@web3-onboard/taho";
|
||||
import coinbaseModule from "@web3-onboard/coinbase";
|
||||
import gnosisModule from "@web3-onboard/gnosis";
|
||||
// import keystoneModule from "@web3-onboard/keystone";
|
||||
// import keepkeyModule from "@web3-onboard/keepkey";
|
||||
// import dcentModule from "@web3-onboard/dcent";
|
||||
// import ledgerModule from "@web3-onboard/ledger";
|
||||
// import trezorModule from "@web3-onboard/trezor";
|
||||
// import walletConnectModule from "@web3-onboard/walletconnect";
|
||||
// import fortmaticModule from "@web3-onboard/fortmatic";
|
||||
// import portisModule from "@web3-onboard/portis";
|
||||
// import magicModule from "@web3-onboard/magic";
|
||||
|
||||
global.Buffer = Buffer;
|
||||
|
||||
export function generateNonce() {
|
||||
@@ -147,3 +165,174 @@ export async function authViaMetaMask(application, provider, method) {
|
||||
showMessage("error", `${i18next.t("login:Failed to obtain MetaMask authorization")}: ${err.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
const web3Wallets = {
|
||||
// injected wallets
|
||||
injected: {
|
||||
label: "Injected",
|
||||
wallet: injectedModule(),
|
||||
},
|
||||
// sdk wallets
|
||||
coinbase: {
|
||||
label: "Coinbase",
|
||||
wallet: coinbaseModule(),
|
||||
},
|
||||
trust: {
|
||||
label: "Trust",
|
||||
wallet: trustModule(),
|
||||
},
|
||||
gnosis: {
|
||||
label: "Gnosis",
|
||||
wallet: gnosisModule(),
|
||||
},
|
||||
sequence: {
|
||||
label: "Sequence",
|
||||
wallet: sequenceModule(),
|
||||
},
|
||||
taho: {
|
||||
label: "Taho",
|
||||
wallet: tahoModule(),
|
||||
},
|
||||
frontier: {
|
||||
label: "Frontier",
|
||||
wallet: frontierModule(),
|
||||
},
|
||||
infinityWallet: {
|
||||
label: "Infinity Wallet",
|
||||
wallet: infinityWalletModule(),
|
||||
},
|
||||
// hardware wallets
|
||||
// keystone: {
|
||||
// label: "Keystone",
|
||||
// wallet: keystoneModule(),
|
||||
// },
|
||||
// keepkey: {
|
||||
// label: "KeepKey",
|
||||
// wallet: keepkeyModule(),
|
||||
// },
|
||||
// dcent: {
|
||||
// label: "D'CENT",
|
||||
// wallet: dcentModule(),
|
||||
// },
|
||||
|
||||
// some wallet need custome `apiKey` or `projectId` configure item
|
||||
// const magic = magicModule({
|
||||
// apiKey: "magicApiKey",
|
||||
// });
|
||||
// const fortmatic = fortmaticModule({
|
||||
// apiKey: "fortmaticApiKey",
|
||||
// });
|
||||
// const portis = portisModule({
|
||||
// apiKey: "portisApiKey",
|
||||
// });
|
||||
// const ledger = ledgerModule({
|
||||
// projectId: "ledgerProjectId"
|
||||
// });
|
||||
// const walletConnect = walletConnectModule({
|
||||
// projectId: "walletConnectProjectId",
|
||||
// });
|
||||
};
|
||||
|
||||
export function getWeb3OnboardWalletsOptions() {
|
||||
return Object.entries(web3Wallets).map(([key, value]) => ({
|
||||
label: value.label,
|
||||
value: key,
|
||||
}));
|
||||
}
|
||||
|
||||
function getWeb3OnboardWallets(options) {
|
||||
if (options === null || options === undefined || !Array.isArray(options)) {
|
||||
return [];
|
||||
}
|
||||
return options.map(walletType => {
|
||||
if (walletType && web3Wallets[walletType]?.wallet) {
|
||||
return web3Wallets[walletType]?.wallet;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function initWeb3Onboard(application, provider) {
|
||||
// init wallet
|
||||
// options = ["injected","coinbase",...]
|
||||
const options = JSON.parse(provider.metadata);
|
||||
const wallets = getWeb3OnboardWallets(options);
|
||||
|
||||
// init chain
|
||||
// const InfuraKey = "2fa45cbe531e4e65be4fcbf408e651a8";
|
||||
const chains = [
|
||||
// {
|
||||
// id: "0x1",
|
||||
// token: "ETH",
|
||||
// label: "Ethereum Mainnet",
|
||||
// rpcUrl: `https://mainnet.infura.io/v3/${InfuraKey}`,
|
||||
// },
|
||||
// {
|
||||
// id: "0x5",
|
||||
// token: "ETH",
|
||||
// label: "Goerli",
|
||||
// rpcUrl: `https://goerli.infura.io/v3/${InfuraKey}`,
|
||||
// },
|
||||
{
|
||||
id: "0x13881",
|
||||
token: "MATIC",
|
||||
label: "Polygon - Mumbai",
|
||||
rpcUrl: "https://matic-mumbai.chainstacklabs.com",
|
||||
},
|
||||
{
|
||||
id: "0x38",
|
||||
token: "BNB",
|
||||
label: "Binance",
|
||||
rpcUrl: "https://bsc-dataseed.binance.org/",
|
||||
},
|
||||
{
|
||||
id: "0xA",
|
||||
token: "OETH",
|
||||
label: "Optimism",
|
||||
rpcUrl: "https://mainnet.optimism.io",
|
||||
},
|
||||
{
|
||||
id: "0xA4B1",
|
||||
token: "ARB-ETH",
|
||||
label: "Arbitrum",
|
||||
rpcUrl: "https://rpc.ankr.com/arbitrum",
|
||||
},
|
||||
];
|
||||
|
||||
const appMetadata = {
|
||||
name: "Casdoor",
|
||||
description: "Connect a wallet using Casdoor",
|
||||
recommendedInjectedWallets: [
|
||||
{name: "MetaMask", url: "https://metamask.io"},
|
||||
{name: "Coinbase", url: "https://wallet.coinbase.com/"},
|
||||
],
|
||||
};
|
||||
|
||||
const web3Onboard = Onboard({
|
||||
wallets,
|
||||
chains,
|
||||
appMetadata,
|
||||
});
|
||||
return web3Onboard;
|
||||
}
|
||||
|
||||
export async function authViaWeb3Onboard(application, provider, method) {
|
||||
try {
|
||||
const onboard = initWeb3Onboard(application, provider);
|
||||
const connectedWallets = await onboard.connectWallet();
|
||||
if (connectedWallets.length > 0) {
|
||||
const wallet = connectedWallets[0];
|
||||
const account = wallet.accounts[0];
|
||||
const address = account.address;
|
||||
const token = {
|
||||
address: address, // e.g."0xbd5444d31fe4139ee36bea29e43d4ac67ae276de"
|
||||
walletType: wallet.label, // e.g."MetaMask"
|
||||
createAt: Math.floor(new Date().getTime() / 1000),
|
||||
};
|
||||
setWeb3AuthToken(token);
|
||||
const redirectUri = `${getAuthUrl(application, provider, method)}&web3AuthTokenKey=${getWeb3AuthTokenKey(address)}`;
|
||||
goToLink(redirectUri);
|
||||
}
|
||||
} catch (err) {
|
||||
showMessage("error", `${i18next.t("login:Failed to obtain Web3-Onboard authorization")}: ${err}`);
|
||||
}
|
||||
}
|
||||
|
25
web/src/backend/DashboardBackend.js
Normal file
25
web/src/backend/DashboardBackend.js
Normal file
@@ -0,0 +1,25 @@
|
||||
// Copyright 2023 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 * as Setting from "../Setting";
|
||||
|
||||
export function getDashboard(owner, name) {
|
||||
return fetch(`${Setting.ServerUrl}/api/get-dashboard`, {
|
||||
method: "GET",
|
||||
credentials: "include",
|
||||
headers: {
|
||||
"Accept-Language": Setting.getAcceptLanguage(),
|
||||
},
|
||||
}).then(res => res.json());
|
||||
}
|
@@ -13,8 +13,11 @@
|
||||
// limitations under the License.
|
||||
|
||||
import React from "react";
|
||||
import {Card, Col, Row} from "antd";
|
||||
import {Card, Col, Row, Spin, Statistic} from "antd";
|
||||
import {ArrowUpOutlined} from "@ant-design/icons";
|
||||
import * as ApplicationBackend from "../backend/ApplicationBackend";
|
||||
import * as DashboardBackend from "../backend/DashboardBackend";
|
||||
import * as echarts from "echarts";
|
||||
import * as Setting from "../Setting";
|
||||
import SingleCard from "./SingleCard";
|
||||
import i18next from "i18next";
|
||||
@@ -25,11 +28,13 @@ class HomePage extends React.Component {
|
||||
this.state = {
|
||||
classes: props,
|
||||
applications: null,
|
||||
dashboardData: null,
|
||||
};
|
||||
}
|
||||
|
||||
UNSAFE_componentWillMount() {
|
||||
this.getApplicationsByOrganization(this.props.account.owner);
|
||||
this.getDashboard();
|
||||
}
|
||||
|
||||
getApplicationsByOrganization(organizationName) {
|
||||
@@ -41,6 +46,21 @@ class HomePage extends React.Component {
|
||||
});
|
||||
}
|
||||
|
||||
getDashboard() {
|
||||
DashboardBackend.getDashboard()
|
||||
.then((res) => {
|
||||
if (res.status === "ok") {
|
||||
this.setState({
|
||||
dashboardData: res.data,
|
||||
}, () => {
|
||||
this.renderEChart();
|
||||
});
|
||||
} else {
|
||||
Setting.showMessage("error", res.msg);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
getItems() {
|
||||
let items = [];
|
||||
if (Setting.isAdminUser(this.props.account)) {
|
||||
@@ -75,9 +95,53 @@ class HomePage extends React.Component {
|
||||
return items;
|
||||
}
|
||||
|
||||
renderEChart() {
|
||||
const data = this.state.dashboardData;
|
||||
|
||||
const chartDom = document.getElementById("echarts-chart");
|
||||
const myChart = echarts.init(chartDom);
|
||||
const currentDate = new Date();
|
||||
const dateArray = [];
|
||||
for (let i = 30; i >= 0; i--) {
|
||||
const date = new Date(currentDate);
|
||||
date.setDate(date.getDate() - i);
|
||||
const month = parseInt(date.getMonth()) + 1;
|
||||
const day = parseInt(date.getDate());
|
||||
const formattedDate = `${month}-${day}`;
|
||||
dateArray.push(formattedDate);
|
||||
}
|
||||
const option = {
|
||||
title: {text: i18next.t("home:Past 30 Days")},
|
||||
tooltip: {trigger: "axis"},
|
||||
legend: {data: [
|
||||
i18next.t("general:Users"),
|
||||
i18next.t("general:Providers"),
|
||||
i18next.t("general:Applications"),
|
||||
i18next.t("general:Organizations"),
|
||||
i18next.t("general:Subscriptions"),
|
||||
]},
|
||||
grid: {left: "3%", right: "4%", bottom: "3%", containLabel: true},
|
||||
xAxis: {type: "category", boundaryGap: false, data: dateArray},
|
||||
yAxis: {type: "value"},
|
||||
series: [
|
||||
{name: i18next.t("general:Organizations"), type: "line", data: data?.organizationCounts},
|
||||
{name: i18next.t("general:Users"), type: "line", data: data?.userCounts},
|
||||
{name: i18next.t("general:Providers"), type: "line", data: data?.providerCounts},
|
||||
{name: i18next.t("general:Applications"), type: "line", data: data?.applicationCounts},
|
||||
{name: i18next.t("general:Subscriptions"), type: "line", data: data?.subscriptionCounts},
|
||||
],
|
||||
};
|
||||
myChart.setOption(option);
|
||||
}
|
||||
|
||||
renderCards() {
|
||||
if (this.state.applications === null) {
|
||||
return null;
|
||||
const data = this.state.dashboardData;
|
||||
if (data === null) {
|
||||
return (
|
||||
<div style={{display: "flex", justifyContent: "center", alignItems: "center", marginTop: "10%"}}>
|
||||
<Spin size="large" tip={i18next.t("login:Loading")} style={{paddingTop: "10%"}} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const items = this.getItems();
|
||||
@@ -96,24 +160,35 @@ class HomePage extends React.Component {
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<div style={{marginRight: "15px", marginLeft: "15px"}}>
|
||||
<Row style={{marginLeft: "-20px", marginRight: "-20px", marginTop: "20px"}} gutter={24}>
|
||||
{
|
||||
items.map(item => {
|
||||
return (
|
||||
<SingleCard logo={item.logo} link={item.link} title={item.name} desc={item.organizer} time={item.createdTime} isSingle={items.length === 1} key={item.name} />
|
||||
);
|
||||
})
|
||||
}
|
||||
</Row>
|
||||
</div>
|
||||
<Row gutter={80}>
|
||||
<Col span={50}>
|
||||
<Card bordered={false} bodyStyle={{width: "100%", height: "150px", display: "flex", alignItems: "center", justifyContent: "center"}}>
|
||||
<Statistic title={i18next.t("home:Total users")} fontSize="100px" value={data?.userCounts[30]} valueStyle={{fontSize: "30px"}} style={{width: "200px", paddingLeft: "10px"}} />
|
||||
</Card>
|
||||
</Col>
|
||||
<Col span={50}>
|
||||
<Card bordered={false} bodyStyle={{width: "100%", height: "150px", display: "flex", alignItems: "center", justifyContent: "center"}}>
|
||||
<Statistic title={i18next.t("home:New users today")} fontSize="100px" value={data?.userCounts[30] - data?.userCounts[30 - 1]} valueStyle={{fontSize: "30px"}} prefix={<ArrowUpOutlined />} style={{width: "200px", paddingLeft: "10px"}} />
|
||||
</Card>
|
||||
</Col>
|
||||
<Col span={50}>
|
||||
<Card bordered={false} bodyStyle={{width: "100%", height: "150px", display: "flex", alignItems: "center", justifyContent: "center"}}>
|
||||
<Statistic title={i18next.t("home:New users past 7 days")} value={data?.userCounts[30] - data?.userCounts[30 - 7]} valueStyle={{fontSize: "30px"}} prefix={<ArrowUpOutlined />} style={{width: "200px", paddingLeft: "10px"}} />
|
||||
</Card>
|
||||
</Col>
|
||||
<Col span={50}>
|
||||
<Card bordered={false} bodyStyle={{width: "100%", height: "150px", display: "flex", alignItems: "center", justifyContent: "center"}}>
|
||||
<Statistic title={i18next.t("home:New users past 30 days")} value={data?.userCounts[30] - data?.userCounts[30 - 30]} valueStyle={{fontSize: "30px"}} prefix={<ArrowUpOutlined />} style={{width: "200px", paddingLeft: "10px"}} />
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<div style={{display: "flex", justifyContent: "center", flexDirection: "column", alignItems: "center"}}>
|
||||
<Row style={{width: "100%"}}>
|
||||
<Col span={24} style={{display: "flex", justifyContent: "center"}} >
|
||||
{
|
||||
@@ -121,6 +196,8 @@ class HomePage extends React.Component {
|
||||
}
|
||||
</Col>
|
||||
</Row>
|
||||
<div id="echarts-chart"
|
||||
style={{width: "80%", height: "400px", textAlign: "center", marginTop: "20px"}}></div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@@ -97,7 +97,7 @@ class OAuthWidget extends React.Component {
|
||||
// should add the unlink user's info, cause the user may not be logged in, but a admin want to unlink the user.
|
||||
user: this.props.user,
|
||||
};
|
||||
if (providerType === "MetaMask") {
|
||||
if (providerType === "MetaMask" || providerType === "Web3Onboard") {
|
||||
delWeb3AuthToken(linkedValue);
|
||||
}
|
||||
AuthBackend.unlink(body)
|
||||
@@ -158,7 +158,12 @@ class OAuthWidget extends React.Component {
|
||||
</Col>
|
||||
<Col span={24 - this.props.labelSpan} >
|
||||
<AccountAvatar style={{marginRight: "10px"}} size={30} src={avatarUrl} alt={name} referrerPolicy="no-referrer" />
|
||||
<span style={{width: this.props.labelSpan === 3 ? "300px" : "200px", display: (Setting.isMobile()) ? "inline" : "inline-block"}}>
|
||||
<span style={{
|
||||
width: this.props.labelSpan === 3 ? "300px" : "200px",
|
||||
display: (Setting.isMobile()) ? "inline" : "inline-block",
|
||||
overflow: "hidden",
|
||||
textOverflow: "ellipsis",
|
||||
}} title={name}>
|
||||
{
|
||||
linkedValue === "" ? (
|
||||
`(${i18next.t("general:empty")})`
|
||||
|
113
web/src/common/modal/EnableMfaModal.js
Normal file
113
web/src/common/modal/EnableMfaModal.js
Normal file
@@ -0,0 +1,113 @@
|
||||
// Copyright 2023 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 {Button, Modal} from "antd";
|
||||
import i18next from "i18next";
|
||||
import React from "react";
|
||||
import {useEffect, useState} from "react";
|
||||
import {EmailMfaType} from "../../auth/MfaSetupPage";
|
||||
import * as MfaBackend from "../../backend/MfaBackend";
|
||||
import * as Setting from "../../Setting";
|
||||
|
||||
const EnableMfaModal = ({user, mfaType, onSuccess}) => {
|
||||
const [open, setOpen] = useState(false);
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (!open || !user) {
|
||||
return;
|
||||
}
|
||||
MfaBackend.MfaSetupInitiate({
|
||||
mfaType,
|
||||
...user,
|
||||
}).then((res) => {
|
||||
if (res.status === "error") {
|
||||
Setting.showMessage("error", i18next.t("mfa:Failed to initiate MFA"));
|
||||
}
|
||||
});
|
||||
}, [open]);
|
||||
|
||||
const handleOk = () => {
|
||||
setLoading(true);
|
||||
MfaBackend.MfaSetupEnable({
|
||||
mfaType,
|
||||
...user,
|
||||
}).then(res => {
|
||||
if (res.status === "ok") {
|
||||
Setting.showMessage("success", i18next.t("general:Enabled successfully"));
|
||||
setOpen(false);
|
||||
onSuccess();
|
||||
} else {
|
||||
Setting.showMessage("error", `${i18next.t("general:Failed to enable")}: ${res.msg}`);
|
||||
}
|
||||
}
|
||||
).finally(() => {
|
||||
setLoading(false);
|
||||
});
|
||||
};
|
||||
|
||||
const handleCancel = () => {
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
const showModal = () => {
|
||||
if (!isValid()) {
|
||||
if (mfaType === EmailMfaType) {
|
||||
Setting.showMessage("error", i18next.t("signup:Please input your Email!"));
|
||||
} else {
|
||||
Setting.showMessage("error", i18next.t("signup:Please input your phone number!"));
|
||||
}
|
||||
return;
|
||||
}
|
||||
setOpen(true);
|
||||
};
|
||||
|
||||
const renderText = () => {
|
||||
return (
|
||||
<p>{i18next.t("mfa:Please confirm the information below")}<br />
|
||||
<b>{i18next.t("general:User")}</b>: {`${user.owner}/${user.name}`}<br />
|
||||
{mfaType === EmailMfaType ?
|
||||
<><b>{i18next.t("general:Email")}</b> : {user.email}</> :
|
||||
<><b>{i18next.t("general:Phone")}</b> : {user.phone}</>}
|
||||
</p>
|
||||
);
|
||||
};
|
||||
|
||||
const isValid = () => {
|
||||
if (mfaType === EmailMfaType) {
|
||||
return user.email !== "";
|
||||
} else {
|
||||
return user.phone !== "";
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Button type="primary" onClick={showModal}>
|
||||
{i18next.t("general:Enable")}
|
||||
</Button>
|
||||
<Modal
|
||||
title={i18next.t("mfa:Enable multi-factor authentication")}
|
||||
open={open}
|
||||
onOk={handleOk}
|
||||
onCancel={handleCancel}
|
||||
confirmLoading={loading}
|
||||
>
|
||||
{renderText()}
|
||||
</Modal>
|
||||
</React.Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
export default EnableMfaModal;
|
@@ -27,6 +27,9 @@ import pt from "./locales/pt/data.json";
|
||||
import it from "./locales/it/data.json";
|
||||
import ms from "./locales/ms/data.json";
|
||||
import tr from "./locales/tr/data.json";
|
||||
import ar from "./locales/ar/data.json";
|
||||
import he from "./locales/he/data.json";
|
||||
import fi from "./locales/fi/data.json";
|
||||
import * as Conf from "./Conf";
|
||||
import {initReactI18next} from "react-i18next";
|
||||
|
||||
@@ -45,6 +48,9 @@ const resources = {
|
||||
it: it,
|
||||
ms: ms,
|
||||
tr: tr,
|
||||
ar: ar,
|
||||
he: he,
|
||||
fi: fi,
|
||||
};
|
||||
|
||||
function initLanguage() {
|
||||
@@ -103,6 +109,15 @@ function initLanguage() {
|
||||
case "tr":
|
||||
language = "tr";
|
||||
break;
|
||||
case "ar":
|
||||
language = "ar";
|
||||
break;
|
||||
case "he":
|
||||
language = "he";
|
||||
break;
|
||||
case "fi":
|
||||
language = "fi";
|
||||
break;
|
||||
default:
|
||||
language = Conf.DefaultLanguage;
|
||||
}
|
||||
|
1008
web/src/locales/ar/data.json
Normal file
1008
web/src/locales/ar/data.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -11,6 +11,7 @@
|
||||
"New Adapter": "Neuer Adapter",
|
||||
"Policies": "Richtlinien",
|
||||
"Policies - Tooltip": "Casbin Richtlinienregeln",
|
||||
"Rule type": "Rule type",
|
||||
"Sync policies successfully": "Richtlinien synchronisiert"
|
||||
},
|
||||
"application": {
|
||||
@@ -353,6 +354,13 @@
|
||||
"Show all": "Show all",
|
||||
"Virtual": "Virtual"
|
||||
},
|
||||
"home": {
|
||||
"New users past 30 days": "New users past 30 days",
|
||||
"New users past 7 days": "New users past 7 days",
|
||||
"New users today": "New users today",
|
||||
"Past 30 Days": "Past 30 Days",
|
||||
"Total users": "Total users"
|
||||
},
|
||||
"ldap": {
|
||||
"Admin": "Admin",
|
||||
"Admin - Tooltip": "CN oder ID des LDAP-Serveradministrators",
|
||||
@@ -388,6 +396,7 @@
|
||||
"Continue with": "Weitermachen mit",
|
||||
"Email or phone": "E-Mail oder Telefon",
|
||||
"Failed to obtain MetaMask authorization": "Failed to obtain MetaMask authorization",
|
||||
"Failed to obtain Web3-Onboard authorization": "Failed to obtain Web3-Onboard authorization",
|
||||
"Forgot password?": "Passwort vergessen?",
|
||||
"Loading": "Laden",
|
||||
"Logging out...": "Ausloggen...",
|
||||
@@ -431,6 +440,7 @@
|
||||
"Passcode": "Passcode",
|
||||
"Please bind your email first, the system will automatically uses the mail for multi-factor authentication": "Please bind your email first, the system will automatically uses the mail for multi-factor authentication",
|
||||
"Please bind your phone first, the system automatically uses the phone for multi-factor authentication": "Please bind your phone first, the system automatically uses the phone for multi-factor authentication",
|
||||
"Please confirm the information below": "Please confirm the information below",
|
||||
"Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code": "Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code",
|
||||
"Protect your account with Multi-factor authentication": "Protect your account with Multi-factor authentication",
|
||||
"Recovery code": "Recovery code",
|
||||
@@ -523,6 +533,7 @@
|
||||
"Return to Website": "Zurück zur Website",
|
||||
"The payment has been canceled": "The payment has been canceled",
|
||||
"The payment has failed": "Die Zahlung ist fehlgeschlagen",
|
||||
"The payment has time out": "The payment has time out",
|
||||
"The payment is still under processing": "Die Zahlung wird immer noch bearbeitet",
|
||||
"Type - Tooltip": "Zahlungsmethode, die beim Kauf des Produkts verwendet wurde",
|
||||
"You have successfully completed the payment": "Sie haben die Zahlung erfolgreich abgeschlossen",
|
||||
@@ -604,6 +615,7 @@
|
||||
"SKU": "SKU",
|
||||
"Sold": "Verkauft",
|
||||
"Sold - Tooltip": "Menge verkauft",
|
||||
"Stripe": "Stripe",
|
||||
"Tag - Tooltip": "Tag des Produkts",
|
||||
"Test buy page..": "Testkaufseite.",
|
||||
"There is no payment channel for this product.": "Es gibt keinen Zahlungskanal für dieses Produkt.",
|
||||
@@ -648,6 +660,8 @@
|
||||
"Client secret - Tooltip": "Client-Geheimnis",
|
||||
"Client secret 2": "Client-Secret 2",
|
||||
"Client secret 2 - Tooltip": "Der zweite Client-Secret-Key",
|
||||
"Content": "Content",
|
||||
"Content - Tooltip": "Content - Tooltip",
|
||||
"Copy": "Kopieren",
|
||||
"Disable SSL": "SSL deaktivieren",
|
||||
"Disable SSL - Tooltip": "Ob die Deaktivierung des SSL-Protokolls bei der Kommunikation mit dem STMP-Server erfolgen soll",
|
||||
@@ -682,6 +696,8 @@
|
||||
"Method - Tooltip": "Anmeldeverfahren, QR-Code oder Silent-Login",
|
||||
"New Provider": "Neuer Provider",
|
||||
"Normal": "Normal",
|
||||
"Parameter name": "Parameter name",
|
||||
"Parameter name - Tooltip": "Parameter name - Tooltip",
|
||||
"Parse": "parsen",
|
||||
"Parse metadata successfully": "Metadaten erfolgreich analysiert",
|
||||
"Path prefix": "Pfadpräfix",
|
||||
@@ -758,6 +774,8 @@
|
||||
"User mapping - Tooltip": "User mapping - Tooltip",
|
||||
"UserInfo URL": "UserInfo-URL",
|
||||
"UserInfo URL - Tooltip": "UserInfo-URL",
|
||||
"Wallets": "Wallets",
|
||||
"Wallets - Tooltip": "Wallets - Tooltip",
|
||||
"admin (Shared)": "admin (Shared)"
|
||||
},
|
||||
"record": {
|
||||
@@ -849,9 +867,7 @@
|
||||
"Table": "Tabelle",
|
||||
"Table - Tooltip": "Name der Datenbanktabelle",
|
||||
"Table columns": "Tabellenspalten",
|
||||
"Table columns - Tooltip": "Spalten in der Tabelle, die an der Datensynchronisierung beteiligt sind. Spalten, die nicht an der Synchronisierung beteiligt sind, müssen nicht hinzugefügt werden",
|
||||
"Table primary key": "Primärschlüssel der Tabelle",
|
||||
"Table primary key - Tooltip": "Primärschlüssel in einer Tabelle, wie beispielsweise eine ID"
|
||||
"Table columns - Tooltip": "Spalten in der Tabelle, die an der Datensynchronisierung beteiligt sind. Spalten, die nicht an der Synchronisierung beteiligt sind, müssen nicht hinzugefügt werden"
|
||||
},
|
||||
"system": {
|
||||
"API Latency": "API Latenz",
|
||||
|
@@ -11,6 +11,7 @@
|
||||
"New Adapter": "New Adapter",
|
||||
"Policies": "Policies",
|
||||
"Policies - Tooltip": "Casbin policy rules",
|
||||
"Rule type": "Rule type",
|
||||
"Sync policies successfully": "Sync policies successfully"
|
||||
},
|
||||
"application": {
|
||||
@@ -353,6 +354,13 @@
|
||||
"Show all": "Show all",
|
||||
"Virtual": "Virtual"
|
||||
},
|
||||
"home": {
|
||||
"New users past 30 days": "New users past 30 days",
|
||||
"New users past 7 days": "New users past 7 days",
|
||||
"New users today": "New users today",
|
||||
"Past 30 Days": "Past 30 Days",
|
||||
"Total users": "Total users"
|
||||
},
|
||||
"ldap": {
|
||||
"Admin": "Admin",
|
||||
"Admin - Tooltip": "CN or ID of the LDAP server administrator",
|
||||
@@ -388,6 +396,7 @@
|
||||
"Continue with": "Continue with",
|
||||
"Email or phone": "Email or phone",
|
||||
"Failed to obtain MetaMask authorization": "Failed to obtain MetaMask authorization",
|
||||
"Failed to obtain Web3-Onboard authorization": "Failed to obtain Web3-Onboard authorization",
|
||||
"Forgot password?": "Forgot password?",
|
||||
"Loading": "Loading",
|
||||
"Logging out...": "Logging out...",
|
||||
@@ -431,6 +440,7 @@
|
||||
"Passcode": "Passcode",
|
||||
"Please bind your email first, the system will automatically uses the mail for multi-factor authentication": "Please bind your email first, the system will automatically uses the mail for multi-factor authentication",
|
||||
"Please bind your phone first, the system automatically uses the phone for multi-factor authentication": "Please bind your phone first, the system automatically uses the phone for multi-factor authentication",
|
||||
"Please confirm the information below": "Please confirm the information below",
|
||||
"Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code": "Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code",
|
||||
"Protect your account with Multi-factor authentication": "Protect your account with Multi-factor authentication",
|
||||
"Recovery code": "Recovery code",
|
||||
@@ -523,6 +533,7 @@
|
||||
"Return to Website": "Return to Website",
|
||||
"The payment has been canceled": "The payment has been canceled",
|
||||
"The payment has failed": "The payment has failed",
|
||||
"The payment has time out": "The payment has time out",
|
||||
"The payment is still under processing": "The payment is still under processing",
|
||||
"Type - Tooltip": "Payment method used when purchasing the product",
|
||||
"You have successfully completed the payment": "You have successfully completed the payment",
|
||||
@@ -604,6 +615,7 @@
|
||||
"SKU": "SKU",
|
||||
"Sold": "Sold",
|
||||
"Sold - Tooltip": "Quantity sold",
|
||||
"Stripe": "Stripe",
|
||||
"Tag - Tooltip": "Tag of product",
|
||||
"Test buy page..": "Test buy page..",
|
||||
"There is no payment channel for this product.": "There is no payment channel for this product.",
|
||||
@@ -648,6 +660,8 @@
|
||||
"Client secret - Tooltip": "Client secret",
|
||||
"Client secret 2": "Client secret 2",
|
||||
"Client secret 2 - Tooltip": "The second client secret key",
|
||||
"Content": "Content",
|
||||
"Content - Tooltip": "Content - Tooltip",
|
||||
"Copy": "Copy",
|
||||
"Disable SSL": "Disable SSL",
|
||||
"Disable SSL - Tooltip": "Whether to disable SSL protocol when communicating with STMP server",
|
||||
@@ -682,6 +696,8 @@
|
||||
"Method - Tooltip": "Login method, QR code or silent login",
|
||||
"New Provider": "New Provider",
|
||||
"Normal": "Normal",
|
||||
"Parameter name": "Parameter name",
|
||||
"Parameter name - Tooltip": "Parameter name - Tooltip",
|
||||
"Parse": "Parse",
|
||||
"Parse metadata successfully": "Parse metadata successfully",
|
||||
"Path prefix": "Path prefix",
|
||||
@@ -758,6 +774,8 @@
|
||||
"User mapping - Tooltip": "User mapping - Tooltip",
|
||||
"UserInfo URL": "UserInfo URL",
|
||||
"UserInfo URL - Tooltip": "UserInfo URL",
|
||||
"Wallets": "Wallets",
|
||||
"Wallets - Tooltip": "Wallets - Tooltip",
|
||||
"admin (Shared)": "admin (Shared)"
|
||||
},
|
||||
"record": {
|
||||
@@ -849,9 +867,7 @@
|
||||
"Table": "Table",
|
||||
"Table - Tooltip": "Name of database table",
|
||||
"Table columns": "Table columns",
|
||||
"Table columns - Tooltip": "Columns in the table involved in data synchronization. Columns that are not involved in synchronization do not need to be added",
|
||||
"Table primary key": "Table primary key",
|
||||
"Table primary key - Tooltip": "Table primary key, such as id"
|
||||
"Table columns - Tooltip": "Columns in the table involved in data synchronization. Columns that are not involved in synchronization do not need to be added"
|
||||
},
|
||||
"system": {
|
||||
"API Latency": "API Latency",
|
||||
|
@@ -11,6 +11,7 @@
|
||||
"New Adapter": "Nuevo adaptador",
|
||||
"Policies": "Políticas",
|
||||
"Policies - Tooltip": "Reglas de política de Casbin",
|
||||
"Rule type": "Rule type",
|
||||
"Sync policies successfully": "Sincronizar políticas correctamente"
|
||||
},
|
||||
"application": {
|
||||
@@ -353,6 +354,13 @@
|
||||
"Show all": "Show all",
|
||||
"Virtual": "Virtual"
|
||||
},
|
||||
"home": {
|
||||
"New users past 30 days": "New users past 30 days",
|
||||
"New users past 7 days": "New users past 7 days",
|
||||
"New users today": "New users today",
|
||||
"Past 30 Days": "Past 30 Days",
|
||||
"Total users": "Total users"
|
||||
},
|
||||
"ldap": {
|
||||
"Admin": "Administrador",
|
||||
"Admin - Tooltip": "CN o ID del administrador del servidor LDAP",
|
||||
@@ -388,6 +396,7 @@
|
||||
"Continue with": "Continúe con",
|
||||
"Email or phone": "Correo electrónico o teléfono",
|
||||
"Failed to obtain MetaMask authorization": "Failed to obtain MetaMask authorization",
|
||||
"Failed to obtain Web3-Onboard authorization": "Failed to obtain Web3-Onboard authorization",
|
||||
"Forgot password?": "¿Olvidaste tu contraseña?",
|
||||
"Loading": "Cargando",
|
||||
"Logging out...": "Cerrando sesión...",
|
||||
@@ -431,6 +440,7 @@
|
||||
"Passcode": "Passcode",
|
||||
"Please bind your email first, the system will automatically uses the mail for multi-factor authentication": "Please bind your email first, the system will automatically uses the mail for multi-factor authentication",
|
||||
"Please bind your phone first, the system automatically uses the phone for multi-factor authentication": "Please bind your phone first, the system automatically uses the phone for multi-factor authentication",
|
||||
"Please confirm the information below": "Please confirm the information below",
|
||||
"Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code": "Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code",
|
||||
"Protect your account with Multi-factor authentication": "Protect your account with Multi-factor authentication",
|
||||
"Recovery code": "Recovery code",
|
||||
@@ -523,6 +533,7 @@
|
||||
"Return to Website": "Regresar al sitio web",
|
||||
"The payment has been canceled": "The payment has been canceled",
|
||||
"The payment has failed": "El pago ha fallado",
|
||||
"The payment has time out": "The payment has time out",
|
||||
"The payment is still under processing": "El pago aún está en proceso",
|
||||
"Type - Tooltip": "Método de pago utilizado al comprar el producto",
|
||||
"You have successfully completed the payment": "Has completado el pago exitosamente",
|
||||
@@ -604,6 +615,7 @@
|
||||
"SKU": "SKU",
|
||||
"Sold": "Vendido",
|
||||
"Sold - Tooltip": "Cantidad vendida",
|
||||
"Stripe": "Stripe",
|
||||
"Tag - Tooltip": "Etiqueta de producto",
|
||||
"Test buy page..": "Página de compra de prueba.",
|
||||
"There is no payment channel for this product.": "No hay canal de pago para este producto.",
|
||||
@@ -648,6 +660,8 @@
|
||||
"Client secret - Tooltip": "Secreto del cliente",
|
||||
"Client secret 2": "Secreto del cliente 2",
|
||||
"Client secret 2 - Tooltip": "La segunda clave secreta del cliente",
|
||||
"Content": "Content",
|
||||
"Content - Tooltip": "Content - Tooltip",
|
||||
"Copy": "Copiar",
|
||||
"Disable SSL": "Desactivar SSL",
|
||||
"Disable SSL - Tooltip": "¿Hay que desactivar el protocolo SSL al comunicarse con el servidor STMP?",
|
||||
@@ -682,6 +696,8 @@
|
||||
"Method - Tooltip": "Método de inicio de sesión, código QR o inicio de sesión silencioso",
|
||||
"New Provider": "Nuevo proveedor",
|
||||
"Normal": "Normal",
|
||||
"Parameter name": "Parameter name",
|
||||
"Parameter name - Tooltip": "Parameter name - Tooltip",
|
||||
"Parse": "Analizar",
|
||||
"Parse metadata successfully": "Analizar los metadatos con éxito",
|
||||
"Path prefix": "Prefijo de ruta",
|
||||
@@ -758,6 +774,8 @@
|
||||
"User mapping - Tooltip": "User mapping - Tooltip",
|
||||
"UserInfo URL": "URL de información del usuario",
|
||||
"UserInfo URL - Tooltip": "URL de información de usuario",
|
||||
"Wallets": "Wallets",
|
||||
"Wallets - Tooltip": "Wallets - Tooltip",
|
||||
"admin (Shared)": "administrador (compartido)"
|
||||
},
|
||||
"record": {
|
||||
@@ -849,9 +867,7 @@
|
||||
"Table": "Mesa",
|
||||
"Table - Tooltip": "Nombre de la tabla de la base de datos",
|
||||
"Table columns": "Columnas de tabla",
|
||||
"Table columns - Tooltip": "Columnas en la tabla involucradas en la sincronización de datos. Las columnas que no estén involucradas en la sincronización no necesitan ser añadidas",
|
||||
"Table primary key": "Clave primaria de la tabla",
|
||||
"Table primary key - Tooltip": "Clave primaria de la tabla, como id"
|
||||
"Table columns - Tooltip": "Columnas en la tabla involucradas en la sincronización de datos. Las columnas que no estén involucradas en la sincronización no necesitan ser añadidas"
|
||||
},
|
||||
"system": {
|
||||
"API Latency": "Retraso API",
|
||||
|
1008
web/src/locales/fi/data.json
Normal file
1008
web/src/locales/fi/data.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -11,6 +11,7 @@
|
||||
"New Adapter": "Nouvel adaptateur",
|
||||
"Policies": "Politiques",
|
||||
"Policies - Tooltip": "Règles de politique Casbin",
|
||||
"Rule type": "Rule type",
|
||||
"Sync policies successfully": "Synchronisation des politiques réussie"
|
||||
},
|
||||
"application": {
|
||||
@@ -353,6 +354,13 @@
|
||||
"Show all": "Show all",
|
||||
"Virtual": "Virtual"
|
||||
},
|
||||
"home": {
|
||||
"New users past 30 days": "New users past 30 days",
|
||||
"New users past 7 days": "New users past 7 days",
|
||||
"New users today": "New users today",
|
||||
"Past 30 Days": "Past 30 Days",
|
||||
"Total users": "Total users"
|
||||
},
|
||||
"ldap": {
|
||||
"Admin": "Admin",
|
||||
"Admin - Tooltip": "CN ou ID de l'administrateur du serveur LDAP",
|
||||
@@ -388,6 +396,7 @@
|
||||
"Continue with": "Continuer avec",
|
||||
"Email or phone": "Email ou téléphone",
|
||||
"Failed to obtain MetaMask authorization": "Failed to obtain MetaMask authorization",
|
||||
"Failed to obtain Web3-Onboard authorization": "Failed to obtain Web3-Onboard authorization",
|
||||
"Forgot password?": "Mot de passe oublié ?",
|
||||
"Loading": "Chargement",
|
||||
"Logging out...": "Déconnexion...",
|
||||
@@ -431,6 +440,7 @@
|
||||
"Passcode": "Passcode",
|
||||
"Please bind your email first, the system will automatically uses the mail for multi-factor authentication": "Please bind your email first, the system will automatically uses the mail for multi-factor authentication",
|
||||
"Please bind your phone first, the system automatically uses the phone for multi-factor authentication": "Please bind your phone first, the system automatically uses the phone for multi-factor authentication",
|
||||
"Please confirm the information below": "Please confirm the information below",
|
||||
"Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code": "Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code",
|
||||
"Protect your account with Multi-factor authentication": "Protect your account with Multi-factor authentication",
|
||||
"Recovery code": "Recovery code",
|
||||
@@ -523,6 +533,7 @@
|
||||
"Return to Website": "Retourner sur le site web",
|
||||
"The payment has been canceled": "The payment has been canceled",
|
||||
"The payment has failed": "Le paiement a échoué",
|
||||
"The payment has time out": "The payment has time out",
|
||||
"The payment is still under processing": "Le paiement est encore en cours de traitement",
|
||||
"Type - Tooltip": "Méthode de paiement utilisée lors de l'achat du produit",
|
||||
"You have successfully completed the payment": "Vous avez effectué le paiement avec succès",
|
||||
@@ -604,6 +615,7 @@
|
||||
"SKU": "SKU",
|
||||
"Sold": "Vendu",
|
||||
"Sold - Tooltip": "Quantité vendue",
|
||||
"Stripe": "Stripe",
|
||||
"Tag - Tooltip": "Étiquette de produit",
|
||||
"Test buy page..": "Page d'achat de test.",
|
||||
"There is no payment channel for this product.": "Il n'y a aucun canal de paiement pour ce produit.",
|
||||
@@ -648,6 +660,8 @@
|
||||
"Client secret - Tooltip": "Secret client",
|
||||
"Client secret 2": "Secret client 2",
|
||||
"Client secret 2 - Tooltip": "La deuxième clé secrète du client",
|
||||
"Content": "Content",
|
||||
"Content - Tooltip": "Content - Tooltip",
|
||||
"Copy": "Copie",
|
||||
"Disable SSL": "Désactiver SSL",
|
||||
"Disable SSL - Tooltip": "Doit-on désactiver le protocole SSL lors de la communication avec le serveur STMP ?",
|
||||
@@ -682,6 +696,8 @@
|
||||
"Method - Tooltip": "Méthode de connexion, code QR ou connexion silencieuse",
|
||||
"New Provider": "Nouveau fournisseur",
|
||||
"Normal": "Normal",
|
||||
"Parameter name": "Parameter name",
|
||||
"Parameter name - Tooltip": "Parameter name - Tooltip",
|
||||
"Parse": "Parser",
|
||||
"Parse metadata successfully": "Parcourir les métadonnées avec succès",
|
||||
"Path prefix": "Préfixe de chemin",
|
||||
@@ -758,6 +774,8 @@
|
||||
"User mapping - Tooltip": "User mapping - Tooltip",
|
||||
"UserInfo URL": "URL d'informations utilisateur",
|
||||
"UserInfo URL - Tooltip": "URL d'informations sur l'utilisateur",
|
||||
"Wallets": "Wallets",
|
||||
"Wallets - Tooltip": "Wallets - Tooltip",
|
||||
"admin (Shared)": "admin (Partagé)"
|
||||
},
|
||||
"record": {
|
||||
@@ -849,9 +867,7 @@
|
||||
"Table": "Table",
|
||||
"Table - Tooltip": "Nom de la table de base de données",
|
||||
"Table columns": "Colonnes de table",
|
||||
"Table columns - Tooltip": "Colonnes dans la table impliquées dans la synchronisation des données. Les colonnes qui ne sont pas impliquées dans la synchronisation n'ont pas besoin d'être ajoutées",
|
||||
"Table primary key": "Clé primaire de table",
|
||||
"Table primary key - Tooltip": "Clé primaire de la table, telle que l'id"
|
||||
"Table columns - Tooltip": "Colonnes dans la table impliquées dans la synchronisation des données. Les colonnes qui ne sont pas impliquées dans la synchronisation n'ont pas besoin d'être ajoutées"
|
||||
},
|
||||
"system": {
|
||||
"API Latency": "Retard API",
|
||||
|
1008
web/src/locales/he/data.json
Normal file
1008
web/src/locales/he/data.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -11,6 +11,7 @@
|
||||
"New Adapter": "Adapter Baru",
|
||||
"Policies": "Kebijakan",
|
||||
"Policies - Tooltip": "Kebijakan aturan Casbin",
|
||||
"Rule type": "Rule type",
|
||||
"Sync policies successfully": "Sinkronisasi kebijakan berhasil dilakukan"
|
||||
},
|
||||
"application": {
|
||||
@@ -353,6 +354,13 @@
|
||||
"Show all": "Show all",
|
||||
"Virtual": "Virtual"
|
||||
},
|
||||
"home": {
|
||||
"New users past 30 days": "New users past 30 days",
|
||||
"New users past 7 days": "New users past 7 days",
|
||||
"New users today": "New users today",
|
||||
"Past 30 Days": "Past 30 Days",
|
||||
"Total users": "Total users"
|
||||
},
|
||||
"ldap": {
|
||||
"Admin": "Admin",
|
||||
"Admin - Tooltip": "CN atau ID dari administrator server LDAP",
|
||||
@@ -388,6 +396,7 @@
|
||||
"Continue with": "Lanjutkan dengan",
|
||||
"Email or phone": "Email atau telepon",
|
||||
"Failed to obtain MetaMask authorization": "Failed to obtain MetaMask authorization",
|
||||
"Failed to obtain Web3-Onboard authorization": "Failed to obtain Web3-Onboard authorization",
|
||||
"Forgot password?": "Lupa kata sandi?",
|
||||
"Loading": "Memuat",
|
||||
"Logging out...": "Keluar...",
|
||||
@@ -431,6 +440,7 @@
|
||||
"Passcode": "Passcode",
|
||||
"Please bind your email first, the system will automatically uses the mail for multi-factor authentication": "Please bind your email first, the system will automatically uses the mail for multi-factor authentication",
|
||||
"Please bind your phone first, the system automatically uses the phone for multi-factor authentication": "Please bind your phone first, the system automatically uses the phone for multi-factor authentication",
|
||||
"Please confirm the information below": "Please confirm the information below",
|
||||
"Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code": "Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code",
|
||||
"Protect your account with Multi-factor authentication": "Protect your account with Multi-factor authentication",
|
||||
"Recovery code": "Recovery code",
|
||||
@@ -523,6 +533,7 @@
|
||||
"Return to Website": "Kembali ke Situs Web",
|
||||
"The payment has been canceled": "The payment has been canceled",
|
||||
"The payment has failed": "Pembayaran gagal",
|
||||
"The payment has time out": "The payment has time out",
|
||||
"The payment is still under processing": "Pembayaran masih dalam proses",
|
||||
"Type - Tooltip": "Metode pembayaran yang digunakan saat membeli produk",
|
||||
"You have successfully completed the payment": "Anda telah berhasil menyelesaikan pembayaran",
|
||||
@@ -604,6 +615,7 @@
|
||||
"SKU": "SKU",
|
||||
"Sold": "Terjual",
|
||||
"Sold - Tooltip": "Jumlah terjual",
|
||||
"Stripe": "Stripe",
|
||||
"Tag - Tooltip": "Tag produk",
|
||||
"Test buy page..": "Halaman pembelian uji coba.",
|
||||
"There is no payment channel for this product.": "Tidak ada saluran pembayaran untuk produk ini.",
|
||||
@@ -648,6 +660,8 @@
|
||||
"Client secret - Tooltip": "Rahasia klien",
|
||||
"Client secret 2": "Rahasia klien 2",
|
||||
"Client secret 2 - Tooltip": "Kunci rahasia klien kedua",
|
||||
"Content": "Content",
|
||||
"Content - Tooltip": "Content - Tooltip",
|
||||
"Copy": "Salin",
|
||||
"Disable SSL": "Menonaktifkan SSL",
|
||||
"Disable SSL - Tooltip": "Apakah perlu menonaktifkan protokol SSL saat berkomunikasi dengan server STMP?",
|
||||
@@ -682,6 +696,8 @@
|
||||
"Method - Tooltip": "Metode login, kode QR atau login tanpa suara",
|
||||
"New Provider": "Penyedia Baru",
|
||||
"Normal": "Normal",
|
||||
"Parameter name": "Parameter name",
|
||||
"Parameter name - Tooltip": "Parameter name - Tooltip",
|
||||
"Parse": "Parse: Memecah atau mengurai data atau teks menjadi bagian-bagian yang lebih kecil dan lebih mudah dipahami atau dimanipulasi",
|
||||
"Parse metadata successfully": "Berhasil mem-parse metadata",
|
||||
"Path prefix": "Awalan jalur",
|
||||
@@ -758,6 +774,8 @@
|
||||
"User mapping - Tooltip": "User mapping - Tooltip",
|
||||
"UserInfo URL": "URL UserInfo",
|
||||
"UserInfo URL - Tooltip": "URL Informasi Pengguna",
|
||||
"Wallets": "Wallets",
|
||||
"Wallets - Tooltip": "Wallets - Tooltip",
|
||||
"admin (Shared)": "Admin (Berbagi)"
|
||||
},
|
||||
"record": {
|
||||
@@ -849,9 +867,7 @@
|
||||
"Table": "Tabel",
|
||||
"Table - Tooltip": "Nama tabel database",
|
||||
"Table columns": "Kolom tabel",
|
||||
"Table columns - Tooltip": "Kolom pada tabel yang terlibat dalam sinkronisasi data. Kolom yang tidak terlibat dalam sinkronisasi tidak perlu ditambahkan",
|
||||
"Table primary key": "Kunci utama tabel",
|
||||
"Table primary key - Tooltip": "Kunci primer tabel, seperti id"
|
||||
"Table columns - Tooltip": "Kolom pada tabel yang terlibat dalam sinkronisasi data. Kolom yang tidak terlibat dalam sinkronisasi tidak perlu ditambahkan"
|
||||
},
|
||||
"system": {
|
||||
"API Latency": "API Latency",
|
||||
|
@@ -11,6 +11,7 @@
|
||||
"New Adapter": "New Adapter",
|
||||
"Policies": "Policies",
|
||||
"Policies - Tooltip": "Casbin policy rules",
|
||||
"Rule type": "Rule type",
|
||||
"Sync policies successfully": "Sync policies successfully"
|
||||
},
|
||||
"application": {
|
||||
@@ -353,6 +354,13 @@
|
||||
"Show all": "Show all",
|
||||
"Virtual": "Virtual"
|
||||
},
|
||||
"home": {
|
||||
"New users past 30 days": "New users past 30 days",
|
||||
"New users past 7 days": "New users past 7 days",
|
||||
"New users today": "New users today",
|
||||
"Past 30 Days": "Past 30 Days",
|
||||
"Total users": "Total users"
|
||||
},
|
||||
"ldap": {
|
||||
"Admin": "Admin",
|
||||
"Admin - Tooltip": "CN or ID of the LDAP server administrator",
|
||||
@@ -388,6 +396,7 @@
|
||||
"Continue with": "Continue with",
|
||||
"Email or phone": "Email or phone",
|
||||
"Failed to obtain MetaMask authorization": "Failed to obtain MetaMask authorization",
|
||||
"Failed to obtain Web3-Onboard authorization": "Failed to obtain Web3-Onboard authorization",
|
||||
"Forgot password?": "Forgot password?",
|
||||
"Loading": "Loading",
|
||||
"Logging out...": "Logging out...",
|
||||
@@ -431,6 +440,7 @@
|
||||
"Passcode": "Passcode",
|
||||
"Please bind your email first, the system will automatically uses the mail for multi-factor authentication": "Please bind your email first, the system will automatically uses the mail for multi-factor authentication",
|
||||
"Please bind your phone first, the system automatically uses the phone for multi-factor authentication": "Please bind your phone first, the system automatically uses the phone for multi-factor authentication",
|
||||
"Please confirm the information below": "Please confirm the information below",
|
||||
"Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code": "Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code",
|
||||
"Protect your account with Multi-factor authentication": "Protect your account with Multi-factor authentication",
|
||||
"Recovery code": "Recovery code",
|
||||
@@ -523,6 +533,7 @@
|
||||
"Return to Website": "Return to Website",
|
||||
"The payment has been canceled": "The payment has been canceled",
|
||||
"The payment has failed": "The payment has failed",
|
||||
"The payment has time out": "The payment has time out",
|
||||
"The payment is still under processing": "The payment is still under processing",
|
||||
"Type - Tooltip": "Payment method used when purchasing the product",
|
||||
"You have successfully completed the payment": "You have successfully completed the payment",
|
||||
@@ -604,6 +615,7 @@
|
||||
"SKU": "SKU",
|
||||
"Sold": "Sold",
|
||||
"Sold - Tooltip": "Quantity sold",
|
||||
"Stripe": "Stripe",
|
||||
"Tag - Tooltip": "Tag of product",
|
||||
"Test buy page..": "Test buy page..",
|
||||
"There is no payment channel for this product.": "There is no payment channel for this product.",
|
||||
@@ -648,6 +660,8 @@
|
||||
"Client secret - Tooltip": "Client secret",
|
||||
"Client secret 2": "Client secret 2",
|
||||
"Client secret 2 - Tooltip": "The second client secret key",
|
||||
"Content": "Content",
|
||||
"Content - Tooltip": "Content - Tooltip",
|
||||
"Copy": "Copy",
|
||||
"Disable SSL": "Disable SSL",
|
||||
"Disable SSL - Tooltip": "Whether to disable SSL protocol when communicating with STMP server",
|
||||
@@ -682,6 +696,8 @@
|
||||
"Method - Tooltip": "Login method, QR code or silent login",
|
||||
"New Provider": "New Provider",
|
||||
"Normal": "Normal",
|
||||
"Parameter name": "Parameter name",
|
||||
"Parameter name - Tooltip": "Parameter name - Tooltip",
|
||||
"Parse": "Parse",
|
||||
"Parse metadata successfully": "Parse metadata successfully",
|
||||
"Path prefix": "Path prefix",
|
||||
@@ -758,6 +774,8 @@
|
||||
"User mapping - Tooltip": "User mapping - Tooltip",
|
||||
"UserInfo URL": "UserInfo URL",
|
||||
"UserInfo URL - Tooltip": "UserInfo URL",
|
||||
"Wallets": "Wallets",
|
||||
"Wallets - Tooltip": "Wallets - Tooltip",
|
||||
"admin (Shared)": "admin (Shared)"
|
||||
},
|
||||
"record": {
|
||||
@@ -849,9 +867,7 @@
|
||||
"Table": "Table",
|
||||
"Table - Tooltip": "Name of database table",
|
||||
"Table columns": "Table columns",
|
||||
"Table columns - Tooltip": "Columns in the table involved in data synchronization. Columns that are not involved in synchronization do not need to be added",
|
||||
"Table primary key": "Table primary key",
|
||||
"Table primary key - Tooltip": "Table primary key, such as id"
|
||||
"Table columns - Tooltip": "Columns in the table involved in data synchronization. Columns that are not involved in synchronization do not need to be added"
|
||||
},
|
||||
"system": {
|
||||
"API Latency": "API Latency",
|
||||
|
@@ -11,6 +11,7 @@
|
||||
"New Adapter": "新しいアダプター",
|
||||
"Policies": "政策",
|
||||
"Policies - Tooltip": "Casbinのポリシールール",
|
||||
"Rule type": "Rule type",
|
||||
"Sync policies successfully": "ポリシーを同期できました"
|
||||
},
|
||||
"application": {
|
||||
@@ -353,6 +354,13 @@
|
||||
"Show all": "Show all",
|
||||
"Virtual": "Virtual"
|
||||
},
|
||||
"home": {
|
||||
"New users past 30 days": "New users past 30 days",
|
||||
"New users past 7 days": "New users past 7 days",
|
||||
"New users today": "New users today",
|
||||
"Past 30 Days": "Past 30 Days",
|
||||
"Total users": "Total users"
|
||||
},
|
||||
"ldap": {
|
||||
"Admin": "Admin",
|
||||
"Admin - Tooltip": "LDAPサーバー管理者のCNまたはID",
|
||||
@@ -388,6 +396,7 @@
|
||||
"Continue with": "続ける",
|
||||
"Email or phone": "メールまたは電話",
|
||||
"Failed to obtain MetaMask authorization": "Failed to obtain MetaMask authorization",
|
||||
"Failed to obtain Web3-Onboard authorization": "Failed to obtain Web3-Onboard authorization",
|
||||
"Forgot password?": "パスワードを忘れましたか?",
|
||||
"Loading": "ローディング",
|
||||
"Logging out...": "ログアウト中...",
|
||||
@@ -431,6 +440,7 @@
|
||||
"Passcode": "Passcode",
|
||||
"Please bind your email first, the system will automatically uses the mail for multi-factor authentication": "Please bind your email first, the system will automatically uses the mail for multi-factor authentication",
|
||||
"Please bind your phone first, the system automatically uses the phone for multi-factor authentication": "Please bind your phone first, the system automatically uses the phone for multi-factor authentication",
|
||||
"Please confirm the information below": "Please confirm the information below",
|
||||
"Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code": "Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code",
|
||||
"Protect your account with Multi-factor authentication": "Protect your account with Multi-factor authentication",
|
||||
"Recovery code": "Recovery code",
|
||||
@@ -523,6 +533,7 @@
|
||||
"Return to Website": "ウェブサイトに戻る",
|
||||
"The payment has been canceled": "The payment has been canceled",
|
||||
"The payment has failed": "支払いに失敗しました",
|
||||
"The payment has time out": "The payment has time out",
|
||||
"The payment is still under processing": "支払いはまだ処理中です",
|
||||
"Type - Tooltip": "製品を購入する際に使用される支払方法",
|
||||
"You have successfully completed the payment": "あなたは支払いを正常に完了しました",
|
||||
@@ -604,6 +615,7 @@
|
||||
"SKU": "SKU",
|
||||
"Sold": "売れました",
|
||||
"Sold - Tooltip": "販売数量",
|
||||
"Stripe": "Stripe",
|
||||
"Tag - Tooltip": "製品のタグ",
|
||||
"Test buy page..": "テスト購入ページ。",
|
||||
"There is no payment channel for this product.": "この製品には支払いチャネルがありません。",
|
||||
@@ -648,6 +660,8 @@
|
||||
"Client secret - Tooltip": "クライアント秘密鍵",
|
||||
"Client secret 2": "クライアントシークレット2",
|
||||
"Client secret 2 - Tooltip": "第二クライアント秘密鍵",
|
||||
"Content": "Content",
|
||||
"Content - Tooltip": "Content - Tooltip",
|
||||
"Copy": "コピー",
|
||||
"Disable SSL": "SSLを無効にする",
|
||||
"Disable SSL - Tooltip": "SMTPサーバーと通信する場合にSSLプロトコルを無効にするかどうか",
|
||||
@@ -682,6 +696,8 @@
|
||||
"Method - Tooltip": "ログイン方法、QRコードまたはサイレントログイン",
|
||||
"New Provider": "新しい提供者",
|
||||
"Normal": "Normal",
|
||||
"Parameter name": "Parameter name",
|
||||
"Parameter name - Tooltip": "Parameter name - Tooltip",
|
||||
"Parse": "パースする",
|
||||
"Parse metadata successfully": "メタデータを正常に解析しました",
|
||||
"Path prefix": "パスプレフィックス",
|
||||
@@ -758,6 +774,8 @@
|
||||
"User mapping - Tooltip": "User mapping - Tooltip",
|
||||
"UserInfo URL": "UserInfo URLを日本語に翻訳すると、「ユーザー情報のURL」となります",
|
||||
"UserInfo URL - Tooltip": "ユーザー情報URL",
|
||||
"Wallets": "Wallets",
|
||||
"Wallets - Tooltip": "Wallets - Tooltip",
|
||||
"admin (Shared)": "管理者(共有)"
|
||||
},
|
||||
"record": {
|
||||
@@ -849,9 +867,7 @@
|
||||
"Table": "テーブル",
|
||||
"Table - Tooltip": "データベーステーブル名",
|
||||
"Table columns": "テーブルの列",
|
||||
"Table columns - Tooltip": "テーブルで同期データに関与する列。同期に関係のない列は追加する必要はありません",
|
||||
"Table primary key": "テーブルの主キー",
|
||||
"Table primary key - Tooltip": "テーブルのプライマリキー、例えばid"
|
||||
"Table columns - Tooltip": "テーブルで同期データに関与する列。同期に関係のない列は追加する必要はありません"
|
||||
},
|
||||
"system": {
|
||||
"API Latency": "API遅延",
|
||||
|
@@ -11,6 +11,7 @@
|
||||
"New Adapter": "새로운 어댑터",
|
||||
"Policies": "정책",
|
||||
"Policies - Tooltip": "Casbin 정책 규칙",
|
||||
"Rule type": "Rule type",
|
||||
"Sync policies successfully": "정책을 성공적으로 동기화했습니다"
|
||||
},
|
||||
"application": {
|
||||
@@ -353,6 +354,13 @@
|
||||
"Show all": "Show all",
|
||||
"Virtual": "Virtual"
|
||||
},
|
||||
"home": {
|
||||
"New users past 30 days": "New users past 30 days",
|
||||
"New users past 7 days": "New users past 7 days",
|
||||
"New users today": "New users today",
|
||||
"Past 30 Days": "Past 30 Days",
|
||||
"Total users": "Total users"
|
||||
},
|
||||
"ldap": {
|
||||
"Admin": "Admin",
|
||||
"Admin - Tooltip": "LDAP 서버 관리자의 CN 또는 ID",
|
||||
@@ -388,6 +396,7 @@
|
||||
"Continue with": "계속하다",
|
||||
"Email or phone": "이메일 또는 전화",
|
||||
"Failed to obtain MetaMask authorization": "Failed to obtain MetaMask authorization",
|
||||
"Failed to obtain Web3-Onboard authorization": "Failed to obtain Web3-Onboard authorization",
|
||||
"Forgot password?": "비밀번호를 잊으셨나요?",
|
||||
"Loading": "로딩 중입니다",
|
||||
"Logging out...": "로그아웃 중...",
|
||||
@@ -431,6 +440,7 @@
|
||||
"Passcode": "Passcode",
|
||||
"Please bind your email first, the system will automatically uses the mail for multi-factor authentication": "Please bind your email first, the system will automatically uses the mail for multi-factor authentication",
|
||||
"Please bind your phone first, the system automatically uses the phone for multi-factor authentication": "Please bind your phone first, the system automatically uses the phone for multi-factor authentication",
|
||||
"Please confirm the information below": "Please confirm the information below",
|
||||
"Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code": "Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code",
|
||||
"Protect your account with Multi-factor authentication": "Protect your account with Multi-factor authentication",
|
||||
"Recovery code": "Recovery code",
|
||||
@@ -523,6 +533,7 @@
|
||||
"Return to Website": "웹 사이트로 돌아가기",
|
||||
"The payment has been canceled": "The payment has been canceled",
|
||||
"The payment has failed": "결제가 실패했습니다",
|
||||
"The payment has time out": "The payment has time out",
|
||||
"The payment is still under processing": "지불은 아직 처리 중입니다",
|
||||
"Type - Tooltip": "제품을 구매할 때 사용되는 결제 방법",
|
||||
"You have successfully completed the payment": "당신은 결제를 성공적으로 완료하셨습니다",
|
||||
@@ -604,6 +615,7 @@
|
||||
"SKU": "SKU",
|
||||
"Sold": "팔렸습니다",
|
||||
"Sold - Tooltip": "판매량",
|
||||
"Stripe": "Stripe",
|
||||
"Tag - Tooltip": "제품 태그",
|
||||
"Test buy page..": "시험 구매 페이지.",
|
||||
"There is no payment channel for this product.": "이 제품에 대한 결제 채널이 없습니다.",
|
||||
@@ -648,6 +660,8 @@
|
||||
"Client secret - Tooltip": "클라이언트 비밀키",
|
||||
"Client secret 2": "클라이언트 비밀번호 2",
|
||||
"Client secret 2 - Tooltip": "두 번째 클라이언트 비밀 키",
|
||||
"Content": "Content",
|
||||
"Content - Tooltip": "Content - Tooltip",
|
||||
"Copy": "복사하다",
|
||||
"Disable SSL": "SSL을 사용하지 않도록 설정하십시오",
|
||||
"Disable SSL - Tooltip": "STMP 서버와 통신할 때 SSL 프로토콜을 비활성화할지 여부",
|
||||
@@ -682,6 +696,8 @@
|
||||
"Method - Tooltip": "로그인 방법, QR 코드 또는 음성 로그인",
|
||||
"New Provider": "새로운 공급 업체",
|
||||
"Normal": "Normal",
|
||||
"Parameter name": "Parameter name",
|
||||
"Parameter name - Tooltip": "Parameter name - Tooltip",
|
||||
"Parse": "파싱",
|
||||
"Parse metadata successfully": "메타데이터를 성공적으로 분석했습니다",
|
||||
"Path prefix": "경로 접두어",
|
||||
@@ -758,6 +774,8 @@
|
||||
"User mapping - Tooltip": "User mapping - Tooltip",
|
||||
"UserInfo URL": "사용자 정보 URL",
|
||||
"UserInfo URL - Tooltip": "UserInfo URL: 사용자 정보 URL",
|
||||
"Wallets": "Wallets",
|
||||
"Wallets - Tooltip": "Wallets - Tooltip",
|
||||
"admin (Shared)": "관리자 (공유)"
|
||||
},
|
||||
"record": {
|
||||
@@ -849,9 +867,7 @@
|
||||
"Table": "테이블",
|
||||
"Table - Tooltip": "데이터베이스 테이블 이름",
|
||||
"Table columns": "테이블 열",
|
||||
"Table columns - Tooltip": "데이터 동기화에 관련된 테이블의 열들입니다. 동기화에 관련되지 않은 열은 추가할 필요가 없습니다",
|
||||
"Table primary key": "테이블 기본키",
|
||||
"Table primary key - Tooltip": "테이블의 기본 키, 예를 들어 id"
|
||||
"Table columns - Tooltip": "데이터 동기화에 관련된 테이블의 열들입니다. 동기화에 관련되지 않은 열은 추가할 필요가 없습니다"
|
||||
},
|
||||
"system": {
|
||||
"API Latency": "API 지연",
|
||||
|
@@ -11,6 +11,7 @@
|
||||
"New Adapter": "New Adapter",
|
||||
"Policies": "Policies",
|
||||
"Policies - Tooltip": "Casbin policy rules",
|
||||
"Rule type": "Rule type",
|
||||
"Sync policies successfully": "Sync policies successfully"
|
||||
},
|
||||
"application": {
|
||||
@@ -353,6 +354,13 @@
|
||||
"Show all": "Show all",
|
||||
"Virtual": "Virtual"
|
||||
},
|
||||
"home": {
|
||||
"New users past 30 days": "New users past 30 days",
|
||||
"New users past 7 days": "New users past 7 days",
|
||||
"New users today": "New users today",
|
||||
"Past 30 Days": "Past 30 Days",
|
||||
"Total users": "Total users"
|
||||
},
|
||||
"ldap": {
|
||||
"Admin": "Admin",
|
||||
"Admin - Tooltip": "CN or ID of the LDAP server administrator",
|
||||
@@ -388,6 +396,7 @@
|
||||
"Continue with": "Continue with",
|
||||
"Email or phone": "Email or phone",
|
||||
"Failed to obtain MetaMask authorization": "Failed to obtain MetaMask authorization",
|
||||
"Failed to obtain Web3-Onboard authorization": "Failed to obtain Web3-Onboard authorization",
|
||||
"Forgot password?": "Forgot password?",
|
||||
"Loading": "Loading",
|
||||
"Logging out...": "Logging out...",
|
||||
@@ -431,6 +440,7 @@
|
||||
"Passcode": "Passcode",
|
||||
"Please bind your email first, the system will automatically uses the mail for multi-factor authentication": "Please bind your email first, the system will automatically uses the mail for multi-factor authentication",
|
||||
"Please bind your phone first, the system automatically uses the phone for multi-factor authentication": "Please bind your phone first, the system automatically uses the phone for multi-factor authentication",
|
||||
"Please confirm the information below": "Please confirm the information below",
|
||||
"Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code": "Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code",
|
||||
"Protect your account with Multi-factor authentication": "Protect your account with Multi-factor authentication",
|
||||
"Recovery code": "Recovery code",
|
||||
@@ -523,6 +533,7 @@
|
||||
"Return to Website": "Return to Website",
|
||||
"The payment has been canceled": "The payment has been canceled",
|
||||
"The payment has failed": "The payment has failed",
|
||||
"The payment has time out": "The payment has time out",
|
||||
"The payment is still under processing": "The payment is still under processing",
|
||||
"Type - Tooltip": "Payment method used when purchasing the product",
|
||||
"You have successfully completed the payment": "You have successfully completed the payment",
|
||||
@@ -604,6 +615,7 @@
|
||||
"SKU": "SKU",
|
||||
"Sold": "Sold",
|
||||
"Sold - Tooltip": "Quantity sold",
|
||||
"Stripe": "Stripe",
|
||||
"Tag - Tooltip": "Tag of product",
|
||||
"Test buy page..": "Test buy page..",
|
||||
"There is no payment channel for this product.": "There is no payment channel for this product.",
|
||||
@@ -648,6 +660,8 @@
|
||||
"Client secret - Tooltip": "Client secret",
|
||||
"Client secret 2": "Client secret 2",
|
||||
"Client secret 2 - Tooltip": "The second client secret key",
|
||||
"Content": "Content",
|
||||
"Content - Tooltip": "Content - Tooltip",
|
||||
"Copy": "Copy",
|
||||
"Disable SSL": "Disable SSL",
|
||||
"Disable SSL - Tooltip": "Whether to disable SSL protocol when communicating with STMP server",
|
||||
@@ -682,6 +696,8 @@
|
||||
"Method - Tooltip": "Login method, QR code or silent login",
|
||||
"New Provider": "New Provider",
|
||||
"Normal": "Normal",
|
||||
"Parameter name": "Parameter name",
|
||||
"Parameter name - Tooltip": "Parameter name - Tooltip",
|
||||
"Parse": "Parse",
|
||||
"Parse metadata successfully": "Parse metadata successfully",
|
||||
"Path prefix": "Path prefix",
|
||||
@@ -758,6 +774,8 @@
|
||||
"User mapping - Tooltip": "User mapping - Tooltip",
|
||||
"UserInfo URL": "UserInfo URL",
|
||||
"UserInfo URL - Tooltip": "UserInfo URL",
|
||||
"Wallets": "Wallets",
|
||||
"Wallets - Tooltip": "Wallets - Tooltip",
|
||||
"admin (Shared)": "admin (Shared)"
|
||||
},
|
||||
"record": {
|
||||
@@ -849,9 +867,7 @@
|
||||
"Table": "Table",
|
||||
"Table - Tooltip": "Name of database table",
|
||||
"Table columns": "Table columns",
|
||||
"Table columns - Tooltip": "Columns in the table involved in data synchronization. Columns that are not involved in synchronization do not need to be added",
|
||||
"Table primary key": "Table primary key",
|
||||
"Table primary key - Tooltip": "Table primary key, such as id"
|
||||
"Table columns - Tooltip": "Columns in the table involved in data synchronization. Columns that are not involved in synchronization do not need to be added"
|
||||
},
|
||||
"system": {
|
||||
"API Latency": "API Latency",
|
||||
|
@@ -11,6 +11,7 @@
|
||||
"New Adapter": "Novo Adaptador",
|
||||
"Policies": "Políticas",
|
||||
"Policies - Tooltip": "Regras de política do Casbin",
|
||||
"Rule type": "Rule type",
|
||||
"Sync policies successfully": "Políticas sincronizadas com sucesso"
|
||||
},
|
||||
"application": {
|
||||
@@ -353,6 +354,13 @@
|
||||
"Show all": "Show all",
|
||||
"Virtual": "Virtual"
|
||||
},
|
||||
"home": {
|
||||
"New users past 30 days": "New users past 30 days",
|
||||
"New users past 7 days": "New users past 7 days",
|
||||
"New users today": "New users today",
|
||||
"Past 30 Days": "Past 30 Days",
|
||||
"Total users": "Total users"
|
||||
},
|
||||
"ldap": {
|
||||
"Admin": "Administrador",
|
||||
"Admin - Tooltip": "CN ou ID do administrador do servidor LDAP",
|
||||
@@ -388,6 +396,7 @@
|
||||
"Continue with": "Continuar com",
|
||||
"Email or phone": "Email ou telefone",
|
||||
"Failed to obtain MetaMask authorization": "Failed to obtain MetaMask authorization",
|
||||
"Failed to obtain Web3-Onboard authorization": "Failed to obtain Web3-Onboard authorization",
|
||||
"Forgot password?": "Esqueceu a senha?",
|
||||
"Loading": "Carregando",
|
||||
"Logging out...": "Saindo...",
|
||||
@@ -431,6 +440,7 @@
|
||||
"Passcode": "Passcode",
|
||||
"Please bind your email first, the system will automatically uses the mail for multi-factor authentication": "Please bind your email first, the system will automatically uses the mail for multi-factor authentication",
|
||||
"Please bind your phone first, the system automatically uses the phone for multi-factor authentication": "Please bind your phone first, the system automatically uses the phone for multi-factor authentication",
|
||||
"Please confirm the information below": "Please confirm the information below",
|
||||
"Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code": "Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code",
|
||||
"Protect your account with Multi-factor authentication": "Protect your account with Multi-factor authentication",
|
||||
"Recovery code": "Recovery code",
|
||||
@@ -523,6 +533,7 @@
|
||||
"Return to Website": "Retornar ao Website",
|
||||
"The payment has been canceled": "The payment has been canceled",
|
||||
"The payment has failed": "O pagamento falhou",
|
||||
"The payment has time out": "The payment has time out",
|
||||
"The payment is still under processing": "O pagamento ainda está sendo processado",
|
||||
"Type - Tooltip": "Método de pagamento utilizado ao comprar o produto",
|
||||
"You have successfully completed the payment": "Você concluiu o pagamento com sucesso",
|
||||
@@ -604,6 +615,7 @@
|
||||
"SKU": "SKU",
|
||||
"Sold": "Vendido",
|
||||
"Sold - Tooltip": "Quantidade vendida",
|
||||
"Stripe": "Stripe",
|
||||
"Tag - Tooltip": "Tag do produto",
|
||||
"Test buy page..": "Página de teste de compra...",
|
||||
"There is no payment channel for this product.": "Não há canal de pagamento disponível para este produto.",
|
||||
@@ -648,6 +660,8 @@
|
||||
"Client secret - Tooltip": "Segredo do cliente",
|
||||
"Client secret 2": "Segredo do cliente 2",
|
||||
"Client secret 2 - Tooltip": "A segunda chave secreta do cliente",
|
||||
"Content": "Content",
|
||||
"Content - Tooltip": "Content - Tooltip",
|
||||
"Copy": "Copiar",
|
||||
"Disable SSL": "Desabilitar SSL",
|
||||
"Disable SSL - Tooltip": "Se deve desabilitar o protocolo SSL ao comunicar com o servidor SMTP",
|
||||
@@ -682,6 +696,8 @@
|
||||
"Method - Tooltip": "Método de login, código QR ou login silencioso",
|
||||
"New Provider": "Novo Provedor",
|
||||
"Normal": "Normal",
|
||||
"Parameter name": "Parameter name",
|
||||
"Parameter name - Tooltip": "Parameter name - Tooltip",
|
||||
"Parse": "Analisar",
|
||||
"Parse metadata successfully": "Metadados analisados com sucesso",
|
||||
"Path prefix": "Prefixo do caminho",
|
||||
@@ -758,6 +774,8 @@
|
||||
"User mapping - Tooltip": "User mapping - Tooltip",
|
||||
"UserInfo URL": "URL do UserInfo",
|
||||
"UserInfo URL - Tooltip": "URL do UserInfo",
|
||||
"Wallets": "Wallets",
|
||||
"Wallets - Tooltip": "Wallets - Tooltip",
|
||||
"admin (Shared)": "admin (Compartilhado)"
|
||||
},
|
||||
"record": {
|
||||
@@ -849,9 +867,7 @@
|
||||
"Table": "Tabela",
|
||||
"Table - Tooltip": "Nome da tabela no banco de dados",
|
||||
"Table columns": "Colunas da tabela",
|
||||
"Table columns - Tooltip": "Colunas na tabela envolvidas na sincronização de dados. Colunas que não estão envolvidas na sincronização não precisam ser adicionadas",
|
||||
"Table primary key": "Chave primária da tabela",
|
||||
"Table primary key - Tooltip": "Chave primária da tabela, como id"
|
||||
"Table columns - Tooltip": "Colunas na tabela envolvidas na sincronização de dados. Colunas que não estão envolvidas na sincronização não precisam ser adicionadas"
|
||||
},
|
||||
"system": {
|
||||
"API Latency": "Latência da API",
|
||||
|
@@ -11,6 +11,7 @@
|
||||
"New Adapter": "Новый адаптер",
|
||||
"Policies": "Политика",
|
||||
"Policies - Tooltip": "Правила политики Casbin",
|
||||
"Rule type": "Rule type",
|
||||
"Sync policies successfully": "Успешно синхронизированы политики"
|
||||
},
|
||||
"application": {
|
||||
@@ -353,6 +354,13 @@
|
||||
"Show all": "Show all",
|
||||
"Virtual": "Virtual"
|
||||
},
|
||||
"home": {
|
||||
"New users past 30 days": "New users past 30 days",
|
||||
"New users past 7 days": "New users past 7 days",
|
||||
"New users today": "New users today",
|
||||
"Past 30 Days": "Past 30 Days",
|
||||
"Total users": "Total users"
|
||||
},
|
||||
"ldap": {
|
||||
"Admin": "Admin",
|
||||
"Admin - Tooltip": "CN или ID администратора сервера LDAP",
|
||||
@@ -388,6 +396,7 @@
|
||||
"Continue with": "Продолжайте с",
|
||||
"Email or phone": "Электронная почта или телефон",
|
||||
"Failed to obtain MetaMask authorization": "Failed to obtain MetaMask authorization",
|
||||
"Failed to obtain Web3-Onboard authorization": "Failed to obtain Web3-Onboard authorization",
|
||||
"Forgot password?": "Забыли пароль?",
|
||||
"Loading": "Загрузка",
|
||||
"Logging out...": "Выход...",
|
||||
@@ -431,6 +440,7 @@
|
||||
"Passcode": "Passcode",
|
||||
"Please bind your email first, the system will automatically uses the mail for multi-factor authentication": "Please bind your email first, the system will automatically uses the mail for multi-factor authentication",
|
||||
"Please bind your phone first, the system automatically uses the phone for multi-factor authentication": "Please bind your phone first, the system automatically uses the phone for multi-factor authentication",
|
||||
"Please confirm the information below": "Please confirm the information below",
|
||||
"Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code": "Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code",
|
||||
"Protect your account with Multi-factor authentication": "Protect your account with Multi-factor authentication",
|
||||
"Recovery code": "Recovery code",
|
||||
@@ -523,6 +533,7 @@
|
||||
"Return to Website": "Вернуться на веб-сайт",
|
||||
"The payment has been canceled": "The payment has been canceled",
|
||||
"The payment has failed": "Оплата не удалась",
|
||||
"The payment has time out": "The payment has time out",
|
||||
"The payment is still under processing": "Оплата все еще обрабатывается",
|
||||
"Type - Tooltip": "Способ оплаты, используемый при покупке товара",
|
||||
"You have successfully completed the payment": "Вы успешно произвели платеж",
|
||||
@@ -604,6 +615,7 @@
|
||||
"SKU": "SKU",
|
||||
"Sold": "Продано",
|
||||
"Sold - Tooltip": "Количество проданных",
|
||||
"Stripe": "Stripe",
|
||||
"Tag - Tooltip": "Метка продукта",
|
||||
"Test buy page..": "Страница для тестовой покупки.",
|
||||
"There is no payment channel for this product.": "Для этого продукта нет канала оплаты.",
|
||||
@@ -648,6 +660,8 @@
|
||||
"Client secret - Tooltip": "Клиентский секрет",
|
||||
"Client secret 2": "Секрет клиента 2",
|
||||
"Client secret 2 - Tooltip": "Второй секретный ключ клиента",
|
||||
"Content": "Content",
|
||||
"Content - Tooltip": "Content - Tooltip",
|
||||
"Copy": "Копировать",
|
||||
"Disable SSL": "Отключить SSL",
|
||||
"Disable SSL - Tooltip": "Нужно ли отключать протокол SSL при общении с SMTP сервером?",
|
||||
@@ -682,6 +696,8 @@
|
||||
"Method - Tooltip": "Метод входа, QR-код или беззвучный вход",
|
||||
"New Provider": "Новый провайдер",
|
||||
"Normal": "Normal",
|
||||
"Parameter name": "Parameter name",
|
||||
"Parameter name - Tooltip": "Parameter name - Tooltip",
|
||||
"Parse": "Спарсить",
|
||||
"Parse metadata successfully": "Успешно обработана метаданные",
|
||||
"Path prefix": "Префикс пути",
|
||||
@@ -758,6 +774,8 @@
|
||||
"User mapping - Tooltip": "User mapping - Tooltip",
|
||||
"UserInfo URL": "URL информации о пользователе",
|
||||
"UserInfo URL - Tooltip": "URL пользовательской информации (URL информации о пользователе)",
|
||||
"Wallets": "Wallets",
|
||||
"Wallets - Tooltip": "Wallets - Tooltip",
|
||||
"admin (Shared)": "администратор (общий)"
|
||||
},
|
||||
"record": {
|
||||
@@ -849,9 +867,7 @@
|
||||
"Table": "Стол",
|
||||
"Table - Tooltip": "Название таблицы базы данных",
|
||||
"Table columns": "Столбцы таблицы",
|
||||
"Table columns - Tooltip": "Столбцы в таблице, участвующие в синхронизации данных. Столбцы, не участвующие в синхронизации, не нужно добавлять",
|
||||
"Table primary key": "Первичный ключ таблицы",
|
||||
"Table primary key - Tooltip": "Идентификатор (id) - основной ключ таблицы"
|
||||
"Table columns - Tooltip": "Столбцы в таблице, участвующие в синхронизации данных. Столбцы, не участвующие в синхронизации, не нужно добавлять"
|
||||
},
|
||||
"system": {
|
||||
"API Latency": "Задержка API",
|
||||
|
@@ -11,6 +11,7 @@
|
||||
"New Adapter": "New Adapter",
|
||||
"Policies": "Policies",
|
||||
"Policies - Tooltip": "Casbin policy rules",
|
||||
"Rule type": "Rule type",
|
||||
"Sync policies successfully": "Sync policies successfully"
|
||||
},
|
||||
"application": {
|
||||
@@ -353,6 +354,13 @@
|
||||
"Show all": "Show all",
|
||||
"Virtual": "Virtual"
|
||||
},
|
||||
"home": {
|
||||
"New users past 30 days": "New users past 30 days",
|
||||
"New users past 7 days": "New users past 7 days",
|
||||
"New users today": "New users today",
|
||||
"Past 30 Days": "Past 30 Days",
|
||||
"Total users": "Total users"
|
||||
},
|
||||
"ldap": {
|
||||
"Admin": "Admin",
|
||||
"Admin - Tooltip": "CN or ID of the LDAP server administrator",
|
||||
@@ -388,6 +396,7 @@
|
||||
"Continue with": "Continue with",
|
||||
"Email or phone": "Email or phone",
|
||||
"Failed to obtain MetaMask authorization": "Failed to obtain MetaMask authorization",
|
||||
"Failed to obtain Web3-Onboard authorization": "Failed to obtain Web3-Onboard authorization",
|
||||
"Forgot password?": "Forgot password?",
|
||||
"Loading": "Loading",
|
||||
"Logging out...": "Logging out...",
|
||||
@@ -431,6 +440,7 @@
|
||||
"Passcode": "Passcode",
|
||||
"Please bind your email first, the system will automatically uses the mail for multi-factor authentication": "Please bind your email first, the system will automatically uses the mail for multi-factor authentication",
|
||||
"Please bind your phone first, the system automatically uses the phone for multi-factor authentication": "Please bind your phone first, the system automatically uses the phone for multi-factor authentication",
|
||||
"Please confirm the information below": "Please confirm the information below",
|
||||
"Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code": "Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code",
|
||||
"Protect your account with Multi-factor authentication": "Protect your account with Multi-factor authentication",
|
||||
"Recovery code": "Recovery code",
|
||||
@@ -523,6 +533,7 @@
|
||||
"Return to Website": "Return to Website",
|
||||
"The payment has been canceled": "The payment has been canceled",
|
||||
"The payment has failed": "The payment has failed",
|
||||
"The payment has time out": "The payment has time out",
|
||||
"The payment is still under processing": "The payment is still under processing",
|
||||
"Type - Tooltip": "Payment method used when purchasing the product",
|
||||
"You have successfully completed the payment": "You have successfully completed the payment",
|
||||
@@ -604,6 +615,7 @@
|
||||
"SKU": "SKU",
|
||||
"Sold": "Sold",
|
||||
"Sold - Tooltip": "Quantity sold",
|
||||
"Stripe": "Stripe",
|
||||
"Tag - Tooltip": "Tag of product",
|
||||
"Test buy page..": "Test buy page..",
|
||||
"There is no payment channel for this product.": "There is no payment channel for this product.",
|
||||
@@ -648,6 +660,8 @@
|
||||
"Client secret - Tooltip": "Client secret",
|
||||
"Client secret 2": "Client secret 2",
|
||||
"Client secret 2 - Tooltip": "The second client secret key",
|
||||
"Content": "Content",
|
||||
"Content - Tooltip": "Content - Tooltip",
|
||||
"Copy": "Copy",
|
||||
"Disable SSL": "Disable SSL",
|
||||
"Disable SSL - Tooltip": "Whether to disable SSL protocol when communicating with STMP server",
|
||||
@@ -682,6 +696,8 @@
|
||||
"Method - Tooltip": "Login method, QR code or silent login",
|
||||
"New Provider": "New Provider",
|
||||
"Normal": "Normal",
|
||||
"Parameter name": "Parameter name",
|
||||
"Parameter name - Tooltip": "Parameter name - Tooltip",
|
||||
"Parse": "Parse",
|
||||
"Parse metadata successfully": "Parse metadata successfully",
|
||||
"Path prefix": "Path prefix",
|
||||
@@ -758,6 +774,8 @@
|
||||
"User mapping - Tooltip": "User mapping - Tooltip",
|
||||
"UserInfo URL": "UserInfo URL",
|
||||
"UserInfo URL - Tooltip": "UserInfo URL",
|
||||
"Wallets": "Wallets",
|
||||
"Wallets - Tooltip": "Wallets - Tooltip",
|
||||
"admin (Shared)": "admin (Shared)"
|
||||
},
|
||||
"record": {
|
||||
@@ -849,9 +867,7 @@
|
||||
"Table": "Table",
|
||||
"Table - Tooltip": "Name of database table",
|
||||
"Table columns": "Table columns",
|
||||
"Table columns - Tooltip": "Columns in the table involved in data synchronization. Columns that are not involved in synchronization do not need to be added",
|
||||
"Table primary key": "Table primary key",
|
||||
"Table primary key - Tooltip": "Table primary key, such as id"
|
||||
"Table columns - Tooltip": "Columns in the table involved in data synchronization. Columns that are not involved in synchronization do not need to be added"
|
||||
},
|
||||
"system": {
|
||||
"API Latency": "API Latency",
|
||||
|
@@ -11,6 +11,7 @@
|
||||
"New Adapter": "Bộ chuyển đổi mới",
|
||||
"Policies": "Chính sách",
|
||||
"Policies - Tooltip": "Quy tắc chính sách Casbin",
|
||||
"Rule type": "Rule type",
|
||||
"Sync policies successfully": "Đồng bộ chính sách thành công"
|
||||
},
|
||||
"application": {
|
||||
@@ -353,6 +354,13 @@
|
||||
"Show all": "Show all",
|
||||
"Virtual": "Virtual"
|
||||
},
|
||||
"home": {
|
||||
"New users past 30 days": "New users past 30 days",
|
||||
"New users past 7 days": "New users past 7 days",
|
||||
"New users today": "New users today",
|
||||
"Past 30 Days": "Past 30 Days",
|
||||
"Total users": "Total users"
|
||||
},
|
||||
"ldap": {
|
||||
"Admin": "Admin",
|
||||
"Admin - Tooltip": "CN hoặc ID của quản trị viên máy chủ LDAP",
|
||||
@@ -388,6 +396,7 @@
|
||||
"Continue with": "Tiếp tục với",
|
||||
"Email or phone": "Email hoặc điện thoại",
|
||||
"Failed to obtain MetaMask authorization": "Failed to obtain MetaMask authorization",
|
||||
"Failed to obtain Web3-Onboard authorization": "Failed to obtain Web3-Onboard authorization",
|
||||
"Forgot password?": "Quên mật khẩu?",
|
||||
"Loading": "Đang tải",
|
||||
"Logging out...": "Đăng xuất ...",
|
||||
@@ -431,6 +440,7 @@
|
||||
"Passcode": "Passcode",
|
||||
"Please bind your email first, the system will automatically uses the mail for multi-factor authentication": "Please bind your email first, the system will automatically uses the mail for multi-factor authentication",
|
||||
"Please bind your phone first, the system automatically uses the phone for multi-factor authentication": "Please bind your phone first, the system automatically uses the phone for multi-factor authentication",
|
||||
"Please confirm the information below": "Please confirm the information below",
|
||||
"Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code": "Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code",
|
||||
"Protect your account with Multi-factor authentication": "Protect your account with Multi-factor authentication",
|
||||
"Recovery code": "Recovery code",
|
||||
@@ -523,6 +533,7 @@
|
||||
"Return to Website": "Trở lại trang web",
|
||||
"The payment has been canceled": "The payment has been canceled",
|
||||
"The payment has failed": "Thanh toán đã thất bại",
|
||||
"The payment has time out": "The payment has time out",
|
||||
"The payment is still under processing": "Thanh toán vẫn đang được xử lý",
|
||||
"Type - Tooltip": "Phương thức thanh toán được sử dụng khi mua sản phẩm",
|
||||
"You have successfully completed the payment": "Bạn đã hoàn thành thanh toán thành công",
|
||||
@@ -604,6 +615,7 @@
|
||||
"SKU": "SKU",
|
||||
"Sold": "Đã bán",
|
||||
"Sold - Tooltip": "Số lượng bán ra",
|
||||
"Stripe": "Stripe",
|
||||
"Tag - Tooltip": "Nhãn sản phẩm",
|
||||
"Test buy page..": "Trang mua thử.",
|
||||
"There is no payment channel for this product.": "Không có kênh thanh toán cho sản phẩm này.",
|
||||
@@ -648,6 +660,8 @@
|
||||
"Client secret - Tooltip": "Mã bí mật khách hàng",
|
||||
"Client secret 2": "Khóa bí mật của khách hàng 2",
|
||||
"Client secret 2 - Tooltip": "Khóa bí mật thứ hai của khách hàng",
|
||||
"Content": "Content",
|
||||
"Content - Tooltip": "Content - Tooltip",
|
||||
"Copy": "Sao chép",
|
||||
"Disable SSL": "Vô hiệu hóa SSL",
|
||||
"Disable SSL - Tooltip": "Có nên vô hiệu hóa giao thức SSL khi giao tiếp với máy chủ STMP hay không?",
|
||||
@@ -682,6 +696,8 @@
|
||||
"Method - Tooltip": "Phương thức đăng nhập, mã QR hoặc đăng nhập im lặng",
|
||||
"New Provider": "Nhà cung cấp mới",
|
||||
"Normal": "Normal",
|
||||
"Parameter name": "Parameter name",
|
||||
"Parameter name - Tooltip": "Parameter name - Tooltip",
|
||||
"Parse": "Phân tích cú pháp",
|
||||
"Parse metadata successfully": "Phân tích siêu dữ liệu thành công",
|
||||
"Path prefix": "Tiền tố đường dẫn",
|
||||
@@ -758,6 +774,8 @@
|
||||
"User mapping - Tooltip": "User mapping - Tooltip",
|
||||
"UserInfo URL": "Đường dẫn UserInfo",
|
||||
"UserInfo URL - Tooltip": "Địa chỉ URL của Thông tin người dùng",
|
||||
"Wallets": "Wallets",
|
||||
"Wallets - Tooltip": "Wallets - Tooltip",
|
||||
"admin (Shared)": "quản trị viên (Chung)"
|
||||
},
|
||||
"record": {
|
||||
@@ -849,9 +867,7 @@
|
||||
"Table": "Bàn",
|
||||
"Table - Tooltip": "Tên của bảng cơ sở dữ liệu",
|
||||
"Table columns": "Các cột bảng",
|
||||
"Table columns - Tooltip": "Cột trong bảng liên quan đến đồng bộ dữ liệu. Các cột không liên quan đến đồng bộ hóa không cần được thêm vào",
|
||||
"Table primary key": "Khóa chính của bảng",
|
||||
"Table primary key - Tooltip": "Khóa chính của bảng, ví dụ như id"
|
||||
"Table columns - Tooltip": "Cột trong bảng liên quan đến đồng bộ dữ liệu. Các cột không liên quan đến đồng bộ hóa không cần được thêm vào"
|
||||
},
|
||||
"system": {
|
||||
"API Latency": "Độ trễ API",
|
||||
|
@@ -11,6 +11,7 @@
|
||||
"New Adapter": "添加适配器",
|
||||
"Policies": "策略",
|
||||
"Policies - Tooltip": "Casbin策略规则",
|
||||
"Rule type": "策略类型",
|
||||
"Sync policies successfully": "同步策略成功"
|
||||
},
|
||||
"application": {
|
||||
@@ -353,6 +354,13 @@
|
||||
"Show all": "显示全部",
|
||||
"Virtual": "虚拟组"
|
||||
},
|
||||
"home": {
|
||||
"New users past 30 days": "New users past 30 days",
|
||||
"New users past 7 days": "New users past 7 days",
|
||||
"New users today": "New users today",
|
||||
"Past 30 Days": "Past 30 Days",
|
||||
"Total users": "Total users"
|
||||
},
|
||||
"ldap": {
|
||||
"Admin": "管理员",
|
||||
"Admin - Tooltip": "LDAP服务器管理员的CN或ID",
|
||||
@@ -388,6 +396,7 @@
|
||||
"Continue with": "使用以下账号继续",
|
||||
"Email or phone": "Email或手机号",
|
||||
"Failed to obtain MetaMask authorization": "获取MetaMask授权失败",
|
||||
"Failed to obtain Web3-Onboard authorization": "Failed to obtain Web3-Onboard authorization",
|
||||
"Forgot password?": "忘记密码?",
|
||||
"Loading": "加载中",
|
||||
"Logging out...": "正在退出登录...",
|
||||
@@ -431,6 +440,7 @@
|
||||
"Passcode": "认证码",
|
||||
"Please bind your email first, the system will automatically uses the mail for multi-factor authentication": "请先绑定邮箱,之后会自动使用该邮箱作为多因素认证的方式",
|
||||
"Please bind your phone first, the system automatically uses the phone for multi-factor authentication": "请先绑定手机号,之后会自动使用该手机号作为多因素认证的方式",
|
||||
"Please confirm the information below": "请确认以下信息",
|
||||
"Please save this recovery code. Once your device cannot provide an authentication code, you can reset mfa authentication by this recovery code": "请保存此恢复代码。一旦您的设备无法提供身份验证码,您可以通过此恢复码重置多因素认证",
|
||||
"Protect your account with Multi-factor authentication": "通过多因素认证保护您的帐户",
|
||||
"Recovery code": "恢复码",
|
||||
@@ -523,6 +533,7 @@
|
||||
"Return to Website": "返回原网站",
|
||||
"The payment has been canceled": "付款已取消",
|
||||
"The payment has failed": "支付失败",
|
||||
"The payment has time out": "The payment has time out",
|
||||
"The payment is still under processing": "支付正在处理",
|
||||
"Type - Tooltip": "商品购买时的支付方式",
|
||||
"You have successfully completed the payment": "支付成功",
|
||||
@@ -604,6 +615,7 @@
|
||||
"SKU": "货号",
|
||||
"Sold": "售出",
|
||||
"Sold - Tooltip": "已售出的数量",
|
||||
"Stripe": "Stripe",
|
||||
"Tag - Tooltip": "商品类别",
|
||||
"Test buy page..": "测试购买页面..",
|
||||
"There is no payment channel for this product.": "该商品没有付款方式。",
|
||||
@@ -648,6 +660,8 @@
|
||||
"Client secret - Tooltip": "Client secret",
|
||||
"Client secret 2": "Client secret 2",
|
||||
"Client secret 2 - Tooltip": "第二个Client secret",
|
||||
"Content": "Content",
|
||||
"Content - Tooltip": "Content - Tooltip",
|
||||
"Copy": "复制",
|
||||
"Disable SSL": "禁用SSL",
|
||||
"Disable SSL - Tooltip": "与STMP服务器通信时是否禁用SSL协议",
|
||||
@@ -682,6 +696,8 @@
|
||||
"Method - Tooltip": "登录方法,二维码或者静默授权登录",
|
||||
"New Provider": "添加提供商",
|
||||
"Normal": "标准",
|
||||
"Parameter name": "Parameter name",
|
||||
"Parameter name - Tooltip": "Parameter name - Tooltip",
|
||||
"Parse": "解析",
|
||||
"Parse metadata successfully": "解析元数据成功",
|
||||
"Path prefix": "路径前缀",
|
||||
@@ -758,6 +774,8 @@
|
||||
"User mapping - Tooltip": "User mapping - Tooltip",
|
||||
"UserInfo URL": "UserInfo URL",
|
||||
"UserInfo URL - Tooltip": "自定义OAuth的UserInfo URL",
|
||||
"Wallets": "Wallets",
|
||||
"Wallets - Tooltip": "Wallets - Tooltip",
|
||||
"admin (Shared)": "admin(共享)"
|
||||
},
|
||||
"record": {
|
||||
@@ -849,9 +867,7 @@
|
||||
"Table": "表名",
|
||||
"Table - Tooltip": "数据库表名",
|
||||
"Table columns": "表格列",
|
||||
"Table columns - Tooltip": "参与数据同步的表格列,不参与同步的列不需要添加",
|
||||
"Table primary key": "表主键",
|
||||
"Table primary key - Tooltip": "表主键,如id等"
|
||||
"Table columns - Tooltip": "参与数据同步的表格列,不参与同步的列不需要添加"
|
||||
},
|
||||
"system": {
|
||||
"API Latency": "API 延迟",
|
||||
|
@@ -33,11 +33,11 @@ class PolicyTable extends React.Component {
|
||||
}
|
||||
|
||||
count = 0;
|
||||
pageSize = 10;
|
||||
pageSize = 100;
|
||||
|
||||
getIndex(index) {
|
||||
// Need to be used in all place when modify table. Parameter is the row index in table, need to calculate the index in dataSource.
|
||||
return index + (this.state.page - 1) * 10;
|
||||
return index + (this.state.page - 1) * this.pageSize;
|
||||
}
|
||||
|
||||
UNSAFE_componentWillMount() {
|
||||
@@ -165,7 +165,7 @@ class PolicyTable extends React.Component {
|
||||
renderTable(table) {
|
||||
const columns = [
|
||||
{
|
||||
title: "Rule Type",
|
||||
title: i18next.t("adapter:Rule type"),
|
||||
dataIndex: "Ptype",
|
||||
width: "100px",
|
||||
// render: (text, record, index) => {
|
||||
@@ -270,8 +270,9 @@ class PolicyTable extends React.Component {
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "Option",
|
||||
key: "option",
|
||||
title: i18next.t("general:Action"),
|
||||
dataIndex: "",
|
||||
key: "op",
|
||||
width: "100px",
|
||||
render: (text, record, index) => {
|
||||
const editable = this.isEditing(index);
|
||||
@@ -304,7 +305,6 @@ class PolicyTable extends React.Component {
|
||||
onChange: (page) => this.setState({
|
||||
page: page,
|
||||
}),
|
||||
disabled: this.state.editingIndex !== "" || Setting.builtInObject({owner: this.props.owner, name: this.props.name}),
|
||||
current: this.state.page,
|
||||
}}
|
||||
columns={columns} dataSource={table} rowKey="key" size="middle" bordered
|
||||
|
2449
web/yarn.lock
2449
web/yarn.lock
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user