mirror of
https://github.com/casdoor/casdoor.git
synced 2025-07-09 01:13:41 +08:00
Compare commits
74 Commits
revert-361
...
v1.920.0
Author | SHA1 | Date | |
---|---|---|---|
8b4637aa3a | |||
87506b84e3 | |||
fed9332246 | |||
33afc52a0b | |||
9035ca365a | |||
b97ae72179 | |||
9190db1099 | |||
1173f75794 | |||
086859d1ce | |||
9afaf5d695 | |||
521f90a603 | |||
4260efcfd0 | |||
d772b0b7a8 | |||
702b390da1 | |||
b15b3b9335 | |||
f8f864c5b9 | |||
90e790f83c | |||
58413246f3 | |||
8f307dd907 | |||
fe42b5e0ba | |||
383bf44391 | |||
36f5de3203 | |||
eae69c41d7 | |||
91057f54f3 | |||
daa7b79915 | |||
d3a5539dae | |||
7d1c614452 | |||
e2eafa909b | |||
56bcef0592 | |||
0860cbf343 | |||
2f4180b1b6 | |||
e3d5619b25 | |||
019fd87b92 | |||
5c41c6c4a5 | |||
b7fafcc62b | |||
493ceddcd9 | |||
fc618b9bd5 | |||
a00900e405 | |||
77ef5828dd | |||
c11f013e04 | |||
b3bafe8402 | |||
f04a431d85 | |||
952538916d | |||
18bb445e71 | |||
cca88e2cb0 | |||
86c10fe0ab | |||
c1b3bf0f45 | |||
62bda61af5 | |||
b6f943e326 | |||
2cc5e82d91 | |||
e55cd94298 | |||
08f7a05e61 | |||
4bee21f4a3 | |||
5417a90223 | |||
131820e34e | |||
2fcbf7cf6c | |||
14ade8b7e4 | |||
a11fe59704 | |||
af55d0547f | |||
81102f8298 | |||
141372cb86 | |||
15a037ca74 | |||
73c680d56f | |||
aafc16e4f4 | |||
7be026dd1f | |||
3e7938e5f6 | |||
30789138e2 | |||
9610ce5b8c | |||
a39a311d2f | |||
08e41ab762 | |||
85ca318e2f | |||
9032865e60 | |||
5692522ee0 | |||
cb1882e589 |
@ -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 && yarn run build
|
||||
RUN yarn install --frozen-lockfile --network-timeout 1000000 && NODE_OPTIONS="--max-old-space-size=4096" yarn run build
|
||||
|
||||
|
||||
FROM --platform=$BUILDPLATFORM golang:1.20.12 AS BACK
|
||||
FROM --platform=$BUILDPLATFORM golang:1.21.13 AS BACK
|
||||
WORKDIR /go/src/casdoor
|
||||
COPY . .
|
||||
RUN ./build.sh
|
||||
|
@ -47,6 +47,7 @@ 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, *, *
|
||||
|
@ -31,7 +31,7 @@ radiusServerPort = 1812
|
||||
radiusDefaultOrganization = "built-in"
|
||||
radiusSecret = "secret"
|
||||
quota = {"organization": -1, "user": -1, "application": -1, "provider": -1}
|
||||
logConfig = {"filename": "logs/casdoor.log", "maxdays":99999, "perm":"0770"}
|
||||
logConfig = {"adapter":"file", "filename": "logs/casdoor.log", "maxdays":99999, "perm":"0770"}
|
||||
initDataNewOnly = false
|
||||
initDataFile = "./init_data.json"
|
||||
frontendBaseDir = "../cc_0"
|
@ -115,7 +115,7 @@ func TestGetConfigLogs(t *testing.T) {
|
||||
description string
|
||||
expected string
|
||||
}{
|
||||
{"Default log config", `{"filename": "logs/casdoor.log", "maxdays":99999, "perm":"0770"}`},
|
||||
{"Default log config", `{"adapter":"file", "filename": "logs/casdoor.log", "maxdays":99999, "perm":"0770"}`},
|
||||
}
|
||||
|
||||
err := beego.LoadAppConfig("ini", "app.conf")
|
||||
|
@ -32,6 +32,7 @@ const (
|
||||
ResponseTypeIdToken = "id_token"
|
||||
ResponseTypeSaml = "saml"
|
||||
ResponseTypeCas = "cas"
|
||||
ResponseTypeDevice = "device"
|
||||
)
|
||||
|
||||
type Response struct {
|
||||
@ -139,6 +140,8 @@ 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())
|
||||
@ -150,6 +153,8 @@ func (c *ApiController) Signup() {
|
||||
c.ResponseError(checkResult.Msg)
|
||||
return
|
||||
}
|
||||
|
||||
userEmailVerified = true
|
||||
}
|
||||
|
||||
var checkPhone string
|
||||
@ -228,6 +233,7 @@ func (c *ApiController) Signup() {
|
||||
Karma: 0,
|
||||
Invitation: invitationName,
|
||||
InvitationCode: authForm.InvitationCode,
|
||||
EmailVerified: userEmailVerified,
|
||||
}
|
||||
|
||||
if len(organization.Tags) > 0 {
|
||||
@ -249,6 +255,10 @@ 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())
|
||||
|
@ -25,10 +25,12 @@ 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"
|
||||
@ -145,7 +147,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, responseType, redirectUri, scope, state, nonce, codeChallenge, c.Ctx.Request.Host, c.GetAcceptLanguage())
|
||||
code, err := object.GetOAuthCode(userId, clientId, form.Provider, responseType, redirectUri, scope, state, nonce, codeChallenge, c.Ctx.Request.Host, c.GetAcceptLanguage())
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error(), nil)
|
||||
return
|
||||
@ -168,6 +170,32 @@ 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 {
|
||||
@ -241,6 +269,7 @@ 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
|
||||
@ -267,6 +296,19 @@ 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)
|
||||
@ -402,11 +444,27 @@ func (c *ApiController) Login() {
|
||||
return
|
||||
}
|
||||
|
||||
if err := object.CheckFaceId(user, authForm.FaceId, c.GetAcceptLanguage()); err != nil {
|
||||
c.ResponseError(err.Error(), nil)
|
||||
return
|
||||
faceIdProvider, err := object.GetFaceIdProviderByApplication(util.GetId(application.Owner, application.Name), "false", c.GetAcceptLanguage())
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
}
|
||||
|
||||
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)
|
||||
@ -466,6 +524,14 @@ 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
|
||||
@ -598,6 +664,9 @@ 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() {
|
||||
@ -986,6 +1055,18 @@ 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()
|
||||
}
|
||||
@ -1175,3 +1256,75 @@ 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()
|
||||
}
|
||||
|
@ -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,7 +269,11 @@ func (c *ApiController) SyncLdapUsers() {
|
||||
return
|
||||
}
|
||||
|
||||
exist, failed, _ := object.SyncLdapUsers(owner, users, ldapId)
|
||||
exist, failed, err := object.SyncLdapUsers(owner, users, ldapId)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.ResponseOk(&LdapSyncResp{
|
||||
Exist: exist,
|
||||
|
@ -16,6 +16,7 @@ package controllers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"github.com/beego/beego/utils/pagination"
|
||||
"github.com/casdoor/casdoor/object"
|
||||
@ -170,12 +171,13 @@ 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 {
|
||||
if len(c.Ctx.Input.RequestBody) != 0 && grantType != "urn:ietf:params:oauth:grant-type:device_code" {
|
||||
// If clientId is empty, try to read data from RequestBody
|
||||
var tokenRequest TokenRequest
|
||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &tokenRequest)
|
||||
@ -219,6 +221,46 @@ 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 {
|
||||
@ -321,6 +363,11 @@ 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 != "" {
|
||||
@ -329,7 +376,12 @@ func (c *ApiController) IntrospectToken() {
|
||||
c.ResponseTokenError(err.Error())
|
||||
return
|
||||
}
|
||||
if token == nil {
|
||||
if token == nil || token.ExpiresIn <= 0 {
|
||||
respondWithInactiveToken()
|
||||
return
|
||||
}
|
||||
|
||||
if token.ExpiresIn <= 0 {
|
||||
c.Data["json"] = &object.IntrospectionResponse{Active: false}
|
||||
c.ServeJSON()
|
||||
return
|
||||
@ -340,12 +392,11 @@ func (c *ApiController) IntrospectToken() {
|
||||
|
||||
if application.TokenFormat == "JWT-Standard" {
|
||||
jwtToken, err := object.ParseStandardJwtTokenByApplication(tokenValue, application)
|
||||
if err != nil || jwtToken.Valid() != nil {
|
||||
if err != 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
|
||||
c.Data["json"] = &object.IntrospectionResponse{Active: false}
|
||||
c.ServeJSON()
|
||||
respondWithInactiveToken()
|
||||
return
|
||||
}
|
||||
|
||||
@ -365,28 +416,34 @@ func (c *ApiController) IntrospectToken() {
|
||||
}
|
||||
} else {
|
||||
jwtToken, err := object.ParseJwtTokenByApplication(tokenValue, application)
|
||||
if err != nil || jwtToken.Valid() != nil {
|
||||
if err != 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
|
||||
c.Data["json"] = &object.IntrospectionResponse{Active: false}
|
||||
c.ServeJSON()
|
||||
respondWithInactiveToken()
|
||||
return
|
||||
}
|
||||
|
||||
introspectionResponse = object.IntrospectionResponse{
|
||||
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,
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@ -396,13 +453,15 @@ func (c *ApiController) IntrospectToken() {
|
||||
c.ResponseTokenError(err.Error())
|
||||
return
|
||||
}
|
||||
if token == nil {
|
||||
c.Data["json"] = &object.IntrospectionResponse{Active: false}
|
||||
c.ServeJSON()
|
||||
if token == nil || token.ExpiresIn <= 0 {
|
||||
respondWithInactiveToken()
|
||||
return
|
||||
}
|
||||
}
|
||||
introspectionResponse.TokenType = token.TokenType
|
||||
|
||||
if token != nil {
|
||||
introspectionResponse.TokenType = token.TokenType
|
||||
}
|
||||
|
||||
c.Data["json"] = introspectionResponse
|
||||
c.ServeJSON()
|
||||
|
@ -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,7 +602,11 @@ func (c *ApiController) CheckUserPassword() {
|
||||
return
|
||||
}
|
||||
|
||||
_, err = object.CheckUserPassword(user.Owner, user.Name, user.Password, c.GetAcceptLanguage())
|
||||
/*
|
||||
* 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 != "")
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
} else {
|
||||
|
@ -242,7 +242,7 @@ func (c *ApiController) SendVerificationCode() {
|
||||
} else if vform.Method == ResetVerification {
|
||||
user = c.getCurrentUser()
|
||||
} else if vform.Method == MfaAuthVerification {
|
||||
mfaProps := user.GetPreferredMfaProps(false)
|
||||
mfaProps := user.GetMfaProps(object.EmailType, false)
|
||||
if user != nil && util.GetMaskedEmail(mfaProps.Secret) == vform.Dest {
|
||||
vform.Dest = mfaProps.Secret
|
||||
}
|
||||
@ -258,7 +258,7 @@ func (c *ApiController) SendVerificationCode() {
|
||||
return
|
||||
}
|
||||
|
||||
sendResp = object.SendVerificationCodeToEmail(organization, user, provider, clientIp, vform.Dest, c.GetAcceptLanguage())
|
||||
sendResp = object.SendVerificationCodeToEmail(organization, user, provider, clientIp, vform.Dest)
|
||||
case object.VerifyTypePhone:
|
||||
if vform.Method == LoginVerification || vform.Method == ForgetVerification {
|
||||
if user != nil && util.GetMaskedPhone(user.Phone) == vform.Dest {
|
||||
@ -281,7 +281,7 @@ func (c *ApiController) SendVerificationCode() {
|
||||
}
|
||||
}
|
||||
} else if vform.Method == MfaAuthVerification {
|
||||
mfaProps := user.GetPreferredMfaProps(false)
|
||||
mfaProps := user.GetMfaProps(object.SmsType, false)
|
||||
if user != nil && util.GetMaskedPhone(mfaProps.Secret) == vform.Dest {
|
||||
vform.Dest = mfaProps.Secret
|
||||
}
|
||||
@ -304,7 +304,7 @@ func (c *ApiController) SendVerificationCode() {
|
||||
c.ResponseError(fmt.Sprintf(c.T("verification:Phone number is invalid in your region %s"), vform.CountryCode))
|
||||
return
|
||||
} else {
|
||||
sendResp = object.SendVerificationCodeToPhone(organization, user, provider, clientIp, phone, c.GetAcceptLanguage())
|
||||
sendResp = object.SendVerificationCodeToPhone(organization, user, provider, clientIp, phone)
|
||||
}
|
||||
}
|
||||
|
||||
@ -436,7 +436,8 @@ func (c *ApiController) ResetEmailOrPhone() {
|
||||
switch destType {
|
||||
case object.VerifyTypeEmail:
|
||||
user.Email = dest
|
||||
_, err = object.SetUserField(user, "email", user.Email)
|
||||
user.EmailVerified = true
|
||||
_, err = object.UpdateUser(user.GetId(), user, []string{"email", "email_verified"}, false)
|
||||
case object.VerifyTypePhone:
|
||||
user.Phone = dest
|
||||
_, err = object.SetUserField(user, "phone", user.Phone)
|
||||
|
@ -16,7 +16,7 @@ package controllers
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"encoding/base64"
|
||||
"io"
|
||||
|
||||
"github.com/casdoor/casdoor/form"
|
||||
@ -118,24 +118,7 @@ func (c *ApiController) WebAuthnSigninBegin() {
|
||||
return
|
||||
}
|
||||
|
||||
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)
|
||||
options, sessionData, err := webauthnObj.BeginDiscoverableLogin()
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
@ -168,20 +151,23 @@ func (c *ApiController) WebAuthnSigninFinish() {
|
||||
return
|
||||
}
|
||||
c.Ctx.Request.Body = io.NopCloser(bytes.NewBuffer(c.Ctx.Input.RequestBody))
|
||||
userId := string(sessionData.UserID)
|
||||
user, err := object.GetUser(userId)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
|
||||
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.FinishLogin(user, sessionData, c.Ctx.Request)
|
||||
_, err = webauthnObj.FinishDiscoverableLogin(handler, sessionData, c.Ctx.Request)
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
c.SetSessionUsername(userId)
|
||||
util.LogInfo(c.Ctx, "API: [%s] signed in", userId)
|
||||
c.SetSessionUsername(user.GetId())
|
||||
util.LogInfo(c.Ctx, "API: [%s] signed in", user.GetId())
|
||||
|
||||
var application *object.Application
|
||||
|
||||
|
@ -34,6 +34,8 @@ func GetCredManager(passwordType string) CredManager {
|
||||
return NewPbkdf2SaltCredManager()
|
||||
} else if passwordType == "argon2id" {
|
||||
return NewArgon2idCredManager()
|
||||
} else if passwordType == "pbkdf2-django" {
|
||||
return NewPbkdf2DjangoCredManager()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
71
cred/pbkdf2_django.go
Normal file
71
cred/pbkdf2_django.go
Normal file
@ -0,0 +1,71 @@
|
||||
// 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
|
||||
}
|
@ -15,6 +15,8 @@
|
||||
package email
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
@ -24,14 +26,24 @@ import (
|
||||
)
|
||||
|
||||
type HttpEmailProvider struct {
|
||||
endpoint string
|
||||
method string
|
||||
endpoint string
|
||||
method string
|
||||
httpHeaders map[string]string
|
||||
bodyMapping map[string]string
|
||||
contentType string
|
||||
}
|
||||
|
||||
func NewHttpEmailProvider(endpoint string, method string) *HttpEmailProvider {
|
||||
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"
|
||||
}
|
||||
|
||||
client := &HttpEmailProvider{
|
||||
endpoint: endpoint,
|
||||
method: method,
|
||||
endpoint: endpoint,
|
||||
method: method,
|
||||
httpHeaders: httpHeaders,
|
||||
bodyMapping: bodyMapping,
|
||||
contentType: contentType,
|
||||
}
|
||||
return client
|
||||
}
|
||||
@ -39,18 +51,52 @@ func NewHttpEmailProvider(endpoint string, method string) *HttpEmailProvider {
|
||||
func (c *HttpEmailProvider) Send(fromAddress string, fromName string, toAddress string, subject string, content string) error {
|
||||
var req *http.Request
|
||||
var err error
|
||||
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()))
|
||||
|
||||
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 err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
req.Header.Set("Content-Type", c.contentType)
|
||||
} else if c.method == "GET" {
|
||||
req, err = http.NewRequest(c.method, c.endpoint, nil)
|
||||
if err != nil {
|
||||
@ -58,15 +104,19 @@ func (c *HttpEmailProvider) Send(fromAddress string, fromName string, toAddress
|
||||
}
|
||||
|
||||
q := req.URL.Query()
|
||||
q.Add("fromName", fromName)
|
||||
q.Add("toAddress", toAddress)
|
||||
q.Add("subject", subject)
|
||||
q.Add("content", content)
|
||||
q.Add(fromNameField, fromName)
|
||||
q.Add(toAddressField, toAddress)
|
||||
q.Add(subjectField, subject)
|
||||
q.Add(contentField, 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 {
|
||||
|
@ -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) EmailProvider {
|
||||
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 {
|
||||
if typ == "Azure ACS" {
|
||||
return NewAzureACSEmailProvider(clientSecret, host)
|
||||
} else if typ == "Custom HTTP Email" {
|
||||
return NewHttpEmailProvider(endpoint, method)
|
||||
return NewHttpEmailProvider(endpoint, method, httpHeaders, bodyMapping, contentType)
|
||||
} else if typ == "SendGrid" {
|
||||
return NewSendgridEmailProvider(clientSecret, host, endpoint)
|
||||
} else {
|
||||
|
81
faceId/aliyun.go
Normal file
81
faceId/aliyun.go
Normal file
@ -0,0 +1,81 @@
|
||||
// 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
|
||||
}
|
23
faceId/provider.go
Normal file
23
faceId/provider.go
Normal file
@ -0,0 +1,23 @@
|
||||
// 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)
|
||||
}
|
@ -34,6 +34,7 @@ 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"`
|
||||
|
||||
@ -67,7 +68,9 @@ type AuthForm struct {
|
||||
Plan string `json:"plan"`
|
||||
Pricing string `json:"pricing"`
|
||||
|
||||
FaceId []float64 `json:"faceId"`
|
||||
FaceId []float64 `json:"faceId"`
|
||||
FaceIdImage []string `json:"faceIdImage"`
|
||||
UserCode string `json:"userCode"`
|
||||
}
|
||||
|
||||
func GetAuthFormFieldValue(form *AuthForm, fieldName string) (bool, string) {
|
||||
|
35
go.mod
35
go.mod
@ -1,10 +1,14 @@
|
||||
module github.com/casdoor/casdoor
|
||||
|
||||
go 1.18
|
||||
go 1.21
|
||||
|
||||
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
|
||||
@ -12,7 +16,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.0
|
||||
github.com/casdoor/notify v1.0.1
|
||||
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
|
||||
@ -27,8 +31,8 @@ require (
|
||||
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.6.0
|
||||
github.com/golang-jwt/jwt/v4 v4.5.0
|
||||
github.com/go-webauthn/webauthn v0.10.2
|
||||
github.com/golang-jwt/jwt/v5 v5.2.2
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/json-iterator/go v1.1.12
|
||||
github.com/lestrrat-go/jwx v1.2.29
|
||||
@ -82,10 +86,22 @@ require (
|
||||
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.6.1 // indirect
|
||||
github.com/atc0005/go-teams-notify/v2 v2.13.0 // 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
|
||||
@ -95,6 +111,7 @@ 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.3 // indirect
|
||||
github.com/cschomburg/go-pushbullet v0.0.0-20171206132031-67759df45fbb // indirect
|
||||
github.com/cyphar/filepath-securejoin v0.2.4 // indirect
|
||||
@ -107,14 +124,15 @@ 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.4.0 // indirect
|
||||
github.com/fxamacker/cbor/v2 v2.6.0 // indirect
|
||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // 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/revoke v0.1.6 // indirect
|
||||
github.com/go-webauthn/x v0.1.9 // 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
|
||||
@ -123,7 +141,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.3.3 // indirect
|
||||
github.com/google/go-tpm v0.9.0 // 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
|
||||
@ -183,6 +201,7 @@ 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
|
||||
|
210
go.sum
210
go.sum
@ -101,25 +101,95 @@ 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/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/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/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=
|
||||
@ -130,6 +200,7 @@ 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=
|
||||
@ -167,8 +238,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.0 h1:oldsaaQFPrlufm/OA314z8DwFVE1Tc9Gt1z4ptRHhXw=
|
||||
github.com/casdoor/notify v1.0.0/go.mod h1:wNHQu0tiDROMBIvz0j3Om3Lhd5yZ+AIfnFb8MYb8OLQ=
|
||||
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/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=
|
||||
@ -191,6 +262,9 @@ 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.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs=
|
||||
github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
|
||||
@ -198,21 +272,13 @@ github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58/go.mod h1:EOBUe0h
|
||||
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=
|
||||
@ -237,8 +303,6 @@ 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=
|
||||
@ -258,6 +322,7 @@ github.com/elazarl/go-bindata-assetfs v1.0.0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo
|
||||
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 v0.0.0-20230808193330-2592e75ae04a h1:mATvB/9r/3gvcejNsXKSkQ6lcIaNec2nyfOdlTBR2lU=
|
||||
github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM=
|
||||
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=
|
||||
@ -284,11 +349,12 @@ 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.4.0 h1:ri0ArlOR+5XunOP8CRUowT0pSJOwhW098ZCUyskZD88=
|
||||
github.com/fxamacker/cbor/v2 v2.4.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo=
|
||||
github.com/fxamacker/cbor/v2 v2.6.0 h1:sU6J2usfADwWlYDAFhZBQ6TnLFBHxgesMrQfQgk1tWA=
|
||||
github.com/fxamacker/cbor/v2 v2.6.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/glendc/gopher-json v0.0.0-20170414221815-dc4743023d0c/go.mod h1:Gja1A+xZ9BoviGJNA2E9vFkPjjsl+CoJxSXiQM1UXtw=
|
||||
github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY=
|
||||
github.com/gliderlabs/ssh v0.3.5/go.mod h1:8XB4KraRrX39qHhT6yxPsHedjA08I/uBVwj4xC+/+z4=
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.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=
|
||||
@ -296,6 +362,7 @@ github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmS
|
||||
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.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=
|
||||
@ -336,16 +403,15 @@ 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/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-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-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=
|
||||
@ -353,12 +419,13 @@ 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=
|
||||
@ -418,17 +485,14 @@ 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.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/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/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=
|
||||
@ -455,23 +519,22 @@ 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=
|
||||
@ -497,7 +560,6 @@ 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=
|
||||
@ -505,9 +567,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=
|
||||
@ -517,6 +579,7 @@ 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=
|
||||
@ -525,10 +588,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=
|
||||
@ -547,7 +610,6 @@ 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=
|
||||
@ -564,6 +626,7 @@ 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=
|
||||
@ -599,7 +662,6 @@ 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=
|
||||
@ -669,7 +731,6 @@ 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=
|
||||
@ -683,6 +744,7 @@ github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1y
|
||||
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.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI=
|
||||
github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M=
|
||||
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=
|
||||
@ -691,7 +753,6 @@ 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=
|
||||
@ -721,7 +782,6 @@ 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=
|
||||
@ -735,8 +795,6 @@ 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=
|
||||
@ -744,14 +802,12 @@ 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=
|
||||
@ -764,12 +820,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=
|
||||
@ -778,10 +834,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=
|
||||
@ -822,26 +878,19 @@ github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDq
|
||||
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=
|
||||
@ -884,11 +933,13 @@ 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=
|
||||
@ -899,8 +950,6 @@ 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=
|
||||
@ -914,8 +963,6 @@ 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=
|
||||
@ -924,6 +971,7 @@ 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=
|
||||
@ -932,7 +980,6 @@ 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=
|
||||
@ -949,7 +996,6 @@ 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=
|
||||
@ -962,14 +1008,12 @@ 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=
|
||||
@ -977,10 +1021,13 @@ 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=
|
||||
@ -997,11 +1044,15 @@ golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0
|
||||
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
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.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I=
|
||||
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=
|
||||
@ -1056,14 +1107,12 @@ golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73r
|
||||
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=
|
||||
@ -1087,6 +1136,7 @@ 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=
|
||||
@ -1102,12 +1152,18 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug
|
||||
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=
|
||||
@ -1142,9 +1198,7 @@ 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=
|
||||
@ -1180,6 +1234,7 @@ 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=
|
||||
@ -1199,7 +1254,6 @@ 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=
|
||||
@ -1217,11 +1271,15 @@ 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=
|
||||
@ -1233,11 +1291,15 @@ 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=
|
||||
@ -1253,10 +1315,12 @@ 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=
|
||||
@ -1266,7 +1330,6 @@ 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=
|
||||
@ -1307,6 +1370,7 @@ 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=
|
||||
@ -1402,7 +1466,6 @@ 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=
|
||||
@ -1448,6 +1511,7 @@ 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=
|
||||
@ -1456,14 +1520,12 @@ 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=
|
||||
@ -1538,6 +1600,7 @@ 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=
|
||||
@ -1545,6 +1608,7 @@ 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=
|
||||
|
@ -1,9 +1,9 @@
|
||||
{
|
||||
"account": {
|
||||
"Failed to add user": "Gagal menambahkan pengguna",
|
||||
"Get init score failed, error: %w": "Gagal mendapatkan nilai init, kesalahan: %w",
|
||||
"Get init score failed, error: %w": "Gagal mendapatkan nilai inisiasi, kesalahan: %w",
|
||||
"Please sign out first": "Silakan keluar terlebih dahulu",
|
||||
"The application does not allow to sign up new account": "Aplikasi tidak memperbolehkan untuk mendaftar akun baru"
|
||||
"The application does not allow to sign up new account": "Aplikasi tidak memperbolehkan pendaftaran 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 provider: %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 penyedia: %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 kata sandi tidak diaktifkan untuk aplikasi tersebut",
|
||||
"The login method: login with password is not enabled for the application": "Metode login: login dengan 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 kata sandi atau pemberi), formulir = %s",
|
||||
"Unknown authentication type (not password or provider), form = %s": "Jenis otentikasi tidak diketahui (bukan sandi atau penyedia), 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": "Face data does not exist, cannot log in",
|
||||
"Face data mismatch": "Face data mismatch",
|
||||
"Face data does not exist, cannot log in": "Data wajah tidak ada, tidak bisa login",
|
||||
"Face data mismatch": "Ketidakcocokan data wajah",
|
||||
"FirstName cannot be blank": "Nama depan tidak boleh kosong",
|
||||
"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",
|
||||
"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",
|
||||
"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": "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",
|
||||
"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",
|
||||
"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": "The user: %s doesn't exist in LDAP server",
|
||||
"The user: %s doesn't exist in LDAP server": "Pengguna: %s tidak ada di server LDAP",
|
||||
"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": "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\\\"",
|
||||
"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\\\"",
|
||||
"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 kata sandi atau kode yang salah terlalu banyak kali, mohon tunggu selama %d menit dan coba lagi",
|
||||
"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",
|
||||
"Your region is not allow to signup by phone": "Wilayah Anda tidak diizinkan untuk mendaftar melalui telepon",
|
||||
"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",
|
||||
"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",
|
||||
"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": "The organization: %s should have one application at least",
|
||||
"The organization: %s should have one application at least": "Organisasi: %s setidaknya harus memiliki satu aplikasi",
|
||||
"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": "this operation is not allowed in demo mode",
|
||||
"this operation requires administrator to perform": "this operation requires administrator to perform"
|
||||
"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"
|
||||
},
|
||||
"ldap": {
|
||||
"Ldap server exist": "Server ldap ada"
|
||||
},
|
||||
"link": {
|
||||
"Please link first": "Tolong tautkan terlebih dahulu",
|
||||
"Please link first": "Silahkan 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": "Pemberi layanan ini tidak dapat dipisahkan",
|
||||
"This provider can't be unlinked": "Penyedia 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": "The permission: \\\"%s\\\" doesn't exist"
|
||||
"The permission: \\\"%s\\\" doesn't exist": "Izin: \\\"%s\\\" tidak ada"
|
||||
},
|
||||
"provider": {
|
||||
"Invalid application id": "ID aplikasi tidak valid",
|
||||
"the provider: %s does not exist": "provider: %s tidak ada"
|
||||
"the provider: %s does not exist": "penyedia: %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": "Invalid client_id = ID klien tidak valid",
|
||||
"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.": "Kata sandi baru tidak boleh mengandung spasi kosong."
|
||||
"New password cannot contain blank space.": "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!": "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!",
|
||||
"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!",
|
||||
"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": "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",
|
||||
"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",
|
||||
"the user does not exist, please sign up first": "Pengguna tidak ada, silakan daftar terlebih dahulu"
|
||||
},
|
||||
"webauthn": {
|
||||
|
@ -136,12 +136,12 @@ func (idp *DingTalkIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, erro
|
||||
dtUserInfo := &DingTalkUserResponse{}
|
||||
accessToken := token.AccessToken
|
||||
|
||||
reqest, err := http.NewRequest("GET", idp.Config.Endpoint.AuthURL, nil)
|
||||
request, err := http.NewRequest("GET", idp.Config.Endpoint.AuthURL, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
reqest.Header.Add("x-acs-dingtalk-access-token", accessToken)
|
||||
resp, err := idp.Client.Do(reqest)
|
||||
request.Header.Add("x-acs-dingtalk-access-token", accessToken)
|
||||
resp, err := idp.Client.Do(request)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
13
idp/goth.go
13
idp/goth.go
@ -278,9 +278,16 @@ func NewGothIdProvider(providerType string, clientId string, clientSecret string
|
||||
Session: &naver.Session{},
|
||||
}
|
||||
case "Nextcloud":
|
||||
idp = GothIdProvider{
|
||||
Provider: nextcloud.New(clientId, clientSecret, redirectUrl),
|
||||
Session: &nextcloud.Session{},
|
||||
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{},
|
||||
}
|
||||
}
|
||||
case "OneDrive":
|
||||
idp = GothIdProvider{
|
||||
|
@ -44,6 +44,7 @@ type ProviderInfo struct {
|
||||
AppId string
|
||||
HostUrl string
|
||||
RedirectUrl string
|
||||
DisableSsl bool
|
||||
|
||||
TokenURL string
|
||||
AuthURL string
|
||||
@ -79,9 +80,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), nil
|
||||
return NewWeComInternalIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl, idpInfo.DisableSsl), nil
|
||||
} else if idpInfo.SubType == "Third-party" {
|
||||
return NewWeComIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl), nil
|
||||
return NewWeComIdProvider(idpInfo.ClientId, idpInfo.ClientSecret, redirectUrl, idpInfo.DisableSsl), nil
|
||||
} else {
|
||||
return nil, fmt.Errorf("WeCom provider subType: %s is not supported", idpInfo.SubType)
|
||||
}
|
||||
|
@ -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))
|
||||
requeset, err := http.NewRequest("POST", qrCodeUrl, bodyData)
|
||||
request, err := http.NewRequest("POST", qrCodeUrl, bodyData)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
resp, err := client.Do(requeset)
|
||||
resp, err := client.Do(request)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
@ -29,13 +29,16 @@ import (
|
||||
type WeComInternalIdProvider struct {
|
||||
Client *http.Client
|
||||
Config *oauth2.Config
|
||||
|
||||
UseIdAsName bool
|
||||
}
|
||||
|
||||
func NewWeComInternalIdProvider(clientId string, clientSecret string, redirectUrl string) *WeComInternalIdProvider {
|
||||
func NewWeComInternalIdProvider(clientId string, clientSecret string, redirectUrl string, useIdAsName bool) *WeComInternalIdProvider {
|
||||
idp := &WeComInternalIdProvider{}
|
||||
|
||||
config := idp.getConfig(clientId, clientSecret, redirectUrl)
|
||||
idp.Config = config
|
||||
idp.UseIdAsName = useIdAsName
|
||||
|
||||
return idp
|
||||
}
|
||||
@ -169,5 +172,9 @@ func (idp *WeComInternalIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo,
|
||||
userInfo.Id = userInfo.Username
|
||||
}
|
||||
|
||||
if idp.UseIdAsName {
|
||||
userInfo.Username = userInfo.Id
|
||||
}
|
||||
|
||||
return &userInfo, nil
|
||||
}
|
||||
|
@ -28,13 +28,16 @@ import (
|
||||
type WeComIdProvider struct {
|
||||
Client *http.Client
|
||||
Config *oauth2.Config
|
||||
|
||||
UseIdAsName bool
|
||||
}
|
||||
|
||||
func NewWeComIdProvider(clientId string, clientSecret string, redirectUrl string) *WeComIdProvider {
|
||||
func NewWeComIdProvider(clientId string, clientSecret string, redirectUrl string, useIdAsName bool) *WeComIdProvider {
|
||||
idp := &WeComIdProvider{}
|
||||
|
||||
config := idp.getConfig(clientId, clientSecret, redirectUrl)
|
||||
idp.Config = config
|
||||
idp.UseIdAsName = useIdAsName
|
||||
|
||||
return idp
|
||||
}
|
||||
@ -183,6 +186,10 @@ 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
19
main.go
@ -15,6 +15,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/beego/beego"
|
||||
@ -77,10 +78,26 @@ func main() {
|
||||
beego.BConfig.WebConfig.Session.SessionGCMaxLifetime = 3600 * 24 * 30
|
||||
// beego.BConfig.WebConfig.Session.SessionCookieSameSite = http.SameSiteNoneMode
|
||||
|
||||
err := logs.SetLogger(logs.AdapterFile, conf.GetConfigString("logConfig"))
|
||||
var logAdapter string
|
||||
logConfigMap := make(map[string]interface{})
|
||||
err := json.Unmarshal([]byte(conf.GetConfigString("logConfig")), &logConfigMap)
|
||||
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)
|
||||
|
@ -191,12 +191,7 @@ func (adapter *Adapter) InitAdapter() error {
|
||||
}
|
||||
}
|
||||
|
||||
var tableName string
|
||||
if driverName == "mssql" {
|
||||
tableName = fmt.Sprintf("[%s]", adapter.Table)
|
||||
} else {
|
||||
tableName = adapter.Table
|
||||
}
|
||||
tableName := adapter.Table
|
||||
|
||||
adapter.Adapter, err = xormadapter.NewAdapterByEngineWithTableName(engine, tableName, "")
|
||||
if err != nil {
|
||||
|
@ -71,6 +71,7 @@ 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"`
|
||||
@ -84,7 +85,7 @@ type Application struct {
|
||||
EnableWebAuthn bool `json:"enableWebAuthn"`
|
||||
EnableLinkWithEmail bool `json:"enableLinkWithEmail"`
|
||||
OrgChoiceMode string `json:"orgChoiceMode"`
|
||||
SamlReplyUrl string `xorm:"varchar(100)" json:"samlReplyUrl"`
|
||||
SamlReplyUrl string `xorm:"varchar(500)" json:"samlReplyUrl"`
|
||||
Providers []*ProviderItem `xorm:"mediumtext" json:"providers"`
|
||||
SigninMethods []*SigninMethod `xorm:"varchar(2000)" json:"signinMethods"`
|
||||
SignupItems []*SignupItem `xorm:"varchar(3000)" json:"signupItems"`
|
||||
@ -97,29 +98,31 @@ 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"`
|
||||
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"`
|
||||
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"`
|
||||
|
||||
FailedSigninLimit int `json:"failedSigninLimit"`
|
||||
FailedSigninFrozenTime int `json:"failedSigninFrozenTime"`
|
||||
@ -539,7 +542,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") {
|
||||
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") {
|
||||
providerItems = append(providerItems, providerItem)
|
||||
}
|
||||
}
|
||||
|
@ -63,7 +63,11 @@ func GetCertCount(owner, field, value string) (int64, error) {
|
||||
|
||||
func GetCerts(owner string) ([]*Cert, error) {
|
||||
certs := []*Cert{}
|
||||
err := ormer.Engine.Where("owner = ? or owner = ? ", "admin", owner).Desc("created_time").Find(&certs, &Cert{})
|
||||
db := ormer.Engine.NewSession()
|
||||
if owner != "" {
|
||||
db = db.Where("owner = ? or owner = ? ", "admin", owner)
|
||||
}
|
||||
err := db.Desc("created_time").Find(&certs, &Cert{})
|
||||
if err != nil {
|
||||
return certs, err
|
||||
}
|
||||
|
@ -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)
|
||||
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)
|
||||
|
||||
fromAddress := provider.ClientId2
|
||||
if fromAddress == "" {
|
||||
|
@ -17,6 +17,7 @@ package object
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/casdoor/casdoor/conf"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
@ -210,6 +211,12 @@ 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
|
||||
|
@ -70,12 +70,12 @@ func InitFromFile() {
|
||||
for _, provider := range initData.Providers {
|
||||
initDefinedProvider(provider)
|
||||
}
|
||||
for _, user := range initData.Users {
|
||||
initDefinedUser(user)
|
||||
}
|
||||
for _, application := range initData.Applications {
|
||||
initDefinedApplication(application)
|
||||
}
|
||||
for _, user := range initData.Users {
|
||||
initDefinedUser(user)
|
||||
}
|
||||
for _, cert := range initData.Certs {
|
||||
initDefinedCert(cert)
|
||||
}
|
||||
|
@ -23,17 +23,18 @@ 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"`
|
||||
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"`
|
||||
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"`
|
||||
|
||||
AutoSync int `json:"autoSync"`
|
||||
LastSync string `xorm:"varchar(100)" json:"lastSync"`
|
||||
@ -150,7 +151,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").Update(ldap)
|
||||
"port", "enable_ssl", "username", "password", "base_dn", "filter", "filter_fields", "auto_sync", "default_group", "password_type", "allow_self_signed_cert").Update(ldap)
|
||||
if err != nil {
|
||||
return false, nil
|
||||
}
|
||||
|
@ -106,6 +106,12 @@ 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())
|
||||
|
@ -16,6 +16,7 @@ package object
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"crypto/tls"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
@ -64,8 +65,11 @@ 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), nil)
|
||||
conn, err = goldap.DialTLS("tcp", fmt.Sprintf("%s:%d", ldap.Host, ldap.Port), &tlsConfig)
|
||||
} else {
|
||||
conn, err = goldap.Dial("tcp", fmt.Sprintf("%s:%d", ldap.Host, ldap.Port))
|
||||
}
|
||||
|
@ -60,7 +60,8 @@ func (mfa *SmsMfa) Enable(user *User) error {
|
||||
columns = append(columns, "mfa_phone_enabled", "phone", "country_code")
|
||||
} else if mfa.MfaType == EmailType {
|
||||
user.MfaEmailEnabled = true
|
||||
columns = append(columns, "mfa_email_enabled", "email")
|
||||
user.EmailVerified = true
|
||||
columns = append(columns, "mfa_email_enabled", "email", "email_verified")
|
||||
}
|
||||
|
||||
_, err := UpdateUser(user.GetId(), user, columns, false)
|
||||
|
@ -30,6 +30,7 @@ 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"`
|
||||
@ -119,6 +120,7 @@ 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"},
|
||||
@ -138,7 +140,7 @@ func GetOidcDiscovery(host string) OidcDiscovery {
|
||||
|
||||
func GetJsonWebKeySet() (jose.JSONWebKeySet, error) {
|
||||
jwks := jose.JSONWebKeySet{}
|
||||
certs, err := GetCerts("admin")
|
||||
certs, err := GetCerts("")
|
||||
if err != nil {
|
||||
return jwks, err
|
||||
}
|
||||
@ -213,3 +215,14 @@ 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,
|
||||
}
|
||||
}
|
||||
|
@ -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:"varchar(200)" json:"countryCodes"`
|
||||
CountryCodes []string `xorm:"mediumtext" json:"countryCodes"`
|
||||
DefaultAvatar string `xorm:"varchar(200)" json:"defaultAvatar"`
|
||||
DefaultApplication string `xorm:"varchar(100)" json:"defaultApplication"`
|
||||
UserTypes []string `xorm:"mediumtext" json:"userTypes"`
|
||||
@ -80,7 +80,8 @@ type Organization struct {
|
||||
UseEmailAsUsername bool `json:"useEmailAsUsername"`
|
||||
EnableTour bool `json:"enableTour"`
|
||||
IpRestriction string `json:"ipRestriction"`
|
||||
NavItems []string `xorm:"varchar(500)" json:"navItems"`
|
||||
NavItems []string `xorm:"varchar(1000)" json:"navItems"`
|
||||
WidgetItems []string `xorm:"varchar(1000)" json:"widgetItems"`
|
||||
|
||||
MfaItems []*MfaItem `xorm:"varchar(300)" json:"mfaItems"`
|
||||
AccountItems []*AccountItem `xorm:"varchar(5000)" json:"accountItems"`
|
||||
@ -227,6 +228,7 @@ 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()
|
||||
|
@ -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, "")
|
||||
return reg.ReplaceAllString(dataSourceName, "dbname=postgres")
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -148,7 +148,7 @@ func UpdatePermission(id string, permission *Permission) (bool, error) {
|
||||
}
|
||||
|
||||
if permission.ResourceType == "Application" && permission.Model != "" {
|
||||
model, err := GetModelEx(util.GetId(owner, permission.Model))
|
||||
model, err := GetModelEx(util.GetId(permission.Owner, permission.Model))
|
||||
if err != nil {
|
||||
return false, err
|
||||
} else if model == nil {
|
||||
|
@ -48,6 +48,7 @@ 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"`
|
||||
@ -384,6 +385,44 @@ 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()
|
||||
@ -436,6 +475,7 @@ 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" {
|
||||
|
@ -263,6 +263,27 @@ 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 {
|
||||
@ -271,7 +292,14 @@ 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)
|
||||
@ -287,12 +315,12 @@ func SendWebhooks(record *casvisorsdk.Record) error {
|
||||
}
|
||||
}
|
||||
|
||||
statusCode, respBody, err := sendWebhook(webhook, record, user)
|
||||
statusCode, respBody, err := sendWebhook(webhook, &record2, user)
|
||||
if err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
|
||||
err = addWebhookRecord(webhook, record, statusCode, respBody, err)
|
||||
err = addWebhookRecord(webhook, &record2, statusCode, respBody, err)
|
||||
if err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/beevik/etree"
|
||||
"github.com/golang-jwt/jwt/v4"
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
"github.com/google/uuid"
|
||||
saml "github.com/russellhaering/gosaml2"
|
||||
dsig "github.com/russellhaering/goxmldsig"
|
||||
|
@ -21,7 +21,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/casdoor/casdoor/util"
|
||||
"github.com/golang-jwt/jwt/v4"
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
)
|
||||
|
||||
type Claims struct {
|
||||
@ -31,7 +31,8 @@ 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"`
|
||||
Azp string `json:"azp,omitempty"`
|
||||
Provider string `json:"provider,omitempty"`
|
||||
jwt.RegisteredClaims
|
||||
}
|
||||
|
||||
@ -46,6 +47,17 @@ 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"`
|
||||
@ -140,6 +152,7 @@ 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
|
||||
}
|
||||
|
||||
@ -159,6 +172,7 @@ type ClaimsWithoutThirdIdp struct {
|
||||
Tag string `json:"tag"`
|
||||
Scope string `json:"scope,omitempty"`
|
||||
Azp string `json:"azp,omitempty"`
|
||||
Provider string `json:"provider,omitempty"`
|
||||
jwt.RegisteredClaims
|
||||
}
|
||||
|
||||
@ -176,6 +190,20 @@ 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,
|
||||
@ -274,6 +302,7 @@ func getShortClaims(claims Claims) ClaimsShort {
|
||||
Scope: claims.Scope,
|
||||
RegisteredClaims: claims.RegisteredClaims,
|
||||
Azp: claims.Azp,
|
||||
Provider: claims.Provider,
|
||||
}
|
||||
return res
|
||||
}
|
||||
@ -287,6 +316,7 @@ func getClaimsWithoutThirdIdp(claims Claims) ClaimsWithoutThirdIdp {
|
||||
Scope: claims.Scope,
|
||||
RegisteredClaims: claims.RegisteredClaims,
|
||||
Azp: claims.Azp,
|
||||
Provider: claims.Provider,
|
||||
}
|
||||
return res
|
||||
}
|
||||
@ -308,6 +338,7 @@ 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)
|
||||
@ -342,7 +373,7 @@ func refineUser(user *User) *User {
|
||||
return user
|
||||
}
|
||||
|
||||
func generateJwtToken(application *Application, user *User, nonce string, scope string, host string) (string, string, string, error) {
|
||||
func generateJwtToken(application *Application, user *User, provider string, 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)
|
||||
@ -362,9 +393,10 @@ func generateJwtToken(application *Application, user *User, nonce string, scope
|
||||
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,
|
||||
Tag: user.Tag,
|
||||
Scope: scope,
|
||||
Azp: application.ClientId,
|
||||
Provider: provider,
|
||||
RegisteredClaims: jwt.RegisteredClaims{
|
||||
Issuer: originBackend,
|
||||
Subject: user.Id,
|
||||
|
@ -18,6 +18,7 @@ import (
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/casdoor/casdoor/i18n"
|
||||
@ -37,6 +38,8 @@ 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"`
|
||||
@ -71,6 +74,22 @@ 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 {
|
||||
@ -117,7 +136,7 @@ func CheckOAuthLogin(clientId string, responseType string, redirectUri string, s
|
||||
return "", application, nil
|
||||
}
|
||||
|
||||
func GetOAuthCode(userId string, clientId 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, provider 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
|
||||
@ -152,7 +171,7 @@ func GetOAuthCode(userId string, clientId string, responseType string, redirectU
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
accessToken, refreshToken, tokenName, err := generateJwtToken(application, user, nonce, scope, host)
|
||||
accessToken, refreshToken, tokenName, err := generateJwtToken(application, user, provider, nonce, scope, host)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -222,6 +241,8 @@ 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 {
|
||||
@ -358,7 +379,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,
|
||||
@ -537,7 +558,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,
|
||||
@ -583,7 +604,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,
|
||||
@ -647,7 +668,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
|
||||
}
|
||||
@ -754,7 +775,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,
|
||||
|
@ -19,11 +19,11 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/casdoor/casdoor/util"
|
||||
"github.com/golang-jwt/jwt/v4"
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
)
|
||||
|
||||
type ClaimsStandard struct {
|
||||
*UserShort
|
||||
*UserStandard
|
||||
EmailVerified bool `json:"email_verified,omitempty"`
|
||||
PhoneNumber string `json:"phone_number,omitempty"`
|
||||
PhoneNumberVerified bool `json:"phone_number_verified,omitempty"`
|
||||
@ -33,6 +33,7 @@ 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
|
||||
}
|
||||
@ -47,13 +48,14 @@ func getStreetAddress(user *User) string {
|
||||
|
||||
func getStandardClaims(claims Claims) ClaimsStandard {
|
||||
res := ClaimsStandard{
|
||||
UserShort: getShortUser(claims.User),
|
||||
UserStandard: getStandardUser(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 = ""
|
||||
|
@ -15,13 +15,17 @@
|
||||
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"
|
||||
@ -244,6 +248,7 @@ 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) {
|
||||
@ -454,6 +459,31 @@ 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
|
||||
@ -807,6 +837,10 @@ 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
|
||||
@ -815,6 +849,16 @@ 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
|
||||
}
|
||||
@ -1179,6 +1223,40 @@ 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
|
||||
|
@ -81,62 +81,12 @@ func UploadUsers(owner string, path string) (bool, error) {
|
||||
return false, err
|
||||
}
|
||||
|
||||
transUsers, err := StringArrayToUser(table)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
newUsers := []*User{}
|
||||
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),
|
||||
}
|
||||
|
||||
for _, user := range transUsers {
|
||||
if _, ok := oldUserMap[user.GetId()]; !ok {
|
||||
newUsers = append(newUsers, user)
|
||||
}
|
||||
|
@ -19,12 +19,14 @@ 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"
|
||||
)
|
||||
@ -689,3 +691,103 @@ 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
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ type VerificationRecord struct {
|
||||
IsUsed bool `xorm:"notnull" json:"isUsed"`
|
||||
}
|
||||
|
||||
func IsAllowSend(user *User, remoteAddr, recordType, lang string) error {
|
||||
func IsAllowSend(user *User, remoteAddr, recordType string) error {
|
||||
var record VerificationRecord
|
||||
record.RemoteAddr = remoteAddr
|
||||
record.Type = recordType
|
||||
@ -78,15 +78,10 @@ func IsAllowSend(user *User, remoteAddr, recordType, lang string) error {
|
||||
return errors.New("you can only send one code in 60s")
|
||||
}
|
||||
|
||||
err = checkSigninErrorTimes(user, lang)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func SendVerificationCodeToEmail(organization *Organization, user *User, provider *Provider, remoteAddr string, dest string, lang string) error {
|
||||
func SendVerificationCodeToEmail(organization *Organization, user *User, provider *Provider, remoteAddr string, dest string) error {
|
||||
sender := organization.DisplayName
|
||||
title := provider.Title
|
||||
|
||||
@ -104,7 +99,7 @@ func SendVerificationCodeToEmail(organization *Organization, user *User, provide
|
||||
}
|
||||
content = strings.Replace(content, "%{user.friendlyName}", userString, 1)
|
||||
|
||||
err := IsAllowSend(user, remoteAddr, provider.Category, lang)
|
||||
err := IsAllowSend(user, remoteAddr, provider.Category)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -122,8 +117,8 @@ func SendVerificationCodeToEmail(organization *Organization, user *User, provide
|
||||
return nil
|
||||
}
|
||||
|
||||
func SendVerificationCodeToPhone(organization *Organization, user *User, provider *Provider, remoteAddr string, dest string, lang string) error {
|
||||
err := IsAllowSend(user, remoteAddr, provider.Category, lang)
|
||||
func SendVerificationCodeToPhone(organization *Organization, user *User, provider *Provider, remoteAddr string, dest string) error {
|
||||
err := IsAllowSend(user, remoteAddr, provider.Category)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -38,6 +38,8 @@ 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"`
|
||||
|
@ -17,6 +17,7 @@ package object
|
||||
import (
|
||||
"io"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/casdoor/casdoor/util"
|
||||
@ -25,17 +26,43 @@ 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
|
||||
|
||||
type RecordEx struct {
|
||||
casvisorsdk.Record
|
||||
ExtendedUser *User `xorm:"-" json:"extendedUser"`
|
||||
}
|
||||
recordEx := &RecordEx{
|
||||
Record: *record,
|
||||
ExtendedUser: extendedUser,
|
||||
}
|
||||
if webhook.TokenFields != nil && len(webhook.TokenFields) > 0 && extendedUser != nil {
|
||||
userValue := reflect.ValueOf(extendedUser).Elem()
|
||||
|
||||
body := strings.NewReader(util.StructToJson(recordEx))
|
||||
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))
|
||||
}
|
||||
|
||||
req, err := http.NewRequest(webhook.Method, webhook.Url, body)
|
||||
if err != nil {
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
@ -180,7 +181,11 @@ func (c *AirwallexClient) authRequest(method, url string, body interface{}) (map
|
||||
return nil, err
|
||||
}
|
||||
b, _ := json.Marshal(body)
|
||||
req, _ := http.NewRequest(method, url, bytes.NewBuffer(b))
|
||||
var reqBody io.Reader
|
||||
if method != "GET" {
|
||||
reqBody = bytes.NewBuffer(b)
|
||||
}
|
||||
req, _ := http.NewRequest(method, url, reqBody)
|
||||
req.Header.Set("Authorization", "Bearer "+token)
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
resp, err := c.client.Do(req)
|
||||
|
@ -66,6 +66,7 @@ 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")
|
||||
|
@ -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 != "" {
|
||||
|
@ -13,8 +13,8 @@
|
||||
// limitations under the License.
|
||||
|
||||
import React from "react";
|
||||
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 {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 * as ApplicationBackend from "./backend/ApplicationBackend";
|
||||
import * as CertBackend from "./backend/CertBackend";
|
||||
import * as Setting from "./Setting";
|
||||
@ -36,6 +36,7 @@ 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;
|
||||
|
||||
@ -52,6 +53,14 @@ 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;
|
||||
@ -85,11 +94,11 @@ const sideTemplate = `<style>
|
||||
}
|
||||
</style>
|
||||
<div class="left-model">
|
||||
<span class="side-logo"> <img src="https://cdn.casbin.org/img/casdoor-logo_1185x256.png" alt="Casdoor" style="width: 120px">
|
||||
<span class="side-logo"> <img src="${Setting.StaticBaseUrl}/img/casdoor-logo_1185x256.png" alt="Casdoor" style="width: 120px">
|
||||
<span>SSO</span>
|
||||
</span>
|
||||
<div class="img">
|
||||
<img src="https://cdn.casbin.org/img/casbin.svg" alt="Casdoor"/>
|
||||
<img src="${Setting.StaticBaseUrl}/img/casbin.svg" alt="Casdoor"/>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
@ -116,6 +125,7 @@ class ApplicationEditPage extends React.Component {
|
||||
UNSAFE_componentWillMount() {
|
||||
this.getApplication();
|
||||
this.getOrganizations();
|
||||
this.getGroups();
|
||||
}
|
||||
|
||||
getApplication() {
|
||||
@ -167,6 +177,17 @@ 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) {
|
||||
@ -397,6 +418,16 @@ 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"))} :
|
||||
@ -423,6 +454,7 @@ 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>)
|
||||
}
|
||||
@ -469,6 +501,31 @@ 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"))} :
|
||||
@ -670,6 +727,7 @@ 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>
|
||||
@ -804,6 +862,33 @@ 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"))} :
|
||||
|
@ -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() || Setting.isMobile() ? null : `url(${this.state.application?.formBackgroundUrl})`}}>
|
||||
style={{backgroundImage: Setting.inIframe() ? null : (Setting.isMobile() ? `url(${this.state.application?.formBackgroundUrlMobile})` : `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,6 +119,7 @@ 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} />} />
|
||||
|
@ -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 specify a default application for ") + selectedOrganization.name);
|
||||
Setting.showMessage("error", i18next.t("invitation:You need to first specify a default application for organization: ") + selectedOrganization.name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -170,6 +170,16 @@ class LdapEditPage extends React.Component {
|
||||
}} />
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{lineHeight: "32px", textAlign: "right", paddingRight: "25px"}} span={3}>
|
||||
{Setting.getLabel(i18next.t("ldap: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"))} :
|
||||
|
@ -95,8 +95,9 @@ 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()
|
||||
@ -175,6 +176,35 @@ 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;
|
||||
@ -188,20 +218,7 @@ function ManagementPage(props) {
|
||||
return (
|
||||
<React.Fragment>
|
||||
{renderRightDropdown()}
|
||||
<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 />
|
||||
{renderWidgets()}
|
||||
{Setting.isAdminUser(props.account) && (props.uri.indexOf("/trees") === -1) &&
|
||||
<OrganizationSelect
|
||||
initValue={Setting.getOrganization()}
|
||||
@ -323,13 +340,7 @@ function ManagementPage(props) {
|
||||
}
|
||||
}
|
||||
|
||||
const navItems = props.account.organization.navItems;
|
||||
|
||||
if (!Array.isArray(navItems)) {
|
||||
return res;
|
||||
}
|
||||
|
||||
if (navItems.includes("all")) {
|
||||
if (navItemsIsAll()) {
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -443,8 +454,6 @@ 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);
|
||||
};
|
||||
@ -456,34 +465,40 @@ function ManagementPage(props) {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<EnableMfaNotification account={props.account} />
|
||||
<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
|
||||
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> :
|
||||
<Menu
|
||||
onClick={onClose}
|
||||
items={getMenuItems()}
|
||||
mode={"horizontal"}
|
||||
selectedKeys={[props.selectedMenuKey]}
|
||||
style={{position: "absolute", left: 0, right: menuStyleRight, backgroundColor: props.themeAlgorithm.includes("dark") ? "black" : "white"}}
|
||||
/>
|
||||
)}
|
||||
<Header style={{display: "flex", justifyContent: "space-between", alignItems: "center", padding: "0", marginBottom: "4px", backgroundColor: props.themeAlgorithm.includes("dark") ? "black" : "white"}} >
|
||||
{
|
||||
renderAccountMenu()
|
||||
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"}}>
|
||||
<Menu
|
||||
onClick={onClose}
|
||||
items={getMenuItems()}
|
||||
mode={"horizontal"}
|
||||
selectedKeys={[props.selectedMenuKey]}
|
||||
style={{backgroundColor: props.themeAlgorithm.includes("dark") ? "black" : "white"}}
|
||||
/>
|
||||
</div>
|
||||
))
|
||||
}
|
||||
<div style={{flexShrink: 0}}>
|
||||
{renderAccountMenu()}
|
||||
</div>
|
||||
</Header>
|
||||
<Content style={{display: "flex", flexDirection: "column"}} >
|
||||
{isWithoutCard() ?
|
||||
|
@ -27,6 +27,7 @@ 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;
|
||||
|
||||
@ -275,7 +276,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"].map(item => Setting.getOption(item, item))}
|
||||
options={["plain", "salt", "sha512-salt", "md5-salt", "bcrypt", "pbkdf2-salt", "argon2id", "pbkdf2-django"].map(item => Setting.getOption(item, item))}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
@ -537,7 +538,7 @@ class OrganizationEditPage extends React.Component {
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||
{Setting.getLabel(i18next.t("general:Navbar items"), i18next.t("general:Navbar items - Tooltip"))} :
|
||||
{Setting.getLabel(i18next.t("organization:Navbar items"), i18next.t("organization:Navbar items - Tooltip"))} :
|
||||
</Col>
|
||||
<Col span={22} >
|
||||
<NavItemTree
|
||||
@ -550,6 +551,21 @@ 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"))} :
|
||||
|
@ -232,6 +232,15 @@ 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>
|
||||
|
@ -139,6 +139,8 @@ 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)";
|
||||
}
|
||||
|
@ -217,6 +217,7 @@ 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>
|
||||
|
@ -29,6 +29,7 @@ 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;
|
||||
@ -41,6 +42,13 @@ const defaultUserMapping = {
|
||||
avatarUrl: "avatarUrl",
|
||||
};
|
||||
|
||||
const defaultEmailMapping = {
|
||||
fromName: "fromName",
|
||||
toAddress: "toAddress",
|
||||
subject: "subject",
|
||||
content: "content",
|
||||
};
|
||||
|
||||
class ProviderEditPage extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
@ -71,7 +79,16 @@ class ProviderEditPage extends React.Component {
|
||||
|
||||
if (res.status === "ok") {
|
||||
const provider = res.data;
|
||||
provider.userMapping = provider.userMapping || defaultUserMapping;
|
||||
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;
|
||||
}
|
||||
this.setState({
|
||||
provider: provider,
|
||||
});
|
||||
@ -145,9 +162,16 @@ class ProviderEditPage extends React.Component {
|
||||
const requiredKeys = ["id", "username", "displayName"];
|
||||
const provider = this.state.provider;
|
||||
|
||||
if (value === "" && requiredKeys.includes(key)) {
|
||||
Setting.showMessage("error", i18next.t("provider:This field is required"));
|
||||
return;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
provider.userMapping[key] = value;
|
||||
@ -183,6 +207,30 @@ 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":
|
||||
@ -288,10 +336,8 @@ 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") {
|
||||
} else if (provider.type === "WeChat Pay" || provider.type === "CUCloud") {
|
||||
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"));
|
||||
}
|
||||
@ -389,8 +435,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 = i18next.t("provider:Topic name");
|
||||
tooltip = i18next.t("provider:Topic name - Tooltip");
|
||||
text = "Topic name";
|
||||
tooltip = "Topic name - Tooltip";
|
||||
}
|
||||
}
|
||||
|
||||
@ -567,6 +613,8 @@ 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");
|
||||
}
|
||||
})}>
|
||||
{
|
||||
@ -580,6 +628,7 @@ 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>)
|
||||
@ -643,23 +692,35 @@ class ProviderEditPage extends React.Component {
|
||||
</Row>
|
||||
{
|
||||
this.state.provider.type !== "WeCom" ? null : (
|
||||
<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>
|
||||
<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>)
|
||||
}
|
||||
</React.Fragment>
|
||||
)
|
||||
@ -770,6 +831,7 @@ 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>
|
||||
{
|
||||
@ -888,7 +950,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" ? 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" && this.state.provider.type !== "Nextcloud" ? null : (
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={2}>
|
||||
{Setting.getLabel(i18next.t("provider:Domain"), i18next.t("provider:Domain - Tooltip"))} :
|
||||
@ -901,7 +963,7 @@ class ProviderEditPage extends React.Component {
|
||||
</Row>
|
||||
)
|
||||
}
|
||||
{this.state.provider.category === "Storage" || ["Custom HTTP SMS", "Custom HTTP Email", "SendGrid", "CUCloud"].includes(this.state.provider.type) ? (
|
||||
{["Face ID", "Storage"].includes(this.state.provider.category) || ["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"}} >
|
||||
@ -915,7 +977,7 @@ class ProviderEditPage extends React.Component {
|
||||
</Col>
|
||||
</Row>
|
||||
)}
|
||||
{["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 : (
|
||||
{["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 : (
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={2}>
|
||||
{Setting.getLabel(i18next.t("provider:Endpoint (Intranet)"), i18next.t("provider:Region endpoint for Intranet"))} :
|
||||
@ -927,7 +989,7 @@ class ProviderEditPage extends React.Component {
|
||||
</Col>
|
||||
</Row>
|
||||
)}
|
||||
{["Custom HTTP SMS", "SendGrid", "Local File System", "CUCloud"].includes(this.state.provider.type) ? null : (
|
||||
{["Custom HTTP SMS", "Custom HTTP Email", "SendGrid", "Local File System", "CUCloud", "Alibaba Cloud Facebody"].includes(this.state.provider.type) ? null : (
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
<Col style={{marginTop: "5px"}} span={2}>
|
||||
{["Casdoor"].includes(this.state.provider.type) ?
|
||||
@ -941,7 +1003,7 @@ class ProviderEditPage extends React.Component {
|
||||
</Col>
|
||||
</Row>
|
||||
)}
|
||||
{["Custom HTTP SMS", "SendGrid", "CUCloud"].includes(this.state.provider.type) ? null : (
|
||||
{["Custom HTTP SMS", "Custom HTTP Email", "SendGrid", "CUCloud", "Alibaba Cloud Facebody"].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"))} :
|
||||
@ -953,7 +1015,7 @@ class ProviderEditPage extends React.Component {
|
||||
</Col>
|
||||
</Row>
|
||||
)}
|
||||
{["Custom HTTP SMS", "SendGrid", "Synology", "Casdoor", "CUCloud"].includes(this.state.provider.type) ? null : (
|
||||
{["Custom HTTP SMS", "Custom HTTP Email", "SendGrid", "Synology", "Casdoor", "CUCloud", "Alibaba Cloud Facebody"].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"))} :
|
||||
@ -1094,6 +1156,66 @@ 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"))} :
|
||||
@ -1162,7 +1284,7 @@ class ProviderEditPage extends React.Component {
|
||||
</Button>
|
||||
</Row>
|
||||
</React.Fragment>
|
||||
) : this.state.provider.category === "SMS" ? (
|
||||
) : ["SMS"].includes(this.state.provider.category) ? (
|
||||
<React.Fragment>
|
||||
{["Custom HTTP SMS", "Twilio SMS", "Amazon SNS", "Azure ACS", "Msg91 SMS", "Infobip SMS"].includes(this.state.provider.type) ?
|
||||
null :
|
||||
@ -1280,7 +1402,7 @@ class ProviderEditPage extends React.Component {
|
||||
}} />
|
||||
</Col>
|
||||
<Col span={16} >
|
||||
<Button type="primary" loading={this.state.metadataLoading} onClick={() => {this.fetchSamlMetadata();}}>{i18next.t("general:Request")}</Button>
|
||||
<Button style={{marginLeft: "10px"}} type="primary" loading={this.state.metadataLoading} onClick={() => {this.fetchSamlMetadata();}}>{i18next.t("general:Request")}</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row style={{marginTop: "20px"}} >
|
||||
|
@ -416,6 +416,12 @@ 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() {
|
||||
@ -1150,6 +1156,10 @@ 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 [];
|
||||
}
|
||||
@ -1522,7 +1532,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=\"https://cdn.casbin.org/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="${StaticBaseUrl}/img/casdoor-logo_1185x256.png"/></a>`;
|
||||
}
|
||||
|
||||
export function getEmptyFooterContent() {
|
||||
@ -1554,7 +1564,7 @@ export function getDefaultHtmlEmailContent() {
|
||||
<div class="email-container">
|
||||
<div class="header">
|
||||
<h3>Casbin Organization</h3>
|
||||
<img src="https://cdn.casbin.org/img/casdoor-logo_1185x256.png" alt="Casdoor Logo" width="300">
|
||||
<img src="${StaticBaseUrl}/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>
|
||||
@ -1593,6 +1603,8 @@ 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)";
|
||||
}
|
||||
@ -1604,7 +1616,7 @@ export function isDarkTheme(themeAlgorithm) {
|
||||
|
||||
function getPreferredMfaProp(mfaProps) {
|
||||
for (const i in mfaProps) {
|
||||
if (mfaProps[i].isPreffered) {
|
||||
if (mfaProps[i].isPreferred) {
|
||||
return mfaProps[i];
|
||||
}
|
||||
}
|
||||
|
@ -37,17 +37,35 @@ 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({
|
||||
systemInfo: res.data,
|
||||
loading: false,
|
||||
});
|
||||
|
||||
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({
|
||||
@ -55,17 +73,25 @@ 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 => {
|
||||
this.setState({
|
||||
versionInfo: res.data,
|
||||
});
|
||||
if (res.status === "ok") {
|
||||
this.setState({
|
||||
versionInfo: res.data,
|
||||
});
|
||||
} else {
|
||||
Setting.showMessage("error", res.msg);
|
||||
this.stopTimer();
|
||||
}
|
||||
}).catch(err => {
|
||||
Setting.showMessage("error", `Version info failed to get: ${err}`);
|
||||
this.stopTimer();
|
||||
});
|
||||
}
|
||||
|
||||
@ -77,10 +103,14 @@ class SystemInfo extends React.Component {
|
||||
this.setState({isTourVisible: TourConfig.getTourVisible()});
|
||||
};
|
||||
|
||||
componentWillUnmount() {
|
||||
stopTimer() {
|
||||
if (this.state.intervalId !== null) {
|
||||
clearInterval(this.state.intervalId);
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.stopTimer();
|
||||
window.removeEventListener("storageTourChanged", this.handleTourChange);
|
||||
}
|
||||
|
||||
@ -125,9 +155,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");
|
||||
|
@ -1,4 +1,5 @@
|
||||
import React from "react";
|
||||
import * as Setting from "./Setting";
|
||||
|
||||
export const TourObj = {
|
||||
home: [
|
||||
@ -8,7 +9,7 @@ export const TourObj = {
|
||||
cover: (
|
||||
<img
|
||||
alt="casdoor.png"
|
||||
src="https://cdn.casbin.org/img/casdoor-logo_1185x256.png"
|
||||
src={`${Setting.StaticBaseUrl}/img/casdoor-logo_1185x256.png`}
|
||||
/>
|
||||
),
|
||||
},
|
||||
|
@ -1054,6 +1054,7 @@ 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>
|
||||
|
@ -144,6 +144,9 @@ class WebhookEditPage extends React.Component {
|
||||
if (["port"].includes(key)) {
|
||||
value = Setting.myParseInt(value);
|
||||
}
|
||||
if (key === "objectFields") {
|
||||
value = value.includes("All") ? ["All"] : value;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@ -174,7 +177,16 @@ class WebhookEditPage extends React.Component {
|
||||
renderWebhook() {
|
||||
const preview = Setting.deepCopy(previewTemplate);
|
||||
if (this.state.webhook.isUserExtended) {
|
||||
preview["extendedUser"] = userTemplate;
|
||||
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;
|
||||
}
|
||||
}
|
||||
const previewText = JSON.stringify(preview, null, 2);
|
||||
|
||||
@ -285,6 +297,19 @@ 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"))} :
|
||||
@ -295,6 +320,18 @@ 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"))} :
|
||||
|
@ -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=${username}`, {
|
||||
return fetch(`${authConfig.serverUrl}/api/get-email-and-phone?organization=${organization}&username=${encodeURIComponent(username)}`, {
|
||||
method: "GET",
|
||||
credentials: "include",
|
||||
headers: {
|
||||
@ -61,7 +61,14 @@ export function oAuthParamsToQuery(oAuthParams) {
|
||||
}
|
||||
|
||||
export function getApplicationLogin(params) {
|
||||
const queryParams = (params?.type === "cas") ? casLoginParamsToQuery(params) : oAuthParamsToQuery(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);
|
||||
}
|
||||
return fetch(`${authConfig.serverUrl}/api/get-app-login${queryParams}`, {
|
||||
method: "GET",
|
||||
credentials: "include",
|
||||
|
@ -193,7 +193,11 @@ 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") {
|
||||
const from = innerParams.get("from");
|
||||
let from = innerParams.get("from");
|
||||
const oauth = innerParams.get("oauth");
|
||||
if (oauth) {
|
||||
from += `?oauth=${oauth}`;
|
||||
}
|
||||
Setting.goToLinkSoftOrJumpSelf(this, from);
|
||||
} else if (responseType === "saml") {
|
||||
if (res.data2.method === "POST") {
|
||||
|
@ -471,6 +471,8 @@ 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"}} />}
|
||||
|
@ -37,6 +37,8 @@ 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 {
|
||||
@ -61,6 +63,10 @@ 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) {
|
||||
@ -77,7 +83,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") {
|
||||
} else if (this.state.type === "code" || this.state.type === "cas" || this.state.type === "device") {
|
||||
this.getApplicationLogin();
|
||||
} else {
|
||||
Setting.showMessage("error", `Unknown authentication type: ${this.state.type}`);
|
||||
@ -151,13 +157,25 @@ class LoginPage extends React.Component {
|
||||
}
|
||||
|
||||
getApplicationLogin() {
|
||||
const loginParams = (this.state.type === "cas") ? Util.getCasLoginParameters("admin", this.state.applicationName) : Util.getOAuthGetParameters();
|
||||
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();
|
||||
}
|
||||
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,
|
||||
@ -262,6 +280,16 @@ 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) {
|
||||
@ -285,6 +313,9 @@ 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;
|
||||
@ -355,6 +386,7 @@ 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 === "") {
|
||||
@ -379,6 +411,9 @@ 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;
|
||||
}
|
||||
@ -415,6 +450,7 @@ 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();
|
||||
@ -442,6 +478,8 @@ 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
|
||||
@ -461,6 +499,11 @@ 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);
|
||||
@ -497,6 +540,8 @@ class LoginPage extends React.Component {
|
||||
} else {
|
||||
Setting.showMessage("error", `${i18next.t("application:Failed to sign in")}: ${res.msg}`);
|
||||
}
|
||||
}).finally(() => {
|
||||
this.setState({loginLoading: false});
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -566,7 +611,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} />
|
||||
<LanguageSelect languages={application.organizationObj.languages} onClick={key => {this.setState({userLang: key});}} />
|
||||
</div>
|
||||
);
|
||||
} else if (signinItem.name === "Signin methods") {
|
||||
@ -578,6 +623,9 @@ 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>")}} />
|
||||
@ -684,6 +732,7 @@ 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"
|
||||
@ -696,19 +745,25 @@ class LoginPage extends React.Component {
|
||||
</Button>
|
||||
{
|
||||
this.state.loginMethod === "faceId" ?
|
||||
<Suspense fallback={null}>
|
||||
<FaceRecognitionModal
|
||||
visible={this.state.openFaceRecognitionModal}
|
||||
onOk={(faceId) => {
|
||||
const values = this.state.values;
|
||||
values["faceId"] = 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;
|
||||
|
||||
this.login(values);
|
||||
this.setState({openFaceRecognitionModal: false});
|
||||
}}
|
||||
onCancel={() => this.setState({openFaceRecognitionModal: false})}
|
||||
/>
|
||||
</Suspense>
|
||||
this.login(values);
|
||||
this.setState({openFaceRecognitionModal: false});
|
||||
}}
|
||||
onCancel={() => this.setState({openFaceRecognitionModal: false, loginLoading: false})}
|
||||
/>
|
||||
</Suspense>
|
||||
:
|
||||
<>
|
||||
</>
|
||||
@ -723,6 +778,8 @@ 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}>
|
||||
@ -730,6 +787,10 @@ 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");
|
||||
@ -790,6 +851,16 @@ 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;
|
||||
@ -805,7 +876,6 @@ class LoginPage extends React.Component {
|
||||
<Form
|
||||
name="normal_login"
|
||||
initialValues={{
|
||||
|
||||
organization: application.organization,
|
||||
application: application.name,
|
||||
autoSignin: true,
|
||||
@ -908,7 +978,7 @@ class LoginPage extends React.Component {
|
||||
this.login(values);
|
||||
this.setState({openCaptchaModal: false});
|
||||
}}
|
||||
onCancel={() => this.setState({openCaptchaModal: false})}
|
||||
onCancel={() => this.setState({openCaptchaModal: false, loginLoading: false})}
|
||||
isCurrentProvider={true}
|
||||
/>;
|
||||
}
|
||||
@ -951,6 +1021,10 @@ 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"}}>
|
||||
@ -975,7 +1049,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}&name=${username}`, {
|
||||
return fetch(`${Setting.ServerUrl}/api/webauthn/signin/begin?owner=${application.organization}`, {
|
||||
method: "GET",
|
||||
credentials: "include",
|
||||
})
|
||||
@ -985,11 +1059,7 @@ 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,
|
||||
@ -1039,6 +1109,12 @@ 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,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@ -1231,6 +1307,15 @@ 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;
|
||||
|
@ -194,8 +194,10 @@ 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) {
|
||||
return "";
|
||||
const signInUrl = sessionStorage.getItem("signinUrl");
|
||||
return oauth === "true" ? signInUrl : "";
|
||||
}
|
||||
return `${redirectUri}?code=${code}&state=${state}`;
|
||||
}
|
||||
|
@ -387,7 +387,8 @@ export function getAuthUrl(application, provider, method, code) {
|
||||
}
|
||||
|
||||
let endpoint = authInfo[provider.type].endpoint;
|
||||
let redirectUri = `${window.location.origin}/callback`;
|
||||
const redirectOrigin = application.forcedRedirectOrigin ? application.forcedRedirectOrigin : window.location.origin;
|
||||
let redirectUri = `${redirectOrigin}/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);
|
||||
@ -398,9 +399,13 @@ export function getAuthUrl(application, provider, method, code) {
|
||||
endpoint = endpoint.replace("common", provider.domain);
|
||||
}
|
||||
} else if (provider.type === "Apple") {
|
||||
redirectUri = `${window.location.origin}/api/callback`;
|
||||
redirectUri = `${redirectOrigin}/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"
|
||||
@ -420,13 +425,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=consent&state=${state}`;
|
||||
return `${endpoint}?client_id=${provider.clientId}&redirect_uri=${redirectUri}&scope=${scope}&response_type=code&prompt=login%20consent&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 `${window.location.origin}/callback?state=${state}&code=${"wechat_oa:" + code}`;
|
||||
return `${redirectOrigin}/callback?state=${state}&code=${"wechat_oa:" + code}`;
|
||||
}
|
||||
return `${endpoint}?appid=${provider.clientId}&redirect_uri=${redirectUri}&scope=${scope}&response_type=code&state=${state}#wechat_redirect`;
|
||||
}
|
||||
@ -469,7 +474,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=${window.location.origin}&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=${redirectOrigin}&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") {
|
||||
|
@ -195,8 +195,9 @@ 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}`;
|
||||
return `/prompt/${application.name}?oauth=${oAuthParams !== null}`;
|
||||
} else {
|
||||
return `/result/${application.name}`;
|
||||
}
|
||||
|
@ -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={{margin: "0 15px"}}>
|
||||
<Row>
|
||||
<div style={{width: "100%", padding: "0 100px"}}>
|
||||
<Row style={{justifyContent: "center"}}>
|
||||
{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>
|
||||
|
@ -2,7 +2,7 @@ import i18next from "i18next";
|
||||
import {Tree} from "antd";
|
||||
import React from "react";
|
||||
|
||||
export const NavItemTree = ({disable, checkedKeys, defaultExpandedKeys, onCheck}) => {
|
||||
export const NavItemTree = ({disabled, checkedKeys, defaultExpandedKeys, onCheck}) => {
|
||||
const NavItemNodes = [
|
||||
{
|
||||
title: i18next.t("organization:All"),
|
||||
@ -86,7 +86,7 @@ export const NavItemTree = ({disable, checkedKeys, defaultExpandedKeys, onCheck}
|
||||
|
||||
return (
|
||||
<Tree
|
||||
disabled={disable}
|
||||
disabled={disabled}
|
||||
checkable
|
||||
checkedKeys={checkedKeys}
|
||||
defaultExpandedKeys={defaultExpandedKeys}
|
||||
|
@ -51,6 +51,8 @@ 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`, {
|
||||
|
@ -16,7 +16,7 @@ import * as Setting from "../Setting";
|
||||
import i18next from "i18next";
|
||||
|
||||
export function sendTestNotification(provider) {
|
||||
testNotificationProvider(provider.content, provider.name)
|
||||
testNotificationProvider(provider)
|
||||
.then((res) => {
|
||||
if (res.status === "ok") {
|
||||
Setting.showMessage("success", i18next.t("general:Successfully sent"));
|
||||
@ -29,12 +29,14 @@ export function sendTestNotification(provider) {
|
||||
});
|
||||
}
|
||||
|
||||
function testNotificationProvider(content, name) {
|
||||
function testNotificationProvider(provider) {
|
||||
const notificationForm = {
|
||||
content: content,
|
||||
content: provider.content,
|
||||
owner: provider.owner,
|
||||
name: provider.name,
|
||||
};
|
||||
|
||||
return fetch(`${Setting.ServerUrl}/api/send-notification?provider=${name}`, {
|
||||
return fetch(`${Setting.ServerUrl}/api/send-notification?provider=${provider.name}`, {
|
||||
method: "POST",
|
||||
credentials: "include",
|
||||
body: JSON.stringify(notificationForm),
|
||||
|
@ -33,6 +33,8 @@ 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, {
|
||||
|
29
web/src/common/WidgetItemTree.js
Normal file
29
web/src/common/WidgetItemTree.js
Normal file
@ -0,0 +1,29 @@
|
||||
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}
|
||||
/>
|
||||
);
|
||||
};
|
177
web/src/common/modal/FaceRecognitionCommonModal.js
Normal file
177
web/src/common/modal/FaceRecognitionCommonModal.js
Normal file
@ -0,0 +1,177 @@
|
||||
// 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;
|
@ -14,11 +14,13 @@
|
||||
|
||||
import * as faceapi from "face-api.js";
|
||||
import React, {useState} from "react";
|
||||
import {Button, Modal, Progress, Spin, message} from "antd";
|
||||
import {Button, Modal, Progress, Space, 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} = props;
|
||||
const {visible, onOk, onCancel, withImage} = props;
|
||||
const [modelsLoaded, setModelsLoaded] = React.useState(false);
|
||||
const [isCameraCaptured, setIsCameraCaptured] = useState(false);
|
||||
|
||||
@ -28,12 +30,14 @@ 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 = "https://cdn.casbin.org/site/casdoor/models";
|
||||
const MODEL_URL = "https://cdn.casdoor.com/casdoor/models";
|
||||
const MODEL_URL = `${Setting.StaticBaseUrl}/casdoor/models`;
|
||||
|
||||
Promise.all([
|
||||
faceapi.nets.tinyFaceDetector.loadFromUri(MODEL_URL),
|
||||
@ -50,6 +54,9 @@ const FaceRecognitionModal = (props) => {
|
||||
}, []);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (withImage) {
|
||||
return;
|
||||
}
|
||||
if (visible) {
|
||||
setPercent(0);
|
||||
if (modelsLoaded) {
|
||||
@ -75,6 +82,9 @@ const FaceRecognitionModal = (props) => {
|
||||
}, [visible, modelsLoaded]);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (withImage) {
|
||||
return;
|
||||
}
|
||||
if (isCameraCaptured) {
|
||||
let count = 0;
|
||||
const interval = setInterval(() => {
|
||||
@ -98,6 +108,9 @@ const FaceRecognitionModal = (props) => {
|
||||
}, [isCameraCaptured]);
|
||||
|
||||
const handleStreamVideo = () => {
|
||||
if (withImage) {
|
||||
return;
|
||||
}
|
||||
let count = 0;
|
||||
let goodCount = 0;
|
||||
if (!detection.current) {
|
||||
@ -148,73 +161,163 @@ const FaceRecognitionModal = (props) => {
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Modal
|
||||
closable={false}
|
||||
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}
|
||||
maskClosable={false}
|
||||
destroyOnClose={true}
|
||||
open={visible && isCameraCaptured}
|
||||
open={visible}
|
||||
title={i18next.t("login:Face Recognition")}
|
||||
width={350}
|
||||
footer={[
|
||||
<Button key="back" onClick={onCancel}>
|
||||
Cancel
|
||||
<Button key="ok" type={"primary"} disabled={!currentFaceId || currentFaceId?.length === 0} onClick={() => {
|
||||
onOk(Array.from(currentFaceId.descriptor));
|
||||
}}>
|
||||
Ok
|
||||
</Button>,
|
||||
]}
|
||||
>
|
||||
<Progress percent={percent} />
|
||||
<div style={{marginTop: "20px", marginBottom: "50px", justifyContent: "center", alignContent: "center", position: "relative", flexDirection: "column"}}>
|
||||
<Button key="back" onClick={onCancel}>
|
||||
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 >
|
||||
{
|
||||
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>
|
||||
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
|
||||
}
|
||||
</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
|
||||
}
|
||||
</Modal>
|
||||
</div>
|
||||
);
|
||||
</div>;
|
||||
}
|
||||
};
|
||||
|
||||
export default FaceRecognitionModal;
|
||||
|
@ -30,6 +30,7 @@ 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) => {
|
||||
@ -50,6 +51,9 @@ 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);
|
||||
};
|
||||
|
||||
|
@ -17,11 +17,15 @@
|
||||
"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",
|
||||
@ -61,8 +65,10 @@
|
||||
"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",
|
||||
@ -163,6 +169,7 @@
|
||||
},
|
||||
"currency": {
|
||||
"AUD": "AUD",
|
||||
"BRL": "BRL",
|
||||
"CAD": "CAD",
|
||||
"CHF": "CHF",
|
||||
"CNY": "CNY",
|
||||
@ -189,6 +196,7 @@
|
||||
"Verify": "Verify"
|
||||
},
|
||||
"general": {
|
||||
"AI Assistant": "AI Assistant",
|
||||
"API key": "API key",
|
||||
"API key - Tooltip": "API key - Tooltip",
|
||||
"Access key": "Access key",
|
||||
@ -201,7 +209,6 @@
|
||||
"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",
|
||||
@ -231,6 +238,7 @@
|
||||
"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",
|
||||
@ -241,6 +249,7 @@
|
||||
"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",
|
||||
@ -258,7 +267,6 @@
|
||||
"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",
|
||||
@ -271,6 +279,7 @@
|
||||
"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",
|
||||
@ -344,6 +353,7 @@
|
||||
"Phone - Tooltip": "Phone number",
|
||||
"Phone only": "Phone only",
|
||||
"Phone or Email": "Phone or Email",
|
||||
"Plain": "Plain",
|
||||
"Plan": "Plan",
|
||||
"Plan - Tooltip": "Plan - Tooltip",
|
||||
"Plans": "Plans",
|
||||
@ -362,6 +372,7 @@
|
||||
"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",
|
||||
@ -412,6 +423,7 @@
|
||||
"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",
|
||||
@ -442,7 +454,8 @@
|
||||
"Parent group - Tooltip": "Parent group - Tooltip",
|
||||
"Physical": "Physical",
|
||||
"Show all": "Show all",
|
||||
"Virtual": "Virtual"
|
||||
"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"
|
||||
},
|
||||
"home": {
|
||||
"New users past 30 days": "New users past 30 days",
|
||||
@ -461,13 +474,16 @@
|
||||
"Quota": "Quota",
|
||||
"Quota - Tooltip": "Quota - Tooltip",
|
||||
"Used count": "Used count",
|
||||
"Used count - Tooltip": "Used count - Tooltip"
|
||||
"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: "
|
||||
},
|
||||
"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",
|
||||
@ -586,11 +602,6 @@
|
||||
"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",
|
||||
@ -610,6 +621,8 @@
|
||||
"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",
|
||||
@ -622,10 +635,14 @@
|
||||
"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"
|
||||
"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"
|
||||
},
|
||||
"payment": {
|
||||
"Confirm your invoice information": "Confirm your invoice information",
|
||||
@ -728,6 +745,7 @@
|
||||
"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",
|
||||
@ -757,7 +775,6 @@
|
||||
"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.",
|
||||
@ -817,6 +834,8 @@
|
||||
"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",
|
||||
@ -830,6 +849,8 @@
|
||||
"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",
|
||||
@ -844,6 +865,8 @@
|
||||
"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",
|
||||
@ -1244,6 +1267,8 @@
|
||||
"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",
|
||||
|
@ -17,11 +17,15 @@
|
||||
"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",
|
||||
@ -61,8 +65,10 @@
|
||||
"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",
|
||||
@ -163,6 +169,7 @@
|
||||
},
|
||||
"currency": {
|
||||
"AUD": "AUD",
|
||||
"BRL": "BRL",
|
||||
"CAD": "CAD",
|
||||
"CHF": "CHF",
|
||||
"CNY": "CNY",
|
||||
@ -189,6 +196,7 @@
|
||||
"Verify": "Ověřit"
|
||||
},
|
||||
"general": {
|
||||
"AI Assistant": "AI Assistant",
|
||||
"API key": "API klíč",
|
||||
"API key - Tooltip": "API klíč - Tooltip",
|
||||
"Access key": "Přístupový klíč",
|
||||
@ -201,7 +209,6 @@
|
||||
"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í",
|
||||
@ -231,6 +238,7 @@
|
||||
"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",
|
||||
@ -241,6 +249,7 @@
|
||||
"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",
|
||||
@ -258,7 +267,6 @@
|
||||
"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",
|
||||
@ -271,6 +279,7 @@
|
||||
"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",
|
||||
@ -344,6 +353,7 @@
|
||||
"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",
|
||||
@ -362,6 +372,7 @@
|
||||
"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",
|
||||
@ -412,6 +423,7 @@
|
||||
"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",
|
||||
@ -442,7 +454,8 @@
|
||||
"Parent group - Tooltip": "Nadřazená skupina - Tooltip",
|
||||
"Physical": "Fyzická",
|
||||
"Show all": "Zobrazit vše",
|
||||
"Virtual": "Virtuální"
|
||||
"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"
|
||||
},
|
||||
"home": {
|
||||
"New users past 30 days": "Noví uživatelé za posledních 30 dní",
|
||||
@ -461,13 +474,16 @@
|
||||
"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"
|
||||
"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: "
|
||||
},
|
||||
"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",
|
||||
@ -586,11 +602,6 @@
|
||||
"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",
|
||||
@ -610,6 +621,8 @@
|
||||
"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",
|
||||
@ -622,10 +635,14 @@
|
||||
"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á"
|
||||
"Website URL - Tooltip": "Domovská URL organizace. Toto pole se v Casdoor nepoužívá",
|
||||
"Widget items": "Widget items",
|
||||
"Widget items - Tooltip": "Widget items - Tooltip"
|
||||
},
|
||||
"payment": {
|
||||
"Confirm your invoice information": "Potvrďte informace na faktuře",
|
||||
@ -728,6 +745,7 @@
|
||||
"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",
|
||||
@ -757,7 +775,6 @@
|
||||
"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.",
|
||||
@ -817,6 +834,8 @@
|
||||
"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",
|
||||
@ -830,6 +849,8 @@
|
||||
"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",
|
||||
@ -844,6 +865,8 @@
|
||||
"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í",
|
||||
@ -1244,6 +1267,8 @@
|
||||
"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",
|
||||
|
@ -17,11 +17,15 @@
|
||||
"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",
|
||||
@ -61,8 +65,10 @@
|
||||
"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",
|
||||
@ -163,6 +169,7 @@
|
||||
},
|
||||
"currency": {
|
||||
"AUD": "AUD",
|
||||
"BRL": "BRL",
|
||||
"CAD": "CAD",
|
||||
"CHF": "CHF",
|
||||
"CNY": "CNY",
|
||||
@ -189,6 +196,7 @@
|
||||
"Verify": "überprüfen"
|
||||
},
|
||||
"general": {
|
||||
"AI Assistant": "AI Assistant",
|
||||
"API key": "API key",
|
||||
"API key - Tooltip": "API key - Tooltip",
|
||||
"Access key": "Access key",
|
||||
@ -201,7 +209,6 @@
|
||||
"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",
|
||||
@ -231,6 +238,7 @@
|
||||
"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",
|
||||
@ -241,6 +249,7 @@
|
||||
"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",
|
||||
@ -258,7 +267,6 @@
|
||||
"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",
|
||||
@ -271,6 +279,7 @@
|
||||
"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",
|
||||
@ -344,6 +353,7 @@
|
||||
"Phone - Tooltip": "Telefonnummer",
|
||||
"Phone only": "Phone only",
|
||||
"Phone or Email": "Phone or Email",
|
||||
"Plain": "Plain",
|
||||
"Plan": "Plan",
|
||||
"Plan - Tooltip": "Plan - Tooltip",
|
||||
"Plans": "Pläne",
|
||||
@ -362,6 +372,7 @@
|
||||
"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",
|
||||
@ -412,6 +423,7 @@
|
||||
"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",
|
||||
@ -442,7 +454,8 @@
|
||||
"Parent group - Tooltip": "Parent group - Tooltip",
|
||||
"Physical": "Physical",
|
||||
"Show all": "Show all",
|
||||
"Virtual": "Virtual"
|
||||
"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"
|
||||
},
|
||||
"home": {
|
||||
"New users past 30 days": "New users past 30 days",
|
||||
@ -461,13 +474,16 @@
|
||||
"Quota": "Quota",
|
||||
"Quota - Tooltip": "Quota - Tooltip",
|
||||
"Used count": "Used count",
|
||||
"Used count - Tooltip": "Used count - Tooltip"
|
||||
"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: "
|
||||
},
|
||||
"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",
|
||||
@ -586,11 +602,6 @@
|
||||
"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",
|
||||
@ -610,6 +621,8 @@
|
||||
"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",
|
||||
@ -622,10 +635,14 @@
|
||||
"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"
|
||||
"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"
|
||||
},
|
||||
"payment": {
|
||||
"Confirm your invoice information": "Bestätigen Sie Ihre Rechnungsinformationen",
|
||||
@ -728,6 +745,7 @@
|
||||
"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",
|
||||
@ -757,7 +775,6 @@
|
||||
"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.",
|
||||
@ -817,6 +834,8 @@
|
||||
"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",
|
||||
@ -830,6 +849,8 @@
|
||||
"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",
|
||||
@ -844,6 +865,8 @@
|
||||
"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",
|
||||
@ -1244,6 +1267,8 @@
|
||||
"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?",
|
||||
|
@ -17,11 +17,15 @@
|
||||
"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",
|
||||
@ -61,8 +65,10 @@
|
||||
"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",
|
||||
@ -163,6 +169,7 @@
|
||||
},
|
||||
"currency": {
|
||||
"AUD": "AUD",
|
||||
"BRL": "BRL",
|
||||
"CAD": "CAD",
|
||||
"CHF": "CHF",
|
||||
"CNY": "CNY",
|
||||
@ -189,6 +196,7 @@
|
||||
"Verify": "Verify"
|
||||
},
|
||||
"general": {
|
||||
"AI Assistant": "AI Assistant",
|
||||
"API key": "API key",
|
||||
"API key - Tooltip": "API key - Tooltip",
|
||||
"Access key": "Access key",
|
||||
@ -201,7 +209,6 @@
|
||||
"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",
|
||||
@ -231,6 +238,7 @@
|
||||
"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",
|
||||
@ -259,7 +267,6 @@
|
||||
"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",
|
||||
@ -272,6 +279,7 @@
|
||||
"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",
|
||||
@ -345,6 +353,7 @@
|
||||
"Phone - Tooltip": "Phone number",
|
||||
"Phone only": "Phone only",
|
||||
"Phone or Email": "Phone or Email",
|
||||
"Plain": "Plain",
|
||||
"Plan": "Plan",
|
||||
"Plan - Tooltip": "Plan - Tooltip",
|
||||
"Plans": "Plans",
|
||||
@ -363,6 +372,7 @@
|
||||
"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",
|
||||
@ -413,6 +423,7 @@
|
||||
"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",
|
||||
@ -443,7 +454,8 @@
|
||||
"Parent group - Tooltip": "Parent group - Tooltip",
|
||||
"Physical": "Physical",
|
||||
"Show all": "Show all",
|
||||
"Virtual": "Virtual"
|
||||
"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"
|
||||
},
|
||||
"home": {
|
||||
"New users past 30 days": "New users past 30 days",
|
||||
@ -462,13 +474,16 @@
|
||||
"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"
|
||||
"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: "
|
||||
},
|
||||
"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",
|
||||
@ -587,11 +602,6 @@
|
||||
"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",
|
||||
@ -611,6 +621,8 @@
|
||||
"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",
|
||||
@ -623,10 +635,14 @@
|
||||
"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"
|
||||
"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"
|
||||
},
|
||||
"payment": {
|
||||
"Confirm your invoice information": "Confirm your invoice information",
|
||||
@ -729,6 +745,7 @@
|
||||
"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",
|
||||
@ -758,7 +775,6 @@
|
||||
"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.",
|
||||
@ -818,6 +834,8 @@
|
||||
"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",
|
||||
@ -831,6 +849,8 @@
|
||||
"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",
|
||||
@ -845,6 +865,8 @@
|
||||
"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",
|
||||
@ -1245,6 +1267,8 @@
|
||||
"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",
|
||||
|
@ -17,11 +17,15 @@
|
||||
"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",
|
||||
@ -61,8 +65,10 @@
|
||||
"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",
|
||||
@ -163,6 +169,7 @@
|
||||
},
|
||||
"currency": {
|
||||
"AUD": "AUD",
|
||||
"BRL": "BRL",
|
||||
"CAD": "CAD",
|
||||
"CHF": "CHF",
|
||||
"CNY": "CNY",
|
||||
@ -189,6 +196,7 @@
|
||||
"Verify": "Verificar"
|
||||
},
|
||||
"general": {
|
||||
"AI Assistant": "AI Assistant",
|
||||
"API key": "API key",
|
||||
"API key - Tooltip": "API key - Tooltip",
|
||||
"Access key": "Access key",
|
||||
@ -201,7 +209,6 @@
|
||||
"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",
|
||||
@ -231,6 +238,7 @@
|
||||
"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",
|
||||
@ -241,6 +249,7 @@
|
||||
"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",
|
||||
@ -258,7 +267,6 @@
|
||||
"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",
|
||||
@ -271,6 +279,7 @@
|
||||
"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",
|
||||
@ -344,6 +353,7 @@
|
||||
"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",
|
||||
@ -362,6 +372,7 @@
|
||||
"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",
|
||||
@ -412,6 +423,7 @@
|
||||
"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",
|
||||
@ -442,7 +454,8 @@
|
||||
"Parent group - Tooltip": "Parent group - Tooltip",
|
||||
"Physical": "Physical",
|
||||
"Show all": "Show all",
|
||||
"Virtual": "Virtual"
|
||||
"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"
|
||||
},
|
||||
"home": {
|
||||
"New users past 30 days": "New users past 30 days",
|
||||
@ -461,13 +474,16 @@
|
||||
"Quota": "Quota",
|
||||
"Quota - Tooltip": "Quota - Tooltip",
|
||||
"Used count": "Used count",
|
||||
"Used count - Tooltip": "Used count - Tooltip"
|
||||
"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: "
|
||||
},
|
||||
"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",
|
||||
@ -586,11 +602,6 @@
|
||||
"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",
|
||||
@ -610,6 +621,8 @@
|
||||
"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",
|
||||
@ -622,10 +635,14 @@
|
||||
"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"
|
||||
"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"
|
||||
},
|
||||
"payment": {
|
||||
"Confirm your invoice information": "Confirma la información de tu factura",
|
||||
@ -728,6 +745,7 @@
|
||||
"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",
|
||||
@ -757,7 +775,6 @@
|
||||
"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.",
|
||||
@ -817,6 +834,8 @@
|
||||
"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",
|
||||
@ -830,6 +849,8 @@
|
||||
"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",
|
||||
@ -844,6 +865,8 @@
|
||||
"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",
|
||||
@ -1244,6 +1267,8 @@
|
||||
"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?",
|
||||
|
@ -17,11 +17,15 @@
|
||||
"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",
|
||||
@ -61,8 +65,10 @@
|
||||
"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 سربرگ",
|
||||
@ -163,6 +169,7 @@
|
||||
},
|
||||
"currency": {
|
||||
"AUD": "AUD",
|
||||
"BRL": "BRL",
|
||||
"CAD": "CAD",
|
||||
"CHF": "CHF",
|
||||
"CNY": "CNY",
|
||||
@ -189,6 +196,7 @@
|
||||
"Verify": "تأیید"
|
||||
},
|
||||
"general": {
|
||||
"AI Assistant": "AI Assistant",
|
||||
"API key": "کلید API",
|
||||
"API key - Tooltip": "کلید API - راهنمای ابزار",
|
||||
"Access key": "کلید دسترسی",
|
||||
@ -201,7 +209,6 @@
|
||||
"Adapter - Tooltip": "نام جدول فروشگاه سیاست",
|
||||
"Adapters": "آداپتورها",
|
||||
"Add": "افزودن",
|
||||
"Add Face Id": "افزودن Face Id",
|
||||
"Add custom item": "افزودن مورد سفارشی",
|
||||
"Admin": "مدیر",
|
||||
"Affiliation URL": "آدرس وابستگی",
|
||||
@ -231,6 +238,7 @@
|
||||
"Created time": "زمان ایجاد",
|
||||
"Custom": "سفارشی",
|
||||
"Dashboard": "داشبورد",
|
||||
"Data": "Data",
|
||||
"Default": "پیشفرض",
|
||||
"Default application": "برنامه پیشفرض",
|
||||
"Default application - Tooltip": "برنامه پیشفرض برای کاربرانی که مستقیماً از صفحه سازمان ثبتنام میکنند",
|
||||
@ -241,6 +249,7 @@
|
||||
"Delete": "حذف",
|
||||
"Description": "توضیحات",
|
||||
"Description - Tooltip": "اطلاعات توضیحات دقیق برای مرجع، خود Casdoor از آن استفاده نمیکند",
|
||||
"Detail": "详情",
|
||||
"Disable": "غیرفعال",
|
||||
"Display name": "نام نمایشی",
|
||||
"Display name - Tooltip": "نام کاربرپسند و قابل خواندن آسان که بهصورت عمومی در رابط کاربری نمایش داده میشود",
|
||||
@ -258,7 +267,6 @@
|
||||
"Enabled": "فعال شده",
|
||||
"Enabled successfully": "با موفقیت فعال شد",
|
||||
"Enforcers": "Enforcerها",
|
||||
"FaceIdData": "دادههای FaceId",
|
||||
"Failed to add": "عدم موفقیت در افزودن",
|
||||
"Failed to connect to server": "عدم موفقیت در اتصال به سرور",
|
||||
"Failed to delete": "عدم موفقیت در حذف",
|
||||
@ -271,6 +279,7 @@
|
||||
"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": "برخی متون هنوز ترجمه نشدهاند؟ لطفاً به ما در ترجمه کمک کنید در",
|
||||
@ -344,6 +353,7 @@
|
||||
"Phone - Tooltip": "شماره تلفن",
|
||||
"Phone only": "فقط تلفن",
|
||||
"Phone or Email": "تلفن یا ایمیل",
|
||||
"Plain": "Plain",
|
||||
"Plan": "طرح",
|
||||
"Plan - Tooltip": "طرح - راهنمای ابزار",
|
||||
"Plans": "طرحها",
|
||||
@ -362,6 +372,7 @@
|
||||
"QR code is too large": "کد QR بیش از حد بزرگ است",
|
||||
"Real name": "نام واقعی",
|
||||
"Records": "سوابق",
|
||||
"Request": "Request",
|
||||
"Request URI": "آدرس URI درخواست",
|
||||
"Resources": "منابع",
|
||||
"Role": "نقش",
|
||||
@ -412,6 +423,7 @@
|
||||
"This is a read-only demo site!": "این یک سایت دمو فقط خواندنی است!",
|
||||
"Timestamp": "مهر زمان",
|
||||
"Tokens": "توکنها",
|
||||
"Tour": "Tour",
|
||||
"Transactions": "تراکنشها",
|
||||
"Type": "نوع",
|
||||
"Type - Tooltip": "نوع - راهنمای ابزار",
|
||||
@ -442,7 +454,8 @@
|
||||
"Parent group - Tooltip": "گروه والد - راهنمای ابزار",
|
||||
"Physical": "فیزیکی",
|
||||
"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"
|
||||
},
|
||||
"home": {
|
||||
"New users past 30 days": "کاربران جدید در ۳۰ روز گذشته",
|
||||
@ -461,13 +474,16 @@
|
||||
"Quota": "سهمیه",
|
||||
"Quota - Tooltip": "حداکثر تعداد کاربرانی که میتوانند با استفاده از این کد دعوت ثبتنام کنند",
|
||||
"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: "
|
||||
},
|
||||
"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",
|
||||
@ -586,11 +602,6 @@
|
||||
"Your phone is": "تلفن شما",
|
||||
"preferred": "مورد علاقه"
|
||||
},
|
||||
"mfaAccount": {
|
||||
"Account Name": "نام حساب",
|
||||
"Issuer": "صادرکننده",
|
||||
"Secret Key": "کلید مخفی"
|
||||
},
|
||||
"model": {
|
||||
"Advanced Editor": "ویرایشگر پیشرفته",
|
||||
"Basic Editor": "ویرایشگر ابتدایی",
|
||||
@ -610,6 +621,8 @@
|
||||
"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",
|
||||
@ -622,10 +635,14 @@
|
||||
"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 استفاده نمیشود"
|
||||
"Website URL - Tooltip": "آدرس صفحه اصلی سازمان. این فیلد در Casdoor استفاده نمیشود",
|
||||
"Widget items": "Widget items",
|
||||
"Widget items - Tooltip": "Widget items - Tooltip"
|
||||
},
|
||||
"payment": {
|
||||
"Confirm your invoice information": "اطلاعات فاکتور خود را تأیید کنید",
|
||||
@ -728,6 +745,7 @@
|
||||
"paid-user do not have active subscription or pending subscription, please select a plan to buy": "کاربر پرداختی اشتراک فعال یا در انتظار ندارد، لطفاً یک طرح برای خرید انتخاب کنید"
|
||||
},
|
||||
"product": {
|
||||
"AirWallex": "AirWallex",
|
||||
"Alipay": "Alipay",
|
||||
"Buy": "خرید",
|
||||
"Buy Product": "خرید محصول",
|
||||
@ -757,7 +775,6 @@
|
||||
"Sold": "فروخته شده",
|
||||
"Sold - Tooltip": "تعداد فروخته شده",
|
||||
"Stripe": "Stripe",
|
||||
"AirWallex": "AirWallex",
|
||||
"Tag - Tooltip": "برچسب محصول",
|
||||
"Test buy page..": "صفحه تست خرید..",
|
||||
"There is no payment channel for this product.": "برای این محصول کانال پرداختی وجود ندارد.",
|
||||
@ -817,6 +834,8 @@
|
||||
"Edit Provider": "ویرایش ارائهدهنده",
|
||||
"Email content": "محتوای ایمیل",
|
||||
"Email content - Tooltip": "محتوای ایمیل",
|
||||
"Email regex": "Email regex",
|
||||
"Email regex - Tooltip": "Email regex - Tooltip",
|
||||
"Email title": "عنوان ایمیل",
|
||||
"Email title - Tooltip": "عنوان ایمیل",
|
||||
"Endpoint": "نقطه پایانی",
|
||||
@ -830,6 +849,8 @@
|
||||
"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",
|
||||
@ -844,6 +865,8 @@
|
||||
"Key text - Tooltip": "متن کلید",
|
||||
"Metadata": "فراداده",
|
||||
"Metadata - Tooltip": "فراداده SAML",
|
||||
"Metadata url": "Metadata url",
|
||||
"Metadata url - Tooltip": "Metadata url - Tooltip",
|
||||
"Method - Tooltip": "روش ورود، کد QR یا ورود بیصدا",
|
||||
"New Provider": "ارائهدهنده جدید",
|
||||
"Normal": "عادی",
|
||||
@ -1244,6 +1267,8 @@
|
||||
"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": "کاربر گسترش یافته است",
|
||||
|
@ -17,11 +17,15 @@
|
||||
"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",
|
||||
@ -61,8 +65,10 @@
|
||||
"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",
|
||||
@ -163,6 +169,7 @@
|
||||
},
|
||||
"currency": {
|
||||
"AUD": "AUD",
|
||||
"BRL": "BRL",
|
||||
"CAD": "CAD",
|
||||
"CHF": "CHF",
|
||||
"CNY": "CNY",
|
||||
@ -189,6 +196,7 @@
|
||||
"Verify": "Verify"
|
||||
},
|
||||
"general": {
|
||||
"AI Assistant": "AI Assistant",
|
||||
"API key": "API key",
|
||||
"API key - Tooltip": "API key - Tooltip",
|
||||
"Access key": "Access key",
|
||||
@ -201,7 +209,6 @@
|
||||
"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",
|
||||
@ -231,6 +238,7 @@
|
||||
"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",
|
||||
@ -241,6 +249,7 @@
|
||||
"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",
|
||||
@ -258,7 +267,6 @@
|
||||
"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",
|
||||
@ -271,6 +279,7 @@
|
||||
"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",
|
||||
@ -344,6 +353,7 @@
|
||||
"Phone - Tooltip": "Phone number",
|
||||
"Phone only": "Phone only",
|
||||
"Phone or Email": "Phone or Email",
|
||||
"Plain": "Plain",
|
||||
"Plan": "Plan",
|
||||
"Plan - Tooltip": "Plan - Tooltip",
|
||||
"Plans": "Plans",
|
||||
@ -362,6 +372,7 @@
|
||||
"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",
|
||||
@ -412,6 +423,7 @@
|
||||
"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",
|
||||
@ -442,7 +454,8 @@
|
||||
"Parent group - Tooltip": "Parent group - Tooltip",
|
||||
"Physical": "Physical",
|
||||
"Show all": "Show all",
|
||||
"Virtual": "Virtual"
|
||||
"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"
|
||||
},
|
||||
"home": {
|
||||
"New users past 30 days": "New users past 30 days",
|
||||
@ -461,13 +474,16 @@
|
||||
"Quota": "Quota",
|
||||
"Quota - Tooltip": "Quota - Tooltip",
|
||||
"Used count": "Used count",
|
||||
"Used count - Tooltip": "Used count - Tooltip"
|
||||
"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: "
|
||||
},
|
||||
"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",
|
||||
@ -586,11 +602,6 @@
|
||||
"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",
|
||||
@ -610,6 +621,8 @@
|
||||
"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",
|
||||
@ -622,10 +635,14 @@
|
||||
"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"
|
||||
"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"
|
||||
},
|
||||
"payment": {
|
||||
"Confirm your invoice information": "Confirm your invoice information",
|
||||
@ -728,6 +745,7 @@
|
||||
"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",
|
||||
@ -757,7 +775,6 @@
|
||||
"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.",
|
||||
@ -817,6 +834,8 @@
|
||||
"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",
|
||||
@ -830,6 +849,8 @@
|
||||
"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",
|
||||
@ -844,6 +865,8 @@
|
||||
"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",
|
||||
@ -1244,6 +1267,8 @@
|
||||
"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",
|
||||
|
@ -17,11 +17,15 @@
|
||||
"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",
|
||||
@ -61,8 +65,10 @@
|
||||
"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",
|
||||
@ -163,6 +169,7 @@
|
||||
},
|
||||
"currency": {
|
||||
"AUD": "AUD",
|
||||
"BRL": "BRL",
|
||||
"CAD": "CAD",
|
||||
"CHF": "CHF",
|
||||
"CNY": "CNY",
|
||||
@ -189,6 +196,7 @@
|
||||
"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",
|
||||
@ -201,7 +209,6 @@
|
||||
"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",
|
||||
@ -231,6 +238,7 @@
|
||||
"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",
|
||||
@ -241,6 +249,7 @@
|
||||
"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",
|
||||
@ -258,7 +267,6 @@
|
||||
"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",
|
||||
@ -271,6 +279,7 @@
|
||||
"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",
|
||||
@ -344,6 +353,7 @@
|
||||
"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",
|
||||
@ -362,6 +372,7 @@
|
||||
"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",
|
||||
@ -412,6 +423,7 @@
|
||||
"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",
|
||||
@ -442,7 +454,8 @@
|
||||
"Parent group - Tooltip": "Groupe parent - Infobulle",
|
||||
"Physical": "Physique",
|
||||
"Show all": "Tout afficher",
|
||||
"Virtual": "Virtuel"
|
||||
"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"
|
||||
},
|
||||
"home": {
|
||||
"New users past 30 days": "Comptes créés dans les 30 derniers jours",
|
||||
@ -461,13 +474,16 @@
|
||||
"Quota": "Quota",
|
||||
"Quota - Tooltip": "Quota - Tooltip",
|
||||
"Used count": "Used count",
|
||||
"Used count - Tooltip": "Used count - Tooltip"
|
||||
"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: "
|
||||
},
|
||||
"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",
|
||||
@ -586,11 +602,6 @@
|
||||
"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",
|
||||
@ -610,6 +621,8 @@
|
||||
"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",
|
||||
@ -622,10 +635,14 @@
|
||||
"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"
|
||||
"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"
|
||||
},
|
||||
"payment": {
|
||||
"Confirm your invoice information": "Confirmez les informations de votre facture",
|
||||
@ -728,6 +745,7 @@
|
||||
"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",
|
||||
@ -757,7 +775,6 @@
|
||||
"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.",
|
||||
@ -817,6 +834,8 @@
|
||||
"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",
|
||||
@ -830,6 +849,8 @@
|
||||
"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)",
|
||||
@ -844,6 +865,8 @@
|
||||
"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",
|
||||
@ -1244,6 +1267,8 @@
|
||||
"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",
|
||||
|
@ -17,11 +17,15 @@
|
||||
"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",
|
||||
@ -61,8 +65,10 @@
|
||||
"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",
|
||||
@ -163,6 +169,7 @@
|
||||
},
|
||||
"currency": {
|
||||
"AUD": "AUD",
|
||||
"BRL": "BRL",
|
||||
"CAD": "CAD",
|
||||
"CHF": "CHF",
|
||||
"CNY": "CNY",
|
||||
@ -189,6 +196,7 @@
|
||||
"Verify": "Verify"
|
||||
},
|
||||
"general": {
|
||||
"AI Assistant": "AI Assistant",
|
||||
"API key": "API key",
|
||||
"API key - Tooltip": "API key - Tooltip",
|
||||
"Access key": "Access key",
|
||||
@ -201,7 +209,6 @@
|
||||
"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",
|
||||
@ -231,6 +238,7 @@
|
||||
"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",
|
||||
@ -241,6 +249,7 @@
|
||||
"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",
|
||||
@ -258,7 +267,6 @@
|
||||
"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",
|
||||
@ -271,6 +279,7 @@
|
||||
"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",
|
||||
@ -344,6 +353,7 @@
|
||||
"Phone - Tooltip": "Phone number",
|
||||
"Phone only": "Phone only",
|
||||
"Phone or Email": "Phone or Email",
|
||||
"Plain": "Plain",
|
||||
"Plan": "Plan",
|
||||
"Plan - Tooltip": "Plan - Tooltip",
|
||||
"Plans": "Plans",
|
||||
@ -362,6 +372,7 @@
|
||||
"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",
|
||||
@ -412,6 +423,7 @@
|
||||
"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",
|
||||
@ -442,7 +454,8 @@
|
||||
"Parent group - Tooltip": "Parent group - Tooltip",
|
||||
"Physical": "Physical",
|
||||
"Show all": "Show all",
|
||||
"Virtual": "Virtual"
|
||||
"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"
|
||||
},
|
||||
"home": {
|
||||
"New users past 30 days": "New users past 30 days",
|
||||
@ -461,13 +474,16 @@
|
||||
"Quota": "Quota",
|
||||
"Quota - Tooltip": "Quota - Tooltip",
|
||||
"Used count": "Used count",
|
||||
"Used count - Tooltip": "Used count - Tooltip"
|
||||
"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: "
|
||||
},
|
||||
"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",
|
||||
@ -586,11 +602,6 @@
|
||||
"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",
|
||||
@ -610,6 +621,8 @@
|
||||
"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",
|
||||
@ -622,10 +635,14 @@
|
||||
"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"
|
||||
"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"
|
||||
},
|
||||
"payment": {
|
||||
"Confirm your invoice information": "Confirm your invoice information",
|
||||
@ -728,6 +745,7 @@
|
||||
"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",
|
||||
@ -757,7 +775,6 @@
|
||||
"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.",
|
||||
@ -817,6 +834,8 @@
|
||||
"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",
|
||||
@ -830,6 +849,8 @@
|
||||
"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",
|
||||
@ -844,6 +865,8 @@
|
||||
"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",
|
||||
@ -1244,6 +1267,8 @@
|
||||
"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",
|
||||
|
@ -17,11 +17,15 @@
|
||||
"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": "Selalu",
|
||||
"Auto signin": "Masuk otomatis",
|
||||
"Auto signin - Tooltip": "Ketika sesi masuk yang terdaftar ada di Casdoor, secara otomatis digunakan untuk masuk ke sisi aplikasi",
|
||||
"Background URL": "URL latar belakang",
|
||||
"Background URL - Tooltip": "URL dari gambar latar belakang yang digunakan di halaman login",
|
||||
"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",
|
||||
@ -61,8 +65,10 @@
|
||||
"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": "Posisi formulir",
|
||||
"Form position - Tooltip": "Tempat pendaftaran, masuk, dan lupa kata sandi",
|
||||
"Generate Face ID": "Generate Face ID",
|
||||
"Grant types": "Jenis-jenis hibah",
|
||||
"Grant types - Tooltip": "Pilih jenis hibah apa yang diperbolehkan dalam protokol OAuth",
|
||||
"Header HTML": "Header HTML",
|
||||
@ -163,6 +169,7 @@
|
||||
},
|
||||
"currency": {
|
||||
"AUD": "AUD",
|
||||
"BRL": "BRL",
|
||||
"CAD": "CAD",
|
||||
"CHF": "CHF",
|
||||
"CNY": "CNY",
|
||||
@ -189,6 +196,7 @@
|
||||
"Verify": "Memverifikasi"
|
||||
},
|
||||
"general": {
|
||||
"AI Assistant": "AI Assistant",
|
||||
"API key": "API key",
|
||||
"API key - Tooltip": "API key - Tooltip",
|
||||
"Access key": "Access key",
|
||||
@ -201,7 +209,6 @@
|
||||
"Adapter - Tooltip": "Nama tabel dari penyimpanan kebijakan",
|
||||
"Adapters": "Adaptor",
|
||||
"Add": "Tambahkan",
|
||||
"Add Face Id": "Add Face Id",
|
||||
"Add custom item": "Add custom item",
|
||||
"Admin": "Admin",
|
||||
"Affiliation URL": "URL Afiliasi",
|
||||
@ -231,6 +238,7 @@
|
||||
"Created time": "Waktu dibuat",
|
||||
"Custom": "Custom",
|
||||
"Dashboard": "Dashboard",
|
||||
"Data": "Data",
|
||||
"Default": "Default",
|
||||
"Default application": "Aplikasi default",
|
||||
"Default application - Tooltip": "Aplikasi default untuk pengguna yang terdaftar langsung dari halaman organisasi",
|
||||
@ -241,6 +249,7 @@
|
||||
"Delete": "Hapus",
|
||||
"Description": "Deskripsi",
|
||||
"Description - Tooltip": "Informasi deskripsi terperinci untuk referensi, Casdoor itu sendiri tidak akan menggunakannya",
|
||||
"Detail": "详情",
|
||||
"Disable": "Disable",
|
||||
"Display name": "Nama tampilan",
|
||||
"Display name - Tooltip": "Sebuah nama yang mudah digunakan dan mudah dibaca yang ditampilkan secara publik di UI",
|
||||
@ -258,7 +267,6 @@
|
||||
"Enabled": "Enabled",
|
||||
"Enabled successfully": "Enabled successfully",
|
||||
"Enforcers": "Enforcers",
|
||||
"FaceIdData": "FaceIdData",
|
||||
"Failed to add": "Gagal menambahkan",
|
||||
"Failed to connect to server": "Gagal terhubung ke server",
|
||||
"Failed to delete": "Gagal menghapus",
|
||||
@ -271,6 +279,7 @@
|
||||
"Favicon": "Favicon",
|
||||
"Favicon - Tooltip": "URL ikon Favicon yang digunakan di semua halaman Casdoor organisasi",
|
||||
"First name": "Nama depan",
|
||||
"Forced redirect origin - Tooltip": "Forced redirect origin - Tooltip",
|
||||
"Forget URL": "Lupakan URL",
|
||||
"Forget URL - Tooltip": "URL kustom untuk halaman \"Lupa kata sandi\". Jika tidak diatur, halaman \"Lupa kata sandi\" default Casdoor akan digunakan. Ketika diatur, tautan \"Lupa kata sandi\" pada halaman masuk akan diarahkan ke URL ini",
|
||||
"Found some texts still not translated? Please help us translate at": "Menemukan beberapa teks yang masih belum diterjemahkan? Tolong bantu kami menerjemahkan di",
|
||||
@ -344,6 +353,7 @@
|
||||
"Phone - Tooltip": "Nomor telepon",
|
||||
"Phone only": "Phone only",
|
||||
"Phone or Email": "Phone or Email",
|
||||
"Plain": "Plain",
|
||||
"Plan": "Plan",
|
||||
"Plan - Tooltip": "Plan - Tooltip",
|
||||
"Plans": "Rencana",
|
||||
@ -362,6 +372,7 @@
|
||||
"QR code is too large": "QR code is too large",
|
||||
"Real name": "Nama asli",
|
||||
"Records": "Catatan",
|
||||
"Request": "Request",
|
||||
"Request URI": "Request URI",
|
||||
"Resources": "Sumber daya",
|
||||
"Role": "Role",
|
||||
@ -412,6 +423,7 @@
|
||||
"This is a read-only demo site!": "Ini adalah situs demo hanya untuk dibaca saja!",
|
||||
"Timestamp": "Timestamp",
|
||||
"Tokens": "Token-token",
|
||||
"Tour": "Tour",
|
||||
"Transactions": "Transactions",
|
||||
"Type": "Type",
|
||||
"Type - Tooltip": "Type - Tooltip",
|
||||
@ -442,7 +454,8 @@
|
||||
"Parent group - Tooltip": "Parent group - Tooltip",
|
||||
"Physical": "Physical",
|
||||
"Show all": "Show all",
|
||||
"Virtual": "Virtual"
|
||||
"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"
|
||||
},
|
||||
"home": {
|
||||
"New users past 30 days": "New users past 30 days",
|
||||
@ -461,13 +474,16 @@
|
||||
"Quota": "Quota",
|
||||
"Quota - Tooltip": "Quota - Tooltip",
|
||||
"Used count": "Used count",
|
||||
"Used count - Tooltip": "Used count - Tooltip"
|
||||
"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: "
|
||||
},
|
||||
"ldap": {
|
||||
"Admin": "Admin",
|
||||
"Admin - Tooltip": "CN atau ID dari administrator server LDAP",
|
||||
"Admin Password": "Kata sandi administrator",
|
||||
"Admin Password - Tooltip": "Kata sandi administrator server LDAP",
|
||||
"Allow self-signed certificate": "Allow self-signed certificate",
|
||||
"Allow self-signed certificate - Tooltip": "Allow self-signed certificate - Tooltip",
|
||||
"Auto Sync": "Auto Sinkronisasi",
|
||||
"Auto Sync - Tooltip": "Konfigurasi auto-sync dimatikan pada 0",
|
||||
"Base DN": "DN dasar",
|
||||
@ -586,11 +602,6 @@
|
||||
"Your phone is": "Your phone is",
|
||||
"preferred": "preferred"
|
||||
},
|
||||
"mfaAccount": {
|
||||
"Account Name": "Account Name",
|
||||
"Issuer": "Issuer",
|
||||
"Secret Key": "Secret Key"
|
||||
},
|
||||
"model": {
|
||||
"Advanced Editor": "Editor lanjutan",
|
||||
"Basic Editor": "Editor dasar",
|
||||
@ -610,6 +621,8 @@
|
||||
"Is profile public": "Apakah profilnya publik?",
|
||||
"Is profile public - Tooltip": "Setelah ditutup, hanya administrator global atau pengguna di organisasi yang sama yang dapat mengakses halaman profil pengguna",
|
||||
"Modify rule": "Mengubah aturan",
|
||||
"Navbar items": "Navbar items",
|
||||
"Navbar items - Tooltip": "Navbar items - Tooltip",
|
||||
"New Organization": "Organisasi baru",
|
||||
"Optional": "Optional",
|
||||
"Password expire days": "Password expire days",
|
||||
@ -622,10 +635,14 @@
|
||||
"Tags - Tooltip": "Kumpulan tag yang tersedia bagi pengguna untuk dipilih",
|
||||
"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": "Aturan tampilan",
|
||||
"Visible": "Terlihat",
|
||||
"Website URL": "URL situs web",
|
||||
"Website URL - Tooltip": "URL halaman utama organisasi. Bidang ini tidak digunakan di Casdoor"
|
||||
"Website URL - Tooltip": "URL halaman utama organisasi. Bidang ini tidak digunakan di Casdoor",
|
||||
"Widget items": "Widget items",
|
||||
"Widget items - Tooltip": "Widget items - Tooltip"
|
||||
},
|
||||
"payment": {
|
||||
"Confirm your invoice information": "Konfirmasikan informasi tagihan Anda",
|
||||
@ -728,6 +745,7 @@
|
||||
"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": "Beli",
|
||||
"Buy Product": "Beli Produk",
|
||||
@ -757,7 +775,6 @@
|
||||
"Sold": "Terjual",
|
||||
"Sold - Tooltip": "Jumlah terjual",
|
||||
"Stripe": "Stripe",
|
||||
"AirWallex": "AirWallex",
|
||||
"Tag - Tooltip": "Tag produk",
|
||||
"Test buy page..": "Halaman pembelian uji coba.",
|
||||
"There is no payment channel for this product.": "Tidak ada saluran pembayaran untuk produk ini.",
|
||||
@ -817,6 +834,8 @@
|
||||
"Edit Provider": "Ubah Penyedia Layanan",
|
||||
"Email content": "Konten Email",
|
||||
"Email content - Tooltip": "Isi Email",
|
||||
"Email regex": "Email regex",
|
||||
"Email regex - Tooltip": "Email regex - Tooltip",
|
||||
"Email title": "Judul Email",
|
||||
"Email title - Tooltip": "Judul email",
|
||||
"Endpoint": "Titik akhir",
|
||||
@ -830,6 +849,8 @@
|
||||
"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": "Tuan rumah",
|
||||
"Host - Tooltip": "Nama tuan rumah",
|
||||
"IdP": "IdP",
|
||||
@ -844,6 +865,8 @@
|
||||
"Key text - Tooltip": "Key text - Tooltip",
|
||||
"Metadata": "Metadata: data yang menjelaskan atau memberikan informasi tentang data atau informasi digital lainnya, seperti informasi mengenai sumber data, format, waktu pembuatan, penulis, dan informasi lainnya yang dapat membantu dalam pengelolaan dan pemrosesan data",
|
||||
"Metadata - Tooltip": "Metadata SAML",
|
||||
"Metadata url": "Metadata url",
|
||||
"Metadata url - Tooltip": "Metadata url - Tooltip",
|
||||
"Method - Tooltip": "Metode login, kode QR atau login tanpa suara",
|
||||
"New Provider": "Penyedia Baru",
|
||||
"Normal": "Normal",
|
||||
@ -1244,6 +1267,8 @@
|
||||
"Edit Webhook": "Mengedit Webhook",
|
||||
"Events": "Acara-acara",
|
||||
"Events - Tooltip": "Acara-acara",
|
||||
"Extended user fields": "Extended user fields",
|
||||
"Extended user fields - Tooltip": "Extended user fields - Tooltip",
|
||||
"Headers": "Headers",
|
||||
"Headers - Tooltip": "Header HTTP (pasangan kunci-nilai)",
|
||||
"Is user extended": "Apakah pengguna diperpanjang?",
|
||||
|
@ -17,11 +17,15 @@
|
||||
"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": "Sempre",
|
||||
"Auto signin": "Accesso automatico",
|
||||
"Auto signin - Tooltip": "Quando una sessione esiste in Casdoor, viene utilizzata automaticamente per il login lato applicazione",
|
||||
"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",
|
||||
@ -61,8 +65,10 @@
|
||||
"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",
|
||||
@ -163,6 +169,7 @@
|
||||
},
|
||||
"currency": {
|
||||
"AUD": "AUD",
|
||||
"BRL": "BRL",
|
||||
"CAD": "CAD",
|
||||
"CHF": "CHF",
|
||||
"CNY": "CNY",
|
||||
@ -189,6 +196,7 @@
|
||||
"Verify": "Verify"
|
||||
},
|
||||
"general": {
|
||||
"AI Assistant": "AI Assistant",
|
||||
"API key": "API key",
|
||||
"API key - Tooltip": "API key - Tooltip",
|
||||
"Access key": "Access key",
|
||||
@ -201,7 +209,6 @@
|
||||
"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",
|
||||
@ -231,6 +238,7 @@
|
||||
"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",
|
||||
@ -241,6 +249,7 @@
|
||||
"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",
|
||||
@ -258,7 +267,6 @@
|
||||
"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",
|
||||
@ -271,6 +279,7 @@
|
||||
"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",
|
||||
@ -344,6 +353,7 @@
|
||||
"Phone - Tooltip": "Phone number",
|
||||
"Phone only": "Phone only",
|
||||
"Phone or Email": "Phone or Email",
|
||||
"Plain": "Plain",
|
||||
"Plan": "Plan",
|
||||
"Plan - Tooltip": "Plan - Tooltip",
|
||||
"Plans": "Plans",
|
||||
@ -362,6 +372,7 @@
|
||||
"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",
|
||||
@ -412,6 +423,7 @@
|
||||
"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",
|
||||
@ -442,7 +454,8 @@
|
||||
"Parent group - Tooltip": "Parent group - Tooltip",
|
||||
"Physical": "Physical",
|
||||
"Show all": "Show all",
|
||||
"Virtual": "Virtual"
|
||||
"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"
|
||||
},
|
||||
"home": {
|
||||
"New users past 30 days": "New users past 30 days",
|
||||
@ -461,13 +474,16 @@
|
||||
"Quota": "Quota",
|
||||
"Quota - Tooltip": "Quota - Tooltip",
|
||||
"Used count": "Used count",
|
||||
"Used count - Tooltip": "Used count - Tooltip"
|
||||
"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: "
|
||||
},
|
||||
"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",
|
||||
@ -586,11 +602,6 @@
|
||||
"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",
|
||||
@ -610,6 +621,8 @@
|
||||
"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",
|
||||
@ -622,10 +635,14 @@
|
||||
"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"
|
||||
"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"
|
||||
},
|
||||
"payment": {
|
||||
"Confirm your invoice information": "Confirm your invoice information",
|
||||
@ -728,6 +745,7 @@
|
||||
"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",
|
||||
@ -757,7 +775,6 @@
|
||||
"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.",
|
||||
@ -817,6 +834,8 @@
|
||||
"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",
|
||||
@ -830,6 +849,8 @@
|
||||
"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",
|
||||
@ -844,6 +865,8 @@
|
||||
"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",
|
||||
@ -1244,6 +1267,8 @@
|
||||
"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",
|
||||
|
@ -17,11 +17,15 @@
|
||||
"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": "常に",
|
||||
"Auto signin": "自動サインイン",
|
||||
"Auto signin - Tooltip": "Casdoorにログインセッションが存在する場合、アプリケーション側のログインに自動的に使用されます",
|
||||
"Background URL": "背景URL",
|
||||
"Background URL - Tooltip": "ログインページで使用される背景画像のURL",
|
||||
"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",
|
||||
@ -61,8 +65,10 @@
|
||||
"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 - Tooltip": "登録、ログイン、パスワード忘れフォームの位置",
|
||||
"Generate Face ID": "Generate Face ID",
|
||||
"Grant types": "グラント種類",
|
||||
"Grant types - Tooltip": "OAuthプロトコルで許可されているグラントタイプを選択してください",
|
||||
"Header HTML": "Header HTML",
|
||||
@ -163,6 +169,7 @@
|
||||
},
|
||||
"currency": {
|
||||
"AUD": "AUD",
|
||||
"BRL": "BRL",
|
||||
"CAD": "CAD",
|
||||
"CHF": "CHF",
|
||||
"CNY": "CNY",
|
||||
@ -189,6 +196,7 @@
|
||||
"Verify": "検証"
|
||||
},
|
||||
"general": {
|
||||
"AI Assistant": "AI Assistant",
|
||||
"API key": "API key",
|
||||
"API key - Tooltip": "API key - Tooltip",
|
||||
"Access key": "Access key",
|
||||
@ -201,7 +209,6 @@
|
||||
"Adapter - Tooltip": "ポリシー・ストアのテーブル名",
|
||||
"Adapters": "アダプター",
|
||||
"Add": "追加",
|
||||
"Add Face Id": "Add Face Id",
|
||||
"Add custom item": "Add custom item",
|
||||
"Admin": "Admin",
|
||||
"Affiliation URL": "所属するURL",
|
||||
@ -231,6 +238,7 @@
|
||||
"Created time": "作成された時間",
|
||||
"Custom": "Custom",
|
||||
"Dashboard": "Dashboard",
|
||||
"Data": "Data",
|
||||
"Default": "Default",
|
||||
"Default application": "デフォルトアプリケーション",
|
||||
"Default application - Tooltip": "組織ページから直接登録されたユーザーのデフォルトアプリケーション",
|
||||
@ -241,6 +249,7 @@
|
||||
"Delete": "削除",
|
||||
"Description": "説明",
|
||||
"Description - Tooltip": "参照用の詳細な説明情報です。Casdoor自体はそれを使用しません",
|
||||
"Detail": "详情",
|
||||
"Disable": "Disable",
|
||||
"Display name": "表示名",
|
||||
"Display name - Tooltip": "UIで公開されている使いやすく読みやすい名前",
|
||||
@ -258,7 +267,6 @@
|
||||
"Enabled": "Enabled",
|
||||
"Enabled successfully": "Enabled successfully",
|
||||
"Enforcers": "Enforcers",
|
||||
"FaceIdData": "FaceIdData",
|
||||
"Failed to add": "追加できませんでした",
|
||||
"Failed to connect to server": "サーバーに接続できませんでした",
|
||||
"Failed to delete": "削除に失敗しました",
|
||||
@ -271,6 +279,7 @@
|
||||
"Favicon": "ファビコン",
|
||||
"Favicon - Tooltip": "組織のすべてのCasdoorページに使用されるFaviconアイコンのURL",
|
||||
"First name": "名前",
|
||||
"Forced redirect origin - Tooltip": "Forced redirect origin - Tooltip",
|
||||
"Forget URL": "URLを忘れてください",
|
||||
"Forget URL - Tooltip": "「パスワードをお忘れの場合」ページのカスタムURL。未設定の場合、デフォルトのCasdoor「パスワードをお忘れの場合」ページが使用されます。設定された場合、ログインページの「パスワードをお忘れの場合」リンクはこのURLにリダイレクトされます",
|
||||
"Found some texts still not translated? Please help us translate at": "まだ翻訳されていない文章が見つかりましたか?是非とも翻訳のお手伝いをお願いします",
|
||||
@ -344,6 +353,7 @@
|
||||
"Phone - Tooltip": "電話番号",
|
||||
"Phone only": "Phone only",
|
||||
"Phone or Email": "Phone or Email",
|
||||
"Plain": "Plain",
|
||||
"Plan": "Plan",
|
||||
"Plan - Tooltip": "Plan - Tooltip",
|
||||
"Plans": "プラン",
|
||||
@ -362,6 +372,7 @@
|
||||
"QR code is too large": "QR code is too large",
|
||||
"Real name": "本名",
|
||||
"Records": "記録",
|
||||
"Request": "Request",
|
||||
"Request URI": "Request URI",
|
||||
"Resources": "リソース",
|
||||
"Role": "Role",
|
||||
@ -412,6 +423,7 @@
|
||||
"This is a read-only demo site!": "これは読み取り専用のデモサイトです!",
|
||||
"Timestamp": "Timestamp",
|
||||
"Tokens": "トークン",
|
||||
"Tour": "Tour",
|
||||
"Transactions": "Transactions",
|
||||
"Type": "Type",
|
||||
"Type - Tooltip": "Type - Tooltip",
|
||||
@ -442,7 +454,8 @@
|
||||
"Parent group - Tooltip": "Parent group - Tooltip",
|
||||
"Physical": "Physical",
|
||||
"Show all": "Show all",
|
||||
"Virtual": "Virtual"
|
||||
"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"
|
||||
},
|
||||
"home": {
|
||||
"New users past 30 days": "New users past 30 days",
|
||||
@ -461,13 +474,16 @@
|
||||
"Quota": "Quota",
|
||||
"Quota - Tooltip": "Quota - Tooltip",
|
||||
"Used count": "Used count",
|
||||
"Used count - Tooltip": "Used count - Tooltip"
|
||||
"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: "
|
||||
},
|
||||
"ldap": {
|
||||
"Admin": "管理者",
|
||||
"Admin - Tooltip": "LDAPサーバー管理者のCNまたはID",
|
||||
"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": "自動同期の設定は、0で無効になっています",
|
||||
"Base DN": "ベース DN",
|
||||
@ -586,11 +602,6 @@
|
||||
"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",
|
||||
@ -610,6 +621,8 @@
|
||||
"Is profile public": "プロフィールは公開されていますか?",
|
||||
"Is profile public - Tooltip": "閉鎖された後、グローバル管理者または同じ組織のユーザーだけがユーザーのプロファイルページにアクセスできます",
|
||||
"Modify rule": "ルールを変更する",
|
||||
"Navbar items": "Navbar items",
|
||||
"Navbar items - Tooltip": "Navbar items - Tooltip",
|
||||
"New Organization": "新しい組織",
|
||||
"Optional": "Optional",
|
||||
"Password expire days": "Password expire days",
|
||||
@ -622,10 +635,14 @@
|
||||
"Tags - Tooltip": "ユーザーが選択できるタグのコレクション",
|
||||
"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": "ビュールール",
|
||||
"Visible": "見える",
|
||||
"Website URL": "ウェブサイトのURL",
|
||||
"Website URL - Tooltip": "組織のホームページのURL。このフィールドはCasdoorでは使用されません"
|
||||
"Website URL - Tooltip": "組織のホームページのURL。このフィールドはCasdoorでは使用されません",
|
||||
"Widget items": "Widget items",
|
||||
"Widget items - Tooltip": "Widget items - Tooltip"
|
||||
},
|
||||
"payment": {
|
||||
"Confirm your invoice information": "請求書の情報を確認してください",
|
||||
@ -728,6 +745,7 @@
|
||||
"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 Product": "製品を購入する",
|
||||
@ -757,7 +775,6 @@
|
||||
"Sold": "売れました",
|
||||
"Sold - Tooltip": "販売数量",
|
||||
"Stripe": "Stripe",
|
||||
"AirWallex": "AirWallex",
|
||||
"Tag - Tooltip": "製品のタグ",
|
||||
"Test buy page..": "テスト購入ページ。",
|
||||
"There is no payment channel for this product.": "この製品には支払いチャネルがありません。",
|
||||
@ -817,6 +834,8 @@
|
||||
"Edit Provider": "編集プロバイダー",
|
||||
"Email content": "Eメールの内容",
|
||||
"Email content - Tooltip": "メールの内容",
|
||||
"Email regex": "Email regex",
|
||||
"Email regex - Tooltip": "Email regex - Tooltip",
|
||||
"Email title": "電子メールのタイトル",
|
||||
"Email title - Tooltip": "メールのタイトル",
|
||||
"Endpoint": "エンドポイント",
|
||||
@ -830,6 +849,8 @@
|
||||
"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 - Tooltip": "ホストの名前",
|
||||
"IdP": "IdP",
|
||||
@ -844,6 +865,8 @@
|
||||
"Key text - Tooltip": "Key text - Tooltip",
|
||||
"Metadata": "メタデータ",
|
||||
"Metadata - Tooltip": "SAMLのメタデータ",
|
||||
"Metadata url": "Metadata url",
|
||||
"Metadata url - Tooltip": "Metadata url - Tooltip",
|
||||
"Method - Tooltip": "ログイン方法、QRコードまたはサイレントログイン",
|
||||
"New Provider": "新しい提供者",
|
||||
"Normal": "Normal",
|
||||
@ -1244,6 +1267,8 @@
|
||||
"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": "ユーザーが拡張されましたか?",
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user