Compare commits

..

1 Commits

Author SHA1 Message Date
a79a2e7e55 Revert "feat: don't send verification code if failed signin limit is reached …"
This reverts commit f2e3037bc5.
2025-03-01 12:57:11 +08:00
121 changed files with 935 additions and 3416 deletions

View File

@ -1,10 +1,10 @@
FROM --platform=$BUILDPLATFORM node:18.19.0 AS FRONT
WORKDIR /web
COPY ./web .
RUN yarn install --frozen-lockfile --network-timeout 1000000 && NODE_OPTIONS="--max-old-space-size=4096" yarn run build
RUN yarn install --frozen-lockfile --network-timeout 1000000 && yarn run build
FROM --platform=$BUILDPLATFORM golang:1.21.13 AS BACK
FROM --platform=$BUILDPLATFORM golang:1.20.12 AS BACK
WORKDIR /go/src/casdoor
COPY . .
RUN ./build.sh

View File

@ -47,7 +47,6 @@ p, *, *, GET, /api/get-app-login, *, *
p, *, *, POST, /api/logout, *, *
p, *, *, GET, /api/logout, *, *
p, *, *, POST, /api/callback, *, *
p, *, *, POST, /api/device-auth, *, *
p, *, *, GET, /api/get-account, *, *
p, *, *, GET, /api/userinfo, *, *
p, *, *, GET, /api/user, *, *

View File

@ -31,7 +31,7 @@ radiusServerPort = 1812
radiusDefaultOrganization = "built-in"
radiusSecret = "secret"
quota = {"organization": -1, "user": -1, "application": -1, "provider": -1}
logConfig = {"adapter":"file", "filename": "logs/casdoor.log", "maxdays":99999, "perm":"0770"}
logConfig = {"filename": "logs/casdoor.log", "maxdays":99999, "perm":"0770"}
initDataNewOnly = false
initDataFile = "./init_data.json"
frontendBaseDir = "../cc_0"

View File

@ -115,7 +115,7 @@ func TestGetConfigLogs(t *testing.T) {
description string
expected string
}{
{"Default log config", `{"adapter":"file", "filename": "logs/casdoor.log", "maxdays":99999, "perm":"0770"}`},
{"Default log config", `{"filename": "logs/casdoor.log", "maxdays":99999, "perm":"0770"}`},
}
err := beego.LoadAppConfig("ini", "app.conf")

View File

@ -32,7 +32,6 @@ const (
ResponseTypeIdToken = "id_token"
ResponseTypeSaml = "saml"
ResponseTypeCas = "cas"
ResponseTypeDevice = "device"
)
type Response struct {
@ -140,8 +139,6 @@ func (c *ApiController) Signup() {
invitationName = invitation.Name
}
userEmailVerified := false
if application.IsSignupItemVisible("Email") && application.GetSignupItemRule("Email") != "No verification" && authForm.Email != "" {
var checkResult *object.VerifyResult
checkResult, err = object.CheckVerificationCode(authForm.Email, authForm.EmailCode, c.GetAcceptLanguage())
@ -153,8 +150,6 @@ func (c *ApiController) Signup() {
c.ResponseError(checkResult.Msg)
return
}
userEmailVerified = true
}
var checkPhone string
@ -233,7 +228,6 @@ func (c *ApiController) Signup() {
Karma: 0,
Invitation: invitationName,
InvitationCode: authForm.InvitationCode,
EmailVerified: userEmailVerified,
}
if len(organization.Tags) > 0 {
@ -255,10 +249,6 @@ func (c *ApiController) Signup() {
user.Groups = []string{invitation.SignupGroup}
}
if application.DefaultGroup != "" && user.Groups == nil {
user.Groups = []string{application.DefaultGroup}
}
affected, err := object.AddUser(user)
if err != nil {
c.ResponseError(err.Error())

View File

@ -25,12 +25,10 @@ import (
"regexp"
"strconv"
"strings"
"time"
"github.com/casdoor/casdoor/captcha"
"github.com/casdoor/casdoor/conf"
"github.com/casdoor/casdoor/form"
"github.com/casdoor/casdoor/i18n"
"github.com/casdoor/casdoor/idp"
"github.com/casdoor/casdoor/object"
"github.com/casdoor/casdoor/proxy"
@ -147,7 +145,7 @@ func (c *ApiController) HandleLoggedIn(application *object.Application, user *ob
c.ResponseError(c.T("auth:Challenge method should be S256"))
return
}
code, err := object.GetOAuthCode(userId, clientId, form.Provider, responseType, redirectUri, scope, state, nonce, codeChallenge, c.Ctx.Request.Host, c.GetAcceptLanguage())
code, err := object.GetOAuthCode(userId, clientId, responseType, redirectUri, scope, state, nonce, codeChallenge, c.Ctx.Request.Host, c.GetAcceptLanguage())
if err != nil {
c.ResponseError(err.Error(), nil)
return
@ -170,32 +168,6 @@ func (c *ApiController) HandleLoggedIn(application *object.Application, user *ob
resp.Data2 = user.NeedUpdatePassword
}
} else if form.Type == ResponseTypeDevice {
authCache, ok := object.DeviceAuthMap.LoadAndDelete(form.UserCode)
if !ok {
c.ResponseError(c.T("auth:UserCode Expired"))
return
}
authCacheCast := authCache.(object.DeviceAuthCache)
if authCacheCast.RequestAt.Add(time.Second * 120).Before(time.Now()) {
c.ResponseError(c.T("auth:UserCode Expired"))
return
}
deviceAuthCacheDeviceCode, ok := object.DeviceAuthMap.Load(authCacheCast.UserName)
if !ok {
c.ResponseError(c.T("auth:DeviceCode Invalid"))
return
}
deviceAuthCacheDeviceCodeCast := deviceAuthCacheDeviceCode.(object.DeviceAuthCache)
deviceAuthCacheDeviceCodeCast.UserName = user.Name
deviceAuthCacheDeviceCodeCast.UserSignIn = true
object.DeviceAuthMap.Store(authCacheCast.UserName, deviceAuthCacheDeviceCodeCast)
resp = &Response{Status: "ok", Msg: "", Data: userId, Data2: user.NeedUpdatePassword}
} else if form.Type == ResponseTypeSaml { // saml flow
res, redirectUrl, method, err := object.GetSamlResponse(application, user, form.SamlRequest, c.Ctx.Request.Host)
if err != nil {
@ -269,7 +241,6 @@ func (c *ApiController) GetApplicationLogin() {
state := c.Input().Get("state")
id := c.Input().Get("id")
loginType := c.Input().Get("type")
userCode := c.Input().Get("userCode")
var application *object.Application
var msg string
@ -296,19 +267,6 @@ func (c *ApiController) GetApplicationLogin() {
c.ResponseError(err.Error())
return
}
} else if loginType == "device" {
deviceAuthCache, ok := object.DeviceAuthMap.Load(userCode)
if !ok {
c.ResponseError(c.T("auth:UserCode Invalid"))
return
}
deviceAuthCacheCast := deviceAuthCache.(object.DeviceAuthCache)
application, err = object.GetApplication(deviceAuthCacheCast.ApplicationId)
if err != nil {
c.ResponseError(err.Error())
return
}
}
clientIp := util.GetClientIpFromRequest(c.Ctx.Request)
@ -444,27 +402,11 @@ func (c *ApiController) Login() {
return
}
faceIdProvider, err := object.GetFaceIdProviderByApplication(util.GetId(application.Owner, application.Name), "false", c.GetAcceptLanguage())
if err != nil {
c.ResponseError(err.Error())
if err := object.CheckFaceId(user, authForm.FaceId, c.GetAcceptLanguage()); err != nil {
c.ResponseError(err.Error(), nil)
return
}
if faceIdProvider == nil {
if err := object.CheckFaceId(user, authForm.FaceId, c.GetAcceptLanguage()); err != nil {
c.ResponseError(err.Error(), nil)
return
}
} else {
ok, err := user.CheckUserFace(authForm.FaceIdImage, faceIdProvider)
if err != nil {
c.ResponseError(err.Error(), nil)
}
if !ok {
c.ResponseError(i18n.Translate(c.GetAcceptLanguage(), "check:Face data does not exist, cannot log in"))
return
}
}
} else if authForm.Password == "" {
if user, err = object.GetUserByFields(authForm.Organization, authForm.Username); err != nil {
c.ResponseError(err.Error(), nil)
@ -524,14 +466,6 @@ func (c *ApiController) Login() {
verificationType = "sms"
} else {
verificationType = "email"
if !user.EmailVerified {
user.EmailVerified = true
_, err = object.UpdateUser(user.GetId(), user, []string{"email_verified"}, false)
if err != nil {
c.ResponseError(err.Error(), nil)
return
}
}
}
} else {
var application *object.Application
@ -664,9 +598,6 @@ func (c *ApiController) Login() {
c.ResponseError(err.Error())
return
}
if provider == nil {
c.ResponseError(fmt.Sprintf(c.T("auth:The provider: %s does not exist"), authForm.Provider))
}
providerItem := application.GetProviderItem(provider.Name)
if !providerItem.IsProviderVisible() {
@ -1055,18 +986,6 @@ func (c *ApiController) Login() {
}
}
if authForm.Language != "" {
user := c.getCurrentUser()
if user != nil {
user.Language = authForm.Language
_, err = object.UpdateUser(user.GetId(), user, []string{"language"}, user.IsAdmin)
if err != nil {
c.ResponseError(err.Error())
return
}
}
}
c.Data["json"] = resp
c.ServeJSON()
}
@ -1256,75 +1175,3 @@ func (c *ApiController) Callback() {
frontendCallbackUrl := fmt.Sprintf("/callback?code=%s&state=%s", code, state)
c.Ctx.Redirect(http.StatusFound, frontendCallbackUrl)
}
// DeviceAuth
// @Title DeviceAuth
// @Tag Device Authorization Endpoint
// @Description Endpoint for the device authorization flow
// @router /device-auth [post]
// @Success 200 {object} object.DeviceAuthResponse The Response object
func (c *ApiController) DeviceAuth() {
clientId := c.Input().Get("client_id")
scope := c.Input().Get("scope")
application, err := object.GetApplicationByClientId(clientId)
if err != nil {
c.Data["json"] = object.TokenError{
Error: err.Error(),
ErrorDescription: err.Error(),
}
c.ServeJSON()
return
}
if application == nil {
c.Data["json"] = object.TokenError{
Error: c.T("token:Invalid client_id"),
ErrorDescription: c.T("token:Invalid client_id"),
}
c.ServeJSON()
return
}
deviceCode := util.GenerateId()
userCode := util.GetRandomName()
generateTime := 0
for {
if generateTime > 5 {
c.Data["json"] = object.TokenError{
Error: "userCode gen",
ErrorDescription: c.T("token:Invalid client_id"),
}
c.ServeJSON()
return
}
_, ok := object.DeviceAuthMap.Load(userCode)
if !ok {
break
}
generateTime++
}
deviceAuthCache := object.DeviceAuthCache{
UserSignIn: false,
UserName: "",
Scope: scope,
ApplicationId: application.GetId(),
RequestAt: time.Now(),
}
userAuthCache := object.DeviceAuthCache{
UserSignIn: false,
UserName: deviceCode,
Scope: scope,
ApplicationId: application.GetId(),
RequestAt: time.Now(),
}
object.DeviceAuthMap.Store(deviceCode, deviceAuthCache)
object.DeviceAuthMap.Store(userCode, userAuthCache)
c.Data["json"] = object.GetDeviceAuthResponse(deviceCode, userCode, c.Ctx.Request.Host)
c.ServeJSON()
}

View File

@ -15,7 +15,6 @@ package controllers
import (
"encoding/json"
"fmt"
"github.com/beego/beego/utils/pagination"
"github.com/casdoor/casdoor/object"
@ -79,12 +78,12 @@ func (c *ApiController) GetGroups() {
}
for _, group := range groups {
_, ok := groupsHaveChildrenMap[group.GetId()]
_, ok := groupsHaveChildrenMap[group.Name]
if ok {
group.HaveChildren = true
}
parent, ok := groupsHaveChildrenMap[fmt.Sprintf("%s/%s", group.Owner, group.ParentId)]
parent, ok := groupsHaveChildrenMap[group.ParentId]
if ok {
group.ParentName = parent.DisplayName
}

View File

@ -27,10 +27,10 @@ type LdapResp struct {
ExistUuids []string `json:"existUuids"`
}
// type LdapRespGroup struct {
//type LdapRespGroup struct {
// GroupId string
// GroupName string
// }
//}
type LdapSyncResp struct {
Exist []object.LdapUser `json:"exist"`
@ -61,18 +61,18 @@ func (c *ApiController) GetLdapUsers() {
}
defer conn.Close()
// groupsMap, err := conn.GetLdapGroups(ldapServer.BaseDn)
// if err != nil {
//groupsMap, err := conn.GetLdapGroups(ldapServer.BaseDn)
//if err != nil {
// c.ResponseError(err.Error())
// return
// }
//}
// for _, group := range groupsMap {
//for _, group := range groupsMap {
// resp.Groups = append(resp.Groups, LdapRespGroup{
// GroupId: group.GidNumber,
// GroupName: group.Cn,
// })
// }
//}
users, err := conn.GetLdapUsers(ldapServer)
if err != nil {
@ -269,11 +269,7 @@ func (c *ApiController) SyncLdapUsers() {
return
}
exist, failed, err := object.SyncLdapUsers(owner, users, ldapId)
if err != nil {
c.ResponseError(err.Error())
return
}
exist, failed, _ := object.SyncLdapUsers(owner, users, ldapId)
c.ResponseOk(&LdapSyncResp{
Exist: exist,

View File

@ -16,7 +16,6 @@ package controllers
import (
"encoding/json"
"time"
"github.com/beego/beego/utils/pagination"
"github.com/casdoor/casdoor/object"
@ -171,13 +170,12 @@ func (c *ApiController) GetOAuthToken() {
tag := c.Input().Get("tag")
avatar := c.Input().Get("avatar")
refreshToken := c.Input().Get("refresh_token")
deviceCode := c.Input().Get("device_code")
if clientId == "" && clientSecret == "" {
clientId, clientSecret, _ = c.Ctx.Request.BasicAuth()
}
if len(c.Ctx.Input.RequestBody) != 0 && grantType != "urn:ietf:params:oauth:grant-type:device_code" {
if len(c.Ctx.Input.RequestBody) != 0 {
// If clientId is empty, try to read data from RequestBody
var tokenRequest TokenRequest
err := json.Unmarshal(c.Ctx.Input.RequestBody, &tokenRequest)
@ -221,46 +219,6 @@ func (c *ApiController) GetOAuthToken() {
}
}
if deviceCode != "" {
deviceAuthCache, ok := object.DeviceAuthMap.Load(deviceCode)
if !ok {
c.Data["json"] = &object.TokenError{
Error: "expired_token",
ErrorDescription: "token is expired",
}
c.SetTokenErrorHttpStatus()
c.ServeJSON()
c.SetTokenErrorHttpStatus()
return
}
deviceAuthCacheCast := deviceAuthCache.(object.DeviceAuthCache)
if !deviceAuthCacheCast.UserSignIn {
c.Data["json"] = &object.TokenError{
Error: "authorization_pending",
ErrorDescription: "authorization pending",
}
c.SetTokenErrorHttpStatus()
c.ServeJSON()
c.SetTokenErrorHttpStatus()
return
}
if deviceAuthCacheCast.RequestAt.Add(time.Second * 120).Before(time.Now()) {
c.Data["json"] = &object.TokenError{
Error: "expired_token",
ErrorDescription: "token is expired",
}
c.SetTokenErrorHttpStatus()
c.ServeJSON()
c.SetTokenErrorHttpStatus()
return
}
object.DeviceAuthMap.Delete(deviceCode)
username = deviceAuthCacheCast.UserName
}
host := c.Ctx.Request.Host
token, err := object.GetOAuthToken(grantType, clientId, clientSecret, code, verifier, scope, nonce, username, password, host, refreshToken, tag, avatar, c.GetAcceptLanguage())
if err != nil {
@ -363,11 +321,6 @@ func (c *ApiController) IntrospectToken() {
return
}
respondWithInactiveToken := func() {
c.Data["json"] = &object.IntrospectionResponse{Active: false}
c.ServeJSON()
}
tokenTypeHint := c.Input().Get("token_type_hint")
var token *object.Token
if tokenTypeHint != "" {
@ -376,12 +329,7 @@ func (c *ApiController) IntrospectToken() {
c.ResponseTokenError(err.Error())
return
}
if token == nil || token.ExpiresIn <= 0 {
respondWithInactiveToken()
return
}
if token.ExpiresIn <= 0 {
if token == nil {
c.Data["json"] = &object.IntrospectionResponse{Active: false}
c.ServeJSON()
return
@ -392,11 +340,12 @@ func (c *ApiController) IntrospectToken() {
if application.TokenFormat == "JWT-Standard" {
jwtToken, err := object.ParseStandardJwtTokenByApplication(tokenValue, application)
if err != nil {
if err != nil || jwtToken.Valid() != nil {
// and token revoked case. but we not implement
// TODO: 2022-03-03 add token revoked check, when we implemented the Token Revocation(rfc7009) Specs.
// refs: https://tools.ietf.org/html/rfc7009
respondWithInactiveToken()
c.Data["json"] = &object.IntrospectionResponse{Active: false}
c.ServeJSON()
return
}
@ -416,34 +365,28 @@ func (c *ApiController) IntrospectToken() {
}
} else {
jwtToken, err := object.ParseJwtTokenByApplication(tokenValue, application)
if err != nil {
if err != nil || jwtToken.Valid() != nil {
// and token revoked case. but we not implement
// TODO: 2022-03-03 add token revoked check, when we implemented the Token Revocation(rfc7009) Specs.
// refs: https://tools.ietf.org/html/rfc7009
respondWithInactiveToken()
c.Data["json"] = &object.IntrospectionResponse{Active: false}
c.ServeJSON()
return
}
introspectionResponse = object.IntrospectionResponse{
Active: true,
ClientId: clientId,
Exp: jwtToken.ExpiresAt.Unix(),
Iat: jwtToken.IssuedAt.Unix(),
Nbf: jwtToken.NotBefore.Unix(),
Sub: jwtToken.Subject,
Aud: jwtToken.Audience,
Iss: jwtToken.Issuer,
Jti: jwtToken.ID,
}
if jwtToken.Scope != "" {
introspectionResponse.Scope = jwtToken.Scope
}
if jwtToken.Name != "" {
introspectionResponse.Username = jwtToken.Name
}
if jwtToken.TokenType != "" {
introspectionResponse.TokenType = jwtToken.TokenType
Active: true,
Scope: jwtToken.Scope,
ClientId: clientId,
Username: jwtToken.Name,
TokenType: jwtToken.TokenType,
Exp: jwtToken.ExpiresAt.Unix(),
Iat: jwtToken.IssuedAt.Unix(),
Nbf: jwtToken.NotBefore.Unix(),
Sub: jwtToken.Subject,
Aud: jwtToken.Audience,
Iss: jwtToken.Issuer,
Jti: jwtToken.ID,
}
}
@ -453,15 +396,13 @@ func (c *ApiController) IntrospectToken() {
c.ResponseTokenError(err.Error())
return
}
if token == nil || token.ExpiresIn <= 0 {
respondWithInactiveToken()
if token == nil {
c.Data["json"] = &object.IntrospectionResponse{Active: false}
c.ServeJSON()
return
}
}
if token != nil {
introspectionResponse.TokenType = token.TokenType
}
introspectionResponse.TokenType = token.TokenType
c.Data["json"] = introspectionResponse
c.ServeJSON()

View File

@ -457,10 +457,10 @@ func (c *ApiController) SetPassword() {
newPassword := c.Ctx.Request.Form.Get("newPassword")
code := c.Ctx.Request.Form.Get("code")
// if userOwner == "built-in" && userName == "admin" {
//if userOwner == "built-in" && userName == "admin" {
// c.ResponseError(c.T("auth:Unauthorized operation"))
// return
// }
//}
if strings.Contains(newPassword, " ") {
c.ResponseError(c.T("user:New password cannot contain blank space."))
@ -602,11 +602,7 @@ func (c *ApiController) CheckUserPassword() {
return
}
/*
* Verified password with user as subject, if field ldap not empty,
* then `isPasswordWithLdapEnabled` is true
*/
_, err = object.CheckUserPassword(user.Owner, user.Name, user.Password, c.GetAcceptLanguage(), false, false, user.Ldap != "")
_, err = object.CheckUserPassword(user.Owner, user.Name, user.Password, c.GetAcceptLanguage())
if err != nil {
c.ResponseError(err.Error())
} else {
@ -703,7 +699,7 @@ func (c *ApiController) RemoveUserFromGroup() {
return
}
affected, err := object.DeleteGroupForUser(util.GetId(owner, name), util.GetId(owner, groupName))
affected, err := object.DeleteGroupForUser(util.GetId(owner, name), groupName)
if err != nil {
c.ResponseError(err.Error())
return

View File

@ -242,7 +242,7 @@ func (c *ApiController) SendVerificationCode() {
} else if vform.Method == ResetVerification {
user = c.getCurrentUser()
} else if vform.Method == MfaAuthVerification {
mfaProps := user.GetMfaProps(object.EmailType, false)
mfaProps := user.GetPreferredMfaProps(false)
if user != nil && util.GetMaskedEmail(mfaProps.Secret) == vform.Dest {
vform.Dest = mfaProps.Secret
}
@ -281,7 +281,7 @@ func (c *ApiController) SendVerificationCode() {
}
}
} else if vform.Method == MfaAuthVerification {
mfaProps := user.GetMfaProps(object.SmsType, false)
mfaProps := user.GetPreferredMfaProps(false)
if user != nil && util.GetMaskedPhone(mfaProps.Secret) == vform.Dest {
vform.Dest = mfaProps.Secret
}
@ -436,8 +436,7 @@ func (c *ApiController) ResetEmailOrPhone() {
switch destType {
case object.VerifyTypeEmail:
user.Email = dest
user.EmailVerified = true
_, err = object.UpdateUser(user.GetId(), user, []string{"email", "email_verified"}, false)
_, err = object.SetUserField(user, "email", user.Email)
case object.VerifyTypePhone:
user.Phone = dest
_, err = object.SetUserField(user, "phone", user.Phone)

View File

@ -16,7 +16,7 @@ package controllers
import (
"bytes"
"encoding/base64"
"fmt"
"io"
"github.com/casdoor/casdoor/form"
@ -118,7 +118,24 @@ func (c *ApiController) WebAuthnSigninBegin() {
return
}
options, sessionData, err := webauthnObj.BeginDiscoverableLogin()
userOwner := c.Input().Get("owner")
userName := c.Input().Get("name")
user, err := object.GetUserByFields(userOwner, userName)
if err != nil {
c.ResponseError(err.Error())
return
}
if user == nil {
c.ResponseError(fmt.Sprintf(c.T("general:The user: %s doesn't exist"), util.GetId(userOwner, userName)))
return
}
if len(user.WebauthnCredentials) == 0 {
c.ResponseError(c.T("webauthn:Found no credentials for this user"))
return
}
options, sessionData, err := webauthnObj.BeginLogin(user)
if err != nil {
c.ResponseError(err.Error())
return
@ -151,23 +168,20 @@ func (c *ApiController) WebAuthnSigninFinish() {
return
}
c.Ctx.Request.Body = io.NopCloser(bytes.NewBuffer(c.Ctx.Input.RequestBody))
var user *object.User
handler := func(rawID, userHandle []byte) (webauthn.User, error) {
user, err = object.GetUserByWebauthID(base64.StdEncoding.EncodeToString(rawID))
if err != nil {
return nil, err
}
return user, nil
}
_, err = webauthnObj.FinishDiscoverableLogin(handler, sessionData, c.Ctx.Request)
userId := string(sessionData.UserID)
user, err := object.GetUser(userId)
if err != nil {
c.ResponseError(err.Error())
return
}
c.SetSessionUsername(user.GetId())
util.LogInfo(c.Ctx, "API: [%s] signed in", user.GetId())
_, err = webauthnObj.FinishLogin(user, sessionData, c.Ctx.Request)
if err != nil {
c.ResponseError(err.Error())
return
}
c.SetSessionUsername(userId)
util.LogInfo(c.Ctx, "API: [%s] signed in", userId)
var application *object.Application

View File

@ -34,8 +34,6 @@ func GetCredManager(passwordType string) CredManager {
return NewPbkdf2SaltCredManager()
} else if passwordType == "argon2id" {
return NewArgon2idCredManager()
} else if passwordType == "pbkdf2-django" {
return NewPbkdf2DjangoCredManager()
}
return nil
}

View File

@ -1,71 +0,0 @@
// Copyright 2025 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 cred
import (
"crypto/sha256"
"encoding/base64"
"strconv"
"strings"
"golang.org/x/crypto/pbkdf2"
)
// password type: pbkdf2-django
type Pbkdf2DjangoCredManager struct{}
func NewPbkdf2DjangoCredManager() *Pbkdf2DjangoCredManager {
cm := &Pbkdf2DjangoCredManager{}
return cm
}
func (m *Pbkdf2DjangoCredManager) GetHashedPassword(password string, userSalt string, organizationSalt string) string {
iterations := 260000
salt := userSalt
if salt == "" {
salt = organizationSalt
}
saltBytes := []byte(salt)
passwordBytes := []byte(password)
computedHash := pbkdf2.Key(passwordBytes, saltBytes, iterations, sha256.Size, sha256.New)
hashBase64 := base64.StdEncoding.EncodeToString(computedHash)
return "pbkdf2_sha256$" + strconv.Itoa(iterations) + "$" + salt + "$" + hashBase64
}
func (m *Pbkdf2DjangoCredManager) IsPasswordCorrect(password string, passwordHash string, userSalt string, organizationSalt string) bool {
parts := strings.Split(passwordHash, "$")
if len(parts) != 4 {
return false
}
algorithm, iterations, salt, hash := parts[0], parts[1], parts[2], parts[3]
if algorithm != "pbkdf2_sha256" {
return false
}
iter, err := strconv.Atoi(iterations)
if err != nil {
return false
}
saltBytes := []byte(salt)
passwordBytes := []byte(password)
computedHash := pbkdf2.Key(passwordBytes, saltBytes, iter, sha256.Size, sha256.New)
computedHashBase64 := base64.StdEncoding.EncodeToString(computedHash)
return computedHashBase64 == hash
}

View File

@ -15,8 +15,6 @@
package email
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"net/url"
@ -26,24 +24,14 @@ import (
)
type HttpEmailProvider struct {
endpoint string
method string
httpHeaders map[string]string
bodyMapping map[string]string
contentType string
endpoint string
method string
}
func NewHttpEmailProvider(endpoint string, method string, httpHeaders map[string]string, bodyMapping map[string]string, contentType string) *HttpEmailProvider {
if contentType == "" {
contentType = "application/x-www-form-urlencoded"
}
func NewHttpEmailProvider(endpoint string, method string) *HttpEmailProvider {
client := &HttpEmailProvider{
endpoint: endpoint,
method: method,
httpHeaders: httpHeaders,
bodyMapping: bodyMapping,
contentType: contentType,
endpoint: endpoint,
method: method,
}
return client
}
@ -51,52 +39,18 @@ func NewHttpEmailProvider(endpoint string, method string, httpHeaders map[string
func (c *HttpEmailProvider) Send(fromAddress string, fromName string, toAddress string, subject string, content string) error {
var req *http.Request
var err error
fromNameField := "fromName"
toAddressField := "toAddress"
subjectField := "subject"
contentField := "content"
for k, v := range c.bodyMapping {
switch k {
case "fromName":
fromNameField = v
case "toAddress":
toAddressField = v
case "subject":
subjectField = v
case "content":
contentField = v
}
}
if c.method == "POST" || c.method == "PUT" || c.method == "DELETE" {
bodyMap := make(map[string]string)
bodyMap[fromNameField] = fromName
bodyMap[toAddressField] = toAddress
bodyMap[subjectField] = subject
bodyMap[contentField] = content
var fromValueBytes []byte
if c.contentType == "application/json" {
fromValueBytes, err = json.Marshal(bodyMap)
if err != nil {
return err
}
req, err = http.NewRequest(c.method, c.endpoint, bytes.NewBuffer(fromValueBytes))
} else {
formValues := url.Values{}
for k, v := range bodyMap {
formValues.Add(k, v)
}
req, err = http.NewRequest(c.method, c.endpoint, strings.NewReader(formValues.Encode()))
}
if c.method == "POST" {
formValues := url.Values{}
formValues.Set("fromName", fromName)
formValues.Set("toAddress", toAddress)
formValues.Set("subject", subject)
formValues.Set("content", content)
req, err = http.NewRequest(c.method, c.endpoint, strings.NewReader(formValues.Encode()))
if err != nil {
return err
}
req.Header.Set("Content-Type", c.contentType)
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
} else if c.method == "GET" {
req, err = http.NewRequest(c.method, c.endpoint, nil)
if err != nil {
@ -104,19 +58,15 @@ func (c *HttpEmailProvider) Send(fromAddress string, fromName string, toAddress
}
q := req.URL.Query()
q.Add(fromNameField, fromName)
q.Add(toAddressField, toAddress)
q.Add(subjectField, subject)
q.Add(contentField, content)
q.Add("fromName", fromName)
q.Add("toAddress", toAddress)
q.Add("subject", subject)
q.Add("content", content)
req.URL.RawQuery = q.Encode()
} else {
return fmt.Errorf("HttpEmailProvider's Send() error, unsupported method: %s", c.method)
}
for k, v := range c.httpHeaders {
req.Header.Set(k, v)
}
httpClient := proxy.DefaultHttpClient
resp, err := httpClient.Do(req)
if err != nil {

View File

@ -18,11 +18,11 @@ type EmailProvider interface {
Send(fromAddress string, fromName, toAddress string, subject string, content string) error
}
func GetEmailProvider(typ string, clientId string, clientSecret string, host string, port int, disableSsl bool, endpoint string, method string, httpHeaders map[string]string, bodyMapping map[string]string, contentType string) EmailProvider {
func GetEmailProvider(typ string, clientId string, clientSecret string, host string, port int, disableSsl bool, endpoint string, method string) EmailProvider {
if typ == "Azure ACS" {
return NewAzureACSEmailProvider(clientSecret, host)
} else if typ == "Custom HTTP Email" {
return NewHttpEmailProvider(endpoint, method, httpHeaders, bodyMapping, contentType)
return NewHttpEmailProvider(endpoint, method)
} else if typ == "SendGrid" {
return NewSendgridEmailProvider(clientSecret, host, endpoint)
} else {

View File

@ -27,7 +27,8 @@ type SmtpEmailProvider struct {
}
func NewSmtpEmailProvider(userName string, password string, host string, port int, typ string, disableSsl bool) *SmtpEmailProvider {
dialer := gomail.NewDialer(host, port, userName, password)
dialer := &gomail.Dialer{}
dialer = gomail.NewDialer(host, port, userName, password)
if typ == "SUBMAIL" {
dialer.TLSConfig = &tls.Config{InsecureSkipVerify: true}
}

View File

@ -1,81 +0,0 @@
// Copyright 2025 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 faceId
import (
"strings"
openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
facebody20191230 "github.com/alibabacloud-go/facebody-20191230/v5/client"
util "github.com/alibabacloud-go/tea-utils/v2/service"
"github.com/alibabacloud-go/tea/tea"
)
type AliyunFaceIdProvider struct {
AccessKey string
AccessSecret string
Endpoint string
QualityScoreThreshold float32
}
func NewAliyunFaceIdProvider(accessKey string, accessSecret string, endPoint string) *AliyunFaceIdProvider {
return &AliyunFaceIdProvider{
AccessKey: accessKey,
AccessSecret: accessSecret,
Endpoint: endPoint,
QualityScoreThreshold: 0.65,
}
}
func (provider *AliyunFaceIdProvider) Check(base64ImageA string, base64ImageB string) (bool, error) {
config := openapi.Config{
AccessKeyId: tea.String(provider.AccessKey),
AccessKeySecret: tea.String(provider.AccessSecret),
}
config.Endpoint = tea.String(provider.Endpoint)
client, err := facebody20191230.NewClient(&config)
if err != nil {
return false, err
}
compareFaceRequest := &facebody20191230.CompareFaceRequest{
QualityScoreThreshold: tea.Float32(provider.QualityScoreThreshold),
ImageDataA: tea.String(strings.Replace(base64ImageA, "data:image/png;base64,", "", -1)),
ImageDataB: tea.String(strings.Replace(base64ImageB, "data:image/png;base64,", "", -1)),
}
runtime := &util.RuntimeOptions{}
defer func() {
if r := tea.Recover(recover()); r != nil {
err = r
}
}()
result, err := client.CompareFaceWithOptions(compareFaceRequest, runtime)
if err != nil {
return false, err
}
if result == nil {
return false, nil
}
if *result.Body.Data.Thresholds[0] < *result.Body.Data.Confidence {
return true, nil
}
return false, nil
}

View File

@ -1,23 +0,0 @@
// Copyright 2025 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 faceId
type FaceIdProvider interface {
Check(base64ImageA string, base64ImageB string) (bool, error)
}
func GetFaceIdProvider(typ string, clientId string, clientSecret string, endPoint string) FaceIdProvider {
return NewAliyunFaceIdProvider(clientId, clientSecret, endPoint)
}

View File

@ -34,7 +34,6 @@ type AuthForm struct {
Phone string `json:"phone"`
Affiliation string `json:"affiliation"`
IdCard string `json:"idCard"`
Language string `json:"language"`
Region string `json:"region"`
InvitationCode string `json:"invitationCode"`
@ -68,9 +67,7 @@ type AuthForm struct {
Plan string `json:"plan"`
Pricing string `json:"pricing"`
FaceId []float64 `json:"faceId"`
FaceIdImage []string `json:"faceIdImage"`
UserCode string `json:"userCode"`
FaceId []float64 `json:"faceId"`
}
func GetAuthFormFieldValue(form *AuthForm, fieldName string) (bool, string) {

57
go.mod
View File

@ -1,14 +1,10 @@
module github.com/casdoor/casdoor
go 1.21
go 1.18
require (
github.com/Masterminds/squirrel v1.5.3
github.com/alexedwards/argon2id v0.0.0-20211130144151-3585854a6387
github.com/alibabacloud-go/darabonba-openapi/v2 v2.1.4
github.com/alibabacloud-go/facebody-20191230/v5 v5.1.2
github.com/alibabacloud-go/tea v1.3.2
github.com/alibabacloud-go/tea-utils/v2 v2.0.7
github.com/aws/aws-sdk-go v1.45.5
github.com/beego/beego v1.12.12
github.com/beevik/etree v1.1.0
@ -16,7 +12,7 @@ require (
github.com/casdoor/go-sms-sender v0.25.0
github.com/casdoor/gomail/v2 v2.1.0
github.com/casdoor/ldapserver v1.2.0
github.com/casdoor/notify v1.0.1
github.com/casdoor/notify v1.0.0
github.com/casdoor/oss v1.8.0
github.com/casdoor/xorm-adapter/v3 v3.1.0
github.com/casvisor/casvisor-go-sdk v1.4.0
@ -25,14 +21,14 @@ require (
github.com/elimity-com/scim v0.0.0-20230426070224-941a5eac92f3
github.com/fogleman/gg v1.3.0
github.com/go-asn1-ber/asn1-ber v1.5.5
github.com/go-git/go-git/v5 v5.13.0
github.com/go-git/go-git/v5 v5.11.0
github.com/go-ldap/ldap/v3 v3.4.6
github.com/go-mysql-org/go-mysql v1.7.0
github.com/go-pay/gopay v1.5.72
github.com/go-sql-driver/mysql v1.6.0
github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible
github.com/go-webauthn/webauthn v0.10.2
github.com/golang-jwt/jwt/v5 v5.2.2
github.com/go-webauthn/webauthn v0.6.0
github.com/golang-jwt/jwt/v4 v4.5.0
github.com/google/uuid v1.6.0
github.com/json-iterator/go v1.1.12
github.com/lestrrat-go/jwx v1.2.29
@ -52,7 +48,7 @@ require (
github.com/shirou/gopsutil v3.21.11+incompatible
github.com/siddontang/go-log v0.0.0-20190221022429-1e957dd83bed
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
github.com/stretchr/testify v1.10.0
github.com/stretchr/testify v1.9.0
github.com/stripe/stripe-go/v74 v74.29.0
github.com/tealeg/xlsx v1.0.5
github.com/thanhpk/randstr v1.0.4
@ -83,25 +79,13 @@ require (
github.com/BurntSushi/toml v0.3.1 // indirect
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible // indirect
github.com/Microsoft/go-winio v0.6.1 // indirect
github.com/ProtonMail/go-crypto v1.1.3 // indirect
github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 // indirect
github.com/RocketChat/Rocket.Chat.Go.SDK v0.0.0-20221121042443-a3fd332d56d9 // indirect
github.com/SherClockHolmes/webpush-go v1.2.0 // indirect
github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.5 // indirect
github.com/alibabacloud-go/darabonba-number v1.0.4 // indirect
github.com/alibabacloud-go/debug v1.0.1 // indirect
github.com/alibabacloud-go/endpoint-util v1.1.0 // indirect
github.com/alibabacloud-go/openapi-util v0.1.0 // indirect
github.com/alibabacloud-go/openplatform-20191219/v2 v2.0.1 // indirect
github.com/alibabacloud-go/tea-fileform v1.1.1 // indirect
github.com/alibabacloud-go/tea-oss-sdk v1.1.3 // indirect
github.com/alibabacloud-go/tea-oss-utils v1.1.0 // indirect
github.com/alibabacloud-go/tea-utils v1.3.6 // indirect
github.com/alibabacloud-go/tea-xml v1.1.3 // indirect
github.com/aliyun/alibaba-cloud-sdk-go v1.62.545 // indirect
github.com/aliyun/aliyun-oss-go-sdk v2.2.2+incompatible // indirect
github.com/aliyun/credentials-go v1.3.10 // indirect
github.com/apistd/uni-go-sdk v0.0.2 // indirect
github.com/atc0005/go-teams-notify/v2 v2.13.0 // indirect
github.com/atc0005/go-teams-notify/v2 v2.6.1 // indirect
github.com/baidubce/bce-sdk-go v0.9.156 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/blinkbean/dingtalk v0.0.0-20210905093040-7d935c0f7e19 // indirect
@ -111,10 +95,9 @@ require (
github.com/casdoor/go-reddit/v2 v2.1.0 // indirect
github.com/cenkalti/backoff/v4 v4.1.3 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/clbanning/mxj/v2 v2.7.0 // indirect
github.com/cloudflare/circl v1.3.7 // indirect
github.com/cloudflare/circl v1.3.3 // indirect
github.com/cschomburg/go-pushbullet v0.0.0-20171206132031-67759df45fbb // indirect
github.com/cyphar/filepath-securejoin v0.2.5 // indirect
github.com/cyphar/filepath-securejoin v0.2.4 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect
github.com/dghubble/oauth1 v0.7.2 // indirect
@ -124,15 +107,14 @@ require (
github.com/drswork/go-twitter v0.0.0-20221107160839-dea1b6ed53d7 // indirect
github.com/elazarl/go-bindata-assetfs v1.0.1 // indirect
github.com/emirpasic/gods v1.18.1 // indirect
github.com/fxamacker/cbor/v2 v2.6.0 // indirect
github.com/fxamacker/cbor/v2 v2.4.0 // indirect
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
github.com/go-git/go-billy/v5 v5.6.0 // indirect
github.com/go-git/go-billy/v5 v5.5.0 // indirect
github.com/go-lark/lark v1.9.0 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-webauthn/x v0.1.9 // indirect
github.com/go-webauthn/revoke v0.1.6 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe // indirect
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
@ -141,7 +123,7 @@ require (
github.com/golang/snappy v0.0.4 // indirect
github.com/gomodule/redigo v2.0.0+incompatible // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/go-tpm v0.9.0 // indirect
github.com/google/go-tpm v0.3.3 // indirect
github.com/google/s2a-go v0.1.7 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
github.com/googleapis/gax-go/v2 v2.12.0 // indirect
@ -185,12 +167,12 @@ require (
github.com/rs/zerolog v1.30.0 // indirect
github.com/scim2/filter-parser/v2 v2.2.0 // indirect
github.com/sendgrid/rest v2.6.9+incompatible // indirect
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect
github.com/sergi/go-diff v1.1.0 // indirect
github.com/shiena/ansicolor v0.0.0-20200904210342-c7312218db18 // indirect
github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24 // indirect
github.com/siddontang/go v0.0.0-20180604090527-bdc77568d726 // indirect
github.com/sirupsen/logrus v1.9.0 // indirect
github.com/skeema/knownhosts v1.3.0 // indirect
github.com/skeema/knownhosts v1.2.1 // indirect
github.com/slack-go/slack v0.12.3 // indirect
github.com/stretchr/objx v0.5.2 // indirect
github.com/syndtr/goleveldb v1.0.0 // indirect
@ -201,7 +183,6 @@ require (
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.1 // indirect
github.com/tidwall/sjson v1.2.5 // indirect
github.com/tjfoc/gmsm v1.4.1 // indirect
github.com/tklauser/go-sysconf v0.3.10 // indirect
github.com/tklauser/numcpus v0.4.0 // indirect
github.com/twilio/twilio-go v1.13.0 // indirect
@ -216,13 +197,13 @@ require (
go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.7.0 // indirect
go.uber.org/zap v1.19.1 // indirect
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect
golang.org/x/exp v0.0.0-20230810033253-352e893a4cad // indirect
golang.org/x/image v0.0.0-20190802002840-cff245a6509b // indirect
golang.org/x/mod v0.19.0 // indirect
golang.org/x/mod v0.17.0 // indirect
golang.org/x/sync v0.10.0 // indirect
golang.org/x/sys v0.29.0 // indirect
golang.org/x/time v0.3.0 // indirect
golang.org/x/tools v0.23.0 // indirect
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
google.golang.org/appengine v1.6.8 // indirect
google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b // indirect

268
go.sum
View File

@ -79,8 +79,8 @@ github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/ProtonMail/go-crypto v1.1.3 h1:nRBOetoydLeUb4nHajyO2bKqMLfWQ/ZPwkXqXxPxCFk=
github.com/ProtonMail/go-crypto v1.1.3/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE=
github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 h1:kkhsdkhsCvIsutKu5zLMgWtgh9YxGCNAw8Ad8hjwfYg=
github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
github.com/RocketChat/Rocket.Chat.Go.SDK v0.0.0-20221121042443-a3fd332d56d9 h1:vuu1KBsr6l7XU3CHsWESP/4B1SNd+VZkrgeFZsUXrsY=
github.com/RocketChat/Rocket.Chat.Go.SDK v0.0.0-20221121042443-a3fd332d56d9/go.mod h1:rjP7sIipbZcagro/6TCk6X0ZeFT2eyudH5+fve/cbBA=
github.com/SherClockHolmes/webpush-go v1.2.0 h1:sGv0/ZWCvb1HUH+izLqrb2i68HuqD/0Y+AmGQfyqKJA=
@ -101,95 +101,25 @@ github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74 h1:Kk6a4nehpJ3Uu
github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74/go.mod h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4=
github.com/alexedwards/argon2id v0.0.0-20211130144151-3585854a6387 h1:loy0fjI90vF44BPW4ZYOkE3tDkGTy7yHURusOJimt+I=
github.com/alexedwards/argon2id v0.0.0-20211130144151-3585854a6387/go.mod h1:GuR5j/NW7AU7tDAQUDGCtpiPxWIOy/c3kiRDnlwiCHc=
github.com/alibabacloud-go/alibabacloud-gateway-pop v0.0.6 h1:eIf+iGJxdU4U9ypaUfbtOWCsZSbTb8AUHvyPrxu6mAA=
github.com/alibabacloud-go/alibabacloud-gateway-pop v0.0.6/go.mod h1:4EUIoxs/do24zMOGGqYVWgw0s9NtiylnJglOeEB5UJo=
github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.4/go.mod h1:sCavSAvdzOjul4cEqeVtvlSaSScfNsTQ+46HwlTL1hc=
github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.5 h1:zE8vH9C7JiZLNJJQ5OwjU9mSi4T9ef9u3BURT6LCLC8=
github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.5/go.mod h1:tWnyE9AjF8J8qqLk645oUmVUnFybApTQWklQmi5tY6g=
github.com/alibabacloud-go/darabonba-array v0.1.0 h1:vR8s7b1fWAQIjEjWnuF0JiKsCvclSRTfDzZHTYqfufY=
github.com/alibabacloud-go/darabonba-array v0.1.0/go.mod h1:BLKxr0brnggqOJPqT09DFJ8g3fsDshapUD3C3aOEFaI=
github.com/alibabacloud-go/darabonba-encode-util v0.0.2 h1:1uJGrbsGEVqWcWxrS9MyC2NG0Ax+GpOM5gtupki31XE=
github.com/alibabacloud-go/darabonba-encode-util v0.0.2/go.mod h1:JiW9higWHYXm7F4PKuMgEUETNZasrDM6vqVr/Can7H8=
github.com/alibabacloud-go/darabonba-map v0.0.2 h1:qvPnGB4+dJbJIxOOfawxzF3hzMnIpjmafa0qOTp6udc=
github.com/alibabacloud-go/darabonba-map v0.0.2/go.mod h1:28AJaX8FOE/ym8OUFWga+MtEzBunJwQGceGQlvaPGPc=
github.com/alibabacloud-go/darabonba-number v1.0.4 h1:aTY1TanasI0A1AYT3Co+PLttFSW0qzUz9wFLIpG0tqI=
github.com/alibabacloud-go/darabonba-number v1.0.4/go.mod h1:9NJbJwLCPxHzFwYqnr27G2X8pSTAz0uSQEJsrjr/kqw=
github.com/alibabacloud-go/darabonba-openapi/v2 v2.0.0/go.mod h1:5JHVmnHvGzR2wNdgaW1zDLQG8kOC4Uec8ubkMogW7OQ=
github.com/alibabacloud-go/darabonba-openapi/v2 v2.0.6/go.mod h1:CzQnh+94WDnJOnKZH5YRyouL+OOcdBnXY5VWAf0McgI=
github.com/alibabacloud-go/darabonba-openapi/v2 v2.1.4 h1:IGSZHlOnWwBbLtX5xDplQvZOH0nkrV7Wmq+Fto7JK5w=
github.com/alibabacloud-go/darabonba-openapi/v2 v2.1.4/go.mod h1:Wxis0IBFusdbo44HO6KYYCJR1rRkoh47QQOYWvaheSU=
github.com/alibabacloud-go/darabonba-signature-util v0.0.7 h1:UzCnKvsjPFzApvODDNEYqBHMFt1w98wC7FOo0InLyxg=
github.com/alibabacloud-go/darabonba-signature-util v0.0.7/go.mod h1:oUzCYV2fcCH797xKdL6BDH8ADIHlzrtKVjeRtunBNTQ=
github.com/alibabacloud-go/darabonba-string v1.0.2 h1:E714wms5ibdzCqGeYJ9JCFywE5nDyvIXIIQbZVFkkqo=
github.com/alibabacloud-go/darabonba-string v1.0.2/go.mod h1:93cTfV3vuPhhEwGGpKKqhVW4jLe7tDpo3LUM0i0g6mA=
github.com/alibabacloud-go/debug v0.0.0-20190504072949-9472017b5c68/go.mod h1:6pb/Qy8c+lqua8cFpEy7g39NRRqOWc3rOwAy8m5Y2BY=
github.com/alibabacloud-go/debug v1.0.0/go.mod h1:8gfgZCCAC3+SCzjWtY053FrOcd4/qlH6IHTI4QyICOc=
github.com/alibabacloud-go/debug v1.0.1 h1:MsW9SmUtbb1Fnt3ieC6NNZi6aEwrXfDksD4QA6GSbPg=
github.com/alibabacloud-go/debug v1.0.1/go.mod h1:8gfgZCCAC3+SCzjWtY053FrOcd4/qlH6IHTI4QyICOc=
github.com/alibabacloud-go/endpoint-util v1.1.0 h1:r/4D3VSw888XGaeNpP994zDUaxdgTSHBbVfZlzf6b5Q=
github.com/alibabacloud-go/endpoint-util v1.1.0/go.mod h1:O5FuCALmCKs2Ff7JFJMudHs0I5EBgecXXxZRyswlEjE=
github.com/alibabacloud-go/facebody-20191230/v5 v5.1.2 h1:Mcd+Cvjr+Av6g5IPAJEmhgrgI86WJRZWUawIlccSPi4=
github.com/alibabacloud-go/facebody-20191230/v5 v5.1.2/go.mod h1:4eivhdae9mcbMODcVGC4hu+LlSIeQNimnLnaZbeDJBg=
github.com/alibabacloud-go/openapi-util v0.0.11/go.mod h1:sQuElr4ywwFRlCCberQwKRFhRzIyG4QTP/P4y1CJ6Ws=
github.com/alibabacloud-go/openapi-util v0.1.0 h1:0z75cIULkDrdEhkLWgi9tnLe+KhAFE/r5Pb3312/eAY=
github.com/alibabacloud-go/openapi-util v0.1.0/go.mod h1:sQuElr4ywwFRlCCberQwKRFhRzIyG4QTP/P4y1CJ6Ws=
github.com/alibabacloud-go/openplatform-20191219/v2 v2.0.1 h1:L0TIjr9Qh/SLVc1yPhFkcB9+9SbCNK/jPq4ZKB5zmnc=
github.com/alibabacloud-go/openplatform-20191219/v2 v2.0.1/go.mod h1:EKxBRDLcMzwl4VLF/1WJwlByZZECJawPXUvinKMsTTs=
github.com/alibabacloud-go/tea v1.1.0/go.mod h1:IkGyUSX4Ba1V+k4pCtJUc6jDpZLFph9QMy2VUPTwukg=
github.com/alibabacloud-go/tea v1.1.7/go.mod h1:/tmnEaQMyb4Ky1/5D+SE1BAsa5zj/KeGOFfwYm3N/p4=
github.com/alibabacloud-go/tea v1.1.8/go.mod h1:/tmnEaQMyb4Ky1/5D+SE1BAsa5zj/KeGOFfwYm3N/p4=
github.com/alibabacloud-go/tea v1.1.10/go.mod h1:/tmnEaQMyb4Ky1/5D+SE1BAsa5zj/KeGOFfwYm3N/p4=
github.com/alibabacloud-go/tea v1.1.11/go.mod h1:/tmnEaQMyb4Ky1/5D+SE1BAsa5zj/KeGOFfwYm3N/p4=
github.com/alibabacloud-go/tea v1.1.12/go.mod h1:/tmnEaQMyb4Ky1/5D+SE1BAsa5zj/KeGOFfwYm3N/p4=
github.com/alibabacloud-go/tea v1.1.17/go.mod h1:nXxjm6CIFkBhwW4FQkNrolwbfon8Svy6cujmKFUq98A=
github.com/alibabacloud-go/tea v1.1.19/go.mod h1:nXxjm6CIFkBhwW4FQkNrolwbfon8Svy6cujmKFUq98A=
github.com/alibabacloud-go/tea v1.1.20/go.mod h1:nXxjm6CIFkBhwW4FQkNrolwbfon8Svy6cujmKFUq98A=
github.com/alibabacloud-go/tea v1.2.1/go.mod h1:qbzof29bM/IFhLMtJPrgTGK3eauV5J2wSyEUo4OEmnA=
github.com/alibabacloud-go/tea v1.2.2/go.mod h1:CF3vOzEMAG+bR4WOql8gc2G9H3EkH3ZLAQdpmpXMgwk=
github.com/alibabacloud-go/tea v1.3.2 h1:4xlOnwYaK3ek1Kh+fgYTOYYOfv+uv3SAiJEIYm+8vJk=
github.com/alibabacloud-go/tea v1.3.2/go.mod h1:A560v/JTQ1n5zklt2BEpurJzZTI8TUT+Psg2drWlxRg=
github.com/alibabacloud-go/tea-fileform v1.1.1 h1:1YG6erAP3joQ0XdCXYIotuD7zyOM6qCR49xkp5FZDeU=
github.com/alibabacloud-go/tea-fileform v1.1.1/go.mod h1:ZeCV91o4ISmxidd686f0ebdS5EDHWU+vW+TkjLhrsFE=
github.com/alibabacloud-go/tea-oss-sdk v1.1.3 h1:EhAHI6edMeqgkZEqP7r4nc9iMWAUBKGxJHoBsOSKTtU=
github.com/alibabacloud-go/tea-oss-sdk v1.1.3/go.mod h1:yUnodpR3Bf2rudLE7V/Gft5txjJF30Pk+hH77K/Eab0=
github.com/alibabacloud-go/tea-oss-utils v1.1.0 h1:y65crjjcZ2Pbb6UZtC2deuIZHDVTS3IaDWE7M9nVLRc=
github.com/alibabacloud-go/tea-oss-utils v1.1.0/go.mod h1:PFCF12e9yEKyBUIn7X1IrF/pNjvxgkHy0CgxX4+xRuY=
github.com/alibabacloud-go/tea-utils v1.3.1/go.mod h1:EI/o33aBfj3hETm4RLiAxF/ThQdSngxrpF8rKUDJjPE=
github.com/alibabacloud-go/tea-utils v1.3.6 h1:bVjrxHztM8hAs6nOfLWCgxQfAtKb9RgFFMV6J3rdvB4=
github.com/alibabacloud-go/tea-utils v1.3.6/go.mod h1:EI/o33aBfj3hETm4RLiAxF/ThQdSngxrpF8rKUDJjPE=
github.com/alibabacloud-go/tea-utils/v2 v2.0.0/go.mod h1:U5MTY10WwlquGPS34DOeomUGBB0gXbLueiq5Trwu0C4=
github.com/alibabacloud-go/tea-utils/v2 v2.0.5/go.mod h1:dL6vbUT35E4F4bFTHL845eUloqaerYBYPsdWR2/jhe4=
github.com/alibabacloud-go/tea-utils/v2 v2.0.7 h1:WDx5qW3Xa5ZgJ1c8NfqJkF6w+AU5wB8835UdhPr6Ax0=
github.com/alibabacloud-go/tea-utils/v2 v2.0.7/go.mod h1:qxn986l+q33J5VkialKMqT/TTs3E+U9MJpd001iWQ9I=
github.com/alibabacloud-go/tea-xml v1.1.1/go.mod h1:Rq08vgCcCAjHyRi/M7xlHKUykZCEtyBy9+DPF6GgEu8=
github.com/alibabacloud-go/tea-xml v1.1.2/go.mod h1:Rq08vgCcCAjHyRi/M7xlHKUykZCEtyBy9+DPF6GgEu8=
github.com/alibabacloud-go/tea-xml v1.1.3 h1:7LYnm+JbOq2B+T/B0fHC4Ies4/FofC4zHzYtqw7dgt0=
github.com/alibabacloud-go/tea-xml v1.1.3/go.mod h1:Rq08vgCcCAjHyRi/M7xlHKUykZCEtyBy9+DPF6GgEu8=
github.com/alicebob/gopher-json v0.0.0-20180125190556-5a6b3ba71ee6/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc=
github.com/alicebob/miniredis v2.5.0+incompatible/go.mod h1:8HZjEj4yU0dwhYHky+DxYx+6BMjkBbe5ONFIF1MXffk=
github.com/aliyun/alibaba-cloud-sdk-go v1.62.545 h1:0LfzeUr4quwrrrTHn1kfLA0FBdsChCMs8eK2EzOwXVQ=
github.com/aliyun/alibaba-cloud-sdk-go v1.62.545/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/aliyun/credentials-go v1.1.2/go.mod h1:ozcZaMR5kLM7pwtCMEpVmQ242suV6qTJya2bDq4X1Tw=
github.com/aliyun/credentials-go v1.3.1/go.mod h1:8jKYhQuDawt8x2+fusqa1Y6mPxemTsBEN04dgcAcYz0=
github.com/aliyun/credentials-go v1.3.6/go.mod h1:1LxUuX7L5YrZUWzBrRyk0SwSdH4OmPrib8NVePL3fxM=
github.com/aliyun/credentials-go v1.3.10 h1:45Xxrae/evfzQL9V10zL3xX31eqgLWEaIdCoPipOEQA=
github.com/aliyun/credentials-go v1.3.10/go.mod h1:Jm6d+xIgwJVLVWT561vy67ZRP4lPTQxMbEYRuT2Ti1U=
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/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/apistd/uni-go-sdk v0.0.2 h1:7kqETCOz/rz8AQU55XGzxDFGoFeMgeZL5fGwvxKBZrc=
github.com/apistd/uni-go-sdk v0.0.2/go.mod h1:eIqYos4IbHgE/rB75r05ypNLahooEMJCrbjXq322b74=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
github.com/armon/go-metrics v0.3.9/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc=
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
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/atc0005/go-teams-notify/v2 v2.13.0 h1:nbDeHy89NjYlF/PEfLVF6lsserY9O5SnN1iOIw3AxXw=
github.com/atc0005/go-teams-notify/v2 v2.13.0/go.mod h1:WSv9moolRsBcpZbwEf6gZxj7h0uJlJskJq5zkEWKO8Y=
github.com/atc0005/go-teams-notify/v2 v2.6.1 h1:t22ybzQuaQs4UJe4ceF5VYGsPhs6ir3nZOId/FBy6Go=
github.com/atc0005/go-teams-notify/v2 v2.6.1/go.mod h1:xo6GejLDHn3tWBA181F8LrllIL0xC1uRsRxq7YNXaaY=
github.com/avast/retry-go v3.0.0+incompatible/go.mod h1:XtSnn+n/sHqQIpZ10K1qAevBhOOCWBLXXy3hyiqqBrY=
github.com/aws/aws-sdk-go v1.40.45/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q=
github.com/aws/aws-sdk-go v1.45.5 h1:bxilnhv9FngUgdPNJmOIv2bk+2sP0dpqX3e4olhWcGM=
@ -200,7 +130,6 @@ github.com/aws/smithy-go v1.8.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAm
github.com/baidubce/bce-sdk-go v0.9.156 h1:f++WfptxGmSp5acsjl4kUxHpWDDccoFqkIrQKxvp/Sw=
github.com/baidubce/bce-sdk-go v0.9.156/go.mod h1:zbYJMQwE4IZuyrJiFO8tO8NbtYiKTFTbwh4eIsqjVdg=
github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f h1:ZNv7On9kyUzm7fvRZumSyy/IUiSC7AzL0I1jKKtwooA=
github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f/go.mod h1:AuiFmCCPBSrqvVMvuqFuk0qogytodnVFVSN5CeJB8Gc=
github.com/beego/beego v1.12.12 h1:ARY1sNVSS23N0mEQIhSqRDTyyDlx95JY0V3GogBbZbQ=
github.com/beego/beego v1.12.12/go.mod h1:QURFL1HldOcCZAxnc1cZ7wrplsYR5dKPHFjmk6WkLAs=
github.com/beego/goyaml2 v0.0.0-20130207012346-5545475820dd/go.mod h1:1b+Y/CofkYwXMUU0OhQqGvsY2Bvgr4j6jfT699wyZKQ=
@ -219,6 +148,7 @@ github.com/blinkbean/dingtalk v0.0.0-20210905093040-7d935c0f7e19/go.mod h1:9BaLu
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc h1:biVzkmvwrH8WK8raXaxBx6fRVTlJILwEwQGL1I/ByEI=
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
github.com/bradfitz/gomemcache v0.0.0-20180710155616-bc664df96737/go.mod h1:PmM6Mmwb0LSuEubjR8N7PtNe1KxZLtOUHtbeikc5h60=
github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
github.com/bwmarrin/discordgo v0.27.1 h1:ib9AIc/dom1E/fSIulrBwnez0CToJE113ZGt4HoliGY=
github.com/bwmarrin/discordgo v0.27.1/go.mod h1:NJZpH+1AfhIcyQsPeuBKsUtYrRnjkyu0kIVMCHkZtRY=
github.com/casbin/casbin v1.7.0/go.mod h1:c67qKN6Oum3UF5Q1+BByfFxkwKvhwW57ITjqwtzR1KE=
@ -237,8 +167,8 @@ github.com/casdoor/gomail/v2 v2.1.0 h1:ua97E3CARnF1Ik8ga/Drz9uGZfaElXJumFexiErWU
github.com/casdoor/gomail/v2 v2.1.0/go.mod h1:GFzOD9RhY0nODiiPaQiOa6DfoKtmO9aTesu5qrp26OI=
github.com/casdoor/ldapserver v1.2.0 h1:HdSYe+ULU6z9K+2BqgTrJKQRR4//ERAXB64ttOun6Ow=
github.com/casdoor/ldapserver v1.2.0/go.mod h1:VwYU2vqQ2pA8sa00PRekH71R2XmgfzMKhmp1XrrDu2s=
github.com/casdoor/notify v1.0.1 h1:p0kzI7OBlvLbL7zWeKIu31LRcEAygNZGKr5gcFfSIoE=
github.com/casdoor/notify v1.0.1/go.mod h1:RUlaFJw87FoM/nbs0iXPP0h+DxKGTaWAIFQV0oZcSQA=
github.com/casdoor/notify v1.0.0 h1:oldsaaQFPrlufm/OA314z8DwFVE1Tc9Gt1z4ptRHhXw=
github.com/casdoor/notify v1.0.0/go.mod h1:wNHQu0tiDROMBIvz0j3Om3Lhd5yZ+AIfnFb8MYb8OLQ=
github.com/casdoor/oss v1.8.0 h1:uuyKhDIp7ydOtV4lpqhAY23Ban2Ln8La8+QT36CwylM=
github.com/casdoor/oss v1.8.0/go.mod h1:uaqO7KBI2lnZcnB8rF7O6C2bN7llIbfC5Ql8ex1yR1U=
github.com/casdoor/xorm-adapter/v3 v3.1.0 h1:NodWayRtSLVSeCvL9H3Hc61k0G17KhV9IymTCNfh3kk=
@ -261,29 +191,34 @@ github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMn
github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
github.com/clbanning/mxj v1.8.4/go.mod h1:BVjHeAH+rl9rs6f+QIpeRl0tfu10SXn1pUSa5PVGJng=
github.com/clbanning/mxj/v2 v2.5.5/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s=
github.com/clbanning/mxj/v2 v2.7.0 h1:WA/La7UGCanFe5NpHF0Q3DNtnCsVoxbPKuyBNHWRyME=
github.com/clbanning/mxj/v2 v2.7.0/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU=
github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA=
github.com/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs=
github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
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/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/couchbase/go-couchbase v0.0.0-20201216133707-c04035124b17/go.mod h1:+/bddYDxXsf9qt0xpDUtRR47A2GjaXmGGAqQ/k3GJ8A=
github.com/couchbase/gomemcached v0.1.2-0.20201224031647-c432ccf49f32/go.mod h1:mxliKQxOv84gQ0bJWbI+w9Wxdpt9HjDvgW9MjCym5Vo=
github.com/couchbase/goutils v0.0.0-20210118111533-e33d3ffb5401/go.mod h1:BQwMFlJzDjFDG3DJUdU0KORxn88UlsOULuxLExMh3Hs=
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/cschomburg/go-pushbullet v0.0.0-20171206132031-67759df45fbb h1:7X9nrm+LNWdxzQOiCjy0G51rNUxbH35IDHCjAMvogyM=
github.com/cschomburg/go-pushbullet v0.0.0-20171206132031-67759df45fbb/go.mod h1:RfQ9wji3fjcSEsQ+uFCtIh3+BXgcZum8Kt3JxvzYzlk=
github.com/cupcake/rdb v0.0.0-20161107195141-43ba34106c76/go.mod h1:vYwsqCOLxGiisLwp9rITslkFNpZD5rz43tf41QFkTWY=
github.com/cyphar/filepath-securejoin v0.2.5 h1:6iR5tXJ/e6tJZzzdMc1km3Sa7RRIVBKAK32O2s7AYfo=
github.com/cyphar/filepath-securejoin v0.2.5/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg=
github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
github.com/cznic/mathutil v0.0.0-20181122101859-297441e03548/go.mod h1:e6NPNENfs9mPDVNRekM7lKScauxd5kXTr1Mfyig6TDM=
github.com/cznic/sortutil v0.0.0-20181122101858-f5f958428db8/go.mod h1:q2w6Bg5jeox1B+QkJ6Wp/+Vn0G/bo3f1uY7Fn3vivIQ=
github.com/cznic/strutil v0.0.0-20171016134553-529a34b1c186/go.mod h1:AHHPPPXTw0h6pVabbcbyGRK1DckRn7r/STdZEeIDzZc=
@ -302,6 +237,8 @@ github.com/dghubble/oauth1 v0.7.2 h1:pwcinOZy8z6XkNxvPmUDY52M7RDPxt0Xw1zgZ6Cl5JA
github.com/dghubble/oauth1 v0.7.2/go.mod h1:9erQdIhqhOHG/7K9s/tgh9Ks/AfoyrO5mW/43Lu2+kE=
github.com/dghubble/sling v1.4.0 h1:/n8MRosVTthvMbwlNZgLx579OGVjUOy3GNEv5BIqAWY=
github.com/dghubble/sling v1.4.0/go.mod h1:0r40aNsU9EdDUVBNhfCstAtFgutjgJGYbO1oNzkMoM8=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/di-wu/parser v0.2.2 h1:I9oHJ8spBXOeL7Wps0ffkFFFiXJf/pk7NX9lcAMqRMU=
github.com/di-wu/parser v0.2.2/go.mod h1:SLp58pW6WamdmznrVRrw2NTyn4wAvT9rrEFynKX7nYo=
github.com/di-wu/xsd-datetime v1.0.0 h1:vZoGNkbzpBNoc+JyfVLEbutNDNydYV8XwHeV7eUJoxI=
@ -320,8 +257,7 @@ github.com/elastic/go-elasticsearch/v6 v6.8.5/go.mod h1:UwaDJsD3rWLM5rKNFzv9hgox
github.com/elazarl/go-bindata-assetfs v1.0.0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4=
github.com/elazarl/go-bindata-assetfs v1.0.1 h1:m0kkaHRKEu7tUIUFVwhGGGYClXvyl4RE03qmvRTNfbw=
github.com/elazarl/go-bindata-assetfs v1.0.1/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4=
github.com/elazarl/goproxy v1.2.1 h1:njjgvO6cRG9rIqN2ebkqy6cQz2Njkx7Fsfv/zIZqgug=
github.com/elazarl/goproxy v1.2.1/go.mod h1:YfEbZtqP4AetfO6d40vWchF3znWX7C7Vd6ZMfdL8z64=
github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a h1:mATvB/9r/3gvcejNsXKSkQ6lcIaNec2nyfOdlTBR2lU=
github.com/elimity-com/scim v0.0.0-20230426070224-941a5eac92f3 h1:+zrUtdBUJpY9qptMaaY3CA3T/lBI2+QqfUbzM2uxJss=
github.com/elimity-com/scim v0.0.0-20230426070224-941a5eac92f3/go.mod h1:JkjcmqbLW+khwt2fmBPJFBhx2zGZ8XobRZ+O0VhlwWo=
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
@ -348,22 +284,20 @@ github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/fxamacker/cbor/v2 v2.6.0 h1:sU6J2usfADwWlYDAFhZBQ6TnLFBHxgesMrQfQgk1tWA=
github.com/fxamacker/cbor/v2 v2.6.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
github.com/fxamacker/cbor/v2 v2.4.0 h1:ri0ArlOR+5XunOP8CRUowT0pSJOwhW098ZCUyskZD88=
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.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c=
github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU=
github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY=
github.com/go-asn1-ber/asn1-ber v1.5.5 h1:MNHlNMBDgEKD4TcKr36vQN68BA00aDfjIt3/bD50WnA=
github.com/go-asn1-ber/asn1-ber v1.5.5/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic=
github.com/go-git/go-billy/v5 v5.6.0 h1:w2hPNtoehvJIxR00Vb4xX94qHQi/ApZfX+nBE2Cjio8=
github.com/go-git/go-billy/v5 v5.6.0/go.mod h1:sFDq7xD3fn3E0GOwUSZqHo9lrkmx8xJhA0ZrfvjBRGM=
github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU=
github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow=
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4=
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII=
github.com/go-git/go-git/v5 v5.13.0 h1:vLn5wlGIh/X78El6r3Jr+30W16Blk0CTcxTYcYPWi5E=
github.com/go-git/go-git/v5 v5.13.0/go.mod h1:Wjo7/JyVKtQgUNdXYXIepzWfJQkUEIGvkvVkiXRR/zw=
github.com/go-git/go-git/v5 v5.11.0 h1:XIZc1p+8YzypNr34itUfSvYJcv+eYdTnTvOZ2vD3cA4=
github.com/go-git/go-git/v5 v5.11.0/go.mod h1:6GFcX2P3NM7FPBfpePbpLd21XxsgdAt+lKqXmCUiUCY=
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=
@ -402,15 +336,16 @@ github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible h1:2cauKuaEL
github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible/go.mod h1:qf9acutJ8cwBUhm1bqgz6Bei9/C/c93FPDljKWwsOgM=
github.com/go-test/deep v1.0.4 h1:u2CU3YKy9I2pmu9pX0eq50wCgjfGIt539SqR7FbHiho=
github.com/go-test/deep v1.0.4/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
github.com/go-webauthn/webauthn v0.10.2 h1:OG7B+DyuTytrEPFmTX503K77fqs3HDK/0Iv+z8UYbq4=
github.com/go-webauthn/webauthn v0.10.2/go.mod h1:Gd1IDsGAybuvK1NkwUTLbGmeksxuRJjVN2PE/xsPxHs=
github.com/go-webauthn/x v0.1.9 h1:v1oeLmoaa+gPOaZqUdDentu6Rl7HkSSsmOT6gxEQHhE=
github.com/go-webauthn/x v0.1.9/go.mod h1:pJNMlIMP1SU7cN8HNlKJpLEnFHCygLCvaLZ8a1xeoQA=
github.com/go-webauthn/revoke v0.1.6 h1:3tv+itza9WpX5tryRQx4GwxCCBrCIiJ8GIkOhxiAmmU=
github.com/go-webauthn/revoke v0.1.6/go.mod h1:TB4wuW4tPlwgF3znujA96F70/YSQXHPPWl7vgY09Iy8=
github.com/go-webauthn/webauthn v0.6.0 h1:uLInMApSvBfP+vEFasNE0rnVPG++fjp7lmAIvNhe+UU=
github.com/go-webauthn/webauthn v0.6.0/go.mod h1:7edMRZXwuM6JIVjN68G24Bzt+bPCvTmjiL0j+cAmXtY=
github.com/go-zookeeper/zk v1.0.2/go.mod h1:nOB03cncLtlp4t+UAkGSV+9beXP/akpekBwL+UX1Qcw=
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A=
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
@ -418,13 +353,12 @@ github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzq
github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8=
github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY=
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@ -484,14 +418,17 @@ github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
github.com/google/go-tpm v0.9.0 h1:sQF6YqWMi+SCXpsmS3fd21oPy/vSddwZry4JnmltHVk=
github.com/google/go-tpm v0.9.0/go.mod h1:FkNVkc6C+IsvDI9Jw1OveJmxGZUUaKxtrpOS47QWKfU=
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=
github.com/google/go-tpm v0.3.3/go.mod h1:9Hyn3rgnzWF9XBWVk6ml6A6hNkbWjNFlDQL51BeghL4=
github.com/google/go-tpm-tools v0.0.0-20190906225433-1614c142f845/go.mod h1:AVfHadzbdzHo54inR2x1v640jdi1YSi3NauM2DUsxk0=
github.com/google/go-tpm-tools v0.2.0/go.mod h1:npUd03rQ60lxN7tzeBJreG38RvWwme2N1reF/eeiBk4=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/martian/v3 v3.3.2 h1:IqNFLAmvJOgVlpdEBiQbDc2EwKW77amAycfTuWKdfvw=
github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
@ -518,22 +455,23 @@ github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qK
github.com/gopackage/ddp v0.0.0-20170117053602-652027933df4 h1:4EZlYQIiyecYJlUbVkFXCXHz1QPhVXcHnQKAzBTPfQo=
github.com/gopackage/ddp v0.0.0-20170117053602-652027933df4/go.mod h1:lEO7XoHJ/xNRBCxrn4h/CEB67h0kW1B0t4ooP2yrjUA=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8=
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/gorilla/pat v0.0.0-20180118222023-199c85a7f6d1 h1:LqbZZ9sNMWVjeXS4NN5oVvhMjDyLhmA1LG86oSo+IqY=
github.com/gorilla/pat v0.0.0-20180118222023-199c85a7f6d1/go.mod h1:YeAe0gNeiNT5hoiZRI4yiOky6jVdNvfO2N6Kav/HmxY=
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gregdel/pushover v1.2.1 h1:IPPJCdzXz60gMqnlzS0ZAW5z5aS1gI4nU+YM0Pe+ssA=
github.com/gregdel/pushover v1.2.1/go.mod h1:EcaO66Nn1StkpEm1iKtBTV3d2A16SoMsVER1PthX7to=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/hashicorp/consul/api v1.10.1/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M=
github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms=
@ -559,6 +497,7 @@ github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg2DmyNY=
github.com/hashicorp/memberlist v0.2.2/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE=
@ -566,9 +505,9 @@ github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKEN
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/hudl/fargo v1.4.0/go.mod h1:9Ai6uvFy5fQNq6VPKtg+Ceq1+eTY4nKUlR2JElEOcDo=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/influxdata/influxdb1-client v0.0.0-20200827194710-b269163b24ab/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
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/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs=
@ -578,7 +517,6 @@ github.com/jcmturner/goidentity/v6 v6.0.1/go.mod h1:X1YW3bgtvwAXju7V3LCIMpY0Gbxy
github.com/jcmturner/gokrb5/v8 v8.4.2/go.mod h1:sb+Xq/fTY5yktf/VxLsE3wlfPqQjp0aWNYyvBVK62bc=
github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc=
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=
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
@ -587,10 +525,10 @@ github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfC
github.com/jmoiron/sqlx v1.3.3/go.mod h1:2BljVx/86SuTyjE+aPYlHCTNvZrnJXghYGpNiXLBMCQ=
github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ=
github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8=
github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible h1:jdpOPRN1zP63Td1hDQbZW73xKmzDvZHzVdNYxhnTMDA=
github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible/go.mod h1:1c7szIrayyPPB/987hsnvNzLushdWf4o/79s3P08L8A=
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
@ -609,6 +547,7 @@ github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNU
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/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
@ -625,7 +564,6 @@ github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfn
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
@ -661,6 +599,7 @@ github.com/localtunnel/go-localtunnel v0.0.0-20170326223115-8a804488f275 h1:IZyc
github.com/localtunnel/go-localtunnel v0.0.0-20170326223115-8a804488f275/go.mod h1:zt6UU74K6Z6oMOYJbJzYpYucqdcQwSMPBEdSvGiaUMw=
github.com/lor00x/goldap v0.0.0-20180618054307-a546dffdd1a3 h1:wIONC+HMNRqmWBjuMxhatuSzHaljStc4gjDeKycxy0A=
github.com/lor00x/goldap v0.0.0-20180618054307-a546dffdd1a3/go.mod h1:37YR9jabpiIxsb8X9VCIx8qFOjTDIIrIHHODa8C4gz0=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
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.79.0 h1:fUYi9R6VubVEK2bpmXvIUp7xRcxA68i8ovfUQx/i5Qc=
@ -730,6 +669,7 @@ github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
github.com/nyaruka/phonenumbers v1.1.5 h1:vYy2DI+z5hdaemqVzXYJ4CVyK92IG484CirEY+40GTo=
github.com/nyaruka/phonenumbers v1.1.5/go.mod h1:yShPJHDSH3aTKzCbXyVxNpbl2kA+F+Ne5Pun/MvFRos=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg=
@ -742,8 +682,7 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.10.2/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY=
github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k=
github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY=
github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI=
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b h1:FfH+VrHHk6Lxt9HdVS0PXzSXFyS2NbZKXv33FYPol0A=
@ -752,6 +691,7 @@ github.com/openzipkin/zipkin-go v0.2.5/go.mod h1:KpXfKdgRDnnhsxw4pNIH9Md5lyFqKUa
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pelletier/go-toml v1.0.1/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/performancecopilot/speed/v4 v4.0.0/go.mod h1:qxrSyuDGrTOWfV+uKRFhfxw6h/4HXRGUiZiufxo49BM=
github.com/peterh/liner v1.0.1-0.20171122030339-3681c2a91233/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc=
github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
@ -781,6 +721,7 @@ github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSg
github.com/pquerna/otp v1.4.0 h1:wZvl1TIVxKRThZIBiwOOHOGP/1+nZyWBil9Y2XNEDzg=
github.com/pquerna/otp v1.4.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU=
github.com/prometheus/client_golang v1.7.0/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
@ -794,6 +735,8 @@ github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY=
github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU=
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4=
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
@ -801,12 +744,14 @@ github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9
github.com/prometheus/common v0.30.0 h1:JEkYlQnpzrzQFxi6gnukFPdQ+ac82oRhzMcIduJu/Ug=
github.com/prometheus/common v0.30.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU=
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/qiangmzsx/string-adapter/v2 v2.1.0 h1:q0y8TPa/sTwtriJPRe8gWL++PuZ+XbOUuvKU+hvtTYs=
github.com/qiangmzsx/string-adapter/v2 v2.1.0/go.mod h1:PElPB7b7HnGKTsuADAffFpOQXHqjEGJz1+U1a6yR5wA=
github.com/qiniu/dyn v1.3.0/go.mod h1:E8oERcm8TtwJiZvkQPbcAh0RL8jO1G0VXJMW3FAWdkk=
@ -819,12 +764,12 @@ github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6O
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/rs/zerolog v1.30.0 h1:SymVODrcRsaRaSInD9yQtKbtWqwsfoPcRff/oRXLj4c=
@ -833,10 +778,10 @@ github.com/russellhaering/gosaml2 v0.9.0 h1:CNMnH42z/GirrKjdmNrSS6bAAs47F9bPdl4P
github.com/russellhaering/gosaml2 v0.9.0/go.mod h1:byViER/1YPUa0Puj9ROZblpoq2jsE7h/CJmitzX0geU=
github.com/russellhaering/goxmldsig v1.2.0 h1:Y6GTTc9Un5hCxSzVz4UIWQ/zuVwDvzJk80guqzwx6Vg=
github.com/russellhaering/goxmldsig v1.2.0/go.mod h1:gM4MDENBQf7M+V824SGfyIUVFWydB7n0KkEubVJl+Tw=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
github.com/scim2/filter-parser/v2 v2.2.0 h1:QGadEcsmypxg8gYChRSM2j1edLyE/2j72j+hdmI4BJM=
github.com/scim2/filter-parser/v2 v2.2.0/go.mod h1:jWnkDToqX/Y0ugz0P5VvpVEUKcWcyHHj+X+je9ce5JA=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
@ -844,8 +789,8 @@ github.com/sendgrid/rest v2.6.9+incompatible h1:1EyIcsNdn9KIisLW50MKwmSRSK+ekuei
github.com/sendgrid/rest v2.6.9+incompatible/go.mod h1:kXX7q3jZtJXK5c5qK83bSGMdV6tsOE70KbHoqJls4lE=
github.com/sendgrid/sendgrid-go v3.14.0+incompatible h1:KDSasSTktAqMJCYClHVE94Fcif2i7P7wzISv1sU6DUA=
github.com/sendgrid/sendgrid-go v3.14.0+incompatible/go.mod h1:QRQt+LX/NmgVEvmdRw0VT/QgUn499+iza2FnDca9fg8=
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
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/go.mod h1:nkxAfR/5quYxwPZhyDxgasBMnRtBZd0FCEpawpjMUFg=
github.com/shiena/ansicolor v0.0.0-20200904210342-c7312218db18 h1:DAYUYH5869yV94zvCES9F51oYtN5oGlwjxJJz7ZCnik=
github.com/shiena/ansicolor v0.0.0-20200904210342-c7312218db18/go.mod h1:nkxAfR/5quYxwPZhyDxgasBMnRtBZd0FCEpawpjMUFg=
@ -870,26 +815,33 @@ github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/skeema/knownhosts v1.3.0 h1:AM+y0rI04VksttfwjkSTNQorvGqmwATnvnAHpSgc0LY=
github.com/skeema/knownhosts v1.3.0/go.mod h1:sPINvnADmT/qYH1kfv+ePMmOBTH6Tbl7b5LvTDjFK7M=
github.com/skeema/knownhosts v1.2.1 h1:SHWdIUa82uGZz+F+47k8SY4QhhI291cXCpopT1lK2AQ=
github.com/skeema/knownhosts v1.2.1/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo=
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/slack-go/slack v0.12.3 h1:92/dfFU8Q5XP6Wp5rr5/T5JHLM5c5Smtn53fhToAP88=
github.com/slack-go/slack v0.12.3/go.mod h1:hlGi5oXA+Gt+yWTPP0plCdRKmjsDxecdHxYQdlMQKOw=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/assertions v1.1.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY=
github.com/sony/sonyflake v1.0.0 h1:MpU6Ro7tfXwgn2l5eluf9xQvQJDROTBImNCfRXn/YeM=
github.com/sony/sonyflake v1.0.0/go.mod h1:Jv3cfhf/UFtolOTTRd3q4Nl6ENqM+KfyZ5PseKfZGF4=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
github.com/ssdb/gossdb v0.0.0-20180723034631-88f6b59b84ec/go.mod h1:QBvMkMya+gXctz3kmljlUCu/yB3GZ6oee+dUozsezQE=
github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
github.com/streadway/amqp v1.0.0/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
github.com/streadway/handy v0.0.0-20200128134331-0f66f006fb2e/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
@ -904,9 +856,8 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/stripe/stripe-go/v74 v74.29.0 h1:ffJ+1Ta1Ccg7yDDz+SfjixX0KizEEJ/wNVRoFYkdwFY=
github.com/stripe/stripe-go/v74 v74.29.0/go.mod h1:f9L6LvaXa35ja7eyvP6GQswoaIPaBRvGAimAO+udbBw=
github.com/syndtr/goleveldb v0.0.0-20160425020131-cfa635847112/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0=
@ -933,13 +884,11 @@ github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY=
github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28=
github.com/tjfoc/gmsm v1.3.2/go.mod h1:HaUcFuY0auTiaHB9MHFGCPx5IaLhTUd2atbCFBQXn9w=
github.com/tjfoc/gmsm v1.4.1 h1:aMe1GlZb+0bLjn+cKTPEvvn9oUEBlJitaZiiBwsbgho=
github.com/tjfoc/gmsm v1.4.1/go.mod h1:j4INPkHWMrhJb38G+J6W4Tw0AbuN8Thu3PbdVYhVcTE=
github.com/tklauser/go-sysconf v0.3.10 h1:IJ1AZGZRWbY8T5Vfk04D9WOA5WSejdflXxP03OUqALw=
github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk=
github.com/tklauser/numcpus v0.4.0 h1:E53Dm1HjH1/R2/aoCtXtPgzmElmn51aOkhCFSuZq//o=
github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
github.com/twilio/twilio-go v1.13.0 h1:8uKXSWAgCvO9Kn12iboy3x/Pw7oxPBufs94fTWQGhLk=
github.com/twilio/twilio-go v1.13.0/go.mod h1:tdnfQ5TjbewoAu4lf9bMsGvfuJ/QU9gYuv9yx3TSIXU=
@ -950,6 +899,8 @@ github.com/uber/jaeger-lib v2.4.1+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6
github.com/ucloud/ucloud-sdk-go v0.22.5 h1:GIltVwMDUqQj4iPL/emsZAMhEYWjLTwZqpOxdkdDrM8=
github.com/ucloud/ucloud-sdk-go v0.22.5/go.mod h1:dyLmFHmUfgb4RZKYQP9IArlvQ2pxzFthfhwxRzOEPIw=
github.com/ugorji/go v0.0.0-20171122102828-84cb69a8af83/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ=
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
github.com/utahta/go-linenotify v0.5.0 h1:E1tJaB/XhqRY/iz203FD0MaHm10DjQPOq5/Mem2A3Gs=
github.com/utahta/go-linenotify v0.5.0/go.mod h1:KsvBXil2wx+ByaCR0e+IZKTbp4pDesc7yjzRigLf6pE=
@ -963,6 +914,8 @@ github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs=
github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM=
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=
github.com/xorm-io/builder v0.3.13/go.mod h1:24o5riRwzre2WvjmN+LM4YpUtJg7W8MdvJ8H57rvrJA=
github.com/xorm-io/core v0.7.4 h1:qIznlqqmYNEb03ewzRXCrNkbbxpkgc/44nVF8yoFV7Y=
@ -971,7 +924,6 @@ github.com/xorm-io/xorm v1.1.6 h1:s4fDpUXJx8Zr/PBovXNaadn+v1P3h/U3iV4OxAkWS8s=
github.com/xorm-io/xorm v1.1.6/go.mod h1:7nsSUdmgLIcqHSSaKOzbVQiZtzIzbpGf1GGSYp6DD70=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.30/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
@ -980,6 +932,7 @@ github.com/yuin/gopher-lua v0.0.0-20171031051903-609c9cd26973/go.mod h1:aEV29Xrm
github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg=
github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ=
@ -996,6 +949,7 @@ go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
@ -1008,12 +962,14 @@ go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9i
go.uber.org/multierr v1.7.0 h1:zaiO/rmgFjbmCXdSYJWQcdvOCsthmdaHfr3Gm2Kx4Ec=
go.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak=
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.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI=
go.uber.org/zap v1.19.1 h1:ue41HOKd1vGURxrmeKIgELGb3jPW9DMUDGtsinblHwI=
go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190131182504-b8fe1690c613/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
@ -1021,13 +977,10 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191219195013-becbf705a915/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
@ -1042,15 +995,13 @@ golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871/go.mod h1:IxCIyHEi3zRg3s0
golang.org/x/crypto v0.0.0-20220208233918-bba287dce954/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-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I=
golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio=
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc=
golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@ -1067,8 +1018,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
golang.org/x/exp v0.0.0-20230810033253-352e893a4cad h1:g0bG7Z4uG+OgH2QDODnjp6ggkk1bJDsINcuWmJN1iJU=
golang.org/x/exp v0.0.0-20230810033253-352e893a4cad/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc=
golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b h1:+qEpEAPhDZ1o0x3tHzZTQDArnOixOzGD9HUJfcg0mb4=
@ -1097,21 +1048,22 @@ golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8=
golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20171115151908-9dfe39835686/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
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=
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
@ -1135,7 +1087,6 @@ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81R
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
@ -1149,18 +1100,14 @@ golang.org/x/net v0.0.0-20210917221730-978cfadd31cf/go.mod h1:9nx3DQGgdP8bBQD5qx
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
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/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ=
golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@ -1195,7 +1142,9 @@ golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190130150945-aca44879d564/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -1231,7 +1180,6 @@ golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200509044756-6aff5f38e54f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -1251,6 +1199,7 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/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-20210917161153-d61c044b1678/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@ -1263,17 +1212,16 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/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/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
@ -1281,17 +1229,15 @@ golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXR
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.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/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.9.0/go.mod h1:M6DEAAIenWoTxdKrOltXcmDY3rSplQUkrvaDU5FcQyo=
golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o=
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0=
golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg=
golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@ -1305,13 +1251,12 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@ -1321,6 +1266,7 @@ golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxb
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@ -1361,7 +1307,6 @@ golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjs
golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200509030707-2212a7e161a5/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
@ -1379,9 +1324,8 @@ golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg=
golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI=
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=
@ -1458,6 +1402,7 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405 h1:
google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405/go.mod h1:67X1fPuzjcrkymZzZV1vvkFeTn2Rvc6lYF9MYFGCcwE=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
@ -1503,7 +1448,6 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EV
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o=
gopkg.in/ini.v1 v1.56.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.66.6/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
@ -1512,12 +1456,14 @@ gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3M
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
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=
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
@ -1592,7 +1538,6 @@ modernc.org/strutil v1.1.3 h1:fNMm+oJklMGYfU9Ylcywl0CO5O6nTfaowNsh2wpPjzY=
modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw=
modernc.org/tcl v1.5.0/go.mod h1:gb57hj4pO8fRrK54zveIfFXBaMHK3SKJNWcmRw1cRzc=
modernc.org/tcl v1.13.2 h1:5PQgL/29XkQ9wsEmmNPjzKs+7iPCaYqUJAhzPvQbjDA=
modernc.org/tcl v1.13.2/go.mod h1:7CLiGIPo1M8Rv1Mitpv5akc2+8fxUd2y2UzC/MfMzy0=
modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
modernc.org/token v1.0.1 h1:A3qvTqOwexpfZZeyI0FeGPDlSWX5pjZu9hF4lU+EKWg=
modernc.org/token v1.0.1/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
@ -1600,7 +1545,6 @@ modernc.org/y v1.0.1/go.mod h1:Ho86I+LVHEI+LYXoUKlmOMAM1JTXOCfj8qi1T8PsClE=
modernc.org/z v1.0.1-0.20210308123920-1f282aa71362/go.mod h1:8/SRk5C/HgiQWCgXdfpb+1RvhORdkz5sw72d3jjtyqA=
modernc.org/z v1.0.1/go.mod h1:8/SRk5C/HgiQWCgXdfpb+1RvhORdkz5sw72d3jjtyqA=
modernc.org/z v1.5.1 h1:RTNHdsrOpeoSeOF4FbzTo8gBYByaJ5xT7NgZ9ZqRiJM=
modernc.org/z v1.5.1/go.mod h1:eWFB510QWW5Th9YGZT81s+LwvaAs3Q2yr4sP0rmLkv8=
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=

View File

@ -84,10 +84,6 @@ func getAllFilePathsInFolder(folder string, fileSuffix string) []string {
return err
}
if strings.HasSuffix(path, "node_modules") {
return filepath.SkipDir
}
if !strings.HasSuffix(info.Name(), fileSuffix) {
return nil
}

View File

@ -1,9 +1,9 @@
{
"account": {
"Failed to add user": "Gagal menambahkan pengguna",
"Get init score failed, error: %w": "Gagal mendapatkan nilai inisiasi, kesalahan: %w",
"Get init score failed, error: %w": "Gagal mendapatkan nilai init, kesalahan: %w",
"Please sign out first": "Silakan keluar terlebih dahulu",
"The application does not allow to sign up new account": "Aplikasi tidak memperbolehkan pendaftaran akun baru"
"The application does not allow to sign up new account": "Aplikasi tidak memperbolehkan untuk mendaftar akun baru"
},
"auth": {
"Challenge method should be S256": "Metode tantangan harus S256",
@ -13,17 +13,17 @@
"State expected: %s, but got: %s": "Diharapkan: %s, tapi diperoleh: %s",
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account via %%s, please use another way to sign up": "Akun untuk penyedia: %s dan nama pengguna: %s (%s) tidak ada dan tidak diizinkan untuk mendaftar sebagai akun baru melalui %%s, silakan gunakan cara lain untuk mendaftar",
"The account for provider: %s and username: %s (%s) does not exist and is not allowed to sign up as new account, please contact your IT support": "Akun untuk penyedia: %s dan nama pengguna: %s (%s) tidak ada dan tidak diizinkan untuk mendaftar sebagai akun baru, silakan hubungi dukungan IT Anda",
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "Akun untuk penyedia: %s dan username: %s (%s) sudah terhubung dengan akun lain: %s (%s)",
"The account for provider: %s and username: %s (%s) is already linked to another account: %s (%s)": "Akun untuk provider: %s dan username: %s (%s) sudah terhubung dengan akun lain: %s (%s)",
"The application: %s does not exist": "Aplikasi: %s tidak ada",
"The login method: login with LDAP is not enabled for the application": "The login method: login with LDAP is not enabled for the application",
"The login method: login with SMS is not enabled for the application": "The login method: login with SMS is not enabled for the application",
"The login method: login with email is not enabled for the application": "The login method: login with email is not enabled for the application",
"The login method: login with face is not enabled for the application": "The login method: login with face is not enabled for the application",
"The login method: login with password is not enabled for the application": "Metode login: login dengan sandi tidak diaktifkan untuk aplikasi tersebut",
"The login method: login with password is not enabled for the application": "Metode login: login dengan kata sandi tidak diaktifkan untuk aplikasi tersebut",
"The organization: %s does not exist": "The organization: %s does not exist",
"The provider: %s is not enabled for the application": "Penyedia: %s tidak diaktifkan untuk aplikasi ini",
"Unauthorized operation": "Operasi tidak sah",
"Unknown authentication type (not password or provider), form = %s": "Jenis otentikasi tidak diketahui (bukan sandi atau penyedia), formulir = %s",
"Unknown authentication type (not password or provider), form = %s": "Jenis otentikasi tidak diketahui (bukan kata sandi atau pemberi), formulir = %s",
"User's tag: %s is not listed in the application's tags": "User's tag: %s is not listed in the application's tags",
"paid-user %s does not have active or pending subscription and the application: %s does not have default pricing": "paid-user %s does not have active or pending subscription and the application: %s does not have default pricing"
},
@ -39,59 +39,59 @@
"Email cannot be empty": "Email tidak boleh kosong",
"Email is invalid": "Email tidak valid",
"Empty username.": "Nama pengguna kosong.",
"Face data does not exist, cannot log in": "Data wajah tidak ada, tidak bisa login",
"Face data mismatch": "Ketidakcocokan data wajah",
"Face data does not exist, cannot log in": "Face data does not exist, cannot log in",
"Face data mismatch": "Face data mismatch",
"FirstName cannot be blank": "Nama depan tidak boleh kosong",
"Invitation code cannot be blank": "Kode undangan tidak boleh kosong",
"Invitation code exhausted": "Kode undangan habis",
"Invitation code is invalid": "Kode undangan tidak valid",
"Invitation code suspended": "Kode undangan ditangguhkan",
"LDAP user name or password incorrect": "Nama pengguna atau sandi LDAP salah",
"Invitation code cannot be blank": "Invitation code cannot be blank",
"Invitation code exhausted": "Invitation code exhausted",
"Invitation code is invalid": "Invitation code is invalid",
"Invitation code suspended": "Invitation code suspended",
"LDAP user name or password incorrect": "Nama pengguna atau kata sandi Ldap salah",
"LastName cannot be blank": "Nama belakang tidak boleh kosong",
"Multiple accounts with same uid, please check your ldap server": "Beberapa akun dengan uid yang sama, harap periksa server LDAP Anda",
"Multiple accounts with same uid, please check your ldap server": "Beberapa akun dengan uid yang sama, harap periksa server ldap Anda",
"Organization does not exist": "Organisasi tidak ada",
"Phone already exists": "Telepon sudah ada",
"Phone cannot be empty": "Telepon tidak boleh kosong",
"Phone number is invalid": "Nomor telepon tidak valid",
"Please register using the email corresponding to the invitation code": "Silakan mendaftar menggunakan email yang sesuai dengan kode undangan",
"Please register using the phone corresponding to the invitation code": "Silakan mendaftar menggunakan email yang sesuai dengan kode undangan",
"Please register using the username corresponding to the invitation code": "Silakan mendaftar menggunakan username yang sesuai dengan kode undangan",
"Session outdated, please login again": "Sesi kadaluwarsa, silakan masuk lagi",
"The invitation code has already been used": "Kode undangan sudah digunakan",
"Please register using the email corresponding to the invitation code": "Please register using the email corresponding to the invitation code",
"Please register using the phone corresponding to the invitation code": "Please register using the phone corresponding to the invitation code",
"Please register using the username corresponding to the invitation code": "Please register using the username corresponding to the invitation code",
"Session outdated, please login again": "Sesi kedaluwarsa, silakan masuk lagi",
"The invitation code has already been used": "The invitation code has already been used",
"The user is forbidden to sign in, please contact the administrator": "Pengguna dilarang masuk, silakan hubungi administrator",
"The user: %s doesn't exist in LDAP server": "Pengguna: %s tidak ada di server LDAP",
"The user: %s doesn't exist in LDAP server": "The user: %s doesn't exist in LDAP server",
"The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.": "Nama pengguna hanya bisa menggunakan karakter alfanumerik, garis bawah atau tanda hubung, tidak boleh memiliki dua tanda hubung atau garis bawah berurutan, dan tidak boleh diawali atau diakhiri dengan tanda hubung atau garis bawah.",
"The value \\\"%s\\\" for account field \\\"%s\\\" doesn't match the account item regex": "Nilai \\\"%s\\\" pada bidang akun \\\"%s\\\" tidak cocok dengan ketentuan",
"The value \\\"%s\\\" for signup field \\\"%s\\\" doesn't match the signup item regex of the application \\\"%s\\\"": "Nilai \\\"%s\\\" pada bidang pendaftaran \\\"%s\\\" tidak cocok dengan ketentuan aplikasi \\\"%s\\\"",
"The value \\\"%s\\\" for account field \\\"%s\\\" doesn't match the account item regex": "The value \\\"%s\\\" for account field \\\"%s\\\" doesn't match the account item regex",
"The value \\\"%s\\\" for signup field \\\"%s\\\" doesn't match the signup item regex of the application \\\"%s\\\"": "The value \\\"%s\\\" for signup field \\\"%s\\\" doesn't match the signup item regex of the application \\\"%s\\\"",
"Username already exists": "Nama pengguna sudah ada",
"Username cannot be an email address": "Username tidak bisa menjadi alamat email",
"Username cannot contain white spaces": "Username tidak boleh mengandung spasi",
"Username cannot start with a digit": "Username tidak dapat dimulai dengan angka",
"Username is too long (maximum is 255 characters).": "Nama pengguna terlalu panjang (maksimum 255 karakter).",
"Username must have at least 2 characters": "Nama pengguna harus memiliki setidaknya 2 karakter",
"You have entered the wrong password or code too many times, please wait for %d minutes and try again": "Anda telah memasukkan sandi atau kode yang salah terlalu sering, mohon tunggu selama %d menit lalu coba kembali",
"You have entered the wrong password or code too many times, please wait for %d minutes and try again": "Anda telah memasukkan kata sandi atau kode yang salah terlalu banyak kali, mohon tunggu selama %d menit dan coba lagi",
"Your region is not allow to signup by phone": "Wilayah Anda tidak diizinkan untuk mendaftar melalui telepon",
"password or code is incorrect": "kata sandi atau kode salah",
"password or code is incorrect, you have %d remaining chances": "Sandi atau kode salah, Anda memiliki %d kesempatan tersisa",
"password or code is incorrect": "password or code is incorrect",
"password or code is incorrect, you have %d remaining chances": "Kata sandi atau kode salah, Anda memiliki %d kesempatan tersisa",
"unsupported password type: %s": "jenis sandi tidak didukung: %s"
},
"general": {
"Missing parameter": "Parameter hilang",
"Please login first": "Silahkan login terlebih dahulu",
"The organization: %s should have one application at least": "Organisasi: %s setidaknya harus memiliki satu aplikasi",
"The organization: %s should have one application at least": "The organization: %s should have one application at least",
"The user: %s doesn't exist": "Pengguna: %s tidak ada",
"don't support captchaProvider: ": "Jangan mendukung captchaProvider:",
"this operation is not allowed in demo mode": "tindakan ini tidak diizinkan pada mode demo",
"this operation requires administrator to perform": "tindakan ini membutuhkan peran administrator"
"this operation is not allowed in demo mode": "this operation is not allowed in demo mode",
"this operation requires administrator to perform": "this operation requires administrator to perform"
},
"ldap": {
"Ldap server exist": "Server ldap ada"
},
"link": {
"Please link first": "Silahkan tautkan terlebih dahulu",
"Please link first": "Tolong tautkan terlebih dahulu",
"This application has no providers": "Aplikasi ini tidak memiliki penyedia",
"This application has no providers of type": " Aplikasi ini tidak memiliki penyedia tipe ",
"This provider can't be unlinked": "Penyedia layanan ini tidak dapat dipisahkan",
"This provider can't be unlinked": "Pemberi layanan ini tidak dapat dipisahkan",
"You are not the global admin, you can't unlink other users": "Anda bukan admin global, Anda tidak dapat memutuskan tautan pengguna lain",
"You can't unlink yourself, you are not a member of any application": "Anda tidak dapat memutuskan tautan diri sendiri, karena Anda bukan anggota dari aplikasi apa pun"
},
@ -101,11 +101,11 @@
"Unknown modify rule %s.": "Aturan modifikasi tidak diketahui %s."
},
"permission": {
"The permission: \\\"%s\\\" doesn't exist": "Izin: \\\"%s\\\" tidak ada"
"The permission: \\\"%s\\\" doesn't exist": "The permission: \\\"%s\\\" doesn't exist"
},
"provider": {
"Invalid application id": "ID aplikasi tidak valid",
"the provider: %s does not exist": "penyedia: %s tidak ada"
"the provider: %s does not exist": "provider: %s tidak ada"
},
"resource": {
"User is nil for tag: avatar": "Pengguna kosong untuk tag: avatar",
@ -129,13 +129,13 @@
"token": {
"Grant_type: %s is not supported in this application": "Jenis grant (grant_type) %s tidak didukung dalam aplikasi ini",
"Invalid application or wrong clientSecret": "Aplikasi tidak valid atau clientSecret salah",
"Invalid client_id": "ID klien tidak valid",
"Invalid client_id": "Invalid client_id = ID klien tidak valid",
"Redirect URI: %s doesn't exist in the allowed Redirect URI list": "URI pengalihan: %s tidak ada dalam daftar URI Pengalihan yang diizinkan",
"Token not found, invalid accessToken": "Token tidak ditemukan, accessToken tidak valid"
},
"user": {
"Display name cannot be empty": "Nama tampilan tidak boleh kosong",
"New password cannot contain blank space.": "Sandi baru tidak boleh mengandung spasi kosong."
"New password cannot contain blank space.": "Kata sandi baru tidak boleh mengandung spasi kosong."
},
"user_upload": {
"Failed to import users": "Gagal mengimpor pengguna"
@ -148,16 +148,16 @@
"verification": {
"Invalid captcha provider.": "Penyedia captcha tidak valid.",
"Phone number is invalid in your region %s": "Nomor telepon tidak valid di wilayah anda %s",
"The verification code has not been sent yet!": "Kode verifikasi belum terkirim!",
"The verification code has not been sent yet, or has already been used!": "Kode verifikasi belum dikirim atau telah digunakan!",
"The verification code has not been sent yet!": "The verification code has not been sent yet!",
"The verification code has not been sent yet, or has already been used!": "The verification code has not been sent yet, or has already been used!",
"Turing test failed.": "Tes Turing gagal.",
"Unable to get the email modify rule.": "Tidak dapat memperoleh aturan modifikasi email.",
"Unable to get the phone modify rule.": "Tidak dapat memodifikasi aturan telepon.",
"Unknown type": "Tipe tidak diketahui",
"Wrong verification code!": "Kode verifikasi salah!",
"You should verify your code in %d min!": "Anda harus memverifikasi kode Anda dalam %d menit!",
"please add a SMS provider to the \\\"Providers\\\" list for the application: %s": "silahkan tambahkan penyedia SMS ke daftar \\\"Penyedia\\\" untuk aplikasi: %s",
"please add an Email provider to the \\\"Providers\\\" list for the application: %s": "silahkan tambahkan penyedia Email ke daftar \\\"Penyedia\\\" untuk aplikasi: %s",
"please add a SMS provider to the \\\"Providers\\\" list for the application: %s": "please add a SMS provider to the \\\"Providers\\\" list for the application: %s",
"please add an Email provider to the \\\"Providers\\\" list for the application: %s": "please add an Email provider to the \\\"Providers\\\" list for the application: %s",
"the user does not exist, please sign up first": "Pengguna tidak ada, silakan daftar terlebih dahulu"
},
"webauthn": {

View File

@ -136,12 +136,12 @@ func (idp *DingTalkIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, erro
dtUserInfo := &DingTalkUserResponse{}
accessToken := token.AccessToken
request, err := http.NewRequest("GET", idp.Config.Endpoint.AuthURL, nil)
reqest, err := http.NewRequest("GET", idp.Config.Endpoint.AuthURL, nil)
if err != nil {
return nil, err
}
request.Header.Add("x-acs-dingtalk-access-token", accessToken)
resp, err := idp.Client.Do(request)
reqest.Header.Add("x-acs-dingtalk-access-token", accessToken)
resp, err := idp.Client.Do(reqest)
if err != nil {
return nil, err
}

View File

@ -278,16 +278,9 @@ func NewGothIdProvider(providerType string, clientId string, clientSecret string
Session: &naver.Session{},
}
case "Nextcloud":
if hostUrl != "" {
idp = GothIdProvider{
Provider: nextcloud.NewCustomisedDNS(clientId, clientSecret, redirectUrl, hostUrl),
Session: &nextcloud.Session{},
}
} else {
idp = GothIdProvider{
Provider: nextcloud.New(clientId, clientSecret, redirectUrl),
Session: &nextcloud.Session{},
}
idp = GothIdProvider{
Provider: nextcloud.New(clientId, clientSecret, redirectUrl),
Session: &nextcloud.Session{},
}
case "OneDrive":
idp = GothIdProvider{

View File

@ -44,7 +44,6 @@ type ProviderInfo struct {
AppId string
HostUrl string
RedirectUrl string
DisableSsl bool
TokenURL string
AuthURL string
@ -80,9 +79,9 @@ func GetIdProvider(idpInfo *ProviderInfo, redirectUrl string) (IdProvider, error
return NewLinkedInIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl), nil
case "WeCom":
if idpInfo.SubType == "Internal" {
return NewWeComInternalIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl, idpInfo.DisableSsl), nil
return NewWeComInternalIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl), nil
} else if idpInfo.SubType == "Third-party" {
return NewWeComIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl, idpInfo.DisableSsl), nil
return NewWeComIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl), nil
} else {
return nil, fmt.Errorf("WeCom provider subType: %s is not supported", idpInfo.SubType)
}

View File

@ -299,12 +299,12 @@ func GetWechatOfficialAccountQRCode(clientId string, clientSecret string, provid
params := fmt.Sprintf(`{"expire_seconds": 3600, "action_name": "QR_STR_SCENE", "action_info": {"scene": {"scene_str": "%s"}}}`, providerId)
bodyData := bytes.NewReader([]byte(params))
request, err := http.NewRequest("POST", qrCodeUrl, bodyData)
requeset, err := http.NewRequest("POST", qrCodeUrl, bodyData)
if err != nil {
return "", "", err
}
resp, err := client.Do(request)
resp, err := client.Do(requeset)
if err != nil {
return "", "", err
}

View File

@ -29,16 +29,13 @@ import (
type WeComInternalIdProvider struct {
Client *http.Client
Config *oauth2.Config
UseIdAsName bool
}
func NewWeComInternalIdProvider(clientId string, clientSecret string, redirectUrl string, useIdAsName bool) *WeComInternalIdProvider {
func NewWeComInternalIdProvider(clientId string, clientSecret string, redirectUrl string) *WeComInternalIdProvider {
idp := &WeComInternalIdProvider{}
config := idp.getConfig(clientId, clientSecret, redirectUrl)
idp.Config = config
idp.UseIdAsName = useIdAsName
return idp
}
@ -172,9 +169,5 @@ func (idp *WeComInternalIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo,
userInfo.Id = userInfo.Username
}
if idp.UseIdAsName {
userInfo.Username = userInfo.Id
}
return &userInfo, nil
}

View File

@ -28,16 +28,13 @@ import (
type WeComIdProvider struct {
Client *http.Client
Config *oauth2.Config
UseIdAsName bool
}
func NewWeComIdProvider(clientId string, clientSecret string, redirectUrl string, useIdAsName bool) *WeComIdProvider {
func NewWeComIdProvider(clientId string, clientSecret string, redirectUrl string) *WeComIdProvider {
idp := &WeComIdProvider{}
config := idp.getConfig(clientId, clientSecret, redirectUrl)
idp.Config = config
idp.UseIdAsName = useIdAsName
return idp
}
@ -186,10 +183,6 @@ func (idp *WeComIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error)
DisplayName: wecomUserInfo.UserInfo.Name,
AvatarUrl: wecomUserInfo.UserInfo.Avatar,
}
if idp.UseIdAsName {
userInfo.Username = userInfo.Id
}
return &userInfo, nil
}

19
main.go
View File

@ -15,7 +15,6 @@
package main
import (
"encoding/json"
"fmt"
"github.com/beego/beego"
@ -78,26 +77,10 @@ func main() {
beego.BConfig.WebConfig.Session.SessionGCMaxLifetime = 3600 * 24 * 30
// beego.BConfig.WebConfig.Session.SessionCookieSameSite = http.SameSiteNoneMode
var logAdapter string
logConfigMap := make(map[string]interface{})
err := json.Unmarshal([]byte(conf.GetConfigString("logConfig")), &logConfigMap)
err := logs.SetLogger(logs.AdapterFile, conf.GetConfigString("logConfig"))
if err != nil {
panic(err)
}
_, ok := logConfigMap["adapter"]
if !ok {
logAdapter = "file"
} else {
logAdapter = logConfigMap["adapter"].(string)
}
if logAdapter == "console" {
logs.Reset()
}
err = logs.SetLogger(logAdapter, conf.GetConfigString("logConfig"))
if err != nil {
panic(err)
}
port := beego.AppConfig.DefaultInt("httpport", 8000)
// logs.SetLevel(logs.LevelInformational)
logs.SetLogFuncCall(false)

View File

@ -191,7 +191,12 @@ func (adapter *Adapter) InitAdapter() error {
}
}
tableName := adapter.Table
var tableName string
if driverName == "mssql" {
tableName = fmt.Sprintf("[%s]", adapter.Table)
} else {
tableName = adapter.Table
}
adapter.Adapter, err = xormadapter.NewAdapterByEngineWithTableName(engine, tableName, "")
if err != nil {

View File

@ -71,7 +71,6 @@ type Application struct {
Description string `xorm:"varchar(100)" json:"description"`
Organization string `xorm:"varchar(100)" json:"organization"`
Cert string `xorm:"varchar(100)" json:"cert"`
DefaultGroup string `xorm:"varchar(100)" json:"defaultGroup"`
HeaderHtml string `xorm:"mediumtext" json:"headerHtml"`
EnablePassword bool `json:"enablePassword"`
EnableSignUp bool `json:"enableSignUp"`
@ -85,7 +84,7 @@ type Application struct {
EnableWebAuthn bool `json:"enableWebAuthn"`
EnableLinkWithEmail bool `json:"enableLinkWithEmail"`
OrgChoiceMode string `json:"orgChoiceMode"`
SamlReplyUrl string `xorm:"varchar(500)" json:"samlReplyUrl"`
SamlReplyUrl string `xorm:"varchar(100)" json:"samlReplyUrl"`
Providers []*ProviderItem `xorm:"mediumtext" json:"providers"`
SigninMethods []*SigninMethod `xorm:"varchar(2000)" json:"signinMethods"`
SignupItems []*SignupItem `xorm:"varchar(3000)" json:"signupItems"`
@ -98,31 +97,29 @@ type Application struct {
IsShared bool `json:"isShared"`
IpRestriction string `json:"ipRestriction"`
ClientId string `xorm:"varchar(100)" json:"clientId"`
ClientSecret string `xorm:"varchar(100)" json:"clientSecret"`
RedirectUris []string `xorm:"varchar(1000)" json:"redirectUris"`
ForcedRedirectOrigin string `xorm:"varchar(100)" json:"forcedRedirectOrigin"`
TokenFormat string `xorm:"varchar(100)" json:"tokenFormat"`
TokenSigningMethod string `xorm:"varchar(100)" json:"tokenSigningMethod"`
TokenFields []string `xorm:"varchar(1000)" json:"tokenFields"`
ExpireInHours int `json:"expireInHours"`
RefreshExpireInHours int `json:"refreshExpireInHours"`
SignupUrl string `xorm:"varchar(200)" json:"signupUrl"`
SigninUrl string `xorm:"varchar(200)" json:"signinUrl"`
ForgetUrl string `xorm:"varchar(200)" json:"forgetUrl"`
AffiliationUrl string `xorm:"varchar(100)" json:"affiliationUrl"`
IpWhitelist string `xorm:"varchar(200)" json:"ipWhitelist"`
TermsOfUse string `xorm:"varchar(100)" json:"termsOfUse"`
SignupHtml string `xorm:"mediumtext" json:"signupHtml"`
SigninHtml string `xorm:"mediumtext" json:"signinHtml"`
ThemeData *ThemeData `xorm:"json" json:"themeData"`
FooterHtml string `xorm:"mediumtext" json:"footerHtml"`
FormCss string `xorm:"text" json:"formCss"`
FormCssMobile string `xorm:"text" json:"formCssMobile"`
FormOffset int `json:"formOffset"`
FormSideHtml string `xorm:"mediumtext" json:"formSideHtml"`
FormBackgroundUrl string `xorm:"varchar(200)" json:"formBackgroundUrl"`
FormBackgroundUrlMobile string `xorm:"varchar(200)" json:"formBackgroundUrlMobile"`
ClientId string `xorm:"varchar(100)" json:"clientId"`
ClientSecret string `xorm:"varchar(100)" json:"clientSecret"`
RedirectUris []string `xorm:"varchar(1000)" json:"redirectUris"`
TokenFormat string `xorm:"varchar(100)" json:"tokenFormat"`
TokenSigningMethod string `xorm:"varchar(100)" json:"tokenSigningMethod"`
TokenFields []string `xorm:"varchar(1000)" json:"tokenFields"`
ExpireInHours int `json:"expireInHours"`
RefreshExpireInHours int `json:"refreshExpireInHours"`
SignupUrl string `xorm:"varchar(200)" json:"signupUrl"`
SigninUrl string `xorm:"varchar(200)" json:"signinUrl"`
ForgetUrl string `xorm:"varchar(200)" json:"forgetUrl"`
AffiliationUrl string `xorm:"varchar(100)" json:"affiliationUrl"`
IpWhitelist string `xorm:"varchar(200)" json:"ipWhitelist"`
TermsOfUse string `xorm:"varchar(100)" json:"termsOfUse"`
SignupHtml string `xorm:"mediumtext" json:"signupHtml"`
SigninHtml string `xorm:"mediumtext" json:"signinHtml"`
ThemeData *ThemeData `xorm:"json" json:"themeData"`
FooterHtml string `xorm:"mediumtext" json:"footerHtml"`
FormCss string `xorm:"text" json:"formCss"`
FormCssMobile string `xorm:"text" json:"formCssMobile"`
FormOffset int `json:"formOffset"`
FormSideHtml string `xorm:"mediumtext" json:"formSideHtml"`
FormBackgroundUrl string `xorm:"varchar(200)" json:"formBackgroundUrl"`
FailedSigninLimit int `json:"failedSigninLimit"`
FailedSigninFrozenTime int `json:"failedSigninFrozenTime"`
@ -542,7 +539,7 @@ func GetMaskedApplication(application *Application, userId string) *Application
providerItems := []*ProviderItem{}
for _, providerItem := range application.Providers {
if providerItem.Provider != nil && (providerItem.Provider.Category == "OAuth" || providerItem.Provider.Category == "Web3" || providerItem.Provider.Category == "Captcha" || providerItem.Provider.Category == "SAML" || providerItem.Provider.Category == "Face ID") {
if providerItem.Provider != nil && (providerItem.Provider.Category == "OAuth" || providerItem.Provider.Category == "Web3" || providerItem.Provider.Category == "Captcha" || providerItem.Provider.Category == "SAML") {
providerItems = append(providerItems, providerItem)
}
}

View File

@ -63,11 +63,7 @@ func GetCertCount(owner, field, value string) (int64, error) {
func GetCerts(owner string) ([]*Cert, error) {
certs := []*Cert{}
db := ormer.Engine.NewSession()
if owner != "" {
db = db.Where("owner = ? or owner = ? ", "admin", owner)
}
err := db.Desc("created_time").Find(&certs, &Cert{})
err := ormer.Engine.Where("owner = ? or owner = ? ", "admin", owner).Desc("created_time").Find(&certs, &Cert{})
if err != nil {
return certs, err
}

View File

@ -31,7 +31,7 @@ func TestSmtpServer(provider *Provider) error {
}
func SendEmail(provider *Provider, title string, content string, dest string, sender string) error {
emailProvider := email.GetEmailProvider(provider.Type, provider.ClientId, provider.ClientSecret, provider.Host, provider.Port, provider.DisableSsl, provider.Endpoint, provider.Method, provider.HttpHeaders, provider.UserMapping, provider.IssuerUrl)
emailProvider := email.GetEmailProvider(provider.Type, provider.ClientId, provider.ClientSecret, provider.Host, provider.Port, provider.DisableSsl, provider.Endpoint, provider.Method)
fromAddress := provider.ClientId2
if fromAddress == "" {

View File

@ -17,7 +17,6 @@ package object
import (
"errors"
"fmt"
"strings"
"github.com/casdoor/casdoor/conf"
"github.com/casdoor/casdoor/util"
@ -95,13 +94,12 @@ func GetGroupsHaveChildrenMap(groups []*Group) (map[string]*Group, error) {
}
}
err := ormer.Engine.Cols("owner", "name", "parent_id", "display_name").Distinct("name").In("name", groupIds).Find(&groupsHaveChildren)
err := ormer.Engine.Cols("owner", "name", "parent_id", "display_name").Distinct("parent_id").In("parent_id", groupIds).Find(&groupsHaveChildren)
if err != nil {
return nil, err
}
for _, group := range groupsHaveChildren {
resultMap[group.GetId()] = group
resultMap[group.ParentId] = groupMap[group.ParentId]
}
return resultMap, nil
}
@ -212,12 +210,6 @@ func DeleteGroup(group *Group) (bool, error) {
}
func checkGroupName(name string) error {
if name == "" {
return errors.New("group name can't be empty")
}
if strings.Contains(name, "/") {
return errors.New("group name can't contain \"/\"")
}
exist, err := ormer.Engine.Exist(&Organization{Owner: "admin", Name: name})
if err != nil {
return err

View File

@ -70,12 +70,12 @@ func InitFromFile() {
for _, provider := range initData.Providers {
initDefinedProvider(provider)
}
for _, application := range initData.Applications {
initDefinedApplication(application)
}
for _, user := range initData.Users {
initDefinedUser(user)
}
for _, application := range initData.Applications {
initDefinedApplication(application)
}
for _, cert := range initData.Certs {
initDefinedCert(cert)
}

View File

@ -23,18 +23,17 @@ type Ldap struct {
Owner string `xorm:"varchar(100)" json:"owner"`
CreatedTime string `xorm:"varchar(100)" json:"createdTime"`
ServerName string `xorm:"varchar(100)" json:"serverName"`
Host string `xorm:"varchar(100)" json:"host"`
Port int `xorm:"int" json:"port"`
EnableSsl bool `xorm:"bool" json:"enableSsl"`
AllowSelfSignedCert bool `xorm:"bool" json:"allowSelfSignedCert"`
Username string `xorm:"varchar(100)" json:"username"`
Password string `xorm:"varchar(100)" json:"password"`
BaseDn string `xorm:"varchar(100)" json:"baseDn"`
Filter string `xorm:"varchar(200)" json:"filter"`
FilterFields []string `xorm:"varchar(100)" json:"filterFields"`
DefaultGroup string `xorm:"varchar(100)" json:"defaultGroup"`
PasswordType string `xorm:"varchar(100)" json:"passwordType"`
ServerName string `xorm:"varchar(100)" json:"serverName"`
Host string `xorm:"varchar(100)" json:"host"`
Port int `xorm:"int" json:"port"`
EnableSsl bool `xorm:"bool" json:"enableSsl"`
Username string `xorm:"varchar(100)" json:"username"`
Password string `xorm:"varchar(100)" json:"password"`
BaseDn string `xorm:"varchar(100)" json:"baseDn"`
Filter string `xorm:"varchar(200)" json:"filter"`
FilterFields []string `xorm:"varchar(100)" json:"filterFields"`
DefaultGroup string `xorm:"varchar(100)" json:"defaultGroup"`
PasswordType string `xorm:"varchar(100)" json:"passwordType"`
AutoSync int `json:"autoSync"`
LastSync string `xorm:"varchar(100)" json:"lastSync"`
@ -151,7 +150,7 @@ func UpdateLdap(ldap *Ldap) (bool, error) {
}
affected, err := ormer.Engine.ID(ldap.Id).Cols("owner", "server_name", "host",
"port", "enable_ssl", "username", "password", "base_dn", "filter", "filter_fields", "auto_sync", "default_group", "password_type", "allow_self_signed_cert").Update(ldap)
"port", "enable_ssl", "username", "password", "base_dn", "filter", "filter_fields", "auto_sync", "default_group", "password_type").Update(ldap)
if err != nil {
return false, nil
}

View File

@ -106,12 +106,6 @@ func (l *LdapAutoSynchronizer) syncRoutine(ldap *Ldap, stopChan chan struct{}) e
}
existed, failed, err := SyncLdapUsers(ldap.Owner, AutoAdjustLdapUser(users), ldap.Id)
if err != nil {
conn.Close()
logs.Warning(fmt.Sprintf("autoSync failed for %s, error %s", ldap.Id, err))
continue
}
if len(failed) != 0 {
logs.Warning(fmt.Sprintf("ldap autosync,%d new users,but %d user failed during :", len(users)-len(existed)-len(failed), len(failed)), failed)
logs.Warning(err.Error())

View File

@ -16,7 +16,6 @@ package object
import (
"crypto/md5"
"crypto/tls"
"encoding/base64"
"errors"
"fmt"
@ -65,11 +64,8 @@ type LdapUser struct {
func (ldap *Ldap) GetLdapConn() (c *LdapConn, err error) {
var conn *goldap.Conn
tlsConfig := tls.Config{
InsecureSkipVerify: ldap.AllowSelfSignedCert,
}
if ldap.EnableSsl {
conn, err = goldap.DialTLS("tcp", fmt.Sprintf("%s:%d", ldap.Host, ldap.Port), &tlsConfig)
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))
}

View File

@ -60,8 +60,7 @@ func (mfa *SmsMfa) Enable(user *User) error {
columns = append(columns, "mfa_phone_enabled", "phone", "country_code")
} else if mfa.MfaType == EmailType {
user.MfaEmailEnabled = true
user.EmailVerified = true
columns = append(columns, "mfa_email_enabled", "email", "email_verified")
columns = append(columns, "mfa_email_enabled", "email")
}
_, err := UpdateUser(user.GetId(), user, columns, false)

View File

@ -30,7 +30,6 @@ type OidcDiscovery struct {
AuthorizationEndpoint string `json:"authorization_endpoint"`
TokenEndpoint string `json:"token_endpoint"`
UserinfoEndpoint string `json:"userinfo_endpoint"`
DeviceAuthorizationEndpoint string `json:"device_authorization_endpoint"`
JwksUri string `json:"jwks_uri"`
IntrospectionEndpoint string `json:"introspection_endpoint"`
ResponseTypesSupported []string `json:"response_types_supported"`
@ -120,7 +119,6 @@ func GetOidcDiscovery(host string) OidcDiscovery {
AuthorizationEndpoint: fmt.Sprintf("%s/login/oauth/authorize", originFrontend),
TokenEndpoint: fmt.Sprintf("%s/api/login/oauth/access_token", originBackend),
UserinfoEndpoint: fmt.Sprintf("%s/api/userinfo", originBackend),
DeviceAuthorizationEndpoint: fmt.Sprintf("%s/api/device-auth", originBackend),
JwksUri: fmt.Sprintf("%s/.well-known/jwks", originBackend),
IntrospectionEndpoint: fmt.Sprintf("%s/api/login/oauth/introspect", originBackend),
ResponseTypesSupported: []string{"code", "token", "id_token", "code token", "code id_token", "token id_token", "code token id_token", "none"},
@ -140,7 +138,7 @@ func GetOidcDiscovery(host string) OidcDiscovery {
func GetJsonWebKeySet() (jose.JSONWebKeySet, error) {
jwks := jose.JSONWebKeySet{}
certs, err := GetCerts("")
certs, err := GetCerts("admin")
if err != nil {
return jwks, err
}
@ -215,14 +213,3 @@ func GetWebFinger(resource string, rels []string, host string) (WebFinger, error
return wf, nil
}
func GetDeviceAuthResponse(deviceCode string, userCode string, host string) DeviceAuthResponse {
originFrontend, _ := getOriginFromHost(host)
return DeviceAuthResponse{
DeviceCode: deviceCode,
UserCode: userCode,
VerificationUri: fmt.Sprintf("%s/login/oauth/device/%s", originFrontend, userCode),
ExpiresIn: 120,
}
}

View File

@ -63,7 +63,7 @@ type Organization struct {
PasswordObfuscatorType string `xorm:"varchar(100)" json:"passwordObfuscatorType"`
PasswordObfuscatorKey string `xorm:"varchar(100)" json:"passwordObfuscatorKey"`
PasswordExpireDays int `json:"passwordExpireDays"`
CountryCodes []string `xorm:"mediumtext" json:"countryCodes"`
CountryCodes []string `xorm:"varchar(200)" json:"countryCodes"`
DefaultAvatar string `xorm:"varchar(200)" json:"defaultAvatar"`
DefaultApplication string `xorm:"varchar(100)" json:"defaultApplication"`
UserTypes []string `xorm:"mediumtext" json:"userTypes"`
@ -80,8 +80,7 @@ type Organization struct {
UseEmailAsUsername bool `json:"useEmailAsUsername"`
EnableTour bool `json:"enableTour"`
IpRestriction string `json:"ipRestriction"`
NavItems []string `xorm:"varchar(1000)" json:"navItems"`
WidgetItems []string `xorm:"varchar(1000)" json:"widgetItems"`
NavItems []string `xorm:"varchar(500)" json:"navItems"`
MfaItems []*MfaItem `xorm:"varchar(300)" json:"mfaItems"`
AccountItems []*AccountItem `xorm:"varchar(5000)" json:"accountItems"`
@ -228,7 +227,6 @@ func UpdateOrganization(id string, organization *Organization, isGlobalAdmin boo
if !isGlobalAdmin {
organization.NavItems = org.NavItems
organization.WidgetItems = org.WidgetItems
}
session := ormer.Engine.ID(core.PK{owner, name}).AllCols()

View File

@ -157,7 +157,7 @@ func NewAdapter(driverName string, dataSourceName string, dbName string) (*Ormer
return a, nil
}
// NewAdapterFromDb is the constructor for Ormer.
// NewAdapterFromdb is the constructor for Ormer.
func NewAdapterFromDb(driverName string, dataSourceName string, dbName string, db *sql.DB) (*Ormer, error) {
a := &Ormer{}
a.driverName = driverName
@ -179,7 +179,7 @@ func NewAdapterFromDb(driverName string, dataSourceName string, dbName string, d
func refineDataSourceNameForPostgres(dataSourceName string) string {
reg := regexp.MustCompile(`dbname=[^ ]+\s*`)
return reg.ReplaceAllString(dataSourceName, "dbname=postgres")
return reg.ReplaceAllString(dataSourceName, "")
}
func createDatabaseForPostgres(driverName string, dataSourceName string, dbName string) error {
@ -190,7 +190,7 @@ func createDatabaseForPostgres(driverName string, dataSourceName string, dbName
}
defer db.Close()
_, err = db.Exec(fmt.Sprintf("CREATE DATABASE \"%s\";", dbName))
_, err = db.Exec(fmt.Sprintf("CREATE DATABASE %s;", dbName))
if err != nil {
if !strings.Contains(err.Error(), "already exists") {
return err

View File

@ -148,7 +148,7 @@ func UpdatePermission(id string, permission *Permission) (bool, error) {
}
if permission.ResourceType == "Application" && permission.Model != "" {
model, err := GetModelEx(util.GetId(permission.Owner, permission.Model))
model, err := GetModelEx(util.GetId(owner, permission.Model))
if err != nil {
return false, err
} else if model == nil {

View File

@ -48,7 +48,6 @@ type Provider struct {
CustomLogo string `xorm:"varchar(200)" json:"customLogo"`
Scopes string `xorm:"varchar(100)" json:"scopes"`
UserMapping map[string]string `xorm:"varchar(500)" json:"userMapping"`
HttpHeaders map[string]string `xorm:"varchar(500)" json:"httpHeaders"`
Host string `xorm:"varchar(100)" json:"host"`
Port int `json:"port"`
@ -385,44 +384,6 @@ func GetCaptchaProviderByApplication(applicationId, isCurrentProvider, lang stri
return nil, nil
}
func GetFaceIdProviderByOwnerName(applicationId, lang string) (*Provider, error) {
owner, name := util.GetOwnerAndNameFromId(applicationId)
provider := Provider{Owner: owner, Name: name, Category: "Face ID"}
existed, err := ormer.Engine.Get(&provider)
if err != nil {
return nil, err
}
if !existed {
return nil, fmt.Errorf(i18n.Translate(lang, "provider:the provider: %s does not exist"), applicationId)
}
return &provider, nil
}
func GetFaceIdProviderByApplication(applicationId, isCurrentProvider, lang string) (*Provider, error) {
if isCurrentProvider == "true" {
return GetFaceIdProviderByOwnerName(applicationId, lang)
}
application, err := GetApplication(applicationId)
if err != nil {
return nil, err
}
if application == nil || len(application.Providers) == 0 {
return nil, fmt.Errorf(i18n.Translate(lang, "provider:Invalid application id"))
}
for _, provider := range application.Providers {
if provider.Provider == nil {
continue
}
if provider.Provider.Category == "Face ID" {
return GetFaceIdProviderByOwnerName(util.GetId(provider.Provider.Owner, provider.Provider.Name), lang)
}
}
return nil, nil
}
func providerChangeTrigger(oldName string, newName string) error {
session := ormer.Engine.NewSession()
defer session.Close()
@ -475,7 +436,6 @@ func FromProviderToIdpInfo(ctx *context.Context, provider *Provider) *idp.Provid
AuthURL: provider.CustomAuthUrl,
UserInfoURL: provider.CustomUserInfoUrl,
UserMapping: provider.UserMapping,
DisableSsl: provider.DisableSsl,
}
if provider.Type == "WeChat" {

View File

@ -263,27 +263,6 @@ func addWebhookRecord(webhook *Webhook, record *casvisorsdk.Record, statusCode i
return err
}
func filterRecordObject(object string, objectFields []string) string {
var rawObject map[string]interface{}
_ = json.Unmarshal([]byte(object), &rawObject)
if rawObject == nil {
return object
}
filteredObject := make(map[string]interface{})
for _, field := range objectFields {
fieldValue, ok := rawObject[field]
if !ok {
continue
}
filteredObject[field] = fieldValue
}
return util.StructToJson(filteredObject)
}
func SendWebhooks(record *casvisorsdk.Record) error {
webhooks, err := getWebhooksByOrganization("")
if err != nil {
@ -292,14 +271,7 @@ func SendWebhooks(record *casvisorsdk.Record) error {
errs := []error{}
webhooks = getFilteredWebhooks(webhooks, record.Organization, record.Action)
record2 := *record
for _, webhook := range webhooks {
if len(webhook.ObjectFields) != 0 && webhook.ObjectFields[0] != "All" {
record2.Object = filterRecordObject(record.Object, webhook.ObjectFields)
}
var user *User
if webhook.IsUserExtended {
user, err = getUser(record.Organization, record.User)
@ -315,12 +287,12 @@ func SendWebhooks(record *casvisorsdk.Record) error {
}
}
statusCode, respBody, err := sendWebhook(webhook, &record2, user)
statusCode, respBody, err := sendWebhook(webhook, record, user)
if err != nil {
errs = append(errs, err)
}
err = addWebhookRecord(webhook, &record2, statusCode, respBody, err)
err = addWebhookRecord(webhook, record, statusCode, respBody, err)
if err != nil {
errs = append(errs, err)
}

View File

@ -30,7 +30,7 @@ import (
"time"
"github.com/beevik/etree"
"github.com/golang-jwt/jwt/v5"
"github.com/golang-jwt/jwt/v4"
"github.com/google/uuid"
saml "github.com/russellhaering/gosaml2"
dsig "github.com/russellhaering/goxmldsig"

View File

@ -21,7 +21,7 @@ import (
"time"
"github.com/casdoor/casdoor/util"
"github.com/golang-jwt/jwt/v5"
"github.com/golang-jwt/jwt/v4"
)
type Claims struct {
@ -31,8 +31,7 @@ type Claims struct {
Tag string `json:"tag"`
Scope string `json:"scope,omitempty"`
// the `azp` (Authorized Party) claim. Optional. See https://openid.net/specs/openid-connect-core-1_0.html#IDToken
Azp string `json:"azp,omitempty"`
Provider string `json:"provider,omitempty"`
Azp string `json:"azp,omitempty"`
jwt.RegisteredClaims
}
@ -47,17 +46,6 @@ type UserShort struct {
Phone string `xorm:"varchar(100) index" json:"phone"`
}
type UserStandard struct {
Owner string `xorm:"varchar(100) notnull pk" json:"owner"`
Name string `xorm:"varchar(100) notnull pk" json:"preferred_username,omitempty"`
Id string `xorm:"varchar(100) index" json:"id"`
DisplayName string `xorm:"varchar(100)" json:"name,omitempty"`
Avatar string `xorm:"varchar(500)" json:"picture,omitempty"`
Email string `xorm:"varchar(100) index" json:"email,omitempty"`
Phone string `xorm:"varchar(100) index" json:"phone,omitempty"`
}
type UserWithoutThirdIdp struct {
Owner string `xorm:"varchar(100) notnull pk" json:"owner"`
Name string `xorm:"varchar(100) notnull pk" json:"name"`
@ -152,7 +140,6 @@ type ClaimsShort struct {
Nonce string `json:"nonce,omitempty"`
Scope string `json:"scope,omitempty"`
Azp string `json:"azp,omitempty"`
Provider string `json:"provider,omitempty"`
jwt.RegisteredClaims
}
@ -172,7 +159,6 @@ type ClaimsWithoutThirdIdp struct {
Tag string `json:"tag"`
Scope string `json:"scope,omitempty"`
Azp string `json:"azp,omitempty"`
Provider string `json:"provider,omitempty"`
jwt.RegisteredClaims
}
@ -190,20 +176,6 @@ func getShortUser(user *User) *UserShort {
return res
}
func getStandardUser(user *User) *UserStandard {
res := &UserStandard{
Owner: user.Owner,
Name: user.Name,
Id: user.Id,
DisplayName: user.DisplayName,
Avatar: user.Avatar,
Email: user.Email,
Phone: user.Phone,
}
return res
}
func getUserWithoutThirdIdp(user *User) *UserWithoutThirdIdp {
res := &UserWithoutThirdIdp{
Owner: user.Owner,
@ -302,7 +274,6 @@ func getShortClaims(claims Claims) ClaimsShort {
Scope: claims.Scope,
RegisteredClaims: claims.RegisteredClaims,
Azp: claims.Azp,
Provider: claims.Provider,
}
return res
}
@ -316,7 +287,6 @@ func getClaimsWithoutThirdIdp(claims Claims) ClaimsWithoutThirdIdp {
Scope: claims.Scope,
RegisteredClaims: claims.RegisteredClaims,
Azp: claims.Azp,
Provider: claims.Provider,
}
return res
}
@ -338,7 +308,6 @@ func getClaimsCustom(claims Claims, tokenField []string) jwt.MapClaims {
res["tag"] = claims.Tag
res["scope"] = claims.Scope
res["azp"] = claims.Azp
res["provider"] = claims.Provider
for _, field := range tokenField {
userField := userValue.FieldByName(field)
@ -373,7 +342,7 @@ func refineUser(user *User) *User {
return user
}
func generateJwtToken(application *Application, user *User, provider string, nonce string, scope string, host string) (string, string, string, error) {
func generateJwtToken(application *Application, user *User, nonce string, scope string, host string) (string, string, string, error) {
nowTime := time.Now()
expireTime := nowTime.Add(time.Duration(application.ExpireInHours) * time.Hour)
refreshExpireTime := nowTime.Add(time.Duration(application.RefreshExpireInHours) * time.Hour)
@ -393,10 +362,9 @@ func generateJwtToken(application *Application, user *User, provider string, non
TokenType: "access-token",
Nonce: nonce,
// FIXME: A workaround for custom claim by reusing `tag` in user info
Tag: user.Tag,
Scope: scope,
Azp: application.ClientId,
Provider: provider,
Tag: user.Tag,
Scope: scope,
Azp: application.ClientId,
RegisteredClaims: jwt.RegisteredClaims{
Issuer: originBackend,
Subject: user.Id,

View File

@ -18,7 +18,6 @@ import (
"crypto/sha256"
"encoding/base64"
"fmt"
"sync"
"time"
"github.com/casdoor/casdoor/i18n"
@ -38,8 +37,6 @@ const (
EndpointError = "endpoint_error"
)
var DeviceAuthMap = sync.Map{}
type Code struct {
Message string `xorm:"varchar(100)" json:"message"`
Code string `xorm:"varchar(100)" json:"code"`
@ -74,22 +71,6 @@ type IntrospectionResponse struct {
Jti string `json:"jti,omitempty"`
}
type DeviceAuthCache struct {
UserSignIn bool
UserName string
ApplicationId string
Scope string
RequestAt time.Time
}
type DeviceAuthResponse struct {
DeviceCode string `json:"device_code"`
UserCode string `json:"user_code"`
VerificationUri string `json:"verification_uri"`
ExpiresIn int `json:"expires_in"`
Interval int `json:"interval"`
}
func ExpireTokenByAccessToken(accessToken string) (bool, *Application, *Token, error) {
token, err := GetTokenByAccessToken(accessToken)
if err != nil {
@ -136,7 +117,7 @@ func CheckOAuthLogin(clientId string, responseType string, redirectUri string, s
return "", application, nil
}
func GetOAuthCode(userId string, clientId string, provider string, responseType string, redirectUri string, scope string, state string, nonce string, challenge string, host string, lang string) (*Code, error) {
func GetOAuthCode(userId string, clientId string, responseType string, redirectUri string, scope string, state string, nonce string, challenge string, host string, lang string) (*Code, error) {
user, err := GetUser(userId)
if err != nil {
return nil, err
@ -171,7 +152,7 @@ func GetOAuthCode(userId string, clientId string, provider string, responseType
if err != nil {
return nil, err
}
accessToken, refreshToken, tokenName, err := generateJwtToken(application, user, provider, nonce, scope, host)
accessToken, refreshToken, tokenName, err := generateJwtToken(application, user, nonce, scope, host)
if err != nil {
return nil, err
}
@ -241,8 +222,6 @@ func GetOAuthToken(grantType string, clientId string, clientSecret string, code
token, tokenError, err = GetClientCredentialsToken(application, clientSecret, scope, host)
case "token", "id_token": // Implicit Grant
token, tokenError, err = GetImplicitToken(application, username, scope, nonce, host)
case "urn:ietf:params:oauth:grant-type:device_code":
token, tokenError, err = GetImplicitToken(application, username, scope, nonce, host)
case "refresh_token":
refreshToken2, err := RefreshToken(grantType, refreshToken, scope, clientId, clientSecret, host)
if err != nil {
@ -379,7 +358,7 @@ func RefreshToken(grantType string, refreshToken string, scope string, clientId
return nil, err
}
newAccessToken, newRefreshToken, tokenName, err := generateJwtToken(application, user, "", "", scope, host)
newAccessToken, newRefreshToken, tokenName, err := generateJwtToken(application, user, "", scope, host)
if err != nil {
return &TokenError{
Error: EndpointError,
@ -558,7 +537,7 @@ func GetPasswordToken(application *Application, username string, password string
return nil, nil, err
}
accessToken, refreshToken, tokenName, err := generateJwtToken(application, user, "", "", scope, host)
accessToken, refreshToken, tokenName, err := generateJwtToken(application, user, "", scope, host)
if err != nil {
return nil, &TokenError{
Error: EndpointError,
@ -604,7 +583,7 @@ func GetClientCredentialsToken(application *Application, clientSecret string, sc
Type: "application",
}
accessToken, _, tokenName, err := generateJwtToken(application, nullUser, "", "", scope, host)
accessToken, _, tokenName, err := generateJwtToken(application, nullUser, "", scope, host)
if err != nil {
return nil, &TokenError{
Error: EndpointError,
@ -668,7 +647,7 @@ func GetTokenByUser(application *Application, user *User, scope string, nonce st
return nil, err
}
accessToken, refreshToken, tokenName, err := generateJwtToken(application, user, "", nonce, scope, host)
accessToken, refreshToken, tokenName, err := generateJwtToken(application, user, nonce, scope, host)
if err != nil {
return nil, err
}
@ -775,7 +754,7 @@ func GetWechatMiniProgramToken(application *Application, code string, host strin
return nil, nil, err
}
accessToken, refreshToken, tokenName, err := generateJwtToken(application, user, "", "", "", host)
accessToken, refreshToken, tokenName, err := generateJwtToken(application, user, "", "", host)
if err != nil {
return nil, &TokenError{
Error: EndpointError,

View File

@ -19,11 +19,11 @@ import (
"strings"
"github.com/casdoor/casdoor/util"
"github.com/golang-jwt/jwt/v5"
"github.com/golang-jwt/jwt/v4"
)
type ClaimsStandard struct {
*UserStandard
*UserShort
EmailVerified bool `json:"email_verified,omitempty"`
PhoneNumber string `json:"phone_number,omitempty"`
PhoneNumberVerified bool `json:"phone_number_verified,omitempty"`
@ -33,7 +33,6 @@ type ClaimsStandard struct {
Scope string `json:"scope,omitempty"`
Address OIDCAddress `json:"address,omitempty"`
Azp string `json:"azp,omitempty"`
Provider string `json:"provider,omitempty"`
jwt.RegisteredClaims
}
@ -48,14 +47,13 @@ func getStreetAddress(user *User) string {
func getStandardClaims(claims Claims) ClaimsStandard {
res := ClaimsStandard{
UserStandard: getStandardUser(claims.User),
UserShort: getShortUser(claims.User),
EmailVerified: claims.User.EmailVerified,
TokenType: claims.TokenType,
Nonce: claims.Nonce,
Scope: claims.Scope,
RegisteredClaims: claims.RegisteredClaims,
Azp: claims.Azp,
Provider: claims.Provider,
}
res.Phone = ""

View File

@ -15,17 +15,13 @@
package object
import (
"encoding/base64"
"encoding/json"
"fmt"
"io"
"reflect"
"strconv"
"strings"
"github.com/casdoor/casdoor/conf"
"github.com/casdoor/casdoor/faceId"
"github.com/casdoor/casdoor/proxy"
"github.com/casdoor/casdoor/util"
"github.com/go-webauthn/webauthn/webauthn"
"github.com/xorm-io/builder"
@ -248,7 +244,6 @@ type MfaAccount struct {
type FaceId struct {
Name string `xorm:"varchar(100) notnull pk" json:"name"`
FaceIdData []float64 `json:"faceIdData"`
ImageUrl string `json:"ImageUrl"`
}
func GetUserFieldStringValue(user *User, fieldName string) (bool, string, error) {
@ -459,31 +454,6 @@ func GetUserByEmail(owner string, email string) (*User, error) {
}
}
func GetUserByWebauthID(webauthId string) (*User, error) {
user := User{}
existed := false
var err error
if ormer.driverName == "postgres" {
existed, err = ormer.Engine.Where(builder.Like{"\"webauthnCredentials\"", webauthId}).Get(&user)
} else if ormer.driverName == "mssql" {
existed, err = ormer.Engine.Where("CAST(webauthnCredentials AS VARCHAR(MAX)) like ?", "%"+webauthId+"%").Get(&user)
} else if ormer.driverName == "sqlite" {
existed, err = ormer.Engine.Where("CAST(webauthnCredentials AS text) like ?", "%"+webauthId+"%").Get(&user)
} else {
existed, err = ormer.Engine.Where("webauthnCredentials like ?", "%"+webauthId+"%").Get(&user)
}
if err != nil {
return nil, err
}
if !existed {
return nil, fmt.Errorf("user not exist")
}
return &user, err
}
func GetUserByEmailOnly(email string) (*User, error) {
if email == "" {
return nil, nil
@ -837,10 +807,6 @@ func AddUser(user *User) (bool, error) {
return false, fmt.Errorf("the user's owner and name should not be empty")
}
if CheckUsernameWithEmail(user.Name, "en") != "" {
user.Name = util.GetRandomName()
}
organization, err := GetOrganizationByUser(user)
if err != nil {
return false, err
@ -849,16 +815,6 @@ func AddUser(user *User) (bool, error) {
return false, fmt.Errorf("the organization: %s is not found", user.Owner)
}
if user.Owner != "built-in" {
applicationCount, err := GetOrganizationApplicationCount(organization.Owner, organization.Name, "", "")
if err != nil {
return false, err
}
if applicationCount == 0 {
return false, fmt.Errorf("The organization: %s should have one application at least", organization.Owner)
}
}
if organization.DefaultPassword != "" && user.Password == "123" {
user.Password = organization.DefaultPassword
}
@ -1117,17 +1073,6 @@ func ExtendUserWithRolesAndPermissions(user *User) (err error) {
}
func DeleteGroupForUser(user string, group string) (bool, error) {
userObj, err := GetUser(user)
if err != nil {
return false, err
}
userObj.Groups = util.DeleteVal(userObj.Groups, group)
_, err = updateUser(user, userObj, []string{"groups"})
if err != nil {
return false, err
}
return userEnforcer.DeleteGroupForUser(user, group)
}
@ -1234,40 +1179,6 @@ func (user *User) IsGlobalAdmin() bool {
return user.Owner == "built-in"
}
func (user *User) CheckUserFace(faceIdImage []string, provider *Provider) (bool, error) {
faceIdChecker := faceId.GetFaceIdProvider(provider.Type, provider.ClientId, provider.ClientSecret, provider.Endpoint)
httpClient := proxy.DefaultHttpClient
errList := []error{}
for _, userFaceId := range user.FaceIds {
if userFaceId.ImageUrl != "" {
imgResp, err := httpClient.Get(userFaceId.ImageUrl)
if err != nil {
continue
}
imgByte, err := io.ReadAll(imgResp.Body)
if err != nil {
continue
}
base64Img := base64.StdEncoding.EncodeToString(imgByte)
for _, imgBase64 := range faceIdImage {
isSuccess, err := faceIdChecker.Check(imgBase64, base64Img)
if err != nil {
errList = append(errList, err)
continue
}
if isSuccess {
return true, nil
}
}
}
}
if len(errList) > 0 {
return false, errList[0]
}
return false, nil
}
func GenerateIdForNewUser(application *Application) (string, error) {
if application == nil || application.GetSignupItemRule("ID") != "Incremental" {
return util.GenerateId(), nil

View File

@ -81,12 +81,62 @@ func UploadUsers(owner string, path string) (bool, error) {
return false, err
}
transUsers, err := StringArrayToUser(table)
if err != nil {
return false, err
}
newUsers := []*User{}
for _, user := range transUsers {
for index, line := range table {
line := line
if index == 0 || parseLineItem(&line, 0) == "" {
continue
}
user := &User{
Owner: parseLineItem(&line, 0),
Name: parseLineItem(&line, 1),
CreatedTime: parseLineItem(&line, 2),
UpdatedTime: parseLineItem(&line, 3),
Id: parseLineItem(&line, 4),
Type: parseLineItem(&line, 5),
Password: parseLineItem(&line, 6),
PasswordSalt: parseLineItem(&line, 7),
DisplayName: parseLineItem(&line, 8),
FirstName: parseLineItem(&line, 9),
LastName: parseLineItem(&line, 10),
Avatar: parseLineItem(&line, 11),
PermanentAvatar: "",
Email: parseLineItem(&line, 12),
Phone: parseLineItem(&line, 13),
Location: parseLineItem(&line, 14),
Address: []string{parseLineItem(&line, 15)},
Affiliation: parseLineItem(&line, 16),
Title: parseLineItem(&line, 17),
IdCardType: parseLineItem(&line, 18),
IdCard: parseLineItem(&line, 19),
Homepage: parseLineItem(&line, 20),
Bio: parseLineItem(&line, 21),
Tag: parseLineItem(&line, 22),
Region: parseLineItem(&line, 23),
Language: parseLineItem(&line, 24),
Gender: parseLineItem(&line, 25),
Birthday: parseLineItem(&line, 26),
Education: parseLineItem(&line, 27),
Score: parseLineItemInt(&line, 28),
Karma: parseLineItemInt(&line, 29),
Ranking: parseLineItemInt(&line, 30),
IsDefaultAvatar: false,
IsOnline: parseLineItemBool(&line, 31),
IsAdmin: parseLineItemBool(&line, 32),
IsForbidden: parseLineItemBool(&line, 33),
IsDeleted: parseLineItemBool(&line, 34),
SignupApplication: parseLineItem(&line, 35),
Hash: "",
PreHash: "",
CreatedIp: parseLineItem(&line, 36),
LastSigninTime: parseLineItem(&line, 37),
LastSigninIp: parseLineItem(&line, 38),
Ldap: "",
Properties: map[string]string{},
DeletedTime: parseLineItem(&line, 39),
}
if _, ok := oldUserMap[user.GetId()]; !ok {
newUsers = append(newUsers, user)
}

View File

@ -19,14 +19,12 @@ import (
"fmt"
"reflect"
"regexp"
"strconv"
"strings"
"github.com/casdoor/casdoor/conf"
"github.com/casdoor/casdoor/i18n"
"github.com/casdoor/casdoor/idp"
"github.com/casdoor/casdoor/util"
"github.com/go-webauthn/webauthn/webauthn"
jsoniter "github.com/json-iterator/go"
"github.com/xorm-io/core"
)
@ -691,103 +689,3 @@ func IsAppUser(userId string) bool {
}
return false
}
func setReflectAttr[T any](fieldValue *reflect.Value, fieldString string) error {
unmarshalValue := new(T)
err := json.Unmarshal([]byte(fieldString), unmarshalValue)
if err != nil {
return err
}
fvElem := fieldValue
fvElem.Set(reflect.ValueOf(*unmarshalValue))
return nil
}
func StringArrayToUser(stringArray [][]string) ([]*User, error) {
fieldNames := stringArray[0]
excelMap := []map[string]string{}
userFieldMap := map[string]int{}
reflectedUser := reflect.TypeOf(User{})
for i := 0; i < reflectedUser.NumField(); i++ {
userFieldMap[strings.ToLower(reflectedUser.Field(i).Name)] = i
}
for idx, field := range stringArray {
if idx == 0 {
continue
}
tempMap := map[string]string{}
for idx, val := range field {
tempMap[fieldNames[idx]] = val
}
excelMap = append(excelMap, tempMap)
}
users := []*User{}
var err error
for _, u := range excelMap {
user := User{}
reflectedUser := reflect.ValueOf(&user).Elem()
for k, v := range u {
if v == "" || v == "null" || v == "[]" || v == "{}" {
continue
}
fName := strings.ToLower(strings.ReplaceAll(k, "_", ""))
fieldIdx, ok := userFieldMap[fName]
if !ok {
continue
}
fv := reflectedUser.Field(fieldIdx)
if !fv.IsValid() {
continue
}
switch fv.Kind() {
case reflect.String:
fv.SetString(v)
continue
case reflect.Bool:
fv.SetBool(v == "1")
continue
case reflect.Int:
intVal, err := strconv.Atoi(v)
if err != nil {
return nil, err
}
fv.SetInt(int64(intVal))
continue
}
switch fv.Type() {
case reflect.TypeOf([]string{}):
err = setReflectAttr[[]string](&fv, v)
case reflect.TypeOf([]*string{}):
err = setReflectAttr[[]*string](&fv, v)
case reflect.TypeOf([]*FaceId{}):
err = setReflectAttr[[]*FaceId](&fv, v)
case reflect.TypeOf([]*MfaProps{}):
err = setReflectAttr[[]*MfaProps](&fv, v)
case reflect.TypeOf([]*Role{}):
err = setReflectAttr[[]*Role](&fv, v)
case reflect.TypeOf([]*Permission{}):
err = setReflectAttr[[]*Permission](&fv, v)
case reflect.TypeOf([]ManagedAccount{}):
err = setReflectAttr[[]ManagedAccount](&fv, v)
case reflect.TypeOf([]MfaAccount{}):
err = setReflectAttr[[]MfaAccount](&fv, v)
case reflect.TypeOf([]webauthn.Credential{}):
err = setReflectAttr[[]webauthn.Credential](&fv, v)
}
if err != nil {
return nil, err
}
}
users = append(users, &user)
}
return users, nil
}

View File

@ -38,8 +38,6 @@ type Webhook struct {
ContentType string `xorm:"varchar(100)" json:"contentType"`
Headers []*Header `xorm:"mediumtext" json:"headers"`
Events []string `xorm:"varchar(1000)" json:"events"`
TokenFields []string `xorm:"varchar(1000)" json:"tokenFields"`
ObjectFields []string `xorm:"varchar(1000)" json:"objectFields"`
IsUserExtended bool `json:"isUserExtended"`
SingleOrgOnly bool `json:"singleOrgOnly"`
IsEnabled bool `json:"isEnabled"`

View File

@ -17,7 +17,6 @@ package object
import (
"io"
"net/http"
"reflect"
"strings"
"github.com/casdoor/casdoor/util"
@ -26,43 +25,17 @@ import (
func sendWebhook(webhook *Webhook, record *casvisorsdk.Record, extendedUser *User) (int, string, error) {
client := &http.Client{}
userMap := make(map[string]interface{})
var body io.Reader
if webhook.TokenFields != nil && len(webhook.TokenFields) > 0 && extendedUser != nil {
userValue := reflect.ValueOf(extendedUser).Elem()
for _, field := range webhook.TokenFields {
userField := userValue.FieldByName(field)
if userField.IsValid() {
newfield := util.SnakeToCamel(util.CamelToSnakeCase(field))
userMap[newfield] = userField.Interface()
}
}
type RecordEx struct {
casvisorsdk.Record
ExtendedUser map[string]interface{} `json:"extendedUser"`
}
recordEx := &RecordEx{
Record: *record,
ExtendedUser: userMap,
}
body = strings.NewReader(util.StructToJson(recordEx))
} else {
type RecordEx struct {
casvisorsdk.Record
ExtendedUser *User `xorm:"-" json:"extendedUser"`
}
recordEx := &RecordEx{
Record: *record,
ExtendedUser: extendedUser,
}
body = strings.NewReader(util.StructToJson(recordEx))
type RecordEx struct {
casvisorsdk.Record
ExtendedUser *User `xorm:"-" json:"extendedUser"`
}
recordEx := &RecordEx{
Record: *record,
ExtendedUser: extendedUser,
}
body := strings.NewReader(util.StructToJson(recordEx))
req, err := http.NewRequest(webhook.Method, webhook.Url, body)
if err != nil {

View File

@ -4,7 +4,6 @@ import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"strings"
@ -181,11 +180,7 @@ func (c *AirwallexClient) authRequest(method, url string, body interface{}) (map
return nil, err
}
b, _ := json.Marshal(body)
var reqBody io.Reader
if method != "GET" {
reqBody = bytes.NewBuffer(b)
}
req, _ := http.NewRequest(method, url, reqBody)
req, _ := http.NewRequest(method, url, bytes.NewBuffer(b))
req.Header.Set("Authorization", "Bearer "+token)
req.Header.Set("Content-Type", "application/json")
resp, err := c.client.Do(req)

View File

@ -66,7 +66,6 @@ func initAPI() {
beego.Router("/api/get-webhook-event", &controllers.ApiController{}, "GET:GetWebhookEventType")
beego.Router("/api/get-captcha-status", &controllers.ApiController{}, "GET:GetCaptchaStatus")
beego.Router("/api/callback", &controllers.ApiController{}, "POST:Callback")
beego.Router("/api/device-auth", &controllers.ApiController{}, "POST:DeviceAuth")
beego.Router("/api/get-organizations", &controllers.ApiController{}, "GET:GetOrganizations")
beego.Router("/api/get-organization", &controllers.ApiController{}, "GET:GetOrganization")

View File

@ -89,7 +89,7 @@ func fastAutoSignin(ctx *context.Context) (string, error) {
return "", nil
}
code, err := object.GetOAuthCode(userId, clientId, "", responseType, redirectUri, scope, state, nonce, codeChallenge, ctx.Request.Host, getAcceptLanguage(ctx))
code, err := object.GetOAuthCode(userId, clientId, responseType, redirectUri, scope, state, nonce, codeChallenge, ctx.Request.Host, getAcceptLanguage(ctx))
if err != nil {
return "", err
} else if code.Message != "" {

View File

@ -13,8 +13,8 @@
// limitations under the License.
import React from "react";
import {Button, Card, Col, ConfigProvider, Input, InputNumber, Popover, Radio, Result, Row, Select, Space, Switch, Upload} from "antd";
import {CopyOutlined, HolderOutlined, LinkOutlined, UploadOutlined, UsergroupAddOutlined} from "@ant-design/icons";
import {Button, Card, Col, ConfigProvider, Input, InputNumber, Popover, Radio, Result, Row, Select, Switch, Upload} from "antd";
import {CopyOutlined, LinkOutlined, UploadOutlined} from "@ant-design/icons";
import * as ApplicationBackend from "./backend/ApplicationBackend";
import * as CertBackend from "./backend/CertBackend";
import * as Setting from "./Setting";
@ -36,7 +36,6 @@ import ThemeEditor from "./common/theme/ThemeEditor";
import SigninTable from "./table/SigninTable";
import Editor from "./common/Editor";
import * as GroupBackend from "./backend/GroupBackend";
const {Option} = Select;
@ -53,14 +52,6 @@ const template = `<style>
background-color: #333333;
box-shadow: 0 0 30px 20px rgba(255, 255, 255, 0.20);
}
.forget-content {
padding: 10px 100px 20px;
margin: 30px auto;
border: 2px solid #fff;
border-radius: 7px;
background-color: rgb(255 255 255);
box-shadow: 0 0 20px rgb(0 0 0 / 20%);
}
</style>`;
const previewGrid = Setting.isMobile() ? 22 : 11;
@ -94,11 +85,11 @@ const sideTemplate = `<style>
}
</style>
<div class="left-model">
<span class="side-logo"> <img src="${Setting.StaticBaseUrl}/img/casdoor-logo_1185x256.png" alt="Casdoor" style="width: 120px">
<span class="side-logo"> <img src="https://cdn.casbin.org/img/casdoor-logo_1185x256.png" alt="Casdoor" style="width: 120px">
<span>SSO</span>
</span>
<div class="img">
<img src="${Setting.StaticBaseUrl}/img/casbin.svg" alt="Casdoor"/>
<img src="https://cdn.casbin.org/img/casbin.svg" alt="Casdoor"/>
</div>
</div>
`;
@ -125,7 +116,6 @@ class ApplicationEditPage extends React.Component {
UNSAFE_componentWillMount() {
this.getApplication();
this.getOrganizations();
this.getGroups();
}
getApplication() {
@ -177,17 +167,6 @@ class ApplicationEditPage extends React.Component {
});
}
getGroups() {
GroupBackend.getGroups(this.state.organizationName)
.then((res) => {
if (res.status === "ok") {
this.setState({
groups: res.data,
});
}
});
}
getCerts(application) {
let owner = application.organization;
if (application.isShared) {
@ -418,16 +397,6 @@ class ApplicationEditPage extends React.Component {
/>
</Col>
</Row>
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("application:Forced redirect origin"), i18next.t("general:Forced redirect origin - Tooltip"))} :
</Col>
<Col span={22} >
<Input prefix={<LinkOutlined />} value={this.state.application.forcedRedirectOrigin} onChange={e => {
this.updateApplicationField("forcedRedirectOrigin", e.target.value);
}} />
</Col>
</Row>
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("application:Token format"), i18next.t("application:Token format - Tooltip"))} :
@ -454,7 +423,6 @@ class ApplicationEditPage extends React.Component {
</Col>
<Col span={22} >
<Select virtual={false} disabled={this.state.application.tokenFormat !== "JWT-Custom"} mode="tags" showSearch style={{width: "100%"}} value={this.state.application.tokenFields} onChange={(value => {this.updateApplicationField("tokenFields", value);})}>
<Option key={"provider"} value={"provider"}>{"Provider"}</Option>)
{
Setting.getUserCommonFields().map((item, index) => <Option key={index} value={item}>{item}</Option>)
}
@ -501,31 +469,6 @@ class ApplicationEditPage extends React.Component {
}} />
</Col>
</Row>
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("ldap:Default group"), i18next.t("ldap:Default group - Tooltip"))} :
</Col>
<Col span={22}>
<Select virtual={false} style={{width: "100%"}} value={this.state.application.defaultGroup ?? []} onChange={(value => {
this.updateApplicationField("defaultGroup", value);
})}
>
<Option key={""} value={""}>
<Space>
{i18next.t("general:Default")}
</Space>
</Option>
{
this.state.groups?.map((group) => <Option key={group.name} value={`${group.owner}/${group.name}`}>
<Space>
{group.type === "Physical" ? <UsergroupAddOutlined /> : <HolderOutlined />}
{group.displayName}
</Space>
</Option>)
}
</Select>
</Col>
</Row>
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 19 : 2}>
{Setting.getLabel(i18next.t("application:Enable signup"), i18next.t("application:Enable signup - Tooltip"))} :
@ -727,7 +670,6 @@ class ApplicationEditPage extends React.Component {
{id: "token", name: "Token"},
{id: "id_token", name: "ID Token"},
{id: "refresh_token", name: "Refresh Token"},
{id: "urn:ietf:params:oauth:grant-type:device_code", name: "Device Code"},
].map((item, index) => <Option key={index} value={item.id}>{item.name}</Option>)
}
</Select>
@ -862,33 +804,6 @@ class ApplicationEditPage extends React.Component {
</Row>
</Col>
</Row>
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("application:Background URL Mobile"), i18next.t("application:Background URL Mobile - Tooltip"))} :
</Col>
<Col span={22} style={(Setting.isMobile()) ? {maxWidth: "100%"} : {}}>
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("general:URL"), i18next.t("general:URL - Tooltip"))} :
</Col>
<Col span={22} >
<Input prefix={<LinkOutlined />} value={this.state.application.formBackgroundUrlMobile} onChange={e => {
this.updateApplicationField("formBackgroundUrlMobile", e.target.value);
}} />
</Col>
</Row>
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
{i18next.t("general:Preview")}:
</Col>
<Col span={22} >
<a target="_blank" rel="noreferrer" href={this.state.application.formBackgroundUrlMobile}>
<img src={this.state.application.formBackgroundUrlMobile} alt={this.state.application.formBackgroundUrlMobile} height={90} style={{marginBottom: "20px"}} />
</a>
</Col>
</Row>
</Col>
</Row>
<Row>
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("application:Custom CSS"), i18next.t("application:Custom CSS - Tooltip"))} :

View File

@ -109,7 +109,7 @@ class EntryPage extends React.Component {
<React.Fragment>
<CustomHead headerHtml={this.state.application?.headerHtml} />
<div className={`${isDarkMode ? "loginBackgroundDark" : "loginBackground"}`}
style={{backgroundImage: Setting.inIframe() ? null : (Setting.isMobile() ? `url(${this.state.application?.formBackgroundUrlMobile})` : `url(${this.state.application?.formBackgroundUrl})`)}}>
style={{backgroundImage: Setting.inIframe() || Setting.isMobile() ? null : `url(${this.state.application?.formBackgroundUrl})`}}>
<Spin size="large" spinning={this.state.application === undefined && this.state.pricing === undefined} tip={i18next.t("login:Loading")}
style={{width: "100%", margin: "0 auto", position: "absolute"}} />
<Switch>
@ -119,7 +119,6 @@ class EntryPage extends React.Component {
<Route exact path="/login/:owner" render={(props) => this.renderHomeIfLoggedIn(<SelfLoginPage {...this.props} application={this.state.application} onUpdateApplication={onUpdateApplication} {...props} />)} />
<Route exact path="/signup/oauth/authorize" render={(props) => <SignupPage {...this.props} application={this.state.application} onUpdateApplication={onUpdateApplication} {...props} />} />
<Route exact path="/login/oauth/authorize" render={(props) => <LoginPage {...this.props} application={this.state.application} type={"code"} mode={"signin"} onUpdateApplication={onUpdateApplication} {...props} />} />
<Route exact path="/login/oauth/device/:userCode" render={(props) => <LoginPage {...this.props} application={this.state.application} type={"device"} mode={"signin"} onUpdateApplication={onUpdateApplication} {...props} />} />
<Route exact path="/login/saml/authorize/:owner/:applicationName" render={(props) => <LoginPage {...this.props} application={this.state.application} type={"saml"} mode={"signin"} onUpdateApplication={onUpdateApplication} {...props} />} />
<Route exact path="/forget" render={(props) => <SelfForgetPage {...this.props} account={this.props.account} application={this.state.application} onUpdateApplication={onUpdateApplication} {...props} />} />
<Route exact path="/forget/:applicationName" render={(props) => <ForgetPage {...this.props} account={this.props.account} application={this.state.application} onUpdateApplication={onUpdateApplication} {...props} />} />

View File

@ -114,7 +114,7 @@ class InvitationEditPage extends React.Component {
const selectedOrganization = Setting.getArrayItem(this.state.organizations, "name", this.state.invitation.owner);
defaultApplication = selectedOrganization.defaultApplication;
if (!defaultApplication) {
Setting.showMessage("error", i18next.t("invitation:You need to first specify a default application for organization: ") + selectedOrganization.name);
Setting.showMessage("error", i18next.t("invitation:You need to specify a default application for ") + selectedOrganization.name);
return;
}
}

View File

@ -170,16 +170,6 @@ 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:Allow self-signed certificate"), i18next.t("ldap:Allow self-signed certificate - Tooltip"))} :
</Col>
<Col span={21} >
<Switch checked={this.state.ldap.allowSelfSignedCert} onChange={checked => {
this.updateLdapField("allowSelfSignedCert", 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"))} :

View File

@ -95,9 +95,8 @@ import TransactionEditPage from "./TransactionEditPage";
import VerificationListPage from "./VerificationListPage";
function ManagementPage(props) {
const [menuVisible, setMenuVisible] = useState(false);
const navItems = props.account?.organization?.navItems;
const widgetItems = props.account?.organization?.widgetItems;
function logout() {
AuthBackend.logout()
@ -176,35 +175,6 @@ function ManagementPage(props) {
);
}
function navItemsIsAll() {
return !Array.isArray(navItems) || !!navItems?.includes("all");
}
function widgetItemsIsAll() {
return !Array.isArray(widgetItems) || !!widgetItems?.includes("all");
}
function renderWidgets() {
const widgets = [
Setting.getItem(<ThemeSelect themeAlgorithm={props.themeAlgorithm} onChange={props.setLogoAndThemeAlgorithm} />, "theme"),
Setting.getItem(<LanguageSelect languages={props.account.organization.languages} />, "language"),
Setting.getItem(Conf.AiAssistantUrl?.trim() && (
<Tooltip title="Click to open AI assistant">
<div className="select-box" onClick={props.openAiAssistant}>
<DeploymentUnitOutlined style={{fontSize: "24px"}} />
</div>
</Tooltip>
), "ai-assistant"),
Setting.getItem(<OpenTour />, "tour"),
];
if (widgetItemsIsAll()) {
return widgets.map(item => item.label);
}
return widgets.filter(item => widgetItems.includes(item.key)).map(item => item.label);
}
function renderAccountMenu() {
if (props.account === undefined) {
return null;
@ -218,7 +188,20 @@ function ManagementPage(props) {
return (
<React.Fragment>
{renderRightDropdown()}
{renderWidgets()}
<ThemeSelect
themeAlgorithm={props.themeAlgorithm}
onChange={props.setLogoAndThemeAlgorithm} />
<LanguageSelect languages={props.account.organization.languages} />
{
Conf.AiAssistantUrl?.trim() && (
<Tooltip title="Click to open AI assistant">
<div className="select-box" onClick={props.openAiAssistant}>
<DeploymentUnitOutlined style={{fontSize: "24px"}} />
</div>
</Tooltip>
)
}
<OpenTour />
{Setting.isAdminUser(props.account) && (props.uri.indexOf("/trees") === -1) &&
<OrganizationSelect
initValue={Setting.getOrganization()}
@ -340,7 +323,13 @@ function ManagementPage(props) {
}
}
if (navItemsIsAll()) {
const navItems = props.account.organization.navItems;
if (!Array.isArray(navItems)) {
return res;
}
if (navItems.includes("all")) {
return res;
}
@ -454,6 +443,8 @@ function ManagementPage(props) {
return Setting.isMobile() || window.location.pathname.startsWith("/trees");
}
const menuStyleRight = Setting.isAdminUser(props.account) && !Setting.isMobile() ? "calc(180px + 280px)" : "320px";
const onClose = () => {
setMenuVisible(false);
};
@ -465,40 +456,34 @@ function ManagementPage(props) {
return (
<React.Fragment>
<EnableMfaNotification account={props.account} />
<Header style={{display: "flex", justifyContent: "space-between", alignItems: "center", padding: "0", marginBottom: "4px", backgroundColor: props.themeAlgorithm.includes("dark") ? "black" : "white"}} >
{
props.requiredEnableMfa || (Setting.isMobile() ? (
<React.Fragment>
<Drawer title={i18next.t("general:Close")} placement="left" open={menuVisible} onClose={onClose}>
<Menu
items={getMenuItems()}
mode={"inline"}
selectedKeys={[props.selectedMenuKey]}
style={{lineHeight: "64px"}}
onClick={onClose}
>
</Menu>
</Drawer>
<Button icon={<BarsOutlined />} onClick={showMenu} type="text">
{i18next.t("general:Menu")}
</Button>
</React.Fragment>
) : (
// Padding 1px for Menu Item Highlight border
<div style={{flex: 1, overflow: "hidden", paddingBottom: "1px"}}>
<Header style={{padding: "0", marginBottom: "3px", backgroundColor: props.themeAlgorithm.includes("dark") ? "black" : "white"}} >
{props.requiredEnableMfa || (Setting.isMobile() ?
<React.Fragment>
<Drawer title={i18next.t("general:Close")} placement="left" open={menuVisible} onClose={onClose}>
<Menu
onClick={onClose}
items={getMenuItems()}
mode={"horizontal"}
mode={"inline"}
selectedKeys={[props.selectedMenuKey]}
style={{backgroundColor: props.themeAlgorithm.includes("dark") ? "black" : "white"}}
/>
</div>
))
style={{lineHeight: "64px"}}
onClick={onClose}
>
</Menu>
</Drawer>
<Button icon={<BarsOutlined />} onClick={showMenu} type="text">
{i18next.t("general:Menu")}
</Button>
</React.Fragment> :
<Menu
onClick={onClose}
items={getMenuItems()}
mode={"horizontal"}
selectedKeys={[props.selectedMenuKey]}
style={{position: "absolute", left: 0, right: menuStyleRight, backgroundColor: props.themeAlgorithm.includes("dark") ? "black" : "white"}}
/>
)}
{
renderAccountMenu()
}
<div style={{flexShrink: 0}}>
{renderAccountMenu()}
</div>
</Header>
<Content style={{display: "flex", flexDirection: "column"}} >
{isWithoutCard() ?

View File

@ -27,7 +27,6 @@ import AccountTable from "./table/AccountTable";
import ThemeEditor from "./common/theme/ThemeEditor";
import MfaTable from "./table/MfaTable";
import {NavItemTree} from "./common/NavItemTree";
import {WidgetItemTree} from "./common/WidgetItemTree";
const {Option} = Select;
@ -276,7 +275,7 @@ class OrganizationEditPage extends React.Component {
</Col>
<Col span={22} >
<Select virtual={false} style={{width: "100%"}} value={this.state.organization.passwordType} onChange={(value => {this.updateOrganizationField("passwordType", value);})}
options={["plain", "salt", "sha512-salt", "md5-salt", "bcrypt", "pbkdf2-salt", "argon2id", "pbkdf2-django"].map(item => Setting.getOption(item, item))}
options={["plain", "salt", "sha512-salt", "md5-salt", "bcrypt", "pbkdf2-salt", "argon2id"].map(item => Setting.getOption(item, item))}
/>
</Col>
</Row>
@ -538,7 +537,7 @@ class OrganizationEditPage extends React.Component {
</Row>
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("organization:Navbar items"), i18next.t("organization:Navbar items - Tooltip"))} :
{Setting.getLabel(i18next.t("general:Navbar items"), i18next.t("general:Navbar items - Tooltip"))} :
</Col>
<Col span={22} >
<NavItemTree
@ -551,21 +550,6 @@ class OrganizationEditPage extends React.Component {
/>
</Col>
</Row>
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("organization:Widget items"), i18next.t("organization:Widget items - Tooltip"))} :
</Col>
<Col span={22} >
<WidgetItemTree
disabled={!Setting.isAdminUser(this.props.account)}
checkedKeys={this.state.organization.widgetItems ?? ["all"]}
defaultExpandedKeys={["all"]}
onCheck={(checked, _) => {
this.updateOrganizationField("widgetItems", checked);
}}
/>
</Col>
</Row>
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("organization:Account items"), i18next.t("organization:Account items - Tooltip"))} :

View File

@ -232,15 +232,6 @@ class PlanEditPage extends React.Component {
[
{id: "USD", name: "USD"},
{id: "CNY", name: "CNY"},
{id: "EUR", name: "EUR"},
{id: "JPY", name: "JPY"},
{id: "GBP", name: "GBP"},
{id: "AUD", name: "AUD"},
{id: "CAD", name: "CAD"},
{id: "CHF", name: "CHF"},
{id: "HKD", name: "HKD"},
{id: "SGD", name: "SGD"},
{id: "BRL", name: "BRL"},
].map((item, index) => <Option key={index} value={item.id}>{item.name}</Option>)
}
</Select>

View File

@ -139,8 +139,6 @@ class ProductBuyPage extends React.Component {
return "HK$";
} else if (product?.currency === "SGD") {
return "S$";
} else if (product?.currency === "BRL") {
return "R$";
} else {
return "(Unknown currency)";
}

View File

@ -217,7 +217,6 @@ class ProductEditPage extends React.Component {
{id: "CHF", name: "CHF"},
{id: "HKD", name: "HKD"},
{id: "SGD", name: "SGD"},
{id: "BRL", name: "BRL"},
].map((item, index) => <Option key={index} value={item.id}>{item.name}</Option>)
}
</Select>

View File

@ -29,7 +29,6 @@ import {CaptchaPreview} from "./common/CaptchaPreview";
import {CountryCodeSelect} from "./common/select/CountryCodeSelect";
import * as Web3Auth from "./auth/Web3Auth";
import Editor from "./common/Editor";
import HttpHeaderTable from "./table/HttpHeaderTable";
const {Option} = Select;
const {TextArea} = Input;
@ -42,13 +41,6 @@ const defaultUserMapping = {
avatarUrl: "avatarUrl",
};
const defaultEmailMapping = {
fromName: "fromName",
toAddress: "toAddress",
subject: "subject",
content: "content",
};
class ProviderEditPage extends React.Component {
constructor(props) {
super(props);
@ -79,16 +71,7 @@ class ProviderEditPage extends React.Component {
if (res.status === "ok") {
const provider = res.data;
if (provider.type === "Custom HTTP Email") {
if (!provider.userMapping) {
provider.userMapping = provider.userMapping || defaultEmailMapping;
}
if (!provider.userMapping?.fromName) {
provider.userMapping = defaultEmailMapping;
}
} else {
provider.userMapping = provider.userMapping || defaultUserMapping;
}
provider.userMapping = provider.userMapping || defaultUserMapping;
this.setState({
provider: provider,
});
@ -162,16 +145,9 @@ class ProviderEditPage extends React.Component {
const requiredKeys = ["id", "username", "displayName"];
const provider = this.state.provider;
if (provider.type === "Custom HTTP Email") {
if (value === "") {
Setting.showMessage("error", i18next.t("provider:This field is required"));
return;
}
} else {
if (value === "" && requiredKeys.includes(key)) {
Setting.showMessage("error", i18next.t("provider:This field is required"));
return;
}
if (value === "" && requiredKeys.includes(key)) {
Setting.showMessage("error", i18next.t("provider:This field is required"));
return;
}
provider.userMapping[key] = value;
@ -207,30 +183,6 @@ class ProviderEditPage extends React.Component {
</React.Fragment>
);
}
renderEmailMappingInput() {
return (
<React.Fragment>
{Setting.getLabel(i18next.t("provider:From name"), i18next.t("provider:From name - Tooltip"))} :
<Input value={this.state.provider.userMapping.fromName} onChange={e => {
this.updateUserMappingField("fromName", e.target.value);
}} />
{Setting.getLabel(i18next.t("provider:From address"), i18next.t("provider:From address - Tooltip"))} :
<Input value={this.state.provider.userMapping.toAddress} onChange={e => {
this.updateUserMappingField("toAddress", e.target.value);
}} />
{Setting.getLabel(i18next.t("provider:Subject"), i18next.t("provider:Subject - Tooltip"))} :
<Input value={this.state.provider.userMapping.subject} onChange={e => {
this.updateUserMappingField("subject", e.target.value);
}} />
{Setting.getLabel(i18next.t("provider:Email content"), i18next.t("provider:Email content - Tooltip"))} :
<Input value={this.state.provider.userMapping.content} onChange={e => {
this.updateUserMappingField("content", e.target.value);
}} />
</React.Fragment>
);
}
getClientIdLabel(provider) {
switch (provider.category) {
case "OAuth":
@ -336,8 +288,10 @@ class ProviderEditPage extends React.Component {
default:
if (provider.type === "Aliyun Captcha") {
return Setting.getLabel(i18next.t("provider:Scene"), i18next.t("provider:Scene - Tooltip"));
} else if (provider.type === "WeChat Pay" || provider.type === "CUCloud") {
} else if (provider.type === "WeChat Pay") {
return Setting.getLabel(i18next.t("provider:App ID"), i18next.t("provider:App ID - Tooltip"));
} else if (provider.type === "CUCloud") {
return Setting.getLabel(i18next.t("provider:Account ID"), i18next.t("provider:Account ID - Tooltip"));
} else {
return Setting.getLabel(i18next.t("provider:Client ID 2"), i18next.t("provider:Client ID 2 - Tooltip"));
}
@ -435,8 +389,8 @@ class ProviderEditPage extends React.Component {
text = i18next.t("provider:App Key");
tooltip = i18next.t("provider:App Key - Tooltip");
} else if (provider.type === "CUCloud") {
text = "Topic name";
tooltip = "Topic name - Tooltip";
text = i18next.t("provider:Topic name");
tooltip = i18next.t("provider:Topic name - Tooltip");
}
}
@ -613,8 +567,6 @@ class ProviderEditPage extends React.Component {
this.updateProviderField("type", "MetaMask");
} else if (value === "Notification") {
this.updateProviderField("type", "Telegram");
} else if (value === "Face ID") {
this.updateProviderField("type", "Alibaba Cloud Facebody");
}
})}>
{
@ -628,7 +580,6 @@ class ProviderEditPage extends React.Component {
{id: "SMS", name: "SMS"},
{id: "Storage", name: "Storage"},
{id: "Web3", name: "Web3"},
{id: "Face ID", name: "Face ID"},
]
.sort((a, b) => a.name.localeCompare(b.name))
.map((providerCategory, index) => <Option key={index} value={providerCategory.id}>{providerCategory.name}</Option>)
@ -692,35 +643,23 @@ class ProviderEditPage extends React.Component {
</Row>
{
this.state.provider.type !== "WeCom" ? null : (
<React.Fragment>
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={2}>
{Setting.getLabel(i18next.t("general:Method"), i18next.t("provider:Method - Tooltip"))} :
</Col>
<Col span={22} >
<Select virtual={false} style={{width: "100%"}} value={this.state.provider.method} onChange={value => {
this.updateProviderField("method", value);
}}>
{
[
{id: "Normal", name: i18next.t("provider:Normal")},
{id: "Silent", name: i18next.t("provider:Silent")},
].map((method, index) => <Option key={index} value={method.id}>{method.name}</Option>)
}
</Select>
</Col>
</Row>
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={2}>
{Setting.getLabel(i18next.t("provider:Use id as name"), i18next.t("provider:Use id as name - Tooltip"))} :
</Col>
<Col span={22} >
<Switch checked={this.state.provider.disableSsl} onChange={checked => {
this.updateProviderField("disableSsl", checked);
}} />
</Col>
</Row>
</React.Fragment>)
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={2}>
{Setting.getLabel(i18next.t("general:Method"), i18next.t("provider:Method - Tooltip"))} :
</Col>
<Col span={22} >
<Select virtual={false} style={{width: "100%"}} value={this.state.provider.method} onChange={value => {
this.updateProviderField("method", value);
}}>
{
[
{id: "Normal", name: i18next.t("provider:Normal")},
{id: "Silent", name: i18next.t("provider:Silent")},
].map((method, index) => <Option key={index} value={method.id}>{method.name}</Option>)
}
</Select>
</Col>
</Row>)
}
</React.Fragment>
)
@ -831,7 +770,6 @@ class ProviderEditPage extends React.Component {
(this.state.provider.category === "Web3") ||
(this.state.provider.category === "Storage" && this.state.provider.type === "Local File System") ||
(this.state.provider.category === "SMS" && this.state.provider.type === "Custom HTTP SMS") ||
(this.state.provider.category === "Email" && this.state.provider.type === "Custom HTTP Email") ||
(this.state.provider.category === "Notification" && (this.state.provider.type === "Google Chat" || this.state.provider.type === "Custom HTTP") || this.state.provider.type === "Balance") ? null : (
<React.Fragment>
{
@ -950,7 +888,7 @@ class ProviderEditPage extends React.Component {
)
}
{
this.state.provider.type !== "ADFS" && this.state.provider.type !== "AzureAD" && this.state.provider.type !== "AzureADB2C" && (this.state.provider.type !== "Casdoor" && this.state.category !== "Storage") && this.state.provider.type !== "Okta" && this.state.provider.type !== "Nextcloud" ? null : (
this.state.provider.type !== "ADFS" && this.state.provider.type !== "AzureAD" && this.state.provider.type !== "AzureADB2C" && (this.state.provider.type !== "Casdoor" && this.state.category !== "Storage") && this.state.provider.type !== "Okta" ? null : (
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={2}>
{Setting.getLabel(i18next.t("provider:Domain"), i18next.t("provider:Domain - Tooltip"))} :
@ -963,7 +901,7 @@ class ProviderEditPage extends React.Component {
</Row>
)
}
{["Face ID", "Storage"].includes(this.state.provider.category) || ["Custom HTTP SMS", "Custom HTTP Email", "SendGrid", "CUCloud"].includes(this.state.provider.type) ? (
{this.state.provider.category === "Storage" || ["Custom HTTP SMS", "Custom HTTP Email", "SendGrid", "CUCloud"].includes(this.state.provider.type) ? (
<div>
{["Local File System", "CUCloud"].includes(this.state.provider.type) ? null : (
<Row style={{marginTop: "20px"}} >
@ -977,7 +915,7 @@ class ProviderEditPage extends React.Component {
</Col>
</Row>
)}
{["Custom HTTP SMS", "Custom HTTP Email", "SendGrid", "Local File System", "MinIO", "Tencent Cloud COS", "Google Cloud Storage", "Qiniu Cloud Kodo", "Synology", "Casdoor", "CUCloud", "Alibaba Cloud Facebody"].includes(this.state.provider.type) ? null : (
{["Custom HTTP SMS", "SendGrid", "Local File System", "MinIO", "Tencent Cloud COS", "Google Cloud Storage", "Qiniu Cloud Kodo", "Synology", "Casdoor", "CUCloud"].includes(this.state.provider.type) ? null : (
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={2}>
{Setting.getLabel(i18next.t("provider:Endpoint (Intranet)"), i18next.t("provider:Region endpoint for Intranet"))} :
@ -989,7 +927,7 @@ class ProviderEditPage extends React.Component {
</Col>
</Row>
)}
{["Custom HTTP SMS", "Custom HTTP Email", "SendGrid", "Local File System", "CUCloud", "Alibaba Cloud Facebody"].includes(this.state.provider.type) ? null : (
{["Custom HTTP SMS", "SendGrid", "Local File System", "CUCloud"].includes(this.state.provider.type) ? null : (
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={2}>
{["Casdoor"].includes(this.state.provider.type) ?
@ -1003,7 +941,7 @@ class ProviderEditPage extends React.Component {
</Col>
</Row>
)}
{["Custom HTTP SMS", "Custom HTTP Email", "SendGrid", "CUCloud", "Alibaba Cloud Facebody"].includes(this.state.provider.type) ? null : (
{["Custom HTTP SMS", "SendGrid", "CUCloud"].includes(this.state.provider.type) ? null : (
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={2}>
{Setting.getLabel(i18next.t("provider:Path prefix"), i18next.t("provider:Path prefix - Tooltip"))} :
@ -1015,7 +953,7 @@ class ProviderEditPage extends React.Component {
</Col>
</Row>
)}
{["Custom HTTP SMS", "Custom HTTP Email", "SendGrid", "Synology", "Casdoor", "CUCloud", "Alibaba Cloud Facebody"].includes(this.state.provider.type) ? null : (
{["Custom HTTP SMS", "SendGrid", "Synology", "Casdoor", "CUCloud"].includes(this.state.provider.type) ? null : (
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={2}>
{Setting.getLabel(i18next.t("provider:Domain"), i18next.t("provider:Domain - Tooltip"))} :
@ -1156,66 +1094,6 @@ class ProviderEditPage extends React.Component {
</Col>
</Row>
)}
{
!["Custom HTTP Email"].includes(this.state.provider.type) ? null : (
<React.Fragment>
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={2}>
{Setting.getLabel(i18next.t("general:Method"), i18next.t("provider:Method - Tooltip"))} :
</Col>
<Col span={22} >
<Select virtual={false} style={{width: "100%"}} value={this.state.provider.method} onChange={value => {
this.updateProviderField("method", value);
}}>
{
[
{id: "GET", name: "GET"},
{id: "POST", name: "POST"},
{id: "PUT", name: "PUT"},
{id: "DELETE", name: "DELETE"},
].map((method, index) => <Option key={index} value={method.id}>{method.name}</Option>)
}
</Select>
</Col>
</Row>
{
this.state.provider.method !== "GET" ? (<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("webhook:Content type"), i18next.t("webhook:Content type - Tooltip"))} :
</Col>
<Col span={22} >
<Select virtual={false} style={{width: "100%"}} value={this.state.provider.issuerUrl === "" ? "application/x-www-form-urlencoded" : this.state.provider.issuerUrl} onChange={value => {
this.updateProviderField("issuerUrl", value);
}}>
{
[
{id: "application/json", name: "application/json"},
{id: "application/x-www-form-urlencoded", name: "application/x-www-form-urlencoded"},
].map((method, index) => <Option key={index} value={method.id}>{method.name}</Option>)
}
</Select>
</Col>
</Row>) : null
}
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("provider:HTTP header"), i18next.t("provider:HTTP header - Tooltip"))} :
</Col>
<Col span={22} >
<HttpHeaderTable httpHeaders={this.state.provider.httpHeaders} onUpdateTable={(value) => {this.updateProviderField("httpHeaders", value);}} />
</Col>
</Row>
{this.state.provider.method !== "GET" ? <Row style={{marginTop: "20px"}}>
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("provider:HTTP body mapping"), i18next.t("provider:HTTP body mapping - Tooltip"))} :
</Col>
<Col span={22}>
{this.renderEmailMappingInput()}
</Col>
</Row> : null}
</React.Fragment>
)
}
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("provider:Email title"), i18next.t("provider:Email title - Tooltip"))} :
@ -1284,7 +1162,7 @@ class ProviderEditPage extends React.Component {
</Button>
</Row>
</React.Fragment>
) : ["SMS"].includes(this.state.provider.category) ? (
) : this.state.provider.category === "SMS" ? (
<React.Fragment>
{["Custom HTTP SMS", "Twilio SMS", "Amazon SNS", "Azure ACS", "Msg91 SMS", "Infobip SMS"].includes(this.state.provider.type) ?
null :
@ -1402,7 +1280,7 @@ class ProviderEditPage extends React.Component {
}} />
</Col>
<Col span={16} >
<Button style={{marginLeft: "10px"}} type="primary" loading={this.state.metadataLoading} onClick={() => {this.fetchSamlMetadata();}}>{i18next.t("general:Request")}</Button>
<Button type="primary" loading={this.state.metadataLoading} onClick={() => {this.fetchSamlMetadata();}}>{i18next.t("general:Request")}</Button>
</Col>
</Row>
<Row style={{marginTop: "20px"}} >

View File

@ -416,12 +416,6 @@ export const OtherProviderInfo = {
url: "https://www.cucloud.cn/",
},
},
"Face ID": {
"Alibaba Cloud Facebody": {
logo: `${StaticBaseUrl}/img/social_aliyun.png`,
url: "https://vision.aliyun.com/facebody",
},
},
};
export function initCountries() {
@ -1156,10 +1150,6 @@ export function getProviderTypeOptions(category) {
{id: "Viber", name: "Viber"},
{id: "CUCloud", name: "CUCloud"},
]);
} else if (category === "Face ID") {
return ([
{id: "Alibaba Cloud Facebody", name: "Alibaba Cloud Facebody"},
]);
} else {
return [];
}
@ -1532,7 +1522,7 @@ export function getUserCommonFields() {
}
export function getDefaultFooterContent() {
return `Powered by <a target="_blank" href="https://casdoor.org" rel="noreferrer"><img style="padding-bottom: 3px" height="20" alt="Casdoor" src="${StaticBaseUrl}/img/casdoor-logo_1185x256.png"/></a>`;
return "Powered by <a target=\"_blank\" href=\"https://casdoor.org\" rel=\"noreferrer\"><img style=\"padding-bottom: 3px\" height=\"20\" alt=\"Casdoor\" src=\"https://cdn.casbin.org/img/casdoor-logo_1185x256.png\"/></a>";
}
export function getEmptyFooterContent() {
@ -1564,7 +1554,7 @@ export function getDefaultHtmlEmailContent() {
<div class="email-container">
<div class="header">
<h3>Casbin Organization</h3>
<img src="${StaticBaseUrl}/img/casdoor-logo_1185x256.png" alt="Casdoor Logo" width="300">
<img src="https://cdn.casbin.org/img/casdoor-logo_1185x256.png" alt="Casdoor Logo" width="300">
</div>
<p><strong>%{user.friendlyName}</strong>, here is your verification code</p>
<p>Use this code for your transaction. It's valid for 5 minutes</p>
@ -1603,8 +1593,6 @@ export function getCurrencyText(product) {
return i18next.t("currency:HKD");
} else if (product?.currency === "SGD") {
return i18next.t("currency:SGD");
} else if (product?.currency === "BRL") {
return i18next.t("currency:BRL");
} else {
return "(Unknown currency)";
}
@ -1616,7 +1604,7 @@ export function isDarkTheme(themeAlgorithm) {
function getPreferredMfaProp(mfaProps) {
for (const i in mfaProps) {
if (mfaProps[i].isPreferred) {
if (mfaProps[i].isPreffered) {
return mfaProps[i];
}
}

View File

@ -37,35 +37,17 @@ class SystemInfo extends React.Component {
UNSAFE_componentWillMount() {
SystemBackend.getSystemInfo("").then(res => {
this.setState({
systemInfo: res.data,
loading: false,
});
if (res.status === "ok") {
this.setState({
systemInfo: res.data,
});
} else {
Setting.showMessage("error", res.msg);
this.stopTimer();
}
const id = setInterval(() => {
SystemBackend.getSystemInfo("").then(res => {
this.setState({
loading: false,
systemInfo: res.data,
});
if (res.status === "ok") {
this.setState({
systemInfo: res.data,
});
} else {
Setting.showMessage("error", res.msg);
this.stopTimer();
}
}).catch(error => {
Setting.showMessage("error", `System info failed to get: ${error}`);
this.stopTimer();
});
SystemBackend.getPrometheusInfo().then(res => {
this.setState({
@ -73,25 +55,17 @@ class SystemInfo extends React.Component {
});
});
}, 1000 * 2);
this.setState({intervalId: id});
}).catch(error => {
Setting.showMessage("error", `System info failed to get: ${error}`);
this.stopTimer();
});
SystemBackend.getVersionInfo().then(res => {
if (res.status === "ok") {
this.setState({
versionInfo: res.data,
});
} else {
Setting.showMessage("error", res.msg);
this.stopTimer();
}
this.setState({
versionInfo: res.data,
});
}).catch(err => {
Setting.showMessage("error", `Version info failed to get: ${err}`);
this.stopTimer();
});
}
@ -103,14 +77,10 @@ class SystemInfo extends React.Component {
this.setState({isTourVisible: TourConfig.getTourVisible()});
};
stopTimer() {
componentWillUnmount() {
if (this.state.intervalId !== null) {
clearInterval(this.state.intervalId);
}
}
componentWillUnmount() {
this.stopTimer();
window.removeEventListener("storageTourChanged", this.handleTourChange);
}
@ -155,9 +125,9 @@ class SystemInfo extends React.Component {
<br /> <br />
<Progress type="circle" percent={Number((Number(this.state.systemInfo.memoryUsed) / Number(this.state.systemInfo.memoryTotal) * 100).toFixed(2))} />
</div>;
const latencyUi = this.state.prometheusInfo?.apiLatency === null || this.state.prometheusInfo?.apiLatency?.length <= 0 ? <Spin size="large" /> :
const latencyUi = this.state.prometheusInfo.apiLatency === null || this.state.prometheusInfo.apiLatency?.length <= 0 ? <Spin size="large" /> :
<PrometheusInfoTable prometheusInfo={this.state.prometheusInfo} table={"latency"} />;
const throughputUi = this.state.prometheusInfo?.apiThroughput === null || this.state.prometheusInfo?.apiThroughput?.length <= 0 ? <Spin size="large" /> :
const throughputUi = this.state.prometheusInfo.apiThroughput === null || this.state.prometheusInfo.apiThroughput?.length <= 0 ? <Spin size="large" /> :
<PrometheusInfoTable prometheusInfo={this.state.prometheusInfo} table={"throughput"} />;
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");

View File

@ -1,5 +1,4 @@
import React from "react";
import * as Setting from "./Setting";
export const TourObj = {
home: [
@ -9,7 +8,7 @@ export const TourObj = {
cover: (
<img
alt="casdoor.png"
src={`${Setting.StaticBaseUrl}/img/casdoor-logo_1185x256.png`}
src="https://cdn.casbin.org/img/casdoor-logo_1185x256.png"
/>
),
},

View File

@ -1054,7 +1054,6 @@ class UserEditPage extends React.Component {
<FaceIdTable
title={i18next.t("user:Face IDs")}
table={this.state.user.faceIds}
{...this.props}
onUpdateTable={(table) => {this.updateUserField("faceIds", table);}}
/>
</Col>

View File

@ -144,9 +144,6 @@ class WebhookEditPage extends React.Component {
if (["port"].includes(key)) {
value = Setting.myParseInt(value);
}
if (key === "objectFields") {
value = value.includes("All") ? ["All"] : value;
}
return value;
}
@ -177,16 +174,7 @@ class WebhookEditPage extends React.Component {
renderWebhook() {
const preview = Setting.deepCopy(previewTemplate);
if (this.state.webhook.isUserExtended) {
if (this.state.webhook.tokenFields && this.state.webhook.tokenFields.length !== 0) {
const extendedUser = {};
this.state.webhook.tokenFields.forEach(field => {
const fieldTrans = field.replace(field[0], field[0].toLowerCase());
extendedUser[fieldTrans] = userTemplate[fieldTrans];
});
preview["extendedUser"] = extendedUser;
} else {
preview["extendedUser"] = userTemplate;
}
preview["extendedUser"] = userTemplate;
}
const previewText = JSON.stringify(preview, null, 2);
@ -297,19 +285,6 @@ class WebhookEditPage extends React.Component {
</Select>
</Col>
</Row>
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("webhook:Object fields"), i18next.t("webhook:Object fields - Tooltip"))} :
</Col>
<Col span={22} >
<Select virtual={false} mode="tags" showSearch style={{width: "100%"}} value={this.state.webhook.objectFields} onChange={(value => {this.updateWebhookField("objectFields", value);})}>
<Option key="All" value="All">{i18next.t("general:All")}</Option>
{
["owner", "name", "createdTime", "updatedTime", "deletedTime", "id", "displayName"].map((item, index) => <Option key={index} value={item}>{item}</Option>)
}
</Select>
</Col>
</Row>
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 19 : 2}>
{Setting.getLabel(i18next.t("webhook:Is user extended"), i18next.t("webhook:Is user extended - Tooltip"))} :
@ -320,18 +295,6 @@ class WebhookEditPage extends React.Component {
}} />
</Col>
</Row>
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("webhook:Extended user fields"), i18next.t("webhook:Extended user fields - Tooltip"))} :
</Col>
<Col span={22} >
<Select virtual={false} mode="tags" showSearch style={{width: "100%"}} value={this.state.webhook.tokenFields} onChange={(value => {this.updateWebhookField("tokenFields", value);})}>
{
Setting.getUserCommonFields().map((item, index) => <Option key={index} value={item}>{item}</Option>)
}
</Select>
</Col>
</Row>
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("general:Preview"), i18next.t("general:Preview - Tooltip"))} :

View File

@ -37,7 +37,7 @@ export function signup(values) {
}
export function getEmailAndPhone(organization, username) {
return fetch(`${authConfig.serverUrl}/api/get-email-and-phone?organization=${organization}&username=${encodeURIComponent(username)}`, {
return fetch(`${authConfig.serverUrl}/api/get-email-and-phone?organization=${organization}&username=${username}`, {
method: "GET",
credentials: "include",
headers: {
@ -61,14 +61,7 @@ export function oAuthParamsToQuery(oAuthParams) {
}
export function getApplicationLogin(params) {
let queryParams = "";
if (params?.type === "cas") {
queryParams = casLoginParamsToQuery(params);
} else if (params?.type === "device") {
queryParams = `?userCode=${params.userCode}&type=device`;
} else {
queryParams = oAuthParamsToQuery(params);
}
const queryParams = (params?.type === "cas") ? casLoginParamsToQuery(params) : oAuthParamsToQuery(params);
return fetch(`${authConfig.serverUrl}/api/get-app-login${queryParams}`, {
method: "GET",
credentials: "include",

View File

@ -193,11 +193,7 @@ class AuthCallback extends React.Component {
const token = res.data;
Setting.goToLink(`${oAuthParams.redirectUri}${concatChar}${responseType}=${token}&state=${oAuthParams.state}&token_type=bearer`);
} else if (responseType === "link") {
let from = innerParams.get("from");
const oauth = innerParams.get("oauth");
if (oauth) {
from += `?oauth=${oauth}`;
}
const from = innerParams.get("from");
Setting.goToLinkSoftOrJumpSelf(this, from);
} else if (responseType === "saml") {
if (res.data2.method === "POST") {

View File

@ -471,8 +471,6 @@ class ForgetPage extends React.Component {
<React.Fragment>
<CustomGithubCorner />
<div className="forget-content" style={{padding: Setting.isMobile() ? "0" : null, boxShadow: Setting.isMobile() ? "none" : null}}>
{Setting.inIframe() || Setting.isMobile() ? null : <div dangerouslySetInnerHTML={{__html: application.formCss}} />}
{Setting.inIframe() || !Setting.isMobile() ? null : <div dangerouslySetInnerHTML={{__html: application.formCssMobile}} />}
<Button type="text"
style={{position: "relative", left: Setting.isMobile() ? "10px" : "-90px", top: 0}}
icon={<ArrowLeftOutlined style={{fontSize: "24px"}} />}

View File

@ -37,8 +37,6 @@ import RedirectForm from "../common/RedirectForm";
import {RequiredMfa} from "./mfa/MfaAuthVerifyForm";
import {GoogleOneTapLoginVirtualButton} from "./GoogleLoginButton";
import * as ProviderButton from "./ProviderButton";
import {goToLink} from "../Setting";
const FaceRecognitionCommonModal = lazy(() => import("../common/modal/FaceRecognitionCommonModal"));
const FaceRecognitionModal = lazy(() => import("../common/modal/FaceRecognitionModal"));
class LoginPage extends React.Component {
@ -63,10 +61,6 @@ class LoginPage extends React.Component {
isTermsOfUseVisible: false,
termsOfUseContent: "",
orgChoiceMode: new URLSearchParams(props.location?.search).get("orgChoiceMode") ?? null,
userLang: null,
loginLoading: false,
userCode: props.userCode ?? (props.match?.params?.userCode ?? null),
userCodeStatus: "",
};
if (this.state.type === "cas" && props.match?.params.casApplicationName !== undefined) {
@ -83,7 +77,7 @@ class LoginPage extends React.Component {
if (this.getApplicationObj() === undefined) {
if (this.state.type === "login" || this.state.type === "saml") {
this.getApplication();
} else if (this.state.type === "code" || this.state.type === "cas" || this.state.type === "device") {
} else if (this.state.type === "code" || this.state.type === "cas") {
this.getApplicationLogin();
} else {
Setting.showMessage("error", `Unknown authentication type: ${this.state.type}`);
@ -157,25 +151,13 @@ class LoginPage extends React.Component {
}
getApplicationLogin() {
let loginParams;
if (this.state.type === "cas") {
loginParams = Util.getCasLoginParameters("admin", this.state.applicationName);
} else if (this.state.type === "device") {
loginParams = {userCode: this.state.userCode, type: this.state.type};
} else {
loginParams = Util.getOAuthGetParameters();
}
const loginParams = (this.state.type === "cas") ? Util.getCasLoginParameters("admin", this.state.applicationName) : Util.getOAuthGetParameters();
AuthBackend.getApplicationLogin(loginParams)
.then((res) => {
if (res.status === "ok") {
const application = res.data;
this.onUpdateApplication(application);
} else {
if (this.state.type === "device") {
this.setState({
userCodeStatus: "expired",
});
}
this.onUpdateApplication(null);
this.setState({
msg: res.msg,
@ -280,16 +262,6 @@ class LoginPage extends React.Component {
onUpdateApplication(application) {
this.props.onUpdateApplication(application);
if (application === null) {
return;
}
for (const idx in application.providers) {
const provider = application.providers[idx];
if (provider.provider?.category === "Face ID") {
this.setState({haveFaceIdProvider: true});
break;
}
}
}
parseOffset(offset) {
@ -313,9 +285,6 @@ class LoginPage extends React.Component {
const oAuthParams = Util.getOAuthGetParameters();
values["type"] = oAuthParams?.responseType ?? this.state.type;
if (this.state.userCode) {
values["userCode"] = this.state.userCode;
}
if (oAuthParams?.samlRequest) {
values["samlRequest"] = oAuthParams.samlRequest;
@ -386,7 +355,6 @@ class LoginPage extends React.Component {
}
onFinish(values) {
this.setState({loginLoading: true});
if (this.state.loginMethod === "webAuthn") {
let username = this.state.username;
if (username === null || username === "") {
@ -411,9 +379,6 @@ class LoginPage extends React.Component {
}).then(res => res.json())
.then((res) => {
if (res.status === "error") {
this.setState({
loginLoading: false,
});
Setting.showMessage("error", res.msg);
return;
}
@ -450,7 +415,6 @@ class LoginPage extends React.Component {
login(values) {
// here we are supposed to determine whether Casdoor is working as an OAuth server or CAS server
values["language"] = this.state.userLang ?? "";
if (this.state.type === "cas") {
// CAS
const casParams = Util.getCasParameters();
@ -478,8 +442,6 @@ class LoginPage extends React.Component {
} else {
Setting.showMessage("error", `${i18next.t("application:Failed to sign in")}: ${res.msg}`);
}
}).finally(() => {
this.setState({loginLoading: false});
});
} else {
// OAuth
@ -499,11 +461,6 @@ class LoginPage extends React.Component {
this.props.onLoginSuccess();
} else if (responseType === "code") {
this.postCodeLoginAction(res);
} else if (responseType === "device") {
Setting.showMessage("success", "Successful login");
this.setState({
userCodeStatus: "success",
});
} else if (responseType === "token" || responseType === "id_token") {
if (res.data2) {
sessionStorage.setItem("signinUrl", window.location.pathname + window.location.search);
@ -540,8 +497,6 @@ class LoginPage extends React.Component {
} else {
Setting.showMessage("error", `${i18next.t("application:Failed to sign in")}: ${res.msg}`);
}
}).finally(() => {
this.setState({loginLoading: false});
});
}
}
@ -611,7 +566,7 @@ class LoginPage extends React.Component {
return (
<div key={resultItemKey} className="login-languages">
<div dangerouslySetInnerHTML={{__html: ("<style>" + signinItem.customCss?.replaceAll("<style>", "").replaceAll("</style>", "") + "</style>")}} />
<LanguageSelect languages={application.organizationObj.languages} onClick={key => {this.setState({userLang: key});}} />
<LanguageSelect languages={application.organizationObj.languages} />
</div>
);
} else if (signinItem.name === "Signin methods") {
@ -623,9 +578,6 @@ class LoginPage extends React.Component {
)
;
} else if (signinItem.name === "Username") {
if (this.state.loginMethod === "webAuthn") {
return null;
}
return (
<div key={resultItemKey}>
<div dangerouslySetInnerHTML={{__html: ("<style>" + signinItem.customCss?.replaceAll("<style>", "").replaceAll("</style>", "") + "</style>")}} />
@ -732,7 +684,6 @@ class LoginPage extends React.Component {
<Form.Item key={resultItemKey} className="login-button-box">
<div dangerouslySetInnerHTML={{__html: ("<style>" + signinItem.customCss?.replaceAll("<style>", "").replaceAll("</style>", "") + "</style>")}} />
<Button
loading={this.state.loginLoading}
type="primary"
htmlType="submit"
className="login-button"
@ -745,25 +696,19 @@ class LoginPage extends React.Component {
</Button>
{
this.state.loginMethod === "faceId" ?
this.state.haveFaceIdProvider ? <Suspense fallback={null}><FaceRecognitionCommonModal visible={this.state.openFaceRecognitionModal} onOk={(FaceIdImage) => {
const values = this.state.values;
values["FaceIdImage"] = FaceIdImage;
this.login(values);
this.setState({openFaceRecognitionModal: false});
}} onCancel={() => this.setState({openFaceRecognitionModal: false, loginLoading: false})} /></Suspense> :
<Suspense fallback={null}>
<FaceRecognitionModal
visible={this.state.openFaceRecognitionModal}
onOk={(faceId) => {
const values = this.state.values;
values["faceId"] = faceId;
<Suspense fallback={null}>
<FaceRecognitionModal
visible={this.state.openFaceRecognitionModal}
onOk={(faceId) => {
const values = this.state.values;
values["faceId"] = faceId;
this.login(values);
this.setState({openFaceRecognitionModal: false});
}}
onCancel={() => this.setState({openFaceRecognitionModal: false, loginLoading: false})}
/>
</Suspense>
this.login(values);
this.setState({openFaceRecognitionModal: false});
}}
onCancel={() => this.setState({openFaceRecognitionModal: false})}
/>
</Suspense>
:
<>
</>
@ -778,8 +723,6 @@ class LoginPage extends React.Component {
if (signinItem.rule === "None" || signinItem.rule === "") {
signinItem.rule = showForm ? "small" : "big";
}
const searchParams = new URLSearchParams(window.location.search);
const providerHint = searchParams.get("provider_hint");
return (
<div key={resultItemKey}>
@ -787,10 +730,6 @@ class LoginPage extends React.Component {
<Form.Item>
{
application.providers.filter(providerItem => this.isProviderVisible(providerItem)).map((providerItem, id) => {
if (providerHint === providerItem.provider.name) {
goToLink(Provider.getAuthUrl(application, providerItem.provider, "signup"));
return;
}
return (
<span key={id} onClick={(e) => {
const agreementChecked = this.form.current.getFieldValue("agreement");
@ -851,16 +790,6 @@ class LoginPage extends React.Component {
);
}
if (this.state.userCode && this.state.userCodeStatus === "success") {
return (
<Result
status="success"
title={i18next.t("application:Logged in successfully")}
>
</Result>
);
}
const showForm = Setting.isPasswordEnabled(application) || Setting.isCodeSigninEnabled(application) || Setting.isWebAuthnEnabled(application) || Setting.isLdapEnabled(application) || Setting.isFaceIdEnabled(application);
if (showForm) {
let loginWidth = 320;
@ -876,6 +805,7 @@ class LoginPage extends React.Component {
<Form
name="normal_login"
initialValues={{
organization: application.organization,
application: application.name,
autoSignin: true,
@ -978,7 +908,7 @@ class LoginPage extends React.Component {
this.login(values);
this.setState({openCaptchaModal: false});
}}
onCancel={() => this.setState({openCaptchaModal: false, loginLoading: false})}
onCancel={() => this.setState({openCaptchaModal: false})}
isCurrentProvider={true}
/>;
}
@ -1021,10 +951,6 @@ class LoginPage extends React.Component {
return null;
}
if (this.state.userCode && this.state.userCodeStatus === "success") {
return null;
}
return (
<div>
<div style={{fontSize: 16, textAlign: "left"}}>
@ -1049,7 +975,7 @@ class LoginPage extends React.Component {
const oAuthParams = Util.getOAuthGetParameters();
this.populateOauthValues(values);
const application = this.getApplicationObj();
return fetch(`${Setting.ServerUrl}/api/webauthn/signin/begin?owner=${application.organization}`, {
return fetch(`${Setting.ServerUrl}/api/webauthn/signin/begin?owner=${application.organization}&name=${username}`, {
method: "GET",
credentials: "include",
})
@ -1059,7 +985,11 @@ class LoginPage extends React.Component {
Setting.showMessage("error", credentialRequestOptions.msg);
throw credentialRequestOptions.status.msg;
}
credentialRequestOptions.publicKey.challenge = UserWebauthnBackend.webAuthnBufferDecode(credentialRequestOptions.publicKey.challenge);
credentialRequestOptions.publicKey.allowCredentials.forEach(function(listItem) {
listItem.id = UserWebauthnBackend.webAuthnBufferDecode(listItem.id);
});
return navigator.credentials.get({
publicKey: credentialRequestOptions.publicKey,
@ -1109,12 +1039,6 @@ class LoginPage extends React.Component {
.catch(error => {
Setting.showMessage("error", `${i18next.t("general:Failed to connect to server")}${error}`);
});
}).catch(error => {
Setting.showMessage("error", `${error}`);
}).finally(() => {
this.setState({
loginLoading: false,
});
});
}
@ -1307,15 +1231,6 @@ class LoginPage extends React.Component {
}
render() {
if (this.state.userCodeStatus === "expired") {
return <Result
style={{width: "100%"}}
status="error"
title={`Code ${i18next.t("subscription:Expired")}`}
>
</Result>;
}
const application = this.getApplicationObj();
if (application === undefined) {
return null;

View File

@ -194,10 +194,8 @@ class PromptPage extends React.Component {
const redirectUri = params.get("redirectUri");
const code = params.get("code");
const state = params.get("state");
const oauth = params.get("oauth");
if (redirectUri === null || code === null || state === null) {
const signInUrl = sessionStorage.getItem("signinUrl");
return oauth === "true" ? signInUrl : "";
return "";
}
return `${redirectUri}?code=${code}&state=${state}`;
}

View File

@ -387,8 +387,7 @@ export function getAuthUrl(application, provider, method, code) {
}
let endpoint = authInfo[provider.type].endpoint;
const redirectOrigin = application.forcedRedirectOrigin ? application.forcedRedirectOrigin : window.location.origin;
let redirectUri = `${redirectOrigin}/callback`;
let redirectUri = `${window.location.origin}/callback`;
let scope = authInfo[provider.type].scope;
const isShortState = (provider.type === "WeChat" && navigator.userAgent.includes("MicroMessenger")) || (provider.type === "Twitter");
const state = Util.getStateFromQueryParams(application.name, provider.name, method, isShortState);
@ -399,13 +398,9 @@ export function getAuthUrl(application, provider, method, code) {
endpoint = endpoint.replace("common", provider.domain);
}
} else if (provider.type === "Apple") {
redirectUri = `${redirectOrigin}/api/callback`;
redirectUri = `${window.location.origin}/api/callback`;
} else if (provider.type === "Google" && provider.disableSsl) {
scope += "+https://www.googleapis.com/auth/user.phonenumbers.read";
} else if (provider.type === "Nextcloud") {
if (provider.domain) {
endpoint = `${provider.domain}/apps/oauth2/authorize`;
}
}
if (provider.type === "Google" || provider.type === "GitHub" || provider.type === "Facebook"
@ -425,13 +420,13 @@ export function getAuthUrl(application, provider, method, code) {
} else if (provider.type === "AzureADB2C") {
return `https://${provider.domain}.b2clogin.com/${provider.domain}.onmicrosoft.com/${provider.appId}/oauth2/v2.0/authorize?client_id=${provider.clientId}&nonce=defaultNonce&redirect_uri=${encodeURIComponent(redirectUri)}&scope=${scope}&response_type=code&state=${state}&prompt=login`;
} else if (provider.type === "DingTalk") {
return `${endpoint}?client_id=${provider.clientId}&redirect_uri=${redirectUri}&scope=${scope}&response_type=code&prompt=login%20consent&state=${state}`;
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`;
} else {
if (provider.clientId2 && provider?.disableSsl && provider?.signName === "media") {
return `${redirectOrigin}/callback?state=${state}&code=${"wechat_oa:" + code}`;
return `${window.location.origin}/callback?state=${state}&code=${"wechat_oa:" + code}`;
}
return `${endpoint}?appid=${provider.clientId}&redirect_uri=${redirectUri}&scope=${scope}&response_type=code&state=${state}#wechat_redirect`;
}
@ -474,7 +469,7 @@ export function getAuthUrl(application, provider, method, code) {
} else if (provider.type === "Apple") {
return `${endpoint}?client_id=${provider.clientId}&redirect_uri=${redirectUri}&state=${state}&response_type=code%20id_token&scope=${scope}&response_mode=form_post`;
} else if (provider.type === "Steam") {
return `${endpoint}?openid.claimed_id=http://specs.openid.net/auth/2.0/identifier_select&openid.identity=http://specs.openid.net/auth/2.0/identifier_select&openid.mode=checkid_setup&openid.ns=http://specs.openid.net/auth/2.0&openid.realm=${redirectOrigin}&openid.return_to=${redirectUri}?state=${state}`;
return `${endpoint}?openid.claimed_id=http://specs.openid.net/auth/2.0/identifier_select&openid.identity=http://specs.openid.net/auth/2.0/identifier_select&openid.mode=checkid_setup&openid.ns=http://specs.openid.net/auth/2.0&openid.realm=${window.location.origin}&openid.return_to=${redirectUri}?state=${state}`;
} else if (provider.type === "Okta") {
return `${provider.domain}/v1/authorize?client_id=${provider.clientId}&redirect_uri=${redirectUri}&state=${state}&response_type=code&scope=${scope}`;
} else if (provider.type === "Douyin" || provider.type === "TikTok") {

View File

@ -195,9 +195,8 @@ class SignupPage extends React.Component {
if (authConfig.appName === application.name) {
return "/result";
} else {
const oAuthParams = Util.getOAuthGetParameters();
if (Setting.hasPromptPage(application)) {
return `/prompt/${application.name}?oauth=${oAuthParams !== null}`;
return `/prompt/${application.name}`;
} else {
return `/result/${application.name}`;
}

View File

@ -35,8 +35,8 @@ const GridCards = (props) => {
{items.map(item => <SingleCard key={item.link} logo={item.logo} link={item.link} title={item.name} desc={item.description} isSingle={items.length === 1} />)}
</Card>
) : (
<div style={{width: "100%", padding: "0 100px"}}>
<Row style={{justifyContent: "center"}}>
<div style={{margin: "0 15px"}}>
<Row>
{items.map(item => <SingleCard logo={item.logo} link={item.link} title={item.name} desc={item.description} time={item.createdTime} isSingle={items.length === 1} key={item.name} />)}
</Row>
</div>

View File

@ -2,7 +2,7 @@ import i18next from "i18next";
import {Tree} from "antd";
import React from "react";
export const NavItemTree = ({disabled, checkedKeys, defaultExpandedKeys, onCheck}) => {
export const NavItemTree = ({disable, checkedKeys, defaultExpandedKeys, onCheck}) => {
const NavItemNodes = [
{
title: i18next.t("organization:All"),
@ -86,7 +86,7 @@ export const NavItemTree = ({disabled, checkedKeys, defaultExpandedKeys, onCheck
return (
<Tree
disabled={disabled}
disabled={disable}
checkable
checkedKeys={checkedKeys}
defaultExpandedKeys={defaultExpandedKeys}

View File

@ -51,8 +51,6 @@ function testEmailProvider(provider, email = "") {
receivers: email === "" ? ["TestSmtpServer"] : [email],
provider: provider.name,
providerObject: provider,
owner: provider.owner,
name: provider.name,
};
return fetch(`${Setting.ServerUrl}/api/send-email`, {

View File

@ -16,7 +16,7 @@ import * as Setting from "../Setting";
import i18next from "i18next";
export function sendTestNotification(provider) {
testNotificationProvider(provider)
testNotificationProvider(provider.content, provider.name)
.then((res) => {
if (res.status === "ok") {
Setting.showMessage("success", i18next.t("general:Successfully sent"));
@ -29,14 +29,12 @@ export function sendTestNotification(provider) {
});
}
function testNotificationProvider(provider) {
function testNotificationProvider(content, name) {
const notificationForm = {
content: provider.content,
owner: provider.owner,
name: provider.name,
content: content,
};
return fetch(`${Setting.ServerUrl}/api/send-notification?provider=${provider.name}`, {
return fetch(`${Setting.ServerUrl}/api/send-notification?provider=${name}`, {
method: "POST",
credentials: "include",
body: JSON.stringify(notificationForm),

View File

@ -33,8 +33,6 @@ function testSmsProvider(provider, phone = "") {
const SmsForm = {
content: "123456",
receivers: [phone],
owner: provider.owner,
name: provider.name,
};
return fetch(`${Setting.ServerUrl}/api/send-sms?provider=` + provider.name, {

View File

@ -1,29 +0,0 @@
import i18next from "i18next";
import {Tree} from "antd";
import React from "react";
export const WidgetItemTree = ({disabled, checkedKeys, defaultExpandedKeys, onCheck}) => {
const WidgetItemNodes = [
{
title: i18next.t("organization:All"),
key: "all",
children: [
{title: i18next.t("general:Tour"), key: "tour"},
{title: i18next.t("general:AI Assistant"), key: "ai-assistant"},
{title: i18next.t("user:Language"), key: "language"},
{title: i18next.t("theme:Theme"), key: "theme"},
],
},
];
return (
<Tree
disabled={disabled}
checkable
checkedKeys={checkedKeys}
defaultExpandedKeys={defaultExpandedKeys}
onCheck={onCheck}
treeData={WidgetItemNodes}
/>
);
};

View File

@ -1,177 +0,0 @@
// Copyright 2025 The Casdoor Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import {Button, Modal, Progress, message} from "antd";
import React, {useState} from "react";
import i18next from "i18next";
const FaceRecognitionCommonModal = (props) => {
const {visible, onOk, onCancel} = props;
const videoRef = React.useRef();
const canvasRef = React.useRef();
const [percent, setPercent] = useState(0);
const mediaStreamRef = React.useRef(null);
const [isCameraCaptured, setIsCameraCaptured] = useState(false);
const [capturedImageArray, setCapturedImageArray] = useState([]);
React.useEffect(() => {
if (isCameraCaptured) {
let count = 0;
let count2 = 0;
const interval = setInterval(() => {
count++;
if (videoRef.current) {
videoRef.current.srcObject = mediaStreamRef.current;
videoRef.current.play();
const interval2 = setInterval(() => {
if (!visible) {
clearInterval(interval);
setPercent(0);
}
count2++;
if (count2 >= 8) {
clearInterval(interval2);
setPercent(0);
onOk(capturedImageArray);
} else if (count2 > 3) {
setPercent((count2 - 4) * 20);
const canvas = document.createElement("canvas");
canvas.width = videoRef.current.videoWidth;
canvas.height = videoRef.current.videoHeight;
const context = canvas.getContext("2d");
context.drawImage(videoRef.current, 0, 0, canvas.width, canvas.height);
const b64 = canvas.toDataURL("image/png");
capturedImageArray.push(b64);
setCapturedImageArray(capturedImageArray);
}
}, 1000);
clearInterval(interval);
}
if (count >= 30) {
clearInterval(interval);
}
}, 100);
} else {
mediaStreamRef.current?.getTracks().forEach(track => track.stop());
if (videoRef.current) {
videoRef.current.srcObject = null;
}
}
}, [isCameraCaptured]);
React.useEffect(() => {
if (visible) {
navigator.mediaDevices
.getUserMedia({video: {facingMode: "user"}})
.then((stream) => {
mediaStreamRef.current = stream;
setIsCameraCaptured(true);
}).catch((error) => {
handleCameraError(error);
});
} else {
setIsCameraCaptured(false);
setCapturedImageArray([]);
}
}, [visible]);
const handleCameraError = (error) => {
if (error instanceof DOMException) {
if (error.name === "NotFoundError" || error.name === "DevicesNotFoundError") {
message.error(i18next.t("login:Please ensure that you have a camera device for facial recognition"));
} else if (error.name === "NotAllowedError" || error.name === "PermissionDeniedError") {
message.error(i18next.t("login:Please provide permission to access the camera"));
} else if (error.name === "NotReadableError" || error.name === "TrackStartError") {
message.error(i18next.t("login:The camera is currently in use by another webpage"));
} else if (error.name === "TypeError") {
message.error(i18next.t("login:Please load the webpage using HTTPS, otherwise the camera cannot be accessed"));
} else {
message.error(error.message);
}
}
};
return <div>
<Modal
closable={false}
maskClosable={false}
title={i18next.t("login:Face Recognition")}
width={350}
footer={[
<Button key="ok" type={"primary"} disabled={capturedImageArray.length === 0} onClick={() => {
onOk(capturedImageArray);
}}>
Ok
</Button>,
<Button key="back" onClick={onCancel}>
Cancel
</Button>,
]}
destroyOnClose={true}
open={visible}>
<Progress percent={percent} />
<div style={{
marginTop: "20px",
marginBottom: "50px",
justifyContent: "center",
alignContent: "center",
position: "relative",
flexDirection: "column",
}}>
{
<div style={{display: "flex", justifyContent: "center", alignContent: "center"}}>
<video
ref={videoRef}
style={{
borderRadius: "50%",
height: "220px",
verticalAlign: "middle",
width: "220px",
objectFit: "cover",
}}
></video>
<div style={{
position: "absolute",
width: "240px",
height: "240px",
top: "50%",
left: "50%",
transform: "translate(-50%, -50%)",
}}>
<svg width="240" height="240" fill="none">
<circle
strokeDasharray="700"
strokeDashoffset={700 - 6.9115 * percent}
strokeWidth="4"
cx="120"
cy="120"
r="110"
stroke="#5734d3"
transform="rotate(-90, 120, 120)"
strokeLinecap="round"
style={{transition: "all .2s linear"}}
></circle>
</svg>
</div>
<canvas ref={canvasRef} style={{position: "absolute"}} />
</div>
}
</div>
</Modal>
</div>;
};
export default FaceRecognitionCommonModal;

View File

@ -14,13 +14,11 @@
import * as faceapi from "face-api.js";
import React, {useState} from "react";
import {Button, Modal, Progress, Space, Spin, message} from "antd";
import {Button, Modal, Progress, Spin, message} from "antd";
import i18next from "i18next";
import Dragger from "antd/es/upload/Dragger";
import * as Setting from "../../Setting";
const FaceRecognitionModal = (props) => {
const {visible, onOk, onCancel, withImage} = props;
const {visible, onOk, onCancel} = props;
const [modelsLoaded, setModelsLoaded] = React.useState(false);
const [isCameraCaptured, setIsCameraCaptured] = useState(false);
@ -30,14 +28,12 @@ const FaceRecognitionModal = (props) => {
const mediaStreamRef = React.useRef(null);
const [percent, setPercent] = useState(0);
const [files, setFiles] = useState([]);
const [currentFaceId, setCurrentFaceId] = React.useState();
const [currentFaceIndex, setCurrentFaceIndex] = React.useState();
React.useEffect(() => {
const loadModels = async() => {
// const MODEL_URL = process.env.PUBLIC_URL + "/models";
// const MODEL_URL = "https://justadudewhohacks.github.io/face-api.js/models";
const MODEL_URL = `${Setting.StaticBaseUrl}/casdoor/models`;
// const MODEL_URL = "https://cdn.casbin.org/site/casdoor/models";
const MODEL_URL = "https://cdn.casdoor.com/casdoor/models";
Promise.all([
faceapi.nets.tinyFaceDetector.loadFromUri(MODEL_URL),
@ -54,9 +50,6 @@ const FaceRecognitionModal = (props) => {
}, []);
React.useEffect(() => {
if (withImage) {
return;
}
if (visible) {
setPercent(0);
if (modelsLoaded) {
@ -82,9 +75,6 @@ const FaceRecognitionModal = (props) => {
}, [visible, modelsLoaded]);
React.useEffect(() => {
if (withImage) {
return;
}
if (isCameraCaptured) {
let count = 0;
const interval = setInterval(() => {
@ -108,9 +98,6 @@ const FaceRecognitionModal = (props) => {
}, [isCameraCaptured]);
const handleStreamVideo = () => {
if (withImage) {
return;
}
let count = 0;
let goodCount = 0;
if (!detection.current) {
@ -161,163 +148,73 @@ const FaceRecognitionModal = (props) => {
}
};
const getBase64 = (file) => {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => resolve(reader.result);
reader.onerror = (error) => reject(error);
});
};
if (!withImage) {
return (
<div>
<Modal
closable={false}
maskClosable={false}
destroyOnClose={true}
open={visible && isCameraCaptured}
title={i18next.t("login:Face Recognition")}
width={350}
footer={[
<Button key="back" onClick={onCancel}>
Cancel
</Button>,
]}
>
<Progress percent={percent} />
<div style={{
marginTop: "20px",
marginBottom: "50px",
justifyContent: "center",
alignContent: "center",
position: "relative",
flexDirection: "column",
}}>
{
modelsLoaded ?
<div style={{display: "flex", justifyContent: "center", alignContent: "center"}}>
<video
ref={videoRef}
onPlay={handleStreamVideo}
style={{
borderRadius: "50%",
height: "220px",
verticalAlign: "middle",
width: "220px",
objectFit: "cover",
}}
></video>
<div style={{
position: "absolute",
width: "240px",
height: "240px",
top: "50%",
left: "50%",
transform: "translate(-50%, -50%)",
}}>
<svg width="240" height="240" fill="none">
<circle
strokeDasharray="700"
strokeDashoffset={700 - 6.9115 * percent}
strokeWidth="4"
cx="120"
cy="120"
r="110"
stroke="#5734d3"
transform="rotate(-90, 120, 120)"
strokeLinecap="round"
style={{transition: "all .2s linear"}}
></circle>
</svg>
</div>
<canvas ref={canvasRef} style={{position: "absolute"}} />
</div>
:
<div>
<Spin tip={i18next.t("login:Loading")} size="large"
style={{display: "flex", justifyContent: "center", alignContent: "center"}}>
<div className="content" />
</Spin>
</div>
}
</div>
</Modal>
</div>
);
} else {
return <div>
<Modal closable={false}
return (
<div>
<Modal
closable={false}
maskClosable={false}
destroyOnClose={true}
open={visible}
open={visible && isCameraCaptured}
title={i18next.t("login:Face Recognition")}
width={350}
footer={[
<Button key="ok" type={"primary"} disabled={!currentFaceId || currentFaceId?.length === 0} onClick={() => {
onOk(Array.from(currentFaceId.descriptor));
}}>
Ok
</Button>,
<Button key="back" onClick={onCancel}>
Cancel
Cancel
</Button>,
]}>
<Space direction={"vertical"} style={{width: "100%"}}>
<Dragger
multiple={true}
defaultFileList={files}
style={{width: "100%"}}
beforeUpload={(file) => {
getBase64(file).then(res => {
file.base64 = res;
files.push(file);
});
setCurrentFaceId([]);
return false;
}}
onRemove={(file) => {
const index = files.indexOf(file);
const newFileList = files.slice();
newFileList.splice(index, 1);
setFiles(newFileList);
setCurrentFaceId([]);
}}
>
<p>{i18next.t("general:Click to Upload")}</p>
</Dragger >
]}
>
<Progress percent={percent} />
<div style={{marginTop: "20px", marginBottom: "50px", justifyContent: "center", alignContent: "center", position: "relative", flexDirection: "column"}}>
{
modelsLoaded ? <Button style={{width: "100%"}} onClick={async() => {
let maxScore = 0;
for (const file of files) {
const fileIndex = files.indexOf(file);
const img = new Image();
img.src = file.base64;
const faceIds = await faceapi.detectAllFaces(img, new faceapi.TinyFaceDetectorOptions()).withFaceLandmarks().withFaceDescriptors();
if (faceIds[0]?.detection.score > 0.9 && faceIds[0]?.detection.score > maxScore) {
maxScore = faceIds[0]?.detection.score;
setCurrentFaceId(faceIds[0]);
setCurrentFaceIndex(fileIndex);
}
}
if (maxScore < 0.9) {
message.error(i18next.t("login:Face recognition failed"));
}
}}> {i18next.t("application:Generate Face ID")}</Button> : null
modelsLoaded ?
<div style={{display: "flex", justifyContent: "center", alignContent: "center"}}>
<video
ref={videoRef}
onPlay={handleStreamVideo}
style={{
borderRadius: "50%",
height: "220px",
verticalAlign: "middle",
width: "220px",
objectFit: "cover",
}}
></video>
<div style={{
position: "absolute",
width: "240px",
height: "240px",
top: "50%",
left: "50%",
transform: "translate(-50%, -50%)",
}}>
<svg width="240" height="240" fill="none">
<circle
strokeDasharray="700"
strokeDashoffset={700 - 6.9115 * percent}
strokeWidth="4"
cx="120"
cy="120"
r="110"
stroke="#5734d3"
transform="rotate(-90, 120, 120)"
strokeLinecap="round"
style={{transition: "all .2s linear"}}
></circle>
</svg>
</div>
<canvas ref={canvasRef} style={{position: "absolute"}} />
</div>
:
<div>
<Spin tip={i18next.t("login:Loading")} size="large" style={{display: "flex", justifyContent: "center", alignContent: "center"}}>
<div className="content" />
</Spin>
</div>
}
</Space>
{
currentFaceId && currentFaceId.length !== 0 ? (
<React.Fragment>
<div>{i18next.t("application:Select")}:{files[currentFaceIndex]?.name}</div>
<div><img src={files[currentFaceIndex]?.base64} alt="selected" style={{width: "100%"}} /></div>
</React.Fragment>
) : null
}
</div>
</Modal>
</div>;
}
</div>
);
};
export default FaceRecognitionModal;

View File

@ -124,7 +124,7 @@ export const PasswordModal = (props) => {
width={600}
>
<Col style={{margin: "0px auto 40px auto", width: 1000, height: 300}}>
{(hasOldPassword && !Setting.isLocalAdminUser(account)) ? (
{(hasOldPassword && !Setting.isAdminUser(account)) ? (
<Row style={{width: "100%", marginBottom: "20px"}}>
<Input.Password addonBefore={i18next.t("user:Old Password")} placeholder={i18next.t("user:input password")} onChange={(e) => setOldPassword(e.target.value)} />
</Row>

View File

@ -30,7 +30,6 @@ class LanguageSelect extends React.Component {
this.state = {
classes: props,
languages: props.languages ?? Setting.Countries.map(item => item.key),
onClick: props.onClick,
};
Setting.Countries.forEach((country) => {
@ -51,9 +50,6 @@ class LanguageSelect extends React.Component {
render() {
const languageItems = this.getOrganizationLanguages(this.state.languages);
const onClick = (e) => {
if (typeof this.state.onClick === "function") {
this.state.onClick(e.key);
}
Setting.setLanguage(e.key);
};

View File

@ -17,15 +17,11 @@
"Use same DB - Tooltip": "Use same DB - Tooltip"
},
"application": {
"Add Face ID": "Add Face ID",
"Add Face ID with Image": "Add Face ID with Image",
"Always": "Always",
"Auto signin": "Auto signin",
"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": "URL of the background image used in the login page",
"Background URL Mobile": "Background URL Mobile",
"Background URL Mobile - Tooltip": "Background URL Mobile - Tooltip",
"Big icon": "Big icon",
"Binding providers": "Binding providers",
"CSS style": "CSS style",
@ -65,10 +61,8 @@
"Footer HTML": "Footer HTML",
"Footer HTML - Edit": "Footer HTML - Edit",
"Footer HTML - Tooltip": "Custom the footer of your application",
"Forced redirect origin": "Forced redirect origin",
"Form position": "Form position",
"Form position - Tooltip": "Location of the signup, signin and forget password forms",
"Generate Face ID": "Generate Face ID",
"Grant types": "Grant types",
"Grant types - Tooltip": "Select which grant types are allowed in the OAuth protocol",
"Header HTML": "Header HTML",
@ -169,7 +163,6 @@
},
"currency": {
"AUD": "AUD",
"BRL": "BRL",
"CAD": "CAD",
"CHF": "CHF",
"CNY": "CNY",
@ -196,7 +189,6 @@
"Verify": "Verify"
},
"general": {
"AI Assistant": "AI Assistant",
"API key": "API key",
"API key - Tooltip": "API key - Tooltip",
"Access key": "Access key",
@ -209,6 +201,7 @@
"Adapter - Tooltip": "Table name of the policy store",
"Adapters": "Adapters",
"Add": "Add",
"Add Face Id": "Add Face Id",
"Add custom item": "Add custom item",
"Admin": "Admin",
"Affiliation URL": "Affiliation URL",
@ -238,7 +231,6 @@
"Created time": "Created time",
"Custom": "Custom",
"Dashboard": "Dashboard",
"Data": "Data",
"Default": "Default",
"Default application": "Default application",
"Default application - Tooltip": "Default application for users registered directly from the organization page",
@ -249,7 +241,6 @@
"Delete": "Delete",
"Description": "Description",
"Description - Tooltip": "Detailed description information for reference, Casdoor itself will not use it",
"Detail": "详情",
"Disable": "Disable",
"Display name": "Display name",
"Display name - Tooltip": "A user-friendly, easily readable name displayed publicly in the UI",
@ -267,6 +258,7 @@
"Enabled": "Enabled",
"Enabled successfully": "Enabled successfully",
"Enforcers": "Enforcers",
"FaceIdData": "FaceIdData",
"Failed to add": "Failed to add",
"Failed to connect to server": "Failed to connect to server",
"Failed to delete": "Failed to delete",
@ -279,7 +271,6 @@
"Favicon": "Favicon",
"Favicon - Tooltip": "Favicon icon URL used in all Casdoor pages of the organization",
"First name": "First name",
"Forced redirect origin - Tooltip": "Forced redirect origin - Tooltip",
"Forget URL": "Forget URL",
"Forget URL - Tooltip": "Custom URL for the \"Forget password\" page. If not set, the default Casdoor \"Forget password\" page will be used. When set, the \"Forget password\" link on the login page will redirect to this URL",
"Found some texts still not translated? Please help us translate at": "Found some texts still not translated? Please help us translate at",
@ -353,7 +344,6 @@
"Phone - Tooltip": "Phone number",
"Phone only": "Phone only",
"Phone or Email": "Phone or Email",
"Plain": "Plain",
"Plan": "Plan",
"Plan - Tooltip": "Plan - Tooltip",
"Plans": "Plans",
@ -372,7 +362,6 @@
"QR code is too large": "QR code is too large",
"Real name": "Real name",
"Records": "Records",
"Request": "Request",
"Request URI": "Request URI",
"Resources": "Resources",
"Role": "Role",
@ -423,7 +412,6 @@
"This is a read-only demo site!": "This is a read-only demo site!",
"Timestamp": "Timestamp",
"Tokens": "Tokens",
"Tour": "Tour",
"Transactions": "Transactions",
"Type": "Type",
"Type - Tooltip": "Type - Tooltip",
@ -454,8 +442,7 @@
"Parent group - Tooltip": "Parent group - Tooltip",
"Physical": "Physical",
"Show all": "Show all",
"Virtual": "Virtual",
"You need to delete all subgroups first. You can view the subgroups in the left group tree of the [Organizations] -\u003e [Groups] page": "You need to delete all subgroups first. You can view the subgroups in the left group tree of the [Organizations] -\u003e [Groups] page"
"Virtual": "Virtual"
},
"home": {
"New users past 30 days": "New users past 30 days",
@ -474,16 +461,13 @@
"Quota": "Quota",
"Quota - Tooltip": "Quota - Tooltip",
"Used count": "Used count",
"Used count - Tooltip": "Used count - Tooltip",
"You need to first specify a default application for organization: ": "You need to first specify a default application for organization: "
"Used count - Tooltip": "Used count - Tooltip"
},
"ldap": {
"Admin": "Admin",
"Admin - Tooltip": "CN or ID of the LDAP server administrator",
"Admin Password": "Admin Password",
"Admin Password - Tooltip": "LDAP server administrator password",
"Allow self-signed certificate": "Allow self-signed certificate",
"Allow self-signed certificate - Tooltip": "Allow self-signed certificate - Tooltip",
"Auto Sync": "Auto Sync",
"Auto Sync - Tooltip": "Auto-sync configuration, disabled at 0",
"Base DN": "Base DN",
@ -602,6 +586,11 @@
"Your phone is": "Your phone is",
"preferred": "preferred"
},
"mfaAccount": {
"Account Name": "Account Name",
"Issuer": "Issuer",
"Secret Key": "Secret Key"
},
"model": {
"Advanced Editor": "Advanced Editor",
"Basic Editor": "Basic Editor",
@ -621,8 +610,6 @@
"Is profile public": "Is profile public",
"Is profile public - Tooltip": "After being closed, only global administrators or users in the same organization can access the user's profile page",
"Modify rule": "Modify rule",
"Navbar items": "Navbar items",
"Navbar items - Tooltip": "Navbar items - Tooltip",
"New Organization": "New Organization",
"Optional": "Optional",
"Password expire days": "Password expire days",
@ -635,14 +622,10 @@
"Tags - Tooltip": "Collection of tags available for users to choose from",
"Use Email as username": "Use Email as username",
"Use Email as username - Tooltip": "Use Email as username if the username field is not visible at signup",
"User types": "User types",
"User types - Tooltip": "User types - Tooltip",
"View rule": "View rule",
"Visible": "Visible",
"Website URL": "Website URL",
"Website URL - Tooltip": "The homepage URL of the organization. This field is not used in Casdoor",
"Widget items": "Widget items",
"Widget items - Tooltip": "Widget items - Tooltip"
"Website URL - Tooltip": "The homepage URL of the organization. This field is not used in Casdoor"
},
"payment": {
"Confirm your invoice information": "Confirm your invoice information",
@ -745,7 +728,6 @@
"paid-user do not have active subscription or pending subscription, please select a plan to buy": "paid-user do not have active subscription or pending subscription, please select a plan to buy"
},
"product": {
"AirWallex": "AirWallex",
"Alipay": "Alipay",
"Buy": "Buy",
"Buy Product": "Buy Product",
@ -775,6 +757,7 @@
"Sold": "Sold",
"Sold - Tooltip": "Quantity sold",
"Stripe": "Stripe",
"AirWallex": "AirWallex",
"Tag - Tooltip": "Tag of product",
"Test buy page..": "Test buy page..",
"There is no payment channel for this product.": "There is no payment channel for this product.",
@ -834,8 +817,6 @@
"Edit Provider": "Edit Provider",
"Email content": "Email content",
"Email content - Tooltip": "Content of the Email",
"Email regex": "Email regex",
"Email regex - Tooltip": "Email regex - Tooltip",
"Email title": "Email title",
"Email title - Tooltip": "Title of the email",
"Endpoint": "Endpoint",
@ -849,8 +830,6 @@
"From name - Tooltip": "Name of \"From\"",
"Get phone number": "Get phone number",
"Get phone number - Tooltip": "If sync phone number is enabled, you should enable google people api first and add scope https://www.googleapis.com/auth/user.phonenumbers.read",
"HTTP header": "HTTP header",
"HTTP header - Tooltip": "HTTP header - Tooltip",
"Host": "Host",
"Host - Tooltip": "Name of host",
"IdP": "IdP",
@ -865,8 +844,6 @@
"Key text - Tooltip": "Key text - Tooltip",
"Metadata": "Metadata",
"Metadata - Tooltip": "SAML metadata",
"Metadata url": "Metadata url",
"Metadata url - Tooltip": "Metadata url - Tooltip",
"Method - Tooltip": "Login method, QR code or silent login",
"New Provider": "New Provider",
"Normal": "Normal",
@ -1267,8 +1244,6 @@
"Edit Webhook": "Edit Webhook",
"Events": "Events",
"Events - Tooltip": "Events",
"Extended user fields": "Extended user fields",
"Extended user fields - Tooltip": "Extended user fields - Tooltip",
"Headers": "Headers",
"Headers - Tooltip": "HTTP headers (key-value pairs)",
"Is user extended": "Is user extended",

View File

@ -17,15 +17,11 @@
"Use same DB - Tooltip": "Použít stejnou DB jako Casdoor"
},
"application": {
"Add Face ID": "Add Face ID",
"Add Face ID with Image": "Add Face ID with Image",
"Always": "Vždy",
"Auto signin": "Automatické přihlášení",
"Auto signin - Tooltip": "Když existuje přihlášená relace v Casdoor, je automaticky použita pro přihlášení na straně aplikace",
"Background URL": "URL pozadí",
"Background URL - Tooltip": "URL obrázku pozadí použitého na přihlašovací stránce",
"Background URL Mobile": "Background URL Mobile",
"Background URL Mobile - Tooltip": "Background URL Mobile - Tooltip",
"Big icon": "Velká ikona",
"Binding providers": "Propojení poskytovatelé",
"CSS style": "CSS styl",
@ -65,10 +61,8 @@
"Footer HTML": "HTML patičky",
"Footer HTML - Edit": "Upravit HTML patičky",
"Footer HTML - Tooltip": "Přizpůsobit patičku vaší aplikace",
"Forced redirect origin": "Forced redirect origin",
"Form position": "Pozice formuláře",
"Form position - Tooltip": "Umístění formulářů pro registraci, přihlášení a zapomenuté heslo",
"Generate Face ID": "Generate Face ID",
"Grant types": "Typy grantů",
"Grant types - Tooltip": "Vyberte, které typy grantů jsou povoleny v OAuth protokolu",
"Header HTML": "HTML hlavičky",
@ -169,7 +163,6 @@
},
"currency": {
"AUD": "AUD",
"BRL": "BRL",
"CAD": "CAD",
"CHF": "CHF",
"CNY": "CNY",
@ -196,7 +189,6 @@
"Verify": "Ověřit"
},
"general": {
"AI Assistant": "AI Assistant",
"API key": "API klíč",
"API key - Tooltip": "API klíč - Tooltip",
"Access key": "Přístupový klíč",
@ -209,6 +201,7 @@
"Adapter - Tooltip": "Název tabulky úložiště politiky",
"Adapters": "Adaptéry",
"Add": "Přidat",
"Add Face Id": "Přidat Face Id",
"Add custom item": "Přidat vlastní položku",
"Admin": "Admin",
"Affiliation URL": "URL přidružení",
@ -238,7 +231,6 @@
"Created time": "Čas vytvoření",
"Custom": "Vlastní",
"Dashboard": "Dashboard",
"Data": "Data",
"Default": "Výchozí",
"Default application": "Výchozí aplikace",
"Default application - Tooltip": "Výchozí aplikace pro uživatele registrované přímo ze stránky organizace",
@ -249,7 +241,6 @@
"Delete": "Smazat",
"Description": "Popis",
"Description - Tooltip": "Podrobný popis pro referenci, Casdoor sám o sobě jej nepoužívá",
"Detail": "详情",
"Disable": "Zakázat",
"Display name": "Zobrazované jméno",
"Display name - Tooltip": "Uživatelsky přívětivé, snadno čitelné jméno zobrazené veřejně v UI",
@ -267,6 +258,7 @@
"Enabled": "Povoleno",
"Enabled successfully": "Úspěšně povoleno",
"Enforcers": "Enforcers",
"FaceIdData": "FaceIdData",
"Failed to add": "Nepodařilo se přidat",
"Failed to connect to server": "Nepodařilo se připojit k serveru",
"Failed to delete": "Nepodařilo se smazat",
@ -279,7 +271,6 @@
"Favicon": "Favicon",
"Favicon - Tooltip": "URL ikony favicon použité na všech stránkách Casdoor organizace",
"First name": "Křestní jméno",
"Forced redirect origin - Tooltip": "Forced redirect origin - Tooltip",
"Forget URL": "URL pro zapomenutí",
"Forget URL - Tooltip": "Vlastní URL pro stránku \"Zapomenuté heslo\". Pokud není nastaveno, bude použita výchozí stránka Casdoor \"Zapomenuté heslo\". Když je nastaveno, odkaz \"Zapomenuté heslo\" na přihlašovací stránce přesměruje na tuto URL",
"Found some texts still not translated? Please help us translate at": "Našli jste nějaké texty, které ještě nejsou přeloženy? Pomozte nám prosím přeložit na",
@ -353,7 +344,6 @@
"Phone - Tooltip": "Telefonní číslo",
"Phone only": "Pouze telefon",
"Phone or Email": "Telefon nebo Email",
"Plain": "Plain",
"Plan": "Plán",
"Plan - Tooltip": "Plán - Tooltip",
"Plans": "Plány",
@ -372,7 +362,6 @@
"QR code is too large": "QR code is too large",
"Real name": "Skutečné jméno",
"Records": "Záznamy",
"Request": "Request",
"Request URI": "Požadavek URI",
"Resources": "Zdroje",
"Role": "Role",
@ -423,7 +412,6 @@
"This is a read-only demo site!": "Toto je demo stránka pouze pro čtení!",
"Timestamp": "Časové razítko",
"Tokens": "Tokeny",
"Tour": "Tour",
"Transactions": "Transakce",
"Type": "Typ",
"Type - Tooltip": "Typ - Tooltip",
@ -454,8 +442,7 @@
"Parent group - Tooltip": "Nadřazená skupina - Tooltip",
"Physical": "Fyzická",
"Show all": "Zobrazit vše",
"Virtual": "Virtuální",
"You need to delete all subgroups first. You can view the subgroups in the left group tree of the [Organizations] -\u003e [Groups] page": "You need to delete all subgroups first. You can view the subgroups in the left group tree of the [Organizations] -\u003e [Groups] page"
"Virtual": "Virtuální"
},
"home": {
"New users past 30 days": "Noví uživatelé za posledních 30 dní",
@ -474,16 +461,13 @@
"Quota": "Kvóta",
"Quota - Tooltip": "Maximální počet uživatelů, kteří se mohou zaregistrovat pomocí tohoto pozvánkového kódu",
"Used count": "Počet použití",
"Used count - Tooltip": "Počet použití tohoto pozvánkového kódu",
"You need to first specify a default application for organization: ": "You need to first specify a default application for organization: "
"Used count - Tooltip": "Počet použití tohoto pozvánkového kódu"
},
"ldap": {
"Admin": "Admin",
"Admin - Tooltip": "CN nebo ID administrátora LDAP serveru",
"Admin Password": "Heslo administrátora",
"Admin Password - Tooltip": "Heslo administrátora LDAP serveru",
"Allow self-signed certificate": "Allow self-signed certificate",
"Allow self-signed certificate - Tooltip": "Allow self-signed certificate - Tooltip",
"Auto Sync": "Automatická synchronizace",
"Auto Sync - Tooltip": "Konfigurace automatické synchronizace, deaktivováno při 0",
"Base DN": "Základní DN",
@ -602,6 +586,11 @@
"Your phone is": "Váš telefon je",
"preferred": "preferované"
},
"mfaAccount": {
"Account Name": "Account Name",
"Issuer": "Issuer",
"Secret Key": "Secret Key"
},
"model": {
"Advanced Editor": "Pokročilý editor",
"Basic Editor": "Základní editor",
@ -621,8 +610,6 @@
"Is profile public": "Je profil veřejný",
"Is profile public - Tooltip": "Po uzavření mohou profilovou stránku uživatele přistupovat pouze globální administrátoři nebo uživatelé ve stejné organizaci",
"Modify rule": "Upravit pravidlo",
"Navbar items": "Navbar items",
"Navbar items - Tooltip": "Navbar items - Tooltip",
"New Organization": "Nová organizace",
"Optional": "Volitelný",
"Password expire days": "Password expire days",
@ -635,14 +622,10 @@
"Tags - Tooltip": "Kolekce štítků dostupných pro uživatele k výběru",
"Use Email as username": "Použít email jako uživatelské jméno",
"Use Email as username - Tooltip": "Použít email jako uživatelské jméno, pokud není při registraci viditelné pole uživatelského jména",
"User types": "User types",
"User types - Tooltip": "User types - Tooltip",
"View rule": "Zobrazit pravidlo",
"Visible": "Viditelné",
"Website URL": "URL webových stránek",
"Website URL - Tooltip": "Domovská URL organizace. Toto pole se v Casdoor nepoužívá",
"Widget items": "Widget items",
"Widget items - Tooltip": "Widget items - Tooltip"
"Website URL - Tooltip": "Domovská URL organizace. Toto pole se v Casdoor nepoužívá"
},
"payment": {
"Confirm your invoice information": "Potvrďte informace na faktuře",
@ -745,7 +728,6 @@
"paid-user do not have active subscription or pending subscription, please select a plan to buy": "placený uživatel nemá aktivní předplatné nebo čekající předplatné, prosím vyberte plán k nákupu"
},
"product": {
"AirWallex": "AirWallex",
"Alipay": "Alipay",
"Buy": "Koupit",
"Buy Product": "Koupit produkt",
@ -775,6 +757,7 @@
"Sold": "Prodáno",
"Sold - Tooltip": "Prodávané množství",
"Stripe": "Stripe",
"AirWallex": "AirWallex",
"Tag - Tooltip": "Štítek produktu",
"Test buy page..": "Testovací stránka nákupu..",
"There is no payment channel for this product.": "Pro tento produkt neexistuje žádný platební kanál.",
@ -834,8 +817,6 @@
"Edit Provider": "Upravit poskytovatele",
"Email content": "Obsah emailu",
"Email content - Tooltip": "Obsah emailu",
"Email regex": "Email regex",
"Email regex - Tooltip": "Email regex - Tooltip",
"Email title": "Název emailu",
"Email title - Tooltip": "Název emailu",
"Endpoint": "Koncový bod",
@ -849,8 +830,6 @@
"From name - Tooltip": "Jméno \"Z\"",
"Get phone number": "Získat telefonní číslo",
"Get phone number - Tooltip": "Pokud je povolena synchronizace telefonního čísla, měli byste nejprve povolit google people API a přidat rozsah https://www.googleapis.com/auth/user.phonenumbers.read",
"HTTP header": "HTTP header",
"HTTP header - Tooltip": "HTTP header - Tooltip",
"Host": "Hostitel",
"Host - Tooltip": "Název hostitele",
"IdP": "IdP",
@ -865,8 +844,6 @@
"Key text - Tooltip": "Text klíče",
"Metadata": "Metadata",
"Metadata - Tooltip": "SAML metadata",
"Metadata url": "Metadata url",
"Metadata url - Tooltip": "Metadata url - Tooltip",
"Method - Tooltip": "Metoda přihlášení, QR kód nebo tiché přihlášení",
"New Provider": "Nový poskytovatel",
"Normal": "Normální",
@ -1267,8 +1244,6 @@
"Edit Webhook": "Upravit Webhook",
"Events": "Události",
"Events - Tooltip": "Události",
"Extended user fields": "Extended user fields",
"Extended user fields - Tooltip": "Extended user fields - Tooltip",
"Headers": "Hlavičky",
"Headers - Tooltip": "HTTP hlavičky (klíč-hodnota)",
"Is user extended": "Jsou rozšířená data uživatele",

View File

@ -17,15 +17,11 @@
"Use same DB - Tooltip": "Use same DB - Tooltip"
},
"application": {
"Add Face ID": "Add Face ID",
"Add Face ID with Image": "Add Face ID with Image",
"Always": "Immer",
"Auto signin": "Automatische Anmeldung",
"Auto signin - Tooltip": "Wenn eine angemeldete Session in Casdoor vorhanden ist, wird diese automatisch für die Anmeldung auf Anwendungsebene verwendet",
"Background URL": "Background-URL",
"Background URL - Tooltip": "URL des Hintergrundbildes, das auf der Anmeldeseite angezeigt wird",
"Background URL Mobile": "Background URL Mobile",
"Background URL Mobile - Tooltip": "Background URL Mobile - Tooltip",
"Big icon": "Big icon",
"Binding providers": "Binding providers",
"CSS style": "CSS style",
@ -65,10 +61,8 @@
"Footer HTML": "Footer HTML",
"Footer HTML - Edit": "Footer HTML - Edit",
"Footer HTML - Tooltip": "Custom the footer of your application",
"Forced redirect origin": "Forced redirect origin",
"Form position": "Formposition",
"Form position - Tooltip": "Position der Anmelde-, Registrierungs- und Passwort-vergessen-Formulare",
"Generate Face ID": "Generate Face ID",
"Grant types": "Grant-Typen",
"Grant types - Tooltip": "Wählen Sie aus, welche Grant-Typen im OAuth-Protokoll zulässig sind",
"Header HTML": "Header HTML",
@ -169,7 +163,6 @@
},
"currency": {
"AUD": "AUD",
"BRL": "BRL",
"CAD": "CAD",
"CHF": "CHF",
"CNY": "CNY",
@ -196,7 +189,6 @@
"Verify": "überprüfen"
},
"general": {
"AI Assistant": "AI Assistant",
"API key": "API key",
"API key - Tooltip": "API key - Tooltip",
"Access key": "Access key",
@ -209,6 +201,7 @@
"Adapter - Tooltip": "Tabellenname des Policy Stores",
"Adapters": "Adapter",
"Add": "Hinzufügen",
"Add Face Id": "Add Face Id",
"Add custom item": "Add custom item",
"Admin": "Admin",
"Affiliation URL": "Zugehörigkeits-URL",
@ -238,7 +231,6 @@
"Created time": "Erstellte Zeit",
"Custom": "Custom",
"Dashboard": "Dashboard",
"Data": "Data",
"Default": "Default",
"Default application": "Standard Anwendung",
"Default application - Tooltip": "Standard-Anwendung für Benutzer, die direkt von der Organisationsseite registriert wurden",
@ -249,7 +241,6 @@
"Delete": "Löschen",
"Description": "Beschreibung",
"Description - Tooltip": "Detaillierte Beschreibungsinformationen zur Referenz, Casdoor selbst wird es nicht verwenden",
"Detail": "详情",
"Disable": "Disable",
"Display name": "Anzeigename",
"Display name - Tooltip": "Ein benutzerfreundlicher, leicht lesbarer Name, der öffentlich in der Benutzeroberfläche angezeigt wird",
@ -267,6 +258,7 @@
"Enabled": "Enabled",
"Enabled successfully": "Enabled successfully",
"Enforcers": "Enforcers",
"FaceIdData": "FaceIdData",
"Failed to add": "Fehler beim hinzufügen",
"Failed to connect to server": "Die Verbindung zum Server konnte nicht hergestellt werden",
"Failed to delete": "Konnte nicht gelöscht werden",
@ -279,7 +271,6 @@
"Favicon": "Favicon",
"Favicon - Tooltip": "Favicon-URL, die auf allen Casdoor-Seiten der Organisation verwendet wird",
"First name": "Vorname",
"Forced redirect origin - Tooltip": "Forced redirect origin - Tooltip",
"Forget URL": "Passwort vergessen URL",
"Forget URL - Tooltip": "Benutzerdefinierte URL für die \"Passwort vergessen\" Seite. Wenn nicht festgelegt, wird die standardmäßige Casdoor \"Passwort vergessen\" Seite verwendet. Wenn sie festgelegt ist, wird der \"Passwort vergessen\" Link auf der Login-Seite zu dieser URL umgeleitet",
"Found some texts still not translated? Please help us translate at": "Haben Sie noch Texte gefunden, die nicht übersetzt wurden? Bitte helfen Sie uns beim Übersetzen",
@ -353,7 +344,6 @@
"Phone - Tooltip": "Telefonnummer",
"Phone only": "Phone only",
"Phone or Email": "Phone or Email",
"Plain": "Plain",
"Plan": "Plan",
"Plan - Tooltip": "Plan - Tooltip",
"Plans": "Pläne",
@ -372,7 +362,6 @@
"QR code is too large": "QR code is too large",
"Real name": "Echter Name",
"Records": "Datensätze",
"Request": "Request",
"Request URI": "Request URI",
"Resources": "Ressourcen",
"Role": "Role",
@ -423,7 +412,6 @@
"This is a read-only demo site!": "Dies ist eine schreibgeschützte Demo-Seite!",
"Timestamp": "Timestamp",
"Tokens": "Token",
"Tour": "Tour",
"Transactions": "Transactions",
"Type": "Type",
"Type - Tooltip": "Type - Tooltip",
@ -454,8 +442,7 @@
"Parent group - Tooltip": "Parent group - Tooltip",
"Physical": "Physical",
"Show all": "Show all",
"Virtual": "Virtual",
"You need to delete all subgroups first. You can view the subgroups in the left group tree of the [Organizations] -\u003e [Groups] page": "You need to delete all subgroups first. You can view the subgroups in the left group tree of the [Organizations] -\u003e [Groups] page"
"Virtual": "Virtual"
},
"home": {
"New users past 30 days": "New users past 30 days",
@ -474,16 +461,13 @@
"Quota": "Quota",
"Quota - Tooltip": "Quota - Tooltip",
"Used count": "Used count",
"Used count - Tooltip": "Used count - Tooltip",
"You need to first specify a default application for organization: ": "You need to first specify a default application for organization: "
"Used count - Tooltip": "Used count - Tooltip"
},
"ldap": {
"Admin": "Admin",
"Admin - Tooltip": "CN oder ID des LDAP-Serveradministrators",
"Admin Password": "Administratoren-Passwort",
"Admin Password - Tooltip": "LDAP-Server-Administratorpasswort",
"Allow self-signed certificate": "Allow self-signed certificate",
"Allow self-signed certificate - Tooltip": "Allow self-signed certificate - Tooltip",
"Auto Sync": "Auto-Synchronisierung",
"Auto Sync - Tooltip": "Auto-Sync-Konfiguration, deaktiviert um 0 Uhr",
"Base DN": "Basis-DN",
@ -602,6 +586,11 @@
"Your phone is": "Your phone is",
"preferred": "preferred"
},
"mfaAccount": {
"Account Name": "Account Name",
"Issuer": "Issuer",
"Secret Key": "Secret Key"
},
"model": {
"Advanced Editor": "Erweiterter Editor",
"Basic Editor": "Basis-Editor",
@ -621,8 +610,6 @@
"Is profile public": "Ist das Profil öffentlich?",
"Is profile public - Tooltip": "Nach der Schließung können nur globale Administratoren oder Benutzer in der gleichen Organisation auf die Profilseite des Benutzers zugreifen",
"Modify rule": "Regel ändern",
"Navbar items": "Navbar items",
"Navbar items - Tooltip": "Navbar items - Tooltip",
"New Organization": "Neue Organisation",
"Optional": "Optional",
"Password expire days": "Password expire days",
@ -635,14 +622,10 @@
"Tags - Tooltip": "Sammlung von Tags, die für Benutzer zur Auswahl zur Verfügung stehen",
"Use Email as username": "Use Email as username",
"Use Email as username - Tooltip": "Use Email as username if the username field is not visible at signup",
"User types": "User types",
"User types - Tooltip": "User types - Tooltip",
"View rule": "Ansichtsregel",
"Visible": "Sichtbar",
"Website URL": "Website-URL",
"Website URL - Tooltip": "Die Homepage-URL der Organisation. Dieses Feld wird in Casdoor nicht verwendet",
"Widget items": "Widget items",
"Widget items - Tooltip": "Widget items - Tooltip"
"Website URL - Tooltip": "Die Homepage-URL der Organisation. Dieses Feld wird in Casdoor nicht verwendet"
},
"payment": {
"Confirm your invoice information": "Bestätigen Sie Ihre Rechnungsinformationen",
@ -745,7 +728,6 @@
"paid-user do not have active subscription or pending subscription, please select a plan to buy": "paid-user do not have active subscription or pending subscription, please select a plan to buy"
},
"product": {
"AirWallex": "AirWallex",
"Alipay": "Alipay",
"Buy": "Kaufen",
"Buy Product": "Produkt kaufen",
@ -775,6 +757,7 @@
"Sold": "Verkauft",
"Sold - Tooltip": "Menge verkauft",
"Stripe": "Stripe",
"AirWallex": "AirWallex",
"Tag - Tooltip": "Tag des Produkts",
"Test buy page..": "Testkaufseite.",
"There is no payment channel for this product.": "Es gibt keinen Zahlungskanal für dieses Produkt.",
@ -834,8 +817,6 @@
"Edit Provider": "Provider bearbeiten",
"Email content": "Email-Inhalt",
"Email content - Tooltip": "Inhalt der E-Mail",
"Email regex": "Email regex",
"Email regex - Tooltip": "Email regex - Tooltip",
"Email title": "Email-Titel",
"Email title - Tooltip": "Betreff der E-Mail",
"Endpoint": "Endpunkt",
@ -849,8 +830,6 @@
"From name - Tooltip": "From name - Tooltip",
"Get phone number": "Get phone number",
"Get phone number - Tooltip": "If sync phone number is enabled, you should enable google people api first and add scope https://www.googleapis.com/auth/user.phonenumbers.read",
"HTTP header": "HTTP header",
"HTTP header - Tooltip": "HTTP header - Tooltip",
"Host": "Host",
"Host - Tooltip": "Name des Hosts",
"IdP": "IdP",
@ -865,8 +844,6 @@
"Key text - Tooltip": "Key text - Tooltip",
"Metadata": "Metadaten",
"Metadata - Tooltip": "SAML-Metadaten",
"Metadata url": "Metadata url",
"Metadata url - Tooltip": "Metadata url - Tooltip",
"Method - Tooltip": "Anmeldeverfahren, QR-Code oder Silent-Login",
"New Provider": "Neuer Provider",
"Normal": "Normal",
@ -1267,8 +1244,6 @@
"Edit Webhook": "Webhook bearbeiten",
"Events": "Ereignisse",
"Events - Tooltip": "Ereignisse",
"Extended user fields": "Extended user fields",
"Extended user fields - Tooltip": "Extended user fields - Tooltip",
"Headers": "Überschriften",
"Headers - Tooltip": "HTTP-Header (Schlüssel-Wert-Paare)",
"Is user extended": "Wurde der Benutzer erweitert?",

View File

@ -17,15 +17,11 @@
"Use same DB - Tooltip": "Use the same DB as Casdoor"
},
"application": {
"Add Face ID": "Add Face ID",
"Add Face ID with Image": "Add Face ID with Image",
"Always": "Always",
"Auto signin": "Auto signin",
"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": "URL of the background image used in the login page",
"Background URL Mobile": "Background URL Mobile",
"Background URL Mobile - Tooltip": "Background URL Mobile - Tooltip",
"Big icon": "Big icon",
"Binding providers": "Binding providers",
"CSS style": "CSS style",
@ -65,10 +61,8 @@
"Footer HTML": "Footer HTML",
"Footer HTML - Edit": "Footer HTML - Edit",
"Footer HTML - Tooltip": "Custom the footer of your application",
"Forced redirect origin": "Forced redirect origin",
"Form position": "Form position",
"Form position - Tooltip": "Location of the signup, signin and forget password forms",
"Generate Face ID": "Generate Face ID",
"Grant types": "Grant types",
"Grant types - Tooltip": "Select which grant types are allowed in the OAuth protocol",
"Header HTML": "Header HTML",
@ -169,7 +163,6 @@
},
"currency": {
"AUD": "AUD",
"BRL": "BRL",
"CAD": "CAD",
"CHF": "CHF",
"CNY": "CNY",
@ -196,7 +189,6 @@
"Verify": "Verify"
},
"general": {
"AI Assistant": "AI Assistant",
"API key": "API key",
"API key - Tooltip": "API key - Tooltip",
"Access key": "Access key",
@ -209,6 +201,7 @@
"Adapter - Tooltip": "Table name of the policy store",
"Adapters": "Adapters",
"Add": "Add",
"Add Face Id": "Add Face Id",
"Add custom item": "Add custom item",
"Admin": "Admin",
"Affiliation URL": "Affiliation URL",
@ -238,7 +231,6 @@
"Created time": "Created time",
"Custom": "Custom",
"Dashboard": "Dashboard",
"Data": "Data",
"Default": "Default",
"Default application": "Default application",
"Default application - Tooltip": "Default application for users registered directly from the organization page",
@ -267,6 +259,7 @@
"Enabled": "Enabled",
"Enabled successfully": "Enabled successfully",
"Enforcers": "Enforcers",
"FaceIdData": "FaceIdData",
"Failed to add": "Failed to add",
"Failed to connect to server": "Failed to connect to server",
"Failed to delete": "Failed to delete",
@ -279,7 +272,6 @@
"Favicon": "Favicon",
"Favicon - Tooltip": "Favicon icon URL used in all Casdoor pages of the organization",
"First name": "First name",
"Forced redirect origin - Tooltip": "Forced redirect origin - Tooltip",
"Forget URL": "Forget URL",
"Forget URL - Tooltip": "Custom URL for the \"Forget password\" page. If not set, the default Casdoor \"Forget password\" page will be used. When set, the \"Forget password\" link on the login page will redirect to this URL",
"Found some texts still not translated? Please help us translate at": "Found some texts still not translated? Please help us translate at",
@ -353,7 +345,6 @@
"Phone - Tooltip": "Phone number",
"Phone only": "Phone only",
"Phone or Email": "Phone or Email",
"Plain": "Plain",
"Plan": "Plan",
"Plan - Tooltip": "Plan - Tooltip",
"Plans": "Plans",
@ -372,7 +363,6 @@
"QR code is too large": "QR code is too large",
"Real name": "Real name",
"Records": "Records",
"Request": "Request",
"Request URI": "Request URI",
"Resources": "Resources",
"Role": "Role",
@ -423,7 +413,6 @@
"This is a read-only demo site!": "This is a read-only demo site!",
"Timestamp": "Timestamp",
"Tokens": "Tokens",
"Tour": "Tour",
"Transactions": "Transactions",
"Type": "Type",
"Type - Tooltip": "Type - Tooltip",
@ -454,8 +443,7 @@
"Parent group - Tooltip": "Parent group - Tooltip",
"Physical": "Physical",
"Show all": "Show all",
"Virtual": "Virtual",
"You need to delete all subgroups first. You can view the subgroups in the left group tree of the [Organizations] -\u003e [Groups] page": "You need to delete all subgroups first. You can view the subgroups in the left group tree of the [Organizations] -\u003e [Groups] page"
"Virtual": "Virtual"
},
"home": {
"New users past 30 days": "New users past 30 days",
@ -474,16 +462,13 @@
"Quota": "Quota",
"Quota - Tooltip": "The maximum number of users that can register using this invitation code",
"Used count": "Used count",
"Used count - Tooltip": "The number of times this invitation code has been used",
"You need to first specify a default application for organization: ": "You need to first specify a default application for organization: "
"Used count - Tooltip": "The number of times this invitation code has been used"
},
"ldap": {
"Admin": "Admin",
"Admin - Tooltip": "CN or ID of the LDAP server administrator",
"Admin Password": "Admin Password",
"Admin Password - Tooltip": "LDAP server administrator password",
"Allow self-signed certificate": "Allow self-signed certificate",
"Allow self-signed certificate - Tooltip": "Allow self-signed certificate - Tooltip",
"Auto Sync": "Auto Sync",
"Auto Sync - Tooltip": "Auto-sync configuration, disabled at 0",
"Base DN": "Base DN",
@ -602,6 +587,11 @@
"Your phone is": "Your phone is",
"preferred": "preferred"
},
"mfaAccount": {
"Account Name": "Account Name",
"Issuer": "Issuer",
"Secret Key": "Secret Key"
},
"model": {
"Advanced Editor": "Advanced Editor",
"Basic Editor": "Basic Editor",
@ -621,8 +611,6 @@
"Is profile public": "Is profile public",
"Is profile public - Tooltip": "After being closed, only global administrators or users in the same organization can access the user's profile page",
"Modify rule": "Modify rule",
"Navbar items": "Navbar items",
"Navbar items - Tooltip": "Navbar items - Tooltip",
"New Organization": "New Organization",
"Optional": "Optional",
"Password expire days": "Password expire days",
@ -635,14 +623,10 @@
"Tags - Tooltip": "Collection of tags available for users to choose from",
"Use Email as username": "Use Email as username",
"Use Email as username - Tooltip": "Use Email as username if the username field is not visible at signup",
"User types": "User types",
"User types - Tooltip": "User types - Tooltip",
"View rule": "View rule",
"Visible": "Visible",
"Website URL": "Website URL",
"Website URL - Tooltip": "The homepage URL of the organization. This field is not used in Casdoor",
"Widget items": "Widget items",
"Widget items - Tooltip": "Widget items - Tooltip"
"Website URL - Tooltip": "The homepage URL of the organization. This field is not used in Casdoor"
},
"payment": {
"Confirm your invoice information": "Confirm your invoice information",
@ -745,7 +729,6 @@
"paid-user do not have active subscription or pending subscription, please select a plan to buy": "paid-user do not have active subscription or pending subscription, please select a plan to buy"
},
"product": {
"AirWallex": "AirWallex",
"Alipay": "Alipay",
"Buy": "Buy",
"Buy Product": "Buy Product",
@ -775,6 +758,7 @@
"Sold": "Sold",
"Sold - Tooltip": "Quantity sold",
"Stripe": "Stripe",
"AirWallex": "AirWallex",
"Tag - Tooltip": "Tag of product",
"Test buy page..": "Test buy page..",
"There is no payment channel for this product.": "There is no payment channel for this product.",
@ -834,8 +818,6 @@
"Edit Provider": "Edit Provider",
"Email content": "Email content",
"Email content - Tooltip": "Content of the Email",
"Email regex": "Email regex",
"Email regex - Tooltip": "Email regex - Tooltip",
"Email title": "Email title",
"Email title - Tooltip": "Title of the email",
"Endpoint": "Endpoint",
@ -849,8 +831,6 @@
"From name - Tooltip": "Name of \"From\"",
"Get phone number": "Get phone number",
"Get phone number - Tooltip": "If sync phone number is enabled, you should enable google people api first and add scope https://www.googleapis.com/auth/user.phonenumbers.read",
"HTTP header": "HTTP header",
"HTTP header - Tooltip": "HTTP header - Tooltip",
"Host": "Host",
"Host - Tooltip": "Name of host",
"IdP": "IdP",
@ -865,8 +845,6 @@
"Key text - Tooltip": "Key text",
"Metadata": "Metadata",
"Metadata - Tooltip": "SAML metadata",
"Metadata url": "Metadata url",
"Metadata url - Tooltip": "Metadata url - Tooltip",
"Method - Tooltip": "Login method, QR code or silent login",
"New Provider": "New Provider",
"Normal": "Normal",
@ -1267,8 +1245,6 @@
"Edit Webhook": "Edit Webhook",
"Events": "Events",
"Events - Tooltip": "Events",
"Extended user fields": "Extended user fields",
"Extended user fields - Tooltip": "Extended user fields - Tooltip",
"Headers": "Headers",
"Headers - Tooltip": "HTTP headers (key-value pairs)",
"Is user extended": "Is user extended",

View File

@ -17,15 +17,11 @@
"Use same DB - Tooltip": "Use same DB - Tooltip"
},
"application": {
"Add Face ID": "Add Face ID",
"Add Face ID with Image": "Add Face ID with Image",
"Always": "siempre",
"Auto signin": "Inicio de sesión automático",
"Auto signin - Tooltip": "Cuando existe una sesión iniciada en Casdoor, se utiliza automáticamente para el inicio de sesión del lado de la aplicación",
"Background URL": "URL de fondo",
"Background URL - Tooltip": "URL de la imagen de fondo utilizada en la página de inicio de sesión",
"Background URL Mobile": "Background URL Mobile",
"Background URL Mobile - Tooltip": "Background URL Mobile - Tooltip",
"Big icon": "Big icon",
"Binding providers": "Binding providers",
"CSS style": "CSS style",
@ -65,10 +61,8 @@
"Footer HTML": "Footer HTML",
"Footer HTML - Edit": "Footer HTML - Edit",
"Footer HTML - Tooltip": "Custom the footer of your application",
"Forced redirect origin": "Forced redirect origin",
"Form position": "Posición de la Forma",
"Form position - Tooltip": "Ubicación de los formularios de registro, inicio de sesión y olvido de contraseña",
"Generate Face ID": "Generate Face ID",
"Grant types": "Tipos de subvenciones",
"Grant types - Tooltip": "Selecciona cuáles tipos de subvenciones están permitidas en el protocolo OAuth",
"Header HTML": "Header HTML",
@ -169,7 +163,6 @@
},
"currency": {
"AUD": "AUD",
"BRL": "BRL",
"CAD": "CAD",
"CHF": "CHF",
"CNY": "CNY",
@ -196,7 +189,6 @@
"Verify": "Verificar"
},
"general": {
"AI Assistant": "AI Assistant",
"API key": "API key",
"API key - Tooltip": "API key - Tooltip",
"Access key": "Access key",
@ -209,6 +201,7 @@
"Adapter - Tooltip": "Nombre de la tabla de la tienda de políticas",
"Adapters": "Adaptadores",
"Add": "Añadir",
"Add Face Id": "Add Face Id",
"Add custom item": "Add custom item",
"Admin": "Admin",
"Affiliation URL": "URL de afiliación",
@ -238,7 +231,6 @@
"Created time": "Tiempo creado",
"Custom": "Custom",
"Dashboard": "Dashboard",
"Data": "Data",
"Default": "Default",
"Default application": "Aplicación predeterminada",
"Default application - Tooltip": "Aplicación predeterminada para usuarios registrados directamente desde la página de la organización",
@ -249,7 +241,6 @@
"Delete": "Eliminar",
"Description": "Descripción",
"Description - Tooltip": "Información detallada de descripción para referencia, Casdoor en sí no la utilizará",
"Detail": "详情",
"Disable": "Disable",
"Display name": "Nombre de pantalla",
"Display name - Tooltip": "Un nombre fácil de usar y leer que se muestra públicamente en la interfaz de usuario",
@ -267,6 +258,7 @@
"Enabled": "Enabled",
"Enabled successfully": "Enabled successfully",
"Enforcers": "Enforcers",
"FaceIdData": "FaceIdData",
"Failed to add": "No se pudo agregar",
"Failed to connect to server": "No se pudo conectar al servidor",
"Failed to delete": "No se pudo eliminar",
@ -279,7 +271,6 @@
"Favicon": "Favicon (ícono de favoritos)",
"Favicon - Tooltip": "URL del icono Favicon utilizado en todas las páginas de Casdoor de la organización",
"First name": "Nombre de pila",
"Forced redirect origin - Tooltip": "Forced redirect origin - Tooltip",
"Forget URL": "Olvide la URL",
"Forget URL - Tooltip": "URL personalizada para la página \"Olvidé mi contraseña\". Si no se establece, se utilizará la página \"Olvidé mi contraseña\" predeterminada de Casdoor. Cuando se establezca, el enlace \"Olvidé mi contraseña\" en la página de inicio de sesión redireccionará a esta URL",
"Found some texts still not translated? Please help us translate at": "¿Encontraste algunos textos que aún no están traducidos? Por favor, ayúdanos a traducirlos en",
@ -353,7 +344,6 @@
"Phone - Tooltip": "Número de teléfono",
"Phone only": "Phone only",
"Phone or Email": "Phone or Email",
"Plain": "Plain",
"Plan": "Plan",
"Plan - Tooltip": "Plan - Tooltip",
"Plans": "Planes",
@ -372,7 +362,6 @@
"QR code is too large": "QR code is too large",
"Real name": "Nombre real",
"Records": "Registros",
"Request": "Request",
"Request URI": "Request URI",
"Resources": "Recursos",
"Role": "Role",
@ -423,7 +412,6 @@
"This is a read-only demo site!": "¡Este es un sitio de demostración solo de lectura!",
"Timestamp": "Timestamp",
"Tokens": "Tokens",
"Tour": "Tour",
"Transactions": "Transactions",
"Type": "Type",
"Type - Tooltip": "Type - Tooltip",
@ -454,8 +442,7 @@
"Parent group - Tooltip": "Parent group - Tooltip",
"Physical": "Physical",
"Show all": "Show all",
"Virtual": "Virtual",
"You need to delete all subgroups first. You can view the subgroups in the left group tree of the [Organizations] -\u003e [Groups] page": "You need to delete all subgroups first. You can view the subgroups in the left group tree of the [Organizations] -\u003e [Groups] page"
"Virtual": "Virtual"
},
"home": {
"New users past 30 days": "New users past 30 days",
@ -474,16 +461,13 @@
"Quota": "Quota",
"Quota - Tooltip": "Quota - Tooltip",
"Used count": "Used count",
"Used count - Tooltip": "Used count - Tooltip",
"You need to first specify a default application for organization: ": "You need to first specify a default application for organization: "
"Used count - Tooltip": "Used count - Tooltip"
},
"ldap": {
"Admin": "Administrador",
"Admin - Tooltip": "CN o ID del administrador del servidor LDAP",
"Admin Password": "Contraseña de administrador",
"Admin Password - Tooltip": "Contraseña del administrador del servidor LDAP",
"Allow self-signed certificate": "Allow self-signed certificate",
"Allow self-signed certificate - Tooltip": "Allow self-signed certificate - Tooltip",
"Auto Sync": "Sincronización automática",
"Auto Sync - Tooltip": "Configuración de sincronización automática, desactivada a las 0",
"Base DN": "DN base",
@ -602,6 +586,11 @@
"Your phone is": "Your phone is",
"preferred": "preferred"
},
"mfaAccount": {
"Account Name": "Account Name",
"Issuer": "Issuer",
"Secret Key": "Secret Key"
},
"model": {
"Advanced Editor": "Editor avanzado",
"Basic Editor": "Editor básico",
@ -621,8 +610,6 @@
"Is profile public": "Es el perfil público",
"Is profile public - Tooltip": "Después de estar cerrado, solo los administradores globales o usuarios de la misma organización pueden acceder a la página de perfil del usuario",
"Modify rule": "Modificar regla",
"Navbar items": "Navbar items",
"Navbar items - Tooltip": "Navbar items - Tooltip",
"New Organization": "Nueva organización",
"Optional": "Optional",
"Password expire days": "Password expire days",
@ -635,14 +622,10 @@
"Tags - Tooltip": "Colección de etiquetas disponibles para que los usuarios elijan",
"Use Email as username": "Use Email as username",
"Use Email as username - Tooltip": "Use Email as username if the username field is not visible at signup",
"User types": "User types",
"User types - Tooltip": "User types - Tooltip",
"View rule": "Regla de visualización",
"Visible": "Visible - Visible",
"Website URL": "URL del sitio web",
"Website URL - Tooltip": "La URL de la página de inicio de la organización. Este campo no se usa en Casdoor",
"Widget items": "Widget items",
"Widget items - Tooltip": "Widget items - Tooltip"
"Website URL - Tooltip": "La URL de la página de inicio de la organización. Este campo no se usa en Casdoor"
},
"payment": {
"Confirm your invoice information": "Confirma la información de tu factura",
@ -745,7 +728,6 @@
"paid-user do not have active subscription or pending subscription, please select a plan to buy": "paid-user do not have active subscription or pending subscription, please select a plan to buy"
},
"product": {
"AirWallex": "AirWallex",
"Alipay": "Alipay",
"Buy": "Comprar",
"Buy Product": "Comprar producto",
@ -775,6 +757,7 @@
"Sold": "Vendido",
"Sold - Tooltip": "Cantidad vendida",
"Stripe": "Stripe",
"AirWallex": "AirWallex",
"Tag - Tooltip": "Etiqueta de producto",
"Test buy page..": "Página de compra de prueba.",
"There is no payment channel for this product.": "No hay canal de pago para este producto.",
@ -834,8 +817,6 @@
"Edit Provider": "Editar proveedor",
"Email content": "Contenido de correo electrónico",
"Email content - Tooltip": "Contenido del correo electrónico",
"Email regex": "Email regex",
"Email regex - Tooltip": "Email regex - Tooltip",
"Email title": "Título del correo electrónico",
"Email title - Tooltip": "Título del correo electrónico",
"Endpoint": "Punto final",
@ -849,8 +830,6 @@
"From name - Tooltip": "From name - Tooltip",
"Get phone number": "Get phone number",
"Get phone number - Tooltip": "If sync phone number is enabled, you should enable google people api first and add scope https://www.googleapis.com/auth/user.phonenumbers.read",
"HTTP header": "HTTP header",
"HTTP header - Tooltip": "HTTP header - Tooltip",
"Host": "Anfitrión",
"Host - Tooltip": "Nombre del anfitrión",
"IdP": "IdP = Proveedor de Identidad",
@ -865,8 +844,6 @@
"Key text - Tooltip": "Key text - Tooltip",
"Metadata": "Metadatos",
"Metadata - Tooltip": "Metadatos SAML",
"Metadata url": "Metadata url",
"Metadata url - Tooltip": "Metadata url - Tooltip",
"Method - Tooltip": "Método de inicio de sesión, código QR o inicio de sesión silencioso",
"New Provider": "Nuevo proveedor",
"Normal": "Normal",
@ -1267,8 +1244,6 @@
"Edit Webhook": "Editar Webhook",
"Events": "Eventos",
"Events - Tooltip": "Eventos",
"Extended user fields": "Extended user fields",
"Extended user fields - Tooltip": "Extended user fields - Tooltip",
"Headers": "Encabezados",
"Headers - Tooltip": "Encabezados de HTTP (pares de clave-valor)",
"Is user extended": "¿Está el usuario extendido?",

View File

@ -17,15 +17,11 @@
"Use same DB - Tooltip": "استفاده از همان پایگاه داده به عنوان Casdoor"
},
"application": {
"Add Face ID": "Add Face ID",
"Add Face ID with Image": "Add Face ID with Image",
"Always": "همیشه",
"Auto signin": "ورود خودکار",
"Auto signin - Tooltip": "هنگامی که یک جلسه ورود در Casdoor وجود دارد، به‌طور خودکار برای ورود به برنامه استفاده می‌شود",
"Background URL": "آدرس پس‌زمینه",
"Background URL - Tooltip": "آدرس تصویر پس‌زمینه استفاده شده در صفحه ورود",
"Background URL Mobile": "Background URL Mobile",
"Background URL Mobile - Tooltip": "Background URL Mobile - Tooltip",
"Big icon": "آیکون بزرگ",
"Binding providers": "اتصال ارائه‌دهندگان",
"CSS style": "استایل CSS",
@ -65,10 +61,8 @@
"Footer HTML": "HTML پاورقی",
"Footer HTML - Edit": "ویرایش HTML پاورقی",
"Footer HTML - Tooltip": "پاورقی برنامه خود را سفارشی کنید",
"Forced redirect origin": "Forced redirect origin",
"Form position": "موقعیت فرم",
"Form position - Tooltip": "مکان فرم‌های ثبت‌نام، ورود و فراموشی رمز عبور",
"Generate Face ID": "Generate Face ID",
"Grant types": "نوع‌های اعطا",
"Grant types - Tooltip": "انتخاب کنید کدام نوع‌های اعطا در پروتکل OAuth مجاز هستند",
"Header HTML": "HTML سربرگ",
@ -169,7 +163,6 @@
},
"currency": {
"AUD": "AUD",
"BRL": "BRL",
"CAD": "CAD",
"CHF": "CHF",
"CNY": "CNY",
@ -196,7 +189,6 @@
"Verify": "تأیید"
},
"general": {
"AI Assistant": "AI Assistant",
"API key": "کلید API",
"API key - Tooltip": "کلید API - راهنمای ابزار",
"Access key": "کلید دسترسی",
@ -209,6 +201,7 @@
"Adapter - Tooltip": "نام جدول فروشگاه سیاست",
"Adapters": "آداپتورها",
"Add": "افزودن",
"Add Face Id": "افزودن Face Id",
"Add custom item": "افزودن مورد سفارشی",
"Admin": "مدیر",
"Affiliation URL": "آدرس وابستگی",
@ -238,7 +231,6 @@
"Created time": "زمان ایجاد",
"Custom": "سفارشی",
"Dashboard": "داشبورد",
"Data": "Data",
"Default": "پیش‌فرض",
"Default application": "برنامه پیش‌فرض",
"Default application - Tooltip": "برنامه پیش‌فرض برای کاربرانی که مستقیماً از صفحه سازمان ثبت‌نام می‌کنند",
@ -249,7 +241,6 @@
"Delete": "حذف",
"Description": "توضیحات",
"Description - Tooltip": "اطلاعات توضیحات دقیق برای مرجع، خود Casdoor از آن استفاده نمی‌کند",
"Detail": "详情",
"Disable": "غیرفعال",
"Display name": "نام نمایشی",
"Display name - Tooltip": "نام کاربرپسند و قابل خواندن آسان که به‌صورت عمومی در رابط کاربری نمایش داده می‌شود",
@ -267,6 +258,7 @@
"Enabled": "فعال شده",
"Enabled successfully": "با موفقیت فعال شد",
"Enforcers": "Enforcerها",
"FaceIdData": "داده‌های FaceId",
"Failed to add": "عدم موفقیت در افزودن",
"Failed to connect to server": "عدم موفقیت در اتصال به سرور",
"Failed to delete": "عدم موفقیت در حذف",
@ -279,7 +271,6 @@
"Favicon": "Favicon",
"Favicon - Tooltip": "آدرس آیکون Favicon استفاده شده در تمام صفحات Casdoor سازمان",
"First name": "نام",
"Forced redirect origin - Tooltip": "Forced redirect origin - Tooltip",
"Forget URL": "آدرس فراموشی",
"Forget URL - Tooltip": "آدرس سفارشی برای صفحه \"فراموشی رمز عبور\". اگر تنظیم نشده باشد، صفحه پیش‌فرض \"فراموشی رمز عبور\" Casdoor استفاده می‌شود. هنگامی که تنظیم شده باشد، لینک \"فراموشی رمز عبور\" در صفحه ورود به این آدرس هدایت می‌شود",
"Found some texts still not translated? Please help us translate at": "برخی متون هنوز ترجمه نشده‌اند؟ لطفاً به ما در ترجمه کمک کنید در",
@ -353,7 +344,6 @@
"Phone - Tooltip": "شماره تلفن",
"Phone only": "فقط تلفن",
"Phone or Email": "تلفن یا ایمیل",
"Plain": "Plain",
"Plan": "طرح",
"Plan - Tooltip": "طرح - راهنمای ابزار",
"Plans": "طرح‌ها",
@ -372,7 +362,6 @@
"QR code is too large": "کد QR بیش از حد بزرگ است",
"Real name": "نام واقعی",
"Records": "سوابق",
"Request": "Request",
"Request URI": "آدرس URI درخواست",
"Resources": "منابع",
"Role": "نقش",
@ -423,7 +412,6 @@
"This is a read-only demo site!": "این یک سایت دمو فقط خواندنی است!",
"Timestamp": "مهر زمان",
"Tokens": "توکن‌ها",
"Tour": "Tour",
"Transactions": "تراکنش‌ها",
"Type": "نوع",
"Type - Tooltip": "نوع - راهنمای ابزار",
@ -454,8 +442,7 @@
"Parent group - Tooltip": "گروه والد - راهنمای ابزار",
"Physical": "فیزیکی",
"Show all": "نمایش همه",
"Virtual": "مجازی",
"You need to delete all subgroups first. You can view the subgroups in the left group tree of the [Organizations] -\u003e [Groups] page": "You need to delete all subgroups first. You can view the subgroups in the left group tree of the [Organizations] -\u003e [Groups] page"
"Virtual": "مجازی"
},
"home": {
"New users past 30 days": "کاربران جدید در ۳۰ روز گذشته",
@ -474,16 +461,13 @@
"Quota": "سهمیه",
"Quota - Tooltip": "حداکثر تعداد کاربرانی که می‌توانند با استفاده از این کد دعوت ثبت‌نام کنند",
"Used count": "تعداد استفاده شده",
"Used count - Tooltip": "تعداد دفعات استفاده از این کد دعوت",
"You need to first specify a default application for organization: ": "You need to first specify a default application for organization: "
"Used count - Tooltip": "تعداد دفعات استفاده از این کد دعوت"
},
"ldap": {
"Admin": "مدیر",
"Admin - Tooltip": "CN یا ID مدیر سرور LDAP",
"Admin Password": "رمز عبور مدیر",
"Admin Password - Tooltip": "رمز عبور مدیر سرور LDAP",
"Allow self-signed certificate": "Allow self-signed certificate",
"Allow self-signed certificate - Tooltip": "Allow self-signed certificate - Tooltip",
"Auto Sync": "همگام‌سازی خودکار",
"Auto Sync - Tooltip": "پیکربندی همگام‌سازی خودکار، در ۰ غیرفعال است",
"Base DN": "پایه DN",
@ -602,6 +586,11 @@
"Your phone is": "تلفن شما",
"preferred": "مورد علاقه"
},
"mfaAccount": {
"Account Name": "نام حساب",
"Issuer": "صادرکننده",
"Secret Key": "کلید مخفی"
},
"model": {
"Advanced Editor": "ویرایشگر پیشرفته",
"Basic Editor": "ویرایشگر ابتدایی",
@ -621,8 +610,6 @@
"Is profile public": "پروفایل عمومی است",
"Is profile public - Tooltip": "پس از بسته شدن، فقط مدیران جهانی یا کاربران در همان سازمان می‌توانند به صفحه پروفایل کاربر دسترسی داشته باشند",
"Modify rule": "قانون اصلاح",
"Navbar items": "Navbar items",
"Navbar items - Tooltip": "Navbar items - Tooltip",
"New Organization": "سازمان جدید",
"Optional": "اختیاری",
"Password expire days": "Password expire days",
@ -635,14 +622,10 @@
"Tags - Tooltip": "مجموعه‌ای از برچسب‌های موجود برای انتخاب کاربران",
"Use Email as username": "استفاده از ایمیل به‌عنوان نام کاربری",
"Use Email as username - Tooltip": "اگر فیلد نام کاربری در ثبت‌نام قابل مشاهده نباشد، از ایمیل به‌عنوان نام کاربری استفاده کنید",
"User types": "User types",
"User types - Tooltip": "User types - Tooltip",
"View rule": "قانون مشاهده",
"Visible": "قابل مشاهده",
"Website URL": "آدرس وب‌سایت",
"Website URL - Tooltip": "آدرس صفحه اصلی سازمان. این فیلد در Casdoor استفاده نمی‌شود",
"Widget items": "Widget items",
"Widget items - Tooltip": "Widget items - Tooltip"
"Website URL - Tooltip": "آدرس صفحه اصلی سازمان. این فیلد در Casdoor استفاده نمی‌شود"
},
"payment": {
"Confirm your invoice information": "اطلاعات فاکتور خود را تأیید کنید",
@ -745,7 +728,6 @@
"paid-user do not have active subscription or pending subscription, please select a plan to buy": "کاربر پرداختی اشتراک فعال یا در انتظار ندارد، لطفاً یک طرح برای خرید انتخاب کنید"
},
"product": {
"AirWallex": "AirWallex",
"Alipay": "Alipay",
"Buy": "خرید",
"Buy Product": "خرید محصول",
@ -775,6 +757,7 @@
"Sold": "فروخته شده",
"Sold - Tooltip": "تعداد فروخته شده",
"Stripe": "Stripe",
"AirWallex": "AirWallex",
"Tag - Tooltip": "برچسب محصول",
"Test buy page..": "صفحه تست خرید..",
"There is no payment channel for this product.": "برای این محصول کانال پرداختی وجود ندارد.",
@ -834,8 +817,6 @@
"Edit Provider": "ویرایش ارائه‌دهنده",
"Email content": "محتوای ایمیل",
"Email content - Tooltip": "محتوای ایمیل",
"Email regex": "Email regex",
"Email regex - Tooltip": "Email regex - Tooltip",
"Email title": "عنوان ایمیل",
"Email title - Tooltip": "عنوان ایمیل",
"Endpoint": "نقطه پایانی",
@ -849,8 +830,6 @@
"From name - Tooltip": "نام \"از\"",
"Get phone number": "دریافت شماره تلفن",
"Get phone number - Tooltip": "اگر همگام‌سازی شماره تلفن فعال باشد، باید ابتدا API افراد گوگل را فعال کنید و محدوده https://www.googleapis.com/auth/user.phonenumbers.read را اضافه کنید",
"HTTP header": "HTTP header",
"HTTP header - Tooltip": "HTTP header - Tooltip",
"Host": "میزبان",
"Host - Tooltip": "نام میزبان",
"IdP": "IdP",
@ -865,8 +844,6 @@
"Key text - Tooltip": "متن کلید",
"Metadata": "فراداده",
"Metadata - Tooltip": "فراداده SAML",
"Metadata url": "Metadata url",
"Metadata url - Tooltip": "Metadata url - Tooltip",
"Method - Tooltip": "روش ورود، کد QR یا ورود بی‌صدا",
"New Provider": "ارائه‌دهنده جدید",
"Normal": "عادی",
@ -1267,8 +1244,6 @@
"Edit Webhook": "ویرایش Webhook",
"Events": "رویدادها",
"Events - Tooltip": "رویدادها",
"Extended user fields": "Extended user fields",
"Extended user fields - Tooltip": "Extended user fields - Tooltip",
"Headers": "هدرها",
"Headers - Tooltip": "هدرهای HTTP (کلید-مقدار)",
"Is user extended": "کاربر گسترش یافته است",

View File

@ -17,15 +17,11 @@
"Use same DB - Tooltip": "Use same DB - Tooltip"
},
"application": {
"Add Face ID": "Add Face ID",
"Add Face ID with Image": "Add Face ID with Image",
"Always": "Always",
"Auto signin": "Auto signin",
"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": "URL of the background image used in the login page",
"Background URL Mobile": "Background URL Mobile",
"Background URL Mobile - Tooltip": "Background URL Mobile - Tooltip",
"Big icon": "Big icon",
"Binding providers": "Binding providers",
"CSS style": "CSS style",
@ -65,10 +61,8 @@
"Footer HTML": "Footer HTML",
"Footer HTML - Edit": "Footer HTML - Edit",
"Footer HTML - Tooltip": "Custom the footer of your application",
"Forced redirect origin": "Forced redirect origin",
"Form position": "Form position",
"Form position - Tooltip": "Location of the signup, signin and forget password forms",
"Generate Face ID": "Generate Face ID",
"Grant types": "Grant types",
"Grant types - Tooltip": "Select which grant types are allowed in the OAuth protocol",
"Header HTML": "Header HTML",
@ -169,7 +163,6 @@
},
"currency": {
"AUD": "AUD",
"BRL": "BRL",
"CAD": "CAD",
"CHF": "CHF",
"CNY": "CNY",
@ -196,7 +189,6 @@
"Verify": "Verify"
},
"general": {
"AI Assistant": "AI Assistant",
"API key": "API key",
"API key - Tooltip": "API key - Tooltip",
"Access key": "Access key",
@ -209,6 +201,7 @@
"Adapter - Tooltip": "Table name of the policy store",
"Adapters": "Adapters",
"Add": "Add",
"Add Face Id": "Add Face Id",
"Add custom item": "Add custom item",
"Admin": "Admin",
"Affiliation URL": "Affiliation URL",
@ -238,7 +231,6 @@
"Created time": "Created time",
"Custom": "Custom",
"Dashboard": "Dashboard",
"Data": "Data",
"Default": "Default",
"Default application": "Default application",
"Default application - Tooltip": "Default application for users registered directly from the organization page",
@ -249,7 +241,6 @@
"Delete": "Delete",
"Description": "Description",
"Description - Tooltip": "Detailed description information for reference, Casdoor itself will not use it",
"Detail": "详情",
"Disable": "Disable",
"Display name": "Display name",
"Display name - Tooltip": "A user-friendly, easily readable name displayed publicly in the UI",
@ -267,6 +258,7 @@
"Enabled": "Enabled",
"Enabled successfully": "Enabled successfully",
"Enforcers": "Enforcers",
"FaceIdData": "FaceIdData",
"Failed to add": "Failed to add",
"Failed to connect to server": "Failed to connect to server",
"Failed to delete": "Failed to delete",
@ -279,7 +271,6 @@
"Favicon": "Favicon",
"Favicon - Tooltip": "Favicon icon URL used in all Casdoor pages of the organization",
"First name": "First name",
"Forced redirect origin - Tooltip": "Forced redirect origin - Tooltip",
"Forget URL": "Forget URL",
"Forget URL - Tooltip": "Custom URL for the \"Forget password\" page. If not set, the default Casdoor \"Forget password\" page will be used. When set, the \"Forget password\" link on the login page will redirect to this URL",
"Found some texts still not translated? Please help us translate at": "Found some texts still not translated? Please help us translate at",
@ -353,7 +344,6 @@
"Phone - Tooltip": "Phone number",
"Phone only": "Phone only",
"Phone or Email": "Phone or Email",
"Plain": "Plain",
"Plan": "Plan",
"Plan - Tooltip": "Plan - Tooltip",
"Plans": "Plans",
@ -372,7 +362,6 @@
"QR code is too large": "QR code is too large",
"Real name": "Real name",
"Records": "Records",
"Request": "Request",
"Request URI": "Request URI",
"Resources": "Resources",
"Role": "Role",
@ -423,7 +412,6 @@
"This is a read-only demo site!": "This is a read-only demo site!",
"Timestamp": "Timestamp",
"Tokens": "Tokens",
"Tour": "Tour",
"Transactions": "Transactions",
"Type": "Type",
"Type - Tooltip": "Type - Tooltip",
@ -454,8 +442,7 @@
"Parent group - Tooltip": "Parent group - Tooltip",
"Physical": "Physical",
"Show all": "Show all",
"Virtual": "Virtual",
"You need to delete all subgroups first. You can view the subgroups in the left group tree of the [Organizations] -\u003e [Groups] page": "You need to delete all subgroups first. You can view the subgroups in the left group tree of the [Organizations] -\u003e [Groups] page"
"Virtual": "Virtual"
},
"home": {
"New users past 30 days": "New users past 30 days",
@ -474,16 +461,13 @@
"Quota": "Quota",
"Quota - Tooltip": "Quota - Tooltip",
"Used count": "Used count",
"Used count - Tooltip": "Used count - Tooltip",
"You need to first specify a default application for organization: ": "You need to first specify a default application for organization: "
"Used count - Tooltip": "Used count - Tooltip"
},
"ldap": {
"Admin": "Admin",
"Admin - Tooltip": "CN or ID of the LDAP server administrator",
"Admin Password": "Admin Password",
"Admin Password - Tooltip": "LDAP server administrator password",
"Allow self-signed certificate": "Allow self-signed certificate",
"Allow self-signed certificate - Tooltip": "Allow self-signed certificate - Tooltip",
"Auto Sync": "Auto Sync",
"Auto Sync - Tooltip": "Auto-sync configuration, disabled at 0",
"Base DN": "Base DN",
@ -602,6 +586,11 @@
"Your phone is": "Your phone is",
"preferred": "preferred"
},
"mfaAccount": {
"Account Name": "Account Name",
"Issuer": "Issuer",
"Secret Key": "Secret Key"
},
"model": {
"Advanced Editor": "Advanced Editor",
"Basic Editor": "Basic Editor",
@ -621,8 +610,6 @@
"Is profile public": "Is profile public",
"Is profile public - Tooltip": "After being closed, only global administrators or users in the same organization can access the user's profile page",
"Modify rule": "Modify rule",
"Navbar items": "Navbar items",
"Navbar items - Tooltip": "Navbar items - Tooltip",
"New Organization": "New Organization",
"Optional": "Optional",
"Password expire days": "Password expire days",
@ -635,14 +622,10 @@
"Tags - Tooltip": "Collection of tags available for users to choose from",
"Use Email as username": "Use Email as username",
"Use Email as username - Tooltip": "Use Email as username if the username field is not visible at signup",
"User types": "User types",
"User types - Tooltip": "User types - Tooltip",
"View rule": "View rule",
"Visible": "Visible",
"Website URL": "Website URL",
"Website URL - Tooltip": "The homepage URL of the organization. This field is not used in Casdoor",
"Widget items": "Widget items",
"Widget items - Tooltip": "Widget items - Tooltip"
"Website URL - Tooltip": "The homepage URL of the organization. This field is not used in Casdoor"
},
"payment": {
"Confirm your invoice information": "Confirm your invoice information",
@ -745,7 +728,6 @@
"paid-user do not have active subscription or pending subscription, please select a plan to buy": "paid-user do not have active subscription or pending subscription, please select a plan to buy"
},
"product": {
"AirWallex": "AirWallex",
"Alipay": "Alipay",
"Buy": "Buy",
"Buy Product": "Buy Product",
@ -775,6 +757,7 @@
"Sold": "Sold",
"Sold - Tooltip": "Quantity sold",
"Stripe": "Stripe",
"AirWallex": "AirWallex",
"Tag - Tooltip": "Tag of product",
"Test buy page..": "Test buy page..",
"There is no payment channel for this product.": "There is no payment channel for this product.",
@ -834,8 +817,6 @@
"Edit Provider": "Edit Provider",
"Email content": "Email content",
"Email content - Tooltip": "Content of the Email",
"Email regex": "Email regex",
"Email regex - Tooltip": "Email regex - Tooltip",
"Email title": "Email title",
"Email title - Tooltip": "Title of the email",
"Endpoint": "Endpoint",
@ -849,8 +830,6 @@
"From name - Tooltip": "Name of \"From\"",
"Get phone number": "Get phone number",
"Get phone number - Tooltip": "If sync phone number is enabled, you should enable google people api first and add scope https://www.googleapis.com/auth/user.phonenumbers.read",
"HTTP header": "HTTP header",
"HTTP header - Tooltip": "HTTP header - Tooltip",
"Host": "Host",
"Host - Tooltip": "Name of host",
"IdP": "IdP",
@ -865,8 +844,6 @@
"Key text - Tooltip": "Key text - Tooltip",
"Metadata": "Metadata",
"Metadata - Tooltip": "SAML metadata",
"Metadata url": "Metadata url",
"Metadata url - Tooltip": "Metadata url - Tooltip",
"Method - Tooltip": "Login method, QR code or silent login",
"New Provider": "New Provider",
"Normal": "Normal",
@ -1267,8 +1244,6 @@
"Edit Webhook": "Edit Webhook",
"Events": "Events",
"Events - Tooltip": "Events",
"Extended user fields": "Extended user fields",
"Extended user fields - Tooltip": "Extended user fields - Tooltip",
"Headers": "Headers",
"Headers - Tooltip": "HTTP headers (key-value pairs)",
"Is user extended": "Is user extended",

View File

@ -17,15 +17,11 @@
"Use same DB - Tooltip": "Use same DB - Tooltip"
},
"application": {
"Add Face ID": "Add Face ID",
"Add Face ID with Image": "Add Face ID with Image",
"Always": "Toujours",
"Auto signin": "Connexion automatique",
"Auto signin - Tooltip": "Lorsqu'une session connectée existe dans Casdoor, elle est automatiquement utilisée pour la connexion côté application",
"Background URL": "URL de fond",
"Background URL - Tooltip": "L'URL de l'image d'arrière-plan utilisée sur la page de connexion",
"Background URL Mobile": "Background URL Mobile",
"Background URL Mobile - Tooltip": "Background URL Mobile - Tooltip",
"Big icon": "Big icon",
"Binding providers": "Fournisseurs liés",
"CSS style": "CSS style",
@ -65,10 +61,8 @@
"Footer HTML": "Footer HTML",
"Footer HTML - Edit": "Footer HTML - Edit",
"Footer HTML - Tooltip": "Custom the footer of your application",
"Forced redirect origin": "Forced redirect origin",
"Form position": "Position du formulaire",
"Form position - Tooltip": "Emplacement des formulaires d'inscription, de connexion et de récupération de mot de passe",
"Generate Face ID": "Generate Face ID",
"Grant types": "Types d'autorisation",
"Grant types - Tooltip": "Sélectionnez les types d'autorisations autorisés dans le protocole OAuth",
"Header HTML": "Header HTML",
@ -169,7 +163,6 @@
},
"currency": {
"AUD": "AUD",
"BRL": "BRL",
"CAD": "CAD",
"CHF": "CHF",
"CNY": "CNY",
@ -196,7 +189,6 @@
"Verify": "Vérifier"
},
"general": {
"AI Assistant": "AI Assistant",
"API key": "Clé API",
"API key - Tooltip": "Clé API - Info-bulle",
"Access key": "Clé d'accès",
@ -209,6 +201,7 @@
"Adapter - Tooltip": "Nom de la table du magasin de règle",
"Adapters": "Adaptateurs",
"Add": "Ajouter",
"Add Face Id": "Add Face Id",
"Add custom item": "Add custom item",
"Admin": "Administration",
"Affiliation URL": "URL d'affiliation",
@ -238,7 +231,6 @@
"Created time": "Date de création",
"Custom": "Personnalisée",
"Dashboard": "Tableau de bord",
"Data": "Data",
"Default": "Par défaut",
"Default application": "Application par défaut",
"Default application - Tooltip": "Application par défaut pour les comptes enregistrés directement depuis la page de l'organisation",
@ -249,7 +241,6 @@
"Delete": "Supprimer",
"Description": "Description",
"Description - Tooltip": "Description détaillée pour référence, Casdoor ne l'utilisera pas en soi",
"Detail": "详情",
"Disable": "Désactiver",
"Display name": "Nom d'affichage",
"Display name - Tooltip": "Un nom convivial et facilement lisible affiché publiquement dans l'interface utilisateur",
@ -267,6 +258,7 @@
"Enabled": "Activé",
"Enabled successfully": "Activé avec succès",
"Enforcers": "Exécuteurs",
"FaceIdData": "FaceIdData",
"Failed to add": "Échec d'ajout",
"Failed to connect to server": "Échec de la connexion au serveur",
"Failed to delete": "Échec de la suppression",
@ -279,7 +271,6 @@
"Favicon": "Icône du site",
"Favicon - Tooltip": "L'URL de l'icône « favicon » utilisée dans toutes les pages Casdoor de l'organisation",
"First name": "Prénom",
"Forced redirect origin - Tooltip": "Forced redirect origin - Tooltip",
"Forget URL": "URL d'oubli",
"Forget URL - Tooltip": "URL personnalisée pour la page \"Mot de passe oublié\". Si elle n'est pas définie, la page par défaut \"Mot de passe oublié\" de Casdoor sera utilisée. Lorsqu'elle est définie, le lien \"Mot de passe oublié\" sur la page de connexion sera redirigé vers cette URL",
"Found some texts still not translated? Please help us translate at": "Trouvé des textes encore non traduits ? Veuillez nous aider à les traduire sur",
@ -353,7 +344,6 @@
"Phone - Tooltip": "Numéro de téléphone",
"Phone only": "Phone only",
"Phone or Email": "Phone or Email",
"Plain": "Plain",
"Plan": "Offre",
"Plan - Tooltip": "Offre - Infobulle",
"Plans": "Offres",
@ -372,7 +362,6 @@
"QR code is too large": "QR code is too large",
"Real name": "Nom complet",
"Records": "Enregistrements",
"Request": "Request",
"Request URI": "Request URI",
"Resources": "Ressources",
"Role": "Rôle",
@ -423,7 +412,6 @@
"This is a read-only demo site!": "Ceci est un site de démonstration en lecture seule !",
"Timestamp": "Timestamp",
"Tokens": "Jetons",
"Tour": "Tour",
"Transactions": "Transactions",
"Type": "Type",
"Type - Tooltip": "Type - Infobulle",
@ -454,8 +442,7 @@
"Parent group - Tooltip": "Groupe parent - Infobulle",
"Physical": "Physique",
"Show all": "Tout afficher",
"Virtual": "Virtuel",
"You need to delete all subgroups first. You can view the subgroups in the left group tree of the [Organizations] -\u003e [Groups] page": "You need to delete all subgroups first. You can view the subgroups in the left group tree of the [Organizations] -\u003e [Groups] page"
"Virtual": "Virtuel"
},
"home": {
"New users past 30 days": "Comptes créés dans les 30 derniers jours",
@ -474,16 +461,13 @@
"Quota": "Quota",
"Quota - Tooltip": "Quota - Tooltip",
"Used count": "Used count",
"Used count - Tooltip": "Used count - Tooltip",
"You need to first specify a default application for organization: ": "You need to first specify a default application for organization: "
"Used count - Tooltip": "Used count - Tooltip"
},
"ldap": {
"Admin": "Compte d'administration",
"Admin - Tooltip": "CN ou ID du compte d'administration du serveur LDAP",
"Admin Password": "Mot de passe du compte d'administration",
"Admin Password - Tooltip": "Mot de passe administrateur du serveur LDAP",
"Allow self-signed certificate": "Allow self-signed certificate",
"Allow self-signed certificate - Tooltip": "Allow self-signed certificate - Tooltip",
"Auto Sync": "Synchronisation automatique",
"Auto Sync - Tooltip": "Configuration de synchronisation automatique, désactivée à 0",
"Base DN": "DN racine",
@ -602,6 +586,11 @@
"Your phone is": "Votre téléphone est",
"preferred": "préféré"
},
"mfaAccount": {
"Account Name": "Account Name",
"Issuer": "Issuer",
"Secret Key": "Secret Key"
},
"model": {
"Advanced Editor": "Éditeur avancé",
"Basic Editor": "Éditeur de base",
@ -621,8 +610,6 @@
"Is profile public": "Est-ce que le profil est public ?",
"Is profile public - Tooltip": "Après sa fermeture, seuls les administrateurs et administratrices globales ou les comptes de la même organisation peuvent accéder à la page de profil de l'utilisateur",
"Modify rule": "Règle de modification",
"Navbar items": "Navbar items",
"Navbar items - Tooltip": "Navbar items - Tooltip",
"New Organization": "Nouvelle organisation",
"Optional": "Optionnel",
"Password expire days": "Password expire days",
@ -635,14 +622,10 @@
"Tags - Tooltip": "Collection d'étiquettes disponibles pour les comptes",
"Use Email as username": "Utiliser l'e-mail comme identifiant",
"Use Email as username - Tooltip": "Utiliser l'adresse e-mail comme identifiant pour les comptes lorsque l'identifiant ne fait pas partie des champs d'inscription",
"User types": "User types",
"User types - Tooltip": "User types - Tooltip",
"View rule": "Règle de visibilité",
"Visible": "Visible",
"Website URL": "URL du site web",
"Website URL - Tooltip": "URL du site web l'organisation. Ce champ n'est pas utilisé dans Casdoor",
"Widget items": "Widget items",
"Widget items - Tooltip": "Widget items - Tooltip"
"Website URL - Tooltip": "URL du site web l'organisation. Ce champ n'est pas utilisé dans Casdoor"
},
"payment": {
"Confirm your invoice information": "Confirmez les informations de votre facture",
@ -745,7 +728,6 @@
"paid-user do not have active subscription or pending subscription, please select a plan to buy": "paid-user do not have active subscription or pending subscription, please select a plan to buy"
},
"product": {
"AirWallex": "AirWallex",
"Alipay": "Alipay",
"Buy": "Acheter",
"Buy Product": "Acheter un produit",
@ -775,6 +757,7 @@
"Sold": "Vendu",
"Sold - Tooltip": "Quantité vendue",
"Stripe": "Stripe",
"AirWallex": "AirWallex",
"Tag - Tooltip": "Étiquette de produit",
"Test buy page..": "Page d'achat de test.",
"There is no payment channel for this product.": "Il n'y a aucun canal de paiement pour ce produit.",
@ -834,8 +817,6 @@
"Edit Provider": "Modifier le fournisseur",
"Email content": "Contenu de l'e-mail",
"Email content - Tooltip": "Contenu de l'e-mail",
"Email regex": "Email regex",
"Email regex - Tooltip": "Email regex - Tooltip",
"Email title": "Titre de l'email",
"Email title - Tooltip": "Titre de l'email",
"Endpoint": "Endpoint",
@ -849,8 +830,6 @@
"From name - Tooltip": "Le nom affiché comme expéditeur dans les e-mails envoyés",
"Get phone number": "Get phone number",
"Get phone number - Tooltip": "If sync phone number is enabled, you should enable google people api first and add scope https://www.googleapis.com/auth/user.phonenumbers.read",
"HTTP header": "HTTP header",
"HTTP header - Tooltip": "HTTP header - Tooltip",
"Host": "Hôte",
"Host - Tooltip": "Nom d'hôte",
"IdP": "IdP (Identité Fournisseur)",
@ -865,8 +844,6 @@
"Key text - Tooltip": "Key text - Tooltip",
"Metadata": "Métadonnées",
"Metadata - Tooltip": "Métadonnées SAML",
"Metadata url": "Metadata url",
"Metadata url - Tooltip": "Metadata url - Tooltip",
"Method - Tooltip": "Méthode de connexion, code QR ou connexion silencieuse",
"New Provider": "Nouveau fournisseur",
"Normal": "Normal",
@ -1267,8 +1244,6 @@
"Edit Webhook": "Modifier le Webhook",
"Events": "Événements",
"Events - Tooltip": "Événements",
"Extended user fields": "Extended user fields",
"Extended user fields - Tooltip": "Extended user fields - Tooltip",
"Headers": "En-têtes",
"Headers - Tooltip": "En-têtes HTTP (paires clé-valeur)",
"Is user extended": "Inclure les champs étendus",

View File

@ -17,15 +17,11 @@
"Use same DB - Tooltip": "Use same DB - Tooltip"
},
"application": {
"Add Face ID": "Add Face ID",
"Add Face ID with Image": "Add Face ID with Image",
"Always": "Always",
"Auto signin": "Auto signin",
"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": "URL of the background image used in the login page",
"Background URL Mobile": "Background URL Mobile",
"Background URL Mobile - Tooltip": "Background URL Mobile - Tooltip",
"Big icon": "Big icon",
"Binding providers": "Binding providers",
"CSS style": "CSS style",
@ -65,10 +61,8 @@
"Footer HTML": "Footer HTML",
"Footer HTML - Edit": "Footer HTML - Edit",
"Footer HTML - Tooltip": "Custom the footer of your application",
"Forced redirect origin": "Forced redirect origin",
"Form position": "Form position",
"Form position - Tooltip": "Location of the signup, signin and forget password forms",
"Generate Face ID": "Generate Face ID",
"Grant types": "Grant types",
"Grant types - Tooltip": "Select which grant types are allowed in the OAuth protocol",
"Header HTML": "Header HTML",
@ -169,7 +163,6 @@
},
"currency": {
"AUD": "AUD",
"BRL": "BRL",
"CAD": "CAD",
"CHF": "CHF",
"CNY": "CNY",
@ -196,7 +189,6 @@
"Verify": "Verify"
},
"general": {
"AI Assistant": "AI Assistant",
"API key": "API key",
"API key - Tooltip": "API key - Tooltip",
"Access key": "Access key",
@ -209,6 +201,7 @@
"Adapter - Tooltip": "Table name of the policy store",
"Adapters": "Adapters",
"Add": "Add",
"Add Face Id": "Add Face Id",
"Add custom item": "Add custom item",
"Admin": "Admin",
"Affiliation URL": "Affiliation URL",
@ -238,7 +231,6 @@
"Created time": "Created time",
"Custom": "Custom",
"Dashboard": "Dashboard",
"Data": "Data",
"Default": "Default",
"Default application": "Default application",
"Default application - Tooltip": "Default application for users registered directly from the organization page",
@ -249,7 +241,6 @@
"Delete": "Delete",
"Description": "Description",
"Description - Tooltip": "Detailed description information for reference, Casdoor itself will not use it",
"Detail": "详情",
"Disable": "Disable",
"Display name": "Display name",
"Display name - Tooltip": "A user-friendly, easily readable name displayed publicly in the UI",
@ -267,6 +258,7 @@
"Enabled": "Enabled",
"Enabled successfully": "Enabled successfully",
"Enforcers": "Enforcers",
"FaceIdData": "FaceIdData",
"Failed to add": "Failed to add",
"Failed to connect to server": "Failed to connect to server",
"Failed to delete": "Failed to delete",
@ -279,7 +271,6 @@
"Favicon": "Favicon",
"Favicon - Tooltip": "Favicon icon URL used in all Casdoor pages of the organization",
"First name": "First name",
"Forced redirect origin - Tooltip": "Forced redirect origin - Tooltip",
"Forget URL": "Forget URL",
"Forget URL - Tooltip": "Custom URL for the \"Forget password\" page. If not set, the default Casdoor \"Forget password\" page will be used. When set, the \"Forget password\" link on the login page will redirect to this URL",
"Found some texts still not translated? Please help us translate at": "Found some texts still not translated? Please help us translate at",
@ -353,7 +344,6 @@
"Phone - Tooltip": "Phone number",
"Phone only": "Phone only",
"Phone or Email": "Phone or Email",
"Plain": "Plain",
"Plan": "Plan",
"Plan - Tooltip": "Plan - Tooltip",
"Plans": "Plans",
@ -372,7 +362,6 @@
"QR code is too large": "QR code is too large",
"Real name": "Real name",
"Records": "Records",
"Request": "Request",
"Request URI": "Request URI",
"Resources": "Resources",
"Role": "Role",
@ -423,7 +412,6 @@
"This is a read-only demo site!": "This is a read-only demo site!",
"Timestamp": "Timestamp",
"Tokens": "Tokens",
"Tour": "Tour",
"Transactions": "Transactions",
"Type": "Type",
"Type - Tooltip": "Type - Tooltip",
@ -454,8 +442,7 @@
"Parent group - Tooltip": "Parent group - Tooltip",
"Physical": "Physical",
"Show all": "Show all",
"Virtual": "Virtual",
"You need to delete all subgroups first. You can view the subgroups in the left group tree of the [Organizations] -\u003e [Groups] page": "You need to delete all subgroups first. You can view the subgroups in the left group tree of the [Organizations] -\u003e [Groups] page"
"Virtual": "Virtual"
},
"home": {
"New users past 30 days": "New users past 30 days",
@ -474,16 +461,13 @@
"Quota": "Quota",
"Quota - Tooltip": "Quota - Tooltip",
"Used count": "Used count",
"Used count - Tooltip": "Used count - Tooltip",
"You need to first specify a default application for organization: ": "You need to first specify a default application for organization: "
"Used count - Tooltip": "Used count - Tooltip"
},
"ldap": {
"Admin": "Admin",
"Admin - Tooltip": "CN or ID of the LDAP server administrator",
"Admin Password": "Admin Password",
"Admin Password - Tooltip": "LDAP server administrator password",
"Allow self-signed certificate": "Allow self-signed certificate",
"Allow self-signed certificate - Tooltip": "Allow self-signed certificate - Tooltip",
"Auto Sync": "Auto Sync",
"Auto Sync - Tooltip": "Auto-sync configuration, disabled at 0",
"Base DN": "Base DN",
@ -602,6 +586,11 @@
"Your phone is": "Your phone is",
"preferred": "preferred"
},
"mfaAccount": {
"Account Name": "Account Name",
"Issuer": "Issuer",
"Secret Key": "Secret Key"
},
"model": {
"Advanced Editor": "Advanced Editor",
"Basic Editor": "Basic Editor",
@ -621,8 +610,6 @@
"Is profile public": "Is profile public",
"Is profile public - Tooltip": "After being closed, only global administrators or users in the same organization can access the user's profile page",
"Modify rule": "Modify rule",
"Navbar items": "Navbar items",
"Navbar items - Tooltip": "Navbar items - Tooltip",
"New Organization": "New Organization",
"Optional": "Optional",
"Password expire days": "Password expire days",
@ -635,14 +622,10 @@
"Tags - Tooltip": "Collection of tags available for users to choose from",
"Use Email as username": "Use Email as username",
"Use Email as username - Tooltip": "Use Email as username if the username field is not visible at signup",
"User types": "User types",
"User types - Tooltip": "User types - Tooltip",
"View rule": "View rule",
"Visible": "Visible",
"Website URL": "Website URL",
"Website URL - Tooltip": "The homepage URL of the organization. This field is not used in Casdoor",
"Widget items": "Widget items",
"Widget items - Tooltip": "Widget items - Tooltip"
"Website URL - Tooltip": "The homepage URL of the organization. This field is not used in Casdoor"
},
"payment": {
"Confirm your invoice information": "Confirm your invoice information",
@ -745,7 +728,6 @@
"paid-user do not have active subscription or pending subscription, please select a plan to buy": "paid-user do not have active subscription or pending subscription, please select a plan to buy"
},
"product": {
"AirWallex": "AirWallex",
"Alipay": "Alipay",
"Buy": "Buy",
"Buy Product": "Buy Product",
@ -775,6 +757,7 @@
"Sold": "Sold",
"Sold - Tooltip": "Quantity sold",
"Stripe": "Stripe",
"AirWallex": "AirWallex",
"Tag - Tooltip": "Tag of product",
"Test buy page..": "Test buy page..",
"There is no payment channel for this product.": "There is no payment channel for this product.",
@ -834,8 +817,6 @@
"Edit Provider": "Edit Provider",
"Email content": "Email content",
"Email content - Tooltip": "Content of the Email",
"Email regex": "Email regex",
"Email regex - Tooltip": "Email regex - Tooltip",
"Email title": "Email title",
"Email title - Tooltip": "Title of the email",
"Endpoint": "Endpoint",
@ -849,8 +830,6 @@
"From name - Tooltip": "Name of \"From\"",
"Get phone number": "Get phone number",
"Get phone number - Tooltip": "If sync phone number is enabled, you should enable google people api first and add scope https://www.googleapis.com/auth/user.phonenumbers.read",
"HTTP header": "HTTP header",
"HTTP header - Tooltip": "HTTP header - Tooltip",
"Host": "Host",
"Host - Tooltip": "Name of host",
"IdP": "IdP",
@ -865,8 +844,6 @@
"Key text - Tooltip": "Key text - Tooltip",
"Metadata": "Metadata",
"Metadata - Tooltip": "SAML metadata",
"Metadata url": "Metadata url",
"Metadata url - Tooltip": "Metadata url - Tooltip",
"Method - Tooltip": "Login method, QR code or silent login",
"New Provider": "New Provider",
"Normal": "Normal",
@ -1267,8 +1244,6 @@
"Edit Webhook": "Edit Webhook",
"Events": "Events",
"Events - Tooltip": "Events",
"Extended user fields": "Extended user fields",
"Extended user fields - Tooltip": "Extended user fields - Tooltip",
"Headers": "Headers",
"Headers - Tooltip": "HTTP headers (key-value pairs)",
"Is user extended": "Is user extended",

Some files were not shown because too many files have changed in this diff Show More