mirror of
https://github.com/casdoor/casdoor.git
synced 2025-07-18 14:43:49 +08:00
Compare commits
28 Commits
Author | SHA1 | Date | |
---|---|---|---|
8ebd16a14e | |||
44ec854465 | |||
26e87b0d98 | |||
7e0ea0b8d9 | |||
ace8e9da06 | |||
aac8714d72 | |||
e71e41b343 | |||
6131286cbd | |||
3bda8fb9dc | |||
11f55a474c | |||
4806e76cf6 | |||
edbd3d4018 | |||
3f0a741e6c | |||
d273fdd670 | |||
3ae81716b9 | |||
3a70f4e788 | |||
842d4865b2 | |||
19fb7273bb | |||
943bd82731 | |||
f2f962b893 | |||
eb72c9f273 | |||
4605938f8e | |||
14fa914e6f | |||
e877045671 | |||
29f1ec08a2 | |||
389744a27d | |||
dc7b66822d | |||
efacf8226c |
17
.github/workflows/build.yml
vendored
17
.github/workflows/build.yml
vendored
@ -97,21 +97,20 @@ jobs:
|
|||||||
- uses: actions/setup-node@v2
|
- uses: actions/setup-node@v2
|
||||||
with:
|
with:
|
||||||
node-version: 16
|
node-version: 16
|
||||||
|
- name: back start
|
||||||
|
run: nohup go run ./main.go &
|
||||||
|
working-directory: ./
|
||||||
- name: front install
|
- name: front install
|
||||||
run: yarn install
|
run: yarn install
|
||||||
working-directory: ./web
|
working-directory: ./web
|
||||||
- name: front start
|
- name: front start
|
||||||
run: nohup yarn start &
|
run: nohup yarn start &
|
||||||
working-directory: ./web
|
working-directory: ./web
|
||||||
- name: back start
|
- uses: cypress-io/github-action@v4
|
||||||
run: nohup go run ./main.go &
|
with:
|
||||||
working-directory: ./
|
working-directory: ./web
|
||||||
- name: Sleep for starting
|
wait-on: 'http://localhost:7001'
|
||||||
run: sleep 90s
|
wait-on-timeout: 180
|
||||||
shell: bash
|
|
||||||
- name: e2e
|
|
||||||
run: npx cypress run --spec "**/e2e/**.cy.js"
|
|
||||||
working-directory: ./web
|
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v3
|
- uses: actions/upload-artifact@v3
|
||||||
if: failure()
|
if: failure()
|
||||||
|
@ -21,19 +21,21 @@ type CaptchaProvider interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func GetCaptchaProvider(captchaType string) CaptchaProvider {
|
func GetCaptchaProvider(captchaType string) CaptchaProvider {
|
||||||
if captchaType == "Default" {
|
switch captchaType {
|
||||||
|
case "Default":
|
||||||
return NewDefaultCaptchaProvider()
|
return NewDefaultCaptchaProvider()
|
||||||
} else if captchaType == "reCAPTCHA" {
|
case "reCAPTCHA":
|
||||||
return NewReCaptchaProvider()
|
return NewReCaptchaProvider()
|
||||||
} else if captchaType == "hCaptcha" {
|
case "Aliyun Captcha":
|
||||||
return NewHCaptchaProvider()
|
|
||||||
} else if captchaType == "Aliyun Captcha" {
|
|
||||||
return NewAliyunCaptchaProvider()
|
return NewAliyunCaptchaProvider()
|
||||||
} else if captchaType == "GEETEST" {
|
case "hCaptcha":
|
||||||
|
return NewHCaptchaProvider()
|
||||||
|
case "GEETEST":
|
||||||
return NewGEETESTCaptchaProvider()
|
return NewGEETESTCaptchaProvider()
|
||||||
} else if captchaType == "Cloudflare Turnstile" {
|
case "Cloudflare Turnstile":
|
||||||
return NewCloudflareTurnstileProvider()
|
return NewCloudflareTurnstileProvider()
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,5 +20,5 @@ staticBaseUrl = "https://cdn.casbin.org"
|
|||||||
isDemoMode = false
|
isDemoMode = false
|
||||||
batchSize = 100
|
batchSize = 100
|
||||||
ldapServerPort = 389
|
ldapServerPort = 389
|
||||||
languages = en,zh,es,fr,de,ja,ko,ru
|
languages = en,zh,es,fr,de,ja,ko,ru,vi
|
||||||
quota = {"organization": -1, "user": -1, "application": -1, "provider": -1}
|
quota = {"organization": -1, "user": -1, "application": -1, "provider": -1}
|
||||||
|
14
conf/conf.go
14
conf/conf.go
@ -105,6 +105,20 @@ func GetConfigDataSourceName() string {
|
|||||||
return dataSourceName
|
return dataSourceName
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetLanguage(language string) string {
|
||||||
|
if language == "" {
|
||||||
|
return "en"
|
||||||
|
}
|
||||||
|
|
||||||
|
language = language[0:2]
|
||||||
|
|
||||||
|
if strings.Contains(GetConfigString("languages"), language) {
|
||||||
|
return language
|
||||||
|
} else {
|
||||||
|
return "en"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func IsDemoMode() bool {
|
func IsDemoMode() bool {
|
||||||
return strings.ToLower(GetConfigString("isDemoMode")) == "true"
|
return strings.ToLower(GetConfigString("isDemoMode")) == "true"
|
||||||
}
|
}
|
||||||
|
@ -58,7 +58,7 @@ type RequestForm struct {
|
|||||||
|
|
||||||
EmailCode string `json:"emailCode"`
|
EmailCode string `json:"emailCode"`
|
||||||
PhoneCode string `json:"phoneCode"`
|
PhoneCode string `json:"phoneCode"`
|
||||||
PhonePrefix string `json:"phonePrefix"`
|
CountryCode string `json:"countryCode"`
|
||||||
|
|
||||||
AutoSignin bool `json:"autoSignin"`
|
AutoSignin bool `json:"autoSignin"`
|
||||||
|
|
||||||
@ -121,7 +121,7 @@ func (c *ApiController) Signup() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
organization := object.GetOrganization(fmt.Sprintf("%s/%s", "admin", form.Organization))
|
organization := object.GetOrganization(fmt.Sprintf("%s/%s", "admin", form.Organization))
|
||||||
msg := object.CheckUserSignup(application, organization, form.Username, form.Password, form.Name, form.FirstName, form.LastName, form.Email, form.Phone, form.Affiliation, c.GetAcceptLanguage())
|
msg := object.CheckUserSignup(application, organization, form.Username, form.Password, form.Name, form.FirstName, form.LastName, form.Email, form.Phone, form.CountryCode, form.Affiliation, c.GetAcceptLanguage())
|
||||||
if msg != "" {
|
if msg != "" {
|
||||||
c.ResponseError(msg)
|
c.ResponseError(msg)
|
||||||
return
|
return
|
||||||
@ -137,7 +137,7 @@ func (c *ApiController) Signup() {
|
|||||||
|
|
||||||
var checkPhone string
|
var checkPhone string
|
||||||
if application.IsSignupItemVisible("Phone") && form.Phone != "" {
|
if application.IsSignupItemVisible("Phone") && form.Phone != "" {
|
||||||
checkPhone = fmt.Sprintf("+%s%s", form.PhonePrefix, form.Phone)
|
checkPhone, _ = util.GetE164Number(form.Phone, form.CountryCode)
|
||||||
checkResult := object.CheckVerificationCode(checkPhone, form.PhoneCode, c.GetAcceptLanguage())
|
checkResult := object.CheckVerificationCode(checkPhone, form.PhoneCode, c.GetAcceptLanguage())
|
||||||
if len(checkResult) != 0 {
|
if len(checkResult) != 0 {
|
||||||
c.ResponseError(c.T("account:Phone: %s"), checkResult)
|
c.ResponseError(c.T("account:Phone: %s"), checkResult)
|
||||||
@ -179,6 +179,7 @@ func (c *ApiController) Signup() {
|
|||||||
Avatar: organization.DefaultAvatar,
|
Avatar: organization.DefaultAvatar,
|
||||||
Email: form.Email,
|
Email: form.Email,
|
||||||
Phone: form.Phone,
|
Phone: form.Phone,
|
||||||
|
CountryCode: form.CountryCode,
|
||||||
Address: []string{},
|
Address: []string{},
|
||||||
Affiliation: form.Affiliation,
|
Affiliation: form.Affiliation,
|
||||||
IdCard: form.IdCard,
|
IdCard: form.IdCard,
|
||||||
@ -255,7 +256,9 @@ func (c *ApiController) Logout() {
|
|||||||
if accessToken == "" && redirectUri == "" {
|
if accessToken == "" && redirectUri == "" {
|
||||||
c.ClearUserSession()
|
c.ClearUserSession()
|
||||||
// TODO https://github.com/casdoor/casdoor/pull/1494#discussion_r1095675265
|
// TODO https://github.com/casdoor/casdoor/pull/1494#discussion_r1095675265
|
||||||
object.DeleteSessionId(util.GetSessionId(object.CasdoorOrganization, object.CasdoorApplication, user), c.Ctx.Input.CruSession.SessionID())
|
owner, username := util.GetOwnerAndNameFromId(user)
|
||||||
|
|
||||||
|
object.DeleteSessionId(util.GetSessionId(owner, username, object.CasdoorApplication), c.Ctx.Input.CruSession.SessionID())
|
||||||
util.LogInfo(c.Ctx, "API: [%s] logged out", user)
|
util.LogInfo(c.Ctx, "API: [%s] logged out", user)
|
||||||
|
|
||||||
application := c.GetSessionApplication()
|
application := c.GetSessionApplication()
|
||||||
|
@ -263,34 +263,32 @@ func (c *ApiController) Login() {
|
|||||||
checkDest = form.Username
|
checkDest = form.Username
|
||||||
} else {
|
} else {
|
||||||
verificationCodeType = "phone"
|
verificationCodeType = "phone"
|
||||||
if len(form.PhonePrefix) == 0 {
|
|
||||||
responseText := fmt.Sprintf(c.T("auth:%s No phone prefix"), verificationCodeType)
|
|
||||||
c.ResponseError(responseText)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if user != nil && util.GetMaskedPhone(user.Phone) == form.Username {
|
if user != nil && util.GetMaskedPhone(user.Phone) == form.Username {
|
||||||
form.Username = user.Phone
|
form.Username = user.Phone
|
||||||
}
|
}
|
||||||
checkDest = fmt.Sprintf("+%s%s", form.PhonePrefix, form.Username)
|
|
||||||
}
|
}
|
||||||
user = object.GetUserByFields(form.Organization, form.Username)
|
|
||||||
if user == nil {
|
if user = object.GetUserByFields(form.Organization, form.Username); user == nil {
|
||||||
c.ResponseError(fmt.Sprintf(c.T("general:The user: %s doesn't exist"), util.GetId(form.Organization, form.Username)))
|
c.ResponseError(fmt.Sprintf(c.T("general:The user: %s doesn't exist"), util.GetId(form.Organization, form.Username)))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if verificationCodeType == "phone" {
|
||||||
|
form.CountryCode = user.GetCountryCode(form.CountryCode)
|
||||||
|
var ok bool
|
||||||
|
if checkDest, ok = util.GetE164Number(form.Username, form.CountryCode); !ok {
|
||||||
|
c.ResponseError(fmt.Sprintf(c.T("verification:Phone number is invalid in your region %s"), form.CountryCode))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
checkResult = object.CheckSigninCode(user, checkDest, form.Code, c.GetAcceptLanguage())
|
checkResult = object.CheckSigninCode(user, checkDest, form.Code, c.GetAcceptLanguage())
|
||||||
if len(checkResult) != 0 {
|
if len(checkResult) != 0 {
|
||||||
responseText := fmt.Sprintf("%s - %s", verificationCodeType, checkResult)
|
c.ResponseError(fmt.Sprintf("%s - %s", verificationCodeType, checkResult))
|
||||||
c.ResponseError(responseText)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// disable the verification code
|
// disable the verification code
|
||||||
if strings.Contains(form.Username, "@") {
|
object.DisableVerificationCode(checkDest)
|
||||||
object.DisableVerificationCode(form.Username)
|
|
||||||
} else {
|
|
||||||
object.DisableVerificationCode(fmt.Sprintf("+%s%s", form.PhonePrefix, form.Username))
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
application := object.GetApplication(fmt.Sprintf("admin/%s", form.Application))
|
application := object.GetApplication(fmt.Sprintf("admin/%s", form.Application))
|
||||||
if application == nil {
|
if application == nil {
|
||||||
|
@ -51,7 +51,7 @@ type LdapSyncResp struct {
|
|||||||
func (c *ApiController) GetLdapUser() {
|
func (c *ApiController) GetLdapUser() {
|
||||||
ldapServer := LdapServer{}
|
ldapServer := LdapServer{}
|
||||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &ldapServer)
|
err := json.Unmarshal(c.Ctx.Input.RequestBody, &ldapServer)
|
||||||
if err != nil || util.IsStrsEmpty(ldapServer.Host, ldapServer.Admin, ldapServer.Passwd, ldapServer.BaseDn) {
|
if err != nil || util.IsStringsEmpty(ldapServer.Host, ldapServer.Admin, ldapServer.Passwd, ldapServer.BaseDn) {
|
||||||
c.ResponseError(c.T("general:Missing parameter"))
|
c.ResponseError(c.T("general:Missing parameter"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -104,7 +104,7 @@ func (c *ApiController) GetLdapUser() {
|
|||||||
// GetLdaps
|
// GetLdaps
|
||||||
// @Tag Account API
|
// @Tag Account API
|
||||||
// @Title GetLdaps
|
// @Title GetLdaps
|
||||||
// @router /get-ldaps [post]
|
// @router /get-ldaps [get]
|
||||||
func (c *ApiController) GetLdaps() {
|
func (c *ApiController) GetLdaps() {
|
||||||
owner := c.Input().Get("owner")
|
owner := c.Input().Get("owner")
|
||||||
|
|
||||||
@ -115,11 +115,11 @@ func (c *ApiController) GetLdaps() {
|
|||||||
// GetLdap
|
// GetLdap
|
||||||
// @Tag Account API
|
// @Tag Account API
|
||||||
// @Title GetLdap
|
// @Title GetLdap
|
||||||
// @router /get-ldap [post]
|
// @router /get-ldap [get]
|
||||||
func (c *ApiController) GetLdap() {
|
func (c *ApiController) GetLdap() {
|
||||||
id := c.Input().Get("id")
|
id := c.Input().Get("id")
|
||||||
|
|
||||||
if util.IsStrsEmpty(id) {
|
if util.IsStringsEmpty(id) {
|
||||||
c.ResponseError(c.T("general:Missing parameter"))
|
c.ResponseError(c.T("general:Missing parameter"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -140,7 +140,7 @@ func (c *ApiController) AddLdap() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if util.IsStrsEmpty(ldap.Owner, ldap.ServerName, ldap.Host, ldap.Admin, ldap.Passwd, ldap.BaseDn) {
|
if util.IsStringsEmpty(ldap.Owner, ldap.ServerName, ldap.Host, ldap.Admin, ldap.Passwd, ldap.BaseDn) {
|
||||||
c.ResponseError(c.T("general:Missing parameter"))
|
c.ResponseError(c.T("general:Missing parameter"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -170,7 +170,7 @@ func (c *ApiController) AddLdap() {
|
|||||||
func (c *ApiController) UpdateLdap() {
|
func (c *ApiController) UpdateLdap() {
|
||||||
var ldap object.Ldap
|
var ldap object.Ldap
|
||||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &ldap)
|
err := json.Unmarshal(c.Ctx.Input.RequestBody, &ldap)
|
||||||
if err != nil || util.IsStrsEmpty(ldap.Owner, ldap.ServerName, ldap.Host, ldap.Admin, ldap.Passwd, ldap.BaseDn) {
|
if err != nil || util.IsStringsEmpty(ldap.Owner, ldap.ServerName, ldap.Host, ldap.Admin, ldap.Passwd, ldap.BaseDn) {
|
||||||
c.ResponseError(c.T("general:Missing parameter"))
|
c.ResponseError(c.T("general:Missing parameter"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -80,7 +80,7 @@ func (c *ApiController) SendEmail() {
|
|||||||
c.ResponseOk()
|
c.ResponseOk()
|
||||||
}
|
}
|
||||||
|
|
||||||
if util.IsStrsEmpty(emailForm.Title, emailForm.Content, emailForm.Sender) {
|
if util.IsStringsEmpty(emailForm.Title, emailForm.Content, emailForm.Sender) {
|
||||||
c.ResponseError(fmt.Sprintf(c.T("service:Empty parameters for emailForm: %v"), emailForm))
|
c.ResponseError(fmt.Sprintf(c.T("service:Empty parameters for emailForm: %v"), emailForm))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -130,13 +130,13 @@ func (c *ApiController) SendSms() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
org := object.GetOrganization(smsForm.OrgId)
|
|
||||||
var invalidReceivers []string
|
var invalidReceivers []string
|
||||||
for idx, receiver := range smsForm.Receivers {
|
for idx, receiver := range smsForm.Receivers {
|
||||||
if !util.IsPhoneCnValid(receiver) {
|
// The receiver phone format: E164 like +8613854673829 +441932567890
|
||||||
|
if !util.IsPhoneValid(receiver, "") {
|
||||||
invalidReceivers = append(invalidReceivers, receiver)
|
invalidReceivers = append(invalidReceivers, receiver)
|
||||||
} else {
|
} else {
|
||||||
smsForm.Receivers[idx] = fmt.Sprintf("+%s%s", org.PhonePrefix, receiver)
|
smsForm.Receivers[idx] = receiver
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,6 +62,10 @@ func checkPermissionForUpdateUser(userId string, newUser object.User, c *ApiCont
|
|||||||
item := object.GetAccountItemByName("Phone", organization)
|
item := object.GetAccountItemByName("Phone", organization)
|
||||||
itemsChanged = append(itemsChanged, item)
|
itemsChanged = append(itemsChanged, item)
|
||||||
}
|
}
|
||||||
|
if oldUser.CountryCode != newUser.CountryCode {
|
||||||
|
item := object.GetAccountItemByName("Country code", organization)
|
||||||
|
itemsChanged = append(itemsChanged, item)
|
||||||
|
}
|
||||||
if oldUser.Region != newUser.Region {
|
if oldUser.Region != newUser.Region {
|
||||||
item := object.GetAccountItemByName("Country/Region", organization)
|
item := object.GetAccountItemByName("Country/Region", organization)
|
||||||
itemsChanged = append(itemsChanged, item)
|
itemsChanged = append(itemsChanged, item)
|
||||||
|
@ -17,7 +17,6 @@ package controllers
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/casdoor/casdoor/conf"
|
"github.com/casdoor/casdoor/conf"
|
||||||
"github.com/casdoor/casdoor/i18n"
|
"github.com/casdoor/casdoor/i18n"
|
||||||
@ -56,11 +55,8 @@ func (c *ApiController) T(error string) string {
|
|||||||
|
|
||||||
// GetAcceptLanguage ...
|
// GetAcceptLanguage ...
|
||||||
func (c *ApiController) GetAcceptLanguage() string {
|
func (c *ApiController) GetAcceptLanguage() string {
|
||||||
lang := c.Ctx.Request.Header.Get("Accept-Language")
|
language := c.Ctx.Request.Header.Get("Accept-Language")
|
||||||
if lang == "" || !strings.Contains(conf.GetConfigString("languages"), lang[0:2]) {
|
return conf.GetLanguage(language)
|
||||||
lang = "en"
|
|
||||||
}
|
|
||||||
return lang[0:2]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetTokenErrorHttpStatus ...
|
// SetTokenErrorHttpStatus ...
|
||||||
|
@ -24,6 +24,13 @@ import (
|
|||||||
"github.com/casdoor/casdoor/util"
|
"github.com/casdoor/casdoor/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
SignupVerification = "signup"
|
||||||
|
ResetVerification = "reset"
|
||||||
|
LoginVerification = "login"
|
||||||
|
ForgetVerification = "forget"
|
||||||
|
)
|
||||||
|
|
||||||
func (c *ApiController) getCurrentUser() *object.User {
|
func (c *ApiController) getCurrentUser() *object.User {
|
||||||
var user *object.User
|
var user *object.User
|
||||||
userId := c.GetSessionUsername()
|
userId := c.GetSessionUsername()
|
||||||
@ -42,18 +49,15 @@ func (c *ApiController) getCurrentUser() *object.User {
|
|||||||
func (c *ApiController) SendVerificationCode() {
|
func (c *ApiController) SendVerificationCode() {
|
||||||
destType := c.Ctx.Request.Form.Get("type")
|
destType := c.Ctx.Request.Form.Get("type")
|
||||||
dest := c.Ctx.Request.Form.Get("dest")
|
dest := c.Ctx.Request.Form.Get("dest")
|
||||||
|
countryCode := c.Ctx.Request.Form.Get("countryCode")
|
||||||
checkType := c.Ctx.Request.Form.Get("checkType")
|
checkType := c.Ctx.Request.Form.Get("checkType")
|
||||||
checkId := c.Ctx.Request.Form.Get("checkId")
|
checkId := c.Ctx.Request.Form.Get("checkId")
|
||||||
checkKey := c.Ctx.Request.Form.Get("checkKey")
|
checkKey := c.Ctx.Request.Form.Get("checkKey")
|
||||||
checkUser := c.Ctx.Request.Form.Get("checkUser")
|
|
||||||
applicationId := c.Ctx.Request.Form.Get("applicationId")
|
applicationId := c.Ctx.Request.Form.Get("applicationId")
|
||||||
method := c.Ctx.Request.Form.Get("method")
|
method := c.Ctx.Request.Form.Get("method")
|
||||||
|
checkUser := c.Ctx.Request.Form.Get("checkUser")
|
||||||
remoteAddr := util.GetIPFromRequest(c.Ctx.Request)
|
remoteAddr := util.GetIPFromRequest(c.Ctx.Request)
|
||||||
|
|
||||||
if destType == "" {
|
|
||||||
c.ResponseError(c.T("general:Missing parameter") + ": type.")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if dest == "" {
|
if dest == "" {
|
||||||
c.ResponseError(c.T("general:Missing parameter") + ": dest.")
|
c.ResponseError(c.T("general:Missing parameter") + ": dest.")
|
||||||
return
|
return
|
||||||
@ -62,98 +66,104 @@ func (c *ApiController) SendVerificationCode() {
|
|||||||
c.ResponseError(c.T("general:Missing parameter") + ": applicationId.")
|
c.ResponseError(c.T("general:Missing parameter") + ": applicationId.")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !strings.Contains(applicationId, "/") {
|
|
||||||
c.ResponseError(c.T("verification:Wrong parameter") + ": applicationId.")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if checkType == "" {
|
if checkType == "" {
|
||||||
c.ResponseError(c.T("general:Missing parameter") + ": checkType.")
|
c.ResponseError(c.T("general:Missing parameter") + ": checkType.")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if !strings.Contains(applicationId, "/") {
|
||||||
|
c.ResponseError(c.T("verification:Wrong parameter") + ": applicationId.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
captchaProvider := captcha.GetCaptchaProvider(checkType)
|
if checkType != "none" {
|
||||||
|
|
||||||
if captchaProvider != nil {
|
|
||||||
if checkKey == "" {
|
if checkKey == "" {
|
||||||
c.ResponseError(c.T("general:Missing parameter") + ": checkKey.")
|
c.ResponseError(c.T("general:Missing parameter") + ": checkKey.")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
isHuman, err := captchaProvider.VerifyCaptcha(checkKey, checkId)
|
|
||||||
if err != nil {
|
if captchaProvider := captcha.GetCaptchaProvider(checkType); captchaProvider == nil {
|
||||||
|
c.ResponseError(c.T("general:don't support captchaProvider: ") + checkType)
|
||||||
|
return
|
||||||
|
} else if isHuman, err := captchaProvider.VerifyCaptcha(checkKey, checkId); err != nil {
|
||||||
c.ResponseError(err.Error())
|
c.ResponseError(err.Error())
|
||||||
return
|
return
|
||||||
}
|
} else if !isHuman {
|
||||||
|
|
||||||
if !isHuman {
|
|
||||||
c.ResponseError(c.T("verification:Turing test failed."))
|
c.ResponseError(c.T("verification:Turing test failed."))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
user := c.getCurrentUser()
|
|
||||||
application := object.GetApplication(applicationId)
|
application := object.GetApplication(applicationId)
|
||||||
organization := object.GetOrganization(fmt.Sprintf("%s/%s", application.Owner, application.Organization))
|
organization := object.GetOrganization(util.GetId(application.Owner, application.Organization))
|
||||||
if organization == nil {
|
if organization == nil {
|
||||||
c.ResponseError(c.T("verification:Organization does not exist"))
|
c.ResponseError(c.T("verification:Organization does not exist"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if checkUser == "true" && user == nil && object.GetUserByFields(organization.Name, dest) == nil {
|
var user *object.User
|
||||||
c.ResponseError(c.T("general:Please login first"))
|
// checkUser != "", means method is ForgetVerification
|
||||||
return
|
if checkUser != "" {
|
||||||
|
owner := application.Organization
|
||||||
|
user = object.GetUser(util.GetId(owner, checkUser))
|
||||||
}
|
}
|
||||||
|
|
||||||
sendResp := errors.New("invalid dest type")
|
sendResp := errors.New("invalid dest type")
|
||||||
|
|
||||||
if user == nil && checkUser != "" && checkUser != "true" {
|
|
||||||
name := application.Organization
|
|
||||||
user = object.GetUser(fmt.Sprintf("%s/%s", name, checkUser))
|
|
||||||
}
|
|
||||||
switch destType {
|
switch destType {
|
||||||
case "email":
|
case "email":
|
||||||
if user != nil && util.GetMaskedEmail(user.Email) == dest {
|
|
||||||
dest = user.Email
|
|
||||||
}
|
|
||||||
if !util.IsEmailValid(dest) {
|
if !util.IsEmailValid(dest) {
|
||||||
c.ResponseError(c.T("verification:Email is invalid"))
|
c.ResponseError(c.T("verification:Email is invalid"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
userByEmail := object.GetUserByEmail(organization.Name, dest)
|
if method == LoginVerification || method == ForgetVerification {
|
||||||
if userByEmail == nil && method != "signup" && method != "reset" {
|
if user != nil && util.GetMaskedEmail(user.Email) == dest {
|
||||||
c.ResponseError(c.T("verification:the user does not exist, please sign up first"))
|
dest = user.Email
|
||||||
return
|
}
|
||||||
|
|
||||||
|
user = object.GetUserByEmail(organization.Name, dest)
|
||||||
|
if user == nil {
|
||||||
|
c.ResponseError(c.T("verification:the user does not exist, please sign up first"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else if method == ResetVerification {
|
||||||
|
user = c.getCurrentUser()
|
||||||
}
|
}
|
||||||
|
|
||||||
provider := application.GetEmailProvider()
|
provider := application.GetEmailProvider()
|
||||||
sendResp = object.SendVerificationCodeToEmail(organization, user, provider, remoteAddr, dest)
|
sendResp = object.SendVerificationCodeToEmail(organization, user, provider, remoteAddr, dest)
|
||||||
case "phone":
|
case "phone":
|
||||||
if user != nil && util.GetMaskedPhone(user.Phone) == dest {
|
if method == LoginVerification || method == ForgetVerification {
|
||||||
dest = user.Phone
|
if user != nil && util.GetMaskedPhone(user.Phone) == dest {
|
||||||
}
|
dest = user.Phone
|
||||||
if !util.IsPhoneCnValid(dest) {
|
}
|
||||||
c.ResponseError(c.T("verification:Phone number is invalid"))
|
|
||||||
return
|
if user = object.GetUserByPhone(organization.Name, dest); user == nil {
|
||||||
|
c.ResponseError(c.T("verification:the user does not exist, please sign up first"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
countryCode = user.GetCountryCode(countryCode)
|
||||||
|
} else if method == ResetVerification {
|
||||||
|
if user = c.getCurrentUser(); user != nil {
|
||||||
|
countryCode = user.GetCountryCode(countryCode)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
userByPhone := object.GetUserByPhone(organization.Name, dest)
|
|
||||||
if userByPhone == nil && method != "signup" && method != "reset" {
|
|
||||||
c.ResponseError(c.T("verification:the user does not exist, please sign up first"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
dest = fmt.Sprintf("+%s%s", organization.PhonePrefix, dest)
|
|
||||||
provider := application.GetSmsProvider()
|
provider := application.GetSmsProvider()
|
||||||
sendResp = object.SendVerificationCodeToPhone(organization, user, provider, remoteAddr, dest)
|
if phone, ok := util.GetE164Number(dest, countryCode); !ok {
|
||||||
|
c.ResponseError(fmt.Sprintf(c.T("verification:Phone number is invalid in your region %s"), countryCode))
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
sendResp = object.SendVerificationCodeToPhone(organization, user, provider, remoteAddr, phone)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if sendResp != nil {
|
if sendResp != nil {
|
||||||
c.Data["json"] = Response{Status: "error", Msg: sendResp.Error()}
|
c.ResponseError(sendResp.Error())
|
||||||
} else {
|
} else {
|
||||||
c.Data["json"] = Response{Status: "ok"}
|
c.ResponseOk()
|
||||||
}
|
}
|
||||||
|
|
||||||
c.ServeJSON()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ResetEmailOrPhone ...
|
// ResetEmailOrPhone ...
|
||||||
@ -169,7 +179,8 @@ func (c *ApiController) ResetEmailOrPhone() {
|
|||||||
destType := c.Ctx.Request.Form.Get("type")
|
destType := c.Ctx.Request.Form.Get("type")
|
||||||
dest := c.Ctx.Request.Form.Get("dest")
|
dest := c.Ctx.Request.Form.Get("dest")
|
||||||
code := c.Ctx.Request.Form.Get("code")
|
code := c.Ctx.Request.Form.Get("code")
|
||||||
if len(dest) == 0 || len(code) == 0 || len(destType) == 0 {
|
|
||||||
|
if util.IsStringsEmpty(destType, dest, code) {
|
||||||
c.ResponseError(c.T("general:Missing parameter"))
|
c.ResponseError(c.T("general:Missing parameter"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -177,7 +188,7 @@ func (c *ApiController) ResetEmailOrPhone() {
|
|||||||
checkDest := dest
|
checkDest := dest
|
||||||
organization := object.GetOrganizationByUser(user)
|
organization := object.GetOrganizationByUser(user)
|
||||||
if destType == "phone" {
|
if destType == "phone" {
|
||||||
if object.HasUserByField(user.Owner, "phone", user.Phone) {
|
if object.HasUserByField(user.Owner, "phone", dest) {
|
||||||
c.ResponseError(c.T("check:Phone already exists"))
|
c.ResponseError(c.T("check:Phone already exists"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -192,14 +203,12 @@ func (c *ApiController) ResetEmailOrPhone() {
|
|||||||
c.ResponseError(errMsg)
|
c.ResponseError(errMsg)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if checkDest, ok = util.GetE164Number(dest, user.GetCountryCode("")); !ok {
|
||||||
phonePrefix := "86"
|
c.ResponseError(fmt.Sprintf(c.T("verification:Phone number is invalid in your region %s"), user.CountryCode))
|
||||||
if organization != nil && organization.PhonePrefix != "" {
|
return
|
||||||
phonePrefix = organization.PhonePrefix
|
|
||||||
}
|
}
|
||||||
checkDest = fmt.Sprintf("+%s%s", phonePrefix, dest)
|
|
||||||
} else if destType == "email" {
|
} else if destType == "email" {
|
||||||
if object.HasUserByField(user.Owner, "email", user.Email) {
|
if object.HasUserByField(user.Owner, "email", dest) {
|
||||||
c.ResponseError(c.T("check:Email already exists"))
|
c.ResponseError(c.T("check:Email already exists"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -215,8 +224,8 @@ func (c *ApiController) ResetEmailOrPhone() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ret := object.CheckVerificationCode(checkDest, code, c.GetAcceptLanguage()); len(ret) != 0 {
|
if msg := object.CheckVerificationCode(checkDest, code, c.GetAcceptLanguage()); len(msg) != 0 {
|
||||||
c.ResponseError(ret)
|
c.ResponseError(msg)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -233,8 +242,7 @@ func (c *ApiController) ResetEmailOrPhone() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
object.DisableVerificationCode(checkDest)
|
object.DisableVerificationCode(checkDest)
|
||||||
c.Data["json"] = Response{Status: "ok"}
|
c.ResponseOk()
|
||||||
c.ServeJSON()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// VerifyCaptcha ...
|
// VerifyCaptcha ...
|
||||||
|
3
go.mod
3
go.mod
@ -9,7 +9,7 @@ require (
|
|||||||
github.com/beego/beego v1.12.11
|
github.com/beego/beego v1.12.11
|
||||||
github.com/beevik/etree v1.1.0
|
github.com/beevik/etree v1.1.0
|
||||||
github.com/casbin/casbin/v2 v2.30.1
|
github.com/casbin/casbin/v2 v2.30.1
|
||||||
github.com/casdoor/go-sms-sender v0.5.1
|
github.com/casdoor/go-sms-sender v0.5.2
|
||||||
github.com/casdoor/gomail/v2 v2.0.1
|
github.com/casdoor/gomail/v2 v2.0.1
|
||||||
github.com/casdoor/oss v1.2.0
|
github.com/casdoor/oss v1.2.0
|
||||||
github.com/casdoor/xorm-adapter/v3 v3.0.4
|
github.com/casdoor/xorm-adapter/v3 v3.0.4
|
||||||
@ -30,6 +30,7 @@ require (
|
|||||||
github.com/lor00x/goldap v0.0.0-20180618054307-a546dffdd1a3
|
github.com/lor00x/goldap v0.0.0-20180618054307-a546dffdd1a3
|
||||||
github.com/markbates/goth v1.75.2
|
github.com/markbates/goth v1.75.2
|
||||||
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d // indirect
|
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d // indirect
|
||||||
|
github.com/nyaruka/phonenumbers v1.1.5
|
||||||
github.com/qiangmzsx/string-adapter/v2 v2.1.0
|
github.com/qiangmzsx/string-adapter/v2 v2.1.0
|
||||||
github.com/robfig/cron/v3 v3.0.1
|
github.com/robfig/cron/v3 v3.0.1
|
||||||
github.com/russellhaering/gosaml2 v0.6.0
|
github.com/russellhaering/gosaml2 v0.6.0
|
||||||
|
6
go.sum
6
go.sum
@ -94,8 +94,8 @@ github.com/casbin/casbin/v2 v2.1.0/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n
|
|||||||
github.com/casbin/casbin/v2 v2.28.3/go.mod h1:vByNa/Fchek0KZUgG5wEsl7iFsiviAYKRtgrQfcJqHg=
|
github.com/casbin/casbin/v2 v2.28.3/go.mod h1:vByNa/Fchek0KZUgG5wEsl7iFsiviAYKRtgrQfcJqHg=
|
||||||
github.com/casbin/casbin/v2 v2.30.1 h1:P5HWadDL7olwUXNdcuKUBk+x75Y2eitFxYTcLNKeKF0=
|
github.com/casbin/casbin/v2 v2.30.1 h1:P5HWadDL7olwUXNdcuKUBk+x75Y2eitFxYTcLNKeKF0=
|
||||||
github.com/casbin/casbin/v2 v2.30.1/go.mod h1:vByNa/Fchek0KZUgG5wEsl7iFsiviAYKRtgrQfcJqHg=
|
github.com/casbin/casbin/v2 v2.30.1/go.mod h1:vByNa/Fchek0KZUgG5wEsl7iFsiviAYKRtgrQfcJqHg=
|
||||||
github.com/casdoor/go-sms-sender v0.5.1 h1:1/Wp1OLkVAVY4lEGQhekSNetSAWhnPcxYPV7xpCZgC0=
|
github.com/casdoor/go-sms-sender v0.5.2 h1:LRjqoXBAOsH4yxXeJ7kINMesyoyEx5pEoiJz9d7lGJA=
|
||||||
github.com/casdoor/go-sms-sender v0.5.1/go.mod h1:kBykbqwgRDXbXdMAIxmZKinVM1WjdqEbej5LAbUbcfI=
|
github.com/casdoor/go-sms-sender v0.5.2/go.mod h1:kBykbqwgRDXbXdMAIxmZKinVM1WjdqEbej5LAbUbcfI=
|
||||||
github.com/casdoor/gomail/v2 v2.0.1 h1:J+FG6x80s9e5lBHUn8Sv0Y56mud34KiWih5YdmudR/w=
|
github.com/casdoor/gomail/v2 v2.0.1 h1:J+FG6x80s9e5lBHUn8Sv0Y56mud34KiWih5YdmudR/w=
|
||||||
github.com/casdoor/gomail/v2 v2.0.1/go.mod h1:VnGPslEAtpix5FjHisR/WKB1qvZDBaujbikxDe9d+2Q=
|
github.com/casdoor/gomail/v2 v2.0.1/go.mod h1:VnGPslEAtpix5FjHisR/WKB1qvZDBaujbikxDe9d+2Q=
|
||||||
github.com/casdoor/oss v1.2.0 h1:ozLAE+nnNdFQBWbzH8U9spzaO8h8NrB57lBcdyMUUQ8=
|
github.com/casdoor/oss v1.2.0 h1:ozLAE+nnNdFQBWbzH8U9spzaO8h8NrB57lBcdyMUUQ8=
|
||||||
@ -354,6 +354,8 @@ github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRW
|
|||||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||||
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d h1:VhgPp6v9qf9Agr/56bj7Y/xa04UccTW04VP0Qed4vnQ=
|
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d h1:VhgPp6v9qf9Agr/56bj7Y/xa04UccTW04VP0Qed4vnQ=
|
||||||
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d/go.mod h1:YUTz3bUH2ZwIWBy3CJBeOBEugqcmXREj14T+iG/4k4U=
|
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d/go.mod h1:YUTz3bUH2ZwIWBy3CJBeOBEugqcmXREj14T+iG/4k4U=
|
||||||
|
github.com/nyaruka/phonenumbers v1.1.5 h1:vYy2DI+z5hdaemqVzXYJ4CVyK92IG484CirEY+40GTo=
|
||||||
|
github.com/nyaruka/phonenumbers v1.1.5/go.mod h1:yShPJHDSH3aTKzCbXyVxNpbl2kA+F+Ne5Pun/MvFRos=
|
||||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
github.com/onsi/ginkgo v1.12.0 h1:Iw5WCbBcaAAd0fpRb1c9r5YCylv4XDoCSigm1zLevwU=
|
github.com/onsi/ginkgo v1.12.0 h1:Iw5WCbBcaAAd0fpRb1c9r5YCylv4XDoCSigm1zLevwU=
|
||||||
|
@ -30,24 +30,26 @@ func TestGenerateI18nFrontend(t *testing.T) {
|
|||||||
enData := parseEnData("frontend")
|
enData := parseEnData("frontend")
|
||||||
writeI18nFile("frontend", "en", enData)
|
writeI18nFile("frontend", "en", enData)
|
||||||
|
|
||||||
applyToOtherLanguage("frontend", "de", enData)
|
applyToOtherLanguage("frontend", "zh", enData)
|
||||||
applyToOtherLanguage("frontend", "es", enData)
|
applyToOtherLanguage("frontend", "es", enData)
|
||||||
applyToOtherLanguage("frontend", "fr", enData)
|
applyToOtherLanguage("frontend", "fr", enData)
|
||||||
|
applyToOtherLanguage("frontend", "de", enData)
|
||||||
applyToOtherLanguage("frontend", "ja", enData)
|
applyToOtherLanguage("frontend", "ja", enData)
|
||||||
applyToOtherLanguage("frontend", "ko", enData)
|
applyToOtherLanguage("frontend", "ko", enData)
|
||||||
applyToOtherLanguage("frontend", "ru", enData)
|
applyToOtherLanguage("frontend", "ru", enData)
|
||||||
applyToOtherLanguage("frontend", "zh", enData)
|
applyToOtherLanguage("frontend", "vi", enData)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGenerateI18nBackend(t *testing.T) {
|
func TestGenerateI18nBackend(t *testing.T) {
|
||||||
enData := parseEnData("backend")
|
enData := parseEnData("backend")
|
||||||
writeI18nFile("backend", "en", enData)
|
writeI18nFile("backend", "en", enData)
|
||||||
|
|
||||||
applyToOtherLanguage("backend", "de", enData)
|
applyToOtherLanguage("backend", "zh", enData)
|
||||||
applyToOtherLanguage("backend", "es", enData)
|
applyToOtherLanguage("backend", "es", enData)
|
||||||
applyToOtherLanguage("backend", "fr", enData)
|
applyToOtherLanguage("backend", "fr", enData)
|
||||||
|
applyToOtherLanguage("backend", "de", enData)
|
||||||
applyToOtherLanguage("backend", "ja", enData)
|
applyToOtherLanguage("backend", "ja", enData)
|
||||||
applyToOtherLanguage("backend", "ko", enData)
|
applyToOtherLanguage("backend", "ko", enData)
|
||||||
applyToOtherLanguage("backend", "ru", enData)
|
applyToOtherLanguage("backend", "ru", enData)
|
||||||
applyToOtherLanguage("backend", "zh", enData)
|
applyToOtherLanguage("backend", "vi", enData)
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
|
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
|
||||||
},
|
},
|
||||||
"auth": {
|
"auth": {
|
||||||
"%s No phone prefix": "%s No phone prefix",
|
|
||||||
"Challenge method should be S256": "Challenge method should be S256",
|
"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 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",
|
"Failed to login in: %s": "Failed to login in: %s",
|
||||||
@ -55,15 +54,17 @@
|
|||||||
"Username cannot contain white spaces": "Username cannot contain white spaces",
|
"Username cannot contain white spaces": "Username cannot contain white spaces",
|
||||||
"Username cannot start with a digit": "Username cannot start with a digit",
|
"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 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",
|
"Username must have at least 2 characters": "Benutzername muss mindestens 2 Zeichen lang sein",
|
||||||
"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",
|
"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, you have %d remaining chances": "password or code is incorrect, you have %d remaining chances",
|
"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"
|
"unsupported password type: %s": "unsupported password type: %s"
|
||||||
},
|
},
|
||||||
"general": {
|
"general": {
|
||||||
"Missing parameter": "Missing parameter",
|
"Missing parameter": "Missing parameter",
|
||||||
"Please login first": "Please login first",
|
"Please login first": "Please login first",
|
||||||
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
"The user: %s doesn't exist": "The user: %s doesn't exist",
|
||||||
|
"don't support captchaProvider: ": "don't support captchaProvider: "
|
||||||
},
|
},
|
||||||
"ldap": {
|
"ldap": {
|
||||||
"Ldap server exist": "Ldap server exist"
|
"Ldap server exist": "Ldap server exist"
|
||||||
@ -130,7 +131,7 @@
|
|||||||
"Email is invalid": "Email is invalid",
|
"Email is invalid": "Email is invalid",
|
||||||
"Invalid captcha provider.": "Invalid captcha provider.",
|
"Invalid captcha provider.": "Invalid captcha provider.",
|
||||||
"Organization does not exist": "Organization does not exist",
|
"Organization does not exist": "Organization does not exist",
|
||||||
"Phone number is invalid": "Phone number is invalid",
|
"Phone number is invalid in your region %s": "Phone number is invalid in your region %s",
|
||||||
"Turing test failed.": "Turing test failed.",
|
"Turing test failed.": "Turing test failed.",
|
||||||
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
|
"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.",
|
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
|
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
|
||||||
},
|
},
|
||||||
"auth": {
|
"auth": {
|
||||||
"%s No phone prefix": "%s No phone prefix",
|
|
||||||
"Challenge method should be S256": "Challenge method should be S256",
|
"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 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",
|
"Failed to login in: %s": "Failed to login in: %s",
|
||||||
@ -57,13 +56,15 @@
|
|||||||
"Username is too long (maximum is 39 characters).": "Username is too long (maximum is 39 characters).",
|
"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",
|
"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",
|
"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, you have %d remaining chances": "password or code is incorrect, you have %d remaining chances",
|
"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"
|
"unsupported password type: %s": "unsupported password type: %s"
|
||||||
},
|
},
|
||||||
"general": {
|
"general": {
|
||||||
"Missing parameter": "Missing parameter",
|
"Missing parameter": "Missing parameter",
|
||||||
"Please login first": "Please login first",
|
"Please login first": "Please login first",
|
||||||
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
"The user: %s doesn't exist": "The user: %s doesn't exist",
|
||||||
|
"don't support captchaProvider: ": "don't support captchaProvider: "
|
||||||
},
|
},
|
||||||
"ldap": {
|
"ldap": {
|
||||||
"Ldap server exist": "Ldap server exist"
|
"Ldap server exist": "Ldap server exist"
|
||||||
@ -130,7 +131,7 @@
|
|||||||
"Email is invalid": "Email is invalid",
|
"Email is invalid": "Email is invalid",
|
||||||
"Invalid captcha provider.": "Invalid captcha provider.",
|
"Invalid captcha provider.": "Invalid captcha provider.",
|
||||||
"Organization does not exist": "Organization does not exist",
|
"Organization does not exist": "Organization does not exist",
|
||||||
"Phone number is invalid": "Phone number is invalid",
|
"Phone number is invalid in your region %s": "Phone number is invalid in your region %s",
|
||||||
"Turing test failed.": "Turing test failed.",
|
"Turing test failed.": "Turing test failed.",
|
||||||
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
|
"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.",
|
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
|
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
|
||||||
},
|
},
|
||||||
"auth": {
|
"auth": {
|
||||||
"%s No phone prefix": "%s No phone prefix",
|
|
||||||
"Challenge method should be S256": "Challenge method should be S256",
|
"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 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",
|
"Failed to login in: %s": "Failed to login in: %s",
|
||||||
@ -57,13 +56,15 @@
|
|||||||
"Username is too long (maximum is 39 characters).": "Username is too long (maximum is 39 characters).",
|
"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",
|
"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",
|
"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, you have %d remaining chances": "password or code is incorrect, you have %d remaining chances",
|
"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"
|
"unsupported password type: %s": "unsupported password type: %s"
|
||||||
},
|
},
|
||||||
"general": {
|
"general": {
|
||||||
"Missing parameter": "Missing parameter",
|
"Missing parameter": "Missing parameter",
|
||||||
"Please login first": "Please login first",
|
"Please login first": "Please login first",
|
||||||
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
"The user: %s doesn't exist": "The user: %s doesn't exist",
|
||||||
|
"don't support captchaProvider: ": "don't support captchaProvider: "
|
||||||
},
|
},
|
||||||
"ldap": {
|
"ldap": {
|
||||||
"Ldap server exist": "Ldap server exist"
|
"Ldap server exist": "Ldap server exist"
|
||||||
@ -130,7 +131,7 @@
|
|||||||
"Email is invalid": "Email is invalid",
|
"Email is invalid": "Email is invalid",
|
||||||
"Invalid captcha provider.": "Invalid captcha provider.",
|
"Invalid captcha provider.": "Invalid captcha provider.",
|
||||||
"Organization does not exist": "Organization does not exist",
|
"Organization does not exist": "Organization does not exist",
|
||||||
"Phone number is invalid": "Phone number is invalid",
|
"Phone number is invalid in your region %s": "Phone number is invalid in your region %s",
|
||||||
"Turing test failed.": "Turing test failed.",
|
"Turing test failed.": "Turing test failed.",
|
||||||
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
|
"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.",
|
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
|
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
|
||||||
},
|
},
|
||||||
"auth": {
|
"auth": {
|
||||||
"%s No phone prefix": "%s No phone prefix",
|
|
||||||
"Challenge method should be S256": "Challenge method should be S256",
|
"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 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",
|
"Failed to login in: %s": "Failed to login in: %s",
|
||||||
@ -57,13 +56,15 @@
|
|||||||
"Username is too long (maximum is 39 characters).": "Username is too long (maximum is 39 characters).",
|
"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",
|
"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",
|
"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, you have %d remaining chances": "password or code is incorrect, you have %d remaining chances",
|
"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"
|
"unsupported password type: %s": "unsupported password type: %s"
|
||||||
},
|
},
|
||||||
"general": {
|
"general": {
|
||||||
"Missing parameter": "Missing parameter",
|
"Missing parameter": "Missing parameter",
|
||||||
"Please login first": "Please login first",
|
"Please login first": "Please login first",
|
||||||
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
"The user: %s doesn't exist": "The user: %s doesn't exist",
|
||||||
|
"don't support captchaProvider: ": "don't support captchaProvider: "
|
||||||
},
|
},
|
||||||
"ldap": {
|
"ldap": {
|
||||||
"Ldap server exist": "Ldap server exist"
|
"Ldap server exist": "Ldap server exist"
|
||||||
@ -130,7 +131,7 @@
|
|||||||
"Email is invalid": "Email is invalid",
|
"Email is invalid": "Email is invalid",
|
||||||
"Invalid captcha provider.": "Invalid captcha provider.",
|
"Invalid captcha provider.": "Invalid captcha provider.",
|
||||||
"Organization does not exist": "Organization does not exist",
|
"Organization does not exist": "Organization does not exist",
|
||||||
"Phone number is invalid": "Phone number is invalid",
|
"Phone number is invalid in your region %s": "Phone number is invalid in your region %s",
|
||||||
"Turing test failed.": "Turing test failed.",
|
"Turing test failed.": "Turing test failed.",
|
||||||
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
|
"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.",
|
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
|
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
|
||||||
},
|
},
|
||||||
"auth": {
|
"auth": {
|
||||||
"%s No phone prefix": "%s No phone prefix",
|
|
||||||
"Challenge method should be S256": "Challenge method should be S256",
|
"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 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",
|
"Failed to login in: %s": "Failed to login in: %s",
|
||||||
@ -57,13 +56,15 @@
|
|||||||
"Username is too long (maximum is 39 characters).": "Username is too long (maximum is 39 characters).",
|
"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",
|
"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",
|
"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, you have %d remaining chances": "password or code is incorrect, you have %d remaining chances",
|
"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"
|
"unsupported password type: %s": "unsupported password type: %s"
|
||||||
},
|
},
|
||||||
"general": {
|
"general": {
|
||||||
"Missing parameter": "Missing parameter",
|
"Missing parameter": "Missing parameter",
|
||||||
"Please login first": "Please login first",
|
"Please login first": "Please login first",
|
||||||
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
"The user: %s doesn't exist": "The user: %s doesn't exist",
|
||||||
|
"don't support captchaProvider: ": "don't support captchaProvider: "
|
||||||
},
|
},
|
||||||
"ldap": {
|
"ldap": {
|
||||||
"Ldap server exist": "Ldap server exist"
|
"Ldap server exist": "Ldap server exist"
|
||||||
@ -130,7 +131,7 @@
|
|||||||
"Email is invalid": "Email is invalid",
|
"Email is invalid": "Email is invalid",
|
||||||
"Invalid captcha provider.": "Invalid captcha provider.",
|
"Invalid captcha provider.": "Invalid captcha provider.",
|
||||||
"Organization does not exist": "Organization does not exist",
|
"Organization does not exist": "Organization does not exist",
|
||||||
"Phone number is invalid": "Phone number is invalid",
|
"Phone number is invalid in your region %s": "Phone number is invalid in your region %s",
|
||||||
"Turing test failed.": "Turing test failed.",
|
"Turing test failed.": "Turing test failed.",
|
||||||
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
|
"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.",
|
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
|
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
|
||||||
},
|
},
|
||||||
"auth": {
|
"auth": {
|
||||||
"%s No phone prefix": "%s No phone prefix",
|
|
||||||
"Challenge method should be S256": "Challenge method should be S256",
|
"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 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",
|
"Failed to login in: %s": "Failed to login in: %s",
|
||||||
@ -57,13 +56,15 @@
|
|||||||
"Username is too long (maximum is 39 characters).": "Username is too long (maximum is 39 characters).",
|
"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",
|
"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",
|
"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, you have %d remaining chances": "password or code is incorrect, you have %d remaining chances",
|
"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"
|
"unsupported password type: %s": "unsupported password type: %s"
|
||||||
},
|
},
|
||||||
"general": {
|
"general": {
|
||||||
"Missing parameter": "Missing parameter",
|
"Missing parameter": "Missing parameter",
|
||||||
"Please login first": "Please login first",
|
"Please login first": "Please login first",
|
||||||
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
"The user: %s doesn't exist": "The user: %s doesn't exist",
|
||||||
|
"don't support captchaProvider: ": "don't support captchaProvider: "
|
||||||
},
|
},
|
||||||
"ldap": {
|
"ldap": {
|
||||||
"Ldap server exist": "Ldap server exist"
|
"Ldap server exist": "Ldap server exist"
|
||||||
@ -130,7 +131,7 @@
|
|||||||
"Email is invalid": "Email is invalid",
|
"Email is invalid": "Email is invalid",
|
||||||
"Invalid captcha provider.": "Invalid captcha provider.",
|
"Invalid captcha provider.": "Invalid captcha provider.",
|
||||||
"Organization does not exist": "Organization does not exist",
|
"Organization does not exist": "Organization does not exist",
|
||||||
"Phone number is invalid": "Phone number is invalid",
|
"Phone number is invalid in your region %s": "Phone number is invalid in your region %s",
|
||||||
"Turing test failed.": "Turing test failed.",
|
"Turing test failed.": "Turing test failed.",
|
||||||
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
|
"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.",
|
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
|
"The application does not allow to sign up new account": "The application does not allow to sign up new account"
|
||||||
},
|
},
|
||||||
"auth": {
|
"auth": {
|
||||||
"%s No phone prefix": "%s No phone prefix",
|
|
||||||
"Challenge method should be S256": "Challenge method should be S256",
|
"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 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",
|
"Failed to login in: %s": "Failed to login in: %s",
|
||||||
@ -57,13 +56,15 @@
|
|||||||
"Username is too long (maximum is 39 characters).": "Username is too long (maximum is 39 characters).",
|
"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",
|
"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",
|
"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, you have %d remaining chances": "password or code is incorrect, you have %d remaining chances",
|
"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"
|
"unsupported password type: %s": "unsupported password type: %s"
|
||||||
},
|
},
|
||||||
"general": {
|
"general": {
|
||||||
"Missing parameter": "Missing parameter",
|
"Missing parameter": "Missing parameter",
|
||||||
"Please login first": "Please login first",
|
"Please login first": "Please login first",
|
||||||
"The user: %s doesn't exist": "The user: %s doesn't exist"
|
"The user: %s doesn't exist": "The user: %s doesn't exist",
|
||||||
|
"don't support captchaProvider: ": "don't support captchaProvider: "
|
||||||
},
|
},
|
||||||
"ldap": {
|
"ldap": {
|
||||||
"Ldap server exist": "Ldap server exist"
|
"Ldap server exist": "Ldap server exist"
|
||||||
@ -130,7 +131,7 @@
|
|||||||
"Email is invalid": "Email is invalid",
|
"Email is invalid": "Email is invalid",
|
||||||
"Invalid captcha provider.": "Invalid captcha provider.",
|
"Invalid captcha provider.": "Invalid captcha provider.",
|
||||||
"Organization does not exist": "Organization does not exist",
|
"Organization does not exist": "Organization does not exist",
|
||||||
"Phone number is invalid": "Phone number is invalid",
|
"Phone number is invalid in your region %s": "Phone number is invalid in your region %s",
|
||||||
"Turing test failed.": "Turing test failed.",
|
"Turing test failed.": "Turing test failed.",
|
||||||
"Unable to get the email modify rule.": "Unable to get the email modify rule.",
|
"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.",
|
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
|
||||||
|
147
i18n/locales/vi/data.json
Normal file
147
i18n/locales/vi/data.json
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
{
|
||||||
|
"account": {
|
||||||
|
"Email: %s": "Email: %s",
|
||||||
|
"Get init score failed, error: %w": "Get init score failed, error: %w",
|
||||||
|
"Invalid information": "Invalid information",
|
||||||
|
"Phone: %s": "Phone: %s",
|
||||||
|
"Please sign out first before signing in": "Please sign out first before signing in",
|
||||||
|
"Please sign out first before signing up": "Please sign out first before signing up",
|
||||||
|
"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 type: %s is not supported": "The provider type: %s is not supported",
|
||||||
|
"The provider: %s is not enabled for the application": "The provider: %s is not enabled for the application",
|
||||||
|
"The user is forbidden to sign in, please contact the administrator": "The user is forbidden to sign in, please contact the administrator",
|
||||||
|
"Turing test failed.": "Turing test failed.",
|
||||||
|
"Unauthorized operation": "Unauthorized operation",
|
||||||
|
"Unknown authentication type (not password or provider), form = %s": "Unknown authentication type (not password or provider), form = %s"
|
||||||
|
},
|
||||||
|
"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",
|
||||||
|
"LastName cannot be blank": "LastName cannot be blank",
|
||||||
|
"Ldap user name or password incorrect": "Ldap user name or password incorrect",
|
||||||
|
"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 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, 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: "
|
||||||
|
},
|
||||||
|
"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.",
|
||||||
|
"New password must have at least 6 characters": "New password must have at least 6 characters"
|
||||||
|
},
|
||||||
|
"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!",
|
||||||
|
"Email is invalid": "Email is invalid",
|
||||||
|
"Invalid captcha provider.": "Invalid captcha provider.",
|
||||||
|
"Organization does not exist": "Organization does not exist",
|
||||||
|
"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 parameter": "Wrong parameter",
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
@ -9,7 +9,6 @@
|
|||||||
"The application does not allow to sign up new account": "该应用不允许注册新用户"
|
"The application does not allow to sign up new account": "该应用不允许注册新用户"
|
||||||
},
|
},
|
||||||
"auth": {
|
"auth": {
|
||||||
"%s No phone prefix": "%s 无此手机号前缀",
|
|
||||||
"Challenge method should be S256": "Challenge 方法应该为 S256",
|
"Challenge method should be S256": "Challenge 方法应该为 S256",
|
||||||
"Failed to create user, user information is invalid: %s": "创建用户失败,用户信息无效: %s",
|
"Failed to create user, user information is invalid: %s": "创建用户失败,用户信息无效: %s",
|
||||||
"Failed to login in: %s": "登录失败: %s",
|
"Failed to login in: %s": "登录失败: %s",
|
||||||
@ -57,13 +56,15 @@
|
|||||||
"Username is too long (maximum is 39 characters).": "用户名过长(最大允许长度为39个字符)",
|
"Username is too long (maximum is 39 characters).": "用户名过长(最大允许长度为39个字符)",
|
||||||
"Username must have at least 2 characters": "用户名至少要有2个字符",
|
"Username must have at least 2 characters": "用户名至少要有2个字符",
|
||||||
"You have entered the wrong password or code too many times, please wait for %d minutes and try again": "密码错误次数已达上限,请在 %d 分后重试",
|
"You have entered the wrong password or code too many times, please wait for %d minutes and try again": "密码错误次数已达上限,请在 %d 分后重试",
|
||||||
|
"Your region is not allow to signup by phone": "所在地区不支持手机号注册",
|
||||||
"password or code is incorrect, you have %d remaining chances": "密码错误,您还有 %d 次尝试的机会",
|
"password or code is incorrect, you have %d remaining chances": "密码错误,您还有 %d 次尝试的机会",
|
||||||
"unsupported password type: %s": "不支持的密码类型: %s"
|
"unsupported password type: %s": "不支持的密码类型: %s"
|
||||||
},
|
},
|
||||||
"general": {
|
"general": {
|
||||||
"Missing parameter": "缺少参数",
|
"Missing parameter": "缺少参数",
|
||||||
"Please login first": "请先登录",
|
"Please login first": "请先登录",
|
||||||
"The user: %s doesn't exist": "用户: %s 不存在"
|
"The user: %s doesn't exist": "用户: %s 不存在",
|
||||||
|
"don't support captchaProvider: ": "不支持验证码提供商: "
|
||||||
},
|
},
|
||||||
"ldap": {
|
"ldap": {
|
||||||
"Ldap server exist": "LDAP服务器已存在"
|
"Ldap server exist": "LDAP服务器已存在"
|
||||||
@ -130,7 +131,7 @@
|
|||||||
"Email is invalid": "非法的邮箱",
|
"Email is invalid": "非法的邮箱",
|
||||||
"Invalid captcha provider.": "非法的验证码提供商",
|
"Invalid captcha provider.": "非法的验证码提供商",
|
||||||
"Organization does not exist": "组织不存在",
|
"Organization does not exist": "组织不存在",
|
||||||
"Phone number is invalid": "非法的手机号码",
|
"Phone number is invalid in your region %s": "您所在地区的电话号码无效 %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.": "无法获取手机号修改规则",
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
"websiteUrl": "",
|
"websiteUrl": "",
|
||||||
"favicon": "",
|
"favicon": "",
|
||||||
"passwordType": "",
|
"passwordType": "",
|
||||||
"phonePrefix": "",
|
"countryCodes": [""],
|
||||||
"defaultAvatar": "",
|
"defaultAvatar": "",
|
||||||
"tags": [""]
|
"tags": [""]
|
||||||
}
|
}
|
||||||
@ -107,6 +107,7 @@
|
|||||||
"avatar": "",
|
"avatar": "",
|
||||||
"email": "",
|
"email": "",
|
||||||
"phone": "",
|
"phone": "",
|
||||||
|
"countryCode": "",
|
||||||
"address": [],
|
"address": [],
|
||||||
"affiliation": "",
|
"affiliation": "",
|
||||||
"tag": "",
|
"tag": "",
|
||||||
|
@ -42,7 +42,7 @@ func init() {
|
|||||||
reFieldWhiteList, _ = regexp.Compile(`^[A-Za-z0-9]+$`)
|
reFieldWhiteList, _ = regexp.Compile(`^[A-Za-z0-9]+$`)
|
||||||
}
|
}
|
||||||
|
|
||||||
func CheckUserSignup(application *Application, organization *Organization, username string, password string, displayName string, firstName string, lastName string, email string, phone string, affiliation string, lang string) string {
|
func CheckUserSignup(application *Application, organization *Organization, username string, password string, displayName string, firstName string, lastName string, email string, phone string, countryCode string, affiliation string, lang string) string {
|
||||||
if organization == nil {
|
if organization == nil {
|
||||||
return i18n.Translate(lang, "check:Organization does not exist")
|
return i18n.Translate(lang, "check:Organization does not exist")
|
||||||
}
|
}
|
||||||
@ -107,7 +107,9 @@ func CheckUserSignup(application *Application, organization *Organization, usern
|
|||||||
|
|
||||||
if HasUserByField(organization.Name, "phone", phone) {
|
if HasUserByField(organization.Name, "phone", phone) {
|
||||||
return i18n.Translate(lang, "check:Phone already exists")
|
return i18n.Translate(lang, "check:Phone already exists")
|
||||||
} else if organization.PhonePrefix == "86" && !util.IsPhoneCnValid(phone) {
|
} else if !util.IsPhoneAllowInRegin(countryCode, organization.CountryCodes) {
|
||||||
|
return i18n.Translate(lang, "check:Your region is not allow to signup by phone")
|
||||||
|
} else if !util.IsPhoneValid(phone, countryCode) {
|
||||||
return i18n.Translate(lang, "check:Phone number is invalid")
|
return i18n.Translate(lang, "check:Phone number is invalid")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,6 +39,39 @@ func InitDb() {
|
|||||||
initWebAuthn()
|
initWebAuthn()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getBuiltInAccountItems() []*AccountItem {
|
||||||
|
return []*AccountItem{
|
||||||
|
{Name: "Organization", Visible: true, ViewRule: "Public", ModifyRule: "Admin"},
|
||||||
|
{Name: "ID", Visible: true, ViewRule: "Public", ModifyRule: "Immutable"},
|
||||||
|
{Name: "Name", Visible: true, ViewRule: "Public", ModifyRule: "Admin"},
|
||||||
|
{Name: "Display name", Visible: true, ViewRule: "Public", ModifyRule: "Self"},
|
||||||
|
{Name: "Avatar", Visible: true, ViewRule: "Public", ModifyRule: "Self"},
|
||||||
|
{Name: "User type", Visible: true, ViewRule: "Public", ModifyRule: "Admin"},
|
||||||
|
{Name: "Password", Visible: true, ViewRule: "Self", ModifyRule: "Self"},
|
||||||
|
{Name: "Email", Visible: true, ViewRule: "Public", ModifyRule: "Self"},
|
||||||
|
{Name: "Phone", Visible: true, ViewRule: "Public", ModifyRule: "Self"},
|
||||||
|
{Name: "CountryCode", Visible: true, ViewRule: "Public", ModifyRule: "Admin"},
|
||||||
|
{Name: "Country/Region", Visible: true, ViewRule: "Public", ModifyRule: "Self"},
|
||||||
|
{Name: "Location", Visible: true, ViewRule: "Public", ModifyRule: "Self"},
|
||||||
|
{Name: "Affiliation", Visible: true, ViewRule: "Public", ModifyRule: "Self"},
|
||||||
|
{Name: "Title", Visible: true, ViewRule: "Public", ModifyRule: "Self"},
|
||||||
|
{Name: "Homepage", Visible: true, ViewRule: "Public", ModifyRule: "Self"},
|
||||||
|
{Name: "Bio", Visible: true, ViewRule: "Public", ModifyRule: "Self"},
|
||||||
|
{Name: "Tag", Visible: true, ViewRule: "Public", ModifyRule: "Admin"},
|
||||||
|
{Name: "Signup application", Visible: true, ViewRule: "Public", ModifyRule: "Admin"},
|
||||||
|
{Name: "Roles", Visible: true, ViewRule: "Public", ModifyRule: "Immutable"},
|
||||||
|
{Name: "Permissions", Visible: true, ViewRule: "Public", ModifyRule: "Immutable"},
|
||||||
|
{Name: "3rd-party logins", Visible: true, ViewRule: "Self", ModifyRule: "Self"},
|
||||||
|
{Name: "Properties", Visible: false, ViewRule: "Admin", ModifyRule: "Admin"},
|
||||||
|
{Name: "Is admin", Visible: true, ViewRule: "Admin", ModifyRule: "Admin"},
|
||||||
|
{Name: "Is global admin", Visible: true, ViewRule: "Admin", ModifyRule: "Admin"},
|
||||||
|
{Name: "Is forbidden", Visible: true, ViewRule: "Admin", ModifyRule: "Admin"},
|
||||||
|
{Name: "Is deleted", Visible: true, ViewRule: "Admin", ModifyRule: "Admin"},
|
||||||
|
{Name: "WebAuthn credentials", Visible: true, ViewRule: "Self", ModifyRule: "Self"},
|
||||||
|
{Name: "Managed accounts", Visible: true, ViewRule: "Self", ModifyRule: "Self"},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func initBuiltInOrganization() bool {
|
func initBuiltInOrganization() bool {
|
||||||
organization := getOrganization("admin", "built-in")
|
organization := getOrganization("admin", "built-in")
|
||||||
if organization != nil {
|
if organization != nil {
|
||||||
@ -53,40 +86,12 @@ func initBuiltInOrganization() bool {
|
|||||||
WebsiteUrl: "https://example.com",
|
WebsiteUrl: "https://example.com",
|
||||||
Favicon: fmt.Sprintf("%s/img/casbin/favicon.ico", conf.GetConfigString("staticBaseUrl")),
|
Favicon: fmt.Sprintf("%s/img/casbin/favicon.ico", conf.GetConfigString("staticBaseUrl")),
|
||||||
PasswordType: "plain",
|
PasswordType: "plain",
|
||||||
PhonePrefix: "86",
|
CountryCodes: []string{"CN"},
|
||||||
DefaultAvatar: fmt.Sprintf("%s/img/casbin.svg", conf.GetConfigString("staticBaseUrl")),
|
DefaultAvatar: fmt.Sprintf("%s/img/casbin.svg", conf.GetConfigString("staticBaseUrl")),
|
||||||
Tags: []string{},
|
Tags: []string{},
|
||||||
Languages: []string{"en", "zh", "es", "fr", "de", "ja", "ko", "ru"},
|
Languages: []string{"en", "zh", "es", "fr", "de", "ja", "ko", "ru", "vi"},
|
||||||
InitScore: 2000,
|
InitScore: 2000,
|
||||||
AccountItems: []*AccountItem{
|
AccountItems: getBuiltInAccountItems(),
|
||||||
{Name: "Organization", Visible: true, ViewRule: "Public", ModifyRule: "Admin"},
|
|
||||||
{Name: "ID", Visible: true, ViewRule: "Public", ModifyRule: "Immutable"},
|
|
||||||
{Name: "Name", Visible: true, ViewRule: "Public", ModifyRule: "Admin"},
|
|
||||||
{Name: "Display name", Visible: true, ViewRule: "Public", ModifyRule: "Self"},
|
|
||||||
{Name: "Avatar", Visible: true, ViewRule: "Public", ModifyRule: "Self"},
|
|
||||||
{Name: "User type", Visible: true, ViewRule: "Public", ModifyRule: "Admin"},
|
|
||||||
{Name: "Password", Visible: true, ViewRule: "Self", ModifyRule: "Self"},
|
|
||||||
{Name: "Email", Visible: true, ViewRule: "Public", ModifyRule: "Self"},
|
|
||||||
{Name: "Phone", Visible: true, ViewRule: "Public", ModifyRule: "Self"},
|
|
||||||
{Name: "Country/Region", Visible: true, ViewRule: "Public", ModifyRule: "Self"},
|
|
||||||
{Name: "Location", Visible: true, ViewRule: "Public", ModifyRule: "Self"},
|
|
||||||
{Name: "Affiliation", Visible: true, ViewRule: "Public", ModifyRule: "Self"},
|
|
||||||
{Name: "Title", Visible: true, ViewRule: "Public", ModifyRule: "Self"},
|
|
||||||
{Name: "Homepage", Visible: true, ViewRule: "Public", ModifyRule: "Self"},
|
|
||||||
{Name: "Bio", Visible: true, ViewRule: "Public", ModifyRule: "Self"},
|
|
||||||
{Name: "Tag", Visible: true, ViewRule: "Public", ModifyRule: "Admin"},
|
|
||||||
{Name: "Signup application", Visible: true, ViewRule: "Public", ModifyRule: "Admin"},
|
|
||||||
{Name: "Roles", Visible: true, ViewRule: "Public", ModifyRule: "Immutable"},
|
|
||||||
{Name: "Permissions", Visible: true, ViewRule: "Public", ModifyRule: "Immutable"},
|
|
||||||
{Name: "3rd-party logins", Visible: true, ViewRule: "Self", ModifyRule: "Self"},
|
|
||||||
{Name: "Properties", Visible: false, ViewRule: "Admin", ModifyRule: "Admin"},
|
|
||||||
{Name: "Is admin", Visible: true, ViewRule: "Admin", ModifyRule: "Admin"},
|
|
||||||
{Name: "Is global admin", Visible: true, ViewRule: "Admin", ModifyRule: "Admin"},
|
|
||||||
{Name: "Is forbidden", Visible: true, ViewRule: "Admin", ModifyRule: "Admin"},
|
|
||||||
{Name: "Is deleted", Visible: true, ViewRule: "Admin", ModifyRule: "Admin"},
|
|
||||||
{Name: "WebAuthn credentials", Visible: true, ViewRule: "Self", ModifyRule: "Self"},
|
|
||||||
{Name: "Managed accounts", Visible: true, ViewRule: "Self", ModifyRule: "Self"},
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
AddOrganization(organization)
|
AddOrganization(organization)
|
||||||
return false
|
return false
|
||||||
@ -109,6 +114,7 @@ func initBuiltInUser() {
|
|||||||
Avatar: fmt.Sprintf("%s/img/casbin.svg", conf.GetConfigString("staticBaseUrl")),
|
Avatar: fmt.Sprintf("%s/img/casbin.svg", conf.GetConfigString("staticBaseUrl")),
|
||||||
Email: "admin@example.com",
|
Email: "admin@example.com",
|
||||||
Phone: "12345678910",
|
Phone: "12345678910",
|
||||||
|
CountryCode: "CN",
|
||||||
Address: []string{},
|
Address: []string{},
|
||||||
Affiliation: "Example Inc.",
|
Affiliation: "Example Inc.",
|
||||||
Tag: "staff",
|
Tag: "staff",
|
||||||
|
@ -179,33 +179,7 @@ func initDefinedOrganization(organization *Organization) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
organization.CreatedTime = util.GetCurrentTime()
|
organization.CreatedTime = util.GetCurrentTime()
|
||||||
organization.AccountItems = []*AccountItem{
|
organization.AccountItems = getBuiltInAccountItems()
|
||||||
{Name: "Organization", Visible: true, ViewRule: "Public", ModifyRule: "Admin"},
|
|
||||||
{Name: "ID", Visible: true, ViewRule: "Public", ModifyRule: "Immutable"},
|
|
||||||
{Name: "Name", Visible: true, ViewRule: "Public", ModifyRule: "Admin"},
|
|
||||||
{Name: "Display name", Visible: true, ViewRule: "Public", ModifyRule: "Self"},
|
|
||||||
{Name: "Avatar", Visible: true, ViewRule: "Public", ModifyRule: "Self"},
|
|
||||||
{Name: "User type", Visible: true, ViewRule: "Public", ModifyRule: "Admin"},
|
|
||||||
{Name: "Password", Visible: true, ViewRule: "Self", ModifyRule: "Self"},
|
|
||||||
{Name: "Email", Visible: true, ViewRule: "Public", ModifyRule: "Self"},
|
|
||||||
{Name: "Phone", Visible: true, ViewRule: "Public", ModifyRule: "Self"},
|
|
||||||
{Name: "Country/Region", Visible: true, ViewRule: "Public", ModifyRule: "Self"},
|
|
||||||
{Name: "Location", Visible: true, ViewRule: "Public", ModifyRule: "Self"},
|
|
||||||
{Name: "Affiliation", Visible: true, ViewRule: "Public", ModifyRule: "Self"},
|
|
||||||
{Name: "Title", Visible: true, ViewRule: "Public", ModifyRule: "Self"},
|
|
||||||
{Name: "Homepage", Visible: true, ViewRule: "Public", ModifyRule: "Self"},
|
|
||||||
{Name: "Bio", Visible: true, ViewRule: "Public", ModifyRule: "Self"},
|
|
||||||
{Name: "Tag", Visible: true, ViewRule: "Public", ModifyRule: "Admin"},
|
|
||||||
{Name: "Signup application", Visible: true, ViewRule: "Public", ModifyRule: "Admin"},
|
|
||||||
{Name: "Roles", Visible: true, ViewRule: "Public", ModifyRule: "Immutable"},
|
|
||||||
{Name: "Permissions", Visible: true, ViewRule: "Public", ModifyRule: "Immutable"},
|
|
||||||
{Name: "3rd-party logins", Visible: true, ViewRule: "Self", ModifyRule: "Self"},
|
|
||||||
{Name: "Properties", Visible: false, ViewRule: "Admin", ModifyRule: "Admin"},
|
|
||||||
{Name: "Is admin", Visible: true, ViewRule: "Admin", ModifyRule: "Admin"},
|
|
||||||
{Name: "Is global admin", Visible: true, ViewRule: "Admin", ModifyRule: "Admin"},
|
|
||||||
{Name: "Is forbidden", Visible: true, ViewRule: "Admin", ModifyRule: "Admin"},
|
|
||||||
{Name: "Is deleted", Visible: true, ViewRule: "Admin", ModifyRule: "Admin"},
|
|
||||||
}
|
|
||||||
|
|
||||||
AddOrganization(organization)
|
AddOrganization(organization)
|
||||||
}
|
}
|
||||||
|
@ -329,7 +329,7 @@ func GetLdaps(owner string) []*Ldap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func GetLdap(id string) *Ldap {
|
func GetLdap(id string) *Ldap {
|
||||||
if util.IsStrsEmpty(id) {
|
if util.IsStringsEmpty(id) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ type Organization struct {
|
|||||||
Favicon string `xorm:"varchar(100)" json:"favicon"`
|
Favicon string `xorm:"varchar(100)" json:"favicon"`
|
||||||
PasswordType string `xorm:"varchar(100)" json:"passwordType"`
|
PasswordType string `xorm:"varchar(100)" json:"passwordType"`
|
||||||
PasswordSalt string `xorm:"varchar(100)" json:"passwordSalt"`
|
PasswordSalt string `xorm:"varchar(100)" json:"passwordSalt"`
|
||||||
PhonePrefix string `xorm:"varchar(10)" json:"phonePrefix"`
|
CountryCodes []string `xorm:"varchar(200)" json:"countryCodes"`
|
||||||
DefaultAvatar string `xorm:"varchar(100)" json:"defaultAvatar"`
|
DefaultAvatar string `xorm:"varchar(100)" json:"defaultAvatar"`
|
||||||
DefaultApplication string `xorm:"varchar(100)" json:"defaultApplication"`
|
DefaultApplication string `xorm:"varchar(100)" json:"defaultApplication"`
|
||||||
Tags []string `xorm:"mediumtext" json:"tags"`
|
Tags []string `xorm:"mediumtext" json:"tags"`
|
||||||
@ -211,6 +211,10 @@ func GetAccountItemByName(name string, organization *Organization) *AccountItem
|
|||||||
}
|
}
|
||||||
|
|
||||||
func CheckAccountItemModifyRule(accountItem *AccountItem, user *User, lang string) (bool, string) {
|
func CheckAccountItemModifyRule(accountItem *AccountItem, user *User, lang string) (bool, string) {
|
||||||
|
if accountItem == nil {
|
||||||
|
return true, ""
|
||||||
|
}
|
||||||
|
|
||||||
switch accountItem.ModifyRule {
|
switch accountItem.ModifyRule {
|
||||||
case "Admin":
|
case "Admin":
|
||||||
if user == nil || !user.IsAdmin && !user.IsGlobalAdmin {
|
if user == nil || !user.IsAdmin && !user.IsGlobalAdmin {
|
||||||
|
@ -64,7 +64,7 @@ func NewSamlResponse(user *User, host string, certificate string, destination st
|
|||||||
assertion.CreateAttr("IssueInstant", now)
|
assertion.CreateAttr("IssueInstant", now)
|
||||||
assertion.CreateElement("saml:Issuer").SetText(host)
|
assertion.CreateElement("saml:Issuer").SetText(host)
|
||||||
subject := assertion.CreateElement("saml:Subject")
|
subject := assertion.CreateElement("saml:Subject")
|
||||||
subject.CreateElement("saml:NameID").SetText(user.Email)
|
subject.CreateElement("saml:NameID").SetText(user.Name)
|
||||||
subjectConfirmation := subject.CreateElement("saml:SubjectConfirmation")
|
subjectConfirmation := subject.CreateElement("saml:SubjectConfirmation")
|
||||||
subjectConfirmation.CreateAttr("Method", "urn:oasis:names:tc:SAML:2.0:cm:bearer")
|
subjectConfirmation.CreateAttr("Method", "urn:oasis:names:tc:SAML:2.0:cm:bearer")
|
||||||
subjectConfirmationData := subjectConfirmation.CreateElement("saml:SubjectConfirmationData")
|
subjectConfirmationData := subjectConfirmation.CreateElement("saml:SubjectConfirmationData")
|
||||||
|
@ -14,7 +14,11 @@
|
|||||||
|
|
||||||
package object
|
package object
|
||||||
|
|
||||||
import "github.com/casdoor/go-sms-sender"
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/casdoor/go-sms-sender"
|
||||||
|
)
|
||||||
|
|
||||||
func SendSms(provider *Provider, content string, phoneNumbers ...string) error {
|
func SendSms(provider *Provider, content string, phoneNumbers ...string) error {
|
||||||
client, err := go_sms_sender.NewSmsClient(provider.Type, provider.ClientId, provider.ClientSecret, provider.SignName, provider.TemplateCode, provider.AppId)
|
client, err := go_sms_sender.NewSmsClient(provider.Type, provider.ClientId, provider.ClientSecret, provider.SignName, provider.TemplateCode, provider.AppId)
|
||||||
@ -25,6 +29,12 @@ func SendSms(provider *Provider, content string, phoneNumbers ...string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if provider.Type == go_sms_sender.Aliyun {
|
||||||
|
for i, number := range phoneNumbers {
|
||||||
|
phoneNumbers[i] = strings.TrimPrefix(number, "+")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
params := map[string]string{}
|
params := map[string]string{}
|
||||||
if provider.Type == go_sms_sender.TencentCloud {
|
if provider.Type == go_sms_sender.TencentCloud {
|
||||||
params["0"] = content
|
params["0"] = content
|
||||||
|
@ -27,7 +27,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
hourMinutes = 60
|
hourSeconds = int(time.Hour / time.Second)
|
||||||
InvalidRequest = "invalid_request"
|
InvalidRequest = "invalid_request"
|
||||||
InvalidClient = "invalid_client"
|
InvalidClient = "invalid_client"
|
||||||
InvalidGrant = "invalid_grant"
|
InvalidGrant = "invalid_grant"
|
||||||
@ -306,7 +306,7 @@ func GetOAuthCode(userId string, clientId string, responseType string, redirectU
|
|||||||
Code: util.GenerateClientId(),
|
Code: util.GenerateClientId(),
|
||||||
AccessToken: accessToken,
|
AccessToken: accessToken,
|
||||||
RefreshToken: refreshToken,
|
RefreshToken: refreshToken,
|
||||||
ExpiresIn: application.ExpireInHours * hourMinutes,
|
ExpiresIn: application.ExpireInHours * hourSeconds,
|
||||||
Scope: scope,
|
Scope: scope,
|
||||||
TokenType: "Bearer",
|
TokenType: "Bearer",
|
||||||
CodeChallenge: challenge,
|
CodeChallenge: challenge,
|
||||||
@ -442,7 +442,7 @@ func RefreshToken(grantType string, refreshToken string, scope string, clientId
|
|||||||
Code: util.GenerateClientId(),
|
Code: util.GenerateClientId(),
|
||||||
AccessToken: newAccessToken,
|
AccessToken: newAccessToken,
|
||||||
RefreshToken: newRefreshToken,
|
RefreshToken: newRefreshToken,
|
||||||
ExpiresIn: application.ExpireInHours * hourMinutes,
|
ExpiresIn: application.ExpireInHours * hourSeconds,
|
||||||
Scope: scope,
|
Scope: scope,
|
||||||
TokenType: "Bearer",
|
TokenType: "Bearer",
|
||||||
}
|
}
|
||||||
@ -592,7 +592,7 @@ func GetPasswordToken(application *Application, username string, password string
|
|||||||
Code: util.GenerateClientId(),
|
Code: util.GenerateClientId(),
|
||||||
AccessToken: accessToken,
|
AccessToken: accessToken,
|
||||||
RefreshToken: refreshToken,
|
RefreshToken: refreshToken,
|
||||||
ExpiresIn: application.ExpireInHours * hourMinutes,
|
ExpiresIn: application.ExpireInHours * hourSeconds,
|
||||||
Scope: scope,
|
Scope: scope,
|
||||||
TokenType: "Bearer",
|
TokenType: "Bearer",
|
||||||
CodeIsUsed: true,
|
CodeIsUsed: true,
|
||||||
@ -632,7 +632,7 @@ func GetClientCredentialsToken(application *Application, clientSecret string, sc
|
|||||||
User: nullUser.Name,
|
User: nullUser.Name,
|
||||||
Code: util.GenerateClientId(),
|
Code: util.GenerateClientId(),
|
||||||
AccessToken: accessToken,
|
AccessToken: accessToken,
|
||||||
ExpiresIn: application.ExpireInHours * hourMinutes,
|
ExpiresIn: application.ExpireInHours * hourSeconds,
|
||||||
Scope: scope,
|
Scope: scope,
|
||||||
TokenType: "Bearer",
|
TokenType: "Bearer",
|
||||||
CodeIsUsed: true,
|
CodeIsUsed: true,
|
||||||
@ -659,7 +659,7 @@ func GetTokenByUser(application *Application, user *User, scope string, host str
|
|||||||
Code: util.GenerateClientId(),
|
Code: util.GenerateClientId(),
|
||||||
AccessToken: accessToken,
|
AccessToken: accessToken,
|
||||||
RefreshToken: refreshToken,
|
RefreshToken: refreshToken,
|
||||||
ExpiresIn: application.ExpireInHours * hourMinutes,
|
ExpiresIn: application.ExpireInHours * hourSeconds,
|
||||||
Scope: scope,
|
Scope: scope,
|
||||||
TokenType: "Bearer",
|
TokenType: "Bearer",
|
||||||
CodeIsUsed: true,
|
CodeIsUsed: true,
|
||||||
|
@ -265,8 +265,8 @@ func generateJwtToken(application *Application, user *User, nonce string, scope
|
|||||||
claimsWithoutThirdIdp := getClaimsWithoutThirdIdp(claims)
|
claimsWithoutThirdIdp := getClaimsWithoutThirdIdp(claims)
|
||||||
|
|
||||||
token = jwt.NewWithClaims(jwt.SigningMethodRS256, claimsWithoutThirdIdp)
|
token = jwt.NewWithClaims(jwt.SigningMethodRS256, claimsWithoutThirdIdp)
|
||||||
claims.ExpiresAt = jwt.NewNumericDate(refreshExpireTime)
|
claimsWithoutThirdIdp.ExpiresAt = jwt.NewNumericDate(refreshExpireTime)
|
||||||
claims.TokenType = "refresh-token"
|
claimsWithoutThirdIdp.TokenType = "refresh-token"
|
||||||
refreshToken = jwt.NewWithClaims(jwt.SigningMethodRS256, claimsWithoutThirdIdp)
|
refreshToken = jwt.NewWithClaims(jwt.SigningMethodRS256, claimsWithoutThirdIdp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,7 +46,8 @@ type User struct {
|
|||||||
PermanentAvatar string `xorm:"varchar(500)" json:"permanentAvatar"`
|
PermanentAvatar string `xorm:"varchar(500)" json:"permanentAvatar"`
|
||||||
Email string `xorm:"varchar(100) index" json:"email"`
|
Email string `xorm:"varchar(100) index" json:"email"`
|
||||||
EmailVerified bool `json:"emailVerified"`
|
EmailVerified bool `json:"emailVerified"`
|
||||||
Phone string `xorm:"varchar(100) index" json:"phone"`
|
Phone string `xorm:"varchar(20) index" json:"phone"`
|
||||||
|
CountryCode string `xorm:"varchar(6)" json:"countryCode"`
|
||||||
Location string `xorm:"varchar(100)" json:"location"`
|
Location string `xorm:"varchar(100)" json:"location"`
|
||||||
Address []string `json:"address"`
|
Address []string `json:"address"`
|
||||||
Affiliation string `xorm:"varchar(100)" json:"affiliation"`
|
Affiliation string `xorm:"varchar(100)" json:"affiliation"`
|
||||||
@ -454,7 +455,7 @@ func UpdateUser(id string, user *User, columns []string, isGlobalAdmin bool) boo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if isGlobalAdmin {
|
if isGlobalAdmin {
|
||||||
columns = append(columns, "name", "email", "phone")
|
columns = append(columns, "name", "email", "phone", "country_code")
|
||||||
}
|
}
|
||||||
|
|
||||||
affected, err := adapter.Engine.ID(core.PK{owner, name}).Cols(columns...).Update(user)
|
affected, err := adapter.Engine.ID(core.PK{owner, name}).Cols(columns...).Update(user)
|
||||||
|
@ -170,3 +170,18 @@ func ClearUserOAuthProperties(user *User, providerType string) bool {
|
|||||||
|
|
||||||
return affected != 0
|
return affected != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (user *User) GetCountryCode(countryCode string) string {
|
||||||
|
if countryCode != "" {
|
||||||
|
return countryCode
|
||||||
|
}
|
||||||
|
|
||||||
|
if user != nil && user.CountryCode != "" {
|
||||||
|
return user.CountryCode
|
||||||
|
}
|
||||||
|
|
||||||
|
if org := GetOrganizationByUser(user); org != nil && len(org.CountryCodes) > 0 {
|
||||||
|
return org.CountryCodes[0]
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
@ -122,11 +122,8 @@ func AddToVerificationRecord(user *User, provider *Provider, remoteAddr, recordT
|
|||||||
record.Owner = provider.Owner
|
record.Owner = provider.Owner
|
||||||
record.Name = util.GenerateId()
|
record.Name = util.GenerateId()
|
||||||
record.CreatedTime = util.GetCurrentTime()
|
record.CreatedTime = util.GetCurrentTime()
|
||||||
if user != nil {
|
|
||||||
record.User = user.GetId()
|
|
||||||
}
|
|
||||||
record.Provider = provider.Name
|
|
||||||
|
|
||||||
|
record.Provider = provider.Name
|
||||||
record.Receiver = dest
|
record.Receiver = dest
|
||||||
record.Code = code
|
record.Code = code
|
||||||
record.Time = time.Now().Unix()
|
record.Time = time.Now().Unix()
|
||||||
|
@ -57,7 +57,7 @@ func AutoSigninFilter(ctx *context.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// "/page?username=abc&password=123"
|
// "/page?username=built-in/admin&password=123"
|
||||||
userId = ctx.Input.Query("username")
|
userId = ctx.Input.Query("username")
|
||||||
password := ctx.Input.Query("password")
|
password := ctx.Input.Query("password")
|
||||||
if userId != "" && password != "" && ctx.Input.Query("grant_type") == "" {
|
if userId != "" && password != "" && ctx.Input.Query("grant_type") == "" {
|
||||||
|
@ -19,6 +19,8 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/beego/beego/context"
|
"github.com/beego/beego/context"
|
||||||
|
"github.com/casdoor/casdoor/conf"
|
||||||
|
"github.com/casdoor/casdoor/i18n"
|
||||||
"github.com/casdoor/casdoor/object"
|
"github.com/casdoor/casdoor/object"
|
||||||
"github.com/casdoor/casdoor/util"
|
"github.com/casdoor/casdoor/util"
|
||||||
)
|
)
|
||||||
@ -46,8 +48,17 @@ func responseError(ctx *context.Context, error string, data ...interface{}) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getAcceptLanguage(ctx *context.Context) string {
|
||||||
|
language := ctx.Request.Header.Get("Accept-Language")
|
||||||
|
return conf.GetLanguage(language)
|
||||||
|
}
|
||||||
|
|
||||||
|
func T(ctx *context.Context, error string) string {
|
||||||
|
return i18n.Translate(getAcceptLanguage(ctx), error)
|
||||||
|
}
|
||||||
|
|
||||||
func denyRequest(ctx *context.Context) {
|
func denyRequest(ctx *context.Context) {
|
||||||
responseError(ctx, "Unauthorized operation")
|
responseError(ctx, T(ctx, "auth:Unauthorized operation"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func getUsernameByClientIdSecret(ctx *context.Context) string {
|
func getUsernameByClientIdSecret(ctx *context.Context) string {
|
||||||
|
@ -119,8 +119,8 @@ func initAPI() {
|
|||||||
beego.Router("/api/get-captcha", &controllers.ApiController{}, "GET:GetCaptcha")
|
beego.Router("/api/get-captcha", &controllers.ApiController{}, "GET:GetCaptcha")
|
||||||
|
|
||||||
beego.Router("/api/get-ldap-user", &controllers.ApiController{}, "POST:GetLdapUser")
|
beego.Router("/api/get-ldap-user", &controllers.ApiController{}, "POST:GetLdapUser")
|
||||||
beego.Router("/api/get-ldaps", &controllers.ApiController{}, "POST:GetLdaps")
|
beego.Router("/api/get-ldaps", &controllers.ApiController{}, "GET:GetLdaps")
|
||||||
beego.Router("/api/get-ldap", &controllers.ApiController{}, "POST:GetLdap")
|
beego.Router("/api/get-ldap", &controllers.ApiController{}, "GET:GetLdap")
|
||||||
beego.Router("/api/add-ldap", &controllers.ApiController{}, "POST:AddLdap")
|
beego.Router("/api/add-ldap", &controllers.ApiController{}, "POST:AddLdap")
|
||||||
beego.Router("/api/update-ldap", &controllers.ApiController{}, "POST:UpdateLdap")
|
beego.Router("/api/update-ldap", &controllers.ApiController{}, "POST:UpdateLdap")
|
||||||
beego.Router("/api/delete-ldap", &controllers.ApiController{}, "POST:DeleteLdap")
|
beego.Router("/api/delete-ldap", &controllers.ApiController{}, "POST:DeleteLdap")
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
|
|
||||||
package util
|
package util
|
||||||
|
|
||||||
|
import "sort"
|
||||||
|
|
||||||
func DeleteVal(values []string, val string) []string {
|
func DeleteVal(values []string, val string) []string {
|
||||||
newValues := []string{}
|
newValues := []string{}
|
||||||
for _, v := range values {
|
for _, v := range values {
|
||||||
@ -23,3 +25,8 @@ func DeleteVal(values []string, val string) []string {
|
|||||||
}
|
}
|
||||||
return newValues
|
return newValues
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ContainsString(values []string, val string) bool {
|
||||||
|
sort.Strings(values)
|
||||||
|
return sort.SearchStrings(values, val) != len(values)
|
||||||
|
}
|
||||||
|
@ -145,7 +145,7 @@ func GetMd5Hash(text string) string {
|
|||||||
return hex.EncodeToString(hash[:])
|
return hex.EncodeToString(hash[:])
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsStrsEmpty(strs ...string) bool {
|
func IsStringsEmpty(strs ...string) bool {
|
||||||
for _, str := range strs {
|
for _, str := range strs {
|
||||||
if len(str) == 0 {
|
if len(str) == 0 {
|
||||||
return true
|
return true
|
||||||
@ -227,7 +227,7 @@ func IsChinese(str string) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func GetMaskedPhone(phone string) string {
|
func GetMaskedPhone(phone string) string {
|
||||||
return getMaskedPhone(phone)
|
return rePhone.ReplaceAllString(phone, "$1****$2")
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetMaskedEmail(email string) string {
|
func GetMaskedEmail(email string) string {
|
||||||
|
@ -183,7 +183,7 @@ func TestIsStrsEmpty(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for _, scenery := range scenarios {
|
for _, scenery := range scenarios {
|
||||||
t.Run(scenery.description, func(t *testing.T) {
|
t.Run(scenery.description, func(t *testing.T) {
|
||||||
actual := IsStrsEmpty(scenery.input...)
|
actual := IsStringsEmpty(scenery.input...)
|
||||||
assert.Equal(t, scenery.expected, actual, "The returned value not is expected")
|
assert.Equal(t, scenery.expected, actual, "The returned value not is expected")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,6 @@ func GetCurrentUnixTime() string {
|
|||||||
|
|
||||||
func IsTokenExpired(createdTime string, expiresIn int) bool {
|
func IsTokenExpired(createdTime string, expiresIn int) bool {
|
||||||
createdTimeObj, _ := time.Parse(time.RFC3339, createdTime)
|
createdTimeObj, _ := time.Parse(time.RFC3339, createdTime)
|
||||||
expiresAtObj := createdTimeObj.Add(time.Duration(expiresIn) * time.Minute)
|
expiresAtObj := createdTimeObj.Add(time.Duration(expiresIn) * time.Second)
|
||||||
return time.Now().After(expiresAtObj)
|
return time.Now().After(expiresAtObj)
|
||||||
}
|
}
|
||||||
|
@ -56,15 +56,15 @@ func Test_IsTokenExpired(t *testing.T) {
|
|||||||
description: "Token emitted now is valid for 60 minutes",
|
description: "Token emitted now is valid for 60 minutes",
|
||||||
input: input{
|
input: input{
|
||||||
createdTime: time.Now().Format(time.RFC3339),
|
createdTime: time.Now().Format(time.RFC3339),
|
||||||
expiresIn: 60,
|
expiresIn: 3600,
|
||||||
},
|
},
|
||||||
expected: false,
|
expected: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: "Token emitted 60 minutes before now is valid for 60 minutes",
|
description: "Token emitted 60 minutes before now is valid for 61 minutes",
|
||||||
input: input{
|
input: input{
|
||||||
createdTime: time.Now().Add(-time.Minute * 60).Format(time.RFC3339),
|
createdTime: time.Now().Add(-time.Minute * 60).Format(time.RFC3339),
|
||||||
expiresIn: 61,
|
expiresIn: 3660,
|
||||||
},
|
},
|
||||||
expected: false,
|
expected: false,
|
||||||
},
|
},
|
||||||
@ -72,7 +72,7 @@ func Test_IsTokenExpired(t *testing.T) {
|
|||||||
description: "Token emitted 2 hours before now is Expired after 60 minutes",
|
description: "Token emitted 2 hours before now is Expired after 60 minutes",
|
||||||
input: input{
|
input: input{
|
||||||
createdTime: time.Now().Add(-time.Hour * 2).Format(time.RFC3339),
|
createdTime: time.Now().Add(-time.Hour * 2).Format(time.RFC3339),
|
||||||
expiresIn: 60,
|
expiresIn: 3600,
|
||||||
},
|
},
|
||||||
expected: true,
|
expected: true,
|
||||||
},
|
},
|
||||||
@ -80,23 +80,23 @@ func Test_IsTokenExpired(t *testing.T) {
|
|||||||
description: "Token emitted 61 minutes before now is Expired after 60 minutes",
|
description: "Token emitted 61 minutes before now is Expired after 60 minutes",
|
||||||
input: input{
|
input: input{
|
||||||
createdTime: time.Now().Add(-time.Minute * 61).Format(time.RFC3339),
|
createdTime: time.Now().Add(-time.Minute * 61).Format(time.RFC3339),
|
||||||
expiresIn: 60,
|
expiresIn: 3600,
|
||||||
},
|
},
|
||||||
expected: true,
|
expected: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: "Token emitted 2 hours before now is valid for 120 minutes",
|
description: "Token emitted 2 hours before now is valid for 121 minutes",
|
||||||
input: input{
|
input: input{
|
||||||
createdTime: time.Now().Add(-time.Hour * 2).Format(time.RFC3339),
|
createdTime: time.Now().Add(-time.Hour * 2).Format(time.RFC3339),
|
||||||
expiresIn: 121,
|
expiresIn: 7260,
|
||||||
},
|
},
|
||||||
expected: false,
|
expected: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: "Token emitted 159 minutes before now is Expired after 60 minutes",
|
description: "Token emitted 159 minutes before now is Expired after 120 minutes",
|
||||||
input: input{
|
input: input{
|
||||||
createdTime: time.Now().Add(-time.Minute * 159).Format(time.RFC3339),
|
createdTime: time.Now().Add(-time.Minute * 159).Format(time.RFC3339),
|
||||||
expiresIn: 120,
|
expiresIn: 7200,
|
||||||
},
|
},
|
||||||
expected: true,
|
expected: true,
|
||||||
},
|
},
|
||||||
|
@ -17,16 +17,13 @@ package util
|
|||||||
import (
|
import (
|
||||||
"net/mail"
|
"net/mail"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
|
||||||
|
"github.com/nyaruka/phonenumbers"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var rePhone *regexp.Regexp
|
||||||
rePhoneCn *regexp.Regexp
|
|
||||||
rePhone *regexp.Regexp
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
// https://learnku.com/articles/31543
|
|
||||||
rePhoneCn, _ = regexp.Compile(`^1(3\d|4[5-9]|5[0-35-9]|6[2567]|7[0-8]|8\d|9[0-35-9])\d{8}$`)
|
|
||||||
rePhone, _ = regexp.Compile("(\\d{3})\\d*(\\d{4})")
|
rePhone, _ = regexp.Compile("(\\d{3})\\d*(\\d{4})")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,10 +32,19 @@ func IsEmailValid(email string) bool {
|
|||||||
return err == nil
|
return err == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsPhoneCnValid(phone string) bool {
|
func IsPhoneValid(phone string, countryCode string) bool {
|
||||||
return rePhoneCn.MatchString(phone)
|
phoneNumber, err := phonenumbers.Parse(phone, countryCode)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return phonenumbers.IsValidNumber(phoneNumber)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getMaskedPhone(phone string) string {
|
func IsPhoneAllowInRegin(countryCode string, allowRegions []string) bool {
|
||||||
return rePhone.ReplaceAllString(phone, "$1****$2")
|
return !ContainsString(allowRegions, countryCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetE164Number(phone string, countryCode string) (string, bool) {
|
||||||
|
phoneNumber, _ := phonenumbers.Parse(phone, countryCode)
|
||||||
|
return phonenumbers.Format(phoneNumber, phonenumbers.E164), phonenumbers.IsValidNumber(phoneNumber)
|
||||||
}
|
}
|
@ -15,7 +15,6 @@ describe("Login test", () => {
|
|||||||
"password": "123",
|
"password": "123",
|
||||||
"autoSignin": true,
|
"autoSignin": true,
|
||||||
"type": "login",
|
"type": "login",
|
||||||
"phonePrefix": "86",
|
|
||||||
},
|
},
|
||||||
}).then((Response) => {
|
}).then((Response) => {
|
||||||
expect(Response).property("body").property("status").to.equal("ok");
|
expect(Response).property("body").property("status").to.equal("ok");
|
||||||
@ -40,7 +39,6 @@ describe("Login test", () => {
|
|||||||
"password": "1234",
|
"password": "1234",
|
||||||
"autoSignin": true,
|
"autoSignin": true,
|
||||||
"type": "login",
|
"type": "login",
|
||||||
"phonePrefix": "86",
|
|
||||||
},
|
},
|
||||||
}).then((Response) => {
|
}).then((Response) => {
|
||||||
expect(Response).property("body").property("status").to.equal("error");
|
expect(Response).property("body").property("status").to.equal("error");
|
||||||
|
@ -34,7 +34,6 @@ Cypress.Commands.add('login', ()=>{
|
|||||||
"password": "123",
|
"password": "123",
|
||||||
"autoSignin": true,
|
"autoSignin": true,
|
||||||
"type": "login",
|
"type": "login",
|
||||||
"phonePrefix": "86",
|
|
||||||
},
|
},
|
||||||
}).then((Response) => {
|
}).then((Response) => {
|
||||||
expect(Response).property("body").property("status").to.equal("ok");
|
expect(Response).property("body").property("status").to.equal("ok");
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@ant-design/cssinjs": "^1.5.6",
|
||||||
"@ant-design/icons": "^4.7.0",
|
"@ant-design/icons": "^4.7.0",
|
||||||
"@craco/craco": "^6.4.5",
|
"@craco/craco": "^6.4.5",
|
||||||
"@crowdin/cli": "^3.7.10",
|
"@crowdin/cli": "^3.7.10",
|
||||||
@ -21,6 +22,7 @@
|
|||||||
"file-saver": "^2.0.5",
|
"file-saver": "^2.0.5",
|
||||||
"i18n-iso-countries": "^7.0.0",
|
"i18n-iso-countries": "^7.0.0",
|
||||||
"i18next": "^19.8.9",
|
"i18next": "^19.8.9",
|
||||||
|
"libphonenumber-js": "^1.10.19",
|
||||||
"moment": "^2.29.1",
|
"moment": "^2.29.1",
|
||||||
"qs": "^6.10.2",
|
"qs": "^6.10.2",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
|
@ -78,6 +78,7 @@ class AccountTable extends React.Component {
|
|||||||
{name: "Password", displayName: i18next.t("general:Password")},
|
{name: "Password", displayName: i18next.t("general:Password")},
|
||||||
{name: "Email", displayName: i18next.t("general:Email")},
|
{name: "Email", displayName: i18next.t("general:Email")},
|
||||||
{name: "Phone", displayName: i18next.t("general:Phone")},
|
{name: "Phone", displayName: i18next.t("general:Phone")},
|
||||||
|
{name: "Country code", displayName: i18next.t("user:Country code")},
|
||||||
{name: "Country/Region", displayName: i18next.t("user:Country/Region")},
|
{name: "Country/Region", displayName: i18next.t("user:Country/Region")},
|
||||||
{name: "Location", displayName: i18next.t("user:Location")},
|
{name: "Location", displayName: i18next.t("user:Location")},
|
||||||
{name: "Affiliation", displayName: i18next.t("user:Affiliation")},
|
{name: "Affiliation", displayName: i18next.t("user:Affiliation")},
|
||||||
|
@ -261,7 +261,7 @@ class AdapterListPage extends BaseListPage {
|
|||||||
searchedColumn: params.searchedColumn,
|
searchedColumn: params.searchedColumn,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
if (res.msg.includes("Unauthorized")) {
|
if (Setting.isResponseDenied(res)) {
|
||||||
this.setState({
|
this.setState({
|
||||||
loading: false,
|
loading: false,
|
||||||
isAuthorized: false,
|
isAuthorized: false,
|
||||||
|
@ -16,8 +16,9 @@ import React, {Component} from "react";
|
|||||||
import "./App.less";
|
import "./App.less";
|
||||||
import {Helmet} from "react-helmet";
|
import {Helmet} from "react-helmet";
|
||||||
import * as Setting from "./Setting";
|
import * as Setting from "./Setting";
|
||||||
import {BarsOutlined, DownOutlined, LogoutOutlined, SettingOutlined} from "@ant-design/icons";
|
import {StyleProvider} from "@ant-design/cssinjs";
|
||||||
import {Avatar, Button, Card, ConfigProvider, Drawer, Dropdown, FloatButton, Layout, Menu, Result} from "antd";
|
import {BarsOutlined, DownOutlined, InfoCircleFilled, LogoutOutlined, SettingOutlined} from "@ant-design/icons";
|
||||||
|
import {Alert, Avatar, Button, Card, ConfigProvider, Drawer, Dropdown, FloatButton, Layout, Menu, Result} from "antd";
|
||||||
import {Link, Redirect, Route, Switch, withRouter} from "react-router-dom";
|
import {Link, Redirect, Route, Switch, withRouter} from "react-router-dom";
|
||||||
import OrganizationListPage from "./OrganizationListPage";
|
import OrganizationListPage from "./OrganizationListPage";
|
||||||
import OrganizationEditPage from "./OrganizationEditPage";
|
import OrganizationEditPage from "./OrganizationEditPage";
|
||||||
@ -671,6 +672,9 @@ class App extends Component {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
|
{
|
||||||
|
this.renderBanner()
|
||||||
|
}
|
||||||
<FloatButton.BackTop />
|
<FloatButton.BackTop />
|
||||||
<CustomGithubCorner />
|
<CustomGithubCorner />
|
||||||
{
|
{
|
||||||
@ -680,6 +684,32 @@ class App extends Component {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderBanner() {
|
||||||
|
if (!Conf.IsDemoMode) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const language = Setting.getLanguage();
|
||||||
|
if (language === "en" || language === "zh") {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Alert type="info" banner showIcon={false} closable message={
|
||||||
|
<div style={{textAlign: "center"}}>
|
||||||
|
<InfoCircleFilled style={{color: "rgb(87,52,211)"}} />
|
||||||
|
|
||||||
|
{i18next.t("general:Found some texts still not translated? Please help us translate at")}
|
||||||
|
|
||||||
|
<a target="_blank" rel="noreferrer" href={"https://crowdin.com/project/casdoor-site"}>
|
||||||
|
Crowdin
|
||||||
|
</a>
|
||||||
|
! 🙏
|
||||||
|
</div>
|
||||||
|
} />
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
@ -700,9 +730,11 @@ class App extends Component {
|
|||||||
},
|
},
|
||||||
algorithm: Setting.getAlgorithm(this.state.themeAlgorithm),
|
algorithm: Setting.getAlgorithm(this.state.themeAlgorithm),
|
||||||
}}>
|
}}>
|
||||||
{
|
<StyleProvider hashPriority="high">
|
||||||
this.renderPage()
|
{
|
||||||
}
|
this.renderPage()
|
||||||
|
}
|
||||||
|
</StyleProvider>
|
||||||
</ConfigProvider>
|
</ConfigProvider>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
|
@ -287,7 +287,7 @@ class ApplicationListPage extends BaseListPage {
|
|||||||
searchedColumn: params.searchedColumn,
|
searchedColumn: params.searchedColumn,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
if (res.msg.includes("Unauthorized")) {
|
if (Setting.isResponseDenied(res)) {
|
||||||
this.setState({
|
this.setState({
|
||||||
loading: false,
|
loading: false,
|
||||||
isAuthorized: false,
|
isAuthorized: false,
|
||||||
|
@ -228,7 +228,7 @@ class CertListPage extends BaseListPage {
|
|||||||
searchedColumn: params.searchedColumn,
|
searchedColumn: params.searchedColumn,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
if (res.msg.includes("Unauthorized")) {
|
if (Setting.isResponseDenied(res)) {
|
||||||
this.setState({
|
this.setState({
|
||||||
loading: false,
|
loading: false,
|
||||||
isAuthorized: false,
|
isAuthorized: false,
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
export const ShowGithubCorner = false;
|
export const ShowGithubCorner = false;
|
||||||
export const GithubRepo = "https://github.com/casdoor/casdoor";
|
export const GithubRepo = "https://github.com/casdoor/casdoor";
|
||||||
|
export const IsDemoMode = false;
|
||||||
|
|
||||||
export const ForceLanguage = "";
|
export const ForceLanguage = "";
|
||||||
export const DefaultLanguage = "en";
|
export const DefaultLanguage = "en";
|
||||||
|
@ -83,8 +83,8 @@ class EntryPage extends React.Component {
|
|||||||
<Route exact path="/forget/:applicationName" render={(props) => this.renderHomeIfLoggedIn(<ForgetPage {...this.props} application={this.state.application} onUpdateApplication={onUpdateApplication} {...props} />)} />
|
<Route exact path="/forget/:applicationName" render={(props) => this.renderHomeIfLoggedIn(<ForgetPage {...this.props} application={this.state.application} onUpdateApplication={onUpdateApplication} {...props} />)} />
|
||||||
<Route exact path="/prompt" render={(props) => this.renderLoginIfNotLoggedIn(<PromptPage {...this.props} application={this.state.application} onUpdateApplication={onUpdateApplication} {...props} />)} />
|
<Route exact path="/prompt" render={(props) => this.renderLoginIfNotLoggedIn(<PromptPage {...this.props} application={this.state.application} onUpdateApplication={onUpdateApplication} {...props} />)} />
|
||||||
<Route exact path="/prompt/:applicationName" render={(props) => this.renderLoginIfNotLoggedIn(<PromptPage {...this.props} application={this.state.application} onUpdateApplication={onUpdateApplication} {...props} />)} />
|
<Route exact path="/prompt/:applicationName" render={(props) => this.renderLoginIfNotLoggedIn(<PromptPage {...this.props} application={this.state.application} onUpdateApplication={onUpdateApplication} {...props} />)} />
|
||||||
<Route exact path="/cas/:owner/:casApplicationName/logout" render={(props) => this.renderHomeIfLoggedIn(<CasLogout {...this.props} application={this.state.application} {...props} />)} />
|
<Route exact path="/cas/:owner/:casApplicationName/logout" render={(props) => this.renderHomeIfLoggedIn(<CasLogout {...this.props} application={this.state.application} onUpdateApplication={onUpdateApplication} {...props} />)} />
|
||||||
<Route exact path="/cas/:owner/:casApplicationName/login" render={(props) => {return (<LoginPage {...this.props} application={this.state.application} type={"cas"} mode={"signup"} {...props} />);}} />
|
<Route exact path="/cas/:owner/:casApplicationName/login" render={(props) => {return (<LoginPage {...this.props} application={this.state.application} type={"cas"} mode={"signup"} onUpdateApplication={onUpdateApplication} {...props} />);}} />
|
||||||
</Switch>
|
</Switch>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -201,7 +201,7 @@ class ModelListPage extends BaseListPage {
|
|||||||
searchedColumn: params.searchedColumn,
|
searchedColumn: params.searchedColumn,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
if (res.msg.includes("Unauthorized")) {
|
if (Setting.isResponseDenied(res)) {
|
||||||
this.setState({
|
this.setState({
|
||||||
loading: false,
|
loading: false,
|
||||||
isAuthorized: false,
|
isAuthorized: false,
|
||||||
|
@ -184,12 +184,20 @@ class OrganizationEditPage extends React.Component {
|
|||||||
</Row>
|
</Row>
|
||||||
<Row style={{marginTop: "20px"}} >
|
<Row style={{marginTop: "20px"}} >
|
||||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||||
{Setting.getLabel(i18next.t("general:Phone prefix"), i18next.t("general:Phone prefix - Tooltip"))} :
|
{Setting.getLabel(i18next.t("general:Supported country code"), i18next.t("general:Supported country code - Tooltip"))} :
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={22} >
|
<Col span={22} >
|
||||||
<Input addonBefore={"+"} value={this.state.organization.phonePrefix} onChange={e => {
|
<Select virtual={false} mode={"multiple"} style={{width: "100%"}} value={this.state.organization.countryCodes ?? []}
|
||||||
this.updateOrganizationField("phonePrefix", e.target.value);
|
options={Setting.getCountriesData().map(country => {
|
||||||
}} />
|
return Setting.getOption(
|
||||||
|
<>
|
||||||
|
{Setting.countryFlag(country)}
|
||||||
|
{`${country.name} +${country.phone}`}
|
||||||
|
</>,
|
||||||
|
country.code);
|
||||||
|
})} onChange={value => {
|
||||||
|
this.updateOrganizationField("countryCodes", value);
|
||||||
|
}} />
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
<Row style={{marginTop: "20px"}} >
|
<Row style={{marginTop: "20px"}} >
|
||||||
@ -257,22 +265,13 @@ class OrganizationEditPage extends React.Component {
|
|||||||
</Col>
|
</Col>
|
||||||
<Col span={22} >
|
<Col span={22} >
|
||||||
<Select virtual={false} mode="tags" style={{width: "100%"}}
|
<Select virtual={false} mode="tags" style={{width: "100%"}}
|
||||||
value={this.state.organization.languages}
|
options={Setting.Countries.map((item) => {
|
||||||
|
return Setting.getOption(item.label, item.key);
|
||||||
|
})}
|
||||||
|
value={this.state.organization.languages ?? []}
|
||||||
onChange={(value => {
|
onChange={(value => {
|
||||||
this.updateOrganizationField("languages", value);
|
this.updateOrganizationField("languages", value);
|
||||||
})} >
|
})} >
|
||||||
{
|
|
||||||
[
|
|
||||||
{value: "en", label: "English"},
|
|
||||||
{value: "zh", label: "简体中文"},
|
|
||||||
{value: "es", label: "Español"},
|
|
||||||
{value: "fr", label: "Français"},
|
|
||||||
{value: "de", label: "Deutsch"},
|
|
||||||
{value: "ja", label: "日本語"},
|
|
||||||
{value: "ko", label: "한국어"},
|
|
||||||
{value: "ru", label: "Русский"},
|
|
||||||
].map((item, index) => <Option key={index} value={item.value}>{item.label}</Option>)
|
|
||||||
}
|
|
||||||
</Select>
|
</Select>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
@ -33,11 +33,11 @@ class OrganizationListPage extends BaseListPage {
|
|||||||
favicon: `${Setting.StaticBaseUrl}/img/favicon.png`,
|
favicon: `${Setting.StaticBaseUrl}/img/favicon.png`,
|
||||||
passwordType: "plain",
|
passwordType: "plain",
|
||||||
PasswordSalt: "",
|
PasswordSalt: "",
|
||||||
phonePrefix: "86",
|
countryCodes: ["CN"],
|
||||||
defaultAvatar: `${Setting.StaticBaseUrl}/img/casbin.svg`,
|
defaultAvatar: `${Setting.StaticBaseUrl}/img/casbin.svg`,
|
||||||
defaultApplication: "",
|
defaultApplication: "",
|
||||||
tags: [],
|
tags: [],
|
||||||
languages: ["en", "zh", "es", "fr", "de", "ja", "ko", "ru"],
|
languages: ["en", "zh", "es", "fr", "de", "ja", "ko", "ru", "vi"],
|
||||||
masterPassword: "",
|
masterPassword: "",
|
||||||
enableSoftDeletion: false,
|
enableSoftDeletion: false,
|
||||||
isProfilePublic: true,
|
isProfilePublic: true,
|
||||||
@ -284,7 +284,7 @@ class OrganizationListPage extends BaseListPage {
|
|||||||
searchedColumn: params.searchedColumn,
|
searchedColumn: params.searchedColumn,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
if (res.msg.includes("Unauthorized")) {
|
if (Setting.isResponseDenied(res)) {
|
||||||
this.setState({
|
this.setState({
|
||||||
loading: false,
|
loading: false,
|
||||||
isAuthorized: false,
|
isAuthorized: false,
|
||||||
|
@ -279,7 +279,7 @@ class PaymentListPage extends BaseListPage {
|
|||||||
searchedColumn: params.searchedColumn,
|
searchedColumn: params.searchedColumn,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
if (res.msg.includes("Unauthorized")) {
|
if (Setting.isResponseDenied(res)) {
|
||||||
this.setState({
|
this.setState({
|
||||||
loading: false,
|
loading: false,
|
||||||
isAuthorized: false,
|
isAuthorized: false,
|
||||||
|
@ -359,7 +359,7 @@ class PermissionListPage extends BaseListPage {
|
|||||||
searchedColumn: params.searchedColumn,
|
searchedColumn: params.searchedColumn,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
if (res.msg.includes("Unauthorized")) {
|
if (Setting.isResponseDenied(res)) {
|
||||||
this.setState({
|
this.setState({
|
||||||
loading: false,
|
loading: false,
|
||||||
isAuthorized: false,
|
isAuthorized: false,
|
||||||
|
@ -296,7 +296,7 @@ class ProductListPage extends BaseListPage {
|
|||||||
searchedColumn: params.searchedColumn,
|
searchedColumn: params.searchedColumn,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
if (res.msg.includes("Unauthorized")) {
|
if (Setting.isResponseDenied(res)) {
|
||||||
this.setState({
|
this.setState({
|
||||||
loading: false,
|
loading: false,
|
||||||
isAuthorized: false,
|
isAuthorized: false,
|
||||||
|
@ -82,20 +82,20 @@ class ProviderEditPage extends React.Component {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
getClientIdLabel() {
|
getClientIdLabel(provider) {
|
||||||
switch (this.state.provider.category) {
|
switch (provider.category) {
|
||||||
case "Email":
|
case "Email":
|
||||||
return Setting.getLabel(i18next.t("signup:Username"), i18next.t("signup:Username - Tooltip"));
|
return Setting.getLabel(i18next.t("signup:Username"), i18next.t("signup:Username - Tooltip"));
|
||||||
case "SMS":
|
case "SMS":
|
||||||
if (this.state.provider.type === "Volc Engine SMS") {
|
if (provider.type === "Volc Engine SMS") {
|
||||||
return Setting.getLabel(i18next.t("provider:Access key"), i18next.t("provider:Access key - Tooltip"));
|
return Setting.getLabel(i18next.t("provider:Access key"), i18next.t("provider:Access key - Tooltip"));
|
||||||
} else if (this.state.provider.type === "Huawei Cloud SMS") {
|
} else if (provider.type === "Huawei Cloud SMS") {
|
||||||
return Setting.getLabel(i18next.t("provider:App key"), i18next.t("provider:App key - Tooltip"));
|
return Setting.getLabel(i18next.t("provider:App key"), i18next.t("provider:App key - Tooltip"));
|
||||||
} else {
|
} else {
|
||||||
return Setting.getLabel(i18next.t("provider:Client ID"), i18next.t("provider:Client ID - Tooltip"));
|
return Setting.getLabel(i18next.t("provider:Client ID"), i18next.t("provider:Client ID - Tooltip"));
|
||||||
}
|
}
|
||||||
case "Captcha":
|
case "Captcha":
|
||||||
if (this.state.provider.type === "Aliyun Captcha") {
|
if (provider.type === "Aliyun Captcha") {
|
||||||
return Setting.getLabel(i18next.t("provider:Access key"), i18next.t("provider:Access key - Tooltip"));
|
return Setting.getLabel(i18next.t("provider:Access key"), i18next.t("provider:Access key - Tooltip"));
|
||||||
} else {
|
} else {
|
||||||
return Setting.getLabel(i18next.t("provider:Site key"), i18next.t("provider:Site key - Tooltip"));
|
return Setting.getLabel(i18next.t("provider:Site key"), i18next.t("provider:Site key - Tooltip"));
|
||||||
@ -105,20 +105,20 @@ class ProviderEditPage extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getClientSecretLabel() {
|
getClientSecretLabel(provider) {
|
||||||
switch (this.state.provider.category) {
|
switch (provider.category) {
|
||||||
case "Email":
|
case "Email":
|
||||||
return Setting.getLabel(i18next.t("login:Password"), i18next.t("login:Password - Tooltip"));
|
return Setting.getLabel(i18next.t("login:Password"), i18next.t("login:Password - Tooltip"));
|
||||||
case "SMS":
|
case "SMS":
|
||||||
if (this.state.provider.type === "Volc Engine SMS") {
|
if (provider.type === "Volc Engine SMS") {
|
||||||
return Setting.getLabel(i18next.t("provider:Secret access key"), i18next.t("provider:SecretAccessKey - Tooltip"));
|
return Setting.getLabel(i18next.t("provider:Secret access key"), i18next.t("provider:SecretAccessKey - Tooltip"));
|
||||||
} else if (this.state.provider.type === "Huawei Cloud SMS") {
|
} else if (provider.type === "Huawei Cloud SMS") {
|
||||||
return Setting.getLabel(i18next.t("provider:App secret"), i18next.t("provider:AppSecret - Tooltip"));
|
return Setting.getLabel(i18next.t("provider:App secret"), i18next.t("provider:AppSecret - Tooltip"));
|
||||||
} else {
|
} else {
|
||||||
return Setting.getLabel(i18next.t("provider:Client secret"), i18next.t("provider:Client secret - Tooltip"));
|
return Setting.getLabel(i18next.t("provider:Client secret"), i18next.t("provider:Client secret - Tooltip"));
|
||||||
}
|
}
|
||||||
case "Captcha":
|
case "Captcha":
|
||||||
if (this.state.provider.type === "Aliyun Captcha") {
|
if (provider.type === "Aliyun Captcha") {
|
||||||
return Setting.getLabel(i18next.t("provider:Secret access key"), i18next.t("provider:SecretAccessKey - Tooltip"));
|
return Setting.getLabel(i18next.t("provider:Secret access key"), i18next.t("provider:SecretAccessKey - Tooltip"));
|
||||||
} else {
|
} else {
|
||||||
return Setting.getLabel(i18next.t("provider:Secret key"), i18next.t("provider:Secret key - Tooltip"));
|
return Setting.getLabel(i18next.t("provider:Secret key"), i18next.t("provider:Secret key - Tooltip"));
|
||||||
@ -128,40 +128,52 @@ class ProviderEditPage extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getAppIdRow() {
|
getAppIdRow(provider) {
|
||||||
let text, tooltip;
|
let text = "";
|
||||||
if (this.state.provider.category === "SMS" && this.state.provider.type === "Tencent Cloud SMS") {
|
let tooltip = "";
|
||||||
text = i18next.t("provider:App ID");
|
|
||||||
tooltip = i18next.t("provider:App ID - Tooltip");
|
if (provider.category === "OAuth") {
|
||||||
} else if (this.state.provider.type === "WeCom" && this.state.provider.subType === "Internal") {
|
if (provider.type === "WeCom" && provider.subType === "Internal") {
|
||||||
text = i18next.t("provider:Agent ID");
|
text = i18next.t("provider:Agent ID");
|
||||||
tooltip = i18next.t("provider:Agent ID - Tooltip");
|
tooltip = i18next.t("provider:Agent ID - Tooltip");
|
||||||
} else if (this.state.provider.type === "Infoflow") {
|
} else if (provider.type === "Infoflow") {
|
||||||
text = i18next.t("provider:Agent ID");
|
text = i18next.t("provider:Agent ID");
|
||||||
tooltip = i18next.t("provider:Agent ID - Tooltip");
|
tooltip = i18next.t("provider:Agent ID - Tooltip");
|
||||||
} else if (this.state.provider.category === "SMS" && this.state.provider.type === "Volc Engine SMS") {
|
}
|
||||||
text = i18next.t("provider:SMS account");
|
} else if (provider.category === "SMS") {
|
||||||
tooltip = i18next.t("provider:SMS account - Tooltip");
|
if (provider.type === "Tencent Cloud SMS") {
|
||||||
} else if (this.state.provider.category === "SMS" && this.state.provider.type === "Huawei Cloud SMS") {
|
text = i18next.t("provider:App ID");
|
||||||
text = i18next.t("provider:Channel No.");
|
tooltip = i18next.t("provider:App ID - Tooltip");
|
||||||
tooltip = i18next.t("provider:Channel No. - Tooltip");
|
} else if (provider.type === "Volc Engine SMS") {
|
||||||
} else if (this.state.provider.category === "Email" && this.state.provider.type === "SUBMAIL") {
|
text = i18next.t("provider:SMS account");
|
||||||
text = i18next.t("provider:App ID");
|
tooltip = i18next.t("provider:SMS account - Tooltip");
|
||||||
tooltip = i18next.t("provider:App ID - Tooltip");
|
} else if (provider.type === "Huawei Cloud SMS") {
|
||||||
} else {
|
text = i18next.t("provider:Channel No.");
|
||||||
return null;
|
tooltip = i18next.t("provider:Channel No. - Tooltip");
|
||||||
|
}
|
||||||
|
} else if (provider.category === "Email") {
|
||||||
|
if (provider.type === "SUBMAIL") {
|
||||||
|
text = i18next.t("provider:App ID");
|
||||||
|
tooltip = i18next.t("provider:App ID - Tooltip");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return <Row style={{marginTop: "20px"}} >
|
if (text === "" && tooltip === "") {
|
||||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
return null;
|
||||||
{Setting.getLabel(text, tooltip)} :
|
} else {
|
||||||
</Col>
|
return (
|
||||||
<Col span={22} >
|
<Row style={{marginTop: "20px"}} >
|
||||||
<Input value={this.state.provider.appId} onChange={e => {
|
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||||
this.updateProviderField("appId", e.target.value);
|
{Setting.getLabel(text, tooltip)} :
|
||||||
}} />
|
</Col>
|
||||||
</Col>
|
<Col span={22} >
|
||||||
</Row>;
|
<Input value={provider.appId} onChange={e => {
|
||||||
|
this.updateProviderField("appId", e.target.value);
|
||||||
|
}} />
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
loadSamlConfiguration() {
|
loadSamlConfiguration() {
|
||||||
@ -404,7 +416,7 @@ class ProviderEditPage extends React.Component {
|
|||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<Row style={{marginTop: "20px"}} >
|
<Row style={{marginTop: "20px"}} >
|
||||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||||
{this.getClientIdLabel()}
|
{this.getClientIdLabel(this.state.provider)}
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={22} >
|
<Col span={22} >
|
||||||
<Input value={this.state.provider.clientId} onChange={e => {
|
<Input value={this.state.provider.clientId} onChange={e => {
|
||||||
@ -414,7 +426,7 @@ class ProviderEditPage extends React.Component {
|
|||||||
</Row>
|
</Row>
|
||||||
<Row style={{marginTop: "20px"}} >
|
<Row style={{marginTop: "20px"}} >
|
||||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||||
{this.getClientSecretLabel()}
|
{this.getClientSecretLabel(this.state.provider)}
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={22} >
|
<Col span={22} >
|
||||||
<Input value={this.state.provider.clientSecret} onChange={e => {
|
<Input value={this.state.provider.clientSecret} onChange={e => {
|
||||||
@ -750,7 +762,7 @@ class ProviderEditPage extends React.Component {
|
|||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
) : null
|
) : null
|
||||||
}
|
}
|
||||||
{this.getAppIdRow()}
|
{this.getAppIdRow(this.state.provider)}
|
||||||
<Row style={{marginTop: "20px"}} >
|
<Row style={{marginTop: "20px"}} >
|
||||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||||
{Setting.getLabel(i18next.t("provider:Provider URL"), i18next.t("provider:Provider URL - Tooltip"))} :
|
{Setting.getLabel(i18next.t("provider:Provider URL"), i18next.t("provider:Provider URL - Tooltip"))} :
|
||||||
|
@ -267,7 +267,7 @@ class ProviderListPage extends BaseListPage {
|
|||||||
searchedColumn: params.searchedColumn,
|
searchedColumn: params.searchedColumn,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
if (res.msg.includes("Unauthorized")) {
|
if (Setting.isResponseDenied(res)) {
|
||||||
this.setState({
|
this.setState({
|
||||||
loading: false,
|
loading: false,
|
||||||
isAuthorized: false,
|
isAuthorized: false,
|
||||||
|
@ -232,7 +232,7 @@ class RoleListPage extends BaseListPage {
|
|||||||
searchedColumn: params.searchedColumn,
|
searchedColumn: params.searchedColumn,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
if (res.msg.includes("Unauthorized")) {
|
if (Setting.isResponseDenied(res)) {
|
||||||
this.setState({
|
this.setState({
|
||||||
loading: false,
|
loading: false,
|
||||||
isAuthorized: false,
|
isAuthorized: false,
|
||||||
|
@ -18,16 +18,6 @@ import {Dropdown} from "antd";
|
|||||||
import "./App.less";
|
import "./App.less";
|
||||||
import {GlobalOutlined} from "@ant-design/icons";
|
import {GlobalOutlined} from "@ant-design/icons";
|
||||||
|
|
||||||
export const Countries = [{label: "English", key: "en", country: "US", alt: "English"},
|
|
||||||
{label: "简体中文", key: "zh", country: "CN", alt: "简体中文"},
|
|
||||||
{label: "Español", key: "es", country: "ES", alt: "Español"},
|
|
||||||
{label: "Français", key: "fr", country: "FR", alt: "Français"},
|
|
||||||
{label: "Deutsch", key: "de", country: "DE", alt: "Deutsch"},
|
|
||||||
{label: "日本語", key: "ja", country: "JP", alt: "日本語"},
|
|
||||||
{label: "한국어", key: "ko", country: "KR", alt: "한국어"},
|
|
||||||
{label: "Русский", key: "ru", country: "RU", alt: "Русский"},
|
|
||||||
];
|
|
||||||
|
|
||||||
function flagIcon(country, alt) {
|
function flagIcon(country, alt) {
|
||||||
return (
|
return (
|
||||||
<img width={24} alt={alt} src={`${Setting.StaticBaseUrl}/flag-icons/${country}.svg`} />
|
<img width={24} alt={alt} src={`${Setting.StaticBaseUrl}/flag-icons/${country}.svg`} />
|
||||||
@ -39,15 +29,15 @@ class SelectLanguageBox extends React.Component {
|
|||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
classes: props,
|
classes: props,
|
||||||
languages: props.languages ?? ["en", "zh", "es", "fr", "de", "ja", "ko", "ru"],
|
languages: props.languages ?? Setting.Countries.map(item => item.key),
|
||||||
};
|
};
|
||||||
|
|
||||||
Countries.forEach((country) => {
|
Setting.Countries.forEach((country) => {
|
||||||
new Image().src = `${Setting.StaticBaseUrl}/flag-icons/${country.country}.svg`;
|
new Image().src = `${Setting.StaticBaseUrl}/flag-icons/${country.country}.svg`;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
items = Countries.map((country) => Setting.getItem(country.label, country.key, flagIcon(country.country, country.alt)));
|
items = Setting.Countries.map((country) => Setting.getItem(country.label, country.key, flagIcon(country.country, country.alt)));
|
||||||
|
|
||||||
getOrganizationLanguages(languages) {
|
getOrganizationLanguages(languages) {
|
||||||
const select = [];
|
const select = [];
|
||||||
|
@ -49,9 +49,9 @@ class SelectRegionBox extends React.Component {
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
{
|
{
|
||||||
Setting.getCountryNames().map((item) => (
|
Setting.getCountriesData().map((item) => (
|
||||||
<Option key={item.code} value={item.code} label={`${item.name} (${item.code})`} >
|
<Option key={item.code} value={item.code} label={`${item.name} (${item.code})`} >
|
||||||
<img src={`${Setting.StaticBaseUrl}/flag-icons/${item.code}.svg`} alt={item.name} height={20} style={{marginRight: 10}} />
|
{Setting.countryFlag(item)}
|
||||||
{`${item.name} (${item.code})`}
|
{`${item.name} (${item.code})`}
|
||||||
</Option>
|
</Option>
|
||||||
))
|
))
|
||||||
|
@ -148,7 +148,7 @@ class SessionListPage extends BaseListPage {
|
|||||||
searchedColumn: params.searchedColumn,
|
searchedColumn: params.searchedColumn,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
if (res.msg.includes("Unauthorized")) {
|
if (Setting.isResponseDenied(res)) {
|
||||||
this.setState({
|
this.setState({
|
||||||
loading: false,
|
loading: false,
|
||||||
isAuthorized: false,
|
isAuthorized: false,
|
||||||
|
@ -23,6 +23,7 @@ import copy from "copy-to-clipboard";
|
|||||||
import {authConfig} from "./auth/Auth";
|
import {authConfig} from "./auth/Auth";
|
||||||
import {Helmet} from "react-helmet";
|
import {Helmet} from "react-helmet";
|
||||||
import * as Conf from "./Conf";
|
import * as Conf from "./Conf";
|
||||||
|
import * as phoneNumber from "libphonenumber-js";
|
||||||
import * as path from "path-browserify";
|
import * as path from "path-browserify";
|
||||||
|
|
||||||
export const ServerUrl = "";
|
export const ServerUrl = "";
|
||||||
@ -30,6 +31,17 @@ export const ServerUrl = "";
|
|||||||
// export const StaticBaseUrl = "https://cdn.jsdelivr.net/gh/casbin/static";
|
// export const StaticBaseUrl = "https://cdn.jsdelivr.net/gh/casbin/static";
|
||||||
export const StaticBaseUrl = "https://cdn.casbin.org";
|
export const StaticBaseUrl = "https://cdn.casbin.org";
|
||||||
|
|
||||||
|
export const Countries = [{label: "English", key: "en", country: "US", alt: "English"},
|
||||||
|
{label: "中文", key: "zh", country: "CN", alt: "中文"},
|
||||||
|
{label: "Español", key: "es", country: "ES", alt: "Español"},
|
||||||
|
{label: "Français", key: "fr", country: "FR", alt: "Français"},
|
||||||
|
{label: "Deutsch", key: "de", country: "DE", alt: "Deutsch"},
|
||||||
|
{label: "日本語", key: "ja", country: "JP", alt: "日本語"},
|
||||||
|
{label: "한국어", key: "ko", country: "KR", alt: "한국어"},
|
||||||
|
{label: "Русский", key: "ru", country: "RU", alt: "Русский"},
|
||||||
|
{label: "TiếngViệt", key: "vi", country: "VI", alt: "TiếngViệt"},
|
||||||
|
];
|
||||||
|
|
||||||
export function getThemeData(organization, application) {
|
export function getThemeData(organization, application) {
|
||||||
if (application?.themeData?.isEnabled) {
|
if (application?.themeData?.isEnabled) {
|
||||||
return application.themeData;
|
return application.themeData;
|
||||||
@ -188,20 +200,33 @@ export const OtherProviderInfo = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export function getCountriesData() {
|
export function initCountries() {
|
||||||
const countries = require("i18n-iso-countries");
|
const countries = require("i18n-iso-countries");
|
||||||
countries.registerLocale(require("i18n-iso-countries/langs/" + getLanguage() + ".json"));
|
countries.registerLocale(require("i18n-iso-countries/langs/" + getLanguage() + ".json"));
|
||||||
return countries;
|
return countries;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getCountryNames() {
|
export function getCountriesData(countryCodes = phoneNumber.getCountries()) {
|
||||||
const data = getCountriesData().getNames(getLanguage(), {select: "official"});
|
return countryCodes?.map((countryCode) => {
|
||||||
|
if (phoneNumber.isSupportedCountry(countryCode)) {
|
||||||
return Object.entries(data).map(items => {
|
const name = initCountries().getName(countryCode, getLanguage());
|
||||||
return {code: items[0], name: items[1]};
|
return {
|
||||||
|
code: countryCode,
|
||||||
|
name: name || "",
|
||||||
|
phone: phoneNumber.getCountryCallingCode(countryCode),
|
||||||
|
};
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function countryFlag(country) {
|
||||||
|
return <img src={`${StaticBaseUrl}/flag-icons/${country.code}.svg`} alt={country.name} height={20} style={{marginRight: 10}} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getPhoneCodeFromCountryCode(countryCode) {
|
||||||
|
return phoneNumber.isSupportedCountry(countryCode) ? phoneNumber.getCountryCallingCode(countryCode) : "";
|
||||||
|
}
|
||||||
|
|
||||||
export function initServerUrl() {
|
export function initServerUrl() {
|
||||||
// const hostname = window.location.hostname;
|
// const hostname = window.location.hostname;
|
||||||
// if (hostname === "localhost") {
|
// if (hostname === "localhost") {
|
||||||
@ -238,6 +263,13 @@ export function isProviderVisible(providerItem) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isResponseDenied(data) {
|
||||||
|
if (data.msg === "Unauthorized operation" || data.msg === "未授权的操作") {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
export function isProviderVisibleForSignUp(providerItem) {
|
export function isProviderVisibleForSignUp(providerItem) {
|
||||||
if (providerItem.canSignUp === false) {
|
if (providerItem.canSignUp === false) {
|
||||||
return false;
|
return false;
|
||||||
@ -299,16 +331,14 @@ export function isValidEmail(email) {
|
|||||||
return emailRegex.test(email);
|
return emailRegex.test(email);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isValidPhone(phone) {
|
export function isValidPhone(phone, countryCode = "") {
|
||||||
return phone !== "";
|
if (countryCode !== "") {
|
||||||
|
return phoneNumber.isValidPhoneNumber(phone, countryCode);
|
||||||
|
}
|
||||||
|
|
||||||
// if (phone === "") {
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // https://learnku.com/articles/31543, `^s*$` filter empty email individually.
|
// // https://learnku.com/articles/31543, `^s*$` filter empty email individually.
|
||||||
// const phoneRegex = /^\s*$|^1(3\d|4[5-9]|5[0-35-9]|6[2567]|7[0-8]|8\d|9[0-35-9])\d{8}$/;
|
const phoneRegex = /[0-9]{4,15}$/;
|
||||||
// return phoneRegex.test(phone);
|
return phoneRegex.test(phone);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isValidInvoiceTitle(invoiceTitle) {
|
export function isValidInvoiceTitle(invoiceTitle) {
|
||||||
|
@ -289,7 +289,7 @@ class SyncerListPage extends BaseListPage {
|
|||||||
searchedColumn: params.searchedColumn,
|
searchedColumn: params.searchedColumn,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
if (res.msg.includes("Unauthorized")) {
|
if (Setting.isResponseDenied(res)) {
|
||||||
this.setState({
|
this.setState({
|
||||||
loading: false,
|
loading: false,
|
||||||
isAuthorized: false,
|
isAuthorized: false,
|
||||||
|
@ -254,7 +254,7 @@ class TokenListPage extends BaseListPage {
|
|||||||
searchedColumn: params.searchedColumn,
|
searchedColumn: params.searchedColumn,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
if (res.msg.includes("Unauthorized")) {
|
if (Setting.isResponseDenied(res)) {
|
||||||
this.setState({
|
this.setState({
|
||||||
loading: false,
|
loading: false,
|
||||||
isAuthorized: false,
|
isAuthorized: false,
|
||||||
|
@ -29,6 +29,7 @@ import SelectRegionBox from "./SelectRegionBox";
|
|||||||
import WebAuthnCredentialTable from "./WebauthnCredentialTable";
|
import WebAuthnCredentialTable from "./WebauthnCredentialTable";
|
||||||
import ManagedAccountTable from "./ManagedAccountTable";
|
import ManagedAccountTable from "./ManagedAccountTable";
|
||||||
import PropertyTable from "./propertyTable";
|
import PropertyTable from "./propertyTable";
|
||||||
|
import PhoneNumberInput from "./common/PhoneNumberInput";
|
||||||
|
|
||||||
const {Option} = Select;
|
const {Option} = Select;
|
||||||
|
|
||||||
@ -286,11 +287,13 @@ class UserEditPage extends React.Component {
|
|||||||
<Col style={{paddingRight: "20px"}} span={11} >
|
<Col style={{paddingRight: "20px"}} span={11} >
|
||||||
{Setting.isLocalAdminUser(this.props.account) ?
|
{Setting.isLocalAdminUser(this.props.account) ?
|
||||||
(<Input value={this.state.user.email}
|
(<Input value={this.state.user.email}
|
||||||
|
style={{width: "280Px"}}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
onChange={e => {
|
onChange={e => {
|
||||||
this.updateUserField("email", e.target.value);
|
this.updateUserField("email", e.target.value);
|
||||||
}} />) :
|
}} />) :
|
||||||
(<Select virtual={false} value={this.state.user.email}
|
(<Select virtual={false} value={this.state.user.email}
|
||||||
|
style={{width: "280Px"}}
|
||||||
options={[Setting.getItem(this.state.user.email, this.state.user.email)]}
|
options={[Setting.getItem(this.state.user.email, this.state.user.email)]}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
onChange={e => {
|
onChange={e => {
|
||||||
@ -298,7 +301,7 @@ class UserEditPage extends React.Component {
|
|||||||
}} />)
|
}} />)
|
||||||
}
|
}
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={11} >
|
<Col span={Setting.isMobile() ? 22 : 11} >
|
||||||
{/* backend auto get the current user, so admin can not edit. Just self can reset*/}
|
{/* backend auto get the current user, so admin can not edit. Just self can reset*/}
|
||||||
{this.isSelf() ? <ResetModal application={this.state.application} disabled={disabled} buttonText={i18next.t("user:Reset Email...")} destType={"email"} /> : null}
|
{this.isSelf() ? <ResetModal application={this.state.application} disabled={disabled} buttonText={i18next.t("user:Reset Email...")} destType={"email"} /> : null}
|
||||||
</Col>
|
</Col>
|
||||||
@ -307,24 +310,37 @@ class UserEditPage extends React.Component {
|
|||||||
} else if (accountItem.name === "Phone") {
|
} else if (accountItem.name === "Phone") {
|
||||||
return (
|
return (
|
||||||
<Row style={{marginTop: "20px"}} >
|
<Row style={{marginTop: "20px"}} >
|
||||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
<Col style={{marginTop: "5px"}} span={Setting.isMobile() ? 22 : 2}>
|
||||||
{Setting.getLabel(i18next.t("general:Phone"), i18next.t("general:Phone - Tooltip"))} :
|
{Setting.getLabel(i18next.t("general:Phone"), i18next.t("general:Phone - Tooltip"))} :
|
||||||
</Col>
|
</Col>
|
||||||
<Col style={{paddingRight: "20px"}} span={11} >
|
<Col style={{paddingRight: "20px"}} span={11} >
|
||||||
{Setting.isLocalAdminUser(this.props.account) ?
|
{Setting.isLocalAdminUser(this.props.account) ?
|
||||||
<Input value={this.state.user.phone} addonBefore={`+${this.state.application?.organizationObj.phonePrefix}`}
|
<Input.Group compact style={{width: "280Px"}}>
|
||||||
disabled={disabled}
|
<PhoneNumberInput
|
||||||
onChange={e => {
|
style={{width: "30%"}}
|
||||||
this.updateUserField("phone", e.target.value);
|
value={this.state.user.countryCode}
|
||||||
}} /> :
|
onChange={(value) => {
|
||||||
(<Select virtual={false} value={`+${this.state.application?.organizationObj.phonePrefix} ${this.state.user.phone}`}
|
this.updateUserField("countryCode", value);
|
||||||
options={[Setting.getItem(`+${this.state.application?.organizationObj.phonePrefix} ${this.state.user.phone}`, this.state.user.phone)]}
|
}}
|
||||||
|
countryCodes={this.state.application?.organizationObj.countryCodes}
|
||||||
|
/>
|
||||||
|
<Input value={this.state.user.phone}
|
||||||
|
style={{width: "70%"}}
|
||||||
|
disabled={disabled}
|
||||||
|
onChange={e => {
|
||||||
|
this.updateUserField("phone", e.target.value);
|
||||||
|
}} />
|
||||||
|
</Input.Group>
|
||||||
|
:
|
||||||
|
(<Select virtual={false} value={this.state.user.phone === "" ? null : `+${Setting.getPhoneCodeFromCountryCode(this.state.user.countryCode)} ${this.state.user.phone}`}
|
||||||
|
options={this.state.user.phone === "" ? null : [Setting.getItem(`+${Setting.getPhoneCodeFromCountryCode(this.state.user.countryCode)} ${this.state.user.phone}`, this.state.user.phone)]}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
|
style={{width: "280px"}}
|
||||||
onChange={e => {
|
onChange={e => {
|
||||||
this.updateUserField("phone", e.target.value);
|
this.updateUserField("phone", e.target.value);
|
||||||
}} />)}
|
}} />)}
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={11} >
|
<Col span={Setting.isMobile() ? 24 : 11} >
|
||||||
{this.isSelf() ? (<ResetModal application={this.state.application} disabled={disabled} buttonText={i18next.t("user:Reset Phone...")} destType={"phone"} />) : null}
|
{this.isSelf() ? (<ResetModal application={this.state.application} disabled={disabled} buttonText={i18next.t("user:Reset Phone...")} destType={"phone"} />) : null}
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
@ -49,6 +49,7 @@ class UserListPage extends BaseListPage {
|
|||||||
avatar: `${Setting.StaticBaseUrl}/img/casbin.svg`,
|
avatar: `${Setting.StaticBaseUrl}/img/casbin.svg`,
|
||||||
email: `${randomName}@example.com`,
|
email: `${randomName}@example.com`,
|
||||||
phone: Setting.getRandomNumber(),
|
phone: Setting.getRandomNumber(),
|
||||||
|
countryCode: this.state.organization.countryCodes?.length > 0 ? this.state.organization.countryCodes[0] : "",
|
||||||
address: [],
|
address: [],
|
||||||
affiliation: "Example Inc.",
|
affiliation: "Example Inc.",
|
||||||
tag: "staff",
|
tag: "staff",
|
||||||
@ -261,7 +262,7 @@ class UserListPage extends BaseListPage {
|
|||||||
sorter: true,
|
sorter: true,
|
||||||
...this.getColumnSearchProps("region"),
|
...this.getColumnSearchProps("region"),
|
||||||
render: (text, record, index) => {
|
render: (text, record, index) => {
|
||||||
return Setting.getCountriesData().getName(record.region, Setting.getLanguage(), {select: "official"});
|
return Setting.initCountries().getName(record.region, Setting.getLanguage(), {select: "official"});
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -403,7 +404,7 @@ class UserListPage extends BaseListPage {
|
|||||||
this.getOrganization(users[0].owner);
|
this.getOrganization(users[0].owner);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (res.msg.includes("Unauthorized")) {
|
if (Setting.isResponseDenied(res)) {
|
||||||
this.setState({
|
this.setState({
|
||||||
loading: false,
|
loading: false,
|
||||||
isAuthorized: false,
|
isAuthorized: false,
|
||||||
@ -431,7 +432,7 @@ class UserListPage extends BaseListPage {
|
|||||||
this.getOrganization(users[0].owner);
|
this.getOrganization(users[0].owner);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (res.msg.includes("Unauthorized")) {
|
if (Setting.isResponseDenied(res)) {
|
||||||
this.setState({
|
this.setState({
|
||||||
loading: false,
|
loading: false,
|
||||||
isAuthorized: false,
|
isAuthorized: false,
|
||||||
|
@ -254,7 +254,7 @@ class WebhookListPage extends BaseListPage {
|
|||||||
searchedColumn: params.searchedColumn,
|
searchedColumn: params.searchedColumn,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
if (res.msg.includes("Unauthorized")) {
|
if (Setting.isResponseDenied(res)) {
|
||||||
this.setState({
|
this.setState({
|
||||||
loading: false,
|
loading: false,
|
||||||
isAuthorized: false,
|
isAuthorized: false,
|
||||||
|
@ -40,7 +40,6 @@ class CasLogout extends React.Component {
|
|||||||
if (res.status === "ok") {
|
if (res.status === "ok") {
|
||||||
Setting.showMessage("success", "Logged out successfully");
|
Setting.showMessage("success", "Logged out successfully");
|
||||||
this.props.onUpdateAccount(null);
|
this.props.onUpdateAccount(null);
|
||||||
this.onUpdateApplication(null);
|
|
||||||
const redirectUri = res.data2;
|
const redirectUri = res.data2;
|
||||||
if (redirectUri !== null && redirectUri !== undefined && redirectUri !== "") {
|
if (redirectUri !== null && redirectUri !== undefined && redirectUri !== "") {
|
||||||
Setting.goToLink(redirectUri);
|
Setting.goToLink(redirectUri);
|
||||||
@ -50,7 +49,6 @@ class CasLogout extends React.Component {
|
|||||||
Setting.goToLinkSoft(this, `/cas/${this.state.owner}/${this.state.applicationName}/login`);
|
Setting.goToLinkSoft(this, `/cas/${this.state.owner}/${this.state.applicationName}/login`);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.onUpdateApplication(null);
|
|
||||||
Setting.showMessage("error", `Failed to log out: ${res.msg}`);
|
Setting.showMessage("error", `Failed to log out: ${res.msg}`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -140,7 +140,6 @@ class ForgetPage extends React.Component {
|
|||||||
username: this.state.username,
|
username: this.state.username,
|
||||||
name: this.state.name,
|
name: this.state.name,
|
||||||
code: forms.step2.getFieldValue("emailCode"),
|
code: forms.step2.getFieldValue("emailCode"),
|
||||||
phonePrefix: this.getApplicationObj()?.organizationObj.phonePrefix,
|
|
||||||
type: "login",
|
type: "login",
|
||||||
}, oAuthParams).then(res => {
|
}, oAuthParams).then(res => {
|
||||||
if (res.status === "ok") {
|
if (res.status === "ok") {
|
||||||
|
@ -16,6 +16,7 @@ import React from "react";
|
|||||||
import {Button, Checkbox, Col, Form, Input, Result, Row, Spin, Tabs} from "antd";
|
import {Button, Checkbox, Col, Form, Input, Result, Row, Spin, Tabs} from "antd";
|
||||||
import {LockOutlined, UserOutlined} from "@ant-design/icons";
|
import {LockOutlined, UserOutlined} from "@ant-design/icons";
|
||||||
import * as UserWebauthnBackend from "../backend/UserWebauthnBackend";
|
import * as UserWebauthnBackend from "../backend/UserWebauthnBackend";
|
||||||
|
import * as Conf from "../Conf";
|
||||||
import * as AuthBackend from "./AuthBackend";
|
import * as AuthBackend from "./AuthBackend";
|
||||||
import * as OrganizationBackend from "../backend/OrganizationBackend";
|
import * as OrganizationBackend from "../backend/OrganizationBackend";
|
||||||
import * as ApplicationBackend from "../backend/ApplicationBackend";
|
import * as ApplicationBackend from "../backend/ApplicationBackend";
|
||||||
@ -189,7 +190,6 @@ class LoginPage extends React.Component {
|
|||||||
} else {
|
} else {
|
||||||
values["type"] = this.state.type;
|
values["type"] = this.state.type;
|
||||||
}
|
}
|
||||||
values["phonePrefix"] = this.getApplicationObj()?.organizationObj.phonePrefix;
|
|
||||||
|
|
||||||
if (oAuthParams !== null) {
|
if (oAuthParams !== null) {
|
||||||
values["samlRequest"] = oAuthParams.samlRequest;
|
values["samlRequest"] = oAuthParams.samlRequest;
|
||||||
@ -204,6 +204,7 @@ class LoginPage extends React.Component {
|
|||||||
values["organization"] = this.getApplicationObj().organization;
|
values["organization"] = this.getApplicationObj().organization;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
postCodeLoginAction(res) {
|
postCodeLoginAction(res) {
|
||||||
const application = this.getApplicationObj();
|
const application = this.getApplicationObj();
|
||||||
const ths = this;
|
const ths = this;
|
||||||
@ -364,7 +365,8 @@ class LoginPage extends React.Component {
|
|||||||
title={i18next.t("application:Sign Up Error")}
|
title={i18next.t("application:Sign Up Error")}
|
||||||
subTitle={i18next.t("application:The application does not allow to sign up new account")}
|
subTitle={i18next.t("application:The application does not allow to sign up new account")}
|
||||||
extra={[
|
extra={[
|
||||||
<Button type="primary" key="signin" onClick={() => Setting.redirectToLoginPage(application, this.props.history)}>
|
<Button type="primary" key="signin"
|
||||||
|
onClick={() => Setting.redirectToLoginPage(application, this.props.history)}>
|
||||||
{
|
{
|
||||||
i18next.t("login:Sign In")
|
i18next.t("login:Sign In")
|
||||||
}
|
}
|
||||||
@ -383,8 +385,12 @@ class LoginPage extends React.Component {
|
|||||||
organization: application.organization,
|
organization: application.organization,
|
||||||
application: application.name,
|
application: application.name,
|
||||||
autoSignin: true,
|
autoSignin: true,
|
||||||
|
username: Conf.ShowGithubCorner ? "admin" : "",
|
||||||
|
password: Conf.ShowGithubCorner ? "123" : "",
|
||||||
|
}}
|
||||||
|
onFinish={(values) => {
|
||||||
|
this.onFinish(values);
|
||||||
}}
|
}}
|
||||||
onFinish={(values) => {this.onFinish(values);}}
|
|
||||||
style={{width: "300px"}}
|
style={{width: "300px"}}
|
||||||
size="large"
|
size="large"
|
||||||
ref={this.form}
|
ref={this.form}
|
||||||
@ -424,7 +430,7 @@ class LoginPage extends React.Component {
|
|||||||
{
|
{
|
||||||
validator: (_, value) => {
|
validator: (_, value) => {
|
||||||
if (this.state.loginMethod === "verificationCode") {
|
if (this.state.loginMethod === "verificationCode") {
|
||||||
if (this.state.email !== "" && !Setting.isValidEmail(this.state.username) && !Setting.isValidPhone(this.state.username)) {
|
if (!Setting.isValidEmail(this.state.username) && !Setting.isValidPhone(this.state.username)) {
|
||||||
this.setState({validEmailOrPhone: false});
|
this.setState({validEmailOrPhone: false});
|
||||||
return Promise.reject(i18next.t("login:The input is not valid Email or Phone!"));
|
return Promise.reject(i18next.t("login:The input is not valid Email or Phone!"));
|
||||||
}
|
}
|
||||||
@ -444,7 +450,7 @@ class LoginPage extends React.Component {
|
|||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<Input
|
<Input
|
||||||
id = "input"
|
id="input"
|
||||||
prefix={<UserOutlined className="site-form-item-icon" />}
|
prefix={<UserOutlined className="site-form-item-icon" />}
|
||||||
placeholder={(this.state.loginMethod === "verificationCode") ? i18next.t("login:Email or phone") : i18next.t("login:username, Email or phone")}
|
placeholder={(this.state.loginMethod === "verificationCode") ? i18next.t("login:Email or phone") : i18next.t("login:username, Email or phone")}
|
||||||
disabled={!application.enablePassword}
|
disabled={!application.enablePassword}
|
||||||
@ -774,13 +780,18 @@ class LoginPage extends React.Component {
|
|||||||
const items = [
|
const items = [
|
||||||
{label: i18next.t("login:Password"), key: "password"},
|
{label: i18next.t("login:Password"), key: "password"},
|
||||||
];
|
];
|
||||||
application.enableCodeSignin ? items.push({label: i18next.t("login:Verification Code"), key: "verificationCode"}) : null;
|
application.enableCodeSignin ? items.push({
|
||||||
|
label: i18next.t("login:Verification Code"),
|
||||||
|
key: "verificationCode",
|
||||||
|
}) : null;
|
||||||
application.enableWebAuthn ? items.push({label: i18next.t("login:WebAuthn"), key: "webAuthn"}) : null;
|
application.enableWebAuthn ? items.push({label: i18next.t("login:WebAuthn"), key: "webAuthn"}) : null;
|
||||||
|
|
||||||
if (application.enableCodeSignin || application.enableWebAuthn) {
|
if (application.enableCodeSignin || application.enableWebAuthn) {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Tabs items={items} size={"small"} defaultActiveKey="password" onChange={(key) => {this.setState({loginMethod: key});}} centered>
|
<Tabs items={items} size={"small"} defaultActiveKey="password" onChange={(key) => {
|
||||||
|
this.setState({loginMethod: key});
|
||||||
|
}} centered>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -823,7 +834,7 @@ class LoginPage extends React.Component {
|
|||||||
<div dangerouslySetInnerHTML={{__html: application.formSideHtml}} />
|
<div dangerouslySetInnerHTML={{__html: application.formSideHtml}} />
|
||||||
</div>
|
</div>
|
||||||
<div className="login-form">
|
<div className="login-form">
|
||||||
<div >
|
<div>
|
||||||
<div>
|
<div>
|
||||||
{
|
{
|
||||||
Setting.renderHelmet(application)
|
Setting.renderHelmet(application)
|
||||||
|
@ -26,6 +26,7 @@ import SelectRegionBox from "../SelectRegionBox";
|
|||||||
import CustomGithubCorner from "../CustomGithubCorner";
|
import CustomGithubCorner from "../CustomGithubCorner";
|
||||||
import SelectLanguageBox from "../SelectLanguageBox";
|
import SelectLanguageBox from "../SelectLanguageBox";
|
||||||
import {withRouter} from "react-router-dom";
|
import {withRouter} from "react-router-dom";
|
||||||
|
import PhoneNumberInput from "../common/PhoneNumberInput";
|
||||||
|
|
||||||
const formItemLayout = {
|
const formItemLayout = {
|
||||||
labelCol: {
|
labelCol: {
|
||||||
@ -68,6 +69,7 @@ class SignupPage extends React.Component {
|
|||||||
application: null,
|
application: null,
|
||||||
email: "",
|
email: "",
|
||||||
phone: "",
|
phone: "",
|
||||||
|
countryCode: "",
|
||||||
emailCode: "",
|
emailCode: "",
|
||||||
phoneCode: "",
|
phoneCode: "",
|
||||||
validEmail: false,
|
validEmail: false,
|
||||||
@ -157,7 +159,6 @@ class SignupPage extends React.Component {
|
|||||||
|
|
||||||
onFinish(values) {
|
onFinish(values) {
|
||||||
const application = this.getApplicationObj();
|
const application = this.getApplicationObj();
|
||||||
values.phonePrefix = application.organizationObj.phonePrefix;
|
|
||||||
AuthBackend.signup(values)
|
AuthBackend.signup(values)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
if (res.status === "ok") {
|
if (res.status === "ok") {
|
||||||
@ -378,35 +379,66 @@ class SignupPage extends React.Component {
|
|||||||
} else if (signupItem.name === "Phone") {
|
} else if (signupItem.name === "Phone") {
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<Form.Item
|
<Form.Item label={i18next.t("general:Phone")} required>
|
||||||
name="phone"
|
<Input.Group compact>
|
||||||
key="phone"
|
<Form.Item
|
||||||
label={i18next.t("general:Phone")}
|
name="countryCode"
|
||||||
rules={[
|
key="countryCode"
|
||||||
{
|
noStyle
|
||||||
required: required,
|
rules={[
|
||||||
message: i18next.t("signup:Please input your phone number!"),
|
{
|
||||||
},
|
required: required,
|
||||||
{
|
message: i18next.t("signup:Please select your country code!"),
|
||||||
validator: (_, value) => {
|
},
|
||||||
if (this.state.phone !== "" && !Setting.isValidPhone(this.state.phone)) {
|
{
|
||||||
this.setState({validPhone: false});
|
validator: (_, value) => {
|
||||||
return Promise.reject(i18next.t("signup:The input is not valid Phone!"));
|
if (this.state.phone !== "" && !Setting.isValidPhone(this.state.phone, this.state.countryCode)) {
|
||||||
}
|
this.setState({validPhone: false});
|
||||||
|
return Promise.reject(i18next.t("signup:The input is not valid Phone!"));
|
||||||
|
}
|
||||||
|
|
||||||
this.setState({validPhone: true});
|
this.setState({validPhone: true});
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<Input
|
<PhoneNumberInput
|
||||||
style={{
|
showSearsh={true}
|
||||||
width: "100%",
|
style={{width: "35%"}}
|
||||||
}}
|
value={this.state.countryCode}
|
||||||
addonBefore={`+${this.getApplicationObj()?.organizationObj.phonePrefix}`}
|
onChange={(value) => {this.setState({countryCode: value});}}
|
||||||
onChange={e => this.setState({phone: e.target.value})}
|
countryCodes={this.getApplicationObj().organizationObj.countryCodes}
|
||||||
/>
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
name="phone"
|
||||||
|
key="phone"
|
||||||
|
noStyle
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: required,
|
||||||
|
message: i18next.t("signup:Please input your phone number!"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
validator: (_, value) => {
|
||||||
|
if (this.state.phone !== "" && !Setting.isValidPhone(this.state.phone, this.state.countryCode)) {
|
||||||
|
this.setState({validPhone: false});
|
||||||
|
return Promise.reject(i18next.t("signup:The input is not valid Phone!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState({validPhone: true});
|
||||||
|
return Promise.resolve();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<Input
|
||||||
|
style={{width: "65%"}}
|
||||||
|
onChange={e => this.setState({phone: e.target.value})}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
</Input.Group>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
name="phoneCode"
|
name="phoneCode"
|
||||||
|
58
web/src/backend/FetchFilter.js
Normal file
58
web/src/backend/FetchFilter.js
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
// 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 {Modal} from "antd";
|
||||||
|
import {ExclamationCircleFilled} from "@ant-design/icons";
|
||||||
|
import i18next from "i18next";
|
||||||
|
import * as Conf from "../Conf";
|
||||||
|
import * as Setting from "../Setting";
|
||||||
|
|
||||||
|
const {confirm} = Modal;
|
||||||
|
const {fetch: originalFetch} = window;
|
||||||
|
|
||||||
|
const demoModeCallback = (res) => {
|
||||||
|
res.json().then(data => {
|
||||||
|
if (Setting.isResponseDenied(data)) {
|
||||||
|
confirm({
|
||||||
|
title: i18next.t("general:This is a read-only demo site!"),
|
||||||
|
icon: <ExclamationCircleFilled />,
|
||||||
|
content: i18next.t("general:Go to writable demo site?"),
|
||||||
|
okText: i18next.t("user:OK"),
|
||||||
|
cancelText: i18next.t("general:Cancel"),
|
||||||
|
onOk() {
|
||||||
|
Setting.openLink(`https://demo.casdoor.com${location.pathname}${location.search}?username=built-in/admin&password=123`);
|
||||||
|
},
|
||||||
|
onCancel() {},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const requestFilters = [];
|
||||||
|
const responseFilters = [];
|
||||||
|
|
||||||
|
if (Conf.IsDemoMode) {
|
||||||
|
responseFilters.push(demoModeCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
window.fetch = async(url, option = {}) => {
|
||||||
|
requestFilters.forEach(filter => filter(url, option));
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
originalFetch(url, option).then(res => {
|
||||||
|
responseFilters.forEach(filter => filter(res.clone()));
|
||||||
|
resolve(res);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
@ -16,7 +16,7 @@ import * as Setting from "../Setting";
|
|||||||
|
|
||||||
export function getLdaps(owner) {
|
export function getLdaps(owner) {
|
||||||
return fetch(`${Setting.ServerUrl}/api/get-ldaps?owner=${owner}`, {
|
return fetch(`${Setting.ServerUrl}/api/get-ldaps?owner=${owner}`, {
|
||||||
method: "POST",
|
method: "GET",
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
headers: {
|
headers: {
|
||||||
"Accept-Language": Setting.getAcceptLanguage(),
|
"Accept-Language": Setting.getAcceptLanguage(),
|
||||||
@ -26,7 +26,7 @@ export function getLdaps(owner) {
|
|||||||
|
|
||||||
export function getLdap(id) {
|
export function getLdap(id) {
|
||||||
return fetch(`${Setting.ServerUrl}/api/get-ldap?id=${id}`, {
|
return fetch(`${Setting.ServerUrl}/api/get-ldap?id=${id}`, {
|
||||||
method: "POST",
|
method: "GET",
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
headers: {
|
headers: {
|
||||||
"Accept-Language": Setting.getAcceptLanguage(),
|
"Accept-Language": Setting.getAcceptLanguage(),
|
||||||
|
58
web/src/common/PhoneNumberInput.js
Normal file
58
web/src/common/PhoneNumberInput.js
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
// 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 {Select} from "antd";
|
||||||
|
import * as Setting from "../Setting";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
const {Option} = Select;
|
||||||
|
|
||||||
|
export default function PhoneNumberInput(props) {
|
||||||
|
const {onChange, style, showSearch} = props;
|
||||||
|
const value = props.value ?? "CN";
|
||||||
|
const countryCodes = props.countryCodes ?? [];
|
||||||
|
|
||||||
|
const handleOnChange = (e) => {
|
||||||
|
onChange?.(e);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Select
|
||||||
|
virtual={false}
|
||||||
|
style={style}
|
||||||
|
value={value}
|
||||||
|
dropdownMatchSelectWidth={false}
|
||||||
|
optionLabelProp={"label"}
|
||||||
|
showSearch={showSearch}
|
||||||
|
onChange={handleOnChange}
|
||||||
|
filterOption={(input, option) =>
|
||||||
|
(option?.label ?? "").toLowerCase().includes(input.toLowerCase())
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{
|
||||||
|
Setting.getCountriesData(countryCodes).map((country) => (
|
||||||
|
<Option key={country.code} value={country.code} label={`+${country.phone}`} >
|
||||||
|
<div style={{display: "flex", justifyContent: "space-between"}}>
|
||||||
|
<div>
|
||||||
|
{Setting.countryFlag(country)}
|
||||||
|
{`${country.name}`}
|
||||||
|
</div>
|
||||||
|
{`+${country.phone}`}
|
||||||
|
</div>
|
||||||
|
</Option>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</Select>
|
||||||
|
);
|
||||||
|
}
|
@ -1,3 +1,17 @@
|
|||||||
|
// Copyright 2022 The Casdoor Authors. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import {Col, Row} from "antd";
|
import {Col, Row} from "antd";
|
||||||
import * as Setting from "../Setting";
|
import * as Setting from "../Setting";
|
||||||
|
@ -13,26 +13,28 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import i18n from "i18next";
|
import i18n from "i18next";
|
||||||
import zh from "./locales/zh/data.json";
|
|
||||||
import en from "./locales/en/data.json";
|
import en from "./locales/en/data.json";
|
||||||
|
import zh from "./locales/zh/data.json";
|
||||||
|
import es from "./locales/es/data.json";
|
||||||
import fr from "./locales/fr/data.json";
|
import fr from "./locales/fr/data.json";
|
||||||
import de from "./locales/de/data.json";
|
import de from "./locales/de/data.json";
|
||||||
|
import ja from "./locales/ja/data.json";
|
||||||
import ko from "./locales/ko/data.json";
|
import ko from "./locales/ko/data.json";
|
||||||
import ru from "./locales/ru/data.json";
|
import ru from "./locales/ru/data.json";
|
||||||
import ja from "./locales/ja/data.json";
|
import vi from "./locales/vi/data.json";
|
||||||
import es from "./locales/es/data.json";
|
|
||||||
import * as Conf from "./Conf";
|
import * as Conf from "./Conf";
|
||||||
import {initReactI18next} from "react-i18next";
|
import {initReactI18next} from "react-i18next";
|
||||||
|
|
||||||
const resources = {
|
const resources = {
|
||||||
en: en,
|
en: en,
|
||||||
es: es,
|
|
||||||
zh: zh,
|
zh: zh,
|
||||||
|
es: es,
|
||||||
fr: fr,
|
fr: fr,
|
||||||
de: de,
|
de: de,
|
||||||
|
ja: ja,
|
||||||
ko: ko,
|
ko: ko,
|
||||||
ru: ru,
|
ru: ru,
|
||||||
ja: ja,
|
vi: vi,
|
||||||
};
|
};
|
||||||
|
|
||||||
function initLanguage() {
|
function initLanguage() {
|
||||||
@ -43,17 +45,20 @@ function initLanguage() {
|
|||||||
} else {
|
} else {
|
||||||
const userLanguage = navigator.language;
|
const userLanguage = navigator.language;
|
||||||
switch (userLanguage) {
|
switch (userLanguage) {
|
||||||
|
case "en":
|
||||||
|
language = "en";
|
||||||
|
break;
|
||||||
|
case "en-US":
|
||||||
|
language = "en";
|
||||||
|
break;
|
||||||
case "zh-CN":
|
case "zh-CN":
|
||||||
language = "zh";
|
language = "zh";
|
||||||
break;
|
break;
|
||||||
case "zh":
|
case "zh":
|
||||||
language = "zh";
|
language = "zh";
|
||||||
break;
|
break;
|
||||||
case "en":
|
case "es":
|
||||||
language = "en";
|
language = "es";
|
||||||
break;
|
|
||||||
case "en-US":
|
|
||||||
language = "en";
|
|
||||||
break;
|
break;
|
||||||
case "fr":
|
case "fr":
|
||||||
language = "fr";
|
language = "fr";
|
||||||
@ -61,14 +66,17 @@ function initLanguage() {
|
|||||||
case "de":
|
case "de":
|
||||||
language = "de";
|
language = "de";
|
||||||
break;
|
break;
|
||||||
|
case "ja":
|
||||||
|
language = "ja";
|
||||||
|
break;
|
||||||
case "ko":
|
case "ko":
|
||||||
language = "ko";
|
language = "ko";
|
||||||
break;
|
break;
|
||||||
case "ru":
|
case "ru":
|
||||||
language = "ru";
|
language = "ru";
|
||||||
break;
|
break;
|
||||||
case "ja":
|
case "vi":
|
||||||
language = "ja";
|
language = "vi";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
language = Conf.DefaultLanguage;
|
language = Conf.DefaultLanguage;
|
||||||
|
@ -22,6 +22,7 @@ import "./App.less";
|
|||||||
import App from "./App";
|
import App from "./App";
|
||||||
import * as serviceWorker from "./serviceWorker";
|
import * as serviceWorker from "./serviceWorker";
|
||||||
import {BrowserRouter} from "react-router-dom";
|
import {BrowserRouter} from "react-router-dom";
|
||||||
|
import "./backend/FetchFilter";
|
||||||
|
|
||||||
const container = document.getElementById("root");
|
const container = document.getElementById("root");
|
||||||
|
|
||||||
|
@ -5,45 +5,45 @@
|
|||||||
"Sign Up": "Registrieren"
|
"Sign Up": "Registrieren"
|
||||||
},
|
},
|
||||||
"adapter": {
|
"adapter": {
|
||||||
"Edit Adapter": "Edit Adapter",
|
"Edit Adapter": "Adapter bearbeiten",
|
||||||
"Failed to sync policies": "Failed to sync policies",
|
"Failed to sync policies": "Fehler beim Synchronisieren der Richtlinien",
|
||||||
"New Adapter": "New Adapter",
|
"New Adapter": "Neuer Adapter",
|
||||||
"Policies": "Policies",
|
"Policies": "Richtlinien",
|
||||||
"Policies - Tooltip": "Policies - Tooltip",
|
"Policies - Tooltip": "Richtlinien - Tooltip",
|
||||||
"Repeated policy rules": "Repeated policy rules",
|
"Repeated policy rules": "Wiederholte Regeln der Richtlinien",
|
||||||
"Sync": "Sync",
|
"Sync": "Synchronisation",
|
||||||
"Sync policies successfully": "Sync policies successfully"
|
"Sync policies successfully": "Richtlinien erfolgreich synchronisiert"
|
||||||
},
|
},
|
||||||
"application": {
|
"application": {
|
||||||
"Always": "Always",
|
"Always": "Immer",
|
||||||
"Auto signin": "Auto signin",
|
"Auto signin": "Automatische Anmeldung",
|
||||||
"Auto signin - Tooltip": "Auto signin - Tooltip",
|
"Auto signin - Tooltip": "Automatische Anmeldung - Tooltip",
|
||||||
"Background URL": "Background URL",
|
"Background URL": "Hintergrund-URL",
|
||||||
"Background URL - Tooltip": "Background URL - Tooltip",
|
"Background URL - Tooltip": "Hintergrund-URL - Kurzinfo",
|
||||||
"Center": "Center",
|
"Center": "Zentriert",
|
||||||
"Copy SAML metadata URL": "Copy SAML metadata URL",
|
"Copy SAML metadata URL": "SAML-Metadaten URL kopieren",
|
||||||
"Copy prompt page URL": "Copy prompt page URL",
|
"Copy prompt page URL": "Copy prompt page URL",
|
||||||
"Copy signin page URL": "Copy signin page URL",
|
"Copy signin page URL": "URL der Anmeldeseite kopieren",
|
||||||
"Copy signup page URL": "Copy signup page URL",
|
"Copy signup page URL": "URL der Registrierungsseite kopieren",
|
||||||
"Edit Application": "Anwendung bearbeiten",
|
"Edit Application": "Anwendung bearbeiten",
|
||||||
"Enable SAML compress": "Enable SAML compress",
|
"Enable SAML compress": "SAML-Komprimierung aktivieren",
|
||||||
"Enable SAML compress - Tooltip": "Enable SAML compress - Tooltip",
|
"Enable SAML compress - Tooltip": "SAML-Komprimierung aktivieren - Tooltip",
|
||||||
"Enable WebAuthn signin": "Enable WebAuthn signin",
|
"Enable WebAuthn signin": "WebAuthn Anmeldung aktivieren",
|
||||||
"Enable WebAuthn signin - Tooltip": "Enable WebAuthn signin - Tooltip",
|
"Enable WebAuthn signin - Tooltip": "WebAuthn Anmeldung aktivieren - Tooltip",
|
||||||
"Enable code signin": "Code-Anmeldung aktivieren",
|
"Enable code signin": "Code-Anmeldung aktivieren",
|
||||||
"Enable code signin - Tooltip": "Aktiviere Codeanmeldung - Tooltip",
|
"Enable code signin - Tooltip": "Aktiviere Codeanmeldung - Tooltip",
|
||||||
"Enable link accounts that with the same email": "Enable link accounts that with the same email",
|
"Enable link accounts that with the same email": "Enable link accounts that with the same email",
|
||||||
"Enable link accounts that with the same email - Tooltip": "Enable link accounts that with the same email - Tooltip",
|
"Enable link accounts that with the same email - Tooltip": "Enable link accounts that with the same email - Tooltip",
|
||||||
"Enable side panel": "Enable side panel",
|
"Enable side panel": "Seitenmenü aktivieren",
|
||||||
"Enable signin session - Tooltip": "Aktiviere Anmeldesession - Tooltip",
|
"Enable signin session - Tooltip": "Aktiviere Anmeldesession - Tooltip",
|
||||||
"Enable signup": "Anmeldung aktivieren",
|
"Enable signup": "Anmeldung aktivieren",
|
||||||
"Enable signup - Tooltip": "Whether to allow users to sign up",
|
"Enable signup - Tooltip": "Whether to allow users to sign up",
|
||||||
"Failed to sign in": "Failed to sign in",
|
"Failed to sign in": "Anmeldung fehlgeschlagen",
|
||||||
"File uploaded successfully": "Datei erfolgreich hochgeladen",
|
"File uploaded successfully": "Datei erfolgreich hochgeladen",
|
||||||
"Follow organization theme": "Follow organization theme",
|
"Follow organization theme": "Follow organization theme",
|
||||||
"Form CSS": "Form CSS",
|
"Form CSS": "Formular-CSS",
|
||||||
"Form CSS - Edit": "Form CSS - Edit",
|
"Form CSS - Edit": "Formular-CSS - Bearbeiten",
|
||||||
"Form CSS - Tooltip": "Form CSS - Tooltip",
|
"Form CSS - Tooltip": "Formular-CSS - Tooltip",
|
||||||
"Form position": "Form position",
|
"Form position": "Form position",
|
||||||
"Form position - Tooltip": "Form position - Tooltip",
|
"Form position - Tooltip": "Form position - Tooltip",
|
||||||
"Grant types": "Grant types",
|
"Grant types": "Grant types",
|
||||||
@ -181,6 +181,8 @@
|
|||||||
"First name": "First name",
|
"First name": "First name",
|
||||||
"Forget URL": "URL vergessen",
|
"Forget URL": "URL vergessen",
|
||||||
"Forget URL - Tooltip": "Unique string-style identifier",
|
"Forget URL - Tooltip": "Unique string-style identifier",
|
||||||
|
"Found some texts still not translated? Please help us translate at": "Found some texts still not translated? Please help us translate at",
|
||||||
|
"Go to writable demo site?": "Go to writable demo site?",
|
||||||
"Home": "Zuhause",
|
"Home": "Zuhause",
|
||||||
"Home - Tooltip": "Application homepage",
|
"Home - Tooltip": "Application homepage",
|
||||||
"ID": "ID",
|
"ID": "ID",
|
||||||
@ -218,8 +220,6 @@
|
|||||||
"Permissions - Tooltip": "Permissions - Tooltip",
|
"Permissions - Tooltip": "Permissions - Tooltip",
|
||||||
"Phone": "Telefon",
|
"Phone": "Telefon",
|
||||||
"Phone - Tooltip": "Phone",
|
"Phone - Tooltip": "Phone",
|
||||||
"Phone prefix": "Telefonpräfix",
|
|
||||||
"Phone prefix - Tooltip": "Mobile phone number prefix, used to distinguish countries or regions",
|
|
||||||
"Preview": "Vorschau",
|
"Preview": "Vorschau",
|
||||||
"Preview - Tooltip": "The form in which the password is stored in the database",
|
"Preview - Tooltip": "The form in which the password is stored in the database",
|
||||||
"Products": "Products",
|
"Products": "Products",
|
||||||
@ -251,10 +251,13 @@
|
|||||||
"Successfully added": "Successfully added",
|
"Successfully added": "Successfully added",
|
||||||
"Successfully deleted": "Successfully deleted",
|
"Successfully deleted": "Successfully deleted",
|
||||||
"Successfully saved": "Successfully saved",
|
"Successfully saved": "Successfully saved",
|
||||||
|
"Supported country code": "Supported country code",
|
||||||
|
"Supported country code - Tooltip": "Supported country code - Tooltip",
|
||||||
"Swagger": "Swagger",
|
"Swagger": "Swagger",
|
||||||
"Sync": "Sync",
|
"Sync": "Sync",
|
||||||
"Syncers": "Syncers",
|
"Syncers": "Syncers",
|
||||||
"SysInfo": "SysInfo",
|
"SysInfo": "SysInfo",
|
||||||
|
"This is a read-only demo site!": "This is a read-only demo site!",
|
||||||
"Timestamp": "Zeitstempel",
|
"Timestamp": "Zeitstempel",
|
||||||
"Tokens": "Token",
|
"Tokens": "Token",
|
||||||
"URL": "URL",
|
"URL": "URL",
|
||||||
@ -309,10 +312,10 @@
|
|||||||
"Or sign in with another account": "Oder melden Sie sich mit einem anderen Konto an",
|
"Or sign in with another account": "Oder melden Sie sich mit einem anderen Konto an",
|
||||||
"Password": "Passwort",
|
"Password": "Passwort",
|
||||||
"Password - Tooltip": "Passwort - Tooltip",
|
"Password - Tooltip": "Passwort - Tooltip",
|
||||||
|
"Please input your Email or Phone!": "Please input your Email or Phone!",
|
||||||
"Please input your code!": "Bitte gib deinen Code ein!",
|
"Please input your code!": "Bitte gib deinen Code ein!",
|
||||||
"Please input your password!": "Bitte geben Sie Ihr Passwort ein!",
|
"Please input your password!": "Bitte geben Sie Ihr Passwort ein!",
|
||||||
"Please input your password, at least 6 characters!": "Bitte geben Sie Ihr Passwort ein, mindestens 6 Zeichen!",
|
"Please input your password, at least 6 characters!": "Bitte geben Sie Ihr Passwort ein, mindestens 6 Zeichen!",
|
||||||
"Please input your username, Email or phone!": "Bitte geben Sie Ihren Benutzernamen, E-Mail oder Telefon ein!",
|
|
||||||
"Redirecting, please wait.": "Redirecting, please wait.",
|
"Redirecting, please wait.": "Redirecting, please wait.",
|
||||||
"Sign In": "Anmelden",
|
"Sign In": "Anmelden",
|
||||||
"Sign in with WebAuthn": "Sign in with WebAuthn",
|
"Sign in with WebAuthn": "Sign in with WebAuthn",
|
||||||
@ -638,6 +641,7 @@
|
|||||||
"Please input your last name!": "Please input your last name!",
|
"Please input your last name!": "Please input your last name!",
|
||||||
"Please input your phone number!": "Bitte geben Sie Ihre Telefonnummer ein!",
|
"Please input your phone number!": "Bitte geben Sie Ihre Telefonnummer ein!",
|
||||||
"Please input your real name!": "Bitte geben Sie Ihren persönlichen Namen ein!",
|
"Please input your real name!": "Bitte geben Sie Ihren persönlichen Namen ein!",
|
||||||
|
"Please select your country code!": "Please select your country code!",
|
||||||
"Please select your country/region!": "Bitte wählen Sie Ihr Land/Ihre Region!",
|
"Please select your country/region!": "Bitte wählen Sie Ihr Land/Ihre Region!",
|
||||||
"Terms of Use": "Nutzungsbedingungen",
|
"Terms of Use": "Nutzungsbedingungen",
|
||||||
"The input is not invoice Tax ID!": "The input is not invoice Tax ID!",
|
"The input is not invoice Tax ID!": "The input is not invoice Tax ID!",
|
||||||
@ -724,6 +728,7 @@
|
|||||||
"Captcha Verify Failed": "Captcha Verify Failed",
|
"Captcha Verify Failed": "Captcha Verify Failed",
|
||||||
"Captcha Verify Success": "Captcha Verify Success",
|
"Captcha Verify Success": "Captcha Verify Success",
|
||||||
"Code Sent": "Code gesendet",
|
"Code Sent": "Code gesendet",
|
||||||
|
"Country code": "Country code",
|
||||||
"Country/Region": "Land/Region",
|
"Country/Region": "Land/Region",
|
||||||
"Country/Region - Tooltip": "Country/Region",
|
"Country/Region - Tooltip": "Country/Region",
|
||||||
"Edit User": "Benutzer bearbeiten",
|
"Edit User": "Benutzer bearbeiten",
|
||||||
|
@ -181,6 +181,8 @@
|
|||||||
"First name": "First name",
|
"First name": "First name",
|
||||||
"Forget URL": "Forget URL",
|
"Forget URL": "Forget URL",
|
||||||
"Forget URL - Tooltip": "Forget URL - Tooltip",
|
"Forget URL - Tooltip": "Forget URL - Tooltip",
|
||||||
|
"Found some texts still not translated? Please help us translate at": "Found some texts still not translated? Please help us translate at",
|
||||||
|
"Go to writable demo site?": "Go to writable demo site?",
|
||||||
"Home": "Home",
|
"Home": "Home",
|
||||||
"Home - Tooltip": "Home - Tooltip",
|
"Home - Tooltip": "Home - Tooltip",
|
||||||
"ID": "ID",
|
"ID": "ID",
|
||||||
@ -218,8 +220,6 @@
|
|||||||
"Permissions - Tooltip": "Permissions - Tooltip",
|
"Permissions - Tooltip": "Permissions - Tooltip",
|
||||||
"Phone": "Phone",
|
"Phone": "Phone",
|
||||||
"Phone - Tooltip": "Phone - Tooltip",
|
"Phone - Tooltip": "Phone - Tooltip",
|
||||||
"Phone prefix": "Phone prefix",
|
|
||||||
"Phone prefix - Tooltip": "Phone prefix - Tooltip",
|
|
||||||
"Preview": "Preview",
|
"Preview": "Preview",
|
||||||
"Preview - Tooltip": "Preview - Tooltip",
|
"Preview - Tooltip": "Preview - Tooltip",
|
||||||
"Products": "Products",
|
"Products": "Products",
|
||||||
@ -251,10 +251,13 @@
|
|||||||
"Successfully added": "Successfully added",
|
"Successfully added": "Successfully added",
|
||||||
"Successfully deleted": "Successfully deleted",
|
"Successfully deleted": "Successfully deleted",
|
||||||
"Successfully saved": "Successfully saved",
|
"Successfully saved": "Successfully saved",
|
||||||
|
"Supported country code": "Supported country code",
|
||||||
|
"Supported country code - Tooltip": "Supported country code - Tooltip",
|
||||||
"Swagger": "Swagger",
|
"Swagger": "Swagger",
|
||||||
"Sync": "Sync",
|
"Sync": "Sync",
|
||||||
"Syncers": "Syncers",
|
"Syncers": "Syncers",
|
||||||
"SysInfo": "SysInfo",
|
"SysInfo": "SysInfo",
|
||||||
|
"This is a read-only demo site!": "This is a read-only demo site!",
|
||||||
"Timestamp": "Timestamp",
|
"Timestamp": "Timestamp",
|
||||||
"Tokens": "Tokens",
|
"Tokens": "Tokens",
|
||||||
"URL": "URL",
|
"URL": "URL",
|
||||||
@ -309,10 +312,10 @@
|
|||||||
"Or sign in with another account": "Or sign in with another account",
|
"Or sign in with another account": "Or sign in with another account",
|
||||||
"Password": "Password",
|
"Password": "Password",
|
||||||
"Password - Tooltip": "Password - Tooltip",
|
"Password - Tooltip": "Password - Tooltip",
|
||||||
|
"Please input your Email or Phone!": "Please input your Email or Phone!",
|
||||||
"Please input your code!": "Please input your code!",
|
"Please input your code!": "Please input your code!",
|
||||||
"Please input your password!": "Please input your password!",
|
"Please input your password!": "Please input your password!",
|
||||||
"Please input your password, at least 6 characters!": "Please input your password, at least 6 characters!",
|
"Please input your password, at least 6 characters!": "Please input your password, at least 6 characters!",
|
||||||
"Please input your username, Email or phone!": "Please input your username, Email or phone!",
|
|
||||||
"Redirecting, please wait.": "Redirecting, please wait.",
|
"Redirecting, please wait.": "Redirecting, please wait.",
|
||||||
"Sign In": "Sign In",
|
"Sign In": "Sign In",
|
||||||
"Sign in with WebAuthn": "Sign in with WebAuthn",
|
"Sign in with WebAuthn": "Sign in with WebAuthn",
|
||||||
@ -638,6 +641,7 @@
|
|||||||
"Please input your last name!": "Please input your last name!",
|
"Please input your last name!": "Please input your last name!",
|
||||||
"Please input your phone number!": "Please input your phone number!",
|
"Please input your phone number!": "Please input your phone number!",
|
||||||
"Please input your real name!": "Please input your real name!",
|
"Please input your real name!": "Please input your real name!",
|
||||||
|
"Please select your country code!": "Please select your country code!",
|
||||||
"Please select your country/region!": "Please select your country/region!",
|
"Please select your country/region!": "Please select your country/region!",
|
||||||
"Terms of Use": "Terms of Use",
|
"Terms of Use": "Terms of Use",
|
||||||
"The input is not invoice Tax ID!": "The input is not invoice Tax ID!",
|
"The input is not invoice Tax ID!": "The input is not invoice Tax ID!",
|
||||||
@ -724,6 +728,7 @@
|
|||||||
"Captcha Verify Failed": "Captcha Verify Failed",
|
"Captcha Verify Failed": "Captcha Verify Failed",
|
||||||
"Captcha Verify Success": "Captcha Verify Success",
|
"Captcha Verify Success": "Captcha Verify Success",
|
||||||
"Code Sent": "Code Sent",
|
"Code Sent": "Code Sent",
|
||||||
|
"Country code": "Country code",
|
||||||
"Country/Region": "Country/Region",
|
"Country/Region": "Country/Region",
|
||||||
"Country/Region - Tooltip": "Country/Region - Tooltip",
|
"Country/Region - Tooltip": "Country/Region - Tooltip",
|
||||||
"Edit User": "Edit User",
|
"Edit User": "Edit User",
|
||||||
|
@ -181,6 +181,8 @@
|
|||||||
"First name": "Nombre",
|
"First name": "Nombre",
|
||||||
"Forget URL": "URL de olvido",
|
"Forget URL": "URL de olvido",
|
||||||
"Forget URL - Tooltip": "URL de olvido - Tooltip",
|
"Forget URL - Tooltip": "URL de olvido - Tooltip",
|
||||||
|
"Found some texts still not translated? Please help us translate at": "Found some texts still not translated? Please help us translate at",
|
||||||
|
"Go to writable demo site?": "Go to writable demo site?",
|
||||||
"Home": "Inicio",
|
"Home": "Inicio",
|
||||||
"Home - Tooltip": "Inicio - Tooltip",
|
"Home - Tooltip": "Inicio - Tooltip",
|
||||||
"ID": "ID",
|
"ID": "ID",
|
||||||
@ -218,8 +220,6 @@
|
|||||||
"Permissions - Tooltip": "Permisos - Tooltip",
|
"Permissions - Tooltip": "Permisos - Tooltip",
|
||||||
"Phone": "Teléfono",
|
"Phone": "Teléfono",
|
||||||
"Phone - Tooltip": "Teléfono - Tooltip",
|
"Phone - Tooltip": "Teléfono - Tooltip",
|
||||||
"Phone prefix": "Prefijo teléfonico",
|
|
||||||
"Phone prefix - Tooltip": "Prefijo teléfonico - Tooltip",
|
|
||||||
"Preview": "Previsualizar",
|
"Preview": "Previsualizar",
|
||||||
"Preview - Tooltip": "Previsualizar - Tooltip",
|
"Preview - Tooltip": "Previsualizar - Tooltip",
|
||||||
"Products": "Productos",
|
"Products": "Productos",
|
||||||
@ -251,10 +251,13 @@
|
|||||||
"Successfully added": "Successfully added",
|
"Successfully added": "Successfully added",
|
||||||
"Successfully deleted": "Successfully deleted",
|
"Successfully deleted": "Successfully deleted",
|
||||||
"Successfully saved": "Successfully saved",
|
"Successfully saved": "Successfully saved",
|
||||||
|
"Supported country code": "Supported country code",
|
||||||
|
"Supported country code - Tooltip": "Supported country code - Tooltip",
|
||||||
"Swagger": "Swagger",
|
"Swagger": "Swagger",
|
||||||
"Sync": "Sincronizador",
|
"Sync": "Sincronizador",
|
||||||
"Syncers": "Sincronizadores",
|
"Syncers": "Sincronizadores",
|
||||||
"SysInfo": "SysInfo",
|
"SysInfo": "SysInfo",
|
||||||
|
"This is a read-only demo site!": "This is a read-only demo site!",
|
||||||
"Timestamp": "Timestamp",
|
"Timestamp": "Timestamp",
|
||||||
"Tokens": "Tokens",
|
"Tokens": "Tokens",
|
||||||
"URL": "URL",
|
"URL": "URL",
|
||||||
@ -309,10 +312,10 @@
|
|||||||
"Or sign in with another account": "O inicia sesión con otra cuenta",
|
"Or sign in with another account": "O inicia sesión con otra cuenta",
|
||||||
"Password": "Contraseña",
|
"Password": "Contraseña",
|
||||||
"Password - Tooltip": "Contraseña - Tooltip",
|
"Password - Tooltip": "Contraseña - Tooltip",
|
||||||
|
"Please input your Email or Phone!": "Please input your Email or Phone!",
|
||||||
"Please input your code!": "¡Por favor ingrese su código!",
|
"Please input your code!": "¡Por favor ingrese su código!",
|
||||||
"Please input your password!": "¡Por favor ingrese su contraseña!",
|
"Please input your password!": "¡Por favor ingrese su contraseña!",
|
||||||
"Please input your password, at least 6 characters!": "Su contraseña debe contener al menos 6 caracteres.",
|
"Please input your password, at least 6 characters!": "Su contraseña debe contener al menos 6 caracteres.",
|
||||||
"Please input your username, Email or phone!": "¡Ingrese su nombre de usuario, correo electrónico o teléfono!",
|
|
||||||
"Redirecting, please wait.": "Redirecting, please wait.",
|
"Redirecting, please wait.": "Redirecting, please wait.",
|
||||||
"Sign In": "Iniciar de sesión",
|
"Sign In": "Iniciar de sesión",
|
||||||
"Sign in with WebAuthn": "Iniciar de sesión con WebAuthn",
|
"Sign in with WebAuthn": "Iniciar de sesión con WebAuthn",
|
||||||
@ -638,6 +641,7 @@
|
|||||||
"Please input your last name!": "Por favor, ingrese su apellido!",
|
"Please input your last name!": "Por favor, ingrese su apellido!",
|
||||||
"Please input your phone number!": "Por favor, ingrese su número teléfonico!",
|
"Please input your phone number!": "Por favor, ingrese su número teléfonico!",
|
||||||
"Please input your real name!": "Por favor, ingrese un nombre real!",
|
"Please input your real name!": "Por favor, ingrese un nombre real!",
|
||||||
|
"Please select your country code!": "Please select your country code!",
|
||||||
"Please select your country/region!": "Por favor, seleccione su pais/region!",
|
"Please select your country/region!": "Por favor, seleccione su pais/region!",
|
||||||
"Terms of Use": "Términos de Uso",
|
"Terms of Use": "Términos de Uso",
|
||||||
"The input is not invoice Tax ID!": "El valor ingresado no es un número de identificación fiscal de factura!",
|
"The input is not invoice Tax ID!": "El valor ingresado no es un número de identificación fiscal de factura!",
|
||||||
@ -724,6 +728,7 @@
|
|||||||
"Captcha Verify Failed": "Fallo la verificación del Captcha",
|
"Captcha Verify Failed": "Fallo la verificación del Captcha",
|
||||||
"Captcha Verify Success": "Captcha verificado con éxito",
|
"Captcha Verify Success": "Captcha verificado con éxito",
|
||||||
"Code Sent": "Código enviado",
|
"Code Sent": "Código enviado",
|
||||||
|
"Country code": "Country code",
|
||||||
"Country/Region": "Pais/Región",
|
"Country/Region": "Pais/Región",
|
||||||
"Country/Region - Tooltip": "Pais/Región - Tooltip",
|
"Country/Region - Tooltip": "Pais/Región - Tooltip",
|
||||||
"Edit User": "Editar usuario",
|
"Edit User": "Editar usuario",
|
||||||
|
@ -181,6 +181,8 @@
|
|||||||
"First name": "First name",
|
"First name": "First name",
|
||||||
"Forget URL": "Oublier l'URL",
|
"Forget URL": "Oublier l'URL",
|
||||||
"Forget URL - Tooltip": "Unique string-style identifier",
|
"Forget URL - Tooltip": "Unique string-style identifier",
|
||||||
|
"Found some texts still not translated? Please help us translate at": "Found some texts still not translated? Please help us translate at",
|
||||||
|
"Go to writable demo site?": "Go to writable demo site?",
|
||||||
"Home": "Domicile",
|
"Home": "Domicile",
|
||||||
"Home - Tooltip": "Application homepage",
|
"Home - Tooltip": "Application homepage",
|
||||||
"ID": "ID",
|
"ID": "ID",
|
||||||
@ -218,8 +220,6 @@
|
|||||||
"Permissions - Tooltip": "Permissions - Tooltip",
|
"Permissions - Tooltip": "Permissions - Tooltip",
|
||||||
"Phone": "Téléphone",
|
"Phone": "Téléphone",
|
||||||
"Phone - Tooltip": "Phone",
|
"Phone - Tooltip": "Phone",
|
||||||
"Phone prefix": "Préfixe du téléphone",
|
|
||||||
"Phone prefix - Tooltip": "Mobile phone number prefix, used to distinguish countries or regions",
|
|
||||||
"Preview": "Aperçu",
|
"Preview": "Aperçu",
|
||||||
"Preview - Tooltip": "The form in which the password is stored in the database",
|
"Preview - Tooltip": "The form in which the password is stored in the database",
|
||||||
"Products": "Products",
|
"Products": "Products",
|
||||||
@ -251,10 +251,13 @@
|
|||||||
"Successfully added": "Successfully added",
|
"Successfully added": "Successfully added",
|
||||||
"Successfully deleted": "Successfully deleted",
|
"Successfully deleted": "Successfully deleted",
|
||||||
"Successfully saved": "Successfully saved",
|
"Successfully saved": "Successfully saved",
|
||||||
|
"Supported country code": "Supported country code",
|
||||||
|
"Supported country code - Tooltip": "Supported country code - Tooltip",
|
||||||
"Swagger": "Swagger",
|
"Swagger": "Swagger",
|
||||||
"Sync": "Sync",
|
"Sync": "Sync",
|
||||||
"Syncers": "Synchronisateurs",
|
"Syncers": "Synchronisateurs",
|
||||||
"SysInfo": "SysInfo",
|
"SysInfo": "SysInfo",
|
||||||
|
"This is a read-only demo site!": "This is a read-only demo site!",
|
||||||
"Timestamp": "Horodatage",
|
"Timestamp": "Horodatage",
|
||||||
"Tokens": "Jetons",
|
"Tokens": "Jetons",
|
||||||
"URL": "URL",
|
"URL": "URL",
|
||||||
@ -309,10 +312,10 @@
|
|||||||
"Or sign in with another account": "Ou connectez-vous avec un autre compte",
|
"Or sign in with another account": "Ou connectez-vous avec un autre compte",
|
||||||
"Password": "Mot de passe",
|
"Password": "Mot de passe",
|
||||||
"Password - Tooltip": "Mot de passe - Info-bulle",
|
"Password - Tooltip": "Mot de passe - Info-bulle",
|
||||||
|
"Please input your Email or Phone!": "Please input your Email or Phone!",
|
||||||
"Please input your code!": "Veuillez saisir votre code !",
|
"Please input your code!": "Veuillez saisir votre code !",
|
||||||
"Please input your password!": "Veuillez saisir votre mot de passe !",
|
"Please input your password!": "Veuillez saisir votre mot de passe !",
|
||||||
"Please input your password, at least 6 characters!": "Veuillez entrer votre mot de passe, au moins 6 caractères !",
|
"Please input your password, at least 6 characters!": "Veuillez entrer votre mot de passe, au moins 6 caractères !",
|
||||||
"Please input your username, Email or phone!": "Veuillez entrer votre nom d'utilisateur, votre e-mail ou votre téléphone!",
|
|
||||||
"Redirecting, please wait.": "Redirecting, please wait.",
|
"Redirecting, please wait.": "Redirecting, please wait.",
|
||||||
"Sign In": "Se connecter",
|
"Sign In": "Se connecter",
|
||||||
"Sign in with WebAuthn": "Sign in with WebAuthn",
|
"Sign in with WebAuthn": "Sign in with WebAuthn",
|
||||||
@ -638,6 +641,7 @@
|
|||||||
"Please input your last name!": "Please input your last name!",
|
"Please input your last name!": "Please input your last name!",
|
||||||
"Please input your phone number!": "Veuillez entrer votre numéro de téléphone!",
|
"Please input your phone number!": "Veuillez entrer votre numéro de téléphone!",
|
||||||
"Please input your real name!": "Veuillez entrer votre nom personnel !",
|
"Please input your real name!": "Veuillez entrer votre nom personnel !",
|
||||||
|
"Please select your country code!": "Please select your country code!",
|
||||||
"Please select your country/region!": "Veuillez sélectionner votre pays/région!",
|
"Please select your country/region!": "Veuillez sélectionner votre pays/région!",
|
||||||
"Terms of Use": "Conditions d'utilisation",
|
"Terms of Use": "Conditions d'utilisation",
|
||||||
"The input is not invoice Tax ID!": "The input is not invoice Tax ID!",
|
"The input is not invoice Tax ID!": "The input is not invoice Tax ID!",
|
||||||
@ -724,6 +728,7 @@
|
|||||||
"Captcha Verify Failed": "Captcha Verify Failed",
|
"Captcha Verify Failed": "Captcha Verify Failed",
|
||||||
"Captcha Verify Success": "Captcha Verify Success",
|
"Captcha Verify Success": "Captcha Verify Success",
|
||||||
"Code Sent": "Code envoyé",
|
"Code Sent": "Code envoyé",
|
||||||
|
"Country code": "Country code",
|
||||||
"Country/Region": "Pays/Région",
|
"Country/Region": "Pays/Région",
|
||||||
"Country/Region - Tooltip": "Country/Region",
|
"Country/Region - Tooltip": "Country/Region",
|
||||||
"Edit User": "Editer l'utilisateur",
|
"Edit User": "Editer l'utilisateur",
|
||||||
|
@ -181,6 +181,8 @@
|
|||||||
"First name": "First name",
|
"First name": "First name",
|
||||||
"Forget URL": "URLを忘れた",
|
"Forget URL": "URLを忘れた",
|
||||||
"Forget URL - Tooltip": "Unique string-style identifier",
|
"Forget URL - Tooltip": "Unique string-style identifier",
|
||||||
|
"Found some texts still not translated? Please help us translate at": "Found some texts still not translated? Please help us translate at",
|
||||||
|
"Go to writable demo site?": "Go to writable demo site?",
|
||||||
"Home": "ホーム",
|
"Home": "ホーム",
|
||||||
"Home - Tooltip": "Application homepage",
|
"Home - Tooltip": "Application homepage",
|
||||||
"ID": "ID",
|
"ID": "ID",
|
||||||
@ -218,8 +220,6 @@
|
|||||||
"Permissions - Tooltip": "Permissions - Tooltip",
|
"Permissions - Tooltip": "Permissions - Tooltip",
|
||||||
"Phone": "電話番号",
|
"Phone": "電話番号",
|
||||||
"Phone - Tooltip": "Phone",
|
"Phone - Tooltip": "Phone",
|
||||||
"Phone prefix": "電話プレフィクス",
|
|
||||||
"Phone prefix - Tooltip": "Mobile phone number prefix, used to distinguish countries or regions",
|
|
||||||
"Preview": "プレビュー",
|
"Preview": "プレビュー",
|
||||||
"Preview - Tooltip": "The form in which the password is stored in the database",
|
"Preview - Tooltip": "The form in which the password is stored in the database",
|
||||||
"Products": "Products",
|
"Products": "Products",
|
||||||
@ -251,10 +251,13 @@
|
|||||||
"Successfully added": "Successfully added",
|
"Successfully added": "Successfully added",
|
||||||
"Successfully deleted": "Successfully deleted",
|
"Successfully deleted": "Successfully deleted",
|
||||||
"Successfully saved": "Successfully saved",
|
"Successfully saved": "Successfully saved",
|
||||||
|
"Supported country code": "Supported country code",
|
||||||
|
"Supported country code - Tooltip": "Supported country code - Tooltip",
|
||||||
"Swagger": "Swagger",
|
"Swagger": "Swagger",
|
||||||
"Sync": "Sync",
|
"Sync": "Sync",
|
||||||
"Syncers": "Syncers",
|
"Syncers": "Syncers",
|
||||||
"SysInfo": "システム情報",
|
"SysInfo": "システム情報",
|
||||||
|
"This is a read-only demo site!": "This is a read-only demo site!",
|
||||||
"Timestamp": "タイムスタンプ",
|
"Timestamp": "タイムスタンプ",
|
||||||
"Tokens": "トークン",
|
"Tokens": "トークン",
|
||||||
"URL": "URL",
|
"URL": "URL",
|
||||||
@ -309,10 +312,10 @@
|
|||||||
"Or sign in with another account": "または別のアカウントでサインイン",
|
"Or sign in with another account": "または別のアカウントでサインイン",
|
||||||
"Password": "パスワード",
|
"Password": "パスワード",
|
||||||
"Password - Tooltip": "パスワード → ツールチップ",
|
"Password - Tooltip": "パスワード → ツールチップ",
|
||||||
|
"Please input your Email or Phone!": "Please input your Email or Phone!",
|
||||||
"Please input your code!": "コードを入力してください!",
|
"Please input your code!": "コードを入力してください!",
|
||||||
"Please input your password!": "パスワードを入力してください!",
|
"Please input your password!": "パスワードを入力してください!",
|
||||||
"Please input your password, at least 6 characters!": "6文字以上でパスワードを入力してください!",
|
"Please input your password, at least 6 characters!": "6文字以上でパスワードを入力してください!",
|
||||||
"Please input your username, Email or phone!": "ユーザー名、メールアドレスまたは電話番号を入力してください。",
|
|
||||||
"Redirecting, please wait.": "Redirecting, please wait.",
|
"Redirecting, please wait.": "Redirecting, please wait.",
|
||||||
"Sign In": "サインイン",
|
"Sign In": "サインイン",
|
||||||
"Sign in with WebAuthn": "Sign in with WebAuthn",
|
"Sign in with WebAuthn": "Sign in with WebAuthn",
|
||||||
@ -638,6 +641,7 @@
|
|||||||
"Please input your last name!": "Please input your last name!",
|
"Please input your last name!": "Please input your last name!",
|
||||||
"Please input your phone number!": "電話番号を入力してください!",
|
"Please input your phone number!": "電話番号を入力してください!",
|
||||||
"Please input your real name!": "個人名を入力してください!",
|
"Please input your real name!": "個人名を入力してください!",
|
||||||
|
"Please select your country code!": "Please select your country code!",
|
||||||
"Please select your country/region!": "あなたの国/地域を選択してください!",
|
"Please select your country/region!": "あなたの国/地域を選択してください!",
|
||||||
"Terms of Use": "利用規約",
|
"Terms of Use": "利用規約",
|
||||||
"The input is not invoice Tax ID!": "The input is not invoice Tax ID!",
|
"The input is not invoice Tax ID!": "The input is not invoice Tax ID!",
|
||||||
@ -724,6 +728,7 @@
|
|||||||
"Captcha Verify Failed": "Captcha Verify Failed",
|
"Captcha Verify Failed": "Captcha Verify Failed",
|
||||||
"Captcha Verify Success": "Captcha Verify Success",
|
"Captcha Verify Success": "Captcha Verify Success",
|
||||||
"Code Sent": "コードを送信しました",
|
"Code Sent": "コードを送信しました",
|
||||||
|
"Country code": "Country code",
|
||||||
"Country/Region": "国/地域",
|
"Country/Region": "国/地域",
|
||||||
"Country/Region - Tooltip": "Country/Region",
|
"Country/Region - Tooltip": "Country/Region",
|
||||||
"Edit User": "ユーザーを編集",
|
"Edit User": "ユーザーを編集",
|
||||||
|
@ -181,6 +181,8 @@
|
|||||||
"First name": "First name",
|
"First name": "First name",
|
||||||
"Forget URL": "Forget URL",
|
"Forget URL": "Forget URL",
|
||||||
"Forget URL - Tooltip": "Unique string-style identifier",
|
"Forget URL - Tooltip": "Unique string-style identifier",
|
||||||
|
"Found some texts still not translated? Please help us translate at": "Found some texts still not translated? Please help us translate at",
|
||||||
|
"Go to writable demo site?": "Go to writable demo site?",
|
||||||
"Home": "Home",
|
"Home": "Home",
|
||||||
"Home - Tooltip": "Application homepage",
|
"Home - Tooltip": "Application homepage",
|
||||||
"ID": "ID",
|
"ID": "ID",
|
||||||
@ -218,8 +220,6 @@
|
|||||||
"Permissions - Tooltip": "Permissions - Tooltip",
|
"Permissions - Tooltip": "Permissions - Tooltip",
|
||||||
"Phone": "Phone",
|
"Phone": "Phone",
|
||||||
"Phone - Tooltip": "Phone",
|
"Phone - Tooltip": "Phone",
|
||||||
"Phone prefix": "Phone prefix",
|
|
||||||
"Phone prefix - Tooltip": "Mobile phone number prefix, used to distinguish countries or regions",
|
|
||||||
"Preview": "Preview",
|
"Preview": "Preview",
|
||||||
"Preview - Tooltip": "The form in which the password is stored in the database",
|
"Preview - Tooltip": "The form in which the password is stored in the database",
|
||||||
"Products": "Products",
|
"Products": "Products",
|
||||||
@ -251,10 +251,13 @@
|
|||||||
"Successfully added": "Successfully added",
|
"Successfully added": "Successfully added",
|
||||||
"Successfully deleted": "Successfully deleted",
|
"Successfully deleted": "Successfully deleted",
|
||||||
"Successfully saved": "Successfully saved",
|
"Successfully saved": "Successfully saved",
|
||||||
|
"Supported country code": "Supported country code",
|
||||||
|
"Supported country code - Tooltip": "Supported country code - Tooltip",
|
||||||
"Swagger": "Swagger",
|
"Swagger": "Swagger",
|
||||||
"Sync": "Sync",
|
"Sync": "Sync",
|
||||||
"Syncers": "Syncers",
|
"Syncers": "Syncers",
|
||||||
"SysInfo": "SysInfo",
|
"SysInfo": "SysInfo",
|
||||||
|
"This is a read-only demo site!": "This is a read-only demo site!",
|
||||||
"Timestamp": "Timestamp",
|
"Timestamp": "Timestamp",
|
||||||
"Tokens": "Tokens",
|
"Tokens": "Tokens",
|
||||||
"URL": "URL",
|
"URL": "URL",
|
||||||
@ -309,10 +312,10 @@
|
|||||||
"Or sign in with another account": "Or sign in with another account",
|
"Or sign in with another account": "Or sign in with another account",
|
||||||
"Password": "Password",
|
"Password": "Password",
|
||||||
"Password - Tooltip": "Password - Tooltip",
|
"Password - Tooltip": "Password - Tooltip",
|
||||||
|
"Please input your Email or Phone!": "Please input your Email or Phone!",
|
||||||
"Please input your code!": "Please input your code!",
|
"Please input your code!": "Please input your code!",
|
||||||
"Please input your password!": "Please input your password!",
|
"Please input your password!": "Please input your password!",
|
||||||
"Please input your password, at least 6 characters!": "Please input your password, at least 6 characters!",
|
"Please input your password, at least 6 characters!": "Please input your password, at least 6 characters!",
|
||||||
"Please input your username, Email or phone!": "Please input your username, Email or phone!",
|
|
||||||
"Redirecting, please wait.": "Redirecting, please wait.",
|
"Redirecting, please wait.": "Redirecting, please wait.",
|
||||||
"Sign In": "Sign In",
|
"Sign In": "Sign In",
|
||||||
"Sign in with WebAuthn": "Sign in with WebAuthn",
|
"Sign in with WebAuthn": "Sign in with WebAuthn",
|
||||||
@ -638,6 +641,7 @@
|
|||||||
"Please input your last name!": "Please input your last name!",
|
"Please input your last name!": "Please input your last name!",
|
||||||
"Please input your phone number!": "Please input your phone number!",
|
"Please input your phone number!": "Please input your phone number!",
|
||||||
"Please input your real name!": "Please input your real name!",
|
"Please input your real name!": "Please input your real name!",
|
||||||
|
"Please select your country code!": "Please select your country code!",
|
||||||
"Please select your country/region!": "Please select your country/region!",
|
"Please select your country/region!": "Please select your country/region!",
|
||||||
"Terms of Use": "Terms of Use",
|
"Terms of Use": "Terms of Use",
|
||||||
"The input is not invoice Tax ID!": "The input is not invoice Tax ID!",
|
"The input is not invoice Tax ID!": "The input is not invoice Tax ID!",
|
||||||
@ -724,6 +728,7 @@
|
|||||||
"Captcha Verify Failed": "Captcha Verify Failed",
|
"Captcha Verify Failed": "Captcha Verify Failed",
|
||||||
"Captcha Verify Success": "Captcha Verify Success",
|
"Captcha Verify Success": "Captcha Verify Success",
|
||||||
"Code Sent": "Code Sent",
|
"Code Sent": "Code Sent",
|
||||||
|
"Country code": "Country code",
|
||||||
"Country/Region": "Country/Region",
|
"Country/Region": "Country/Region",
|
||||||
"Country/Region - Tooltip": "Country/Region",
|
"Country/Region - Tooltip": "Country/Region",
|
||||||
"Edit User": "Edit User",
|
"Edit User": "Edit User",
|
||||||
|
@ -181,6 +181,8 @@
|
|||||||
"First name": "Имя",
|
"First name": "Имя",
|
||||||
"Forget URL": "Забыть URL",
|
"Forget URL": "Забыть URL",
|
||||||
"Forget URL - Tooltip": "Unique string-style identifier",
|
"Forget URL - Tooltip": "Unique string-style identifier",
|
||||||
|
"Found some texts still not translated? Please help us translate at": "Found some texts still not translated? Please help us translate at",
|
||||||
|
"Go to writable demo site?": "Go to writable demo site?",
|
||||||
"Home": "Домашний",
|
"Home": "Домашний",
|
||||||
"Home - Tooltip": "Application homepage",
|
"Home - Tooltip": "Application homepage",
|
||||||
"ID": "ID",
|
"ID": "ID",
|
||||||
@ -218,8 +220,6 @@
|
|||||||
"Permissions - Tooltip": "Permissions - Tooltip",
|
"Permissions - Tooltip": "Permissions - Tooltip",
|
||||||
"Phone": "Телефон",
|
"Phone": "Телефон",
|
||||||
"Phone - Tooltip": "Phone",
|
"Phone - Tooltip": "Phone",
|
||||||
"Phone prefix": "Префикс телефона",
|
|
||||||
"Phone prefix - Tooltip": "Mobile phone number prefix, used to distinguish countries or regions",
|
|
||||||
"Preview": "Предпросмотр",
|
"Preview": "Предпросмотр",
|
||||||
"Preview - Tooltip": "The form in which the password is stored in the database",
|
"Preview - Tooltip": "The form in which the password is stored in the database",
|
||||||
"Products": "Продукты",
|
"Products": "Продукты",
|
||||||
@ -251,10 +251,13 @@
|
|||||||
"Successfully added": "Successfully added",
|
"Successfully added": "Successfully added",
|
||||||
"Successfully deleted": "Successfully deleted",
|
"Successfully deleted": "Successfully deleted",
|
||||||
"Successfully saved": "Successfully saved",
|
"Successfully saved": "Successfully saved",
|
||||||
|
"Supported country code": "Supported country code",
|
||||||
|
"Supported country code - Tooltip": "Supported country code - Tooltip",
|
||||||
"Swagger": "Swagger",
|
"Swagger": "Swagger",
|
||||||
"Sync": "Sync",
|
"Sync": "Sync",
|
||||||
"Syncers": "Синхронизаторы",
|
"Syncers": "Синхронизаторы",
|
||||||
"SysInfo": "Информация о системе",
|
"SysInfo": "Информация о системе",
|
||||||
|
"This is a read-only demo site!": "This is a read-only demo site!",
|
||||||
"Timestamp": "Отметка времени",
|
"Timestamp": "Отметка времени",
|
||||||
"Tokens": "Жетоны",
|
"Tokens": "Жетоны",
|
||||||
"URL": "URL",
|
"URL": "URL",
|
||||||
@ -309,10 +312,10 @@
|
|||||||
"Or sign in with another account": "Или войти с помощью другой учетной записи",
|
"Or sign in with another account": "Или войти с помощью другой учетной записи",
|
||||||
"Password": "Пароль",
|
"Password": "Пароль",
|
||||||
"Password - Tooltip": "Пароль - Подсказка",
|
"Password - Tooltip": "Пароль - Подсказка",
|
||||||
|
"Please input your Email or Phone!": "Please input your Email or Phone!",
|
||||||
"Please input your code!": "Пожалуйста, введите ваш код!",
|
"Please input your code!": "Пожалуйста, введите ваш код!",
|
||||||
"Please input your password!": "Пожалуйста, введите ваш пароль!",
|
"Please input your password!": "Пожалуйста, введите ваш пароль!",
|
||||||
"Please input your password, at least 6 characters!": "Пожалуйста, введите ваш пароль, по крайней мере 6 символов!",
|
"Please input your password, at least 6 characters!": "Пожалуйста, введите ваш пароль, по крайней мере 6 символов!",
|
||||||
"Please input your username, Email or phone!": "Пожалуйста, введите ваше имя пользователя, адрес электронной почты или телефон!",
|
|
||||||
"Redirecting, please wait.": "Redirecting, please wait.",
|
"Redirecting, please wait.": "Redirecting, please wait.",
|
||||||
"Sign In": "Войти",
|
"Sign In": "Войти",
|
||||||
"Sign in with WebAuthn": "Sign in with WebAuthn",
|
"Sign in with WebAuthn": "Sign in with WebAuthn",
|
||||||
@ -638,6 +641,7 @@
|
|||||||
"Please input your last name!": "Please input your last name!",
|
"Please input your last name!": "Please input your last name!",
|
||||||
"Please input your phone number!": "Пожалуйста, введите ваш номер телефона!",
|
"Please input your phone number!": "Пожалуйста, введите ваш номер телефона!",
|
||||||
"Please input your real name!": "Пожалуйста, введите ваше личное имя!",
|
"Please input your real name!": "Пожалуйста, введите ваше личное имя!",
|
||||||
|
"Please select your country code!": "Please select your country code!",
|
||||||
"Please select your country/region!": "Пожалуйста, выберите вашу страну/регион!",
|
"Please select your country/region!": "Пожалуйста, выберите вашу страну/регион!",
|
||||||
"Terms of Use": "Условия использования",
|
"Terms of Use": "Условия использования",
|
||||||
"The input is not invoice Tax ID!": "The input is not invoice Tax ID!",
|
"The input is not invoice Tax ID!": "The input is not invoice Tax ID!",
|
||||||
@ -724,6 +728,7 @@
|
|||||||
"Captcha Verify Failed": "Captcha Verify Failed",
|
"Captcha Verify Failed": "Captcha Verify Failed",
|
||||||
"Captcha Verify Success": "Captcha Verify Success",
|
"Captcha Verify Success": "Captcha Verify Success",
|
||||||
"Code Sent": "Код отправлен",
|
"Code Sent": "Код отправлен",
|
||||||
|
"Country code": "Country code",
|
||||||
"Country/Region": "Страна/регион",
|
"Country/Region": "Страна/регион",
|
||||||
"Country/Region - Tooltip": "Country/Region",
|
"Country/Region - Tooltip": "Country/Region",
|
||||||
"Edit User": "Изменить пользователя",
|
"Edit User": "Изменить пользователя",
|
||||||
|
805
web/src/locales/vi/data.json
Normal file
805
web/src/locales/vi/data.json
Normal file
@ -0,0 +1,805 @@
|
|||||||
|
{
|
||||||
|
"account": {
|
||||||
|
"Logout": "Logout",
|
||||||
|
"My Account": "My Account",
|
||||||
|
"Sign Up": "Sign Up"
|
||||||
|
},
|
||||||
|
"adapter": {
|
||||||
|
"Edit Adapter": "Edit Adapter",
|
||||||
|
"Failed to sync policies": "Failed to sync policies",
|
||||||
|
"New Adapter": "New Adapter",
|
||||||
|
"Policies": "Policies",
|
||||||
|
"Policies - Tooltip": "Policies - Tooltip",
|
||||||
|
"Repeated policy rules": "Repeated policy rules",
|
||||||
|
"Sync": "Sync",
|
||||||
|
"Sync policies successfully": "Sync policies successfully"
|
||||||
|
},
|
||||||
|
"application": {
|
||||||
|
"Always": "Always",
|
||||||
|
"Auto signin": "Auto signin",
|
||||||
|
"Auto signin - Tooltip": "Auto signin - Tooltip",
|
||||||
|
"Background URL": "Background URL",
|
||||||
|
"Background URL - Tooltip": "Background URL - Tooltip",
|
||||||
|
"Center": "Center",
|
||||||
|
"Copy SAML metadata URL": "Copy SAML metadata URL",
|
||||||
|
"Copy prompt page URL": "Copy prompt page URL",
|
||||||
|
"Copy signin page URL": "Copy signin page URL",
|
||||||
|
"Copy signup page URL": "Copy signup page URL",
|
||||||
|
"Edit Application": "Edit Application",
|
||||||
|
"Enable SAML compress": "Enable SAML compress",
|
||||||
|
"Enable SAML compress - Tooltip": "Enable SAML compress - Tooltip",
|
||||||
|
"Enable WebAuthn signin": "Enable WebAuthn signin",
|
||||||
|
"Enable WebAuthn signin - Tooltip": "Enable WebAuthn signin - Tooltip",
|
||||||
|
"Enable code signin": "Enable code signin",
|
||||||
|
"Enable code signin - Tooltip": "Enable code signin - Tooltip",
|
||||||
|
"Enable link accounts that with the same email": "Enable link accounts that with the same email",
|
||||||
|
"Enable link accounts that with the same email - Tooltip": "Enable link accounts that with the same email - Tooltip",
|
||||||
|
"Enable side panel": "Enable side panel",
|
||||||
|
"Enable signin session - Tooltip": "Enable signin session - Tooltip",
|
||||||
|
"Enable signup": "Enable signup",
|
||||||
|
"Enable signup - Tooltip": "Enable signup - Tooltip",
|
||||||
|
"Failed to sign in": "Failed to sign in",
|
||||||
|
"File uploaded successfully": "File uploaded successfully",
|
||||||
|
"Follow organization theme": "Follow organization theme",
|
||||||
|
"Form CSS": "Form CSS",
|
||||||
|
"Form CSS - Edit": "Form CSS - Edit",
|
||||||
|
"Form CSS - Tooltip": "Form CSS - Tooltip",
|
||||||
|
"Form position": "Form position",
|
||||||
|
"Form position - Tooltip": "Form position - Tooltip",
|
||||||
|
"Grant types": "Grant types",
|
||||||
|
"Grant types - Tooltip": "Grant types - Tooltip",
|
||||||
|
"Left": "Left",
|
||||||
|
"Logged in successfully": "Logged in successfully",
|
||||||
|
"Logged out successfully": "Logged out successfully",
|
||||||
|
"New Application": "New Application",
|
||||||
|
"None": "None",
|
||||||
|
"Password ON": "Password ON",
|
||||||
|
"Password ON - Tooltip": "Password ON - Tooltip",
|
||||||
|
"Please input your application!": "Please input your application!",
|
||||||
|
"Please input your organization!": "Please input your organization!",
|
||||||
|
"Please select a HTML file": "Please select a HTML file",
|
||||||
|
"Prompt page URL copied to clipboard successfully, please paste it into the incognito window or another browser": "Prompt page URL copied to clipboard successfully, please paste it into the incognito window or another browser",
|
||||||
|
"Redirect URL": "Redirect URL",
|
||||||
|
"Redirect URL (Assertion Consumer Service POST Binding URL) - Tooltip": "Redirect URL (Assertion Consumer Service POST Binding URL) - Tooltip",
|
||||||
|
"Redirect URLs": "Redirect URLs",
|
||||||
|
"Redirect URLs - Tooltip": "Redirect URLs - Tooltip",
|
||||||
|
"Refresh token expire": "Refresh token expire",
|
||||||
|
"Refresh token expire - Tooltip": "Refresh token expire - Tooltip",
|
||||||
|
"Right": "Right",
|
||||||
|
"Rule": "Rule",
|
||||||
|
"SAML Reply URL": "SAML Reply URL",
|
||||||
|
"SAML metadata": "SAML metadata",
|
||||||
|
"SAML metadata - Tooltip": "SAML metadata - Tooltip",
|
||||||
|
"SAML metadata URL copied to clipboard successfully": "SAML metadata URL copied to clipboard successfully",
|
||||||
|
"Side panel HTML": "Side panel HTML",
|
||||||
|
"Side panel HTML - Edit": "Side panel HTML - Edit",
|
||||||
|
"Side panel HTML - Tooltip": "Side panel HTML - Tooltip",
|
||||||
|
"Sign Up Error": "Sign Up Error",
|
||||||
|
"Signin page URL copied to clipboard successfully, please paste it into the incognito window or another browser": "Signin page URL copied to clipboard successfully, please paste it into the incognito window or another browser",
|
||||||
|
"Signin session": "Signin session",
|
||||||
|
"Signup items": "Signup items",
|
||||||
|
"Signup items - Tooltip": "Signup items - Tooltip",
|
||||||
|
"Signup page URL copied to clipboard successfully, please paste it into the incognito window or another browser": "Signup page URL copied to clipboard successfully, please paste it into the incognito window or another browser",
|
||||||
|
"The application does not allow to sign up new account": "The application does not allow to sign up new account",
|
||||||
|
"Token expire": "Token expire",
|
||||||
|
"Token expire - Tooltip": "Token expire - Tooltip",
|
||||||
|
"Token format": "Token format",
|
||||||
|
"Token format - Tooltip": "Token format - Tooltip",
|
||||||
|
"You are unexpected to see this prompt page": "You are unexpected to see this prompt page"
|
||||||
|
},
|
||||||
|
"cert": {
|
||||||
|
"Bit size": "Bit size",
|
||||||
|
"Bit size - Tooltip": "Bit size - Tooltip",
|
||||||
|
"Certificate": "Certificate",
|
||||||
|
"Certificate - Tooltip": "Certificate - Tooltip",
|
||||||
|
"Certificate copied to clipboard successfully": "Certificate copied to clipboard successfully",
|
||||||
|
"Copy certificate": "Copy certificate",
|
||||||
|
"Copy private key": "Copy private key",
|
||||||
|
"Crypto algorithm": "Crypto algorithm",
|
||||||
|
"Crypto algorithm - Tooltip": "Crypto algorithm - Tooltip",
|
||||||
|
"Download certificate": "Download certificate",
|
||||||
|
"Download private key": "Download private key",
|
||||||
|
"Edit Cert": "Edit Cert",
|
||||||
|
"Expire in years": "Expire in years",
|
||||||
|
"Expire in years - Tooltip": "Expire in years - Tooltip",
|
||||||
|
"New Cert": "New Cert",
|
||||||
|
"Private key": "Private key",
|
||||||
|
"Private key - Tooltip": "Private key - Tooltip",
|
||||||
|
"Private key copied to clipboard successfully": "Private key copied to clipboard successfully",
|
||||||
|
"Scope": "Scope",
|
||||||
|
"Scope - Tooltip": "Scope - Tooltip",
|
||||||
|
"Type": "Type",
|
||||||
|
"Type - Tooltip": "Type - Tooltip"
|
||||||
|
},
|
||||||
|
"code": {
|
||||||
|
"Code You Received": "Code You Received",
|
||||||
|
"Email code": "Email code",
|
||||||
|
"Empty Code": "Empty Code",
|
||||||
|
"Enter your code": "Enter your code",
|
||||||
|
"Phone code": "Phone code",
|
||||||
|
"Please input your phone verification code!": "Please input your phone verification code!",
|
||||||
|
"Please input your verification code!": "Please input your verification code!",
|
||||||
|
"Send Code": "Send Code",
|
||||||
|
"Sending Code": "Sending Code",
|
||||||
|
"Submit and complete": "Submit and complete"
|
||||||
|
},
|
||||||
|
"forget": {
|
||||||
|
"Account": "Account",
|
||||||
|
"Change Password": "Change Password",
|
||||||
|
"Choose email or phone": "Choose email or phone",
|
||||||
|
"Confirm": "Confirm",
|
||||||
|
"Next Step": "Next Step",
|
||||||
|
"Password": "Password",
|
||||||
|
"Please input your username!": "Please input your username!",
|
||||||
|
"Reset": "Reset",
|
||||||
|
"Retrieve password": "Retrieve password",
|
||||||
|
"Unknown forget type: ": "Unknown forget type: ",
|
||||||
|
"Verify": "Verify"
|
||||||
|
},
|
||||||
|
"general": {
|
||||||
|
"Action": "Action",
|
||||||
|
"Adapter": "Adapter",
|
||||||
|
"Adapter - Tooltip": "Adapter - Tooltip",
|
||||||
|
"Adapters": "Adapters",
|
||||||
|
"Add": "Add",
|
||||||
|
"Affiliation URL": "Affiliation URL",
|
||||||
|
"Affiliation URL - Tooltip": "Affiliation URL - Tooltip",
|
||||||
|
"Application": "Application",
|
||||||
|
"Applications": "Applications",
|
||||||
|
"Applications that require authentication": "Applications that require authentication",
|
||||||
|
"Avatar": "Avatar",
|
||||||
|
"Avatar - Tooltip": "Avatar - Tooltip",
|
||||||
|
"Back Home": "Back Home",
|
||||||
|
"Cancel": "Cancel",
|
||||||
|
"Captcha": "Captcha",
|
||||||
|
"Cert": "Cert",
|
||||||
|
"Cert - Tooltip": "Cert - Tooltip",
|
||||||
|
"Certs": "Certs",
|
||||||
|
"Click to Upload": "Click to Upload",
|
||||||
|
"Client IP": "Client IP",
|
||||||
|
"Close": "Close",
|
||||||
|
"Created time": "Created time",
|
||||||
|
"Default application": "Default application",
|
||||||
|
"Default application - Tooltip": "Default application - Tooltip",
|
||||||
|
"Default avatar": "Default avatar",
|
||||||
|
"Default avatar - Tooltip": "Default avatar - Tooltip",
|
||||||
|
"Delete": "Delete",
|
||||||
|
"Description": "Description",
|
||||||
|
"Description - Tooltip": "Description - Tooltip",
|
||||||
|
"Display name": "Display name",
|
||||||
|
"Display name - Tooltip": "Display name - Tooltip",
|
||||||
|
"Down": "Down",
|
||||||
|
"Edit": "Edit",
|
||||||
|
"Email": "Email",
|
||||||
|
"Email - Tooltip": "Email - Tooltip",
|
||||||
|
"Failed to add": "Failed to add",
|
||||||
|
"Failed to connect to server": "Failed to connect to server",
|
||||||
|
"Failed to delete": "Failed to delete",
|
||||||
|
"Failed to save": "Failed to save",
|
||||||
|
"Favicon": "Favicon",
|
||||||
|
"Favicon - Tooltip": "Favicon - Tooltip",
|
||||||
|
"First name": "First name",
|
||||||
|
"Forget URL": "Forget URL",
|
||||||
|
"Forget URL - Tooltip": "Forget URL - Tooltip",
|
||||||
|
"Found some texts still not translated? Please help us translate at": "Found some texts still not translated? Please help us translate at",
|
||||||
|
"Go to writable demo site?": "Go to writable demo site?",
|
||||||
|
"Home": "Home",
|
||||||
|
"Home - Tooltip": "Home - Tooltip",
|
||||||
|
"ID": "ID",
|
||||||
|
"ID - Tooltip": "ID - Tooltip",
|
||||||
|
"Is enabled": "Is enabled",
|
||||||
|
"Is enabled - Tooltip": "Is enabled - Tooltip",
|
||||||
|
"LDAPs": "LDAPs",
|
||||||
|
"LDAPs - Tooltip": "LDAPs - Tooltip",
|
||||||
|
"Languages": "Languages",
|
||||||
|
"Languages - Tooltip": "Languages - Tooltip",
|
||||||
|
"Last name": "Last name",
|
||||||
|
"Logo": "Logo",
|
||||||
|
"Logo - Tooltip": "Logo - Tooltip",
|
||||||
|
"Master password": "Master password",
|
||||||
|
"Master password - Tooltip": "Master password - Tooltip",
|
||||||
|
"Menu": "Menu",
|
||||||
|
"Method": "Method",
|
||||||
|
"Model": "Model",
|
||||||
|
"Model - Tooltip": "Model - Tooltip",
|
||||||
|
"Models": "Models",
|
||||||
|
"Name": "Name",
|
||||||
|
"Name - Tooltip": "Name - Tooltip",
|
||||||
|
"OAuth providers": "OAuth providers",
|
||||||
|
"Organization": "Organization",
|
||||||
|
"Organization - Tooltip": "Organization - Tooltip",
|
||||||
|
"Organizations": "Organizations",
|
||||||
|
"Password": "Password",
|
||||||
|
"Password - Tooltip": "Password - Tooltip",
|
||||||
|
"Password salt": "Password salt",
|
||||||
|
"Password salt - Tooltip": "Password salt - Tooltip",
|
||||||
|
"Password type": "Password type",
|
||||||
|
"Password type - Tooltip": "Password type - Tooltip",
|
||||||
|
"Payments": "Payments",
|
||||||
|
"Permissions": "Permissions",
|
||||||
|
"Permissions - Tooltip": "Permissions - Tooltip",
|
||||||
|
"Phone": "Phone",
|
||||||
|
"Phone - Tooltip": "Phone - Tooltip",
|
||||||
|
"Preview": "Preview",
|
||||||
|
"Preview - Tooltip": "Preview - Tooltip",
|
||||||
|
"Products": "Products",
|
||||||
|
"Provider": "Provider",
|
||||||
|
"Provider - Tooltip": "Provider - Tooltip",
|
||||||
|
"Providers": "Providers",
|
||||||
|
"Providers - Tooltip": "Providers - Tooltip",
|
||||||
|
"Real name": "Real name",
|
||||||
|
"Records": "Records",
|
||||||
|
"Request URI": "Request URI",
|
||||||
|
"Resources": "Resources",
|
||||||
|
"Roles": "Roles",
|
||||||
|
"Roles - Tooltip": "Roles - Tooltip",
|
||||||
|
"Save": "Save",
|
||||||
|
"Save & Exit": "Save & Exit",
|
||||||
|
"Session ID": "Session ID",
|
||||||
|
"Sessions": "Sessions",
|
||||||
|
"Signin URL": "Signin URL",
|
||||||
|
"Signin URL - Tooltip": "Signin URL - Tooltip",
|
||||||
|
"Signup URL": "Signup URL",
|
||||||
|
"Signup URL - Tooltip": "Signup URL - Tooltip",
|
||||||
|
"Signup application": "Signup application",
|
||||||
|
"Signup application - Tooltip": "Signup application - Tooltip",
|
||||||
|
"Sorry, the page you visited does not exist.": "Sorry, the page you visited does not exist.",
|
||||||
|
"Sorry, the user you visited does not exist or you are not authorized to access this user.": "Sorry, the user you visited does not exist or you are not authorized to access this user.",
|
||||||
|
"Sorry, you do not have permission to access this page or logged in status invalid.": "Sorry, you do not have permission to access this page or logged in status invalid.",
|
||||||
|
"State": "State",
|
||||||
|
"State - Tooltip": "State - Tooltip",
|
||||||
|
"Successfully added": "Successfully added",
|
||||||
|
"Successfully deleted": "Successfully deleted",
|
||||||
|
"Successfully saved": "Successfully saved",
|
||||||
|
"Supported country code": "Supported country code",
|
||||||
|
"Supported country code - Tooltip": "Supported country code - Tooltip",
|
||||||
|
"Swagger": "Swagger",
|
||||||
|
"Sync": "Sync",
|
||||||
|
"Syncers": "Syncers",
|
||||||
|
"SysInfo": "SysInfo",
|
||||||
|
"This is a read-only demo site!": "This is a read-only demo site!",
|
||||||
|
"Timestamp": "Timestamp",
|
||||||
|
"Tokens": "Tokens",
|
||||||
|
"URL": "URL",
|
||||||
|
"URL - Tooltip": "URL - Tooltip",
|
||||||
|
"Up": "Up",
|
||||||
|
"User": "User",
|
||||||
|
"User - Tooltip": "User - Tooltip",
|
||||||
|
"User containers": "User containers",
|
||||||
|
"User type": "User type",
|
||||||
|
"User type - Tooltip": "User type - Tooltip",
|
||||||
|
"Users": "Users",
|
||||||
|
"Users under all organizations": "Users under all organizations",
|
||||||
|
"Webhooks": "Webhooks",
|
||||||
|
"{total} in total": "{total} in total"
|
||||||
|
},
|
||||||
|
"ldap": {
|
||||||
|
"Address": "Address",
|
||||||
|
"Admin": "Admin",
|
||||||
|
"Admin - Tooltip": "Admin - Tooltip",
|
||||||
|
"Admin Password": "Admin Password",
|
||||||
|
"Admin Password - Tooltip": "Admin Password - Tooltip",
|
||||||
|
"Auto Sync": "Auto Sync",
|
||||||
|
"Auto Sync - Tooltip": "Auto Sync - Tooltip",
|
||||||
|
"Base DN": "Base DN",
|
||||||
|
"Base DN - Tooltip": "Base DN - Tooltip",
|
||||||
|
"CN": "CN",
|
||||||
|
"Edit LDAP": "Edit LDAP",
|
||||||
|
"Email": "Email",
|
||||||
|
"Group Id": "Group Id",
|
||||||
|
"ID": "ID",
|
||||||
|
"Last Sync": "Last Sync",
|
||||||
|
"Phone": "Phone",
|
||||||
|
"Server": "Server",
|
||||||
|
"Server Host": "Server Host",
|
||||||
|
"Server Host - Tooltip": "Server Host - Tooltip",
|
||||||
|
"Server Name": "Server Name",
|
||||||
|
"Server Name - Tooltip": "Server Name - Tooltip",
|
||||||
|
"Server Port": "Server Port",
|
||||||
|
"Server Port - Tooltip": "Server Port - Tooltip",
|
||||||
|
"Sync": "Sync",
|
||||||
|
"The Auto Sync option will sync all users to specify organization": "The Auto Sync option will sync all users to specify organization",
|
||||||
|
"UidNumber / Uid": "UidNumber / Uid"
|
||||||
|
},
|
||||||
|
"login": {
|
||||||
|
"Auto sign in": "Auto sign in",
|
||||||
|
"Continue with": "Continue with",
|
||||||
|
"Email or phone": "Email or phone",
|
||||||
|
"Forgot password?": "Forgot password?",
|
||||||
|
"Loading": "Loading",
|
||||||
|
"Logging out...": "Logging out...",
|
||||||
|
"No account?": "No account?",
|
||||||
|
"Or sign in with another account": "Or sign in with another account",
|
||||||
|
"Password": "Password",
|
||||||
|
"Password - Tooltip": "Password - Tooltip",
|
||||||
|
"Please input your Email or Phone!": "Please input your Email or Phone!",
|
||||||
|
"Please input your code!": "Please input your code!",
|
||||||
|
"Please input your password!": "Please input your password!",
|
||||||
|
"Please input your password, at least 6 characters!": "Please input your password, at least 6 characters!",
|
||||||
|
"Redirecting, please wait.": "Redirecting, please wait.",
|
||||||
|
"Sign In": "Sign In",
|
||||||
|
"Sign in with WebAuthn": "Sign in with WebAuthn",
|
||||||
|
"Sign in with {type}": "Sign in with {type}",
|
||||||
|
"Signing in...": "Signing in...",
|
||||||
|
"Successfully logged in with webauthn credentials": "Successfully logged in with webauthn credentials",
|
||||||
|
"The input is not valid Email or Phone!": "The input is not valid Email or Phone!",
|
||||||
|
"To access": "To access",
|
||||||
|
"Verification Code": "Verification Code",
|
||||||
|
"WebAuthn": "WebAuthn",
|
||||||
|
"sign up now": "sign up now",
|
||||||
|
"username, Email or phone": "username, Email or phone"
|
||||||
|
},
|
||||||
|
"model": {
|
||||||
|
"Edit Model": "Edit Model",
|
||||||
|
"Model text": "Model text",
|
||||||
|
"Model text - Tooltip": "Model text - Tooltip",
|
||||||
|
"New Model": "New Model"
|
||||||
|
},
|
||||||
|
"organization": {
|
||||||
|
"Account items": "Account items",
|
||||||
|
"Account items - Tooltip": "Account items - Tooltip",
|
||||||
|
"Default avatar": "Default avatar",
|
||||||
|
"Edit Organization": "Edit Organization",
|
||||||
|
"Favicon": "Favicon",
|
||||||
|
"Follow global theme": "Follow global theme",
|
||||||
|
"InitScore": "InitScore",
|
||||||
|
"Is profile public": "Is profile public",
|
||||||
|
"Is profile public - Tooltip": "Is profile public - Tooltip",
|
||||||
|
"Modify rule": "Modify rule",
|
||||||
|
"New Organization": "New Organization",
|
||||||
|
"Soft deletion": "Soft deletion",
|
||||||
|
"Soft deletion - Tooltip": "Soft deletion - Tooltip",
|
||||||
|
"Tags": "Tags",
|
||||||
|
"Tags - Tooltip": "Tags - Tooltip",
|
||||||
|
"The user's initScore - Tooltip": "The user's initScore - Tooltip",
|
||||||
|
"View rule": "View rule",
|
||||||
|
"Visible": "Visible",
|
||||||
|
"Website URL": "Website URL",
|
||||||
|
"Website URL - Tooltip": "Website URL - Tooltip"
|
||||||
|
},
|
||||||
|
"payment": {
|
||||||
|
"Confirm your invoice information": "Confirm your invoice information",
|
||||||
|
"Currency": "Currency",
|
||||||
|
"Currency - Tooltip": "Currency - Tooltip",
|
||||||
|
"Download Invoice": "Download Invoice",
|
||||||
|
"Edit Payment": "Edit Payment",
|
||||||
|
"Individual": "Individual",
|
||||||
|
"Invoice URL": "Invoice URL",
|
||||||
|
"Invoice URL - Tooltip": "Invoice URL - Tooltip",
|
||||||
|
"Invoice actions": "Invoice actions",
|
||||||
|
"Invoice actions - Tooltip": "Invoice actions - Tooltip",
|
||||||
|
"Invoice remark": "Invoice remark",
|
||||||
|
"Invoice remark - Tooltip": "Invoice remark - Tooltip",
|
||||||
|
"Invoice tax ID": "Invoice tax ID",
|
||||||
|
"Invoice tax ID - Tooltip": "Invoice tax ID - Tooltip",
|
||||||
|
"Invoice title": "Invoice title",
|
||||||
|
"Invoice title - Tooltip": "Invoice title - Tooltip",
|
||||||
|
"Invoice type": "Invoice type",
|
||||||
|
"Invoice type - Tooltip": "Invoice type - Tooltip",
|
||||||
|
"Issue Invoice": "Issue Invoice",
|
||||||
|
"Message": "Message",
|
||||||
|
"Message - Tooltip": "Message - Tooltip",
|
||||||
|
"New Payment": "New Payment",
|
||||||
|
"Organization": "Organization",
|
||||||
|
"Person Email": "Person Email",
|
||||||
|
"Person Email - Tooltip": "Person Email - Tooltip",
|
||||||
|
"Person ID card": "Person ID card",
|
||||||
|
"Person ID card - Tooltip": "Person ID card - Tooltip",
|
||||||
|
"Person name": "Person name",
|
||||||
|
"Person name - Tooltip": "Person name - Tooltip",
|
||||||
|
"Person phone": "Person phone",
|
||||||
|
"Person phone - Tooltip": "Person phone - Tooltip",
|
||||||
|
"Please carefully check your invoice information. Once the invoice is issued, it cannot be withdrawn or modified.": "Please carefully check your invoice information. Once the invoice is issued, it cannot be withdrawn or modified.",
|
||||||
|
"Please click the below button to return to the original website": "Please click the below button to return to the original website",
|
||||||
|
"Please pay the order first!": "Please pay the order first!",
|
||||||
|
"Price": "Price",
|
||||||
|
"Price - Tooltip": "Price - Tooltip",
|
||||||
|
"Processing...": "Processing...",
|
||||||
|
"Product": "Product",
|
||||||
|
"Product - Tooltip": "Product - Tooltip",
|
||||||
|
"Result": "Result",
|
||||||
|
"Return to Website": "Return to Website",
|
||||||
|
"State": "State",
|
||||||
|
"State - Tooltip": "State - Tooltip",
|
||||||
|
"The payment has failed": "The payment has failed",
|
||||||
|
"The payment is still under processing": "The payment is still under processing",
|
||||||
|
"Type": "Type",
|
||||||
|
"Type - Tooltip": "Type - Tooltip",
|
||||||
|
"You have successfully completed the payment": "You have successfully completed the payment",
|
||||||
|
"please wait for a few seconds...": "please wait for a few seconds...",
|
||||||
|
"the current state is": "the current state is"
|
||||||
|
},
|
||||||
|
"permission": {
|
||||||
|
"Actions": "Actions",
|
||||||
|
"Actions - Tooltip": "Actions - Tooltip",
|
||||||
|
"Admin": "Admin",
|
||||||
|
"Allow": "Allow",
|
||||||
|
"Approve time": "Approve time",
|
||||||
|
"Approve time - Tooltip": "Approve time - Tooltip",
|
||||||
|
"Approved": "Approved",
|
||||||
|
"Approver": "Approver",
|
||||||
|
"Approver - Tooltip": "Approver - Tooltip",
|
||||||
|
"Deny": "Deny",
|
||||||
|
"Edit Permission": "Edit Permission",
|
||||||
|
"Effect": "Effect",
|
||||||
|
"Effect - Tooltip": "Effect - Tooltip",
|
||||||
|
"New Permission": "New Permission",
|
||||||
|
"Pending": "Pending",
|
||||||
|
"Read": "Read",
|
||||||
|
"Resource type": "Resource type",
|
||||||
|
"Resource type - Tooltip": "Resource type - Tooltip",
|
||||||
|
"Resources": "Resources",
|
||||||
|
"Resources - Tooltip": "Resources - Tooltip",
|
||||||
|
"State": "State",
|
||||||
|
"State - Tooltip": "State - Tooltip",
|
||||||
|
"Submitter": "Submitter",
|
||||||
|
"Submitter - Tooltip": "Submitter - Tooltip",
|
||||||
|
"TreeNode": "TreeNode",
|
||||||
|
"Write": "Write"
|
||||||
|
},
|
||||||
|
"product": {
|
||||||
|
"Alipay": "Alipay",
|
||||||
|
"Buy": "Buy",
|
||||||
|
"Buy Product": "Buy Product",
|
||||||
|
"CNY": "CNY",
|
||||||
|
"Currency": "Currency",
|
||||||
|
"Currency - Tooltip": "Currency - Tooltip",
|
||||||
|
"Description": "Description",
|
||||||
|
"Description - Tooltip": "Description - Tooltip",
|
||||||
|
"Detail": "Detail",
|
||||||
|
"Detail - Tooltip": "Detail - Tooltip",
|
||||||
|
"Edit Product": "Edit Product",
|
||||||
|
"I have completed the payment": "I have completed the payment",
|
||||||
|
"Image": "Image",
|
||||||
|
"Image - Tooltip": "Image - Tooltip",
|
||||||
|
"New Product": "New Product",
|
||||||
|
"Pay": "Pay",
|
||||||
|
"Payment providers": "Payment providers",
|
||||||
|
"Payment providers - Tooltip": "Payment providers - Tooltip",
|
||||||
|
"Paypal": "Paypal",
|
||||||
|
"Placing order...": "Placing order...",
|
||||||
|
"Please provide your username in the remark": "Please provide your username in the remark",
|
||||||
|
"Please scan the QR code to pay": "Please scan the QR code to pay",
|
||||||
|
"Price": "Price",
|
||||||
|
"Price - Tooltip": "Price - Tooltip",
|
||||||
|
"Quantity": "Quantity",
|
||||||
|
"Quantity - Tooltip": "Quantity - Tooltip",
|
||||||
|
"Return URL": "Return URL",
|
||||||
|
"Return URL - Tooltip": "Return URL - Tooltip",
|
||||||
|
"SKU": "SKU",
|
||||||
|
"Sold": "Sold",
|
||||||
|
"Sold - Tooltip": "Sold - Tooltip",
|
||||||
|
"Tag": "Tag",
|
||||||
|
"Tag - Tooltip": "Tag - Tooltip",
|
||||||
|
"Test buy page..": "Test buy page..",
|
||||||
|
"There is no payment channel for this product.": "There is no payment channel for this product.",
|
||||||
|
"This product is currently not in sale.": "This product is currently not in sale.",
|
||||||
|
"USD": "USD",
|
||||||
|
"WeChat Pay": "WeChat Pay"
|
||||||
|
},
|
||||||
|
"provider": {
|
||||||
|
"Access key": "Access key",
|
||||||
|
"Access key - Tooltip": "Access key - Tooltip",
|
||||||
|
"Agent ID": "Agent ID",
|
||||||
|
"Agent ID - Tooltip": "Agent ID - Tooltip",
|
||||||
|
"App ID": "App ID",
|
||||||
|
"App ID - Tooltip": "App ID - Tooltip",
|
||||||
|
"App key": "App key",
|
||||||
|
"App key - Tooltip": "App key - Tooltip",
|
||||||
|
"App secret": "App secret",
|
||||||
|
"AppSecret - Tooltip": "AppSecret - Tooltip",
|
||||||
|
"Auth URL": "Auth URL",
|
||||||
|
"Auth URL - Tooltip": "Auth URL - Tooltip",
|
||||||
|
"Bucket": "Bucket",
|
||||||
|
"Bucket - Tooltip": "Bucket - Tooltip",
|
||||||
|
"Can not parse Metadata": "Can not parse Metadata",
|
||||||
|
"Can signin": "Can signin",
|
||||||
|
"Can signup": "Can signup",
|
||||||
|
"Can unlink": "Can unlink",
|
||||||
|
"Category": "Category",
|
||||||
|
"Category - Tooltip": "Category - Tooltip",
|
||||||
|
"Channel No.": "Channel No.",
|
||||||
|
"Channel No. - Tooltip": "Channel No. - Tooltip",
|
||||||
|
"Client ID": "Client ID",
|
||||||
|
"Client ID - Tooltip": "Client ID - Tooltip",
|
||||||
|
"Client ID 2": "Client ID 2",
|
||||||
|
"Client ID 2 - Tooltip": "Client ID 2 - Tooltip",
|
||||||
|
"Client secret": "Client secret",
|
||||||
|
"Client secret - Tooltip": "Client secret - Tooltip",
|
||||||
|
"Client secret 2": "Client secret 2",
|
||||||
|
"Client secret 2 - Tooltip": "Client secret 2 - Tooltip",
|
||||||
|
"Copy": "Copy",
|
||||||
|
"Disable SSL": "Disable SSL",
|
||||||
|
"Disable SSL - Tooltip": "Disable SSL - Tooltip",
|
||||||
|
"Domain": "Domain",
|
||||||
|
"Domain - Tooltip": "Domain - Tooltip",
|
||||||
|
"Edit Provider": "Edit Provider",
|
||||||
|
"Email Content": "Email Content",
|
||||||
|
"Email Content - Tooltip": "Email Content - Tooltip",
|
||||||
|
"Email Title": "Email Title",
|
||||||
|
"Email Title - Tooltip": "Email Title - Tooltip",
|
||||||
|
"Enable QR code": "Enable QR code",
|
||||||
|
"Enable QR code - Tooltip": "Enable QR code - Tooltip",
|
||||||
|
"Endpoint": "Endpoint",
|
||||||
|
"Endpoint (Intranet)": "Endpoint (Intranet)",
|
||||||
|
"Host": "Host",
|
||||||
|
"Host - Tooltip": "Host - Tooltip",
|
||||||
|
"IdP": "IdP",
|
||||||
|
"IdP certificate": "IdP certificate",
|
||||||
|
"Issuer URL": "Issuer URL",
|
||||||
|
"Issuer URL - Tooltip": "Issuer URL - Tooltip",
|
||||||
|
"Link copied to clipboard successfully": "Link copied to clipboard successfully",
|
||||||
|
"Metadata": "Metadata",
|
||||||
|
"Metadata - Tooltip": "Metadata - Tooltip",
|
||||||
|
"Method": "Method",
|
||||||
|
"Method - Tooltip": "Method - Tooltip",
|
||||||
|
"Name": "Name",
|
||||||
|
"New Provider": "New Provider",
|
||||||
|
"Parse": "Parse",
|
||||||
|
"Parse Metadata successfully": "Parse Metadata successfully",
|
||||||
|
"Path prefix": "Path prefix",
|
||||||
|
"Please use WeChat and scan the QR code to sign in": "Please use WeChat and scan the QR code to sign in",
|
||||||
|
"Port": "Port",
|
||||||
|
"Port - Tooltip": "Port - Tooltip",
|
||||||
|
"Prompted": "Prompted",
|
||||||
|
"Provider URL": "Provider URL",
|
||||||
|
"Provider URL - Tooltip": "Provider URL - Tooltip",
|
||||||
|
"Region ID": "Region ID",
|
||||||
|
"Region ID - Tooltip": "Region ID - Tooltip",
|
||||||
|
"Region endpoint for Internet": "Region endpoint for Internet",
|
||||||
|
"Region endpoint for Intranet": "Region endpoint for Intranet",
|
||||||
|
"Required": "Required",
|
||||||
|
"SAML 2.0 Endpoint (HTTP)": "SAML 2.0 Endpoint (HTTP)",
|
||||||
|
"SMS account": "SMS account",
|
||||||
|
"SMS account - Tooltip": "SMS account - Tooltip",
|
||||||
|
"SP ACS URL": "SP ACS URL",
|
||||||
|
"SP ACS URL - Tooltip": "SP ACS URL - Tooltip",
|
||||||
|
"SP Entity ID": "SP Entity ID",
|
||||||
|
"Scene": "Scene",
|
||||||
|
"Scene - Tooltip": "Scene - Tooltip",
|
||||||
|
"Scope": "Scope",
|
||||||
|
"Scope - Tooltip": "Scope - Tooltip",
|
||||||
|
"Secret access key": "Secret access key",
|
||||||
|
"Secret key": "Secret key",
|
||||||
|
"Secret key - Tooltip": "Secret key - Tooltip",
|
||||||
|
"SecretAccessKey - Tooltip": "SecretAccessKey - Tooltip",
|
||||||
|
"Send Test Email": "Send Test Email",
|
||||||
|
"Sign Name": "Sign Name",
|
||||||
|
"Sign Name - Tooltip": "Sign Name - Tooltip",
|
||||||
|
"Sign request": "Sign request",
|
||||||
|
"Sign request - Tooltip": "Sign request - Tooltip",
|
||||||
|
"Signin HTML": "Signin HTML",
|
||||||
|
"Signin HTML - Edit": "Signin HTML - Edit",
|
||||||
|
"Signin HTML - Tooltip": "Signin HTML - Tooltip",
|
||||||
|
"Signup HTML": "Signup HTML",
|
||||||
|
"Signup HTML - Edit": "Signup HTML - Edit",
|
||||||
|
"Signup HTML - Tooltip": "Signup HTML - Tooltip",
|
||||||
|
"Site key": "Site key",
|
||||||
|
"Site key - Tooltip": "Site key - Tooltip",
|
||||||
|
"Sub type": "Sub type",
|
||||||
|
"Sub type - Tooltip": "Sub type - Tooltip",
|
||||||
|
"Template Code": "Template Code",
|
||||||
|
"Template Code - Tooltip": "Template Code - Tooltip",
|
||||||
|
"Terms of Use": "Terms of Use",
|
||||||
|
"Terms of Use - Tooltip": "Terms of Use - Tooltip",
|
||||||
|
"Test Connection": "Test Connection",
|
||||||
|
"Test Email": "Test Email",
|
||||||
|
"Test Email - Tooltip": "Test Email - Tooltip",
|
||||||
|
"The prefix path of the file - Tooltip": "The prefix path of the file - Tooltip",
|
||||||
|
"Token URL": "Token URL",
|
||||||
|
"Token URL - Tooltip": "Token URL - Tooltip",
|
||||||
|
"Type": "Type",
|
||||||
|
"Type - Tooltip": "Type - Tooltip",
|
||||||
|
"UserInfo URL": "UserInfo URL",
|
||||||
|
"UserInfo URL - Tooltip": "UserInfo URL - Tooltip",
|
||||||
|
"Visible": "Visible",
|
||||||
|
"admin (share)": "admin (share)",
|
||||||
|
"alertType": "alertType"
|
||||||
|
},
|
||||||
|
"record": {
|
||||||
|
"Is Triggered": "Is Triggered"
|
||||||
|
},
|
||||||
|
"resource": {
|
||||||
|
"Application": "Application",
|
||||||
|
"Copy Link": "Copy Link",
|
||||||
|
"File name": "File name",
|
||||||
|
"File size": "File size",
|
||||||
|
"Format": "Format",
|
||||||
|
"Link copied to clipboard successfully": "Link copied to clipboard successfully",
|
||||||
|
"Parent": "Parent",
|
||||||
|
"Tag": "Tag",
|
||||||
|
"Type": "Type",
|
||||||
|
"Upload a file...": "Upload a file...",
|
||||||
|
"User": "User"
|
||||||
|
},
|
||||||
|
"role": {
|
||||||
|
"Edit Role": "Edit Role",
|
||||||
|
"New Role": "New Role",
|
||||||
|
"Sub domains": "Sub domains",
|
||||||
|
"Sub domains - Tooltip": "Sub domains - Tooltip",
|
||||||
|
"Sub roles": "Sub roles",
|
||||||
|
"Sub roles - Tooltip": "Sub roles - Tooltip",
|
||||||
|
"Sub users": "Sub users",
|
||||||
|
"Sub users - Tooltip": "Sub users - Tooltip"
|
||||||
|
},
|
||||||
|
"signup": {
|
||||||
|
"Accept": "Accept",
|
||||||
|
"Agreement": "Agreement",
|
||||||
|
"Confirm": "Confirm",
|
||||||
|
"Decline": "Decline",
|
||||||
|
"Have account?": "Have account?",
|
||||||
|
"Please accept the agreement!": "Please accept the agreement!",
|
||||||
|
"Please click the below button to sign in": "Please click the below button to sign in",
|
||||||
|
"Please confirm your password!": "Please confirm your password!",
|
||||||
|
"Please input the correct ID card number!": "Please input the correct ID card number!",
|
||||||
|
"Please input your Email!": "Please input your Email!",
|
||||||
|
"Please input your ID card number!": "Please input your ID card number!",
|
||||||
|
"Please input your address!": "Please input your address!",
|
||||||
|
"Please input your affiliation!": "Please input your affiliation!",
|
||||||
|
"Please input your display name!": "Please input your display name!",
|
||||||
|
"Please input your first name!": "Please input your first name!",
|
||||||
|
"Please input your last name!": "Please input your last name!",
|
||||||
|
"Please input your phone number!": "Please input your phone number!",
|
||||||
|
"Please input your real name!": "Please input your real name!",
|
||||||
|
"Please select your country code!": "Please select your country code!",
|
||||||
|
"Please select your country/region!": "Please select your country/region!",
|
||||||
|
"Terms of Use": "Terms of Use",
|
||||||
|
"The input is not invoice Tax ID!": "The input is not invoice Tax ID!",
|
||||||
|
"The input is not invoice title!": "The input is not invoice title!",
|
||||||
|
"The input is not valid Email!": "The input is not valid Email!",
|
||||||
|
"The input is not valid Phone!": "The input is not valid Phone!",
|
||||||
|
"Username": "Username",
|
||||||
|
"Username - Tooltip": "Username - Tooltip",
|
||||||
|
"Your account has been created!": "Your account has been created!",
|
||||||
|
"Your confirmed password is inconsistent with the password!": "Your confirmed password is inconsistent with the password!",
|
||||||
|
"sign in now": "sign in now"
|
||||||
|
},
|
||||||
|
"syncer": {
|
||||||
|
"Affiliation table": "Affiliation table",
|
||||||
|
"Affiliation table - Tooltip": "Affiliation table - Tooltip",
|
||||||
|
"Avatar base URL": "Avatar base URL",
|
||||||
|
"Avatar base URL - Tooltip": "Avatar base URL - Tooltip",
|
||||||
|
"Casdoor column": "Casdoor column",
|
||||||
|
"Column name": "Column name",
|
||||||
|
"Column type": "Column type",
|
||||||
|
"Database": "Database",
|
||||||
|
"Database - Tooltip": "Database - Tooltip",
|
||||||
|
"Database type": "Database type",
|
||||||
|
"Database type - Tooltip": "Database type - Tooltip",
|
||||||
|
"Edit Syncer": "Edit Syncer",
|
||||||
|
"Error text": "Error text",
|
||||||
|
"Error text - Tooltip": "Error text - Tooltip",
|
||||||
|
"Is hashed": "Is hashed",
|
||||||
|
"New Syncer": "New Syncer",
|
||||||
|
"Sync interval": "Sync interval",
|
||||||
|
"Sync interval - Tooltip": "Sync interval - Tooltip",
|
||||||
|
"Table": "Table",
|
||||||
|
"Table - Tooltip": "Table - Tooltip",
|
||||||
|
"Table columns": "Table columns",
|
||||||
|
"Table columns - Tooltip": "Table columns - Tooltip",
|
||||||
|
"Table primary key": "Table primary key",
|
||||||
|
"Table primary key - Tooltip": "Table primary key - Tooltip"
|
||||||
|
},
|
||||||
|
"system": {
|
||||||
|
"About Casdoor": "About Casdoor",
|
||||||
|
"An Identity and Access Management (IAM) / Single-Sign-On (SSO) platform with web UI supporting OAuth 2.0, OIDC, SAML and CAS": "An Identity and Access Management (IAM) / Single-Sign-On (SSO) platform with web UI supporting OAuth 2.0, OIDC, SAML and CAS",
|
||||||
|
"CPU Usage": "CPU Usage",
|
||||||
|
"Community": "Community",
|
||||||
|
"Get CPU Usage Failed": "Get CPU Usage Failed",
|
||||||
|
"Get Memory Usage Failed": "Get Memory Usage Failed",
|
||||||
|
"Memory Usage": "Memory Usage",
|
||||||
|
"Official Website": "Official Website",
|
||||||
|
"Unknown Version": "Unknown Version",
|
||||||
|
"Version": "Version"
|
||||||
|
},
|
||||||
|
"theme": {
|
||||||
|
"Blossom": "Blossom",
|
||||||
|
"Border radius": "Border radius",
|
||||||
|
"Compact": "Compact",
|
||||||
|
"Customize theme": "Customize theme",
|
||||||
|
"Dark": "Dark",
|
||||||
|
"Default": "Default",
|
||||||
|
"Document": "Document",
|
||||||
|
"Is compact": "Is compact",
|
||||||
|
"Primary color": "Primary color",
|
||||||
|
"Theme": "Theme",
|
||||||
|
"Theme - Tooltip": "Theme - Tooltip"
|
||||||
|
},
|
||||||
|
"token": {
|
||||||
|
"Access token": "Access token",
|
||||||
|
"Authorization code": "Authorization code",
|
||||||
|
"Edit Token": "Edit Token",
|
||||||
|
"Expires in": "Expires in",
|
||||||
|
"New Token": "New Token",
|
||||||
|
"Scope": "Scope",
|
||||||
|
"Token type": "Token type"
|
||||||
|
},
|
||||||
|
"user": {
|
||||||
|
"\" + destType + \" reset": "\" + destType + \" reset",
|
||||||
|
"3rd-party logins": "3rd-party logins",
|
||||||
|
"3rd-party logins - Tooltip": "3rd-party logins - Tooltip",
|
||||||
|
"Address": "Address",
|
||||||
|
"Address - Tooltip": "Address - Tooltip",
|
||||||
|
"Affiliation": "Affiliation",
|
||||||
|
"Affiliation - Tooltip": "Affiliation - Tooltip",
|
||||||
|
"Bio": "Bio",
|
||||||
|
"Bio - Tooltip": "Bio - Tooltip",
|
||||||
|
"Cancel": "Cancel",
|
||||||
|
"Captcha Verify Failed": "Captcha Verify Failed",
|
||||||
|
"Captcha Verify Success": "Captcha Verify Success",
|
||||||
|
"Code Sent": "Code Sent",
|
||||||
|
"Country code": "Country code",
|
||||||
|
"Country/Region": "Country/Region",
|
||||||
|
"Country/Region - Tooltip": "Country/Region - Tooltip",
|
||||||
|
"Edit User": "Edit User",
|
||||||
|
"Email cannot be empty": "Email cannot be empty",
|
||||||
|
"Empty input!": "Empty input!",
|
||||||
|
"Homepage": "Homepage",
|
||||||
|
"Homepage - Tooltip": "Homepage - Tooltip",
|
||||||
|
"ID card": "ID card",
|
||||||
|
"Input your email": "Input your email",
|
||||||
|
"Input your phone number": "Input your phone number",
|
||||||
|
"Is admin": "Is admin",
|
||||||
|
"Is admin - Tooltip": "Is admin - Tooltip",
|
||||||
|
"Is deleted": "Is deleted",
|
||||||
|
"Is deleted - Tooltip": "Is deleted - Tooltip",
|
||||||
|
"Is forbidden": "Is forbidden",
|
||||||
|
"Is forbidden - Tooltip": "Is forbidden - Tooltip",
|
||||||
|
"Is global admin": "Is global admin",
|
||||||
|
"Is global admin - Tooltip": "Is global admin - Tooltip",
|
||||||
|
"Keys": "Keys",
|
||||||
|
"Link": "Link",
|
||||||
|
"Location": "Location",
|
||||||
|
"Location - Tooltip": "Location - Tooltip",
|
||||||
|
"Managed accounts": "Managed accounts",
|
||||||
|
"Modify password...": "Modify password...",
|
||||||
|
"New Email": "New Email",
|
||||||
|
"New Password": "New Password",
|
||||||
|
"New User": "New User",
|
||||||
|
"New phone": "New phone",
|
||||||
|
"OK": "OK",
|
||||||
|
"Old Password": "Old Password",
|
||||||
|
"Password": "Password",
|
||||||
|
"Password Set": "Password Set",
|
||||||
|
"Phone cannot be empty": "Phone cannot be empty",
|
||||||
|
"Please select avatar from resources": "Please select avatar from resources",
|
||||||
|
"Properties": "Properties",
|
||||||
|
"Properties - Tooltip": "Properties - Tooltip",
|
||||||
|
"Re-enter New": "Re-enter New",
|
||||||
|
"Reset Email...": "Reset Email...",
|
||||||
|
"Reset Phone...": "Reset Phone...",
|
||||||
|
"Select a photo...": "Select a photo...",
|
||||||
|
"Set Password": "Set Password",
|
||||||
|
"Set new profile picture": "Set new profile picture",
|
||||||
|
"Set password...": "Set password...",
|
||||||
|
"Tag": "Tag",
|
||||||
|
"Tag - Tooltip": "Tag - Tooltip",
|
||||||
|
"Title": "Title",
|
||||||
|
"Title - Tooltip": "Title - Tooltip",
|
||||||
|
"Two passwords you typed do not match.": "Two passwords you typed do not match.",
|
||||||
|
"Unlink": "Unlink",
|
||||||
|
"Upload (.xlsx)": "Upload (.xlsx)",
|
||||||
|
"Upload a photo": "Upload a photo",
|
||||||
|
"Values": "Values",
|
||||||
|
"WebAuthn credentials": "WebAuthn credentials",
|
||||||
|
"input password": "input password"
|
||||||
|
},
|
||||||
|
"webhook": {
|
||||||
|
"Content type": "Content type",
|
||||||
|
"Content type - Tooltip": "Content type - Tooltip",
|
||||||
|
"Edit Webhook": "Edit Webhook",
|
||||||
|
"Events": "Events",
|
||||||
|
"Events - Tooltip": "Events - Tooltip",
|
||||||
|
"Headers": "Headers",
|
||||||
|
"Headers - Tooltip": "Headers - Tooltip",
|
||||||
|
"Is user extended": "Is user extended",
|
||||||
|
"Is user extended - Tooltip": "Is user extended - Tooltip",
|
||||||
|
"Method": "Method",
|
||||||
|
"Method - Tooltip": "Method - Tooltip",
|
||||||
|
"Name": "Name",
|
||||||
|
"New Webhook": "New Webhook",
|
||||||
|
"URL": "URL",
|
||||||
|
"URL - Tooltip": "URL - Tooltip",
|
||||||
|
"Value": "Value"
|
||||||
|
}
|
||||||
|
}
|
@ -181,6 +181,8 @@
|
|||||||
"First name": "名字",
|
"First name": "名字",
|
||||||
"Forget URL": "忘记密码URL",
|
"Forget URL": "忘记密码URL",
|
||||||
"Forget URL - Tooltip": "忘记密码URL",
|
"Forget URL - Tooltip": "忘记密码URL",
|
||||||
|
"Found some texts still not translated? Please help us translate at": "发现有些文字尚未翻译?请移步这里帮我们翻译:",
|
||||||
|
"Go to writable demo site?": "跳转至可写演示站点?",
|
||||||
"Home": "首页",
|
"Home": "首页",
|
||||||
"Home - Tooltip": "应用的首页",
|
"Home - Tooltip": "应用的首页",
|
||||||
"ID": "ID",
|
"ID": "ID",
|
||||||
@ -218,8 +220,6 @@
|
|||||||
"Permissions - Tooltip": "权限",
|
"Permissions - Tooltip": "权限",
|
||||||
"Phone": "手机号",
|
"Phone": "手机号",
|
||||||
"Phone - Tooltip": "手机号",
|
"Phone - Tooltip": "手机号",
|
||||||
"Phone prefix": "手机号前缀",
|
|
||||||
"Phone prefix - Tooltip": "移动电话号码前缀,用于区分国家或地区",
|
|
||||||
"Preview": "预览",
|
"Preview": "预览",
|
||||||
"Preview - Tooltip": "预览",
|
"Preview - Tooltip": "预览",
|
||||||
"Products": "商品",
|
"Products": "商品",
|
||||||
@ -251,10 +251,13 @@
|
|||||||
"Successfully added": "添加成功",
|
"Successfully added": "添加成功",
|
||||||
"Successfully deleted": "删除成功",
|
"Successfully deleted": "删除成功",
|
||||||
"Successfully saved": "保存成功",
|
"Successfully saved": "保存成功",
|
||||||
|
"Supported country code": "支持的国家代码",
|
||||||
|
"Supported country code - Tooltip": "支持发送短信的国家 - Tooltip",
|
||||||
"Swagger": "API文档",
|
"Swagger": "API文档",
|
||||||
"Sync": "同步",
|
"Sync": "同步",
|
||||||
"Syncers": "同步器",
|
"Syncers": "同步器",
|
||||||
"SysInfo": "系统信息",
|
"SysInfo": "系统信息",
|
||||||
|
"This is a read-only demo site!": "这是一个只读演示站点!",
|
||||||
"Timestamp": "时间戳",
|
"Timestamp": "时间戳",
|
||||||
"Tokens": "令牌",
|
"Tokens": "令牌",
|
||||||
"URL": "链接",
|
"URL": "链接",
|
||||||
@ -309,10 +312,10 @@
|
|||||||
"Or sign in with another account": "或者,登录其他账号",
|
"Or sign in with another account": "或者,登录其他账号",
|
||||||
"Password": "密码",
|
"Password": "密码",
|
||||||
"Password - Tooltip": "密码",
|
"Password - Tooltip": "密码",
|
||||||
|
"Please input your Email or Phone!": "请输入您的Email或手机号!",
|
||||||
"Please input your code!": "请输入您的验证码!",
|
"Please input your code!": "请输入您的验证码!",
|
||||||
"Please input your password!": "请输入您的密码!",
|
"Please input your password!": "请输入您的密码!",
|
||||||
"Please input your password, at least 6 characters!": "请输入您的密码,不少于6位",
|
"Please input your password, at least 6 characters!": "请输入您的密码,不少于6位",
|
||||||
"Please input your username, Email or phone!": "请输入您的用户名、Email或手机号!",
|
|
||||||
"Redirecting, please wait.": "正在跳转, 请稍等.",
|
"Redirecting, please wait.": "正在跳转, 请稍等.",
|
||||||
"Sign In": "登录",
|
"Sign In": "登录",
|
||||||
"Sign in with WebAuthn": "WebAuthn登录",
|
"Sign in with WebAuthn": "WebAuthn登录",
|
||||||
@ -638,6 +641,7 @@
|
|||||||
"Please input your last name!": "请输入您的姓氏!",
|
"Please input your last name!": "请输入您的姓氏!",
|
||||||
"Please input your phone number!": "请输入您的手机号码!",
|
"Please input your phone number!": "请输入您的手机号码!",
|
||||||
"Please input your real name!": "请输入您的姓名!",
|
"Please input your real name!": "请输入您的姓名!",
|
||||||
|
"Please select your country code!": "请选择国家代码!",
|
||||||
"Please select your country/region!": "请选择您的国家/地区",
|
"Please select your country/region!": "请选择您的国家/地区",
|
||||||
"Terms of Use": "《用户协议》",
|
"Terms of Use": "《用户协议》",
|
||||||
"The input is not invoice Tax ID!": "您输入的纳税人识别号有误!",
|
"The input is not invoice Tax ID!": "您输入的纳税人识别号有误!",
|
||||||
@ -724,6 +728,7 @@
|
|||||||
"Captcha Verify Failed": "验证码校验失败",
|
"Captcha Verify Failed": "验证码校验失败",
|
||||||
"Captcha Verify Success": "验证码校验成功",
|
"Captcha Verify Success": "验证码校验成功",
|
||||||
"Code Sent": "验证码已发送",
|
"Code Sent": "验证码已发送",
|
||||||
|
"Country code": "国家代码",
|
||||||
"Country/Region": "国家/地区",
|
"Country/Region": "国家/地区",
|
||||||
"Country/Region - Tooltip": "国家/地区",
|
"Country/Region - Tooltip": "国家/地区",
|
||||||
"Edit User": "编辑用户",
|
"Edit User": "编辑用户",
|
||||||
|
@ -7829,6 +7829,11 @@ levn@~0.3.0:
|
|||||||
prelude-ls "~1.1.2"
|
prelude-ls "~1.1.2"
|
||||||
type-check "~0.3.2"
|
type-check "~0.3.2"
|
||||||
|
|
||||||
|
libphonenumber-js@^1.10.19:
|
||||||
|
version "1.10.20"
|
||||||
|
resolved "https://registry.yarnpkg.com/libphonenumber-js/-/libphonenumber-js-1.10.20.tgz#03c310adf83381eeceb4bd6830442fd14e64964d"
|
||||||
|
integrity sha512-kQovlKNdLcVzerbTPmJ+Fx4R+7/pYXmPDIllHjg7IxL4X6MsMG7jaT5opfYrBok0uqkByVif//JUR8e11l/V7w==
|
||||||
|
|
||||||
lilconfig@2.0.5:
|
lilconfig@2.0.5:
|
||||||
version "2.0.5"
|
version "2.0.5"
|
||||||
resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.0.5.tgz#19e57fd06ccc3848fd1891655b5a447092225b25"
|
resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.0.5.tgz#19e57fd06ccc3848fd1891655b5a447092225b25"
|
||||||
|
Reference in New Issue
Block a user