mirror of
https://github.com/casdoor/casdoor.git
synced 2025-08-07 21:37:51 +08:00
Compare commits
21 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
dd939b5c7e | ||
![]() |
eeba21bf0d | ||
![]() |
5e47406e09 | ||
![]() |
fd883a3211 | ||
![]() |
312412ffe4 | ||
![]() |
295a69c5f7 | ||
![]() |
a8a8f39963 | ||
![]() |
90f8eba02d | ||
![]() |
2cca1c9136 | ||
![]() |
c2eebd61a1 | ||
![]() |
59566f61d7 | ||
![]() |
7e4c9c91cd | ||
![]() |
430ee616db | ||
![]() |
2e3a323528 | ||
![]() |
09e8408a3d | ||
![]() |
2998bbf4b9 | ||
![]() |
404382f2e0 | ||
![]() |
71db1f62a9 | ||
![]() |
07dc6bf7cd | ||
![]() |
2de3f6772d | ||
![]() |
3f623570fd |
@@ -129,8 +129,8 @@ func (c *ApiController) Signup() {
|
||||
|
||||
if application.IsSignupItemVisible("Email") && application.GetSignupItemRule("Email") != "No verification" && form.Email != "" {
|
||||
checkResult := object.CheckVerificationCode(form.Email, form.EmailCode, c.GetAcceptLanguage())
|
||||
if len(checkResult) != 0 {
|
||||
c.ResponseError(c.T("account:Email: %s"), checkResult)
|
||||
if checkResult.Code != object.VerificationSuccess {
|
||||
c.ResponseError(checkResult.Msg)
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -139,8 +139,8 @@ func (c *ApiController) Signup() {
|
||||
if application.IsSignupItemVisible("Phone") && form.Phone != "" {
|
||||
checkPhone, _ = util.GetE164Number(form.Phone, form.CountryCode)
|
||||
checkResult := object.CheckVerificationCode(checkPhone, form.PhoneCode, c.GetAcceptLanguage())
|
||||
if len(checkResult) != 0 {
|
||||
c.ResponseError(c.T("account:Phone: %s"), checkResult)
|
||||
if checkResult.Code != object.VerificationSuccess {
|
||||
c.ResponseError(checkResult.Msg)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@@ -451,7 +451,7 @@ func (c *ApiController) Login() {
|
||||
}
|
||||
|
||||
properties := map[string]string{}
|
||||
properties["no"] = strconv.Itoa(len(object.GetUsers(application.Organization)) + 2)
|
||||
properties["no"] = strconv.Itoa(object.GetUserCount(application.Organization, "", "") + 2)
|
||||
initScore, err := getInitScore(organization)
|
||||
if err != nil {
|
||||
c.ResponseError(fmt.Errorf(c.T("account:Get init score failed, error: %w"), err).Error())
|
||||
|
@@ -21,14 +21,6 @@ import (
|
||||
"github.com/casdoor/casdoor/util"
|
||||
)
|
||||
|
||||
type LdapServer struct {
|
||||
Host string `json:"host"`
|
||||
Port int `json:"port"`
|
||||
Admin string `json:"admin"`
|
||||
Passwd string `json:"passwd"`
|
||||
BaseDn string `json:"baseDn"`
|
||||
}
|
||||
|
||||
type LdapResp struct {
|
||||
// Groups []LdapRespGroup `json:"groups"`
|
||||
Users []object.LdapRespUser `json:"users"`
|
||||
@@ -44,21 +36,17 @@ type LdapSyncResp struct {
|
||||
Failed []object.LdapRespUser `json:"failed"`
|
||||
}
|
||||
|
||||
// GetLdapUser
|
||||
// GetLdapUsers
|
||||
// @Tag Account API
|
||||
// @Title GetLdapser
|
||||
// @router /get-ldap-user [post]
|
||||
func (c *ApiController) GetLdapUser() {
|
||||
ldapServer := LdapServer{}
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &ldapServer)
|
||||
if err != nil || util.IsStringsEmpty(ldapServer.Host, ldapServer.Admin, ldapServer.Passwd, ldapServer.BaseDn) {
|
||||
c.ResponseError(c.T("general:Missing parameter"))
|
||||
return
|
||||
}
|
||||
// @router /get-ldap-users [get]
|
||||
func (c *ApiController) GetLdapUsers() {
|
||||
id := c.Input().Get("id")
|
||||
|
||||
var resp LdapResp
|
||||
_, ldapId := util.GetOwnerAndNameFromId(id)
|
||||
ldapServer := object.GetLdap(ldapId)
|
||||
|
||||
conn, err := object.GetLdapConn(ldapServer.Host, ldapServer.Port, ldapServer.Admin, ldapServer.Passwd)
|
||||
conn, err := ldapServer.GetLdapConn()
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
@@ -83,6 +71,8 @@ func (c *ApiController) GetLdapUser() {
|
||||
return
|
||||
}
|
||||
|
||||
var resp LdapResp
|
||||
uuids := make([]string, len(users))
|
||||
for _, user := range users {
|
||||
resp.Users = append(resp.Users, object.LdapRespUser{
|
||||
UidNumber: user.UidNumber,
|
||||
@@ -95,9 +85,12 @@ func (c *ApiController) GetLdapUser() {
|
||||
Phone: util.GetMaxLenStr(user.TelephoneNumber, user.Mobile, user.MobileTelephoneNumber),
|
||||
Address: util.GetMaxLenStr(user.RegisteredAddress, user.PostalAddress),
|
||||
})
|
||||
uuids = append(uuids, user.Uuid)
|
||||
}
|
||||
|
||||
c.ResponseOk(resp)
|
||||
existUuids := object.CheckLdapUuidExist(ldapServer.Owner, uuids)
|
||||
|
||||
c.ResponseOk(resp, existUuids)
|
||||
}
|
||||
|
||||
// GetLdaps
|
||||
@@ -134,7 +127,7 @@ func (c *ApiController) AddLdap() {
|
||||
var ldap object.Ldap
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &ldap)
|
||||
if err != nil {
|
||||
c.ResponseError(c.T("general:Missing parameter"))
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
@@ -150,14 +143,14 @@ func (c *ApiController) AddLdap() {
|
||||
|
||||
affected := object.AddLdap(&ldap)
|
||||
resp := wrapActionResponse(affected)
|
||||
if affected {
|
||||
resp.Data2 = ldap
|
||||
}
|
||||
resp.Data2 = ldap
|
||||
|
||||
if ldap.AutoSync != 0 {
|
||||
object.GetLdapAutoSynchronizer().StartAutoSync(ldap.Id)
|
||||
}
|
||||
|
||||
c.ResponseOk(resp)
|
||||
c.Data["json"] = resp
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// UpdateLdap
|
||||
@@ -174,17 +167,15 @@ func (c *ApiController) UpdateLdap() {
|
||||
|
||||
prevLdap := object.GetLdap(ldap.Id)
|
||||
affected := object.UpdateLdap(&ldap)
|
||||
resp := wrapActionResponse(affected)
|
||||
if affected {
|
||||
resp.Data2 = ldap
|
||||
}
|
||||
|
||||
if ldap.AutoSync != 0 {
|
||||
object.GetLdapAutoSynchronizer().StartAutoSync(ldap.Id)
|
||||
} else if ldap.AutoSync == 0 && prevLdap.AutoSync != 0 {
|
||||
object.GetLdapAutoSynchronizer().StopAutoSync(ldap.Id)
|
||||
}
|
||||
|
||||
c.ResponseOk(resp)
|
||||
c.Data["json"] = wrapActionResponse(affected)
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// DeleteLdap
|
||||
@@ -199,8 +190,12 @@ func (c *ApiController) DeleteLdap() {
|
||||
return
|
||||
}
|
||||
|
||||
affected := object.DeleteLdap(&ldap)
|
||||
|
||||
object.GetLdapAutoSynchronizer().StopAutoSync(ldap.Id)
|
||||
c.ResponseOk(wrapActionResponse(object.DeleteLdap(&ldap)))
|
||||
|
||||
c.Data["json"] = wrapActionResponse(affected)
|
||||
c.ServeJSON()
|
||||
}
|
||||
|
||||
// SyncLdapUsers
|
||||
@@ -226,20 +221,3 @@ func (c *ApiController) SyncLdapUsers() {
|
||||
Failed: *failed,
|
||||
})
|
||||
}
|
||||
|
||||
// CheckLdapUsersExist
|
||||
// @Tag Account API
|
||||
// @Title CheckLdapUserExist
|
||||
// @router /check-ldap-users-exist [post]
|
||||
func (c *ApiController) CheckLdapUsersExist() {
|
||||
owner := c.Input().Get("owner")
|
||||
var uuids []string
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &uuids)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
exist := object.CheckLdapUuidExist(owner, uuids)
|
||||
c.ResponseOk(exist)
|
||||
}
|
||||
|
@@ -15,16 +15,9 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"github.com/casdoor/casdoor/object"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
)
|
||||
|
||||
type SystemInfo struct {
|
||||
MemoryUsed uint64 `json:"memory_used"`
|
||||
MemoryTotal uint64 `json:"memory_total"`
|
||||
CpuUsage []float64 `json:"cpu_usage"`
|
||||
}
|
||||
|
||||
// GetSystemInfo
|
||||
// @Title GetSystemInfo
|
||||
// @Tag System API
|
||||
@@ -33,50 +26,32 @@ type SystemInfo struct {
|
||||
// @Success 200 {object} object.SystemInfo The Response object
|
||||
// @router /get-system-info [get]
|
||||
func (c *ApiController) GetSystemInfo() {
|
||||
id := c.GetString("id")
|
||||
if id == "" {
|
||||
id = c.GetSessionUsername()
|
||||
}
|
||||
|
||||
user := object.GetUser(id)
|
||||
if user == nil || !user.IsGlobalAdmin {
|
||||
c.ResponseError(c.T("auth:Unauthorized operation"))
|
||||
_, ok := c.RequireAdmin()
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
cpuUsage, err := util.GetCpuUsage()
|
||||
systemInfo, err := util.GetSystemInfo()
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
memoryUsed, memoryTotal, err := util.GetMemoryUsage()
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = SystemInfo{
|
||||
CpuUsage: cpuUsage,
|
||||
MemoryUsed: memoryUsed,
|
||||
MemoryTotal: memoryTotal,
|
||||
}
|
||||
c.ServeJSON()
|
||||
c.ResponseOk(systemInfo)
|
||||
}
|
||||
|
||||
// GitRepoVersion
|
||||
// @Title GitRepoVersion
|
||||
// GetVersionInfo
|
||||
// @Title GetVersionInfo
|
||||
// @Tag System API
|
||||
// @Description get local github repo's latest release version info
|
||||
// @Success 200 {string} local latest version hash of casdoor
|
||||
// @router /get-release [get]
|
||||
func (c *ApiController) GitRepoVersion() {
|
||||
version, err := util.GetGitRepoVersion()
|
||||
// @Description get local git repo's latest release version info
|
||||
// @Success 200 {string} local latest version hash of Casdoor
|
||||
// @router /get-version-info [get]
|
||||
func (c *ApiController) GetVersionInfo() {
|
||||
versionInfo, err := util.GetVersionInfo()
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.Data["json"] = version
|
||||
c.ServeJSON()
|
||||
c.ResponseOk(versionInfo)
|
||||
}
|
||||
|
@@ -224,8 +224,8 @@ func (c *ApiController) ResetEmailOrPhone() {
|
||||
return
|
||||
}
|
||||
}
|
||||
if msg := object.CheckVerificationCode(checkDest, code, c.GetAcceptLanguage()); len(msg) != 0 {
|
||||
c.ResponseError(msg)
|
||||
if result := object.CheckVerificationCode(checkDest, code, c.GetAcceptLanguage()); result.Code != object.VerificationSuccess {
|
||||
c.ResponseError(result.Msg)
|
||||
return
|
||||
}
|
||||
|
||||
|
2
go.mod
2
go.mod
@@ -18,6 +18,7 @@ require (
|
||||
github.com/dchest/captcha v0.0.0-20200903113550-03f5f0333e1f
|
||||
github.com/denisenkom/go-mssqldb v0.9.0
|
||||
github.com/forestmgy/ldapserver v1.1.0
|
||||
github.com/go-git/go-git/v5 v5.6.0
|
||||
github.com/go-ldap/ldap/v3 v3.3.0
|
||||
github.com/go-mysql-org/go-mysql v1.7.0
|
||||
github.com/go-pay/gopay v1.5.72
|
||||
@@ -25,7 +26,6 @@ require (
|
||||
github.com/go-webauthn/webauthn v0.8.2
|
||||
github.com/golang-jwt/jwt/v4 v4.5.0
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
github.com/google/go-cmp v0.5.8 // indirect
|
||||
github.com/google/uuid v1.3.0
|
||||
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 // indirect
|
||||
github.com/lestrrat-go/jwx v1.2.21
|
||||
|
81
go.sum
81
go.sum
@@ -60,9 +60,15 @@ github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible h1
|
||||
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
|
||||
github.com/Masterminds/squirrel v1.5.3 h1:YPpoceAcxuzIljlr5iWpNKaql7hLeG1KLSrhvdHpkZc=
|
||||
github.com/Masterminds/squirrel v1.5.3/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA400rg+riTZj10=
|
||||
github.com/Microsoft/go-winio v0.5.2 h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VMrpA=
|
||||
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20221026131551-cf6655e29de4 h1:ra2OtmuW0AE5csawV4YXMNGNQQXvLRps3z2Z59OPO+I=
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20221026131551-cf6655e29de4/go.mod h1:UBYPn8k0D56RtnR8RFQMjmh4KrZzWJ5o7Z9SYjossQ8=
|
||||
github.com/RobotsAndPencils/go-saml v0.0.0-20170520135329-fb13cb52a46b h1:EgJ6N2S0h1WfFIjU5/VVHWbMSVYXAluop97Qxpr/lfQ=
|
||||
github.com/RobotsAndPencils/go-saml v0.0.0-20170520135329-fb13cb52a46b/go.mod h1:3SAoF0F5EbcOuBD5WT9nYkbIJieBS84cUQXADbXeBsU=
|
||||
github.com/acomagu/bufpipe v1.0.3 h1:fxAGrHZTgQ9w5QqVItgzwj235/uYZYgbXitB+dLupOk=
|
||||
github.com/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
@@ -76,7 +82,11 @@ github.com/aliyun/alibaba-cloud-sdk-go v1.62.188 h1:8lIVcOlHW+fKCGMEf6nuGTTEFOt/
|
||||
github.com/aliyun/alibaba-cloud-sdk-go v1.62.188/go.mod h1:Api2AkmMgGaSUAhmk76oaFObkoeCPc/bKAqcyplPODs=
|
||||
github.com/aliyun/aliyun-oss-go-sdk v2.2.2+incompatible h1:9gWa46nstkJ9miBReJcN8Gq34cBFbzSpQZVVT9N09TM=
|
||||
github.com/aliyun/aliyun-oss-go-sdk v2.2.2+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
|
||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
|
||||
github.com/avast/retry-go v3.0.0+incompatible/go.mod h1:XtSnn+n/sHqQIpZ10K1qAevBhOOCWBLXXy3hyiqqBrY=
|
||||
github.com/aws/aws-sdk-go v1.44.4 h1:ePN0CVJMdiz2vYUcJH96eyxRrtKGSDMgyhP6rah2OgE=
|
||||
github.com/aws/aws-sdk-go v1.44.4/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
|
||||
@@ -95,6 +105,7 @@ github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+Ce
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/bradfitz/gomemcache v0.0.0-20180710155616-bc664df96737/go.mod h1:PmM6Mmwb0LSuEubjR8N7PtNe1KxZLtOUHtbeikc5h60=
|
||||
github.com/bwesterb/go-ristretto v1.2.0/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
|
||||
github.com/casbin/casbin v1.7.0 h1:PuzlE8w0JBg/DhIqnkF1Dewf3z+qmUZMVN07PonvVUQ=
|
||||
github.com/casbin/casbin v1.7.0/go.mod h1:c67qKN6Oum3UF5Q1+BByfFxkwKvhwW57ITjqwtzR1KE=
|
||||
github.com/casbin/casbin/v2 v2.1.0/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
|
||||
@@ -118,6 +129,8 @@ github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWR
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cloudflare/circl v1.1.0 h1:bZgT/A+cikZnKIwn7xL2OBj012Bmvho/o6RpRvv3GKY=
|
||||
github.com/cloudflare/circl v1.1.0/go.mod h1:prBCrKB9DV4poKZY1l9zBXg2QJY7mvgRvtMxxK7fi4I=
|
||||
github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58/go.mod h1:EOBUe0h4xcZ5GoxqC5SDxFQ8gwyZPKQoEzownBlhI80=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
||||
@@ -154,6 +167,8 @@ github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712/go.mod h1:YO35OhQPt
|
||||
github.com/elastic/go-elasticsearch/v6 v6.8.5/go.mod h1:UwaDJsD3rWLM5rKNFzv9hgox93HoX8utj1kxD9aFUcI=
|
||||
github.com/elazarl/go-bindata-assetfs v1.0.0 h1:G/bYguwHIzWq9ZoyUQqrjTmJbbYn3j3CKKpKinvZLFk=
|
||||
github.com/elazarl/go-bindata-assetfs v1.0.0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4=
|
||||
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
|
||||
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
@@ -167,8 +182,19 @@ github.com/fxamacker/cbor/v2 v2.4.0 h1:ri0ArlOR+5XunOP8CRUowT0pSJOwhW098ZCUyskZD
|
||||
github.com/fxamacker/cbor/v2 v2.4.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/glendc/gopher-json v0.0.0-20170414221815-dc4743023d0c/go.mod h1:Gja1A+xZ9BoviGJNA2E9vFkPjjsl+CoJxSXiQM1UXtw=
|
||||
github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY=
|
||||
github.com/gliderlabs/ssh v0.3.5/go.mod h1:8XB4KraRrX39qHhT6yxPsHedjA08I/uBVwj4xC+/+z4=
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.1 h1:pDbRAunXzIUXfx4CB2QJFv5IuPiuoW+sWvr/Us009o8=
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.1/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
|
||||
github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4=
|
||||
github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E=
|
||||
github.com/go-git/go-billy/v5 v5.3.1/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
|
||||
github.com/go-git/go-billy/v5 v5.4.0 h1:Vaw7LaSTRJOUric7pe4vnzBSgyuf2KrLsu2Y4ZpQBDE=
|
||||
github.com/go-git/go-billy/v5 v5.4.0/go.mod h1:vjbugF6Fz7JIflbVpl1hJsGjSHNltrSw45YK/ukIvQg=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.3.1 h1:y5z6dd3qi8Hl+stezc8p3JxDkoTRqMAlKnXHuzrfjTQ=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.3.1/go.mod h1:8LHG1a3SRW71ettAD/jW13h8c6AqjVSeL11RAdgaqpo=
|
||||
github.com/go-git/go-git/v5 v5.6.0 h1:JvBdYfcttd+0kdpuWO7KTu0FYgCf5W0t5VwkWGobaa4=
|
||||
github.com/go-git/go-git/v5 v5.6.0/go.mod h1:6nmJ0tJ3N4noMV1Omv7rC5FG3/o8Cm51TB4CJp7mRmE=
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
@@ -258,8 +284,8 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
||||
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
|
||||
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-tpm v0.1.2-0.20190725015402-ae6dd98980d4/go.mod h1:H9HbmUG2YgV/PHITkO7p6wxEEj/v5nlsVWIwumwH2NI=
|
||||
github.com/google/go-tpm v0.3.0/go.mod h1:iVLWvrPp/bHeEkxTFi9WG6K9w0iy2yIszHwZGHPbzAw=
|
||||
github.com/google/go-tpm v0.3.3 h1:P/ZFNBZYXRxc+z7i5uyd8VP7MaDteuLZInzrH2idRGo=
|
||||
@@ -305,9 +331,14 @@ github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T
|
||||
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk=
|
||||
github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/jarcoal/httpmock v0.0.0-20180424175123-9c70cfe4a1da h1:FjHUJJ7oBW4G/9j1KzlHaXL09LyMVM9rupS39lncbXk=
|
||||
github.com/jarcoal/httpmock v0.0.0-20180424175123-9c70cfe4a1da/go.mod h1:ks+b9deReOc7jgqp+e7LuFiCBH6Rm5hL32cLcEAArb4=
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
|
||||
github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
|
||||
github.com/jinzhu/configor v1.2.1 h1:OKk9dsR8i6HPOCZR8BcMtcEImAFjIhbJFZNyn5GCZko=
|
||||
github.com/jinzhu/configor v1.2.1/go.mod h1:nX89/MOmDba7ZX7GCyU/VIaQ2Ar2aizBl2d3JLF/rDc=
|
||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||
@@ -333,6 +364,8 @@ github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 h1:iQTw/8FWTuc7uia
|
||||
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8=
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
|
||||
github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
|
||||
github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
@@ -376,6 +409,8 @@ github.com/markbates/going v1.0.0 h1:DQw0ZP7NbNlFGcKbcE/IVSOAFzScxRtLpd0rLMzLhq0
|
||||
github.com/markbates/going v1.0.0/go.mod h1:I6mnB4BPnEeqo85ynXIx1ZFLLbtiLHNXVgWeFO9OGOA=
|
||||
github.com/markbates/goth v1.75.2 h1:C7KloBMMk50JyXaHhzfqWYLW6+bDcSVIvUGHXneLWro=
|
||||
github.com/markbates/goth v1.75.2/go.mod h1:X6xdNgpapSENS0O35iTBBcMHoJDQDfI9bJl+APCkYMc=
|
||||
github.com/matryer/is v1.2.0 h1:92UTHpy8CDwaJ08GqLDzhhuixiBUUD1p3AU6PHddz4A=
|
||||
github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA=
|
||||
github.com/mattermost/xml-roundtrip-validator v0.0.0-20201208211235-fe770d50d911 h1:erppMjjp69Rertg1zlgRbLJH1u+eCmRPxKjMZ5I8/Ro=
|
||||
github.com/mattermost/xml-roundtrip-validator v0.0.0-20201208211235-fe770d50d911/go.mod h1:qccnGMcpgwcNaBnxqpJpWWUiPNr5H3O8eDgGV9gT5To=
|
||||
github.com/mattn/go-ieproxy v0.0.1 h1:qiyop7gCflfhwCzGyeT0gro3sF9AIg9HU98JORTkqfI=
|
||||
@@ -392,6 +427,7 @@ github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrk
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/mmcloughlin/avo v0.5.0/go.mod h1:ChHFdoV7ql95Wi7vuq2YT1bwCJqiWdZrQ1im3VujLYM=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
@@ -428,6 +464,8 @@ github.com/pingcap/log v0.0.0-20210625125904-98ed8e2eb1c7 h1:k2BbABz9+TNpYRwsCCF
|
||||
github.com/pingcap/log v0.0.0-20210625125904-98ed8e2eb1c7/go.mod h1:8AanEdAHATuRurdGxZXBz0At+9avep+ub7U1AGYLIMM=
|
||||
github.com/pingcap/tidb/parser v0.0.0-20221126021158-6b02a5d8ba7d h1:1DyyRrgYeNjqPkgjrdEsaIbX+kHpuTTk5ZOCtrcRFcQ=
|
||||
github.com/pingcap/tidb/parser v0.0.0-20221126021158-6b02a5d8ba7d/go.mod h1:ElJiub4lRy6UZDb+0JHDkGEdr6aOli+ykhyej7VCLoI=
|
||||
github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4=
|
||||
github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI=
|
||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
@@ -479,6 +517,8 @@ github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
|
||||
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
||||
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
|
||||
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||
github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644 h1:X+yvsM2yrEktyI+b2qND5gpH8YhURn0k8OCaeRnkINo=
|
||||
github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644/go.mod h1:nkxAfR/5quYxwPZhyDxgasBMnRtBZd0FCEpawpjMUFg=
|
||||
github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI=
|
||||
@@ -496,6 +536,9 @@ github.com/siddontang/goredis v0.0.0-20150324035039-760763f78400/go.mod h1:DDcKz
|
||||
github.com/siddontang/rdb v0.0.0-20150307021120-fc89ed2e418d/go.mod h1:AMEsy7v5z92TR1JKMkLLoaOQk++LVnOKL3ScbJ8GNGA=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/skeema/knownhosts v1.1.0 h1:Wvr9V0MxhjRbl3f9nMnKnFfiWTJmtECJ9Njkea3ysW0=
|
||||
github.com/skeema/knownhosts v1.1.0/go.mod h1:sKFq3RD6/TKZkSWn8boUbDC7Qkgcv+8XXijpFO6roag=
|
||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0=
|
||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
@@ -553,6 +596,8 @@ github.com/volcengine/volc-sdk-golang v1.0.19/go.mod h1:+GGi447k4p1I5PNdbpG2GLaF
|
||||
github.com/wendal/errors v0.0.0-20181209125328-7f31f4b264ec/go.mod h1:Q12BUT7DqIlHRmgv3RskH+UCM/4eqVMgI0EMmlSpAXc=
|
||||
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
|
||||
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
|
||||
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
|
||||
github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
|
||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||
github.com/xorm-io/builder v0.3.13 h1:J4oZxt4Gjgm/Si9iKazfzYwHB/ijEOD9EHInyjOSX+M=
|
||||
@@ -592,6 +637,7 @@ go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
go.uber.org/zap v1.18.1 h1:CSUJ2mjFszzEWt4CdKISEuChVIXGBn3lAPwkRGyVrc4=
|
||||
go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI=
|
||||
golang.org/x/arch v0.1.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
@@ -609,6 +655,11 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y
|
||||
golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220208233918-bba287dce954/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220826181053-bd7e27e6170d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
|
||||
golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
|
||||
golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc=
|
||||
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
|
||||
golang.org/x/exp v0.0.0-20181106170214-d68db9428509/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
@@ -644,8 +695,9 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I=
|
||||
golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@@ -686,6 +738,9 @@ golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qx
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
||||
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
|
||||
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
|
||||
golang.org/x/net v0.6.0 h1:L4ZwwTvKW9gr0ZMS1yrHD9GZhIuVjOBBnaKH+SPQK0Q=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
@@ -751,22 +806,34 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201126233918-771906719818/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210629170331-7dc0b73dc9fb/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211020174200-9d6173849985/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.0.0-20220722155259-a9ba230a4035/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
||||
golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
@@ -775,6 +842,7 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
@@ -831,8 +899,9 @@ golang.org/x/tools v0.0.0-20200929161345-d7fc70abf50f/go.mod h1:z6u4i615ZeAfBE4X
|
||||
golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20201125231158-b5590deeca9b/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE=
|
||||
golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
@@ -943,6 +1012,8 @@ gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI
|
||||
gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
|
||||
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
|
||||
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
@@ -953,6 +1024,7 @@ gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
@@ -1002,5 +1074,6 @@ modernc.org/z v1.0.1-0.20210308123920-1f282aa71362/go.mod h1:8/SRk5C/HgiQWCgXdfp
|
||||
modernc.org/z v1.0.1 h1:WyIDpEpAIx4Hel6q/Pcgj/VhaQV5XPJ2I6ryIYbjnpc=
|
||||
modernc.org/z v1.0.1/go.mod h1:8/SRk5C/HgiQWCgXdfpb+1RvhORdkz5sw72d3jjtyqA=
|
||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||
|
@@ -12,6 +12,9 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//go:build !skipCi
|
||||
// +build !skipCi
|
||||
|
||||
package i18n
|
||||
|
||||
import (
|
||||
|
@@ -1,9 +1,7 @@
|
||||
{
|
||||
"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"
|
||||
@@ -137,6 +135,7 @@
|
||||
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
|
||||
"Unknown type": "Unknown type",
|
||||
"Wrong parameter": "Wrong parameter",
|
||||
"Wrong verification code!": "Wrong verification code!",
|
||||
"You should verify your code in %d min!": "You should verify your code in %d min!",
|
||||
"the user does not exist, please sign up first": "the user does not exist, please sign up first"
|
||||
},
|
||||
|
@@ -1,9 +1,7 @@
|
||||
{
|
||||
"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"
|
||||
@@ -137,6 +135,7 @@
|
||||
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
|
||||
"Unknown type": "Unknown type",
|
||||
"Wrong parameter": "Wrong parameter",
|
||||
"Wrong verification code!": "Wrong verification code!",
|
||||
"You should verify your code in %d min!": "You should verify your code in %d min!",
|
||||
"the user does not exist, please sign up first": "the user does not exist, please sign up first"
|
||||
},
|
||||
|
@@ -1,9 +1,7 @@
|
||||
{
|
||||
"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"
|
||||
@@ -137,6 +135,7 @@
|
||||
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
|
||||
"Unknown type": "Unknown type",
|
||||
"Wrong parameter": "Wrong parameter",
|
||||
"Wrong verification code!": "Wrong verification code!",
|
||||
"You should verify your code in %d min!": "You should verify your code in %d min!",
|
||||
"the user does not exist, please sign up first": "the user does not exist, please sign up first"
|
||||
},
|
||||
|
@@ -1,9 +1,7 @@
|
||||
{
|
||||
"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"
|
||||
@@ -137,6 +135,7 @@
|
||||
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
|
||||
"Unknown type": "Unknown type",
|
||||
"Wrong parameter": "Wrong parameter",
|
||||
"Wrong verification code!": "Wrong verification code!",
|
||||
"You should verify your code in %d min!": "You should verify your code in %d min!",
|
||||
"the user does not exist, please sign up first": "the user does not exist, please sign up first"
|
||||
},
|
||||
|
@@ -1,9 +1,7 @@
|
||||
{
|
||||
"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"
|
||||
@@ -137,6 +135,7 @@
|
||||
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
|
||||
"Unknown type": "Unknown type",
|
||||
"Wrong parameter": "Wrong parameter",
|
||||
"Wrong verification code!": "Wrong verification code!",
|
||||
"You should verify your code in %d min!": "You should verify your code in %d min!",
|
||||
"the user does not exist, please sign up first": "the user does not exist, please sign up first"
|
||||
},
|
||||
|
@@ -1,9 +1,7 @@
|
||||
{
|
||||
"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"
|
||||
@@ -137,6 +135,7 @@
|
||||
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
|
||||
"Unknown type": "Unknown type",
|
||||
"Wrong parameter": "Wrong parameter",
|
||||
"Wrong verification code!": "Wrong verification code!",
|
||||
"You should verify your code in %d min!": "You should verify your code in %d min!",
|
||||
"the user does not exist, please sign up first": "the user does not exist, please sign up first"
|
||||
},
|
||||
|
@@ -1,9 +1,7 @@
|
||||
{
|
||||
"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"
|
||||
@@ -137,6 +135,7 @@
|
||||
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
|
||||
"Unknown type": "Unknown type",
|
||||
"Wrong parameter": "Wrong parameter",
|
||||
"Wrong verification code!": "Wrong verification code!",
|
||||
"You should verify your code in %d min!": "You should verify your code in %d min!",
|
||||
"the user does not exist, please sign up first": "the user does not exist, please sign up first"
|
||||
},
|
||||
|
@@ -1,9 +1,7 @@
|
||||
{
|
||||
"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"
|
||||
@@ -137,6 +135,7 @@
|
||||
"Unable to get the phone modify rule.": "Unable to get the phone modify rule.",
|
||||
"Unknown type": "Unknown type",
|
||||
"Wrong parameter": "Wrong parameter",
|
||||
"Wrong verification code!": "Wrong verification code!",
|
||||
"You should verify your code in %d min!": "You should verify your code in %d min!",
|
||||
"the user does not exist, please sign up first": "the user does not exist, please sign up first"
|
||||
},
|
||||
|
@@ -1,9 +1,7 @@
|
||||
{
|
||||
"account": {
|
||||
"Email: %s": "邮件: %s",
|
||||
"Get init score failed, error: %w": "初始化分数失败: %w",
|
||||
"Invalid information": "无效信息",
|
||||
"Phone: %s": "手机号: %s",
|
||||
"Please sign out first before signing in": "请在登录前先退出登录",
|
||||
"Please sign out first before signing up": "请在注册前先退出登录",
|
||||
"The application does not allow to sign up new account": "该应用不允许注册新用户"
|
||||
@@ -137,6 +135,7 @@
|
||||
"Unable to get the phone modify rule.": "无法获取手机号修改规则",
|
||||
"Unknown type": "未知类型",
|
||||
"Wrong parameter": "参数错误",
|
||||
"Wrong verification code!": "验证码错误!",
|
||||
"You should verify your code in %d min!": "请在 %d 分钟内输入正确验证码",
|
||||
"the user does not exist, please sign up first": "用户不存在,请先注册"
|
||||
},
|
||||
|
@@ -15,11 +15,9 @@
|
||||
package idp
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"strings"
|
||||
@@ -170,10 +168,18 @@ func (idp *DingTalkIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, erro
|
||||
Email: dtUserInfo.Email,
|
||||
AvatarUrl: dtUserInfo.AvatarUrl,
|
||||
}
|
||||
isUserInOrg, err := idp.isUserInOrg(userInfo.UnionId)
|
||||
if !isUserInOrg {
|
||||
|
||||
corpAccessToken := idp.getInnerAppAccessToken()
|
||||
userId, err := idp.getUserId(userInfo.UnionId, corpAccessToken)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
corpEmail, err := idp.getUserCorpEmail(userId, corpAccessToken)
|
||||
if err == nil && corpEmail != "" {
|
||||
userInfo.Email = corpEmail
|
||||
}
|
||||
|
||||
return &userInfo, nil
|
||||
}
|
||||
|
||||
@@ -202,23 +208,14 @@ func (idp *DingTalkIdProvider) postWithBody(body interface{}, url string) ([]byt
|
||||
}
|
||||
|
||||
func (idp *DingTalkIdProvider) getInnerAppAccessToken() string {
|
||||
appKey := idp.Config.ClientID
|
||||
appSecret := idp.Config.ClientSecret
|
||||
body := make(map[string]string)
|
||||
body["appKey"] = appKey
|
||||
body["appSecret"] = appSecret
|
||||
bodyData, err := json.Marshal(body)
|
||||
if err != nil {
|
||||
log.Println(err.Error())
|
||||
}
|
||||
reader := bytes.NewReader(bodyData)
|
||||
request, err := http.NewRequest("POST", "https://api.dingtalk.com/v1.0/oauth2/accessToken", reader)
|
||||
request.Header.Set("Content-Type", "application/json;charset=UTF-8")
|
||||
resp, err := idp.Client.Do(request)
|
||||
respBytes, err := ioutil.ReadAll(resp.Body)
|
||||
body["appKey"] = idp.Config.ClientID
|
||||
body["appSecret"] = idp.Config.ClientSecret
|
||||
respBytes, err := idp.postWithBody(body, "https://api.dingtalk.com/v1.0/oauth2/accessToken")
|
||||
if err != nil {
|
||||
log.Println(err.Error())
|
||||
}
|
||||
|
||||
var data struct {
|
||||
ExpireIn int `json:"expireIn"`
|
||||
AccessToken string `json:"accessToken"`
|
||||
@@ -230,34 +227,53 @@ func (idp *DingTalkIdProvider) getInnerAppAccessToken() string {
|
||||
return data.AccessToken
|
||||
}
|
||||
|
||||
func (idp *DingTalkIdProvider) isUserInOrg(unionId string) (bool, error) {
|
||||
func (idp *DingTalkIdProvider) getUserId(unionId string, accessToken string) (string, error) {
|
||||
body := make(map[string]string)
|
||||
body["unionid"] = unionId
|
||||
bodyData, err := json.Marshal(body)
|
||||
respBytes, err := idp.postWithBody(body, "https://oapi.dingtalk.com/topapi/user/getbyunionid?access_token="+accessToken)
|
||||
if err != nil {
|
||||
log.Println(err.Error())
|
||||
}
|
||||
reader := bytes.NewReader(bodyData)
|
||||
accessToken := idp.getInnerAppAccessToken()
|
||||
request, _ := http.NewRequest("POST", "https://oapi.dingtalk.com/topapi/user/getbyunionid?access_token="+accessToken, reader)
|
||||
request.Header.Set("Content-Type", "application/json;charset=UTF-8")
|
||||
resp, err := idp.Client.Do(request)
|
||||
respBytes, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
log.Println(err.Error())
|
||||
return "", err
|
||||
}
|
||||
|
||||
var data struct {
|
||||
ErrCode int `json:"errcode"`
|
||||
ErrMessage string `json:"errmsg"`
|
||||
Result struct {
|
||||
UserId string `json:"userid"`
|
||||
} `json:"result"`
|
||||
}
|
||||
err = json.Unmarshal(respBytes, &data)
|
||||
if err != nil {
|
||||
log.Println(err.Error())
|
||||
return "", err
|
||||
}
|
||||
if data.ErrCode == 60121 {
|
||||
return false, fmt.Errorf("the user is not found in the organization where clientId and clientSecret belong")
|
||||
return "", fmt.Errorf("the user is not found in the organization where clientId and clientSecret belong")
|
||||
} else if data.ErrCode != 0 {
|
||||
return false, fmt.Errorf(data.ErrMessage)
|
||||
return "", fmt.Errorf(data.ErrMessage)
|
||||
}
|
||||
return true, nil
|
||||
return data.Result.UserId, nil
|
||||
}
|
||||
|
||||
func (idp *DingTalkIdProvider) getUserCorpEmail(userId string, accessToken string) (string, error) {
|
||||
body := make(map[string]string)
|
||||
body["userid"] = userId
|
||||
respBytes, err := idp.postWithBody(body, "https://oapi.dingtalk.com/topapi/v2/user/get?access_token="+accessToken)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var data struct {
|
||||
ErrMessage string `json:"errmsg"`
|
||||
Result struct {
|
||||
Email string `json:"email"`
|
||||
} `json:"result"`
|
||||
}
|
||||
err = json.Unmarshal(respBytes, &data)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if data.ErrMessage != "ok" {
|
||||
return "", fmt.Errorf(data.ErrMessage)
|
||||
}
|
||||
return data.Result.Email, nil
|
||||
}
|
||||
|
2
main.go
2
main.go
@@ -55,7 +55,7 @@ func main() {
|
||||
beego.SetStaticPath("/swagger", "swagger")
|
||||
beego.SetStaticPath("/files", "files")
|
||||
// https://studygolang.com/articles/2303
|
||||
beego.InsertFilter("*", beego.BeforeRouter, routers.StaticFilter)
|
||||
beego.InsertFilter("*", beego.BeforeStatic, routers.StaticFilter)
|
||||
beego.InsertFilter("*", beego.BeforeRouter, routers.AutoSigninFilter)
|
||||
beego.InsertFilter("*", beego.BeforeRouter, routers.CorsFilter)
|
||||
beego.InsertFilter("*", beego.BeforeRouter, routers.AuthzFilter)
|
||||
|
@@ -84,15 +84,13 @@ func CheckUserSignup(application *Application, organization *Organization, usern
|
||||
if email == "" {
|
||||
if application.IsSignupItemRequired("Email") {
|
||||
return i18n.Translate(lang, "check:Email cannot be empty")
|
||||
} else {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
if HasUserByField(organization.Name, "email", email) {
|
||||
return i18n.Translate(lang, "check:Email already exists")
|
||||
} else if !util.IsEmailValid(email) {
|
||||
return i18n.Translate(lang, "check:Email is invalid")
|
||||
} else {
|
||||
if HasUserByField(organization.Name, "email", email) {
|
||||
return i18n.Translate(lang, "check:Email already exists")
|
||||
} else if !util.IsEmailValid(email) {
|
||||
return i18n.Translate(lang, "check:Email is invalid")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,17 +98,15 @@ func CheckUserSignup(application *Application, organization *Organization, usern
|
||||
if phone == "" {
|
||||
if application.IsSignupItemRequired("Phone") {
|
||||
return i18n.Translate(lang, "check:Phone cannot be empty")
|
||||
} else {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
if HasUserByField(organization.Name, "phone", phone) {
|
||||
return i18n.Translate(lang, "check:Phone already exists")
|
||||
} 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")
|
||||
} else {
|
||||
if HasUserByField(organization.Name, "phone", phone) {
|
||||
return i18n.Translate(lang, "check:Phone already exists")
|
||||
} 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")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -196,7 +192,7 @@ func checkLdapUserPassword(user *User, password string, lang string) (*User, str
|
||||
ldaps := GetLdaps(user.Owner)
|
||||
ldapLoginSuccess := false
|
||||
for _, ldapServer := range ldaps {
|
||||
conn, err := GetLdapConn(ldapServer.Host, ldapServer.Port, ldapServer.Admin, ldapServer.Passwd)
|
||||
conn, err := ldapServer.GetLdapConn()
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
@@ -33,6 +33,7 @@ type Ldap struct {
|
||||
ServerName string `xorm:"varchar(100)" json:"serverName"`
|
||||
Host string `xorm:"varchar(100)" json:"host"`
|
||||
Port int `json:"port"`
|
||||
EnableSsl bool `xorm:"bool" json:"enableSsl"`
|
||||
Admin string `xorm:"varchar(100)" json:"admin"`
|
||||
Passwd string `xorm:"varchar(100)" json:"passwd"`
|
||||
BaseDn string `xorm:"varchar(100)" json:"baseDn"`
|
||||
@@ -152,20 +153,26 @@ func isMicrosoftAD(Conn *goldap.Conn) (bool, error) {
|
||||
return isMicrosoft, err
|
||||
}
|
||||
|
||||
func GetLdapConn(host string, port int, adminUser string, adminPasswd string) (*ldapConn, error) {
|
||||
conn, err := goldap.Dial("tcp", fmt.Sprintf("%s:%d", host, port))
|
||||
func (ldap *Ldap) GetLdapConn() (c *ldapConn, err error) {
|
||||
var conn *goldap.Conn
|
||||
if ldap.EnableSsl {
|
||||
conn, err = goldap.DialTLS("tcp", fmt.Sprintf("%s:%d", ldap.Host, ldap.Port), nil)
|
||||
} else {
|
||||
conn, err = goldap.Dial("tcp", fmt.Sprintf("%s:%d", ldap.Host, ldap.Port))
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = conn.Bind(adminUser, adminPasswd)
|
||||
err = conn.Bind(ldap.Admin, ldap.Passwd)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("fail to login Ldap server with [%s]", adminUser)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
isAD, err := isMicrosoftAD(conn)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("fail to get Ldap server type [%s]", adminUser)
|
||||
return nil, err
|
||||
}
|
||||
return &ldapConn{Conn: conn, IsAD: isAD}, nil
|
||||
}
|
||||
@@ -352,7 +359,7 @@ func UpdateLdap(ldap *Ldap) bool {
|
||||
}
|
||||
|
||||
affected, err := adapter.Engine.ID(ldap.Id).Cols("owner", "server_name", "host",
|
||||
"port", "admin", "passwd", "base_dn", "auto_sync").Update(ldap)
|
||||
"port", "enable_ssl", "admin", "passwd", "base_dn", "auto_sync").Update(ldap)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
@@ -76,7 +76,7 @@ func (l *LdapAutoSynchronizer) syncRoutine(ldap *Ldap, stopChan chan struct{}) {
|
||||
|
||||
UpdateLdapSyncTime(ldap.Id)
|
||||
// fetch all users
|
||||
conn, err := GetLdapConn(ldap.Host, ldap.Port, ldap.Admin, ldap.Passwd)
|
||||
conn, err := ldap.GetLdapConn()
|
||||
if err != nil {
|
||||
logs.Warning(fmt.Sprintf("autoSync failed for %s, error %s", ldap.Id, err))
|
||||
continue
|
||||
|
@@ -44,7 +44,7 @@ func SendSms(provider *Provider, content string, phoneNumbers ...string) error {
|
||||
|
||||
if provider.Type == sender.Aliyun {
|
||||
for i, number := range phoneNumbers {
|
||||
phoneNumbers[i] = strings.TrimPrefix(number, "+")
|
||||
phoneNumbers[i] = strings.TrimPrefix(number, "+86")
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -26,8 +26,16 @@ import (
|
||||
"github.com/xorm-io/core"
|
||||
)
|
||||
|
||||
type VerifyResult struct {
|
||||
Code int
|
||||
Msg string
|
||||
}
|
||||
|
||||
const (
|
||||
wrongCode = "wrongCode"
|
||||
VerificationSuccess int = 0
|
||||
wrongCodeError = 1
|
||||
noRecordError = 2
|
||||
timeoutError = 3
|
||||
)
|
||||
|
||||
type VerificationRecord struct {
|
||||
@@ -150,11 +158,11 @@ func getVerificationRecord(dest string) *VerificationRecord {
|
||||
return &record
|
||||
}
|
||||
|
||||
func CheckVerificationCode(dest, code, lang string) string {
|
||||
func CheckVerificationCode(dest, code, lang string) *VerifyResult {
|
||||
record := getVerificationRecord(dest)
|
||||
|
||||
if record == nil {
|
||||
return i18n.Translate(lang, "verification:Code has not been sent yet!")
|
||||
return &VerifyResult{noRecordError, i18n.Translate(lang, "verification:Code has not been sent yet!")}
|
||||
}
|
||||
|
||||
timeout, err := conf.GetConfigInt64("verificationCodeTimeout")
|
||||
@@ -164,14 +172,14 @@ func CheckVerificationCode(dest, code, lang string) string {
|
||||
|
||||
now := time.Now().Unix()
|
||||
if now-record.Time > timeout*60 {
|
||||
return fmt.Sprintf(i18n.Translate(lang, "verification:You should verify your code in %d min!"), timeout)
|
||||
return &VerifyResult{timeoutError, fmt.Sprintf(i18n.Translate(lang, "verification:You should verify your code in %d min!"), timeout)}
|
||||
}
|
||||
|
||||
if record.Code != code {
|
||||
return wrongCode
|
||||
return &VerifyResult{wrongCodeError, i18n.Translate(lang, "verification:Wrong verification code!")}
|
||||
}
|
||||
|
||||
return ""
|
||||
return &VerifyResult{VerificationSuccess, ""}
|
||||
}
|
||||
|
||||
func DisableVerificationCode(dest string) {
|
||||
@@ -194,14 +202,14 @@ func CheckSigninCode(user *User, dest, code, lang string) string {
|
||||
}
|
||||
|
||||
result := CheckVerificationCode(dest, code, lang)
|
||||
switch result {
|
||||
case "":
|
||||
switch result.Code {
|
||||
case VerificationSuccess:
|
||||
resetUserSigninErrorTimes(user)
|
||||
return ""
|
||||
case wrongCode:
|
||||
case wrongCodeError:
|
||||
return recordSigninErrorInfo(user, lang)
|
||||
default:
|
||||
return result
|
||||
return result.Msg
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -36,7 +36,7 @@ func CorsFilter(ctx *context.Context) {
|
||||
if origin != "" && originConf != "" && origin != originConf {
|
||||
if object.IsOriginAllowed(origin) {
|
||||
ctx.Output.Header(headerAllowOrigin, origin)
|
||||
ctx.Output.Header(headerAllowMethods, "POST, GET, OPTIONS")
|
||||
ctx.Output.Header(headerAllowMethods, "POST, GET, OPTIONS, DELETE")
|
||||
ctx.Output.Header(headerAllowHeaders, "Content-Type, Authorization")
|
||||
} else {
|
||||
ctx.ResponseWriter.WriteHeader(http.StatusForbidden)
|
||||
@@ -48,4 +48,11 @@ func CorsFilter(ctx *context.Context) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if ctx.Input.Method() == "OPTIONS" {
|
||||
ctx.Output.Header(headerAllowOrigin, "*")
|
||||
ctx.Output.Header(headerAllowMethods, "POST, GET, OPTIONS, DELETE")
|
||||
ctx.ResponseWriter.WriteHeader(http.StatusOK)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@@ -118,13 +118,12 @@ func initAPI() {
|
||||
beego.Router("/api/reset-email-or-phone", &controllers.ApiController{}, "POST:ResetEmailOrPhone")
|
||||
beego.Router("/api/get-captcha", &controllers.ApiController{}, "GET:GetCaptcha")
|
||||
|
||||
beego.Router("/api/get-ldap-user", &controllers.ApiController{}, "POST:GetLdapUser")
|
||||
beego.Router("/api/get-ldap-users", &controllers.ApiController{}, "GET:GetLdapUsers")
|
||||
beego.Router("/api/get-ldaps", &controllers.ApiController{}, "GET:GetLdaps")
|
||||
beego.Router("/api/get-ldap", &controllers.ApiController{}, "GET:GetLdap")
|
||||
beego.Router("/api/add-ldap", &controllers.ApiController{}, "POST:AddLdap")
|
||||
beego.Router("/api/update-ldap", &controllers.ApiController{}, "POST:UpdateLdap")
|
||||
beego.Router("/api/delete-ldap", &controllers.ApiController{}, "POST:DeleteLdap")
|
||||
beego.Router("/api/check-ldap-users-exist", &controllers.ApiController{}, "POST:CheckLdapUsersExist")
|
||||
beego.Router("/api/sync-ldap-users", &controllers.ApiController{}, "POST:SyncLdapUsers")
|
||||
|
||||
beego.Router("/api/get-providers", &controllers.ApiController{}, "GET:GetProviders")
|
||||
@@ -225,5 +224,5 @@ func initAPI() {
|
||||
beego.Router("/api/webauthn/signin/finish", &controllers.ApiController{}, "Post:WebAuthnSigninFinish")
|
||||
|
||||
beego.Router("/api/get-system-info", &controllers.ApiController{}, "GET:GetSystemInfo")
|
||||
beego.Router("/api/get-release", &controllers.ApiController{}, "GET:GitRepoVersion")
|
||||
beego.Router("/api/get-version-info", &controllers.ApiController{}, "GET:GetVersionInfo")
|
||||
}
|
||||
|
@@ -18,6 +18,7 @@ import (
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/beego/beego/context"
|
||||
"github.com/casdoor/casdoor/conf"
|
||||
@@ -31,6 +32,11 @@ var (
|
||||
|
||||
func StaticFilter(ctx *context.Context) {
|
||||
urlPath := ctx.Request.URL.Path
|
||||
|
||||
if urlPath == "/.well-known/acme-challenge/filename" {
|
||||
http.ServeContent(ctx.ResponseWriter, ctx.Request, "acme-challenge", time.Now(), strings.NewReader("content"))
|
||||
}
|
||||
|
||||
if strings.HasPrefix(urlPath, "/api/") || strings.HasPrefix(urlPath, "/.well-known/") {
|
||||
return
|
||||
}
|
||||
|
@@ -636,14 +636,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/check-ldap-users-exist": {
|
||||
"post": {
|
||||
"tags": [
|
||||
"Account API"
|
||||
],
|
||||
"operationId": "ApiController.CheckLdapUserExist"
|
||||
}
|
||||
},
|
||||
"/api/check-user-password": {
|
||||
"post": {
|
||||
"tags": [
|
||||
@@ -1349,8 +1341,8 @@
|
||||
"operationId": "ApiController.GetLdap"
|
||||
}
|
||||
},
|
||||
"/api/get-ldap-user": {
|
||||
"post": {
|
||||
"/api/get-ldap-users": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"Account API"
|
||||
],
|
||||
@@ -1835,20 +1827,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/get-release": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"System API"
|
||||
],
|
||||
"description": "get local github repo's latest release version info",
|
||||
"operationId": "ApiController.GitRepoVersion",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "{string} local latest version hash of casdoor"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/get-resource": {
|
||||
"get": {
|
||||
"tags": [
|
||||
@@ -2340,6 +2318,20 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/get-version-info": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"System API"
|
||||
],
|
||||
"description": "get local git repo's latest release version info",
|
||||
"operationId": "ApiController.GetVersionInfo",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "{string} local latest version hash of Casdoor"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/get-webhook": {
|
||||
"get": {
|
||||
"tags": [
|
||||
@@ -3635,11 +3627,11 @@
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
"2346.0xc000278ab0.false": {
|
||||
"2268.0xc000528cf0.false": {
|
||||
"title": "false",
|
||||
"type": "object"
|
||||
},
|
||||
"2381.0xc000278ae0.false": {
|
||||
"2302.0xc000528d20.false": {
|
||||
"title": "false",
|
||||
"type": "object"
|
||||
},
|
||||
@@ -3766,10 +3758,10 @@
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"data": {
|
||||
"$ref": "#/definitions/2346.0xc000278ab0.false"
|
||||
"$ref": "#/definitions/2268.0xc000528cf0.false"
|
||||
},
|
||||
"data2": {
|
||||
"$ref": "#/definitions/2381.0xc000278ae0.false"
|
||||
"$ref": "#/definitions/2302.0xc000528d20.false"
|
||||
},
|
||||
"msg": {
|
||||
"type": "string"
|
||||
|
@@ -412,11 +412,6 @@ paths:
|
||||
description: The Response object
|
||||
schema:
|
||||
$ref: '#/definitions/controllers.Response'
|
||||
/api/check-ldap-users-exist:
|
||||
post:
|
||||
tags:
|
||||
- Account API
|
||||
operationId: ApiController.CheckLdapUserExist
|
||||
/api/check-user-password:
|
||||
post:
|
||||
tags:
|
||||
@@ -875,8 +870,8 @@ paths:
|
||||
tags:
|
||||
- Account API
|
||||
operationId: ApiController.GetLdap
|
||||
/api/get-ldap-user:
|
||||
post:
|
||||
/api/get-ldap-users:
|
||||
get:
|
||||
tags:
|
||||
- Account API
|
||||
operationId: ApiController.GetLdapser
|
||||
@@ -1193,15 +1188,6 @@ paths:
|
||||
description: The Response object
|
||||
schema:
|
||||
$ref: '#/definitions/object.Record'
|
||||
/api/get-release:
|
||||
get:
|
||||
tags:
|
||||
- System API
|
||||
description: get local github repo's latest release version info
|
||||
operationId: ApiController.GitRepoVersion
|
||||
responses:
|
||||
"200":
|
||||
description: '{string} local latest version hash of casdoor'
|
||||
/api/get-resource:
|
||||
get:
|
||||
tags:
|
||||
@@ -1525,6 +1511,15 @@ paths:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/definitions/object.User'
|
||||
/api/get-version-info:
|
||||
get:
|
||||
tags:
|
||||
- System API
|
||||
description: get local git repo's latest release version info
|
||||
operationId: ApiController.GetVersionInfo
|
||||
responses:
|
||||
"200":
|
||||
description: '{string} local latest version hash of Casdoor'
|
||||
/api/get-webhook:
|
||||
get:
|
||||
tags:
|
||||
@@ -2379,10 +2374,10 @@ paths:
|
||||
schema:
|
||||
$ref: '#/definitions/Response'
|
||||
definitions:
|
||||
2346.0xc000278ab0.false:
|
||||
2268.0xc000528cf0.false:
|
||||
title: "false"
|
||||
type: object
|
||||
2381.0xc000278ae0.false:
|
||||
2302.0xc000528d20.false:
|
||||
title: "false"
|
||||
type: object
|
||||
Response:
|
||||
@@ -2469,9 +2464,9 @@ definitions:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
$ref: '#/definitions/2346.0xc000278ab0.false'
|
||||
$ref: '#/definitions/2268.0xc000528cf0.false'
|
||||
data2:
|
||||
$ref: '#/definitions/2381.0xc000278ae0.false'
|
||||
$ref: '#/definitions/2302.0xc000528d20.false'
|
||||
msg:
|
||||
type: string
|
||||
name:
|
||||
|
17
sync/conf.go
17
sync/conf.go
@@ -1,17 +0,0 @@
|
||||
package sync
|
||||
|
||||
var (
|
||||
host1 = "127.0.0.1"
|
||||
port1 = 3306
|
||||
username1 = "root"
|
||||
password1 = "123456"
|
||||
database1 = "db"
|
||||
)
|
||||
|
||||
var (
|
||||
host2 = "127.0.0.1"
|
||||
port2 = 3306
|
||||
username2 = "root"
|
||||
password2 = "123456"
|
||||
database2 = "db"
|
||||
)
|
100
sync/database.go
Normal file
100
sync/database.go
Normal file
@@ -0,0 +1,100 @@
|
||||
// Copyright 2023 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package sync
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/go-mysql-org/go-mysql/canal"
|
||||
"github.com/xorm-io/xorm"
|
||||
)
|
||||
|
||||
type Database struct {
|
||||
host string
|
||||
port int
|
||||
database string
|
||||
username string
|
||||
password string
|
||||
|
||||
engine *xorm.Engine
|
||||
serverId uint32
|
||||
serverUuid string
|
||||
Gtid string
|
||||
canal.DummyEventHandler
|
||||
}
|
||||
|
||||
func newDatabase(host string, port int, database string, username string, password string) *Database {
|
||||
db := &Database{
|
||||
host: host,
|
||||
port: port,
|
||||
database: database,
|
||||
username: username,
|
||||
password: password,
|
||||
}
|
||||
|
||||
dataSourceName := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s", username, password, host, port, database)
|
||||
engine, err := createEngine(dataSourceName)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
db.engine = engine
|
||||
|
||||
db.serverId, err = getServerId(engine)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
db.serverUuid, err = getServerUuid(engine)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return db
|
||||
}
|
||||
|
||||
func (db *Database) getCanalConfig() *canal.Config {
|
||||
// config canal
|
||||
cfg := canal.NewDefaultConfig()
|
||||
cfg.Addr = fmt.Sprintf("%s:%d", db.host, db.port)
|
||||
cfg.Password = db.password
|
||||
cfg.User = db.username
|
||||
// We only care table in database1
|
||||
cfg.Dump.TableDB = db.database
|
||||
return cfg
|
||||
}
|
||||
|
||||
func (db *Database) startCanal(targetDb *Database) error {
|
||||
canalConfig := db.getCanalConfig()
|
||||
c, err := canal.NewCanal(canalConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
gtidSet, err := c.GetMasterGTIDSet()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Register a handler to handle RowsEvent
|
||||
c.SetEventHandler(targetDb)
|
||||
|
||||
// Start replication
|
||||
err = c.StartFromGTID(gtidSet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
@@ -17,84 +17,32 @@ package sync
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/go-mysql-org/go-mysql/canal"
|
||||
"github.com/go-mysql-org/go-mysql/mysql"
|
||||
"github.com/go-mysql-org/go-mysql/replication"
|
||||
"github.com/siddontang/go-log/log"
|
||||
"github.com/xorm-io/xorm"
|
||||
)
|
||||
|
||||
type MyEventHandler struct {
|
||||
dataSourceName string
|
||||
engine *xorm.Engine
|
||||
serverId uint32
|
||||
serverUUID string
|
||||
GTID string
|
||||
canal.DummyEventHandler
|
||||
}
|
||||
|
||||
func StartCanal(cfg *canal.Config, username string, password string, host string, port int, database string) error {
|
||||
c, err := canal.NewCanal(cfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
GTIDSet, err := c.GetMasterGTIDSet()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
eventHandler := GetMyEventHandler(username, password, host, port, database)
|
||||
// Register a handler to handle RowsEvent
|
||||
c.SetEventHandler(&eventHandler)
|
||||
|
||||
// Start replication
|
||||
err = c.StartFromGTID(GTIDSet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func StartBinlogSync() error {
|
||||
var wg sync.WaitGroup
|
||||
// init config
|
||||
cfg1 := GetCanalConfig(username1, password1, host1, port1, database1)
|
||||
cfg2 := GetCanalConfig(username2, password2, host2, port2, database2)
|
||||
|
||||
// start canal1 replication
|
||||
go StartCanal(cfg1, username2, password2, host2, port2, database2)
|
||||
wg.Add(1)
|
||||
|
||||
// start canal2 replication
|
||||
go StartCanal(cfg2, username1, password1, host1, port1, database1)
|
||||
wg.Add(1)
|
||||
|
||||
wg.Wait()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *MyEventHandler) OnGTID(header *replication.EventHeader, gtid mysql.GTIDSet) error {
|
||||
func (db *Database) OnGTID(header *replication.EventHeader, gtid mysql.GTIDSet) error {
|
||||
log.Info("OnGTID: ", gtid.String())
|
||||
h.GTID = gtid.String()
|
||||
db.Gtid = gtid.String()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *MyEventHandler) onDDL(header *replication.EventHeader, nextPos mysql.Position, queryEvent *replication.QueryEvent) error {
|
||||
func (db *Database) onDDL(header *replication.EventHeader, nextPos mysql.Position, queryEvent *replication.QueryEvent) error {
|
||||
log.Info("into DDL event")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *MyEventHandler) OnRow(e *canal.RowsEvent) error {
|
||||
func (db *Database) OnRow(e *canal.RowsEvent) error {
|
||||
log.Info("serverId: ", e.Header.ServerID)
|
||||
if strings.Contains(h.GTID, h.serverUUID) {
|
||||
if strings.Contains(db.Gtid, db.serverUuid) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Set the next gtid of the target library to the gtid of the current target library to avoid loopbacks
|
||||
h.engine.Exec(fmt.Sprintf("SET GTID_NEXT= '%s'", h.GTID))
|
||||
db.engine.Exec(fmt.Sprintf("SET GTID_NEXT= '%s'", db.Gtid))
|
||||
length := len(e.Table.Columns)
|
||||
columnNames := make([]string, length)
|
||||
oldColumnValue := make([]interface{}, length)
|
||||
@@ -110,11 +58,11 @@ func (h *MyEventHandler) OnRow(e *canal.RowsEvent) error {
|
||||
}
|
||||
}
|
||||
// get pk column name
|
||||
pkColumnNames := GetPKColumnNames(columnNames, e.Table.PKColumns)
|
||||
pkColumnNames := getPkColumnNames(columnNames, e.Table.PKColumns)
|
||||
|
||||
switch e.Action {
|
||||
case canal.UpdateAction:
|
||||
h.engine.Exec("BEGIN")
|
||||
db.engine.Exec("BEGIN")
|
||||
for i, row := range e.Rows {
|
||||
for j, item := range row {
|
||||
if i%2 == 0 {
|
||||
@@ -136,23 +84,23 @@ func (h *MyEventHandler) OnRow(e *canal.RowsEvent) error {
|
||||
}
|
||||
}
|
||||
if i%2 == 1 {
|
||||
pkColumnValue := GetPKColumnValues(oldColumnValue, e.Table.PKColumns)
|
||||
updateSql, args, err := GetUpdateSql(e.Table.Schema, e.Table.Name, columnNames, newColumnValue, pkColumnNames, pkColumnValue)
|
||||
pkColumnValue := getPkColumnValues(oldColumnValue, e.Table.PKColumns)
|
||||
updateSql, args, err := getUpdateSql(e.Table.Schema, e.Table.Name, columnNames, newColumnValue, pkColumnNames, pkColumnValue)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
res, err := h.engine.DB().Exec(updateSql, args...)
|
||||
res, err := db.engine.DB().Exec(updateSql, args...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Info(updateSql, args, res)
|
||||
}
|
||||
}
|
||||
h.engine.Exec("COMMIT")
|
||||
h.engine.Exec("SET GTID_NEXT='automatic'")
|
||||
db.engine.Exec("COMMIT")
|
||||
db.engine.Exec("SET GTID_NEXT='automatic'")
|
||||
case canal.DeleteAction:
|
||||
h.engine.Exec("BEGIN")
|
||||
db.engine.Exec("BEGIN")
|
||||
for _, row := range e.Rows {
|
||||
for j, item := range row {
|
||||
if isChar[j] == true {
|
||||
@@ -162,22 +110,22 @@ func (h *MyEventHandler) OnRow(e *canal.RowsEvent) error {
|
||||
}
|
||||
}
|
||||
|
||||
pkColumnValue := GetPKColumnValues(oldColumnValue, e.Table.PKColumns)
|
||||
deleteSql, args, err := GetDeleteSql(e.Table.Schema, e.Table.Name, pkColumnNames, pkColumnValue)
|
||||
pkColumnValue := getPkColumnValues(oldColumnValue, e.Table.PKColumns)
|
||||
deleteSql, args, err := getDeleteSql(e.Table.Schema, e.Table.Name, pkColumnNames, pkColumnValue)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
res, err := h.engine.DB().Exec(deleteSql, args...)
|
||||
res, err := db.engine.DB().Exec(deleteSql, args...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Info(deleteSql, args, res)
|
||||
}
|
||||
h.engine.Exec("COMMIT")
|
||||
h.engine.Exec("SET GTID_NEXT='automatic'")
|
||||
db.engine.Exec("COMMIT")
|
||||
db.engine.Exec("SET GTID_NEXT='automatic'")
|
||||
case canal.InsertAction:
|
||||
h.engine.Exec("BEGIN")
|
||||
db.engine.Exec("BEGIN")
|
||||
for _, row := range e.Rows {
|
||||
for j, item := range row {
|
||||
if isChar[j] == true {
|
||||
@@ -191,25 +139,25 @@ func (h *MyEventHandler) OnRow(e *canal.RowsEvent) error {
|
||||
}
|
||||
}
|
||||
|
||||
insertSql, args, err := GetInsertSql(e.Table.Schema, e.Table.Name, columnNames, newColumnValue)
|
||||
insertSql, args, err := getInsertSql(e.Table.Schema, e.Table.Name, columnNames, newColumnValue)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
res, err := h.engine.DB().Exec(insertSql, args...)
|
||||
res, err := db.engine.DB().Exec(insertSql, args...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Info(insertSql, args, res)
|
||||
}
|
||||
h.engine.Exec("COMMIT")
|
||||
h.engine.Exec("SET GTID_NEXT='automatic'")
|
||||
db.engine.Exec("COMMIT")
|
||||
db.engine.Exec("SET GTID_NEXT='automatic'")
|
||||
default:
|
||||
log.Infof("%v", e.String())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *MyEventHandler) String() string {
|
||||
return "MyEventHandler"
|
||||
func (db *Database) String() string {
|
||||
return "Database"
|
||||
}
|
32
sync/sync.go
Normal file
32
sync/sync.go
Normal file
@@ -0,0 +1,32 @@
|
||||
// Copyright 2023 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package sync
|
||||
|
||||
import "sync"
|
||||
|
||||
func startSyncJob(db1 *Database, db2 *Database) error {
|
||||
var wg sync.WaitGroup
|
||||
|
||||
// start canal1 replication
|
||||
go db1.startCanal(db2)
|
||||
wg.Add(1)
|
||||
|
||||
// start canal2 replication
|
||||
go db2.startCanal(db1)
|
||||
wg.Add(1)
|
||||
|
||||
wg.Wait()
|
||||
return nil
|
||||
}
|
@@ -1,4 +1,4 @@
|
||||
// Copyright 2022 The Casdoor Authors. All Rights Reserved.
|
||||
// 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.
|
||||
@@ -12,22 +12,19 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package util
|
||||
//go:build !skipCi
|
||||
// +build !skipCi
|
||||
|
||||
package sync
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
)
|
||||
|
||||
func TestGetCpuUsage(t *testing.T) {
|
||||
usage, err := GetCpuUsage()
|
||||
assert.Nil(t, err)
|
||||
t.Log(usage)
|
||||
}
|
||||
|
||||
func TestGetMemoryUsage(t *testing.T) {
|
||||
used, total, err := GetMemoryUsage()
|
||||
assert.Nil(t, err)
|
||||
t.Log(used, total)
|
||||
func TestStartSyncJob(t *testing.T) {
|
||||
db1 := newDatabase("127.0.0.1", 3306, "casdoor", "root", "123456")
|
||||
db2 := newDatabase("127.0.0.1", 3306, "casdoor2", "root", "123456")
|
||||
startSyncJob(db1, db2)
|
||||
}
|
@@ -19,13 +19,11 @@ import (
|
||||
"log"
|
||||
"strconv"
|
||||
|
||||
"github.com/go-mysql-org/go-mysql/canal"
|
||||
|
||||
"github.com/Masterminds/squirrel"
|
||||
"github.com/xorm-io/xorm"
|
||||
)
|
||||
|
||||
func GetUpdateSql(schemaName string, tableName string, columnNames []string, newColumnVal []interface{}, pkColumnNames []string, pkColumnValue []interface{}) (string, []interface{}, error) {
|
||||
func getUpdateSql(schemaName string, tableName string, columnNames []string, newColumnVal []interface{}, pkColumnNames []string, pkColumnValue []interface{}) (string, []interface{}, error) {
|
||||
updateSql := squirrel.Update(schemaName + "." + tableName)
|
||||
for i, columnName := range columnNames {
|
||||
updateSql = updateSql.Set(columnName, newColumnVal[i])
|
||||
@@ -43,13 +41,13 @@ func GetUpdateSql(schemaName string, tableName string, columnNames []string, new
|
||||
return sql, args, nil
|
||||
}
|
||||
|
||||
func GetInsertSql(schemaName string, tableName string, columnNames []string, columnValue []interface{}) (string, []interface{}, error) {
|
||||
func getInsertSql(schemaName string, tableName string, columnNames []string, columnValue []interface{}) (string, []interface{}, error) {
|
||||
insertSql := squirrel.Insert(schemaName + "." + tableName).Columns(columnNames...).Values(columnValue...)
|
||||
|
||||
return insertSql.ToSql()
|
||||
}
|
||||
|
||||
func GetDeleteSql(schemaName string, tableName string, pkColumnNames []string, pkColumnValue []interface{}) (string, []interface{}, error) {
|
||||
func getDeleteSql(schemaName string, tableName string, pkColumnNames []string, pkColumnValue []interface{}) (string, []interface{}, error) {
|
||||
deleteSql := squirrel.Delete(schemaName + "." + tableName)
|
||||
|
||||
for i, columnName := range pkColumnNames {
|
||||
@@ -59,7 +57,7 @@ func GetDeleteSql(schemaName string, tableName string, pkColumnNames []string, p
|
||||
return deleteSql.ToSql()
|
||||
}
|
||||
|
||||
func CreateEngine(dataSourceName string) (*xorm.Engine, error) {
|
||||
func createEngine(dataSourceName string) (*xorm.Engine, error) {
|
||||
engine, err := xorm.NewEngine("mysql", dataSourceName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -75,7 +73,7 @@ func CreateEngine(dataSourceName string) (*xorm.Engine, error) {
|
||||
return engine, nil
|
||||
}
|
||||
|
||||
func GetServerId(engin *xorm.Engine) (uint32, error) {
|
||||
func getServerId(engin *xorm.Engine) (uint32, error) {
|
||||
res, err := engin.QueryInterface("SELECT @@server_id")
|
||||
if err != nil {
|
||||
return 0, err
|
||||
@@ -84,16 +82,16 @@ func GetServerId(engin *xorm.Engine) (uint32, error) {
|
||||
return uint32(serverId), nil
|
||||
}
|
||||
|
||||
func GetServerUUID(engin *xorm.Engine) (string, error) {
|
||||
func getServerUuid(engin *xorm.Engine) (string, error) {
|
||||
res, err := engin.QueryString("show variables like 'server_uuid'")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
serverUUID := fmt.Sprintf("%s", res[0]["Value"])
|
||||
return serverUUID, err
|
||||
serverUuid := fmt.Sprintf("%s", res[0]["Value"])
|
||||
return serverUuid, err
|
||||
}
|
||||
|
||||
func GetPKColumnNames(columnNames []string, PKColumns []int) []string {
|
||||
func getPkColumnNames(columnNames []string, PKColumns []int) []string {
|
||||
pkColumnNames := make([]string, len(PKColumns))
|
||||
for i, index := range PKColumns {
|
||||
pkColumnNames[i] = columnNames[index]
|
||||
@@ -101,30 +99,10 @@ func GetPKColumnNames(columnNames []string, PKColumns []int) []string {
|
||||
return pkColumnNames
|
||||
}
|
||||
|
||||
func GetPKColumnValues(columnValues []interface{}, PKColumns []int) []interface{} {
|
||||
func getPkColumnValues(columnValues []interface{}, PKColumns []int) []interface{} {
|
||||
pkColumnNames := make([]interface{}, len(PKColumns))
|
||||
for i, index := range PKColumns {
|
||||
pkColumnNames[i] = columnValues[index]
|
||||
}
|
||||
return pkColumnNames
|
||||
}
|
||||
|
||||
func GetCanalConfig(username string, password string, host string, port int, database string) *canal.Config {
|
||||
// config canal
|
||||
cfg := canal.NewDefaultConfig()
|
||||
cfg.Addr = fmt.Sprintf("%s:%d", host, port)
|
||||
cfg.Password = password
|
||||
cfg.User = username
|
||||
// We only care table in database1
|
||||
cfg.Dump.TableDB = database
|
||||
return cfg
|
||||
}
|
||||
|
||||
func GetMyEventHandler(username string, password string, host string, port int, database string) MyEventHandler {
|
||||
var eventHandler MyEventHandler
|
||||
eventHandler.dataSourceName = fmt.Sprintf("%s:%s@tcp(%s:%d)/%s", username, password, host, port, database)
|
||||
eventHandler.engine, _ = CreateEngine(eventHandler.dataSourceName)
|
||||
eventHandler.serverId, _ = GetServerId(eventHandler.engine)
|
||||
eventHandler.serverUUID, _ = GetServerUUID(eventHandler.engine)
|
||||
return eventHandler
|
||||
}
|
124
util/system.go
124
util/system.go
@@ -15,26 +15,37 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/go-git/go-git/v5"
|
||||
"github.com/go-git/go-git/v5/plumbing"
|
||||
"github.com/go-git/go-git/v5/plumbing/object"
|
||||
"github.com/shirou/gopsutil/cpu"
|
||||
"github.com/shirou/gopsutil/mem"
|
||||
)
|
||||
|
||||
// get cpu usage
|
||||
func GetCpuUsage() ([]float64, error) {
|
||||
type SystemInfo struct {
|
||||
CpuUsage []float64 `json:"cpuUsage"`
|
||||
MemoryUsed uint64 `json:"memoryUsed"`
|
||||
MemoryTotal uint64 `json:"memoryTotal"`
|
||||
}
|
||||
|
||||
type VersionInfo struct {
|
||||
Version string `json:"version"`
|
||||
CommitId string `json:"commitId"`
|
||||
CommitOffset int `json:"commitOffset"`
|
||||
}
|
||||
|
||||
// getCpuUsage get cpu usage
|
||||
func getCpuUsage() ([]float64, error) {
|
||||
usage, err := cpu.Percent(time.Second, true)
|
||||
return usage, err
|
||||
}
|
||||
|
||||
var fileDate, version string
|
||||
|
||||
// get memory usage
|
||||
func GetMemoryUsage() (uint64, uint64, error) {
|
||||
// getMemoryUsage get memory usage
|
||||
func getMemoryUsage() (uint64, uint64, error) {
|
||||
virtualMem, err := mem.VirtualMemory()
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
@@ -46,33 +57,86 @@ func GetMemoryUsage() (uint64, uint64, error) {
|
||||
return m.TotalAlloc, virtualMem.Total, nil
|
||||
}
|
||||
|
||||
// get github repo release version
|
||||
func GetGitRepoVersion() (string, error) {
|
||||
pwd, err := os.Getwd()
|
||||
func GetSystemInfo() (*SystemInfo, error) {
|
||||
cpuUsage, err := getCpuUsage()
|
||||
if err != nil {
|
||||
return "", err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
fileInfos, err := ioutil.ReadDir(pwd + "/.git/refs/heads")
|
||||
for _, v := range fileInfos {
|
||||
if v.Name() == "master" {
|
||||
if v.ModTime().String() == fileDate {
|
||||
return version, nil
|
||||
} else {
|
||||
fileDate = v.ModTime().String()
|
||||
break
|
||||
memoryUsed, memoryTotal, err := getMemoryUsage()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res := &SystemInfo{
|
||||
CpuUsage: cpuUsage,
|
||||
MemoryUsed: memoryUsed,
|
||||
MemoryTotal: memoryTotal,
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// GetVersionInfo get git current commit and repo release version
|
||||
func GetVersionInfo() (*VersionInfo, error) {
|
||||
res := &VersionInfo{
|
||||
Version: "",
|
||||
CommitId: "",
|
||||
CommitOffset: -1,
|
||||
}
|
||||
|
||||
_, filename, _, _ := runtime.Caller(0)
|
||||
rootPath := path.Dir(path.Dir(filename))
|
||||
r, err := git.PlainOpen(rootPath)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
ref, err := r.Head()
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
tags, err := r.Tags()
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
tagMap := make(map[plumbing.Hash]string)
|
||||
err = tags.ForEach(func(t *plumbing.Reference) error {
|
||||
// This technique should work for both lightweight and annotated tags.
|
||||
revHash, err := r.ResolveRevision(plumbing.Revision(t.Name()))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tagMap[*revHash] = t.Name().Short()
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
cIter, err := r.Log(&git.LogOptions{From: ref.Hash()})
|
||||
|
||||
commitOffset := 0
|
||||
version := ""
|
||||
// iterates over the commits
|
||||
err = cIter.ForEach(func(c *object.Commit) error {
|
||||
tag, ok := tagMap[c.Hash]
|
||||
if ok {
|
||||
if version == "" {
|
||||
version = tag
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
content, err := ioutil.ReadFile(pwd + "/.git/refs/heads/master")
|
||||
if version == "" {
|
||||
commitOffset++
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
return res, err
|
||||
}
|
||||
|
||||
// Convert to full length
|
||||
temp := string(content)
|
||||
version = strings.ReplaceAll(temp, "\n", "")
|
||||
|
||||
return version, nil
|
||||
res = &VersionInfo{
|
||||
Version: version,
|
||||
CommitId: ref.Hash().String(),
|
||||
CommitOffset: commitOffset,
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
92
util/system_test.go
Normal file
92
util/system_test.go
Normal file
@@ -0,0 +1,92 @@
|
||||
// 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.
|
||||
|
||||
//go:build !skipCi
|
||||
// +build !skipCi
|
||||
|
||||
package util
|
||||
|
||||
import (
|
||||
"path"
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
"github.com/go-git/go-git/v5"
|
||||
"github.com/go-git/go-git/v5/plumbing"
|
||||
"github.com/go-git/go-git/v5/plumbing/object"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestGetCpuUsage(t *testing.T) {
|
||||
usage, err := getCpuUsage()
|
||||
assert.Nil(t, err)
|
||||
t.Log(usage)
|
||||
}
|
||||
|
||||
func TestGetMemoryUsage(t *testing.T) {
|
||||
used, total, err := getMemoryUsage()
|
||||
assert.Nil(t, err)
|
||||
t.Log(used, total)
|
||||
}
|
||||
|
||||
func TestGetGitRepoVersion(t *testing.T) {
|
||||
versionInfo, err := GetVersionInfo()
|
||||
assert.Nil(t, err)
|
||||
t.Log(versionInfo)
|
||||
}
|
||||
|
||||
func TestGetVersion(t *testing.T) {
|
||||
_, filename, _, _ := runtime.Caller(0)
|
||||
root := path.Dir(path.Dir(filename))
|
||||
r, err := git.PlainOpen(root)
|
||||
if err != nil {
|
||||
t.Log(err)
|
||||
}
|
||||
tags, err := r.Tags()
|
||||
if err != nil {
|
||||
t.Log(err)
|
||||
}
|
||||
tagMap := make(map[plumbing.Hash]string)
|
||||
err = tags.ForEach(func(t *plumbing.Reference) error {
|
||||
// This technique should work for both lightweight and annotated tags.
|
||||
revHash, err := r.ResolveRevision(plumbing.Revision(t.Name()))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tagMap[*revHash] = t.Name().Short()
|
||||
return nil
|
||||
})
|
||||
|
||||
testHash := plumbing.NewHash("f8bc87eb4e5ba3256424cf14aafe0549f812f1cf")
|
||||
cIter, err := r.Log(&git.LogOptions{From: testHash})
|
||||
|
||||
aheadCnt := 0
|
||||
releaseVersion := ""
|
||||
// iterates over the commits
|
||||
err = cIter.ForEach(func(c *object.Commit) error {
|
||||
tag, ok := tagMap[c.Hash]
|
||||
if ok {
|
||||
if releaseVersion == "" {
|
||||
releaseVersion = tag
|
||||
}
|
||||
}
|
||||
if releaseVersion == "" {
|
||||
aheadCnt++
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
assert.Equal(t, 3, aheadCnt)
|
||||
assert.Equal(t, "v1.257.0", releaseVersion)
|
||||
}
|
@@ -14,12 +14,13 @@
|
||||
|
||||
import React from "react";
|
||||
import {Link} from "react-router-dom";
|
||||
import {Button, Popconfirm, Switch, Table} from "antd";
|
||||
import {Button, Switch, Table} from "antd";
|
||||
import moment from "moment";
|
||||
import * as Setting from "./Setting";
|
||||
import * as AdapterBackend from "./backend/AdapterBackend";
|
||||
import i18next from "i18next";
|
||||
import BaseListPage from "./BaseListPage";
|
||||
import PopconfirmModal from "./PopconfirmModal";
|
||||
|
||||
class AdapterListPage extends BaseListPage {
|
||||
newAdapter() {
|
||||
@@ -204,12 +205,11 @@ class AdapterListPage extends BaseListPage {
|
||||
return (
|
||||
<div>
|
||||
<Button style={{marginTop: "10px", marginBottom: "10px", marginRight: "10px"}} type="primary" onClick={() => this.props.history.push(`/adapters/${record.owner}/${record.name}`)}>{i18next.t("general:Edit")}</Button>
|
||||
<Popconfirm
|
||||
<PopconfirmModal
|
||||
title={i18next.t("general:Sure to delete") + `: ${record.name} ?`}
|
||||
onConfirm={() => this.deleteAdapter(index)}
|
||||
>
|
||||
<Button style={{marginBottom: "10px"}} type="primary" danger>{i18next.t("general:Delete")}</Button>
|
||||
</Popconfirm>
|
||||
</PopconfirmModal>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
@@ -16,7 +16,7 @@ import React, {Component} from "react";
|
||||
import "./App.less";
|
||||
import {Helmet} from "react-helmet";
|
||||
import * as Setting from "./Setting";
|
||||
import {StyleProvider} from "@ant-design/cssinjs";
|
||||
import {StyleProvider, legacyLogicalPropertiesTransformer} from "@ant-design/cssinjs";
|
||||
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";
|
||||
@@ -730,7 +730,7 @@ class App extends Component {
|
||||
},
|
||||
algorithm: Setting.getAlgorithm(this.state.themeAlgorithm),
|
||||
}}>
|
||||
<StyleProvider hashPriority="high">
|
||||
<StyleProvider hashPriority="high" transformers={[legacyLogicalPropertiesTransformer]}>
|
||||
{
|
||||
this.renderPage()
|
||||
}
|
||||
|
@@ -14,13 +14,14 @@
|
||||
|
||||
import React from "react";
|
||||
import {Link} from "react-router-dom";
|
||||
import {Button, Col, List, Popconfirm, Row, Table, Tooltip} from "antd";
|
||||
import {Button, Col, List, Row, Table, Tooltip} from "antd";
|
||||
import {EditOutlined} from "@ant-design/icons";
|
||||
import moment from "moment";
|
||||
import * as Setting from "./Setting";
|
||||
import * as ApplicationBackend from "./backend/ApplicationBackend";
|
||||
import i18next from "i18next";
|
||||
import BaseListPage from "./BaseListPage";
|
||||
import PopconfirmModal from "./PopconfirmModal";
|
||||
|
||||
class ApplicationListPage extends BaseListPage {
|
||||
constructor(props) {
|
||||
@@ -232,13 +233,12 @@ class ApplicationListPage extends BaseListPage {
|
||||
return (
|
||||
<div>
|
||||
<Button style={{marginTop: "10px", marginBottom: "10px", marginRight: "10px"}} type="primary" onClick={() => this.props.history.push(`/applications/${record.organization}/${record.name}`)}>{i18next.t("general:Edit")}</Button>
|
||||
<Popconfirm
|
||||
<PopconfirmModal
|
||||
title={i18next.t("general:Sure to delete") + `: ${record.name} ?`}
|
||||
onConfirm={() => this.deleteApplication(index)}
|
||||
disabled={record.name === "app-built-in"}
|
||||
>
|
||||
<Button style={{marginBottom: "10px"}} disabled={record.name === "app-built-in"} type="primary" danger>{i18next.t("general:Delete")}</Button>
|
||||
</Popconfirm>
|
||||
</PopconfirmModal>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
@@ -14,12 +14,13 @@
|
||||
|
||||
import React from "react";
|
||||
import {Link} from "react-router-dom";
|
||||
import {Button, Popconfirm, Table} from "antd";
|
||||
import {Button, Table} from "antd";
|
||||
import moment from "moment";
|
||||
import * as Setting from "./Setting";
|
||||
import * as CertBackend from "./backend/CertBackend";
|
||||
import i18next from "i18next";
|
||||
import BaseListPage from "./BaseListPage";
|
||||
import PopconfirmModal from "./PopconfirmModal";
|
||||
|
||||
class CertListPage extends BaseListPage {
|
||||
newCert() {
|
||||
@@ -168,12 +169,11 @@ class CertListPage extends BaseListPage {
|
||||
return (
|
||||
<div>
|
||||
<Button style={{marginTop: "10px", marginBottom: "10px", marginRight: "10px"}} type="primary" onClick={() => this.props.history.push(`/certs/${record.name}`)}>{i18next.t("general:Edit")}</Button>
|
||||
<Popconfirm
|
||||
<PopconfirmModal
|
||||
title={i18next.t("general:Sure to delete") + `: ${record.name} ?`}
|
||||
onConfirm={() => this.deleteCert(index)}
|
||||
>
|
||||
<Button style={{marginBottom: "10px"}} type="primary" danger>{i18next.t("general:Delete")}</Button>
|
||||
</Popconfirm>
|
||||
</PopconfirmModal>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
@@ -13,7 +13,7 @@
|
||||
// limitations under the License.
|
||||
|
||||
import React from "react";
|
||||
import {Button, Card, Col, Input, InputNumber, Row, Select} from "antd";
|
||||
import {Button, Card, Col, Input, InputNumber, Row, Select, Switch} from "antd";
|
||||
import {EyeInvisibleOutlined, EyeTwoTone} from "@ant-design/icons";
|
||||
import * as LddpBackend from "./backend/LdapBackend";
|
||||
import * as OrganizationBackend from "./backend/OrganizationBackend";
|
||||
@@ -83,7 +83,12 @@ class LdapEditPage extends React.Component {
|
||||
<Card size="small" title={
|
||||
<div>
|
||||
{i18next.t("ldap:Edit LDAP")}
|
||||
<Button type="primary" onClick={() => this.submitLdapEdit()}>{i18next.t("general:Save")}</Button>
|
||||
<Button onClick={() => this.submitLdapEdit()}>{i18next.t("general:Save")}</Button>
|
||||
<Button style={{marginLeft: "20px"}} type="primary" onClick={() => this.submitLdapEdit(true)}>{i18next.t("general:Save & Exit")}</Button>
|
||||
<Button style={{marginLeft: "20px"}}
|
||||
onClick={() => Setting.goToLink(`/ldap/sync/${this.state.organizationName}/${this.state.ldapId}`)}>
|
||||
{i18next.t("ldap:Sync")} LDAP
|
||||
</Button>
|
||||
</div>
|
||||
} style={{marginLeft: "5px"}} type="inner">
|
||||
<Row style={{marginTop: "10px"}}>
|
||||
@@ -141,6 +146,16 @@ class LdapEditPage extends React.Component {
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{lineHeight: "32px", textAlign: "right", paddingRight: "25px"}} span={3}>
|
||||
{Setting.getLabel(i18next.t("ldap:Enable SSL"), i18next.t("ldap:Enable SSL - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={21} >
|
||||
<Switch checked={this.state.ldap.enableSsl} onChange={checked => {
|
||||
this.updateLdapField("enableSsl", checked);
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}}>
|
||||
<Col style={{lineHeight: "32px", textAlign: "right", paddingRight: "25px"}} span={3}>
|
||||
{Setting.getLabel(i18next.t("ldap:Base DN"), i18next.t("ldap:Base DN - Tooltip"))} :
|
||||
@@ -190,14 +205,18 @@ class LdapEditPage extends React.Component {
|
||||
);
|
||||
}
|
||||
|
||||
submitLdapEdit() {
|
||||
submitLdapEdit(willExist) {
|
||||
LddpBackend.updateLdap(this.state.ldap)
|
||||
.then((res) => {
|
||||
if (res.status === "ok") {
|
||||
Setting.showMessage("success", "Update LDAP server success");
|
||||
this.setState((prevState) => {
|
||||
prevState.ldap = res.data2;
|
||||
this.setState({
|
||||
organizationName: this.state.ldap.owner,
|
||||
});
|
||||
|
||||
if (willExist) {
|
||||
this.props.history.push(`/organizations/${this.state.organizationName}`);
|
||||
}
|
||||
} else {
|
||||
Setting.showMessage("error", res.msg);
|
||||
}
|
||||
@@ -210,25 +229,13 @@ class LdapEditPage extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<Row style={{width: "100%"}}>
|
||||
<Col span={1}>
|
||||
</Col>
|
||||
<Col span={22}>
|
||||
{
|
||||
this.state.ldap !== null ? this.renderLdap() : null
|
||||
}
|
||||
</Col>
|
||||
<Col span={1}>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{margin: 10}}>
|
||||
<Col span={2}>
|
||||
</Col>
|
||||
<Col span={18}>
|
||||
<Button type="primary" size="large"
|
||||
onClick={() => this.submitLdapEdit()}>{i18next.t("general:Save")}</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
{
|
||||
this.state.ldap !== null ? this.renderLdap() : null
|
||||
}
|
||||
<div style={{marginTop: "20px", marginLeft: "40px"}}>
|
||||
<Button size="large" onClick={() => this.submitLdapEdit()}>{i18next.t("general:Save")}</Button>
|
||||
<Button style={{marginLeft: "20px"}} type="primary" size="large" onClick={() => this.submitLdapEdit(true)}>{i18next.t("general:Save & Exit")}</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@@ -14,10 +14,11 @@
|
||||
|
||||
import React from "react";
|
||||
import {Link} from "react-router-dom";
|
||||
import {Button, Col, Popconfirm, Row, Table} from "antd";
|
||||
import {Button, Col, Row, Table} from "antd";
|
||||
import * as Setting from "./Setting";
|
||||
import * as LdapBackend from "./backend/LdapBackend";
|
||||
import i18next from "i18next";
|
||||
import PopconfirmModal from "./PopconfirmModal";
|
||||
|
||||
class LdapListPage extends React.Component {
|
||||
constructor(props) {
|
||||
@@ -139,13 +140,11 @@ class LdapListPage extends React.Component {
|
||||
onClick={() => Setting.goToLink(`/ldap/sync/${record.id}`)}>{i18next.t("ldap:Sync")}</Button>
|
||||
<Button style={{marginTop: "10px", marginBottom: "10px", marginRight: "10px"}}
|
||||
onClick={() => Setting.goToLink(`/ldap/${record.id}`)}>{i18next.t("general:Edit")}</Button>
|
||||
<Popconfirm
|
||||
<PopconfirmModal
|
||||
title={i18next.t("general:Sure to delete") + `: ${record.serverName} ?`}
|
||||
onConfirm={() => this.deleteLdap(index)}
|
||||
>
|
||||
<Button style={{marginBottom: "10px"}}
|
||||
type="primary" danger>{i18next.t("general:Delete")}</Button>
|
||||
</Popconfirm>
|
||||
</PopconfirmModal>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
@@ -81,44 +81,28 @@ class LdapSyncPage extends React.Component {
|
||||
prevState.ldap = res.data;
|
||||
return prevState;
|
||||
});
|
||||
this.getLdapUser(res.data);
|
||||
this.getLdapUser();
|
||||
} else {
|
||||
Setting.showMessage("error", res.msg);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
getLdapUser(ldap) {
|
||||
LdapBackend.getLdapUser(ldap)
|
||||
getLdapUser() {
|
||||
LdapBackend.getLdapUser(this.state.organizationName, this.state.ldapId)
|
||||
.then((res) => {
|
||||
if (res.status === "ok") {
|
||||
this.setState((prevState) => {
|
||||
prevState.users = res.data.users;
|
||||
prevState.existUuids = res.data2?.length > 0 ? res.data2 : [];
|
||||
return prevState;
|
||||
});
|
||||
this.getExistUsers(ldap.owner, res.data.users);
|
||||
} else {
|
||||
Setting.showMessage("error", res.msg);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
getExistUsers(owner, users) {
|
||||
const uuidArray = [];
|
||||
users.forEach(elem => {
|
||||
uuidArray.push(elem.uuid);
|
||||
});
|
||||
LdapBackend.checkLdapUsersExist(owner, uuidArray)
|
||||
.then((res) => {
|
||||
if (res.status === "ok") {
|
||||
this.setState(prevState => {
|
||||
prevState.existUuids = res.data?.length > 0 ? res.data : [];
|
||||
return prevState;
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
buildValArray(data, key) {
|
||||
const valTypesArray = [];
|
||||
|
||||
@@ -220,9 +204,14 @@ class LdapSyncPage extends React.Component {
|
||||
title={"Please confirm to sync selected users"}
|
||||
onConfirm={() => this.syncUsers()}
|
||||
>
|
||||
<Button type="primary" size="small"
|
||||
style={{marginLeft: "10px"}}>{i18next.t("ldap:Sync")}</Button>
|
||||
<Button type="primary" style={{marginLeft: "10px"}}>
|
||||
{i18next.t("ldap:Sync")}
|
||||
</Button>
|
||||
</Popconfirm>
|
||||
<Button style={{marginLeft: "20px"}}
|
||||
onClick={() => Setting.goToLink(`/ldap/${this.state.organizationName}/${this.state.ldapId}`)}>
|
||||
{i18next.t("general:Edit")} LDAP
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
loading={users === null}
|
||||
@@ -234,17 +223,20 @@ class LdapSyncPage extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<Row style={{width: "100%"}}>
|
||||
<Col span={1}>
|
||||
</Col>
|
||||
<Row style={{width: "100%", justifyContent: "center"}}>
|
||||
<Col span={22}>
|
||||
{
|
||||
this.renderTable(this.state.users)
|
||||
}
|
||||
</Col>
|
||||
<Col span={1}>
|
||||
</Col>
|
||||
</Row>
|
||||
<div style={{marginTop: "20px", marginLeft: "40px"}}>
|
||||
<Button style={{marginLeft: "20px"}} type="primary" size="large" onClick={() => {
|
||||
this.props.history.push(`/organizations/${this.state.organizationName}`);
|
||||
}}>
|
||||
{i18next.t("general:Save & Exit")}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@@ -13,11 +13,12 @@
|
||||
// limitations under the License.
|
||||
|
||||
import React from "react";
|
||||
import {Button, Col, Popconfirm, Row, Table} from "antd";
|
||||
import {Button, Col, Row, Table} from "antd";
|
||||
import * as Setting from "./Setting";
|
||||
import i18next from "i18next";
|
||||
import * as LdapBackend from "./backend/LdapBackend";
|
||||
import {Link} from "react-router-dom";
|
||||
import PopconfirmModal from "./PopconfirmModal";
|
||||
|
||||
class LdapTable extends React.Component {
|
||||
constructor(props) {
|
||||
@@ -57,14 +58,14 @@ class LdapTable extends React.Component {
|
||||
LdapBackend.addLdap(newLdap)
|
||||
.then((res) => {
|
||||
if (res.status === "ok") {
|
||||
Setting.showMessage("success", "Add LDAP server success");
|
||||
Setting.showMessage("success", i18next.t("general:Successfully added"));
|
||||
if (table === undefined) {
|
||||
table = [];
|
||||
}
|
||||
table = Setting.addRow(table, res.data2);
|
||||
this.updateTable(table);
|
||||
} else {
|
||||
Setting.showMessage("error", res.msg);
|
||||
Setting.showMessage("error", `${i18next.t("general:Failed to add")}: ${res.msg}`);
|
||||
}
|
||||
}
|
||||
)
|
||||
@@ -77,14 +78,13 @@ class LdapTable extends React.Component {
|
||||
LdapBackend.deleteLdap(table[i])
|
||||
.then((res) => {
|
||||
if (res.status === "ok") {
|
||||
Setting.showMessage("success", "Delete LDAP server success");
|
||||
Setting.showMessage("success", i18next.t("general:Successfully deleted"));
|
||||
table = Setting.deleteRow(table, i);
|
||||
this.updateTable(table);
|
||||
} else {
|
||||
Setting.showMessage("error", `${i18next.t("general:Failed to save")}: ${res.msg}`);
|
||||
Setting.showMessage("error", `${i18next.t("general:Failed to delete")}: ${res.msg}`);
|
||||
}
|
||||
}
|
||||
)
|
||||
})
|
||||
.catch(error => {
|
||||
Setting.showMessage("error", `Delete LDAP server failed: ${error}`);
|
||||
});
|
||||
@@ -152,18 +152,19 @@ class LdapTable extends React.Component {
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<div>
|
||||
<Button style={{marginTop: "10px", marginBottom: "10px", marginRight: "10px"}} type="primary"
|
||||
onClick={() => Setting.goToLink(`/ldap/sync/${record.owner}/${record.id}`)}>
|
||||
{i18next.t("ldap:Sync")}
|
||||
</Button>
|
||||
<Button style={{marginTop: "10px", marginBottom: "10px", marginRight: "10px"}}
|
||||
type="primary"
|
||||
onClick={() => Setting.goToLink(`/ldap/sync/${record.owner}/${record.id}`)}>{i18next.t("ldap:Sync")}</Button>
|
||||
<Button style={{marginTop: "10px", marginBottom: "10px", marginRight: "10px"}}
|
||||
onClick={() => Setting.goToLink(`/ldap/${record.owner}/${record.id}`)}>{i18next.t("general:Edit")}</Button>
|
||||
<Popconfirm
|
||||
onClick={() => Setting.goToLink(`/ldap/${record.owner}/${record.id}`)}>
|
||||
{i18next.t("general:Edit")}
|
||||
</Button>
|
||||
<PopconfirmModal
|
||||
title={i18next.t("general:Sure to delete") + `: ${record.serverName} ?`}
|
||||
onConfirm={() => this.deleteRow(table, index)}
|
||||
>
|
||||
<Button style={{marginBottom: "10px"}}
|
||||
type="primary" danger>{i18next.t("general:Delete")}</Button>
|
||||
</Popconfirm>
|
||||
</PopconfirmModal>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
@@ -14,12 +14,13 @@
|
||||
|
||||
import React from "react";
|
||||
import {Link} from "react-router-dom";
|
||||
import {Button, Popconfirm, Switch, Table} from "antd";
|
||||
import {Button, Switch, Table} from "antd";
|
||||
import moment from "moment";
|
||||
import * as Setting from "./Setting";
|
||||
import * as ModelBackend from "./backend/ModelBackend";
|
||||
import i18next from "i18next";
|
||||
import BaseListPage from "./BaseListPage";
|
||||
import PopconfirmModal from "./PopconfirmModal";
|
||||
|
||||
class ModelListPage extends BaseListPage {
|
||||
newModel() {
|
||||
@@ -142,12 +143,11 @@ class ModelListPage extends BaseListPage {
|
||||
<div>
|
||||
<Button style={{marginTop: "10px", marginBottom: "10px", marginRight: "10px"}} type="primary"
|
||||
onClick={() => this.props.history.push(`/models/${record.owner}/${record.name}`)}>{i18next.t("general:Edit")}</Button>
|
||||
<Popconfirm
|
||||
<PopconfirmModal
|
||||
title={i18next.t("general:Sure to delete") + `: ${record.name} ?`}
|
||||
onConfirm={() => this.deleteModel(index)}
|
||||
>
|
||||
<Button style={{marginBottom: "10px"}} type="primary" danger>{i18next.t("general:Delete")}</Button>
|
||||
</Popconfirm>
|
||||
</PopconfirmModal>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
@@ -14,12 +14,13 @@
|
||||
|
||||
import React from "react";
|
||||
import {Link} from "react-router-dom";
|
||||
import {Button, Popconfirm, Switch, Table} from "antd";
|
||||
import {Button, Switch, Table} from "antd";
|
||||
import moment from "moment";
|
||||
import * as Setting from "./Setting";
|
||||
import * as OrganizationBackend from "./backend/OrganizationBackend";
|
||||
import i18next from "i18next";
|
||||
import BaseListPage from "./BaseListPage";
|
||||
import PopconfirmModal from "./PopconfirmModal";
|
||||
|
||||
class OrganizationListPage extends BaseListPage {
|
||||
newOrganization() {
|
||||
@@ -226,13 +227,12 @@ class OrganizationListPage extends BaseListPage {
|
||||
<div>
|
||||
<Button style={{marginTop: "10px", marginBottom: "10px", marginRight: "10px"}} type="primary" onClick={() => this.props.history.push(`/organizations/${record.name}/users`)}>{i18next.t("general:Users")}</Button>
|
||||
<Button style={{marginTop: "10px", marginBottom: "10px", marginRight: "10px"}} onClick={() => this.props.history.push(`/organizations/${record.name}`)}>{i18next.t("general:Edit")}</Button>
|
||||
<Popconfirm
|
||||
<PopconfirmModal
|
||||
title={i18next.t("general:Sure to delete") + `: ${record.name} ?`}
|
||||
onConfirm={() => this.deleteOrganization(index)}
|
||||
disabled={record.name === "built-in"}
|
||||
>
|
||||
<Button style={{marginBottom: "10px"}} disabled={record.name === "built-in"} type="primary" danger>{i18next.t("general:Delete")}</Button>
|
||||
</Popconfirm>
|
||||
</PopconfirmModal>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
@@ -14,13 +14,14 @@
|
||||
|
||||
import React from "react";
|
||||
import {Link} from "react-router-dom";
|
||||
import {Button, Popconfirm, Table} from "antd";
|
||||
import {Button, Table} from "antd";
|
||||
import moment from "moment";
|
||||
import * as Setting from "./Setting";
|
||||
import * as PaymentBackend from "./backend/PaymentBackend";
|
||||
import i18next from "i18next";
|
||||
import BaseListPage from "./BaseListPage";
|
||||
import * as Provider from "./auth/Provider";
|
||||
import PopconfirmModal from "./PopconfirmModal";
|
||||
|
||||
class PaymentListPage extends BaseListPage {
|
||||
newPayment() {
|
||||
@@ -222,12 +223,11 @@ class PaymentListPage extends BaseListPage {
|
||||
<div>
|
||||
<Button style={{marginTop: "10px", marginBottom: "10px", marginRight: "10px"}} onClick={() => this.props.history.push(`/payments/${record.name}/result`)}>{i18next.t("payment:Result")}</Button>
|
||||
<Button style={{marginTop: "10px", marginBottom: "10px", marginRight: "10px"}} type="primary" onClick={() => this.props.history.push(`/payments/${record.name}`)}>{i18next.t("general:Edit")}</Button>
|
||||
<Popconfirm
|
||||
<PopconfirmModal
|
||||
title={i18next.t("general:Sure to delete") + `: ${record.name} ?`}
|
||||
onConfirm={() => this.deletePayment(index)}
|
||||
>
|
||||
<Button style={{marginBottom: "10px"}} type="primary" danger>{i18next.t("general:Delete")}</Button>
|
||||
</Popconfirm>
|
||||
</PopconfirmModal>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
@@ -14,12 +14,13 @@
|
||||
|
||||
import React from "react";
|
||||
import {Link} from "react-router-dom";
|
||||
import {Button, Popconfirm, Switch, Table} from "antd";
|
||||
import {Button, Switch, Table} from "antd";
|
||||
import moment from "moment";
|
||||
import * as Setting from "./Setting";
|
||||
import * as PermissionBackend from "./backend/PermissionBackend";
|
||||
import i18next from "i18next";
|
||||
import BaseListPage from "./BaseListPage";
|
||||
import PopconfirmModal from "./PopconfirmModal";
|
||||
|
||||
class PermissionListPage extends BaseListPage {
|
||||
newPermission() {
|
||||
@@ -300,12 +301,11 @@ class PermissionListPage extends BaseListPage {
|
||||
return (
|
||||
<div>
|
||||
<Button style={{marginTop: "10px", marginBottom: "10px", marginRight: "10px"}} type="primary" onClick={() => this.props.history.push(`/permissions/${record.owner}/${record.name}`)}>{i18next.t("general:Edit")}</Button>
|
||||
<Popconfirm
|
||||
<PopconfirmModal
|
||||
title={i18next.t("general:Sure to delete") + `: ${record.name} ?`}
|
||||
onConfirm={() => this.deletePermission(index)}
|
||||
>
|
||||
<Button style={{marginBottom: "10px"}} type="primary" danger>{i18next.t("general:Delete")}</Button>
|
||||
</Popconfirm>
|
||||
</PopconfirmModal>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
33
web/src/PopconfirmModal.js
Normal file
33
web/src/PopconfirmModal.js
Normal file
@@ -0,0 +1,33 @@
|
||||
// Copyright 2021 The Casdoor Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import {Button, Popconfirm} from "antd";
|
||||
import i18next from "i18next";
|
||||
import React from "react";
|
||||
|
||||
export const PopconfirmModal = (props) => {
|
||||
return (
|
||||
<Popconfirm
|
||||
title={props.title}
|
||||
onConfirm={props.onConfirm}
|
||||
disabled={props.disabled}
|
||||
okText={i18next.t("user:OK")}
|
||||
cancelText={i18next.t("general:Cancel")}
|
||||
>
|
||||
<Button style={{marginBottom: "10px"}} disabled={props.disabled} type="primary" danger>{i18next.t("general:Delete")}</Button>
|
||||
</Popconfirm>
|
||||
);
|
||||
};
|
||||
|
||||
export default PopconfirmModal;
|
@@ -14,13 +14,14 @@
|
||||
|
||||
import React from "react";
|
||||
import {Link} from "react-router-dom";
|
||||
import {Button, Col, List, Popconfirm, Row, Table, Tooltip} from "antd";
|
||||
import {Button, Col, List, Row, Table, Tooltip} from "antd";
|
||||
import moment from "moment";
|
||||
import * as Setting from "./Setting";
|
||||
import * as ProductBackend from "./backend/ProductBackend";
|
||||
import i18next from "i18next";
|
||||
import BaseListPage from "./BaseListPage";
|
||||
import {EditOutlined} from "@ant-design/icons";
|
||||
import PopconfirmModal from "./PopconfirmModal";
|
||||
|
||||
class ProductListPage extends BaseListPage {
|
||||
newProduct() {
|
||||
@@ -239,12 +240,11 @@ class ProductListPage extends BaseListPage {
|
||||
<div>
|
||||
<Button style={{marginTop: "10px", marginBottom: "10px", marginRight: "10px"}} onClick={() => this.props.history.push(`/products/${record.name}/buy`)}>{i18next.t("product:Buy")}</Button>
|
||||
<Button style={{marginTop: "10px", marginBottom: "10px", marginRight: "10px"}} type="primary" onClick={() => this.props.history.push(`/products/${record.name}`)}>{i18next.t("general:Edit")}</Button>
|
||||
<Popconfirm
|
||||
<PopconfirmModal
|
||||
title={i18next.t("general:Sure to delete") + `: ${record.name} ?`}
|
||||
onConfirm={() => this.deleteProduct(index)}
|
||||
>
|
||||
<Button style={{marginBottom: "10px"}} type="primary" danger>{i18next.t("general:Delete")}</Button>
|
||||
</Popconfirm>
|
||||
</PopconfirmModal>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
@@ -14,13 +14,14 @@
|
||||
|
||||
import React from "react";
|
||||
import {Link} from "react-router-dom";
|
||||
import {Button, Popconfirm, Table} from "antd";
|
||||
import {Button, Table} from "antd";
|
||||
import moment from "moment";
|
||||
import * as Setting from "./Setting";
|
||||
import * as ProviderBackend from "./backend/ProviderBackend";
|
||||
import * as Provider from "./auth/Provider";
|
||||
import i18next from "i18next";
|
||||
import BaseListPage from "./BaseListPage";
|
||||
import PopconfirmModal from "./PopconfirmModal";
|
||||
|
||||
class ProviderListPage extends BaseListPage {
|
||||
constructor(props) {
|
||||
@@ -206,12 +207,11 @@ class ProviderListPage extends BaseListPage {
|
||||
return (
|
||||
<div>
|
||||
<Button disabled={!Setting.isAdminUser(this.props.account) && (record.owner !== this.props.account.owner)} style={{marginTop: "10px", marginBottom: "10px", marginRight: "10px"}} type="primary" onClick={() => this.props.history.push(`/providers/${record.owner}/${record.name}`)}>{i18next.t("general:Edit")}</Button>
|
||||
<Popconfirm
|
||||
<PopconfirmModal
|
||||
title={i18next.t("general:Sure to delete") + `: ${record.name} ?`}
|
||||
onConfirm={() => this.deleteProvider(index)}
|
||||
>
|
||||
<Button disabled={!Setting.isAdminUser(this.props.account) && (record.owner !== this.props.account.owner)} style={{marginBottom: "10px"}} type="primary" danger>{i18next.t("general:Delete")}</Button>
|
||||
</Popconfirm>
|
||||
</PopconfirmModal>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
@@ -13,7 +13,7 @@
|
||||
// limitations under the License.
|
||||
|
||||
import React from "react";
|
||||
import {Button, Popconfirm, Table, Upload} from "antd";
|
||||
import {Button, Table, Upload} from "antd";
|
||||
import {UploadOutlined} from "@ant-design/icons";
|
||||
import copy from "copy-to-clipboard";
|
||||
import * as Setting from "./Setting";
|
||||
@@ -21,6 +21,7 @@ import * as ResourceBackend from "./backend/ResourceBackend";
|
||||
import i18next from "i18next";
|
||||
import {Link} from "react-router-dom";
|
||||
import BaseListPage from "./BaseListPage";
|
||||
import PopconfirmModal from "./PopconfirmModal";
|
||||
|
||||
class ResourceListPage extends BaseListPage {
|
||||
constructor(props) {
|
||||
@@ -244,15 +245,13 @@ class ResourceListPage extends BaseListPage {
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<div>
|
||||
{/* <Button style={{marginTop: '10px', marginBottom: '10px', marginRight: '10px'}} type="primary" onClick={() => this.props.history.push(`/resources/${record.name}`)}>{i18next.t("general:Edit")}</Button>*/}
|
||||
<Popconfirm
|
||||
<PopconfirmModal
|
||||
title={i18next.t("general:Sure to delete") + `: ${record.name} ?`}
|
||||
onConfirm={() => this.deleteResource(index)}
|
||||
okText={i18next.t("user:OK")}
|
||||
cancelText={i18next.t("user:Cancel")}
|
||||
>
|
||||
<Button type="primary" danger>{i18next.t("general:Delete")}</Button>
|
||||
</Popconfirm>
|
||||
</PopconfirmModal>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
@@ -14,12 +14,13 @@
|
||||
|
||||
import React from "react";
|
||||
import {Link} from "react-router-dom";
|
||||
import {Button, Popconfirm, Switch, Table} from "antd";
|
||||
import {Button, Switch, Table} from "antd";
|
||||
import moment from "moment";
|
||||
import * as Setting from "./Setting";
|
||||
import * as RoleBackend from "./backend/RoleBackend";
|
||||
import i18next from "i18next";
|
||||
import BaseListPage from "./BaseListPage";
|
||||
import PopconfirmModal from "./PopconfirmModal";
|
||||
|
||||
class RoleListPage extends BaseListPage {
|
||||
newRole() {
|
||||
@@ -175,12 +176,11 @@ class RoleListPage extends BaseListPage {
|
||||
return (
|
||||
<div>
|
||||
<Button style={{marginTop: "10px", marginBottom: "10px", marginRight: "10px"}} type="primary" onClick={() => this.props.history.push(`/roles/${record.owner}/${record.name}`)}>{i18next.t("general:Edit")}</Button>
|
||||
<Popconfirm
|
||||
<PopconfirmModal
|
||||
title={i18next.t("general:Sure to delete") + `: ${record.name} ?`}
|
||||
onConfirm={() => this.deleteRole(index)}
|
||||
>
|
||||
<Button style={{marginBottom: "10px"}} type="primary" danger>{i18next.t("general:Delete")}</Button>
|
||||
</Popconfirm>
|
||||
</PopconfirmModal>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
@@ -16,9 +16,10 @@ import BaseListPage from "./BaseListPage";
|
||||
import * as Setting from "./Setting";
|
||||
import i18next from "i18next";
|
||||
import {Link} from "react-router-dom";
|
||||
import {Button, Popconfirm, Table, Tag} from "antd";
|
||||
import {Table, Tag} from "antd";
|
||||
import React from "react";
|
||||
import * as SessionBackend from "./backend/SessionBackend";
|
||||
import PopconfirmModal from "./PopconfirmModal";
|
||||
|
||||
class SessionListPage extends BaseListPage {
|
||||
|
||||
@@ -97,12 +98,11 @@ class SessionListPage extends BaseListPage {
|
||||
render: (text, record, index) => {
|
||||
return (
|
||||
<div>
|
||||
<Popconfirm
|
||||
<PopconfirmModal
|
||||
title={i18next.t("general:Sure to delete") + `: ${record.name} ?`}
|
||||
onConfirm={() => this.deleteSession(index)}
|
||||
>
|
||||
<Button style={{marginBottom: "10px"}} type="primary" danger>{i18next.t("general:Delete")}</Button>
|
||||
</Popconfirm>
|
||||
</PopconfirmModal>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
@@ -14,12 +14,13 @@
|
||||
|
||||
import React from "react";
|
||||
import {Link} from "react-router-dom";
|
||||
import {Button, Popconfirm, Switch, Table} from "antd";
|
||||
import {Button, Switch, Table} from "antd";
|
||||
import moment from "moment";
|
||||
import * as Setting from "./Setting";
|
||||
import * as SyncerBackend from "./backend/SyncerBackend";
|
||||
import i18next from "i18next";
|
||||
import BaseListPage from "./BaseListPage";
|
||||
import PopconfirmModal from "./PopconfirmModal";
|
||||
|
||||
class SyncerListPage extends BaseListPage {
|
||||
newSyncer() {
|
||||
@@ -232,12 +233,11 @@ class SyncerListPage extends BaseListPage {
|
||||
<div>
|
||||
<Button style={{marginTop: "10px", marginBottom: "10px", marginRight: "10px"}} type="primary" onClick={() => this.runSyncer(index)}>{i18next.t("general:Sync")}</Button>
|
||||
<Button style={{marginTop: "10px", marginBottom: "10px", marginRight: "10px"}} onClick={() => this.props.history.push(`/syncers/${record.name}`)}>{i18next.t("general:Edit")}</Button>
|
||||
<Popconfirm
|
||||
<PopconfirmModal
|
||||
title={i18next.t("general:Sure to delete") + `: ${record.name} ?`}
|
||||
onConfirm={() => this.deleteSyncer(index)}
|
||||
>
|
||||
<Button style={{marginBottom: "10px"}} type="primary" danger>{i18next.t("general:Delete")}</Button>
|
||||
</Popconfirm>
|
||||
</PopconfirmModal>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
@@ -23,31 +23,24 @@ class SystemInfo extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
cpuUsage: [],
|
||||
memUsed: 0,
|
||||
memTotal: 0,
|
||||
latestVersion: undefined,
|
||||
systemInfo: {cpuUsage: [], memoryUsed: 0, memoryTotal: 0},
|
||||
versionInfo: {},
|
||||
intervalId: null,
|
||||
href: "",
|
||||
loading: true,
|
||||
};
|
||||
}
|
||||
|
||||
UNSAFE_componentWillMount() {
|
||||
SystemBackend.getSystemInfo(this.props.account?.owner, this.props.account?.name).then(res => {
|
||||
SystemBackend.getSystemInfo().then(res => {
|
||||
this.setState({
|
||||
cpuUsage: res.cpu_usage,
|
||||
memUsed: res.memory_used,
|
||||
memTotal: res.memory_total,
|
||||
systemInfo: res.data,
|
||||
loading: false,
|
||||
});
|
||||
|
||||
const id = setInterval(() => {
|
||||
SystemBackend.getSystemInfo(this.props.account?.owner, this.props.account?.name).then(res => {
|
||||
SystemBackend.getSystemInfo().then(res => {
|
||||
this.setState({
|
||||
cpuUsage: res.cpu_usage,
|
||||
memUsed: res.memory_used,
|
||||
memTotal: res.memory_total,
|
||||
systemInfo: res.data,
|
||||
});
|
||||
}).catch(error => {
|
||||
Setting.showMessage("error", `System info failed to get: ${error}`);
|
||||
@@ -58,12 +51,12 @@ class SystemInfo extends React.Component {
|
||||
Setting.showMessage("error", `System info failed to get: ${error}`);
|
||||
});
|
||||
|
||||
SystemBackend.getGitHubLatestReleaseVersion().then(res => {
|
||||
const href = res && res.length >= 8 ? `https://github.com/casdoor/casdoor/commit/${res}` : "";
|
||||
const versionText = res && res.length >= 8 ? res.substring(0, 8) : i18next.t("system:Unknown Version");
|
||||
this.setState({latestVersion: versionText, href: href});
|
||||
SystemBackend.getVersionInfo().then(res => {
|
||||
this.setState({
|
||||
versionInfo: res.data,
|
||||
});
|
||||
}).catch(err => {
|
||||
Setting.showMessage("error", `get latest commit version failed: ${err}`);
|
||||
Setting.showMessage("error", `Version info failed to get: ${err}`);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -74,21 +67,25 @@ class SystemInfo extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const CPUInfo = this.state.cpuUsage?.length > 0 ?
|
||||
this.state.cpuUsage.map((usage, i) => {
|
||||
const cpuUi = this.state.systemInfo.cpuUsage?.length <= 0 ? i18next.t("system:Get CPU Usage Failed") :
|
||||
this.state.systemInfo.cpuUsage.map((usage, i) => {
|
||||
return (
|
||||
<Progress key={i} percent={Number(usage.toFixed(1))} />
|
||||
);
|
||||
}) : i18next.t("system:Get CPU Usage Failed");
|
||||
});
|
||||
|
||||
const MemInfo = (
|
||||
this.state.memUsed && this.state.memTotal && this.state.memTotal !== 0 ?
|
||||
<div>
|
||||
{Setting.getFriendlyFileSize(this.state.memUsed)} / {Setting.getFriendlyFileSize(this.state.memTotal)}
|
||||
<br /> <br />
|
||||
<Progress type="circle" percent={Number((Number(this.state.memUsed) / Number(this.state.memTotal) * 100).toFixed(2))} />
|
||||
</div> : i18next.t("system:Get Memory Usage Failed")
|
||||
);
|
||||
const memUi = this.state.systemInfo.memoryUsed && this.state.systemInfo.memoryTotal && this.state.systemInfo.memoryTotal <= 0 ? i18next.t("system:Get Memory Usage Failed") :
|
||||
<div>
|
||||
{Setting.getFriendlyFileSize(this.state.systemInfo.memoryUsed)} / {Setting.getFriendlyFileSize(this.state.systemInfo.memoryTotal)}
|
||||
<br /> <br />
|
||||
<Progress type="circle" percent={Number((Number(this.state.systemInfo.memoryUsed) / Number(this.state.systemInfo.memoryTotal) * 100).toFixed(2))} />
|
||||
</div>;
|
||||
|
||||
const link = this.state.versionInfo?.version !== "" ? `https://github.com/casdoor/casdoor/releases/tag/${this.state.versionInfo?.version}` : "";
|
||||
let versionText = this.state.versionInfo?.version !== "" ? this.state.versionInfo?.version : i18next.t("system:Unknown Version");
|
||||
if (this.state.versionInfo?.commitOffset > 0) {
|
||||
versionText += ` (ahead+${this.state.versionInfo?.commitOffset})`;
|
||||
}
|
||||
|
||||
if (!Setting.isMobile()) {
|
||||
return (
|
||||
@@ -98,25 +95,25 @@ class SystemInfo extends React.Component {
|
||||
<Row gutter={[10, 10]}>
|
||||
<Col span={12}>
|
||||
<Card title={i18next.t("system:CPU Usage")} bordered={true} style={{textAlign: "center", height: "100%"}}>
|
||||
{this.state.loading ? <Spin size="large" /> : CPUInfo}
|
||||
{this.state.loading ? <Spin size="large" /> : cpuUi}
|
||||
</Card>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Card title={i18next.t("system:Memory Usage")} bordered={true} style={{textAlign: "center", height: "100%"}}>
|
||||
{this.state.loading ? <Spin size="large" /> : MemInfo}
|
||||
{this.state.loading ? <Spin size="large" /> : memUi}
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
<Divider />
|
||||
<Card title={i18next.t("system:About Casdoor")} bordered={true} style={{textAlign: "center"}}>
|
||||
<div>{i18next.t("system:An Identity and Access Management (IAM) / Single-Sign-On (SSO) platform with web UI supporting OAuth 2.0, OIDC, SAML and CAS")}</div>
|
||||
GitHub: <a href="https://github.com/casdoor/casdoor">casdoor</a>
|
||||
GitHub: <a target="_blank" rel="noreferrer" href="https://github.com/casdoor/casdoor">Casdoor</a>
|
||||
<br />
|
||||
{i18next.t("system:Version")}: <a href={this.state.href}>{this.state.latestVersion}</a>
|
||||
{i18next.t("system:Version")}: <a target="_blank" rel="noreferrer" href={link}>{versionText}</a>
|
||||
<br />
|
||||
{i18next.t("system:Official Website")}: <a href="https://casdoor.org/">casdoor.org</a>
|
||||
{i18next.t("system:Official Website")}: <a target="_blank" rel="noreferrer" href="https://casdoor.org">https://casdoor.org</a>
|
||||
<br />
|
||||
{i18next.t("system:Community")}: <a href="https://casdoor.org/#:~:text=Casdoor%20API-,Community,-GitHub">contact us</a>
|
||||
{i18next.t("system:Community")}: <a target="_blank" rel="noreferrer" href="https://casdoor.org/#:~:text=Casdoor%20API-,Community,-GitHub">Get in Touch!</a>
|
||||
</Card>
|
||||
</Col>
|
||||
<Col span={6}></Col>
|
||||
@@ -127,24 +124,24 @@ class SystemInfo extends React.Component {
|
||||
<Row gutter={[16, 0]}>
|
||||
<Col span={24}>
|
||||
<Card title={i18next.t("system:CPU Usage")} bordered={true} style={{textAlign: "center", width: "100%"}}>
|
||||
{this.state.loading ? <Spin size="large" /> : CPUInfo}
|
||||
{this.state.loading ? <Spin size="large" /> : cpuUi}
|
||||
</Card>
|
||||
</Col>
|
||||
<Col span={24}>
|
||||
<Card title={i18next.t("system:Memory Usage")} bordered={true} style={{textAlign: "center", width: "100%"}}>
|
||||
{this.state.loading ? <Spin size="large" /> : MemInfo}
|
||||
{this.state.loading ? <Spin size="large" /> : memUi}
|
||||
</Card>
|
||||
</Col>
|
||||
<Col span={24}>
|
||||
<Card title={i18next.t("system:About Casdoor")} bordered={true} style={{textAlign: "center"}}>
|
||||
<div>{i18next.t("system:An Identity and Access Management (IAM) / Single-Sign-On (SSO) platform with web UI supporting OAuth 2.0, OIDC, SAML and CAS")}</div>
|
||||
GitHub: <a href="https://github.com/casdoor/casdoor">casdoor</a>
|
||||
GitHub: <a target="_blank" rel="noreferrer" href="https://github.com/casdoor/casdoor">Casdoor</a>
|
||||
<br />
|
||||
{i18next.t("system:Version")}: <a href={this.state.href}>{this.state.latestVersion}</a>
|
||||
{i18next.t("system:Version")}: <a target="_blank" rel="noreferrer" href={link}>{versionText}</a>
|
||||
<br />
|
||||
{i18next.t("system:Official Website")}: <a href="https://casdoor.org/">casdoor.org</a>
|
||||
{i18next.t("system:Official Website")}: <a target="_blank" rel="noreferrer" href="https://casdoor.org">https://casdoor.org</a>
|
||||
<br />
|
||||
{i18next.t("system:Community")}: <a href="https://casdoor.org/#:~:text=Casdoor%20API-,Community,-GitHub">contact us</a>
|
||||
{i18next.t("system:Community")}: <a target="_blank" rel="noreferrer" href="https://casdoor.org/#:~:text=Casdoor%20API-,Community,-GitHub">Get in Touch!</a>
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
|
@@ -14,12 +14,13 @@
|
||||
|
||||
import React from "react";
|
||||
import {Link} from "react-router-dom";
|
||||
import {Button, Popconfirm, Table} from "antd";
|
||||
import {Button, Table} from "antd";
|
||||
import moment from "moment";
|
||||
import * as Setting from "./Setting";
|
||||
import * as TokenBackend from "./backend/TokenBackend";
|
||||
import i18next from "i18next";
|
||||
import BaseListPage from "./BaseListPage";
|
||||
import PopconfirmModal from "./PopconfirmModal";
|
||||
|
||||
class TokenListPage extends BaseListPage {
|
||||
newToken() {
|
||||
@@ -201,12 +202,11 @@ class TokenListPage extends BaseListPage {
|
||||
return (
|
||||
<div>
|
||||
<Button style={{marginTop: "10px", marginBottom: "10px", marginRight: "10px"}} type="primary" onClick={() => this.props.history.push(`/tokens/${record.name}`)}>{i18next.t("general:Edit")}</Button>
|
||||
<Popconfirm
|
||||
<PopconfirmModal
|
||||
title={i18next.t("general:Sure to delete") + `: ${record.name} ?`}
|
||||
onConfirm={() => this.deleteToken(index)}
|
||||
>
|
||||
<Button style={{marginBottom: "10px"}} type="primary" danger>{i18next.t("general:Delete")}</Button>
|
||||
</Popconfirm>
|
||||
</PopconfirmModal>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
@@ -14,7 +14,7 @@
|
||||
|
||||
import React from "react";
|
||||
import {Link} from "react-router-dom";
|
||||
import {Button, Popconfirm, Switch, Table, Upload} from "antd";
|
||||
import {Button, Switch, Table, Upload} from "antd";
|
||||
import {UploadOutlined} from "@ant-design/icons";
|
||||
import moment from "moment";
|
||||
import * as OrganizationBackend from "./backend/OrganizationBackend";
|
||||
@@ -22,6 +22,7 @@ import * as Setting from "./Setting";
|
||||
import * as UserBackend from "./backend/UserBackend";
|
||||
import i18next from "i18next";
|
||||
import BaseListPage from "./BaseListPage";
|
||||
import PopconfirmModal from "./PopconfirmModal";
|
||||
|
||||
class UserListPage extends BaseListPage {
|
||||
constructor(props) {
|
||||
@@ -341,13 +342,12 @@ class UserListPage extends BaseListPage {
|
||||
return (
|
||||
<div>
|
||||
<Button style={{marginTop: "10px", marginBottom: "10px", marginRight: "10px"}} type="primary" onClick={() => this.props.history.push(`/users/${record.owner}/${record.name}`)}>{i18next.t("general:Edit")}</Button>
|
||||
<Popconfirm
|
||||
<PopconfirmModal
|
||||
title={i18next.t("general:Sure to delete") + `: ${record.name} ?`}
|
||||
onConfirm={() => this.deleteUser(index)}
|
||||
disabled={disabled}
|
||||
>
|
||||
<Button disabled={disabled} style={{marginBottom: "10px"}} type="primary" danger>{i18next.t("general:Delete")}</Button>
|
||||
</Popconfirm>
|
||||
</PopconfirmModal>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
@@ -384,7 +384,7 @@ class UserListPage extends BaseListPage {
|
||||
const field = params.searchedColumn, value = params.searchText;
|
||||
const sortField = params.sortField, sortOrder = params.sortOrder;
|
||||
this.setState({loading: true});
|
||||
if (this.state.organizationName === undefined) {
|
||||
if (this.props.match.params.organizationName === undefined) {
|
||||
(Setting.isAdminUser(this.props.account) ? UserBackend.getGlobalUsers(params.pagination.current, params.pagination.pageSize, field, value, sortField, sortOrder) : UserBackend.getUsers(this.props.account.owner, params.pagination.current, params.pagination.pageSize, field, value, sortField, sortOrder))
|
||||
.then((res) => {
|
||||
if (res.status === "ok") {
|
||||
@@ -413,7 +413,7 @@ class UserListPage extends BaseListPage {
|
||||
}
|
||||
});
|
||||
} else {
|
||||
UserBackend.getUsers(this.state.organizationName, params.pagination.current, params.pagination.pageSize, field, value, sortField, sortOrder)
|
||||
UserBackend.getUsers(this.props.match.params.organizationName, params.pagination.current, params.pagination.pageSize, field, value, sortField, sortOrder)
|
||||
.then((res) => {
|
||||
if (res.status === "ok") {
|
||||
this.setState({
|
||||
|
@@ -14,12 +14,13 @@
|
||||
|
||||
import React from "react";
|
||||
import {Link} from "react-router-dom";
|
||||
import {Button, Popconfirm, Switch, Table} from "antd";
|
||||
import {Button, Switch, Table} from "antd";
|
||||
import moment from "moment";
|
||||
import * as Setting from "./Setting";
|
||||
import * as WebhookBackend from "./backend/WebhookBackend";
|
||||
import i18next from "i18next";
|
||||
import BaseListPage from "./BaseListPage";
|
||||
import PopconfirmModal from "./PopconfirmModal";
|
||||
|
||||
class WebhookListPage extends BaseListPage {
|
||||
newWebhook() {
|
||||
@@ -197,12 +198,11 @@ class WebhookListPage extends BaseListPage {
|
||||
return (
|
||||
<div>
|
||||
<Button style={{marginTop: "10px", marginBottom: "10px", marginRight: "10px"}} type="primary" onClick={() => this.props.history.push(`/webhooks/${record.name}`)}>{i18next.t("general:Edit")}</Button>
|
||||
<Popconfirm
|
||||
<PopconfirmModal
|
||||
title={i18next.t("general:Sure to delete") + `: ${record.name} ?`}
|
||||
onConfirm={() => this.deleteWebhook(index)}
|
||||
>
|
||||
<Button style={{marginBottom: "10px"}} type="primary" danger>{i18next.t("general:Delete")}</Button>
|
||||
</Popconfirm>
|
||||
</PopconfirmModal>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
@@ -46,7 +46,6 @@ class LoginPage extends React.Component {
|
||||
username: null,
|
||||
validEmailOrPhone: false,
|
||||
validEmail: false,
|
||||
validPhone: false,
|
||||
loginMethod: "password",
|
||||
enableCaptchaModal: false,
|
||||
openCaptchaModal: false,
|
||||
@@ -427,16 +426,15 @@ class LoginPage extends React.Component {
|
||||
{
|
||||
validator: (_, value) => {
|
||||
if (this.state.loginMethod === "verificationCode") {
|
||||
if (!Setting.isValidEmail(this.state.username) && !Setting.isValidPhone(this.state.username)) {
|
||||
if (!Setting.isValidEmail(value) && !Setting.isValidPhone(value)) {
|
||||
this.setState({validEmailOrPhone: false});
|
||||
return Promise.reject(i18next.t("login:The input is not valid Email or Phone!"));
|
||||
}
|
||||
|
||||
if (Setting.isValidPhone(this.state.username)) {
|
||||
this.setState({validPhone: true});
|
||||
}
|
||||
if (Setting.isValidEmail(this.state.username)) {
|
||||
if (Setting.isValidEmail(value)) {
|
||||
this.setState({validEmail: true});
|
||||
} else {
|
||||
this.setState({validEmail: false});
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -378,7 +378,7 @@ export function getAuthUrl(application, provider, method) {
|
||||
const state = Util.getStateFromQueryParams(application.name, provider.name, method, isShortState);
|
||||
const codeChallenge = "P3S-a7dr8bgM4bF6vOyiKkKETDl16rcAzao9F8UIL1Y"; // SHA256(Base64-URL-encode("casdoor-verifier"))
|
||||
|
||||
if (provider.type === "Google" || provider.type === "GitHub" || provider.type === "QQ" || provider.type === "Facebook" || provider.type === "DingTalk"
|
||||
if (provider.type === "Google" || provider.type === "GitHub" || provider.type === "QQ" || provider.type === "Facebook"
|
||||
|| provider.type === "Weibo" || provider.type === "Gitee" || provider.type === "LinkedIn" || provider.type === "GitLab" || provider.type === "AzureAD"
|
||||
|| provider.type === "Slack" || provider.type === "Line" || provider.type === "Amazon" || provider.type === "Auth0" || provider.type === "BattleNet"
|
||||
|| provider.type === "Bitbucket" || provider.type === "Box" || provider.type === "CloudFoundry" || provider.type === "Dailymotion"
|
||||
@@ -390,6 +390,8 @@ export function getAuthUrl(application, provider, method) {
|
||||
|| provider.type === "Twitch" || provider.type === "Typetalk" || provider.type === "Uber" || provider.type === "VK" || provider.type === "Wepay"
|
||||
|| provider.type === "Xero" || provider.type === "Yahoo" || provider.type === "Yammer" || provider.type === "Yandex" || provider.type === "Zoom") {
|
||||
return `${endpoint}?client_id=${provider.clientId}&redirect_uri=${redirectUri}&scope=${scope}&response_type=code&state=${state}`;
|
||||
} else if (provider.type === "DingTalk") {
|
||||
return `${endpoint}?client_id=${provider.clientId}&redirect_uri=${redirectUri}&scope=${scope}&response_type=code&prompt=consent&state=${state}`;
|
||||
} else if (provider.type === "WeChat") {
|
||||
if (navigator.userAgent.includes("MicroMessenger")) {
|
||||
return `${authInfo[provider.type].mpEndpoint}?appid=${provider.clientId2}&redirect_uri=${redirectUri}&state=${state}&scope=${authInfo[provider.type].mpScope}&response_type=code#wechat_redirect`;
|
||||
|
@@ -370,7 +370,7 @@ class SignupPage extends React.Component {
|
||||
} else if (signupItem.name === "Phone") {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Form.Item label={i18next.t("general:Phone")} required>
|
||||
<Form.Item label={i18next.t("general:Phone")} required={required}>
|
||||
<Input.Group compact>
|
||||
<Form.Item
|
||||
name="countryCode"
|
||||
@@ -398,6 +398,10 @@ class SignupPage extends React.Component {
|
||||
},
|
||||
({getFieldValue}) => ({
|
||||
validator: (_, value) => {
|
||||
if (!required && value === "") {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
if (value !== "" && !Setting.isValidPhone(value, getFieldValue("countryCode"))) {
|
||||
this.setState({validPhone: false});
|
||||
return Promise.reject(i18next.t("signup:The input is not valid Phone!"));
|
||||
|
@@ -67,11 +67,10 @@ export function updateLdap(body) {
|
||||
}).then(res => res.json());
|
||||
}
|
||||
|
||||
export function getLdapUser(body) {
|
||||
return fetch(`${Setting.ServerUrl}/api/get-ldap-user`, {
|
||||
method: "POST",
|
||||
export function getLdapUser(owner, name) {
|
||||
return fetch(`${Setting.ServerUrl}/api/get-ldap-users?id=${owner}/${encodeURIComponent(name)}`, {
|
||||
method: "GET",
|
||||
credentials: "include",
|
||||
body: JSON.stringify(body),
|
||||
headers: {
|
||||
"Accept-Language": Setting.getAcceptLanguage(),
|
||||
},
|
||||
@@ -88,14 +87,3 @@ export function syncUsers(owner, ldapId, body) {
|
||||
},
|
||||
}).then(res => res.json());
|
||||
}
|
||||
|
||||
export function checkLdapUsersExist(owner, body) {
|
||||
return fetch(`${Setting.ServerUrl}/api/check-ldap-users-exist?owner=${owner}`, {
|
||||
method: "POST",
|
||||
credentials: "include",
|
||||
body: JSON.stringify(body),
|
||||
headers: {
|
||||
"Accept-Language": Setting.getAcceptLanguage(),
|
||||
},
|
||||
}).then(res => res.json());
|
||||
}
|
||||
|
@@ -14,8 +14,8 @@
|
||||
|
||||
import * as Setting from "../Setting";
|
||||
|
||||
export function getSystemInfo(owner, name) {
|
||||
return fetch(`${Setting.ServerUrl}/api/get-system-info?id=${owner}/${encodeURIComponent(name)}`, {
|
||||
export function getSystemInfo() {
|
||||
return fetch(`${Setting.ServerUrl}/api/get-system-info`, {
|
||||
method: "GET",
|
||||
credentials: "include",
|
||||
headers: {
|
||||
@@ -24,8 +24,8 @@ export function getSystemInfo(owner, name) {
|
||||
}).then(res => res.json());
|
||||
}
|
||||
|
||||
export function getGitHubLatestReleaseVersion() {
|
||||
return fetch(`${Setting.ServerUrl}/api/get-release`, {
|
||||
export function getVersionInfo() {
|
||||
return fetch(`${Setting.ServerUrl}/api/get-version-info`, {
|
||||
method: "GET",
|
||||
credentials: "include",
|
||||
headers: {
|
||||
|
@@ -67,7 +67,7 @@ export const SendCodeInput = (props) => {
|
||||
onChange={e => onChange(e.target.value)}
|
||||
enterButton={
|
||||
<Button style={{fontSize: 14}} type={"primary"} disabled={disabled || buttonLeftTime > 0} loading={buttonLoading}>
|
||||
{buttonLeftTime > 0 ? `${buttonLeftTime} s` : buttonLoading ? i18next.t("code:Sending Code") : i18next.t("code:Send Code")}
|
||||
{buttonLeftTime > 0 ? `${buttonLeftTime} s` : buttonLoading ? i18next.t("code:Sending") : i18next.t("code:Send Code")}
|
||||
</Button>
|
||||
}
|
||||
onSearch={() => setVisible(true)}
|
||||
|
@@ -121,7 +121,7 @@
|
||||
"Please input your phone verification code!": "Bitte geben Sie Ihren Telefon-Verifizierungscode ein!",
|
||||
"Please input your verification code!": "Bitte geben Sie Ihren Bestätigungscode ein!",
|
||||
"Send Code": "Code senden",
|
||||
"Sending Code": "Code wird gesendet",
|
||||
"Sending": "Code wird gesendet",
|
||||
"Submit and complete": "Absenden und abschließen"
|
||||
},
|
||||
"forget": {
|
||||
@@ -288,6 +288,8 @@
|
||||
"CN": "KN",
|
||||
"Edit LDAP": "LDAP bearbeiten",
|
||||
"Email": "E-Mail",
|
||||
"Enable SSL": "Enable SSL",
|
||||
"Enable SSL - Tooltip": "Enable SSL - Tooltip",
|
||||
"Group Id": "Gruppen Id",
|
||||
"ID": "ID",
|
||||
"Last Sync": "Letzter Sync",
|
||||
|
@@ -9,7 +9,7 @@
|
||||
"Failed to sync policies": "Failed to sync policies",
|
||||
"New Adapter": "New Adapter",
|
||||
"Policies": "Policies",
|
||||
"Policies - Tooltip": "Policies - Tooltip",
|
||||
"Policies - Tooltip": "CURD to the policy rules",
|
||||
"Repeated policy rules": "Repeated policy rules",
|
||||
"Sync": "Sync",
|
||||
"Sync policies successfully": "Sync policies successfully"
|
||||
@@ -17,9 +17,9 @@
|
||||
"application": {
|
||||
"Always": "Always",
|
||||
"Auto signin": "Auto signin",
|
||||
"Auto signin - Tooltip": "Auto signin - Tooltip",
|
||||
"Auto signin - Tooltip": "When a logged-in session exists in Casdoor, it is automatically used for application-side login",
|
||||
"Background URL": "Background URL",
|
||||
"Background URL - Tooltip": "Background URL - Tooltip",
|
||||
"Background URL - Tooltip": "Link to the background image of the login page",
|
||||
"Center": "Center",
|
||||
"Copy SAML metadata URL": "Copy SAML metadata URL",
|
||||
"Copy prompt page URL": "Copy prompt page URL",
|
||||
@@ -27,90 +27,90 @@
|
||||
"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 SAML compress - Tooltip": "Whether to compress SAML response messages when Casdoor is used as SAML idp",
|
||||
"Enable WebAuthn signin": "Enable WebAuthn signin",
|
||||
"Enable WebAuthn signin - Tooltip": "Enable WebAuthn signin - Tooltip",
|
||||
"Enable WebAuthn signin - Tooltip": "Whether to allow login with cell phone or email verification code",
|
||||
"Enable code signin": "Enable code signin",
|
||||
"Enable code signin - Tooltip": "Enable code signin - Tooltip",
|
||||
"Enable code signin - Tooltip": "Whether to allow login with cell phone or email verification code",
|
||||
"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",
|
||||
"Enable side panel": "Enable side panel",
|
||||
"Enable signin session - Tooltip": "Enable signin session - Tooltip",
|
||||
"Enable signin session - Tooltip": "Whether Casdoor maintains a session after logging into Casdoor from the app",
|
||||
"Enable signup": "Enable signup",
|
||||
"Enable signup - Tooltip": "Enable signup - Tooltip",
|
||||
"Enable signup - Tooltip": "Whether to allow users to register",
|
||||
"Failed to log in": "Failed to log in",
|
||||
"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 CSS - Tooltip": "CSS styling of forms (e.g. adding borders and shadows)",
|
||||
"Form position": "Form position",
|
||||
"Form position - Tooltip": "Form position - Tooltip",
|
||||
"Form position - Tooltip": "Location of forms for registration, login, forgotten password, etc.",
|
||||
"Grant types": "Grant types",
|
||||
"Grant types - Tooltip": "Grant types - Tooltip",
|
||||
"Grant types - Tooltip": "Select which Grant types are allowed in the OAuth protocol",
|
||||
"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",
|
||||
"Password ON - Tooltip": "Whether to allow password login",
|
||||
"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 URL (Assertion Consumer Service POST Binding URL) - Tooltip": "Redirect URL (Assertion Consumer Service POST Binding URL)",
|
||||
"Redirect URLs": "Redirect URLs",
|
||||
"Redirect URLs - Tooltip": "Redirect URLs - Tooltip",
|
||||
"Redirect URLs - Tooltip": "List of redirected addresses after successful login",
|
||||
"Refresh token expire": "Refresh token expire",
|
||||
"Refresh token expire - Tooltip": "Refresh token expire - Tooltip",
|
||||
"Refresh token expire - Tooltip": "Refresh token expiration time",
|
||||
"Right": "Right",
|
||||
"Rule": "Rule",
|
||||
"SAML Reply URL": "SAML Reply URL",
|
||||
"SAML metadata": "SAML metadata",
|
||||
"SAML metadata - Tooltip": "SAML metadata - Tooltip",
|
||||
"SAML metadata - Tooltip": "Metadata information of SAML protocol",
|
||||
"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",
|
||||
"Side panel HTML - Tooltip": "Side panel HTML",
|
||||
"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 items - Tooltip": "Items to be filled in when registering users",
|
||||
"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 expire - Tooltip": "Access token expiration time",
|
||||
"Token format": "Token format",
|
||||
"Token format - Tooltip": "Token format - Tooltip",
|
||||
"Token format - Tooltip": "Select access token format",
|
||||
"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",
|
||||
"Bit size - Tooltip": "Secret key length",
|
||||
"Certificate": "Certificate",
|
||||
"Certificate - Tooltip": "Certificate - Tooltip",
|
||||
"Certificate - Tooltip": "The public key, configured on your server, is used to decrypt the signature",
|
||||
"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",
|
||||
"Crypto algorithm - Tooltip": "Encryption algorithm of the certificate",
|
||||
"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",
|
||||
"Expire in years - Tooltip": "Expire in years",
|
||||
"New Cert": "New Cert",
|
||||
"Private key": "Private key",
|
||||
"Private key - Tooltip": "Private key - Tooltip",
|
||||
"Private key - Tooltip": "Private key for signature generation",
|
||||
"Private key copied to clipboard successfully": "Private key copied to clipboard successfully",
|
||||
"Scope": "Scope",
|
||||
"Scope - Tooltip": "Scope - Tooltip",
|
||||
"Scope - Tooltip": "Scope of the certificate",
|
||||
"Type": "Type",
|
||||
"Type - Tooltip": "Type - Tooltip"
|
||||
"Type - Tooltip": "Type of certificate"
|
||||
},
|
||||
"code": {
|
||||
"Code You Received": "Code You Received",
|
||||
@@ -121,7 +121,7 @@
|
||||
"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",
|
||||
"Sending": "Sending",
|
||||
"Submit and complete": "Submit and complete"
|
||||
},
|
||||
"forget": {
|
||||
@@ -140,120 +140,120 @@
|
||||
"general": {
|
||||
"Action": "Action",
|
||||
"Adapter": "Adapter",
|
||||
"Adapter - Tooltip": "Adapter - Tooltip",
|
||||
"Adapter - Tooltip": "Table name of the policy store",
|
||||
"Adapters": "Adapters",
|
||||
"Add": "Add",
|
||||
"Affiliation URL": "Affiliation URL",
|
||||
"Affiliation URL - Tooltip": "Affiliation URL - Tooltip",
|
||||
"Affiliation URL - Tooltip": "Affiliation URL",
|
||||
"Application": "Application",
|
||||
"Applications": "Applications",
|
||||
"Applications that require authentication": "Applications that require authentication",
|
||||
"Avatar": "Avatar",
|
||||
"Avatar - Tooltip": "Avatar - Tooltip",
|
||||
"Avatar - Tooltip": "Avatar to show to others",
|
||||
"Back Home": "Back Home",
|
||||
"Cancel": "Cancel",
|
||||
"Captcha": "Captcha",
|
||||
"Cert": "Cert",
|
||||
"Cert - Tooltip": "Cert - Tooltip",
|
||||
"Cert - Tooltip": "The public key certificate that needs to be verified by the client SDK corresponding to this application",
|
||||
"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 application - Tooltip": "Default application",
|
||||
"Default avatar": "Default avatar",
|
||||
"Default avatar - Tooltip": "Default avatar - Tooltip",
|
||||
"Default avatar - Tooltip": "Default avatar",
|
||||
"Delete": "Delete",
|
||||
"Description": "Description",
|
||||
"Description - Tooltip": "Description - Tooltip",
|
||||
"Description - Tooltip": "Descriptive information related to this",
|
||||
"Display name": "Display name",
|
||||
"Display name - Tooltip": "Display name - Tooltip",
|
||||
"Display name - Tooltip": "The name displayed, it can be repeated",
|
||||
"Down": "Down",
|
||||
"Edit": "Edit",
|
||||
"Email": "Email",
|
||||
"Email - Tooltip": "Email - Tooltip",
|
||||
"Email - Tooltip": "Email address",
|
||||
"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",
|
||||
"Favicon - Tooltip": "Favicon icons for the website",
|
||||
"First name": "First name",
|
||||
"Forget URL": "Forget URL",
|
||||
"Forget URL - Tooltip": "Forget URL - Tooltip",
|
||||
"Forget URL - Tooltip": "Forgot password URL",
|
||||
"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",
|
||||
"Home - Tooltip": "Home page of the application",
|
||||
"ID": "ID",
|
||||
"ID - Tooltip": "ID - Tooltip",
|
||||
"ID - Tooltip": "Unique random string",
|
||||
"Is enabled": "Is enabled",
|
||||
"Is enabled - Tooltip": "Is enabled - Tooltip",
|
||||
"Is enabled - Tooltip": "Set whether it can use",
|
||||
"LDAPs": "LDAPs",
|
||||
"LDAPs - Tooltip": "LDAPs - Tooltip",
|
||||
"LDAPs - Tooltip": "LDAP servers",
|
||||
"Languages": "Languages",
|
||||
"Languages - Tooltip": "Languages - Tooltip",
|
||||
"Languages - Tooltip": "Available languages",
|
||||
"Last name": "Last name",
|
||||
"Logo": "Logo",
|
||||
"Logo - Tooltip": "Logo - Tooltip",
|
||||
"Logo - Tooltip": "Icons that the application presents to the outside world",
|
||||
"Master password": "Master password",
|
||||
"Master password - Tooltip": "Master password - Tooltip",
|
||||
"Master password - Tooltip": "Can be used to log in to all users under the organization and facilitate administrators to log in as that user to solve technical problems",
|
||||
"Menu": "Menu",
|
||||
"Method": "Method",
|
||||
"Model": "Model",
|
||||
"Model - Tooltip": "Model - Tooltip",
|
||||
"Model - Tooltip": "Select one model belonging to the organization",
|
||||
"Models": "Models",
|
||||
"Name": "Name",
|
||||
"Name - Tooltip": "Name - Tooltip",
|
||||
"Name - Tooltip": "Unique, string-based ID",
|
||||
"OAuth providers": "OAuth providers",
|
||||
"Organization": "Organization",
|
||||
"Organization - Tooltip": "Organization - Tooltip",
|
||||
"Organization - Tooltip": "Select one from the organizations",
|
||||
"Organizations": "Organizations",
|
||||
"Password": "Password",
|
||||
"Password - Tooltip": "Password - Tooltip",
|
||||
"Password - Tooltip": "Make sure the password is correct",
|
||||
"Password salt": "Password salt",
|
||||
"Password salt - Tooltip": "Password salt - Tooltip",
|
||||
"Password salt - Tooltip": "Random parameters for password encryption",
|
||||
"Password type": "Password type",
|
||||
"Password type - Tooltip": "Password type - Tooltip",
|
||||
"Password type - Tooltip": "Form of password storage in the database",
|
||||
"Payments": "Payments",
|
||||
"Permissions": "Permissions",
|
||||
"Permissions - Tooltip": "Permissions - Tooltip",
|
||||
"Permissions - Tooltip": "Permissions owned",
|
||||
"Phone": "Phone",
|
||||
"Phone - Tooltip": "Phone - Tooltip",
|
||||
"Phone - Tooltip": "Phone number",
|
||||
"Preview": "Preview",
|
||||
"Preview - Tooltip": "Preview - Tooltip",
|
||||
"Preview - Tooltip": "Preview screen",
|
||||
"Products": "Products",
|
||||
"Provider": "Provider",
|
||||
"Provider - Tooltip": "Provider - Tooltip",
|
||||
"Provider - Tooltip": "Payment providers, such as paypel",
|
||||
"Providers": "Providers",
|
||||
"Providers - Tooltip": "Providers - Tooltip",
|
||||
"Providers - Tooltip": "Configuration providers such as OAuth, SMS, storage",
|
||||
"Real name": "Real name",
|
||||
"Records": "Records",
|
||||
"Request URI": "Request URI",
|
||||
"Resources": "Resources",
|
||||
"Roles": "Roles",
|
||||
"Roles - Tooltip": "Roles - Tooltip",
|
||||
"Roles - Tooltip": "Roles owned",
|
||||
"Save": "Save",
|
||||
"Save & Exit": "Save & Exit",
|
||||
"Session ID": "Session ID",
|
||||
"Sessions": "Sessions",
|
||||
"Signin URL": "Signin URL",
|
||||
"Signin URL - Tooltip": "Signin URL - Tooltip",
|
||||
"Signin URL - Tooltip": "User's login address",
|
||||
"Signup URL": "Signup URL",
|
||||
"Signup URL - Tooltip": "Signup URL - Tooltip",
|
||||
"Signup URL - Tooltip": "Registration address displayed to users",
|
||||
"Signup application": "Signup application",
|
||||
"Signup application - Tooltip": "Signup application - Tooltip",
|
||||
"Signup application - Tooltip": "Which application the user registered through when registering",
|
||||
"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",
|
||||
"State - Tooltip": "State",
|
||||
"Successfully added": "Successfully added",
|
||||
"Successfully deleted": "Successfully deleted",
|
||||
"Successfully saved": "Successfully saved",
|
||||
"Supported country codes": "Supported country codes",
|
||||
"Supported country codes - Tooltip": "Supported country codes - Tooltip",
|
||||
"Supported country codes - Tooltip": "Cell phone number prefix, used to distinguish between countries or regions",
|
||||
"Sure to delete": "Sure to delete",
|
||||
"Swagger": "Swagger",
|
||||
"Sync": "Sync",
|
||||
@@ -263,13 +263,13 @@
|
||||
"Timestamp": "Timestamp",
|
||||
"Tokens": "Tokens",
|
||||
"URL": "URL",
|
||||
"URL - Tooltip": "URL - Tooltip",
|
||||
"URL - Tooltip": "URL Link",
|
||||
"Up": "Up",
|
||||
"User": "User",
|
||||
"User - Tooltip": "User - Tooltip",
|
||||
"User - Tooltip": "Make sure the username is spelled correctly",
|
||||
"User containers": "User containers",
|
||||
"User type": "User type",
|
||||
"User type - Tooltip": "User type - Tooltip",
|
||||
"User type - Tooltip": "User roles with different privileges",
|
||||
"Users": "Users",
|
||||
"Users under all organizations": "Users under all organizations",
|
||||
"Webhooks": "Webhooks",
|
||||
@@ -278,27 +278,29 @@
|
||||
"ldap": {
|
||||
"Address": "Address",
|
||||
"Admin": "Admin",
|
||||
"Admin - Tooltip": "Admin - Tooltip",
|
||||
"Admin - Tooltip": "CN or ID of the LDAP server administrator",
|
||||
"Admin Password": "Admin Password",
|
||||
"Admin Password - Tooltip": "Admin Password - Tooltip",
|
||||
"Admin Password - Tooltip": "LDAP server administrator password",
|
||||
"Auto Sync": "Auto Sync",
|
||||
"Auto Sync - Tooltip": "Auto Sync - Tooltip",
|
||||
"Auto Sync - Tooltip": "Auto-sync configuration, disabled at 0",
|
||||
"Base DN": "Base DN",
|
||||
"Base DN - Tooltip": "Base DN - Tooltip",
|
||||
"Base DN - Tooltip": "Base DN during LDAP search",
|
||||
"CN": "CN",
|
||||
"Edit LDAP": "Edit LDAP",
|
||||
"Email": "Email",
|
||||
"Enable SSL": "Enable SSL",
|
||||
"Enable SSL - Tooltip": "Enable SSL - Tooltip",
|
||||
"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 Host - Tooltip": "LDAP server address",
|
||||
"Server Name": "Server Name",
|
||||
"Server Name - Tooltip": "Server Name - Tooltip",
|
||||
"Server Name - Tooltip": "LDAP server configuration display name",
|
||||
"Server Port": "Server Port",
|
||||
"Server Port - Tooltip": "Server Port - Tooltip",
|
||||
"Server Port - Tooltip": "LDAP server port",
|
||||
"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"
|
||||
@@ -313,7 +315,7 @@
|
||||
"No account?": "No account?",
|
||||
"Or sign in with another account": "Or sign in with another account",
|
||||
"Password": "Password",
|
||||
"Password - Tooltip": "Password - Tooltip",
|
||||
"Password - Tooltip": "Make sure the password is correct",
|
||||
"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!",
|
||||
@@ -334,108 +336,108 @@
|
||||
"model": {
|
||||
"Edit Model": "Edit Model",
|
||||
"Model text": "Model text",
|
||||
"Model text - Tooltip": "Model text - Tooltip",
|
||||
"Model text - Tooltip": "Casbin Access Control Model",
|
||||
"New Model": "New Model"
|
||||
},
|
||||
"organization": {
|
||||
"Account items": "Account items",
|
||||
"Account items - Tooltip": "Account items - Tooltip",
|
||||
"Account items - Tooltip": "Items in the Personal settings page",
|
||||
"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",
|
||||
"Is profile public - Tooltip": "When closed, only global administrators or users from the same organization can access the user home page",
|
||||
"Modify rule": "Modify rule",
|
||||
"New Organization": "New Organization",
|
||||
"Soft deletion": "Soft deletion",
|
||||
"Soft deletion - Tooltip": "Soft deletion - Tooltip",
|
||||
"Soft deletion - Tooltip": "When enabled, deletion of user information will not be completely cleared in the database, but will be marked as deleted",
|
||||
"Tags": "Tags",
|
||||
"Tags - Tooltip": "Tags - Tooltip",
|
||||
"The user's initScore - Tooltip": "The user's initScore - Tooltip",
|
||||
"Tags - Tooltip": "Collection of user-selectable tags",
|
||||
"The user's initScore - Tooltip": "User's initial points",
|
||||
"View rule": "View rule",
|
||||
"Visible": "Visible",
|
||||
"Website URL": "Website URL",
|
||||
"Website URL - Tooltip": "Website URL - Tooltip"
|
||||
"Website URL - Tooltip": "Website URL"
|
||||
},
|
||||
"payment": {
|
||||
"Confirm your invoice information": "Confirm your invoice information",
|
||||
"Currency": "Currency",
|
||||
"Currency - Tooltip": "Currency - Tooltip",
|
||||
"Currency - Tooltip": "Payment Currency",
|
||||
"Download Invoice": "Download Invoice",
|
||||
"Edit Payment": "Edit Payment",
|
||||
"Individual": "Individual",
|
||||
"Invoice URL": "Invoice URL",
|
||||
"Invoice URL - Tooltip": "Invoice URL - Tooltip",
|
||||
"Invoice URL - Tooltip": "URL for downloading the invoice",
|
||||
"Invoice actions": "Invoice actions",
|
||||
"Invoice actions - Tooltip": "Invoice actions - Tooltip",
|
||||
"Invoice actions - Tooltip": "Operation includes both invoicing and downloading invoices",
|
||||
"Invoice remark": "Invoice remark",
|
||||
"Invoice remark - Tooltip": "Invoice remark - Tooltip",
|
||||
"Invoice remark - Tooltip": "Remarks no more than 50 words",
|
||||
"Invoice tax ID": "Invoice tax ID",
|
||||
"Invoice tax ID - Tooltip": "Invoice tax ID - Tooltip",
|
||||
"Invoice tax ID - Tooltip": "When the invoicing type is unit, the unit taxpayer identification number must be entered; when the invoicing type is individual, it is not necessary to fill in",
|
||||
"Invoice title": "Invoice title",
|
||||
"Invoice title - Tooltip": "Invoice title - Tooltip",
|
||||
"Invoice title - Tooltip": "When the invoicing type is unit, the name of the unit can be entered in the invoice payable; when the invoicing type is individual, the system automatically fills in the name of the contributor",
|
||||
"Invoice type": "Invoice type",
|
||||
"Invoice type - Tooltip": "Invoice type - Tooltip",
|
||||
"Invoice type - Tooltip": "Invoicing type can be personal or unit",
|
||||
"Issue Invoice": "Issue Invoice",
|
||||
"Message": "Message",
|
||||
"Message - Tooltip": "Message - Tooltip",
|
||||
"Message - Tooltip": "Payment processing result message",
|
||||
"New Payment": "New Payment",
|
||||
"Organization": "Organization",
|
||||
"Person Email": "Person Email",
|
||||
"Person Email - Tooltip": "Person Email - Tooltip",
|
||||
"Person Email - Tooltip": "Person Email",
|
||||
"Person ID card": "Person ID card",
|
||||
"Person ID card - Tooltip": "Person ID card - Tooltip",
|
||||
"Person ID card - Tooltip": "ID number of the payer",
|
||||
"Person name": "Person name",
|
||||
"Person name - Tooltip": "Person name - Tooltip",
|
||||
"Person name - Tooltip": "Name of the payer",
|
||||
"Person phone": "Person phone",
|
||||
"Person phone - Tooltip": "Person phone - Tooltip",
|
||||
"Person phone - Tooltip": "The cell phone number of the payer",
|
||||
"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",
|
||||
"Price - Tooltip": "Price of payment",
|
||||
"Processing...": "Processing...",
|
||||
"Product": "Product",
|
||||
"Product - Tooltip": "Product - Tooltip",
|
||||
"Product - Tooltip": "Product Name",
|
||||
"Result": "Result",
|
||||
"Return to Website": "Return to Website",
|
||||
"State": "State",
|
||||
"State - Tooltip": "State - Tooltip",
|
||||
"State - Tooltip": "Payment Status",
|
||||
"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",
|
||||
"Type - Tooltip": "Payment method when purchasing product",
|
||||
"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",
|
||||
"Actions - Tooltip": "Authorized actions",
|
||||
"Admin": "Admin",
|
||||
"Allow": "Allow",
|
||||
"Approve time": "Approve time",
|
||||
"Approve time - Tooltip": "Approve time - Tooltip",
|
||||
"Approve time - Tooltip": "The time when the authorization was approved",
|
||||
"Approved": "Approved",
|
||||
"Approver": "Approver",
|
||||
"Approver - Tooltip": "Approver - Tooltip",
|
||||
"Approver - Tooltip": "The person who approved the authorization",
|
||||
"Deny": "Deny",
|
||||
"Edit Permission": "Edit Permission",
|
||||
"Effect": "Effect",
|
||||
"Effect - Tooltip": "Effect - Tooltip",
|
||||
"Effect - Tooltip": "Allow or reject",
|
||||
"New Permission": "New Permission",
|
||||
"Pending": "Pending",
|
||||
"Read": "Read",
|
||||
"Resource type": "Resource type",
|
||||
"Resource type - Tooltip": "Resource type - Tooltip",
|
||||
"Resource type - Tooltip": "Type of authorized resources",
|
||||
"Resources": "Resources",
|
||||
"Resources - Tooltip": "Resources - Tooltip",
|
||||
"Resources - Tooltip": "Authorized resources",
|
||||
"State": "State",
|
||||
"State - Tooltip": "State - Tooltip",
|
||||
"State - Tooltip": "The current statue of the authorization",
|
||||
"Submitter": "Submitter",
|
||||
"Submitter - Tooltip": "Submitter - Tooltip",
|
||||
"Submitter - Tooltip": "The person applying for this authorization",
|
||||
"TreeNode": "TreeNode",
|
||||
"Write": "Write"
|
||||
},
|
||||
@@ -445,34 +447,34 @@
|
||||
"Buy Product": "Buy Product",
|
||||
"CNY": "CNY",
|
||||
"Currency": "Currency",
|
||||
"Currency - Tooltip": "Currency - Tooltip",
|
||||
"Currency - Tooltip": "Currency accepted for the product",
|
||||
"Description": "Description",
|
||||
"Description - Tooltip": "Description - Tooltip",
|
||||
"Description - Tooltip": "Product Description",
|
||||
"Detail": "Detail",
|
||||
"Detail - Tooltip": "Detail - Tooltip",
|
||||
"Detail - Tooltip": "Product Details",
|
||||
"Edit Product": "Edit Product",
|
||||
"I have completed the payment": "I have completed the payment",
|
||||
"Image": "Image",
|
||||
"Image - Tooltip": "Image - Tooltip",
|
||||
"Image - Tooltip": "Product Image",
|
||||
"New Product": "New Product",
|
||||
"Pay": "Pay",
|
||||
"Payment providers": "Payment providers",
|
||||
"Payment providers - Tooltip": "Payment providers - Tooltip",
|
||||
"Payment providers - Tooltip": "Providers of payment services",
|
||||
"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",
|
||||
"Price - Tooltip": "Price of the product",
|
||||
"Quantity": "Quantity",
|
||||
"Quantity - Tooltip": "Quantity - Tooltip",
|
||||
"Quantity - Tooltip": "Quantity of the product",
|
||||
"Return URL": "Return URL",
|
||||
"Return URL - Tooltip": "Return URL - Tooltip",
|
||||
"Return URL - Tooltip": "The link that jumps after payment is complete",
|
||||
"SKU": "SKU",
|
||||
"Sold": "Sold",
|
||||
"Sold - Tooltip": "Sold - Tooltip",
|
||||
"Sold - Tooltip": "Number of this product sold",
|
||||
"Tag": "Tag",
|
||||
"Tag - Tooltip": "Tag - Tooltip",
|
||||
"Tag - Tooltip": "Tag of the product",
|
||||
"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.",
|
||||
@@ -481,61 +483,61 @@
|
||||
},
|
||||
"provider": {
|
||||
"Access key": "Access key",
|
||||
"Access key - Tooltip": "Access key - Tooltip",
|
||||
"Access key - Tooltip": "Access key",
|
||||
"Agent ID": "Agent ID",
|
||||
"Agent ID - Tooltip": "Agent ID - Tooltip",
|
||||
"Agent ID - Tooltip": "Agent ID",
|
||||
"App ID": "App ID",
|
||||
"App ID - Tooltip": "App ID - Tooltip",
|
||||
"App ID - Tooltip": "App ID",
|
||||
"App key": "App key",
|
||||
"App key - Tooltip": "App key - Tooltip",
|
||||
"App key - Tooltip": "App key",
|
||||
"App secret": "App secret",
|
||||
"AppSecret - Tooltip": "AppSecret - Tooltip",
|
||||
"AppSecret - Tooltip": "AppSecret",
|
||||
"Auth URL": "Auth URL",
|
||||
"Auth URL - Tooltip": "Auth URL - Tooltip",
|
||||
"Auth URL - Tooltip": "Auth URL",
|
||||
"Bucket": "Bucket",
|
||||
"Bucket - Tooltip": "Bucket - Tooltip",
|
||||
"Bucket - Tooltip": "Name of Bucket",
|
||||
"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",
|
||||
"Category - Tooltip": "Select a category",
|
||||
"Channel No.": "Channel No.",
|
||||
"Channel No. - Tooltip": "Channel No. - Tooltip",
|
||||
"Channel No. - Tooltip": "Channel No.",
|
||||
"Client ID": "Client ID",
|
||||
"Client ID - Tooltip": "Client ID - Tooltip",
|
||||
"Client ID - Tooltip": "Client ID",
|
||||
"Client ID 2": "Client ID 2",
|
||||
"Client ID 2 - Tooltip": "Client ID 2 - Tooltip",
|
||||
"Client ID 2 - Tooltip": "The second Client ID",
|
||||
"Client secret": "Client secret",
|
||||
"Client secret - Tooltip": "Client secret - Tooltip",
|
||||
"Client secret - Tooltip": "Client secret",
|
||||
"Client secret 2": "Client secret 2",
|
||||
"Client secret 2 - Tooltip": "Client secret 2 - Tooltip",
|
||||
"Client secret 2 - Tooltip": "The second client secret key",
|
||||
"Copy": "Copy",
|
||||
"Disable SSL": "Disable SSL",
|
||||
"Disable SSL - Tooltip": "Disable SSL - Tooltip",
|
||||
"Disable SSL - Tooltip": "Whether to disable SSL security protocol when communicating with STMP server",
|
||||
"Domain": "Domain",
|
||||
"Domain - Tooltip": "Domain - Tooltip",
|
||||
"Domain - Tooltip": "Storage node custom domain name",
|
||||
"Edit Provider": "Edit Provider",
|
||||
"Email content": "Email content",
|
||||
"Email content - Tooltip": "Email content - Tooltip",
|
||||
"Email content - Tooltip": "Content of the email",
|
||||
"Email sent successfully": "Email sent successfully",
|
||||
"Email title": "Email title",
|
||||
"Email title - Tooltip": "Email title - Tooltip",
|
||||
"Email title - Tooltip": "Title of the email",
|
||||
"Enable QR code": "Enable QR code",
|
||||
"Enable QR code - Tooltip": "Enable QR code - Tooltip",
|
||||
"Enable QR code - Tooltip": "Enable scan code to login",
|
||||
"Endpoint": "Endpoint",
|
||||
"Endpoint (Intranet)": "Endpoint (Intranet)",
|
||||
"Host": "Host",
|
||||
"Host - Tooltip": "Host - Tooltip",
|
||||
"Host - Tooltip": "Fill in the host address and make sure you can connect",
|
||||
"IdP": "IdP",
|
||||
"IdP certificate": "IdP certificate",
|
||||
"Issuer URL": "Issuer URL",
|
||||
"Issuer URL - Tooltip": "Issuer URL - Tooltip",
|
||||
"Issuer URL - Tooltip": "Issuer URL",
|
||||
"Link copied to clipboard successfully": "Link copied to clipboard successfully",
|
||||
"Metadata": "Metadata",
|
||||
"Metadata - Tooltip": "Metadata - Tooltip",
|
||||
"Metadata - Tooltip": "Metadata",
|
||||
"Method": "Method",
|
||||
"Method - Tooltip": "Method - Tooltip",
|
||||
"Method - Tooltip": "Login behavior, QR code or silent authorization login",
|
||||
"Name": "Name",
|
||||
"New Provider": "New Provider",
|
||||
"Parse": "Parse",
|
||||
@@ -543,10 +545,10 @@
|
||||
"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",
|
||||
"Port - Tooltip": "Make sure the port is open",
|
||||
"Prompted": "Prompted",
|
||||
"Provider URL": "Provider URL",
|
||||
"Provider URL - Tooltip": "Provider URL - Tooltip",
|
||||
"Provider URL - Tooltip": "Provider URL",
|
||||
"Region ID": "Region ID",
|
||||
"Region ID - Tooltip": "Region ID - Tooltip",
|
||||
"Region endpoint for Internet": "Region endpoint for Internet",
|
||||
@@ -554,51 +556,51 @@
|
||||
"Required": "Required",
|
||||
"SAML 2.0 Endpoint (HTTP)": "SAML 2.0 Endpoint (HTTP)",
|
||||
"SMS Test": "SMS Test",
|
||||
"SMS Test - Tooltip": "SMS Test - Tooltip",
|
||||
"SMS Test - Tooltip": "Phone number for sending test SMS",
|
||||
"SMS account": "SMS account",
|
||||
"SMS account - Tooltip": "SMS account - Tooltip",
|
||||
"SMS account - Tooltip": "SMS account",
|
||||
"SMS sent successfully": "SMS sent successfully",
|
||||
"SP ACS URL": "SP ACS URL",
|
||||
"SP ACS URL - Tooltip": "SP ACS URL - Tooltip",
|
||||
"SP ACS URL - Tooltip": "SP ACS URL",
|
||||
"SP Entity ID": "SP Entity ID",
|
||||
"Scene": "Scene",
|
||||
"Scene - Tooltip": "Scene - Tooltip",
|
||||
"Scene - Tooltip": "Scene",
|
||||
"Scope": "Scope",
|
||||
"Scope - Tooltip": "Scope - Tooltip",
|
||||
"Scope - Tooltip": "Scope",
|
||||
"Secret access key": "Secret access key",
|
||||
"Secret key": "Secret key",
|
||||
"Secret key - Tooltip": "Secret key - Tooltip",
|
||||
"SecretAccessKey - Tooltip": "SecretAccessKey - Tooltip",
|
||||
"Secret key - Tooltip": "Used by the server to call the verification code provider API for verification",
|
||||
"SecretAccessKey - Tooltip": "SecretAccessKey",
|
||||
"Send Testing Email": "Send Testing Email",
|
||||
"Send Testing SMS": "Send Testing SMS",
|
||||
"Sign Name": "Sign Name",
|
||||
"Sign Name - Tooltip": "Sign Name - Tooltip",
|
||||
"Sign Name - Tooltip": "Name of the signature to be used",
|
||||
"Sign request": "Sign request",
|
||||
"Sign request - Tooltip": "Sign request - Tooltip",
|
||||
"Sign request - Tooltip": "Whether the request requires a signature",
|
||||
"Signin HTML": "Signin HTML",
|
||||
"Signin HTML - Edit": "Signin HTML - Edit",
|
||||
"Signin HTML - Tooltip": "Signin HTML - Tooltip",
|
||||
"Signin HTML - Tooltip": "Custom HTML for replacing the default login page style",
|
||||
"Signup HTML": "Signup HTML",
|
||||
"Signup HTML - Edit": "Signup HTML - Edit",
|
||||
"Signup HTML - Tooltip": "Signup HTML - Tooltip",
|
||||
"Signup HTML - Tooltip": "Custom HTML for replacing the default registration page style",
|
||||
"Site key": "Site key",
|
||||
"Site key - Tooltip": "Site key - Tooltip",
|
||||
"Site key - Tooltip": "For front-end embedded pages",
|
||||
"Sub type": "Sub type",
|
||||
"Sub type - Tooltip": "Sub type - Tooltip",
|
||||
"Sub type - Tooltip": "Sub type",
|
||||
"Template Code": "Template Code",
|
||||
"Template Code - Tooltip": "Template Code - Tooltip",
|
||||
"Template Code - Tooltip": "The code of the template used",
|
||||
"Terms of Use": "Terms of Use",
|
||||
"Terms of Use - Tooltip": "Terms of Use - Tooltip",
|
||||
"Terms of Use - Tooltip": "Terms of use to be followed by users",
|
||||
"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",
|
||||
"Test Email - Tooltip": "Address to accept test emails",
|
||||
"The prefix path of the file - Tooltip": "The prefix path of the file",
|
||||
"Token URL": "Token URL",
|
||||
"Token URL - Tooltip": "Token URL - Tooltip",
|
||||
"Token URL - Tooltip": "Token URL",
|
||||
"Type": "Type",
|
||||
"Type - Tooltip": "Type - Tooltip",
|
||||
"Type - Tooltip": "Select a type",
|
||||
"UserInfo URL": "UserInfo URL",
|
||||
"UserInfo URL - Tooltip": "UserInfo URL - Tooltip",
|
||||
"UserInfo URL - Tooltip": "UserInfo URL",
|
||||
"Visible": "Visible",
|
||||
"admin (share)": "admin (share)",
|
||||
"alertType": "alertType"
|
||||
@@ -623,11 +625,11 @@
|
||||
"Edit Role": "Edit Role",
|
||||
"New Role": "New Role",
|
||||
"Sub domains": "Sub domains",
|
||||
"Sub domains - Tooltip": "Sub domains - Tooltip",
|
||||
"Sub domains - Tooltip": "Sub domains included in the current role",
|
||||
"Sub roles": "Sub roles",
|
||||
"Sub roles - Tooltip": "Sub roles - Tooltip",
|
||||
"Sub roles - Tooltip": "Sub-roles contained in the current role",
|
||||
"Sub users": "Sub users",
|
||||
"Sub users - Tooltip": "Sub users - Tooltip"
|
||||
"Sub users - Tooltip": "Select the sub-users under the role"
|
||||
},
|
||||
"signup": {
|
||||
"Accept": "Accept",
|
||||
@@ -656,36 +658,36 @@
|
||||
"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",
|
||||
"Username - Tooltip": "Allowed characters include letters, numbers, underscores, and may not begin with a number",
|
||||
"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",
|
||||
"Affiliation table - Tooltip": "Database table name of the work unit",
|
||||
"Avatar base URL": "Avatar base URL",
|
||||
"Avatar base URL - Tooltip": "Avatar base URL - Tooltip",
|
||||
"Avatar base URL - Tooltip": "Prefix of the avatar URL",
|
||||
"Casdoor column": "Casdoor column",
|
||||
"Column name": "Column name",
|
||||
"Column type": "Column type",
|
||||
"Database": "Database",
|
||||
"Database - Tooltip": "Database - Tooltip",
|
||||
"Database - Tooltip": "The original database name",
|
||||
"Database type": "Database type",
|
||||
"Database type - Tooltip": "Database type - Tooltip",
|
||||
"Database type - Tooltip": "Database type, now support MySQL, PostgreSQL, SQL server, Oracle, SQLite 3",
|
||||
"Edit Syncer": "Edit Syncer",
|
||||
"Error text": "Error text",
|
||||
"Error text - Tooltip": "Error text - Tooltip",
|
||||
"Error text - Tooltip": "Error when synchronizer connects to database",
|
||||
"Is hashed": "Is hashed",
|
||||
"New Syncer": "New Syncer",
|
||||
"Sync interval": "Sync interval",
|
||||
"Sync interval - Tooltip": "Sync interval - Tooltip",
|
||||
"Sync interval - Tooltip": "Unit in seconds",
|
||||
"Table": "Table",
|
||||
"Table - Tooltip": "Table - Tooltip",
|
||||
"Table - Tooltip": "Name of table",
|
||||
"Table columns": "Table columns",
|
||||
"Table columns - Tooltip": "Table columns - Tooltip",
|
||||
"Table columns - Tooltip": "Columns of the table that participate in data synchronization, columns that do not participate in synchronization do not need to be added",
|
||||
"Table primary key": "Table primary key",
|
||||
"Table primary key - Tooltip": "Table primary key - Tooltip"
|
||||
"Table primary key - Tooltip": "Table primary key, such as id"
|
||||
},
|
||||
"system": {
|
||||
"About Casdoor": "About Casdoor",
|
||||
@@ -710,7 +712,7 @@
|
||||
"Is compact": "Is compact",
|
||||
"Primary color": "Primary color",
|
||||
"Theme": "Theme",
|
||||
"Theme - Tooltip": "Theme - Tooltip"
|
||||
"Theme - Tooltip": "Select a theme for your application"
|
||||
},
|
||||
"token": {
|
||||
"Access token": "Access token",
|
||||
@@ -724,40 +726,40 @@
|
||||
"user": {
|
||||
"\" + destType + \" reset": "\" + destType + \" reset",
|
||||
"3rd-party logins": "3rd-party logins",
|
||||
"3rd-party logins - Tooltip": "3rd-party logins - Tooltip",
|
||||
"3rd-party logins - Tooltip": "Login using a third-party application",
|
||||
"Address": "Address",
|
||||
"Address - Tooltip": "Address - Tooltip",
|
||||
"Address - Tooltip": "Usual residence address",
|
||||
"Affiliation": "Affiliation",
|
||||
"Affiliation - Tooltip": "Affiliation - Tooltip",
|
||||
"Affiliation - Tooltip": "Workplace, such as company name",
|
||||
"Bio": "Bio",
|
||||
"Bio - Tooltip": "Bio - Tooltip",
|
||||
"Bio - Tooltip": "Self Introduction",
|
||||
"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",
|
||||
"Country/Region - Tooltip": "Select Country/Region",
|
||||
"Edit User": "Edit User",
|
||||
"Email cannot be empty": "Email cannot be empty",
|
||||
"Empty input!": "Empty input!",
|
||||
"Homepage": "Homepage",
|
||||
"Homepage - Tooltip": "Homepage - Tooltip",
|
||||
"Homepage - Tooltip": "Link to personal homepage",
|
||||
"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 admin - Tooltip": "Is the application admin",
|
||||
"Is deleted": "Is deleted",
|
||||
"Is deleted - Tooltip": "Is deleted - Tooltip",
|
||||
"Is deleted - Tooltip": "Is the account deleted",
|
||||
"Is forbidden": "Is forbidden",
|
||||
"Is forbidden - Tooltip": "Is forbidden - Tooltip",
|
||||
"Is forbidden - Tooltip": "Is the account disabled",
|
||||
"Is global admin": "Is global admin",
|
||||
"Is global admin - Tooltip": "Is global admin - Tooltip",
|
||||
"Is global admin - Tooltip": "Is the global application",
|
||||
"Keys": "Keys",
|
||||
"Link": "Link",
|
||||
"Location": "Location",
|
||||
"Location - Tooltip": "Location - Tooltip",
|
||||
"Location - Tooltip": "City of residence",
|
||||
"Managed accounts": "Managed accounts",
|
||||
"Modify password...": "Modify password...",
|
||||
"New Email": "New Email",
|
||||
@@ -780,9 +782,9 @@
|
||||
"Set new profile picture": "Set new profile picture",
|
||||
"Set password...": "Set password...",
|
||||
"Tag": "Tag",
|
||||
"Tag - Tooltip": "Tag - Tooltip",
|
||||
"Tag - Tooltip": "User's Tags",
|
||||
"Title": "Title",
|
||||
"Title - Tooltip": "Title - Tooltip",
|
||||
"Title - Tooltip": "Position in the unit/company",
|
||||
"Two passwords you typed do not match.": "Two passwords you typed do not match.",
|
||||
"Unlink": "Unlink",
|
||||
"Upload (.xlsx)": "Upload (.xlsx)",
|
||||
@@ -793,20 +795,20 @@
|
||||
},
|
||||
"webhook": {
|
||||
"Content type": "Content type",
|
||||
"Content type - Tooltip": "Content type - Tooltip",
|
||||
"Content type - Tooltip": "Content type",
|
||||
"Edit Webhook": "Edit Webhook",
|
||||
"Events": "Events",
|
||||
"Events - Tooltip": "Events - Tooltip",
|
||||
"Events - Tooltip": "Events",
|
||||
"Headers": "Headers",
|
||||
"Headers - Tooltip": "Headers - Tooltip",
|
||||
"Headers - Tooltip": "HTTP protocol headers (key-value pairs)",
|
||||
"Is user extended": "Is user extended",
|
||||
"Is user extended - Tooltip": "Is user extended - Tooltip",
|
||||
"Is user extended - Tooltip": "Add extendedUser to JSON to extend the user field",
|
||||
"Method": "Method",
|
||||
"Method - Tooltip": "Method - Tooltip",
|
||||
"Method - Tooltip": "Http method",
|
||||
"Name": "Name",
|
||||
"New Webhook": "New Webhook",
|
||||
"URL": "URL",
|
||||
"URL - Tooltip": "URL - Tooltip",
|
||||
"URL - Tooltip": "URL",
|
||||
"Value": "Value"
|
||||
}
|
||||
}
|
||||
|
@@ -121,7 +121,7 @@
|
||||
"Please input your phone verification code!": "Ingrese su código de verificación teléfonico!",
|
||||
"Please input your verification code!": "Ingrese su código de verificación!",
|
||||
"Send Code": "Enviar código",
|
||||
"Sending Code": "Enviando código",
|
||||
"Sending": "Enviando código",
|
||||
"Submit and complete": "Enviar y completar"
|
||||
},
|
||||
"forget": {
|
||||
@@ -288,6 +288,8 @@
|
||||
"CN": "CN",
|
||||
"Edit LDAP": "Editar LDAP",
|
||||
"Email": "Email",
|
||||
"Enable SSL": "Enable SSL",
|
||||
"Enable SSL - Tooltip": "Enable SSL - Tooltip",
|
||||
"Group Id": "Group Id",
|
||||
"ID": "ID",
|
||||
"Last Sync": "Última Sincronización",
|
||||
|
@@ -121,7 +121,7 @@
|
||||
"Please input your phone verification code!": "Veuillez entrer le code de vérification de votre téléphone !",
|
||||
"Please input your verification code!": "Veuillez entrer votre code de vérification !",
|
||||
"Send Code": "Envoyer le code",
|
||||
"Sending Code": "Code d'envoi",
|
||||
"Sending": "Code d'envoi",
|
||||
"Submit and complete": "Soumettre et compléter"
|
||||
},
|
||||
"forget": {
|
||||
@@ -288,6 +288,8 @@
|
||||
"CN": "CN",
|
||||
"Edit LDAP": "Modifier LDAP",
|
||||
"Email": "Courriel",
|
||||
"Enable SSL": "Enable SSL",
|
||||
"Enable SSL - Tooltip": "Enable SSL - Tooltip",
|
||||
"Group Id": "Identifiant du groupe",
|
||||
"ID": "ID",
|
||||
"Last Sync": "Dernière synchronisation",
|
||||
|
@@ -121,7 +121,7 @@
|
||||
"Please input your phone verification code!": "電話番号を入力してください!",
|
||||
"Please input your verification code!": "認証コードを入力してください!",
|
||||
"Send Code": "コードを送信",
|
||||
"Sending Code": "コードを送信中",
|
||||
"Sending": "コードを送信中",
|
||||
"Submit and complete": "提出して完了"
|
||||
},
|
||||
"forget": {
|
||||
@@ -288,6 +288,8 @@
|
||||
"CN": "CN",
|
||||
"Edit LDAP": "LDAP を編集",
|
||||
"Email": "Eメールアドレス",
|
||||
"Enable SSL": "Enable SSL",
|
||||
"Enable SSL - Tooltip": "Enable SSL - Tooltip",
|
||||
"Group Id": "グループ ID",
|
||||
"ID": "ID",
|
||||
"Last Sync": "前回の同期",
|
||||
|
@@ -121,7 +121,7 @@
|
||||
"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",
|
||||
"Sending": "Sending",
|
||||
"Submit and complete": "Submit and complete"
|
||||
},
|
||||
"forget": {
|
||||
@@ -288,6 +288,8 @@
|
||||
"CN": "CN",
|
||||
"Edit LDAP": "Edit LDAP",
|
||||
"Email": "Email",
|
||||
"Enable SSL": "Enable SSL",
|
||||
"Enable SSL - Tooltip": "Enable SSL - Tooltip",
|
||||
"Group Id": "Group Id",
|
||||
"ID": "ID",
|
||||
"Last Sync": "Last Sync",
|
||||
|
@@ -121,7 +121,7 @@
|
||||
"Please input your phone verification code!": "Пожалуйста, введите код подтверждения!",
|
||||
"Please input your verification code!": "Пожалуйста, введите код подтверждения!",
|
||||
"Send Code": "Отправить код",
|
||||
"Sending Code": "Отправка кода",
|
||||
"Sending": "Отправка кода",
|
||||
"Submit and complete": "Отправить и завершить"
|
||||
},
|
||||
"forget": {
|
||||
@@ -288,6 +288,8 @@
|
||||
"CN": "КНР",
|
||||
"Edit LDAP": "Редактировать LDAP",
|
||||
"Email": "Почта",
|
||||
"Enable SSL": "Enable SSL",
|
||||
"Enable SSL - Tooltip": "Enable SSL - Tooltip",
|
||||
"Group Id": "ID группы",
|
||||
"ID": "ID",
|
||||
"Last Sync": "Последняя синхронизация",
|
||||
|
@@ -121,7 +121,7 @@
|
||||
"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",
|
||||
"Sending": "Sending",
|
||||
"Submit and complete": "Submit and complete"
|
||||
},
|
||||
"forget": {
|
||||
@@ -288,6 +288,8 @@
|
||||
"CN": "CN",
|
||||
"Edit LDAP": "Edit LDAP",
|
||||
"Email": "Email",
|
||||
"Enable SSL": "Enable SSL",
|
||||
"Enable SSL - Tooltip": "Enable SSL - Tooltip",
|
||||
"Group Id": "Group Id",
|
||||
"ID": "ID",
|
||||
"Last Sync": "Last Sync",
|
||||
|
@@ -90,9 +90,9 @@
|
||||
},
|
||||
"cert": {
|
||||
"Bit size": "位大小",
|
||||
"Bit size - Tooltip": "位大小 - 工具提示",
|
||||
"Bit size - Tooltip": "秘钥长度",
|
||||
"Certificate": "证书",
|
||||
"Certificate - Tooltip": "证书 - 工具提示",
|
||||
"Certificate - Tooltip": "在你的服务器上配置的公钥,用于解密签名",
|
||||
"Certificate copied to clipboard successfully": "证书已成功复制到剪贴板",
|
||||
"Copy certificate": "复制证书",
|
||||
"Copy private key": "复制私钥",
|
||||
@@ -102,15 +102,15 @@
|
||||
"Download private key": "下载私钥",
|
||||
"Edit Cert": "编辑证书",
|
||||
"Expire in years": "有效期(年)",
|
||||
"Expire in years - Tooltip": "到期年份-工具提示",
|
||||
"Expire in years - Tooltip": "到期年份",
|
||||
"New Cert": "添加证书",
|
||||
"Private key": "私钥",
|
||||
"Private key - Tooltip": "私钥 - 工具提示",
|
||||
"Private key - Tooltip": "私钥用于生成秘钥",
|
||||
"Private key copied to clipboard successfully": "私钥已成功复制到剪贴板",
|
||||
"Scope": "用途",
|
||||
"Scope - Tooltip": "范围 - 工具提示",
|
||||
"Scope - Tooltip": "证书作用范围",
|
||||
"Type": "类型",
|
||||
"Type - Tooltip": "类型 - 工具提示"
|
||||
"Type - Tooltip": "证书的类型"
|
||||
},
|
||||
"code": {
|
||||
"Code You Received": "验证码",
|
||||
@@ -121,7 +121,7 @@
|
||||
"Please input your phone verification code!": "请输入您的手机验证码!",
|
||||
"Please input your verification code!": "请输入您的验证码!",
|
||||
"Send Code": "发送验证码",
|
||||
"Sending Code": "发送中",
|
||||
"Sending": "发送中",
|
||||
"Submit and complete": "完成提交"
|
||||
},
|
||||
"forget": {
|
||||
@@ -253,7 +253,7 @@
|
||||
"Successfully deleted": "删除成功",
|
||||
"Successfully saved": "保存成功",
|
||||
"Supported country codes": "支持的国家代码",
|
||||
"Supported country codes - Tooltip": "支持发送短信的国家 - Tooltip",
|
||||
"Supported country codes - Tooltip": "支持发送短信的国家",
|
||||
"Sure to delete": "确定删除",
|
||||
"Swagger": "API文档",
|
||||
"Sync": "同步",
|
||||
@@ -288,6 +288,8 @@
|
||||
"CN": "CN",
|
||||
"Edit LDAP": "编辑LDAP",
|
||||
"Email": "电子邮件",
|
||||
"Enable SSL": "启用 SSL",
|
||||
"Enable SSL - Tooltip": "启用 SSL",
|
||||
"Group Id": "组ID",
|
||||
"ID": "ID",
|
||||
"Last Sync": "最近同步",
|
||||
|
Reference in New Issue
Block a user